From e05a6a957eb8ae289e7910290f9a1341467595dc Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Thu, 15 Oct 2026 12:56:46 -0400 Subject: [PATCH] docs(protocols): second pass over application, misc and the protocol base (#1103) protocol.rst: - give ProtocolBase targets for every member Protocol documents, as grouped stubs linking to the Protocol entries, so the ProtocolBase.* references across the tree resolve; document its own __init_subclass__, and __keywords__ and __length_hint__ under Protocol - drop the FRAME_LAYER_LIMIT versionremoved, a beta-only name, here and in protocol.py Accuracy: - register() names the public Protocol class, as ruled on #1016: put back the wording #1765 changed to ProtocolBase in protocol.py, PCAP and PCAP-NG - HTTP/2 makers: the settings types accepted and the type check otherwise; sid_dep sets PRIORITY - PCAP-NG: EPB timestamps are not in seconds; SPB's interface, timestamp and epoch are fixed; opt_endofopt and nrb_record_end are moved to the end, not ignored; NWK, not NKW - PCAP ts_usec holds nanoseconds in a nanosecond-resolution file Refs #1103 --- docs/source/pcapkit/protocols/protocol.rst | 116 +++++++++++++++++++-- pcapkit/protocols/application/httpv2.py | 11 +- pcapkit/protocols/data/misc/pcap/frame.py | 2 +- pcapkit/protocols/data/misc/pcapng.py | 11 +- pcapkit/protocols/misc/pcap/frame.py | 4 +- pcapkit/protocols/misc/pcapng.py | 20 ++-- pcapkit/protocols/protocol.py | 8 +- pcapkit/protocols/schema/misc/pcapng.py | 6 +- 8 files changed, 142 insertions(+), 36 deletions(-) diff --git a/docs/source/pcapkit/protocols/protocol.rst b/docs/source/pcapkit/protocols/protocol.rst index 266d1cb365..caba2553b7 100644 --- a/docs/source/pcapkit/protocols/protocol.rst +++ b/docs/source/pcapkit/protocols/protocol.rst @@ -64,6 +64,8 @@ Internal Definitions below. :no-value: .. autoattribute:: __proto__ :no-value: + .. autoattribute:: __keywords__ + :no-value: .. autoattribute:: __schema__ :no-value: @@ -104,6 +106,7 @@ Internal Definitions below. .. automethod:: __getitem__ .. automethod:: __contains__ .. automethod:: __index__ + .. automethod:: __length_hint__ .. autoattribute:: _exlayer .. autoattribute:: _exproto @@ -128,12 +131,6 @@ The ``pyshark``, ``scapy`` and ``pypcapfile`` engines dissect with their own parsers, which do not apply the frame's layer bound (:issue:`1609`). The ``dpkt`` toolkit reads what :mod:`dpkt` decodes, which applies neither bound. -.. versionremoved:: 1.5.0 - - ``pcapkit.protocols.protocol.FRAME_LAYER_LIMIT``, now - :data:`pcapkit.utilities.config.FRAME_LAYER_LIMIT`, set with - :envvar:`PCAPKIT_FRAME_LAYER_LIMIT` (:issue:`1726`). - Data Models ----------- @@ -148,6 +145,113 @@ Internal Definitions :no-members: :show-inheritance: + .. automethod:: __init_subclass__ + + :class:`Protocol` inherits the other members of this class, and they are + documented under it above; each group below links to its entries. + + .. py:property:: name + alias + info_name + info + data + length + payload + protocol + protochain + packet + schema + :no-index-entry: + :no-contents-entry: + + :attr:`~Protocol.name`, :attr:`~Protocol.alias`, + :attr:`~Protocol.info_name`, :attr:`~Protocol.info`, + :attr:`~Protocol.data`, :attr:`~Protocol.length`, + :attr:`~Protocol.payload`, :attr:`~Protocol.protocol`, + :attr:`~Protocol.protochain`, :attr:`~Protocol.packet`, + :attr:`~Protocol.schema` + + .. py:method:: id + register + analyze + from_schema + from_data + read + make + unpack + pack + decode + unquote + expand_comp + _read_packet + _get_payload + _make_data + _make_index + _make_payload + _lookup_registry + _lookup_next_layer + _decode_next_layer + _import_next_layer + _parse_next_layer + _get_context + __init__ + __post_init__ + __repr__ + __str__ + __getitem__ + __contains__ + __index__ + __length_hint__ + :no-index-entry: + :no-contents-entry: + + :meth:`~Protocol.id`, :meth:`~Protocol.register`, + :meth:`~Protocol.analyze`, :meth:`~Protocol.from_schema`, + :meth:`~Protocol.from_data`, :meth:`~Protocol.read`, + :meth:`~Protocol.make`, :meth:`~Protocol.unpack`, :meth:`~Protocol.pack`, + :meth:`~Protocol.decode`, :meth:`~Protocol.unquote`, + :meth:`~Protocol.expand_comp`, :meth:`~Protocol._read_packet`, + :meth:`~Protocol._get_payload`, :meth:`~Protocol._make_data`, + :meth:`~Protocol._make_index`, :meth:`~Protocol._make_payload`, + :meth:`~Protocol._lookup_registry`, :meth:`~Protocol._lookup_next_layer`, + :meth:`~Protocol._decode_next_layer`, + :meth:`~Protocol._import_next_layer`, + :meth:`~Protocol._parse_next_layer`, :meth:`~Protocol._get_context`, + :meth:`~Protocol.__init__`, :meth:`~Protocol.__post_init__`, + :meth:`~Protocol.__repr__`, :meth:`~Protocol.__str__`, + :meth:`~Protocol.__getitem__`, :meth:`~Protocol.__contains__`, + :meth:`~Protocol.__index__`, :meth:`~Protocol.__length_hint__` + + .. py:attribute:: __layer__ + __proto__ + __keywords__ + __schema__ + __header__ + _data + _file + _info + _next + _protos + _seekset + _sigterm + _past_layer_limit + __data__ + _exlayer + _exproto + _exctx + :no-index-entry: + :no-contents-entry: + + :attr:`~Protocol.__layer__`, :attr:`~Protocol.__proto__`, + :attr:`~Protocol.__keywords__`, :attr:`~Protocol.__schema__`, + :attr:`~Protocol.__header__`, :attr:`~Protocol._data`, + :attr:`~Protocol._file`, :attr:`~Protocol._info`, + :attr:`~Protocol._next`, :attr:`~Protocol._protos`, + :attr:`~Protocol._seekset`, :attr:`~Protocol._sigterm`, + :attr:`~Protocol._past_layer_limit`, :attr:`~Protocol.__data__`, + :attr:`~Protocol._exlayer`, :attr:`~Protocol._exproto`, + :attr:`~Protocol._exctx` + .. autoclass:: pcapkit.protocols.protocol.ProtocolMeta :no-members: :show-inheritance: diff --git a/pcapkit/protocols/application/httpv2.py b/pcapkit/protocols/application/httpv2.py index 3223515322..beee8b6ac5 100644 --- a/pcapkit/protocols/application/httpv2.py +++ b/pcapkit/protocols/application/httpv2.py @@ -1158,7 +1158,8 @@ def _make_http_headers(self, frame: 'Optional[Data_HeadersFrame]' = None, *, padded: Padded flag, implied by a non-zero ``pad_len``. pad_len: Padding length. excl_dep: Exclusive dependency flag. - sid_dep: Dependency stream identifier. + sid_dep: Dependency stream identifier. Giving one sets the + ``PRIORITY`` flag. weight: Priority weight value. fragment: Header block fragment. padding: Padding octets, truncated or zero-filled to ``pad_len`` @@ -1276,12 +1277,18 @@ def _make_http_settings(self, frame: 'Optional[Data_SettingsFrame]' = None, *, Args: frame: Frame data model. ack: Acknowledge flag. - settings: Settings. + settings: Settings, as raw octets, an + :class:`~pcapkit.corekit.multidict.OrderedMultiDict` or a list of + ``(identifier, value)`` pairs. **kwargs: Arbitrary keyword arguments. Returns: Constructed frame schema and updated flags. + Raises: + ProtocolError: If ``settings`` is not :obj:`bytes`, a :obj:`dict` + or a :obj:`list`, :data:`None` (the default) included. + """ if frame is not None: ack = frame.flags.ACK diff --git a/pcapkit/protocols/data/misc/pcap/frame.py b/pcapkit/protocols/data/misc/pcap/frame.py index 0ebac932c6..18ded196a8 100644 --- a/pcapkit/protocols/data/misc/pcap/frame.py +++ b/pcapkit/protocols/data/misc/pcap/frame.py @@ -20,7 +20,7 @@ class FrameInfo(Data): #: Timestamp seconds. ts_sec: 'int' - #: Timestamp microseconds. + #: Timestamp microseconds, or nanoseconds in a nanosecond-resolution file. ts_usec: 'int' #: Number of octets of packet saved in file. incl_len: 'int' diff --git a/pcapkit/protocols/data/misc/pcapng.py b/pcapkit/protocols/data/misc/pcapng.py index 77f50f00c9..b16ea2fa6d 100644 --- a/pcapkit/protocols/data/misc/pcapng.py +++ b/pcapkit/protocols/data/misc/pcapng.py @@ -486,7 +486,7 @@ class EnhancedPacketBlock(PCAPNG): #: Interface ID. interface_id: 'int' - #: Timestamp (in seconds). + #: Timestamp. timestamp: 'dt_type' #: Timestamp as in UNIX epoch (in seconds). timestamp_epoch: 'Decimal' @@ -543,11 +543,12 @@ def __post_init__(self) -> 'None': #: Protocol chain. protocols: 'str' - #: Interface ID. + #: Interface ID, always 0: the block refers to the section's first + #: interface. interface_id: 'int' - #: Timestamp (in seconds). + #: Timestamp, always the UNIX epoch, as the block carries none. timestamp: 'dt_type' - #: Timestamp as in UNIX epoch (in seconds). + #: Timestamp as in UNIX epoch (in seconds), always 0. timestamp_epoch: 'Decimal' def __init__(self, section_number: 'int', number: 'int', type: 'Enum_BlockType', @@ -853,7 +854,7 @@ def __init__(self, entries: 'OrderedMultiDict[WireGuardKeyLabel, bytes]') -> 'No class ZigBeeNWKKey(DSBSecrets): """Data model for ZigBee NWK Key and ZigBee PANID secrets data.""" - #: AES-128 NKW key. + #: AES-128 NWK key. nwk_key: 'bytes' #: PAN ID. pan_id: 'int' diff --git a/pcapkit/protocols/misc/pcap/frame.py b/pcapkit/protocols/misc/pcap/frame.py index 0f49e59274..95bc5d5f36 100644 --- a/pcapkit/protocols/misc/pcap/frame.py +++ b/pcapkit/protocols/misc/pcap/frame.py @@ -150,11 +150,11 @@ def register(cls, code: 'Enum_LinkType', protocol: 'ModuleDescriptor[ProtocolBas Arguments: code: protocol code as in :class:`~pcapkit.const.reg.linktype.LinkType` protocol: module descriptor or a - :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass + :class:`~pcapkit.protocols.protocol.Protocol` subclass Raises: pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a - class, or not a :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass. + class, or not a :class:`~pcapkit.protocols.protocol.Protocol` subclass. Warns: pcapkit.utilities.warnings.RegistryWarning: If this link type is diff --git a/pcapkit/protocols/misc/pcapng.py b/pcapkit/protocols/misc/pcapng.py index a0c973a879..2fa85936f4 100644 --- a/pcapkit/protocols/misc/pcapng.py +++ b/pcapkit/protocols/misc/pcapng.py @@ -1038,11 +1038,11 @@ def register(cls, code: 'Enum_LinkType', protocol: 'ModuleDescriptor[ProtocolBas Arguments: code: protocol code as in :class:`~pcapkit.const.reg.linktype.LinkType` protocol: module descriptor or a - :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass + :class:`~pcapkit.protocols.protocol.Protocol` subclass Raises: pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a - class, or not a :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass. + class, or not a :class:`~pcapkit.protocols.protocol.Protocol` subclass. Warns: pcapkit.utilities.warnings.RegistryWarning: If this link type is @@ -4920,7 +4920,7 @@ def _make_pcapng_options(self, options: 'Option | list[Schema_Option | tuple[Enu if isinstance(schema, bytes): code = Enum_OptionType.get(int.from_bytes(schema[0:2], self._byte, signed=False), namespace=namespace) - if code == Enum_OptionType.opt_endofopt: # ignore opt_endofopt by default + if code == Enum_OptionType.opt_endofopt: # moved to the end, written once has_endofopt = True continue @@ -4928,7 +4928,7 @@ def _make_pcapng_options(self, options: 'Option | list[Schema_Option | tuple[Enu data_len = len(data) elif isinstance(schema, Schema): code = schema.type - if code == Enum_OptionType.opt_endofopt: # ignore opt_endofopt by default + if code == Enum_OptionType.opt_endofopt: # moved to the end, written once has_endofopt = True continue @@ -4936,7 +4936,7 @@ def _make_pcapng_options(self, options: 'Option | list[Schema_Option | tuple[Enu data_len = len(schema.pack()) else: code, args = cast('tuple[Enum_OptionType, dict[str, Any]]', schema) - if code == Enum_OptionType.opt_endofopt: # ignore opt_endofopt by default + if code == Enum_OptionType.opt_endofopt: # moved to the end, written once has_endofopt = True continue @@ -4963,7 +4963,7 @@ def _make_pcapng_options(self, options: 'Option | list[Schema_Option | tuple[Enu options_list = [] for code, option in options.items(multi=True): - if code == Enum_OptionType.opt_endofopt: # ignore opt_endofopt by default + if code == Enum_OptionType.opt_endofopt: # moved to the end, written once has_endofopt = True continue @@ -6383,7 +6383,7 @@ def _make_nrb_records(self, records: 'Record | list[Schema_NameResolutionRecord for schema in records: if isinstance(schema, bytes): code = Enum_RecordType.get(int.from_bytes(schema[0:2], self._byte, signed=False)) - if code == Enum_RecordType.nrb_record_end: # ignore nrb_record_end by default + if code == Enum_RecordType.nrb_record_end: # moved to the end, written once has_record_end = True continue @@ -6391,7 +6391,7 @@ def _make_nrb_records(self, records: 'Record | list[Schema_NameResolutionRecord data_len = len(data) elif isinstance(schema, Schema): code = schema.type - if code == Enum_RecordType.nrb_record_end: # ignore nrb_record_end by default + if code == Enum_RecordType.nrb_record_end: # moved to the end, written once has_record_end = True continue @@ -6399,7 +6399,7 @@ def _make_nrb_records(self, records: 'Record | list[Schema_NameResolutionRecord data_len = len(schema.pack()) else: code, args = cast('tuple[Enum_RecordType, dict[str, Any]]', schema) - if code == Enum_RecordType.nrb_record_end: # ignore nrb_record_end by default + if code == Enum_RecordType.nrb_record_end: # moved to the end, written once has_record_end = True continue @@ -6425,7 +6425,7 @@ def _make_nrb_records(self, records: 'Record | list[Schema_NameResolutionRecord records_list = [] for code, record in records.items(multi=True): - if code == Enum_RecordType.nrb_record_end: # ignore nrb_record_end by default + if code == Enum_RecordType.nrb_record_end: # moved to the end, written once has_record_end = True continue diff --git a/pcapkit/protocols/protocol.py b/pcapkit/protocols/protocol.py index 5e44b1058d..a5a92c9d4b 100644 --- a/pcapkit/protocols/protocol.py +++ b/pcapkit/protocols/protocol.py @@ -19,12 +19,6 @@ its header is kept as :class:`~pcapkit.protocols.misc.raw.Raw`, where it was parsed with zero-filled fields (:issue:`1170`). -.. versionremoved:: 1.5.0 - - ``pcapkit.protocols.protocol.FRAME_LAYER_LIMIT``, now - :data:`pcapkit.utilities.config.FRAME_LAYER_LIMIT`, set with - :envvar:`PCAPKIT_FRAME_LAYER_LIMIT` (:issue:`1726`). - """ import abc import ast @@ -972,7 +966,7 @@ def register(cls, code: 'int', protocol: 'ModuleDescriptor | Type[ProtocolBase]' Arguments: code: protocol code protocol: module descriptor or a - :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass + :class:`~pcapkit.protocols.protocol.Protocol` subclass Raises: pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a diff --git a/pcapkit/protocols/schema/misc/pcapng.py b/pcapkit/protocols/schema/misc/pcapng.py index d8e8c70812..71ca04a307 100644 --- a/pcapkit/protocols/schema/misc/pcapng.py +++ b/pcapkit/protocols/schema/misc/pcapng.py @@ -1551,9 +1551,9 @@ class EnhancedPacketBlock(BlockType, code=Enum_BlockType.Enhanced_Packet_Block): length: 'int' = UInt32Field(callback=byteorder_callback) #: Interface ID. interface_id: 'int' = UInt32Field(callback=byteorder_callback) - #: Higher 32-bit of timestamp (in seconds). + #: Timestamp (higher 32 bits). timestamp_high: 'int' = UInt32Field(callback=byteorder_callback) - #: Lower 32-bit of timestamp (in seconds). + #: Timestamp (lower 32 bits). timestamp_low: 'int' = UInt32Field(callback=byteorder_callback) #: Captured packet length. captured_len: 'int' = UInt32Field(callback=byteorder_callback) @@ -2317,7 +2317,7 @@ def __init__(self, data: 'str') -> 'None': ... class ZigBeeNWKKey(DSBSecrets, code=Enum_SecretsType.ZigBee_NWK_Key): """Header schema for ZigBee NWK Key and ZigBee PANID secrets data.""" - #: AES-128 NKW key. + #: AES-128 NWK key. key: 'bytes' = BytesField(length=16) #: ZigBee PANID. panid: 'int' = UInt16Field(byteorder='little')