Skip to content

Commit

Permalink
feat: Add WASM build for toxcore and websocket bootstrap node.
Browse files Browse the repository at this point in the history
The websocket bootstrap node will be running on Heroku.
  • Loading branch information
iphydf committed Feb 2, 2022
1 parent 727982d commit 71965a0
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 8 deletions.
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

0 comments on commit 71965a0

Please sign in to comment.