summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-05-03 10:42:47 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-05-03 10:43:11 +0300
commitcfc94bec9ffdb774a6e33d10ad71ef7c69efc957 (patch)
treeb681ef1ba57a8cfed8f7b27c48dcfebe51c8793c
parent879bc4197a9cfa8312fbf21fb3b99529b043b6ea (diff)
downloadmicropython-cfc94bec9ffdb774a6e33d10ad71ef7c69efc957.tar.gz
micropython-cfc94bec9ffdb774a6e33d10ad71ef7c69efc957.zip
extmod/modlwip: Implement sendall() method for TCP sockets.
-rw-r--r--extmod/modlwip.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index 452b7eca34..090e1005a8 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -964,6 +964,48 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recvfrom_obj, lwip_socket_recvfrom);
+STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
+ lwip_socket_obj_t *socket = self_in;
+ lwip_socket_check_connected(socket);
+
+ int _errno;
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+
+ mp_uint_t ret = 0;
+ switch (socket->type) {
+ case MOD_NETWORK_SOCK_STREAM: {
+ if (socket->timeout == 0) {
+ // Behavior of sendall() for non-blocking sockets isn't explicitly specified.
+ // But it's specified that "On error, an exception is raised, there is no
+ // way to determine how much data, if any, was successfully sent." Then, the
+ // most useful behavior is: check whether we will be able to send all of input
+ // data without EAGAIN, and if won't be, raise it without sending any.
+ if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EAGAIN)));
+ }
+ }
+ // TODO: In CPython3.5, socket timeout should apply to the
+ // entire sendall() operation, not to individual send() chunks.
+ while (bufinfo.len != 0) {
+ ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
+ if (ret == -1) {
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
+ }
+ bufinfo.len -= ret;
+ bufinfo.buf = (char*)bufinfo.buf + ret;
+ }
+ break;
+ }
+ case MOD_NETWORK_SOCK_DGRAM:
+ mp_not_implemented("");
+ break;
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_sendall_obj, lwip_socket_sendall);
+
STATIC mp_obj_t lwip_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
lwip_socket_obj_t *socket = self_in;
mp_uint_t timeout;
@@ -1068,6 +1110,7 @@ STATIC const mp_map_elem_t lwip_socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&lwip_socket_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&lwip_socket_sendto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&lwip_socket_recvfrom_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sendall), (mp_obj_t)&lwip_socket_sendall_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&lwip_socket_settimeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&lwip_socket_setblocking_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&lwip_socket_setsockopt_obj },