1 /*
2 * This file is part of the MicroPython project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013-2019 Damien P. George
7 * Copyright (c) 2015 Galen Hazelwood
8 * Copyright (c) 2015-2017 Paul Sokolovsky
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 */
28
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "py/objlist.h"
33 #include "py/runtime.h"
34 #include "py/stream.h"
35 #include "py/mperrno.h"
36 #include "py/mphal.h"
37
38 #include "shared/netutils/netutils.h"
39
40 #include "lwip/init.h"
41 #include "lwip/tcp.h"
42 #include "lwip/udp.h"
43 #include "lwip/raw.h"
44 #include "lwip/dns.h"
45 #include "lwip/igmp.h"
46 #if LWIP_VERSION_MAJOR < 2
47 #include "lwip/timers.h"
48 #include "lwip/tcp_impl.h"
49 #else
50 #include "lwip/timeouts.h"
51 #include "lwip/priv/tcp_priv.h"
52 #endif
53
54 #if 0 // print debugging info
55 #define DEBUG_printf DEBUG_printf
56 #else // don't print debugging info
57 #define DEBUG_printf(...) (void)0
58 #endif
59
60 // Timeout between closing a TCP socket and doing a tcp_abort on that
61 // socket, if the connection isn't closed cleanly in that time.
62 #define MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS (10000)
63
64 // All socket options should be globally distinct,
65 // because we ignore option levels for efficiency.
66 #define IP_ADD_MEMBERSHIP 0x400
67
68 // For compatibilily with older lwIP versions.
69 #ifndef ip_set_option
70 #define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt))
71 #endif
72 #ifndef ip_reset_option
73 #define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt))
74 #endif
75
76 // A port can define these hooks to provide concurrency protection
77 #ifndef MICROPY_PY_LWIP_ENTER
78 #define MICROPY_PY_LWIP_ENTER
79 #define MICROPY_PY_LWIP_REENTER
80 #define MICROPY_PY_LWIP_EXIT
81 #endif
82
83 #ifdef MICROPY_PY_LWIP_SLIP
84 #include "netif/slipif.h"
85 #include "lwip/sio.h"
86 #endif
87
88 #ifdef MICROPY_PY_LWIP_SLIP
89 /******************************************************************************/
90 // Slip object for modlwip. Requires a serial driver for the port that supports
91 // the lwip serial callback functions.
92
93 typedef struct _lwip_slip_obj_t {
94 mp_obj_base_t base;
95 struct netif lwip_netif;
96 } lwip_slip_obj_t;
97
98 // Slip object is unique for now. Possibly can fix this later. FIXME
99 STATIC lwip_slip_obj_t lwip_slip_obj;
100
101 // Declare these early.
102 void mod_lwip_register_poll(void (*poll)(void *arg), void *poll_arg);
103 void mod_lwip_deregister_poll(void (*poll)(void *arg), void *poll_arg);
104
slip_lwip_poll(void * netif)105 STATIC void slip_lwip_poll(void *netif) {
106 slipif_poll((struct netif *)netif);
107 }
108
109 STATIC const mp_obj_type_t lwip_slip_type;
110
111 // lwIP SLIP callback functions
sio_open(u8_t dvnum)112 sio_fd_t sio_open(u8_t dvnum) {
113 // We support singleton SLIP interface, so just return any truish value.
114 return (sio_fd_t)1;
115 }
116
sio_send(u8_t c,sio_fd_t fd)117 void sio_send(u8_t c, sio_fd_t fd) {
118 mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream));
119 int error;
120 type->stream_p->write(MP_STATE_VM(lwip_slip_stream), &c, 1, &error);
121 }
122
sio_tryread(sio_fd_t fd,u8_t * data,u32_t len)123 u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len) {
124 mp_obj_type_t *type = mp_obj_get_type(MP_STATE_VM(lwip_slip_stream));
125 int error;
126 mp_uint_t out_sz = type->stream_p->read(MP_STATE_VM(lwip_slip_stream), data, len, &error);
127 if (out_sz == MP_STREAM_ERROR) {
128 if (mp_is_nonblocking_error(error)) {
129 return 0;
130 }
131 // Can't do much else, can we?
132 return 0;
133 }
134 return out_sz;
135 }
136
137 // constructor lwip.slip(device=integer, iplocal=string, ipremote=string)
lwip_slip_make_new(mp_obj_t type_in,size_t n_args,size_t n_kw,const mp_obj_t * args)138 STATIC mp_obj_t lwip_slip_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
139 mp_arg_check_num(n_args, n_kw, 3, 3, false);
140
141 lwip_slip_obj.base.type = &lwip_slip_type;
142
143 MP_STATE_VM(lwip_slip_stream) = args[0];
144
145 ip_addr_t iplocal, ipremote;
146 if (!ipaddr_aton(mp_obj_str_get_str(args[1]), &iplocal)) {
147 mp_raise_ValueError(MP_ERROR_TEXT("not a valid local IP"));
148 }
149 if (!ipaddr_aton(mp_obj_str_get_str(args[2]), &ipremote)) {
150 mp_raise_ValueError(MP_ERROR_TEXT("not a valid remote IP"));
151 }
152
153 struct netif *n = &lwip_slip_obj.lwip_netif;
154 if (netif_add(n, &iplocal, IP_ADDR_BROADCAST, &ipremote, NULL, slipif_init, ip_input) == NULL) {
155 mp_raise_ValueError(MP_ERROR_TEXT("out of memory"));
156 }
157 netif_set_up(n);
158 netif_set_default(n);
159 mod_lwip_register_poll(slip_lwip_poll, n);
160
161 return (mp_obj_t)&lwip_slip_obj;
162 }
163
lwip_slip_status(mp_obj_t self_in)164 STATIC mp_obj_t lwip_slip_status(mp_obj_t self_in) {
165 // Null function for now.
166 return mp_const_none;
167 }
168
169 STATIC MP_DEFINE_CONST_FUN_OBJ_1(lwip_slip_status_obj, lwip_slip_status);
170
171 STATIC const mp_rom_map_elem_t lwip_slip_locals_dict_table[] = {
172 { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lwip_slip_status_obj) },
173 };
174
175 STATIC MP_DEFINE_CONST_DICT(lwip_slip_locals_dict, lwip_slip_locals_dict_table);
176
177 STATIC const mp_obj_type_t lwip_slip_type = {
178 { &mp_type_type },
179 .name = MP_QSTR_slip,
180 .make_new = lwip_slip_make_new,
181 .locals_dict = (mp_obj_dict_t *)&lwip_slip_locals_dict,
182 };
183
184 #endif // MICROPY_PY_LWIP_SLIP
185
186 /******************************************************************************/
187 // Table to convert lwIP err_t codes to socket errno codes, from the lwIP
188 // socket API.
189
190 // lwIP 2 changed LWIP_VERSION and it can no longer be used in macros,
191 // so we define our own equivalent version that can.
192 #define LWIP_VERSION_MACRO (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 \
193 | LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC)
194
195 // Extension to lwIP error codes
196 #define _ERR_BADF -16
197 // TODO: We just know that change happened somewhere between 1.4.0 and 1.4.1,
198 // investigate in more detail.
199 #if LWIP_VERSION_MACRO < 0x01040100
200 static const int error_lookup_table[] = {
201 0, /* ERR_OK 0 No error, everything OK. */
202 MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
203 MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
204 MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
205 MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
206 MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
207 MP_EINVAL, /* ERR_VAL -6 Illegal value. */
208 MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
209
210 MP_ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
211 MP_ECONNRESET, /* ERR_RST -9 Connection reset. */
212 MP_ENOTCONN, /* ERR_CLSD -10 Connection closed. */
213 MP_ENOTCONN, /* ERR_CONN -11 Not connected. */
214 MP_EIO, /* ERR_ARG -12 Illegal argument. */
215 MP_EADDRINUSE, /* ERR_USE -13 Address in use. */
216 -1, /* ERR_IF -14 Low-level netif error */
217 MP_EALREADY, /* ERR_ISCONN -15 Already connected. */
218 MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
219 };
220 #elif LWIP_VERSION_MACRO < 0x02000000
221 static const int error_lookup_table[] = {
222 0, /* ERR_OK 0 No error, everything OK. */
223 MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
224 MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
225 MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
226 MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
227 MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
228 MP_EINVAL, /* ERR_VAL -6 Illegal value. */
229 MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
230
231 MP_EADDRINUSE, /* ERR_USE -8 Address in use. */
232 MP_EALREADY, /* ERR_ISCONN -9 Already connected. */
233 MP_ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
234 MP_ECONNRESET, /* ERR_RST -11 Connection reset. */
235 MP_ENOTCONN, /* ERR_CLSD -12 Connection closed. */
236 MP_ENOTCONN, /* ERR_CONN -13 Not connected. */
237 MP_EIO, /* ERR_ARG -14 Illegal argument. */
238 -1, /* ERR_IF -15 Low-level netif error */
239 MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
240 };
241 #else
242 // Matches lwIP 2.0.3
243 #undef _ERR_BADF
244 #define _ERR_BADF -17
245 static const int error_lookup_table[] = {
246 0, /* ERR_OK 0 No error, everything OK */
247 MP_ENOMEM, /* ERR_MEM -1 Out of memory error */
248 MP_ENOBUFS, /* ERR_BUF -2 Buffer error */
249 MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
250 MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem */
251 MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
252 MP_EINVAL, /* ERR_VAL -6 Illegal value */
253 MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block */
254 MP_EADDRINUSE, /* ERR_USE -8 Address in use */
255 MP_EALREADY, /* ERR_ALREADY -9 Already connecting */
256 MP_EALREADY, /* ERR_ISCONN -10 Conn already established */
257 MP_ENOTCONN, /* ERR_CONN -11 Not connected */
258 -1, /* ERR_IF -12 Low-level netif error */
259 MP_ECONNABORTED, /* ERR_ABRT -13 Connection aborted */
260 MP_ECONNRESET, /* ERR_RST -14 Connection reset */
261 MP_ENOTCONN, /* ERR_CLSD -15 Connection closed */
262 MP_EIO, /* ERR_ARG -16 Illegal argument. */
263 MP_EBADF, /* _ERR_BADF -17 Closed socket (null pcb) */
264 };
265 #endif
266
267 /*******************************************************************************/
268 // The socket object provided by lwip.socket.
269
270 #define MOD_NETWORK_AF_INET (2)
271 #define MOD_NETWORK_AF_INET6 (10)
272
273 #define MOD_NETWORK_SOCK_STREAM (1)
274 #define MOD_NETWORK_SOCK_DGRAM (2)
275 #define MOD_NETWORK_SOCK_RAW (3)
276
277 typedef struct _lwip_socket_obj_t {
278 mp_obj_base_t base;
279
280 volatile union {
281 struct tcp_pcb *tcp;
282 struct udp_pcb *udp;
283 struct raw_pcb *raw;
284 } pcb;
285 volatile union {
286 struct pbuf *pbuf;
287 struct {
288 uint8_t alloc;
289 uint8_t iget;
290 uint8_t iput;
291 union {
292 struct tcp_pcb *item; // if alloc == 0
293 struct tcp_pcb **array; // if alloc != 0
294 } tcp;
295 } connection;
296 } incoming;
297 mp_obj_t callback;
298 byte peer[4];
299 mp_uint_t peer_port;
300 mp_uint_t timeout;
301 uint16_t recv_offset;
302
303 uint8_t domain;
304 uint8_t type;
305
306 #define STATE_NEW 0
307 #define STATE_LISTENING 1
308 #define STATE_CONNECTING 2
309 #define STATE_CONNECTED 3
310 #define STATE_PEER_CLOSED 4
311 #define STATE_ACTIVE_UDP 5
312 // Negative value is lwIP error
313 int8_t state;
314 } lwip_socket_obj_t;
315
poll_sockets(void)316 static inline void poll_sockets(void) {
317 #ifdef MICROPY_EVENT_POLL_HOOK
318 MICROPY_EVENT_POLL_HOOK;
319 #else
320 mp_hal_delay_ms(1);
321 #endif
322 }
323
lwip_socket_incoming_array(lwip_socket_obj_t * socket)324 STATIC struct tcp_pcb *volatile *lwip_socket_incoming_array(lwip_socket_obj_t *socket) {
325 if (socket->incoming.connection.alloc == 0) {
326 return &socket->incoming.connection.tcp.item;
327 } else {
328 return &socket->incoming.connection.tcp.array[0];
329 }
330 }
331
lwip_socket_free_incoming(lwip_socket_obj_t * socket)332 STATIC void lwip_socket_free_incoming(lwip_socket_obj_t *socket) {
333 bool socket_is_listener =
334 socket->type == MOD_NETWORK_SOCK_STREAM
335 && socket->pcb.tcp->state == LISTEN;
336
337 if (!socket_is_listener) {
338 if (socket->incoming.pbuf != NULL) {
339 pbuf_free(socket->incoming.pbuf);
340 socket->incoming.pbuf = NULL;
341 }
342 } else {
343 uint8_t alloc = socket->incoming.connection.alloc;
344 struct tcp_pcb *volatile *tcp_array = lwip_socket_incoming_array(socket);
345 for (uint8_t i = 0; i < alloc; ++i) {
346 // Deregister callback and abort
347 if (tcp_array[i] != NULL) {
348 tcp_poll(tcp_array[i], NULL, 0);
349 tcp_abort(tcp_array[i]);
350 tcp_array[i] = NULL;
351 }
352 }
353 }
354 }
355
356 /*******************************************************************************/
357 // Callback functions for the lwIP raw API.
358
exec_user_callback(lwip_socket_obj_t * socket)359 static inline void exec_user_callback(lwip_socket_obj_t *socket) {
360 if (socket->callback != MP_OBJ_NULL) {
361 // Schedule the user callback to execute outside the lwIP context
362 mp_sched_schedule(socket->callback, MP_OBJ_FROM_PTR(socket));
363 }
364 }
365
366 #if MICROPY_PY_LWIP_SOCK_RAW
367 // Callback for incoming raw packets.
368 #if LWIP_VERSION_MAJOR < 2
_lwip_raw_incoming(void * arg,struct raw_pcb * pcb,struct pbuf * p,ip_addr_t * addr)369 STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr)
370 #else
371 STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
372 #endif
373 {
374 lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
375
376 if (socket->incoming.pbuf != NULL) {
377 pbuf_free(p);
378 } else {
379 socket->incoming.pbuf = p;
380 memcpy(&socket->peer, addr, sizeof(socket->peer));
381 }
382 return 1; // we ate the packet
383 }
384 #endif
385
386 // Callback for incoming UDP packets. We simply stash the packet and the source address,
387 // in case we need it for recvfrom.
388 #if LWIP_VERSION_MAJOR < 2
_lwip_udp_incoming(void * arg,struct udp_pcb * upcb,struct pbuf * p,ip_addr_t * addr,u16_t port)389 STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
390 #else
391 STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
392 #endif
393 {
394 lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
395
396 if (socket->incoming.pbuf != NULL) {
397 // That's why they call it "unreliable". No room in the inn, drop the packet.
398 pbuf_free(p);
399 } else {
400 socket->incoming.pbuf = p;
401 socket->peer_port = (mp_uint_t)port;
402 memcpy(&socket->peer, addr, sizeof(socket->peer));
403 }
404 }
405
406 // Callback for general tcp errors.
_lwip_tcp_error(void * arg,err_t err)407 STATIC void _lwip_tcp_error(void *arg, err_t err) {
408 lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
409
410 // Free any incoming buffers or connections that are stored
411 lwip_socket_free_incoming(socket);
412 // Pass the error code back via the connection variable.
413 socket->state = err;
414 // If we got here, the lwIP stack either has deallocated or will deallocate the pcb.
415 socket->pcb.tcp = NULL;
416 }
417
418 // Callback for tcp connection requests. Error code err is unused. (See tcp.h)
_lwip_tcp_connected(void * arg,struct tcp_pcb * tpcb,err_t err)419 STATIC err_t _lwip_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
420 lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
421
422 socket->state = STATE_CONNECTED;
423 return ERR_OK;
424 }
425
426 // Handle errors (eg connection aborted) on TCP PCBs that have been put on the
427 // accept queue but are not yet actually accepted.
_lwip_tcp_err_unaccepted(void * arg,err_t err)428 STATIC void _lwip_tcp_err_unaccepted(void *arg, err_t err) {
429 struct tcp_pcb *pcb = (struct tcp_pcb *)arg;
430
431 // The ->connected entry is repurposed to store the parent socket; this is safe
432 // because it's only ever used by lwIP if tcp_connect is called on the TCP PCB.
433 lwip_socket_obj_t *socket = (lwip_socket_obj_t *)pcb->connected;
434
435 // Array is not volatile because thiss callback is executed within the lwIP context
436 uint8_t alloc = socket->incoming.connection.alloc;
437 struct tcp_pcb **tcp_array = (struct tcp_pcb **)lwip_socket_incoming_array(socket);
438
439 // Search for PCB on the accept queue of the parent socket
440 struct tcp_pcb **shift_down = NULL;
441 uint8_t i = socket->incoming.connection.iget;
442 do {
443 if (shift_down == NULL) {
444 if (tcp_array[i] == pcb) {
445 shift_down = &tcp_array[i];
446 }
447 } else {
448 *shift_down = tcp_array[i];
449 shift_down = &tcp_array[i];
450 }
451 if (++i >= alloc) {
452 i = 0;
453 }
454 } while (i != socket->incoming.connection.iput);
455
456 // PCB found in queue, remove it
457 if (shift_down != NULL) {
458 *shift_down = NULL;
459 socket->incoming.connection.iput = shift_down - tcp_array;
460 }
461 }
462
463 // By default, a child socket of listen socket is created with recv
464 // handler which discards incoming pbuf's. We don't want to do that,
465 // so set this handler which requests lwIP to keep pbuf's and deliver
466 // them later. We cannot cache pbufs in child socket on Python side,
467 // until it is created in accept().
_lwip_tcp_recv_unaccepted(void * arg,struct tcp_pcb * pcb,struct pbuf * p,err_t err)468 STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
469 return ERR_BUF;
470 }
471
472 // Callback for incoming tcp connections.
_lwip_tcp_accept(void * arg,struct tcp_pcb * newpcb,err_t err)473 STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
474 // err can be ERR_MEM to notify us that there was no memory for an incoming connection
475 if (err != ERR_OK) {
476 return ERR_OK;
477 }
478
479 lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
480 tcp_recv(newpcb, _lwip_tcp_recv_unaccepted);
481
482 // Search for an empty slot to store the new connection
483 struct tcp_pcb *volatile *slot = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iput];
484 if (*slot == NULL) {
485 // Have an empty slot to store waiting connection
486 *slot = newpcb;
487 if (++socket->incoming.connection.iput >= socket->incoming.connection.alloc) {
488 socket->incoming.connection.iput = 0;
489 }
490
491 // Schedule user accept callback
492 exec_user_callback(socket);
493
494 // Set the error callback to handle the case of a dropped connection before we
495 // have a chance to take it off the accept queue.
496 // The ->connected entry is repurposed to store the parent socket; this is safe
497 // because it's only ever used by lwIP if tcp_connect is called on the TCP PCB.
498 newpcb->connected = (void *)socket;
499 tcp_arg(newpcb, newpcb);
500 tcp_err(newpcb, _lwip_tcp_err_unaccepted);
501
502 return ERR_OK;
503 }
504
505 DEBUG_printf("_lwip_tcp_accept: No room to queue pcb waiting for accept\n");
506 return ERR_BUF;
507 }
508
509 // Callback for inbound tcp packets.
_lwip_tcp_recv(void * arg,struct tcp_pcb * tcpb,struct pbuf * p,err_t err)510 STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err_t err) {
511 lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
512
513 if (p == NULL) {
514 // Other side has closed connection.
515 DEBUG_printf("_lwip_tcp_recv[%p]: other side closed connection\n", socket);
516 socket->state = STATE_PEER_CLOSED;
517 exec_user_callback(socket);
518 return ERR_OK;
519 }
520
521 if (socket->incoming.pbuf == NULL) {
522 socket->incoming.pbuf = p;
523 } else {
524 #ifdef SOCKET_SINGLE_PBUF
525 return ERR_BUF;
526 #else
527 pbuf_cat(socket->incoming.pbuf, p);
528 #endif
529 }
530
531 exec_user_callback(socket);
532
533 return ERR_OK;
534 }
535
536 /*******************************************************************************/
537 // Functions for socket send/receive operations. Socket send/recv and friends call
538 // these to do the work.
539
540 // Helper function for send/sendto to handle raw/UDP packets.
lwip_raw_udp_send(lwip_socket_obj_t * socket,const byte * buf,mp_uint_t len,byte * ip,mp_uint_t port,int * _errno)541 STATIC mp_uint_t lwip_raw_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
542 if (len > 0xffff) {
543 // Any packet that big is probably going to fail the pbuf_alloc anyway, but may as well try
544 len = 0xffff;
545 }
546
547 MICROPY_PY_LWIP_ENTER
548
549 // FIXME: maybe PBUF_ROM?
550 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
551 if (p == NULL) {
552 MICROPY_PY_LWIP_EXIT
553 *_errno = MP_ENOMEM;
554 return -1;
555 }
556
557 memcpy(p->payload, buf, len);
558
559 err_t err;
560 if (ip == NULL) {
561 #if MICROPY_PY_LWIP_SOCK_RAW
562 if (socket->type == MOD_NETWORK_SOCK_RAW) {
563 err = raw_send(socket->pcb.raw, p);
564 } else
565 #endif
566 {
567 err = udp_send(socket->pcb.udp, p);
568 }
569 } else {
570 ip_addr_t dest;
571 IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]);
572 #if MICROPY_PY_LWIP_SOCK_RAW
573 if (socket->type == MOD_NETWORK_SOCK_RAW) {
574 err = raw_sendto(socket->pcb.raw, p, &dest);
575 } else
576 #endif
577 {
578 err = udp_sendto(socket->pcb.udp, p, &dest, port);
579 }
580 }
581
582 pbuf_free(p);
583
584 MICROPY_PY_LWIP_EXIT
585
586 // udp_sendto can return 1 on occasion for ESP8266 port. It's not known why
587 // but it seems that the send actually goes through without error in this case.
588 // So we treat such cases as a success until further investigation.
589 if (err != ERR_OK && err != 1) {
590 *_errno = error_lookup_table[-err];
591 return -1;
592 }
593
594 return len;
595 }
596
597 // Helper function for recv/recvfrom to handle raw/UDP packets
lwip_raw_udp_receive(lwip_socket_obj_t * socket,byte * buf,mp_uint_t len,byte * ip,mp_uint_t * port,int * _errno)598 STATIC mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
599
600 if (socket->incoming.pbuf == NULL) {
601 if (socket->timeout == 0) {
602 // Non-blocking socket.
603 *_errno = MP_EAGAIN;
604 return -1;
605 }
606
607 // Wait for data to arrive on UDP socket.
608 mp_uint_t start = mp_hal_ticks_ms();
609 while (socket->incoming.pbuf == NULL) {
610 if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
611 *_errno = MP_ETIMEDOUT;
612 return -1;
613 }
614 poll_sockets();
615 }
616 }
617
618 if (ip != NULL) {
619 memcpy(ip, &socket->peer, sizeof(socket->peer));
620 *port = socket->peer_port;
621 }
622
623 struct pbuf *p = socket->incoming.pbuf;
624
625 MICROPY_PY_LWIP_ENTER
626
627 u16_t result = pbuf_copy_partial(p, buf, ((p->tot_len > len) ? len : p->tot_len), 0);
628 pbuf_free(p);
629 socket->incoming.pbuf = NULL;
630
631 MICROPY_PY_LWIP_EXIT
632
633 return (mp_uint_t)result;
634 }
635
636 // For use in stream virtual methods
637 #define STREAM_ERROR_CHECK(socket) \
638 if (socket->state < 0) { \
639 *_errno = error_lookup_table[-socket->state]; \
640 return MP_STREAM_ERROR; \
641 } \
642 assert(socket->pcb.tcp);
643
644 // Version of above for use when lock is held
645 #define STREAM_ERROR_CHECK_WITH_LOCK(socket) \
646 if (socket->state < 0) { \
647 *_errno = error_lookup_table[-socket->state]; \
648 MICROPY_PY_LWIP_EXIT \
649 return MP_STREAM_ERROR; \
650 } \
651 assert(socket->pcb.tcp);
652
653
654 // Helper function for send/sendto to handle TCP packets
lwip_tcp_send(lwip_socket_obj_t * socket,const byte * buf,mp_uint_t len,int * _errno)655 STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
656 // Check for any pending errors
657 STREAM_ERROR_CHECK(socket);
658
659 MICROPY_PY_LWIP_ENTER
660
661 u16_t available = tcp_sndbuf(socket->pcb.tcp);
662
663 if (available == 0) {
664 // Non-blocking socket
665 if (socket->timeout == 0) {
666 MICROPY_PY_LWIP_EXIT
667 *_errno = MP_EAGAIN;
668 return MP_STREAM_ERROR;
669 }
670
671 mp_uint_t start = mp_hal_ticks_ms();
672 // Assume that STATE_PEER_CLOSED may mean half-closed connection, where peer closed it
673 // sending direction, but not receiving. Consequently, check for both STATE_CONNECTED
674 // and STATE_PEER_CLOSED as normal conditions and still waiting for buffers to be sent.
675 // If peer fully closed socket, we would have socket->state set to ERR_RST (connection
676 // reset) by error callback.
677 // Avoid sending too small packets, so wait until at least 16 bytes available
678 while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) {
679 MICROPY_PY_LWIP_EXIT
680 if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
681 *_errno = MP_ETIMEDOUT;
682 return MP_STREAM_ERROR;
683 }
684 poll_sockets();
685 MICROPY_PY_LWIP_REENTER
686 }
687
688 // While we waited, something could happen
689 STREAM_ERROR_CHECK_WITH_LOCK(socket);
690 }
691
692 u16_t write_len = MIN(available, len);
693
694 // If tcp_write returns ERR_MEM then there's currently not enough memory to
695 // queue the write, so wait and keep trying until it succeeds (with 10s limit).
696 // Note: if the socket is non-blocking then this code will actually block until
697 // there's enough memory to do the write, but by this stage we have already
698 // committed to being able to write the data.
699 err_t err;
700 for (int i = 0; i < 200; ++i) {
701 err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
702 if (err != ERR_MEM) {
703 break;
704 }
705 err = tcp_output(socket->pcb.tcp);
706 if (err != ERR_OK) {
707 break;
708 }
709 MICROPY_PY_LWIP_EXIT
710 mp_hal_delay_ms(50);
711 MICROPY_PY_LWIP_REENTER
712 }
713
714 // If the output buffer is getting full then send the data to the lower layers
715 if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) {
716 err = tcp_output(socket->pcb.tcp);
717 }
718
719 MICROPY_PY_LWIP_EXIT
720
721 if (err != ERR_OK) {
722 *_errno = error_lookup_table[-err];
723 return MP_STREAM_ERROR;
724 }
725
726 return write_len;
727 }
728
729 // Helper function for recv/recvfrom to handle TCP packets
lwip_tcp_receive(lwip_socket_obj_t * socket,byte * buf,mp_uint_t len,int * _errno)730 STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
731 // Check for any pending errors
732 STREAM_ERROR_CHECK(socket);
733
734 if (socket->incoming.pbuf == NULL) {
735
736 // Non-blocking socket
737 if (socket->timeout == 0) {
738 if (socket->state == STATE_PEER_CLOSED) {
739 return 0;
740 }
741 *_errno = MP_EAGAIN;
742 return -1;
743 }
744
745 mp_uint_t start = mp_hal_ticks_ms();
746 while (socket->state == STATE_CONNECTED && socket->incoming.pbuf == NULL) {
747 if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
748 *_errno = MP_ETIMEDOUT;
749 return -1;
750 }
751 poll_sockets();
752 }
753
754 if (socket->state == STATE_PEER_CLOSED) {
755 if (socket->incoming.pbuf == NULL) {
756 // socket closed and no data left in buffer
757 return 0;
758 }
759 } else if (socket->state != STATE_CONNECTED) {
760 if (socket->state >= STATE_NEW) {
761 *_errno = MP_ENOTCONN;
762 } else {
763 *_errno = error_lookup_table[-socket->state];
764 }
765 return -1;
766 }
767 }
768
769 MICROPY_PY_LWIP_ENTER
770
771 assert(socket->pcb.tcp != NULL);
772
773 struct pbuf *p = socket->incoming.pbuf;
774
775 mp_uint_t remaining = p->len - socket->recv_offset;
776 if (len > remaining) {
777 len = remaining;
778 }
779
780 memcpy(buf, (byte *)p->payload + socket->recv_offset, len);
781
782 remaining -= len;
783 if (remaining == 0) {
784 socket->incoming.pbuf = p->next;
785 // If we don't ref here, free() will free the entire chain,
786 // if we ref, it does what we need: frees 1st buf, and decrements
787 // next buf's refcount back to 1.
788 pbuf_ref(p->next);
789 pbuf_free(p);
790 socket->recv_offset = 0;
791 } else {
792 socket->recv_offset += len;
793 }
794 tcp_recved(socket->pcb.tcp, len);
795
796 MICROPY_PY_LWIP_EXIT
797
798 return len;
799 }
800
801 /*******************************************************************************/
802 // The socket functions provided by lwip.socket.
803
804 STATIC const mp_obj_type_t lwip_socket_type;
805
lwip_socket_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)806 STATIC void lwip_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
807 lwip_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
808 mp_printf(print, "<socket state=%d timeout=%d incoming=%p off=%d>", self->state, self->timeout,
809 self->incoming.pbuf, self->recv_offset);
810 }
811
812 // FIXME: Only supports two arguments at present
lwip_socket_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)813 STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
814 mp_arg_check_num(n_args, n_kw, 0, 4, false);
815
816 lwip_socket_obj_t *socket = m_new_obj_with_finaliser(lwip_socket_obj_t);
817 socket->base.type = &lwip_socket_type;
818 socket->timeout = -1;
819 socket->recv_offset = 0;
820 socket->domain = MOD_NETWORK_AF_INET;
821 socket->type = MOD_NETWORK_SOCK_STREAM;
822 socket->callback = MP_OBJ_NULL;
823 socket->state = STATE_NEW;
824
825 if (n_args >= 1) {
826 socket->domain = mp_obj_get_int(args[0]);
827 if (n_args >= 2) {
828 socket->type = mp_obj_get_int(args[1]);
829 }
830 }
831
832 switch (socket->type) {
833 case MOD_NETWORK_SOCK_STREAM:
834 socket->pcb.tcp = tcp_new();
835 socket->incoming.connection.alloc = 0;
836 socket->incoming.connection.tcp.item = NULL;
837 break;
838 case MOD_NETWORK_SOCK_DGRAM:
839 socket->pcb.udp = udp_new();
840 socket->incoming.pbuf = NULL;
841 break;
842 #if MICROPY_PY_LWIP_SOCK_RAW
843 case MOD_NETWORK_SOCK_RAW: {
844 mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int(args[2]);
845 socket->pcb.raw = raw_new(proto);
846 break;
847 }
848 #endif
849 default:
850 mp_raise_OSError(MP_EINVAL);
851 }
852
853 if (socket->pcb.tcp == NULL) {
854 mp_raise_OSError(MP_ENOMEM);
855 }
856
857 switch (socket->type) {
858 case MOD_NETWORK_SOCK_STREAM: {
859 // Register the socket object as our callback argument.
860 tcp_arg(socket->pcb.tcp, (void *)socket);
861 // Register our error callback.
862 tcp_err(socket->pcb.tcp, _lwip_tcp_error);
863 break;
864 }
865 case MOD_NETWORK_SOCK_DGRAM: {
866 socket->state = STATE_ACTIVE_UDP;
867 // Register our receive callback now. Since UDP sockets don't require binding or connection
868 // before use, there's no other good time to do it.
869 udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void *)socket);
870 break;
871 }
872 #if MICROPY_PY_LWIP_SOCK_RAW
873 case MOD_NETWORK_SOCK_RAW: {
874 // Register our receive callback now. Since raw sockets don't require binding or connection
875 // before use, there's no other good time to do it.
876 raw_recv(socket->pcb.raw, _lwip_raw_incoming, (void *)socket);
877 break;
878 }
879 #endif
880 }
881
882 return MP_OBJ_FROM_PTR(socket);
883 }
884
lwip_socket_bind(mp_obj_t self_in,mp_obj_t addr_in)885 STATIC mp_obj_t lwip_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
886 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
887
888 uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE];
889 mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
890
891 ip_addr_t bind_addr;
892 IP4_ADDR(&bind_addr, ip[0], ip[1], ip[2], ip[3]);
893
894 err_t err = ERR_ARG;
895 switch (socket->type) {
896 case MOD_NETWORK_SOCK_STREAM: {
897 err = tcp_bind(socket->pcb.tcp, &bind_addr, port);
898 break;
899 }
900 case MOD_NETWORK_SOCK_DGRAM: {
901 err = udp_bind(socket->pcb.udp, &bind_addr, port);
902 break;
903 }
904 }
905
906 if (err != ERR_OK) {
907 mp_raise_OSError(error_lookup_table[-err]);
908 }
909
910 return mp_const_none;
911 }
912 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_bind_obj, lwip_socket_bind);
913
lwip_socket_listen(mp_obj_t self_in,mp_obj_t backlog_in)914 STATIC mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
915 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
916 mp_int_t backlog = mp_obj_get_int(backlog_in);
917
918 if (socket->pcb.tcp == NULL) {
919 mp_raise_OSError(MP_EBADF);
920 }
921 if (socket->type != MOD_NETWORK_SOCK_STREAM) {
922 mp_raise_OSError(MP_EOPNOTSUPP);
923 }
924
925 struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
926 if (new_pcb == NULL) {
927 mp_raise_OSError(MP_ENOMEM);
928 }
929 socket->pcb.tcp = new_pcb;
930
931 // Allocate memory for the backlog of connections
932 if (backlog <= 1) {
933 socket->incoming.connection.alloc = 0;
934 socket->incoming.connection.tcp.item = NULL;
935 } else {
936 socket->incoming.connection.alloc = backlog;
937 socket->incoming.connection.tcp.array = m_new0(struct tcp_pcb *, backlog);
938 }
939 socket->incoming.connection.iget = 0;
940 socket->incoming.connection.iput = 0;
941
942 tcp_accept(new_pcb, _lwip_tcp_accept);
943
944 // Socket is no longer considered "new" for purposes of polling
945 socket->state = STATE_LISTENING;
946
947 return mp_const_none;
948 }
949 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_listen_obj, lwip_socket_listen);
950
lwip_socket_accept(mp_obj_t self_in)951 STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
952 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
953
954 if (socket->type != MOD_NETWORK_SOCK_STREAM) {
955 mp_raise_OSError(MP_EOPNOTSUPP);
956 }
957
958 // Create new socket object, do it here because we must not raise an out-of-memory
959 // exception when the LWIP concurrency lock is held
960 lwip_socket_obj_t *socket2 = m_new_obj_with_finaliser(lwip_socket_obj_t);
961 socket2->base.type = &lwip_socket_type;
962
963 MICROPY_PY_LWIP_ENTER
964
965 if (socket->pcb.tcp == NULL) {
966 MICROPY_PY_LWIP_EXIT
967 m_del_obj(lwip_socket_obj_t, socket2);
968 mp_raise_OSError(MP_EBADF);
969 }
970
971 // I need to do this because "tcp_accepted", later, is a macro.
972 struct tcp_pcb *listener = socket->pcb.tcp;
973 if (listener->state != LISTEN) {
974 MICROPY_PY_LWIP_EXIT
975 m_del_obj(lwip_socket_obj_t, socket2);
976 mp_raise_OSError(MP_EINVAL);
977 }
978
979 // accept incoming connection
980 struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget];
981 if (*incoming_connection == NULL) {
982 if (socket->timeout == 0) {
983 MICROPY_PY_LWIP_EXIT
984 m_del_obj(lwip_socket_obj_t, socket2);
985 mp_raise_OSError(MP_EAGAIN);
986 } else if (socket->timeout != -1) {
987 mp_uint_t retries = socket->timeout / 100;
988 while (*incoming_connection == NULL) {
989 MICROPY_PY_LWIP_EXIT
990 if (retries-- == 0) {
991 m_del_obj(lwip_socket_obj_t, socket2);
992 mp_raise_OSError(MP_ETIMEDOUT);
993 }
994 mp_hal_delay_ms(100);
995 MICROPY_PY_LWIP_REENTER
996 }
997 } else {
998 while (*incoming_connection == NULL) {
999 MICROPY_PY_LWIP_EXIT
1000 poll_sockets();
1001 MICROPY_PY_LWIP_REENTER
1002 }
1003 }
1004 }
1005
1006 // We get a new pcb handle...
1007 socket2->pcb.tcp = *incoming_connection;
1008 if (++socket->incoming.connection.iget >= socket->incoming.connection.alloc) {
1009 socket->incoming.connection.iget = 0;
1010 }
1011 *incoming_connection = NULL;
1012
1013 // ...and set up the new socket for it.
1014 socket2->domain = MOD_NETWORK_AF_INET;
1015 socket2->type = MOD_NETWORK_SOCK_STREAM;
1016 socket2->incoming.pbuf = NULL;
1017 socket2->timeout = socket->timeout;
1018 socket2->state = STATE_CONNECTED;
1019 socket2->recv_offset = 0;
1020 socket2->callback = MP_OBJ_NULL;
1021 tcp_arg(socket2->pcb.tcp, (void *)socket2);
1022 tcp_err(socket2->pcb.tcp, _lwip_tcp_error);
1023 tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv);
1024
1025 tcp_accepted(listener);
1026
1027 MICROPY_PY_LWIP_EXIT
1028
1029 // make the return value
1030 uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE];
1031 memcpy(ip, &(socket2->pcb.tcp->remote_ip), sizeof(ip));
1032 mp_uint_t port = (mp_uint_t)socket2->pcb.tcp->remote_port;
1033 mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
1034 client->items[0] = MP_OBJ_FROM_PTR(socket2);
1035 client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
1036
1037 return MP_OBJ_FROM_PTR(client);
1038 }
1039 STATIC MP_DEFINE_CONST_FUN_OBJ_1(lwip_socket_accept_obj, lwip_socket_accept);
1040
lwip_socket_connect(mp_obj_t self_in,mp_obj_t addr_in)1041 STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
1042 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1043
1044 if (socket->pcb.tcp == NULL) {
1045 mp_raise_OSError(MP_EBADF);
1046 }
1047
1048 // get address
1049 uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE];
1050 mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
1051
1052 ip_addr_t dest;
1053 IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]);
1054
1055 err_t err = ERR_ARG;
1056 switch (socket->type) {
1057 case MOD_NETWORK_SOCK_STREAM: {
1058 if (socket->state != STATE_NEW) {
1059 if (socket->state == STATE_CONNECTED) {
1060 mp_raise_OSError(MP_EISCONN);
1061 } else {
1062 mp_raise_OSError(MP_EALREADY);
1063 }
1064 }
1065
1066 // Register our receive callback.
1067 MICROPY_PY_LWIP_ENTER
1068 tcp_recv(socket->pcb.tcp, _lwip_tcp_recv);
1069 socket->state = STATE_CONNECTING;
1070 err = tcp_connect(socket->pcb.tcp, &dest, port, _lwip_tcp_connected);
1071 if (err != ERR_OK) {
1072 MICROPY_PY_LWIP_EXIT
1073 socket->state = STATE_NEW;
1074 mp_raise_OSError(error_lookup_table[-err]);
1075 }
1076 socket->peer_port = (mp_uint_t)port;
1077 memcpy(socket->peer, &dest, sizeof(socket->peer));
1078 MICROPY_PY_LWIP_EXIT
1079
1080 // And now we wait...
1081 if (socket->timeout != -1) {
1082 for (mp_uint_t retries = socket->timeout / 100; retries--;) {
1083 mp_hal_delay_ms(100);
1084 if (socket->state != STATE_CONNECTING) {
1085 break;
1086 }
1087 }
1088 if (socket->state == STATE_CONNECTING) {
1089 mp_raise_OSError(MP_EINPROGRESS);
1090 }
1091 } else {
1092 while (socket->state == STATE_CONNECTING) {
1093 poll_sockets();
1094 }
1095 }
1096 if (socket->state == STATE_CONNECTED) {
1097 err = ERR_OK;
1098 } else {
1099 err = socket->state;
1100 }
1101 break;
1102 }
1103 case MOD_NETWORK_SOCK_DGRAM: {
1104 err = udp_connect(socket->pcb.udp, &dest, port);
1105 break;
1106 }
1107 #if MICROPY_PY_LWIP_SOCK_RAW
1108 case MOD_NETWORK_SOCK_RAW: {
1109 err = raw_connect(socket->pcb.raw, &dest);
1110 break;
1111 }
1112 #endif
1113 }
1114
1115 if (err != ERR_OK) {
1116 mp_raise_OSError(error_lookup_table[-err]);
1117 }
1118
1119 return mp_const_none;
1120 }
1121 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_connect_obj, lwip_socket_connect);
1122
lwip_socket_check_connected(lwip_socket_obj_t * socket)1123 STATIC void lwip_socket_check_connected(lwip_socket_obj_t *socket) {
1124 if (socket->pcb.tcp == NULL) {
1125 // not connected
1126 int _errno = error_lookup_table[-socket->state];
1127 socket->state = _ERR_BADF;
1128 mp_raise_OSError(_errno);
1129 }
1130 }
1131
lwip_socket_send(mp_obj_t self_in,mp_obj_t buf_in)1132 STATIC mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
1133 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1134 int _errno;
1135
1136 lwip_socket_check_connected(socket);
1137
1138 mp_buffer_info_t bufinfo;
1139 mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
1140
1141 mp_uint_t ret = 0;
1142 switch (socket->type) {
1143 case MOD_NETWORK_SOCK_STREAM: {
1144 ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
1145 break;
1146 }
1147 case MOD_NETWORK_SOCK_DGRAM:
1148 #if MICROPY_PY_LWIP_SOCK_RAW
1149 case MOD_NETWORK_SOCK_RAW:
1150 #endif
1151 ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno);
1152 break;
1153 }
1154 if (ret == -1) {
1155 mp_raise_OSError(_errno);
1156 }
1157
1158 return mp_obj_new_int_from_uint(ret);
1159 }
1160 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_send_obj, lwip_socket_send);
1161
lwip_socket_recv(mp_obj_t self_in,mp_obj_t len_in)1162 STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
1163 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1164 int _errno;
1165
1166 lwip_socket_check_connected(socket);
1167
1168 mp_int_t len = mp_obj_get_int(len_in);
1169 vstr_t vstr;
1170 vstr_init_len(&vstr, len);
1171
1172 mp_uint_t ret = 0;
1173 switch (socket->type) {
1174 case MOD_NETWORK_SOCK_STREAM: {
1175 ret = lwip_tcp_receive(socket, (byte *)vstr.buf, len, &_errno);
1176 break;
1177 }
1178 case MOD_NETWORK_SOCK_DGRAM:
1179 #if MICROPY_PY_LWIP_SOCK_RAW
1180 case MOD_NETWORK_SOCK_RAW:
1181 #endif
1182 ret = lwip_raw_udp_receive(socket, (byte *)vstr.buf, len, NULL, NULL, &_errno);
1183 break;
1184 }
1185 if (ret == -1) {
1186 mp_raise_OSError(_errno);
1187 }
1188
1189 if (ret == 0) {
1190 return mp_const_empty_bytes;
1191 }
1192 vstr.len = ret;
1193 return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
1194 }
1195 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recv_obj, lwip_socket_recv);
1196
lwip_socket_sendto(mp_obj_t self_in,mp_obj_t data_in,mp_obj_t addr_in)1197 STATIC mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
1198 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1199 int _errno;
1200
1201 lwip_socket_check_connected(socket);
1202
1203 mp_buffer_info_t bufinfo;
1204 mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
1205
1206 uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE];
1207 mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
1208
1209 mp_uint_t ret = 0;
1210 switch (socket->type) {
1211 case MOD_NETWORK_SOCK_STREAM: {
1212 ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
1213 break;
1214 }
1215 case MOD_NETWORK_SOCK_DGRAM:
1216 #if MICROPY_PY_LWIP_SOCK_RAW
1217 case MOD_NETWORK_SOCK_RAW:
1218 #endif
1219 ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno);
1220 break;
1221 }
1222 if (ret == -1) {
1223 mp_raise_OSError(_errno);
1224 }
1225
1226 return mp_obj_new_int_from_uint(ret);
1227 }
1228 STATIC MP_DEFINE_CONST_FUN_OBJ_3(lwip_socket_sendto_obj, lwip_socket_sendto);
1229
lwip_socket_recvfrom(mp_obj_t self_in,mp_obj_t len_in)1230 STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
1231 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1232 int _errno;
1233
1234 lwip_socket_check_connected(socket);
1235
1236 mp_int_t len = mp_obj_get_int(len_in);
1237 vstr_t vstr;
1238 vstr_init_len(&vstr, len);
1239 byte ip[4];
1240 mp_uint_t port;
1241
1242 mp_uint_t ret = 0;
1243 switch (socket->type) {
1244 case MOD_NETWORK_SOCK_STREAM: {
1245 memcpy(ip, &socket->peer, sizeof(socket->peer));
1246 port = (mp_uint_t)socket->peer_port;
1247 ret = lwip_tcp_receive(socket, (byte *)vstr.buf, len, &_errno);
1248 break;
1249 }
1250 case MOD_NETWORK_SOCK_DGRAM:
1251 #if MICROPY_PY_LWIP_SOCK_RAW
1252 case MOD_NETWORK_SOCK_RAW:
1253 #endif
1254 ret = lwip_raw_udp_receive(socket, (byte *)vstr.buf, len, ip, &port, &_errno);
1255 break;
1256 }
1257 if (ret == -1) {
1258 mp_raise_OSError(_errno);
1259 }
1260
1261 mp_obj_t tuple[2];
1262 if (ret == 0) {
1263 tuple[0] = mp_const_empty_bytes;
1264 } else {
1265 vstr.len = ret;
1266 tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
1267 }
1268 tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
1269 return mp_obj_new_tuple(2, tuple);
1270 }
1271 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recvfrom_obj, lwip_socket_recvfrom);
1272
lwip_socket_sendall(mp_obj_t self_in,mp_obj_t buf_in)1273 STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
1274 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1275 lwip_socket_check_connected(socket);
1276
1277 int _errno;
1278 mp_buffer_info_t bufinfo;
1279 mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
1280
1281 mp_uint_t ret = 0;
1282 switch (socket->type) {
1283 case MOD_NETWORK_SOCK_STREAM: {
1284 if (socket->timeout == 0) {
1285 // Behavior of sendall() for non-blocking sockets isn't explicitly specified.
1286 // But it's specified that "On error, an exception is raised, there is no
1287 // way to determine how much data, if any, was successfully sent." Then, the
1288 // most useful behavior is: check whether we will be able to send all of input
1289 // data without EAGAIN, and if won't be, raise it without sending any.
1290 if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) {
1291 mp_raise_OSError(MP_EAGAIN);
1292 }
1293 }
1294 // TODO: In CPython3.5, socket timeout should apply to the
1295 // entire sendall() operation, not to individual send() chunks.
1296 while (bufinfo.len != 0) {
1297 ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
1298 if (ret == -1) {
1299 mp_raise_OSError(_errno);
1300 }
1301 bufinfo.len -= ret;
1302 bufinfo.buf = (char *)bufinfo.buf + ret;
1303 }
1304 break;
1305 }
1306 case MOD_NETWORK_SOCK_DGRAM:
1307 mp_raise_NotImplementedError(NULL);
1308 break;
1309 }
1310
1311 return mp_const_none;
1312 }
1313 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_sendall_obj, lwip_socket_sendall);
1314
lwip_socket_settimeout(mp_obj_t self_in,mp_obj_t timeout_in)1315 STATIC mp_obj_t lwip_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
1316 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1317 mp_uint_t timeout;
1318 if (timeout_in == mp_const_none) {
1319 timeout = -1;
1320 } else {
1321 #if MICROPY_PY_BUILTINS_FLOAT
1322 timeout = (mp_uint_t)(MICROPY_FLOAT_CONST(1000.0) * mp_obj_get_float(timeout_in));
1323 #else
1324 timeout = 1000 * mp_obj_get_int(timeout_in);
1325 #endif
1326 }
1327 socket->timeout = timeout;
1328 return mp_const_none;
1329 }
1330 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_settimeout_obj, lwip_socket_settimeout);
1331
lwip_socket_setblocking(mp_obj_t self_in,mp_obj_t flag_in)1332 STATIC mp_obj_t lwip_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
1333 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1334 bool val = mp_obj_is_true(flag_in);
1335 if (val) {
1336 socket->timeout = -1;
1337 } else {
1338 socket->timeout = 0;
1339 }
1340 return mp_const_none;
1341 }
1342 STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_setblocking_obj, lwip_socket_setblocking);
1343
lwip_socket_setsockopt(size_t n_args,const mp_obj_t * args)1344 STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
1345 (void)n_args; // always 4
1346 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(args[0]);
1347
1348 int opt = mp_obj_get_int(args[2]);
1349 if (opt == 20) {
1350 if (args[3] == mp_const_none) {
1351 socket->callback = MP_OBJ_NULL;
1352 } else {
1353 socket->callback = args[3];
1354 }
1355 return mp_const_none;
1356 }
1357
1358 switch (opt) {
1359 // level: SOL_SOCKET
1360 case SOF_REUSEADDR: {
1361 mp_int_t val = mp_obj_get_int(args[3]);
1362 // Options are common for UDP and TCP pcb's.
1363 if (val) {
1364 ip_set_option(socket->pcb.tcp, SOF_REUSEADDR);
1365 } else {
1366 ip_reset_option(socket->pcb.tcp, SOF_REUSEADDR);
1367 }
1368 break;
1369 }
1370
1371 // level: IPPROTO_IP
1372 case IP_ADD_MEMBERSHIP: {
1373 mp_buffer_info_t bufinfo;
1374 mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
1375 if (bufinfo.len != sizeof(ip_addr_t) * 2) {
1376 mp_raise_ValueError(NULL);
1377 }
1378
1379 // POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa
1380 err_t err = igmp_joingroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf);
1381 if (err != ERR_OK) {
1382 mp_raise_OSError(error_lookup_table[-err]);
1383 }
1384 break;
1385 }
1386
1387 default:
1388 printf("Warning: lwip.setsockopt() not implemented\n");
1389 }
1390 return mp_const_none;
1391 }
1392 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_socket_setsockopt_obj, 4, 4, lwip_socket_setsockopt);
1393
lwip_socket_makefile(size_t n_args,const mp_obj_t * args)1394 STATIC mp_obj_t lwip_socket_makefile(size_t n_args, const mp_obj_t *args) {
1395 (void)n_args;
1396 return args[0];
1397 }
1398 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_socket_makefile_obj, 1, 3, lwip_socket_makefile);
1399
lwip_socket_read(mp_obj_t self_in,void * buf,mp_uint_t size,int * errcode)1400 STATIC mp_uint_t lwip_socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
1401 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1402
1403 switch (socket->type) {
1404 case MOD_NETWORK_SOCK_STREAM:
1405 return lwip_tcp_receive(socket, buf, size, errcode);
1406 case MOD_NETWORK_SOCK_DGRAM:
1407 #if MICROPY_PY_LWIP_SOCK_RAW
1408 case MOD_NETWORK_SOCK_RAW:
1409 #endif
1410 return lwip_raw_udp_receive(socket, buf, size, NULL, NULL, errcode);
1411 }
1412 // Unreachable
1413 return MP_STREAM_ERROR;
1414 }
1415
lwip_socket_write(mp_obj_t self_in,const void * buf,mp_uint_t size,int * errcode)1416 STATIC mp_uint_t lwip_socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
1417 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1418
1419 switch (socket->type) {
1420 case MOD_NETWORK_SOCK_STREAM:
1421 return lwip_tcp_send(socket, buf, size, errcode);
1422 case MOD_NETWORK_SOCK_DGRAM:
1423 #if MICROPY_PY_LWIP_SOCK_RAW
1424 case MOD_NETWORK_SOCK_RAW:
1425 #endif
1426 return lwip_raw_udp_send(socket, buf, size, NULL, 0, errcode);
1427 }
1428 // Unreachable
1429 return MP_STREAM_ERROR;
1430 }
1431
_lwip_tcp_close_poll(void * arg,struct tcp_pcb * pcb)1432 STATIC err_t _lwip_tcp_close_poll(void *arg, struct tcp_pcb *pcb) {
1433 // Connection has not been cleanly closed so just abort it to free up memory
1434 tcp_poll(pcb, NULL, 0);
1435 tcp_abort(pcb);
1436 return ERR_OK;
1437 }
1438
lwip_socket_ioctl(mp_obj_t self_in,mp_uint_t request,uintptr_t arg,int * errcode)1439 STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
1440 lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
1441 mp_uint_t ret;
1442
1443 MICROPY_PY_LWIP_ENTER
1444
1445 if (request == MP_STREAM_POLL) {
1446 uintptr_t flags = arg;
1447 ret = 0;
1448
1449 if (flags & MP_STREAM_POLL_RD) {
1450 if (socket->state == STATE_LISTENING) {
1451 // Listening TCP socket may have one or multiple connections waiting
1452 if (lwip_socket_incoming_array(socket)[socket->incoming.connection.iget] != NULL) {
1453 ret |= MP_STREAM_POLL_RD;
1454 }
1455 } else {
1456 // Otherwise there is just one slot for incoming data
1457 if (socket->incoming.pbuf != NULL) {
1458 ret |= MP_STREAM_POLL_RD;
1459 }
1460 }
1461 }
1462
1463 if (flags & MP_STREAM_POLL_WR) {
1464 if (socket->type == MOD_NETWORK_SOCK_DGRAM && socket->pcb.udp != NULL) {
1465 // UDP socket is writable
1466 ret |= MP_STREAM_POLL_WR;
1467 #if MICROPY_PY_LWIP_SOCK_RAW
1468 } else if (socket->type == MOD_NETWORK_SOCK_RAW && socket->pcb.raw != NULL) {
1469 // raw socket is writable
1470 ret |= MP_STREAM_POLL_WR;
1471 #endif
1472 } else if (socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) {
1473 // TCP socket is writable
1474 // Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf
1475 ret |= MP_STREAM_POLL_WR;
1476 }
1477 }
1478
1479 if (socket->state == STATE_NEW) {
1480 // New sockets are not connected so set HUP
1481 ret |= MP_STREAM_POLL_HUP;
1482 } else if (socket->state == STATE_PEER_CLOSED) {
1483 // Peer-closed socket is both readable and writable: read will
1484 // return EOF, write - error. Without this poll will hang on a
1485 // socket which was closed by peer.
1486 ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR);
1487 } else if (socket->state == ERR_RST) {
1488 // Socket was reset by peer, a write will return an error
1489 ret |= flags & MP_STREAM_POLL_WR;
1490 ret |= MP_STREAM_POLL_HUP;
1491 } else if (socket->state == _ERR_BADF) {
1492 ret |= MP_STREAM_POLL_NVAL;
1493 } else if (socket->state < 0) {
1494 // Socket in some other error state, use catch-all ERR flag
1495 // TODO: may need to set other return flags here
1496 ret |= MP_STREAM_POLL_ERR;
1497 }
1498
1499 } else if (request == MP_STREAM_CLOSE) {
1500 if (socket->pcb.tcp == NULL) {
1501 MICROPY_PY_LWIP_EXIT
1502 return 0;
1503 }
1504
1505 // Free any incoming buffers or connections that are stored
1506 lwip_socket_free_incoming(socket);
1507
1508 switch (socket->type) {
1509 case MOD_NETWORK_SOCK_STREAM: {
1510 // Deregister callback (pcb.tcp is set to NULL below so must deregister now)
1511 tcp_arg(socket->pcb.tcp, NULL);
1512 tcp_err(socket->pcb.tcp, NULL);
1513 tcp_recv(socket->pcb.tcp, NULL);
1514
1515 if (socket->pcb.tcp->state != LISTEN) {
1516 // Schedule a callback to abort the connection if it's not cleanly closed after
1517 // the given timeout. The callback must be set before calling tcp_close since
1518 // the latter may free the pcb; if it doesn't then the callback will be active.
1519 tcp_poll(socket->pcb.tcp, _lwip_tcp_close_poll, MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS / 500);
1520 }
1521 if (tcp_close(socket->pcb.tcp) != ERR_OK) {
1522 DEBUG_printf("lwip_close: had to call tcp_abort()\n");
1523 tcp_abort(socket->pcb.tcp);
1524 }
1525 break;
1526 }
1527 case MOD_NETWORK_SOCK_DGRAM:
1528 udp_recv(socket->pcb.udp, NULL, NULL);
1529 udp_remove(socket->pcb.udp);
1530 break;
1531 #if MICROPY_PY_LWIP_SOCK_RAW
1532 case MOD_NETWORK_SOCK_RAW:
1533 raw_recv(socket->pcb.raw, NULL, NULL);
1534 raw_remove(socket->pcb.raw);
1535 break;
1536 #endif
1537 }
1538
1539 socket->pcb.tcp = NULL;
1540 socket->state = _ERR_BADF;
1541 ret = 0;
1542
1543 } else {
1544 *errcode = MP_EINVAL;
1545 ret = MP_STREAM_ERROR;
1546 }
1547
1548 MICROPY_PY_LWIP_EXIT
1549
1550 return ret;
1551 }
1552
1553 STATIC const mp_rom_map_elem_t lwip_socket_locals_dict_table[] = {
1554 { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
1555 { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
1556 { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&lwip_socket_bind_obj) },
1557 { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&lwip_socket_listen_obj) },
1558 { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&lwip_socket_accept_obj) },
1559 { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&lwip_socket_connect_obj) },
1560 { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&lwip_socket_send_obj) },
1561 { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&lwip_socket_recv_obj) },
1562 { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&lwip_socket_sendto_obj) },
1563 { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&lwip_socket_recvfrom_obj) },
1564 { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&lwip_socket_sendall_obj) },
1565 { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&lwip_socket_settimeout_obj) },
1566 { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&lwip_socket_setblocking_obj) },
1567 { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&lwip_socket_setsockopt_obj) },
1568 { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&lwip_socket_makefile_obj) },
1569
1570 { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
1571 { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
1572 { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
1573 { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
1574 };
1575 STATIC MP_DEFINE_CONST_DICT(lwip_socket_locals_dict, lwip_socket_locals_dict_table);
1576
1577 STATIC const mp_stream_p_t lwip_socket_stream_p = {
1578 .read = lwip_socket_read,
1579 .write = lwip_socket_write,
1580 .ioctl = lwip_socket_ioctl,
1581 };
1582
1583 STATIC const mp_obj_type_t lwip_socket_type = {
1584 { &mp_type_type },
1585 .name = MP_QSTR_socket,
1586 .print = lwip_socket_print,
1587 .make_new = lwip_socket_make_new,
1588 .protocol = &lwip_socket_stream_p,
1589 .locals_dict = (mp_obj_dict_t *)&lwip_socket_locals_dict,
1590 };
1591
1592 /******************************************************************************/
1593 // Support functions for memory protection. lwIP has its own memory management
1594 // routines for its internal structures, and since they might be called in
1595 // interrupt handlers, they need some protection.
sys_arch_protect()1596 sys_prot_t sys_arch_protect() {
1597 return (sys_prot_t)MICROPY_BEGIN_ATOMIC_SECTION();
1598 }
1599
sys_arch_unprotect(sys_prot_t state)1600 void sys_arch_unprotect(sys_prot_t state) {
1601 MICROPY_END_ATOMIC_SECTION((mp_uint_t)state);
1602 }
1603
1604 /******************************************************************************/
1605 // Polling callbacks for the interfaces connected to lwIP. Right now it calls
1606 // itself a "list" but isn't; we only support a single interface.
1607
1608 typedef struct nic_poll {
1609 void (*poll)(void *arg);
1610 void *poll_arg;
1611 } nic_poll_t;
1612
1613 STATIC nic_poll_t lwip_poll_list;
1614
mod_lwip_register_poll(void (* poll)(void * arg),void * poll_arg)1615 void mod_lwip_register_poll(void (*poll)(void *arg), void *poll_arg) {
1616 lwip_poll_list.poll = poll;
1617 lwip_poll_list.poll_arg = poll_arg;
1618 }
1619
mod_lwip_deregister_poll(void (* poll)(void * arg),void * poll_arg)1620 void mod_lwip_deregister_poll(void (*poll)(void *arg), void *poll_arg) {
1621 lwip_poll_list.poll = NULL;
1622 }
1623
1624 /******************************************************************************/
1625 // The lwip global functions.
1626
mod_lwip_reset()1627 STATIC mp_obj_t mod_lwip_reset() {
1628 lwip_init();
1629 lwip_poll_list.poll = NULL;
1630 return mp_const_none;
1631 }
1632 MP_DEFINE_CONST_FUN_OBJ_0(mod_lwip_reset_obj, mod_lwip_reset);
1633
mod_lwip_callback()1634 STATIC mp_obj_t mod_lwip_callback() {
1635 if (lwip_poll_list.poll != NULL) {
1636 lwip_poll_list.poll(lwip_poll_list.poll_arg);
1637 }
1638 sys_check_timeouts();
1639 return mp_const_none;
1640 }
1641 MP_DEFINE_CONST_FUN_OBJ_0(mod_lwip_callback_obj, mod_lwip_callback);
1642
1643 typedef struct _getaddrinfo_state_t {
1644 volatile int status;
1645 volatile ip_addr_t ipaddr;
1646 } getaddrinfo_state_t;
1647
1648 // Callback for incoming DNS requests.
1649 #if LWIP_VERSION_MAJOR < 2
lwip_getaddrinfo_cb(const char * name,ip_addr_t * ipaddr,void * arg)1650 STATIC void lwip_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg)
1651 #else
1652 STATIC void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
1653 #endif
1654 {
1655 getaddrinfo_state_t *state = arg;
1656 if (ipaddr != NULL) {
1657 state->status = 1;
1658 state->ipaddr = *ipaddr;
1659 } else {
1660 // error
1661 state->status = -2;
1662 }
1663 }
1664
1665 // lwip.getaddrinfo
lwip_getaddrinfo(size_t n_args,const mp_obj_t * args)1666 STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
1667 mp_obj_t host_in = args[0], port_in = args[1];
1668 const char *host = mp_obj_str_get_str(host_in);
1669 mp_int_t port = mp_obj_get_int(port_in);
1670
1671 // If constraints were passed then check they are compatible with the supported params
1672 if (n_args > 2) {
1673 mp_int_t family = mp_obj_get_int(args[2]);
1674 mp_int_t type = 0;
1675 mp_int_t proto = 0;
1676 mp_int_t flags = 0;
1677 if (n_args > 3) {
1678 type = mp_obj_get_int(args[3]);
1679 if (n_args > 4) {
1680 proto = mp_obj_get_int(args[4]);
1681 if (n_args > 5) {
1682 flags = mp_obj_get_int(args[5]);
1683 }
1684 }
1685 }
1686 if (!((family == 0 || family == MOD_NETWORK_AF_INET)
1687 && (type == 0 || type == MOD_NETWORK_SOCK_STREAM)
1688 && proto == 0
1689 && flags == 0)) {
1690 mp_warning(MP_WARN_CAT(RuntimeWarning), "unsupported getaddrinfo constraints");
1691 }
1692 }
1693
1694 getaddrinfo_state_t state;
1695 state.status = 0;
1696
1697 MICROPY_PY_LWIP_ENTER
1698 err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state);
1699 MICROPY_PY_LWIP_EXIT
1700
1701 switch (ret) {
1702 case ERR_OK:
1703 // cached
1704 state.status = 1;
1705 break;
1706 case ERR_INPROGRESS:
1707 while (state.status == 0) {
1708 poll_sockets();
1709 }
1710 break;
1711 default:
1712 state.status = ret;
1713 }
1714
1715 if (state.status < 0) {
1716 // TODO: CPython raises gaierror, we raise with native lwIP negative error
1717 // values, to differentiate from normal errno's at least in such way.
1718 mp_raise_OSError(state.status);
1719 }
1720
1721 mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
1722 tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
1723 tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
1724 tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
1725 tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
1726 tuple->items[4] = netutils_format_inet_addr((uint8_t *)&state.ipaddr, port, NETUTILS_BIG);
1727 return mp_obj_new_list(1, (mp_obj_t *)&tuple);
1728 }
1729 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_getaddrinfo_obj, 2, 6, lwip_getaddrinfo);
1730
1731 // Debug functions
1732
lwip_print_pcbs()1733 STATIC mp_obj_t lwip_print_pcbs() {
1734 tcp_debug_print_pcbs();
1735 return mp_const_none;
1736 }
1737 MP_DEFINE_CONST_FUN_OBJ_0(lwip_print_pcbs_obj, lwip_print_pcbs);
1738
1739 #if MICROPY_PY_LWIP
1740
1741 STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = {
1742 { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_lwip) },
1743 { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mod_lwip_reset_obj) },
1744 { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&mod_lwip_callback_obj) },
1745 { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&lwip_getaddrinfo_obj) },
1746 { MP_ROM_QSTR(MP_QSTR_print_pcbs), MP_ROM_PTR(&lwip_print_pcbs_obj) },
1747 // objects
1748 { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&lwip_socket_type) },
1749 #ifdef MICROPY_PY_LWIP_SLIP
1750 { MP_ROM_QSTR(MP_QSTR_slip), MP_ROM_PTR(&lwip_slip_type) },
1751 #endif
1752 // class constants
1753 { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) },
1754 { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) },
1755
1756 { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
1757 { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
1758 #if MICROPY_PY_LWIP_SOCK_RAW
1759 { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
1760 #endif
1761
1762 { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) },
1763 { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SOF_REUSEADDR) },
1764
1765 { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(0) },
1766 { MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) },
1767 };
1768
1769 STATIC MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table);
1770
1771 const mp_obj_module_t mp_module_lwip = {
1772 .base = { &mp_type_module },
1773 .globals = (mp_obj_dict_t *)&mp_module_lwip_globals,
1774 };
1775
1776 #endif // MICROPY_PY_LWIP
1777