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
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ the MRO, so whichever base owns it *earliest* wins:
:obj:`None` from :class:`~pcapkit.protocols.protocol.ProtocolBase` -- so a class
naming both :class:`~pcapkit.protocols.application.application.Application` and
:class:`~pcapkit.protocols.misc.raw.Raw` reports ``'Application'`` in either base order.
:class:`~pcapkit.protocols.application.ftp.FTP_DATA` names
:class:`~pcapkit.protocols.misc.raw.Raw` alone, so its ``__layer__`` is :obj:`None`.
So :class:`~pcapkit.protocols.application.ftp_data.FTP_DATA`, declared
``class FTP_DATA(Application, Raw)``, reports ``'Application'``.
:class:`~pcapkit.protocols.link.arp.ARP`'s chain reaches
:class:`~pcapkit.protocols.link.link.Link`, which **does** own it, so
``class RARP(ARP, Application)`` would report ``'Link'`` and be wrong.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/contributing/pep.rst
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ Some wanted only a table entry, because the dissector was already there:
:class:`~pcapkit.protocols.link.l2tpv2.L2TPv2` at UDP port 1701.
``__index__`` raises on both, which is correct: neither is reached through a
link-layer EtherType.
* **Done.** :class:`~pcapkit.protocols.application.ftp.FTP_DATA` is bound at TCP
* **Done.** :class:`~pcapkit.protocols.application.ftp_data.FTP_DATA` is bound at TCP
port 20 (IANA ``ftp-data``). It is a thin
:class:`~pcapkit.protocols.misc.raw.Raw` subclass, so this buys the payload a
*name* rather than a parse -- which is the right answer for a data channel
Expand Down
2 changes: 1 addition & 1 deletion docs/source/ext.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The protocol classes :mod:`pcapkit` ships:
+------------------------------------------------------------------+----------------+-----------------------+-------------------------------------------------------------+
| | | :class:`pcapkit.protocols.application.ftp.FTP` |
+ + FTP Family +-----------------------+-------------------------------------------------------------+
| | | :class:`pcapkit.protocols.application.ftp.FTP_DATA` |
| | | :class:`pcapkit.protocols.application.ftp_data.FTP_DATA` |
+ Application Layer +----------------+-----------------------+-------------------------------------------------------------+
| (:class:`~pcapkit.protocols.application.application.Application` | | :class:`pcapkit.protocols.application.http.HTTP` |
+ subclasses) + +-----------------------+-------------------------------------------------------------+
Expand Down
18 changes: 10 additions & 8 deletions docs/source/pcapkit/protocols/application/ftp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ FTP - File Transfer Protocol
:mod:`pcapkit.protocols.application.ftp` contains
:class:`~pcapkit.protocols.application.ftp.FTP`,
which implements an extractor for File Transfer Protocol
(FTP) [*]_, and :class:`~pcapkit.protocols.application.ftp.FTP_DATA`
for its data channel.
(FTP) [*]_, the control channel; the data channel is
:class:`~pcapkit.protocols.application.ftp_data.FTP_DATA`, in
:mod:`pcapkit.protocols.application.ftp_data`.

.. versionchanged:: 1.5.0

Expand All @@ -17,6 +18,13 @@ for its data channel.
parse and rebuild as captured (:issue:`1238`, :issue:`1239`,
:issue:`1240`, :issue:`1241`, :issue:`1303`, :issue:`1333`).

.. versionremoved:: 1.5.0

``pcapkit.protocols.application.ftp.FTP_DATA``, with no alias. The class
moved to :mod:`pcapkit.protocols.application.ftp_data`, since TCP port 20
dispatches it and port 21 the control channel -- two protocols, so two
modules (:issue:`2285`).

.. autoclass:: pcapkit.protocols.application.ftp.FTP
:no-members:
:show-inheritance:
Expand All @@ -29,12 +37,6 @@ for its data channel.

.. automethod:: _make_data

.. autoclass:: pcapkit.protocols.application.ftp.FTP_DATA
:no-members:
:show-inheritance:

.. autoproperty:: name

Auxiliary Data
--------------

Expand Down
29 changes: 29 additions & 0 deletions docs/source/pcapkit/protocols/application/ftp_data.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FTP_DATA - FTP Data Channel
===========================

.. module:: pcapkit.protocols.application.ftp_data

