Skip to content

Commit 5dc4aeb

Browse files
authored
Merge pull request #36 from xorbit/master
Implement DHCP lease maintenance with renew / rebind.
2 parents 0ac4cb0 + b04926d commit 5dc4aeb

7 files changed

+385
-163
lines changed

README.rst

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,29 +126,28 @@ This example demonstrates a simple web server that allows setting the Neopixel c
126126
cs = digitalio.DigitalInOut(board.D10)
127127
spi_bus = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
128128
129-
# Initialize ethernet interface with DHCP and the MAC we have from the 24AA02E48
129+
# Initialize Ethernet interface with DHCP
130130
eth = WIZNET5K(spi_bus, cs)
131131
132132
# Here we create our application, registering the
133133
# following functions to be called on specific HTTP GET requests routes
134134
135135
web_app = WSGIApp()
136136
137-
138137
@web_app.route("/led/<r>/<g>/<b>")
139138
def led_on(request, r, g, b):
140-
print("led handler")
139+
print("LED handler")
141140
led.fill((int(r), int(g), int(b)))
142-
return ("200 OK", [], ["led set!"])
141+
return ("200 OK", [], ["LED set!"])
143142
144143
@web_app.route("/")
145144
def root(request):
146-
print("root handler")
147-
return ("200 OK", [], ["root document"])
145+
print("Root handler")
146+
return ("200 OK", [], ["Root document"])
148147
149148
@web_app.route("/large")
150149
def large(request):
151-
print("large handler")
150+
print("Large pattern handler")
152151
return ("200 OK", [], ["*-.-" * 2000])
153152
154153
@@ -163,6 +162,8 @@ This example demonstrates a simple web server that allows setting the Neopixel c
163162
while True:
164163
# Our main loop where we have the server poll for incoming requests
165164
wsgiServer.update_poll()
165+
# Maintain DHCP lease
166+
eth.maintain_dhcp_lease()
166167
# Could do any other background tasks here, like reading sensors
167168
168169
Contributing

adafruit_wiznet5k/adafruit_wiznet5k.py

Lines changed: 34 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@
121121
# UDP socket struct.
122122
UDP_SOCK = {"bytes_remaining": 0, "remote_ip": 0, "remote_port": 0}
123123

124+
# Source ports in use
125+
SRC_PORTS = [0] * W5200_W5500_MAX_SOCK_NUM
126+
124127

125128
class WIZNET5K: # pylint: disable=too-many-public-methods
126129
"""Interface for WIZNET5K module.
@@ -173,69 +176,48 @@ def __init__(
173176
assert self._w5100_init() == 1, "Failed to initialize WIZnet module."
174177
# Set MAC address
175178
self.mac_address = mac
176-
self._src_port = 0
179+
self.src_port = 0
177180
self._dns = 0
178181
# Set DHCP
182+
self._dhcp_client = None
179183
if is_dhcp:
180184
ret = self.set_dhcp(hostname, dhcp_timeout)
185+
if ret != 0:
186+
self._dhcp_client = None
181187
assert ret == 0, "Failed to configure DHCP Server!"
182188

183-
def set_dhcp(self, hostname=None, response_timeout=3):
189+
def set_dhcp(self, hostname=None, response_timeout=30):
184190
"""Initializes the DHCP client and attempts to retrieve
185191
and set network configuration from the DHCP server.
186-
Returns True if DHCP configured, False otherwise.
192+
Returns 0 if DHCP configured, -1 otherwise.
187193
:param str hostname: The desired hostname, with optional {} to fill in MAC.
188194
:param int response_timeout: Time to wait for server to return packet, in seconds.
189195
190196
"""
191197
if self._debug:
192198
print("* Initializing DHCP")
193-
self._src_port = 68
194199
# Return IP assigned by DHCP
195-
_dhcp_client = dhcp.DHCP(
200+
self._dhcp_client = dhcp.DHCP(
196201
self, self.mac_address, hostname, response_timeout, debug=self._debug
197202
)
198-
ret = _dhcp_client.request_dhcp_lease()
203+
ret = self._dhcp_client.request_dhcp_lease()
199204
if ret == 1:
200-
_ip = (
201-
_dhcp_client.local_ip[0],
202-
_dhcp_client.local_ip[1],
203-
_dhcp_client.local_ip[2],
204-
_dhcp_client.local_ip[3],
205-
)
206-
207-
_subnet_mask = (
208-
_dhcp_client.subnet_mask[0],
209-
_dhcp_client.subnet_mask[1],
210-
_dhcp_client.subnet_mask[2],
211-
_dhcp_client.subnet_mask[3],
212-
)
213-
214-
_gw_addr = (
215-
_dhcp_client.gateway_ip[0],
216-
_dhcp_client.gateway_ip[1],
217-
_dhcp_client.gateway_ip[2],
218-
_dhcp_client.gateway_ip[3],
219-
)
220-
221-
self._dns = (
222-
_dhcp_client.dns_server_ip[0],
223-
_dhcp_client.dns_server_ip[1],
224-
_dhcp_client.dns_server_ip[2],
225-
_dhcp_client.dns_server_ip[3],
226-
)
227-
self.ifconfig = (_ip, _subnet_mask, _gw_addr, self._dns)
228205
if self._debug:
206+
_ifconfig = self.ifconfig
229207
print("* Found DHCP Server:")
230208
print(
231209
"IP: {}\nSubnet Mask: {}\nGW Addr: {}\nDNS Server: {}".format(
232-
_ip, _subnet_mask, _gw_addr, self._dns
210+
*_ifconfig
233211
)
234212
)
235-
self._src_port = 0
236213
return 0
237214
return -1
238215

216+
def maintain_dhcp_lease(self):
217+
"""Maintain DHCP lease"""
218+
if self._dhcp_client is not None:
219+
self._dhcp_client.maintain_dhcp_lease()
220+
239221
def get_host_by_name(self, hostname):
240222
"""Convert a hostname to a packed 4-byte IP Address.
241223
Returns a 4 bytearray.
@@ -244,14 +226,12 @@ def get_host_by_name(self, hostname):
244226
print("* Get host by name")
245227
if isinstance(hostname, str):
246228
hostname = bytes(hostname, "utf-8")
247-
self._src_port = int(time.monotonic()) & 0xFFFF
248229
# Return IP assigned by DHCP
249230
_dns_client = dns.DNS(self, self._dns, debug=self._debug)
250231
ret = _dns_client.gethostbyname(hostname)
251232
if self._debug:
252233
print("* Resolved IP: ", ret)
253234
assert ret != -1, "Failed to resolve hostname!"
254-
self._src_port = 0
255235
return ret
256236

