Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/source/pcapkit/foundation/reassembly/reassembly.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Base Class
:mod:`pcapkit.foundation.reassembly.reassembly` contains
:class:`~pcapkit.foundation.reassembly.reassembly.Reassembly` only,
which is an abstract base class for all reassembly classes,
bases on algorithms described in :rfc:`791` and :rfc:`815`,
implements datagram reassembly of IP and TCP packets.
based on algorithms described in :rfc:`791` and :rfc:`815`,
that implement datagram reassembly of IP and TCP packets.

.. autoclass:: pcapkit.foundation.reassembly.reassembly.Reassembly
:no-members:
Expand All @@ -30,7 +30,7 @@ implements datagram reassembly of IP and TCP packets.


.. property:: protocol
:type: typing.Type[Protocol]
:type: typing.Type[pcapkit.protocols.protocol.ProtocolBase]

Protocol of current reassembly class.

Expand Down
3 changes: 2 additions & 1 deletion docs/source/pcapkit/foundation/reassembly/tcp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Algorithm
} give up until (no entry from HDL)
}

The following algorithm implement is based on the **IP Datagram
The following algorithm implementation is based on the **IP Datagram
Reassembly Algorithm** introduced in :rfc:`815`, which presents hole
descriptors as an alternative to the ``RCVBT`` (fragment received bit
table) approach used by the reassembly procedure in :rfc:`791`. And
Expand Down Expand Up @@ -378,5 +378,6 @@ Type Variables

.. data:: pcapkit.foundation.reassembly.data.tcp.BufferID
:type: typing.Tuple[_AT, int, _AT, int]
:no-index:

Buffer ID data structure.
19 changes: 9 additions & 10 deletions docs/source/pcapkit/utilities/exceptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,15 @@ Such an error emits nothing on any channel and touches no process-global state.
It is still an ordinary exception carrying its message, so ``except`` clauses and
:func:`repr` are unaffected.

.. attention::

Up to and including v1.4.1, ``quiet=True`` logged at ``ERROR`` instead of
``CRITICAL`` rather than not logging, and :data:`sys.tracebacklimit` was set
on both paths. A single ``MultiDict.get()`` miss therefore produced an
``ERROR`` record -- one per frame when parsing unfragmented IPv6 with
reassembly enabled -- and truncated the tracebacks of unrelated exceptions
for the rest of the process. Those records never corresponded to a fault and
are gone; to observe internal lookup misses, catch the exception rather than
read the log.
.. versionchanged:: 1.5.0

In 1.4.x, ``quiet=True`` logged at ``ERROR`` instead of ``CRITICAL`` rather
than not logging, and :data:`sys.tracebacklimit` was set on both paths. A
single ``MultiDict.get()`` miss therefore produced an ``ERROR`` record -- one
per frame when parsing unfragmented IPv6 with reassembly enabled -- and
truncated the tracebacks of unrelated exceptions for the rest of the process.
Those records never corresponded to a fault; to observe internal lookup
misses, catch the exception rather than read the log (:issue:`362`).

.. autoexception:: pcapkit.utilities.exceptions.BaseError
:no-members:
Expand Down
16 changes: 11 additions & 5 deletions docs/source/pcapkit/utilities/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ Logging System
at :data:`~pcapkit.utilities.logging.logger`, and the API through which an
application decides what, if anything, :mod:`pcapkit` emits.

.. versionchanged:: 1.5.0

Importing :mod:`pcapkit` attaches only a :class:`logging.NullHandler` and
sets no level; 1.4.x attached a :obj:`sys.stderr` handler at
:data:`logging.INFO`.

.. autodata:: pcapkit.utilities.logging.logger
:no-value:

Expand Down Expand Up @@ -142,9 +148,9 @@ Compatibility Note
Before 1.5.0, importing :mod:`pcapkit` attached a
:class:`logging.StreamHandler` on :obj:`sys.stderr` and forced the level to
:data:`logging.INFO` (or :data:`logging.DEBUG` under
:envvar:`PCAPKIT_DEVMODE`). It no longer does, because that hijacked the
logging configuration of every application importing :mod:`pcapkit`. Two
consequences are visible to existing code:
:envvar:`PCAPKIT_DEVMODE`). That hijacked the logging configuration of every
application importing :mod:`pcapkit`, so 1.5.0 does it only under
:envvar:`PCAPKIT_DEVMODE`. Two consequences are visible to existing code:

1. **Nothing reaches stderr by default.** The ``registered ...`` bookkeeping
is at :data:`logging.DEBUG`, not :data:`logging.INFO`. To restore the
Expand All @@ -156,8 +162,8 @@ Compatibility Note
from pcapkit.utilities.logging import configure
configure(logging.INFO, stream=sys.stderr)