:mod:`pcapkit.protocols.application.ftp_data` contains
:class:`~pcapkit.protocols.application.ftp_data.FTP_DATA` only,
which implements an extractor for the data channel of File
Transfer Protocol (FTP) [*]_, whose octets it keeps undissected.

.. versionadded:: 1.5.0

Moved here from :mod:`pcapkit.protocols.application.ftp`, which keeps
:class:`~pcapkit.protocols.application.ftp.FTP` alone. The control and data
channels are dispatched separately -- FTP at TCP port 21, the data channel
at port 20 -- so each is a protocol of its own and gets its own module,
unlike :class:`~pcapkit.protocols.application.rarp.RARP` and
:class:`~pcapkit.protocols.application.rarp.DRARP`, which one dispatch
entry reaches (:issue:`2285`).

.. autoclass:: pcapkit.protocols.application.ftp_data.FTP_DATA
:no-members:
:show-inheritance:

.. autoproperty:: name

.. rubric:: Footnotes

.. [*] https://en.wikipedia.org/wiki/File_Transfer_Protocol
1 change: 1 addition & 0 deletions docs/source/pcapkit/protocols/application/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function rather than encapsulation, see
httpv1
httpv2
ftp
ftp_data
ngap
ospf
rarp
Expand Down
4 changes: 2 additions & 2 deletions docs/source/pcapkit/protocols/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`:
end

subgraph application [Application Layer]
Application --> HTTP & FTP & NGAP & OSPF & RARP
Application --> HTTP & FTP & FTP_DATA & NGAP & OSPF & RARP

subgraph http [HTTP Family]
HTTP --> h1["HTTP/1.*"] & h2["HTTP/2"]
Expand Down Expand Up @@ -145,7 +145,7 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`:
click h1 "application/httpv1.html#pcapkit.protocols.application.httpv1.HTTP"
click h2 "application/httpv2.html#pcapkit.protocols.application.httpv2.HTTP"
click FTP "application/ftp.html#pcapkit.protocols.application.ftp.FTP"
click FTP_DATA "application/ftp.html#pcapkit.protocols.application.ftp.FTP_DATA"
click FTP_DATA "application/ftp_data.html#pcapkit.protocols.application.ftp_data.FTP_DATA"
click NGAP "application/ngap.html#pcapkit.protocols.application.ngap.NGAP"
click OSPF "application/ospf.html#pcapkit.protocols.application.ospf.OSPF"
click RARP "application/rarp.html#pcapkit.protocols.application.rarp.RARP"
Expand Down
2 changes: 1 addition & 1 deletion examples/generators/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ def _link_enum() -> 'Any':
'internet/Shim6': ('pcapkit.protocols.internet.ipv6_ext', 'IPv6_Ext'),

# -- TCP.__proto__ (port) --------------------------------------------------
'tcp/20': ('pcapkit.protocols.application.ftp', 'FTP_DATA'),
'tcp/20': ('pcapkit.protocols.application.ftp_data', 'FTP_DATA'),
'tcp/21': ('pcapkit.protocols.application.ftp', 'FTP'),
# The version-identifying proxy (#682), as for ``udp/80`` and ``udp/8080``
# below.
Expand Down
3 changes: 2 additions & 1 deletion pcapkit/protocols/application/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
from pcapkit.protocols.application.application import Application

# Utility Classes for Protocols
from pcapkit.protocols.application.ftp import FTP, FTP_DATA
from pcapkit.protocols.application.ftp import FTP
from pcapkit.protocols.application.ftp_data import FTP_DATA
from pcapkit.protocols.application.httpv1 import HTTP as HTTPv1
from pcapkit.protocols.application.httpv2 import HTTP as HTTPv2
from pcapkit.protocols.application.ngap import NGAP
Expand Down
30 changes: 11 additions & 19 deletions pcapkit/protocols/application/ftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
:mod:`pcapkit.protocols.application.ftp` contains
:class:`~pcapkit.protocols.application.ftp.FTP`,
which implements an extractor for File Transfer Protocol
(FTP) [*]_, and
:class:`~pcapkit.protocols.application.ftp.FTP_DATA`
for its data channel.
(FTP) [*]_, the control channel; the data channel is
:class:`~pcapkit.protocols.application.ftp_data.FTP_DATA`, in
:mod:`pcapkit.protocols.application.ftp_data`.

.. [*] https://en.wikipedia.org/wiki/File_Transfer_Protocol

