diff --git a/Environment.js b/Environment.js index 92fd77434..c156fbde3 100644 --- a/Environment.js +++ b/Environment.js @@ -33,6 +33,7 @@ exports.newEnvironment = function () { DESKTOP_APP_SIGNING_ACCOUNT: 'Social-Trading-Desktop-App-1', DESKTOP_APP_MAX_OUTGOING_PEERS: 1, TASK_SERVER_APP_MAX_OUTGOING_PEERS: 1, + TASK_SERVER_APP_MAX_OUTGOING_HEADS: 1, MOBILE_APP_SIGNING_ACCOUNT: 'Social-Trading-Mobile-App-1', SERVER_APP_SIGNING_ACCOUNT: 'Social-Trading-Server-App-1', PLATFORM_APP_SIGNING_ACCOUNT: 'Algo-Traders-Platform-1', diff --git a/Projects/Network/SA/Modules/P2PNetworkHead.js b/Projects/Network/SA/Modules/P2PNetworkHead.js new file mode 100644 index 000000000..2aa175599 --- /dev/null +++ b/Projects/Network/SA/Modules/P2PNetworkHead.js @@ -0,0 +1,89 @@ +exports.newNetworkModulesP2PNetworkHead = function newNetworkModulesP2PNetworkHead() { + /* + This has identified which are the nodes at the head of the network worm, + and it is ready to send messages to it. + */ + let thisObject = { + peers: undefined, + sendMessage: sendMessage, + + /* Framework Functions */ + initialize: initialize, + finalize: finalize + } + + const RECONNECT_DELAY = 10 * 1000 + let intervalIdConnectToPeers + + return thisObject + + function finalize() { + thisObject.peers = undefined + clearInterval(intervalIdConnectToPeers) + } + + async function initialize( + callerRole, + p2pNetworkIdentity, + p2pNetwork, + maxOutgoingPeers + ) { + + thisObject.peers = [] + + connectToPeers() + intervalIdConnectToPeers = setInterval(connectToPeers, RECONNECT_DELAY); + + async function connectToPeers() { + + if (thisObject.peers.length >= maxOutgoingPeers) { return } + + for (let i = 0; i < p2pNetwork.p2pNodesToConnect.length; i++) { + if (thisObject.peers.length >= maxOutgoingPeers) { break } + + let peer = { + p2pNetworkNode: undefined, + httpClient: undefined + } + + peer.p2pNetworkNode = p2pNetwork.p2pNodesToConnect[i] + if (isPeerConnected(peer) === true) { continue } + if (isPeerOnline(peer) === false) { continue } + + thisObject.peers.push(peer) + + } + + function isPeerConnected(peer) { + for (let i = 0; i < thisObject.peers.length; i++) { + let connectedPeer = thisObject.peers[i] + if (connectedPeer.p2pNetworkNode.node.id === peer.p2pNetworkNode.node.id) { + return true + } + } + } + + async function isPeerOnline(peer) { + /* + Test if the peer is actually online. + */ + if (peer.httpClient === undefined) { + peer.httpClient = SA.projects.network.modules.webSocketsNetworkClient.newNetworkModulesHttpNetworkClient() + peer.httpClient.initialize(callerRole, p2pNetworkIdentity, peer.p2pNetworkNode) + } + + return await peer.httpClient.testConnection() + } + } + } + + async function sendMessage(message) { + /* + This function will send the message from a random picked network node + selected from the array of already verified online peers. + */ + let peerIndex = Math.max(Math.round(Math.random() * thisObject.peers.length) - 1, 0) + let peer = thisObject.peers[peerIndex] + return await peer.httpClient.sendMessage(message) + } +} \ No newline at end of file diff --git a/Projects/Network/SA/Modules/P2PNetworkPeers.js b/Projects/Network/SA/Modules/P2PNetworkPeers.js index a11e388d3..deb9cf111 100644 --- a/Projects/Network/SA/Modules/P2PNetworkPeers.js +++ b/Projects/Network/SA/Modules/P2PNetworkPeers.js @@ -46,7 +46,7 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkP } peer.p2pNetworkNode = p2pNetwork.p2pNodesToConnect[i] - if (isConnectedPeer(peer) === true) { continue } + if (isPeerConnected(peer) === true) { continue } peer.webSocketsClient = SA.projects.network.modules.webSocketsNetworkClient.newNetworkModulesWebSocketsNetworkClient() await peer.webSocketsClient.initialize(callerRole, p2pNetworkIdentity, peer.p2pNetworkNode, onConnectionClosed) .then(addPeer) @@ -75,7 +75,7 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkP } } - function isConnectedPeer(peer) { + function isPeerConnected(peer) { for (let i = 0; i < thisObject.peers.length; i++) { let connectedPeer = thisObject.peers[i] if (connectedPeer.p2pNetworkNode.node.id === peer.p2pNetworkNode.node.id) { diff --git a/Projects/ProjectsSchema.json b/Projects/ProjectsSchema.json index 4b36377df..8f17dcec3 100644 --- a/Projects/ProjectsSchema.json +++ b/Projects/ProjectsSchema.json @@ -1637,6 +1637,12 @@ "functionName": "newNetworkModulesP2PNetworkPeers", "fileName": "P2PNetworkPeers.js" }, + { + "name": "P2P Network Head", + "propertyName": "p2pNetworkHead", + "functionName": "newNetworkModulesP2PNetworkHead", + "fileName": "P2PNetworkHead.js" + }, { "name": "P2P Network Client", "propertyName": "p2pNetworkClient", diff --git a/TaskServer/TaskServer.js b/TaskServer/TaskServer.js index 907df4ff9..5bcba0275 100644 --- a/TaskServer/TaskServer.js +++ b/TaskServer/TaskServer.js @@ -142,7 +142,7 @@ exports.newTaskServer = function newTaskServer() { TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetwork = SA.projects.network.modules.p2pNetwork.newNetworkModulesP2PNetwork() await TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetwork.initialize('Network Client') /* - Set up the connections to network nodes. + Set up the connections to network peers nodes. These connections will be used to consume signals. */ TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkPeers() await TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetworkPeers.initialize( @@ -151,7 +151,17 @@ exports.newTaskServer = function newTaskServer() { TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetwork, global.env.TASK_SERVER_APP_MAX_OUTGOING_PEERS ) - } + /* + Set up the connections to network head nodes. These connections will be used to send signals. + */ + TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkHead() + await TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetworkPeers.initialize( + 'Network Client', + TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetworkClient, + TS.projects.foundations.globals.taskConstants.P2P_NETWORK.p2pNetwork, + global.env.TASK_SERVER_APP_MAX_OUTGOING_HEADS + ) + } function setupTaskHeartbeats() { /*