diff --git a/.gitignore b/.gitignore index 8af868e..096746c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,60 +1 @@ -# This .gitignore file should be placed at the root of your Unity project directory -# -# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore -# -/[Ll]ibrary/ -/[Tt]emp/ -/[Oo]bj/ -/[Bb]uild/ -/[Bb]uilds/ -/[Ll]ogs/ -/[Mm]emoryCaptures/ - -# Asset meta data should only be ignored when the corresponding asset is also ignored -!/[Aa]ssets/**/*.meta - -# Uncomment this line if you wish to ignore the asset store tools plugin -# /[Aa]ssets/AssetStoreTools* - -# Autogenerated Jetbrains Rider plugin -[Aa]ssets/Plugins/Editor/JetBrains* - -# Visual Studio cache directory -.vs/ - -# Gradle cache directory -.gradle/ - -# Autogenerated VS/MD/Consulo solution and project files -ExportedObj/ -.consulo/ -*.csproj -*.unityproj -*.sln -*.suo -*.tmp -*.user -*.userprefs -*.pidb -*.booproj -*.svd -*.pdb -*.mdb -*.opendb -*.VC.db - -# Unity3D generated meta files -*.pidb.meta -*.pdb.meta -*.mdb.meta - -# Unity3D generated file on crash reports -sysinfo.txt - -# Builds -*.apk -*.unitypackage - -# Crashlytics generated file -crashlytics-build.properties - +/node_modules/ \ No newline at end of file diff --git a/INetwork.js b/INetwork.js new file mode 100644 index 0000000..25b7ef4 --- /dev/null +++ b/INetwork.js @@ -0,0 +1,192 @@ +"use strict"; +var NetEventType; +(function (NetEventType) { + NetEventType[NetEventType["Invalid"] = 0] = "Invalid"; + NetEventType[NetEventType["UnreliableMessageReceived"] = 1] = "UnreliableMessageReceived"; + NetEventType[NetEventType["ReliableMessageReceived"] = 2] = "ReliableMessageReceived"; + NetEventType[NetEventType["ServerInitialized"] = 3] = "ServerInitialized"; + NetEventType[NetEventType["ServerInitFailed"] = 4] = "ServerInitFailed"; + NetEventType[NetEventType["ServerClosed"] = 5] = "ServerClosed"; + NetEventType[NetEventType["NewConnection"] = 6] = "NewConnection"; + NetEventType[NetEventType["ConnectionFailed"] = 7] = "ConnectionFailed"; + NetEventType[NetEventType["Disconnected"] = 8] = "Disconnected"; + NetEventType[NetEventType["FatalError"] = 100] = "FatalError"; + NetEventType[NetEventType["Warning"] = 101] = "Warning"; + NetEventType[NetEventType["Log"] = 102] = "Log"; //not yet used +})(NetEventType || (NetEventType = {})); +exports.NetEventType = NetEventType; +var NetEventDataType; +(function (NetEventDataType) { + NetEventDataType[NetEventDataType["Null"] = 0] = "Null"; + NetEventDataType[NetEventDataType["ByteArray"] = 1] = "ByteArray"; + NetEventDataType[NetEventDataType["UTF16String"] = 2] = "UTF16String"; +})(NetEventDataType || (NetEventDataType = {})); +var NetworkEvent = (function () { + function NetworkEvent(t, conId, data) { + this.type = t; + this.connectionId = conId; + this.data = data; + } + Object.defineProperty(NetworkEvent.prototype, "RawData", { + get: function () { + return this.data; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(NetworkEvent.prototype, "MessageData", { + get: function () { + if (typeof this.data != "string") + return this.data; + return null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(NetworkEvent.prototype, "Info", { + get: function () { + if (typeof this.data == "string") + return this.data; + return null; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(NetworkEvent.prototype, "Type", { + get: function () { + return this.type; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(NetworkEvent.prototype, "ConnectionId", { + get: function () { + return this.connectionId; + }, + enumerable: true, + configurable: true + }); + //for debugging only + NetworkEvent.prototype.toString = function () { + var output = "NetworkEvent["; + output += "NetEventType: ("; + output += NetEventType[this.type]; + output += "), id: ("; + output += this.connectionId.id; + output += "), Data: ("; + if (typeof this.data == "string") { + output += this.data; + } + output += ")]"; + return output; + }; + NetworkEvent.parseFromString = function (str) { + var values = JSON.parse(str); + var data; + if (values.data == null) { + data = null; + } + else if (typeof values.data == "string") { + data = values.data; + } + else if (typeof values.data == "object") { + //json represents the array as an object containing each index and the + //value as string number ... improve that later + var arrayAsObject = values.data; + var length = 0; + for (var prop in arrayAsObject) { + //if (arrayAsObject.hasOwnProperty(prop)) { //shouldnt be needed + length++; + } + var buffer = new Uint8Array(Object.keys(arrayAsObject).length); + for (var i = 0; i < buffer.length; i++) + buffer[i] = arrayAsObject[i]; + data = buffer; + } + else { + console.error("data can't be parsed"); + } + var evt = new NetworkEvent(values.type, values.connectionId, data); + return evt; + }; + NetworkEvent.toString = function (evt) { + return JSON.stringify(evt); + }; + NetworkEvent.fromByteArray = function (arr) { + var type = arr[0]; //byte + var dataType = arr[1]; //byte + var id = new Int16Array(arr.buffer, arr.byteOffset + 2, 1)[0]; //short + var data = null; + if (dataType == NetEventDataType.ByteArray) { + var length_1 = new Uint32Array(arr.buffer, arr.byteOffset + 4, 1)[0]; //uint + var byteArray = new Uint8Array(arr.buffer, arr.byteOffset + 8, length_1); + data = byteArray; + } + else if (dataType == NetEventDataType.UTF16String) { + var length_2 = new Uint32Array(arr.buffer, arr.byteOffset + 4, 1)[0]; //uint + var uint16Arr = new Uint16Array(arr.buffer, arr.byteOffset + 8, length_2); + var str = ""; + for (var i = 0; i < uint16Arr.length; i++) { + str += String.fromCharCode(uint16Arr[i]); + } + data = str; + } + var conId = new ConnectionId(id); + var result = new NetworkEvent(type, conId, data); + return result; + }; + NetworkEvent.toByteArray = function (evt) { + var dataType; + var length = 4; //4 bytes are always needed + //getting type and length + if (evt.data == null) { + dataType = NetEventDataType.Null; + } + else if (typeof evt.data == "string") { + dataType = NetEventDataType.UTF16String; + var str = evt.data; + length += str.length * 2 + 4; + } + else { + dataType = NetEventDataType.ByteArray; + var byteArray = evt.data; + length += 4 + byteArray.length; + } + //creating the byte array + var result = new Uint8Array(length); + result[0] = evt.type; + ; + result[1] = dataType; + var conIdField = new Int16Array(result.buffer, result.byteOffset + 2, 1); + conIdField[0] = evt.connectionId.id; + if (dataType == NetEventDataType.ByteArray) { + var byteArray = evt.data; + var lengthField = new Uint32Array(result.buffer, result.byteOffset + 4, 1); + lengthField[0] = byteArray.length; + for (var i = 0; i < byteArray.length; i++) { + result[8 + i] = byteArray[i]; + } + } + else if (dataType == NetEventDataType.UTF16String) { + var str = evt.data; + var lengthField = new Uint32Array(result.buffer, result.byteOffset + 4, 1); + lengthField[0] = str.length; + var dataField = new Uint16Array(result.buffer, result.byteOffset + 8, str.length); + for (var i = 0; i < dataField.length; i++) { + dataField[i] = str.charCodeAt(i); + } + } + return result; + }; + return NetworkEvent; +}()); +exports.NetworkEvent = NetworkEvent; +var ConnectionId = (function () { + function ConnectionId(nid) { + this.id = nid; + } + ConnectionId.INVALID = new ConnectionId(-1); + return ConnectionId; +}()); +exports.ConnectionId = ConnectionId; +//# sourceMappingURL=INetwork.js.map \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a8b3ee9 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# AirSignal + +## Installation +Install [Nodejs](https://nodejs.org/en/) which comes with [NPM](https://www.npmjs.com/get-npm) +After installing run the following commands: + +`npm install` +This will install all required packages for it to work. + +`node server.js` +This will run the server using config.json + +You can change used ports and other details in the file config.json. + +## SSL +Create ssl.cert and ssl.key to allow using secure connections. Add ssl details +in `config.json` as per the structure shown in `config_template.json` + +## Contact +The original creator of the server Christoph Kutza can be reached here: +Send a mail to contact@because-why-not.com or BecauseWhyNotHelp@gmail.com or visit http://because-why-not.com ! + +If you're here from [AirPeer](https://www.github.com/adrenal/airpeer) and have questions about it, contact Vatsal Ambastha: + +[@email](ambastha.vatsal@gmail.com) +[@github](https://www.github.com/adrenak) +[@website](http://www.vatsalambastha.com) +[@twitter](https://www.twitter.com/vatsalAmbastha) \ No newline at end of file diff --git a/WebsocketNetworkServer.js b/WebsocketNetworkServer.js new file mode 100644 index 0000000..c6c8950 --- /dev/null +++ b/WebsocketNetworkServer.js @@ -0,0 +1,362 @@ +"use strict"; +var ws = require('ws'); +var inet = require('./INetwork'); +var WebsocketNetworkServer = (function () { + function WebsocketNetworkServer() { + this.mPool = {}; + } + WebsocketNetworkServer.log = function (msg) { + console.log("(" + new Date().toISOString() + ")" + msg); + }; + WebsocketNetworkServer.prototype.onConnection = function (socket, appname) { + //it would be possible to enforce the client to send a certain introduction first + //to determine to which pool we add it -> for now only one pool is supported + this.mPool[appname].add(socket); + }; + // + WebsocketNetworkServer.prototype.addSocketServer = function (websocketServer, appConfig) { + var _this = this; + if (this.mPool[appConfig.name] == null) { + this.mPool[appConfig.name] = new PeerPool(appConfig); + } + var name = appConfig.name; + websocketServer.on('connection', function (socket) { _this.onConnection(socket, name); }); + }; + return WebsocketNetworkServer; +}()); +exports.WebsocketNetworkServer = WebsocketNetworkServer; +; +//Pool of client connects that are allowed to communicate to each other +var PeerPool = (function () { + function PeerPool(config) { + this.mConnections = new Array(); + this.mServers = {}; + this.mAddressSharing = false; + this.maxAddressLength = 256; + this.mAppConfig = config; + if (this.mAppConfig.address_sharing) { + this.mAddressSharing = this.mAppConfig.address_sharing; + } + } + PeerPool.prototype.hasAddressSharing = function () { + return this.mAddressSharing; + }; + //add a new connection based on this websocket + PeerPool.prototype.add = function (socket) { + this.mConnections.push(new SignalingPeer(this, socket)); + }; + //Returns the SignalingClientConnection that opened a server using the given address + //or null if address not in use + PeerPool.prototype.getServerConnection = function (address) { + return this.mServers[address]; + }; + //Tests if the address is available for use. + //returns true in the following cases + //the address is longer than the maxAddressLength and the server the address is not yet in use or address sharing is active + PeerPool.prototype.isAddressAvailable = function (address) { + if (address.length <= this.maxAddressLength // only allow addresses shorter than maxAddressLength + && (this.mServers[address] == null || this.mAddressSharing)) { + return true; + } + return false; + }; + //Adds the server. No checking is performed here! logic should be solely in the connection class + PeerPool.prototype.addServer = function (client, address) { + if (this.mServers[address] == null) { + this.mServers[address] = new Array(); + } + this.mServers[address].push(client); + }; + //Removes an address from the server. No checks performed + PeerPool.prototype.removeServer = function (client, address) { + //supports address sharing. remove the client from the server list that share the address + var index = this.mServers[address].indexOf(client); + if (index != -1) { + this.mServers[address].splice(index, 1); + } + //delete the whole list if the last one left + if (this.mServers[address].length == 0) { + delete this.mServers[address]; + } + }; + //Removes a given connection from the pool + PeerPool.prototype.removeConnection = function (client) { + var index = this.mConnections.indexOf(client); + if (index != -1) { + this.mConnections.splice(index, 1); + } + else { + console.warn("Tried to remove unknown SignalingClientConnection. Bug?" + client); + } + }; + PeerPool.prototype.count = function () { + return this.mConnections.length; + }; + return PeerPool; +}()); +var SignalingConnectionState; +(function (SignalingConnectionState) { + SignalingConnectionState[SignalingConnectionState["Uninitialized"] = 0] = "Uninitialized"; + SignalingConnectionState[SignalingConnectionState["Connecting"] = 1] = "Connecting"; + SignalingConnectionState[SignalingConnectionState["Connected"] = 2] = "Connected"; + SignalingConnectionState[SignalingConnectionState["Disconnecting"] = 3] = "Disconnecting"; + SignalingConnectionState[SignalingConnectionState["Disconnected"] = 4] = "Disconnected"; //means the instance is destroyed and unusable +})(SignalingConnectionState || (SignalingConnectionState = {})); +; +///note: all methods starting with "internal" might leave the system in an inconsistent state +///e.g. peerA is connected to peerB means peerB is connected to peerA but internalRemoveConnection +///could cause peerA being disconnected from peerB but peerB still thinking to be connected to peerA!!! +var SignalingPeer = (function () { + function SignalingPeer(pool, socket) { + var _this = this; + this.mState = SignalingConnectionState.Uninitialized; + this.mConnections = {}; + //C# version uses short so 16384 is 50% of the positive numbers (maybe might make sense to change to ushort or int) + this.mNextIncomingConnectionId = new inet.ConnectionId(16384); + this.mConInfo = "[con info missing]"; + this.mConnectionPool = pool; + this.mSocket = socket; + //(this.mSocket as any).maxPayload = 16; + this.mState = SignalingConnectionState.Connecting; + this.mConInfo = this.mSocket.upgradeReq.connection.remoteAddress + ":" + this.mSocket.upgradeReq.connection.remotePort; + WebsocketNetworkServer.log("[" + this.mConInfo + "]" + " connected "); + socket.on('message', function (message, flags) { + _this.onMessage(message, flags); + }); + socket.on('error', function (error) { + console.error(error); + }); + socket.on('close', function (code, message) { _this.onClose(code, message); }); + socket.on('pong', function (data, flags) { + WebsocketNetworkServer.log("[" + _this.mConInfo + "]" + "INC: pong "); + }); + this.mState = SignalingConnectionState.Connected; + this.mPingInterval = setInterval(function () { _this.doPing(); }, 30000); + } + SignalingPeer.prototype.doPing = function () { + if (this.mState == SignalingConnectionState.Connected && this.mSocket.readyState == ws.OPEN) { + this.mSocket.ping(); + WebsocketNetworkServer.log("[" + this.mConInfo + "]" + "OUT: ping"); + } + }; + SignalingPeer.prototype.evtToString = function (evt) { + var output = "["; + output += "NetEventType: ("; + output += inet.NetEventType[evt.Type]; + output += "), id: ("; + output += evt.ConnectionId.id; + if (evt.Info != null) { + output += "), Data: ("; + output += evt.Info; + } + else if (evt.MessageData != null) { + var chars = new Uint16Array(evt.MessageData.buffer, evt.MessageData.byteOffset, evt.MessageData.byteLength / 2); + output += "), Data: ("; + var binaryString = ""; + for (var i = 0; i < chars.length; i++) { + binaryString += String.fromCharCode(chars[i]); + } + output += binaryString; + } + output += ")]"; + return output; + }; + SignalingPeer.prototype.onMessage = function (message, flags) { + try { + //unlike browsers ws will give a Uint8Array + var evt = inet.NetworkEvent.fromByteArray(message); + WebsocketNetworkServer.log("[" + this.mConInfo + "]" + "INC: " + this.evtToString(evt)); + this.handleIncomingEvent(evt); + } + catch (err) { + WebsocketNetworkServer.log("[" + this.mConInfo + "]" + "Invalid message received: " + message + " \n Error: " + err); + } + }; + SignalingPeer.prototype.sendToClient = function (evt) { + //this method is also called during cleanup after a disconnect + //check first if we are still connected + //bugfix: apprently 2 sockets can be closed at exactly the same time without + //onclosed being called immediately -> socket has to be checked if open + if (this.mState == SignalingConnectionState.Connected + && this.mSocket.readyState == this.mSocket.OPEN) { + WebsocketNetworkServer.log("[" + this.mConInfo + "]" + "OUT: " + this.evtToString(evt)); + var msg = inet.NetworkEvent.toByteArray(evt); + this.mSocket.send(msg); + } + }; + SignalingPeer.prototype.onClose = function (code, error) { + this.mState = SignalingConnectionState.Disconnecting; + this.Cleanup(); + }; + //so far only used if the socket was disconnected + SignalingPeer.prototype.Cleanup = function () { + if (this.mPingInterval != null) { + clearInterval(this.mPingInterval); + } + this.mConnectionPool.removeConnection(this); + WebsocketNetworkServer.log("[" + this.mConInfo + "]" + "disconnected " + + " " + this.mConnectionPool.count() + + " connections left."); + //disconnect all connections + var test = this.mConnections; //workaround for not having a proper dictionary yet... + for (var v in this.mConnections) { + if (this.mConnections.hasOwnProperty(v)) + this.disconnect(new inet.ConnectionId(+v)); + } + //make sure the server address is freed + if (this.mServerAddress != null) { + this.stopServer(); + } + this.mState = SignalingConnectionState.Disconnected; + }; + SignalingPeer.prototype.handleIncomingEvent = function (evt) { + //update internal state based on the event + if (evt.Type == inet.NetEventType.NewConnection) { + //client wants to connect to another client + var address = evt.Info; + //the id this connection should be addressed with + var newConnectionId = evt.ConnectionId; + this.connect(address, newConnectionId); + } + else if (evt.Type == inet.NetEventType.ConnectionFailed) { + } + else if (evt.Type == inet.NetEventType.Disconnected) { + //peer tries to disconnect from another peer + var otherPeerId = evt.ConnectionId; + this.disconnect(otherPeerId); + } + else if (evt.Type == inet.NetEventType.ServerInitialized) { + this.startServer(evt.Info); + } + else if (evt.Type == inet.NetEventType.ServerInitFailed) { + } + else if (evt.Type == inet.NetEventType.ServerClosed) { + //stop server request + this.stopServer(); + } + else if (evt.Type == inet.NetEventType.ReliableMessageReceived) { + this.sendData(evt.ConnectionId, evt.MessageData, true); + } + else if (evt.Type == inet.NetEventType.UnreliableMessageReceived) { + this.sendData(evt.ConnectionId, evt.MessageData, false); + } + }; + SignalingPeer.prototype.internalAddIncomingPeer = function (peer) { + //another peer connected to this (while allowing incoming connections) + //store the reference + var id = this.nextConnectionId(); + this.mConnections[id.id] = peer; + //event to this (the other peer gets the event via addOutgoing + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.NewConnection, id, null)); + }; + SignalingPeer.prototype.internalAddOutgoingPeer = function (peer, id) { + //this peer successfully connected to another peer. id was generated on the + //client side + this.mConnections[id.id] = peer; + //event to this (the other peer gets the event via addOutgoing + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.NewConnection, id, null)); + }; + SignalingPeer.prototype.internalRemovePeer = function (id) { + delete this.mConnections[id.id]; + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.Disconnected, id, null)); + }; + //test this. might cause problems + //the number is converted to string trough java script but we need get back the number + //for creating the connection id + SignalingPeer.prototype.findPeerConnectionId = function (otherPeer) { + for (var peer in this.mConnections) { + if (this.mConnections[peer] === otherPeer) { + return new inet.ConnectionId(+peer); + } + } + }; + SignalingPeer.prototype.nextConnectionId = function () { + var result = this.mNextIncomingConnectionId; + this.mNextIncomingConnectionId = new inet.ConnectionId(this.mNextIncomingConnectionId.id + 1); + return result; + }; + //public methods (not really needed but can be used for testing or server side deubgging) + //this peer initializes a connection to a certain address. The connection id is set by the client + //to allow tracking of the connection attempt + SignalingPeer.prototype.connect = function (address, newConnectionId) { + var serverConnections = this.mConnectionPool.getServerConnection(address); + // + if (serverConnections != null && serverConnections.length == 1) { + //inform the server connection about the new peer + //events will be send by these methods + //shared addresses -> connect to everyone listening + serverConnections[0].internalAddIncomingPeer(this); + this.internalAddOutgoingPeer(serverConnections[0], newConnectionId); + } + else { + //if address is not in use or it is in multi join mode -> connection fails + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.ConnectionFailed, newConnectionId, null)); + } + }; + //join connection happens if another user joins a multi address. it will connect to every address + //listening to that room + SignalingPeer.prototype.connectJoin = function (address) { + var serverConnections = this.mConnectionPool.getServerConnection(address); + //in join mode every connection is incoming as everyone listens together + if (serverConnections != null) { + for (var _i = 0, serverConnections_1 = serverConnections; _i < serverConnections_1.length; _i++) { + var v = serverConnections_1[_i]; + if (v != this) { + v.internalAddIncomingPeer(this); + this.internalAddIncomingPeer(v); + } + } + } + }; + SignalingPeer.prototype.disconnect = function (connectionId) { + var otherPeer = this.mConnections[connectionId.id]; + if (otherPeer != null) { + var idOfOther = otherPeer.findPeerConnectionId(this); + //find the connection id the other peer uses to talk to this one + this.internalRemovePeer(connectionId); + otherPeer.internalRemovePeer(idOfOther); + } + else { + } + }; + SignalingPeer.prototype.startServer = function (address) { + //what to do if it is already a server? + if (this.mServerAddress != null) + this.stopServer(); + if (this.mConnectionPool.isAddressAvailable(address)) { + this.mServerAddress = address; + this.mConnectionPool.addServer(this, address); + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.ServerInitialized, inet.ConnectionId.INVALID, address)); + if (this.mConnectionPool.hasAddressSharing()) { + //address sharing is active. connect to every endpoint already listening on this address + this.connectJoin(address); + } + } + else { + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.ServerInitFailed, inet.ConnectionId.INVALID, address)); + } + }; + SignalingPeer.prototype.stopServer = function () { + if (this.mServerAddress != null) { + this.mConnectionPool.removeServer(this, this.mServerAddress); + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.ServerClosed, inet.ConnectionId.INVALID, null)); + this.mServerAddress = null; + } + //do nothing if it wasnt a server + }; + //delivers the message to the local peer + SignalingPeer.prototype.forwardMessage = function (senderPeer, msg, reliable) { + var id = this.findPeerConnectionId(senderPeer); + if (reliable) + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.ReliableMessageReceived, id, msg)); + else + this.sendToClient(new inet.NetworkEvent(inet.NetEventType.UnreliableMessageReceived, id, msg)); + }; + SignalingPeer.prototype.sendData = function (id, msg, reliable) { + var peer = this.mConnections[id.id]; + if (peer != null) + peer.forwardMessage(this, msg, reliable); + }; + return SignalingPeer; +}()); +//# sourceMappingURL=WebsocketNetworkServer.js.map \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..bb075d2 --- /dev/null +++ b/config.json @@ -0,0 +1,14 @@ +{ + "httpConfig": + { + "port": 12776 + }, + "maxPayload": + 16777216, + "apps": [ + { + "name": "Main", + "path": "/" + } + ] +} \ No newline at end of file diff --git a/config_template.json b/config_template.json new file mode 100644 index 0000000..b9347ec --- /dev/null +++ b/config_template.json @@ -0,0 +1,21 @@ +{ + "httpConfig": + { + "port": VALUE + }, + "httpsConfig": + { + "port": VALUE, + "ssl_key_file": FILE.key, + "ssl_cert_file": FILE.crt + }, + "maxPayload": + SIZE_IN_BYTES, + "apps": [ + { + "name": NAME, + "path": PATH, + "address_sharing": BOOL + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..dd29d7f --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "websocket-signaling", + "version": "0.97.4", + "description": "A websocket signaling server for use with WebRTC Network and Video Chat assets for Unity.", + "main": "server.js", + "author": { + "name": "Christoph Kutza", + "email": "contact@because-why-not.com" + }, + "dependencies": { + "express": "^4.13.4", + "requirejs": "^2.2.0", + "typescript": "1.8.9", + "ws": "^1.1.0" + }, + "scripts": { + "tsc": "tsc" + } +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..f1bec56 --- /dev/null +++ b/server.js @@ -0,0 +1,36 @@ +"use strict"; +var config = require("./config.json"); +var http = require('http'); +var https = require('https'); +var ws = require('ws'); +var fs = require('fs'); +var wns = require('./WebsocketNetworkServer'); +//setup +var httpServer = null; +var httpsServer = null; +if (config.httpConfig) { + httpServer = http.createServer(); + httpServer.listen(config.httpConfig.port, function () { console.log('Listening on ' + httpServer.address().port); }); +} +if (config.httpsConfig) { + httpsServer = https.createServer({ + key: fs.readFileSync(config.httpsConfig.ssl_key_file), + cert: fs.readFileSync(config.httpsConfig.ssl_cert_file) + }); + httpsServer.listen(config.httpsConfig.port, function () { console.log('Listening on ' + httpsServer.address().port); }); +} +var websocketSignalingServer = new wns.WebsocketNetworkServer(); +for (var _i = 0, _a = config.apps; _i < _a.length; _i++) { + var app = _a[_i]; + if (httpServer) { + //perMessageDeflate: false needs to be set to false turning off the compression. if set to true + //the websocket library crashes if big messages are received (eg.128mb) no matter which payload is set!!! + var webSocket = new ws.Server({ server: httpServer, path: app.path, maxPayload: config.maxPayload, perMessageDeflate: false }); + websocketSignalingServer.addSocketServer(webSocket, app); + } + if (httpsServer) { + var webSocketSecure = new ws.Server({ server: httpsServer, path: app.path, maxPayload: config.maxPayload, perMessageDeflate: false }); //problem in the typings -> setup to only accept http not https so cast to any to turn off typechecks + websocketSignalingServer.addSocketServer(webSocketSecure, app); + } +} +//# sourceMappingURL=server.js.map \ No newline at end of file