Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for networking #123

Merged
merged 1 commit into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@ jobs:
env:
OUTPUT_DIR: ${{ github.workspace }}/builds
steps:
- uses: actions/setup-go@v4
with:
go-version: 1.21.x
- uses: actions/checkout@v4
- name: Build
- name: Build binaries
run: |
PREFIX=${OUTPUT_DIR} make artifacts
- name: Build wasm image
run: |
PREFIX=${OUTPUT_DIR} make c2w-net-proxy.wasm
- name: sha256sum
run: |
( cd ${OUTPUT_DIR}; sha256sum * ) > "${GITHUB_WORKSPACE}/SHA256SUMS"
mv "${GITHUB_WORKSPACE}/SHA256SUMS" "${OUTPUT_DIR}/SHA256SUMS"
- name: Create Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
SHA256SUM_OF_SHA256SUM=$(sha256sum ${OUTPUT_DIR}/SHA256SUMS | cut -d ' ' -f 1)
SHA256SUM_OF_SHA256SUMS=$(sha256sum ${OUTPUT_DIR}/SHA256SUMS | cut -d ' ' -f 1)
RELEASE_TAG="${GITHUB_REF##*/}"
MINIMAL_TAR=$(ls -1 ${OUTPUT_DIR} | grep container2wasm-v | head -1)
MINIMAL_TAR_LIST=$(tar --list -vvf ${OUTPUT_DIR}/${MINIMAL_TAR})
Expand All @@ -50,9 +58,13 @@ jobs:

</details>

## About \`c2w-net-proxy.wasm\`

