import { EventEmitter } from "node:events"; import type { KeyPair } from "../crypto/keypair.js"; export declare const TCP_PACKET_ROUTING_REQUEST = 0; export declare const TCP_PACKET_ROUTING_RESPONSE = 1; export declare const TCP_PACKET_CONNECTION_NOTIFICATION = 2; export declare const TCP_PACKET_DISCONNECT_NOTIFICATION = 3; export declare const TCP_PACKET_PING = 4; export declare const TCP_PACKET_PONG = 5; export declare const TCP_PACKET_OOB_SEND = 6; export declare const TCP_PACKET_OOB_RECV = 7; export declare const TCP_PACKET_ONION_REQUEST = 8; export declare const TCP_PACKET_ONION_RESPONSE = 9; export type TcpRelayState = "disconnected" | "connecting" | "handshake-sent" | "connected" | "closed"; export type TcpRelayOptions = { /** Hostname or IPv4 of the relay server. */ host: string; /** TCP port. Carrier bootstraps typically run on 443, 3389, or 33445. */ port: number; /** Server's DHT public key (the same `pk` field used for the UDP DHT). */ serverPublicKey: Uint8Array; /** Our DHT keypair (= our real keypair in this codebase). */ selfKeyPair: KeyPair; /** Optional debug label (operator-supplied) for log lines. */ label?: string; }; /** Inbound traffic surfaced to the owner. */ export type TcpRelayEvents = { /** Handshake completed; the relay is now usable. */ open: () => void; /** Connection terminated, either by us or by remote. */ close: (reason: string) => void; /** * The relay accepted our ROUTING_REQUEST and assigned a connection_id. * Surfaced for diagnostics; for actual messaging use the `friendOnline` * / `peerData` events which key by the friend's real public key. */ routing: (connectionId: number, friendKey: Uint8Array) => void; /** * Friend (identified by their real pubkey) is now actively connected * to this relay and routing is up. Both sides asked the relay about * each other; we and they can now exchange DATA. */ friendOnline: (friendPublicKey: Uint8Array) => void; /** Friend dropped from the relay. */ friendOffline: (friendPublicKey: Uint8Array) => void; /** * Inbound DATA from a connected friend, already mapped by the client's * internal connection_id → pubkey table. Treat the payload as you * would a UDP datagram from that friend (cookie request / response / * handshake / crypto_data, with the same iveg magic prefix as UDP). */ peerData: (friendPublicKey: Uint8Array, payload: Uint8Array) => void; /** Inbound OOB_RECV — friend's pubkey + payload (used for friend requests). */ oob: (senderPublicKey: Uint8Array, payload: Uint8Array) => void; /** Pong (response to our ping). */ pong: (pingId: bigint) => void; /** Inbound TCP_PACKET_ONION_RESPONSE — the raw onion packet (announce or * onion-data response), routed back through this relay. Treat exactly like a * UDP onion datagram. */ onionResponse: (packet: Uint8Array) => void; }; export declare class TcpRelayClient extends EventEmitter { #private; constructor(opts: TcpRelayOptions); state(): TcpRelayState; /** * Open the TCP connection and perform the handshake. Resolves once the * relay is in "connected" state (handshake response decrypted, session * keys derived). Rejects on any failure during connect or handshake. */ connect(timeoutMs?: number): Promise; /** * Send ROUTING_REQUEST so the relay starts watching for `friendPublicKey`. * Idempotent — calling twice with the same key is a no-op (the relay * would otherwise allocate a duplicate cid). Use `forgetRoute` to * forcibly re-request. */ requestRoute(friendPublicKey: Uint8Array): boolean; /** Returns true if we've received a CONNECTION_NOTIFICATION for this friend. */ hasFriendOnline(friendPublicKey: Uint8Array): boolean; /** Returns true if we've sent a ROUTING_REQUEST for this friend (regardless of online state). */ hasRequestedRoute(friendPublicKey: Uint8Array): boolean; /** * Send a DATA payload to `friendPublicKey` over this relay. Returns * false if the friend hasn't been routed (no ROUTING_RESPONSE yet) or * if the relay says they're offline. Caller should treat false as * "try another transport". */ sendToFriend(friendPublicKey: Uint8Array, payload: Uint8Array, droppable?: boolean): boolean; /** Send a PING; relay echoes it as PONG. ping_id is opaque 8 bytes. */ sendPing(): boolean; /** * Send an onion request THROUGH this relay (toxcore TCP_client.c:: * send_onion_request). `packet` is a create_onion_packet_tcp payload * (createOnionRequest0Tcp) — the relay acts as onion node A, forwards it to * node B over UDP, and routes the onion response back to us over this TCP * connection as TCP_PACKET_ONION_RESPONSE (surfaced via the "onionResponse" * event). This is the NAT-resilient announce / friend-lookup path. */ sendOnionRequest(packet: Uint8Array): boolean; /** Send DATA payload to the friend at `connectionId`. */ sendData(connectionId: number, payload: Uint8Array, droppable?: boolean): boolean; /** Send OOB_SEND (used for delivering friend requests via TCP relay). */ sendOob(receiverPublicKey: Uint8Array, payload: Uint8Array): boolean; close(reason?: string): void; on(event: E, listener: TcpRelayEvents[E]): this; once(event: E, listener: TcpRelayEvents[E]): this; off(event: E, listener: TcpRelayEvents[E]): this; }