Skip to content

Commit 452ebe2

Browse files
committed
socketpool: make socket objects selectable
.. which will lead to them being usable in async contexts, pending relevant changes in asyncio
1 parent 9dc559b commit 452ebe2

File tree

4 files changed

+99
-4
lines changed

4 files changed

+99
-4
lines changed

ports/espressif/common-hal/socketpool/Socket.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,3 +553,27 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
553553
void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t *self, uint32_t timeout_ms) {
554554
self->timeout_ms = timeout_ms;
555555
}
556+
557+
bool common_hal_socketpool_readable(socketpool_socket_obj_t *self) {
558+
struct timeval immediate = {0, 0};
559+
560+
fd_set fds;
561+
FD_ZERO(&fds);
562+
FD_SET(self->num, &fds);
563+
int num_triggered = select(self->num + 1, &fds, NULL, &fds, &immediate);
564+
565+
// including returning true in the error case
566+
return num_triggered != 0;
567+
}
568+
569+
bool common_hal_socketpool_writable(socketpool_socket_obj_t *self) {
570+
struct timeval immediate = {0, 0};
571+
572+
fd_set fds;
573+
FD_ZERO(&fds);
574+
FD_SET(self->num, &fds);
575+
int num_triggered = select(self->num + 1, NULL, &fds, &fds, &immediate);
576+
577+
// including returning true in the error case
578+
return num_triggered != 0;
579+
}

ports/raspberrypi/common-hal/socketpool/Socket.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,3 +1163,46 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *socket,
11631163
void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t *self, uint32_t timeout_ms) {
11641164
self->timeout = timeout_ms;
11651165
}
1166+
1167+
bool common_hal_socketpool_readable(socketpool_socket_obj_t *self) {
1168+
1169+
MICROPY_PY_LWIP_ENTER;
1170+
1171+
bool result = self->incoming.pbuf != NULL;
1172+
1173+
if (self->state == STATE_PEER_CLOSED) {
1174+
result = true;
1175+
}
1176+
1177+
if (self->type == SOCKETPOOL_SOCK_STREAM && self->pcb.tcp->state == LISTEN) {
1178+
struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(self)[self->incoming.connection.iget];
1179+
result = (incoming_connection != NULL);
1180+
}
1181+
1182+
MICROPY_PY_LWIP_EXIT;
1183+
1184+
return result;
1185+
}
1186+
1187+
bool common_hal_socketpool_writable(socketpool_socket_obj_t *self) {
1188+
bool result = false;
1189+
1190+
MICROPY_PY_LWIP_ENTER;
1191+
1192+
switch (self->type) {
1193+
case SOCKETPOOL_SOCK_STREAM: {
1194+
result = tcp_sndbuf(self->pcb.tcp) != 0;
1195+
break;
1196+
}
1197+
case SOCKETPOOL_SOCK_DGRAM:
1198+
#if MICROPY_PY_LWIP_SOCK_RAW
1199+
case SOCKETPOOL_SOCK_RAW:
1200+
#endif
1201+
result = true;
1202+
break;
1203+
}
1204+
1205+
MICROPY_PY_LWIP_EXIT;
1206+
1207+
return result;
1208+
}

shared-bindings/socketpool/Socket.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,14 @@
3030
#include <stdio.h>
3131
#include <string.h>
3232

33-
#include "shared/runtime/context_manager_helpers.h"
34-
#include "py/objtuple.h"
33+
#include "py/mperrno.h"
3534
#include "py/objlist.h"
35+
#include "py/objtuple.h"
3636
#include "py/runtime.h"
37-
#include "py/mperrno.h"
37+
#include "py/stream.h"
3838

3939
#include "shared/netutils/netutils.h"
40+
#include "shared/runtime/context_manager_helpers.h"
4041
#include "shared/runtime/interrupt_char.h"
4142

4243
//| class Socket:
@@ -422,12 +423,38 @@ STATIC const mp_rom_map_elem_t socketpool_socket_locals_dict_table[] = {
422423

423424
STATIC MP_DEFINE_CONST_DICT(socketpool_socket_locals_dict, socketpool_socket_locals_dict_table);
424425

426+
STATIC mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
427+
socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
428+
mp_uint_t ret;
429+
if (request == MP_STREAM_POLL) {
430+
mp_uint_t flags = arg;
431+
ret = 0;
432+
if ((flags & MP_STREAM_POLL_RD) && common_hal_socketpool_readable(self) > 0) {
433+
ret |= MP_STREAM_POLL_RD;
434+
}
435+
if ((flags & MP_STREAM_POLL_WR) && common_hal_socketpool_writable(self)) {
436+
ret |= MP_STREAM_POLL_WR;
437+
}
438+
} else {
439+
*errcode = MP_EINVAL;
440+
ret = MP_STREAM_ERROR;
441+
}
442+
return ret;
443+
}
444+
445+
STATIC const mp_stream_p_t socket_stream_p = {
446+
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
447+
.ioctl = socket_ioctl,
448+
.is_text = false,
449+
};
450+
425451
const mp_obj_type_t socketpool_socket_type = {
426452
{ &mp_type_type },
427453
.flags = MP_TYPE_FLAG_EXTENDED,
428454
.name = MP_QSTR_Socket,
429455
.locals_dict = (mp_obj_dict_t *)&socketpool_socket_locals_dict,
430456
MP_TYPE_EXTENDED_FIELDS(
431457
.unary_op = mp_generic_unary_op,
458+
.protocol = &socket_stream_p,
432459
)
433460
};

shared-bindings/socketpool/Socket.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,13 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const
4646
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
4747
const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len);
4848
void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t *self, uint32_t timeout_ms);
49+
bool common_hal_socketpool_readable(socketpool_socket_obj_t *self);
50+
bool common_hal_socketpool_writable(socketpool_socket_obj_t *self);
4951

5052
// Non-allocating versions for internal use.
5153
int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_t *port);
5254
void socketpool_socket_close(socketpool_socket_obj_t *self);
5355
int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len);
5456
int socketpool_socket_recv_into(socketpool_socket_obj_t *self,
5557
const uint8_t *buf, uint32_t len);
56-
5758
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SOCKETPOOL_SOCKET_H

0 commit comments

Comments
 (0)