Source code for pcapkit.foundation.analysis.tcp

# -*- coding: utf-8 -*-
"""TCP Datagram Analysis
===========================

.. module:: pcapkit.foundation.analysis.tcp

:mod:`pcapkit.foundation.analysis.tcp` contains
:func:`~pcapkit.foundation.analysis.tcp.tcp_datagram` only, which parses the
application-layer payload of a TCP datagram that
:class:`~pcapkit.foundation.reassembly.tcp.TCP` reassembled.

.. versionadded:: 1.6.0

"""
from typing import TYPE_CHECKING

from pcapkit.const.reg.apptype import TransportProtocol as Enum_TransportProtocol
from pcapkit.protocols.transport.tcp import TCP

if TYPE_CHECKING:
    from typing import Optional, Type

    from pcapkit.const.reg.apptype import TCP as AppType_TCP
    from pcapkit.foundation.reassembly.data.tcp import Datagram as TCP_Datagram
    from pcapkit.protocols.protocol import ProtocolBase

__all__ = ['tcp_datagram']


[docs] def tcp_datagram(datagram: 'TCP_Datagram') -> 'Optional[ProtocolBase]': """Parse the payload of a TCP datagram reassembled by :class:`~pcapkit.foundation.reassembly.tcp.TCP`. A reassembled datagram carries no protocol number, so its payload is dispatched on its ``(source, destination)`` ports by :meth:`Transport.analyze <pcapkit.protocols.transport.transport.Transport.analyze>` of :class:`~pcapkit.protocols.transport.tcp.TCP`. Each port is resolved to its :class:`~pcapkit.const.reg.apptype.tcp.TCP` member by :meth:`Transport._make_port <pcapkit.protocols.transport.transport.Transport._make_port>`, as :meth:`TCP._make_ports <pcapkit.foundation.reassembly.tcp.TCP._make_ports>` resolves them for the reassembly. Args: datagram: Reassembled datagram (:term:`reasm.tcp.datagram`). Returns: The parsed payload. A payload reported as one contiguous run is parsed whether or not ``datagram`` is complete, as ``strict=False`` reports an incomplete one. :data:`None` if the payload is the tuple of runs received, as ``strict=True`` reports an incomplete one. Note: :attr:`Datagram.packet <pcapkit.foundation.reassembly.data.tcp.Datagram.packet>` holds the same result, parsed on its first read, unless the reassembly's ``__protocol_type__`` names another protocol, which then parses it instead. """ if isinstance(datagram.payload, tuple): return None transport = Enum_TransportProtocol.tcp ports = (TCP._make_port(datagram.id.src[1], transport), # pylint: disable=protected-access TCP._make_port(datagram.id.dst[1], transport)) # pylint: disable=protected-access return _analyze_payload(TCP, ports, datagram.payload)
def _analyze_payload(protocol: 'Type[TCP]', ports: 'tuple[AppType_TCP, AppType_TCP]', payload: 'bytes') -> 'ProtocolBase': """Parse a reassembled payload by its datagram's ports. :func:`tcp_datagram` runs this, and so does the :class:`~pcapkit.foundation.reassembly.data.data.Deferred` that :meth:`TCP.submit <pcapkit.foundation.reassembly.tcp.TCP.submit>` stores as a datagram's ``packet``, with the reassembly's own protocol bound as ``protocol``. Args: protocol: The TCP protocol whose ``analyze`` parses ``payload``. ports: The datagram's ``(source, destination)`` ports. payload: The reassembled payload. Returns: The parsed payload. """ return protocol.analyze(ports, payload)