Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add back console relay #182

Merged
merged 12 commits into from
Jun 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/console/consoleRelay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Ports } from "@slippi/slippi-js";
import log from "electron-log";
import net from "net";

interface ConsoleDataBuffer {
buffersToConcat: Buffer[];
fullBuffer: Buffer;
}

export class ConsoleRelay {
private server: net.Server | null;
private dataBuffer: ConsoleDataBuffer;
private clients: net.Socket[];

public constructor(id: number) {
this.clients = [];
this.dataBuffer = {
buffersToConcat: [],
fullBuffer: Buffer.from([]),
};
this.server = net.createServer((socket) => {
socket.setNoDelay().setTimeout(20000);

// Only get the full buffer when the client connects for performance
const buf = this.getFullBuffer();
socket.write(buf);

this.clients.push(socket);
socket.on("close", (err) => {
if (err) {
console.warn(err);
}
this.clients = this.clients.filter((client) => socket !== client);
});
});
this.server.listen(Ports.RELAY_START + id, "0.0.0.0");
}

public stopRelay() {
this.clients.forEach((client) => client.destroy());
this.clients = [];
if (this.server !== null) {
this.server.close();
}
this.server = null;
}

public write(newData: Buffer) {
this.dataBuffer.buffersToConcat.push(newData);
if (this.clients) {
this.clients.forEach((client) => {
try {
client.write(newData);
} catch (err) {
log.warn(`Could not write to a client...${err}`);
}
});
}
}

public async clearBuffer() {
this.dataBuffer.buffersToConcat = [];
this.dataBuffer.fullBuffer = Buffer.from([]);
}

private getFullBuffer() {
if (this.dataBuffer.buffersToConcat.length > 0) {
this.dataBuffer.fullBuffer = Buffer.concat([this.dataBuffer.fullBuffer, ...this.dataBuffer.buffersToConcat]);
}
this.dataBuffer.buffersToConcat = [];
return this.dataBuffer.fullBuffer;
}
}
23 changes: 22 additions & 1 deletion src/console/mirrorManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import log from "electron-log";
import path from "path";

import { AutoSwitcher } from "./autoSwitcher";
import { ConsoleRelay } from "./consoleRelay";
import { consoleMirrorStatusUpdated } from "./ipc";
import { MirrorConfig, MirrorDetails } from "./types";

Expand Down Expand Up @@ -49,6 +50,7 @@ export class MirrorManager {
}

public async connect(config: MirrorConfig) {
log.info(config.id);
if (this.mirrors[config.ipAddress]) {
log.info(`[Mirroring] already connected to Wii @ ${config.ipAddress}`);
return;
Expand Down Expand Up @@ -83,6 +85,12 @@ export class MirrorManager {
.catch((err) => log.warn(err));
});

let relay: ConsoleRelay | null = null;
if (config.enableRelay) {
log.info("starting relay");
relay = new ConsoleRelay(config.id);
}

const connection = new ConsoleConnection();
connection.once("connect", () => {
log.info("[Mirroring] Connecting to Wii");
Expand Down Expand Up @@ -113,8 +121,14 @@ export class MirrorManager {
.catch((err) => log.warn(err));
});

connection.on(ConnectionEvent.DATA, (data) => fileWriter.write(data));
connection.on(ConnectionEvent.DATA, (data: Buffer) => {
fileWriter.write(data);
if (relay) {
relay.write(data);
}
});
});
log.info(config.port);
connection.connect(config.ipAddress, config.port ?? Ports.DEFAULT);

let autoSwitcher: AutoSwitcher | null = null;
Expand All @@ -141,6 +155,9 @@ export class MirrorManager {
if ((payload as GameEndType).gameEndMethod !== 7) {
autoSwitcher.handleStatusOutput(700);
}
if (relay) {
relay.clearBuffer(); // clear buffer after each game to avoid concating a gigantic array
}
break;
}
}
Expand All @@ -152,6 +169,7 @@ export class MirrorManager {
fileWriter,
connection,
autoSwitcher,
relay,
};
}

Expand All @@ -167,6 +185,9 @@ export class MirrorManager {
if (details.autoSwitcher) {
details.autoSwitcher.disconnect();
}
if (details.relay) {
details.relay.stopRelay();
}
delete this.mirrors[ip];

// FIXME: Not sure why the disconnected status update isn't working
Expand Down
5 changes: 4 additions & 1 deletion src/console/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ConsoleConnection, SlpFileWriter } from "@slippi/slippi-js";

import { AutoSwitcher } from "./autoSwitcher";
import { ConsoleRelay } from "./consoleRelay";

export interface ConsoleMirrorStatusUpdate {
status: number;
Expand All @@ -9,11 +10,12 @@ export interface ConsoleMirrorStatusUpdate {
}

export interface MirrorConfig {
id?: number;
id: number;
ipAddress: string;
port: number;
folderPath: string;
isRealTimeMode?: boolean;
enableRelay?: boolean;
autoSwitcherSettings?: AutoSwitcherSettings;
}

Expand All @@ -22,6 +24,7 @@ export interface MirrorDetails extends MirrorConfig {
connection: ConsoleConnection;
fileWriter: SlpFileWriter;
autoSwitcher: AutoSwitcher | null;
relay: ConsoleRelay | null;
}

export interface AutoSwitcherSettings {
Expand Down
4 changes: 2 additions & 2 deletions src/dolphin/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import path from "path";

import { DolphinLaunchType } from "./types";

export async function findDolphinExecutable(type: DolphinLaunchType | string, dolphinPath?: string): Promise<string> {
export async function findDolphinExecutable(type: DolphinLaunchType, dolphinPath?: string): Promise<string> {
// Make sure the directory actually exists
if (!dolphinPath) {
dolphinPath = settingsManager.getDolphinPath(type as DolphinLaunchType);
dolphinPath = settingsManager.getDolphinPath(type);
}

await fs.ensureDir(dolphinPath);
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/containers/Console/AddConnectionDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import DialogTitle from "@material-ui/core/DialogTitle";
import { useTheme } from "@material-ui/core/styles";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { StoredConnection } from "@settings/types";
import { Ports } from "@slippi/slippi-js";
import merge from "lodash/merge";
import React from "react";

Expand Down Expand Up @@ -35,7 +36,7 @@ export const AddConnectionDialog: React.FC<AddConnectionDialogProps> = ({
setTitle(isEditing ? "Edit Connection" : "New Connection");
};
const defaultValues: Partial<StoredConnection> = merge(
{ isRealTimeMode: false, folderPath: spectateFolder },
{ isRealTimeMode: false, folderPath: spectateFolder, port: Ports.DEFAULT },
selectedConnection,
);
return (
Expand Down
Loading