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

feat: Add WASM build for toxcore and websocket bootstrap node. #1950

Merged
merged 1 commit into from
Feb 2, 2022
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
5 changes: 4 additions & 1 deletion .github/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ branches:
- "bazel-opt"
- "bazel-tsan"
- "bazel-valgrind"
- "build-bootstrapd-docker"
- "build-compcert"
- "build-macos"
- "build-msan"
- "build-nacl"
- "build-tcc"
- "build-win32"
Expand All @@ -38,6 +38,9 @@ branches:
- "cimple"
- "code-review/reviewable"
- "continuous-integration/appveyor/pr"
- "docker-bootstrap-node"
- "docker-bootstrap-node-websocket"
- "docker-toxcore-js"
- "mypy"
- "sonar-scan"

Expand Down
51 changes: 45 additions & 6 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ on:
branches: [master]

jobs:
build-bootstrapd-docker:
docker-bootstrap-node:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
if: github.event_name == 'push'
if: ${{ github.event_name == 'push' }}
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
Expand All @@ -22,8 +20,49 @@ jobs:
- name: Docker Build
run: .github/scripts/tox-bootstrapd-docker local
- name: Push latest image to DockerHub
if: github.event_name == 'push'
if: ${{ github.event_name == 'push' }}
run: docker push toxchat/bootstrap-node:latest
- name: Push versioned image to DockerHub
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
if: ${{ github.event_name == 'push' && contains(github.ref, 'refs/tags/') }}
run: docker push toxchat/bootstrap-node:"$(other/print-version)"

docker-toxcore-js:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
if: ${{ github.event_name == 'push' }}
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
file: other/emscripten/Dockerfile
push: ${{ github.event_name == 'push' }}
tags: toxchat/toxcore-js:latest
cache-from: type=registry,ref=toxchat/toxcore-js:latest
cache-to: type=inline

docker-bootstrap-node-websocket:
runs-on: ubuntu-latest
needs: [docker-bootstrap-node]
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
if: ${{ github.event_name == 'push' }}
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: "{{defaultContext}}:other/bootstrap_daemon/websocket"
push: ${{ github.event_name == 'push' }}
tags: toxchat/bootstrap-node:latest-websocket
cache-from: type=registry,ref=toxchat/bootstrap-node:latest-websocket
cache-to: type=inline
4 changes: 4 additions & 0 deletions .hadolint.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
---
ignored:
# "cd" is sometimes useful when you want to run one command in one directory
# and then another command in another directory, but they should be executed
# in the same RUN instruction.
- DL3003
- DL3007
- DL3008
- DL3013
Expand Down
4 changes: 4 additions & 0 deletions heroku.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
build:
docker:
web: other/bootstrap_daemon/websocket/Dockerfile
2 changes: 1 addition & 1 deletion other/bootstrap_daemon/docker/update-sha256
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env bash

set -eux

Expand Down
29 changes: 29 additions & 0 deletions other/bootstrap_daemon/websocket/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Stage 1 - Compile websockify.
FROM toxchat/bootstrap-node:latest AS tox
FROM golang:1.17-alpine AS websockify

COPY websockify /work/websockify
RUN cd /work/websockify && go mod download github.com/gorilla/websocket && go install

# Stage 2 - Create the run-time image with bootstrap daemon and websockify.
FROM alpine:latest

RUN addgroup -S tox && adduser -SDH -G tox tox

COPY --from=websockify /go/bin/websockify /usr/local/bin/
COPY --from=tox /usr/local /usr/local/
COPY --from=tox /etc/tox-bootstrapd.conf /etc/
COPY entrypoint.sh /

RUN mkdir -p /var/lib/tox-bootstrapd/ /var/run/tox-bootstrapd/ \
&& chown tox:tox /var/lib/tox-bootstrapd/ /var/run/tox-bootstrapd/
# Public Key: 122837CCDD474DD1183A83152164D51427044B3EAAA52ED683F6BA602568673B
COPY keys /var/lib/tox-bootstrapd/
USER tox

# Use this to generate a keys file:
#RUN /usr/local/bin/tox-bootstrapd --config /etc/tox-bootstrapd.conf --log-backend stdout \
# && sleep 1

WORKDIR /web
CMD ["/entrypoint.sh"]
6 changes: 6 additions & 0 deletions other/bootstrap_daemon/websocket/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

set -eux

