Root Protocol¶
pcapkit.protocols.protocol contains
Protocol, an abstract base class with
pre-defined utility arguments and methods. Inherit it directly only to create a
new protocol stack; a new protocol in an existing layer subclasses that layer’s
base class – Link,
Internet,
Transport or
Application – instead, c.f.
Customisation & Extensions. The built-in protocol families, those layer classes included,
derive from ProtocolBase, whose metaclass
is ProtocolMeta; both are listed under
Internal Definitions below.
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(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, c.f. 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 payload: ProtocolBase¶
Payload of current instance.
- property protochain: ProtoChain¶
Protocol chain of current instance.
- property packet: Packet¶
Data_Packet data of the protocol.
Note
The split relies on
self.lengthbeing the length of the octets preceding the payload, and on the payload running from there to the end of the buffer. Both hold for a protocol laid out as a header followed by its payload, which is nearly all of them.A protocol laid out otherwise has to override this: one whose
lengthcounts something else, or one carrying a trailer after the payload, gets a header that eats the payload and a payload ofb''.PCAPNGis the example – 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 becauseProtocolBase.__init__()injects it into every parsed_info, which the dumpers write out.
- classmethod id()¶
Index ID of the protocol.
- classmethod register(code, protocol)¶
Register a new protocol class.
Notes
The full qualified class name of the new protocol class should be as
{protocol.module}.{protocol.name}.- Parameters:
code (
int) – protocol codeprotocol (
ModuleDescriptor|Type[ProtocolBase]) – module descriptor or aProtocolsubclass
- Raises:
pcapkit.utilities.exceptions.RegistryError – If
protocolis not a class, or not aProtocolBasesubclass.- Warns:
pcapkit.utilities.warnings.RegistryWarning – If
codeis already registered, naming the displaced entry and its replacement so a caller can tell what was lost rather than only that something was. Fires only when the incumbent differs from the replacement; an unresolvedModuleDescriptorincumbent counts as different from the class it names.
Note
The guard matches
register_protocol’s: it fires only when the incumbent differs from the replacement, so handing back the entry already stored undercode– the same class object, or aModuleDescriptorequal to the stored one – is a silent no-op rather than a warning about nothing displaced, and the stored entry is kept as it is (#1364). The comparison runs beforeprotocolis resolved and resolves nothing, so a stored descriptor stays deferred, and an incumbent left as an unresolved descriptor still reports as different from the class it names.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
Protocolinstance.
- classmethod from_schema(schema)¶
Create protocol instance from schema.
- classmethod from_data(data, **kwargs)¶
Create protocol instance from data.
- Parameters:
- Return type:
Self- 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:
TypeVar(_ST, bound= Schema)- Returns:
Curated protocol schema data.
Note
The
**kwargshere absorbs the keywords thatProtocolBase.__post_init__hands to the parse as well as to the construction, so an implementation is not expected to declare every keyword it is called with. It is not a place for a caller to put a keyword no signature declares: building a protocol through its constructor with such a keyword raisesUnsupportedCallfromProtocolBase.__init__(#617).Warning
Calling this method directly is not checked, and still discards an undeclared keyword in silence. The check lives in
ProtocolBase.__init__, so it coversSomeProtocol(...)and thepack()it leads to, but notSomeProtocol.make(...)on an instance obtained some other way –object.__new__(cls).make(**kwargs)is the idiom, used by this package’s own tests and byHTTP.maketo reach its versioned implementation. Covering it would mean interposing on everymakein the tree rather than on the one place their keywords converge, so it is deliberately not done. Construct through the constructor to get the check.
- unpack(length=None, **kwargs)¶
Unpack (parse) packet data.
- Parameters:
- Return type:
TypeVar(_PT, bound= Data)- Returns:
Parsed packet data.
Notes
We used a special keyword argument
__packet__to pass the global packet data to underlying methods. This is useful when the packet data is not available in the current instance.When
self.__header__is already set, byfrom_schema()or by thepack()call that__post_init__()makes to construct the instance, that schema is kept, unless it still holds rawbyteswhere parsing its packed octets yields a schema – e.g. a raw option given tomake()– whichread()cannot consume. The header is then replaced by the parsed one (#1312).- 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__.
- pack(**kwargs)¶
Pack (construct) packet data.
- Parameters:
**kwargs (
Any) – Arbitrary keyword arguments.- Return type:
- Returns:
Constructed packet data.
Notes
We used a special keyword argument
__packet__to pass the global packet data to underlying methods. This is useful when the packet data is not available in the current instance.The octets are built from
kwargsalone, throughmake(); the instance’s own parsed or constructed state is not read. A bareSomeProtocol(...).pack()therefore returns the octets of a default header, not the instance’s:dataholds those.Nor is that state written. Once the instance has been parsed or constructed, the header is made on a shallow copy of it (see
_packing_target()), soschema,infoand anythingmake()sets along the way, such asTCP.connection, still describe that packet. Only the call that__post_init__()makes to construct the instance keeps the header made here, as the oneunpack()reads back.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 failed 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 failed , 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 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 protocols names in upper case obtained fromProtocol.id.If
valueisstr, the method will attempt to search for the existing registered protocol class frompcapkit.protocols.__proto__and follow step 2; otherwise, return the value itself.
- 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 next layer, c.f.
self._decode_next_layer&self._import_next_layer. Each value is aModuleDescriptornaming the module and class, or aProtocolsubclass.
- __keywords__: frozenset[str] | None¶
Construction keywords this protocol consumes out of
**kwargsinstead of declaring as a parameter, e.g. withkwargs.get('spam')inread()– asESP.readdoes withpacket._declared_keywords()finds keywords by reading signatures, which cannot see such a name, so a protocol that consumes one names it here and the construction check of__init__()accepts it. The union over the MRO is used, so a subclass need not repeat its parents’ entries.Declaring the parameter is preferable where possible, since that also documents the keyword to the caller and to
inspect. This is for the cases where it is not – a keyword handled uniformly for a whole family of names, say. It is opt-in per class, so it can only exempt a name whose author wrote it down (#617).Nonemeans the keywords cannot be enumerated and the check is skipped for this protocol. That is for a dispatcher, whose real signature belongs to a class chosen at call time:HTTP.makedeclares onlyversionand forwards everything else toHTTPv1.makeorHTTPv2.makedepending on that value, so no set of names is right for it. Use it only for that shape, since a protocol that skips the check silently discards an unknown keyword. Unlike a set, theNoneis not inherited: a subclass of a dispatcher is checked normally unless it dispatches too and says so, becauseHTTPv1andHTTPv2declare their keywords in full and exempting them along with their base would forgo the check on the only two classes here that can have it.
- _read_packet(length=None, *, header=None, payload=None, discard=False)¶
Read raw packet data.
- Overloads:
self, length (Optional[int]), header (None) → bytes
self, header (int), payload (Optional[int]), discard (Literal[True]) → bytes
self, header (int), payload (Optional[int]), discard (Literal[False]) → Data_Packet
- 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.Schema.get_payload().
- classmethod _make_data(data)¶
Create key-value pairs from
datafor protocol construction.
- classmethod _make_index(name, default=None, *, namespace=None, reversed=False, pack=False, size=4, signed=False, lilendian=False)¶
Return first index of
namefrom adictor enumeration.- Overloads:
cls, name (int | StdlibEnum | AenumEnum), pack (Literal[False]) → int
cls, name (int | StdlibEnum | AenumEnum), pack (Literal[True]), size (int), signed (bool), lilendian (bool) → bytes
cls, name (str), default (Optional[int]), namespace (Type[StdlibEnum] | Type[AenumEnum]), pack (Literal[False]) → int
cls, name (str), default (Optional[int]), namespace (Type[StdlibEnum] | Type[AenumEnum]), pack (Literal[True]), size (int), signed (bool), lilendian (bool) → bytes
cls, name (str), default (Optional[int]), namespace (dict[int, str]), reversed (Literal[False]), pack (Literal[False]) → int
cls, name (str), default (Optional[int]), namespace (dict[int, str]), reversed (Literal[False]), pack (Literal[True]), size (int), signed (bool), lilendian (bool) → bytes
cls, name (str), default (Optional[int]), namespace (dict[str, int]), reversed (Literal[True]), pack (Literal[False]) → int
cls, name (str), default (Optional[int]), namespace (dict[str, int]), reversed (Literal[True]), pack (Literal[True]), size (int), signed (bool), lilendian (bool) → bytes
cls, name (str | int | StdlibEnum | AenumEnum), default (Optional[int]), namespace (Optional[dict[str, int] | dict[int, str] | Type[StdlibEnum] | Type[AenumEnum]]), reversed (bool), pack (Literal[False]) → int
- Parameters:
namespace (
dict[str,int] |dict[int,str] |Type[IntEnum] |Type[IntEnum] |None) – namespace for itemreversed (
bool) – if namespace isstr -> intpairspack (
bool) – if needstruct.pack()to pack the resultsize (
int) – buffer sizesigned (
bool) – signed flaglilendian (
bool) – little-endian flag
- Returns:
Index of
namefrom a dict or enumeration. IfpackisTrue, returnsbytes; otherwise, returnsint.- Raises:
ProtocolNotImplemented – If
nameis NOT innamespaceanddefaultisNone.
- classmethod _make_payload(data, exclude=())¶
Create payload from
datafor protocol construction.This method uses
__next_type__and__next_name__to determine the payload type and name. If either of them isNone, aNoPayloadinstance will be returned. Otherwise, the payload will be constructed byProtocol.from_data.Info.to_dictleaves both keys out, sodatarebuilt from such adictcarries neither. The payload is then found from the structure ofdatainstead, by_lookup_payload().The payload is built one layer further into the frame than this protocol, as
_parse_next_layer()counts it, since each layer built parses its own octets again. So rebuilding a frame stops atFRAME_LAYER_LIMITwhere parsing it did, rather than that many layers below each layer of it (#1610). Nor does the payload’s parse warn of the limit: this protocol’s own parse goes over the same octets, so the rebuilt frame warns of it once, as the parsed one did.- Parameters:
- Return type:
- Returns:
Payload for protocol construction.
- _packing_target()¶
Return the instance that
pack()makes its header on.- Return type:
Self- 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.
- static _lookup_registry(registry, code)¶
Look up a dispatch registry entry without recording a miss.
- Parameters:
registry (
DefaultDict[Any,TypeVar(_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:
TypeVar(_VT)- Returns:
The entry registered for
code, or the fallbackregistrydeclares whencodeis not registered.
Important
Every one of these registries is a
collections.defaultdictheld on a class attribute, shared by every instance of the class in the process. Soregistry[code]inserts each code it misses, and parsing one packet carrying an unrecognised code grows the registry permanently.The inserted value is what the default factory would have produced anyway, so the entry buys nothing. It costs a spurious “already registered” warning from the next genuine
registercall for that code, and makes “is this code registered?” depend on what has been parsed. The fallback is therefore read from the default factory directly rather than through a lookup that records it.
- 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 itself is
self._lookup_registry, so a miss does not grow the shared registry. What this adds is the next-layer-specific resolution step: the entry found – registered, or the fallback – may be aModuleDescriptorrather than a class, and it is resolved to the class it names.Nothing is written back, on a hit or a miss. A miss has no key to write under, and recording one would be exactly the insertion
self._lookup_registryexists to avoid. A hit memoised underprotowould retain a class thatimportlib.reload()then makes stale, and would make parsing mutate a registry shared by the whole process (#1559). The same holds for a memo inregistry’s default factory or in a cache beside the registry (#421, #425, #555).So every lookup resolves its descriptor again, and what keeps that affordable is
ModuleDescriptor.klassreadingsys.modulesinstead of re-enteringimportlib.import_module()(#574).
- _decode_next_layer(dict_, proto, length=None, *, packet=None)¶
Decode next layer protocol.
- Parameters:
- Return type:
TypeVar(_PT, bound= Data)- Returns:
Current protocol with next layer extracted.
Notes
We added a new key
__next_type__todict_to store the next layer protocol type, and a new key__next_name__to store the next layer protocol name. These two keys will NOT be included whenInfo.to_dictis called;_lookup_payload()finds the payload of such adictinstead.
- _import_next_layer(proto, length=None, *, packet=None)¶
Import next layer extractor.
- Parameters:
- Return type:
- Returns:
Instance of next layer.
- 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 it is known whether it is. They are dropped when it is, since they describe a header the result does not have –
packet length < 0twice for an Ethernet frame of 10 octets (#1580) – and reported as the parse ends when it is kept, still inside the guard that catches them under anerrorfilter. A layer kept with its header cut short still warns. 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 past
FRAME_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[TypeVar(_CTX, bound= ProtocolContext)] |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:
- Returns:
The matching context, or
Nonewhen the caller supplied none.
See also
- _next: ProtocolBase¶
Next layer protocol instance.
- _protos: ProtoChain¶
Protocol chain instance.
- _past_layer_limit: bool = False¶
Whether this layer is past
FRAME_LAYER_LIMIT, and so was kept asRawby_parse_next_layer()without being parsed. Such a layer carries anerroras one that failed to parse does, so this is what tells the two apart: what follows the limit is not to be read on (#1610).
- __data__: Type[_PT] = <class 'pcapkit.protocols.data.misc.raw.Raw'>¶
Protocol packet data definition.
- __init__(file=None, length=None, **kwargs)¶
Initialisation.
- Overloads:
self, file (IO[bytes] | bytes), length (Optional[int]), kwargs (Any) → None
self, kwargs (Any) → None
- Parameters:
_layer (
str) – Parse packet until_layer(self._exlayer). While parsing, the un-prefixedlayeris accepted as well – see the note below._protocol (
Union[str,Protocol,Type[Protocol]]) – Parse packet until_protocol(self._exproto). While parsing, the un-prefixedprotocolis accepted as well – see the note below.packet (
dict[str,Any]) – Packet context of the enclosing layer, as 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__ (
Union[ContextRegistry,ProtocolContext,Mapping[str,ProtocolContext],Iterable[ProtocolContext]]) – Caller supplied parsing context (self._exctx), c.f.pcapkit.corekit.context. 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, and is not listed in__keywords__. Parsing (fileis given) is unaffected.
Note
Three of the keywords above are out-of-band: they configure the parse rather than describing the packet, and every one of them is consumed here, at the one point each of a protocol’s producers passes through. That is deliberate, and the normalisation below relies on it: fixing a spelling here fixes it for the engines, for all four
_import_next_layerimplementations, and for any third party protocol that copied their shape, rather than one call site at a time.
- __post_init__(file=None, length=None, **kwargs)¶
Post initialisation hook.
- Overloads:
self, file (IO[bytes] | bytes), length (Optional[int]), kwargs (Any) → None
self, kwargs (Any) → None
- Parameters:
See also
For construction arguments, please refer to
self.make.
- classmethod __init_subclass__(schema=None, data=None, code=None, *args, **kwargs)[source]¶
Initialisation for subclasses.
- Parameters:
schema (
Type[TypeVar(_ST, bound= Schema)] |None) – Schema class.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.
This method is called when a subclass of
Protocolis defined. It is used to set theself.__schema__attribute of the subclass.Notes
When
schemaand/ordatais not specified, the method will first try to find the corresponding class in theschemaanddatamodules respectively. If the class is not found, the defaultRawandRawclasses will be used.This method also registers the subclass to the protocol registry, i.e.,
pcapkit.protocols.__proto__. That registration is unconditional – it is the name-keyed identity registry, unrelated to thecodekeyword – whereascode’s next-layer dispatch registration is opt-in; seeProtocolBase.__init_subclass__()for the latter.See also
For more information on the registry, please refer to
pcapkit.foundation.registry.protocols.register_protocol().
- __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.- Return type:
- abstractmethod classmethod __index__()¶
Numeral registry index of the protocol.
- Return type:
IntEnum|IntEnum
- _exproto: str | ProtocolBase | Type[ProtocolBase] | None¶
Parse packet until such protocol.
- Type:
- _exctx: ContextRegistry | None = None¶
Caller supplied parsing context, c.f.
pcapkit.corekit.context.self.__init__replaces this with a realContextRegistry; the class-levelNoneis what an instance built without__init__(e.g.object.__new__(SomeProtocol)) sees, so reading it is always safe.
Layers per Frame¶
A frame is dissected to at most
FRAME_LAYER_LIMIT layers of its protocol
chain, counted from the first layer the frame record carries, through tunnels,
VLAN tags and IPv6 extension headers alike. What follows is kept as
Raw, with one
ProtocolWarning (#1610), and is
marked _past_layer_limit, so the
default engine’s TCP reassembly and flow tracing do not read a TCP segment
there back out, as they do one the TCP parser rejected (#1518). A
protocol constructed from its own octets is not counted itself, so the count
starts at the first layer it dissects. One chain of extension headers is also bounded on
its own, by EXTENSION_HEADER_LIMIT.
The pyshark, scapy and pypcapfile engines dissect with their own
parsers, which do not apply the frame’s layer bound (#1609). The
dpkt toolkit reads what dpkt decodes, which applies neither bound.
Data Models¶
Internal Definitions¶
- class pcapkit.protocols.protocol.ProtocolBase(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.- 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.
This method is called when a subclass of
Protocolis defined. It is used to set theself.__schema__attribute of the subclass, and, ifcodeis given, to register the subclass into the next-layer dispatch registry (or registries) thatcodenames – e.g.Link.__proto__.Notes
When
schemaand/ordatais not specified, the method will first try to find the corresponding class in theschemaanddatamodules respectively. If the class is not found, the defaultRawandRawclasses will be used.Dispatch registration is opt-in, like the
engine=/protocol=/fmt=keywords ofEngine,Reassembly,TraceFlowandDumper. Omittingcodeis a deliberate way to decline registration, and what every built-in protocol class does: the built-in dispatch tables (e.g.Link.__proto__) are populated by literal assignment in each layer module, not by this hook. A subclass that declines can still be registered later via the owning class’sregister()classmethod 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 explicit mapping form is accepted even for a key whose type could be inferred: being more explicit than required is never an error.
Inference refuses rather than guesses: an enum member whose type names no known destination raises
RegistryErrorrather than doing nothing or picking an arbitrary registry.See also
pcapkit.foundation.registry.protocols.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]¶
name,alias,info_name,info,data,length,payload,protocol,protochain,packet,schema
- id()[source]¶
- register()[source]¶
- analyze()[source]¶
- from_schema()[source]¶
- from_data()[source]¶
- read()[source]¶
- make()[source]¶
- unpack()[source]¶
- pack()[source]¶
- decode()[source]¶
- unquote()[source]¶
- expand_comp()[source]¶
- _read_packet()[source]¶
- _get_payload()[source]¶
- _make_data()[source]¶
- _make_index()[source]¶
- _make_payload()[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(),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__()
- __layer__¶
- __proto__¶
- __keywords__¶
- __schema__¶
- __header__¶
- _data¶
- _file¶
- _info¶
- _next¶
- _protos¶
- _seekset¶
- _sigterm¶
- _past_layer_limit¶
- __data__¶
- _exlayer¶
- _exproto¶
- _exctx¶
__layer__,__proto__,__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.It adds no behaviour of its own over
abc.ABCMeta.
Type Variables¶
- pcapkit.protocols.protocol._PT: pcapkit.protocols.data.data.Data¶
- pcapkit.protocols.protocol._ST: pcapkit.protocols.schema.schema.Schema¶