import { EventEmitter } from "events";
import { SrpServer } from "fast-srp-hap";
import { IncomingMessage, ServerResponse } from "http";
import { AddressInfo, Socket } from "net";
import { CharacteristicValue, Nullable, SessionIdentifier } from "../../types";
/**
 * @group HAP Accessory Server
 */
export type HAPUsername = string;
/**
 * @group HAP Accessory Server
 */
export type EventName = string;
/**
 * Simple struct to hold vars needed to support HAP encryption.
 *
 * @group Cryptography
 */
export declare class HAPEncryption {
    readonly clientPublicKey: Buffer;
    readonly secretKey: Buffer;
    readonly publicKey: Buffer;
    readonly sharedSecret: Buffer;
    readonly hkdfPairEncryptionKey: Buffer;
    accessoryToControllerCount: number;
    controllerToAccessoryCount: number;
    accessoryToControllerKey: Buffer;
    controllerToAccessoryKey: Buffer;
    incompleteFrame?: Buffer;
    constructor(clientPublicKey: Buffer, secretKey: Buffer, publicKey: Buffer, sharedSecret: Buffer, hkdfPairEncryptionKey: Buffer);
}
/**
 * @group HAP Accessory Server
 */
export declare const enum EventedHTTPServerEvent {
    LISTENING = "listening",
    CONNECTION_OPENED = "connection-opened",
    REQUEST = "request",
    CONNECTION_CLOSED = "connection-closed"
}
/**
 * @group HAP Accessory Server
 */
export declare interface EventedHTTPServer {
    on(event: "listening", listener: (port: number, address: string) => void): this;
    on(event: "connection-opened", listener: (connection: HAPConnection) => void): this;
    on(event: "request", listener: (connection: HAPConnection, request: IncomingMessage, response: ServerResponse) => void): this;
    on(event: "connection-closed", listener: (connection: HAPConnection) => void): this;
    emit(event: "listening", port: number, address: string): boolean;
    emit(event: "connection-opened", connection: HAPConnection): boolean;
    emit(event: "request", connection: HAPConnection, request: IncomingMessage, response: ServerResponse): boolean;
    emit(event: "connection-closed", connection: HAPConnection): boolean;
}
/**
 * EventedHTTPServer provides an HTTP-like server that supports HAP "extensions" for security and events.
 *
 * Implementation
 * --------------
 * In order to implement the "custom HTTP" server required by the HAP protocol (see HAPServer.js) without completely
 * reinventing the wheel, we create both a generic TCP socket server and a standard Node HTTP server.
 * The TCP socket server acts as a proxy, allowing users of this class to transform data (for encryption) as necessary
 * and passing through bytes directly to the HTTP server for processing. This way we get Node to do all
 * the "heavy lifting" of HTTP like parsing headers and formatting responses.
 *
 * Events are sent by simply waiting for current HTTP traffic to subside and then sending a custom response packet
 * directly down the wire via the socket.
 *
 * Each connection to the main TCP server gets its own internal HTTP server, so we can track ongoing requests/responses
 * for safe event insertion.
 *
 * @group HAP Accessory Server
 */
export declare class EventedHTTPServer extends EventEmitter {
    private static readonly CONNECTION_TIMEOUT_LIMIT;
    private static readonly MAX_CONNECTION_IDLE_TIME;
    private readonly tcpServer;
    /**
     * Set of all currently connected HAP connections.
     */
    private readonly connections;
    /**
     * Session dictionary indexed by username/identifier. The username uniquely identifies every person added to the home.
     * So there can be multiple sessions open for a single username (multiple devices connected to the same Apple ID).
     */
    private readonly connectionsByUsername;
    private connectionIdleTimeout?;
    private connectionLoggingInterval?;
    constructor();
    private scheduleNextConnectionIdleTimeout;
    address(): AddressInfo;
    listen(targetPort: number, hostname?: string): void;
    stop(): void;
    destroy(): void;
    /**
     * Send an event notification for given characteristic and changed value to all connected clients.
     * If `originator` is specified, the given {@link HAPConnection} will be excluded from the broadcast.
     *
     * @param aid - The accessory id of the updated characteristic.
     * @param iid - The instance id of the updated characteristic.
     * @param value - The newly set value of the characteristic.
     * @param originator - If specified, the connection will not get an event message.
     * @param immediateDelivery - The HAP spec requires some characteristics to be delivery immediately.
     *   Namely, for the {@link Characteristic.ButtonEvent} and the {@link Characteristic.ProgrammableSwitchEvent} characteristics.
     */
    broadcastEvent(aid: number, iid: number, value: Nullable<CharacteristicValue>, originator?: HAPConnection, immediateDelivery?: boolean): void;
    private onConnection;
    private handleConnectionAuthenticated;
    private handleConnectionClose;
    /**
     * This method is to be called when a given {@link HAPConnection} performs a request that should result in the disconnection
     * of all other {@link HAPConnection} with the same {@link HAPUsername}.
     *
     * The initiator MUST be in the middle of a http request were the response was not served yet.
     * Otherwise, the initiator connection might reside in a state where it isn't disconnected and can't make any further requests.
     *
     * @param initiator - The connection that requested to disconnect all connections of the same username.
     * @param username - The username for which all connections shall be closed.
     */
    static destroyExistingConnectionsAfterUnpair(initiator: HAPConnection, username: HAPUsername): void;
}
/**
 * @private
 * @group HAP Accessory Server
 */