257237
@property
@@ -469,7 +449,11 @@ def socket_available(self, socket_num, sock_type=SNMR_TCP):
469449
:param int sock_type: Socket type, defaults to TCP.
470450
"""
471451
if self._debug:
472-
print("* socket_available called with protocol", sock_type)
452+
print(
453+
"* socket_available called on socket {}, protocol {}".format(
454+
socket_num, sock_type
455+
)
456+
)
473457
assert socket_num <= self.max_sockets, "Provided socket exceeds max_sockets."
474458

475459
res = self._get_rx_rcv_size(socket_num)
@@ -549,13 +533,7 @@ def get_socket(self):
549533
sock = SOCKET_INVALID
550534
for _sock in range(self.max_sockets):
551535
status = self.socket_status(_sock)[0]
552-
if status in (
553-
SNSR_SOCK_CLOSED,
554-
SNSR_SOCK_TIME_WAIT,
555-
SNSR_SOCK_FIN_WAIT,
556-
SNSR_SOCK_CLOSE_WAIT,
557-
SNSR_SOCK_CLOSING,
558-
):
536+
if status == SNSR_SOCK_CLOSED:
559537
sock = _sock
560538
break
561539

@@ -576,15 +554,16 @@ def socket_listen(self, socket_num, port):
576554
)
577555
)
578556
# Initialize a socket and set the mode
579-
self._src_port = port
557+
self.src_port = port
580558
res = self.socket_open(socket_num, conn_mode=SNMR_TCP)
559+
self.src_port = 0
581560
if res == 1:
582561
raise RuntimeError("Failed to initalize the socket.")
583562
# Send listen command
584563
self._send_socket_cmd(socket_num, CMD_SOCK_LISTEN)
585564
# Wait until ready
586565
status = [SNSR_SOCK_CLOSED]
587-
while status[0] != SNSR_SOCK_LISTEN:
566+
while status[0] not in (SNSR_SOCK_LISTEN, SNSR_SOCK_ESTABLISHED):
588567
status = self._read_snsr(socket_num)
589568
if status[0] == SNSR_SOCK_CLOSED:
590569
raise RuntimeError("Listening socket closed.")
@@ -627,11 +606,15 @@ def socket_open(self, socket_num, conn_mode=SNMR_TCP):
627606
self._write_snmr(socket_num, conn_mode)
628607
self._write_snir(socket_num, 0xFF)
629608

630-
if self._src_port > 0:
609+
if self.src_port > 0:
631610
# write to socket source port
632-
self._write_sock_port(socket_num, self._src_port)
611+
self._write_sock_port(socket_num, self.src_port)
633612
else:
634-
self._write_sock_port(socket_num, randint(49152, 65535))
613+
s_port = randint(49152, 65535)
614+
while s_port in SRC_PORTS:
615+
s_port = randint(49152, 65535)
616+
self._write_sock_port(socket_num, s_port)
617+
SRC_PORTS[socket_num] = s_port
635618

636619
# open socket
637620
self._write_sncr(socket_num, CMD_SOCK_OPEN)

0 commit comments

Comments
 (0)