Skip to content

Commit 27467f1

Browse files
committed
working on MH protocol impl (message types)
1 parent 6d1853b commit 27467f1

File tree

5 files changed

+333
-9
lines changed

5 files changed

+333
-9
lines changed

pcapkit/protocols/data/internet/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@
201201
from pcapkit.protocols.data.internet.mh import CareofTestInitMessage as MH_CareofTestInitMessage
202202
from pcapkit.protocols.data.internet.mh import HomeTestMessage as MH_HomeTestMessage
203203
from pcapkit.protocols.data.internet.mh import CareofTestMessage as MH_CareofTestMessage
204+
from pcapkit.protocols.data.internet.mh import BindingUpdateMessage as MH_BindingUpdateMessage
205+
from pcapkit.protocols.data.internet.mh import BindingAcknowledgementMessage as MH_BindingAcknowledgementMessage
204206

205207
__all__ = [
206208
# Authentication Header

pcapkit/protocols/data/internet/mh.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
"""data model for MH protocol"""
33

44
from typing import TYPE_CHECKING
5+
from pcapkit.const.mh import status_code
56

67
from pcapkit.corekit.infoclass import info_final
78
from pcapkit.protocols.data.data import Data
89

910
if TYPE_CHECKING:
10-
from datetime import datetime as dt_type
11+
from datetime import datetime as dt_type, timedelta
1112
from ipaddress import IPv6Address, IPv6Network
1213

1314
from pcapkit.const.mh.access_type import AccessType as Enum_AccessType
@@ -60,11 +61,12 @@
6061
from pcapkit.const.reg.transtype import TransType
6162
from pcapkit.corekit.multidict import OrderedMultiDict
6263
from pcapkit.protocols.internet.mh import NTPTimestamp
64+
from pcapkit.const.mh.binding_error import BindingError as Enum_BindingError
6365

6466
__all__ = [
6567
'MH',
6668
'UnknownMessage', 'BindingRefreshRequestMessage', 'HomeTestInitMessage', 'CareofTestInitMessage',
67-
'HomeTestMessage', 'CareofTestMessage',
69+
'HomeTestMessage', 'CareofTestMessage', 'BindingUpdateMessage', 'BindingAcknowledgementMessage',
6870

6971
'Option',
7072
'UnassignedOption', 'PadOption', 'BindRefreshAdviceOption', 'AlternateCareofAddressOption',
@@ -182,6 +184,50 @@ def __init__(self, next: 'TransType', length: 'int', type: 'Packet', chksum: 'by
182184
options: 'OrderedMultiDict[Enum_Option, Option]') -> 'None': ...
183185

184186

187+
@info_final
188+
class BindingUpdateMessage(MH):
189+
"""Data model for MH Binding Update message type."""
190+
191+
#: Sequence number.
192+
seq: 'int'
193+
#: Acknowledge flag.
194+
ack: 'bool'
195+
#: home registration flag.
196+
home: 'bool'
197+
#: Link-local address compability flag.
198+
lla_compat: 'bool'
199+
#: Key management mobility capability flag.
200+
key_mngt: 'bool'
201+
#: Lifetime.
202+
lifetime: 'timedelta'
203+
#: Mobility options.
204+
options: 'OrderedMultiDict[Enum_Option, Option]'
205+
206+
if TYPE_CHECKING:
207+
def __init__(self, next: 'TransType', length: 'int', type: 'Packet', chksum: 'bytes',
208+
seq: 'int', ack: 'bool', home: 'bool', lla_compat: 'bool', key_mngt: 'bool',
209+
lifetime: 'timedelta', options: 'OrderedMultiDict[Enum_Option, Option]') -> 'None': ...
210+
211+
212+
@info_final
213+
class BindingAcknowledgementMessage(MH):
214+
"""Data model for MH Binding Acknowledge (BA) message type."""
215+
216+
#: Status.
217+
status: 'Enum_StatusCode'
218+
#: Key management mobility capability flag.
219+
key_mngt: 'bool'
220+
#: Sequence number.
221+
seq: 'int'
222+
#: Lifetime.
223+
lifetime: 'timedelta'
224+
#: Mobility options.
225+
options: 'OrderedMultiDict[Enum_Option, Option]'
226+
227+
if TYPE_CHECKING:
228+
def __init__(self, next: 'TransType', length: 'int', type: 'Packet', chksum: 'bytes',
229+
status: 'Enum_StatusCode', key_mngt: 'bool', seq: 'int', lifetime: 'timedelta',
230+
options: 'OrderedMultiDict[Enum_Option, Option]') -> 'None': ...
185231

186232

187233

pcapkit/protocols/internet/mh.py

Lines changed: 196 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from tokenize import Name
2929
from typing import TYPE_CHECKING, cast, overload
3030

31+
from pcapkit.const.mh.binding_error import BindingError as Enum_BindingError
3132
from pcapkit.const.mh.access_type import AccessType as Enum_AccessType
3233
from pcapkit.const.mh.ack_status_code import ACKStatusCode as Enum_ACKStatusCode
3334
from pcapkit.const.mh.ani_suboption import ANISuboption as Enum_ANISuboption
@@ -146,9 +147,13 @@
146147
from pcapkit.protocols.data.internet.mh import HomeTestMessage as Data_HomeTestMessage
147148
from pcapkit.protocols.schema.internet.mh import CareofTestMessage as Schema_CareofTestMessage
148149
from pcapkit.protocols.data.internet.mh import CareofTestMessage as Data_CareofTestMessage
150+
from pcapkit.protocols.schema.internet.mh import BindingUpdateMessage as Schema_BindingUpdateMessage
151+
from pcapkit.protocols.data.internet.mh import BindingUpdateMessage as Data_BindingUpdateMessage
152+
from pcapkit.protocols.schema.internet.mh import BindingAcknowledgementMessage as Schema_BindingAcknowledgementMessage
153+
from pcapkit.protocols.data.internet.mh import BindingAcknowledgementMessage as Data_BindingAcknowledgementMessage
149154

150155
if TYPE_CHECKING:
151-
from datetime import datetime as dt_type
156+
from datetime import timedelta, datetime as dt_type
152157
from enum import IntEnum as StdlibEnum
153158
from ipaddress import IPv6Address, IPv6Network
154159
from typing import IO, Any, Callable, DefaultDict, NoReturn, Optional, Type
@@ -207,6 +212,8 @@ class MH(Internet[Data_MH, Schema_MH],
207212
Enum_Packet.Care_of_Test_Init: 'coti',
208213
Enum_Packet.Home_Test: 'hot',
209214
Enum_Packet.Care_of_Test: 'cot',
215+
Enum_Packet.Binding_Update: 'bu',
216+
Enum_Packet.Binding_Acknowledgement: 'ba',
210217
},
211218
) # type: DefaultDict[Enum_Packet | int, str | tuple[PacketParser, PacketConstructor]]
212219

@@ -384,9 +391,9 @@ def make(self,
384391
Constructed packet data.
385392
386393
"""
387-
next_val = self._make_index(next, next_default, namespace=next_namespace, # type: ignore[call-overload]
394+
next_val = self._make_index(next, next_default, namespace=next_namespace,
388395
reversed=next_reversed, pack=False)
389-
type_val = self._make_index(type, type_default, namespace=type_namespace, # type: ignore[call-overload]
396+
type_val = self._make_index(type, type_default, namespace=type_namespace,
390397
reversed=type_reversed, pack=False)
391398

392399
if isinstance(data, bytes):
@@ -716,6 +723,90 @@ def _read_msg_cot(self, schema: 'Schema_CareofTestMessage', *,
716723
)
717724
return data
718725

726+
def _read_msg_bu(self, schema: 'Schema_BindingUpdateMessage', *,
727+
header: 'Schema_MH') -> 'Data_BindingUpdateMessage':
728+
"""Read MH binding update (BU) message type.
729+
730+
Structure of MH Binding Update Message [:rfc:`6275`]:
731+
732+
.. code-block:: text
733+
734+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
735+
| Sequence # |
736+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
737+
|A|H|L|K| Reserved | Lifetime |
738+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
739+
| |
740+
. .
741+
. Mobility Options .
742+
. .
743+
| |
744+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
745+
746+
Args:
747+
schema: Parsed message type schema.
748+
header: Parsed MH header schema.
749+
750+
Returns:
751+
Parsed message type data.
752+
753+
"""
754+
data = Data_BindingUpdateMessage(
755+
next=header.next,
756+
length=(header.length + 1) * 8,
757+
type=header.type,
758+
chksum=header.chksum,
759+
seq=schema.seq,
760+
ack=bool(schema.flags['A']),
761+
home=bool(schema.flags['H']),
762+
lla_compat=bool(schema.flags['L']),
763+
key_mngt=bool(schema.flags['K']),
764+
lifetime=datetime.timedelta(seconds=schema.lifetime * 4),
765+
options=self._read_mh_options(schema.options),
766+
)
767+
return data
768+
769+
def _read_msg_ba(self, schema: 'Schema_BindingAcknowledgementMessage', *,
770+
header: 'Schema_MH') -> 'Data_BindingAcknowledgementMessage':
771+
"""Read MH binding acknowledgement (BA) message type.
772+
773+
Structure of MH Binding Acknowledgement Message [:rfc:`6275`]:
774+
775+
.. code-block:: text
776+
777+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
778+
| Status |K| Reserved |
779+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
780+
| Sequence # | Lifetime |
781+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
782+
| |
783+
. .
784+
. Mobility Options .
785+
. .
786+
| |
787+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
788+
789+
Args:
790+
schema: Parsed message type schema.
791+
header: Parsed MH header schema.
792+
793+
Returns:
794+
Parsed message type data.
795+
796+
"""
797+
data = Data_BindingAcknowledgementMessage(
798+
next=header.next,
799+
length=(header.length + 1) * 8,
800+
type=header.type,
801+
chksum=header.chksum,
802+
status=schema.status,
803+
key_mngt=bool(schema.flags['K']),
804+
seq=schema.seq,
805+
lifetime=datetime.timedelta(seconds=schema.lifetime * 4),
806+
options=self._read_mh_options(schema.options),
807+
)
808+
return data
809+
719810

720811

721812

@@ -1663,6 +1754,106 @@ def _make_msg_cot(self, message: 'Optional[Data_CareofTestMessage]', *,
16631754
options=self._make_mh_options(options),
16641755
)
16651756

1757+
def _make_msg_bu(self, message: 'Optional[Data_BindingUpdateMessage]', *,
1758+
seq: 'int' = 0,
1759+
ack: 'bool' = False,
1760+
home: 'bool' = False,
1761+
lla_compat: 'bool' = False,
1762+
key_mngt: 'bool' = False,
1763+
lifetime: 'int | timedelta' = 4, # reasonable default value
1764+
options: 'Optional[Option | list[Schema_Option | tuple[Enum_Option, dict[str, Any]] | bytes]]' = None,
1765+
**kwargs: 'Any') -> 'Schema_BindingUpdateMessage':
1766+
"""Make MH care-of test (CoT) message type.
1767+
1768+
Args:
1769+
message: Message data model.
1770+
seq: Sequence number.
1771+
ack: Acknowledgement flag.
1772+
home: Home registration flag.
1773+
lla_compat: LLA compatibility flag.
1774+
key_mngt: Key management mobility option flag.
1775+
lifetime: Lifetime in seconds or timedelta.
1776+
options: Mobility options.
1777+
**kwargs: Arbitrary keyword arguments.
1778+
1779+
Returns:
1780+
Constructed message type.
1781+
1782+
"""
1783+
if message is not None:
1784+
seq = message.seq
1785+
ack = message.ack
1786+
home = message.home
1787+
lla_compat = message.lla_compat
1788+
key_mngt = message.key_mngt
1789+
lifetime_val = math.ceil(message.lifetime.total_seconds())
1790+
options = message.options
1791+
else:
1792+
lifetime_val = lifetime if isinstance(lifetime, int) else math.ceil(lifetime.total_seconds())
1793+
options = options or []
1794+
1795+
return Schema_BindingUpdateMessage(
1796+
seq=seq,
1797+
flags={
1798+
'A': ack,
1799+
'H': home,
1800+
'L': lla_compat,
1801+
'K': key_mngt,
1802+
},
1803+
lifetime=math.ceil(lifetime_val / 4),
1804+
options=self._make_mh_options(options),
1805+
)
1806+
1807+
def _make_msg_ba(self, message: 'Optional[Data_BindingAcknowledgementMessage]', *,
1808+
status: 'Enum_StatusCode | StdlibEnum | AenumEnum | str | int' = Enum_StatusCode.Binding_Update_accepted_Proxy_Binding_Update_accepted,
1809+
status_default: 'Optional[int]' = None,
1810+
status_namespace: 'Optional[dict[str, int] | dict[int, str] | Type[StdlibEnum] | Type[AenumEnum]]' = None, # pylint: disable=line-too-long
1811+
status_reversed: 'bool' = False,
1812+
key_mngt: 'bool' = False,
1813+
seq: 'int' = 0,
1814+
lifetime: 'int | timedelta' = 4, # reasonable default value
1815+
options: 'Optional[Option | list[Schema_Option | tuple[Enum_Option, dict[str, Any]] | bytes]]' = None,
1816+
**kwargs: 'Any') -> 'Schema_BindingAcknowledgementMessage':
1817+
"""Make MH care-of test (CoT) message type.
1818+
1819+
Args:
1820+
message: Message data model.
1821+
status: Status code.
1822+
status_default: Default status code.
1823+
status_namespace: Status code namespace.
1824+
status_reversed: Reverse status code namespace.
1825+
key_mngt: Key management mobility option flag.
1826+
seq: Sequence number.
1827+
lifetime: Lifetime in seconds or timedelta.
1828+
options: Mobility options.
1829+
**kwargs: Arbitrary keyword arguments.
1830+
1831+
Returns:
1832+
Constructed message type.
1833+
1834+
"""
1835+
if message is not None:
1836+
status_val = message.status
1837+
key_mngt = message.key_mngt
1838+
seq = message.seq
1839+
lifetime_val = math.ceil(message.lifetime.total_seconds())
1840+
options = message.options
1841+
else:
1842+
status_val = self._make_index(status, status_default, namespace=status_namespace, # type: ignore[assignment]
1843+
reversed=status_reversed, pack=False)
1844+
lifetime_val = lifetime if isinstance(lifetime, int) else math.ceil(lifetime.total_seconds())
1845+
options = options or []
1846+
1847+
return Schema_BindingAcknowledgementMessage(
1848+
status=status_val,
1849+
flags={
1850+
'K': key_mngt,
1851+
},
1852+
seq=seq,
1853+
lifetime=math.ceil(lifetime_val / 4),
1854+
options=self._make_mh_options(options),
1855+
)
1856+
16661857

16671858

16681859

@@ -1958,7 +2149,7 @@ def _make_opt_mn_id(self, type: 'Enum_Option', option: 'Optional[Data_MNIDOption
19582149
subtype_val = option.subtype
19592150
identifier = option.identifier
19602151
else:
1961-
subtype_val = self._make_index(subtype, subtype_default, namespace=subtype_namespace, # type: ignore[call-overload]
2152+
subtype_val = self._make_index(subtype, subtype_default, namespace=subtype_namespace, # type: ignore[assignment]
19622153
reversed=subtype_reversed, pack=False)
19632154

19642155
if isinstance(identifier, ipaddress.IPv6Address):
@@ -2005,7 +2196,7 @@ def _make_opt_auth(self, type: 'Enum_Option', option: 'Optional[Data_AuthOption]
20052196
spi = option.spi
20062197
data = option.data
20072198
else:
2008-
subtype_val = self._make_index(subtype, subtype_default, namespace=subtype_namespace, # type: ignore[call-overload]
2199+
subtype_val = self._make_index(subtype, subtype_default, namespace=subtype_namespace, # type: ignore[assignment]
20092200
reversed=subtype_reversed, pack=False)
20102201

20112202
if (len(data) + 6) % 4 != 0:

pcapkit/protocols/schema/internet/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
from pcapkit.protocols.schema.internet.mh import CareofTestInitMessage as MH_CareofTestInitMessage
201201
from pcapkit.protocols.schema.internet.mh import HomeTestMessage as MH_HomeTestMessage
202202
from pcapkit.protocols.schema.internet.mh import CareofTestMessage as MH_CareofTestMessage
203+
from pcapkit.protocols.schema.internet.mh import BindingUpdateMessage as MH_BindingUpdateMessage
204+
from pcapkit.protocols.schema.internet.mh import BindingAcknowledgementMessage as MH_BindingAcknowledgementMessage
203205

204206
__all__ = [
205207
# Authentication Header

0 commit comments

Comments
 (0)