Skip to content

Commit

Permalink
Fall back to port 9001 if mdns doesn't seem to work
Browse files Browse the repository at this point in the history
  • Loading branch information
SenkyDragon committed Nov 3, 2023
1 parent 7a7b381 commit f34e8e2
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 57 deletions.
136 changes: 79 additions & 57 deletions src/main/OscConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import VrchatOscqueryService from "./services/VrchatOscqueryService";
import http from "node:http";
import {Protocol} from "@homebridge/ciao";
import { getResponder } from "@homebridge/ciao";
import Bonjour from "bonjour-service";

type MyEvents = {
add: (key: string, value: OscValue) => void,
Expand All @@ -33,9 +34,10 @@ export default class OscConnection extends (EventEmitter as new () => TypedEmitt
private oscQuery: OSCQueryServer | undefined;
private oscSocket: osc.UDPPort | undefined;
socketopen = false;
private retryTimeout: ReturnType<typeof setTimeout> | undefined;
private lastPacket: number = 0;
public port: number = 0;
private shutdown: (()=>void)[] = [];
public useOscQuery: boolean = true;

constructor(
private myAddresses: MyAddressesService,
Expand All @@ -57,6 +59,26 @@ export default class OscConnection extends (EventEmitter as new () => TypedEmitt
this.recentlyRcvdOscCmds = 0;
}
}, 15000);

const mdns = new Bonjour();
const mdnsBrowser = mdns.find({
type: "oscjson",
protocol: "tcp"
});
const mdnsTimeout = setTimeout(() => {
this.logger.log("Mdns watchdog timed out! Mdns must not work on this machine. Reverting to legacy port 9001 mode.");
this.useOscQuery = false;
this.openSocket();
}, 5000);
mdnsBrowser.on('up', service => {
if (service.port != this.port) return;
const ip = service.addresses?.[0];
if (!ip) return;
if (!this.myAddresses.has(ip)) return;
this.logger.log("Mdns watchdog found own oscquery announcement");
clearTimeout(mdnsTimeout);
mdns.destroy();
})
}

public static parsePort(inputObj: string | undefined, defAddress: string, defPort: number): [string,number] {
Expand Down Expand Up @@ -86,48 +108,63 @@ export default class OscConnection extends (EventEmitter as new () => TypedEmitt
}

private async openSocketUnsafe() {
const port = this.port = await portfinder.getPortPromise({
port: 33776,
});
this.logger.log(`Selected port: ${port}`);
// Shutdown old service
this.updateBulkAttempt = undefined;
this.waitingForBulk = false;
this.clearValues();
for(const s of this.shutdown) { s(); }
this.shutdown.length = 0;

this.logger.log(`Starting OSCQuery handler...`);
const oscQuery = this.oscQuery = new OSCQueryServer({
httpPort: port,
serviceName: "OGB"
});
oscQuery.addMethod("/avatar/change", { access: OSCQAccess.WRITEONLY });
this.logger.log(`Started`);

this.logger.log(`Starting OSCQuery HTTP server...`);
const httpServer = http.createServer(oscQuery._httpHandler.bind(oscQuery));
httpServer.on('error', e => this.logger.log(`HTTP server error ${e.stack}`));
await new Promise<void>((resolve, reject) => {
httpServer.listen(port, () => {
resolve();
}).on('error', (err) => {
reject(err);
let port = 9001;
if (this.useOscQuery) {
port = this.port = await portfinder.getPortPromise({
port: 33776,
});
});
this.logger.log(`Started on port ${port}`);
}
this.logger.log(`Selected port: ${port}`);

this.logger.log(`Starting OSCQuery MDNS server...`);
const mdns = getResponder();
const mdnsService = mdns.createService({
name: "OGB",
type: "oscjson",
port: port,
protocol: Protocol.TCP,
});
// Do this async, in case it never returns, which seems to happen for some reason
(async () => {
try {
await mdnsService.advertise();
this.logger.log(`MDNS is advertising`);
} catch (e) {
this.logger.log(`MDNS advertising error ${e instanceof Error ? e.stack : e}`);
}
})().then();
if (this.useOscQuery) {
this.logger.log(`Starting OSCQuery handler...`);
const oscQuery = this.oscQuery = new OSCQueryServer({
httpPort: port,
serviceName: "OGB"
});
this.shutdown.push(() => oscQuery.stop());
oscQuery.addMethod("/avatar/change", { access: OSCQAccess.WRITEONLY });
this.logger.log(`Started`);

this.logger.log(`Starting OSCQuery HTTP server...`);
const httpServer = http.createServer(oscQuery._httpHandler.bind(oscQuery));
this.shutdown.push(() => httpServer.close());
httpServer.on('error', e => this.logger.log(`HTTP server error ${e.stack}`));
await new Promise<void>((resolve, reject) => {
httpServer.listen(port, () => {
resolve();
}).on('error', (err) => {
reject(err);
});
});
this.logger.log(`Started on port ${port}`);

this.logger.log(`Starting OSCQuery MDNS server...`);
const mdns = getResponder();
this.shutdown.push(() => mdns.shutdown());
const mdnsService = mdns.createService({
name: "OGB",
type: "oscjson",
port: port,
protocol: Protocol.TCP,
});
// Do this async, in case it never returns, which seems to happen for some reason
(async () => {
try {
await mdnsService.advertise();
this.logger.log(`MDNS is advertising`);
} catch (e) {
this.logger.log(`MDNS advertising error ${e instanceof Error ? e.stack : e}`);
}
})().then();
}

let receivedOne = false;

Expand All @@ -137,13 +174,15 @@ export default class OscConnection extends (EventEmitter as new () => TypedEmitt
localPort: port,
metadata: true
});
this.shutdown.push(() => oscSocket.close());
oscSocket.on('ready', () => {
this.socketopen = true;
this.recentlyRcvdOscCmds = 0;
this.lastPacket = 0;
this.logger.log('<-', 'OPEN');
this.logger.log("Waiting for first message from OSC ...");
});
this.shutdown.push(() => this.socketopen = false);
oscSocket.on('error', (e: unknown) => {
// node osc throws errors for all sorts of invalid packets and things we often receive
// that otherwise shouldn't be fatal to the socket. Just ignore them.
Expand Down Expand Up @@ -251,23 +290,6 @@ export default class OscConnection extends (EventEmitter as new () => TypedEmitt
}
}

delayRetry() {
this.socketopen = false;
this.updateBulkAttempt = undefined;
this.waitingForBulk = false;
this.clearValues();
if (this.oscSocket) {
this.oscSocket.close();
this.oscSocket = undefined;
}
if (this.oscQuery) {
this.oscQuery.stop();
this.oscQuery = undefined;
}
clearTimeout(this.retryTimeout);
this.retryTimeout = setTimeout(() => this.openSocket(), 1000);
}

send(paramName: string, value: number) {
if (!this.oscSocket || !this.socketopen) return;
const sendAddr = this.vrchatOscqueryService.getOscAddress();
Expand Down
1 change: 1 addition & 0 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ try {
} else {
sections.push(
`OGB OSC: ${oscConnection.port}\n`
+ `OGB OSCQ: ${oscConnection.useOscQuery ? 'Enabled' : 'Disabled'}\n`
+ `VRC OSC: ${vrchatOscqueryService.getOscAddress()?.join(':')}\n`
+ `VRC OSCQ: ${vrchatOscqueryService.getOscqueryAddress()?.join(':')}`
);
Expand Down

0 comments on commit f34e8e2

Please sign in to comment.