You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
790 lines
23 KiB
JavaScript
790 lines
23 KiB
JavaScript
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
//-- Server side logic. Serves pixel streaming WebRTC-based page, proxies data back to WebRTC proxy --//
|
|
|
|
var express = require('express');
|
|
var app = express();
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const querystring = require('querystring');
|
|
const bodyParser = require('body-parser');
|
|
const logging = require('./modules/logging.js');
|
|
logging.RegisterConsoleLogger();
|
|
|
|
// Command line argument --configFile needs to be checked before loading the config, all other command line arguments are dealt with through the config object
|
|
|
|
const defaultConfig = {
|
|
UseFrontend: false,
|
|
UseMatchmaker: false,
|
|
UseHTTPS: false,
|
|
UseAuthentication: false,
|
|
LogToFile: true,
|
|
HomepageFile: 'player.htm',
|
|
AdditionalRoutes: new Map()
|
|
};
|
|
|
|
const argv = require('yargs').argv;
|
|
var configFile = (typeof argv.configFile != 'undefined') ? argv.configFile.toString() : '.\\config.json';
|
|
const config = require('./modules/config.js').init(configFile, defaultConfig)
|
|
|
|
if (config.LogToFile) {
|
|
logging.RegisterFileLogger('./logs');
|
|
}
|
|
|
|
console.log("Config: " + JSON.stringify(config, null, '\t'))
|
|
|
|
var http = require('http').Server(app);
|
|
|
|
if(config.UseHTTPS){
|
|
//HTTPS certificate details
|
|
const options = {
|
|
key: fs.readFileSync(path.join(__dirname, './certificates/client-key.pem')),
|
|
cert: fs.readFileSync(path.join(__dirname, './certificates/client-cert.pem'))
|
|
};
|
|
|
|
var https = require('https').Server(options, app);
|
|
var io = require('socket.io')(https);
|
|
} else {
|
|
var io = require('socket.io')(http);
|
|
}
|
|
|
|
//If not using authetication then just move on to the next function/middleware
|
|
var isAuthenticated = redirectUrl => function(req, res, next){ return next(); }
|
|
|
|
if(config.UseAuthentication && config.UseHTTPS){
|
|
var passport = require('passport');
|
|
require('./modules/authentication').init(app);
|
|
// Replace the isAuthenticated with the one setup on passport module
|
|
isAuthenticated = passport.authenticationMiddleware ? passport.authenticationMiddleware : isAuthenticated
|
|
} else if(config.UseAuthentication && !config.UseHTTPS) {
|
|
console.log('ERROR: Trying to use authentication without using HTTPS, this is not allowed and so authentication will NOT be turned on, please turn on HTTPS to turn on authentication');
|
|
}
|
|
|
|
const helmet = require('helmet');
|
|
var hsts = require('hsts');
|
|
var net = require('net');
|
|
|
|
var FRONTEND_WEBSERVER = 'https://localhost';
|
|
if(config.UseFrontend){
|
|
var httpPort = 3000;
|
|
var httpsPort = 8000;
|
|
|
|
//Required for self signed certs otherwise just get an error back when sending request to frontend see https://stackoverflow.com/a/35633993
|
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
|
|
|
|
const httpsClient = require('./modules/httpsClient.js');
|
|
var webRequest = new httpsClient();
|
|
} else {
|
|
var httpPort = 80;
|
|
var httpsPort = 443;
|
|
}
|
|
|
|
var proxyPort = 8888; // port to listen to WebRTC proxy connections
|
|
var proxyBuffer = new Buffer(0);
|
|
|
|
var matchmakerAddress = '127.0.0.1';
|
|
var matchmakerPort = 9999;
|
|
|
|
var gameSessionId;
|
|
var userSessionId;
|
|
var serverPublicIp;
|
|
|
|
//Example of STUN server setting
|
|
//let clientConfig = {peerConnectionOptions: { 'iceServers': [{'urls': ['stun:34.250.222.95:19302']}] }};
|
|
var clientConfig = {peerConnectionOptions: {}};
|
|
|
|
// Parse public server address from command line
|
|
// --publicIp <public address>
|
|
try {
|
|
if(typeof config.publicIp != 'undefined'){
|
|
serverPublicIp = config.publicIp.toString();
|
|
}
|
|
|
|
if(typeof config.httpPort != 'undefined'){
|
|
httpPort = config.httpPort;
|
|
}
|
|
|
|
if(typeof config.httpsPort != 'undefined'){
|
|
httpsPort = config.httpsPort;
|
|
}
|
|
|
|
if(typeof config.proxyPort != 'undefined'){
|
|
proxyPort = config.proxyPort;
|
|
}
|
|
|
|
if(typeof config.frontendUrl != 'undefined'){
|
|
FRONTEND_WEBSERVER = config.frontendUrl;
|
|
}
|
|
|
|
if(typeof config.peerConnectionOptions != 'undefined'){
|
|
clientConfig.peerConnectionOptions = JSON.parse(config.peerConnectionOptions);
|
|
console.log(`peerConnectionOptions = ${JSON.stringify(clientConfig.peerConnectionOptions)}`);
|
|
}
|
|
|
|
if (typeof config.matchmakerAddress != 'undefined') {
|
|
matchmakerAddress = config.matchmakerAddress;
|
|
}
|
|
|
|
if (typeof config.matchmakerPort != 'undefined') {
|
|
matchmakerPort = config.matchmakerPort;
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
process.exit(2);
|
|
}
|
|
|
|
if(config.UseHTTPS){
|
|
app.use(helmet());
|
|
|
|
app.use(hsts({
|
|
maxAge: 15552000 // 180 days in seconds
|
|
}));
|
|
|
|
//Setup http -> https redirect
|
|
console.log('Redirecting http->https');
|
|
app.use(function (req, res, next) {
|
|
if (!req.secure) {
|
|
if(req.get('Host')){
|
|
var hostAddressParts = req.get('Host').split(':');
|
|
var hostAddress = hostAddressParts[0];
|
|
if(httpsPort != 443) {
|
|
hostAddress = `${hostAddress}:${httpsPort}`;
|
|
}
|
|
return res.redirect(['https://', hostAddress, req.originalUrl].join(''));
|
|
} else {
|
|
console.log(`ERROR unable to get host name from header. Requestor ${req.ip}, url path: '${req.originalUrl}', available headers ${JSON.stringify(req.headers)}`);
|
|
return res.status(400).send('Bad Request');
|
|
}
|
|
}
|
|
next();
|
|
});
|
|
}
|
|
|
|
sendGameSessionData();
|
|
|
|
//Setup folders
|
|
app.use(express.static(path.join(__dirname, '/public')))
|
|
app.use('/images', express.static(path.join(__dirname, './images')))
|
|
app.use('/scripts', [isAuthenticated('/login'), express.static(path.join(__dirname, '/scripts'))]);
|
|
app.use('/', [isAuthenticated('/login'), express.static(path.join(__dirname, '/custom_html'))])
|
|
|
|
try{
|
|
for (var property in config.AdditionalRoutes) {
|
|
if (config.AdditionalRoutes.hasOwnProperty(property)) {
|
|
console.log(`Adding additional routes "${property}" -> "${config.AdditionalRoutes[property]}"`)
|
|
app.use(property, [isAuthenticated('/login'), express.static(path.join(__dirname, config.AdditionalRoutes[property]))]);
|
|
}
|
|
}
|
|
} catch(err) {
|
|
console.log(`Error reading config.AdditionalRoutes: ${err}`)
|
|
}
|
|
|
|
|
|
app.get('/', isAuthenticated('/login'), function(req, res){
|
|
homepageFile = (typeof config.HomepageFile != 'undefined' && config.HomepageFile != '') ? config.HomepageFile.toString() : defaultConfig.HomepageFile;
|
|
homepageFilePath = path.join(__dirname, homepageFile)
|
|
|
|
fs.access(homepageFilePath, (err) => {
|
|
if (err) {
|
|
console.log('Unable to locate file ' + homepageFilePath)
|
|
res.status(404).send('Unable to locate file ' + homepageFile);
|
|
}
|
|
else {
|
|
res.sendFile(homepageFilePath);
|
|
}
|
|
});
|
|
});
|
|
|
|
//Setup the login page if we are using authentication
|
|
if(config.UseAuthentication){
|
|
app.get('/login', function(req, res){
|
|
res.sendFile(__dirname + '/login.htm');
|
|
});
|
|
|
|
// create application/x-www-form-urlencoded parser
|
|
var urlencodedParser = bodyParser.urlencoded({ extended: false })
|
|
|
|
//login page form data is posted here
|
|
app.post('/login',
|
|
urlencodedParser,
|
|
passport.authenticate('local', { failureRedirect: '/login' }),
|
|
function(req, res){
|
|
//On success try to redirect to the page that they originally tired to get to, default to '/' if no redirect was found
|
|
var redirectTo = req.session.redirectTo ? req.session.redirectTo : '/';
|
|
delete req.session.redirectTo;
|
|
console.log(`Redirecting to: '${redirectTo}'`);
|
|
res.redirect(redirectTo);
|
|
}
|
|
);
|
|
}
|
|
|
|
/*
|
|
app.get('/:sessionId', isAuthenticated('/login'), function(req, res){
|
|
let sessionId = req.params.sessionId;
|
|
console.log(sessionId);
|
|
|
|
//For now don't verify session id is valid, just send player.htm if they get the right server
|
|
res.sendFile(__dirname + '/player.htm');
|
|
});
|
|
*/
|
|
|
|
/*
|
|
app.get('/custom_html/:htmlFilename', isAuthenticated('/login'), function(req, res){
|
|
let htmlFilename = req.params.htmlFilename;
|
|
|
|
let htmlPathname = __dirname + '/custom_html/' + htmlFilename;
|
|
|
|
console.log(htmlPathname);
|
|
fs.access(htmlPathname, (err) => {
|
|
if (err) {
|
|
res.status(404).send('Unable to locate file ' + htmlPathname);
|
|
}
|
|
else {
|
|
res.sendFile(htmlPathname);
|
|
}
|
|
});
|
|
});
|
|
*/
|
|
|
|
let clients = []; // either web-browsers or native webrtc receivers
|
|
let nextClientId = 100;
|
|
|
|
let proxySocket;
|
|
|
|
function cleanUpProxyConnection() {
|
|
if(proxySocket){
|
|
proxySocket.end();
|
|
proxySocket = undefined;
|
|
proxyBuffer = new Buffer(0);
|
|
// make a copy of `clients` array as it will be modified in the loop
|
|
let clientsCopy = clients.slice();
|
|
clientsCopy.forEach(function (c) {
|
|
c.ws.disconnect();
|
|
});
|
|
}
|
|
}
|
|
|
|
let proxyListener = net.createServer(function(socket) {
|
|
// 'connection' listener
|
|
console.log('proxy connected');
|
|
|
|
socket.setNoDelay();
|
|
|
|
socket.on('data', function (data) {
|
|
proxyBuffer = Buffer.concat([proxyBuffer, data]);
|
|
|
|
// WebRTC proxy uses json messages instead of binary blob so need to read messages differently
|
|
while (handleProxyMessage(socket)) { }
|
|
});
|
|
|
|
socket.on('end', function () {
|
|
console.log('proxy connection end');
|
|
cleanUpProxyConnection();
|
|
});
|
|
|
|
socket.on('disconnect', function () {
|
|
console.log('proxy disconnected');
|
|
cleanUpProxyConnection();
|
|
});
|
|
|
|
socket.on('close', function() {
|
|
sendServerDisconnect();
|
|
console.log('proxy connection closed');
|
|
proxySocket = undefined;
|
|
});
|
|
|
|
socket.on('error', function (error) {
|
|
console.log(`proxy connection error ${JSON.stringify(error)}`);
|
|
cleanUpProxyConnection();
|
|
});
|
|
|
|
proxySocket = socket;
|
|
|
|
sendConfigToProxy();
|
|
});
|
|
|
|
proxyListener.maxConnections = 1;
|
|
proxyListener.listen(proxyPort, () => {
|
|
console.log('Listening to proxy connections on: ' + proxyPort);
|
|
});
|
|
|
|
// Must be kept in sync with PixelStreamingProtocol::EProxyToCirrusMsg C++ enum.
|
|
const EProxyToCirrusMsg = {
|
|
answer: 0, // [msgId:1][clientId:4][size:4][string:size]
|
|
iceCandidate: 1, // [msgId:1][clientId:4][size:4][string:size]
|
|
disconnectClient: 2 // [msgId:1][clientId:4]
|
|
}
|
|
|
|
// Must be kept in sync with PixelStreamingProtocol::ECirrusToProxyMsg C++ enum.
|
|
const ECirrusToProxyMsg = {
|
|
offer: 0, // [msgId: 1][clientId:4][size:4][string:size]
|
|
iceCandidate: 1, // [msgId:1][clientId:4][size:4][string:size]
|
|
clientDisconnected: 2, // [msgId:1][clientId:4]
|
|
config: 3 // [msgId:1][size:4][config:size]
|
|
}
|
|
|
|
function readJsonMsg(consumed) {
|
|
// format: [size:4][string:size]
|
|
if (proxyBuffer.length < consumed + 4)
|
|
return [0, ""];
|
|
let msgSize = proxyBuffer.readUInt32LE(consumed);
|
|
consumed += 4;
|
|
if (proxyBuffer.length < consumed + msgSize)
|
|
return [0, ""];
|
|
let msg = proxyBuffer.toString('ascii', consumed, consumed + msgSize);
|
|
consumed += msgSize;
|
|
return [consumed, JSON.parse(msg)];
|
|
}
|
|
|
|
function handleProxyMessage(socket) {
|
|
// msgId
|
|
if(proxyBuffer.length == 0)
|
|
return false;
|
|
let msgId = proxyBuffer.readUInt8(0);
|
|
let consumed = 1;
|
|
|
|
// clientId
|
|
if (proxyBuffer.length < consumed + 4)
|
|
return false;
|
|
let clientId = proxyBuffer.readUInt32LE(consumed);
|
|
consumed += 4;
|
|
|
|
let client = clients.find(function(c) { return c.id == clientId; });
|
|
if (!client) {
|
|
// Client is likely no longer connected, but this can also occur if bad data is recieved, this can not be validated as yet so assume former
|
|
console.error(`proxy message ${msgId}: client ${clientId} not found. Check proxy->cirrus protocol consistency`);
|
|
}
|
|
|
|
switch (msgId) {
|
|
case EProxyToCirrusMsg.answer: // fall through
|
|
case EProxyToCirrusMsg.iceCandidate:
|
|
let [localConsumed, msg] = readJsonMsg(consumed);
|
|
if (localConsumed == 0)
|
|
return false;
|
|
consumed = localConsumed;
|
|
|
|
if(client){
|
|
switch (msgId)
|
|
{
|
|
case EProxyToCirrusMsg.answer:
|
|
console.log(`answer -> client ${clientId}`);
|
|
client.ws.emit('webrtc-answer', msg);
|
|
break;
|
|
case EProxyToCirrusMsg.iceCandidate:
|
|
console.log(`ICE candidate -> client ${clientId}`);
|
|
client.ws.emit('webrtc-ice', msg);
|
|
break;
|
|
default:
|
|
throw "unhandled case, check all \"fall through\" cases from above";
|
|
}
|
|
}
|
|
|
|
break;
|
|
case EProxyToCirrusMsg.disconnectClient:
|
|
console.warn(`Proxy instructed to disconnect client ${clientId}`);
|
|
if(client){
|
|
client.ws.onclose = function() {};
|
|
client.ws.disconnect(true);
|
|
let idx = clients.map(function(p) { return p.id; }).indexOf(clientId);
|
|
clients.splice(idx, 1); // remove it
|
|
sendClientDisconnectedToProxy(clientId);
|
|
}
|
|
break;
|
|
default:
|
|
console.error(`Invalid message id ${msgId} from proxy`);
|
|
cleanUpProxyConnection();
|
|
return false;
|
|
}
|
|
|
|
proxyBuffer = proxyBuffer.slice(consumed);
|
|
return true;
|
|
}
|
|
|
|
function sendConfigToProxy() {
|
|
// [msgId:1][size:4][string:size]
|
|
if (!proxySocket)
|
|
return false;
|
|
|
|
let cfg = {};
|
|
cfg.peerConnectionConfig = clientConfig.peerConnectionOptions;
|
|
let msg = JSON.stringify(cfg);
|
|
console.log(`config to Proxy: ${msg}`);
|
|
|
|
let data = new DataView(new ArrayBuffer(1 + 4 + msg.length));
|
|
data.setUint8(0, ECirrusToProxyMsg.config);
|
|
data.setUint32(1, msg.length, true);
|
|
for (let i = 0; i != msg.length; ++i)
|
|
data.setUint8(1 + 4 + i, msg.charCodeAt(i));
|
|
proxySocket.write(Buffer.from(data.buffer));
|
|
return true;
|
|
}
|
|
|
|
function sendClientDisconnectedToProxy(clientId) {
|
|
// [msgId:1][clientId:4]
|
|
if (!proxySocket)
|
|
return;
|
|
let data = new DataView(new ArrayBuffer(1 + 4));
|
|
data.setUint8(0, ECirrusToProxyMsg.clientDisconnected);
|
|
data.setUint32(1, clientId, true);
|
|
proxySocket.write(Buffer.from(data.buffer));
|
|
}
|
|
|
|
function sendStringMsgToProxy(msgId, clientId, msg) {
|
|
// [msgId:1][clientId:4][size:4][string:size]
|
|
if (!proxySocket)
|
|
return false;
|
|
let data = new DataView(new ArrayBuffer(1 + 4 + 4 + msg.length));
|
|
data.setUint8(0, msgId);
|
|
data.setUint32(1, clientId, true);
|
|
data.setUint32(1 + 4, msg.length, true);
|
|
for (let i = 0; i != msg.length; ++i)
|
|
data.setUint8(1 + 4 + 4 + i, msg.charCodeAt(i));
|
|
proxySocket.write(Buffer.from(data.buffer));
|
|
return true;
|
|
}
|
|
|
|
function sendOfferToProxy(clientId, offer) {
|
|
sendStringMsgToProxy(ECirrusToProxyMsg.offer, clientId, offer);
|
|
}
|
|
|
|
function sendIceCandidateToProxy(clientId, iceCandidate) {
|
|
sendStringMsgToProxy(ECirrusToProxyMsg.iceCandidate, clientId, iceCandidate);
|
|
}
|
|
|
|
/**
|
|
* Function that handles the connection to the matchmaker.
|
|
*/
|
|
|
|
if (config.UseMatchmaker) {
|
|
var matchmaker = net.connect(matchmakerPort, matchmakerAddress, () => {
|
|
console.log(`Cirrus connected to Matchmaker ${matchmakerAddress}:${matchmakerPort}`);
|
|
message = {
|
|
type: 'connect',
|
|
address: typeof serverPublicIp === 'undefined' ? '127.0.0.1' : serverPublicIp,
|
|
port: httpPort
|
|
};
|
|
matchmaker.write(JSON.stringify(message));
|
|
});
|
|
|
|
matchmaker.on('error', () => {
|
|
console.log('Cirrus disconnected from matchmaker');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Function that handles an incoming client connection.
|
|
*/
|
|
function handleNewClient(ws) {
|
|
// NOTE: This needs to be the first thing to be sent
|
|
ws.emit('clientConfig', clientConfig);
|
|
|
|
var clientId = ++nextClientId;
|
|
console.log(`client ${clientId} (${ws.request.connection.remoteAddress}) connected`);
|
|
clients.push({ws: ws, id: clientId});
|
|
|
|
// Send client counts to all connected clients
|
|
ws.emit('clientCount', {count: clients.length - 1});
|
|
|
|
clients.forEach(function(c){
|
|
if(c.id == clientId)
|
|
return;
|
|
c.ws.emit('clientCount', {count: clients.length - 1});
|
|
});
|
|
|
|
ws.on('userConfig', function(userConfig) {
|
|
receiveUserConfig(clientId, userConfig, ws);
|
|
});
|
|
|
|
/**
|
|
* This is where events received from client are translated
|
|
* and sent on to the proxy socket
|
|
*/
|
|
|
|
ws.on('message', function (msg) {
|
|
console.error(`client #${clientId}: unexpected msg "${msg}"`);
|
|
});
|
|
|
|
ws.on('kick', function(msg){
|
|
// make a copy of `clients` cos the array will be modified in the loop
|
|
let clientsCopy = clients.slice();
|
|
clientsCopy.forEach(function(c){
|
|
if(c.id == clientId)
|
|
return;
|
|
console.log('Kicking client ' + c.id);
|
|
c.ws.disconnect();
|
|
})
|
|
ws.emit('clientCount', {count: 0});
|
|
})
|
|
|
|
var removeClient = function() {
|
|
let idx = clients.map(function(c) { return c.ws; }).indexOf(ws);
|
|
let clientId = clients[idx].id;
|
|
clients.splice(idx, 1); // remove it
|
|
sendClientDisconnectedToProxy(clientId);
|
|
sendClientDisconnectedToFrontend();
|
|
sendClientDisconnectedToMatchmaker();
|
|
}
|
|
|
|
ws.on('disconnect', function () {
|
|
console.log(`client ${clientId} disconnected`);
|
|
removeClient();
|
|
});
|
|
|
|
ws.on('close', function (code, reason) {
|
|
console.log(`client ${clientId} connection closed: ${code} - ${reason}`);
|
|
removeClient();
|
|
});
|
|
|
|
ws.on('error', function (err) {
|
|
console.log(`client ${clientId} connection error: ${err}`);
|
|
removeClient();
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Config data received from the web browser or device native client.
|
|
*/
|
|
function receiveUserConfig(clientId, userConfigString, ws) {
|
|
console.log(`client ${clientId}: userConfig = ${userConfigString}`);
|
|
userConfig = JSON.parse(userConfigString)
|
|
|
|
// Check the sort of data the web browser or device native client will send.
|
|
switch (userConfig.emitData)
|
|
{
|
|
case "ArrayBuffer":
|
|
{
|
|
ws.on('webrtc-offer', function(offer) {
|
|
console.log(`offer <- client ${clientId}`);
|
|
sendOfferToProxy(clientId, offer);
|
|
});
|
|
|
|
ws.on('webrtc-ice', function(candidate) {
|
|
console.log(`ICE candidate <- client ${clientId}`);
|
|
sendIceCandidateToProxy(clientId, candidate);
|
|
});
|
|
|
|
ws.on('webrtc-stats', function(stats){
|
|
console.log(`Received webRTC stats from player ID: ${clientId} \r\n${JSON.stringify(stats)}`);
|
|
});
|
|
|
|
break;
|
|
}
|
|
case "Array":
|
|
{
|
|
//TODO: this is untested as requires iOS WebRTC integration
|
|
ws.on('webrtc-offer', function(offer) {
|
|
console.log(`offer <- client ${clientId}`);
|
|
sendOfferToProxy(clientId, offer);
|
|
});
|
|
|
|
ws.on('webrtc-ice', function(candidate) {
|
|
console.log(`ICE candidate <- client ${clientId}`);
|
|
sendIceCandidateToProxy(clientId, candidate);
|
|
});
|
|
|
|
ws.on('webrtc-stats', function(stats){
|
|
console.log(`Received webRTC stats from player ID: ${clientId} \r\n${JSON.stringify(stats)}`);
|
|
});
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
console.log(`Unknown user config emit data type ${userConfig.emitData}`);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//IO events
|
|
io.on('connection', function (ws) {
|
|
// Reject connection if proxy is not connected
|
|
if (!proxySocket) {
|
|
ws.disconnect();
|
|
return;
|
|
}
|
|
|
|
handleNewClient(ws);
|
|
sendClientConnectedToFrontend();
|
|
sendClientConnectedToMatchmaker();
|
|
});
|
|
|
|
//Setup http and https servers
|
|
http.listen(httpPort, function () {
|
|
console.logColor(logging.Green, 'Http listening on *: ' + httpPort);
|
|
});
|
|
|
|
if(config.UseHTTPS){
|
|
https.listen(httpsPort, function () {
|
|
console.logColor(logging.Green, 'Https listening on *: ' + httpsPort);
|
|
});
|
|
}
|
|
|
|
//Keep trying to send gameSessionId in case the server isn't ready yet
|
|
function sendGameSessionData(){
|
|
//If we are not using the frontend web server don't try and make requests to it
|
|
if(!config.UseFrontend)
|
|
return;
|
|
|
|
webRequest.get(`${FRONTEND_WEBSERVER}/server/requestSessionId`,
|
|
function(response, body) {
|
|
if(response.statusCode === 200){
|
|
gameSessionId = body;
|
|
console.log('SessionId: ' + gameSessionId);
|
|
}
|
|
else{
|
|
console.log('Status code: ' + response.statusCode);
|
|
console.log(body);
|
|
}
|
|
},
|
|
function(err){
|
|
//Repeatedly try in cases where the connection timed out or never connected
|
|
if (err.code === "ECONNRESET") {
|
|
//timeout
|
|
sendGameSessionData();
|
|
} else if(err.code === 'ECONNREFUSED') {
|
|
console.log('Frontend server not running, unable to setup game session');
|
|
} else {
|
|
console.log(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
function sendUserSessionData(serverPort){
|
|
//If we are not using the frontend web server don't try and make requests to it
|
|
if(!config.UseFrontend)
|
|
return;
|
|
|
|
webRequest.get(`${FRONTEND_WEBSERVER}/server/requestUserSessionId?gameSessionId=${gameSessionId}&serverPort=${serverPort}&appName=${querystring.escape(clientConfig.AppName)}&appDescription=${querystring.escape(clientConfig.AppDescription)}${(typeof serverPublicIp === 'undefined' ? '' : '&serverHost=' + serverPublicIp)}`,
|
|
function(response, body) {
|
|
if(response.statusCode === 410){
|
|
sendUserSessionData(serverPort);
|
|
}else if(response.statusCode === 200){
|
|
userSessionId = body;
|
|
console.log('UserSessionId: ' + userSessionId);
|
|
} else {
|
|
console.log('Status code: ' + response.statusCode);
|
|
console.log(body);
|
|
}
|
|
},
|
|
function(err){
|
|
//Repeatedly try in cases where the connection timed out or never connected
|
|
if (err.code === "ECONNRESET") {
|
|
//timeout
|
|
sendUserSessionData(serverPort);
|
|
} else if(err.code === 'ECONNREFUSED') {
|
|
console.log('Frontend server not running, unable to setup user session');
|
|
} else {
|
|
console.log(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
function sendServerDisconnect(){
|
|
//If we are not using the frontend web server don't try and make requests to it
|
|
if(!config.UseFrontend)
|
|
return;
|
|
|
|
webRequest.get(`${FRONTEND_WEBSERVER}/server/serverDisconnected?gameSessionId=${gameSessionId}&appName=${querystring.escape(clientConfig.AppName)}`,
|
|
function(response, body) {
|
|
if(response.statusCode === 200){
|
|
console.log('serverDisconnected acknowledged by Frontend');
|
|
} else {
|
|
console.log('Status code: ' + response.statusCode);
|
|
console.log(body);
|
|
}
|
|
},
|
|
function(err){
|
|
//Repeatedly try in cases where the connection timed out or never connected
|
|
if (err.code === "ECONNRESET") {
|
|
//timeout
|
|
sendServerDisconnect();
|
|
} else if(err.code === 'ECONNREFUSED') {
|
|
console.log('Frontend server not running, unable to setup user session');
|
|
} else {
|
|
console.log(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
function sendClientConnectedToFrontend(){
|
|
//If we are not using the frontend web server don't try and make requests to it
|
|
if(!config.UseFrontend)
|
|
return;
|
|
|
|
webRequest.get(`${FRONTEND_WEBSERVER}/server/clientConnected?gameSessionId=${gameSessionId}&appName=${querystring.escape(clientConfig.AppName)}`,
|
|
function(response, body) {
|
|
if(response.statusCode === 200){
|
|
console.log('clientConnected acknowledged by Frontend');
|
|
}
|
|
else{
|
|
console.log('Status code: ' + response.statusCode);
|
|
console.log(body);
|
|
}
|
|
},
|
|
function(err){
|
|
//Repeatedly try in cases where the connection timed out or never connected
|
|
if (err.code === "ECONNRESET") {
|
|
//timeout
|
|
sendClientConnectedToFrontend();
|
|
} else if(err.code === 'ECONNREFUSED') {
|
|
console.log('Frontend server not running, unable to setup game session');
|
|
} else {
|
|
console.log(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
function sendClientDisconnectedToFrontend(){
|
|
//If we are not using the frontend web server don't try and make requests to it
|
|
if(!config.UseFrontend)
|
|
return;
|
|
|
|
webRequest.get(`${FRONTEND_WEBSERVER}/server/clientDisconnected?gameSessionId=${gameSessionId}&appName=${querystring.escape(clientConfig.AppName)}`,
|
|
function(response, body) {
|
|
if(response.statusCode === 200){
|
|
console.log('clientDisconnected acknowledged by Frontend');
|
|
}
|
|
else{
|
|
console.log('Status code: ' + response.statusCode);
|
|
console.log(body);
|
|
}
|
|
},
|
|
function(err){
|
|
//Repeatedly try in cases where the connection timed out or never connected
|
|
if (err.code === "ECONNRESET") {
|
|
//timeout
|
|
sendClientDisconnectedEvent();
|
|
} else if(err.code === 'ECONNREFUSED') {
|
|
console.log('Frontend server not running, unable to setup game session');
|
|
} else {
|
|
console.log(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
// The Matchmaker will not re-direct clients to this Cirrus server if any client
|
|
// is connected.
|
|
function sendClientConnectedToMatchmaker() {
|
|
if (!config.UseMatchmaker)
|
|
return;
|
|
|
|
message = {
|
|
type: 'clientConnected'
|
|
};
|
|
matchmaker.write(JSON.stringify(message));
|
|
}
|
|
|
|
// The Matchmaker is interested when nobody is connected to a Cirrus server
|
|
// because then it can re-direct clients to this re-cycled Cirrus server.
|
|
function sendClientDisconnectedToMatchmaker() {
|
|
if (!config.UseMatchmaker)
|
|
return;
|
|
|
|
message = {
|
|
type: 'clientDisconnected'
|
|
};
|
|
matchmaker.write(JSON.stringify(message));
|
|
} |