From 957f2be1be2dbe4032b5adb58a32ce2e16ba6794 Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Sun, 25 Oct 2026 23:46:51 -0400 Subject: [PATCH] docs(tcp): name what the MPTCP and option makers raise; give Quick-Start rate its unit (#2235) TCP._make_mptcp_join raises ProtocolError on a flags combination that is none of SYN, SYN/ACK and ACK, and TCP._make_tcp_options passes on what its option makers raise, yet neither had a Raises section. Add one to each: ProtocolError for both, plus ProtocolNotImplemented for a named MPTCP subtype or alternate checksum algorithm not in its namespace. The TCP Quick-Start Response req_rate and the IPv4, HOPOPT and IPv6-Opts Quick-Start rate fields hold an int since #2167 but gave no unit. State that they are in kbps, 40 * 2 ** N or 0 for N = 0 (RFC 4782 Section 3.1), and add a versionchanged 1.5.0 for the float to int change, matching the FastOpenCookie note from the same fix. Docstring and #: comments only; the AST guard passes, so there is no fail-without-fix test. --- pcapkit/protocols/data/internet/hopopt.py | 12 ++++++++++-- pcapkit/protocols/data/internet/ipv4.py | 12 ++++++++++-- pcapkit/protocols/data/internet/ipv6_opts.py | 12 ++++++++++-- pcapkit/protocols/data/transport/tcp.py | 12 ++++++++++-- pcapkit/protocols/transport/tcp.py | 12 ++++++++++++ 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/pcapkit/protocols/data/internet/hopopt.py b/pcapkit/protocols/data/internet/hopopt.py index 8d49872038..e984f2beb4 100644 --- a/pcapkit/protocols/data/internet/hopopt.py +++ b/pcapkit/protocols/data/internet/hopopt.py @@ -210,11 +210,19 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' class QuickStartOption(Option): - """Data model for HOPOPT Quick Start option.""" + """Data model for HOPOPT Quick Start option. + + .. versionchanged:: 1.5.0 + + ``rate`` is an :obj:`int` rather than a :obj:`float` (:issue:`2167`). + + """ #: QS function. func: 'QSFunction' - #: Rate request/report. + #: Rate request/report, in kbps: ``40 * 2 ** N`` for the Rate Request or + #: Rate Report field ``N``, or ``0`` if ``N`` is ``0`` (:rfc:`4782` + #: Section 3.1). rate: 'int' diff --git a/pcapkit/protocols/data/internet/ipv4.py b/pcapkit/protocols/data/internet/ipv4.py index 81ccf4abbb..f87ed2420d 100644 --- a/pcapkit/protocols/data/internet/ipv4.py +++ b/pcapkit/protocols/data/internet/ipv4.py @@ -409,11 +409,19 @@ def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', aler class QSOption(Option): - """Data model for IPv4 Quick Start (``QS``) option.""" + """Data model for IPv4 Quick Start (``QS``) option. + + .. versionchanged:: 1.5.0 + + ``rate`` is an :obj:`int` rather than a :obj:`float` (:issue:`2167`). + + """ #: QS function. func: 'QSFunction' - #: Rate request/report. + #: Rate request/report, in kbps: ``40 * 2 ** N`` for the Rate Request or + #: Rate Report field ``N``, or ``0`` if ``N`` is ``0`` (:rfc:`4782` + #: Section 3.1). rate: 'int' diff --git a/pcapkit/protocols/data/internet/ipv6_opts.py b/pcapkit/protocols/data/internet/ipv6_opts.py index 1b4d134245..2d8f763f55 100644 --- a/pcapkit/protocols/data/internet/ipv6_opts.py +++ b/pcapkit/protocols/data/internet/ipv6_opts.py @@ -219,11 +219,19 @@ def __init__(self, type: 'Enum_Option', action: 'int', change: 'bool', length: ' class QuickStartOption(Option): - """Data model for IPv6-Opts Quick Start option.""" + """Data model for IPv6-Opts Quick Start option. + + .. versionchanged:: 1.5.0 + + ``rate`` is an :obj:`int` rather than a :obj:`float` (:issue:`2167`). + + """ #: QS function. func: 'QSFunction' - #: Rate request/report. + #: Rate request/report, in kbps: ``40 * 2 ** N`` for the Rate Request or + #: Rate Report field ``N``, or ``0`` if ``N`` is ``0`` (:rfc:`4782` + #: Section 3.1). rate: 'int' diff --git a/pcapkit/protocols/data/transport/tcp.py b/pcapkit/protocols/data/transport/tcp.py index 7b0d5eeb43..5baf4266a2 100644 --- a/pcapkit/protocols/data/transport/tcp.py +++ b/pcapkit/protocols/data/transport/tcp.py @@ -341,9 +341,17 @@ def __init__(self, kind: 'OptionNumber', length: 'int', digest: 'bytes') -> 'Non @info_final class QuickStartResponse(Option): - """Data model for TCP quick start response option.""" + """Data model for TCP quick start response option. - #: Rate request. + .. versionchanged:: 1.5.0 + + ``req_rate`` is an :obj:`int` rather than a :obj:`float` + (:issue:`2167`). + + """ + + #: Rate request, in kbps: ``40 * 2 ** N`` for the Rate Request field + #: ``N``, or ``0`` if ``N`` is ``0`` (:rfc:`4782` Section 3.1). req_rate: 'int' #: TTL difference. ttl_diff: 'int' diff --git a/pcapkit/protocols/transport/tcp.py b/pcapkit/protocols/transport/tcp.py index ef51e8125d..856010acea 100644 --- a/pcapkit/protocols/transport/tcp.py +++ b/pcapkit/protocols/transport/tcp.py @@ -2156,6 +2156,14 @@ def _make_tcp_options(self, options: 'list[Schema_Option | tuple[Enum_Option, di Returns: Tuple of options and total length of options. + Raises: + ProtocolError: If an option maker rejects its option, e.g. a user + timeout too large for 15 bits of minutes, or an MPTCP option + whose fields, or the segment's flags, it cannot encode. + ProtocolNotImplemented: If an option argument given by name, an + MPTCP ``subtype`` or an alternate checksum ``algorithm``, is + not in its namespace and has no default. + Note: The options are emitted in the given order, ``NOP`` and ``EOOL`` included, so that a parsed option list re-emits the same octets. @@ -2975,6 +2983,10 @@ def _make_mptcp_join(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTC Returns: Constructed option schema. + Raises: + ProtocolError: If the segment's flags are none of SYN, SYN/ACK and + ACK. + """ if Enum_Flags.SYN in self._flags and Enum_Flags.ACK not in self._flags: # MP_JOIN-SYN return self._make_join_syn(subtype, opt, **kwargs) # type: ignore[arg-type]