Equivalently, re-attach the module's own handler, which is still built
with the historical format:
Equivalently, re-attach the module's own handler, which is built with the
1.4.x format:

.. code-block:: python

Expand Down
21 changes: 13 additions & 8 deletions docs/source/pcapkit/utilities/warnings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ User Defined Warnings

:mod:`pcapkit.utilities.warnings` refined built-in warnings.

.. versionremoved:: 1.5.0

``pcapkit.utilities.warnings.DEVMODE``, which 1.4.x imported from
:mod:`pcapkit.utilities.logging`; read
:data:`pcapkit.utilities.logging.DEVMODE` instead.

How a Warning Is Reported
-------------------------

Expand Down Expand Up @@ -79,16 +85,15 @@ configured separately, through the :mod:`logging` module::

logging.getLogger('pcapkit').setLevel(logging.ERROR) # drop WARNING records

.. attention::
.. versionchanged:: 1.5.0

Up to and including v1.4.1, constructing a
:mod:`pcapkit` warnings reach the :mod:`warnings` channel by default, and
the first snippet above restores the 1.4.x quiet. In 1.4.x, constructing a
:class:`~pcapkit.utilities.warnings.BaseWarning` installed an ``ignore``
filter for its own class, so :mod:`pcapkit` warnings were invisible on the
:mod:`warnings` channel by default and a caller could not re-enable them.
They are now delivered; the first snippet above restores the old quiet. The
filter went at the *front* of the process-global :data:`warnings.filters`, so
it also overrode the host application's own configuration for those
categories and made unrelated warnings re-fire.
filter for its own class, so a caller could not re-enable them. The filter
went at the *front* of the process-global :data:`warnings.filters`, so it
also overrode the host application's own configuration for those categories
and made unrelated warnings re-fire (:issue:`364`).

.. autoexception:: pcapkit.utilities.warnings.BaseWarning
:no-members:
Expand Down
20 changes: 20 additions & 0 deletions pcapkit/dumpkit/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ class MyMixin(Dumper): # not registered

register_dumper('my_mixin', MyMixin, '.mine')

.. versionchanged:: 1.5.0

Registration is opt-in, under the ``fmt`` class keyword; 1.4.x
registered every subclass, under its
:attr:`~dictdumper.dumper.Dumper.kind` when the keyword was omitted
(:issue:`514`).

"""

def __init_subclass__(cls, /, fmt: 'Optional[str]' = None,
Expand Down Expand Up @@ -307,6 +314,19 @@ def make_dumper(output: 'Type[ABCDumper]') -> 'Type[ABCDumper]':
Returns:
Customised :class:`~dictdumper.dumper.Dumper` object.

.. versionchanged:: 1.5.0

Several dumped shapes change. A nameless flag value renders its value
as the name, ``Flags::0 [0]`` rather than ``Flags::None [0]``
(:issue:`648`). An :class:`~pcapkit.corekit.multidict.OrderedMultiDict`
dumps as a list of one-key mappings in wire order, not grouped by key
(:issue:`1263`). A timezone dumps as its offset in seconds, and
:data:`~pcapkit.corekit.sentinels.NULL` and
:data:`~pcapkit.corekit.sentinels.NO_VALUE` as ``'<NULL>'`` and
``'<NO_VALUE>'`` (:issue:`1258`). In ``plist`` output, :data:`None` is
kept (:issue:`1257`), and a string carrying a character XML forbids
is written as ``<data>`` (:issue:`1262`).

"""
# NOTE: :class:`~dictdumper.plist.PLIST` -- which is also what
# :attr:`Extractor.__output__ <pcapkit.foundation.extraction.Extractor.__output__>`
Expand Down
7 changes: 7 additions & 0 deletions pcapkit/dumpkit/pcap.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ class PCAPIO(DumperBase):
**kwargs: further global header fields, i.e. ``version``, ``thiszone``,
``sigfigs`` and ``snaplen``, and arbitrary keyword arguments

.. versionchanged:: 1.5.0

The global header takes ``version``, ``thiszone``, ``sigfigs`` and
``snaplen`` from ``**kwargs``, so ``format='pcap'`` output keeps the
input's values; 1.4.x wrote the defaults (:issue:`1165`,
:issue:`1255`).

"""
if TYPE_CHECKING:
#: PCAP file global header.
Expand Down
7 changes: 7 additions & 0 deletions pcapkit/foundation/engines/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ class MyMixin(Engine): # not registered
Args:
extractor: :class:`~pcapkit.foundation.extraction.Extractor` instance.

.. versionchanged:: 1.5.0

Registration is opt-in, under the ``engine`` class keyword, which
replaces 1.4.x's ``name`` with no alias; 1.4.x registered every
subclass, under its class name when ``name`` was omitted
(:issue:`514`).

"""

