diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 5458267a05..1a073ca035 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -93,6 +93,11 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc mp_int_t r = read(o->fd, buf, size); if (r == -1) { *errcode = errno; + + if (*errcode == EAGAIN) { + *errcode = MP_ETIMEDOUT; + } + return MP_STREAM_ERROR; } return r; @@ -103,6 +108,11 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in mp_int_t r = write(o->fd, buf, size); if (r == -1) { *errcode = errno; + + if (*errcode == EAGAIN) { + *errcode = MP_ETIMEDOUT; + } + return MP_STREAM_ERROR; } return r; @@ -314,6 +324,28 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); +STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { + mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); + struct timeval tv = {0,}; + if (timeout_in == mp_const_none) { + setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, NULL, 0); + setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, NULL, 0); + } else { + tv.tv_sec = mp_obj_get_int(timeout_in); + + #if MICROPY_PY_BUILTINS_FLOAT + tv.tv_usec = (mp_obj_get_float(timeout_in) - tv.tv_sec) * 1000000; + #endif + + setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, + &tv, sizeof(struct timeval)); + setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, + &tv, sizeof(struct timeval)); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); + STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { // TODO: CPython explicitly says that closing returned object doesn't close // the original socket (Python2 at all says that fd is dup()ed). But we @@ -369,6 +401,7 @@ STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, + { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, };