signalk-server
Version:
An implementation of a [Signal K](http://signalk.org) server for boats.
221 lines • 6.9 kB
TypeScript
/**
* WASM Socket Manager
*
* Manages UDP and TCP sockets for WASM plugins that need raw network access
* (e.g., radar plugins, NMEA receivers, etc.)
*
* Uses Node.js dgram and net modules, bridged to WASM via FFI
*/
import * as dgram from 'dgram';
import * as net from 'net';
/**
* Buffered datagram for non-blocking receive
*/
interface BufferedDatagram {
data: Buffer;
address: string;
port: number;
timestamp: number;
}
/**
* Pending socket option to apply after bind
*/
interface PendingOption {
type: 'broadcast' | 'multicastTTL' | 'multicastLoopback' | 'joinMulticast' | 'leaveMulticast';
value: boolean | number | {
multicastAddress: string;
interfaceAddress?: string;
};
}
/**
* Managed UDP socket with receive buffer
*/
interface ManagedSocket {
socket: dgram.Socket;
pluginId: string;
bound: boolean;
bindPromise: Promise<number> | null;
receiveBuffer: BufferedDatagram[];
maxBufferSize: number;
multicastGroups: Set<string>;
pendingOptions: PendingOption[];
}
/**
* Socket Manager - singleton for managing plugin sockets
*/
declare class SocketManager {
private sockets;
private nextSocketId;
/**
* Create a new UDP socket
* @param pluginId - Plugin that owns the socket
* @param type - Socket type: 'udp4' or 'udp6'
* @returns Socket ID, or -1 on error
*/
createSocket(pluginId: string, type?: 'udp4' | 'udp6'): number;
/**
* Bind socket to a port
* @param socketId - Socket to bind
* @param port - Port number (0 for any available port)
* @param address - Address to bind to (optional, defaults to all interfaces)
* @returns 0 on success, -1 on error
*/
bind(socketId: number, port: number, address?: string): Promise<number>;
/**
* Join a multicast group
* @param socketId - Socket to use
* @param multicastAddress - Multicast group address (e.g., "239.254.2.0")
* @param interfaceAddress - Interface address to use (optional)
* @returns 0 on success, -1 on error
*/
joinMulticast(socketId: number, multicastAddress: string, interfaceAddress?: string): number;
/**
* Leave a multicast group
* @param socketId - Socket to use
* @param multicastAddress - Multicast group address
* @param interfaceAddress - Interface address (optional)
* @returns 0 on success, -1 on error
*/
leaveMulticast(socketId: number, multicastAddress: string, interfaceAddress?: string): number;
/**
* Set socket options
*/
setMulticastTTL(socketId: number, ttl: number): number;
setMulticastLoopback(socketId: number, enabled: boolean): number;
setBroadcast(socketId: number, enabled: boolean): number;
/**
* Send data via UDP
* @param socketId - Socket to use
* @param data - Data to send
* @param address - Destination address
* @param port - Destination port
* @returns Bytes sent, or -1 on error
*/
send(socketId: number, data: Buffer, address: string, port: number): Promise<number>;
/**
* Receive data from buffer (non-blocking)
* @param socketId - Socket to receive from
* @returns Buffered datagram, or null if buffer empty
*/
receive(socketId: number): BufferedDatagram | null;
/**
* Get number of buffered datagrams
*/
getBufferedCount(socketId: number): number;
/**
* Close a socket
* @param socketId - Socket to close
*/
close(socketId: number): void;
/**
* Close all sockets for a plugin (cleanup on plugin stop)
*/
closeAllForPlugin(pluginId: string): void;
/**
* Get socket statistics
*/
getStats(): {
totalSockets: number;
socketsPerPlugin: Record<string, number>;
};
}
export declare const socketManager: SocketManager;
/**
* Managed TCP socket with line-buffered receive
*/
interface ManagedTcpSocket {
socket: net.Socket;
pluginId: string;
connected: boolean;
connecting: boolean;
receiveBuffer: string[];
rawBuffer: Buffer[];
partialLine: string;
maxBufferSize: number;
error: string | null;
useLineBuffering: boolean;
}
/**
* TCP Socket Manager - manages TCP connections for WASM plugins
*
* Key differences from UDP:
* - Connection-oriented (connect before send)
* - Line-buffered receive (splits on \r\n or \n)
*/
declare class TcpSocketManager {
private sockets;
private nextSocketId;
/**
* Create a new TCP socket
* @param pluginId - Plugin that owns the socket
* @returns Socket ID, or -1 on error
*/
createSocket(pluginId: string): number;
/**
* Connect to a remote host
* @param socketId - Socket to connect
* @param address - Remote host address
* @param port - Remote port
* @returns 0 if connection initiated, -1 on error
*/
connect(socketId: number, address: string, port: number): number;
/**
* Check if socket is connected
* @param socketId - Socket to check
* @returns 1 if connected, 0 if not, -1 if socket not found
*/
isConnected(socketId: number): number;
/**
* Send data over TCP
* @param socketId - Socket to use
* @param data - Data to send
* @returns Bytes sent, or -1 on error
*/
send(socketId: number, data: Buffer): Promise<number>;
/**
* Receive a complete line (non-blocking)
* @param socketId - Socket to receive from
* @returns Complete line without line ending, or null if no complete line available
*/
receiveLine(socketId: number): string | null;
/**
* Receive raw data (non-blocking)
* @param socketId - Socket to receive from
* @returns Raw data buffer, or null if no data available
*/
receiveRaw(socketId: number): Buffer | null;
/**
* Set buffering mode
* @param socketId - Socket to configure
* @param lineBuffering - true for line-buffered (text), false for raw (binary)
* @returns 0 on success, -1 on error
*/
setLineBuffering(socketId: number, lineBuffering: boolean): number;
/**
* Get number of buffered items (lines or raw chunks)
*/
getBufferedCount(socketId: number): number;
/**
* Get last error message
*/
getError(socketId: number): string | null;
/**
* Close a TCP socket
* @param socketId - Socket to close
*/
close(socketId: number): void;
/**
* Close all TCP sockets for a plugin
*/
closeAllForPlugin(pluginId: string): void;
/**
* Get TCP socket statistics
*/
getStats(): {
totalSockets: number;
socketsPerPlugin: Record<string, number>;
};
}
export declare const tcpSocketManager: TcpSocketManager;
export type { BufferedDatagram, ManagedSocket, ManagedTcpSocket };
//# sourceMappingURL=socket-manager.d.ts.map