export declare const enum HAPConnectionState {
    CONNECTING = 0,// initial state, setup is going on
    FULLY_SET_UP = 1,// internal http server is running and connection is established
    AUTHENTICATED = 2,// encryption is set up
    TO_BE_TEARED_DOWN = 3,// when in this state, connection should be closed down after response was sent out
    CLOSING = 4,// close was called
    CLOSED = 5
}
/**
 * @group HAP Accessory Server
 */
export declare const enum HAPConnectionEvent {
    REQUEST = "request",
    AUTHENTICATED = "authenticated",
    CLOSED = "closed"
}
/**
 * @group HAP Accessory Server
 */
export declare interface HAPConnection {
    on(event: "request", listener: (request: IncomingMessage, response: ServerResponse) => void): this;
    on(event: "authenticated", listener: (username: HAPUsername) => void): this;
    on(event: "closed", listener: () => void): this;
    emit(event: "request", request: IncomingMessage, response: ServerResponse): boolean;
    emit(event: "authenticated", username: HAPUsername): boolean;
    emit(event: "closed"): boolean;
}
/**
 * Manages a single iOS-initiated HTTP connection during its lifetime.
 * @group HAP Accessory Server
 */
export declare class HAPConnection extends EventEmitter {
    /**
     * @private file-private API
     */
    readonly server: EventedHTTPServer;
    readonly sessionID: SessionIdentifier;
    private state;
    readonly localAddress: string;
    readonly remoteAddress: string;
    readonly remotePort: number;
    readonly networkInterface: string;
    private readonly tcpSocket;
    private readonly internalHttpServer;
    private httpSocket?;
    private internalHttpServerPort?;
    private internalHttpServerAddress?;
    lastSocketOperation: number;
    private pendingClientSocketData?;
    private handlingRequest;
    username?: HAPUsername;
    encryption?: HAPEncryption;
    srpServer?: SrpServer;
    _pairSetupState?: number;
    _pairVerifyState?: number;
    private registeredEvents;
    private eventsTimer?;
    private readonly queuedEvents;
    /**
     * If true, the above {@link queuedEvents} contains events which are set to be delivered immediately!
     */
    private eventsQueuedForImmediateDelivery;
    timedWritePid?: number;
    timedWriteTimeout?: NodeJS.Timeout;
    constructor(server: EventedHTTPServer, clientSocket: Socket);
    private debugListenerRegistration;
    addListener(event: string | symbol, listener: (...args: any[]) => void): this;
    removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
    off(event: string | symbol, listener: (...args: any[]) => void): this;
    /**
     * This method is called once the connection has gone through pair-verify.
     * As any HomeKit controller will initiate a pair-verify after the pair-setup procedure, this method gets
     * not called on the initial pair-setup.
     *
     * Once this method has been called, the connection is authenticated and encryption is turned on.
     */
    connectionAuthenticated(username: HAPUsername): void;
    isAuthenticated(): boolean;
    close(): void;
    closeConnectionAsOfUnpair(initiator: HAPConnection): void;
    sendEvent(aid: number, iid: number, value: Nullable<CharacteristicValue>, immediateDelivery?: boolean): void;
    private handleEventsTimeout;
    private writeQueuedEventNotifications;
    /**
     * This will create an EVENT/1.0 notification header with the provided event notification.
     * If currently an HTTP request is in progress the assembled packet will be
     * added to the pending events list.
     *
     * @param notification - The event which should be sent out
     */
    private writeEventNotification;
    enableEventNotifications(aid: number, iid: number): void;
    disableEventNotifications(aid: number, iid: number): void;
    hasEventNotifications(aid: number, iid: number): boolean;
    getRegisteredEvents(): Set<EventName>;
    clearRegisteredEvents(): void;
    private encrypt;
    private decrypt;
    private onHttpServerListening;
    /**
     * This event handler is called when we receive data from a HomeKit controller on our tcp socket.
     * We store the data if the internal http server is not read yet, or forward it to the http server.
     */
    private onTCPSocketData;
    /**
     * This event handler is called when the internal http server receives a request.
     * Meaning we received data from the HomeKit controller in {@link onTCPSocketData}, which then send the
     * data unencrypted to the internal http server. And now it landed here, fully parsed as a http request.
     */
    private handleHttpServerRequest;
    /**
     * This event handler is called by the socket which is connected to our internal http server.
     * It is called with the response returned from the http server.
     * In this method we have to encrypt and forward the message back to the HomeKit controller.
     */
    private handleHttpServerResponse;
    private handleTCPSocketWriteFulfilled;
    private onTCPSocketError;
    private onTCPSocketClose;
    private onHttpServerError;
    private onHttpServerClose;
    private onHttpSocketError;
    private onHttpSocketClose;
    getLocalAddress(ipVersion: "ipv4" | "ipv6"): string;
    private static getLocalNetworkInterface;
}
//# sourceMappingURL=eventedhttp.d.ts.map