From be4e4fbd5b366571b7cfe8e9187bea066b493f3b Mon Sep 17 00:00:00 2001 From: Universal Web Date: Fri, 5 May 2023 07:32:32 -0400 Subject: [PATCH] New Packet Design (active) Merging in new chunking & reliability algo (inactive) --- jsconfig.json | 4 +- packetActions.md | 2 +- packetDesign.md | 12 +- scripts/simulateClient.js | 3 +- serverApp/index.js | 16 +-- udsp/ask.js | 14 +-- udsp/client/index.js | 37 +++--- udsp/client/listening.js | 4 +- udsp/client/send.js | 63 ++++------ udsp/request.js | 4 +- udsp/requested.js | 116 ++++++++++++++++++ udsp/server/clients/index.js | 11 +- .../clients/{construct.js => initialize.js} | 4 +- udsp/server/createClient.js | 1 - udsp/server/index.js | 19 ++- udsp/server/onPacket.js | 45 +++---- udsp/server/processPacket.js | 2 +- udsp/server/processSocket.js | 40 ++++-- udsp/server/send.js | 2 +- utilities/crypto.js | 2 +- utilities/logs.js | 13 +- 21 files changed, 262 insertions(+), 152 deletions(-) create mode 100644 udsp/requested.js rename udsp/server/clients/{construct.js => initialize.js} (94%) diff --git a/jsconfig.json b/jsconfig.json index c43e5111..add05d84 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -9,13 +9,13 @@ "udsp/server/*.js" ], "#client/*": [ - "udsp/server/*.js" + "udsp/client/*.js" ], "#server*": [ "udsp/server/index.js" ], "#client*": [ - "udsp/server/index.js" + "udsp/client/index.js" ], "#profile/*": [ "./profile/*.js" diff --git a/packetActions.md b/packetActions.md index 61de3914..d3eddde8 100644 --- a/packetActions.md +++ b/packetActions.md @@ -1,6 +1,6 @@ # Packet Actions numbers and their meanings -Packet Actions have two formats one which is numerical and one which is character based. Prefered is numerical as its smaller and faster. +Packet Actions have two formats one which is numerical and one which is character based. Preferred is numerical as its smaller & faster. - 0 (connect) - 1 (file) diff --git a/packetDesign.md b/packetDesign.md index e12d5110..5ac66a3d 100644 --- a/packetDesign.md +++ b/packetDesign.md @@ -14,13 +14,15 @@ #### PROPERTY NAMES & MEANINGS - id - Connection ID (MANDATORY) -- api - API function that is requested (OPTIONAL) +- act - primary action related to primary protocol functions only (OPTIONAL) - Watcher (OPTIONAL) -- Head (OPTIONAL) -- Body (OPTIONAL) (MSGPack Object) +- Head (OPTIONAL) (Chunked MSGPack Object) + - evnt (Event related to application level events) +- Body (OPTIONAL) (Chunked MSGPack Object) - Pid - Packet ID (MANDATORY) -- Status - Status Code (OPTIONAL) - - If status is left blank it defaults to 200 or is considered a success +- sid - Stream ID (MANDATORY) +- State - State Code (OPTIONAL) + - If state is left blank it defaults to 200 or is considered a success - end - Kill connection (OPTIONAL) - Puzzle - Solve a puzzle to continue (OPTIONAL) - ReKey (OPTIONAL) diff --git a/scripts/simulateClient.js b/scripts/simulateClient.js index 8773f564..286bd0a2 100644 --- a/scripts/simulateClient.js +++ b/scripts/simulateClient.js @@ -22,5 +22,6 @@ const stateRequest = await uwClient.request({ }); console.timeEnd('File Request'); console.timeEnd('Full script runtime'); -console.log('Request state', stateRequest, stateRequest.response.body.data.toString('UTF8')); +console.log('Request state', stateRequest); +console.log(stateRequest.response.body.data.toString('UTF8')); diff --git a/serverApp/index.js b/serverApp/index.js index 76f7c826..ded67d49 100644 --- a/serverApp/index.js +++ b/serverApp/index.js @@ -1,5 +1,5 @@ /* - * App server example + * App server example */ import { createServer } from '#udsp'; import { info } from '#logs'; @@ -18,14 +18,16 @@ const appServer = await createServer({ maxResponseRetries: 3, // Max size of packets maxPacketSize: 1100, - // Max size of a message - maxMessageSize: 10000, + // Max size of body and head data sections in a single packet + maxPacketPayloadSize: 1000, + // max file size + maxFileSize: 9000, + // Max size of a Response + maxResponseSize: 10000, + // Max size of a Packet for Responses + maxResponsePacketSize: 10000, // default file extension default is .js but WWW default is www defaultExtension: 'html', - // Max size of body and head data sections in packets - maxPayloadSize: 1000, - // max data size in a singular packet - maxFileSize: 900, // Domain certificate to be loaded used for connection encryption profile: `${currentPath(import.meta)}../services/universal.web.cert`, // Where to load app resources from diff --git a/udsp/ask.js b/udsp/ask.js index 278930e0..5c806b45 100644 --- a/udsp/ask.js +++ b/udsp/ask.js @@ -1,22 +1,22 @@ import { promise } from 'Acid'; export class Ask { - constructor(payload, thisContext) { - const askContext = this; + constructor(payload, thisClient) { + const thisAsk = this; const timeStamp = Date.now(); const { requestQueue, packetIdGenerator - } = thisContext; + } = thisClient; // sid is a Stream ID const sid = packetIdGenerator.get(); payload.sid = sid; payload.t = timeStamp; - askContext.payload = payload; + thisAsk.payload = payload; const awaitingResult = promise((accept) => { - askContext.accept = accept; + thisAsk.accept = accept; }); - requestQueue.set(sid, askContext); - thisContext.send(payload); + requestQueue.set(sid, thisAsk); + thisClient.send(payload); return awaitingResult; } /* `completedChunks = [];` is initializing an empty array called `completedChunks` as a property of diff --git a/udsp/client/index.js b/udsp/client/index.js index 3349734f..eb365612 100644 --- a/udsp/client/index.js +++ b/udsp/client/index.js @@ -14,11 +14,12 @@ import { assign, construct, UniqID, - isString + isString, + promise } from 'Acid'; import dgram from 'dgram'; // Default utility imports -import { success, configure } from '#logs'; +import { success, configure, info } from '#logs'; import { buildPacketSize } from '#buildPacketSize'; import { buildStringSize } from '#buildStringSize'; import { @@ -38,7 +39,7 @@ import { request } from '#udsp/request'; import { processMessage } from './processMessage.js'; import { onMessage } from './onMessage.js'; import { connect } from './connect.js'; -import { onListening, listen } from './listening.js'; +import { onListening } from './listening.js'; import { currentPath } from '#directory'; // UNIVERSAL WEB Client Class export class Client { @@ -46,7 +47,7 @@ export class Client { description = `The Universal Web's UDSP client module to initiate connections to a UDSP Server.`; descriptor = 'UDSP_CLIENT'; constructor(configuration) { - const thisContext = this; + const thisClient = this; console.log('-------CLIENT INITIALIZING-------\n', configuration); this.configuration = configuration; const { @@ -72,22 +73,20 @@ export class Client { this.processMessage = processMessage.bind(this); this.emit = emit.bind(this); this.onListening = onListening.bind(this); - this.listen = listen.bind(this); this.onMessage = onMessage.bind(this); - thisContext.clientId = createClientId(); + thisClient.clientId = createClientId(); success(`clientId:`, this.clientId); success(`Creating Shared Keys`); - const transmitKey = thisContext.transmitKey = createSessionKey(); - const receiveKey = thisContext.receiveKey = createSessionKey(); + const transmitKey = thisClient.transmitKey = createSessionKey(); + const receiveKey = thisClient.receiveKey = createSessionKey(); // Currently unused but may in the future - const ephemeralProfileTransmitKey = thisContext.ephemeralProfileTransmitKey = createSessionKey(); - const ephemeralProfileReceiveKey = thisContext.ephemeralProfileReceiveKey = createSessionKey(); - console.log(ephemeralProfileTransmitKey, ephemeralProfileReceiveKey); + const ephemeralProfileTransmitKey = thisClient.ephemeralProfileTransmitKey = createSessionKey(); + const ephemeralProfileReceiveKey = thisClient.ephemeralProfileReceiveKey = createSessionKey(); success(`Creating Connection Keypair`); - thisContext.keypair = keypair(); - thisContext.ephemeralPublic = omit(profile.ephemeral, ['private']); + thisClient.keypair = keypair(); + thisClient.ephemeralPublic = omit(profile.ephemeral, ['private']); if (profile.master) { - thisContext.masterPublic = omit(profile.master, ['private']); + thisClient.masterPublic = omit(profile.master, ['private']); } const { ephemeral: { signature: profileSignature } } = profile; const { @@ -99,21 +98,21 @@ export class Client { const { publicKey, secretKey: privateKey, - } = thisContext.keypair; + } = thisClient.keypair; clientSession(receiveKey, transmitKey, publicKey, privateKey, serverPublicKey); // Can be used to encrypt-authenticate the profile with the server // clientSession(ephemeralProfileReceiveKey, ephemeralProfileTransmitKey, profile.ephemeral.publicKey, profile.ephemeral.secretKey, serverPublicKey); configure(`Shared Keys Created`); console.log(receiveKey, transmitKey); - this.listen(); - thisContext.server.on('message', thisContext.onMessage.bind(thisContext)); const serviceKey = toBase64(serviceSignature); const profileKey = toBase64(profileSignature); // Needs to be more complex if forcing no connection with the same credentials const connectionKey = `${serviceKey}${profileKey}`; this.connectionKey = connectionKey; - Client.connections.set(connectionKey, thisContext); - return thisContext; + Client.connections.set(connectionKey, thisClient); + thisClient.server.on('message', thisClient.onMessage.bind(thisClient)); + thisClient.server.on('listening', thisClient.onListening); + return this; } maxMTU = 1000; encoding = 'binary'; diff --git a/udsp/client/listening.js b/udsp/client/listening.js index 682d4466..26cccac8 100644 --- a/udsp/client/listening.js +++ b/udsp/client/listening.js @@ -1,10 +1,8 @@ import { success, failed, imported, msgSent, info } from '#logs'; +import { promise } from 'Acid'; export function onListening() { const connection = this.server.address(); success(`Universal Web Client Server Listening`, connection); } -export function listen() { - this.server.on('listening', this.onListening); -} diff --git a/udsp/client/send.js b/udsp/client/send.js index aafd9b1d..94295ee1 100644 --- a/udsp/client/send.js +++ b/udsp/client/send.js @@ -12,7 +12,8 @@ import { encrypt, nonceBox, toBase64, - hashSign + hashSign, + encryptABytes } from '#crypto'; imported('Client Send'); export async function send(message, priority) { @@ -28,18 +29,6 @@ export async function send(message, priority) { const headers = {}; const clientStatusCode = thisContext.state; console.log(`client Status Code is ${clientStatusCode}`); - if (clientStatusCode === 0) { - if (!message.head) { - message.head = {}; - } - message.head.cert = thisContext.ephemeralPublic; - } - if (message.head) { - message.head = encode(message.head); - } - if (message.body) { - message.body = encode(message.body); - } info(`Send to server`); const nonce = nonceBox(); success(`Nonce Size: ${nonce.length} ${toBase64(nonce)}`); @@ -47,55 +36,51 @@ export async function send(message, priority) { if (transmitID) { headers.id = transmitID; } else { - return console.error(`NO CLIENT ID IS'T ASSIGNED`); + return console.error(`CLIENT ID IS'T ASSIGNED`); } headers.nonce = nonce; if (clientStatusCode === 0) { - // PERFECT FORWARD SECRECY USE RANDOM EPHEMERAL KEY TO ENCRYPT IDENTITY CERT + // PERFECT FORWARD SECRECY USE RANDOM EPHEMERAL KEY TO ENCRYPT headers.key = thisContext.keypair.publicKey; - headers.sig = hashSign(headers.key, thisContext.profile.ephemeral.private); - console.log(`Sig:${toBase64(headers.sig)}`); - console.log(`Sig Size:${headers.sig.length}`); + const profileKeypairSignature = hashSign(headers.key, thisContext.profile.ephemeral.private); + message.sig = profileKeypairSignature; + message.idc = thisContext.ephemeralPublic; + console.log(`Sig Size:${message.sig.length}`); console.log(`Setting ephemeral random public key to header & profile cert to message.body`); } console.log('PACKET HEADERS', headers); + if (message.head) { + message.head = encode(message.head); + } + if (message.body) { + message.body = encode(message.body); + } const headersEncoded = encode(headers); - const headersEndIndex = headersEncoded.length + 3; - const headersEndIndexBuffer = buildStringSize(headersEndIndex); - console.log(headersEndIndex, headers); - const headersCompiled = Buffer.concat([headersEndIndexBuffer, headersEncoded]); - success(`Additional Data End Index ${headersEndIndex.toString()}`); - console.log(toBase64(thisContext.transmitKey)); + console.log(headers); + success(`Additional Data Headers Encoded Size ${headersEncoded.length}`); + console.log('TransmitKey', toBase64(thisContext.transmitKey)); console.log(message); const messageEncoded = encode(message); const encryptedMessage = encrypt(messageEncoded, headersEncoded, nonce, thisContext.transmitKey); if (!encryptedMessage) { return failed('Encryption failed'); } - success(`Encrypted Message Size:${encryptedMessage.length} -> ${toBase64(encryptedMessage)}`); - const encryptedLength = encryptedMessage.length; - const encryptedDataEndIndex = buildPacketSize(headersEndIndex + 4 + encryptedLength); - success(`Encrypted Data End Index: ${encryptedDataEndIndex.toString()}`); - const messageBuffer = Buffer.concat([ - headersCompiled, - encryptedDataEndIndex, - encryptedMessage, - ]); - console.log(toBase64(encryptedMessage)); - const packetSize = messageBuffer.length; + success(`Encrypted Message Size:${encryptedMessage.length}`); + const encryptedMessageLength = encryptedMessage.length; + const compactedMessage = encode([headersEncoded, encryptedMessage]); + const packetSize = compactedMessage.length; success(`Packet End Index ${packetSize}`); - success('Message Buffer Size', Buffer.from(messageBuffer).length); if (packetSize >= 1280) { - console.log(messageBuffer); + console.log(compactedMessage); failed(`WARNING: Packet size is larger than max allowed size -> ${packetSize}`); } return promise((accept, reject) => { - server.send(messageBuffer, port, ip, (error) => { + server.send(compactedMessage, port, ip, (error) => { if (error) { failed(error); return reject(error); } - msgSent(messageBuffer); + msgSent(compactedMessage); accept(); }); }); diff --git a/udsp/request.js b/udsp/request.js index 192d75f3..f3d57723 100644 --- a/udsp/request.js +++ b/udsp/request.js @@ -5,8 +5,8 @@ import { promise, construct } from 'Acid'; import { Ask } from './ask.js'; imported('Request'); export async function request(payload, sendAsIs) { - const thisContext = this; + const thisClient = this; info(`Requested ${payload}`); - const ask = await (construct(Ask, [payload, thisContext])); + const ask = await (construct(Ask, [payload, thisClient])); return ask; } diff --git a/udsp/requested.js b/udsp/requested.js new file mode 100644 index 00000000..649e17e4 --- /dev/null +++ b/udsp/requested.js @@ -0,0 +1,116 @@ +import { isEmpty, promise, eachArray } from 'Acid'; +import { processPacketEvent } from './server/processPacketEvent.js'; +export class Reply { + constructor(message, thisServer) { + const thisReply = this; + const { + replyQueue, + packetIdGenerator + } = thisServer; + const timeStamp = Date.now(); + thisReply.created = timeStamp; + thisReply.server = function() { + return thisServer; + }; + const { sid } = message; + thisReply.sid = sid; + replyQueue.set(sid, thisReply); + thisReply.received(message); + return thisReply; + } + // Incoming + incomingPayload = {}; + incomingPackets = []; + incomingChunks = []; + totalIncomingPackets = 0; + totalIncomingPayloadSize = 0; + // Must be checked for uniqueness + totalReceivedPackets = 0; + // Outgoing + outgoingPayload = {}; + outgoingPackets = []; + outgoingChunks = []; + totalOutgoingPackets = 0; + totalOutgoingPayloadSize = 0; + /* + 0 Created + 1 Receiving + 2 Completed + 3 Sending + 4 Sent + 5 Acknowledged + */ + state = 0; + // Flush Ask Data to Free Memory + flushAsk() { + this.incomingPayload = {}; + this.incomingPackets = []; + this.incomingChunks = []; + this.totalIncomingPackets = 0; + this.totalIncomingPayloadSize = 0; + } + // Flush Reply Data to Free Memory + flushReply() { + this.outgoingPayload = {}; + this.outgoingPackets = []; + this.outgoingChunks = []; + this.totalOutgoingPackets = 0; + this.totalOutgoingPayloadSize = 0; + } + // Flush all data + flush() { + this.flushReply(); + this.flushAsk(); + } + // Flush All data and remove this reply from the map + destroy() { + this.flush(); + this.server().replyQueue.delete(this.sid); + } + // Raw Send Packet + send(message) { + this.server().send(message); + } + reply(packetIDs) { + const thisReply = this; + eachArray(packetIDs, (id) => { + thisReply.send(thisReply.outgoingPackets[id]); + }); + } + replyAll() { + const thisReply = this; + eachArray(thisReply.outgoingPackets, (packet) => { + thisReply.send(packet); + }); + } + received(message) { + const thisReply = this; + const { + body, + head, + sid, + pid, + act, + tp + } = message; + if (tp) { + thisReply.totalIncomingPackets = pid; + } + if (pid) { + if (!thisReply.packets[pid]) { + thisReply.packets[pid] = message; + thisReply.totalReceivedPackets++; + } + } + if (thisReply.totalIncomingPackets === thisReply.totalReceivedPackets) { + thisReply.state = 2; + } + if (thisReply.state === 2) { + thisReply.process(); + } + } + // Incoming Packets have been received begin to process response by first providing the Reply for API processing + process() { + processPacketEvent(this); + } +} diff --git a/udsp/server/clients/index.js b/udsp/server/clients/index.js index c0f8962e..e561a4b6 100644 --- a/udsp/server/clients/index.js +++ b/udsp/server/clients/index.js @@ -1,6 +1,6 @@ import { connected } from './connected.js'; import { connection } from './connection.js'; -import { construct } from './construct.js'; +import { initialize } from './initialize.js'; import { created } from './created.js'; import { destroy } from './destroy.js'; import { reKey } from './reKey.js'; @@ -11,17 +11,18 @@ import { received } from './received.js'; import { success, failed, imported, msgSent, info, msgReceived } from '#logs'; +import { UniqID, construct } from 'Acid'; export class Client { descriptor = 'client'; client = true; pending = false; - messageQueue = new Map(); + responseQueue = construct(Map); + packetIdGenerator = construct(UniqID); constructor(server, connectionInfo, receiveKey, transmitKey, clientId) { this.server = function() { return server; }; - console.log(server); - return construct(this, server, connectionInfo, receiveKey, transmitKey, clientId); + return initialize(this, server, connectionInfo, receiveKey, transmitKey, clientId); } async created() { const server = this.server(); @@ -33,7 +34,7 @@ export class Client { await connected(this, server); success(`socket EVENT -> connected - ID:${this.id}`); } - async state() { + async status() { const server = this.server(); await state(this); info(`socket EVENT -> statusUpdate - ID:${this.id}`); diff --git a/udsp/server/clients/construct.js b/udsp/server/clients/initialize.js similarity index 94% rename from udsp/server/clients/construct.js rename to udsp/server/clients/initialize.js index 9678d6e9..2bed3b15 100644 --- a/udsp/server/clients/construct.js +++ b/udsp/server/clients/initialize.js @@ -3,7 +3,7 @@ import { toBase64, emptyNonce, randombytes_buf } from '#crypto'; import { success, failed, imported, msgSent, info, msgReceived } from '#logs'; -export async function construct(client, server, connection, receiveKey, transmitKey, clientId) { +export async function initialize(client, server, connection, receiveKey, transmitKey, clientId) { const { nodes, configuration: { id: serverIdRaw } @@ -53,7 +53,7 @@ export async function construct(client, server, connection, receiveKey, transmit client.receiveKey = receiveKey; if (!server.realtime && server.gracePeriod) { client.gracePeriod = setTimeout(() => { - if (client.pending === false) { + if (client.state === 1) { client.destroy(1); } }, 30000); diff --git a/udsp/server/createClient.js b/udsp/server/createClient.js index 5376ac14..70cf5296 100644 --- a/udsp/server/createClient.js +++ b/udsp/server/createClient.js @@ -10,6 +10,5 @@ export async function createClient(server, connectionInfo, receiveKey, transmitK console.log('Creating Client Object', toBase64(clientId)); const client = await construct(Client, [server, connectionInfo, receiveKey, transmitKey, clientId]); console.log('Client has been created', toBase64(clientId)); - console.log(client); return client; } diff --git a/udsp/server/index.js b/udsp/server/index.js index 5178efaa..00069030 100644 --- a/udsp/server/index.js +++ b/udsp/server/index.js @@ -18,34 +18,35 @@ import { sendPacket } from './sendPacket.js'; import { send } from './send.js'; import { actions } from './actions/index.js'; import { getCertificate } from '#certificate'; +const { seal } = Object; /* * socket ID: SID */ export class Server { + description = 'Server'; constructor(serverConfiguration) { return this.initialize(serverConfiguration); } bindMethods(methods) { - const thisContext = this; - console.log(methods); + const thisServer = this; each(methods, (method, methodName) => { - console.log(); - thisContext[methodName] = method.bind(thisContext); + thisServer[methodName] = method.bind(thisServer); }); } bindActions(methods) { - const thisContext = this; + const thisServer = this; each(methods, (method, methodName) => { - thisContext.actions.set(methodName, method.bind(thisContext)); + thisServer.actions.set(methodName, method.bind(thisServer)); }); } async initialize(configuration) { console.log('-------SERVER INITIALIZING-------'); - this.configuration = configuration; + this.configuration = seal(assign({}, configuration)); console.log(this.configuration); assign(this, this.configuration); this.server = dgram.createSocket(this.ipVersion); // convert some to just using them as modules with arguments instead of bind/this + console.log(this.description); this.bindMethods({ on, bindServer, @@ -107,12 +108,10 @@ export class Server { success(`Client Node Event: ${eventName} -> SocketID: ${socket.id}`); const foundEvent = this.nodeEvents.get(eventName); if (foundEvent) { - foundEvent(this, socket); + // foundEvent(this, socket); } } events = construct(Map); - responseQueue = construct(Map); - packetIdGenerator = construct(UniqID); streamIdGenerator = construct(UniqID); // default file extension default is .js but WWW default is www defaultExtension = 'js'; diff --git a/udsp/server/onPacket.js b/udsp/server/onPacket.js index 08d4fc77..b61fafe7 100644 --- a/udsp/server/onPacket.js +++ b/udsp/server/onPacket.js @@ -8,42 +8,35 @@ import { import { decrypt } from '#crypto'; import { processPacket } from './processPacket.js'; import { processSocket } from './processSocket.js'; -export async function onPacket(messageBuffer, connection) { +import { isEmpty } from 'Acid'; +export async function onPacket(packet, connection) { + const thisServer = this; msgReceived('Message Received'); - console.log(messageBuffer); - const headersEndIndex = Number(messageBuffer.slice(0, 3)); - if (!headersEndIndex) { - return failed(`No headers size number -> Invalid Packet`); + console.log(packet); + const packetDecoded = decode(packet); + if (isEmpty(packetDecoded)) { + return failed(`No header buffer -> Invalid Packet`); } - success(`Additional Data size ${headersEndIndex - 3}`); - const headersBuffer = messageBuffer.slice(3, headersEndIndex); - const headers = decode(headersBuffer); - if (!headers) { - return failed(`No headers -> Invalid Packet`); - } - success(`Additional Data`); - console.log(headers); - const packetEndIndex = Number(messageBuffer.slice(headersEndIndex, headersEndIndex + 4)); - if (!packetEndIndex) { - return failed(`No packet size number -> Invalid Packet`); + const headersBuffer = packetDecoded[0]; + if (!headersBuffer) { + return failed(`No header buffer -> Invalid Packet`); } - success(`Packet size ${packetEndIndex}`); - console.log(headersEndIndex + 4, packetEndIndex); - const packet = messageBuffer.slice(headersEndIndex + 4, packetEndIndex); + const messageBuffer = packetDecoded[1]; if (!packet) { return failed(`No packet -> Invalid Packet`); } + const headers = decode(headersBuffer); + if (!headers) { + return failed(`No headers -> Invalid Packet`); + } success(`Packet`); - const { - key, - sig - } = headers; + const { key, } = headers; console.log('Headers', headers); - if (key && sig) { + if (key) { success(`Public Key is given -> Processing handshake`); - await processSocket(this, connection, headersBuffer, headers, packet); + await processSocket(thisServer, connection, headersBuffer, headers, messageBuffer); } else { success(`No Public Key is given -> Processing as a message`); - await processPacket(this, connection, headersBuffer, headers, packet); + await processPacket(thisServer, connection, headersBuffer, headers, messageBuffer); } } diff --git a/udsp/server/processPacket.js b/udsp/server/processPacket.js index fe3c9586..214e955a 100644 --- a/udsp/server/processPacket.js +++ b/udsp/server/processPacket.js @@ -32,5 +32,5 @@ export async function processPacket(server, connection, headersBuffer, headers, server.packetCount++; info(`Packet Count: ${server.packetCount}`); await processPacketEvent(server, client, message); - success(`Messages Received: ${server.packetCount}`); + success(`Packet Count: ${server.packetCount}`); } diff --git a/udsp/server/processSocket.js b/udsp/server/processSocket.js index a37d92dd..07d6aa9d 100644 --- a/udsp/server/processSocket.js +++ b/udsp/server/processSocket.js @@ -17,7 +17,7 @@ import { createClient } from './createClient.js'; import { parsePacket } from './parsePacket.js'; import { processPacketEvent } from './processPacketEvent.js'; // additionalData (ad) are the main UDSP headers. It may be called headers at times or additionalData. -export async function processSocket(server, connection, additionalDataBuffer, additionalData, packet) { +export async function processSocket(server, connection, additionalDataBuffer, additionalData, messageBuffer) { const { profile: { ephemeral: { @@ -26,21 +26,19 @@ export async function processSocket(server, connection, additionalDataBuffer, ad } }, } = server; - const signature = additionalData.sig; const ephemeralKeypair = additionalData.key; - success(`Encrypted Message Signature: ${toBase64(signature)}`); - success(`Encrypted Message Signature Size: ${signature.length}`); const clientId = additionalData.id; const nonce = additionalData.nonce; - success(`Encrypted Message Size: ${packet.length}`); + success(`Encrypted Message Size: ${messageBuffer.length}`); const sessionKey = serverSession(serverPublicKey, serverPrivateKey, ephemeralKeypair); const receiveKey = sessionKey.receiveKey; const transmitKey = sessionKey.transmitKey; - success(`receiveKey: ${toBase64(receiveKey)}`); - success(`transmitKey: ${toBase64(transmitKey)}`); - console.log(toBase64(packet)); + info(`receiveKey: ${toBase64(receiveKey)}`); + info(`transmitKey: ${toBase64(transmitKey)}`); + console.log(toBase64(messageBuffer)); console.log(toBase64(nonce)); - const decrypted = decrypt(packet, additionalDataBuffer, nonce, receiveKey); + console.log(additionalDataBuffer.length); + const decrypted = decrypt(messageBuffer, additionalDataBuffer, nonce, receiveKey); if (!decrypted) { return failed(`Decrypt Failed`); } @@ -48,16 +46,32 @@ export async function processSocket(server, connection, additionalDataBuffer, ad if (decrypted) { const message = parsePacket(decrypted); if (!message) { - return failed('JSON ERROR', connection); + return failed('MSGPACK ERROR', connection); } + console.log(message); + if (!message.idc) { + return failed('No Identity Provided', connection); + } + if (!message.sig) { + return failed('No Sig Provided', connection); + } + const { + idc, + sig + } = message; server.socketCount++; console.log(message); - const isValid = signVerify(signature, message.head.cert.key); + success(`Encrypted Message Signature: ${toBase64(sig)}`); + success(`Encrypted Message Signature Size: ${sig.length}`); + const isValid = signVerify(sig, idc.key); console.log('SIGNATURE CHECK', isValid); if (!isValid) { return failed(`Signature isn't valid`); } - const signatureHash = signOpen(signature, message.head.cert.key); + const signatureHash = signOpen(sig, idc.key); + if (!signatureHash) { + return failed(`Signature open failed`); + } const sigCompare = Buffer.compare(signatureHash, hash(ephemeralKeypair)) === 0; if (sigCompare) { msgReceived(`Signature is valid`); @@ -68,6 +82,6 @@ export async function processSocket(server, connection, additionalDataBuffer, ad console.log('SIGNATURE FAILED NO SOCKET CREATED'); return; } - success(`Messages Received: ${server.socketCount}`); + success(`Socket Count: ${server.socketCount}`); } } diff --git a/udsp/server/send.js b/udsp/server/send.js index e0a3311c..d0c65efa 100644 --- a/udsp/server/send.js +++ b/udsp/server/send.js @@ -68,7 +68,7 @@ export async function send(client, rawMessage, options) { queued.size = size; if (sid) { console.log('Queued Message', queued); - server().responseQueue.set(sid, queued); + // server().responseQueue.set(sid, queued); } if (size > this.maxPayloadSize) { console.log('SEND - Item is too large will need to chunk into packets.'); diff --git a/utilities/crypto.js b/utilities/crypto.js index 54fa43dc..16b556b8 100644 --- a/utilities/crypto.js +++ b/utilities/crypto.js @@ -104,6 +104,7 @@ export function encrypt(message, ad, nonce, secretKey) { crypto_aead_xchacha20poly1305_ietf_encrypt(cipher, message, ad, null, nonce, secretKey); return cipher; } +export const encryptABytes = crypto_aead_xchacha20poly1305_ietf_ABYTES; export function decrypt(cipher, ad, nonce, secretKey) { const message = Buffer.alloc(cipher.length - crypto_aead_xchacha20poly1305_ietf_ABYTES); const verify = crypto_aead_xchacha20poly1305_ietf_decrypt(message, null, cipher, ad, nonce, secretKey); @@ -128,7 +129,6 @@ export function clientSession(receiveKey, transmissionKey, publicKey, privateKey crypto_kx_client_session_keys(receiveKey, transmissionKey, publicKey, privateKey, serverPublicKey); } export function createSessionKey() { - console.log(crypto_kx_SESSIONKEYBYTES); const sessionKey = Buffer.alloc(crypto_kx_SESSIONKEYBYTES); return sessionKey; } diff --git a/utilities/logs.js b/utilities/logs.js index 2827bf33..feb9c931 100644 --- a/utilities/logs.js +++ b/utilities/logs.js @@ -2,8 +2,10 @@ import chalk from 'chalk'; import { stringify, each, - isPlainObject, - initialString + isPrimitive, + initialString, + isArray, + isBuffer } from 'Acid'; const arrayNumberRegex = /\[([\d\s,]*?)\]/gm; function truncateArray(match) { @@ -14,20 +16,19 @@ function shortenArrays(item) { } export function prettyObjects(args, consoleBase) { return each(args, (item) => { - console.log(consoleBase((isPlainObject(item)) ? shortenArrays(stringify(item, null, ` `)) : item)); + console.log(consoleBase((isPrimitive(item) || isArray(item) || isBuffer(item)) ? item : shortenArrays(stringify(item, null, ` `)))); }); } function logFactory(bg, color, header, footer) { const consoleBase = (bg) ? chalk[bg].hex(color) : chalk.hex(color); return function(...args) { - const descriptor = this?.descriptor || ''; if (footer) { - const fullHeader = (descriptor) ? ` ---------------- ${descriptor}: ${header} START ---------------- ` : ` ---------------- ${header} START ---------------- `; + const fullHeader = ` ---------------- ${header} START ---------------- `; console.log(consoleBase(fullHeader)); prettyObjects(args, consoleBase); console.log(consoleBase(` ---------------- ${header} END ---------------- `, `\n`)); } else { - const fullHeader = (descriptor) ? `${descriptor}: ${header} => ` : `${header} => `; + const fullHeader = `${header} => `; console.log(consoleBase(fullHeader)); prettyObjects(args, consoleBase); }