Please refer to [the document about networking for container on browser](https://github.com/ktock/container2wasm/tree/${RELEASE_TAG}/examples/networking/fetch/) for details and usage.

---

The sha256sum of SHA256SUM is \`${SHA256SUM_OF_SHA256SUM}\`
The sha256sum of SHA256SUMS is \`${SHA256SUM_OF_SHA256SUMS}\`

EOF
ASSET_FLAGS=()
Expand Down
13 changes: 7 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ jobs:
make
ls -al ./out/c2w
if ldd ./out/c2w ; then echo "must be static binary" ; exit 1 ; fi
ls -al ./out/c2w-net
if ldd ./out/c2w-net ; then echo "must be static binary" ; exit 1 ; fi

test:
runs-on: ubuntu-22.04
Expand All @@ -30,16 +32,15 @@ jobs:
fail-fast: false
matrix:
target: ["TestWasmtime", "TestWamr", "TestWasmer", "TestWazero", "TestWasmedge"]
arch: ["x86_64", "(riscv64|aarch64)"]
steps:
- uses: actions/checkout@v4
- name: x86_64
env:
GO_TEST_FLAGS: -run ${{ matrix.target }}/.*arch=x86_64.*
- name: binfmt
run: |
make test
- name: riscv64
docker run --privileged --rm tonistiigi/binfmt --install riscv64
- name: test
env:
GO_TEST_FLAGS: -run ${{ matrix.target }}/.*arch=(riscv64|aarch64).*
GO_TEST_FLAGS: -run ${{ matrix.target }}/.*arch=${{ matrix.arch }}.*
run: |
make test

Expand Down
30 changes: 17 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ COPY --link --from=oci-image-src / /oci
# <vm-rootfs>/oci/rootfs : rootfs dir this Dockerfile creates container's rootfs and used by the container.
# <vm-rootfs>/oci/image.json : container image config file used by init
# <vm-rootfs>/oci/spec.json : container runtime spec file used by init
# <vm-rootfs>/etc/initconfig.json : configuration file for init
RUN mkdir -p /out/oci/rootfs /out/oci/bundle /out/etc && \
# <vm-rootfs>/oci/initconfig.json : configuration file for init
RUN mkdir -p /out/oci/rootfs /out/oci/bundle && \
IS_WIZER=false && \
if test "${OPTIMIZATION_MODE}" = "wizer" ; then IS_WIZER=true ; fi && \
NO_VMTOUCH_F=false && \
Expand All @@ -65,7 +65,7 @@ RUN mkdir -p /out/oci/rootfs /out/oci/bundle /out/etc && \
--runtime-config-path=/oci/spec.json \
--rootfs-path=/oci/rootfs \
/oci "${TARGETPLATFORM}" /out/oci/rootfs && \
mv image.json spec.json /out/oci/ && mv initconfig.json /out/etc/
mv image.json spec.json /out/oci/ && mv initconfig.json /out/oci/

FROM ubuntu:22.04 AS gcc-riscv64-linux-gnu-base
RUN apt-get update && apt-get install -y gcc-riscv64-linux-gnu libc-dev-riscv64-cross git make
Expand Down Expand Up @@ -162,10 +162,11 @@ RUN git clone -b $BUSYBOX_VERSION --depth 1 https://git.busybox.net/busybox
WORKDIR /work/busybox
RUN make CROSS_COMPILE=riscv64-linux-gnu- LDFLAGS=--static defconfig
RUN make CROSS_COMPILE=riscv64-linux-gnu- LDFLAGS=--static -j$(nproc)
RUN mkdir -p /out && mv busybox /out/busybox
RUN mkdir -p /out/bin && mv busybox /out/bin/busybox
RUN make LDFLAGS=--static defconfig
RUN make LDFLAGS=--static -j$(nproc)
RUN for i in $(./busybox --list) ; do ln -s busybox /out/$i ; done
RUN for i in $(./busybox --list) ; do ln -s busybox /out/bin/$i ; done
RUN mkdir -p /out/usr/share/udhcpc/ && cp ./examples/udhcp/simple.script /out/usr/share/udhcpc/default.script

FROM gcc-riscv64-linux-gnu-base AS tini-riscv64-dev
# https://github.com/krallin/tini#building-tini
Expand All @@ -179,15 +180,14 @@ RUN cmake . && make && mkdir /out/ && mv tini /out/

FROM ubuntu:22.04 AS rootfs-riscv64-dev
RUN apt-get update -y && apt-get install -y mkisofs
COPY --link --from=busybox-riscv64-dev /out/ /rootfs/bin/
COPY --link --from=busybox-riscv64-dev /out/ /rootfs/
COPY --link --from=binfmt-dev / /rootfs/
COPY --link --from=runc-riscv64-dev /out/runc /rootfs/sbin/runc
COPY --link --from=bundle-dev /out/ /rootfs/
COPY --link --from=init-riscv64-dev /out/init /rootfs/sbin/init
COPY --link --from=vmtouch-riscv64-dev /out/vmtouch /rootfs/bin/
COPY --link --from=tini-riscv64-dev /out/tini /rootfs/sbin/tini
RUN mkdir -p /rootfs/proc /rootfs/sys /rootfs/mnt /rootfs/run /rootfs/tmp /rootfs/dev /rootfs/var && mknod /rootfs/dev/null c 1 3 && chmod 666 /rootfs/dev/null
RUN touch /rootfs/etc/resolv.conf /rootfs/etc/hosts
RUN mkdir -p /rootfs/proc /rootfs/sys /rootfs/mnt /rootfs/run /rootfs/tmp /rootfs/dev /rootfs/var /rootfs/etc && mknod /rootfs/dev/null c 1 3 && chmod 666 /rootfs/dev/null
RUN mkdir /out/ && mkisofs -l -J -R -o /out/rootfs.bin /rootfs/
# RUN isoinfo -i /out/rootfs.bin -l

Expand Down Expand Up @@ -320,10 +320,11 @@ RUN git clone -b $BUSYBOX_VERSION --depth 1 https://git.busybox.net/busybox
WORKDIR /work/busybox
RUN make CROSS_COMPILE=x86_64-linux-gnu- LDFLAGS=--static defconfig
RUN make CROSS_COMPILE=x86_64-linux-gnu- LDFLAGS=--static -j$(nproc)
RUN mkdir -p /out && mv busybox /out/busybox
RUN mkdir -p /out/bin && mv busybox /out/bin/busybox
RUN make LDFLAGS=--static defconfig
RUN make LDFLAGS=--static -j$(nproc)
RUN for i in $(./busybox --list) ; do ln -s busybox /out/$i ; done
RUN for i in $(./busybox --list) ; do ln -s busybox /out/bin/$i ; done
RUN mkdir -p /out/usr/share/udhcpc/ && cp ./examples/udhcp/simple.script /out/usr/share/udhcpc/default.script

FROM golang-base AS runc-amd64-dev
ARG RUNC_VERSION
Expand Down Expand Up @@ -385,14 +386,13 @@ RUN git clone https://github.com/hoytech/vmtouch.git && \

FROM ubuntu:22.04 AS rootfs-amd64-dev
RUN apt-get update -y && apt-get install -y mkisofs
COPY --link --from=busybox-amd64-dev /out/ /rootfs/bin/
COPY --link --from=busybox-amd64-dev /out/ /rootfs/
COPY --link --from=runc-amd64-dev /out/runc /rootfs/sbin/runc
COPY --link --from=bundle-dev /out/ /rootfs/
COPY --link --from=init-amd64-dev /out/init /rootfs/sbin/init
COPY --link --from=vmtouch-amd64-dev /out/vmtouch /rootfs/bin/
COPY --link --from=tini-amd64-dev /out/tini /rootfs/sbin/tini
RUN mkdir -p /rootfs/proc /rootfs/sys /rootfs/mnt /rootfs/run /rootfs/tmp /rootfs/dev /rootfs/var /rootfs/etc && mknod /rootfs/dev/null c 1 3 && chmod 666 /rootfs/dev/null
RUN touch /rootfs/etc/resolv.conf /rootfs/etc/hosts
RUN mkdir /out/ && mkisofs -l -J -R -o /out/rootfs.bin /rootfs/
# RUN isoinfo -i /out/rootfs.bin -l

Expand Down Expand Up @@ -450,6 +450,10 @@ RUN ${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -O2
RUN ${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -O2 --target=wasm32-unknown-wasi -Wl,--export=wasm_setjmp -c jmp.S -o jmp_wrapper.o
RUN ${WASI_SDK_PATH}/bin/wasm-ld jmp.o jmp_wrapper.o --export=wasm_setjmp --export=wasm_longjmp --export=handle_jmp --no-entry -r -o jmp

COPY --link --from=assets ./patches/bochs/vfs /vfs
WORKDIR /vfs
RUN ${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -O2 --target=wasm32-unknown-wasi -c vfs.c -I . -o vfs.o

COPY --link --from=assets /patches/bochs/Bochs /Bochs
WORKDIR /Bochs/bochs
ARG INIT_DEBUG
Expand All @@ -461,7 +465,7 @@ RUN LOGGING_FLAG=--disable-logging && \
./configure --host wasm32-unknown-wasi --enable-x86-64 --with-nogui --enable-usb --enable-usb-ehci \
--disable-large-ramfile --disable-show-ips --disable-stats ${LOGGING_FLAG} \
--enable-repeat-speedups --enable-fast-function-calls --disable-trace-linking --enable-handlers-chaining # TODO: --enable-trace-linking causes "out of bounds memory access"
RUN make -j$(nproc) bochs EMU_DEPS="/tools/wasi-vfs/libwasi_vfs.a /jmp/jmp -lrt"
RUN make -j$(nproc) bochs EMU_DEPS="/tools/wasi-vfs/libwasi_vfs.a /jmp/jmp /vfs/vfs.o -lrt"
RUN /binaryen/binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt bochs --asyncify -O2 -o bochs.async --pass-arg=asyncify-ignore-imports
RUN mv bochs.async bochs

Expand Down
14 changes: 14 additions & 0 deletions Dockerfile.test
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ COPY ./tests/wazero /wazero
WORKDIR /wazero
RUN go build -o /out/wazero-test main.go

FROM golang:1.21 AS httphello-dev
COPY ./tests/httphello /httphello
WORKDIR /httphello
RUN go build -o /out/httphello main.go

FROM golang:1.21 AS c2w-net-proxy-test-dev
COPY ./tests/c2w-net-proxy-test /c2w-net-proxy-test
WORKDIR /c2w-net-proxy-test
RUN go build -o /out/c2w-net-proxy-test main.go

FROM ubuntu:22.04
ARG BUILDX_VERSION
ARG DOCKER_VERSION
Expand Down Expand Up @@ -58,6 +68,8 @@ RUN wget https://github.com/WasmEdge/WasmEdge/releases/download/${WASMEDGE_VERSI

# install wazero
COPY --from=wazero-test-dev /out/wazero-test /usr/local/bin/
COPY --from=httphello-dev /out/httphello /usr/local/bin/
COPY --from=c2w-net-proxy-test-dev /out/c2w-net-proxy-test /usr/local/bin/

# install golang
RUN wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz
Expand All @@ -69,6 +81,8 @@ ENV PATH=$PATH:/usr/local/go/bin
COPY . /test/
WORKDIR /test/
RUN go build -o /usr/local/bin/ ./cmd/c2w
RUN go build -o /usr/local/bin/ ./cmd/c2w-net
RUN cd extras/c2w-net-proxy/ ; GOOS=wasip1 GOARCH=wasm go build -o /opt/c2w-net-proxy.wasm .

ENTRYPOINT ["dockerd-entrypoint.sh"]
CMD []
21 changes: 14 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,31 @@ GO_EXTRA_LDFLAGS=-extldflags '-static'
GO_LD_FLAGS=-ldflags '-s -w -X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) $(GO_EXTRA_LDFLAGS)'
GO_BUILDTAGS=-tags "osusergo netgo static_build"

all: c2w
all: c2w c2w-net

build: c2w
build: c2w c2w-net

c2w:
CGO_ENABLED=0 go build -o $(PREFIX)/c2w $(GO_LD_FLAGS) $(GO_BUILDTAGS) -v ./cmd/c2w

c2w-net:
CGO_ENABLED=0 go build -o $(PREFIX)/c2w-net $(GO_LD_FLAGS) $(GO_BUILDTAGS) -v ./cmd/c2w-net

c2w-net-proxy.wasm:
cd extras/c2w-net-proxy/ ; GOOS=wasip1 GOARCH=wasm go build -o $(PREFIX)/c2w-net-proxy.wasm .

install:
install -D -m 755 $(PREFIX)/c2w $(CMD_DESTDIR)/bin
install -D -m 755 $(PREFIX)/c2w-net $(CMD_DESTDIR)/bin

artifacts: clean
GOOS=linux GOARCH=amd64 make c2w
tar -C $(PREFIX) --owner=0 --group=0 -zcvf $(PREFIX)/container2wasm-$(VERSION)-linux-amd64.tar.gz c2w
GOOS=linux GOARCH=amd64 make c2w c2w-net
tar -C $(PREFIX) --owner=0 --group=0 -zcvf $(PREFIX)/container2wasm-$(VERSION)-linux-amd64.tar.gz c2w c2w-net

GOOS=linux GOARCH=arm64 make c2w
tar -C $(PREFIX) --owner=0 --group=0 -zcvf $(PREFIX)/container2wasm-$(VERSION)-linux-arm64.tar.gz c2w
GOOS=linux GOARCH=arm64 make c2w c2w-net
tar -C $(PREFIX) --owner=0 --group=0 -zcvf $(PREFIX)/container2wasm-$(VERSION)-linux-arm64.tar.gz c2w c2w-net

rm -f $(PREFIX)/c2w
rm -f $(PREFIX)/c2w $(PREFIX)/c2w-net

test:
./tests/test.sh
Expand Down
83 changes: 64 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@ $ wasmtime --mapdir /mnt/share::/tmp/share out.wasm cat /mnt/share/from-host
hi
```

> Please refer to [`./examples/networking/wasi/`](./examples/networking/wasi/) for enabling networking

### Container on Browser

![Container on browser](./docs/images/ubuntu-wasi-on-browser.png)

You can run the container on browser as well.
There are two methods for running the container on browser.

> NOTE: Please also refer to [`./examples/wasi-browser`](./examples/wasi-browser/) (WASI-on-browser example) and [`./examples/emscripten`](./examples/emscripten/) (emscripten example).
> Please also refer to [`./examples/wasi-browser`](./examples/wasi-browser/) (WASI-on-browser example) and [`./examples/emscripten`](./examples/emscripten/) (emscripten example).

> Please refer to [`./examples/networking/`](./examples/networking/) for details about enabling networking.

#### WASI on browser

Expand All @@ -80,6 +84,41 @@ $ docker run --rm -p 8080:80 \

You can run the container on browser via `localhost:8080`.

##### WASI on browser with networking

![Debian container on browser with browser networking](./docs/images/debian-curl-wasi-on-browser-frontend-networking.png)

Container can also perform networking.
This section is the demo of using curl command in the container.

> Tested only on Chrome. The example might not work on other browsers.

```
$ cat <<EOF | docker build -t debian-curl -
FROM debian:sid-slim
RUN apt-get update && apt-get install -y curl
EOF
$ c2w debian-curl /tmp/out-js2/htdocs/out.wasm
```

This example serves the image on `localhost:8080` using apache http server.
The following also builds the [network stack runnable on browser](./extras/c2w-net-proxy/) and puts it to the document root.

```
$ cp -R ./examples/wasi-browser/* /tmp/out-js2/ && chmod 755 /tmp/out-js2/htdocs
$ PREFIX=/tmp/out-js2/htdocs/ make c2w-net-proxy.wasm
$ docker run --rm -p 8080:80 \
-v "/tmp/out-js2/htdocs:/usr/local/apache2/htdocs/:ro" \
-v "/tmp/out-js2/xterm-pty.conf:/usr/local/apache2/conf/extra/xterm-pty.conf:ro" \
--entrypoint=/bin/sh httpd -c 'echo "Include conf/extra/xterm-pty.conf" >> /usr/local/apache2/conf/httpd.conf && httpd-foreground'
```

You can run the container on browser with several types of configurations:

- `localhost:8080/?net=browser`: Container with networking. [Network stack](./extras/c2w-net-proxy/) based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) runs on browser and forwards HTTP/HTTPS packets using the browser's Fetch API. The set of accesible sites is restricted by the browser configuration (e.g. CORS restriction). See also [`./examples/networking/fetch`](./examples/networking/fetch/) for detalis.
- `localhost:8080/?net=delegate=ws://localhost:8888`: Container with networking. You need to run [user-space network stack](./cmd/c2w-net/) based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) on the host (outside of browser). It forwards all packets received from the browser over WebSocket. See also [`./examples/networking/websocket`](./examples/networking/websocket/) for detalis and configuration.
- `localhost:8080`: Container without networking.

