Skip to content

Commit 80a11f9

Browse files
committed
docs(conventions): scope the family grouping page to the rulings (#2476)
- id() criterion: members-only and own-name-first tuples; ARP alone. - Drop the Shim6 narration and the SSL/TLS/DTLS grouping. - Versioned class names "may"; add #2443's selector ruling. - ProtoChain also matches aliases; ARP row names RARP/DRARP on 0x8035. - Cite pull requests with :pr:; no count.
1 parent 3a46515 commit 80a11f9

1 file changed

Lines changed: 69 additions & 57 deletions

File tree

‎docs/source/contributing/conventions/protocol-family-grouping.rst‎

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,64 +5,60 @@ Protocol Family Grouping
55

66
A protocol family is a base class named after the family plus its member classes.
77
What the base and each member return from
8-
:meth:`~pcapkit.protocols.protocol.Protocol.id` decides what every selector matches,
9-
so the tuples are settled here rather than re-derived per family. Set on
10-
:issue:`2441`, :issue:`2446` and :issue:`2462`.
8+
:meth:`~pcapkit.protocols.protocol.Protocol.id` is what the selectors on
9+
:class:`~pcapkit.protocols.protocol.Protocol` match against, so the tuples are
10+
settled here rather than re-derived per family. Set on :pr:`2441`, :pr:`2443`,
11+
:pr:`2446` and :issue:`2462`.
1112

1213
The ``id()`` Criterion
1314
~~~~~~~~~~~~~~~~~~~~~~
1415

15-
**A family base lists its direct concrete subclasses, and nothing else.** An abstract
16-
intermediate is left out, and so is everything beneath it, since that intermediate
17-
carries its own tuple. :issue:`2441`.
16+
**A family base lists its direct concrete subclasses.** An abstract intermediate is
17+
left out, and so is everything beneath it, since that intermediate carries its own
18+
tuple. :pr:`2441`.
1819

19-
* :meth:`IP.id() <pcapkit.protocols.internet.ip.IP.id>` is ``('IPv4', 'IPv6')``.
20-
:class:`~pcapkit.protocols.internet.ah.AH` and
21-
:class:`~pcapkit.protocols.internet.esp.ESP` are not in it: they belong to the
22-
separate abstract :class:`~pcapkit.protocols.internet.ipsec.IPsec`.
23-
* :meth:`IPsec.id() <pcapkit.protocols.internet.ipsec.IPsec.id>` is
24-
``('AH', 'ESP')``.
20+
The member list takes either of these forms:
21+
22+
* **Members only.** :meth:`IP.id() <pcapkit.protocols.internet.ip.IP.id>` is
23+
``('IPv4', 'IPv6')``; :class:`~pcapkit.protocols.internet.ah.AH` and
24+
:class:`~pcapkit.protocols.internet.esp.ESP` are not in it, since they belong to
25+
the separate abstract :class:`~pcapkit.protocols.internet.ipsec.IPsec`, whose
26+
:meth:`~pcapkit.protocols.internet.ipsec.IPsec.id` is ``('AH', 'ESP')``.
27+
* **The base's own name, then the members.**
28+
:meth:`VLAN.id() <pcapkit.protocols.link.vlan.VLAN.id>` is
29+
``('VLAN', 'C_Tag', 'S_Tag')``,
30+
:meth:`L2TP.id() <pcapkit.protocols.link.l2tp.L2TP.id>` is ``('L2TP', 'L2TPv2')``
31+
and :meth:`HTTP.id() <pcapkit.protocols.application.http.HTTP.id>` is
32+
``('HTTP', 'HTTPv1', 'HTTPv2')``.
33+
34+
:meth:`ARP.id() <pcapkit.protocols.link.arp.ARP.id>` is ``('ARP',)`` alone; see
35+
:ref:`protocol-family-shapes`.
2536

2637
Abstract Family Names
2738
~~~~~~~~~~~~~~~~~~~~~
2839

29-
**A family name composes its members even when the base also parses.**
30-
:class:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext` is concrete -- it is the
31-
fallback :class:`~pcapkit.protocols.internet.ipv6.IPv6` substitutes when a dedicated
32-
extension-header parser fails -- but its name is the family's, so its ``id()`` is to
33-
list its direct concrete members, and each member narrows its own ``id()`` to itself.
34-
:issue:`2462`.
35-
36-
The rejected alternative gave the base only its own name, because it also parses
37-
``Shim6``, which has no member class and which every member's name would then select.
38-
That case ends once ``Shim6`` gets its own parser, so the ruling does not wait for it.
39-
40-
One consequence is accepted: once composed, an
41-
:class:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext` standing in for a header whose
42-
own parser failed matches every member's name.
43-
44-
Grouping by Name and History
45-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46-
47-
**Members share a base because they share a name and a lineage, not a wire format.**
48-
SSL is the case that settled it: its family covers every SSL version, TLS (a rebrand
49-
of SSL) and DTLS, although the SSL versions are not wire-compatible with each other.
50-
The same reading puts HTTP/1 and HTTP/2 under
51-
:class:`~pcapkit.protocols.application.http.HTTP`, IPv4 and IPv6 under
52-
:class:`~pcapkit.protocols.internet.ip.IP`, and AH and ESP under
53-
:class:`~pcapkit.protocols.internet.ipsec.IPsec`. :issue:`2441`.
54-
55-
Shared parsing code is an implementation detail and does not decide the grouping.
56-
Nor does a family base need dispatcher logic: :class:`~pcapkit.protocols.internet.ip.IP`
57-
and :class:`~pcapkit.protocols.internet.ipsec.IPsec` have none, and each member is
58-
bound directly. :class:`~pcapkit.protocols.application.http.HTTP` dispatches
59-
because it has to guess a version its wire format does not state, not because it is
60-
a family base.
40+
**An abstract family name composes its members.**
41+
:class:`~pcapkit.protocols.internet.ipv6_ext.IPv6_Ext` carries the family's name, so
42+
its ``id()`` is to list its direct concrete members, and each member narrows its own
43+
``id()`` to itself. :issue:`2462`.
44+
45+
Grouping by Name
46+
~~~~~~~~~~~~~~~~
47+
48+
**Members share a base because they share a name, not a wire format.** HTTP/1 and
49+
HTTP/2 share :class:`~pcapkit.protocols.application.http.HTTP`, IPv4 and IPv6 share
50+
:class:`~pcapkit.protocols.internet.ip.IP`, and AH and ESP share
51+
:class:`~pcapkit.protocols.internet.ipsec.IPsec`. A family base needs no dispatcher
52+
logic: :class:`~pcapkit.protocols.internet.ip.IP` and
53+
:class:`~pcapkit.protocols.internet.ipsec.IPsec` have none, and each member is bound
54+
directly. :pr:`2441`.
55+
56+
.. _protocol-family-shapes:
6157

6258
Member Shapes
6359
~~~~~~~~~~~~~
6460

65-
Three shapes are in use. Pick by how far a sibling's selector should reach.
61+
Pick a member's shape by how far a sibling's selector should reach.
6662

6763
.. list-table::
6864
:header-rows: 1
@@ -85,11 +81,15 @@ Three shapes are in use. Pick by how far a sibling's selector should reach.
8581
:class:`~pcapkit.protocols.link.l2tpv2.L2TPv2` ``('L2TP', 'L2TPv2')``
8682
* - One parser, dynamic alias
8783
- fixed, whichever protocol was read
88-
- :class:`~pcapkit.protocols.link.arp.ARP` ``('ARP',)`` parses ARP, InARP,
89-
RARP and DRARP and reports which through
84+
- :class:`~pcapkit.protocols.link.arp.ARP` ``('ARP',)`` reads the operation
85+
code and reports ARP, InARP, RARP or DRARP through
9086
:attr:`~pcapkit.protocols.protocol.Protocol.alias`;
9187
:class:`~pcapkit.protocols.link.arp.InARP` ``('InARP',)`` is a thin
92-
subclass that exists for explicit construction
88+
subclass that exists for explicit construction.
89+
:class:`~pcapkit.protocols.application.rarp.RARP` ``('RARP', 'DRARP')`` and
90+
:class:`~pcapkit.protocols.application.rarp.DRARP` ``('DRARP',)`` are
91+
separate classes, bound to EtherType ``0x8035``
92+
(:attr:`~pcapkit.const.reg.ethertype.EtherType.Reverse_Address_Resolution_Protocol`)
9393

9494
A family-inclusive member is selected by any sibling's registry key, because both
9595
expand to the shared family name (see :ref:`below <protocol-family-selectors>`). A
@@ -102,16 +102,23 @@ Canonical Names
102102

103103
**A class name may carry a version that the protocol's own name does not.** Where
104104
the defining RFC names the protocol without a version, a versioned class and module
105-
name are fine for telling the members apart in code, but ``id()`` returns the RFC's
106-
canonical name and :attr:`~pcapkit.protocols.protocol.Protocol.name` follows the
107-
RFC's title, with no version string added. :issue:`2446`.
105+
name may tell the members apart in code; ``id()`` is then expected to drop the
106+
version for the RFC's canonical name, and
107+
:attr:`~pcapkit.protocols.protocol.Protocol.name` to follow the RFC's title with no
108+
version string. :pr:`2446`.
108109

109110
.. _protocol-family-selectors:
110111

111112
Selector Matching
112113
~~~~~~~~~~~~~~~~~
113114

114-
What a selector reaches is defined by
115+
**A family name selects every version, and each version name selects its own.**
116+
:pr:`2443`. The narrow-to-self shape gives exactly that: ``'IP' in frame`` is
117+
``True`` for an IPv4 frame and an IPv6 frame alike, and ``'IPv6' in frame`` is
118+
``False`` for an IPv4 frame. Under the family-inclusive shape a version name also
119+
selects its siblings, as the second bullet below shows for HTTP.
120+
121+
What a selector on a frame or a layer reaches is defined by
115122
:meth:`~pcapkit.protocols.protocol.Protocol.expand_comp`,
116123
:meth:`~pcapkit.protocols.protocol.Protocol.__contains__`,
117124
:meth:`~pcapkit.protocols.protocol.Protocol.__getitem__` and ``Protocol.__eq__``.
@@ -126,7 +133,13 @@ All comparisons are case-insensitive.
126133
``True`` for an IPv4 frame, and ``'HTTPv2' in frame`` is ``True`` for an HTTP/1.1
127134
frame, since both sides carry ``'HTTP'``.
128135
* A string that is **not** a registry key is matched by name alone against each
129-
layer's ``id()``. An alias such as ``'HTTP/1.1'`` matches nothing.
136+
layer's class and ``id()``, so an alias such as ``'HTTP/1.1'`` selects no layer:
137+
``'HTTP/1.1' in frame`` is ``False``.
138+
139+
:class:`~pcapkit.corekit.protochain.ProtoChain` matches more widely: its
140+
:meth:`~pcapkit.corekit.protochain.ProtoChain.index`,
141+
:meth:`~pcapkit.corekit.protochain.ProtoChain.count` and ``in`` also compare each
142+
layer's alias, so ``'HTTP/1.1' in frame.protochain`` is ``True``.
130143

131144
So adding a name to an ``id()`` tuple widens every ``in`` and ``[]`` selector that
132145
can reach it; check the reach before choosing a shape.
@@ -139,7 +152,6 @@ No Invented Suffixes
139152
:class:`~pcapkit.protocols.internet.ipsec.IPsec`,
140153
:class:`~pcapkit.protocols.application.http.HTTP`,
141154
:class:`~pcapkit.protocols.link.vlan.VLAN` and
142-
:class:`~pcapkit.protocols.link.l2tp.L2TP` are the precedent. No ``_Family`` base
143-
exists, and none is to be minted. Where a member already holds the family name, the
144-
member takes its versioned class name instead, as :ref:`above
145-
<protocol-family-canonical-names>`. :issue:`2446`.
155+
:class:`~pcapkit.protocols.link.l2tp.L2TP` are the precedent. No ``_Family`` base is
156+
to be minted. A member that shares the family's protocol name may take a versioned
157+
class name, as :ref:`above <protocol-family-canonical-names>`. :pr:`2446`.

0 commit comments

Comments
 (0)