diff --git a/src/client/network/network.ts b/src/client/network/network.ts index e0982771..8ef7a0b6 100644 --- a/src/client/network/network.ts +++ b/src/client/network/network.ts @@ -1,3 +1,5 @@ +import { NUClearNetSend } from 'nuclearnet.js' + import { NUsightNetwork } from './nusight_network' import { MessageType } from './nusight_network' import { MessageCallback } from './nusight_network' @@ -44,4 +46,11 @@ export class Network { } this.offNUClearMessages.clear() } + + /** + * Send the given message on the network + */ + send(opts: NUClearNetSend): void { + this.nusightNetwork.send(opts) + } } diff --git a/src/client/network/nusight_network.ts b/src/client/network/nusight_network.ts index e51a3365..2df0c3a1 100644 --- a/src/client/network/nusight_network.ts +++ b/src/client/network/nusight_network.ts @@ -1,6 +1,7 @@ import { NUClearNetPacket } from 'nuclearnet.js' import { NUClearNetOptions } from 'nuclearnet.js' import { NUClearNetPeer } from 'nuclearnet.js' +import { NUClearNetSend } from 'nuclearnet.js' import { NUClearNetClient } from '../../shared/nuclearnet/nuclearnet_client' import { AppModel } from '../components/app/model' @@ -30,6 +31,10 @@ export class NUsightNetwork { return this.nuclearnetClient.connect(opts) } + send(opts: NUClearNetSend) { + this.nuclearnetClient.send(opts) + } + onNUClearMessage(messageType: MessageType, cb: MessageCallback) { const messageTypeName = this.messageTypePath.getPath(messageType) return this.nuclearnetClient.on(messageTypeName, (packet: NUClearNetPacket) => { diff --git a/src/client/nuclearnet/tests/web_socket_proxy_nuclearnet_client.tests.ts b/src/client/nuclearnet/tests/web_socket_proxy_nuclearnet_client.tests.ts index 4d55529e..c6c9c690 100644 --- a/src/client/nuclearnet/tests/web_socket_proxy_nuclearnet_client.tests.ts +++ b/src/client/nuclearnet/tests/web_socket_proxy_nuclearnet_client.tests.ts @@ -88,7 +88,7 @@ describe('WebSocketProxyNUClearNetClient', () => { payload: Buffer.alloc(8), } client.send(opts) - expect(mockWebSocket.send).toHaveBeenCalledWith('foo', opts) + expect(mockWebSocket.send).toHaveBeenCalledWith('packet', opts) }) }) }) diff --git a/src/client/nuclearnet/web_socket_proxy_nuclearnet_client.ts b/src/client/nuclearnet/web_socket_proxy_nuclearnet_client.ts index efa5b503..f038a6ab 100644 --- a/src/client/nuclearnet/web_socket_proxy_nuclearnet_client.ts +++ b/src/client/nuclearnet/web_socket_proxy_nuclearnet_client.ts @@ -119,9 +119,7 @@ export class WebSocketProxyNUClearNetClient implements NUClearNetClient { } send(options: NUClearNetSend): void { - if (typeof options.type === 'string') { - this.socket.send(options.type, options) - } + this.socket.send('packet', options) } private onReconnect = (options: NUClearNetOptions) => { diff --git a/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts b/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts index 32272885..ded329ab 100644 --- a/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts +++ b/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts @@ -1,3 +1,4 @@ +import { NUClearNetSend } from 'nuclearnet.js' import { NUClearNetOptions } from 'nuclearnet.js' import { NUClearNetPeer } from 'nuclearnet.js' import { NUClearNetPacket } from 'nuclearnet.js' @@ -52,6 +53,7 @@ class WebSocketServerClient { this.offLeave = this.nuclearnetClient.onLeave(this.onLeave) this.offListenMap = new Map() + this.socket.on('packet', this.onClientPacket) this.socket.on('listen', this.onListen) this.socket.on('unlisten', this.onUnlisten) this.socket.on('nuclear_connect', this.onConnect) @@ -85,7 +87,7 @@ class WebSocketServerClient { } private onListen = (event: string, requestToken: string) => { - const off = this.nuclearnetClient.on(event, this.onPacket.bind(this, event)) + const off = this.nuclearnetClient.on(event, this.onServerPacket.bind(this, event)) this.offListenMap.set(requestToken, off) } @@ -101,9 +103,13 @@ class WebSocketServerClient { this.offLeave() } - private onPacket = (event: string, packet: NUClearNetPacket) => { + private onServerPacket = (event: string, packet: NUClearNetPacket) => { this.processor.onPacket(event, packet) } + + private onClientPacket = (options: NUClearNetSend) => { + this.nuclearnetClient.send(options) + } } class PacketProcessor { diff --git a/src/shared/nuclearnet/nuclearnet_proxy_parser.ts b/src/shared/nuclearnet/nuclearnet_proxy_parser.ts index b74a1033..b620753a 100644 --- a/src/shared/nuclearnet/nuclearnet_proxy_parser.ts +++ b/src/shared/nuclearnet/nuclearnet_proxy_parser.ts @@ -1,6 +1,7 @@ import * as Emitter from 'component-emitter' import { NUClearNetPacket } from 'nuclearnet.js' import { NUClearNetPeer } from 'nuclearnet.js' +import { NUClearNetSend } from 'nuclearnet.js' import { Packet } from './nuclearnet_proxy_parser_socketio' import { TYPES } from './nuclearnet_proxy_parser_socketio' @@ -35,8 +36,16 @@ export class Encoder { case 'unlisten': return callback([JSON.stringify(packet)]) + case 'packet': { + const { id, data: [key, { target, type, payload, reliable }] } = packet + return callback([ + JSON.stringify({ id, nsp, key, header: { target, type, reliable } }), + payload, + ]) + } + // For NUClearNet packets, we send the payload separately to avoid array slicing later - default: + default: { const { id, data: [key, { peer, hash, payload, reliable }] } = packet // Send the header as a JSON and then the payload as binary @@ -45,6 +54,7 @@ export class Encoder { hash, payload, ]) + } } default: return callback([JSON.stringify(packet)]) @@ -58,7 +68,7 @@ export class Decoder extends Emitter { private nuclearPacket?: { nsp: string, type: TYPES.EVENT, - data: [string, Partial], + data: [string, Partial | Partial], id: number } @@ -85,10 +95,19 @@ export class Decoder extends Emitter { } } else { switch (this.state) { - // State 1 means we are getting a hash + // State 1 means we are getting a payload or hash case 1: - this.nuclearPacket!.data[1].hash = obj - this.state = 2 + if (this.nuclearPacket!.data[0] === 'packet') { + // 'packet' messages are sent using NUClearNetSend which doesn't have a hash, + // so here we get the payload and emit + this.nuclearPacket!.data[1].payload = obj + this.emit('decoded', this.nuclearPacket) + this.state = 0 + } else { + // For NUClearNetPackets we get a hash in state 1 and move to state 2 for the payload + (this.nuclearPacket!.data[1] as NUClearNetPacket).hash = obj + this.state = 2 + } break // State 2 means we are getting a packet