Skip to content

Commit

Permalink
Fix build of WASM-page using Go instead of TinyGo
Browse files Browse the repository at this point in the history
  • Loading branch information
stv0g committed May 5, 2023
1 parent b02acab commit 7d4457d
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 117 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/gh-pages-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ jobs:
submodules: true
fetch-depth: 0

- name: Install tinygo
run: wget https://github.com/tinygo-org/tinygo/releases/download/v0.21.0/tinygo_0.21.0_amd64.deb && sudo dpkg -i tinygo_0.21.0_amd64.deb
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: 1.20

- name: Build WASM
run: cd web && cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js . && tinygo build -o wasm.wasm -target wasm -no-debug --panic trap ../pkg/wasm/
run: |
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" web/
GOOS=js GOARCH=wasm go build -o web/wasm.wasm ./pkg/wasm/
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
Expand Down
5 changes: 2 additions & 3 deletions examples/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ You can download the WASM build and `wasm_exec.js` from master build OR build yo
* `wget https://pe.pion.ly/wasm_exec.js`

### Build
* [Install TinyGo](https://tinygo.org/getting-started/install/)
* Copy wasm_exec - `cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js .`
* Build - `tinygo build -o wasm.wasm -target wasm -no-debug --panic trap github.com/pion/explainer/pkg/wasm`
* Copy `wasm_exec.js`: `cp "$(go env GOROOT)/misc/wasm/wasm_exec_node.js" .`
* Build - `GOOS=js GOARCH=wasm go build -o wasm.wasm ../../pkg/wasm`

### Run
Run `node main.js`
56 changes: 32 additions & 24 deletions examples/node/main.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

/* global WebAssembly, TextDecoder, TextEncoder */

require('./wasm_exec.js')
const go = new global.Go()
const importObject = go.importObject

const remoteDescription = `{"type": "offer", "sdp": "v=0\r\no=- 0 0 IN IP4 127.0.0.1\r\ns=-\r\nc=IN IP4 127.0.0.1\r\nt=0 0\r\nm=audio 4000 RTP/AVP 111\r\na=rtpmap:111 OPUS/48000/2\r\nm=video 4002 RTP/AVP 96\r\na=rtpmap:96 VP8/90000"}`
const localDescription = `{"type": "answer", "sdp": "v=0\r\no=- 0 0 IN IP4 127.0.0.1\r\ns=-\r\nc=IN IP4 127.0.0.1\r\nt=0 0\r\nm=audio 4000 RTP/AVP 111\r\na=rtpmap:111 OPUS/48000/2\r\nm=video 4002 RTP/AVP 96\r\na=rtpmap:96 VP8/90000"}`

WebAssembly.instantiate(require('fs').readFileSync('wasm.wasm'), importObject).then(wasmModule => {
go.run(wasmModule.instance)
let exports = wasmModule.instance.exports

let wasmMemory = () => {
return new Uint8Array(exports.memory.buffer)
}
let memoryOffset = exports.getWasmMemoryBufferOffset()

wasmMemory().set((new TextEncoder().encode(remoteDescription)), memoryOffset)
exports.SetRemoteDescription(remoteDescription.length)

wasmMemory().set((new TextEncoder().encode(localDescription)), memoryOffset)
exports.SetLocalDescription(localDescription.length)

let explainSize = exports.Explain()
console.log(new TextDecoder().decode(wasmMemory().subarray(memoryOffset, memoryOffset + explainSize)))
})
globalThis.require = require;
globalThis.fs = require("fs");
globalThis.TextEncoder = require("util").TextEncoder;
globalThis.TextDecoder = require("util").TextDecoder;

globalThis.performance = {
now() {
const [sec, nsec] = process.hrtime();
return sec * 1000 + nsec / 1000000;
},
};

const crypto = require("crypto");
globalThis.crypto = {
getRandomValues(b) {
crypto.randomFillSync(b);
},
};

require("./wasm_exec");

const go = new Go();
WebAssembly.instantiate(fs.readFileSync('wasm.wasm'), go.importObject).then((result) => {
go.run(result.instance);

result_str = explain(localDescription, remoteDescription)
result = JSON.parse(result_str)
console.log(result)
}).catch((err) => {
console.error(err);
process.exit(1);
});
80 changes: 17 additions & 63 deletions pkg/wasm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,85 +6,39 @@ package main

import (
"encoding/json"
"syscall/js"

"github.com/pion/explainer"
)

// nolint: deadcode, unused, revive
type (
Result = explainer.Result
SessionDetails = explainer.SessionDetails
PeerDetails = explainer.PeerDetails
)

const (
bufferSize int = 500000
)

// nolint: unused, golint, gochecknoglobals
//nolint:gochecknoglobals
var (
buffer [bufferSize]byte
peerConnectionExplainer explainer.PeerConnectionExplainer
exp explainer.PeerConnectionExplainer
)

func main() {}

//export getWasmMemoryBufferOffset
func getWasmMemoryBufferOffset() *[bufferSize]byte { //nolint: deadcode, unused
return &buffer
}

func maybeInitExplainer() { //nolint: deadcode, unused
if peerConnectionExplainer == nil {
peerConnectionExplainer = explainer.NewPeerConnectionExplainer()
func explain(_ js.Value, inputs []js.Value) interface{} {
if len(inputs) != 2 {
panic("invalid number of inputs") //nolint:forbidigo
}
}

// SetLocalDescription updates the PeerConnectionExplainer with the provided SessionDescription
//
//export SetLocalDescription
func SetLocalDescription(length int) { //nolint: unused, deadcode
maybeInitExplainer()
peerConnectionExplainer.SetLocalDescription(string(buffer[:length]))
}

// SetRemoteDescription updates the PeerConnectionExplainer with the provided SessionDescription
//
//export SetRemoteDescription
func SetRemoteDescription(length int) { //nolint: deadcode, unused, golint
maybeInitExplainer()
peerConnectionExplainer.SetRemoteDescription(string(buffer[:length]))
}
localDescription := inputs[0].String()
remoteDescription := inputs[1].String()

// Explain returns the result of the current PeerConnectionExplainer.
//
//export Explain
func Explain() int { //nolint: deadcode, unused
maybeInitExplainer()
exp.SetLocalDescription(localDescription)
exp.SetRemoteDescription(remoteDescription)

result := peerConnectionExplainer.Explain()
j, err := json.Marshal(result)
out, err := json.Marshal(exp.Explain())
if err != nil {
return 0
panic(err) //nolint:forbidigo
}

return copy(buffer[:], j)
return string(out)
}

// GetLocalDescription returns the current SDP we are using from SetLocalDescription
//
//export GetLocalDescription
func GetLocalDescription() int { //nolint: deadcode, unused
maybeInitExplainer()

return copy(buffer[:], peerConnectionExplainer.GetLocalDescription())
}
func main() {
exp = explainer.NewPeerConnectionExplainer()

// GetRemoteDescription returns the current SDP we are using from GetRemoteDescription
//
//export GetRemoteDescription
func GetRemoteDescription() int { //nolint: deadcode, unused
maybeInitExplainer()
js.Global().Set("explain", js.FuncOf(explain))

return copy(buffer[:], peerConnectionExplainer.GetRemoteDescription())
select {}
}
5 changes: 2 additions & 3 deletions web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ You can download the WASM build and `wasm_exec.js` from master build OR build yo
* `wget https://pe.pion.ly/wasm_exec.js`

### Build
* [Install TinyGo](https://tinygo.org/getting-started/install/)
* Copy wasm_exec - `cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js .`
* Build - `tinygo build -o wasm.wasm -target wasm -no-debug --panic trap github.com/pion/explainer/pkg/wasm`
* Copy `wasm_exec.js`: `cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .`
* Build - `GOOS=js GOARCH=wasm go build -o wasm.wasm ../pkg/wasm`

### Run
You can now run using any HTTP server. If you have Python available `python -m SimpleHTTPServer` is a good option.
Expand Down
27 changes: 6 additions & 21 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -243,35 +243,22 @@ <h3> Parsed Local Session Description </h3>
}
}

let wasm, memoryOffset
let wasmMemory = () => {
return new Uint8Array(wasm.exports.memory.buffer)
}

let handleInput = () => {
const localDescription = document.querySelector('#local-description-div textarea').value
const remoteDescription = document.querySelector('#remote-description-div textarea').value

if (wasm === undefined) {
if (explain === undefined) {
return
} else if (document.querySelector('#remote-description-div input').checked && remoteDescription.length === 0) {
return
} else if (document.querySelector('#local-description-div input').checked && localDescription.length === 0) {
return
}

wasmMemory().set((new TextEncoder().encode(remoteDescription)), memoryOffset)
wasm.exports.SetRemoteDescription(remoteDescription.length)

wasmMemory().set((new TextEncoder().encode(localDescription)), memoryOffset)
wasm.exports.SetLocalDescription(localDescription.length)

let explainResult = wasm.exports.Explain()
renderOutput(
JSON.parse(new TextDecoder().decode(wasmMemory().subarray(memoryOffset, memoryOffset + explainResult))),
new TextDecoder().decode(wasmMemory().subarray(memoryOffset, memoryOffset + wasm.exports.GetLocalDescription())),
new TextDecoder().decode(wasmMemory().subarray(memoryOffset, memoryOffset + wasm.exports.GetRemoteDescription()))
)
result_str = explain(localDescription, remoteDescription)
result = JSON.parse(result_str)

renderOutput(result, localDescription, remoteDescription)
}

for (let i of document.querySelectorAll('input[type=checkbox]')) {
Expand All @@ -290,9 +277,7 @@ <h3> Parsed Local Session Description </h3>
resp.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {
wasm = obj.instance
memoryOffset = wasm.exports.getWasmMemoryBufferOffset()
go.run(wasm)
go.run(obj.instance)
})
)
</script>
Expand Down

0 comments on commit 7d4457d

Please sign in to comment.