Skip to content

Commit cb28557

Browse files
committed
Refactored code of the UDP Echo client.
1 parent 7544fc7 commit cb28557

File tree

3 files changed

+48
-130
lines changed

3 files changed

+48
-130
lines changed

examples/icmp_echo_client.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
Ip6Address,
5151
IpVersion,
5252
)
53-
from pytcp import socket
5453
from run_stack import cli as stack_cli
5554

5655

@@ -171,31 +170,6 @@ def _thread__client__sender(self) -> None:
171170

172171
click.echo("Client ICMP Echo: Stopped sender thread.")
173172

174-
@override
175-
def _thread__client__receiver(self) -> None:
176-
"""
177-
Client thread used to receive data.
178-
"""
179-
180-
if self._client_socket:
181-
click.echo("Client ICMP Echo: Started receiver thread.")
182-
183-
while self._run_thread:
184-
try:
185-
data, _ = self._client_socket.recvfrom(
186-
bufsize=1024,
187-
timeout=1,
188-
)
189-
if data:
190-
click.echo(
191-
f"Client ICMP Echo: Received {len(data) - 8} bytes from "
192-
f"'{self._remote_ip_address}'."
193-
)
194-
except socket.ReceiveTimeout:
195-
pass
196-
197-
click.echo("Client ICMP Echo: Stopped receiver thread.")
198-
199173

200174
@click.command()
201175
@click.argument(

examples/lib/client.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
SOCK_RAW,
5656
SOCK_STREAM,
5757
socket,
58+
ReceiveTimeout,
5859
)
5960

6061
if TYPE_CHECKING:
@@ -185,10 +186,30 @@ def _thread__client__sender(self) -> None:
185186

186187
raise NotImplementedError
187188

188-
@abstractmethod
189189
def _thread__client__receiver(self) -> None:
190190
"""
191-
Client thread used to send data.
191+
Client thread used to receive data.
192192
"""
193193

194-
raise NotImplementedError
194+
if self._client_socket:
195+
click.echo(
196+
f"Client {self._protocol_name} {self._client_name}: Started receiver thread."
197+
)
198+
199+
while self._run_thread:
200+
try:
201+
data, _ = self._client_socket.recvfrom(
202+
bufsize=1024,
203+
timeout=1,
204+
)
205+
if data:
206+
click.echo(
207+
f"Client {self._protocol_name} {self._client_name}: Received {len(data) - 8} bytes from "
208+
f"'{self._remote_ip_address}'."
209+
)
210+
except ReceiveTimeout:
211+
pass
212+
213+
click.echo(
214+
f"Client {self._protocol_name} {self._client_name}: Stopped receiver thread."
215+
)

examples/udp_echo_client.py

Lines changed: 24 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,16 @@
3535

3636

3737
from __future__ import annotations
38-
3938
import time
40-
39+
from typing import Any
4140
import click
42-
4341
from examples.lib.client import Client
4442
from net_addr import (
45-
ClickTypeIp4Address,
46-
ClickTypeIp4Host,
47-
ClickTypeIp6Address,
48-
ClickTypeIp6Host,
4943
ClickTypeIpAddress,
50-
ClickTypeMacAddress,
5144
Ip4Address,
52-
Ip4Host,
5345
Ip6Address,
54-
Ip6Host,
55-
IpAddress,
56-
MacAddress,
5746
)
58-
from pytcp import stack
47+
from run_stack import cli as stack_cli
5948

6049

