Skip to content

Commit

Permalink
Allow for running both an UDP and TCP server at the same time
Browse files Browse the repository at this point in the history
Signed-off-by: Axel Boberg <[email protected]>
  • Loading branch information
axelboberg committed Apr 14, 2024
1 parent 0402de6 commit 9e44c2a
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 51 deletions.
112 changes: 71 additions & 41 deletions plugins/osc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,24 @@ require('./lib/commands')
*/

/**
* The default server port,
* The default server port for the UDP transport
*
* this will be used as the default
* settings value if no other is provided
*
* @type { Number }
*/
const DEFAULT_SERVER_PORT = 8080
const DEFAULT_UDP_SERVER_PORT = 8080

/**
* The default server port for the TCP transport
*
* this will be used as the default
* settings value if no other is provided
*
* @type { Number }
*/
const DEFAULT_TCP_SERVER_PORT = 8081

/**
* Declare the valid types
Expand All @@ -62,7 +72,7 @@ const DEFAULT_SERVER_PORT = 8080
*/
const VALID_OSC_ARG_TYPES = ['string', 'integer', 'float', 'boolean']

const SERVER_MODES = {
const SERVER_TYPES = {
1: 'udp',
2: 'tcp'
}
Expand Down Expand Up @@ -135,30 +145,38 @@ function parseAsArgumentType (type, value) {
}

/**
* A reference to the current server
* A reference to the current servers
* indexed by their type
* @type { Server | undefined }
*/
let server
const servers = {}

/**
* Set up the server and start listen
* on a specific port
* @param { Number } port
*/
function setupServer (port = DEFAULT_SERVER_PORT, address, mode) {
teardownServer()
function setupServer (type, port, address) {
teardownServer(type)

let transport
if (mode === 'udp') {
let defaultPort

if (type === 'udp') {
transport = new UDPTransport()
} else if (mode === 'tcp') {
defaultPort = DEFAULT_UDP_SERVER_PORT
} else if (type === 'tcp') {
transport = new TCPTransport()
defaultPort = DEFAULT_TCP_SERVER_PORT
}

transport.listen(port, address)
transport.on('error', err => {
logger.warn(err)
})
transport.listen(port || defaultPort, address)

server = new Server(transport)
server.on('message', async osc => {
servers[type] = new Server(transport)
servers[type].on('message', async osc => {
try {
log.addLog({
timestamp: Date.now(),
Expand All @@ -175,13 +193,14 @@ function setupServer (port = DEFAULT_SERVER_PORT, address, mode) {
/**
* Tear down the
* current server
* by its type
*/
function teardownServer () {
if (!server) {
function teardownServer (type) {
if (!servers[type]) {
return
}
server.teardown()
server = undefined
servers[type].teardown()
servers[type] = undefined
}

/**
Expand Down Expand Up @@ -284,12 +303,12 @@ exports.activate = async () => {

/**
* A snapshot of the current
* server configuration used
* server configurations used
* for diffing against state
* updates
* @type { String }
*/
let serverConfigSnapshot
const serverConfigSnapshots = {}

/*
Listen to state changes and compare
Expand All @@ -299,43 +318,54 @@ exports.activate = async () => {
configuration has changed
*/
bridge.events.on('state.change', newState => {
const serverConfig = newState?.plugins?.[manifest.name]?.settings.server
if (serverConfigSnapshot !== JSON.stringify(serverConfig)) {
serverConfigSnapshot = JSON.stringify(serverConfig)

if (!serverConfig?.mode) {
teardownServer()
} else {
setupServer(serverConfig?.port, serverConfig?.bindToAll ? '0.0.0.0' : '127.0.0.1', SERVER_MODES[serverConfig?.mode])
const settings = newState?.plugins?.[manifest.name]?.settings

for (const type of Object.values(SERVER_TYPES)) {
const config = settings?.[type]

if (serverConfigSnapshots[type] !== JSON.stringify(config)) {
serverConfigSnapshots[type] = JSON.stringify(config)

if (!config?.active) {
teardownServer(type)
} else {
setupServer(type, config?.port, config?.bindToAll ? '0.0.0.0' : '127.0.0.1')
}
}
}
})

const settings = await bridge.state.get(`plugins.${manifest.name}.settings`)

/*
Set up the server on
Set up servers on
startup if active
*/
const serverConfig = await bridge.state.get(`plugins.${manifest.name}.settings.server`)
serverConfigSnapshot = JSON.stringify(serverConfig)
if (serverConfig?.mode) {
setupServer(serverConfig?.port, serverConfig?.bindToAll ? '0.0.0.0' : '127.0.0.1', SERVER_MODES[serverConfig?.mode])
for (const type of Object.values(SERVER_TYPES)) {
const config = settings?.[type]
if (!config?.active) {
teardownServer(type)
} else {
setupServer(type, config?.port, config?.bindToAll ? '0.0.0.0' : '127.0.0.1')
}
}

/*
Set defaults
if missing
*/
if (!serverConfig?.port) {
bridge.state.apply({
plugins: {
[manifest.name]: {
settings: {
server: {
port: DEFAULT_SERVER_PORT
}
bridge.state.apply({
plugins: {
[manifest.name]: {
settings: {
udp: {
port: settings?.udp?.port || DEFAULT_UDP_SERVER_PORT
},
tcp: {
port: settings?.tcp?.port || DEFAULT_TCP_SERVER_PORT
}
}
}
})
}
}
})
}
5 changes: 5 additions & 0 deletions plugins/osc/lib/TCPTransport.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ class TCPTransport extends Transport {
})
socket.setTimeout(DEFAULT_SOCKET_TIMEOUT_MS)
})

this.#server.on('error', err => {
this.emit('error', err)
})
}

teardown () {
super.teardown()
this.#server.close()
this.#server.removeAllListeners()
}

listen (port, address) {
Expand Down
4 changes: 4 additions & 0 deletions plugins/osc/lib/UDPTransport.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class UDPTransport extends Transport {
this.#socket.on('message', msg => {
this.emit('message', msg)
})

this.#socket.on('error', err => {
this.emit('error', err)
})
}

teardown () {
Expand Down
47 changes: 37 additions & 10 deletions plugins/osc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,30 @@
"settings": [
{
"group": "OSC",
"title": "Server mode",
"title": "UDP Server",
"inputs": [
{
"type": "segmented",
"bind": "shared.plugins.bridge-plugin-osc.settings.server.mode",
"default": 0,
"segments": [ "Off", "UDP", "TCP" ]
"type": "boolean",
"label": "Activate",
"bind": "shared.plugins.bridge-plugin-osc.settings.udp.active",
"default": false
},
{
"type": "boolean",
"bind": "shared.plugins.bridge-plugin-osc.settings.udp.bindToAll",
"label": "Bind to 0.0.0.0",
"default": false
}
]
},
{
"group": "OSC",
"title": "Server port",
"title": "UDP Server port",
"inputs": [
{
"type": "number",
"bind": "shared.plugins.bridge-plugin-osc.settings.server.port",
"label": "Port",
"bind": "shared.plugins.bridge-plugin-osc.settings.udp.port",
"default": 8080,
"min": 3000,
"max": 65535
Expand All @@ -45,12 +51,33 @@
},
{
"group": "OSC",
"title": "Server listen on all interfaces",
"title": "TCP Server",
"inputs": [
{
"type": "boolean",
"bind": "shared.plugins.bridge-plugin-osc.settings.server.bindToAll",
"label": "Bind to 0.0.0.0"
"label": "Activate",
"bind": "shared.plugins.bridge-plugin-osc.settings.tcp.active",
"default": false
},
{
"type": "boolean",
"bind": "shared.plugins.bridge-plugin-osc.settings.tcp.bindToAll",
"label": "Bind to 0.0.0.0",
"default": false
}
]
},
{
"group": "OSC",
"title": "TCP Server port",
"inputs": [
{
"type": "number",
"label": "Port",
"bind": "shared.plugins.bridge-plugin-osc.settings.tcp.port",
"default": 8081,
"min": 3000,
"max": 65535
}
]
}
Expand Down

0 comments on commit 9e44c2a

Please sign in to comment.