/usr/local/bin/tox-bootstrapd --config /etc/tox-bootstrapd.conf --log-backend stdout
/usr/local/bin/websockify -l "0.0.0.0:$PORT" -t 127.0.0.1:33445
1 change: 1 addition & 0 deletions other/bootstrap_daemon/websocket/keys
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(7��GM�:�!d�'K>��.փ��`%hg;�G��Y�:�Zy5��S�$�|Cڠ�Ǹ�2� �t
7 changes: 7 additions & 0 deletions other/bootstrap_daemon/websocket/websockify/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module github.com/TokTok/c-toxcore/other/bootstrap_daemon/websocket/websockify

go 1.17

require (
github.com/gorilla/websocket master
)
111 changes: 111 additions & 0 deletions other/bootstrap_daemon/websocket/websockify/websockify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// A Go version WebSocket to TCP socket proxy
//
// This is a heavily modified version of this file:
// https://github.com/novnc/websockify-other/blob/master/golang/websockify.go
//
// Changes include:
// - Fix infinite loop on error.
// - Proper logging.
// - Proper error handling in general.
// - Support both websocket and regular GET requests on /.
//
// Copyright 2022 The TokTok team.
// Copyright 2021 Michael.liu.
// See LICENSE for licensing conditions.

package main

import (
"encoding/hex"
"flag"
"log"
"net"
"net/http"

"github.com/gorilla/websocket"
)

var (
sourceAddr = flag.String("l", "127.0.0.1:8080", "http service address")
targetAddr = flag.String("t", "127.0.0.1:5900", "tcp service address")
)

var upgrader = websocket.Upgrader{
// Should be enough to fit any Tox TCP packets.
ReadBufferSize: 2048,
WriteBufferSize: 2048,
Subprotocols: []string{"binary"},
CheckOrigin: func(r *http.Request) bool {
return true
},
}

func forwardTCP(wsconn *websocket.Conn, conn net.Conn) {
var tcpbuffer [2048]byte
defer wsconn.Close()
defer conn.Close()
for {
n, err := conn.Read(tcpbuffer[0:])
if err != nil {
log.Println("TCP READ :", err)
break
}
log.Println("TCP READ :", n, hex.EncodeToString(tcpbuffer[0:n]))

if err := wsconn.WriteMessage(websocket.BinaryMessage, tcpbuffer[0:n]); err != nil {
log.Println("WS WRITE :", err)
break
}
log.Println("WS WRITE :", n)
}
}

func forwardWeb(wsconn *websocket.Conn, conn net.Conn) {
defer wsconn.Close()
defer conn.Close()
for {
_, buffer, err := wsconn.ReadMessage()
if err != nil {
log.Println("WS READ :", err)
break
}
log.Println("WS READ :", len(buffer), hex.EncodeToString(buffer))

m, err := conn.Write(buffer)
if err != nil {
log.Println("TCP WRITE:", err)
break
}
log.Println("TCP WRITE:", m)
}
}

func serveWs(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("upgrade:", err)
return
}
vnc, err := net.Dial("tcp", *targetAddr)
if err != nil {
log.Println("dial:", err)
return
}
go forwardTCP(ws, vnc)
go forwardWeb(ws, vnc)

}

func main() {
flag.Parse()
log.Println("Starting up websockify endpoint")

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Upgrade") == "websocket" {
serveWs(w, r)
} else {
http.ServeFile(w, r, r.URL.Path[1:])
}
})
log.Fatal(http.ListenAndServe(*sourceAddr, nil))
}
84 changes: 84 additions & 0 deletions other/emscripten/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
FROM ubuntu:20.04

ENV DEBIAN_FRONTEND="noninteractive"

# Install dependencies.
RUN apt-get update && apt-get install --no-install-recommends -y \
autoconf \
automake \
ca-certificates \
cmake \
curl \
git \
libtool \
make \
ninja-build \
pkg-config \
python3 \
unzip \
wget \
xz-utils \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /work/emsdk
RUN git clone --depth=1 https://github.com/emscripten-core/emsdk /work/emsdk \
&& ./emsdk install latest \
&& ./emsdk activate latest

# Build libsodium.
RUN . "/work/emsdk/emsdk_env.sh" \
&& git clone --depth=1 --branch=1.0.18 https://github.com/jedisct1/libsodium /work/libsodium \
&& cd /work/libsodium \
&& autoreconf -fi \
&& emconfigure ./configure --disable-shared \
--without-pthreads \
--disable-ssp --disable-asm --disable-pie \
&& emmake make install -j8

# Build an unused libsodium binding first so emcc caches all the system
# libraries. This makes rebuilds of toxcore below much faster.
RUN . "/work/emsdk/emsdk_env.sh" \
&& mkdir -p /work/wasm \
&& emcc -O3 -flto \
--closure=1 \
-s ALLOW_UNIMPLEMENTED_SYSCALLS=1 \
-s EXPORT_NAME=libtoxcore \
-s IGNORE_MISSING_MAIN=1 \
-s MAIN_MODULE=1 \
-s MALLOC=emmalloc \
-s MODULARIZE=1 \
-s STRICT=1 \
-s WEBSOCKET_URL=wss:// \
/usr/local/lib/libsodium.a \
-o /work/wasm/libsodium.js

# Build c-toxcore.
COPY . /work/c-toxcore
RUN . "/work/emsdk/emsdk_env.sh" \
&& cd /work/c-toxcore \
&& emcmake cmake -B_build -H. -GNinja \
-DCMAKE_C_FLAGS="-O3 -flto -fPIC" \
-DBUILD_TOXAV=OFF \
-DENABLE_SHARED=OFF \
-DBOOTSTRAP_DAEMON=OFF \
-DCMAKE_INSTALL_PREFIX:PATH="/usr/local" \
-DMIN_LOGGER_LEVEL=DEBUG \
&& emmake cmake --build _build --parallel 8 --target install

# Build wasm bindings.
RUN . "/work/emsdk/emsdk_env.sh" \
&& mkdir -p /work/wasm \
&& emcc -O3 -flto \
--closure=1 \
-s ALLOW_UNIMPLEMENTED_SYSCALLS=1 \
-s EXPORT_NAME=libtoxcore \
-s IGNORE_MISSING_MAIN=1 \
-s MAIN_MODULE=1 \
-s MALLOC=emmalloc \
-s MODULARIZE=1 \
-s STRICT=1 \
-s WEBSOCKET_URL=wss:// \
/usr/local/lib/libsodium.a \
/usr/local/lib/libtoxcore.a \
-o /work/wasm/libtoxcore.js