UNPKG

hap-nodejs

Version:

HAP-NodeJS is a Node.js implementation of HomeKit Accessory Server.

357 lines 13.3 kB
import { EventEmitter } from "events"; import { Socket } from "net"; import { HAPConnection } from "../util/eventedhttp"; /** * @group HomeKit Data Streams (HDS) */ export type PreparedDataStreamSession = { connection: HAPConnection; accessoryToControllerEncryptionKey: Buffer; controllerToAccessoryEncryptionKey: Buffer; accessoryKeySalt: Buffer; port?: number; connectTimeout?: NodeJS.Timeout; }; /** * @group HomeKit Data Streams (HDS) */ export type PrepareSessionCallback = (error?: Error, preparedSession?: PreparedDataStreamSession) => void; /** * @group HomeKit Data Streams (HDS) */ export type EventHandler = (message: Record<any, any>) => void; /** * @group HomeKit Data Streams (HDS) */ export type RequestHandler = (id: number, message: Record<any, any>) => void; /** * @group HomeKit Data Streams (HDS) */ export type ResponseHandler = (error: Error | undefined, status: HDSStatus | undefined, message: Record<any, any>) => void; /** * @group HomeKit Data Streams (HDS) */ export type GlobalEventHandler = (connection: DataStreamConnection, message: Record<any, any>) => void; /** * @group HomeKit Data Streams (HDS) */ export type GlobalRequestHandler = (connection: DataStreamConnection, id: number, message: Record<any, any>) => void; /** * @group HomeKit Data Streams (HDS) */ export interface DataStreamProtocolHandler { eventHandler?: Record<string, EventHandler>; requestHandler?: Record<string, RequestHandler>; } /** * @group HomeKit Data Streams (HDS) */ export declare const enum Protocols { CONTROL = "control", TARGET_CONTROL = "targetControl", DATA_SEND = "dataSend" } /** * @group HomeKit Data Streams (HDS) */ export declare const enum Topics { HELLO = "hello", WHOAMI = "whoami", OPEN = "open", DATA = "data", ACK = "ack", CLOSE = "close" } /** * @group HomeKit Data Streams (HDS) */ export declare enum HDSStatus { SUCCESS = 0, OUT_OF_MEMORY = 1, TIMEOUT = 2, HEADER_ERROR = 3, PAYLOAD_ERROR = 4, MISSING_PROTOCOL = 5, PROTOCOL_SPECIFIC_ERROR = 6 } /** * @group HomeKit Data Streams (HDS) */ export declare const enum HDSProtocolSpecificErrorReason { NORMAL = 0, NOT_ALLOWED = 1, BUSY = 2, CANCELLED = 3, UNSUPPORTED = 4, UNEXPECTED_FAILURE = 5, TIMEOUT = 6, BAD_DATA = 7, PROTOCOL_ERROR = 8, INVALID_CONFIGURATION = 9 } /** * An error indicating a protocol level HDS error. * E.g. it may be used to encode a {@link HDSStatus.PROTOCOL_SPECIFIC_ERROR} in the {@link Protocols.DATA_SEND} protocol. * @group HomeKit Data Streams (HDS) */ export declare class HDSProtocolError extends Error { reason: HDSProtocolSpecificErrorReason; /** * Initializes a new `HDSProtocolError` * @param reason - The {@link HDSProtocolSpecificErrorReason}. * Values MUST NOT be {@link HDSProtocolSpecificErrorReason.NORMAL}. */ constructor(reason: HDSProtocolSpecificErrorReason); } /** * @group HomeKit Data Streams (HDS) */ export type HDSFrame = { header: Buffer; cipheredPayload: Buffer; authTag: Buffer; plaintextPayload?: Buffer; }; /** * @group HomeKit Data Streams (HDS) */ export declare const enum MessageType { EVENT = 1, REQUEST = 2, RESPONSE = 3 } /** * @group HomeKit Data Streams (HDS) */ export type DataStreamMessage = { type: MessageType; protocol: string; topic: string; id?: number; status?: HDSStatus; message: Record<any, any>; }; /** * @group HomeKit Data Streams (HDS) */ export declare const enum DataStreamServerEvent { /** * This event is emitted when a new client socket is received. At this point we have no idea to what * hap session this connection will be matched. */ CONNECTION_OPENED = "connection-opened", /** * This event is emitted when the socket of a connection gets closed. */ CONNECTION_CLOSED = "connection-closed" } /** * @group HomeKit Data Streams (HDS) */ export declare interface DataStreamServer { on(event: "connection-opened", listener: (connection: DataStreamConnection) => void): this; on(event: "connection-closed", listener: (connection: DataStreamConnection) => void): this; emit(event: "connection-opened", connection: DataStreamConnection): boolean; emit(event: "connection-closed", connection: DataStreamConnection): boolean; } /** * DataStreamServer which listens for incoming tcp connections and handles identification of new connections * @group HomeKit Data Streams (HDS) */ export declare class DataStreamServer extends EventEmitter { static readonly version = "1.0"; private state; private static accessoryToControllerInfo; private static controllerToAccessoryInfo; private tcpServer?; private tcpPort?; preparedSessions: PreparedDataStreamSession[]; private readonly connections; private removeListenersOnceClosed; private readonly internalEventEmitter; constructor(); /** * Registers a new event handler to handle incoming event messages. * The handler is only called for a connection if for the give protocol no ProtocolHandler * was registered on the connection level. * * @param protocol - name of the protocol to register the handler for * @param event - name of the event (also referred to as topic. See {@link Topics} for some known ones) * @param handler - function to be called for every occurring event */ onEventMessage(protocol: string | Protocols, event: string | Topics, handler: GlobalEventHandler): this; /** * Removes a registered event handler. * * @param protocol - name of the protocol to unregister the handler for * @param event - name of the event (also referred to as topic. See {@link Topics} for some known ones) * @param handler - registered event handler */ removeEventHandler(protocol: string | Protocols, event: string | Topics, handler: GlobalEventHandler): this; /** * Registers a new request handler to handle incoming request messages. * The handler is only called for a connection if for the give protocol no ProtocolHandler * was registered on the connection level. * * @param protocol - name of the protocol to register the handler for * @param request - name of the request (also referred to as topic. See {@link Topics} for some known ones) * @param handler - function to be called for every occurring request */ onRequestMessage(protocol: string | Protocols, request: string | Topics, handler: GlobalRequestHandler): this; /** * Removes a registered request handler. * * @param protocol - name of the protocol to unregister the handler for * @param request - name of the request (also referred to as topic. See {@link Topics} for some known ones) * @param handler - registered request handler */ removeRequestHandler(protocol: string | Protocols, request: string | Topics, handler: GlobalRequestHandler): this; prepareSession(connection: HAPConnection, controllerKeySalt: Buffer, callback: PrepareSessionCallback): void; private timeoutPreparedSession; private checkTCPServerEstablished; private listening; private onConnection; private handleSessionIdentification; private handleMessageGlobally; private connectionClosed; private checkCloseable; /** * This method will fully stop the DataStreamServer */ destroy(): void; private closed; } /** * @group HomeKit Data Streams (HDS) */ export type IdentificationCallback = (identifiedSession?: PreparedDataStreamSession) => void; /** * @group HomeKit Data Streams (HDS) */ export declare const enum DataStreamConnectionEvent { /** * This event is emitted when the first HDSFrame is received from a new connection. * The connection expects the handler to identify the connection by trying to match the decryption keys. * If identification was successful the PreparedDataStreamSession should be supplied to the callback, * otherwise undefined should be supplied. */ IDENTIFICATION = "identification", /** * This event is emitted when no handler could be found for the given protocol of an event or request message. */ HANDLE_MESSAGE_GLOBALLY = "handle-message-globally", /** * This event is emitted when the socket of the connection was closed. */ CLOSED = "closed" } /** * @group HomeKit Data Streams (HDS) */ export declare interface DataStreamConnection { on(event: "identification", listener: (frame: HDSFrame, callback: IdentificationCallback) => void): this; on(event: "handle-message-globally", listener: (message: DataStreamMessage) => void): this; on(event: "closed", listener: () => void): this; emit(event: "identification", frame: HDSFrame, callback: IdentificationCallback): boolean; emit(event: "handle-message-globally", message: DataStreamMessage): boolean; emit(event: "closed"): boolean; } /** * @group HomeKit Data Streams (HDS) */ export declare const enum HDSConnectionErrorType { ILLEGAL_STATE = 1, CLOSED_SOCKET = 2, MAX_PAYLOAD_LENGTH = 3 } /** * @group HomeKit Data Streams (HDS) */ export declare class HDSConnectionError extends Error { readonly type: HDSConnectionErrorType; constructor(message: string, type: HDSConnectionErrorType); } /** * DataStream connection which holds any necessary state information, encryption and decryption keys, manages * protocol handlers and also handles sending and receiving of data stream frames. * * @group HomeKit Data Streams (HDS) */ export declare class DataStreamConnection extends EventEmitter { private static readonly MAX_PAYLOAD_LENGTH; private socket; private connection?; readonly remoteAddress: string; private state; private accessoryToControllerEncryptionKey?; private controllerToAccessoryEncryptionKey?; private accessoryToControllerNonce; private readonly accessoryToControllerNonceBuffer; private controllerToAccessoryNonce; private readonly controllerToAccessoryNonceBuffer; private frameBuffer?; private readonly hapConnectionClosedListener; private protocolHandlers; private responseHandlers; private responseTimers; private helloTimer?; constructor(socket: Socket); private handleHello; /** * Registers a new protocol handler to handle incoming messages. * The same protocol cannot be registered multiple times. * * @param protocol - name of the protocol to register the handler for * @param protocolHandler - object to be registered as protocol handler */ addProtocolHandler(protocol: string | Protocols, protocolHandler: DataStreamProtocolHandler): boolean; /** * Removes a protocol handler if it is registered. * * @param protocol - name of the protocol to unregister the handler for * @param protocolHandler - object which will be unregistered */ removeProtocolHandler(protocol: string | Protocols, protocolHandler: DataStreamProtocolHandler): void; /** * Sends a new event message to the connected client. * * @param protocol - name of the protocol * @param event - name of the event (also referred to as topic. See {@link Topics} for some known ones) * @param message - message dictionary which gets sent along the event */ sendEvent(protocol: string | Protocols, event: string | Topics, message?: Record<any, any>): void; /** * Sends a new request message to the connected client. * * @param protocol - name of the protocol * @param request - name of the request (also referred to as topic. See {@link Topics} for some known ones) * @param message - message dictionary which gets sent along the request * @param callback - handler which gets supplied with an error object if the response didn't * arrive in time or the status and the message dictionary from the response */ sendRequest(protocol: string | Protocols, request: string | Topics, message: Record<any, any> | undefined, callback: ResponseHandler): void; /** * Send a new response message to a received request message to the client. * * @param protocol - name of the protocol * @param response - name of the response (also referred to as topic. See {@link Topics} for some known ones) * @param id - id from the request, to associate the response to the request * @param status - status indication if the request was successful. A status of zero indicates success. * @param message - message dictionary which gets sent along the response */ sendResponse(protocol: string | Protocols, response: string | Topics, id: number, status?: HDSStatus, message?: Record<any, any>): void; private onSocketData; private decodeHDSFrames; /** * @private file-private API */ decryptHDSFrame(frame: HDSFrame, keyOverwrite?: Buffer): boolean; private decodePayloads; private sendHDSFrame; close(): void; isConsideredClosed(): boolean; private onHAPSessionClosed; private onSocketError; private onSocketClose; } //# sourceMappingURL=DataStreamServer.d.ts.map