# Network Library Phase 2: Transport Layer Implementation Plan Now that we've successfully completed Phase 0 with comprehensive test coverage, we're ready to move on to Phase 2: Transport Layer. This phase will build upon our foundational architecture to implement the transport capabilities needed for actual network communication. ## Overview Phase 2 focuses on creating the transport abstraction and plugin framework that will allow different transport mechanisms (WebRTC, WebSocket, etc.) to be plugged into the network system. We'll start with a memory-based transport for testing and simulation. ## Implementation Goals 1. **Transport Interface Layer**: Create the transport abstraction interfaces 2. **Base Transport Class**: Develop an abstract base class for common functionality 3. **Memory Transport**: Implement an in-memory transport for testing 4. **Transport Manager**: Create a system to manage multiple transport types 5. **Plugin Framework**: Build a plugin system for transport extensibility 6. **Integration**: Connect transport layer with existing NetworkNode implementation ## Detailed Implementation Plan ### 1. Transport Interfaces and Types First, we'll define the transport interfaces and types that will be used throughout the system: ```typescript // src/transport/types.ts export interface ConnectionOptions { timeout?: number; retries?: number; metadata?: Record; } export interface TransportStats { latency: number; packetLoss: number; bandwidth: number; // Additional stats } export enum TransportState { DISCONNECTED = 'disconnected', CONNECTING = 'connecting', CONNECTED = 'connected', DISCONNECTING = 'disconnecting', ERROR = 'error' } export interface TransportCapabilities { supportsReliableDelivery: boolean; supportsOrdering: boolean; supportsBroadcast: boolean; supportsMulticast: boolean; // Additional capabilities } export interface ITransport { readonly id: string; readonly state: TransportState; readonly capabilities: TransportCapabilities; connect(options?: ConnectionOptions): Promise; disconnect(): Promise; sendTo(recipient: string, message: any): Promise; getStats(): TransportStats; on(event: string, handler: Function): void; off(event: string, handler?: Function): void; } export interface ITransportPlugin { readonly id: string; readonly version: string; readonly capabilities: TransportCapabilities; initialize(options: any): Promise; createTransport(nodeId: string, config: any): ITransport; // Lifecycle hooks onRegister(): void; onUnregister(): void; } ``` ### 2. Base Transport Abstract Class Next, we'll implement an abstract base class that provides common functionality for transport implementations: ```typescript // src/transport/base-transport.ts export abstract class BaseTransport implements ITransport { protected _id: string; protected _state: TransportState = TransportState.DISCONNECTED; protected _eventEmitter: INetworkEventEmitter; constructor(id: string, eventEmitter?: INetworkEventEmitter) { this._id = id; this._eventEmitter = eventEmitter || new NetworkEventEmitter(); } get id(): string { return this._id; } get state(): TransportState { return this._state; } abstract get capabilities(): TransportCapabilities; abstract connect(options?: ConnectionOptions): Promise; abstract disconnect(): Promise; abstract sendTo(recipient: string, message: any): Promise; abstract getStats(): TransportStats; on(event: string, handler: Function): void { this._eventEmitter.on(event, handler); } off(event: string, handler?: Function): void { this._eventEmitter.off(event, handler); } protected _setState(state: TransportState): void { this._state = state; this._eventEmitter.emit(TransportEvents.STATE_CHANGED, this, state); } } ``` ### 3. Memory Transport Implementation We'll implement an in-memory transport for testing and simulation: ```typescript // src/transport/memory-transport.ts export class MemoryTransport extends BaseTransport { private static _instances: Map = new Map(); private _messageQueue: Map> = new Map(); private _connectionStats: TransportStats; private _simOptions: MemoryTransportSimulationOptions; constructor(id: string, options?: MemoryTransportOptions) { super(id, options?.eventEmitter); this._simOptions = options?.simulationOptions || {}; this._connectionStats = this._createDefaultStats(); // Register instance globally so other memory transports can communicate MemoryTransport._instances.set(id, this); } get capabilities(): TransportCapabilities { return { supportsReliableDelivery: !this._simOptions.packetLoss, supportsOrdering: true, supportsBroadcast: true, supportsMulticast: true }; } async connect(options?: ConnectionOptions): Promise { if (this._state === TransportState.CONNECTED) { return; } this._setState(TransportState.CONNECTING); // Simulate connection delay if (this._simOptions.connectionDelay) { await new Promise(resolve => setTimeout(resolve, this._simOptions.connectionDelay)); } // Simulate connection errors if (this._simOptions.connectionErrorRate && Math.random() < this._simOptions.connectionErrorRate) { this._setState(TransportState.ERROR); throw new Error('Simulated connection error'); } this._setState(TransportState.CONNECTED); } async disconnect(): Promise { if (this._state === TransportState.DISCONNECTED) { return; } this._setState(TransportState.DISCONNECTING); // Simulate disconnection delay if (this._simOptions.disconnectionDelay) { await new Promise(resolve => setTimeout(resolve, this._simOptions.disconnectionDelay)); } this._setState(TransportState.DISCONNECTED); // Cleanup MemoryTransport._instances.delete(this._id); } async sendTo(recipient: string, message: any): Promise { if (this._state !== TransportState.CONNECTED) { throw new Error('Cannot send message: transport not connected'); } // Find recipient instance const recipientTransport = MemoryTransport._instances.get(recipient); if (!recipientTransport) { throw new Error(`Recipient not found: ${recipient}`); } // Clone message to simulate network isolation const messageClone = JSON.parse(JSON.stringify(message)); // Simulate network conditions if (this._simOptions.latency) { await new Promise(resolve => setTimeout(resolve, this._simOptions.latency)); } // Simulate packet loss if (this._simOptions.packetLoss && Math.random() < this._simOptions.packetLoss) { // Message lost, but don't throw - silently drop return; } // Deliver message recipientTransport._receiveMessage(this._id, messageClone); } getStats(): TransportStats { return { ...this._connectionStats }; } // Additional methods for simulation control setSimulationOptions(options: Partial): void { this._simOptions = { ...this._simOptions, ...options }; } private _receiveMessage(sender: string, message: any): void { this._eventEmitter.emit(TransportEvents.MESSAGE_RECEIVED, message, sender); } private _createDefaultStats(): TransportStats { return { latency: this._simOptions.latency || 0, packetLoss: this._simOptions.packetLoss || 0, bandwidth: Number.POSITIVE_INFINITY }; } } ``` ### 4. Transport Manager Implementation Next, we'll implement the TransportManager to handle multiple transport types: ```typescript // src/transport/transport-manager.ts export class TransportManager { private _transports: Map = new Map(); private _plugins: Map = new Map(); private _config: TransportManagerConfig; private _eventEmitter: INetworkEventEmitter; constructor(config?: Partial, eventEmitter?: INetworkEventEmitter) { this._config = { ...this._getDefaultConfig(), ...config }; this._eventEmitter = eventEmitter || new NetworkEventEmitter(); } registerTransport(transport: ITransport): boolean { if (this._transports.has(transport.id)) { return false; } this._transports.set(transport.id, transport); this._eventEmitter.emit(TransportEvents.TRANSPORT_REGISTERED, transport); return true; } removeTransport(transportId: string): boolean { const transport = this._transports.get(transportId); if (!transport) { return false; } this._transports.delete(transportId); this._eventEmitter.emit(TransportEvents.TRANSPORT_UNREGISTERED, transport); return true; } getTransport(transportId: string): ITransport | undefined { return this._transports.get(transportId); } registerPlugin(plugin: ITransportPlugin): boolean { if (this._plugins.has(plugin.id)) { return false; } this._plugins.set(plugin.id, plugin); plugin.onRegister(); this._eventEmitter.emit(TransportEvents.PLUGIN_REGISTERED, plugin); return true; } removePlugin(pluginId: string): boolean { const plugin = this._plugins.get(pluginId); if (!plugin) { return false; } this._plugins.delete(pluginId); plugin.onUnregister(); this._eventEmitter.emit(TransportEvents.PLUGIN_UNREGISTERED, plugin); return true; } getPlugin(pluginId: string): ITransportPlugin | undefined { return this._plugins.get(pluginId); } createTransport(nodeId: string, pluginId: string, config?: any): ITransport | null { const plugin = this._plugins.get(pluginId); if (!plugin) { return null; } try { const transport = plugin.createTransport(nodeId, config); this.registerTransport(transport); return transport; } catch (error) { this._eventEmitter.emit(TransportEvents.TRANSPORT_ERROR, error); return null; } } private _getDefaultConfig(): TransportManagerConfig { return { transportFallbackOrder: [], defaultTransportOptions: {} }; } } ``` ### 5. Transport Plugin Development Kit (PDK) Now, we'll create a plugin development kit to make it easier to develop transport plugins: ```typescript // src/transport/pdk/base-transport-plugin.ts export abstract class BaseTransportPlugin implements ITransportPlugin { readonly id: string; readonly version: string; protected _initialized: boolean = false; constructor(id: string, version: string) { this.id = id; this.version = version; } abstract get capabilities(): TransportCapabilities; abstract createTransport(nodeId: string, config: any): ITransport; async initialize(options: any): Promise { // Base implementation this._initialized = true; } onRegister(): void { // Base implementation } onUnregister(): void { // Base implementation } } // src/transport/pdk/transport-testing.ts export class TransportTester { static async testBasicFunctionality(transport: ITransport): Promise { // Test connection let success = true; try { await transport.connect(); success = success && transport.state === TransportState.CONNECTED; // Test disconnection await transport.disconnect(); success = success && transport.state === TransportState.DISCONNECTED; } catch (error) { return false; } return success; } static async testReliability( sender: ITransport, receiver: ITransport, messageCount: number = 100 ): Promise { // Connect both transports await sender.connect(); await receiver.connect(); // Track received messages let receivedCount = 0; const handler = () => receivedCount++; receiver.on(TransportEvents.MESSAGE_RECEIVED, handler); // Send messages for (let i = 0; i < messageCount; i++) { await sender.sendTo(receiver.id, { test: true, sequence: i }); } // Wait for possible delayed messages await new Promise(resolve => setTimeout(resolve, 1000)); // Cleanup receiver.off(TransportEvents.MESSAGE_RECEIVED, handler); await sender.disconnect(); await receiver.disconnect(); // Return reliability ratio (0-1) return receivedCount / messageCount; } } ``` ### 6. Memory Transport Plugin We'll create a plugin for our memory transport: ```typescript // src/transport/plugins/memory-transport-plugin.ts export class MemoryTransportPlugin extends BaseTransportPlugin { constructor() { super('memory-transport', '1.0.0'); } get capabilities(): TransportCapabilities { return { supportsReliableDelivery: true, supportsOrdering: true, supportsBroadcast: true, supportsMulticast: true }; } createTransport(nodeId: string, config: any): ITransport { return new MemoryTransport(nodeId, config); } } ``` ### 7. Transport Events We'll add transport-specific events: ```typescript // src/transport/events.ts export enum TransportEvents { // Connection events CONNECTING = 'transport:connecting', CONNECTED = 'transport:connected', DISCONNECTING = 'transport:disconnecting', DISCONNECTED = 'transport:disconnected', CONNECTION_ERROR = 'transport:connection-error', // Message events MESSAGE_SENT = 'transport:message-sent', MESSAGE_RECEIVED = 'transport:message-received', MESSAGE_ERROR = 'transport:message-error', // Transport management events STATE_CHANGED = 'transport:state-changed', TRANSPORT_REGISTERED = 'transport:registered', TRANSPORT_UNREGISTERED = 'transport:unregistered', // Plugin events PLUGIN_REGISTERED = 'transport:plugin-registered', PLUGIN_UNREGISTERED = 'transport:plugin-unregistered', // Error events TRANSPORT_ERROR = 'transport:error' } ``` ### 8. Integrate with NetworkNode Finally, we'll update the NetworkNode class to use the transport layer: ```typescript // Updates to NetworkNode class class NetworkNode { // ... existing implementation // Update constructor to accept transport constructor( id: string, level: number, capabilities: NodeCapabilities, transport?: ITransport, config?: NetworkSystemConfig, eventEmitter?: INetworkEventEmitter ) { // ... existing implementation // Set transport if provided if (transport) { this._transport = transport; this._setupTransportEvents(); } } // Add method to set transport setTransport(transport: ITransport): void { if (this._transport) { this._teardownTransportEvents(); } this._transport = transport; this._setupTransportEvents(); } // Update sendMessage to use transport async sendMessage(message: NetworkMessage): Promise { if (!this._transport || this._transport.state !== TransportState.CONNECTED) { throw new Error('Cannot send message: transport not connected or unavailable'); } // Emit event for monitoring this._events.emit(NetworkEvents.MESSAGE_SENT, message, this); // Send via transport if (message.targetId) { await this._transport.sendTo(message.targetId, message); } else { // Handle broadcast or hierarchical routing in later phases await this._routeMessage(message); } } // Add private methods for transport events private _setupTransportEvents(): void { if (!this._transport) return; this._transport.on(TransportEvents.CONNECTED, () => { this._state = NodeState.CONNECTED; this._events.emit(NetworkEvents.NODE_CONNECTED, this); }); this._transport.on(TransportEvents.DISCONNECTED, () => { this._state = NodeState.DISCONNECTED; this._events.emit(NetworkEvents.NODE_DISCONNECTED, this); }); this._transport.on(TransportEvents.MESSAGE_RECEIVED, (message, senderId) => { this._events.emit(NetworkEvents.MESSAGE_RECEIVED, message, this); this._handleIncomingMessage(message); }); } private _teardownTransportEvents(): void { if (!this._transport) return; this._transport.off(TransportEvents.CONNECTED); this._transport.off(TransportEvents.DISCONNECTED); this._transport.off(TransportEvents.MESSAGE_RECEIVED); } } ``` ## Testing Plan 1. **Unit Tests**: - Test ITransport interface implementations - Test MemoryTransport functionality - Test TransportManager operations - Test transport plugins 2. **Integration Tests**: - Test communication between nodes using transports - Test transport fallback strategies - Test plugin discovery and initialization 3. **Performance Tests**: - Test message throughput - Test latency simulation - Test reliability under packet loss ## Implementation Schedule 1. **Week 1**: Implement transport interfaces and base classes 2. **Week 2**: Implement MemoryTransport and TransportManager 3. **Week 3**: Create transport plugin framework 4. **Week 4**: Integrate with NetworkNode and write tests ## Conclusion This plan outlines a comprehensive approach to implementing the Transport Layer (Phase 2) of our network library. By focusing on a plugin-based architecture, we enable easy extension to different transport mechanisms while providing a solid in-memory implementation for testing and simulation.