diff --git a/Environment.js b/Environment.js index f6e60b177..bb00891ce 100644 --- a/Environment.js +++ b/Environment.js @@ -32,6 +32,7 @@ exports.newEnvironment = function () { SERVER_APP_SIGNING_ACCOUNT: 'Social-Trading-Server-App-1', PLATFORM_APP_SIGNING_ACCOUNT: 'Algo-Traders-Platform-1', P2P_NETWORK_NODE_SIGNING_ACCOUNT: 'P2P-Network-Node-1', + P2P_NETWORK_NODE_MAX_INCOMING_CLIENTS: 20, P2P_NETWORK_NODE_MAX_INCOMING_PEERS: 2, P2P_NETWORK_NODE_MAX_OUTGOING_PEERS: 2 } diff --git a/Projects/Network/NT/Modules/WebSocketsInterface.js b/Projects/Network/NT/Modules/WebSocketsInterface.js index 7374e869e..16c2593e6 100644 --- a/Projects/Network/NT/Modules/WebSocketsInterface.js +++ b/Projects/Network/NT/Modules/WebSocketsInterface.js @@ -86,6 +86,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'messageHeader Not Coorrect JSON Format.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -97,6 +98,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'messageType Not Provided.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } @@ -114,6 +116,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock } response.messageId = messageHeader.messageId caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } @@ -144,6 +147,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'messageType Not Supported.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() break } } @@ -170,6 +174,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'step Not Provided.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } if (messageHeader.step !== 'One' && messageHeader.step !== 'Two') { @@ -178,6 +183,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'step Not Supported.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } switch (messageHeader.step) { @@ -200,6 +206,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'callerRole Not Provided.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } @@ -209,11 +216,41 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'callerRole Not Supported.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } caller.role = messageHeader.callerRole /* + We will check that we have not exeeded the max amount of callers. + */ + switch (caller.role) { + case 'Network Client': { + if (thisObject.networkClients.length >= global.env.P2P_NETWORK_NODE_MAX_INCOMING_CLIENTS) { + let response = { + result: 'Error', + message: 'P2P_NETWORK_NODE_MAX_INCOMING_CLIENTS reached.' + } + caller.socket.send(JSON.stringify(response)) + caller.socket.close() + return + } + break + } + case 'Network Peer': { + if (thisObject.networkPeers.length >= global.env.P2P_NETWORK_NODE_MAX_INCOMING_PEERS) { + let response = { + result: 'Error', + message: 'P2P_NETWORK_NODE_MAX_INCOMING_PEERS reached.' + } + caller.socket.send(JSON.stringify(response)) + caller.socket.close() + return + } + break + } + } + /* The caller needs to provide it's User Profile Handle. */ if (messageHeader.callerProfileHandle === undefined) { @@ -222,6 +259,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'callerProfileHandle Not Provided.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } @@ -235,6 +273,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'callerTimestamp Not Provided.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -246,6 +285,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'callerTimestamp Too Old.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -278,6 +318,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'Handshake Step One Not Completed.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -289,6 +330,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'signature Not Provided.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } @@ -301,6 +343,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'Bad Signature.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -314,6 +357,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'userProfile Not Found.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } let signedMessage = JSON.parse(signature.message) @@ -329,6 +373,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'signature.message Hashed Does Not Match signature.messageHash.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -341,6 +386,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'callerProfileHandle Does Not Match witnessUserProfile.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -353,6 +399,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'calledProfileHandle Does Not Match This Network Node Handle.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* @@ -364,6 +411,7 @@ exports.newNetworkModulesWebSocketsInterface = function newNetworkModulesWebSock message: 'calledTimestamp Does Not Match calledTimestamp On Record.' } caller.socket.send(JSON.stringify(response)) + caller.socket.close() return } /* diff --git a/Projects/Network/SA/Modules/P2PNetworkPeers.js b/Projects/Network/SA/Modules/P2PNetworkPeers.js index 0441f952a..e22197804 100644 --- a/Projects/Network/SA/Modules/P2PNetworkPeers.js +++ b/Projects/Network/SA/Modules/P2PNetworkPeers.js @@ -1,9 +1,9 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkPeers() { /* - This module represents the P2P Nodes we are connected to. + This module holds the P2P Nodes we are coonected to and that are connected to us. */ let thisObject = { - peers: undefined, + outgoingConnectedPeers: undefined, /* Framework Functions */ initialize: initialize, @@ -16,13 +16,13 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkP return thisObject function finalize() { - thisObject.peers = undefined + thisObject.outgoingConnectedPeers = undefined clearInterval(intervalIdConnectToPeers) } async function initialize() { - thisObject.peers = [] + thisObject.outgoingConnectedPeers = [] connectToPeers() intervalIdConnectToPeers = setInterval(connectToPeers, RECONNECT_DELAY); @@ -31,20 +31,20 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkP async function connectToPeers() { - if (thisObject.peers.count >= global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS) { return } + if (thisObject.outgoingConnectedPeers.count >= global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS) { return } for (let i = 0; i < NT.networkNode.p2pNetwork.p2pNodesToConnect.length; i++) { - if (thisObject.peers.count >= global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS) { break } + if (thisObject.outgoingConnectedPeers.count >= global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS) { break } let peer = {} peer.p2pNetworkNode = NT.networkNode.p2pNetwork.p2pNodesToConnect[i] - if (isAlreadyAConnectedPeer(peer) === true) { continue } + if (isOutgoingConnectedPeer(peer) === true) { continue } peer.webSocketsClient = SA.projects.network.modules.webSocketsNetworkClient.newNetworkModulesWebSocketsNetworkClient() - await peer.webSocketsClient.initialize('Network Peer', peer.p2pNetworkNode) + await peer.webSocketsClient.initialize('Network Peer', peer.p2pNetworkNode, onConnectionClosed) .then(addPeer) .catch(onError) function addPeer() { - thisObject.peers.push(peer) + thisObject.outgoingConnectedPeers.push(peer) } function onError(err) { @@ -54,11 +54,21 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkP console.log('[WARN] P2P Network Peers -> onError -> Peer Not Available at the Moment -> ' + peer.p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + peer.p2pNetworkNode.node.name) } } + + function onConnectionClosed(webSocketsClientId) { + for (let i = 0; i < thisObject.outgoingConnectedPeers.length; i++) { + let connectedPeer = thisObject.outgoingConnectedPeers[i] + if (connectedPeer.webSocketsClient.id === webSocketsClientId) { + thisObject.outgoingConnectedPeers.splice(i, 1) + return + } + } + } } - function isAlreadyAConnectedPeer(peer) { - for (let i = 0; i < thisObject.peers.length; i++) { - let connectedPeer = thisObject.peers[i] + function isOutgoingConnectedPeer(peer) { + for (let i = 0; i < thisObject.outgoingConnectedPeers.length; i++) { + let connectedPeer = thisObject.outgoingConnectedPeers[i] if (connectedPeer.p2pNetworkNode.node.id === peer.p2pNetworkNode.node.id) { return true } diff --git a/Projects/Network/SA/Modules/WebSocketsNetworkClient.js b/Projects/Network/SA/Modules/WebSocketsNetworkClient.js index c2db2516a..38fed2cea 100644 --- a/Projects/Network/SA/Modules/WebSocketsNetworkClient.js +++ b/Projects/Network/SA/Modules/WebSocketsNetworkClient.js @@ -1,6 +1,8 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWebSocketsNetworkClient() { let thisObject = { + id: undefined, + isConnected: undefined, host: undefined, port: undefined, sendMessage: sendMessage, @@ -27,20 +29,23 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb onMessageFunctionsMap = undefined } - async function initialize(callerRole, p2pNetworkNode) { + async function initialize(callerRole, p2pNetworkNode, onConnectionClosedCallBack) { web3 = new SA.nodeModules.web3() + thisObject.id = SA.projects.foundations.utilities.miscellaneousFunctions.genereteUniqueId() + thisObject.host = JSON.parse(p2pNetworkNode.node.config).host thisObject.port = JSON.parse(p2pNetworkNode.node.config).webSocketsPort socketClient = new SA.nodeModules.ws('ws://' + thisObject.host + ':' + thisObject.port) - await setUpWebsocketClient(callerRole, p2pNetworkNode) + await setUpWebsocketClient(callerRole, p2pNetworkNode, onConnectionClosedCallBack) console.log('Websockets Client Connected to Network Node via Web Sockets .............. Connected to ' + p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + p2pNetworkNode.node.name + ' -> ' + thisObject.host + ':' + thisObject.port) + thisObject.isConnected = true } - async function setUpWebsocketClient(callerRole, p2pNetworkNode) { + async function setUpWebsocketClient(callerRole, p2pNetworkNode, onConnectionClosedCallBack) { return new Promise(connectToNewtwork) @@ -48,10 +53,11 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb try { - socketClient.onopen = () => { onConnection() } + socketClient.onopen = () => { onConnectionOpened() } + socketClient.onclose = () => { onConnectionClosed() } socketClient.onerror = err => { onError(err) } - function onConnection() { + function onConnectionOpened() { handshakeProcedure() @@ -200,6 +206,16 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb } } + function onConnectionClosed() { + if (thisObject.isConnected === true) { + console.log('Websockets Client Connected to Network Node via Web Sockets .............. Disconnected from ' + p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + p2pNetworkNode.node.name + ' -> ' + thisObject.host + ':' + thisObject.port) + } + if (onConnectionClosedCallBack !== undefined) { + onConnectionClosedCallBack(thisObject.id) + } + thisObject.isConnected = false + } + function onError(err) { if (err.message.indexOf('ECONNREFUSED') >= 0) { console.log('[WARN] Web Sockets Client -> onError -> Nobody home at ' + thisObject.host + ':' + thisObject.port)