6150
class UdpEchoClient(Client):
@@ -69,8 +58,7 @@ class UdpEchoClient(Client):
6958
def __init__(
7059
self,
7160
*,
72-
local_ip_address: IpAddress,
73-
remote_ip_address: IpAddress,
61+
remote_ip_address: Ip6Address | Ip4Address,
7462
local_port: int = 0,
7563
remote_port: int = 7,
7664
message_count: int = -1,
@@ -81,7 +69,6 @@ def __init__(
8169
Class constructor.
8270
"""
8371

84-
self._local_ip_address = local_ip_address
8572
self._remote_ip_address = remote_ip_address
8673
self._local_port = local_port
8774
self._remote_port = remote_port
@@ -90,9 +77,9 @@ def __init__(
9077
self._message_size = message_size
9178
self._run_thread = False
9279

93-
def _thread__client(self) -> None:
80+
def _thread__client__sender(self) -> None:
9481
"""
95-
Client thread.
82+
Client thread used to send data.
9683
"""
9784

9885
if client_socket := self._get_client_socket():
@@ -125,102 +112,38 @@ def _thread__client(self) -> None:
125112

126113

127114
@click.command()
128-
@click.option(
129-
"--interface",
130-
default="tap7",
131-
help="Name of the interface to be used by the stack.",
132-
)
133-
@click.option(
134-
"--mac-address",
135-
type=ClickTypeMacAddress(),
136-
default=None,
137-
help="MAC address to be assigned to the interface.",
138-
)
139-
@click.option(
140-
"--ip6-address",
141-
"ip6_host",
142-
type=ClickTypeIp6Host(),
143-
default=None,
144-
help="IPv6 address/mask to be assigned to the interface.",
145-
)
146-
@click.option(
147-
"--ip6-gateway",
148-
type=ClickTypeIp6Address(),
149-
default=None,
150-
help="IPv6 gateway address to be assigned to the interface.",
151-
)
152-
@click.option(
153-
"--ip4-address",
154-
"ip4_host",
155-
type=ClickTypeIp4Host(),
156-
default=None,
157-
help="IPv4 address/mask to be assigned to the interface.",
158-
)
159-
@click.option(
160-
"--ip4-gateway",
161-
type=ClickTypeIp4Address(),
162-
default=None,
163-
help="IPv4 gateway address to be assigned to the interface.",
164-
)
165115
@click.argument(
166116
"remote_ip_address",
167117
type=ClickTypeIpAddress(),
168118
required=True,
169119
)
120+
@click.argument(
121+
"remote_port",
122+
type=click.IntRange(1, 65535),
123+
default=7,
124+
)
125+
@click.pass_context
170126
def cli(
127+
ctx: click.Context,
171128
*,
172-
interface: str,
173-
mac_address: MacAddress | None,
174-
ip6_host: Ip6Host | None,
175-
ip6_gateway: Ip6Address | None,
176-
ip4_host: Ip4Host | None,
177-
ip4_gateway: Ip4Address | None,
178-
remote_ip_address: IpAddress,
129+
remote_ip_address: Ip6Address | Ip4Address,
130+
remote_port: int,
131+
**kwargs: Any,
179132
) -> None:
180133
"""
181-
Start PyTCP stack and stop it when user presses Ctrl-C.
182134
Start UDP Echo client.
183135
"""
184136

185-
if ip6_host:
186-
ip6_host.gateway = ip6_gateway
187-
188-
if ip4_host:
189-
ip4_host.gateway = ip4_gateway
190-
191-
stack.init(
192-
*stack.initialize_interface(interface),
193-
mac_address=mac_address,
194-
ip6_host=ip6_host,
195-
ip4_host=ip4_host,
137+
ctx.invoke(
138+
stack_cli,
139+
subsystem=UdpEchoClient(
140+
remote_ip_address=remote_ip_address, remote_port=remote_port
141+
),
142+
**kwargs,
196143
)
197144

198-
match remote_ip_address.version:
199-
case 6:
200-
client = UdpEchoClient(
201-
local_ip_address=ip6_host.address if ip6_host else Ip6Address(),
202-
remote_ip_address=remote_ip_address,
203-
)
204-
case 4:
205-
client = UdpEchoClient(
206-
local_ip_address=ip4_host.address if ip4_host else Ip4Address(),
207-
remote_ip_address=remote_ip_address,
208-
)
209-
case _:
210-
raise ValueError(
211-
f"Invalid remote IP address version: {remote_ip_address.version}"
212-
)
213-
214-
try:
215-
stack.start()
216-
client.start()
217-
while True:
218-
time.sleep(60)
219-
220-
except KeyboardInterrupt:
221-
client.stop()
222-
stack.stop()
223-
224145

225146
if __name__ == "__main__":
226-
cli() # pylint: disable = missing-kwoa
147+
cli.help = (cli.help or "").rstrip() + (stack_cli.help or "")
148+
cli.params += stack_cli.params
149+
cli.main()

0 commit comments

Comments
 (0)