Skip to content

Commit cfc94be

Browse files
committed
extmod/modlwip: Implement sendall() method for TCP sockets.
1 parent 879bc41 commit cfc94be

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

extmod/modlwip.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,48 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
964964
}
965965
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recvfrom_obj, lwip_socket_recvfrom);
966966

967+
STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
968+
lwip_socket_obj_t *socket = self_in;
969+
lwip_socket_check_connected(socket);
970+
971+
int _errno;
972+
mp_buffer_info_t bufinfo;
973+
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
974+
975+
mp_uint_t ret = 0;
976+
switch (socket->type) {
977+
case MOD_NETWORK_SOCK_STREAM: {
978+
if (socket->timeout == 0) {
979+
// Behavior of sendall() for non-blocking sockets isn't explicitly specified.
980+
// But it's specified that "On error, an exception is raised, there is no
981+
// way to determine how much data, if any, was successfully sent." Then, the
982+
// most useful behavior is: check whether we will be able to send all of input
983+
// data without EAGAIN, and if won't be, raise it without sending any.
984+
if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) {
985+
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EAGAIN)));
986+
}
987+
}
988+
// TODO: In CPython3.5, socket timeout should apply to the
989+
// entire sendall() operation, not to individual send() chunks.
990+
while (bufinfo.len != 0) {
991+
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
992+
if (ret == -1) {
993+
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
994+
}
995+
bufinfo.len -= ret;
996+
bufinfo.buf = (char*)bufinfo.buf + ret;
997+
}
998+
break;
999+
}
1000+
case MOD_NETWORK_SOCK_DGRAM:
1001+
mp_not_implemented("");
1002+
break;
1003+
}
1004+
1005+
return mp_const_none;
1006+
}
1007+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_sendall_obj, lwip_socket_sendall);
1008+
9671009
STATIC mp_obj_t lwip_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
9681010
lwip_socket_obj_t *socket = self_in;
9691011
mp_uint_t timeout;
@@ -1068,6 +1110,7 @@ STATIC const mp_map_elem_t lwip_socket_locals_dict_table[] = {
10681110
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&lwip_socket_recv_obj },
10691111
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&lwip_socket_sendto_obj },
10701112
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&lwip_socket_recvfrom_obj },
1113+
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendall), (mp_obj_t)&lwip_socket_sendall_obj },
10711114
{ MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&lwip_socket_settimeout_obj },
10721115
{ MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&lwip_socket_setblocking_obj },
10731116
{ MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&lwip_socket_setsockopt_obj },

0 commit comments

Comments
 (0)