tasq/node_modules/agentic-flow/dist/transport/quic-handshake.js

199 lines
7.1 KiB
JavaScript

// QUIC Handshake Protocol Implementation
// Implements QUIC connection establishment using existing WASM API
import { logger } from '../utils/logger.js';
export var HandshakeState;
(function (HandshakeState) {
HandshakeState["Initial"] = "initial";
HandshakeState["Handshaking"] = "handshaking";
HandshakeState["Established"] = "established";
HandshakeState["Failed"] = "failed";
HandshakeState["Closed"] = "closed";
})(HandshakeState || (HandshakeState = {}));
/**
* QUIC Handshake Manager
* Implements connection establishment protocol using WASM sendMessage/recvMessage
*/
export class QuicHandshakeManager {
contexts;
constructor() {
this.contexts = new Map();
}
/**
* Initiate QUIC handshake for a new connection
*/
async initiateHandshake(connectionId, remoteAddr, wasmClient, createMessage) {
try {
logger.info('Initiating QUIC handshake', { connectionId, remoteAddr });
const context = {
connectionId,
state: HandshakeState.Initial,
remoteAddr,
startTime: Date.now(),
wasmClient,
createMessage
};
this.contexts.set(connectionId, context);
// Step 1: Send Initial packet
await this.sendInitialPacket(context);
// Step 2: Wait for Server Hello
const success = await this.waitForServerHello(context);
if (success) {
context.state = HandshakeState.Established;
logger.info('QUIC handshake established', {
connectionId,
duration: Date.now() - context.startTime
});
return true;
}
else {
context.state = HandshakeState.Failed;
logger.warn('QUIC handshake failed', { connectionId });
return false;
}
}
catch (error) {
logger.error('QUIC handshake error', { connectionId, error });
const context = this.contexts.get(connectionId);
if (context) {
context.state = HandshakeState.Failed;
}
return false;
}
}
/**
* Send QUIC Initial packet
*/
async sendInitialPacket(context) {
context.state = HandshakeState.Handshaking;
// Create QUIC Initial packet
const initialPayload = this.createInitialPayload();
const message = context.createMessage(`handshake-init-${Date.now()}`, 'handshake', initialPayload, {
connectionId: context.connectionId,
packetType: 'Initial',
timestamp: Date.now()
});
logger.debug('Sending QUIC Initial packet', {
connectionId: context.connectionId,
bytes: initialPayload.length
});
await context.wasmClient.sendMessage(context.remoteAddr, message);
}
/**
* Wait for Server Hello response
*/
async waitForServerHello(context) {
try {
logger.debug('Waiting for Server Hello', { connectionId: context.connectionId });
// Receive response from WASM
const response = await context.wasmClient.recvMessage(context.remoteAddr);
if (response && response.metadata?.packetType === 'ServerHello') {
logger.debug('Received Server Hello', {
connectionId: context.connectionId,
metadata: response.metadata
});
// Send Handshake Complete
await this.sendHandshakeComplete(context);
return true;
}
// If no Server Hello, assume graceful degradation
logger.debug('No Server Hello received, using graceful connection mode', {
connectionId: context.connectionId
});
// Mark as established for graceful degradation
return true;
}
catch (error) {
logger.debug('Server Hello wait error (expected for direct mode)', {
connectionId: context.connectionId,
error: error instanceof Error ? error.message : String(error)
});
// Graceful degradation: allow connection without full handshake
return true;
}
}
/**
* Send Handshake Complete packet
*/
async sendHandshakeComplete(context) {
const completePayload = this.createHandshakeCompletePayload();
const message = context.createMessage(`handshake-complete-${Date.now()}`, 'handshake', completePayload, {
connectionId: context.connectionId,
packetType: 'HandshakeComplete',
timestamp: Date.now()
});
logger.debug('Sending Handshake Complete', {
connectionId: context.connectionId
});
await context.wasmClient.sendMessage(context.remoteAddr, message);
}
/**
* Create QUIC Initial packet payload
*/
createInitialPayload() {
// Simplified QUIC Initial packet
// In production, this would be a full QUIC Initial with TLS ClientHello
const payload = new Uint8Array(64);
// QUIC header flags (Long Header, Initial packet type)
payload[0] = 0xC0 | 0x00; // Long Header + Initial
// Version (QUIC v1 = 0x00000001)
payload[1] = 0x00;
payload[2] = 0x00;
payload[3] = 0x00;
payload[4] = 0x01;
// Connection ID length
payload[5] = 0x08; // 8-byte connection ID
// Random connection ID
for (let i = 6; i < 14; i++) {
payload[i] = Math.floor(Math.random() * 256);
}
// Packet number
payload[14] = 0x01;
// Remaining bytes are simplified payload
for (let i = 15; i < payload.length; i++) {
payload[i] = 0x00;
}
return payload;
}
/**
* Create Handshake Complete payload
*/
createHandshakeCompletePayload() {
const payload = new Uint8Array(32);
payload[0] = 0xFF; // Handshake Complete marker
return payload;
}
/**
* Get handshake state for connection
*/
getHandshakeState(connectionId) {
const context = this.contexts.get(connectionId);
return context?.state || HandshakeState.Initial;
}
/**
* Check if connection is established
*/
isEstablished(connectionId) {
return this.getHandshakeState(connectionId) === HandshakeState.Established;
}
/**
* Close handshake context
*/
closeHandshake(connectionId) {
const context = this.contexts.get(connectionId);
if (context) {
context.state = HandshakeState.Closed;
this.contexts.delete(connectionId);
logger.debug('Handshake context closed', { connectionId });
}
}
/**
* Get all active handshakes
*/
getActiveHandshakes() {
return Array.from(this.contexts.keys()).filter(id => {
const state = this.getHandshakeState(id);
return state === HandshakeState.Handshaking || state === HandshakeState.Established;
});
}
}
//# sourceMappingURL=quic-handshake.js.map