Skip to content

Commit

Permalink
New Handshake Intro Process
Browse files Browse the repository at this point in the history
Introduce Queue
Introduce wait for intro to complete before more requests are sent
  • Loading branch information
Universal Web committed Jul 11, 2023
1 parent c7a0bb0 commit 5b8c543
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 40 deletions.
4 changes: 1 addition & 3 deletions udsp/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import { cryptography } from '#udsp/cryptography';
import dgram from 'dgram';
import { randomConnectionId } from '#crypto';
export class UDSP {
constructor(config) {
// return this.initialize(config);
}
async calculatePacketOverhead() {
const {
connectionIdSize,
Expand Down Expand Up @@ -78,4 +75,5 @@ export class UDSP {
heapSize = 0;
throttle = false;
debounce = false;
requestQueue = [];
}
9 changes: 0 additions & 9 deletions udsp/client/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,7 @@ export async function connect(message) {
if (state === 1 && sid) {
connectedLog(data);
this.state = 1;
this.connected = true;
this.realtime = true;
this.destination.id = sid;
this.lastPacketTime = Date.now();
this.lastPacketGivenTime = time;
// const dataDecoded = decode(data);
// console.log(dataDecoded);
// if (dataDecoded.reKey) {
// this.reKey(dataDecoded.reKey);
// }
}
console.log('-------CLIENT CONNECTED-------\n');
return connectResponse;
Expand Down
14 changes: 9 additions & 5 deletions udsp/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { request } from '#udsp/request';
import { cryptography } from '#udsp/cryptography';
import { processMessage } from './processMessage.js';
import { onPacket } from './onPacket.js';
import { connect as clientConnect } from './connect.js';
import { intro } from './intro.js';
import { onListening } from './listening.js';
import { keychainGet } from '#keychain';
import { Ask } from '../ask.js';
Expand Down Expand Up @@ -169,7 +169,7 @@ export class Client extends UDSP {
Client.connections.set(this.idString, this);
if (this.autoConnect) {
console.time('CONNECTING');
const connectRequest = await this.connect();
this.handshake = await this.intro();
console.timeEnd('CONNECTING');
}
return this;
Expand All @@ -187,7 +187,12 @@ export class Client extends UDSP {
const ask = construct(Ask, [message, options, this]);
return ask;
}
connect = clientConnect;
intro(ask) {
if (!this.handshake) {
this.handshake = intro.call(this, ask);
}
return this.handshake;
}
send = send;
request = request;
fetch = fetchRequest;
Expand All @@ -196,9 +201,8 @@ export class Client extends UDSP {
onListening = onListening;
onPacket = onPacket;
destination = {};
autoConnect = true;
autoConnect = false;
static connections = new Map();
queue = new Map();
packetIdGenerator = construct(UniqID);
}
export async function client(configuration) {
Expand Down
31 changes: 31 additions & 0 deletions udsp/client/intro.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { connectedLog } from '#logs';
import { decode } from 'msgpackr';
import { randomBuffer } from '#utilities/crypto';
export async function intro(message) {
console.log('-------CLIENT INTRO-------\n');
// opn stands for open meaning connect to a server
const connectRequest = this.request({
message: randomBuffer()
}, 'open');
console.log('HANDSHAKE: Intro request', connectRequest);
const connectResponse = await connectRequest.send();
const {
data,
state,
time,
// server connection ID
sid
} = connectResponse;
if (state === 1 && sid) {
connectedLog(data);
this.handshake = true;
this.state = 1;
this.connected = true;
this.destination.id = sid;
if (data.key) {
console.log('New Key Provided for Perfect Forward Secrecy');
}
}
console.log('-------CLIENT HANDSHAKE CONNECTED-------\n');
return connectResponse;
}
5 changes: 5 additions & 0 deletions udsp/client/onPacket.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ export async function onPacket(packet) {
if (!wasDecoded) {
return failed('When decoding the packet but header passed');
}
if (this.state === 0) {
if (!config.packetDecoded.error) {
this.state = 1;
}
}
processMessage(config.packetDecoded, this);
}

43 changes: 27 additions & 16 deletions udsp/decodePacket.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,35 @@ export async function decodePacket(config) {
} else if (footer) {
packetDecoded.footer = footer;
}
const messageEncoded = packet[1];
if (header.error) {
console.log('Critical Error', header.error);
// can be returned if a server so chooses to respond to bad/mal/incorrect requests
// can return unencrypted data
if (messageEncoded) {
packetDecoded.message = decode(messageEncoded);
}
return true;
}
const ad = (footer) ? Buffer.concat([packet[0], packet[2]]) : packet[0];
info(`Transmit Key ${toBase64(destination.sessionKeys.receiveKey)}`);
if (!packet[1]) {
return failed(`No Encrypted Message - failed to decode -> Invalid Packet`);
}
info(`encryptedMessage ${packet[1].length} bytes`);
const decryptedMessage = cryptography.decrypt(packet[1], destination.sessionKeys, ad);
if (!decryptedMessage) {
return failed('Encryption failed');
}
info(`encryptedMessage ${decryptedMessage.length} bytes`);
const message = decode(decryptedMessage);
if (message.head) {
console.log('head PAYLOAD', message.head);
}
if (message.data) {
success('data PAYLOAD', message.data?.length || message.data);
if (messageEncoded) {
info(`encryptedMessage ${messageEncoded.length} bytes`);
const decryptedMessage = cryptography.decrypt(packet[1], destination.sessionKeys, ad);
if (!decryptedMessage) {
return failed('Encryption failed');
}
info(`encryptedMessage ${decryptedMessage.length} bytes`);
const message = decode(decryptedMessage);
if (message.head) {
console.log('head PAYLOAD', message.head);
}
if (message.data) {
success('data PAYLOAD', message.data?.length || message.data);
}
packetDecoded.message = message;
} else {
failed(`No Encrypted Message - failed to decode -> Invalid Packet`);
}
packetDecoded.message = message;
return true;
}
35 changes: 33 additions & 2 deletions udsp/request/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { sendPacketsById } from './sendPacketsById.js';
import { onPacket } from './onPacket.js';
import {
isBuffer, isPlainObject, isString, promise, assign,
objectSize, eachArray, jsonParse, construct, isArray, clear
objectSize, eachArray, jsonParse, construct, isArray, clear, isFalse
} from '@universalweb/acid';
import { encode, decode } from 'msgpackr';
import { request } from '#udsp/request';
Expand Down Expand Up @@ -38,6 +38,9 @@ export class Base {
if (packetMaxPayloadSafeEstimate) {
this.packetMaxPayloadSafeEstimate = packetMaxPayloadSafeEstimate;
}
if (this.isAsk) {
this.handshake = source.handshake;
}
}
setHeaders(target) {
const source = (this.isAsk) ? this.request : this.response;
Expand Down Expand Up @@ -98,7 +101,6 @@ export class Base {
console.log('Missing packets: ', missingDataPackets);
console.log('Last known EndIndex: ', lastKnownEndIndex);
} else if (this.head.dataSize === this.currentIncomingDataSize) {
this.ok = true;
this.complete();
}
}
Expand Down Expand Up @@ -133,6 +135,19 @@ export class Base {
packet.headerSize = this.outgoingHeadSize;
this.sendPacket(packet);
}
sendIntro() {
const packet = this.getPacketTemplate();
packet.intro = true;
this.sendPacket(packet);
}
sendFinished() {
if (this.state === 0) {
this.state = 1;
}
const packet = this.getPacketTemplate();
packet.intro = true;
this.sendPacket(packet);
}
sendHeadReady() {
if (this.state === 1) {
this.state = 2;
Expand Down Expand Up @@ -222,10 +237,24 @@ export class Base {
}
async send() {
const thisSource = this;
if (isFalse(this.handshake)) {
if (this.method !== 'intro') {
if (!this.waitingOnIntro) {
console.log('Handshake not complete.');
this.waitingOnIntro = true;
}
await this.source().intro(this);
this.handshake = this.source().handshake;
}
}
if (this.sent) {
return this.accept;
}
const {
isAsk,
isReply,
} = this;
this.sent = true;
const message = (isAsk) ? this.request : this.response;
console.log(`${this.type}.send`, message);
const awaitingResult = promise((accept) => {
Expand Down Expand Up @@ -327,4 +356,6 @@ export class Base {
to keep track of the state of the request, where `0` represents an unsent request, `1` represents a
request that is currently being sent, and `2` represents a completed request. */
state = 0;
handshake = false;
inRequestQueue = false;
}
2 changes: 1 addition & 1 deletion udsp/sendPacket.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export async function sendPacket(packetConfig) {
reject(error);
return failed(error);
}
msgSent('Message Sent', packet.length);
success('Packet Sent Out', packet.length);
accept();
});
});
Expand Down
4 changes: 2 additions & 2 deletions udsp/server/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { connect } from './connect.js';
import { intro } from './intro.js';
import { file } from './file.js';
import { reKey } from './reKey.js';
import { state } from './state.js';
export const actions = {
connect,
intro,
file,
reKey,
state
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { info } from '#logs';
export async function connect(reply) {
export async function intro(reply) {
const {
resourceDirectory,
cacheMaxAge,
Expand Down Expand Up @@ -40,5 +40,7 @@ export async function connect(reply) {
response.data.message = onConnectResponse;
}
reply.setHeader('serialization', 'struct');
reply.send();
// swap to new key but only for the specific request?
const clientResponse = await reply.send();
console.log(clientResponse);
}

0 comments on commit 5b8c543

Please sign in to comment.