feat: enhance WebAssembly API by adding requestPath, setPacketCallback, and setAnnounceCallback functions; refactor SendMessage to SendDataJS for improved data handling
Some checks failed
Bearer / scan (push) Successful in 8s
Go Build Multi-Platform / build (amd64, darwin) (push) Successful in 43s
Go Build Multi-Platform / build (amd64, linux) (push) Successful in 43s
Go Build Multi-Platform / build (arm, windows) (push) Successful in 41s
Go Build Multi-Platform / build (arm, freebsd) (push) Successful in 44s
TinyGo Build / tinygo-build (tinygo-wasm, tinygo-wasm, reticulum-go.wasm, wasm) (pull_request) Has been cancelled
Go Build Multi-Platform / build (wasm, js) (push) Successful in 51s
Go Build Multi-Platform / build (arm64, linux) (push) Successful in 55s
Go Build Multi-Platform / build (arm64, windows) (push) Successful in 53s
TinyGo Build / tinygo-build (tinygo-build, tinygo-default, reticulum-go-tinygo, ) (pull_request) Has been cancelled
Go Revive Lint / lint (push) Successful in 1m9s
Go Test Multi-Platform / Test (ubuntu-latest, arm64) (push) Successful in 1m27s
Run Gosec / tests (push) Successful in 1m31s
Go Test Multi-Platform / Test (ubuntu-latest, amd64) (push) Failing after 2m16s
Go Build Multi-Platform / build (amd64, freebsd) (push) Failing after 4m42s
Go Build Multi-Platform / build (amd64, windows) (push) Successful in 9m27s
Go Build Multi-Platform / build (arm64, darwin) (push) Successful in 9m27s
Go Build Multi-Platform / build (arm, linux) (push) Successful in 9m29s
Go Build Multi-Platform / build (arm64, freebsd) (push) Successful in 9m29s
Go Build Multi-Platform / Create Release (push) Has been skipped
Some checks failed
Bearer / scan (push) Successful in 8s
Go Build Multi-Platform / build (amd64, darwin) (push) Successful in 43s
Go Build Multi-Platform / build (amd64, linux) (push) Successful in 43s
Go Build Multi-Platform / build (arm, windows) (push) Successful in 41s
Go Build Multi-Platform / build (arm, freebsd) (push) Successful in 44s
TinyGo Build / tinygo-build (tinygo-wasm, tinygo-wasm, reticulum-go.wasm, wasm) (pull_request) Has been cancelled
Go Build Multi-Platform / build (wasm, js) (push) Successful in 51s
Go Build Multi-Platform / build (arm64, linux) (push) Successful in 55s
Go Build Multi-Platform / build (arm64, windows) (push) Successful in 53s
TinyGo Build / tinygo-build (tinygo-build, tinygo-default, reticulum-go-tinygo, ) (pull_request) Has been cancelled
Go Revive Lint / lint (push) Successful in 1m9s
Go Test Multi-Platform / Test (ubuntu-latest, arm64) (push) Successful in 1m27s
Run Gosec / tests (push) Successful in 1m31s
Go Test Multi-Platform / Test (ubuntu-latest, amd64) (push) Failing after 2m16s
Go Build Multi-Platform / build (amd64, freebsd) (push) Failing after 4m42s
Go Build Multi-Platform / build (amd64, windows) (push) Successful in 9m27s
Go Build Multi-Platform / build (arm64, darwin) (push) Successful in 9m27s
Go Build Multi-Platform / build (arm, linux) (push) Successful in 9m29s
Go Build Multi-Platform / build (arm64, freebsd) (push) Successful in 9m29s
Go Build Multi-Platform / Create Release (push) Has been skipped
This commit is contained in:
257
pkg/wasm/wasm.go
257
pkg/wasm/wasm.go
@@ -21,31 +21,82 @@ var (
|
|||||||
reticulumTransport *transport.Transport
|
reticulumTransport *transport.Transport
|
||||||
reticulumDest *destination.Destination
|
reticulumDest *destination.Destination
|
||||||
reticulumIdentity *identity.Identity
|
reticulumIdentity *identity.Identity
|
||||||
userName string
|
|
||||||
peerMap = make(map[string]string)
|
|
||||||
stats = struct {
|
stats = struct {
|
||||||
packetsSent int
|
packetsSent int
|
||||||
packetsReceived int
|
packetsReceived int
|
||||||
bytesSent int
|
bytesSent int
|
||||||
bytesReceived int
|
bytesReceived int
|
||||||
}{}
|
}{}
|
||||||
|
packetCallback js.Value
|
||||||
|
announceHandler js.Value
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterJSFunctions registers the Reticulum WASM API to the JavaScript global scope.
|
// RegisterJSFunctions registers the Reticulum WASM API to the JavaScript global scope.
|
||||||
func RegisterJSFunctions() {
|
func RegisterJSFunctions() {
|
||||||
js.Global().Set("reticulum", js.ValueOf(map[string]interface{}{
|
js.Global().Set("reticulum", js.ValueOf(map[string]interface{}{
|
||||||
"init": js.FuncOf(InitReticulum),
|
"init": js.FuncOf(InitReticulum),
|
||||||
"getIdentity": js.FuncOf(GetIdentity),
|
"getIdentity": js.FuncOf(GetIdentity),
|
||||||
"getDestination": js.FuncOf(GetDestination),
|
"getDestination": js.FuncOf(GetDestination),
|
||||||
"announce": js.FuncOf(SendAnnounce),
|
"connect": js.FuncOf(ConnectWebSocket),
|
||||||
"connect": js.FuncOf(ConnectWebSocket),
|
"disconnect": js.FuncOf(DisconnectWebSocket),
|
||||||
"disconnect": js.FuncOf(DisconnectWebSocket),
|
"isConnected": js.FuncOf(IsConnected),
|
||||||
"isConnected": js.FuncOf(IsConnected),
|
"requestPath": js.FuncOf(RequestPath),
|
||||||
"sendMessage": js.FuncOf(SendMessage),
|
"getStats": js.FuncOf(GetStats),
|
||||||
"getStats": js.FuncOf(GetStats),
|
"setPacketCallback": js.FuncOf(SetPacketCallback),
|
||||||
|
"setAnnounceCallback": js.FuncOf(SetAnnounceCallback),
|
||||||
|
"sendData": js.FuncOf(SendDataJS),
|
||||||
|
"announce": js.FuncOf(SendAnnounceJS),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetPacketCallback(this js.Value, args []js.Value) interface{} {
|
||||||
|
if len(args) > 0 && args[0].Type() == js.TypeFunction {
|
||||||
|
packetCallback = args[0]
|
||||||
|
return js.ValueOf(true)
|
||||||
|
}
|
||||||
|
return js.ValueOf(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetAnnounceCallback(this js.Value, args []js.Value) interface{} {
|
||||||
|
if len(args) > 0 && args[0].Type() == js.TypeFunction {
|
||||||
|
announceHandler = args[0]
|
||||||
|
return js.ValueOf(true)
|
||||||
|
}
|
||||||
|
return js.ValueOf(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequestPath(this js.Value, args []js.Value) interface{} {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"error": "Destination hash required",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
destHashHex := args[0].String()
|
||||||
|
destHash, err := hex.DecodeString(destHashHex)
|
||||||
|
if err != nil {
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"error": fmt.Sprintf("Invalid destination hash: %v", err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if reticulumTransport == nil {
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"error": "Reticulum not initialized",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := reticulumTransport.RequestPath(destHash, "", nil, true); err != nil {
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"error": fmt.Sprintf("Failed to request path: %v", err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"success": true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func GetStats(this js.Value, args []js.Value) interface{} {
|
func GetStats(this js.Value, args []js.Value) interface{} {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
"packetsSent": stats.packetsSent,
|
"packetsSent": stats.packetsSent,
|
||||||
@@ -68,8 +119,9 @@ func InitReticulum(this js.Value, args []js.Value) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wsURL := args[0].String()
|
wsURL := args[0].String()
|
||||||
if len(args) >= 2 {
|
appName := "wasm_core"
|
||||||
userName = args[1].String()
|
if len(args) >= 2 && args[1].Type() == js.TypeString {
|
||||||
|
appName = args[1].String()
|
||||||
}
|
}
|
||||||
|
|
||||||
var id *identity.Identity
|
var id *identity.Identity
|
||||||
@@ -105,7 +157,7 @@ func InitReticulum(this js.Value, args []js.Value) interface{} {
|
|||||||
id,
|
id,
|
||||||
destination.IN,
|
destination.IN,
|
||||||
destination.SINGLE,
|
destination.SINGLE,
|
||||||
"wasm_core",
|
appName,
|
||||||
t,
|
t,
|
||||||
"browser",
|
"browser",
|
||||||
)
|
)
|
||||||
@@ -115,33 +167,21 @@ func InitReticulum(this js.Value, args []js.Value) interface{} {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if userName != "" {
|
|
||||||
dest.SetDefaultAppData([]byte(userName))
|
|
||||||
}
|
|
||||||
|
|
||||||
dest.SetPacketCallback(func(data []byte, ni common.NetworkInterface) {
|
dest.SetPacketCallback(func(data []byte, ni common.NetworkInterface) {
|
||||||
stats.packetsReceived++
|
stats.packetsReceived++
|
||||||
stats.bytesReceived += len(data)
|
stats.bytesReceived += len(data)
|
||||||
|
|
||||||
var from string
|
if !packetCallback.IsUndefined() {
|
||||||
var text string
|
// Convert bytes to JS Uint8Array for performance and compatibility
|
||||||
if len(data) >= 16 {
|
uint8Array := js.Global().Get("Uint8Array").New(len(data))
|
||||||
from = hex.EncodeToString(data[:16])
|
js.CopyBytesToJS(uint8Array, data)
|
||||||
text = string(data[16:])
|
packetCallback.Invoke(uint8Array)
|
||||||
} else {
|
|
||||||
from = ""
|
|
||||||
text = string(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
js.Global().Call("onChatMessage", js.ValueOf(map[string]interface{}{
|
|
||||||
"text": text,
|
|
||||||
"from": from,
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
dest.SetProofStrategy(destination.PROVE_ALL)
|
dest.SetProofStrategy(destination.PROVE_ALL)
|
||||||
|
|
||||||
t.RegisterAnnounceHandler(&announceHandler{})
|
t.RegisterAnnounceHandler(&genericAnnounceHandler{})
|
||||||
|
|
||||||
wsInterface, err := interfaces.NewWebSocketInterface("wasm0", wsURL, true)
|
wsInterface, err := interfaces.NewWebSocketInterface("wasm0", wsURL, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -181,6 +221,16 @@ func InitReticulum(this js.Value, args []js.Value) interface{} {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTransport returns the internal transport pointer.
|
||||||
|
func GetTransport() *transport.Transport {
|
||||||
|
return reticulumTransport
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDestinationPointer returns the internal destination pointer.
|
||||||
|
func GetDestinationPointer() *destination.Destination {
|
||||||
|
return reticulumDest
|
||||||
|
}
|
||||||
|
|
||||||
func GetIdentity(this js.Value, args []js.Value) interface{} {
|
func GetIdentity(this js.Value, args []js.Value) interface{} {
|
||||||
if reticulumIdentity == nil {
|
if reticulumIdentity == nil {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
@@ -205,34 +255,19 @@ func GetDestination(this js.Value, args []js.Value) interface{} {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendAnnounce(this js.Value, args []js.Value) interface{} {
|
func IsConnected(this js.Value, args []js.Value) interface{} {
|
||||||
if reticulumDest == nil {
|
if reticulumTransport == nil {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(false)
|
||||||
"error": "Reticulum not initialized",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var appData []byte
|
ifaces := reticulumTransport.GetInterfaces()
|
||||||
if len(args) >= 1 && args[0].String() != "" {
|
for _, iface := range ifaces {
|
||||||
appData = []byte(args[0].String())
|
if iface.IsOnline() {
|
||||||
userName = args[0].String()
|
return js.ValueOf(true)
|
||||||
} else if userName != "" {
|
}
|
||||||
appData = []byte(userName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(appData) > 0 {
|
return js.ValueOf(false)
|
||||||
reticulumDest.SetDefaultAppData(appData)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := reticulumDest.Announce(false, nil, nil); err != nil {
|
|
||||||
return js.ValueOf(map[string]interface{}{
|
|
||||||
"error": fmt.Sprintf("Failed to send announce: %v", err),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return js.ValueOf(map[string]interface{}{
|
|
||||||
"success": true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectWebSocket(this js.Value, args []js.Value) interface{} {
|
func ConnectWebSocket(this js.Value, args []js.Value) interface{} {
|
||||||
@@ -246,7 +281,7 @@ func ConnectWebSocket(this js.Value, args []js.Value) interface{} {
|
|||||||
for name, iface := range ifaces {
|
for name, iface := range ifaces {
|
||||||
if iface.IsOnline() {
|
if iface.IsOnline() {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
"success": true,
|
"success": true,
|
||||||
"interface": name,
|
"interface": name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -256,7 +291,7 @@ func ConnectWebSocket(this js.Value, args []js.Value) interface{} {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
"success": true,
|
"success": true,
|
||||||
"interface": name,
|
"interface": name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -290,51 +325,36 @@ func DisconnectWebSocket(this js.Value, args []js.Value) interface{} {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsConnected(this js.Value, args []js.Value) interface{} {
|
type genericAnnounceHandler struct{}
|
||||||
if reticulumTransport == nil {
|
|
||||||
return js.ValueOf(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
ifaces := reticulumTransport.GetInterfaces()
|
func (h *genericAnnounceHandler) AspectFilter() []string {
|
||||||
for _, iface := range ifaces {
|
|
||||||
if iface.IsOnline() {
|
|
||||||
return js.ValueOf(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return js.ValueOf(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
type announceHandler struct{}
|
|
||||||
|
|
||||||
func (h *announceHandler) AspectFilter() []string {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *announceHandler) ReceivePathResponses() bool {
|
func (h *genericAnnounceHandler) ReceivePathResponses() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *announceHandler) ReceivedAnnounce(destHash []byte, ident interface{}, appData []byte) error {
|
func (h *genericAnnounceHandler) ReceivedAnnounce(destHash []byte, ident interface{}, appData []byte) error {
|
||||||
hashStr := hex.EncodeToString(destHash)
|
if !announceHandler.IsUndefined() {
|
||||||
peerMap[hashStr] = string(appData)
|
hashStr := hex.EncodeToString(destHash)
|
||||||
js.Global().Call("onPeerDiscovered", js.ValueOf(map[string]interface{}{
|
announceHandler.Invoke(js.ValueOf(map[string]interface{}{
|
||||||
"hash": hashStr,
|
"hash": hashStr,
|
||||||
"appData": string(appData),
|
"appData": string(appData),
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendMessage(this js.Value, args []js.Value) interface{} {
|
// SendDataJS is the JS-facing wrapper for SendData
|
||||||
|
func SendDataJS(this js.Value, args []js.Value) interface{} {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
"error": "Destination hash and message required",
|
"error": "Destination hash and data required",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
destHashHex := args[0].String()
|
destHashHex := args[0].String()
|
||||||
message := args[1].String()
|
|
||||||
|
|
||||||
destHash, err := hex.DecodeString(destHashHex)
|
destHash, err := hex.DecodeString(destHashHex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
@@ -342,6 +362,26 @@ func SendMessage(this js.Value, args []js.Value) interface{} {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support both string and Uint8Array data from JS
|
||||||
|
var data []byte
|
||||||
|
if args[1].Type() == js.TypeString {
|
||||||
|
data = []byte(args[1].String())
|
||||||
|
} else {
|
||||||
|
data = make([]byte, args[1].Length())
|
||||||
|
js.CopyBytesToGo(data, args[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return SendData(destHash, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendData is a generic function to send raw bytes to a destination
|
||||||
|
func SendData(destHash []byte, data []byte) interface{} {
|
||||||
|
if reticulumTransport == nil {
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"error": "Reticulum not initialized",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
remoteIdentity, err := identity.Recall(destHash)
|
remoteIdentity, err := identity.Recall(destHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
@@ -356,11 +396,7 @@ func SendMessage(this js.Value, args []js.Value) interface{} {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepend sender hash to message
|
encrypted, err := targetDest.Encrypt(data)
|
||||||
senderHash := reticulumDest.GetHash()
|
|
||||||
payload := append(senderHash, []byte(message)...)
|
|
||||||
|
|
||||||
encrypted, err := targetDest.Encrypt(payload)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
"error": fmt.Sprintf("Encryption failed: %v", err),
|
"error": fmt.Sprintf("Encryption failed: %v", err),
|
||||||
@@ -393,7 +429,42 @@ func SendMessage(this js.Value, args []js.Value) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stats.packetsSent++
|
stats.packetsSent++
|
||||||
stats.bytesSent += len(message)
|
stats.bytesSent += len(data)
|
||||||
|
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"success": true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendAnnounceJS is the JS-facing wrapper for SendAnnounce
|
||||||
|
func SendAnnounceJS(this js.Value, args []js.Value) interface{} {
|
||||||
|
var appData []byte
|
||||||
|
if len(args) >= 1 && args[0].Type() == js.TypeString {
|
||||||
|
appData = []byte(args[0].String())
|
||||||
|
} else if len(args) >= 1 && args[0].Type() == js.TypeObject {
|
||||||
|
appData = make([]byte, args[0].Length())
|
||||||
|
js.CopyBytesToGo(appData, args[0])
|
||||||
|
}
|
||||||
|
return SendAnnounce(appData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendAnnounce is a generic function to send an announce
|
||||||
|
func SendAnnounce(appData []byte) interface{} {
|
||||||
|
if reticulumDest == nil {
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"error": "Reticulum not initialized",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(appData) > 0 {
|
||||||
|
reticulumDest.SetDefaultAppData(appData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := reticulumDest.Announce(false, nil, nil); err != nil {
|
||||||
|
return js.ValueOf(map[string]interface{}{
|
||||||
|
"error": fmt.Sprintf("Failed to send announce: %v", err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return js.ValueOf(map[string]interface{}{
|
return js.ValueOf(map[string]interface{}{
|
||||||
"success": true,
|
"success": true,
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ func TestRegisterJSFunctions(t *testing.T) {
|
|||||||
|
|
||||||
functions := []string{
|
functions := []string{
|
||||||
"init", "getIdentity", "getDestination", "announce",
|
"init", "getIdentity", "getDestination", "announce",
|
||||||
"connect", "disconnect", "isConnected", "sendMessage", "getStats",
|
"connect", "disconnect", "isConnected", "requestPath", "getStats",
|
||||||
|
"setPacketCallback", "setAnnounceCallback", "sendData",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fn := range functions {
|
for _, fn := range functions {
|
||||||
@@ -60,9 +61,7 @@ func TestIsConnected(t *testing.T) {
|
|||||||
|
|
||||||
func TestInitReticulum(t *testing.T) {
|
func TestInitReticulum(t *testing.T) {
|
||||||
// Mock JS global functions
|
// Mock JS global functions
|
||||||
js.Global().Set("onChatMessage", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
|
||||||
js.Global().Set("log", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
js.Global().Set("log", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
||||||
js.Global().Set("onPeerDiscovered", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
|
||||||
|
|
||||||
// Test without arguments
|
// Test without arguments
|
||||||
result := InitReticulum(js.Undefined(), []js.Value{})
|
result := InitReticulum(js.Undefined(), []js.Value{})
|
||||||
@@ -71,10 +70,10 @@ func TestInitReticulum(t *testing.T) {
|
|||||||
t.Errorf("expected error 'WebSocket URL required', got %v", val.Get("error"))
|
t.Errorf("expected error 'WebSocket URL required', got %v", val.Get("error"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test with valid URL and username
|
// Test with valid URL and app name
|
||||||
wsURL := "ws://localhost:8080"
|
wsURL := "ws://localhost:8080"
|
||||||
username := "testuser"
|
appName := "test_app"
|
||||||
result = InitReticulum(js.Undefined(), []js.Value{js.ValueOf(wsURL), js.ValueOf(username)})
|
result = InitReticulum(js.Undefined(), []js.Value{js.ValueOf(wsURL), js.ValueOf(appName)})
|
||||||
val = result.(js.Value)
|
val = result.(js.Value)
|
||||||
|
|
||||||
if !val.Get("success").Bool() {
|
if !val.Get("success").Bool() {
|
||||||
@@ -84,10 +83,6 @@ func TestInitReticulum(t *testing.T) {
|
|||||||
if reticulumIdentity == nil {
|
if reticulumIdentity == nil {
|
||||||
t.Fatal("reticulumIdentity should not be nil after successful init")
|
t.Fatal("reticulumIdentity should not be nil after successful init")
|
||||||
}
|
}
|
||||||
|
|
||||||
if userName != username {
|
|
||||||
t.Errorf("expected userName %s, got %s", username, userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with provided identity
|
// Test with provided identity
|
||||||
id, _ := identity.NewIdentity()
|
id, _ := identity.NewIdentity()
|
||||||
@@ -96,7 +91,7 @@ func TestInitReticulum(t *testing.T) {
|
|||||||
idBytes := id.GetPrivateKey()
|
idBytes := id.GetPrivateKey()
|
||||||
idHexFull := hex.EncodeToString(idBytes)
|
idHexFull := hex.EncodeToString(idBytes)
|
||||||
|
|
||||||
result = InitReticulum(js.Undefined(), []js.Value{js.ValueOf(wsURL), js.ValueOf(username), js.ValueOf(idHexFull)})
|
result = InitReticulum(js.Undefined(), []js.Value{js.ValueOf(wsURL), js.ValueOf(appName), js.ValueOf(idHexFull)})
|
||||||
val = result.(js.Value)
|
val = result.(js.Value)
|
||||||
|
|
||||||
if !val.Get("success").Bool() {
|
if !val.Get("success").Bool() {
|
||||||
@@ -110,9 +105,7 @@ func TestInitReticulum(t *testing.T) {
|
|||||||
|
|
||||||
func TestIdentityAndDestination(t *testing.T) {
|
func TestIdentityAndDestination(t *testing.T) {
|
||||||
// Ensure initialized
|
// Ensure initialized
|
||||||
js.Global().Set("onChatMessage", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
|
||||||
js.Global().Set("log", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
js.Global().Set("log", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
||||||
js.Global().Set("onPeerDiscovered", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return nil }))
|
|
||||||
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
|
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
|
||||||
|
|
||||||
idResult := GetIdentity(js.Undefined(), nil).(js.Value)
|
idResult := GetIdentity(js.Undefined(), nil).(js.Value)
|
||||||
@@ -127,21 +120,7 @@ func TestIdentityAndDestination(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnnounce(t *testing.T) {
|
func TestSendDataJS(t *testing.T) {
|
||||||
// Ensure initialized
|
|
||||||
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
|
|
||||||
|
|
||||||
result := SendAnnounce(js.Undefined(), []js.Value{js.ValueOf("new_username")}).(js.Value)
|
|
||||||
if !result.Get("success").Bool() {
|
|
||||||
t.Errorf("SendAnnounce failed: %v", result.Get("error"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if userName != "new_username" {
|
|
||||||
t.Errorf("userName should have been updated to 'new_username', got %s", userName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMessage(t *testing.T) {
|
|
||||||
// Ensure initialized
|
// Ensure initialized
|
||||||
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
|
InitReticulum(js.Undefined(), []js.Value{js.ValueOf("ws://localhost")})
|
||||||
|
|
||||||
@@ -153,22 +132,16 @@ func TestSendMessage(t *testing.T) {
|
|||||||
// Manually add to known destinations so Recall works
|
// Manually add to known destinations so Recall works
|
||||||
identity.Remember([]byte("mock_packet"), peerHash, peerId.GetPublicKey(), []byte("peer_app_data"))
|
identity.Remember([]byte("mock_packet"), peerHash, peerId.GetPublicKey(), []byte("peer_app_data"))
|
||||||
|
|
||||||
// Test SendMessage
|
// Test SendDataJS with string
|
||||||
msg := "Hello Peer!"
|
data := "Hello Peer!"
|
||||||
result := SendMessage(js.Undefined(), []js.Value{js.ValueOf(peerHashHex), js.ValueOf(msg)}).(js.Value)
|
result := SendDataJS(js.Undefined(), []js.Value{js.ValueOf(peerHashHex), js.ValueOf(data)}).(js.Value)
|
||||||
|
|
||||||
if !result.Get("error").IsUndefined() {
|
if !result.Get("error").IsUndefined() {
|
||||||
errStr := result.Get("error").String()
|
errStr := result.Get("error").String()
|
||||||
if errStr != "Packet sending failed: no path to destination" {
|
if errStr != "Packet sending failed: no path to destination" {
|
||||||
t.Errorf("SendMessage failed with unexpected error: %s", errStr)
|
t.Errorf("SendDataJS failed with unexpected error: %s", errStr)
|
||||||
} else {
|
|
||||||
t.Log("SendMessage correctly failed with 'no path to destination' (as expected in test environment)")
|
|
||||||
}
|
}
|
||||||
} else if !result.Get("success").Bool() {
|
} else if !result.Get("success").Bool() {
|
||||||
t.Errorf("SendMessage failed without error message")
|
t.Errorf("SendDataJS failed without error message")
|
||||||
} else {
|
|
||||||
if stats.packetsSent != 1 {
|
|
||||||
t.Errorf("expected 1 packet sent, got %d", stats.packetsSent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user