Skip to content

Commit

Permalink
Merge pull request #33 from SlimeVR/feat/tracker-emulation/server-dis…
Browse files Browse the repository at this point in the history
…connect

feat(tracker-emulation): disconnecting and deinitialization
  • Loading branch information
TheDevMinerTV authored Jun 7, 2024
2 parents 65cff4d + a608b5e commit 190e0b3
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-mails-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@slimevr/tracker-emulation': patch
---

implement disconnecting and deinitializing for the trackers
8 changes: 8 additions & 0 deletions apps/emulated-tracker-demo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const sensors: EmulatedSensor[] = [];

const main = async () => {
tracker.on('ready', (ip, port) => console.log(`ready and running on ${ip}:${port}`));
tracker.on('unready', () => console.log('unready'));

tracker.on('error', (err) => console.error(err));

tracker.on('searching-for-server', () => console.log('searching for server...'));
Expand Down Expand Up @@ -98,6 +100,12 @@ const main = async () => {
i += 0.1;
}, 100).unref();
}

setTimeout(() => {
tracker.disconnectFromServer();

tracker.deinit()
}, 10000);
};

main();
88 changes: 56 additions & 32 deletions packages/tracker-emulation/src/EmulatedTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { EmulatedSensor } from './EmulatedSensor.js';

type State =
| { status: 'initializing' }
| { status: 'disconnected' }
| { status: 'idle' }
| { status: 'searching-for-server'; discoveryInterval: NodeJS.Timeout }
| {
status: 'connected-to-server';
Expand All @@ -51,12 +51,13 @@ export class TimeoutError extends Error {
}
}

type DisconnectReason = TimeoutError | Error;
type DisconnectReason = TimeoutError | Error | 'manual';
type SearchStopReason = 'manual' | 'found-server';

interface EmulatedTrackerEvents {
error: (error: Error) => void;
ready: (ip: string, port: number) => void;
unready: () => void;

'searching-for-server': () => void;
'stopped-searching-for-server': (reason: SearchStopReason) => void;
Expand Down Expand Up @@ -105,17 +106,8 @@ export class EmulatedTracker extends (EventEmitter as {
});
}

private disconnectFromServer(reason: DisconnectReason) {
if (this.state.status === 'searching-for-server') {
clearInterval(this.state.discoveryInterval);
}

this.state = { status: 'disconnected' };
this.emit('disconnected-from-server', reason);

if (this.autoSearchForServer) {
this.searchForServer();
}
disconnectFromServer() {
this.disconnectFromServerWithReason('manual');
}

unref() {
Expand All @@ -133,25 +125,14 @@ export class EmulatedTracker extends (EventEmitter as {
return sensor;
}

private async sendDiscovery() {
await this.sendPacket(
new ServerBoundHandshakePacket(
this.boardType,
SensorType.UNKNOWN,
this.mcuType,
SUPPORTED_FIRMWARE_PROTOCOL_VERSION,
this.firmware,
this.mac
),
this.serverDiscoveryPort,
this.serverDiscoveryIP
);
}

async init() {
await new Promise<void>((resolve) => this.socket.bind(0, () => resolve()));
if (this.state.status !== 'initializing') return;

await new Promise<void>((resolve) => this.socket.bind(0, resolve));
this.socket.setBroadcast(true);

this.state = { status: 'idle' };

const addr = this.socket.address();
this.emit('ready', addr.address, addr.port);

Expand All @@ -160,7 +141,20 @@ export class EmulatedTracker extends (EventEmitter as {
}
}

async deinit() {
if (this.state.status === 'initializing') return;

this.stopSearchingForServer();
this.disconnectFromServer();
await new Promise<void>((resolve) => this.socket.close(resolve));

this.state = { status: 'initializing' };
this.emit('unready');
}

searchForServer() {
if (this.state.status !== 'idle') return;

this.state = {
status: 'searching-for-server',
discoveryInterval: setInterval(() => this.sendDiscovery(), 1000)
Expand All @@ -172,7 +166,7 @@ export class EmulatedTracker extends (EventEmitter as {
if (this.state.status !== 'searching-for-server') return;

clearInterval(this.state.discoveryInterval);
this.state = { status: 'disconnected' };
this.state = { status: 'idle' };

this.emit('stopped-searching-for-server', 'manual');
}
Expand Down Expand Up @@ -226,6 +220,8 @@ export class EmulatedTracker extends (EventEmitter as {
}

private async sendPacket(packet: Packet, port: number, ip: string) {
if (this.state.status === 'initializing') return;

const encoded = packet.encode(this.state.status === 'connected-to-server' ? this.state.packetNumber++ : 0n);

await new Promise<void>((res, rej) =>
Expand All @@ -235,8 +231,32 @@ export class EmulatedTracker extends (EventEmitter as {
this.emit('outgoing-packet', packet);
}

private disconnectFromServerWithReason(reason: DisconnectReason) {
if (this.state.status !== 'connected-to-server') return;

clearInterval(this.state.timeoutCheckInterval);

this.state = { status: 'idle' };
this.emit('disconnected-from-server', reason);
}

private async sendDiscovery() {
await this.sendPacket(
new ServerBoundHandshakePacket(
this.boardType,
SensorType.UNKNOWN,
this.mcuType,
SUPPORTED_FIRMWARE_PROTOCOL_VERSION,
this.firmware,
this.mac
),
this.serverDiscoveryPort,
this.serverDiscoveryIP
);
}

private async handle(msg: Buffer, addr: RemoteInfo) {
if (this.state.status === 'initializing' || this.state.status === 'disconnected') return;
if (this.state.status === 'initializing' || this.state.status === 'idle') return;

if (this.state.status === 'searching-for-server') {
if (msg.readUint8(0) !== DeviceBoundHandshakePacket.type) return;
Expand All @@ -254,7 +274,11 @@ export class EmulatedTracker extends (EventEmitter as {
if (this.state.status !== 'connected-to-server') return;
if (Date.now() - this.state.lastReceivedPacketTimestamp < this.serverTimeout) return;

this.disconnectFromServer(new TimeoutError('heartbeat', this.serverTimeout));
this.disconnectFromServerWithReason(new TimeoutError('heartbeat', this.serverTimeout));

if (this.autoSearchForServer) {
this.searchForServer();
}
}, 1000).unref()
};

Expand Down

0 comments on commit 190e0b3

Please sign in to comment.