Skip to content

Commit

Permalink
New comms system in progress
Browse files Browse the repository at this point in the history
New Ask
New sendPacket
New Encode
Optimized sending
UDSP headers can be added via the ASK
Handshake can have arbitrary payloads ie a certificate
  • Loading branch information
Universal Web committed Jul 15, 2023
1 parent 28ed664 commit ee0171f
Show file tree
Hide file tree
Showing 17 changed files with 142 additions and 157 deletions.
1 change: 1 addition & 0 deletions notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ The packet based approach in the ASK for the new handshake is the first step but
Client Hello
Server Hello Server Connection ID Packet Sent to Client
Client responds with new server connection ID - connection is established (if fails at this step just re-transmit next packets)
Allows for Head and Data like a full request in the event a certificate is requested if not then it can terminate early on in the packet process
21 changes: 16 additions & 5 deletions scripts/certificates.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const domainProfile = await createProfile({
// Encrypt public key sent in the packet
// encryptClientKey: 'sealedbox',
// encryptServerKey: 'sealedbox',
encryptKeypair: true
// encryptKeypair: true
},
// Max connection id size in bytes usually randomly generated and checked but used to calculate max packet payload size
connectionIdSize: 8,
Expand All @@ -47,11 +47,18 @@ const domainProfile = await createProfile({
// maxHeadSize: 1200,
// heartbeat is an interval check for when a client must send something to the server to remain connected
heartbeat: 30000,
url: 'universal.web',
domain: 'universal',
extension: 'web',
ip: '::1',
port: 8888,
domain: 'universal.web',
hostname: 'universal',
extension: 'web',
// Used when a custom Domain name server is used to resolve the domain name locations still provides valid certificates else will be warned of invalid certificate
// domainInfoServer: {
// url: 'dis.universal.web',
// subdomain: 'dis',
// domain: 'universal',
// extension: 'web',
// },
// Shows the browser how to display the domain name for humans correctly
encoding: 'utf8',
entity: {
Expand All @@ -73,12 +80,16 @@ const domainProfile = await createProfile({
publicKey: true
},
// This allows a browser or connection to use the realtime mode for the UDSP connection
// Allowing it to act like a webtransport, websocket, and or traditional HTTP like connection
realtime: true,
// blocked methods mean methods the server doesn't permit
// blockedMethods: ['open'],
allowedMethods: ['get', 'connect', 'open', 'file', 'stream', 'close'],
// deafult compression of payload data only
compression: true,
headerCompression: true,
// packetCompression: true,
// headerCompression: true,
// footerCompression: true,
autoLogin: true,
},
master: {},
Expand Down
3 changes: 1 addition & 2 deletions todo.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# TODO

Swap to simple binary IDs instead of UTF8 strings
Swap to simple binary Codes
Swap to simple numerical Codes
Minify property names for packets
Minify property names for certificates
2 changes: 1 addition & 1 deletion udsp/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { onPacket } from './onPacket.js';
import { intro } from './intro.js';
import { onListening } from './listening.js';
import { keychainGet } from '#keychain';
import { Ask } from '../ask.js';
import { Ask } from '../request/ask.js';
import { fetchRequest } from '../fetch.js';
import { UDSP } from '#udsp/base';
// UNIVERSAL WEB Client Class
Expand Down
8 changes: 2 additions & 6 deletions udsp/client/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import { promise } from '@universalweb/acid';
import { encodePacket } from '#udsp/encodePacket';
import { sendPacket } from '#udsp/sendPacket';
imported('Client Send');
export async function send(packet) {
const packetConfig = {
source: this,
packet,
};
export async function send(packet, options) {
console.log(`client.send to Server`, this.destination.port, this.destination.ip);
return sendPacket(packetConfig);
return sendPacket(packet, this, this.socket);
}
72 changes: 32 additions & 40 deletions udsp/encodePacket.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,78 +16,70 @@ import {
objectSize
} from '@universalweb/acid';
import { toBase64 } from '#crypto';
export async function encodePacket(config) {
export async function encodePacket(packet, source, destination) {
success(`PROCESSING ENCODE PACKET`);
const {
source,
options,
packet: message
} = config;
message,
header: headers,
footer
} = packet;
const {
state,
isClient,
isServer,
isServerEnd,
isServerClient
} = source;
const header = options?.header || {};
const footer = options?.footer;
const destination = source.destination || config.destination;
let id = destination.id || source.id;
const { cryptography } = source;
let encryptConnectionId;
if (isServerEnd) {
encryptConnectionId = cryptography.config.encryptClientConnectionId;
} else {
encryptConnectionId = cryptography.config.encryptServerConnectionId;
}
if (!id) {
return console.error(`ID IS'T ASSIGNED`);
}
const { cryptography } = source;
let encryptConnectionId = cryptography.config.encryptConnectionId;
if (!encryptConnectionId) {
if (isServerEnd) {
encryptConnectionId = cryptography.config.encryptClientConnectionId;
} else {
encryptConnectionId = cryptography.config.encryptServerConnectionId;
}
}
if (encryptConnectionId) {
// console.log(destination);
if (encryptConnectionId === 'sealedbox') {
if (isServerEnd) {
id = cryptography.encryptClientConnectionId(id, destination.connectionIdKeypair);
} else {
id = cryptography.encryptServerConnectionId(id, destination.connectionIdKeypair);
}
if (isServerEnd) {
id = cryptography.encryptClientConnectionId(id, destination.connectionIdKeypair);
} else {
id = cryptography.encryptServerConnectionId(id, destination.connectionIdKeypair);
}
if (!id) {
return console.error(`Connection ID Encrypt failed method given ${encryptConnectionId}`);
}
}
header.id = id;
let header;
if (headers && objectSize(headers)) {
header = headers;
header.id = id;
} else {
header = id;
}
// console.log(config);
message.t = Date.now();
if (isClient) {
if (state === 0) {
console.log('DESTINATION ENCRYPT PUBLIC KEY', toBase64(destination.encryptKeypair.publicKey));
if (!header.key) {
header.key = source.encryptKeypair.publicKey;
}
}
}
if (header.key) {
const {
encryptClientKey,
encryptServerKey
} = cryptography.config;
if (isClient) {
if (encryptClientKey === 'sealedbox') {
if (encryptClientKey) {
header.key = cryptography.encryptClientKey(header.key, destination.encryptKeypair);
}
}
if (isServerEnd) {
if (encryptServerKey === 'sealedbox') {
if (encryptServerKey) {
header.key = cryptography.encryptServerKey(header.key, destination.encryptKeypair);
}
}
}
if (options) {
console.log('Packet Options', options);
}
const headerEncoded = (objectSize(header) === 1 && header.id) ? encode(id) : encode(header);
const headerEncoded = encode(header);
const messageEncoded = encode(message);
const ad = (footer) ? Buffer.concat([headerEncoded, footer]) : headerEncoded;
const encryptedMessage = cryptography.encrypt(messageEncoded, source.sessionKeys, ad);
Expand All @@ -98,16 +90,16 @@ export async function encodePacket(config) {
if (footer) {
packetStructure[2] = encode(footer);
}
const packet = encode(packetStructure);
const packetEncoded = encode(packetStructure);
info(`clientId: ${toBase64(header.id)}`);
info(`Transmit Key ${toBase64(source.sessionKeys.transmitKey)}`);
const packetSize = packet.length;
const packetSize = packetEncoded.length;
console.log('Size Unencrypted', encode([headerEncoded, messageEncoded]).length);
info(`encoded Packet Size ${packetSize}`);
if (packetSize >= 1328) {
console.log(packet);
console.log(packetEncoded);
failed(`WARNING: Packet size is larger than max allowed size 1328 -> ${packetSize} over by ${packetSize - 1328}`);
}
success(`PROCESSED ENCODE PACKET`);
return packet;
return packetEncoded;
}
8 changes: 3 additions & 5 deletions udsp/ask.js → udsp/request/ask.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { decode, encode } from 'msgpackr';
import {
failed, info, msgReceived, msgSent
} from '#logs';
import { Base } from './request/base.js';
import { Base } from './base.js';
import { request } from '#udsp/request';
export class Ask extends Base {
constructor(requestObject, options = {}, source) {
Expand All @@ -24,7 +24,7 @@ export class Ask extends Base {
data,
method = 'get'
} = requestObject;
const head = requestObject.head || requestObject.headers || options.head || options.headers || {};
const head = requestObject.head || options.head;
console.log('Ask', requestObject);
const streamId = packetIdGenerator.get();
this.request.sid = streamId;
Expand All @@ -48,9 +48,7 @@ export class Ask extends Base {
}
isAsk = true;
type = 'ask';
request = {
head: {}
};
request = {};
}
export async function ask(source) {
return construct(Ask, omit);
Expand Down
47 changes: 32 additions & 15 deletions udsp/request/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { encode, decode } from 'msgpackr';
import { request } from '#udsp/request';
import { assembleData } from './assembleData.js';
import { toBase64 } from '#crypto';
export class Base {
constructor(options = {}, source) {
const { events, } = options;
Expand Down Expand Up @@ -131,48 +132,48 @@ export class Base {
this.state = 1;
}
const packet = this.getPacketTemplate();
packet.setup = true;
packet.headerSize = this.outgoingHeadSize;
packet.message.setup = true;
packet.message.headerSize = this.outgoingHeadSize;
this.sendPacket(packet);
}
sendIntro() {
const packet = this.getPacketTemplate();
packet.intro = true;
packet.message.intro = true;
this.sendPacket(packet);
}
sendIntroReply() {
const packet = this.getPacketTemplate();
packet.introReply = true;
packet.scid = this.client().id;
packet.message.introReply = true;
packet.message.scid = this.client().id;
this.sendPacket(packet);
}
sendFinished() {
if (this.state === 0) {
this.state = 1;
}
const packet = this.getPacketTemplate();
packet.intro = true;
packet.message.intro = true;
this.sendPacket(packet);
}
sendHeadReady() {
if (this.state === 1) {
this.state = 2;
}
const packet = this.getPacketTemplate();
packet.headReady = true;
packet.message.headReady = true;
this.sendPacket(packet);
}
sendDataReady() {
if (this.state === 2) {
this.state = 3;
}
const packet = this.getPacketTemplate();
packet.dataReady = true;
packet.message.dataReady = true;
this.sendPacket(packet);
}
async sendEnd() {
const packet = this.getPacketTemplate();
packet.end = true;
packet.message.end = true;
this.sendPacket(packet);
}
get headers() {
Expand Down Expand Up @@ -203,12 +204,12 @@ export class Base {
const headSize = this.outgoingHeadSize;
while (currentBytePosition < this.outgoingHeadSize) {
const packet = this.getPacketTemplate();
packet.sid = sid;
packet.pid = packetId;
packet.message.sid = sid;
packet.message.pid = packetId;
const endIndex = currentBytePosition + maxHeadSize;
const safeEndIndex = endIndex > headSize ? headSize : endIndex;
packet.head = this.outgoingHead.subarray(currentBytePosition, safeEndIndex);
packet.headSize = packet.head.length;
packet.message.head = this.outgoingHead.subarray(currentBytePosition, safeEndIndex);
packet.message.headSize = packet.head.length;
outgoingHeadPackets[packetId] = packet;
if (safeEndIndex === headSize) {
packet.last = true;
Expand Down Expand Up @@ -313,13 +314,29 @@ export class Base {
getPacketTemplate() {
const { id, } = this;
const packet = {
sid: id
message: {
sid: id
}
};
return packet;
}
destroy = destroy;
onPacket = onPacket;
sendPacket = sendPacket;
sendPacket(packet, options) {
this.source().send(packet, options);
}
addUDSPHeader(packet, headerName, headerValue) {
if (!packet.header) {
packet.header = {};
}
packet.header[headerName] = headerValue;
}
addPublicKeyHeader(packet) {
const source = this.source();
const key = source.encryptKeypair.publicKey;
console.log('DESTINATION ENCRYPT PUBLIC KEY', toBase64(key));
this.addUDSPHeader(packet, 'key', key);
}
on = on;
outgoingHead;
outgoingData;
Expand Down
19 changes: 12 additions & 7 deletions udsp/request/dataPacketization.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,30 @@ export async function dataPacketization(source) {
const safeEndIndex = endIndex > dataSize ? dataSize : endIndex;
const chunk = outgoingData.subarray(currentBytePosition, safeEndIndex);
console.log('chunksize', chunk.length, currentBytePosition, endIndex);
const packet = {
const message = {
pid: packetId,
endIndex: safeEndIndex,
sid
};
packet.data = chunk;
outgoingDataPackets[packetId] = outgoingDataPackets;
message.data = chunk;
const packet = {
message
};
outgoingDataPackets[packetId] = packet;
if (safeEndIndex === dataSize) {
packet.last = true;
message.last = true;
break;
}
currentBytePosition += maxDataSize;
packetId++;
}
} else {
const packet = {
pid: 0,
end: true,
data: outgoingData
message: {
pid: 0,
end: true,
data: outgoingData
}
};
console.log(source);
outgoingDataPackets[0] = packet;
Expand Down
Loading

0 comments on commit ee0171f

Please sign in to comment.