import dgram from 'node:dgram'; import { EventEmitter } from 'node:events'; import { type Logger } from 'zapo-js'; type PeerConnectionClass = RTCPeerConnection; type DataChannelClass = RTCDataChannel; /** * The port a web client's relay media rides on. * * A relay answers only on the port it advertises, and the `` blocks carry * a mix. WhatsApp Web calls this one `TRUE_WEB_CLIENT_RELAY_PORT` and 3478 * `FAUX_WEB_CLIENT_RELAY_PORT`, and dials its candidates here rather than on * the advertised port: a relay reached on 3478 completes the handshake and * accepts the uplink, but never forwards the peer's stream back, so the call is * silently one way. */ export declare const TRUE_WEB_CLIENT_RELAY_PORT = 3480; declare enum ConnectionState { None = "None", Connecting = "Connecting", Open = "Open", Closed = "Closed", Failed = "Failed" } interface RelayInfo { id: string; ip: string; port: number; token: string; authToken?: string; rawAuthToken?: Uint8Array; rawToken?: Uint8Array; key: string; relayId: number; name?: string; authTokenId?: string; isFna?: boolean; } interface Connection { state: ConnectionState; peerConnection: PeerConnectionClass | null; channel: DataChannelClass | null; udpSocket: dgram.Socket | null; incomingChannels: DataChannelClass[]; buffer: ArrayBuffer[]; bufferedBytes: number; id: string; relayInfo: RelayInfo; connectionTimeout: NodeJS.Timeout | null; hasReceivedFirstPacket: boolean; localUfrag: string; stableRoutingConnId: bigint; stats: { sentPackets: number; receivedPackets: number; sentBytes: number; receivedBytes: number; }; } export interface WaSctpRelayOptions { readonly logger?: Logger; } export declare class WaSctpRelay extends EventEmitter { private readonly logger; private connections; private relayMap; private stats; private configuring; private globalBuffer; private globalBufferedBytes; private keepaliveTimers; private audioSsrc; private subscriptionSsrc; private selfStreamSsrcs; private peerStreamSsrcs; private selfPid; private peerPid; constructor(options?: WaSctpRelayOptions); setSsrc(ssrc: number): void; setSubscriptionSsrc(ssrc: number): void; setStreamSsrcs(selfSsrcs: number[], peerSsrcs: number[]): void; setParticipantIds(selfPid?: number, peerPid?: number): void; resendSubscriptions(): void; private addRelayCandidate; private modifySdpForRelay; private makeConnectionId; connectToRelay(relayInfo: RelayInfo): Promise; private failConnection; private isConnOpen; private setupUdpRelay; private findConnectionByIpPort; private sendStunAllocateOnOpen; private startKeepalive; private stopKeepalive; private closeConnection; private drainBuffer; private sendCount; private sendToChannel; private pongCount; private rtpRecvCount; private unknownRecvCount; private handleRelayMessage; private isPong; configureRelays(relays: Array<{ ip: string; port: number; token: string; authToken?: string; rawAuthToken?: Uint8Array; rawToken?: Uint8Array; key: string; relayId: number; name?: string; authTokenId?: string; isFna?: boolean; }>): Promise; sendToRelay(ip: string, port: number, data: ArrayBuffer): boolean; private bufferData; broadcast(data: ArrayBuffer): void; hasConnection(): boolean; getConnectedCount(): number; cleanup(): void; } export {};