hap-nodejs
Version:
HAP-NodeJS is a Node.js implementation of HomeKit Accessory Server.
357 lines • 13.3 kB
TypeScript
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