#### emscripten on browser

This example uses emscripten for converting the container to WASM.
Expand Down Expand Up @@ -108,20 +147,25 @@ You can run the container on browser via `localhost:8080`.

> NOTE: It can take some time to load and start the container.

Networking can also be enabled using the [user-space network stack](./cmd/c2w-net/) based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) serving over WebSocket on the host (outside of browser).
See also [`./examples/networking/websocket`](./examples/networking/websocket/) for detalis.

## Getting Started

- requirements
- Docker 18.09+ (w/ `DOCKER_BUILDKIT=1`)
- [Docker Buildx](https://docs.docker.com/build/install-buildx/) v0.8+ (recommended) or `docker build` (w/ `DOCKER_BUILDKIT=1`)

You can install the converter command `c2w` using one of the following methods:
You can install the converter command `c2w` using one of the following methods.

> NOTE: The output binary also contains [`c2w-net`](./cmd/c2w-net/) which a command usable for controlling networking feature (please see also [./examples/networking](./examples/networking/) for details).

### Release binary
### Release binaries

Binaries are available from https://github.com/ktock/container2wasm/releases
Extract the tarball and put the binary somewhere under `$PATH`.

### Building binary using make
### Building binaries using make

Go 1.19+ is needed.

Expand Down Expand Up @@ -218,23 +262,23 @@ The following shows the techniqual details:

### x86_64 containers

|runtime |stdio|mapdir|note|
|---|---|---|---|
|wasmtime|:heavy_check_mark:|:heavy_check_mark:||
|wamr(wasm-micro-runtime)|:heavy_check_mark:|:heavy_check_mark:||
|wazero|:heavy_check_mark:|:heavy_check_mark:||
|wasmer|:construction: (stdin unsupported)|:heavy_check_mark:|non-blocking stdin doesn't seem to work|
|wasmedge|:construction: (stdin unsupported)|:heavy_check_mark:|non-blocking stdin doesn't seem to work|
|runtime|stdio|mapdir|networking|note|
|---|---|---|---|---|
|wasmtime|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/))||
|wamr(wasm-micro-runtime)|:heavy_check_mark:|:heavy_check_mark:|:construction:||
|wazero|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/)||
|wasmer|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|
|wasmedge|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|

