Skip to content
Snippets Groups Projects
Commit 32b48d82 authored by Jono Wenger's avatar Jono Wenger
Browse files

Implement broadcast

parent 3f3c26bc
Branches
Tags
1 merge request!60Revert "Fail a test to be sure it works"
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
package bindings
import (
"gitlab.com/elixxir/client/bindings"
)
type Channel struct {
api *bindings.Channel
}
......@@ -11,10 +11,8 @@ package main
import (
"fmt"
"gitlab.com/elixxir/xxdk-wasm/bindings"
"gitlab.com/elixxir/xxdk-wasm/wasm"
"os"
"os/signal"
"syscall"
"syscall/js"
)
......@@ -22,64 +20,63 @@ func main() {
fmt.Println("Go Web Assembly")
// wasm/cmix.go
js.Global().Set("NewCmix", js.FuncOf(bindings.NewCmix))
js.Global().Set("LoadCmix", js.FuncOf(bindings.LoadCmix))
js.Global().Set("NewCmix", js.FuncOf(wasm.NewCmix))
js.Global().Set("LoadCmix", js.FuncOf(wasm.LoadCmix))
// wasm/e2e.go
js.Global().Set("Login", js.FuncOf(bindings.Login))
js.Global().Set("LoginEphemeral", js.FuncOf(bindings.LoginEphemeral))
js.Global().Set("Login", js.FuncOf(wasm.Login))
js.Global().Set("LoginEphemeral", js.FuncOf(wasm.LoginEphemeral))
// wasm/identity.go
js.Global().Set("StoreReceptionIdentity",
js.FuncOf(bindings.StoreReceptionIdentity))
js.FuncOf(wasm.StoreReceptionIdentity))
js.Global().Set("LoadReceptionIdentity",
js.FuncOf(bindings.LoadReceptionIdentity))
js.FuncOf(wasm.LoadReceptionIdentity))
js.Global().Set("GetIDFromContact",
js.FuncOf(bindings.GetIDFromContact))
js.FuncOf(wasm.GetIDFromContact))
js.Global().Set("GetPubkeyFromContact",
js.FuncOf(bindings.GetPubkeyFromContact))
js.FuncOf(wasm.GetPubkeyFromContact))
js.Global().Set("SetFactsOnContact",
js.FuncOf(bindings.SetFactsOnContact))
js.FuncOf(wasm.SetFactsOnContact))
js.Global().Set("GetFactsFromContact",
js.FuncOf(bindings.GetFactsFromContact))
js.FuncOf(wasm.GetFactsFromContact))
// wasm/params.go
js.Global().Set("GetDefaultCMixParams",
js.FuncOf(bindings.GetDefaultCMixParams))
js.FuncOf(wasm.GetDefaultCMixParams))
js.Global().Set("GetDefaultE2EParams",
js.FuncOf(bindings.GetDefaultE2EParams))
js.FuncOf(wasm.GetDefaultE2EParams))
js.Global().Set("GetDefaultFileTransferParams",
js.FuncOf(bindings.GetDefaultFileTransferParams))
js.FuncOf(wasm.GetDefaultFileTransferParams))
js.Global().Set("GetDefaultSingleUseParams",
js.FuncOf(bindings.GetDefaultSingleUseParams))
js.FuncOf(wasm.GetDefaultSingleUseParams))
js.Global().Set("GetDefaultE2eFileTransferParams",
js.FuncOf(bindings.GetDefaultE2eFileTransferParams))
js.FuncOf(wasm.GetDefaultE2eFileTransferParams))
// wasm/logging.go
js.Global().Set("LogLevel", js.FuncOf(bindings.LogLevel))
js.Global().Set("RegisterLogWriter", js.FuncOf(bindings.RegisterLogWriter))
js.Global().Set("EnableGrpcLogs", js.FuncOf(bindings.EnableGrpcLogs))
js.Global().Set("LogLevel", js.FuncOf(wasm.LogLevel))
js.Global().Set("RegisterLogWriter", js.FuncOf(wasm.RegisterLogWriter))
js.Global().Set("EnableGrpcLogs", js.FuncOf(wasm.EnableGrpcLogs))
// wasm/ndf.go
js.Global().Set("DownloadAndVerifySignedNdfWithUrl",
js.FuncOf(bindings.DownloadAndVerifySignedNdfWithUrl))
js.FuncOf(wasm.DownloadAndVerifySignedNdfWithUrl))
// wasm/version.go
js.Global().Set("GetVersion", js.FuncOf(bindings.GetVersion))
js.Global().Set("GetGitVersion", js.FuncOf(bindings.GetGitVersion))
js.Global().Set("GetDependencies", js.FuncOf(bindings.GetDependencies))
js.Global().Set("GetVersion", js.FuncOf(wasm.GetVersion))
js.Global().Set("GetGitVersion", js.FuncOf(wasm.GetGitVersion))
js.Global().Set("GetDependencies", js.FuncOf(wasm.GetDependencies))
// wasm/secrets.go
js.Global().Set("GenerateSecret", js.FuncOf(bindings.GenerateSecret))
js.Global().Set("GenerateSecret", js.FuncOf(wasm.GenerateSecret))
// wasm/dummy.go
js.Global().Set("NewDummyTrafficManager",
js.FuncOf(bindings.NewDummyTrafficManager))
js.FuncOf(wasm.NewDummyTrafficManager))
// Wait until the user terminates the program
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
// bindings/broadcast
js.Global().Set("NewBroadcastChannel", js.FuncOf(wasm.NewBroadcastChannel))
<-make(chan bool)
os.Exit(0)
}
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
//go:build js && wasm
package wasm
import (
"gitlab.com/elixxir/client/bindings"
"syscall/js"
)
type Channel struct {
api *bindings.Channel
}
// newE2eJS creates a new Javascript compatible object (map[string]interface{})
// that matches the E2e structure.
func newChannelJS(api *bindings.Channel) map[string]interface{} {
c := Channel{api}
chMap := map[string]interface{}{
"Listen": c.Listen,
"Broadcast": c.Broadcast,
"BroadcastAsymmetric": c.BroadcastAsymmetric,
"MaxPayloadSize": c.MaxPayloadSize,
"MaxAsymmetricPayloadSize": c.MaxAsymmetricPayloadSize,
"Get": c.Get,
"Stop": c.Stop,
}
return chMap
}
// NewBroadcastChannel creates a bindings-layer broadcast channel and starts
// listening for new messages
//
// Parameters:
// - args[0] - ID of Cmix object in tracker (int).
// - args[1] - JSON of [bindings.ChannelDef] (Uint8Array).
//
// Returns:
// - Javascript representation of the Channel object.
// - Throws a TypeError if creation fails.
func NewBroadcastChannel(_ js.Value, args []js.Value) interface{} {
channelDefinition := CopyBytesToGo(args[1])
api, err := bindings.NewBroadcastChannel(args[0].Int(), channelDefinition)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return newChannelJS(api)
}
// broadcastListener wraps Javascript callbacks to adhere to the
// [bindings.BroadcastListener] interface.
type broadcastListener struct {
callback func(args ...interface{}) js.Value
}
func (bl *broadcastListener) Callback(payload []byte, err error) {
bl.callback(CopyBytesToJS(payload), err.Error())
}
// Listen registers a BroadcastListener for a given method. This allows users to
// handle incoming broadcast messages.
//
// Parameters:
// - args[0] - Javascript object that has functions that implement the
// [bindings.BroadcastListener] interface.
// - args[1] - number corresponding to broadcast.Method constant, 0 for
// symmetric or 1 for asymmetric (int).
//
// Returns:
// - Throws a TypeError if registering the listener fails.
func (c *Channel) Listen(_ js.Value, args []js.Value) interface{} {
err := c.api.Listen(&broadcastListener{args[0].Invoke}, args[1].Int())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
}
// Broadcast sends a given payload over the broadcast channel using symmetric
// broadcast.
//
// Parameters:
// - args[0] - payload (Uint8Array).
//
// Returns:
// - JSON of [bindings.BroadcastReport], which can be passed into
// Cmix.WaitForRoundResult to see if the broadcast succeeded (Uint8Array).
// - Throws a TypeError if broadcasting fails.
func (c *Channel) Broadcast(_ js.Value, args []js.Value) interface{} {
report, err := c.api.Broadcast(CopyBytesToGo(args[0]))
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(report)
}
// BroadcastAsymmetric sends a given payload over the broadcast channel using
// asymmetric broadcast. This mode of encryption requires a private key.
//
// Parameters:
// - args[0] - payload (Uint8Array).
// - args[1] - private key (Uint8Array).
//
// Returns:
// - JSON of [bindings.BroadcastReport], which can be passed into
// Cmix.WaitForRoundResult to see if the broadcast succeeded (Uint8Array).
// - Throws a TypeError if broadcasting fails.
func (c *Channel) BroadcastAsymmetric(_ js.Value, args []js.Value) interface{} {
report, err := c.api.BroadcastAsymmetric(
CopyBytesToGo(args[0]), CopyBytesToGo(args[1]))
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(report)
}
// MaxPayloadSize returns the maximum possible payload size which can be
// broadcast.
//
// Returns:
// - int
func (c *Channel) MaxPayloadSize(js.Value, []js.Value) interface{} {
return c.api.MaxPayloadSize()
}
// MaxAsymmetricPayloadSize returns the maximum possible payload size which can
// be broadcast.
//
// Returns:
// - int
func (c *Channel) MaxAsymmetricPayloadSize(js.Value, []js.Value) interface{} {
return c.api.MaxAsymmetricPayloadSize()
}
// Get returns the JSON of the channel definition.
//
// Returns:
// - JSON of [bindings.ChannelDef] (Uint8Array).
// - Throws a TypeError if marshalling fails.
func (c *Channel) Get(js.Value, []js.Value) interface{} {
def, err := c.api.Get()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(def)
}
// Stop stops the channel from listening for more messages.
func (c *Channel) Stop(js.Value, []js.Value) interface{} {
c.api.Stop()
return nil
}
package wasm
import (
"gitlab.com/elixxir/client/bindings"
"reflect"
"testing"
)
// Tests that the map representing Channel returned by newChannelJS contains
// all of the methods on Channel.
func Test_newChannelJS(t *testing.T) {
chanType := reflect.TypeOf(&Channel{})
ch := newChannelJS(&bindings.Channel{})
if len(ch) != chanType.NumMethod() {
t.Errorf("Channel JS object does not have all methods."+
"\nexpected: %d\nreceived: %d", chanType.NumMethod(), len(ch))
}
for i := 0; i < chanType.NumMethod(); i++ {
method := chanType.Method(i)
if _, exists := ch[method.Name]; !exists {
t.Errorf("Method %s does not exist.", method.Name)
}
}
}
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......@@ -22,8 +22,8 @@ type Cmix struct {
// newCmixJS creates a new Javascript compatible object (map[string]interface{})
// that matches the Cmix structure.
func newCmixJS(net *bindings.Cmix) map[string]interface{} {
c := Cmix{net}
func newCmixJS(api *bindings.Cmix) map[string]interface{} {
c := Cmix{api}
cmix := map[string]interface{}{
// cmix.go
"GetID": js.FuncOf(c.GetID),
......
......@@ -8,7 +8,7 @@
//go:build js && wasm
// +build js,wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......@@ -64,6 +64,7 @@ func (c *Cmix) Connect(_ js.Value, args []js.Value) interface{} {
conn, err := c.api.Connect(args[0].Int(), recipientContact, e2eParamsJSON)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return newConnectJS(conn)
......@@ -88,6 +89,7 @@ func (c *Connection) SendE2E(_ js.Value, args []js.Value) interface{} {
sendReport, err := c.c.SendE2E(args[0].Int(), CopyBytesToGo(args[1]))
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(sendReport)
}
......@@ -100,6 +102,7 @@ func (c *Connection) Close(js.Value, []js.Value) interface{} {
err := c.c.Close()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -137,6 +140,7 @@ func (c *Connection) RegisterListener(_ js.Value, args []js.Value) interface{} {
&listener{args[1].Get("Hear").Invoke, args[1].Get("Name").Invoke})
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......
......@@ -5,7 +5,7 @@
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"syscall/js"
......@@ -53,6 +53,7 @@ func (c *Cmix) WaitForRoundResult(_ js.Value, args []js.Value) interface{} {
err := c.api.WaitForRoundResult(roundList, mdc, args[2].Int())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......@@ -57,6 +57,7 @@ func NewDummyTrafficManager(_ js.Value, args []js.Value) interface{} {
args[0].Int(), args[1].Int(), args[2].Int(), args[3].Int())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return newDummyTrafficJS(dt)
......@@ -80,6 +81,7 @@ func (dt *DummyTraffic) SetStatus(_ js.Value, args []js.Value) interface{} {
err := dt.api.SetStatus(args[0].Bool())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......@@ -22,8 +22,8 @@ type E2e struct {
// newE2eJS creates a new Javascript compatible object (map[string]interface{})
// that matches the E2e structure.
func newE2eJS(newE2E *bindings.E2e) map[string]interface{} {
e := E2e{newE2E}
func newE2eJS(api *bindings.E2e) map[string]interface{} {
e := E2e{api}
e2e := map[string]interface{}{
// e2e.go
"GetID": js.FuncOf(e.GetID),
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"syscall/js"
......@@ -44,6 +44,7 @@ func (e *E2e) Request(_ js.Value, args []js.Value) interface{} {
rid, err := e.api.Request(partnerContact, factsListJson)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return rid
......@@ -76,6 +77,7 @@ func (e *E2e) Confirm(_ js.Value, args []js.Value) interface{} {
rid, err := e.api.Confirm(partnerContact)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return rid
......@@ -106,6 +108,7 @@ func (e *E2e) Reset(_ js.Value, args []js.Value) interface{} {
rid, err := e.api.Reset(partnerContact)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return rid
......@@ -130,6 +133,7 @@ func (e *E2e) ReplayConfirm(_ js.Value, args []js.Value) interface{} {
rid, err := e.api.ReplayConfirm(partnerContact)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return rid
......@@ -154,6 +158,7 @@ func (e *E2e) DeleteRequest(_ js.Value, args []js.Value) interface{} {
err := e.api.DeleteRequest(partnerContact)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -167,6 +172,7 @@ func (e *E2e) DeleteAllRequests(js.Value, []js.Value) interface{} {
err := e.api.DeleteAllRequests()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -180,6 +186,7 @@ func (e *E2e) DeleteSentRequests(js.Value, []js.Value) interface{} {
err := e.api.DeleteSentRequests()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -193,6 +200,7 @@ func (e *E2e) DeleteReceiveRequests(js.Value, []js.Value) interface{} {
err := e.api.DeleteReceiveRequests()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -211,6 +219,7 @@ func (e *E2e) GetReceivedRequest(_ js.Value, args []js.Value) interface{} {
c, err := e.api.GetReceivedRequest(partnerContact)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(c)
......@@ -233,6 +242,7 @@ func (e *E2e) VerifyOwnership(_ js.Value, args []js.Value) interface{} {
receivedContact, verifiedContact, args[2].Int())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return isValid
......@@ -254,6 +264,7 @@ func (e *E2e) AddPartnerCallback(_ js.Value, args []js.Value) interface{} {
err := e.api.AddPartnerCallback(partnerID, callbacks)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -272,6 +283,7 @@ func (e *E2e) DeletePartnerCallback(_ js.Value, args []js.Value) interface{} {
err := e.api.DeletePartnerCallback(partnerID)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"syscall/js"
......@@ -31,6 +31,7 @@ func (e *E2e) GetAllPartnerIDs(js.Value, []js.Value) interface{} {
partnerIDs, err := e.api.GetAllPartnerIDs()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(partnerIDs)
}
......@@ -83,6 +84,7 @@ func (e *E2e) GetHistoricalDHPrivkey(js.Value, []js.Value) interface{} {
privKey, err := e.api.GetHistoricalDHPrivkey()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(privKey)
}
......@@ -97,6 +99,7 @@ func (e *E2e) GetHistoricalDHPubkey(js.Value, []js.Value) interface{} {
pubKey, err := e.api.GetHistoricalDHPubkey()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(pubKey)
}
......@@ -114,6 +117,7 @@ func (e *E2e) HasAuthenticatedChannel(_ js.Value, args []js.Value) interface{} {
exists, err := e.api.HasAuthenticatedChannel(CopyBytesToGo(args[0]))
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return exists
}
......@@ -129,6 +133,7 @@ func (e *E2e) RemoveService(_ js.Value, args []js.Value) interface{} {
err := e.api.RemoveService(args[0].String())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -156,6 +161,7 @@ func (e *E2e) SendE2E(_ js.Value, args []js.Value) interface{} {
args[0].Int(), recipientId, payload, e2eParams)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(sendReport)
......@@ -200,6 +206,7 @@ func (e *E2e) AddService(_ js.Value, args []js.Value) interface{} {
err := e.api.AddService(args[0].String(), p)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -224,6 +231,7 @@ func (e *E2e) RegisterListener(_ js.Value, args []js.Value) interface{} {
err := e.api.RegisterListener(recipientId, args[1].Int(), l)
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......
......@@ -8,7 +8,7 @@
//go:build js && wasm
// +build js,wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"syscall/js"
......@@ -56,6 +56,7 @@ func (c *Cmix) StartNetworkFollower(_ js.Value, args []js.Value) interface{} {
err := c.api.StartNetworkFollower(args[0].Int())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -73,6 +74,7 @@ func (c *Cmix) StopNetworkFollower(js.Value, []js.Value) interface{} {
err := c.api.StopNetworkFollower()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......@@ -114,6 +116,7 @@ func (c *Cmix) GetNodeRegistrationStatus(js.Value, []js.Value) interface{} {
b, err := c.api.GetNodeRegistrationStatus()
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(b)
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......@@ -38,6 +38,7 @@ func LogLevel(_ js.Value, args []js.Value) interface{} {
err := bindings.LogLevel(args[0].Int())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return nil
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......@@ -29,6 +29,7 @@ func DownloadAndVerifySignedNdfWithUrl(_ js.Value, args []js.Value) interface{}
args[0].String(), args[1].String())
if err != nil {
Throw(TypeError, err.Error())
return nil
}
return CopyBytesToJS(ndf)
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......
......@@ -7,7 +7,7 @@
//go:build js && wasm
package bindings
package wasm
import (
"gitlab.com/elixxir/client/bindings"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment