summaryrefslogtreecommitdiff
path: root/extmod/modlwip.c
diff options
context:
space:
mode:
Diffstat (limited to 'extmod/modlwip.c')
-rw-r--r--extmod/modlwip.c153
1 files changed, 79 insertions, 74 deletions
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index 0f3ab7c15..274a07daa 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;