UNPKG

strophe.js

Version:

Strophe.js is an XMPP library for JavaScript

223 lines 8.54 kB
/** * This file implements the XEP-0114 "Jabber Component Protocol" transport for * Strophe.js, letting a Connection attach to an XMPP server as an external * component (`jabber:component:accept`) over a raw TCP stream. * * It is a streaming transport modelled on {@link Websocket}, not on the * request/response BOSH transport. Unlike a client-to-server stream there is no * SASL, no TLS negotiation and no resource binding: after the stream is opened * the component authenticates with a single SHA-1 handshake (XEP-0114 §3) and * is then CONNECTED. Because it relies on `node:net` and `node:crypto` it is * inherently Node-only and is never included in the browser build. * * The connection is created like this: * * const conn = new Strophe.Connection('tcp://localhost:5347', { protocol: 'component' }); * // jid = the component's own domain; pass = the shared secret * conn.connect('component.example.org', 'the-shared-secret', (status) => { * if (status === Strophe.Status.CONNECTED) { * // send/receive stanzas (stamp `from` under component.example.org) * } * }); */ import { Buffer } from 'node:buffer'; import { type Socket } from 'node:net'; import type Connection from './connection'; import Builder from './builder'; /** * Helper class that handles XEP-0114 external component connections. * * Like {@link Websocket} it is used internally by {@link Connection} to * encapsulate a session and is not meant to be used from user code. Select it * with the `protocol: 'component'` connection option and a `tcp://host:port` * service URL. */ declare class Component { _conn: Connection; strip: string; socket: Socket | null; private _parser; private _streamId; /** Whether the XEP-0114 handshake has completed successfully. */ private _authenticated; /** * Create and initialize a Component object. * @param connection - The Connection that will use this component transport. */ constructor(connection: Connection); /** * Parse the component service URL into a host and port. * * Accepts `tcp://host:port` (the recommended plaintext form) and tolerates a * bare `host:port`. The port defaults to 5347, the conventional component * listener port. */ _serviceUrl(): { host: string; port: number; }; /** * Reset the transport. Called by {@link Connection#reset}. */ _reset(): void; /** * _Private_ function called by Connection.connect * * Opens a TCP socket to the component listener and wires up its callbacks. */ _connect(): void; /** * _Private_ function called by Connection._connect_cb * * The component protocol has no <stream:features> to inspect, so there is * nothing to check here. Kept for interface parity with the other * transports. */ _connect_cb(_bodyWrap: Element): number | void; /** * _Private_ function to handle a successful TCP connection. * Sends the component stream header (XEP-0114 §2). */ _onOpen(): void; /** * The opening `<stream:stream>` header sent to the server. `to` is the * component's own domain, per XEP-0114. */ _streamHeader(): string; /** * A self-closed representation of the stream header, purely for the * `xmlOutput` debug hook (the real header sent on the wire never closes). */ _streamOpenElement(): Element; /** * _Private_ function called when raw bytes arrive on the socket. * Feeds them into the incremental stream parser. * @param chunk - The bytes received from the socket. */ _onData(chunk: Buffer): void; /** * Handle the server's opening stream header. Captures the stream id and * replies with the SHA-1 handshake (XEP-0114 §3). * @param attrs - The attributes of the server's <stream:stream> header. */ _onStreamStart(attrs: Record<string, string>): void; /** * Compute and send the XEP-0114 handshake digest, * `hex( SHA1( STREAM_ID + SHARED_SECRET ) )` in lowercase. * @param streamId - The stream id from the server's stream header. */ _sendHandshake(streamId: string): void; /** * Route a complete inbound stanza. Before the handshake completes this is * the handshake result; afterwards it's ordinary traffic. * @param stanza - A complete top-level stanza element. */ _onStanza(stanza: Element): void; /** * Inspect the server's reply to our handshake. An empty `<handshake/>` * means success and the component is CONNECTED; a `<stream:error/>` (e.g. * `<not-authorized/>`) means the shared secret was wrong. * @param stanza - The first stanza received after sending the handshake. */ _handleHandshakeResult(stanza: Element): void; /** * _Private_ function to handle incoming stanzas once authenticated. * Wraps the stanza and routes it through the normal handler machinery, * exactly as {@link Websocket#_onMessage} does. * @param stanza - A complete top-level stanza element. */ _onMessage(stanza: Element): void; /** * Serialize an element to a string, reusing Strophe's own serializer so * output matches the other transports. */ _serialize(elem: Element): string; /** * _Private_ checks a received stream error and tears the connection down. * @param streamError - The <stream:error/> element. */ _checkStreamError(streamError: Element): void; /** * Handle the closing `</stream:stream>` tag from the server. */ _onStreamEnd(): void; /** * Handle a fatal XML parse error on the inbound stream. * @param error - The parse error. */ _onParseError(error: Error): void; /** * _Private_ function called by Connection.disconnect * Sends an optional last stanza, then the closing stream tag, then * tears down the socket. * @param pres - This stanza will be sent before disconnecting. */ _disconnect(pres?: Element | Builder): void; /** * _Private_ function to disconnect. Just closes the socket. */ _doDisconnect(): void; /** * _Private_ function to close the TCP socket and drop its listeners. */ _closeSocket(): void; /** * _Private_ function to check if the message queue is empty. * @returns True, because stanzas are written to the socket immediately. */ _emptyQueue(): true; /** * _Private_ function to handle the socket closing. */ _onClose(): void; /** * Called on stream start/restart when no authentication mechanism is * offered. Not reachable on the component path (there is no SASL), but kept * for interface parity. * @param callback */ _no_auth_received(callback?: (this: Connection) => void): void; /** * _Private_ timeout handler for a non-graceful disconnection. * Nothing to do for a plain TCP socket. */ _onDisconnectTimeout(): void; /** * _Private_ helper that makes sure all pending requests are aborted. * A component has no in-flight requests, so this is a no-op. */ _abortAllRequests(): void; /** * _Private_ function to handle socket errors. * @param error - The socket error. */ _onError(error: Error): void; /** * _Private_ function called by Connection._onIdle * Serializes queued stanzas and writes them to the socket, stamping a * `from` attribute under the component's domain when one is absent (the * server validates that a component stamps `from`, per XEP-0114). */ _onIdle(): void; /** * Ensure an outgoing stanza carries a `from` attribute under the * component's domain, which XEP-0114 requires the server to validate. * An explicit `from` (e.g. a sub-JID of the component) is left untouched. * @param stanza - The outgoing stanza element. */ _stampFrom(stanza: Element): void; /** * _Private_ part of the Connection.send function for the component transport. * Just flushes the messages that are in the queue. */ _send(): void; /** * Send an xmpp:restart stanza. * * Components never restart their stream, so this only flushes any queued * data. Included for interface parity with the other transports. */ _sendRestart(): void; } export default Component; //# sourceMappingURL=component.d.ts.map