diff --git a/extmod/lwip-include/lwipopts.h b/extmod/lwip-include/lwipopts.h index a11bac935a..e4a33b2381 100644 --- a/extmod/lwip-include/lwipopts.h +++ b/extmod/lwip-include/lwipopts.h @@ -3,7 +3,7 @@ #include #include -#include MICROPY_HAL_H +#include // We're running without an OS for this port. We don't provide any services except light protection. #define NO_SYS 1 diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 0f3ab7c155..274a07daa1 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -32,7 +32,7 @@ #include "py/objlist.h" #include "py/runtime.h" #include "py/stream.h" -#include MICROPY_HAL_H +#include "py/mphal.h" #include "netutils.h" @@ -183,8 +183,14 @@ static const int error_lookup_table[] = { typedef struct _lwip_socket_obj_t { mp_obj_base_t base; - void *pcb; - void *volatile incoming; + union { + struct tcp_pcb *tcp; + struct udp_pcb *udp; + } pcb; + union { + struct pbuf *pbuf; + struct tcp_pcb *connection; + } incoming; byte peer[4]; mp_uint_t peer_port; mp_uint_t timeout; @@ -205,11 +211,11 @@ typedef struct _lwip_socket_obj_t { STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port) { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; - if (socket->incoming != NULL) { + if (socket->incoming.pbuf != NULL) { // That's why they call it "unreliable". No room in the inn, drop the packet. pbuf_free(p); } else { - socket->incoming = (void*)p; + socket->incoming.pbuf = p; socket->peer_port = (mp_uint_t)port; memcpy(&socket->peer, addr, 4); } @@ -222,7 +228,7 @@ STATIC void _lwip_tcp_error(void *arg, err_t err) { // Pass the error code back via the connection variable. socket->connected = err; // If we got here, the lwIP stack either has deallocated or will deallocate the pcb. - socket->pcb = NULL; + socket->pcb.tcp = NULL; } // Callback for tcp connection requests. Error code err is unused. (See tcp.h) @@ -237,12 +243,12 @@ STATIC err_t _lwip_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) { STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; - if (socket->incoming != NULL) { + if (socket->incoming.connection != NULL) { // We need to handle this better. This single-level structure makes the // backlog setting kind of pointless. FIXME return ERR_BUF; } else { - socket->incoming = (void*)newpcb; + socket->incoming.connection = newpcb; return ERR_OK; } } @@ -255,11 +261,11 @@ STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err // Other side has closed connection. socket->connected = 3; return ERR_OK; - } else if (socket->incoming != NULL) { + } else if (socket->incoming.pbuf != NULL) { // No room in the inn, let LWIP know it's still responsible for delivery later return ERR_BUF; } - socket->incoming = (void*)p; + socket->incoming.pbuf = p; return ERR_OK; } @@ -298,11 +304,11 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui err_t err; if (ip == NULL) { - err = udp_send((struct udp_pcb*)socket->pcb, p); + err = udp_send(socket->pcb.udp, p); } else { ip_addr_t dest; IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]); - err = udp_sendto((struct udp_pcb*)socket->pcb, p, &dest, port); + err = udp_sendto(socket->pcb.udp, p, &dest, port); } pbuf_free(p); @@ -318,18 +324,18 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui // Helper function for recv/recvfrom to handle UDP packets STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { - if (socket->incoming == NULL) { + if (socket->incoming.pbuf == NULL) { if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); - if (socket->incoming != NULL) break; + if (socket->incoming.pbuf != NULL) break; } - if (socket->incoming == NULL) { + if (socket->incoming.pbuf == NULL) { *_errno = ETIMEDOUT; return -1; } } else { - while (socket->incoming == NULL) { + while (socket->incoming.pbuf == NULL) { mp_hal_delay_ms(100); } } @@ -340,22 +346,21 @@ STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_ *port = socket->peer_port; } - struct pbuf *p = (struct pbuf*)socket->incoming; + struct pbuf *p = socket->incoming.pbuf; u16_t result = pbuf_copy_partial(p, buf, ((p->tot_len > len) ? len : p->tot_len), 0); pbuf_free(p); - socket->incoming = NULL; + socket->incoming.pbuf = NULL; return (mp_uint_t) result; } // Helper function for send/sendto to handle TCP packets STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { - struct tcp_pcb *pcb = (struct tcp_pcb *)socket->pcb; - u16_t available = tcp_sndbuf(pcb); + u16_t available = tcp_sndbuf(socket->pcb.tcp); u16_t write_len = MIN(available, len); - err_t err = tcp_write(pcb, buf, write_len, TCP_WRITE_FLAG_COPY); + err_t err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY); if (err != ERR_OK) { *_errno = error_lookup_table[-err]; @@ -372,24 +377,24 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_ return 0; } - if (socket->incoming == NULL) { + if (socket->incoming.pbuf == NULL) { if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); - if (socket->incoming != NULL) break; + if (socket->incoming.pbuf != NULL) break; } - if (socket->incoming == NULL) { + if (socket->incoming.pbuf == NULL) { *_errno = ETIMEDOUT; return -1; } } else { - while (socket->incoming == NULL) { + while (socket->incoming.pbuf == NULL) { mp_hal_delay_ms(100); } } } - struct pbuf *p = (struct pbuf *)socket->incoming; + struct pbuf *p = socket->incoming.pbuf; if (socket->leftover_count == 0) { socket->leftover_count = p->tot_len; @@ -401,11 +406,11 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_ socket->leftover_count -= len; } else { pbuf_free(p); - socket->incoming = NULL; + socket->incoming.pbuf = NULL; socket->leftover_count = 0; } - tcp_recved((struct tcp_pcb *)socket->pcb, result); + tcp_recved(socket->pcb.tcp, result); return (mp_uint_t) result; } @@ -431,33 +436,33 @@ STATIC mp_obj_t lwip_socket_make_new(mp_obj_t type_in, mp_uint_t n_args, } switch (socket->type) { - case MOD_NETWORK_SOCK_STREAM: socket->pcb = (void*)tcp_new(); break; - case MOD_NETWORK_SOCK_DGRAM: socket->pcb = (void*)udp_new(); break; - //case MOD_NETWORK_SOCK_RAW: socket->pcb = (void*)raw_new(); break; + case MOD_NETWORK_SOCK_STREAM: socket->pcb.tcp = tcp_new(); break; + case MOD_NETWORK_SOCK_DGRAM: socket->pcb.udp = udp_new(); break; + //case MOD_NETWORK_SOCK_RAW: socket->pcb.raw = raw_new(); break; default: nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL))); } - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM))); } switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { // Register the socket object as our callback argument. - tcp_arg((struct tcp_pcb*)socket->pcb, (void*)socket); + tcp_arg(socket->pcb.tcp, (void*)socket); // Register our error callback. - tcp_err((struct tcp_pcb*)socket->pcb, _lwip_tcp_error); + tcp_err(socket->pcb.tcp, _lwip_tcp_error); break; } case MOD_NETWORK_SOCK_DGRAM: { // Register our receive callback now. Since UDP sockets don't require binding or connection // before use, there's no other good time to do it. - udp_recv((struct udp_pcb*)socket->pcb, _lwip_udp_incoming, (void*)socket); + udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void*)socket); break; } } - socket->incoming = NULL; + socket->incoming.pbuf = NULL; socket->timeout = -1; socket->connected = 0; socket->leftover_count = 0; @@ -468,31 +473,31 @@ STATIC mp_obj_t lwip_socket_close(mp_obj_t self_in) { lwip_socket_obj_t *socket = self_in; bool socket_is_listener = false; - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { return mp_const_none; } switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { - if (((struct tcp_pcb*)socket->pcb)->state == LISTEN) { + if (socket->pcb.tcp->state == LISTEN) { socket_is_listener = true; } - if (tcp_close((struct tcp_pcb*)socket->pcb) != ERR_OK) { - tcp_abort((struct tcp_pcb*)socket->pcb); + if (tcp_close(socket->pcb.tcp) != ERR_OK) { + tcp_abort(socket->pcb.tcp); } break; } - case MOD_NETWORK_SOCK_DGRAM: udp_remove((struct udp_pcb*)socket->pcb); break; - //case MOD_NETWORK_SOCK_RAW: raw_remove((struct raw_pcb*)socket->pcb); break; + case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break; + //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; } - socket->pcb = NULL; + socket->pcb.tcp = NULL; socket->connected = -16; // EBADF - if (socket->incoming != NULL) { + if (socket->incoming.pbuf != NULL) { if (!socket_is_listener) { - pbuf_free((struct pbuf*)socket->incoming); + pbuf_free(socket->incoming.pbuf); } else { - tcp_abort((struct tcp_pcb*)socket->incoming); + tcp_abort(socket->incoming.connection); } - socket->incoming = NULL; + socket->incoming.pbuf = NULL; } return mp_const_none; @@ -511,11 +516,11 @@ STATIC mp_obj_t lwip_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { err_t err = ERR_ARG; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { - err = tcp_bind((struct tcp_pcb*)socket->pcb, &bind_addr, port); + err = tcp_bind(socket->pcb.tcp, &bind_addr, port); break; } case MOD_NETWORK_SOCK_DGRAM: { - err = udp_bind((struct udp_pcb*)socket->pcb, &bind_addr, port); + err = udp_bind(socket->pcb.udp, &bind_addr, port); break; } } @@ -532,18 +537,18 @@ STATIC mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { lwip_socket_obj_t *socket = self_in; mp_int_t backlog = mp_obj_get_int(backlog_in); - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF))); } if (socket->type != MOD_NETWORK_SOCK_STREAM) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP))); } - struct tcp_pcb *new_pcb = tcp_listen_with_backlog((struct tcp_pcb*)socket->pcb, (u8_t)backlog); + struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog); if (new_pcb == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM))); } - socket->pcb = (void*)new_pcb; + socket->pcb.tcp = new_pcb; tcp_accept(new_pcb, _lwip_tcp_accept); return mp_const_none; @@ -553,30 +558,30 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_listen_obj, lwip_socket_listen); STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) { lwip_socket_obj_t *socket = self_in; - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF))); } if (socket->type != MOD_NETWORK_SOCK_STREAM) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP))); } // I need to do this because "tcp_accepted", later, is a macro. - struct tcp_pcb *listener = (struct tcp_pcb*)socket->pcb; + struct tcp_pcb *listener = socket->pcb.tcp; if (listener->state != LISTEN) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL))); } // accept incoming connection - if (socket->incoming == NULL) { + if (socket->incoming.connection == NULL) { if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); - if (socket->incoming != NULL) break; + if (socket->incoming.connection != NULL) break; } - if (socket->incoming == NULL) { + if (socket->incoming.connection == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT))); } } else { - while (socket->incoming == NULL) { + while (socket->incoming.connection == NULL) { mp_hal_delay_ms(100); } } @@ -587,26 +592,26 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) { socket2->base.type = (mp_obj_t)&lwip_socket_type; // We get a new pcb handle... - socket2->pcb = socket->incoming; - socket->incoming = NULL; + socket2->pcb.tcp = socket->incoming.connection; + socket->incoming.connection = NULL; // ...and set up the new socket for it. socket2->domain = MOD_NETWORK_AF_INET; socket2->type = MOD_NETWORK_SOCK_STREAM; - socket2->incoming = NULL; + socket2->incoming.pbuf = NULL; socket2->timeout = socket->timeout; socket2->connected = 2; socket2->leftover_count = 0; - tcp_arg((struct tcp_pcb*)socket2->pcb, (void*)socket2); - tcp_err((struct tcp_pcb*)socket2->pcb, _lwip_tcp_error); - tcp_recv((struct tcp_pcb*)socket2->pcb, _lwip_tcp_recv); + tcp_arg(socket2->pcb.tcp, (void*)socket2); + tcp_err(socket2->pcb.tcp, _lwip_tcp_error); + tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv); tcp_accepted(listener); // make the return value uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE]; - memcpy(ip, &(((struct tcp_pcb*)socket2->pcb)->remote_ip), 4); - mp_uint_t port = (mp_uint_t)((struct tcp_pcb*)socket2->pcb)->remote_port; + memcpy(ip, &(socket2->pcb.tcp->remote_ip), 4); + mp_uint_t port = (mp_uint_t)socket2->pcb.tcp->remote_port; mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = socket2; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); @@ -618,7 +623,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(lwip_socket_accept_obj, lwip_socket_accept); STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { lwip_socket_obj_t *socket = self_in; - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF))); } @@ -640,10 +645,10 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { } } // Register our recieve callback. - tcp_recv((struct tcp_pcb*)socket->pcb, _lwip_tcp_recv); + tcp_recv(socket->pcb.tcp, _lwip_tcp_recv); // Mark us as "connecting" socket->connected = 1; - err = tcp_connect((struct tcp_pcb*)socket->pcb, &dest, port, _lwip_tcp_connected); + err = tcp_connect(socket->pcb.tcp, &dest, port, _lwip_tcp_connected); if (err != ERR_OK) { socket->connected = 0; nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error_lookup_table[-err]))); @@ -672,7 +677,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { break; } case MOD_NETWORK_SOCK_DGRAM: { - err = udp_connect((struct udp_pcb*)socket->pcb, &dest, port); + err = udp_connect(socket->pcb.udp, &dest, port); break; } } @@ -689,7 +694,7 @@ STATIC mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) { lwip_socket_obj_t *socket = self_in; int _errno; - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { // not connected _errno = error_lookup_table[-(socket->connected)]; socket->connected = -16; @@ -722,7 +727,7 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) { lwip_socket_obj_t *socket = self_in; int _errno; - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { // not connected _errno = error_lookup_table[-(socket->connected)]; socket->connected = -16; @@ -760,7 +765,7 @@ STATIC mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t lwip_socket_obj_t *socket = self_in; int _errno; - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { // not connected _errno = error_lookup_table[-(socket->connected)]; socket->connected = -16; @@ -796,7 +801,7 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { lwip_socket_obj_t *socket = self_in; int _errno; - if (socket->pcb == NULL) { + if (socket->pcb.tcp == NULL) { // not connected _errno = error_lookup_table[-(socket->connected)]; socket->connected = -16;