TLS record layer header encoding and decoding (RFC 8446 section 5.1).

Every TLS record — regardless of higher-layer content — opens with a 5-byte record header followed by a fragment of exactly length bytes:

+--------+--------+--------+--------+--------+
|  Type  | Legacy Version  |     Length      |
+--------+--------+--------+--------+--------+
|                                            |
|            Fragment (variable)             |
|                                            |
+--------------------------------------------+

type identifies the record's content (TLS_CONTENT_TYPE) and legacyVersion is a compatibility field frozen at {0x03, 0x01} (TLS 1.0) for the initial ClientHello and at {0x03, 0x03} (TLS 1.2) for every other record — TLS 1.3 negotiates its actual version out-of-band via the supported_versions extension, so this field is not a reliable version indicator (TLS_VERSION lists the assigned constants anyway, for comparison and for protocols that still rely on it).

length is the fragment size in bytes (at most 2^14 + 256 for encrypted records, 2^14 for plaintext ones per the spec, though this coder does not enforce either limit).

This package covers the record header only — v0.0.1 scope is deliberately shallow. The fragment is returned as raw, potentially still-encrypted bytes; parsing handshake messages, alerts, or application data out of it, decompressing, and decrypting are all left to higher layers.

Examples

Round-trip a handshake record

import { assertEquals } from "@std/assert";
import { tlsRecord, TLS_CONTENT_TYPE, TLS_VERSION } from "@binstruct/tls-record";

const coder = tlsRecord();
const fragment = new Uint8Array([0x01, 0x00, 0x00, 0x00]);
const record = {
  contentType: TLS_CONTENT_TYPE.handshake,
  legacyVersion: TLS_VERSION.TLS1_0,
  length: fragment.length,
  fragment,
};

const buffer = new Uint8Array(64);
const written = coder.encode(record, buffer);
const [decoded, read] = coder.decode(buffer.subarray(0, written));

assertEquals(written, read);
assertEquals(decoded.contentType, TLS_CONTENT_TYPE.handshake);
assertEquals(decoded.legacyVersion, TLS_VERSION.TLS1_0);
assertEquals(decoded.fragment, fragment);