1 | import { EventEmitter } from "events";
|
2 | import { SrpServer } from "fast-srp-hap";
|
3 | import { IncomingMessage, ServerResponse } from "http";
|
4 | import { AddressInfo, Socket } from "net";
|
5 | import { CharacteristicValue, Nullable, SessionIdentifier } from "../../types";
|
6 |
|
7 |
|
8 |
|
9 | export type HAPUsername = string;
|
10 |
|
11 |
|
12 |
|
13 | export type EventName = string;
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | export declare class HAPEncryption {
|
20 | readonly clientPublicKey: Buffer;
|
21 | readonly secretKey: Buffer;
|
22 | readonly publicKey: Buffer;
|
23 | readonly sharedSecret: Buffer;
|
24 | readonly hkdfPairEncryptionKey: Buffer;
|
25 | accessoryToControllerCount: number;
|
26 | controllerToAccessoryCount: number;
|
27 | accessoryToControllerKey: Buffer;
|
28 | controllerToAccessoryKey: Buffer;
|
29 | incompleteFrame?: Buffer;
|
30 | constructor(clientPublicKey: Buffer, secretKey: Buffer, publicKey: Buffer, sharedSecret: Buffer, hkdfPairEncryptionKey: Buffer);
|
31 | }
|
32 | /**
|
33 | * @group HAP Accessory Server
|
34 | */
|
35 | export declare const enum EventedHTTPServerEvent {
|
36 | LISTENING = "listening",
|
37 | CONNECTION_OPENED = "connection-opened",
|
38 | REQUEST = "request",
|
39 | CONNECTION_CLOSED = "connection-closed"
|
40 | }
|
41 |
|
42 |
|
43 |
|
44 | export declare interface EventedHTTPServer {
|
45 | on(event: "listening", listener: (port: number, address: string) => void): this;
|
46 | on(event: "connection-opened", listener: (connection: HAPConnection) => void): this;
|
47 | on(event: "request", listener: (connection: HAPConnection, request: IncomingMessage, response: ServerResponse) => void): this;
|
48 | on(event: "connection-closed", listener: (connection: HAPConnection) => void): this;
|
49 | emit(event: "listening", port: number, address: string): boolean;
|
50 | emit(event: "connection-opened", connection: HAPConnection): boolean;
|
51 | emit(event: "request", connection: HAPConnection, request: IncomingMessage, response: ServerResponse): boolean;
|
52 | emit(event: "connection-closed", connection: HAPConnection): boolean;
|
53 | }
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | export declare class EventedHTTPServer extends EventEmitter {
|
74 | private static readonly CONNECTION_TIMEOUT_LIMIT;
|
75 | private static readonly MAX_CONNECTION_IDLE_TIME;
|
76 | private readonly tcpServer;
|
77 | |
78 |
|
79 |
|
80 | private readonly connections;
|
81 | |
82 |
|
83 |
|
84 |
|
85 | private readonly connectionsByUsername;
|
86 | private connectionIdleTimeout?;
|
87 | private connectionLoggingInterval?;
|
88 | constructor();
|
89 | private scheduleNextConnectionIdleTimeout;
|
90 | address(): AddressInfo;
|
91 | listen(targetPort: number, hostname?: string): void;
|
92 | stop(): void;
|
93 | destroy(): void;
|
94 | /**
|
95 | * Send an event notification for given characteristic and changed value to all connected clients.
|
96 | * If `originator` is specified, the given {@link HAPConnection} will be excluded from the broadcast.
|
97 | *
|
98 | * @param aid - The accessory id of the updated characteristic.
|
99 | * @param iid - The instance id of the updated characteristic.
|
100 | * @param value - The newly set value of the characteristic.
|
101 | * @param originator - If specified, the connection will not get an event message.
|
102 | * @param immediateDelivery - The HAP spec requires some characteristics to be delivery immediately.
|
103 | * Namely, for the {@link Characteristic.ButtonEvent} and the {@link Characteristic.ProgrammableSwitchEvent} characteristics.
|
104 | */
|
105 | broadcastEvent(aid: number, iid: number, value: Nullable<CharacteristicValue>, originator?: HAPConnection, immediateDelivery?: boolean): void;
|
106 | private onConnection;
|
107 | private handleConnectionAuthenticated;
|
108 | private handleConnectionClose;
|
109 | |
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 | static destroyExistingConnectionsAfterUnpair(initiator: HAPConnection, username: HAPUsername): void;
|
120 | }
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | export declare const enum HAPConnectionState {
|
126 | CONNECTING = 0,
|
127 | FULLY_SET_UP = 1,
|
128 | AUTHENTICATED = 2,
|
129 | TO_BE_TEARED_DOWN = 3,
|
130 | CLOSING = 4,
|
131 | CLOSED = 5
|
132 | }
|
133 |
|
134 |
|
135 |
|
136 | export declare const enum HAPConnectionEvent {
|
137 | REQUEST = "request",
|
138 | AUTHENTICATED = "authenticated",
|
139 | CLOSED = "closed"
|
140 | }
|
141 |
|
142 |
|
143 |
|
144 | export declare interface HAPConnection {
|
145 | on(event: "request", listener: (request: IncomingMessage, response: ServerResponse) => void): this;
|
146 | on(event: "authenticated", listener: (username: HAPUsername) => void): this;
|
147 | on(event: "closed", listener: () => void): this;
|
148 | emit(event: "request", request: IncomingMessage, response: ServerResponse): boolean;
|
149 | emit(event: "authenticated", username: HAPUsername): boolean;
|
150 | emit(event: "closed"): boolean;
|
151 | }
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | export declare class HAPConnection extends EventEmitter {
|
157 | |
158 |
|
159 |
|
160 | readonly server: EventedHTTPServer;
|
161 | readonly sessionID: SessionIdentifier;
|
162 | private state;
|
163 | readonly localAddress: string;
|
164 | readonly remoteAddress: string;
|
165 | readonly remotePort: number;
|
166 | readonly networkInterface: string;
|
167 | private readonly tcpSocket;
|
168 | private readonly internalHttpServer;
|
169 | private httpSocket?;
|
170 | private internalHttpServerPort?;
|
171 | private internalHttpServerAddress?;
|
172 | lastSocketOperation: number;
|
173 | private pendingClientSocketData?;
|
174 | private handlingRequest;
|
175 | username?: HAPUsername;
|
176 | encryption?: HAPEncryption;
|
177 | srpServer?: SrpServer;
|
178 | _pairSetupState?: number;
|
179 | _pairVerifyState?: number;
|
180 | private registeredEvents;
|
181 | private eventsTimer?;
|
182 | private readonly queuedEvents;
|
183 | |
184 |
|
185 |
|
186 | private eventsQueuedForImmediateDelivery;
|
187 | timedWritePid?: number;
|
188 | timedWriteTimeout?: NodeJS.Timeout;
|
189 | constructor(server: EventedHTTPServer, clientSocket: Socket);
|
190 | private debugListenerRegistration;
|
191 | addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
192 | removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
193 | off(event: string | symbol, listener: (...args: any[]) => void): this;
|
194 | /**
|
195 | * This method is called once the connection has gone through pair-verify.
|
196 | * As any HomeKit controller will initiate a pair-verify after the pair-setup procedure, this method gets
|
197 | * not called on the initial pair-setup.
|
198 | *
|
199 | * Once this method has been called, the connection is authenticated and encryption is turned on.
|
200 | */
|
201 | connectionAuthenticated(username: HAPUsername): void;
|
202 | isAuthenticated(): boolean;
|
203 | close(): void;
|
204 | closeConnectionAsOfUnpair(initiator: HAPConnection): void;
|
205 | sendEvent(aid: number, iid: number, value: Nullable<CharacteristicValue>, immediateDelivery?: boolean): void;
|
206 | private handleEventsTimeout;
|
207 | private writeQueuedEventNotifications;
|
208 | /**
|
209 | * This will create an EVENT/1.0 notification header with the provided event notification.
|
210 | * If currently an HTTP request is in progress the assembled packet will be
|
211 | * added to the pending events list.
|
212 | *
|
213 | * @param notification - The event which should be sent out
|
214 | */
|
215 | private writeEventNotification;
|
216 | enableEventNotifications(aid: number, iid: number): void;
|
217 | disableEventNotifications(aid: number, iid: number): void;
|
218 | hasEventNotifications(aid: number, iid: number): boolean;
|
219 | getRegisteredEvents(): Set<EventName>;
|
220 | clearRegisteredEvents(): void;
|
221 | private encrypt;
|
222 | private decrypt;
|
223 | private onHttpServerListening;
|
224 | /**
|
225 | * This event handler is called when we receive data from a HomeKit controller on our tcp socket.
|
226 | * We store the data if the internal http server is not read yet, or forward it to the http server.
|
227 | */
|
228 | private onTCPSocketData;
|
229 | /**
|
230 | * This event handler is called when the internal http server receives a request.
|
231 | * Meaning we received data from the HomeKit controller in {@link onTCPSocketData}, which then send the
|
232 | * data unencrypted to the internal http server. And now it landed here, fully parsed as a http request.
|
233 | */
|
234 | private handleHttpServerRequest;
|
235 | |
236 |
|
237 |
|
238 |
|
239 |
|
240 | private handleHttpServerResponse;
|
241 | private handleTCPSocketWriteFulfilled;
|
242 | private onTCPSocketError;
|
243 | private onTCPSocketClose;
|
244 | private onHttpServerError;
|
245 | private onHttpServerClose;
|
246 | private onHttpSocketError;
|
247 | private onHttpSocketClose;
|
248 | getLocalAddress(ipVersion: "ipv4" | "ipv6"): string;
|
249 | private static getLocalNetworkInterface;
|
250 | }
|
251 |
|
\ | No newline at end of file |