Expand All @@ -21,6 +21,13 @@
parse and rebuild as captured (:issue:`1238`, :issue:`1239`,
:issue:`1240`, :issue:`1241`, :issue:`1303`, :issue:`1333`).

.. versionremoved:: 1.5.0

``pcapkit.protocols.application.ftp.FTP_DATA``, with no alias. The class
moved to :mod:`pcapkit.protocols.application.ftp_data`, since TCP port 20
dispatches it and port 21 the control channel -- two protocols, so two
modules (:issue:`2285`).

"""
import re
from typing import TYPE_CHECKING
Expand All @@ -32,7 +39,6 @@
from pcapkit.protocols.data.application.ftp import FTP as Data_FTP
from pcapkit.protocols.data.application.ftp import Request as Data_Request
from pcapkit.protocols.data.application.ftp import Response as Data_Response
from pcapkit.protocols.misc.raw import Raw
from pcapkit.protocols.schema.application.ftp import FTP as Schema_FTP
from pcapkit.utilities.chardet import detect
from pcapkit.utilities.compat import StrEnum, auto
Expand All @@ -43,7 +49,7 @@

from typing_extensions import Literal

__all__ = ['FTP', 'FTP_DATA']
__all__ = ['FTP']

# regex for FTP, per :rfc:`959#section-4` (replies) and :rfc:`959#section-5`
# (commands): a command is ``<command> [<SP> <argument>] <CRLF>``, a reply line is
Expand Down Expand Up @@ -322,17 +328,3 @@ def _decode_args(self, args: 'Optional[bytes]') -> 'tuple[Optional[str], Optiona
except (LookupError, UnicodeError):
pass
return args.decode('latin-1'), 'latin-1'


class FTP_DATA(Raw):
"""This class implements FTP data channel transmission."""

##########################################################################
# Properties.
##########################################################################

# name of current protocol
@property
def name(self) -> 'Literal["FTP_DATA"]': # type: ignore[override]
"""Name of current protocol."""
return 'FTP_DATA'
64 changes: 64 additions & 0 deletions pcapkit/protocols/application/ftp_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
"""FTP_DATA - FTP Data Channel
=================================

.. module:: pcapkit.protocols.application.ftp_data

:mod:`pcapkit.protocols.application.ftp_data` contains
:class:`~pcapkit.protocols.application.ftp_data.FTP_DATA` only,
which implements an extractor for the data channel of File
Transfer Protocol (FTP) [*]_, whose octets it keeps undissected.

.. [*] https://en.wikipedia.org/wiki/File_Transfer_Protocol

.. versionadded:: 1.5.0

Moved here from :mod:`pcapkit.protocols.application.ftp`, which keeps
:class:`~pcapkit.protocols.application.ftp.FTP` alone. The control and data
channels are dispatched separately -- FTP at TCP port 21, the data channel
at port 20 -- so each is a protocol of its own and gets its own module,
unlike :class:`~pcapkit.protocols.application.rarp.RARP` and
:class:`~pcapkit.protocols.application.rarp.DRARP`, which one dispatch
entry reaches (:issue:`2285`).

"""
from typing import TYPE_CHECKING

from pcapkit.protocols.application.application import Application
from pcapkit.protocols.misc.raw import Raw

if TYPE_CHECKING:
from typing_extensions import Literal

__all__ = ['FTP_DATA']


class FTP_DATA(Application, Raw): # pylint: disable=abstract-method
"""This class implements FTP data channel transmission.

The layer base :class:`~pcapkit.protocols.application.application.Application`
comes first, for ``layer == 'Application'``, then the parsing base
:class:`~pcapkit.protocols.misc.raw.Raw`, which keeps the channel's octets
undissected. See :doc:`/contributing/conventions/protocol-layer-placement`.

.. versionchanged:: 1.5.0

Derives from :class:`~pcapkit.protocols.application.application.Application`
as well as :class:`~pcapkit.protocols.misc.raw.Raw`, so its layer is
``'Application'``, where it was :obj:`None`, and its ``__index__`` is
:meth:`Application.__index__
<pcapkit.protocols.application.application.Application.__index__>`,
raising :exc:`~pcapkit.utilities.exceptions.IntError` where it raised
:exc:`~pcapkit.utilities.exceptions.UnsupportedCall` (:issue:`2285`).