def __init_subclass__(cls, /, engine: 'Optional[str]' = None, *args: 'Any', **kwargs: 'Any') -> 'None':
Expand Down
16 changes: 14 additions & 2 deletions pcapkit/foundation/extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
:class:`~pcapkit.foundation.extraction.Extractor` only,
which synthesises file I/O and protocol analysis,
coordinates information exchange in all network layers,
extracts parametres from a PCAP file.
extracts parameters from a PCAP file.

"""
import collections
Expand Down Expand Up @@ -108,6 +108,18 @@ class Extractor(Generic[_P]):
For supported engines, please refer to
:meth:`~pcapkit.foundation.extraction.Extractor.run`.

.. versionchanged:: 1.5.0

``layer`` and ``protocol`` stop the dissection where they say, which
1.4.x ignored (:issue:`356`). A stream given as ``fin`` is left open:
only a file the extractor opened itself is closed (:issue:`610`).
``reasm_timeout``, ``trace_bidirectional`` and ``trace_analyse`` are
inserted among the positional parameters and ``context`` is appended,
so a positional argument after ``reasm_store`` has to move to a
keyword. Flows are traced bidirectionally by default. :attr:`engine`
is typed :class:`~pcapkit.foundation.engines.engine.EngineBase`, the
base every engine derives from (:issue:`1022`).

"""
if TYPE_CHECKING:
#: Input file name.
Expand Down Expand Up @@ -1075,7 +1087,7 @@ def __init__(self,

Args:
fin: file name to be read or a binary IO object;
if file not exist, raise :exc:`FileNotFound`
if file not exist, raise :exc:`~pcapkit.utilities.exceptions.FileNotFound`
fout: file name to be written
format: file format of output

Expand Down
2 changes: 1 addition & 1 deletion pcapkit/foundation/reassembly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

.. module:: pcapkit.foundation.reassembly

:mod:`pcapkit.foundation.reassembly` bases on algorithms described
:mod:`pcapkit.foundation.reassembly`, based on algorithms described
in :rfc:`791` and :rfc:`815`, implements datagram reassembly
of IP and TCP packets.

Expand Down
2 changes: 2 additions & 0 deletions pcapkit/foundation/reassembly/data/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ class Deferred:
proto: Payload protocol type.
payload: Reassembled payload to parse.

.. versionadded:: 1.5.0

"""

__slots__ = ('analyze', 'proto', 'payload')
Expand Down
10 changes: 10 additions & 0 deletions pcapkit/foundation/reassembly/data/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,16 @@ class HoleDescriptor(Info):
whole; a hole whose ``first`` is ``-sys.maxsize`` stands for whatever
preceded a capture that missed the handshake, and does not count.

.. versionadded:: 1.5.0

Replaces the misspelt ``HoleDiscriptor``.

.. versionremoved:: 1.5.0

``HoleDiscriptor``, and its re-export
``pcapkit.foundation.reassembly.data.TCP_HoleDiscriptor``, with no
alias; import ``HoleDescriptor`` and ``TCP_HoleDescriptor`` instead.

"""

#: Sequence number of the first missing octet.
Expand Down
19 changes: 14 additions & 5 deletions pcapkit/foundation/reassembly/ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
:mod:`pcapkit.foundation.reassembly.ip` contains
:class:`~pcapkit.foundation.reassembly.ip.IP`
only, which reconstructs fragmented IP packets back to
origin. The following algorithm implement is based on IP
reassembly procedure introduced in :rfc:`791`, using
``RCVBT`` (fragment received bit table). Though another
algorithm is explained in :rfc:`815`, replacing ``RCVBT``,
however, this implement still used the elder one.
origin. The implementation follows the IP reassembly
procedure introduced in :rfc:`791`, using ``RCVBT``
(fragment received bit table). :rfc:`815` explains another
algorithm, replacing ``RCVBT``, but this implementation
uses the elder one.

"""
from typing import TYPE_CHECKING, Generic
Expand Down Expand Up @@ -57,6 +57,15 @@ class IP(ReassemblyBase[Packet[_AT], Datagram[_AT], BufferID, Buffer[_AT]], Gene
but rather used as a base class for the protocol-aware
reassembly classes.

.. versionchanged:: 1.5.0

An overlapping fragment that disagrees with octets already received is
recorded in :attr:`Datagram.conflict
<pcapkit.foundation.reassembly.data.ip.Datagram.conflict>` rather than
overwriting them unnoticed (:issue:`477`). An incomplete buffer expires
after ``timeout`` seconds of capture time, 60 by default for both IPv4
and IPv6.

"""
if TYPE_CHECKING:
protocol: 'Type[IP_Protocol]'
Expand Down
7 changes: 7 additions & 0 deletions pcapkit/foundation/reassembly/ipv6.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ class IPv6(IP):
# Fetch result:
>>> result = ipv6_reassembly.datagram

.. versionchanged:: 1.5.0

The reassembled ``header`` leaves out the Fragment header and carries
its Next Header, per :rfc:`8200#section-4.5`, whichever engine fed it;
1.4.x kept the Fragment header on the ``default`` and ``pcapng``
engines (:issue:`415`).

"""

##########################################################################
Expand Down
11 changes: 9 additions & 2 deletions pcapkit/foundation/reassembly/reassembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
:mod:`pcapkit.foundation.reassembly.reassembly` contains
:class:`~pcapkit.foundation.reassembly.reassembly.Reassembly` only,
which is an abstract base class for all reassembly classes,
bases on algorithms described in :rfc:`791` and :rfc:`815`,
implements datagram reassembly of IP and TCP packets.
based on algorithms described in :rfc:`791` and :rfc:`815`,
that implement datagram reassembly of IP and TCP packets.

"""
import abc
Expand Down Expand Up @@ -541,6 +541,13 @@ class MyMixin(Reassembly): # not registered
timeout: reassembly timeout in seconds, on the capture's own clock;
:data:`None` selects the protocol's :attr:`__timeout__` default

.. versionchanged:: 1.5.0

Registration is opt-in, under the ``protocol`` class keyword; 1.4.x
registered every subclass, under its :attr:`name` when the keyword was
omitted (:issue:`514`). The ``timeout`` argument is added: a buffer
older than it on the capture's clock is abandoned.

"""

def __init_subclass__(cls, /, protocol: 'Optional[str]' = None, *args: 'Any', **kwargs: 'Any') -> 'None':
Expand Down
8 changes: 8 additions & 0 deletions pcapkit/foundation/reassembly/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ class TCP(ReassemblyBase[Packet, Datagram, BufferID, Buffer]):
start is the SYN's own sequence number, and a FIN completes the
stream only when every octet from there up to the FIN has arrived.

.. versionchanged:: 1.5.0

Of two overlapping segments that disagree, the octets received first
are kept, per :rfc:`9293#section-3.10`, and the contested range is
recorded in :attr:`Datagram.conflict
<pcapkit.foundation.reassembly.data.tcp.Datagram.conflict>`; 1.4.x
kept the later octets without a record (:issue:`443`).

"""
if TYPE_CHECKING:
protocol: 'Type[TCP_Protocol]'
Expand Down
10 changes: 10 additions & 0 deletions pcapkit/foundation/registry/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,11 @@ def register_mh_extension(code: 'MH_CGAExtension', meth: 'str | tuple[MH_Extensi
schema: :class:`~pcapkit.protocols.schema.schema.Schema` class for the message type.
It should be a subclass of :class:`pcapkit.protocols.schema.internet.mh.CGAExtension`.

.. versionchanged:: 1.5.0

``schema`` is keyword-only, as in the other ``register_*`` functions
that take one (:issue:`516`).

"""
if isinstance(meth, str) and not hasattr(MH, f'_read_ext_{meth}'):
raise RegistryError('method must be a valid MH CGA extension function')
Expand Down Expand Up @@ -1031,6 +1036,11 @@ def register_apptype(code: 'int | Enum_AppType', module: 'str | ModuleDescriptor
* :func:`pcapkit.foundation.registry.register_udp`
* :func:`pcapkit.foundation.registry.register_sctp`

.. versionchanged:: 1.5.0

The keyword-only ``proto`` is replaced by ``*transport``, one transport
protocol per argument, with no alias (:issue:`806`).

"""
# NOTE: ``class_`` sits at the sibling position -- positional, ahead of
# ``*transport`` -- per maintainer ruling, so a third positional that is
Expand Down
2 changes: 0 additions & 2 deletions pcapkit/foundation/traceflow/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ class TCP(TraceFlowBase[BufferID, Buffer[_AT], Index, Packet[_AT]], Generic[_AT]
analyse: reassemble each flow's application layer, so that
:attr:`Index.packet <pcapkit.foundation.traceflow.data.tcp.Index.packet>`
can be read
*args: Arbitrary positional arguments.
**kwargs: Arbitrary keyword arguments.

Note:
A TCP connection has two halves, and by default they are traced as **one
Expand Down
Loading
Loading