From 8024d0c476d6479f7c6cf5f21362ea3534bac1ef Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 7 Nov 2021 16:04:00 +0100 Subject: [PATCH] Superalgos P2P Network: Desktop connecting to multiple Network Peers --- Desktop/DesktopApp.js | 16 ++-- Environment.js | 1 + Network/NetwokNode.js | 9 +- .../Network/SA/Modules/P2PNetworkPeers.js | 89 +++++++++++-------- .../SA/Modules/WebSocketsNetworkClient.js | 2 +- .../DK/modules/WebAppInterface.js | 4 +- .../NT/Modules/PeerInterface.js | 2 +- 7 files changed, 73 insertions(+), 50 deletions(-) diff --git a/Desktop/DesktopApp.js b/Desktop/DesktopApp.js index 90693c4a7..5da36f492 100644 --- a/Desktop/DesktopApp.js +++ b/Desktop/DesktopApp.js @@ -4,6 +4,7 @@ exports.newDesktopApp = function newDesktopApp() { userProfiles: undefined, p2pNetworkClient: undefined, p2pNetwork: undefined, + p2pNetworkPeers: undefined, webSocketsClient: undefined, webSocketsInterface: undefined, socialGraph: undefined, @@ -36,14 +37,15 @@ exports.newDesktopApp = function newDesktopApp() { thisObject.p2pNetwork = SA.projects.network.modules.p2pNetwork.newNetworkModulesP2PNetwork() await thisObject.p2pNetwork.initialize('Network Client') /* - Here we will pick a Network Node from all users profiles available that do have a Network Node running. + Set up the connections to network nodes. */ - let selectedNetworkNode = thisObject.p2pNetwork.p2pNodesToConnect[0] - /* - This is the Web Sockets client that interacts with the Superalgos Network. - */ - thisObject.webSocketsClient = SA.projects.network.modules.webSocketsNetworkClient.newNetworkModulesWebSocketsNetworkClient() - await thisObject.webSocketsClient.initialize('Network Client', thisObject.p2pNetworkClient, selectedNetworkNode) + thisObject.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkPeers() + await thisObject.p2pNetworkPeers.initialize( + 'Network Client', + thisObject.p2pNetworkClient, + thisObject.p2pNetwork, + global.env.DESKTOP_APP_MAX_OUTGOING_PEERS + ) } async function setupServices() { diff --git a/Environment.js b/Environment.js index 2e75c6265..04b9a78a4 100644 --- a/Environment.js +++ b/Environment.js @@ -28,6 +28,7 @@ exports.newEnvironment = function () { PATH_TO_MY_WORKSPACES: path.join(basePath, './Platform/My-Workspaces'), PATH_TO_FONTS: path.join(basePath, './Platform/WebServer/Fonts'), DESKTOP_APP_SIGNING_ACCOUNT: 'Social-Trading-Desktop-App-1', + DESKTOP_APP_MAX_OUTGOING_PEERS: 2, 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/Network/NetwokNode.js b/Network/NetwokNode.js index faa70ab93..8edc1c6f4 100644 --- a/Network/NetwokNode.js +++ b/Network/NetwokNode.js @@ -37,10 +37,15 @@ exports.newNetworkNode = function newNetworkNode() { thisObject.p2pNetwork = SA.projects.network.modules.p2pNetwork.newNetworkModulesP2PNetwork() await thisObject.p2pNetwork.initialize('Network Peer') /* - We can join now the P2P Network as a new peer there. + Set up the connections to network nodes. */ thisObject.p2pNetworkPeers = SA.projects.network.modules.p2pNetworkPeers.newNetworkModulesP2PNetworkPeers() - await thisObject.p2pNetworkPeers.initialize() + await thisObject.p2pNetworkPeers.initialize( + 'Network Peer', + thisObject.p2pNetworkNode, + thisObject.p2pNetwork, + global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS + ) } async function setupServices() { diff --git a/Projects/Network/SA/Modules/P2PNetworkPeers.js b/Projects/Network/SA/Modules/P2PNetworkPeers.js index 19e90e8da..a11e388d3 100644 --- a/Projects/Network/SA/Modules/P2PNetworkPeers.js +++ b/Projects/Network/SA/Modules/P2PNetworkPeers.js @@ -4,6 +4,7 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkP */ let thisObject = { peers: undefined, + sendMessage: sendMessage, /* Framework Functions */ initialize: initialize, @@ -20,64 +21,78 @@ exports.newNetworkModulesP2PNetworkPeers = function newNetworkModulesP2PNetworkP clearInterval(intervalIdConnectToPeers) } - async function initialize() { + async function initialize( + callerRole, + p2pNetworkIdentity, + p2pNetwork, + maxOutgoingPeers + ) { thisObject.peers = [] connectToPeers() intervalIdConnectToPeers = setInterval(connectToPeers, RECONNECT_DELAY); - } + async function connectToPeers() { - async function connectToPeers() { + if (thisObject.peers.length >= maxOutgoingPeers) { return } - if (thisObject.peers.count >= global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS) { return } + for (let i = 0; i < p2pNetwork.p2pNodesToConnect.length; i++) { + if (thisObject.peers.length >= maxOutgoingPeers) { break } - for (let i = 0; i < NT.networkNode.p2pNetwork.p2pNodesToConnect.length; i++) { - if (thisObject.peers.count >= global.env.P2P_NETWORK_NODE_MAX_OUTGOING_PEERS) { break } - - let peer = { - p2pNetworkNode: undefined, - webSocketsClient: undefined - } + let peer = { + p2pNetworkNode: undefined, + webSocketsClient: undefined + } - peer.p2pNetworkNode = NT.networkNode.p2pNetwork.p2pNodesToConnect[i] - if (isOutgoingConnectedPeer(peer) === true) { continue } - peer.webSocketsClient = SA.projects.network.modules.webSocketsNetworkClient.newNetworkModulesWebSocketsNetworkClient() - await peer.webSocketsClient.initialize('Network Peer', NT.networkNode.p2pNetworkNode, peer.p2pNetworkNode, onConnectionClosed) - .then(addPeer) - .catch(onError) + peer.p2pNetworkNode = p2pNetwork.p2pNodesToConnect[i] + if (isConnectedPeer(peer) === true) { continue } + peer.webSocketsClient = SA.projects.network.modules.webSocketsNetworkClient.newNetworkModulesWebSocketsNetworkClient() + await peer.webSocketsClient.initialize(callerRole, p2pNetworkIdentity, peer.p2pNetworkNode, onConnectionClosed) + .then(addPeer) + .catch(onError) - function addPeer() { - thisObject.peers.push(peer) - } + function addPeer() { + thisObject.peers.push(peer) + } - function onError(err) { - if (err !== undefined) { - console.log('[ERROR] P2P Network Peers -> onError -> While connecting to node -> ' + peer.p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + peer.p2pNetworkNode.node.name + ' -> ' + err.message) - } else { - console.log('[WARN] P2P Network Peers -> onError -> Peer Not Available at the Moment -> ' + peer.p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + peer.p2pNetworkNode.node.name) + function onError(err) { + if (err !== undefined) { + console.log('[ERROR] P2P Network Peers -> onError -> While connecting to node -> ' + peer.p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + peer.p2pNetworkNode.node.name + ' -> ' + err.message) + } else { + 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.peers.length; i++) { + let connectedPeer = thisObject.peers[i] + if (connectedPeer.webSocketsClient.id === webSocketsClientId) { + thisObject.peers.splice(i, 1) + return + } + } } } - function onConnectionClosed(webSocketsClientId) { + function isConnectedPeer(peer) { for (let i = 0; i < thisObject.peers.length; i++) { let connectedPeer = thisObject.peers[i] - if (connectedPeer.webSocketsClient.id === webSocketsClientId) { - thisObject.peers.splice(i, 1) - return + if (connectedPeer.p2pNetworkNode.node.id === peer.p2pNetworkNode.node.id) { + return true } } } } + } - function isOutgoingConnectedPeer(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 sendMessage(message) { + /* + This function will send the message from a random picked network node + selected from the array of already connected peers. + */ + let peerIndex = Math.max(Math.round(Math.random() * thisObject.peers.length) - 1, 0) + let peer = thisObject.peers[peerIndex] + return await peer.webSocketsClient.sendMessage(message) } } \ No newline at end of file diff --git a/Projects/Network/SA/Modules/WebSocketsNetworkClient.js b/Projects/Network/SA/Modules/WebSocketsNetworkClient.js index 9c028e18c..1542e743f 100644 --- a/Projects/Network/SA/Modules/WebSocketsNetworkClient.js +++ b/Projects/Network/SA/Modules/WebSocketsNetworkClient.js @@ -223,7 +223,7 @@ exports.newNetworkModulesWebSocketsNetworkClient = function newNetworkModulesWeb function onConnectionClosed() { if (thisObject.isConnected === true) { - console.log('Websockets Client Connected to Network Node via Web Sockets ............... Disconnected from ' + thisObject.p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + thisObject.p2pNetworkNode.node.name + ' -> ' + thisObject.host + ':' + thisObject.port) + console.log('Websockets Client Disconnected from Network Node via Web Sockets ......... Disconnected from ' + thisObject.p2pNetworkNode.userProfile.userProfileHandle + ' -> ' + thisObject.p2pNetworkNode.node.name + ' -> ' + thisObject.host + ':' + thisObject.port) } if (thisObject.onConnectionClosedCallBack !== undefined) { thisObject.onConnectionClosedCallBack(thisObject.id) diff --git a/Projects/Social-Trading/DK/modules/WebAppInterface.js b/Projects/Social-Trading/DK/modules/WebAppInterface.js index d4b522dd7..96830e81e 100644 --- a/Projects/Social-Trading/DK/modules/WebAppInterface.js +++ b/Projects/Social-Trading/DK/modules/WebAppInterface.js @@ -58,11 +58,11 @@ exports.newSocialTradingModulesWebAppInterface = function newSocialTradingModule response = { result: 'Ok', message: 'Web App Interface Query Processed.', - data: await DK.desktopApp.webSocketsClient.sendMessage(JSON.stringify(messageHeader)) + data: await DK.desktopApp.p2pNetworkPeers.sendMessage(JSON.stringify(messageHeader)) } } else { - let events = await DK.desktopApp.webSocketsClient.sendMessage(JSON.stringify(messageHeader)) + let events = await DK.desktopApp.p2pNetworkPeers.sendMessage(JSON.stringify(messageHeader)) for (let i = 0; i < events.length; i++) { let event = events[i] if (event.eventType === SA.projects.socialTrading.globals.eventTypes.NEW_USER_POST) { diff --git a/Projects/Social-Trading/NT/Modules/PeerInterface.js b/Projects/Social-Trading/NT/Modules/PeerInterface.js index 344e356c5..29ff7c114 100644 --- a/Projects/Social-Trading/NT/Modules/PeerInterface.js +++ b/Projects/Social-Trading/NT/Modules/PeerInterface.js @@ -111,7 +111,7 @@ exports.newSocialTradingModulesPeerInterface = function newSocialTradingModulesP if (NT.projects.network.globals.memory.maps.EVENTS.get(eventReceived.eventId) !== undefined) { let response = { - result: 'Error', + result: 'Ok', message: 'Peer Interface Event Already Exists.' } return response