Skip to content

Commit

Permalink
Merge pull request #201 from Troid-Tech/connect-to-wss
Browse files Browse the repository at this point in the history
Fix https and add wss support
  • Loading branch information
stonedDiscord committed Nov 22, 2023
2 parents 6480caf + f848f34 commit 26e3cd4
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 106 deletions.
29 changes: 22 additions & 7 deletions webAO/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { loadResources } from './client/loadResources'
import { AO_HOST } from './client/aoHost'
import { fetchBackgroundList, fetchEvidenceList, fetchCharacterList } from './client/fetchLists'

const { ip: serverIP, mode, theme, serverName } = queryParser();
const { ip: serverIP, connect, mode, theme, serverName } = queryParser();

document.title = serverName;

Expand Down Expand Up @@ -70,12 +70,27 @@ fpPromise
.then((result) => {
hdid = result.visitorId;

if (!serverIP) {
alert("No server IP specified!");
return;
let connectionString = connect;

if (!connectionString) {
if (serverIP) {
// if connectionString is not set, try IP
// and just guess ws, though it could be wss
connectionString = `ws://${serverIP}`;
} else {
alert("No connection string specified!");
return;
}
}

if (window.location.protocol === "https:" && connectionString.startsWith("ws://")) {
// If protocol is https: and connectionString is ws://
// We have a problem, since it's impossible to connect to ws:// from https://
// Connection will fail, but at least warn the user
alert('Attempted to connect using insecure websockets on https page. Please try removing s from https:// in the URL bar.')
}

client = new Client(serverIP);
client = new Client(connectionString);
client.connect()
isLowMemory();
loadResources();
Expand Down Expand Up @@ -117,7 +132,7 @@ class Client extends EventEmitter {
connect: () => void;
loadResources: () => void
isLowMemory: () => void
constructor(address: string) {
constructor(connectionString: string) {
super();

this.connect = () => {
Expand All @@ -126,7 +141,7 @@ class Client extends EventEmitter {
this.on("message", this.onMessage.bind(this));
this.on("error", this.onError.bind(this));
if (mode !== "replay") {
this.serv = new WebSocket(`ws://${address}`);
this.serv = new WebSocket(connectionString);
// Assign the websocket events
this.serv.addEventListener("open", this.emit.bind(this, "open"));
this.serv.addEventListener("close", this.emit.bind(this, "close"));
Expand Down
9 changes: 9 additions & 0 deletions webAO/client/aoHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,14 @@ import queryParser from '../utils/queryParser'
const { asset } = queryParser();
export let AO_HOST = asset;
export const setAOhost = (val: string) => {
const currentProtocol = window.location.protocol;
const assetProtocol = val.split(':')[0] + ':';

if (currentProtocol === 'https:' && assetProtocol === 'http:') {
// In this specific case, we need to request assets over HTTPS
console.log('Upgrading asset link to https');
val = val.replace('http:', 'https:');
}

AO_HOST = val;
}
156 changes: 59 additions & 97 deletions webAO/master.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import FingerprintJS from '@fingerprintjs/fingerprintjs';

import { safeTags } from './encoding';

declare global {
Expand Down Expand Up @@ -28,10 +26,6 @@ const protocol = window.location.protocol;

const serverlist_cache_key = 'masterlist';

let hdid: string;

let selectedServer: number = -1;

const servers: AOServer[] = [];
servers[-2] = {
name: 'Singleplayer',
Expand All @@ -52,96 +46,29 @@ servers[-1] = {
players: 0,
};

const fpPromise = FingerprintJS.load();
fpPromise
.then((fp) => fp.get())
.then(async (result) => {
hdid = result.visitorId;

check_https();

getServerlist().then((serverlist) => {
processServerlist(serverlist);
});

processClientVersion(clientVersion);
function main() {
getServerlist().then((serverlist) => {
processServerlist(serverlist);
});

getMasterVersion().then((masterVersion) => {
processMasterVersion(masterVersion);
});
processClientVersion(clientVersion);

// i don't need the ms to play alone
setTimeout(() => checkOnline(-1, '127.0.0.1:50001'), 0);
getMasterVersion().then((masterVersion) => {
processMasterVersion(masterVersion);
});

export function check_https() {
if (protocol === 'https:') {
document.getElementById('https_error').style.display = '';
setTimeout(() => window.location.replace("http://web.aceattorneyonline.com/"), 5000);
}
}

export function setServ(ID: number) {
selectedServer = ID;
main();

if (document.getElementById(`server${ID}`).className === '') { checkOnline(ID, `${servers[ID].ip}:${servers[ID].ws_port}`); }

document.getElementById('serverdescription_content').innerHTML = `<b>${servers[ID].online}</b><br>${safeTags(servers[ID].description)}`;
export function setServ(ID: number) {
const server = servers[ID];
const onlineStr = server.online;
const serverDesc = safeTags(server.description);
document.getElementById('serverdescription_content').innerHTML = `<b>${onlineStr}</b><br>${serverDesc}`;
}
window.setServ = setServ;

function checkOnline(serverID: number, coIP: string) {
let serverConnection: WebSocket;
if (serverID !== -2) {
try {
serverConnection = new WebSocket(`ws://${coIP}`);
} catch (SecurityError) {
document.getElementById(`server${serverID}`).className = 'unavailable';
return;
}
}

// define what the callbacks do
function onCOOpen() {
document.getElementById(`server${serverID}`).className = 'available';
serverConnection.send(`HI#${hdid}#%`);
serverConnection.send('ID#webAO#webAO#%');
}

function onCOMessage(e: MessageEvent) {
const comsg = e.data;
const coheader = comsg.split('#', 2)[0];
const coarguments = comsg.split('#').slice(1);
if (coheader === 'PN') {
servers[serverID].online = `Online: ${Number(coarguments[0])}/${Number(coarguments[1])}`;
serverConnection.close();
return;
} if (coheader === 'BD') {
servers[serverID].online = 'Banned';
servers[serverID].description = coarguments[0];
serverConnection.close();
return;
}
if (serverID === selectedServer) {
document.getElementById('serverdescription_content').innerHTML = `<b>${servers[serverID].online}</b><br>${safeTags(servers[serverID].description)}`;
}
}

// assign the callbacks
serverConnection.onopen = function () {
onCOOpen();
};

serverConnection.onmessage = function (evt: MessageEvent) {
onCOMessage(evt);
};

serverConnection.onerror = function (_evt: Event) {
document.getElementById(`server${serverID}`).className = 'unavailable';
console.error(`Error connecting to ${coIP}`);
console.error(_evt);
};
}

// Fetches the serverlist from the masterserver
// Returns a properly typed list of servers
Expand Down Expand Up @@ -209,32 +136,67 @@ function getCachedServerlist(): AOServer[] {
return JSON.parse(cached) as AOServer[];
}

// Constructs the client URL robustly, independent of domain and path
function constructClientURL(protocol: string): string {
const clientURL = new URL(window.location.href);

// Use the given protocol
clientURL.protocol = protocol;

// Remove the last part of the pathname (e.g., "index.html")
const pathname = clientURL.pathname;
const parts = pathname.split('/');
parts.pop();

// Reconstruct the pathname
clientURL.pathname = parts.join('/');

// If clientURL.pathname does not end with a slash, add one
if (clientURL.pathname[clientURL.pathname.length - 1] !== '/') {
clientURL.pathname += '/'
}

clientURL.pathname += "client.html";

return clientURL.href;
}

function processServerlist(serverlist: AOServer[]) {
const host = window.location.host;
const clientURL: string = `${protocol}//${host}/client.html`;
for (let i = 0; i < serverlist.length - 1; i++) {
for (let i = 0; i < serverlist.length; i++) {
const server = serverlist[i];
let port = 0;
let ws_port = 0;
let ws_protocol = '';
let http_protocol = '';

if (server.ws_port) {
port = server.ws_port;
ws_port = server.ws_port;
ws_protocol = 'ws';
http_protocol = 'http';
}
if (server.wss_port) {
port = server.wss_port;
ws_port = server.wss_port;
ws_protocol = 'wss';
http_protocol = 'https';
}
if (port === 0) {

if (ws_port === 0 || ws_protocol === '' || http_protocol === '') {
console.warn(`Server ${server.name} has no websocket port, skipping`)
continue;
}

const ipport = `${server.ip}:${port}`;
const clientURL = constructClientURL(http_protocol);
const connect = `${ws_protocol}://${server.ip}:${ws_port}`;
const serverName = server.name;
server.online = 'Offline';
const fullClientWatchURL = `${clientURL}?mode=watch&connect=${connect}&serverName=${serverName}`;
const fullClientJoinURL = `${clientURL}?mode=join&connect=${connect}&serverName=${serverName}`;

server.online = `Players: ${server.players}`;
servers.push(server);

document.getElementById('masterlist').innerHTML
+= `<li id="server${i}" onmouseover="setServ(${i})"><p>${safeTags(server.name)} (${server.players})</p>`
+ `<a class="button" href="${clientURL}?mode=watch&ip=${ipport}&serverName=${serverName}">Watch</a>`
+ `<a class="button" href="${clientURL}?mode=join&ip=${ipport}&serverName=${serverName}">Join</a></li>`;
+ `<a class="button" href="${fullClientWatchURL}" target="_blank">Watch</a>`
+ `<a class="button" href="${fullClientJoinURL}" target="_blank">Join</a></li>`;
}
}

Expand Down
7 changes: 5 additions & 2 deletions webAO/utils/queryParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@

interface QueryParams {
ip: string;
connect: string;
mode: string;
asset: string;
theme: string;
serverName: string;
}

const queryParser = (): QueryParams => {
const protocol = window.location.protocol;
const urlParams = new URLSearchParams(window.location.search);
const queryParams = {
ip: urlParams.get("ip") || "",
connect: urlParams.get("connect") || "",
mode: urlParams.get("mode") || "join",
asset: urlParams.get("asset") || "http://attorneyoffline.de/base/",
asset: urlParams.get("asset") || `${protocol}//attorneyoffline.de/base/`,
theme: urlParams.get("theme") || "default",
serverName: urlParams.get("serverName") || "Attorney Online session"
serverName: urlParams.get("serverName") || "Attorney Online session",
}
return queryParams as QueryParams;
};
Expand Down

0 comments on commit 26e3cd4

Please sign in to comment.