From 06d0f3bf53f430c5a6cf1e6c849f5749b28964e9 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 31 Aug 2021 09:23:10 +0200 Subject: [PATCH] Websockets Handshake Procedure --- Client/client.js | 2 +- Client/webSocketsInterface.js | 2 +- Environment.js | 2 +- EnvironmentForDebug.js | 2 +- Network/NetwokNode.js | 3 +- Network/WebSocketsInterface.js | 181 +++++++++++++++++++++++ Projects/Network/NT/Globals/Memory.js | 11 +- Projects/Network/NT/Modules/Bootstrap.js | 5 +- 8 files changed, 196 insertions(+), 12 deletions(-) create mode 100644 Network/WebSocketsInterface.js diff --git a/Client/client.js b/Client/client.js index d44a7aa2b..07990149a 100644 --- a/Client/client.js +++ b/Client/client.js @@ -163,7 +163,7 @@ try { WEB_SOCKETS_INTERFACE = WEB_SOCKETS_INTERFACE.newWebSocketsInterface() WEB_SOCKETS_INTERFACE.initialize() WEB_SOCKETS_INTERFACE.run() - console.log('Web Sockets Interface ....................................... Listening at port ' + global.env.WEB_SOCKETS_INTERFACE_PORT) + console.log('Web Sockets Interface ....................................... Listening at port ' + global.env.CLIENT_WEB_SOCKETS_INTERFACE_PORT) HTTP_INTERFACE = HTTP_INTERFACE.newHttpInterface() HTTP_INTERFACE.initialize() diff --git a/Client/webSocketsInterface.js b/Client/webSocketsInterface.js index 84963a977..36dfd2aef 100644 --- a/Client/webSocketsInterface.js +++ b/Client/webSocketsInterface.js @@ -10,7 +10,7 @@ const WEB_SOCKET = require('ws') let socketServer - let port = global.env.WEB_SOCKETS_INTERFACE_PORT + let port = global.env.CLIENT_WEB_SOCKETS_INTERFACE_PORT return thisObject diff --git a/Environment.js b/Environment.js index aed0520ff..76276e22a 100644 --- a/Environment.js +++ b/Environment.js @@ -2,7 +2,7 @@ exports.newEnvironment = function () { let thisObject = { WEB_SERVER_URL: 'localhost', - WEB_SOCKETS_INTERFACE_PORT: 18041, + CLIENT_WEB_SOCKETS_INTERFACE_PORT: 18041, HTTP_INTERFACE_PORT: 34248, PATH_TO_TASK_SERVER: './TaskServer', PATH_TO_DATA_STORAGE: './Data-Storage', diff --git a/EnvironmentForDebug.js b/EnvironmentForDebug.js index 3d1094e83..cbb68d289 100644 --- a/EnvironmentForDebug.js +++ b/EnvironmentForDebug.js @@ -2,7 +2,7 @@ exports.newEnvironment = function () { let thisObject = { WEB_SERVER_URL: 'localhost', - WEB_SOCKETS_INTERFACE_PORT: 18041, + CLIENT_WEB_SOCKETS_INTERFACE_PORT: 18041, HTTP_INTERFACE_PORT: 34248, PATH_TO_TASK_SERVER: '../TaskServer', PATH_TO_DATA_STORAGE: '../Data-Storage', diff --git a/Network/NetwokNode.js b/Network/NetwokNode.js index 73520d046..f712800d4 100644 --- a/Network/NetwokNode.js +++ b/Network/NetwokNode.js @@ -42,7 +42,8 @@ Setting up external dependencies. SA.nodeModules = { fs: require('fs'), nodeFetch: require('node-fetch'), - web3: require('web3') + web3: require('web3'), + ws: require('ws') } start() diff --git a/Network/WebSocketsInterface.js b/Network/WebSocketsInterface.js new file mode 100644 index 000000000..1f80b7d04 --- /dev/null +++ b/Network/WebSocketsInterface.js @@ -0,0 +1,181 @@ +exports.newWebSocketsInterface = function newWebSocketsInterface() { + + let thisObject = { + initialize: initialize, + finalize: finalize, + run: run + } + + let socketServer + let port = global.env.Network_WEB_SOCKETS_INTERFACE_PORT + + return thisObject + + function finalize() { + + } + + function initialize() { + + } + + function run() { + setUpWebSocketServer() + } + + function setUpWebSocketServer() { + try { + socketServer = new SA.nodeModule.ws.Server({ port: port }) + socketServer.on('connection', onConnection) + + function onConnection(socket) { + let caller = {} + socket.on('message', onMenssage) + + + function onMenssage(message) { + try { + let messageHeader = JSON.parse(message) + /* + We will run some validations. + */ + if (messageHeader.messageType === undefined) { + let response = { + result: 'Error', + message: 'messageType Not Provided.' + } + socket.send(JSON.stringify(response)) + return + } + + switch (messageHeader.messageType) { + case "Handshake": { + handShakeProducedure(socket, caller, messageHeader) + break + + } + case "Request": { + break + } + + } + + + + + + + + + + + let origin = messageArray[0] + let nonce = messageArray[1] + let messageToEventServer = messageArray[2] + + if (origin === 'Web Browser') { + try { + JSON.parse(messageToEventServer) + } catch (err) { + console.log('[ERROR] Network -> Web Sockets Interface -> run -> setUpWebSocketServer -> Message received from the browser is not a valid JSON. message = ' + message.substring(0, 1000)) + console.log('[ERROR] Network -> Web Sockets Interface -> run -> setUpWebSocketServer -> Message received from the browser is not a valid JSON. messageToEventServer = ' + messageToEventServer) + return + } + + let acknowledgeMessage = { + action: 'Acknowledge', + nonce: nonce + } + + socket.send(JSON.stringify(acknowledgeMessage)) + } + + + CL.servers.EVENT_SERVER.onMessage(messageToEventServer, onResponse) + + function onResponse(message) { + socket.send(message) + } + } catch (err) { + console.log('[ERROR] Network -> Web Sockets Interface -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. err = ' + err.stack) + } + } + } + + + function handShakeProducedure(socket, caller, messageHeader) { + /* + The caller needs to identify itself as either a Network Client or Peer. + */ + if (messageHeader.callerRole === undefined) { + let response = { + result: 'Error', + message: 'callerRole Not Provided.' + } + socket.send(JSON.stringify(response)) + return + } + + if (messageHeader.callerRole !== 'Network Client' && messageHeader.callerRole !== 'Network Peer') { + let response = { + result: 'Error', + message: 'callerRole Not Supported.' + } + socket.send(JSON.stringify(response)) + return + } + + caller.role = messageHeader.callerRole + /* + We will identify the caller by the signature at the message. + */ + if (messageHeader.signature === undefined) { + let response = { + result: 'Error', + message: 'signature Not Provided.' + } + socket.send(JSON.stringify(response)) + return + } + + let web3 = new SA.nodeModules.web3() + let blockchainAccount = web3.eth.accounts.recover(messageHeader.signature) + + if (caller.blockchainAccount === undefined) { + let response = { + result: 'Error', + message: 'Bad signature.' + } + socket.send(JSON.stringify(response)) + return + } + /* + The signature gives us the blockchain account, and the account the user profile. + */ + let userProfile = NT.projects.network.globals.memory.maps.USER_PROFILES_BY_BLOCHAIN_ACCOUNT.set(blockchainAccount) + + if (userProfile === undefined) { + let response = { + result: 'Error', + message: 'userProfile Not Found.' + } + socket.send(JSON.stringify(response)) + return + } + /* + We will remember the user profile behind this caller. + */ + caller.userProfile = userProfile + + let response = { + result: 'Ok', + message: 'Handshake Successful.' + } + socket.send(JSON.stringify(response)) + } + + } catch (err) { + console.log('[ERROR] Network -> Web Sockets Interface -> run -> setUpWebSocketServer -> err.message = ' + err.message.substring(0, 1000)) + } + } +} \ No newline at end of file diff --git a/Projects/Network/NT/Globals/Memory.js b/Projects/Network/NT/Globals/Memory.js index 3248bd2ca..1c5fbb70d 100644 --- a/Projects/Network/NT/Globals/Memory.js +++ b/Projects/Network/NT/Globals/Memory.js @@ -4,13 +4,14 @@ exports.newNetworkGlobalsMemory = function () { */ let thisObject = { maps: { - USER_PROFILES_BY_ID: new Map(), // Here we will store the user profiles by User Profile Id. - USER_PROFILES_BY_HANDLE: new Map(), // Here we will store the user profiles by User Profile Handle. - EVENTS: new Map(), // This is the registry of all events received that prevents processing them more than once. + USER_PROFILES_BY_ID: new Map(), // Here we will store the user profiles by User Profile Id. + USER_PROFILES_BY_HANDLE: new Map(), // Here we will store the user profiles by User Profile Handle. + USER_PROFILES_BY_BLOCHAIN_ACCOUNT: new Map(), // Here we will store the user profiles by Blockchain Account. + EVENTS: new Map(), // This is the registry of all events received that prevents processing them more than once. }, arrays: { - NETWORK_CLIENTS: [], // These are the Network Clients connected to this Network Node ordered by Ranking. - NETWORK_PEERS: [], // These are the Network Peers connected to this Network Node ordered by Ranking. + NETWORK_CLIENTS: [], // These are the Network Clients connected to this Network Node ordered by Ranking. + NETWORK_PEERS: [], // These are the Network Peers connected to this Network Node ordered by Ranking. } } diff --git a/Projects/Network/NT/Modules/Bootstrap.js b/Projects/Network/NT/Modules/Bootstrap.js index b840e3575..c98029769 100644 --- a/Projects/Network/NT/Modules/Bootstrap.js +++ b/Projects/Network/NT/Modules/Bootstrap.js @@ -36,7 +36,7 @@ exports.newBootstrap = function newBootstrap() { let config = JSON.parse(userProfilePlugin.config) let signatureObject = config.signature let web3 = new SA.nodeModules.web3() - let bloackchainAddress = web3.eth.accounts.recover(signatureObject) + let blockchainAccount = web3.eth.accounts.recover(signatureObject) let ranking = 0 // TODO: read the blockchain balance and transactions from the Treasury Account to calculate the profile ranking. let userProfileId = userProfilePlugin.id let userHandle = config.signature.message @@ -45,12 +45,13 @@ exports.newBootstrap = function newBootstrap() { userProfile.initialize( userProfileId, userHandle, - bloackchainAddress, + blockchainAccount, ranking ) NT.projects.network.globals.memory.maps.USER_PROFILES_BY_ID.set(userProfileId, userProfile) NT.projects.network.globals.memory.maps.USER_PROFILES_BY_HANDLE.set(userHandle, userProfile) + NT.projects.network.globals.memory.maps.USER_PROFILES_BY_BLOCHAIN_ACCOUNT.set(blockchainAccount, userProfile) } }