/**
 * hosting/webSocketFrames — the frame codec the conversation door speaks, and
 * nothing else.
 *
 * Pure bytes in, pure bytes out: no socket, no session, no handler, no port
 * vocabulary. That is what makes it testable the only way protocol code is
 * worth testing — against the byte sequences the specification itself
 * publishes, rather than against a client we also wrote.
 *
 * ── Why this file exists instead of a dependency ─────────────────────────────
 * The alternative was an optional peer dependency carrying a complete
 * implementation. It was rejected for a reason that is about honesty rather
 * than about lines of code: `capabilities` is declared at CONSTRUCTION and is
 * static thereafter, so a host whose conversation door only works when an
 * optional package happens to be installed can only either claim
 * `'conversation'` and then refuse to do it — the library declaring a promise
 * it cannot keep, which is the one thing the capability union forbids — or
 * probe `node_modules` and let feature detection depend on install state, so a
 * deployment that forgot the dependency silently gets a host that quietly does
 * not do conversations. The shipped adapter honours what it declares, always,
 * with nothing to install. That was worth these bytes.
 *
 * ── What is implemented, exactly ─────────────────────────────────────────────
 * The server half of RFC 6455 for a text channel: the handshake, text frames,
 * continuation frames, ping/pong, and close. Payloads are unmasked on the way
 * in (client frames MUST be masked) and written unmasked on the way out (server
 * frames MUST NOT be), which is the asymmetry the RFC requires.
 *
 * ── What is NOT, and how far the verification goes ───────────────────────────
 * No extensions and no compression: `permessage-deflate` is negotiated, and
 * this door never negotiates it, so the RSV bits must always be zero and a peer
 * that sets one is refused. No binary frames — the port carries text, and
 * binary is a capability nobody has minted evidence for. No client role.
 *
 * Verification is: the byte vectors published in RFC 6455 §5.7, which were
 * authored by the specification and not by this repository, plus a live
 * exchange against the platform's own WebSocket client where the runtime has
 * one, plus the conversation conformance suite over a real socket. It is **not**
 * run against the Autobahn test suite, and this file does not claim more
 * coverage than the tests beside it actually execute.
 *
 * Pattern: pure codec. Role: innermost ring — imports nothing from this package.
 */
/// <reference types="node" />
/// <reference types="node" />
/** The frame kinds this door speaks. Numbers, because the wire uses numbers. */
export declare const OPCODE: {
    readonly continuation: 0;
    readonly text: 1;
    readonly binary: 2;
    readonly close: 8;
    readonly ping: 9;
    readonly pong: 10;
};
/**
 * Close codes this door produces. The RFC's own numbers, named — a bare `1009`
 * in a branch is a fact nobody can check without opening the specification.
 */
export declare const CLOSE_CODE: {
    /** Ordinary end: the work is done. */
    readonly normal: 1000;
    /** The host is shutting down. */
    readonly goingAway: 1001;
    /** The peer broke the protocol. */
    readonly protocolError: 1002;
    /** Data this endpoint cannot accept — a binary frame, here. */
    readonly unsupportedData: 1003;
    /** Reserved: never sent on the wire, used only as "we were not told". */
    readonly noStatus: 1005;
    /** Text that is not valid UTF-8. */
    readonly invalidPayload: 1007;
    /** The endpoint's policy ended it — here: the sign-in behind the socket ended. */
    readonly policyViolation: 1008;
    /** Past a declared ceiling. */
    readonly tooBig: 1009;
    /**
     * Something went wrong on THIS side — the RFC's own word for a condition
     * that stopped this endpoint fulfilling the request. Used where the fault is
     * demonstrably not the peer's, so that a close code never blames them for it.
     */
    readonly internalError: 1011;
};
/** One frame, as it came off the wire, already unmasked. */
export interface WebSocketFrame {
    /** Last frame of its message? */
    readonly fin: boolean;
    /** One of {@link OPCODE}. */
    readonly opcode: number;
    /** The unmasked payload. */
    readonly payload: Buffer;
}
/**
 * A peer that broke the protocol, carrying the close code the RFC names for
 * that breakage — so the caller does not have to re-derive which number means
 * what at the point it has to write one.
 */
export declare class FrameProtocolError extends Error {
    readonly closeCode: number;
    constructor(closeCode: number, message: string);
}
/**
 * The `Sec-WebSocket-Accept` value for a client's `Sec-WebSocket-Key`:
 * base64(sha1(key + GUID)). Deterministic, and pinned against the RFC's own
 * worked example.
 */
export declare function acceptKey(clientKey: string): string;
/**
 * The 101 response, as bytes.
 *
 * `protocol` is echoed only when the caller selected one. Echoing a subprotocol
 * the client did not offer would make the client fail the connection, so
 * choosing one is the wire's job (it read the offer) and not this function's.
 */
export declare function handshakeResponse(clientKey: string, protocol?: string): Buffer;
/**
 * One frame, ready to write. **Never masked**: a server that masks its frames
 * is a server the client closes on, per RFC 6455 §5.1.
 */
export declare function encodeFrame(opcode: number, payload: Buffer, fin?: boolean): Buffer;
/** A text frame carrying one whole message. */
export declare function encodeText(text: string): Buffer;
/**
 * A close frame carrying a code and, when there is one, a reason.
 *
 * The reason is truncated to 123 bytes because a control frame's payload may
 * not exceed 125 and the code takes two of them. Truncating a REASON is safe in
 * a way truncating a message never is: it is diagnostic prose about an ending
 * that has already been decided.
 */
export declare function encodeClose(code: number, reason?: string): Buffer;
/** What a close frame said, pulled apart. */
export interface CloseFramePayload {
    /** The peer's code, or `noStatus` when it sent none — which is legal. */
    readonly code: number;
    /** The peer's words, when it sent any. */
    readonly reason?: string;
}
/** Read a close frame's payload. An empty payload is "no status", never an error. */
export declare function decodeClose(payload: Buffer): CloseFramePayload;
/** Is this one of the three control opcodes? */
export declare function isControlFrame(opcode: number): boolean;
/**
 * Turns a stream of TCP chunks into whole frames.
 *
 * Stateful by necessity — a frame arrives in as many pieces as the network
 * feels like, and two frames arrive in one piece just as often. Every branch
 * that gives up does so by throwing a {@link FrameProtocolError} carrying the
 * code to close with, so the layer above never has to invent one.
 */
export declare class FrameReader {
    private buffered;
    private readonly maxFrameBytes;
    /**
     * @param maxFrameBytes The declared ceiling, when there is one. Checked
     * against the length in the HEADER — before the payload is buffered, so an
     * announced 4GB frame costs nothing to refuse.
     */
    constructor(maxFrameBytes?: number);
    /** Feed one chunk; get back every frame that completed. */
    push(chunk: Buffer): WebSocketFrame[];
    /** One frame, or `undefined` when the bytes for a whole one are not here yet. */
    private readOne;
}
/**
 * Decode a whole message's bytes as UTF-8, refusing anything that is not.
 *
 * Strict on purpose (RFC 6455 §8.1): a text frame that is not valid UTF-8 is a
 * protocol violation, and the lenient alternative silently replaces the bad
 * bytes with `U+FFFD` — handing the consumer a string the far side never sent
 * and no way to know it happened.
 */
export declare function decodeText(payload: Buffer): string;
//# sourceMappingURL=webSocketFrames.d.ts.map