Skip to content

Commit db54fbb

Browse files
committed
Working on improving examples code.
1 parent 7fdffb2 commit db54fbb

18 files changed

+107
-153
lines changed

examples/icmp_echo_client.py

Lines changed: 20 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,19 @@
3939
import os
4040
import struct
4141
import time
42-
from typing import override
42+
from typing import Any, override
4343

4444
import click
45+
from net_addr import Ip4Address
46+
from net_addr import Ip6Address
47+
from net_addr import IpVersion
4548

4649
from examples.lib.client import Client
4750
from net_addr import (
48-
ClickTypeIp4Address,
49-
ClickTypeIp4Host,
50-
ClickTypeIp6Address,
51-
ClickTypeIp6Host,
5251
ClickTypeIpAddress,
53-
ClickTypeMacAddress,
54-
Ip4Address,
55-
Ip4Host,
56-
Ip6Address,
57-
Ip6Host,
58-
IpAddress,
59-
MacAddress,
6052
)
61-
from pytcp import socket, stack
53+
from pytcp import socket
54+
from run_stack import cli as stack_cli
6255

6356
ICMP4__ECHO_REQUEST__TYPE = 8
6457
ICMP4__ECHO_REQUEST__CODE = 0
@@ -78,8 +71,7 @@ class IcmpEchoClient(Client):
7871
def __init__(
7972
self,
8073
*,
81-
local_ip_address: IpAddress,
82-
remote_ip_address: IpAddress,
74+
remote_ip_address: Ip6Address | Ip4Address,
8375
message_count: int = -1,
8476
message_delay: int = 1,
8577
message_size: int = 5,
@@ -88,7 +80,6 @@ def __init__(
8880
Class constructor.
8981
"""
9082

91-
self._local_ip_address = local_ip_address
9283
self._remote_ip_address = remote_ip_address
9384
self._message_count = message_count
9485
self._message_delay = message_delay
@@ -147,22 +138,17 @@ def _thread__client__sender(self) -> None:
147138
message_count = self._message_count
148139

149140
while self._run_thread and message_count:
150-
match (
151-
self._local_ip_address.version,
152-
self._remote_ip_address.version,
153-
):
154-
case 6, 6:
141+
match self._remote_ip_address.version:
142+
case IpVersion.IP6:
155143
icmp_message = self._create_icmp6_message(
156144
identifier=identifier,
157145
sequence=self._message_count - message_count + 1,
158146
)
159-
case 4, 4:
147+
case IpVersion.IP4:
160148
icmp_message = self._create_icmp4_message(
161149
identifier=identifier,
162150
sequence=self._message_count - message_count + 1,
163151
)
164-
case _:
165-
raise ValueError("Invalid IP address versions.")
166152

167153
try:
168154
self._client_socket.send(icmp_message)
@@ -212,110 +198,31 @@ def _thread__client__receiver(self) -> None:
212198

213199

214200
@click.command()
215-
@click.option(
216-
"--stack-interface",
217-
"stack__interface",
218-
default="tap7",
219-
help="Name of the interface to be used by the stack.",
220-
)
221-
@click.option(
222-
"--stack-mac-address",
223-
"stack__mac_address",
224-
type=ClickTypeMacAddress(),
225-
default=None,
226-
help="MAC address to be assigned to the stack interface.",
227-
)
228-
@click.option(
229-
"--stack-ip6-address",
230-
"stack__ip6_host",
231-
type=ClickTypeIp6Host(),
232-
default=None,
233-
help="IPv6 address/mask to be assigned to the stack interface.",
234-
)
235-
@click.option(
236-
"--stack-ip6-gateway",
237-
"stack__ip6_gateway",
238-
type=ClickTypeIp6Address(),
239-
default=None,
240-
help="IPv6 gateway address to be assigned to the stack interface.",
241-
)
242-
@click.option(
243-
"--stack-ip4-address",
244-
"stack__ip4_host",
245-
type=ClickTypeIp4Host(),
246-
default=None,
247-
help="IPv4 address/mask to be assigned to the stack interface.",
248-
)
249-
@click.option(
250-
"--stack-ip4-gateway",
251-
"stack__ip4_gateway",
252-
type=ClickTypeIp4Address(),
253-
default=None,
254-
help="IPv4 gateway address to be assigned to the stack interface.",
255-
)
256201
@click.argument(
257202
"remote_ip_address",
258203
type=ClickTypeIpAddress(),
259204
required=True,
260205
)
206+
@click.pass_context
261207
def cli(
208+
ctx: click.Context,
262209
*,
263-
stack__interface: str,
264-
stack__mac_address: MacAddress | None,
265-
stack__ip6_host: Ip6Host | None,
266-
stack__ip6_gateway: Ip6Address | None,
267-
stack__ip4_host: Ip4Host | None,
268-
stack__ip4_gateway: Ip4Address | None,
269-
remote_ip_address: IpAddress,
210+
remote_ip_address: Ip6Address | Ip4Address,
211+
**kwargs: dict[str, Any],
270212
) -> None:
271213
"""
272214
Start PyTCP stack and stop it when user presses Ctrl-C.
273215
Start ICMP Echo client.
274216
"""
275217

276-
if stack__ip6_host:
277-
stack__ip6_host.gateway = stack__ip6_gateway
278-
279-
if stack__ip4_host:
280-
stack__ip4_host.gateway = stack__ip4_gateway
281-
282-
stack.init(
283-
*stack.initialize_interface(stack__interface),
284-
mac_address=stack__mac_address,
285-
ip6_host=stack__ip6_host,
286-
ip4_host=stack__ip4_host,
287-
)
288-
289218
match remote_ip_address.version:
290-
case 6:
291-
client = IcmpEchoClient(
292-
local_ip_address=(
293-
stack__ip6_host.address if stack__ip6_host else Ip6Address()
294-
),
295-
remote_ip_address=remote_ip_address,
296-
)
297-
case 4:
298-
client = IcmpEchoClient(
299-
local_ip_address=(
300-
stack__ip4_host.address if stack__ip4_host else Ip4Address()
301-
),
302-
remote_ip_address=remote_ip_address,
303-
)
304-
case _:
305-
raise ValueError(
306-
f"Invalid remote IP address version: {remote_ip_address.version}"
307-
)
308-
309-
try:
310-
stack.start()
311-
client.start()
312-
while True:
313-
time.sleep(1)
219+
case IpVersion.IP6:
220+
client = IcmpEchoClient(remote_ip_address=remote_ip_address)
221+
case IpVersion.IP4:
222+
client = IcmpEchoClient(remote_ip_address=remote_ip_address)
314223

315-
except KeyboardInterrupt:
316-
client.stop()
317-
stack.stop()
224+
ctx.invoke(stack_cli, subsystem=client, **kwargs)
318225

319226

320227
if __name__ == "__main__":
321-
cli() # pylint: disable = missing-kwoa
228+
cli.main()

examples/lib/client.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141
from typing import TYPE_CHECKING, override
4242

4343
import click
44-
from net_addr.ip_address import IpAddress
44+
from net_addr.ip4_address import Ip4Address
45+
from net_addr.ip6_address import Ip6Address
46+
from net_addr.ip_address import IpVersion
4547

4648
from examples.lib.subsystem import Subsystem
4749
from pytcp.socket import (
@@ -66,9 +68,9 @@ class Client(Subsystem):
6668

6769
_protocol_name: str
6870
_client_name: str
69-
_local_ip_address: IpAddress
71+
_local_ip_address: Ip4Address | Ip6Address
7072
_local_port: int
71-
_remote_ip_address: IpAddress
73+
_remote_ip_address: Ip4Address | Ip6Address
7274
_remote_port: int
7375
_run_thread: bool
7476
_client_socket: Socket | None
@@ -83,6 +85,12 @@ def start(self) -> None:
8385
f"Starting the {self._protocol_name} {self._client_name} service."
8486
)
8587

88+
if isinstance(self._remote_ip_address, Ip4Address):
89+
self._local_ip_address = self.stack_ip4_address
90+
91+
if isinstance(self._remote_ip_address, Ip6Address):
92+
self._local_ip_address = self.stack_ip6_address
93+
8694
self._client_socket = self._get_client_socket()
8795

8896
self._run_thread = True
@@ -108,25 +116,24 @@ def _get_client_socket(self) -> Socket | None:
108116
"""
109117

110118
match (
111-
self._local_ip_address.version,
112119
self._remote_ip_address.version,
113120
self._protocol_name,
114121
):
115-
case 6, 6, "TCP":
122+
case IpVersion.IP6, "TCP":
116123
client_socket = socket(family=AF_INET6, type=SOCK_STREAM)
117-
case 4, 4, "TCP":
124+
case IpVersion.IP4, "TCP":
118125
client_socket = socket(family=AF_INET4, type=SOCK_STREAM)
119-
case 6, 6, "UDP":
126+
case IpVersion.IP6, "UDP":
120127
client_socket = socket(family=AF_INET6, type=SOCK_DGRAM)
121-
case 4, 4, "UDP":
128+
case IpVersion.IP4, "UDP":
122129
client_socket = socket(family=AF_INET4, type=SOCK_DGRAM)
123-
case 6, 6, "ICMP":
130+
case IpVersion.IP6, "ICMP":
124131
client_socket = socket(
125132
family=AF_INET6, type=SOCK_RAW, protocol=IPPROTO_ICMP6
126133
)
127134
self._local_port = int(IPPROTO_ICMP6)
128135
self._remote_port = 0
129-
case 4, 4, "ICMP":
136+
case IpVersion.IP4, "ICMP":
130137
client_socket = socket(
131138
family=AF_INET4, type=SOCK_RAW, protocol=IPPROTO_ICMP4
132139
)

examples/lib/subsystem.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,21 @@
3636
from __future__ import annotations
3737

3838
from abc import ABC, abstractmethod
39+
from typing import TYPE_CHECKING
40+
41+
if TYPE_CHECKING:
42+
from net_addr.ip4_address import Ip4Address
43+
from net_addr.ip6_address import Ip6Address
3944

4045

4146
class Subsystem(ABC):
4247
"""
4348
Base class for 'user space' services like clients and servers.
4449
"""
4550

51+
stack_ip4_address: Ip4Address
52+
stack_ip6_address: Ip6Address
53+
4654
@abstractmethod
4755
def start(self) -> None:
4856
"""

examples/run_stack.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ def cli(
126126
try:
127127
stack.start()
128128
if subsystem is not None:
129+
subsystem.stack_ip4_address = (
130+
stack__ip4_host.address if stack__ip4_host else Ip4Address()
131+
)
132+
subsystem.stack_ip6_address = (
133+
stack__ip6_host.address if stack__ip6_host else Ip6Address()
134+
)
129135
subsystem.start()
130136

131137
while True:
@@ -138,4 +144,4 @@ def cli(
138144

139145

140146
if __name__ == "__main__":
141-
cli() # pylint: disable = missing-kwoa
147+
cli.main()

net_addr/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,5 @@
7474
from .ip6_host import Ip6Host, Ip6HostOrigin
7575
from .ip6_mask import Ip6Mask
7676
from .ip6_network import Ip6Network
77-
from .ip_address import IpAddress
77+
from .ip_address import IpAddress, IpVersion
7878
from .mac_address import MacAddress

net_addr/ip4_address.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
from typing import override
4141

4242
from .errors import Ip4AddressFormatError
43-
from .ip_address import IpAddress
43+
from .ip_address import IpAddress, IpVersion
4444
from .mac_address import MacAddress
4545

4646
IP4__ADDRESS_LEN = 4
@@ -56,7 +56,7 @@ class Ip4Address(IpAddress):
5656
IPv4 address support class.
5757
"""
5858

59-
_version: int = 4
59+
_version: IpVersion = IpVersion.IP4
6060

6161
def __init__(
6262
self,

net_addr/ip4_host.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
from enum import auto
4040
from typing import override
4141

42+
from net_addr.ip_address import IpVersion
43+
4244
from .errors import (
4345
Ip4AddressFormatError,
4446
Ip4HostFormatError,
@@ -67,7 +69,7 @@ class Ip4Host(IpHost[Ip4Address, Ip4Network, Ip4HostOrigin]):
6769
IPv4 host support class.
6870
"""
6971

70-
_version: int = 4
72+
_version: IpVersion = IpVersion.IP4
7173
_primary: bool
7274
_gateway: Ip4Address | None
7375
_origin: Ip4HostOrigin

net_addr/ip4_mask.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import socket
4040
from typing import override
4141

42+
from net_addr.ip_address import IpVersion
43+
4244
from .errors import Ip4MaskFormatError
4345
from .ip4_address import IP4__ADDRESS_LEN, IP4__REGEX
4446
from .ip_mask import IpMask
@@ -49,7 +51,7 @@ class Ip4Mask(IpMask):
4951
IPv4 mask support class.
5052
"""
5153

52-
_version: int = 4
54+
_version: IpVersion = IpVersion.IP4
5355

5456
def __init__(
5557
self,

net_addr/ip4_network.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737

3838
from typing import override
3939

40+
from net_addr.ip_address import IpVersion
41+
4042
from .errors import (
4143
Ip4AddressFormatError,
4244
Ip4MaskFormatError,
@@ -52,7 +54,7 @@ class Ip4Network(IpNetwork[Ip4Address, Ip4Mask]):
5254
IPv4 network support class.
5355
"""
5456

55-
_version = 4
57+
_version = IpVersion.IP4
5658

5759
def __init__(
5860
self,

0 commit comments

Comments
 (0)