├── tests
├── fibonacci
│ ├── stdin
│ └── golden
│ │ ├── stdin
│ │ └── default
├── run.sh
└── benchmark
│ └── plot.py
├── demos
├── fibonacci
│ ├── go
│ │ ├── go.mod
│ │ ├── main.go
│ │ └── LICENSE
│ ├── rust
│ │ ├── Cargo.lock
│ │ ├── Cargo.toml
│ │ ├── src
│ │ │ └── main.rs
│ │ └── LICENSE
│ ├── java
│ │ ├── README.md
│ │ ├── fibonacci.java
│ │ └── LICENSE
│ ├── Enarx.toml
│ ├── assemblyscript
│ │ └── fibo.ts
│ ├── typescript
│ │ └── index.ts
│ ├── javascript
│ │ └── index.js
│ ├── ruby
│ │ ├── fibonacci.rb
│ │ └── LICENSE
│ ├── c#
│ │ ├── Program.cs
│ │ └── LICENSE
│ ├── swift
│ │ └── fibonacci.swift
│ ├── c++
│ │ ├── fibonacci.cpp
│ │ └── LICENSE
│ ├── c
│ │ ├── fibonacci.c
│ │ └── LICENSE
│ ├── grain
│ │ └── fibonacci.gr
│ └── zig
│ │ ├── build.zig
│ │ ├── src
│ │ └── main.zig
│ │ └── LICENSE
├── chat-client
│ ├── web-ui
│ │ ├── README.md
│ │ ├── LICENSE
│ │ ├── index.html
│ │ ├── script.js
│ │ └── style.css
│ ├── rust
│ │ ├── .cargo
│ │ │ └── config
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── c++
│ │ ├── README.md
│ │ ├── process_assets.py
│ │ ├── assets
│ │ │ ├── index.html
│ │ │ ├── script.js
│ │ │ └── style.css
│ │ └── main.cpp
│ ├── Enarx.toml
│ └── c
│ │ └── main.c
├── chat-server
│ ├── rust
│ │ ├── .cargo
│ │ │ └── config
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ └── Enarx.toml
└── README.md
├── examples
├── rust
│ ├── std
│ │ └── tcp-client
│ │ │ ├── Cargo.toml
│ │ │ ├── Cargo.lock
│ │ │ ├── Enarx.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ └── main.rs
│ ├── tokio
│ │ ├── http
│ │ │ ├── src
│ │ │ │ ├── fireworks.gif
│ │ │ │ ├── index.html
│ │ │ │ ├── date.rs
│ │ │ │ ├── main.rs
│ │ │ │ ├── protocol.rs
│ │ │ │ └── enarx-white.svg
│ │ │ ├── .cargo
│ │ │ │ └── config
│ │ │ ├── Enarx.toml
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── LICENSE
│ │ └── echo-tcp
│ │ │ ├── .cargo
│ │ │ └── config
│ │ │ ├── Enarx.toml
│ │ │ ├── Cargo.toml
│ │ │ ├── src
│ │ │ └── main.rs
│ │ │ ├── README.md
│ │ │ └── Cargo.lock
│ ├── README.md
│ └── mio
│ │ └── echo-tcp
│ │ ├── Enarx.toml
│ │ ├── Cargo.toml
│ │ ├── Cargo.lock
│ │ ├── README.md
│ │ └── src
│ │ └── main.rs
├── c
│ └── README.md
├── c#
│ └── README.md
├── c++
│ └── README.md
├── go
│ └── README.md
├── ruby
│ └── README.md
├── zig
│ └── README.md
├── grain
│ └── README.md
├── swift
│ └── README.md
├── javascript
│ └── README.md
├── typescript
│ └── README.md
├── assemblyscript
│ └── README.md
└── README.md
├── .gitignore
├── .github
├── CODEOWNERS
└── workflows
│ ├── automerge.yml
│ ├── commisery.yml
│ ├── nix-update.yml
│ └── build.yml
├── .gitmodules
└── README.md
/tests/fibonacci/stdin:
--------------------------------------------------------------------------------
1 | 25
2 |
--------------------------------------------------------------------------------
/demos/fibonacci/go/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/enarx/codex/demos/fibonacci/go
2 |
3 | go 1.17
4 |
--------------------------------------------------------------------------------
/demos/chat-client/web-ui/README.md:
--------------------------------------------------------------------------------
1 | # Chat Web UI
2 |
3 | Web user interface for a chat client.
4 |
--------------------------------------------------------------------------------
/tests/fibonacci/golden/stdin:
--------------------------------------------------------------------------------
1 | Enter a non-negative number:
2 | Fibonacci sequence number at index 25 is 75025
3 |
--------------------------------------------------------------------------------
/examples/rust/std/tcp-client/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "std-tcp-client"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
--------------------------------------------------------------------------------
/tests/fibonacci/golden/default:
--------------------------------------------------------------------------------
1 | Fibonacci sequence number at index 7 is 13
2 | Fibonacci sequence number at index 21 is 10946
3 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/src/fireworks.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/enarx/codex/HEAD/examples/rust/tokio/http/src/fireworks.gif
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/rust/**/target/
2 | **/zig/**/zig-cache/
3 | **/zig/**/zig-out/
4 | *.wasm
5 | .idea/
6 | .vscode/
7 | a.out
8 | result
9 |
--------------------------------------------------------------------------------
/demos/chat-server/rust/.cargo/config:
--------------------------------------------------------------------------------
1 | [build]
2 | target = "wasm32-wasi"
3 |
4 | [target.wasm32-wasi]
5 | runner = ["enarx", "run", "--wasmcfgfile", "Enarx.toml"]
6 | rustflags = [ "--cfg", "tokio_unstable"]
7 |
--------------------------------------------------------------------------------
/demos/fibonacci/rust/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "fibonacci"
7 | version = "0.3.0"
8 |
--------------------------------------------------------------------------------
/examples/c/README.md:
--------------------------------------------------------------------------------
1 | # C Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with C](https://enarx.dev/docs/WebAssembly/C).
4 |
--------------------------------------------------------------------------------
/demos/chat-client/rust/.cargo/config:
--------------------------------------------------------------------------------
1 | [build]
2 | target = "wasm32-wasi"
3 |
4 | [target.wasm32-wasi]
5 | runner = ["enarx", "run", "--wasmcfgfile", "../Enarx.toml"]
6 | rustflags = [ "--cfg", "tokio_unstable"]
7 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/.cargo/config:
--------------------------------------------------------------------------------
1 | [build]
2 | target = "wasm32-wasi"
3 |
4 | [target.wasm32-wasi]
5 | runner = ["wasmtime", "run", "--tcplisten", "127.0.0.1:8080"]
6 | rustflags = [ "--cfg", "tokio_unstable"]
7 |
--------------------------------------------------------------------------------
/examples/c#/README.md:
--------------------------------------------------------------------------------
1 | # C# Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with C#](https://enarx.dev/docs/WebAssembly/dotnet).
4 |
--------------------------------------------------------------------------------
/examples/c++/README.md:
--------------------------------------------------------------------------------
1 | # C++ Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with C++](https://enarx.dev/docs/WebAssembly/C++).
4 |
--------------------------------------------------------------------------------
/examples/go/README.md:
--------------------------------------------------------------------------------
1 | # Go Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with Go](https://enarx.dev/docs/WebAssembly/Golang).
4 |
--------------------------------------------------------------------------------
/examples/ruby/README.md:
--------------------------------------------------------------------------------
1 | # Ruby Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with Ruby](https://enarx.dev/docs/WebAssembly/Ruby).
4 |
--------------------------------------------------------------------------------
/examples/rust/README.md:
--------------------------------------------------------------------------------
1 | # Rust Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with Rust](https://enarx.dev/docs/WebAssembly/Rust).
4 |
--------------------------------------------------------------------------------
/examples/rust/tokio/echo-tcp/.cargo/config:
--------------------------------------------------------------------------------
1 | [build]
2 | target = "wasm32-wasi"
3 |
4 | [target.wasm32-wasi]
5 | runner = ["wasmtime", "run", "--tcplisten", "127.0.0.1:12345"]
6 | rustflags = [ "--cfg", "tokio_unstable"]
7 |
--------------------------------------------------------------------------------
/examples/zig/README.md:
--------------------------------------------------------------------------------
1 | # Zig Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with Zig](https://enarx.dev/docs/WebAssembly/Zig).
4 |
--------------------------------------------------------------------------------
/demos/chat-client/c++/README.md:
--------------------------------------------------------------------------------
1 | Compile to WASM first, then run with --wasmcfgfile directed to Enarx.toml
2 | Use the --webinterface argument in the Enarx.toml to switch to a web interface (enabled by default), at localhost:50010
--------------------------------------------------------------------------------
/examples/grain/README.md:
--------------------------------------------------------------------------------
1 | # Grain Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with Grain](https://enarx.dev/docs/WebAssembly/Grain).
4 |
--------------------------------------------------------------------------------
/examples/rust/std/tcp-client/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "std-tcp-client"
7 | version = "0.1.0"
8 |
--------------------------------------------------------------------------------
/examples/swift/README.md:
--------------------------------------------------------------------------------
1 | # Swift Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with Swift](https://enarx.dev/docs/WebAssembly/Swift).
4 |
--------------------------------------------------------------------------------
/demos/fibonacci/java/README.md:
--------------------------------------------------------------------------------
1 | # Java Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with Java](https://enarx.dev/docs/WebAssembly/Java).
4 |
--------------------------------------------------------------------------------
/demos/fibonacci/rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "fibonacci"
3 | version = "0.3.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Each line is a file pattern followed by one or more owners.
2 | # Owners will be automatically notified about new PRs and
3 | # an owner's approval is required to merge to protected branches.
4 | * @enarx/codeowners
5 |
--------------------------------------------------------------------------------
/demos/chat-server/Enarx.toml:
--------------------------------------------------------------------------------
1 | [[files]]
2 | kind = "stdin"
3 |
4 | [[files]]
5 | kind = "stdout"
6 |
7 | [[files]]
8 | kind = "stderr"
9 |
10 | [[files]]
11 | name = "ingest"
12 | kind = "listen"
13 | port = 50000
14 | prot = "tcp"
15 |
--------------------------------------------------------------------------------
/examples/javascript/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with JavaScript](https://enarx.dev/docs/WebAssembly/JavaScript).
4 |
--------------------------------------------------------------------------------
/examples/typescript/README.md:
--------------------------------------------------------------------------------
1 | # TypeScript Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with TypeScript](https://enarx.dev/docs/WebAssembly/TypeScript).
4 |
--------------------------------------------------------------------------------
/demos/fibonacci/Enarx.toml:
--------------------------------------------------------------------------------
1 | # Arguments
2 | args = [
3 | "7",
4 | "21"
5 | ]
6 |
7 | # Pre-opened file descriptors
8 | [[files]]
9 | kind = "stdin"
10 |
11 | [[files]]
12 | kind = "stdout"
13 |
14 | [[files]]
15 | kind = "stderr"
16 |
--------------------------------------------------------------------------------
/demos/fibonacci/assemblyscript/fibo.ts:
--------------------------------------------------------------------------------
1 | import "wasi";
2 |
3 | export function fibo(n: i32): i32 {
4 | if (n == 0 || n == 1) return n;
5 | return fibo(n - 1) + fibo(n - 2);
6 | }
7 |
8 | let res = fibo(7);
9 | console.log(res.toString());
10 |
--------------------------------------------------------------------------------
/examples/assemblyscript/README.md:
--------------------------------------------------------------------------------
1 | # AssemblyScript Examples
2 |
3 | For setting up your environment and installing the necessary tools, see [the Enarx documentation on using WebAssembly with AssemblyScript](https://enarx.dev/docs/WebAssembly/AssemblyScript).
4 |
--------------------------------------------------------------------------------
/examples/rust/mio/echo-tcp/Enarx.toml:
--------------------------------------------------------------------------------
1 | [[files]]
2 | kind = "stdin"
3 |
4 | [[files]]
5 | kind = "stdout"
6 |
7 | [[files]]
8 | kind = "stderr"
9 |
10 | [[files]]
11 | kind = "listen"
12 | prot = "tcp"
13 | port = 10000
14 | name = "TEST_TCP_LISTEN"
15 |
--------------------------------------------------------------------------------
/.github/workflows/automerge.yml:
--------------------------------------------------------------------------------
1 | name: Auto merge
2 | on:
3 | pull_request_target
4 |
5 | jobs:
6 | auto-merge:
7 | permissions:
8 | pull-requests: write
9 | contents: write
10 | uses: enarx/.github/.github/workflows/automerge.yml@main
11 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "demos/cryptle/rust"]
2 | path = demos/cryptle/rust
3 | url = https://github.com/enarx/cryptle.git
4 | [submodule "demos/green-house-monitor/c#"]
5 | path = "demos/green-house-monitor/c#"
6 | url = https://github.com/enarx/GreenhouseMonitor.git
7 |
--------------------------------------------------------------------------------
/examples/rust/std/tcp-client/Enarx.toml:
--------------------------------------------------------------------------------
1 | [[files]]
2 | kind = "stdin"
3 |
4 | [[files]]
5 | kind = "stdout"
6 |
7 | [[files]]
8 | kind = "stderr"
9 |
10 | [[files]]
11 | name = "CONNECT"
12 | kind = "connect"
13 | prot = "tcp"
14 | host = "127.0.0.1"
15 | port = 10010
16 |
--------------------------------------------------------------------------------
/tests/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [ "$#" -lt 2 ]; then
4 | echo "Usage: $0 GOLDEN [enarx run arguments]"
5 | exit 1
6 | fi
7 |
8 | golden="${1}"
9 | shift 1
10 |
11 | set -ex
12 | enarx run "${@}" | { read line; while read line; do echo $line; done } | diff "${golden}" -
13 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/Enarx.toml:
--------------------------------------------------------------------------------
1 | steward = "https://attest.profian.com"
2 |
3 | [[files]]
4 | kind = "stdin"
5 |
6 | [[files]]
7 | kind = "stdout"
8 |
9 | [[files]]
10 | kind = "stderr"
11 |
12 | [[files]]
13 | kind = "listen"
14 | port = 10020
15 | name = "TCP_LISTEN"
16 | prot = "tcp"
17 |
--------------------------------------------------------------------------------
/examples/rust/tokio/echo-tcp/Enarx.toml:
--------------------------------------------------------------------------------
1 | #steward = "https://attest.profian.com"
2 |
3 | [[files]]
4 | kind = "stdin"
5 |
6 | [[files]]
7 | kind = "stdout"
8 |
9 | [[files]]
10 | kind = "stderr"
11 |
12 | [[files]]
13 | name = "LISTEN"
14 | kind = "listen"
15 | port = 10010
16 | prot = "tcp"
17 | #prot = "tls"
18 |
--------------------------------------------------------------------------------
/.github/workflows/commisery.yml:
--------------------------------------------------------------------------------
1 | name: Commisery
2 | on:
3 | pull_request:
4 | types: [edited, opened, synchronize, reopened]
5 |
6 | permissions:
7 | contents: read
8 | pull-requests: write
9 | issues: write
10 |
11 | jobs:
12 | commit-message:
13 | uses: enarx/.github/.github/workflows/commisery.yml@main
14 |
--------------------------------------------------------------------------------
/demos/fibonacci/typescript/index.ts:
--------------------------------------------------------------------------------
1 | function fibonacci(num: number) {
2 | var a: number = 1;
3 | var b: number = 0;
4 | var temp: number;
5 | while (num >= 0) {
6 | temp = a;
7 | a = a + b;
8 | b = temp;
9 | num--;
10 | }
11 | console.log("Fibonacci Term is:", b);
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/.github/workflows/nix-update.yml:
--------------------------------------------------------------------------------
1 | name: Update Nix flake
2 |
3 | on:
4 | schedule:
5 | - cron: "0 0 * * *"
6 | workflow_dispatch:
7 |
8 | jobs:
9 | nix-update:
10 | permissions:
11 | contents: write
12 | pull-requests: write
13 | secrets: inherit
14 | uses: enarx/.github/.github/workflows/nix-update.yml@main
15 |
--------------------------------------------------------------------------------
/examples/rust/mio/echo-tcp/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "mio-echo-tcp"
3 | version = "0.2.0"
4 | edition = "2021"
5 | license = "MIT"
6 |
7 | [target.'cfg(any(unix, target_os="wasi"))'.dependencies]
8 | env_logger = { version = "0.9.0", default-features = false }
9 | mio = { version = "0.8.3", features = ["os-poll", "net"], default-features = false }
10 |
--------------------------------------------------------------------------------
/demos/chat-client/Enarx.toml:
--------------------------------------------------------------------------------
1 | [[files]]
2 | kind = "stdin"
3 |
4 | [[files]]
5 | kind = "stdout"
6 |
7 | [[files]]
8 | kind = "stderr"
9 |
10 | [[files]]
11 | name = "server"
12 | kind = "connect"
13 | port = 50000
14 | prot = "tcp"
15 | host = "127.0.0.1"
16 |
17 | [[files]]
18 | name = "web"
19 | kind = "listen"
20 | port = 50010
21 | prot = "tcp"
22 | host = "127.0.0.1"
--------------------------------------------------------------------------------
/examples/rust/tokio/echo-tcp/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tokio-echo-tcp"
3 | version = "0.2.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8 |
9 | [dependencies]
10 | tokio = { version = "1.24.2", default-features = false, features = ["net", "rt", "macros", "io-util", "io-std"] }
11 |
--------------------------------------------------------------------------------
/demos/fibonacci/java/fibonacci.java:
--------------------------------------------------------------------------------
1 | package wasi;
2 |
3 | public class Fibonacci {
4 | public static void main(String[] args) {
5 | int n = Integer.parseInt(args[0]);
6 | System.out.println(fib(n));
7 | }
8 |
9 | private static int fib(int n)
10 | {
11 | if (n <= 1)
12 | return n;
13 | return fib(n - 1) + fib(n - 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/demos/fibonacci/javascript/index.js:
--------------------------------------------------------------------------------
1 | //Simple Program to calculate Fibonacci Sequence of an Integer Input
2 | function fibonacci(){
3 | var num = 10;
4 | var a = 1, b = 0, temp;
5 |
6 | while (num >= 0){
7 | temp = a;
8 | a = a + b;
9 | b = temp;
10 | num--;
11 | }
12 | console.log("Fibonacci result is: ",b);
13 |
14 | }
15 |
16 | var Shopify = {
17 | main: fibonacci
18 | };
19 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Enarx Examples
2 |
3 | This directory contains small, focused code examples that demonstrate how to perform
4 | specific tasks in the context of Enarx.
5 |
6 | The examples within this directory are categorized by programming language.
7 | Within each language's directory, you will also find instructions on how to install
8 | and run the tools necessary to compile that language to a WebAssembly module.
9 |
--------------------------------------------------------------------------------
/demos/chat-client/rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "chat-client"
3 | version = "0.1.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | [dependencies]
8 | anyhow = "1.0.57"
9 | futures = { version = "0.3.25", features = ["io-compat"] }
10 | tokio = { version = "1.24.2", default-features = false, features = ["net", "rt", "macros"] }
11 | tokio-stream = { version = "0.1.11", default-features = false, features = ["net", "io-util", "sync"] }
12 |
--------------------------------------------------------------------------------
/demos/chat-server/rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "chat-server"
3 | version = "0.1.1"
4 | edition = "2021"
5 | publish = false
6 |
7 | [dependencies]
8 | anyhow = "1.0.57"
9 | futures = { version = "0.3.25", features = ["io-compat"] }
10 | tokio = { version = "1.24.2", default-features = false, features = ["net", "rt", "macros"] }
11 | tokio-stream = { version = "0.1.11", default-features = false, features = ["net", "io-util", "sync"] }
12 | ulid = "1.0.0"
13 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tokio-http"
3 | version = "0.2.0"
4 | publish = false
5 | edition = "2021"
6 |
7 | [dependencies]
8 | tokio = { version = "1.24.2", features = ["net", "rt", "macros"] }
9 | tokio-util = { version = "0.7.4", features = ["codec"] }
10 | tokio-stream = "0.1.11"
11 |
12 | bytes = "1.0.0"
13 | futures = { version = "0.3.0", features = ["thread-pool"]}
14 |
15 | http = "0.2"
16 | httparse = "1.0"
17 | httpdate = "1.0"
18 |
--------------------------------------------------------------------------------
/demos/fibonacci/ruby/fibonacci.rb:
--------------------------------------------------------------------------------
1 | def FibonacciSequence( n )
2 | return n if ( 0..1 ).include? n
3 | ( FibonacciSequence( n - 1 ) + FibonacciSequence( n - 2 ) )
4 | end
5 |
6 | puts "Ruby - Fibonacci sequence example"
7 |
8 | if ARGV.length > 0
9 | ARGV.each { |arg|
10 | n = arg.to_i
11 | puts "Fibonacci sequence number at index #{n} is #{FibonacciSequence(n)}"
12 | }
13 | else
14 | puts "Enter a non-negative number:"
15 | n = ARGF.gets.to_i
16 | puts "Fibonacci sequence number at index #{n} is #{FibonacciSequence(n)}"
17 | end
18 |
--------------------------------------------------------------------------------
/demos/fibonacci/c#/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MyFirstWasiApp
4 | {
5 | public class Program
6 | {
7 |
8 | public void fibonacci(ref int num){
9 | int a=1,b=0,temp;
10 | while(num >= 0){
11 | temp=a;
12 | a=a+b;
13 | b=temp;
14 | num--;
15 | }
16 | Console.WriteLine("Fibonacci Term is: "+b);
17 | }
18 |
19 | public static void Main(string[] args)
20 | {
21 | Program p = new Program();
22 | int num=10;
23 | p.fibonacci(ref num);
24 | }
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demos/chat-client/c++/process_assets.py:
--------------------------------------------------------------------------------
1 | # Python script from https://github.com/rjzak/web_wordpuzzle
2 |
3 | ASSETS = ( ("index_page", open("assets/index.html", "rb").read()), ("script", open("assets/script.js", "rb").read()), ("style", open("assets/style.css", "rb").read()) )
4 |
5 | output_file = open("assets.h", "w")
6 |
7 | output_file.write("//This is an auto-generated file generated from the process_asets.py script\n\n")
8 |
9 | for asset in ASSETS:
10 | name = asset[0]
11 | data = asset[1]
12 | output_file.write("unsigned char %s[%d]= {" % (name, len(data)));
13 | output_file.write(",".join(["0x%02X"%x for x in data]))
14 | output_file.write("};\n")
15 |
16 |
17 | output_file.close()
--------------------------------------------------------------------------------
/tests/benchmark/plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import subprocess
3 | import sys
4 |
5 | ret = []
6 | for prog in sys.argv[1:]:
7 | ret.append([[], []])
8 | for _ in range(10): # run 10 times
9 | s = subprocess.run(['time', '--format', "%e %M", 'enarx', 'deploy', prog], capture_output=True)
10 | if s.returncode != 0:
11 | print(s.stderr.decode('utf-8'))
12 | exit(1)
13 | s = s.stderr.decode('utf-8').split()
14 | ret[-1][0].append(float(s[0])) # time
15 | ret[-1][1].append(float(s[1])/1000) # memory
16 |
17 | fig, ax = plt.subplots()
18 | for lang, data in zip(sys.argv[1:], ret):
19 | ax.scatter(*data, label=lang)
20 |
21 | ax.legend()
22 | ax.set_xlabel('Time (s)')
23 | ax.set_ylabel('Memory (MB)')
24 | plt.show()
25 |
--------------------------------------------------------------------------------
/demos/fibonacci/rust/src/main.rs:
--------------------------------------------------------------------------------
1 | use std::env::args;
2 | use std::io::stdin;
3 |
4 | fn fib(n: u32) -> u32 {
5 | match n {
6 | 0 => 0,
7 | 1 => 1,
8 | n => fib(n - 1) + fib(n - 2),
9 | }
10 | }
11 |
12 | fn main() {
13 | println!("Rust - Fibonacci sequence example");
14 |
15 | let mut args: Vec<_> = args().skip(1).collect();
16 |
17 | if args.is_empty() {
18 | println!("Enter a non-negative number:");
19 | let mut idx = String::new();
20 | stdin().read_line(&mut idx).expect("Failed to read line");
21 | args.push(idx);
22 | }
23 |
24 | for arg in args {
25 | let idx = arg.trim().parse().expect("Failed to parse number");
26 | println!("Fibonacci sequence number at index {} is {}", idx, fib(idx));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/demos/fibonacci/swift/fibonacci.swift:
--------------------------------------------------------------------------------
1 | func fib(n: UInt) -> UInt {
2 | if n <= 1 {
3 | return n
4 | }
5 |
6 | return fib(n: n-1) + fib(n: n-2)
7 | }
8 |
9 | print("Swift - Fibonacci sequence example\n")
10 |
11 | let arguments = CommandLine.arguments
12 |
13 | var n:UInt
14 | if (arguments.count > 1) {
15 | for i in 1...arguments.count-1 {
16 | if let n = UInt(arguments[i]) {
17 | print("Fibonacci sequence number at index \(n) is \(fib(n: n))\n")
18 | } else {
19 | print("Failed to parse argument into a number: \(arguments[i])\n")
20 | }
21 | }
22 | } else {
23 | print("Enter a non-negative number:\n")
24 | if let line = readLine() {
25 | if let n = UInt(line) {
26 | print("Fibonacci sequence number at index \(n) is \(fib(n: n))\n")
27 | } else {
28 | print("Could not convert \(line) to integer.\n")
29 | }
30 | } else {
31 | print("Could not read user input.\n")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/src/index.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 | hello_enarx
7 |
27 |
28 |
29 |
30 |
31 |
Hello Enarx!
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/demos/fibonacci/go/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "flag"
6 | "fmt"
7 | "log"
8 | "os"
9 | "strconv"
10 | )
11 |
12 | func init() {
13 | log.SetFlags(0)
14 | }
15 |
16 | func fib(n uint64) uint64 {
17 | if n <= 1 {
18 | return n
19 | }
20 | return fib(n-1) + fib(n-2)
21 | }
22 |
23 | func main() {
24 | fmt.Println("Go - Fibonacci sequence example")
25 |
26 | flag.Parse()
27 |
28 | args := flag.Args()
29 | if len(args) == 0 {
30 | fmt.Println("Enter a non-negative number:")
31 | sc := bufio.NewScanner(os.Stdin)
32 | sc.Scan()
33 | b, err := sc.Bytes(), sc.Err()
34 | if err != nil {
35 | log.Fatalf("Failed to read stdin: %s", err)
36 | }
37 | args = []string{string(b)}
38 | }
39 |
40 | for _, arg := range args {
41 | n, err := strconv.ParseUint(arg, 10, 64)
42 | if err != nil {
43 | log.Fatalf("Failed to parse number: %s", err)
44 | }
45 | fmt.Printf("Fibonacci sequence number at index %d is %d\n", n, fib(n))
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/demos/fibonacci/c++/fibonacci.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | using namespace std;
6 |
7 | unsigned long fib(unsigned long i) {
8 | if (i <= 1) {
9 | return i;
10 | }
11 | return fib(i - 1) + fib(i - 2);
12 | }
13 |
14 | int main(int argc, char *argv[]) {
15 | cout << "C++ - Fibonacci sequence example" << endl;
16 | if (argc <= 1) {
17 | unsigned long n;
18 | cout << "Enter a non-negative number:" << endl;
19 | cin >> n;
20 | cout << "Fibonacci sequence number at index " << n << " is " << fib(n)
21 | << endl;
22 | } else {
23 | for (unsigned int i = 1; i < argc; i++) {
24 | errno = 0;
25 | unsigned long n = strtoul(argv[i], NULL, 10);
26 | if (errno != 0) {
27 | cerr << "Failed to parse argument into a number: " << strerror(errno)
28 | << endl;
29 | exit(1);
30 | }
31 | cout << "Fibonacci sequence number at index " << n << " is " << fib(n)
32 | << endl;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/README.md:
--------------------------------------------------------------------------------
1 | # wasi_tokio_http
2 |
3 | This is a modified version of the
4 | [`tinyhttp.rs`](https://github.com/tokio-rs/tokio/blob/5288e1e144d33ace0070325b16029523b1db0ffe/examples/tinyhttp.rs)
5 | example in the tokio repository.
6 |
7 | ## Prerequisites
8 |
9 | Be sure to use a stable Rust toolchain that is no older than Rust 1.60.0. You can use `cargo --version` to view the version of your default Rust toolchain.
10 |
11 | ## Running
12 |
13 | ### wasmtime
14 |
15 | ```console
16 | ❯ CARGO_TARGET_WASM32_WASI_RUNNER="wasmtime run --tcplisten 127.0.0.1:10020" cargo run --target wasm32-wasi
17 | ```
18 |
19 | Server is running on [`http://127.0.0.1:10020`](http://127.0.0.1:10020).
20 |
21 | ### enarx
22 |
23 | after installing [enarx](https://github.com/enarx/enarx/) in `$PATH` with `cargo install`
24 |
25 | ```console
26 | ❯ CARGO_TARGET_WASM32_WASI_RUNNER="enarx run --wasmcfgfile Enarx.toml" cargo run --target wasm32-wasi
27 | ```
28 |
29 | Server is running on [`https://127.0.0.1:10020`](https://127.0.0.1:10020).
30 |
--------------------------------------------------------------------------------
/demos/fibonacci/c/fibonacci.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | unsigned long fib(unsigned long i) {
7 | if (i <= 1) {
8 | return i;
9 | }
10 | return fib(i - 1) + fib(i - 2);
11 | }
12 |
13 | int main(int argc, char *argv[]) {
14 | printf("C - Fibonacci sequence example\n");
15 | if (argc <= 1) {
16 | unsigned long n;
17 | printf("Enter a non-negative number:\n");
18 | if (scanf("%lu", &n) != 1) {
19 | fprintf(stderr, "Failed to read number from stdin\n");
20 | exit(1);
21 | }
22 | printf("Fibonacci sequence number at index %lu is %lu\n", n, fib(n));
23 | } else {
24 | for (unsigned int i = 1; i < argc; i++) {
25 | errno = 0;
26 | unsigned long n = strtoul(argv[i], NULL, 10);
27 | if (errno != 0) {
28 | fprintf(stderr, "Failed to parse argument into a number: %s\n",
29 | strerror(errno));
30 | exit(1);
31 | }
32 | printf("Fibonacci sequence number at index %lu is %lu\n", n, fib(n));
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/examples/rust/std/tcp-client/README.md:
--------------------------------------------------------------------------------
1 | Simple TCP client for the tokio-echo-tcp server
2 | -----------------------------------------------
3 |
4 | This demo is a TCP client which connects to tokio-echo-tcp server.
5 |
6 | # You need to lauch the server
7 |
8 | Follow README.md documentation under codex/Rust/tokio-echo-tcp and execute the server:
9 |
10 | ```sh
11 | cargo build --target wasm32-wasi --release
12 | enarx run --backend=nil --wasmcfgfile Enarx.toml target/wasm32-wasi/release/tokio-echo-tcp.wasm
13 | ```
14 |
15 | Now when the TCP echo server is running you can build this TCP client and test it:
16 |
17 | Run release without Enarx:
18 |
19 | ```sh
20 | cargo run
21 | ```
22 |
23 | Run inside Enarx Keep:
24 |
25 | ```sh
26 | cargo build --release --target=wasm32-wasi
27 | enarx run --backend=nil --wasmcfgfile Enarx.toml target/wasm32-wasi/release/std-tcp-client.wasm
28 | ```
29 |
30 | Expected result following:
31 |
32 | ```sh
33 | Successfully connected to server.
34 | request_data = "GET / HTTP/1.0\r\n\r\n"
35 | "GET / HTTP/1.0\r\n\r\n"
36 | Finished.
37 | ```
38 |
--------------------------------------------------------------------------------
/demos/fibonacci/grain/fibonacci.gr:
--------------------------------------------------------------------------------
1 | import {toList} from "array"
2 | import {drop, forEach, length, map} from "list"
3 | import {parseInt} from "number"
4 | import {trim} from "string"
5 | import {fdRead, stdin} from "sys/file"
6 | import {argv} from "sys/process"
7 | import {expect} from "result"
8 |
9 | print("Grain - Fibonacci sequence example")
10 |
11 | let rec fibonacci = (i) => {
12 | if (i <= 1) {
13 | i
14 | } else {
15 | fibonacci(i - 1) + fibonacci(i - 2)
16 | }
17 | }
18 |
19 | let args = expect("failed to parse arguments", argv())
20 | let indexes = drop(1, toList(args))
21 | let indexes = if (length(indexes) == 0) {
22 | print("Enter a non-negative number:")
23 | let (s, _) = expect("failed to read stdin", fdRead(stdin, 19))
24 | let i = expect("failed to parse stdin as integer number", parseInt(trim(s), 10))
25 | [i]
26 | } else {
27 | map((arg) => { expect("failed to parse argument " ++ toString(arg) ++ " as integer number", parseInt(arg, 10)) }, indexes)
28 | }
29 | forEach((i) => { print("Fibonacci sequence number at index " ++ toString(i) ++ " is " ++ toString(fibonacci(i))) }, indexes)
30 |
--------------------------------------------------------------------------------
/demos/chat-client/web-ui/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Abhishek Gupta
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2022 Tokio Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/demos/chat-client/c++/assets/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Enarx Chat
10 |
11 |
12 |
13 |
14 |
15 |
Enarx Chat
16 |
Click on the chat button to start
17 |
Click the stop button to stop the chat client
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/demos/README.md:
--------------------------------------------------------------------------------
1 | # Enarx Demos
2 |
3 | This directory contains full-featured applications that demonstrate the capabilities of
4 | WebAssembly running within Enarx.
5 |
6 | These apps are also featured on the [Try Enarx](try.enarx.dev) website, where they can be easily
7 | launched from your browser and run within real, secured Enarx Keeps on supported cloud platforms.
8 |
9 | Some demos have implementations in multiple programming languages.
10 | Each demo's directory is categorized by language.
11 |
12 | ## Chat Client
13 |
14 | The Chat Server app is the frontend of a simple messaging app, intended to be used with the Chat
15 | Server app.
16 |
17 | ## Chat Server
18 |
19 | The Chat Server app is the backend of a simple messaging app, intended to be used with the Chat
20 | Client app.
21 |
22 | ## Cryptle
23 |
24 | The Cryptle app is a multiplayer implementation of
25 | [Wordle](https://www.nytimes.com/games/wordle/index.html).
26 |
27 | ## Fibonacci
28 |
29 | The Fibonacci app is a simple program that demonstrates setting up file descriptors and printing
30 | to stdout.
31 | It features implementations in every language officially supported by Enarx.
32 |
33 | ## Greenhouse Monitor
34 |
35 | The Greenhouse Monitor app implements a dashboard that demonstrates features such as WebSockets
36 | and gRPC.
37 |
--------------------------------------------------------------------------------
/demos/fibonacci/zig/build.zig:
--------------------------------------------------------------------------------
1 | const std = @import("std");
2 |
3 | pub fn build(b: *std.build.Builder) void {
4 | // Standard target options allows the person running `zig build` to choose
5 | // what target to build for. Here we do not override the defaults, which
6 | // means any target is allowed, and the default is native. Other options
7 | // for restricting supported target set are available.
8 | const target = b.standardTargetOptions(.{});
9 |
10 | // Standard release options allow the person running `zig build` to select
11 | // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
12 | const mode = b.standardReleaseOptions();
13 |
14 | const exe = b.addExecutable("fibonacci", "src/main.zig");
15 | exe.setTarget(target);
16 | exe.setBuildMode(mode);
17 | exe.install();
18 |
19 | const run_cmd = exe.run();
20 | run_cmd.step.dependOn(b.getInstallStep());
21 | if (b.args) |args| {
22 | run_cmd.addArgs(args);
23 | }
24 |
25 | const run_step = b.step("run", "Run the app");
26 | run_step.dependOn(&run_cmd.step);
27 |
28 | const exe_tests = b.addTest("src/main.zig");
29 | exe_tests.setTarget(target);
30 | exe_tests.setBuildMode(mode);
31 |
32 | const test_step = b.step("test", "Run unit tests");
33 | test_step.dependOn(&exe_tests.step);
34 | }
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Enarx Codex
2 |
3 | A collection of code examples that can be compiled to WebAssembly and run within Enarx.
4 |
5 | This repository contains git submodules.
6 | After cloning this repository, please run `git submodule update --init` to retrieve the submodules.
7 |
8 | ## Demos
9 |
10 | The `demos` directory contains full-featured applications that demonstrate the capabilities of
11 | WebAssembly running within Enarx.
12 | Look here if you're interested in seeing what complete, working Enarx applications look like.
13 |
14 | These apps are also featured on the [Try Enarx](try.enarx.dev) website, where they can be easily
15 | launched from your browser and run within real, secured Enarx Keeps on supported cloud platforms.
16 |
17 | Some demos have implementations in multiple programming languages.
18 | Each demo's directory is categorized by language.
19 |
20 | ## Examples
21 |
22 | The `examples` directory contains small, focused code examples that demonstrate how to perform
23 | specific tasks in the context of Enarx.
24 | Look here if you're writing an Enarx application and need guidance on how to perform a certain
25 | task.
26 |
27 | The examples within this directory are categorized by programming language.
28 | Within each language's directory, you will also find instructions on how to install
29 | and run the tools necessary to compile that language to a WebAssembly module.
30 |
--------------------------------------------------------------------------------
/demos/fibonacci/zig/src/main.zig:
--------------------------------------------------------------------------------
1 | const std = @import("std");
2 |
3 | fn fibonacci(i: u64) u64 {
4 | if (i <= 1) return i;
5 | return fibonacci(i - 1) + fibonacci(i - 2);
6 | }
7 |
8 | fn print_fibonacci(w: anytype, s: []const u8) !void {
9 | const i = try std.fmt.parseUnsigned(u64, s, 10);
10 | try w.print("Fibonacci sequence number at index {d} is {d}\n", .{i, fibonacci(i)});
11 | }
12 |
13 | pub fn main() !void {
14 | const alloc: std.mem.Allocator = std.heap.page_allocator;
15 |
16 | var args = try std.process.argsAlloc(alloc);
17 | defer alloc.free(args);
18 |
19 | const stdout = std.io.getStdOut();
20 | defer stdout.close();
21 |
22 | const out = stdout.writer();
23 |
24 | try out.print("Zig - Fibonacci sequence example\n", .{});
25 |
26 | const indexes = args[1..];
27 | if (indexes.len > 0) {
28 | for (indexes) |arg| {
29 | try print_fibonacci(out, arg);
30 | }
31 | } else {
32 | const stdin = std.io.getStdIn();
33 | defer stdin.close();
34 |
35 | try out.print("Enter a non-negative number:\n", .{});
36 | var buf: [19]u8 = undefined;
37 | if (try stdin.reader().readUntilDelimiterOrEof(&buf, '\n')) |arg| {
38 | try print_fibonacci(out, arg);
39 | } else {
40 | std.debug.print("failed to read from stdin", .{});
41 | std.process.exit(1);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/demos/chat-client/web-ui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Enarx Chat
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | chat
20 |
21 |
Enarx Chat
22 |
23 |
24 |
25 |
26 | face
27 | Enarx Chat
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/examples/rust/tokio/echo-tcp/src/main.rs:
--------------------------------------------------------------------------------
1 | use std::io::Write;
2 | use std::os::wasi::prelude::FromRawFd;
3 |
4 | use tokio::io::{AsyncReadExt, AsyncWriteExt};
5 | use tokio::net::{TcpListener, TcpStream};
6 |
7 | #[tokio::main(flavor = "current_thread")]
8 |
9 | async fn main() -> std::io::Result<()> {
10 | // Set up pre-established listening socket.
11 | let standard = unsafe { std::net::TcpListener::from_raw_fd(3) };
12 | standard.set_nonblocking(true).unwrap();
13 | let listener = TcpListener::from_std(standard)?;
14 |
15 | loop {
16 | // Accept new sockets in a loop.
17 | let socket = match listener.accept().await {
18 | Ok(s) => s.0,
19 | Err(e) => {
20 | eprintln!("> ERROR: {}", e);
21 | continue;
22 | }
23 | };
24 |
25 | // Spawn a background task for each new connection.
26 | tokio::spawn(async move {
27 | eprintln!("> CONNECTED");
28 | match handle(socket).await {
29 | Ok(()) => eprintln!("> DISCONNECTED"),
30 | Err(e) => eprintln!("> ERROR: {}", e),
31 | }
32 | });
33 | }
34 | }
35 |
36 | async fn handle(mut socket: TcpStream) -> std::io::Result<()> {
37 | loop {
38 | let mut buf = [0u8; 4096];
39 |
40 | // Read some bytes from the socket.
41 | let read = socket.read(&mut buf).await?;
42 |
43 | // Handle a clean disconnection.
44 | if read == 0 {
45 | return Ok(());
46 | }
47 |
48 | // Write bytes both locally and remotely.
49 | std::io::stdout().write_all(&buf[..read])?;
50 | socket.write_all(&buf[..read]).await?;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/examples/rust/std/tcp-client/src/main.rs:
--------------------------------------------------------------------------------
1 | use std::io::{BufReader, Read, Write};
2 | use std::net::TcpStream;
3 |
4 | // When build to wasi
5 | #[cfg(target_os = "wasi")]
6 | fn get_tcpstream() -> std::result::Result> {
7 | use std::os::wasi::io::FromRawFd;
8 | let stdstream = unsafe { std::net::TcpStream::from_raw_fd(3) };
9 | Ok(stdstream)
10 | }
11 |
12 | // When the target of the build is not wasi
13 | #[cfg(not(target_os = "wasi"))]
14 | fn get_tcpstream() -> std::result::Result {
15 | std::net::TcpStream::connect("127.0.0.1:10010")
16 | }
17 |
18 | fn main() {
19 | // Use the TCP connection
20 | match get_tcpstream() {
21 | Ok(mut _stream) => {
22 | println!("Successfully connected to server.");
23 |
24 | // Send data over TCP
25 | let mut request_data = String::new();
26 | request_data.push_str("GET / HTTP/1.0\r\n\r\n");
27 | println!("request_data = {:?}", request_data);
28 | let _result = _stream.write_all(request_data.as_bytes());
29 |
30 | // Receive data from TCP
31 | let mut reader = BufReader::new(_stream);
32 | // Echo TCP server returns our request
33 | // We read the same amount of bytes
34 | let byte_count = request_data.len();
35 | let mut data = vec![0; byte_count];
36 | reader.read(&mut data).unwrap(); // Read from TCP
37 | let data_str = std::str::from_utf8(&data).unwrap();
38 | println!("{:?}", data_str);
39 | },
40 | Err(e) => {
41 | println!("Failed to connect: {}", e);
42 | }
43 | }
44 | println!("Finished.");
45 | }
46 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on: [ push, pull_request ]
3 | concurrency:
4 | group: ${{ github.workflow }}-${{ github.ref }}
5 | cancel-in-progress: true
6 | jobs:
7 | check:
8 | runs-on: ubuntu-20.04
9 | steps:
10 | - uses: actions/checkout@v3
11 | - uses: cachix/install-nix-action@v18
12 | - uses: cachix/cachix-action@v12
13 | continue-on-error: true
14 | with:
15 | name: enarx
16 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
17 | - run: nix flake check -L --show-trace --keep-going
18 |
19 | build:
20 | needs: [ check ]
21 | strategy:
22 | matrix:
23 | output:
24 | - chat-client-c
25 | - chat-client-cpp
26 | - chat-client-rust
27 | - chat-server-rust
28 | - cryptle-rust
29 | - fibonacci-c
30 | - fibonacci-cpp
31 | - fibonacci-go
32 | - fibonacci-rust
33 | - fibonacci-zig
34 |
35 | runs-on: ubuntu-20.04
36 | steps:
37 | - uses: actions/checkout@v3
38 | - uses: cachix/install-nix-action@v18
39 | - uses: cachix/cachix-action@v12
40 | continue-on-error: true
41 | with:
42 | name: enarx
43 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
44 | - name: Build ${{ matrix.output }} Enarx package
45 | run: nix build -L '.#${{ matrix.output }}'
46 | - run: nix run --inputs-from . 'nixpkgs#coreutils' -- --coreutils-prog=ginstall -p ./result/main.wasm ${{ matrix.output }}.wasm
47 | - uses: actions/upload-artifact@v3
48 | with:
49 | name: ${{ matrix.output }}.wasm
50 | path: ${{ matrix.output }}.wasm
51 |
52 | # TODO: Publish packages once
53 | # - https://github.com/profianinc/drawbridge/issues/148
54 | # - https://github.com/enarx/enarx/issues/2048
55 | # are done
56 | #- run: enarx package publish "examples/${{ matrix.output }}:$(nix eval --raw '.#${{ matrix.output }}.version')" ./result
57 |
--------------------------------------------------------------------------------
/examples/rust/tokio/echo-tcp/README.md:
--------------------------------------------------------------------------------
1 | # tokio_echo
2 |
3 | This demo is a TCP Echo server for tokio.
4 |
5 | ## Prerequisites
6 |
7 | Be sure to update your rust stable toolchain to at least 1.60.0.
8 |
9 | Please ensure that you're using the standard toolchain (if using [`rustup`](https://rustup.rs/): `rustup default`).
10 |
11 | ## Running from Try Enarx
12 |
13 | First generate the Wasm file on localhost:
14 |
15 | ```sh
16 | cargo build --target wasm32-wasi
17 | ```
18 |
19 | Access the __Try Enarx__ website:
20 |
21 | https://try.enarx.dev
22 |
23 | Select a platform. Let's try Intel SGX on Equinix.
24 |
25 | Upload the generated Wasm file from:
26 |
27 | ```sh
28 | /target/wasm32-wasi/debug/tokio-echo.wasm
29 | ```
30 |
31 | Paste the following to the Enarx.toml text area:
32 |
33 | ```toml
34 | [[files]]
35 | kind = "stdin"
36 |
37 | [[files]]
38 | kind = "stdout"
39 |
40 | [[files]]
41 | kind = "stderr"
42 |
43 | [[files]]
44 | name = "LISTEN"
45 | kind = "listen"
46 | port = 10010
47 | prot = "tcp"
48 | ```
49 |
50 | Click on the `Deploy` button.
51 |
52 | Now open a terminal on your machine. You are going to connect with the server using either ncat or nc (these are popular networking tools that are usually available out-of-the-box):
53 |
54 | ```sh
55 | echo hello | ncat sgx.equinix.try.enarx.dev 10010
56 | ```
57 |
58 | In the __Try Enarx__ website, you should see the following output:
59 |
60 | ```sh
61 | hello
62 | > CONNECTED
63 | > DISCONNECTED
64 | ```
65 |
66 | Congratulations!
67 |
68 | ## Running from localhost
69 |
70 | ### enarx
71 |
72 | After installing [enarx](https://enarx.dev/docs/Quickstart) run:
73 |
74 | ```sh
75 | CARGO_TARGET_WASM32_WASI_RUNNER="enarx run --wasmcfgfile Enarx.toml" cargo run --target wasm32-wasi
76 | ```
77 |
78 | Open another shell and enter:
79 |
80 | ```sh
81 | echo hello | ncat 127.0.0.1 10010
82 | ```
83 |
84 | You should see the following output from Enarx:
85 |
86 | ```sh
87 | Running enarx run --wasmcfgfile Enarx.toml target/wasm32-wasi/debug/tokio-echo.wasm
88 | > CONNECTED
89 | hello
90 | > DISCONNECTED
91 | ```
92 |
--------------------------------------------------------------------------------
/demos/chat-client/c++/assets/script.js:
--------------------------------------------------------------------------------
1 | function init() {
2 | chatArea = document.querySelector(".chat-area")
3 | chatSubmit = document.querySelector(".chat-submit")
4 | chatHeader = document.querySelector(".chat-header")
5 | chatInput = document.querySelector(".chat-input")
6 | stopButton = document.querySelector(".stop-btn")
7 | root = document.documentElement;
8 | var host = "http://localhost:50010"
9 |
10 | chatSubmit.addEventListener("click", () => {
11 | let userResponse = chatInput.value.trim();
12 | if (userResponse !== "") {
13 | setUserResponse();
14 | send(userResponse, host)
15 | }
16 | })
17 |
18 | stopButton.addEventListener("click", () => {
19 | send("/04".trim(), host);
20 | chatInput.disabled = true;
21 | })
22 | }
23 |
24 | // end of init function
25 |
26 | function userResponseBtn(e) {
27 | send(e.value);
28 | }
29 |
30 | // to submit user input when pressing enter
31 | function givenUserInput(e) {
32 | if (e.keyCode == 13) {
33 | let userResponse = chatInput.value.trim();
34 | if (userResponse !== "") {
35 | setUserResponse()
36 | send(userResponse)
37 | }
38 | }
39 | }
40 |
41 | // to display user message on UI
42 | function setUserResponse() {
43 | let userInput = chatInput.value;
44 | if (userInput) {
45 | let temp = `
${userInput}
`
46 | chatArea.innerHTML += temp;
47 | chatInput.value = ""
48 | } else {
49 | chatInput.disabled = false;
50 | }
51 | scrollToBottomOfResults();
52 | }
53 |
54 |
55 |
56 | function scrollToBottomOfResults() {
57 | chatArea.scrollTop = chatArea.scrollHeight;
58 | }
59 |
60 | function send(message, host) {
61 | chatInput.type = "text"
62 | passwordInput = false;
63 | chatInput.focus();
64 | console.log("User Message:", message)
65 | $.ajax({
66 | url: host,
67 | method: 'PUT',
68 | data: {
69 | message: message
70 | }
71 | });
72 | chatInput.focus();
73 | }
74 |
75 | init();
--------------------------------------------------------------------------------
/demos/chat-client/rust/src/main.rs:
--------------------------------------------------------------------------------
1 | use std::env;
2 | #[cfg(unix)]
3 | use std::os::unix::io::FromRawFd;
4 | #[cfg(target_os = "wasi")]
5 | use std::os::wasi::io::FromRawFd;
6 | use std::str::FromStr;
7 |
8 | use anyhow::{bail, Context};
9 | use futures::StreamExt;
10 | use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
11 | use tokio::net::TcpStream;
12 | use tokio_stream::wrappers::LinesStream;
13 |
14 | #[tokio::main(flavor = "current_thread")]
15 | async fn main() -> anyhow::Result<()> {
16 | let fd_count = env::var("FD_COUNT").context("failed to lookup `FD_COUNT`")?;
17 | let fd_count = usize::from_str(&fd_count).context("failed to parse `FD_COUNT`")?;
18 | assert_eq!(
19 | fd_count,
20 | 5, // STDIN, STDOUT, STDERR and 2 sockets
21 | "unexpected amount of file descriptors received"
22 | );
23 | let mut stream = match env::var("FD_NAMES")
24 | .context("failed to lookup `FD_NAMES`")?
25 | .splitn(fd_count, ':')
26 | .nth(3)
27 | {
28 | None => bail!("failed to parse `FD_NAMES`"),
29 | Some("server") => {
30 | let s = unsafe { std::net::TcpStream::from_raw_fd(3) };
31 | s.set_nonblocking(true)
32 | .context("failed to set non-blocking flag on socket")?;
33 | TcpStream::from_std(s).context("failed to initialize Tokio stream")?
34 | }
35 | Some(name) => bail!("unknown socket name `{name}`"),
36 | };
37 |
38 | // TODO: Send and receive multiple messages concurrently once async reads from stdin are possible
39 | for line in std::io::stdin().lines() {
40 | let line = line.context("failed to read line from STDIN")?;
41 | stream
42 | .write_all(format!("{line}\n").as_bytes())
43 | .await
44 | .context("failed to send line")?;
45 | }
46 | LinesStream::new(BufReader::new(stream).lines())
47 | .for_each(|line| async {
48 | match line {
49 | Err(e) => eprintln!("* failed to receive line: {e}"),
50 | Ok(line) => println!("{line}"),
51 | }
52 | })
53 | .await;
54 | Ok(())
55 | }
56 |
--------------------------------------------------------------------------------
/demos/chat-client/c/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #ifndef __wasi__
7 | #include
8 | #include
9 | #endif
10 |
11 | int main(int argc, char const *argv[]) {
12 | #ifdef __wasi__
13 | int fd_count = atoi(getenv("FD_COUNT"));
14 | if (fd_count != 4) {
15 | fprintf(stderr, "unexpected amount of file descriptors received:%d\n",
16 | fd_count);
17 | return -1;
18 | }
19 |
20 | char *stream_str = getenv("FD_NAMES");
21 | char *sep_at;
22 | for (int i = 0; i < 3; i++) {
23 | sep_at = strchr(stream_str, ':');
24 | stream_str = sep_at + 1;
25 | }
26 | if (stream_str == NULL) {
27 | fprintf(stderr, "failed to parse FD_NAMES\n");
28 | return -1;
29 | } else if (strcmp(stream_str, "server") != 0) {
30 | fprintf(stderr, "unknown socket name `%s`\n", stream_str);
31 | return -1;
32 | }
33 | int stream = 3;
34 | #else
35 | int sock = socket(AF_INET, SOCK_STREAM, 0);
36 | struct sockaddr_in serv_addr;
37 | serv_addr.sin_family = AF_INET;
38 | serv_addr.sin_port = htons(50000);
39 |
40 | if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
41 | fprintf(stderr, "invalid address/address not supported\n");
42 | return -1;
43 | }
44 |
45 | int stream = connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
46 | if (stream < 0) {
47 | fprintf(stderr, "connection failed\n");
48 | return -1;
49 | }
50 | #endif
51 | // TODO: Send and receive multiple messages concurrently once async reads from
52 | // stdin are possible
53 | while (1) {
54 | char line[1024];
55 | char c = '\0';
56 | int numBytes = 0;
57 | while (c != '\n') {
58 | c = getc(stdin);
59 | line[numBytes] = c;
60 | numBytes++;
61 | if (ferror(stdin)) {
62 | fprintf(stderr, "failed to read line from STDIN\n");
63 | return -1;
64 | }
65 | }
66 | line[numBytes] = '\0';
67 | printf("\nyou entered: %s\n", line);
68 | int ret = write(stream, line, numBytes);
69 | if (ret <= 0) {
70 | fprintf(stderr, "failed to send line\n");
71 | return -1;
72 | }
73 | }
74 | close(stream);
75 | }
76 |
--------------------------------------------------------------------------------
/demos/chat-client/web-ui/script.js:
--------------------------------------------------------------------------------
1 | function init() {
2 | var inactiveMessage = "Server is down"
3 | chatPopup = document.querySelector(".chat-popup")
4 | chatSubmit = document.querySelector(".chat-submit")
5 | chatHeader = document.querySelector(".chat-header")
6 | chatArea = document.querySelector(".chat-area")
7 | chatInput = document.querySelector(".chat-input")
8 | root = document.documentElement;
9 | chatPopup.style.display = "flex"
10 | var host = "http://localhost:8080"
11 |
12 | chatSubmit.addEventListener("click", () => {
13 | let userResponse = chatInput.value.trim();
14 | if (userResponse !== "") {
15 | setUserResponse();
16 | send(userResponse)
17 | }
18 | })
19 | }
20 |
21 | function userResponseBtn(e) {
22 | send(e.value);
23 | }
24 |
25 | // to submit user input when he presses enter
26 | function givenUserInput(e) {
27 | if (e.keyCode == 13) {
28 | let userResponse = chatInput.value.trim();
29 | if (userResponse !== "") {
30 | setUserResponse()
31 | send(userResponse)
32 | }
33 | }
34 | }
35 |
36 | // to display user message on UI
37 | function setUserResponse() {
38 | let userInput = chatInput.value;
39 | if (userInput) {
40 | let temp = `
${userInput}
`
41 | chatArea.innerHTML += temp;
42 | chatInput.value = ""
43 | } else {
44 | chatInput.disabled = false;
45 | }
46 | scrollToBottomOfResults();
47 | }
48 |
49 | function scrollToBottomOfResults() {
50 | chatArea.scrollTop = chatArea.scrollHeight;
51 | }
52 |
53 | function send(message) {
54 | chatInput.type = "text"
55 | passwordInput = false;
56 | chatInput.focus();
57 | console.log("User Message:", message)
58 | $.ajax({
59 | url: host,
60 | method: 'PUT',
61 | data: {
62 | message: message
63 | }
64 | });
65 | chatInput.focus();
66 | }
67 |
68 | function createChat() {
69 |
70 | host = "http://localhost:8080";
71 | init()
72 | const msg = document.querySelector(".msg");
73 | msg.innerText = "Welcome to Enarx Chat! Send a message to an Enarx Keep below:";
74 |
75 | const botTitle = document.querySelector(".bot-title");
76 | botTitle.innerText = "Enarx Chat";
77 | }
78 |
79 | createChat();
--------------------------------------------------------------------------------
/examples/rust/tokio/http/src/date.rs:
--------------------------------------------------------------------------------
1 | use std::cell::RefCell;
2 | use std::fmt::{self, Write};
3 | use std::str;
4 | use std::time::SystemTime;
5 |
6 | use httpdate::HttpDate;
7 |
8 | pub struct Now(());
9 |
10 | /// Returns a struct, which when formatted, renders an appropriate `Date`
11 | /// header value.
12 | pub fn now() -> Now {
13 | Now(())
14 | }
15 |
16 | // Gee Alex, doesn't this seem like premature optimization. Well you see
17 | // there Billy, you're absolutely correct! If your server is *bottlenecked*
18 | // on rendering the `Date` header, well then boy do I have news for you, you
19 | // don't need this optimization.
20 | //
21 | // In all seriousness, though, a simple "hello world" benchmark which just
22 | // sends back literally "hello world" with standard headers actually is
23 | // bottlenecked on rendering a date into a byte buffer. Since it was at the
24 | // top of a profile, and this was done for some competitive benchmarks, this
25 | // module was written.
26 | //
27 | // Just to be clear, though, I was not intending on doing this because it
28 | // really does seem kinda absurd, but it was done by someone else [1], so I
29 | // blame them! :)
30 | //
31 | // [1]: https://github.com/rapidoid/rapidoid/blob/f1c55c0555007e986b5d069fe1086e6d09933f7b/rapidoid-commons/src/main/java/org/rapidoid/commons/Dates.java#L48-L66
32 |
33 | struct LastRenderedNow {
34 | bytes: [u8; 128],
35 | amt: usize,
36 | unix_date: u64,
37 | }
38 |
39 | thread_local!(static LAST: RefCell = RefCell::new(LastRenderedNow {
40 | bytes: [0; 128],
41 | amt: 0,
42 | unix_date: 0,
43 | }));
44 |
45 | impl fmt::Display for Now {
46 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 | LAST.with(|cache| {
48 | let mut cache = cache.borrow_mut();
49 | let now = SystemTime::now();
50 | let now_unix = now
51 | .duration_since(SystemTime::UNIX_EPOCH)
52 | .map(|since_epoch| since_epoch.as_secs())
53 | .unwrap_or(0);
54 | if cache.unix_date != now_unix {
55 | cache.update(now, now_unix);
56 | }
57 | f.write_str(cache.buffer())
58 | })
59 | }
60 | }
61 |
62 | impl LastRenderedNow {
63 | fn buffer(&self) -> &str {
64 | str::from_utf8(&self.bytes[..self.amt]).unwrap()
65 | }
66 |
67 | fn update(&mut self, now: SystemTime, now_unix: u64) {
68 | self.amt = 0;
69 | self.unix_date = now_unix;
70 | write!(LocalBuffer(self), "{}", HttpDate::from(now)).unwrap();
71 | }
72 | }
73 |
74 | struct LocalBuffer<'a>(&'a mut LastRenderedNow);
75 |
76 | impl fmt::Write for LocalBuffer<'_> {
77 | fn write_str(&mut self, s: &str) -> fmt::Result {
78 | let start = self.0.amt;
79 | let end = start + s.len();
80 | self.0.bytes[start..end].copy_from_slice(s.as_bytes());
81 | self.0.amt += s.len();
82 | Ok(())
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/examples/rust/mio/echo-tcp/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "cfg-if"
7 | version = "1.0.0"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
10 |
11 | [[package]]
12 | name = "env_logger"
13 | version = "0.9.0"
14 | source = "registry+https://github.com/rust-lang/crates.io-index"
15 | checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
16 | dependencies = [
17 | "log",
18 | ]
19 |
20 | [[package]]
21 | name = "libc"
22 | version = "0.2.132"
23 | source = "registry+https://github.com/rust-lang/crates.io-index"
24 | checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
25 |
26 | [[package]]
27 | name = "log"
28 | version = "0.4.17"
29 | source = "registry+https://github.com/rust-lang/crates.io-index"
30 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
31 | dependencies = [
32 | "cfg-if",
33 | ]
34 |
35 | [[package]]
36 | name = "mio"
37 | version = "0.8.4"
38 | source = "registry+https://github.com/rust-lang/crates.io-index"
39 | checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
40 | dependencies = [
41 | "libc",
42 | "log",
43 | "wasi",
44 | "windows-sys",
45 | ]
46 |
47 | [[package]]
48 | name = "mio-echo-tcp"
49 | version = "0.2.0"
50 | dependencies = [
51 | "env_logger",
52 | "mio",
53 | ]
54 |
55 | [[package]]
56 | name = "wasi"
57 | version = "0.11.0+wasi-snapshot-preview1"
58 | source = "registry+https://github.com/rust-lang/crates.io-index"
59 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
60 |
61 | [[package]]
62 | name = "windows-sys"
63 | version = "0.36.1"
64 | source = "registry+https://github.com/rust-lang/crates.io-index"
65 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
66 | dependencies = [
67 | "windows_aarch64_msvc",
68 | "windows_i686_gnu",
69 | "windows_i686_msvc",
70 | "windows_x86_64_gnu",
71 | "windows_x86_64_msvc",
72 | ]
73 |
74 | [[package]]
75 | name = "windows_aarch64_msvc"
76 | version = "0.36.1"
77 | source = "registry+https://github.com/rust-lang/crates.io-index"
78 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
79 |
80 | [[package]]
81 | name = "windows_i686_gnu"
82 | version = "0.36.1"
83 | source = "registry+https://github.com/rust-lang/crates.io-index"
84 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
85 |
86 | [[package]]
87 | name = "windows_i686_msvc"
88 | version = "0.36.1"
89 | source = "registry+https://github.com/rust-lang/crates.io-index"
90 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
91 |
92 | [[package]]
93 | name = "windows_x86_64_gnu"
94 | version = "0.36.1"
95 | source = "registry+https://github.com/rust-lang/crates.io-index"
96 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
97 |
98 | [[package]]
99 | name = "windows_x86_64_msvc"
100 | version = "0.36.1"
101 | source = "registry+https://github.com/rust-lang/crates.io-index"
102 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
103 |
--------------------------------------------------------------------------------
/demos/chat-client/c++/assets/style.css:
--------------------------------------------------------------------------------
1 | @import "https://cdnjs.cloudflare.com/ajax/libs/material-design-icons/3.0.1/iconfont/material-icons.min.css";
2 | * {
3 | margin: 0;
4 | padding: 0;
5 | box-sizing: border-box;
6 | }
7 |
8 | :root {
9 | --chat-window-total-width: 380px;
10 | --chat-window-height: 500px;
11 | --chat-window-color-theme: #1e90ff;
12 | --chat-window-bg-color: #fff;
13 | --chat-send-button: #1e90ff;
14 | --chat-user-msg-bg: #ddd;
15 | --chat-header-bg: linear-gradient(160deg, dodgerblue 0%, #80D0C7 100%);
16 | }
17 |
18 | body {
19 | font-family: Arial, Helvetica, sans-serif;
20 | background-color: #e5e5e5;
21 | display: flex;
22 | justify-content: center;
23 | height: 100vh;
24 | width: 100%;
25 | }
26 |
27 | section {
28 | max-width: 1100px;
29 | margin: auto;
30 | text-align: center;
31 | padding: 0 1rem;
32 | }
33 |
34 | h1 {
35 | font-size: 3rem;
36 | margin-bottom: 2rem;
37 | }
38 |
39 | p {
40 | font-size: 2rem;
41 | }
42 |
43 | .icon {
44 | transform: scale(1.2);
45 | }
46 |
47 | .stop-btn {
48 | padding: 5px;
49 | margin-top: 10px;
50 | }
51 |
52 | .chat-submit:hover {
53 | opacity: 1;
54 | }
55 |
56 | .chat-area {
57 | height: 300px;
58 | width: 600px;
59 | overflow-y: auto;
60 | overflow-x: hidden;
61 | background-color: var(--chat-window-bg-color);
62 | border-radius: 30px;
63 | margin: 20px;
64 | }
65 |
66 | .msg {
67 | background-color: var(--chat-window-color-theme);
68 | color: white;
69 | padding: 0.5rem;
70 | border-radius: 5px;
71 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
72 | }
73 |
74 | .user-msg {
75 | display: flex;
76 | align-items: center;
77 | margin-left: 10px;
78 | }
79 |
80 | .user-msg .msg {
81 | background-color: var(--chat-user-msg-bg);
82 | color: black;
83 | margin: 0.5rem;
84 | padding: 0.5rem;
85 | border-radius: 5px;
86 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
87 | word-break: break-all;
88 | text-align: left;
89 | }
90 |
91 | .msg-image {
92 | max-width: 90%;
93 | max-height: 400px;
94 | }
95 |
96 | .chat-input-area {
97 | position: relative;
98 | display: flex;
99 | justify-content: center;
100 | }
101 |
102 | .chat-input {
103 | width: 100%;
104 | border: 1px solid #ccc;
105 | padding: 0.5rem;
106 | font-size: 1rem;
107 | border-radius: 5px;
108 | height: 2.2rem;
109 | margin-bottom: 0.5rem;
110 | margin-left: 0.5rem;
111 | outline-color: var(--chat-window-color-theme);
112 | }
113 |
114 | .chat-submit {
115 | padding: 0.25rem 0.5rem;
116 | margin-left: 0.5rem;
117 | background-color: var(--chat-send-button);
118 | color: white;
119 | display: flex;
120 | justify-content: center;
121 | align-items: center;
122 | border-radius: 5px;
123 | border: none;
124 | outline: none;
125 | cursor: pointer;
126 | margin-bottom: 0.5rem;
127 | margin-right: 0.5rem;
128 | /* opacity: 0.8;
129 | transition: opacity 0.3s; */
130 | }
131 |
132 | .show {
133 | display: flex;
134 | }
135 |
136 | .btn-primary {
137 | /* background-color: #0096fe; */
138 | border: 1px solid var(--chat-window-color-theme);
139 | outline: none;
140 | display: inline-block;
141 | color: var(--chat-window-color-theme);
142 | padding: 5px 15px;
143 | border-radius: 4px;
144 | cursor: pointer;
145 | margin: 5px;
146 | font-weight: bold;
147 | }
148 |
149 | .btn-primary:hover {
150 | background-color: #0096fe;
151 | color: #fff;
152 | transform: scale(1.1);
153 | }
154 |
155 | @media (max-width:500px) {
156 | .chat-popup {
157 | bottom: 120px;
158 | right: 10%;
159 | width: 80vw;
160 | height: 100%;
161 | }
162 | }
--------------------------------------------------------------------------------
/examples/rust/mio/echo-tcp/README.md:
--------------------------------------------------------------------------------
1 | # MIO TCP Echo Server Example
2 |
3 | This example is an adapted version of the upstream `mio` crate `tcp_server` example.
4 |
5 | It currently depends on a modified version of `mio` with support for WASI.
6 |
7 | The added part creates the `TcpListener` from file descriptor `3`,
8 | if the `LISTEN_FDS` environment variable is set.
9 |
10 |
11 | ## How to run this example
12 |
13 | ### Install `enarx`
14 |
15 | Either from `crates.io` or from this git repository:
16 |
17 | ```
18 | $ cd
19 | $ cargo install --path .
20 | ```
21 |
22 | ### Build the WASM application
23 |
24 | It will need at least rust version `>= 1.60.0`.
25 |
26 | ```
27 | $ cd
28 | $ cargo build --target wasm32-wasi -p tcp_server
29 | […]
30 | Finished dev [unoptimized + debuginfo] target(s) in 1.44s
31 | ```
32 |
33 | ### Run it
34 |
35 | ```
36 | $ enarx run --wasmcfgfile examples/tcp_server/Enarx.toml target/wasm32-wasi/debug/tcp_server.wasm
37 | [WARN wasmldr] 🌭DEV-ONLY BUILD, NOT FOR PRODUCTION USE🌭
38 | [DEBUG wasmldr] parsing argv
39 | [INFO wasmldr] opts: RunOptions {
40 | module: None,
41 | config: None,
42 | }
43 | [INFO wasmldr] reading module from fd 3
44 | [INFO wasmldr] reading config from fd 4
45 | [INFO wasmldr] running workload
46 | [DEBUG wasmldr::workload] configuring wasmtime engine
47 | [DEBUG wasmldr::workload] instantiating wasmtime linker
48 | [DEBUG wasmldr::workload] adding WASI to linker
49 | [DEBUG wasmldr::workload] creating WASI context
50 | [DEBUG wasmldr::workload] Processing loader config Config {
51 | files: Some(
52 | [
53 | File {
54 | type_: "stdio",
55 | name: "stdin",
56 | addr: None,
57 | port: None,
58 | },
59 | File {
60 | type_: "stdio",
61 | name: "stdout",
62 | addr: None,
63 | port: None,
64 | },
65 | File {
66 | type_: "stdio",
67 | name: "stderr",
68 | addr: None,
69 | port: None,
70 | },
71 | File {
72 | type_: "tcp_listen",
73 | name: "TEST_TCP_LISTEN",
74 | addr: None,
75 | port: Some(
76 | 9000,
77 | ),
78 | },
79 | ],
80 | ),
81 | }
82 | [DEBUG wasmldr::workload] creating wasmtime Store
83 | [DEBUG wasmldr::workload] instantiating module from bytes
84 | [DEBUG wasmldr::workload] adding module to store
85 | [DEBUG wasmldr::workload] getting module's default function
86 | [DEBUG wasmldr::workload] calling function
87 | Using preopened socket FD 3
88 | You can connect to the server using `nc`:
89 | $ nc
90 | You'll see our welcome message and anything you type will be printed here.
91 |
92 | ```
93 |
94 | Then from another shell:
95 | ```
96 | $ echo ECHO | ncat 127.0.0.1 9000
97 | Hello world!
98 | ECHO
99 | ```
100 |
101 | or, if you don't have `ncat`:
102 | ```
103 | $ echo ECHO | netcat -q 1 127.0.0.1 9000
104 | Hello world!
105 | ECHO
106 | ```
107 |
108 | and see the output of the Enarx keep:
109 | ```
110 | Accepted connection from: 0.0.0.0:0
111 | Received data: ECHO
112 | Connection closed
113 | ```
114 |
115 | To modify the port and listen address see the `Enarx.toml` file in the
116 | example directory.
117 |
118 | ### Transparent TLS
119 |
120 | Enarx automatically wraps the TCP connection in a TLS session, if you change the `proto` field in the `Enarx.toml` from `tcp` to `tls`.
121 | In this case you can connect to the echo server via `openssl`
122 |
123 | ```
124 | $ openssl s_client -connect 127.0.0.1:9000
125 | ```
126 |
127 | Enter your messages manually, and to end the connection enter `ctrl-d` or `Q`.
128 |
--------------------------------------------------------------------------------
/demos/chat-server/rust/src/main.rs:
--------------------------------------------------------------------------------
1 | use std::env;
2 | use std::error::Error;
3 | use std::fmt::Display;
4 | #[cfg(target_os = "wasi")]
5 | use std::os::wasi::io::FromRawFd;
6 | use std::str::FromStr;
7 |
8 | use anyhow::{bail, Context};
9 | use futures::{join, select, Stream, StreamExt, TryFutureExt};
10 | use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
11 | use tokio::net::{TcpListener, TcpStream};
12 | use tokio::sync::broadcast;
13 | use tokio::sync::broadcast::Sender;
14 | use tokio_stream::wrappers::{BroadcastStream, LinesStream, TcpListenerStream};
15 | use ulid::Ulid;
16 |
17 | /// Handles the peer TCP stream I/O.
18 | async fn handle_io(
19 | peer: &mut TcpStream,
20 | tx: &Sender,
21 | rx: impl Stream> + Unpin,
22 | id: impl Display,
23 | ) -> anyhow::Result<()> {
24 | let (input, mut output) = peer.split();
25 | let mut input = LinesStream::new(BufReader::new(input).lines()).fuse();
26 | let mut rx = rx.fuse();
27 | loop {
28 | select! {
29 | line = input.next() => match line {
30 | None => return Ok(()),
31 | Some(Err(e)) => bail!("failed to receive line from {id}: {e}"),
32 | Some(Ok(line)) => if let Err(e) = tx.send(format!("{id}: {line}")) {
33 | bail!("failed to send line from {id}: {e}")
34 | },
35 | },
36 | line = rx.next() => match line {
37 | None => return Ok(()),
38 | Some(Err(e)) => bail!("failed to receive line for {id}: {e}"),
39 | Some(Ok(line)) => if let Err(e) = output.write_all(format!("{line}\n").as_bytes()).await {
40 | bail!("failed to send line to {id}: {e}")
41 | },
42 | },
43 | complete => return Ok(()),
44 | };
45 | }
46 | }
47 |
48 | /// Handles the peer TCP stream.
49 | async fn handle(peer: &mut TcpStream, tx: &Sender) {
50 | let id = Ulid::new();
51 |
52 | let rx = BroadcastStream::new(tx.subscribe());
53 | if let Err(e) = tx.send(format!("{id} joined the chat")) {
54 | eprintln!("failed to send {id} join event to peers: {e}");
55 | return;
56 | }
57 |
58 | _ = handle_io(peer, tx, rx, id)
59 | .map_err(|e| eprintln!("failed to handle {id} peer I/O: {e}"))
60 | .await;
61 |
62 | if let Err(e) = tx.send(format!("{id} left the chat")) {
63 | eprintln!("failed to send {id} leave event to peers: {e}")
64 | }
65 | }
66 |
67 | #[tokio::main(flavor = "current_thread")]
68 | async fn main() -> anyhow::Result<()> {
69 | let fd_count = env::var("FD_COUNT").context("failed to lookup `FD_COUNT`")?;
70 | let fd_count = usize::from_str(&fd_count).context("failed to parse `FD_COUNT`")?;
71 | assert_eq!(
72 | fd_count,
73 | 4, // STDIN, STDOUT, STDERR and a socket
74 | "unexpected amount of file descriptors received"
75 | );
76 | let listener = match env::var("FD_NAMES")
77 | .context("failed to lookup `FD_NAMES`")?
78 | .splitn(fd_count, ':')
79 | .nth(3)
80 | {
81 | None => bail!("failed to parse `FD_NAMES`"),
82 | Some("ingest") => {
83 | let l = unsafe { std::net::TcpListener::from_raw_fd(3) };
84 | l.set_nonblocking(true)
85 | .context("failed to set non-blocking flag on socket")?;
86 | TcpListener::from_std(l)
87 | .context("failed to initialize Tokio listener")
88 | .map(TcpListenerStream::new)?
89 | }
90 | Some(name) => bail!("unknown socket name `{name}`"),
91 | };
92 |
93 | let (tx, rx) = broadcast::channel(128);
94 | join!(
95 | BroadcastStream::new(rx).for_each(|line| async {
96 | match line {
97 | Err(e) => eprintln!("failed to receive line: {e}"),
98 | Ok(line) => println!("> {line}"),
99 | }
100 | }),
101 | listener.for_each_concurrent(None, |peer| async {
102 | match peer {
103 | Err(e) => eprintln!("failed to accept connection: {e}"),
104 | Ok(mut peer) => handle(&mut peer, &tx).await,
105 | };
106 | })
107 | );
108 | Ok(())
109 | }
110 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/src/main.rs:
--------------------------------------------------------------------------------
1 | //! A "tiny" example of HTTP request/response handling using transports.
2 | //!
3 | //! This example is intended for *learning purposes* to see how various pieces
4 | //! hook up together and how HTTP can get up and running. Note that this example
5 | //! is written with the restriction that it *can't* use any "big" library other
6 | //! than Tokio, if you'd like a "real world" HTTP library you likely want a
7 | //! crate like Hyper.
8 | //!
9 | //! Code here is based on the `tinyhttp` example of tokio.
10 |
11 | #![warn(rust_2018_idioms)]
12 |
13 | use ::http::{Request, Response, StatusCode};
14 | use futures::SinkExt;
15 | use http::header::{CACHE_CONTROL, CONTENT_TYPE, LAST_MODIFIED};
16 | use protocol::Http;
17 | use std::os::wasi::io::FromRawFd;
18 | use std::{error::Error, io};
19 | use tokio::net::{TcpListener, TcpStream};
20 | use tokio_stream::StreamExt;
21 | use tokio_util::codec::Framed;
22 |
23 | mod date;
24 | mod protocol;
25 |
26 | fn enarx_logo() -> &'static [u8] {
27 | include_bytes!("enarx-white.svg")
28 | }
29 |
30 | fn fireworks_gif() -> &'static [u8] {
31 | include_bytes!("fireworks.gif")
32 | }
33 |
34 | fn index_page() -> &'static [u8] {
35 | include_bytes!("index.html")
36 | }
37 |
38 | const NOT_FOUND: &str = r#"
39 |
40 |
41 | 404 Not Found
42 |
43 |
Not Found
44 |
The requested URL was not found on this server.
45 |
46 | "#;
47 |
48 | #[tokio::main(flavor = "current_thread")]
49 | async fn main() -> Result<(), Box> {
50 | // Parse the arguments, bind the TCP socket we'll be listening to, spin up
51 | // our worker threads, and start shipping sockets to those worker threads.
52 | /* let addr = env::args()
53 | .nth(1)
54 | .unwrap_or_else(|| "127.0.0.1:8080".to_string());
55 | let server = TcpListener::bind(&addr).await?;
56 | */
57 | let listener = unsafe { std::net::TcpListener::from_raw_fd(3) };
58 | listener.set_nonblocking(true).unwrap();
59 | let server = TcpListener::from_std(listener).unwrap();
60 |
61 | loop {
62 | eprintln!("Accepting connections");
63 | let stream_res = server.accept().await;
64 | match stream_res {
65 | Err(e) => {
66 | eprintln!("failed to accept connection; error = {}", e);
67 | }
68 | Ok((stream, _)) => {
69 | tokio::spawn(async move {
70 | if let Err(e) = process(stream).await {
71 | eprintln!("failed to process connection; error = {}", e);
72 | }
73 | });
74 | }
75 | }
76 | }
77 | }
78 |
79 | async fn process(stream: TcpStream) -> Result<(), Box> {
80 | let mut transport = Framed::new(stream, Http);
81 |
82 | while let Some(request) = transport.next().await {
83 | match request {
84 | Ok(request) => {
85 | let response = respond(request).await?;
86 | transport.send(response).await?;
87 | }
88 | Err(e) => return Err(e.into()),
89 | }
90 | }
91 |
92 | Ok(())
93 | }
94 |
95 | async fn respond(req: Request<()>) -> Result>, Box> {
96 | let response = Response::builder();
97 | let now_str = date::now().to_string();
98 | let response = match req.uri().path() {
99 | "/enarx-logo.svg" => response
100 | .status(StatusCode::OK)
101 | .header(CONTENT_TYPE, "image/svg+xml")
102 | .header(LAST_MODIFIED, &now_str)
103 | .header(CACHE_CONTROL, "max-age=60, public")
104 | .body(enarx_logo().to_vec()),
105 | "/fireworks.gif" => response
106 | .status(StatusCode::OK)
107 | .header(CONTENT_TYPE, "image/gif")
108 | .header(LAST_MODIFIED, &now_str)
109 | .header(CACHE_CONTROL, "max-age=60, public")
110 | .body(fireworks_gif().to_vec()),
111 | "/" => response
112 | .status(StatusCode::OK)
113 | .header(CONTENT_TYPE, "text/html; charset=UTF-8")
114 | .header(LAST_MODIFIED, &now_str)
115 | .header(CACHE_CONTROL, "max-age=60, public")
116 | .body(index_page().to_vec()),
117 | _ => response
118 | .status(StatusCode::NOT_FOUND)
119 | .header(CONTENT_TYPE, "text/html; charset=UTF-8")
120 | .header(LAST_MODIFIED, &now_str)
121 | .header(CACHE_CONTROL, "no-store, must-revalidate")
122 | .body(NOT_FOUND.as_bytes().to_vec()),
123 | };
124 |
125 | let response = response.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
126 |
127 | Ok(response)
128 | }
129 |
--------------------------------------------------------------------------------
/examples/rust/tokio/http/src/protocol.rs:
--------------------------------------------------------------------------------
1 | use bytes::BytesMut;
2 | use http::{HeaderValue, Request, Response};
3 | use std::io;
4 | use tokio_util::codec::{Decoder, Encoder};
5 |
6 | pub struct Http;
7 |
8 | /// Implementation of encoding an HTTP response into a `BytesMut`, basically
9 | /// just writing out an HTTP/1.1 response.
10 | impl Encoder>> for Http {
11 | type Error = io::Error;
12 |
13 | fn encode(&mut self, item: Response>, dst: &mut BytesMut) -> io::Result<()> {
14 | use crate::date;
15 | use std::fmt;
16 | use std::fmt::Write;
17 |
18 | write!(
19 | BytesWrite(dst),
20 | "\
21 | HTTP/1.1 {}\r\n\
22 | Server: Example\r\n\
23 | Content-Length: {}\r\n\
24 | Date: {}\r\n\
25 | ",
26 | item.status(),
27 | item.body().len(),
28 | date::now()
29 | )
30 | .unwrap();
31 |
32 | for (k, v) in item.headers() {
33 | dst.extend_from_slice(k.as_str().as_bytes());
34 | dst.extend_from_slice(b": ");
35 | dst.extend_from_slice(v.as_bytes());
36 | dst.extend_from_slice(b"\r\n");
37 | }
38 |
39 | dst.extend_from_slice(b"\r\n");
40 | dst.extend_from_slice(item.body());
41 |
42 | return Ok(());
43 |
44 | // Right now `write!` on `Vec` goes through io::Write and is not
45 | // super speedy, so inline a less-crufty implementation here which
46 | // doesn't go through io::Error.
47 | struct BytesWrite<'a>(&'a mut BytesMut);
48 |
49 | impl fmt::Write for BytesWrite<'_> {
50 | fn write_str(&mut self, s: &str) -> fmt::Result {
51 | self.0.extend_from_slice(s.as_bytes());
52 | Ok(())
53 | }
54 |
55 | fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
56 | fmt::write(self, args)
57 | }
58 | }
59 | }
60 | }
61 |
62 | /// Implementation of decoding an HTTP request from the bytes we've read so far.
63 | /// This leverages the `httparse` crate to do the actual parsing and then we use
64 | /// that information to construct an instance of a `http::Request` object,
65 | /// trying to avoid allocations where possible.
66 | impl Decoder for Http {
67 | type Item = Request<()>;
68 | type Error = io::Error;
69 |
70 | fn decode(&mut self, src: &mut BytesMut) -> io::Result