### risc-v and other architecutre's containers

|runtime |stdio|mapdir|note|
|---|---|---|---|
|wasmtime|:heavy_check_mark:|:heavy_check_mark:||
|wamr(wasm-micro-runtime)|:heavy_check_mark:|:heavy_check_mark:||
|wazero|:heavy_check_mark:|:heavy_check_mark:||
|wasmer|:construction: (stdin unsupported)|:heavy_check_mark:|non-blocking stdin doesn't seem to work|
|wasmedge|:construction: (stdin unsupported)|:heavy_check_mark:|non-blocking stdin doesn't seem to work|
|runtime |stdio|mapdir|networking|note|
|---|---|---|---|---|
|wasmtime|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/))||
|wamr(wasm-micro-runtime)|:heavy_check_mark:|:heavy_check_mark:|:construction:||
|wazero|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/))||
|wasmer|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|
|wasmedge|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|

## Similar projects

Expand Down Expand Up @@ -282,6 +326,7 @@ Re-compilation (and possibe re-implementation) of the application is needed.
- vmtouch ([license](https://github.com/hoytech/vmtouch/blob/master/LICENSE)): https://github.com/hoytech/vmtouch
- BusyBox ([GNU General Public License version 2](https://www.busybox.net/license.html)): https://git.busybox.net/busybox

- On-browser example relies on xterm-pty and `browser_wasi_shim`(for WASI-on-browser).
- On-browser example relies on the following softwares.
- xterm-pty ([MIT License](https://github.com/mame/xterm-pty/blob/main/LICENSE.txt)): https://github.com/mame/xterm-pty
- `browser_wasi_shim` (either of [MIT License](https://github.com/bjorn3/browser_wasi_shim/blob/main/LICENSE-MIT) and [Apache License 2.0](https://github.com/bjorn3/browser_wasi_shim/blob/main/LICENSE-APACHE)): https://github.com/bjorn3/browser_wasi_shim
- `gvisor-tap-vsock` ([Apache License 2.0](https://github.com/containers/gvisor-tap-vsock/blob/main/LICENSE)): https://github.com/containers/gvisor-tap-vsock
Loading