Root Protocol¶
pcapkit.protocols.protocol contains
Protocol, the abstract base for a new
protocol stack. A protocol in an existing layer subclasses that layer’s base
instead – Link,
Internet,
Transport or
Application (Customisation & Extensions).
The built-in families, those bases included, derive from
ProtocolBase, whose metaclass is
ProtocolMeta, both under
Internal Definitions.
Changed in version 1.5.0: Constructing a protocol with a keyword that none of its signatures
declares raises UnsupportedCall,
where it was discarded (#617). A next layer captured shorter than
its header is kept as Raw, where it
was parsed with zero-filled fields (#1170).
- class pcapkit.protocols.protocol.Protocol[_PT: Data, _ST: Schema](file=None, length=None, **kwargs)[source]¶
Bases:
ProtocolBase,Generic[_PT,_ST]User-facing abstract base class for third-party protocols.
Inherit it directly only to create a new protocol stack; a new protocol in an existing layer subclasses that layer’s base class instead; see Customisation & Extensions. The built-in protocol families do not derive from this class but from
ProtocolBase, whose metaclass isProtocolMeta.Changed in version 1.3.0: The built-in protocol families derive from
ProtocolBase, so a built-in protocol is not an instance of this class, where every one was; and a subclass is registered inpcapkit.protocols.__proto__when it is defined.- property info_name: str¶
Key the enclosing layer’s data model holds
infounder.
- property info: _PT¶
Parsed data model of current instance.
- property payload: ProtocolBase¶
Payload of current instance.
- property protochain: ProtoChain¶
Protocol chain of current instance.
Note
NoPayloadhas no chain and narrows this toNone;_decode_next_layer()passes it on asbasis, whichProtoChainaccepts.
- property packet: Packet¶
Packet data of the protocol.
Note
The split takes
self.lengthas the length of the octets preceding the payload, and the payload as running to the end of the buffer: a header followed by its payload.A protocol laid out otherwise overrides this, or its header eats the payload and the payload is
b''.PCAPNGdoes: itslengthis the wire’s Block Total Length, and the captured octets sit ahead of the option list and the trailing length field. The payload matters becauseProtocol.__init__()injects it into every parsed_info, which the dumpers write out.
- property context: ContextRegistry¶
Caller supplied parsing context.
See also
pcapkit.corekit.contextfor what this channel is for, andself._get_contextfor how a protocol implementation reaches its own entry.
- classmethod id()¶
Index ID of the protocol.
- classmethod register(code, protocol)¶
Register a new protocol class.
Notes
The fully qualified class name of the new protocol class should be
{protocol.module}.{protocol.name}.- Parameters:
code (
int) – protocol codeprotocol (
ModuleDescriptor|Type[ProtocolBase]) – module descriptor or aProtocolBasesubclass
- Raises:
pcapkit.utilities.exceptions.RegistryError – If
protocolis not a class, or not aProtocolBasesubclass.- Warns:
pcapkit.utilities.warnings.RegistryWarning– Ifcodeholds a different entry, naming the displaced one and its replacement. An unresolvedModuleDescriptorincumbent counts as different from the class it names.
Note
As for
register_protocol, handing back the entry stored undercode– the same class object, or an equalModuleDescriptor– is a silent no-op that keeps the stored entry (#1364). The comparison resolves nothing, so a stored descriptor stays deferred.A descriptor equal to the one
codeshipped with restores that shipped object, unresolved, so undoing an override leaves the entry as shipped (#1504); see_next_layer_entry(), which every layer’sregistershares.
- classmethod analyze(proto, payload, **kwargs)¶
Analyse packet payload.
- Parameters:
- Return type:
- Returns:
Parsed payload as a
ProtocolBaseinstance.
- classmethod from_schema(schema)¶
Create protocol instance from schema.
- classmethod from_data(data, **kwargs)¶
Create protocol instance from data.
datamay be thedictthatInfo.to_dictreturns, which carries the metadata the rebuild reads:__next_name__and__next_type__, which the payload is dispatched on,__short_read__and__short_width__, and, forIPv6, the extension header chain under__exthdr__. A hand-writtendictwithout them rebuilds no payload (nor IPv6 extension header) and cuts no short read back; nothing is guessed from its other keys (see_make_payload(), #2003).A header the capture cut short, as
__short_read__records, is cut back and read at the width__short_width__records, so the rebuild parses the octets captured as the capture did (#2703): it holds the values its parse read, not thosemake()fills in past the cut (#2761), and theRawnext layer that parse left (#2717). Inside a payload_make_payload()rebuilds, which gives only its octets, the header made is read instead.- Parameters:
- Return type:
- Returns:
Protocol instance.
- Raises:
UnsupportedCall – If any of
kwargsmatches no parameter of the protocol, as for a direct construction.
- abstractmethod read(length=None, **kwargs)¶
Read (parse) packet data.
- abstractmethod make(**kwargs)¶
Make (construct) packet data.
- Parameters:
**kwargs (
Any) – Arbitrary keyword arguments.- Return type:
_ST- Returns:
Curated protocol schema data.
Note
The
**kwargsabsorbs the keywordsProtocol.__post_init__hands to the parse as well as the construction, so an implementation need not declare every keyword it is called with. A caller’s keyword that no signature declares still raisesUnsupportedCallfromProtocol.__init__(#617).Warning
Calling this method directly is not checked, and discards an undeclared keyword silently. The check lives in
Protocol.__init__, the one place the keywords converge, so it coversSomeProtocol(...)and itspack(), but notobject.__new__(cls).make(**kwargs), asHTTP.makecalls its versioned implementation. Construct through the constructor to get the check.
- unpack(length=None, **kwargs)¶
Unpack (parse) packet data.
- Parameters:
- Return type:
_PT- Returns:
Parsed packet data.
Notes
The special keyword argument
__packet__passes the global packet data to underlying methods, for when the current instance does not have it.A
self.__header__already set, byfrom_schema()or by thepack()call of__post_init__(), is kept, unless it holds rawbyteswhere parsing its packed octets yields a schema – e.g. a raw option given tomake(), directly or inside a data model – whichread()cannot consume; it is then replaced by the parsed one (#1312).A header
from_data()rebuilds from a short read is parsed from the octets captured, its warnings discarded, and given its data model’s__short_read__beforeread()runs, as the record of a cut those octets may not show (#2761).- Raises:
ProtocolError – If the made header holds raw items and its packed octets do not parse, either as a schema or by
read(). The message carries the original error’s, which is also chained as__cause__.
Changed in version 1.6.0: A raw item that
make()takes from inside a data model, such as the onefrom_data()passes on, is replaced too, rather than reachingread()(#2725).
- pack(**kwargs)¶
Pack (construct) packet data.
- Parameters:
**kwargs (
Any) – Arbitrary keyword arguments.- Return type:
- Returns:
Constructed packet data.
Notes
The special keyword argument
__packet__passes the global packet data to underlying methods, for when the current instance does not have it.The octets are built from
kwargsalone, throughmake(); the instance’s state is not read, so a bareSomeProtocol(...).pack()returns a default header, not the instance’s octets, whichdataholds.Nor is that state written. Once the instance is parsed or constructed, the header is made on a shallow copy (see
_packing_target()), soschema,infoand anythingmake()sets, such asTCP.connection, still describe that packet. Only the call__post_init__()makes to construct the instance keeps the header, forunpack()to read back.When
from_data()rebuilds a header the capture cut short, that call cuts it back to the octets captured, through__short_read__andSchema._cut_short_read(#2703).__post_init__()then drops that header, sounpack()parses the octets back and the rebuild holds the values its parse read, not thosemake()filled in past the cut (#2761).Changed in version 1.5.0: Calling it no longer replaces the instance’s
__header__, which leftschemadisagreeing withinfo(#1769).
- static decode(byte, *, encoding=None, errors='strict')¶
-
Should decoding fail using
encoding, the method will try again decoding thebytesas'unicode_escape'with'replace'for error handling.See also
The method is a wrapping function for
bytes.decode().- Parameters:
byte (
bytes) – Source bytestring.encoding (
str|None) – The encoding with which to decode thebytes. If not provided,pcapkitwill first try detecting its encoding usingchardet. The fallback encoding is UTF-8.errors (
Literal['strict','ignore','replace']) – The error handling scheme to use for the handling of decoding errors. The default is'strict'meaning that decoding errors raise aUnicodeDecodeError. Other possible values are'ignore'and'replace'as well as any other name registered withcodecs.register_error()that can handleUnicodeDecodeError.
- Return type:
- static unquote(url, *, encoding='utf-8', errors='replace')¶
Unquote URLs into readable format.
Should decoding fail, the method will try again replacing
'%'with'\x'then decoding theurlas'unicode_escape'with'replace'for error handling.See also
This method is a wrapper function for
urllib.parse.unquote().- Parameters:
url (
str) – URL string.encoding (
str) – The encoding with which to decode thebytes.errors (
Literal['strict','ignore','replace']) – The error handling scheme to use for the handling of decoding errors. The default is'replace', which substitutes a replacement marker for each undecodable sequence. Other possible values are'strict', under which decoding errors raise aUnicodeDecodeError, and'ignore', as well as any other name registered withcodecs.register_error()that can handleUnicodeDecodeError.
- Return type:
- static resolve_index(name, default=None, *, namespace, reversed=False)¶
Resolve a name for an enumeration field of
make().A field of
make()that holds an enumeration takes a member or anintcode, and refuses a name (#2594). This resolves a name against anamespacegiven explicitly, so that its result can be passed on:>>> from pcapkit.const.reg.ethertype import EtherType >>> from pcapkit.protocols.link.ethernet.protocol import Ethernet >>> code = Ethernet.resolve_index('Address_Resolution_Protocol', ... namespace=EtherType) >>> Ethernet(type=code).info.type <EtherType.Address_Resolution_Protocol: 2054>
- Parameters:
name (
str|int|IntEnum|aenum.IntEnum) – a member name; a member or anintis returned as it is, formake()to resolvedefault (
int|None) – the code to return whennameis not innamespacenamespace (
dict[str,int] |dict[int,str] |Type[IntEnum] |Type[aenum.IntEnum]) – the enumerationnamenames a member of, or adictof codes and namesreversed (
bool) – ifnamespaceis adictof names to codes, rather than of codes to names
- Return type:
- Returns:
The member
namenames, for an enumerationnamespace; the code it names, for adict; elsedefault.- Raises:
ProtocolNotImplemented – If
nameis astrthat is not innamespaceanddefaultisNone.
- static expand_comp(value)¶
Expand protocol class to protocol name.
The method is used to expand protocol class to protocol name, in the following manner:
If
valueis a protocol instance, the method will return the protocol class, and the protocol names in upper case obtained fromProtocol.id.If
valueis a protocol class, the method will return the protocol class itself, and the protocol names in upper case obtained fromProtocol.id.If
valueisstr, the method will attempt to search for the existing registered protocol class withProtocolBase.get_protocol()and follow step 2; otherwise, return the value in upper case alone.
- Parameters:
value (
str|ProtocolBase|Type[ProtocolBase]) – Protocol class or name.- Return type:
- __layer__: Literal['Link', 'Internet', 'Transport', 'Application'] | None¶
Layer of protocol, can be one of
Link,Internet,TransportandApplication. For example, the layer ofEthernetisLink. However, certain protocols are not in any layer, such asRaw, and thus its layer isNone.
- __proto__: DefaultDict[int, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]¶
Protocol index mapping for decoding the next layer; see
self._decode_next_layerandself._import_next_layer. Each value is aModuleDescriptornaming the module and class, or aProtocolBasesubclass.
- __keywords__: frozenset[str] | None¶
Construction keywords this protocol takes out of
**kwargsby name rather than declaring as a parameter, asIPv6_Ext.readdoes withalias._declared_keywords()reads signatures, which miss such a name, so the construction check of__init__()accepts only those listed here, unioned over the MRO. Prefer a declared parameter, which also documents the keyword (#617).Noneskips the check, for a dispatcher whose real signature is chosen at call time:HTTP.makedeclares onlyversionand forwards the rest toHTTPv1.makeorHTTPv2.make. A protocol that skips the check discards an unknown keyword silently. Unlike a set,Noneis not inherited, soHTTPv1andHTTPv2, which declare their keywords in full, stay checked.
- __own_make_keywords__: bool¶
Whether the parameters of this class’s own
make()are accepted only while thatmakeis the one in use. By default_declared_keywords()takes everymakein the MRO. A base whose subclasses overridemakewithout forwarding sets this, so its keywords are refused for them rather than accepted and dropped, asIPv6_Extdoes forlenanddata(#2286). Not inherited, and__keywords__and the other construction methods are unaffected.
- _read_packet(length=None, *, header=None, payload=None, discard=False)¶
Read raw packet data.
- Overloads:
- Parameters:
- _get_payload()¶
Get payload from
self.__header__.- Return type:
- Returns:
Payload of
self.__header__asbytes.
See also
This is a wrapper function for
pcapkit.protocols.schema.Schema.get_payload().
- classmethod _make_data(data)¶
Create key-value pairs from
datafor protocol construction.
- _make_index(value, namespace, *, bits, name, alias=None)¶
Resolve the code given for an enumeration field of
make().The field takes a member of
namespaceor anintcode, and either resolves withnamespace’sget(). A name is refused rather than looked up, so a caller holding one resolves it first, withresolve_index()(#2594). The code is checked as_make_uint()checks an integer, so aboolpasses only for a one-bit field (#2617): the field’s width decides what is refused, not the enumeration’s range.- Parameters:
value (
Any) – the value given for the fieldnamespace (
Type[_ET]) – the enumeration the field holdsbits (
int) – width of the field, in bitsname (
str) – name of the field, for the error messagealias (
str|None) – prefix of the error message, for a caller whosealiasraises beforeread()sets it;aliasby default
- Return type:
_ET- Returns:
What
namespace’sget()resolvesvalueto. For most registries that includes an unassigned code, as theUnassignedorReservedmember their_missing_builds. WheregetraisesValueErrorfor a code the field carries, as a closed enumeration does, the code itself comes back as anint, so that the field is rebuilt as captured.- Raises:
ProtocolError – If
valueis not anint(a name among them), is aboolfor a field wider than one bit, is negative, or does not fit inbitsbits. The message namesalias.
Changed in version 1.6.0: Takes the enumeration and the width of the field, in place of the
default,namespace,reversedandpackarguments, refuses a code the field cannot carry, and refuses a name rather than resolving it against an enumeration inferred from the calling method’s frame (#2594).
- classmethod _make_payload(data)¶
Create payload from
datafor protocol construction.The payload’s type and name are
__next_type__and__next_name__. If either is missing orNone, ordataholds nothing under__next_name__, the payload is aNoPayload, as for a protocol with no next layer; otherwiseProtocol.from_databuilds it.Info.to_dictcarries both keys, sodatarebuilt from such adictdispatches as the info did. A hand-writtendictmust carry them too, as it must__short_read__and, for IPv6,__exthdr__: the payload is never guessed from the other keys ofdata(#2003).The payload is built one layer further into the frame, as
_parse_next_layer()counts it, so a rebuild stops atFRAME_LAYER_LIMITwhere the parse did (#1610). The payload’s parse reports nothing, the limit included: this protocol’s own parse goes over the same octets, so the rebuilt frame reports each warning, and each error a next-layer fallback absorbs, once, as the parsed one did (#2711).- Parameters:
data (
Data) – protocol data- Return type:
- Returns:
Payload for protocol construction.
- _packing_target()¶
Return the instance that
pack()makes its header on.- Return type:
- Returns:
The instance itself while it is being constructed, i.e. before
__post_init__()has set itsinfo, since itsunpack()reads the made header back; a shallow copy of it otherwise, so that neither that header nor an attribute thatmake()sets is left on the instance (#1769).
Note
A
pack()override that does not call this one has to build on this target too, asFrame.packandPCAPNG.packdo. The copy is shallow, so amake()that mutates a container in place still reaches the instance’s.
- _read_unpack(size=1, *, signed=False, lilendian=False, quiet=False)¶
Read bytes and unpack for integers.
- Parameters:
- Return type:
- Returns:
Unpacked data upon success
- Raises:
StructError – If the buffer is empty, whatever
quietsays, or if fewer thansizeoctets were read, withoutquiet.
- _read_octets(data, pos=0, *, size, what)¶
Read exactly
sizeoctets out ofdataatpos.A plain slice comes back short past the end of
data, which would let a truncated field parse rather than fail.- Parameters:
- Return type:
- Returns:
The
sizeoctets atpos.- Raises:
ProtocolError – If fewer than
sizeoctets remain frompos. The message namesalias.
Added in version 1.6.0.
- _read_uint(data, pos=0, *, size, what, lilendian=False)¶
Read a
size-octet unsigned integer out ofdataatpos._read_unpack()reads the file; this reads a buffer already in hand. The inverse is_make_pack(), not_make_uint(), which checks a value and packs nothing.- Parameters:
- Return type:
- Returns:
The integer.
- Raises:
ProtocolError – If fewer than
sizeoctets remain frompos, as_read_octets()raises it.
Added in version 1.6.0.
- static _read_sint(value, bits)¶
Read
value, an unsignedbits-bit field, as a two’s-complement one.It takes the unsigned integer a field has already read, such as a
BitFieldsub-field, rather than a buffer.- Parameters:
- Return type:
- Returns:
The signed value the same bits denote.
Added in version 1.6.0.
- _read_vector(data, pos=0, *, size=1, what)¶
Read a length-prefixed vector out of
data.The vector is a
size-octet unsigned big-endian length, then that many octets, as the variable-length vectors of TLS’s presentation language are (RFC 9846 Section 3.4).- Parameters:
- Return type:
- Returns:
The vector’s octets, and the offset just past them.
- Raises:
ProtocolError – If the length prefix, or the octets it counts, run past the end of
data. The message namesalias.
Added in version 1.6.0.
- _read_whole_vector(data, *, size=1, what)¶
Read the one length-prefixed vector that
dataholds.The vector is read as
_read_vector()reads it from offset zero, and has to end wheredatadoes.- Parameters:
- Return type:
- Returns:
The vector’s octets.
- Raises:
ProtocolError – If the vector runs past the end of
data, or octets follow it. The message namesalias.
Added in version 1.6.0.
- _read_uints(data, *, size=1, what)¶
Read
dataas a run ofsize-octet unsigned big-endian integers.- Parameters:
- Return type:
- Returns:
The integers, in order.
- Raises:
ProtocolError – If the length of
datais not a multiple ofsize, whose trailing octets would otherwise be padded out when the list is made again. The message namesalias.
Added in version 1.6.0.
- classmethod _make_pack(integer, *, size=1, signed=False, lilendian=False)¶
Pack integers to bytes.
- _make_octets(value, *, size, name, alias=None)¶
Check that
valueis exactlysizeoctets.The octets
_read_octets()reads are written as they are, so their size is all there is to check.- Parameters:
- Return type:
- Returns:
valueasbytes.- Raises:
ProtocolError – If
valueis notbytesorbytearray, or is notsizeoctets long. The message namesalias.
Added in version 1.6.0.
- classmethod _fill_short_read(value, *, size, model, field, offset=0)¶
Zero-fill the octets of
valuethat a capture cut short.A model parsed from a capture cut short records, in its
__short_read__, the field of__schema__the capture ended inside and the octets of it present. A padding field keeps only those octets, where the other fields read the rest as zeros, so a value read at or past the cut comes back short. Zero-filled, it rebuilds as the rest of the header does, and the rebuild is cut back to what was captured. A value of any other width is handed back for_make_octets()to refuse.- Parameters:
- Return type:
- Returns:
valuezero-filled tosizewhere it is exactly the octets the cut kept of it; otherwisevalueitself.
Added in version 1.6.0.
- _make_uint(value, *, bits, name, alias=None)¶
Check that
valueis an unsigned integer that fits inbitsbits.A
boolpasses only for a one-bit field, so that a flag given for a wider field is refused rather than read as0or1.- Parameters:
- Return type:
- Returns:
valueas a plainint.- Raises:
ProtocolError – If
valueis not anint, is aboolfor a field wider than one bit, is negative, or does not fit inbitsbits. The message namesalias.
Added in version 1.6.0.
- _make_sint(value, *, bits, name, alias=None, allow_unsigned=False)¶
Check that
valueis a signed integer that fits inbitsbits.The inverse of
_read_sint(). Aboolis refused whateverbitsis, since no signed field holds a flag.- Parameters:
value (
Any) – the value given for the fieldbits (
int) – width of the field, in bitsname (
str) – name of the field, for the error messagealias (
str|None) – prefix of the error message, for a caller whosealiasraises beforeread()sets it or is not the prefix its messages carry;aliasby defaultallow_unsigned (
bool) – also accept the unsigned spelling of the field’sbitsbits, i.e. up to2 ** bits - 1, for a field whose specification spells one value both ways, as a sentinel written-1and0xFF...F; both denote the same bits
- Return type:
- Returns:
The unsigned integer whose
bitsbits denotevaluein two’s complement.- Raises:
ProtocolError – If
valueis not anint, is abool, or does not fit inbitsbits as two’s complement (or, withallow_unsigned, as an unsigned integer either). The message namesalias.
Added in version 1.6.0.
- static _uint_size(value, *, minimum=0)¶
Count the octets a non-negative integer needs.
value.bit_length()is rounded up to whole octets:// 8alone floors, and counts one octet too few for a width that is not a multiple of eight.- Parameters:
- Return type:
- Returns:
The octets
valueneeds, and at leastminimum.
Added in version 1.6.0.
- classmethod _make_vector(octets, *, size=1)¶
Write
octetsas a length-prefixed vector.The inverse of
_read_vector(): asize-octet unsigned big-endian length, packed by_make_pack(), thenoctets.- Parameters:
- Return type:
- Returns:
The length prefix followed by
octets.- Raises:
StructError – If the length of
octetsdoes not fit insizeoctets.
Added in version 1.6.0.
- classmethod _make_uints(values, *, size=1)¶
Write
valuesas a run ofsize-octet unsigned big-endian integers.The inverse of
_read_uints(), each value packed by_make_pack().- Parameters:
- Return type:
- Returns:
The packed integers, concatenated in order.
- Raises:
StructError – If a value is negative, or does not fit in
sizeoctets.
Added in version 1.6.0.
- _read_mac_addr(addr)¶
Read a MAC address, an EUI-64 one included.
- Parameters:
addr (
bytes) – the address octets- Return type:
- Returns:
Colon (
:) separated hex encoded address.
Added in version 1.6.0.
- _make_mac_addr(addr, *, size=6, name='MAC address', alias=None)¶
Make a MAC address, or an EUI-64 one with
size=8.The inverse of
_read_mac_addr().- Parameters:
addr (
str|bytes|bytearray) –:- or--separated hex encoded addresssize (
int|None) – octets in the address, orNonefor any number of them, none includedname (
str) – name of the address, for the error messagealias (
str|None) – prefix of the error message, for a caller whosealiasraises beforeread()sets it or is not the prefix its messages carry;aliasby default
- Return type:
- Returns:
The address octets.
- Raises:
ProtocolError – If
addris not astr,bytesorbytearray(aboolincluded), or is not a:- or--separated hex encoded address ofsizeoctets. The message namesalias.
Added in version 1.6.0.
- static _lookup_registry(registry, code)¶
Look up a dispatch registry entry without recording a miss.
- Parameters:
registry (
DefaultDict[Any,_VT]) – dispatch registry to read, i.e.self.__proto__or one of the per-protocol__option__/__chunk__/__block__family. Passed in rather than read from the class, so that a caller reaching the registry through an instance keeps doing so.code (
Any) – registry key to look up, i.e. the wire code being dispatched on
- Return type:
_VT- Returns:
The entry registered for
code, or the fallbackregistrydeclares whencodeis not registered.
Important
Each of these registries is a
collections.defaultdicton a class attribute, shared process-wide, soregistry[code]would insert every code it misses: one packet with an unrecognised code would grow the registry permanently. The entry buys nothing, costs a spurious “already registered” warning on the next genuineregisterof that code, and makes “is this code registered?” depend on what has been parsed, so the fallback is read from the default factory directly.
- static _lookup_next_layer(registry, proto)¶
Look up the protocol class registered for a next layer code.
- Parameters:
registry (
DefaultDict[int,ModuleDescriptor[ProtocolBase] |Type[ProtocolBase]]) – next layer protocol registry, i.e.self.__proto__. Passed in rather than read from the class, so that a caller reaching the registry through an instance keeps doing so.proto (
int) – next layer protocol index
- Return type:
- Returns:
The class registered for
proto, or the fallbackregistrydeclares – normallyRaw– whenprotois not registered.
Important
The lookup is
self._lookup_registry, so a miss does not grow the shared registry. The entry found, registered or the fallback, may be aModuleDescriptor, resolved to the class it names.Nothing is written back. A hit memoised under
protowould keep a classimportlib.reload()makes stale, and make parsing mutate a registry the whole process shares (#1559); so would a memo in the default factory or in a cache beside the registry (#421, #425, #555). Each lookup resolves its descriptor again, kept cheap byModuleDescriptor.klassreadingsys.modulesrather than re-enteringimportlib.import_module()(#574).
- _decode_next_layer(dict_, proto, length=None, *, packet=None)¶
Decode next layer protocol.
- Parameters:
- Return type:
_PT- Returns:
Current protocol with next layer extracted.
Notes
The method adds a
__next_type__key todict_to store the next layer protocol type, and a__next_name__key to store the next layer protocol name.Info.to_dictcarries both, so that_make_payload()dispatches adictrebuild on them, while the dumpers andreprleave them out (#2003).
- _import_next_layer(proto, length=None, *, packet=None)¶
Import next layer extractor.
- Parameters:
- Return type:
- Returns:
Instance of next layer.
- _empty_next_layer(file_, length)¶
The class a next layer with nothing to parse is kept as.
- Parameters:
- Return type:
Type[ProtocolBase] |None- Returns:
Noneif octets were captured past the header and it leaves its next layer a length, which is then parsed. OtherwiseRawif no octets were captured past a header leaving its next layer a negative length, andNoPayloadif the header leaves none, or no octets past it.
Note
A header leaves a negative length when it declares more than it was given: one the capture cut short, read at the octets captured, or an IPv6 extension header overrunning the payload (#2477). Such a next layer is kept raw, not dispatched on a code the cut may have read as zeros (#1170).
from_data()reads the rebuild of a cut header at the width its parse read it at, which leaves it the same length, so the rebuild keepsRawwhere its data model did (#2717, #2761).Added in version 1.6.0.
- static _parse_next_layer(klass, file_, length, **kwargs)¶
Parse the next layer, or keep it as raw octets if its header was not captured.
- Parameters:
klass (
Type[ProtocolBase]) – next layer protocol classfile_ (
bytes) – payload of the current layerlength (
int) – valid (non-padding) length**kwargs (
Any) – keyword arguments for the next layer’s constructor
- Return type:
- Returns:
Instance of
klass, or ofRawwhen fewer octets were captured than its header needs, or when it is pastFRAME_LAYER_LIMIT.
Note
Schema.unpackzero-fills a field the stream ends inside, so a header parsed from too few octets is filled with values that were never on the wire, andfrom_datarebuilds them (#1170). Such a payload is kept asRawinstead, as an unparseable one is.The captured octets are the first
lengthoffile_, or all of it when it holds fewer, as a truncated capture does. They are short of the header when there are fewer than the next layer’s__length_hint__, unless the header it parsed,lengthoctets long, fits in them anyway: for a variable-length header such asL2TPv2the hint is the longest form rather than the shortest. A next layer that reports no hint is kept as parsed.The warnings of a parse that may be replaced are held until that is known, then:
replaced as short – dropped, since they describe a header the result does not have:
packet length < 0twice for an Ethernet frame of 10 octets (#1580);kept – reported as the parse ends, inside the guard that catches them under an
errorfilter; a layer kept with its header cut short still warns;raised – dropped when
beholder(), which wraps_import_next_layer(), replaces the layer, whoseerrorreports the failure (#2308); otherwise reported as the error leaves.
Under
beholdera layer is held however much was captured, since one that raises is replaced at any length (#2516), so a kept layer’s warnings follow those of the layers it carries. Outside it, a layer captured at least as long as its hint cannot be replaced, and is parsed holding nothing, even inside one that holds.A layer past
FRAME_LAYER_LIMITin its frame is not parsed: it and the rest of the frame are kept asRaw, marked_past_layer_limit, with oneProtocolWarning(#1610).- Warns:
ProtocolWarning– If the next layer is pastFRAME_LAYER_LIMIT.
- _get_context(cls=None)¶
Get the caller supplied context for this protocol, if any.
The lookup is keyed on
self.id, so a protocol finds its own context without knowing how the caller spelled the registry.- Parameters:
cls (
Type[_CTX] |None) – Expected context class; when given, a context registered under this protocol’s name but of another type is ignored rather than returned for the implementation to trip over.- Return type:
_CTX|None- Returns:
The matching context, or
Nonewhen the caller supplied none.
See also
- _next: ProtocolBase¶
Next layer protocol instance.
- _protos: ProtoChain¶
Protocol chain instance.
- __reconstructing__: bool = False¶
Whether
from_data()is rebuilding this instance from a parsed data model, rather than from keywords somebody wrote. It decides only whether the construction keyword check of__init__()raises or warns, and is set for that call alone; every other code path seesFalse.
- __short_read__: tuple[str, int] | None = None¶
The
__short_read__record of the data modelfrom_data()rebuilds this instance from.pack()cuts the header it makes back to the octets captured, and__post_init__()hasunpack()parse them at the width__short_width__records, so the rebuild is parsed as its capture was (#2703, #2761). Set for that call alone, like__reconstructing__; otherwiseNone.
- _past_layer_limit: bool = False¶
Whether
_parse_next_layer()kept this layer asRawunparsed, being pastFRAME_LAYER_LIMIT. Such a layer carries anerroras a failed parse does; this tells the two apart, for what follows the limit is not to be read on (#1610).
- __data__: Type[_PT] = <class 'pcapkit.protocols.misc.raw.data.Raw'>¶
Protocol packet data definition.
- __init__(file=None, length=None, **kwargs)¶
Initialisation.
- Overloads:
- Parameters:
_layer (
str) – Parse packet until_layer(self._exlayer). While parsing, the un-prefixedlayeris accepted as well – see the note below._protocol – Parse packet until
_protocol(self._exproto), given as a protocol name (str), a protocol class or a protocol instance. While parsing, the un-prefixedprotocolis accepted as well – see the note below.packet – Packet context of the enclosing layer, a
dictas handed over byself._import_next_layer. While parsing, it is republished as__packet__so thatself.unpack– and through it the schema – can see it; see the note below.__context__ – Caller supplied parsing context (
self._exctx; seepcapkit.corekit.context): aContextRegistry, aProtocolContext, a mapping of names toProtocolContext, or an iterable ofProtocolContext. It is consumed here rather than being forwarded toself.read, and is propagated to nested layers byself._import_next_layer.**kwargs (
Any) – Arbitrary keyword arguments.
- Raises:
UnsupportedCall – When constructing (
fileisNone), if a keyword names no parameter of this protocol’smake(),read(),pack(),unpack(),__post_init__()or__init__(), anywhere in the MRO – except amakewhose class sets__own_make_keywords__, which counts only while it is themakeof the protocol being constructed – and is not listed in__keywords__. Parsing (fileis given) is unaffected.
Note
The
_layer,_protocoland__context__keywords are out-of-band: they configure the parse rather than describe the packet, and are consumed here, the one point every producer passes through, so a spelling normalised here is normalised for the engines, every_import_next_layerand any third-party protocol alike.packetis read but not consumed: it stays in the keywords forwarded to__post_init__(), and while parsing a copy is republished beside it as__packet__.
- __post_init__(file=None, length=None, **kwargs)¶
Post initialisation hook.
- Overloads:
- Parameters:
See also
For construction arguments, please refer to
self.make.Note
Inside a payload
_make_payload()rebuilds, the parse’s warnings are dropped, since the enclosing layer parses the same octets again and reports them (#2711). A parse that raises reports its warnings, unlessbeholder()replaces the layer.
- classmethod __init_subclass__(schema=None, data=None, code=None, *args, **kwargs)[source]¶
Initialisation for subclasses.
- Parameters:
code (
Any) – Next-layer dispatch registration key(s).None(the default) skips registration entirely. SeeProtocolBase.__init_subclass__()for the accepted shapes and the enum-type inference rule.*args (
Any) – Arbitrary positional arguments.**kwargs (
Any) – Arbitrary keyword arguments.
- Return type:
Sets
self.__schema__andself.__data__on the subclass throughProtocolBase.__init_subclass__(), which also finds an omitted one.Once that has accepted
code, a concrete subclass is also named in the by-name registry,ProtocolBase.__registry__, under its upper-cased class name; unlikecode’s dispatch registration, this is not opt-in. An abstract subclass, asisabstract()reports it, is not named, nor is a class derivingProtocolBasealone, as every built-in protocol does. A name holding another entry keeps it, with aRegistryWarning; onlyProtocolBase.register_protocolreplaces one. TheModuleDescriptornaming the class’s own module and name is no clash, and stays.See also
For more information on the registry, please refer to
ProtocolBase.register_protocol.Changed in version 1.6.0: An abstract subclass is not registered, and a name already holding an entry keeps it, where every subclass was registered over it (#2763).
- __repr__()¶
Returns representation of parsed protocol data.
Example
>>> protocol <Frame frame=<Frame ..., ethernet=Ethernet(...), protocols='Ethernet:IPv6:Raw', packet=b'...'>>
- Return type:
- __str__()¶
Returns formatted hex representation of source data stream.
Example
>>> protocol <Frame frame=<Frame ..., ethernet=Ethernet(...), protocols='Ethernet:IPv6:Raw', packet=b'...'>> >>> print(protocol) 00 00 00 00 00 00 00 a6 87 f9 27 93 16 ee fe 80 00 00 00 ..........'........ 00 00 00 1c cd 7c 77 ba c7 46 b7 87 00 0e aa 00 00 00 00 .....|w..F......... fe 80 00 00 00 00 00 00 1c cd 7c 77 ba c7 46 b7 01 01 a4 ..........|w..F.... 5e 60 d9 6b 97 ^`.k.
- Return type:
- __getitem__(key)¶
Subscription (
getitem) support.If
keyis aProtocolobject, the method will fetch its indexes (self.id).Later, search the packet’s chain of protocols with the calculated
key.If no matches, then raises
ProtocolNotFound.
- Parameters:
- Return type:
- Returns:
The sub-packet from the current packet of indexed protocol.
- Raises:
ProtocolNotFound – If
keyis not in the current packet.
See also
The method calls
self.expand_compto handle thekeyand expand it for robust searching.
- __contains__(name)¶
Returns if certain protocol is in the instance.
See also
The method calls
self.expand_compto handle thenameand expand it for robust searching.
- abstractmethod classmethod __index__()¶
Numeral registry index of the protocol.
- Return type:
IntEnum|aenum.IntEnum
- _exproto: str | ProtocolBase | Type[ProtocolBase] | None¶
Parse packet until such protocol.
- _exctx: ContextRegistry | None = None¶
Caller supplied parsing context; see
pcapkit.corekit.context.self.__init__sets aContextRegistry; an instance built without__init__reads the class-levelNone.
Parsing and Construction¶
Parsing, construction, from_schema() and from_data()
share one path:
flowchart TD
FS["from\_schema(schema)"] -->|"\_\_header\_\_ = schema,<br/>then its octets"| P
FD["from\_data(data)"] -->|"\_make\_data(data) gives the fields,<br/>\_\_reconstructing\_\_ set"| C
P["Proto(file, length, ...)<br/>parse"] --> INIT
C["Proto(field=value, ...)<br/>construct"] --> INIT
INIT["\_\_init\_\_<br/>consumes \_layer, \_protocol and \_\_context\_\_"]
INIT -->|construct| CHK["\_check\_construction\_keywords<br/>an undeclared keyword: UnsupportedCall,<br/>or a warning when reconstructing"]
CHK --> PACK["\_\_post\_init\_\_: pack(...)<br/>make() gives the schema, kept as \_\_header\_\_,<br/>and its octets"]
INIT -->|parse| OCT["\_\_post\_init\_\_: the octets given,<br/>or file.read(length)"]
PACK --> DATA["\_data, and \_file over it"]
OCT --> DATA
DATA --> UNP{"unpack: \_\_header\_\_ set?"}
UNP -->|no| SCH["\_\_schema\_\_.unpack(\_file, length, packet)"]
UNP -->|yes| KEPT["kept, or replaced by the parse of its octets<br/>where it holds raw items"]
SCH --> READ
KEPT --> READ
READ["read(): the data model,<br/>calling \_decode\_next\_layer"] --> INFO["\_\_init\_\_: \_info updated with packet"]
click FS "protocol.html#pcapkit.protocols.protocol.Protocol.from_schema"
click FD "protocol.html#pcapkit.protocols.protocol.Protocol.from_data"
click INIT "protocol.html#pcapkit.protocols.protocol.Protocol.__init__"
click PACK "protocol.html#pcapkit.protocols.protocol.Protocol.pack"
click UNP "protocol.html#pcapkit.protocols.protocol.Protocol.unpack"
click READ "protocol.html#protocol-next-layer-dispatch"
A rebuild of a header the capture cut short drops the header pack()
made, so unpack() parses its octets back (#2761), and inside a
payload being rebuilt the parse’s warnings are held and dropped (#2711).
Next-Layer Dispatch¶
How a layer picks and builds the layer it carries, and where it keeps
Raw or
NoPayload instead:
flowchart TD
DEC["\_decode\_next\_layer(dict\_, proto, length)<br/>called from read()"] --> IMP["\_import\_next\_layer, wrapped by beholder"]
IMP --> EMP{"\_empty\_next\_layer"}
EMP -->|"octets and a non-zero length"| TERM{"layer= or protocol= reached?"}
EMP -->|"no octets, length < 0"| KRAW["Raw"]
EMP -->|"otherwise: no octets,<br/>or a length of 0"| KNOP["NoPayload"]
TERM -->|yes| KRAW
TERM -->|no| LOOK["\_lookup\_next\_layer(\_\_proto\_\_, proto)<br/>the registered class, or the registry's fallback,<br/>normally Raw"]
KRAW --> LIM
KNOP --> LIM
LOOK --> LIM
LIM{"\_parse\_next\_layer:<br/>past FRAME\_LAYER\_LIMIT,<br/>and not already Raw or NoPayload?"}
LIM -->|yes| RAWL["Raw, marked \_past\_layer\_limit<br/>one ProtocolWarning"]
LIM -->|no| NEW["klass(file\_, length, ...)"]
NEW -->|raises| BEH["beholder: NoPayload for an end-of-file StructError,<br/>else Raw carrying the error"]
NEW -->|parsed| SHORT{"captured fewer octets than both<br/>\_\_length\_hint\_\_() and its length?"}
SHORT -->|yes| RAWS["Raw, its held warnings dropped"]
SHORT -->|no| KEEP["the parsed layer"]
RAWL --> WRITE
BEH --> WRITE
RAWS --> WRITE
KEEP --> WRITE
WRITE["dict\_ gets its info, \_\_next\_type\_\_ and \_\_next\_name\_\_<br/>self.\_next and self.\_protos set"]
click DEC "protocol.html#pcapkit.protocols.protocol.Protocol._decode_next_layer"
click IMP "protocol.html#pcapkit.protocols.protocol.Protocol._import_next_layer"
click EMP "protocol.html#pcapkit.protocols.protocol.Protocol._empty_next_layer"
click LOOK "protocol.html#pcapkit.protocols.protocol.Protocol._lookup_next_layer"
click LIM "protocol.html#pcapkit.protocols.protocol.Protocol._parse_next_layer"
click BEH "../corekit/decorators.html#pcapkit.corekit.decorators.beholder"
Some layers add steps of their own:
Internet the
EXTENSION_HEADER_LIMIT bound and IGMP’s dispatch,
Transport a family base’s dispatch, and
IPv6 the walk drawn under
The Extension Header Walk.
Layers per Frame¶
A frame is dissected to at most
FRAME_LAYER_LIMIT layers, counted from the
first layer its frame record carries, through tunnels, VLAN tags and IPv6
extension headers alike; a protocol constructed from its own octets is not
counted, so its count starts at the first layer it dissects. The rest is kept as
Raw, with one
ProtocolWarning (#1610), and marked
_past_layer_limit, so the
default engine’s TCP reassembly and flow tracing do not read a TCP segment
back out of it, as they do one the TCP parser rejected (#1518). One chain
of extension headers is bounded separately, by
EXTENSION_HEADER_LIMIT.
The pyshark, scapy and pypcapfile engines dissect with their own
parsers, which do not apply the frame’s bound (#1609); the dpkt
toolkit reads what dpkt decodes, which applies neither bound.
Value Helpers¶
A protocol reads and makes field values through the helpers on
Protocol, not copies of its own
(#2614). A maker checks a caller’s values through them before packing,
and raises ProtocolError for a value its
field cannot carry rather than masking it (#2617):
Helper |
Does |
|---|---|
checks an unsigned integer; a |
|
checks a two’s-complement integer, the inverse of
|
|
checks a fixed-size field’s octets, refusing any other width rather than padding or cutting it (#2676) |
|
zero-fills the octets a cut capture left out of a value
taken from its model, before |
|
counts the octets a variable-width integer needs |
|
counts the padding that takes a length to an alignment boundary |
Data Models¶
Internal Definitions¶
- class pcapkit.protocols.protocol.ProtocolBase[_PT: Data, _ST: Schema](file=None, length=None, **kwargs)[source]¶
-
Abstract base class for all protocol families.
The built-in protocol families – the layer base classes
Link,Internet,TransportandApplication, and the miscellaneous protocols inpcapkit.protocols.misc, PCAP and PCAP-NG included – derive from this class directly. Its metaclass isProtocolMeta.Note
This class is for internal use only. For customisation, subclass
Protocolto create a new protocol stack, or the matching layer base class above for a new protocol in an existing layer.- __registry__: dict[str, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]¶
Protocol registry by name, holding each protocol class under its upper-cased class name,
'IPV4'forIPv4. Each built-in protocol is aModuleDescriptorhere, so the map names every one before any is imported, andget_protocol()imports a class only when it resolves its entry (#2763).Protocol.__init_subclass__()adds each concreteProtocolsubclass as it is defined,register_protocol()replaces an entry, andProtocolMeta.registryis a read-only view.Added in version 1.6.0.
- classmethod register_protocol(protocol)[source]¶
Register a protocol class in
__registry__, replacing what its name holds.The key is
protocol.__name__.upper(). Defining a concreteProtocolsubclass registers it already, but keeps an entry its name holds, so this is how to replace one, or to register a class that derivesProtocolBasealone.- Parameters:
protocol (
Type[ProtocolBase]) –ProtocolBasesubclass- Raises:
pcapkit.utilities.exceptions.RegistryError – If
protocolis not a class, or not aProtocolBasesubclass.- Warns:
pcapkit.utilities.warnings.RegistryWarning– If the name holds a different class, naming it and its replacement, and their ids where the two read the same. AModuleDescriptorentry is resolved to compare, so registering the class it names is silent and leaves the descriptor in place.
Note
A built-in protocol is stored as the descriptor it shipped as, per
_shipped_registry, rather than as its class, so undoing an override leaves the entry as shipped, to be imported on lookup.Added in version 1.6.0.
- classmethod get_protocol(name, default=None)[source]¶
Look a protocol class up in
__registry__by name.- Overloads:
name (
str) →Type[ProtocolBase] |Nonename (
str), default (_VT) →Type[ProtocolBase] |_VT
- Parameters:
- Returns:
The class registered under
name.upper(), imported where its entry is aModuleDescriptor, ordefault. The entry is left as it is, so a descriptor is resolved again on each lookup and follows a reloaded module.- Raises:
pcapkit.utilities.exceptions.ProtocolError – If a descriptor names a class its module does not define.
Added in version 1.6.0.
- classmethod __init_subclass__(schema=None, data=None, code=None, *args, **kwargs)[source]¶
Initialisation for subclasses.
- Parameters:
- Raises:
UnsupportedCall – If any unrecognised class keyword is given.
- Return type:
Sets
self.__schema__andself.__data__on the subclass and, ifcodeis given, registers it into the next-layer dispatch registry (or registries)codenames, e.g.Link.__proto__.Notes
An omitted
schemaordatais the class of the subclass’s own name in theschemaordatamodule beside theprotocolmodule defining it, asL2TPfindsL2TP(#2534), elseRaworRaw.Dispatch registration is opt-in, like the
engine=/protocol=/fmt=keywords ofEngine,Reassembly,TraceFlowandDumper. Every built-in protocol omitscode: the built-in dispatch tables (e.g.Link.__proto__) are literal assignments in each layer module. A class defined withoutcodecan be registered later through the owning class’sregister()or the matchingregister_*helper inpcapkit.foundation.registry.protocols.codeaccepts:a single enum member, whose type determines the destination registry (or registries) – e.g. any
EtherTypemember always meansLink, and anyLinkTypemember means bothFrameandPCAPNG;a
dictmapping a destination class to a key, for a key that cannot name its own destination – a rawintport, for instance, is ambiguous betweenTCPandUDP, and must use this form;an iterable mixing either of the above, to register the same class into several registries from a single declaration – e.g. a
L2TPsubclass reachable both by its IP protocol number and by a UDP port.
The mapping form is accepted even where the key’s type could be inferred. An enum member whose type names no known destination raises
RegistryErrorrather than guessing.See also
pcapkit.foundation.registry.protocols.protocol.register_protocol_code()implements the resolution described above.
Protocolinherits the other members of this class, and they are documented under it above; each group below links to its entries.- property name¶
- property alias¶
- property info_name¶
- property info¶
- property data¶
- property length¶
- property payload¶
- property protocol¶
- property protochain¶
- property packet[source]¶
- property schema[source]¶
- property context¶
name,alias,info_name,info,data,length,payload,protocol,protochain,packet,schema,context
- id()[source]¶
- register()[source]¶
- analyze()[source]¶
- from_schema()[source]¶
- from_data()[source]¶
- read()[source]¶
- make()[source]¶
- unpack()[source]¶
- pack()[source]¶
- decode()[source]¶
- unquote()[source]¶
- resolve_index()[source]¶
- expand_comp()[source]¶
- _read_packet()[source]¶
- _get_payload()[source]¶
- _make_data()[source]¶
- _make_index()[source]¶
- _make_payload()[source]¶
- _packing_target()[source]¶
- _read_unpack()[source]¶
- _read_octets()[source]¶
- _read_uint()[source]¶
- _read_sint()[source]¶
- _read_vector()[source]¶
- _read_whole_vector()[source]¶
- _read_uints()[source]¶
- _make_pack()[source]¶
- _make_octets()[source]¶
- _fill_short_read()[source]¶
- _make_uint()[source]¶
- _make_sint()[source]¶
- _uint_size()[source]¶
- _make_vector()[source]¶
- _make_uints()[source]¶
- _read_mac_addr()[source]¶
- _make_mac_addr()[source]¶
- _lookup_registry()[source]¶
- _lookup_next_layer()[source]¶
- _decode_next_layer()[source]¶
- _import_next_layer()[source]¶
- _parse_next_layer()[source]¶
- _get_context()[source]¶
- __init__()[source]¶
- __post_init__()[source]¶
- __repr__()[source]¶
- __str__()[source]¶
- __getitem__()[source]¶
- __contains__()[source]¶
- __index__()[source]¶
- __length_hint__()[source]¶
id(),register(),analyze(),from_schema(),from_data(),read(),make(),unpack(),pack(),decode(),unquote(),resolve_index(),expand_comp(),_read_packet(),_get_payload(),_make_data(),_make_index(),_make_payload(),_packing_target(),_read_unpack(),_read_octets(),_read_uint(),_read_sint(),_read_vector(),_read_whole_vector(),_read_uints(),_make_pack(),_make_octets(),_fill_short_read(),_make_uint(),_make_sint(),_uint_size(),_make_vector(),_make_uints(),_read_mac_addr(),_make_mac_addr(),_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__()
- __layer__¶
- __proto__¶
- __keywords__¶
- __own_make_keywords__¶
- __schema__¶
- __header__¶
- _data¶
- _file¶
- _info¶
- _next¶
- _protos¶
- _seekset¶
- _sigterm¶
- _past_layer_limit¶
- __data__¶
- _exlayer¶
- _exproto¶
- _exctx¶
__layer__,__proto__,__keywords__,__own_make_keywords__,__schema__,__header__,_data,_file,_info,_next,_protos,_seekset,_sigterm,_past_layer_limit,__data__,_exlayer,_exproto,_exctx
- class pcapkit.protocols.protocol.ProtocolMeta(name, bases, namespace, /, **kwargs)[source]¶
Bases:
ABCMetaMetaclass of
ProtocolBase, and so of every protocol class.Over
abc.ABCMeta, it adds the class propertyregistry.- property registry: MappingProxyType[str, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]¶
Read-only view of the by-name protocol registry.
It is
ProtocolBase.__registry__, with each entry as stored: a built-in protocol is theModuleDescriptornaming it, so reading the view imports nothing. Look a class up withProtocolBase.get_protocol(), which resolves a descriptor.Note
Every protocol class reads the same map, later registrations included. Defined on the metaclass, it is a class attribute, not an instance one.
Added in version 1.6.0.
- pcapkit.protocols.protocol.OUT_OF_BAND_KEYWORDS¶
Construction keywords that name no field.
Protocol.__init__or the schema layer consumes them, notmake. No signature declares them, so_declared_keywords()takes them from here.packetis injected by the library:Protocol.__init__putspacket=self.packet.payloadinto every parsed_info, which the defaultProtocol._make_data(data.to_dict()) carries into the keywordsProtocol.from_datarebuilds from. Refusing it would breakfrom_datafor every protocol whosemakelacks it, starting withNoPayload. Where it is a real field, as the packet type ofHIP.make, listing it here only stops it being refused.
- pcapkit.protocols.protocol._KEYWORD_CONSUMERS¶
Methods a construction keyword may be for.
Protocol.__post_init__passes the same**kwargstopack(and somake) andunpack(and soread).
- pcapkit.protocols.protocol._declared_keywords(cls)[source]¶
Collect every keyword the protocol
clsdeclares a parameter for.- Parameters:
cls (
type) – Protocol class to inspect.- Return type:
- Returns:
Names of every keyword-acceptable parameter declared by any of
_KEYWORD_CONSUMERSanywhere in the MRO ofcls, plus every entry ofProtocol.__keywords__found there, plusOUT_OF_BAND_KEYWORDS.Noneifclsitself sets__keywords__toNone, meaning its keywords cannot be enumerated and are not to be checked – inheritedNonedoes not count, asProtocol.__keywords__explains.
The union is wider than the signature of
cls.make:Protocol.__post_init__hands one**kwargsto both the construction and the parse, so a keywordreaddeclares travels throughmaketoo, asextensionofHIP.readdoes.The walk covers the whole MRO, not the most derived override of each method, so a subclass forwarding to its parent keeps the parent’s keywords. The exception is a class that sets
Protocol.__own_make_keywords__: itsmakecounts only while no subclass overrides it (#2286).
Type Variables¶
- pcapkit.protocols.protocol._PT: pcapkit.protocols.data.Data¶
- pcapkit.protocols.protocol._ST: pcapkit.protocols.schema.Schema¶