"""

##########################################################################
# Properties.
##########################################################################

# name of current protocol
@property
def name(self) -> 'Literal["FTP_DATA"]': # type: ignore[override]
"""Name of current protocol."""
return 'FTP_DATA'
4 changes: 2 additions & 2 deletions pcapkit/protocols/transport/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class TCP(Transport[Data_TCP, Schema_TCP],
* - Port Number
- Protocol
* - 20
- :class:`pcapkit.protocols.application.ftp.FTP_DATA`
- :class:`pcapkit.protocols.application.ftp_data.FTP_DATA`
* - 21
- :class:`pcapkit.protocols.application.ftp.FTP`
* - 80
Expand Down Expand Up @@ -362,7 +362,7 @@ class TCP(Transport[Data_TCP, Schema_TCP],
# connection preface, then an HTTP/1 start line) and trial-parses
# only as a last resort. UDP's table binds the same class for the
# same ports.
20: ModuleDescriptor('pcapkit.protocols.application.ftp', 'FTP_DATA'),
20: ModuleDescriptor('pcapkit.protocols.application.ftp_data', 'FTP_DATA'),
21: ModuleDescriptor('pcapkit.protocols.application.ftp', 'FTP'),
80: ModuleDescriptor('pcapkit.protocols.application.http', 'HTTP'),
8080: ModuleDescriptor('pcapkit.protocols.application.http', 'HTTP'),
Expand Down
6 changes: 3 additions & 3 deletions tests/project/test_all_layer_grouping_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ def classes_on(self, layer: 'str') -> 'set[str]':
def foreign(self, group: 'list[str]', layer: 'str') -> 'set[str]':
"""Names in ``group`` whose class reports a layer other than ``layer``.

A class whose ``__layer__`` is unset (``FTP_DATA`` subclasses ``Raw``) is not
foreign.
An unset ``__layer__`` is foreign too: a class that names no layer base
reports :obj:`None` and would otherwise pass unnoticed (#2285).
"""
return {name for name in group
if (getattr(self.exported.get(name), '__layer__', None) or layer) != layer}
if getattr(self.exported.get(name), '__layer__', None) != layer}

def test_groups_are_found(self) -> None:
self.assertIn('ARP', self.link)
Expand Down
4 changes: 4 additions & 0 deletions tests/project/test_no_moved_name_re_exports_1744_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
('pcapkit.foundation.reassembly.data', 'DeferredPacket'),
('pcapkit.foundation.reassembly.data.data', 'DeferredPacket'),
('pcapkit.foundation.traceflow.data.data', 'DeferredPacket'),
('pcapkit.protocols.application.ftp', 'FTP_DATA'),
('pcapkit.protocols.application.ngap', 'ProcedureCode'),
('pcapkit.protocols.application.ngap', 'ProtocolIE'),
('pcapkit.protocols.internet.mh', 'NTPTimestamp'),
Expand All @@ -80,6 +81,9 @@
'pcapkit/corekit/fields/field.py', 'pcapkit/corekit/fields/field.rst'),
('pcapkit.protocols.internet.mh', 'NTPTimestamp',
'pcapkit/protocols/internet/mh.py', 'pcapkit/protocols/internet/mh.rst'),
('pcapkit.protocols.application.ftp', 'FTP_DATA',
'pcapkit/protocols/application/ftp.py',
'pcapkit/protocols/application/ftp.rst'),
)


Expand Down
2 changes: 1 addition & 1 deletion tests/project/test_rfc_constants_one_home_1739_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@
('pcapkit/protocols/transport/tcp.py', 'bytes(20)'):
'an MP_JOIN SYN/ACK HMAC default of 20 octets',
('pcapkit/protocols/transport/tcp.py',
"{20: ModuleDescriptor('pcapkit.protocols.application.ftp', 'FTP_DATA')}"):
"{20: ModuleDescriptor('pcapkit.protocols.application.ftp_data', 'FTP_DATA')}"):
'the FTP data port, not the minimum header length',
('pcapkit/protocols/transport/tcp.py', 'schema.length not in (4, 12, 20, 22, 24)'):
'the MP_CAPABLE option lengths, :rfc:`8684#section-3.1`',
Expand Down
2 changes: 1 addition & 1 deletion tests/protocols/application/test_ftp_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def test_ftp_make_data_preserves_request_and_response_fields(self) -> None:
)

def test_ftp_data_channel_name_is_stable(self) -> None:
from pcapkit.protocols.application.ftp import FTP_DATA
from pcapkit.protocols.application.ftp_data import FTP_DATA

ftp_data = object.__new__(FTP_DATA)

Expand Down
Loading
Loading