From 32736dd2c33430d934878f4bbce0a04b48ca22ac Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Mon, 14 Dec 2020 12:57:39 -0500 Subject: Implement server API --- shared-bindings/socketpool/Socket.c | 153 ++++++++++++++---------------------- shared-bindings/socketpool/Socket.h | 5 ++ 2 files changed, 63 insertions(+), 95 deletions(-) (limited to 'shared-bindings/socketpool') diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index 0e6968d5f..37ba0cee3 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -64,94 +64,72 @@ STATIC mp_obj_t socketpool_socket___exit__(size_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket___exit___obj, 4, 4, socketpool_socket___exit__); -// //| def bind(self, address: tuple) -> None: -// //| """Bind a socket to an address -// //| -// //| :param ~tuple address: tuple of (remote_address, remote_port)""" -// //| ... -// //| - -// STATIC mp_obj_t socketpool_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { -// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); - -// // // get address -// // uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; -// // mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); - -// // // check if we need to select a NIC -// // socket_select_nic(self, ip); - -// // // call the NIC to bind the socket -// // int _errno; -// // if (self->nic_type->bind(self, ip, port, &_errno) != 0) { -// // mp_raise_OSError(_errno); -// // } - -// return mp_const_none; -// } -// STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_bind_obj, socketpool_socket_bind); - -// //| def listen(self, backlog: int) -> None: -// //| """Set socket to listen for incoming connections -// //| -// //| :param ~int backlog: length of backlog queue for waiting connetions""" -// //| ... -// //| +//| def bind(self, address: Tuple[str, int]) -> None: +//| """Bind a socket to an address +//| +//| :param ~tuple address: tuple of (remote_address, remote_port)""" +//| ... +//| +STATIC mp_obj_t socketpool_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { + socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); -// STATIC mp_obj_t socketpool_socket_listen(mp_obj_t self_in, mp_obj_t backlog) { -// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t *addr_items; + mp_obj_get_array_fixed_n(addr_in, 2, &addr_items); -// // if (self->nic == MP_OBJ_NULL) { -// // // not connected -// // // TODO I think we can listen even if not bound... -// // mp_raise_OSError(MP_ENOTCONN); -// // } + size_t hostlen; + const char* host = mp_obj_str_get_data(addr_items[0], &hostlen); + mp_int_t port = mp_obj_get_int(addr_items[1]); -// // int _errno; -// // if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) { -// // mp_raise_OSError(_errno); -// // } + bool ok = common_hal_socketpool_socket_bind(self, host, hostlen, port); + if (!ok) { + mp_raise_ValueError(translate("Error: Failure to bind")); + } -// return mp_const_none; -// } -// STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_listen_obj, socketpool_socket_listen); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_bind_obj, socketpool_socket_bind); -// //| def accept(self) -> tuple: -// //| """Accept a connection on a listening socket of type SOCK_STREAM, -// //| creating a new socket of type SOCK_STREAM. -// //| Returns a tuple of (new_socket, remote_address)""" -// //| +//| def listen(self, backlog: int) -> None: +//| """Set socket to listen for incoming connections +//| +//| :param ~int backlog: length of backlog queue for waiting connetions""" +//| ... +//| +STATIC mp_obj_t socketpool_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { + socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); -// STATIC mp_obj_t socketpool_socket_accept(mp_obj_t self_in) { -// // mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + int backlog = mp_obj_get_int(backlog_in); -// // // create new socket object -// // // starts with empty NIC so that finaliser doesn't run close() method if accept() fails -// // mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); -// // socket2->base.type = &socket_type; -// // socket2->nic = MP_OBJ_NULL; -// // socket2->nic_type = NULL; + common_hal_socketpool_socket_listen(self, backlog); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_listen_obj, socketpool_socket_listen); -// // // accept incoming connection -// // uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; -// // mp_uint_t port; -// // int _errno; -// // if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) { -// // mp_raise_OSError(_errno); -// // } +//| def accept(self) -> tuple: +//| """Accept a connection on a listening socket of type SOCK_STREAM, +//| creating a new socket of type SOCK_STREAM. +//| Returns a tuple of (new_socket, remote_address)""" +//| +STATIC mp_obj_t socketpool_socket_accept(mp_obj_t self_in) { + socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint8_t ip[4]; + uint port; -// // // new socket has valid state, so set the NIC to the same as parent -// // socket2->nic = self->nic; -// // socket2->nic_type = self->nic_type; + int socknum = common_hal_socketpool_socket_accept(self, ip, &port); -// // // make the return value -// // mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); -// // client->items[0] = MP_OBJ_FROM_PTR(socket2); -// // client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); + sock->base.type = &socketpool_socket_type; + sock->num = socknum; + sock->tls = NULL; + sock->ssl_context = NULL; + sock->pool = self->pool; -// return mp_const_none; -// } -// STATIC MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_accept_obj, socketpool_socket_accept); + mp_obj_t tuple_contents[2]; + tuple_contents[0] = MP_OBJ_FROM_PTR(sock); + tuple_contents[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + return mp_obj_new_tuple(2, tuple_contents); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_accept_obj, socketpool_socket_accept); //| def close(self) -> None: //| """Closes this Socket and makes its resources available to its SocketPool.""" @@ -169,7 +147,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_close_obj, socketpool_socket_ //| :param ~tuple address: tuple of (remote_address, remote_port)""" //| ... //| - STATIC mp_obj_t socketpool_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -196,7 +173,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_connect_obj, socketpool_socke //| :param ~bytes bytes: some bytes to send""" //| ... //| - STATIC mp_obj_t socketpool_socket_send(mp_obj_t self_in, mp_obj_t buf_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (common_hal_socketpool_socket_get_closed(self)) { @@ -216,19 +192,6 @@ STATIC mp_obj_t socketpool_socket_send(mp_obj_t self_in, mp_obj_t buf_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_send_obj, socketpool_socket_send); - -// helper function for socket_recv and socket_recv_into to handle common operations of both -// STATIC mp_int_t _socket_recv_into(mod_network_socket_obj_t *sock, byte *buf, mp_int_t len) { -// mp_int_t ret = 0; -// // int _errno; -// // mp_int_t ret = sock->nic_type->recv(sock, buf, len, &_errno); -// // if (ret == -1) { -// // mp_raise_OSError(_errno); -// // } -// return ret; -// } - - //| def recv_into(self, buffer: WriteableBuffer, bufsize: int) -> int: //| """Reads some bytes from the connected remote address, writing //| into the provided buffer. If bufsize <= len(buffer) is given, @@ -430,9 +393,9 @@ STATIC const mp_rom_map_elem_t socketpool_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&socketpool_socket_close_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socketpool_socket_close_obj) }, - // { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socketpool_socket_bind_obj) }, - // { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socketpool_socket_listen_obj) }, - // { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socketpool_socket_accept_obj) }, + { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socketpool_socket_bind_obj) }, + { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socketpool_socket_listen_obj) }, + { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socketpool_socket_accept_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socketpool_socket_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socketpool_socket_send_obj) }, { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socketpool_socket_sendto_obj) }, diff --git a/shared-bindings/socketpool/Socket.h b/shared-bindings/socketpool/Socket.h index 54fbe59b2..e2ea32d39 100644 --- a/shared-bindings/socketpool/Socket.h +++ b/shared-bindings/socketpool/Socket.h @@ -32,6 +32,11 @@ extern const mp_obj_type_t socketpool_socket_type; void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_uint_t timeout_ms); + +bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self, const char* host, size_t hostlen, uint8_t port); +bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int backlog); +int common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, uint8_t* ip, uint *port); + bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, const char* host, size_t hostlen, mp_int_t port); mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len); mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len); -- cgit v1.2.3 From 75620884e6c553b1f5f954762c72eb431357aa24 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Mon, 21 Dec 2020 13:04:52 -0500 Subject: Fix stubs, recv_into error --- ports/esp32s2/common-hal/socketpool/Socket.c | 2 +- shared-bindings/socketpool/Socket.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-bindings/socketpool') diff --git a/ports/esp32s2/common-hal/socketpool/Socket.c b/ports/esp32s2/common-hal/socketpool/Socket.c index d92bed1d1..d5608c7ed 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.c +++ b/ports/esp32s2/common-hal/socketpool/Socket.c @@ -210,7 +210,7 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, if (received == 0) { // socket closed - common_hal_socketpool_socket_close(self); + mp_raise_OSError(0); } return received; } diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index 37ba0cee3..548514f28 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -105,7 +105,7 @@ STATIC mp_obj_t socketpool_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_listen_obj, socketpool_socket_listen); -//| def accept(self) -> tuple: +//| def accept(self) -> Tuple[Socket, Tuple[str, int]]: //| """Accept a connection on a listening socket of type SOCK_STREAM, //| creating a new socket of type SOCK_STREAM. //| Returns a tuple of (new_socket, remote_address)""" -- cgit v1.2.3 From f07dd487af935b34f1c735c874cf5351612029d9 Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:49:50 -0600 Subject: change IPPROTO_* comments to match usage in current shared-bindings and common-hal code --- shared-bindings/socketpool/SocketPool.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'shared-bindings/socketpool') diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index 73eeed265..326131124 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -62,14 +62,12 @@ STATIC mp_obj_t socketpool_socketpool_make_new(const mp_obj_type_t *type, size_t //| SOCK_STREAM: int //| SOCK_DGRAM: int //| SOCK_RAW: int -//| IPPROTO_TCP: int //| -//| def socket(self, family: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP) -> socketpool.Socket: +//| def socket(self, family: int = AF_INET, type: int = SOCK_STREAM) -> socketpool.Socket: //| """Create a new socket //| //| :param ~int family: AF_INET or AF_INET6 //| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW -//| :param ~int proto: IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW (ignored)""" //| ... //| -- cgit v1.2.3 From 4cdb298a20eced513536f30d3d81990eb9fbceaa Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Tue, 12 Jan 2021 15:05:28 -0500 Subject: WIP of non-blocking calls --- ports/esp32s2/common-hal/socketpool/Socket.c | 17 ++++++++++++++++- shared-bindings/socketpool/Socket.c | 8 ++++---- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'shared-bindings/socketpool') diff --git a/ports/esp32s2/common-hal/socketpool/Socket.c b/ports/esp32s2/common-hal/socketpool/Socket.c index d5608c7ed..757156e08 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.c +++ b/ports/esp32s2/common-hal/socketpool/Socket.c @@ -51,6 +51,7 @@ STATIC void _lazy_init_LWIP(socketpool_socket_obj_t* self) { mp_raise_RuntimeError(translate("Out of sockets")); } self->num = socknum; + lwip_fcntl(socknum, F_SETFL, O_NONBLOCK); } STATIC void _lazy_init_TLS(socketpool_socket_obj_t* self) { @@ -88,12 +89,20 @@ int common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, uint8_t* ip, uint *port) { struct sockaddr_in accept_addr; socklen_t socklen = sizeof(accept_addr); - int newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen); + + int newsoc = -1; + //(self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) + while ((newsoc == -1) && !mp_hal_is_interrupted() ) { + RUN_BACKGROUND_TASKS; + newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen); + } + mp_printf(&mp_plat_print, "oldsoc:%d newsoc:%d\n",self->num, newsoc); memcpy((void *)ip, (void*)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr)); *port = accept_addr.sin_port; if (newsoc > 0) { + lwip_fcntl(newsoc, F_SETFL, O_NONBLOCK); return newsoc; } else { return 0; @@ -169,7 +178,11 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, if (self->num != -1) { // LWIP Socket + mp_printf(&mp_plat_print, "lwip_recv:\n"); + received = lwip_recv(self->num, (void*) buf, len - 1, 0); + mp_printf(&mp_plat_print, "received:%d\n",received); + } else if (self->tls != NULL) { // TLS Socket int status = 0; @@ -257,7 +270,9 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se struct sockaddr_in source_addr; socklen_t socklen = sizeof(source_addr); + mp_printf(&mp_plat_print, "recvfrom_into\n"); int bytes_received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen); + mp_printf(&mp_plat_print, "received:%d\n",bytes_received); memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr)); *port = source_addr.sin_port; diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index 548514f28..a92e508b6 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -213,10 +213,10 @@ STATIC mp_obj_t socketpool_socket_recv_into(size_t n_args, const mp_obj_t *args) // Bad file number. mp_raise_OSError(MP_EBADF); } - if (!common_hal_socketpool_socket_get_connected(self)) { - // not connected - mp_raise_OSError(MP_ENOTCONN); - } + // if (!common_hal_socketpool_socket_get_connected(self)) { + // // not connected + // mp_raise_OSError(MP_ENOTCONN); + // } mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); mp_int_t len = bufinfo.len; -- cgit v1.2.3 From e703e065952b7e3f25a23f08609160e9a7a22fae Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Wed, 13 Jan 2021 11:17:37 -0600 Subject: Update shared-bindings/socketpool/SocketPool.c Co-authored-by: Scott Shawcroft --- shared-bindings/socketpool/SocketPool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-bindings/socketpool') diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index 326131124..8f4069faa 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -67,7 +67,7 @@ STATIC mp_obj_t socketpool_socketpool_make_new(const mp_obj_type_t *type, size_t //| """Create a new socket //| //| :param ~int family: AF_INET or AF_INET6 -//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW +//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW""" //| ... //| -- cgit v1.2.3 From 37a8c1c57518ac35724ee026cdf6f2f2871aaea2 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Wed, 13 Jan 2021 19:05:07 -0500 Subject: Complete non-blocking implementations, add socket close checking --- ports/esp32s2/common-hal/socketpool/Socket.c | 162 ++++++++++++++++++++++----- ports/esp32s2/common-hal/socketpool/Socket.h | 3 + ports/esp32s2/supervisor/port.c | 5 + shared-bindings/socketpool/Socket.c | 9 +- shared-bindings/socketpool/Socket.h | 2 +- 5 files changed, 143 insertions(+), 38 deletions(-) (limited to 'shared-bindings/socketpool') diff --git a/ports/esp32s2/common-hal/socketpool/Socket.c b/ports/esp32s2/common-hal/socketpool/Socket.c index 757156e08..743414ae7 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.c +++ b/ports/esp32s2/common-hal/socketpool/Socket.c @@ -38,6 +38,32 @@ #include "components/lwip/lwip/src/include/lwip/sys.h" #include "components/lwip/lwip/src/include/lwip/netdb.h" +STATIC socketpool_socket_obj_t * open_socket_handles[CONFIG_LWIP_MAX_SOCKETS]; // 4 on the wrover/wroom + +void socket_reset(void) { + for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) { + if (open_socket_handles[i]) { + if (open_socket_handles[i]->num > 0) { + common_hal_socketpool_socket_close(open_socket_handles[i]); + open_socket_handles[i] = NULL; + } else { + // accidentally got a TCP socket in here, or something. + open_socket_handles[i] = NULL; + } + } + } +} + +bool register_open_socket(socketpool_socket_obj_t* self) { + for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) { + if (open_socket_handles[i] == NULL) { + open_socket_handles[i] = self; + return true; + } + } + return false; +} + STATIC void _lazy_init_LWIP(socketpool_socket_obj_t* self) { if (self->num != -1) { return; //safe to call on existing socket @@ -47,7 +73,7 @@ STATIC void _lazy_init_LWIP(socketpool_socket_obj_t* self) { } int socknum = -1; socknum = lwip_socket(self->family, self->type, self->ipproto); - if (socknum < 0) { + if (socknum < 0 || !register_open_socket(self)) { mp_raise_RuntimeError(translate("Out of sockets")); } self->num = socknum; @@ -78,34 +104,74 @@ bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self, bind_addr.sin_family = AF_INET; bind_addr.sin_port = htons(port); - return lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) == 0; + int opt = 1; + int err = lwip_setsockopt(self->num, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + if (err != 0) { + mp_raise_RuntimeError(translate("Issue setting SO_REUSEADDR")); + } + int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) == 0; + return result; } bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int backlog) { return lwip_listen(self->num, backlog) == 0; } -int common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, +socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, uint8_t* ip, uint *port) { struct sockaddr_in accept_addr; socklen_t socklen = sizeof(accept_addr); - int newsoc = -1; - //(self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) - while ((newsoc == -1) && !mp_hal_is_interrupted() ) { + bool timed_out = false; + uint64_t start_ticks = supervisor_ticks_ms64(); + + if (self->timeout_ms != (uint)-1) { + mp_printf(&mp_plat_print, "will timeout"); + } else { + mp_printf(&mp_plat_print, "won't timeout"); + } + + // Allow timeouts and interrupts + while (newsoc == -1 && + !timed_out && + !mp_hal_is_interrupted()) { + if (self->timeout_ms != (uint)-1) { + timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } RUN_BACKGROUND_TASKS; newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen); + // In non-blocking mode, fail instead of looping + if (newsoc == -1 && self->timeout_ms == 0) { + mp_raise_OSError(MP_EAGAIN); + } } - mp_printf(&mp_plat_print, "oldsoc:%d newsoc:%d\n",self->num, newsoc); - memcpy((void *)ip, (void*)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr)); - *port = accept_addr.sin_port; + if (!timed_out) { + // harmless on failure but avoiding memcpy is faster + memcpy((void *)ip, (void*)&accept_addr.sin_addr.s_addr, sizeof(accept_addr.sin_addr.s_addr)); + *port = accept_addr.sin_port; + } else { + mp_raise_OSError(ETIMEDOUT); + } if (newsoc > 0) { + // Create the socket + socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); + sock->base.type = &socketpool_socket_type; + sock->num = newsoc; + sock->tls = NULL; + sock->ssl_context = NULL; + sock->pool = self->pool; + + if (!register_open_socket(sock)) { + mp_raise_OSError(MP_EBADF); + } + lwip_fcntl(newsoc, F_SETFL, O_NONBLOCK); - return newsoc; + return sock; } else { - return 0; + mp_raise_OSError(MP_EBADF); + return NULL; } } @@ -158,9 +224,10 @@ bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self) { } mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) { - size_t sent = -1; + int sent = -1; if (self->num != -1) { // LWIP Socket + // TODO: deal with potential failure/add timeout? sent = lwip_send(self->num, buf, len, 0); } else if (self->tls != NULL) { // TLS Socket @@ -174,15 +241,27 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const } mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) { - size_t received = 0; + int received = 0; + bool timed_out = false; if (self->num != -1) { // LWIP Socket - mp_printf(&mp_plat_print, "lwip_recv:\n"); - - received = lwip_recv(self->num, (void*) buf, len - 1, 0); - mp_printf(&mp_plat_print, "received:%d\n",received); + uint64_t start_ticks = supervisor_ticks_ms64(); + received = -1; + while (received == -1 && + !timed_out && + !mp_hal_is_interrupted()) { + if (self->timeout_ms != (uint)-1) { + timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } + RUN_BACKGROUND_TASKS; + received = lwip_recv(self->num, (void*) buf, len - 1, 0); + // In non-blocking mode, fail instead of looping + if (received == -1 && self->timeout_ms == 0) { + mp_raise_OSError(MP_EAGAIN); + } + } } else if (self->tls != NULL) { // TLS Socket int status = 0; @@ -194,8 +273,11 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, } while (received == 0 && status >= 0 && - (self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) && + !timed_out && !mp_hal_is_interrupted()) { + if (self->timeout_ms != (uint)-1) { + timed_out = self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } RUN_BACKGROUND_TASKS; size_t available = esp_tls_get_bytes_avail(self->tls); if (available == 0) { @@ -219,11 +301,13 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, } } } + } else { + // Socket does not have a valid descriptor of either type + mp_raise_OSError(MP_EBADF); } - if (received == 0) { - // socket closed - mp_raise_OSError(0); + if (timed_out) { + mp_raise_OSError(ETIMEDOUT); } return received; } @@ -270,19 +354,39 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se struct sockaddr_in source_addr; socklen_t socklen = sizeof(source_addr); - mp_printf(&mp_plat_print, "recvfrom_into\n"); - int bytes_received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen); - mp_printf(&mp_plat_print, "received:%d\n",bytes_received); - memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr)); - *port = source_addr.sin_port; + // LWIP Socket + uint64_t start_ticks = supervisor_ticks_ms64(); + int received = -1; + bool timed_out = false; + while (received == -1 && + !timed_out && + !mp_hal_is_interrupted()) { + if (self->timeout_ms != (uint)-1) { + timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } + RUN_BACKGROUND_TASKS; + received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen); + + // In non-blocking mode, fail instead of looping + if (received == -1 && self->timeout_ms == 0) { + mp_raise_OSError(MP_EAGAIN); + } + } + + if (!timed_out) { + memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr)); + *port = source_addr.sin_port; + } else { + mp_raise_OSError(ETIMEDOUT); + } - if (bytes_received < 0) { + if (received < 0) { mp_raise_BrokenPipeError(); return 0; } else { - buf[bytes_received] = 0; // Null-terminate whatever we received - return bytes_received; + buf[received] = 0; // Null-terminate whatever we received + return received; } } diff --git a/ports/esp32s2/common-hal/socketpool/Socket.h b/ports/esp32s2/common-hal/socketpool/Socket.h index 3cffeeb6a..4e6cfa5ef 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.h +++ b/ports/esp32s2/common-hal/socketpool/Socket.h @@ -47,4 +47,7 @@ typedef struct { mp_uint_t timeout_ms; } socketpool_socket_obj_t; +void socket_reset(void); +bool register_open_socket(socketpool_socket_obj_t* self); + #endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SOCKETPOOL_SOCKET_H diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index 7037b4f05..1b123d19d 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -46,6 +46,7 @@ #include "common-hal/pwmio/PWMOut.h" #include "common-hal/touchio/TouchIn.h" #include "common-hal/watchdog/WatchDogTimer.h" +#include "common-hal/socketpool/Socket.h" #include "common-hal/wifi/__init__.h" #include "supervisor/memory.h" #include "supervisor/shared/tick.h" @@ -174,6 +175,10 @@ void reset_port(void) { #if CIRCUITPY_WIFI wifi_reset(); #endif + +#if CIRCUITPY_SOCKETPOOL + socket_reset(); +#endif } void reset_to_bootloader(void) { diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index a92e508b6..007417340 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -115,14 +115,7 @@ STATIC mp_obj_t socketpool_socket_accept(mp_obj_t self_in) { uint8_t ip[4]; uint port; - int socknum = common_hal_socketpool_socket_accept(self, ip, &port); - - socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); - sock->base.type = &socketpool_socket_type; - sock->num = socknum; - sock->tls = NULL; - sock->ssl_context = NULL; - sock->pool = self->pool; + socketpool_socket_obj_t * sock = common_hal_socketpool_socket_accept(self, ip, &port); mp_obj_t tuple_contents[2]; tuple_contents[0] = MP_OBJ_FROM_PTR(sock); diff --git a/shared-bindings/socketpool/Socket.h b/shared-bindings/socketpool/Socket.h index e2ea32d39..b5dceb50f 100644 --- a/shared-bindings/socketpool/Socket.h +++ b/shared-bindings/socketpool/Socket.h @@ -35,7 +35,7 @@ void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_u bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self, const char* host, size_t hostlen, uint8_t port); bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int backlog); -int common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, uint8_t* ip, uint *port); +socketpool_socket_obj_t * common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, uint8_t* ip, uint *port); bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, const char* host, size_t hostlen, mp_int_t port); mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len); -- cgit v1.2.3