|
28 | 28 | from tokenize import Name
|
29 | 29 | from typing import TYPE_CHECKING, cast, overload
|
30 | 30 |
|
| 31 | +from pcapkit.const.mh.binding_error import BindingError as Enum_BindingError |
31 | 32 | from pcapkit.const.mh.access_type import AccessType as Enum_AccessType
|
32 | 33 | from pcapkit.const.mh.ack_status_code import ACKStatusCode as Enum_ACKStatusCode
|
33 | 34 | from pcapkit.const.mh.ani_suboption import ANISuboption as Enum_ANISuboption
|
|
146 | 147 | from pcapkit.protocols.data.internet.mh import HomeTestMessage as Data_HomeTestMessage
|
147 | 148 | from pcapkit.protocols.schema.internet.mh import CareofTestMessage as Schema_CareofTestMessage
|
148 | 149 | 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 |
149 | 154 |
|
150 | 155 | if TYPE_CHECKING:
|
151 |
| - from datetime import datetime as dt_type |
| 156 | + from datetime import timedelta, datetime as dt_type |
152 | 157 | from enum import IntEnum as StdlibEnum
|
153 | 158 | from ipaddress import IPv6Address, IPv6Network
|
154 | 159 | from typing import IO, Any, Callable, DefaultDict, NoReturn, Optional, Type
|
@@ -207,6 +212,8 @@ class MH(Internet[Data_MH, Schema_MH],
|
207 | 212 | Enum_Packet.Care_of_Test_Init: 'coti',
|
208 | 213 | Enum_Packet.Home_Test: 'hot',
|
209 | 214 | Enum_Packet.Care_of_Test: 'cot',
|
| 215 | + Enum_Packet.Binding_Update: 'bu', |
| 216 | + Enum_Packet.Binding_Acknowledgement: 'ba', |
210 | 217 | },
|
211 | 218 | ) # type: DefaultDict[Enum_Packet | int, str | tuple[PacketParser, PacketConstructor]]
|
212 | 219 |
|
@@ -384,9 +391,9 @@ def make(self,
|
384 | 391 | Constructed packet data.
|
385 | 392 |
|
386 | 393 | """
|
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, |
388 | 395 | 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, |
390 | 397 | reversed=type_reversed, pack=False)
|
391 | 398 |
|
392 | 399 | if isinstance(data, bytes):
|
@@ -716,6 +723,90 @@ def _read_msg_cot(self, schema: 'Schema_CareofTestMessage', *,
|
716 | 723 | )
|
717 | 724 | return data
|
718 | 725 |
|
| 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 | + |
719 | 810 |
|
720 | 811 |
|
721 | 812 |
|
@@ -1663,6 +1754,106 @@ def _make_msg_cot(self, message: 'Optional[Data_CareofTestMessage]', *,
|
1663 | 1754 | options=self._make_mh_options(options),
|
1664 | 1755 | )
|
1665 | 1756 |
|
| 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 | + |
1666 | 1857 |
|
1667 | 1858 |
|
1668 | 1859 |
|
@@ -1958,7 +2149,7 @@ def _make_opt_mn_id(self, type: 'Enum_Option', option: 'Optional[Data_MNIDOption
|
1958 | 2149 | subtype_val = option.subtype
|
1959 | 2150 | identifier = option.identifier
|
1960 | 2151 | 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] |
1962 | 2153 | reversed=subtype_reversed, pack=False)
|
1963 | 2154 |
|
1964 | 2155 | if isinstance(identifier, ipaddress.IPv6Address):
|
@@ -2005,7 +2196,7 @@ def _make_opt_auth(self, type: 'Enum_Option', option: 'Optional[Data_AuthOption]
|
2005 | 2196 | spi = option.spi
|
2006 | 2197 | data = option.data
|
2007 | 2198 | 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] |
2009 | 2200 | reversed=subtype_reversed, pack=False)
|
2010 | 2201 |
|
2011 | 2202 | if (len(data) + 6) % 4 != 0:
|
|
0 commit comments