// method socket.recv(bufsize) STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = self_in; if (self->nic == MP_OBJ_NULL) { // not connected nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN))); } mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); int _errno; mp_uint_t ret = self->nic_type->recv(self, (byte*)vstr.buf, len, &_errno); if (ret == -1) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } if (ret == 0) { return mp_const_empty_bytes; } vstr.len = ret; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
// method socket.recv(bufsize) STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = self_in; mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); int _errno; mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno); if (ret < 0) { if (_errno == EAGAIN && self->sock_base.has_timeout) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out")); } nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); } if (ret == 0) { return mp_const_empty_bytes; } vstr.len = ret; vstr.buf[vstr.len] = '\0'; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
/** * def read_block(self, block) */ static mp_obj_t class_sd_read_block(mp_obj_t self_in, mp_obj_t block_in) { struct class_sd_t *self_p; vstr_t vstr; uint32_t block; self_p = MP_OBJ_TO_PTR(self_in); block = mp_obj_get_int(block_in); vstr_init_len(&vstr, SD_BLOCK_SIZE); if (sd_read_block(&self_p->drv, vstr.buf, block) != SD_BLOCK_SIZE) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "sd_read_block(%d) failed", block)); } return (mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr)); }
// method socket.recvfrom(bufsize) STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = self_in; vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(len_in)); byte ip[4]; mp_uint_t port; int _errno; mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); if (ret == -1) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } mp_obj_t tuple[2]; if (ret == 0) { tuple[0] = mp_const_empty_bytes; } else { vstr.len = ret; vstr.buf[vstr.len] = '\0'; tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); return mp_obj_new_tuple(2, tuple); }
STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { lwip_socket_obj_t *socket = self_in; int _errno; lwip_socket_check_connected(socket); mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); byte ip[4]; mp_uint_t port; mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { memcpy(ip, &socket->peer, sizeof(socket->peer)); port = (mp_uint_t) socket->peer_port; ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno); break; } case MOD_NETWORK_SOCK_DGRAM: { ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, ip, &port, &_errno); break; } } if (ret == -1) { mp_raise_OSError(_errno); } mp_obj_t tuple[2]; if (ret == 0) { tuple[0] = mp_const_empty_bytes; } else { vstr.len = ret; tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return mp_obj_new_tuple(2, tuple); }
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mp_int_t max_len = mp_obj_get_int(len_in); vstr_t vstr; // +1 to accommodate for trailing \0 vstr_init_len(&vstr, max_len + 1); int err; mp_uint_t len = sock_read(self_in, vstr.buf, max_len, &err); if (len == MP_STREAM_ERROR) { vstr_clear(&vstr); mp_raise_OSError(err); } if (len == 0) { vstr_clear(&vstr); return mp_const_empty_bytes; } vstr.len = len; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) { lwip_socket_obj_t *socket = self_in; int _errno; if (socket->pcb == NULL) { // not connected _errno = error_lookup_table[-(socket->connected)]; socket->connected = -16; nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno); break; } case MOD_NETWORK_SOCK_DGRAM: { ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, NULL, NULL, &_errno); break; } } if (ret == -1) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } if (ret == 0) { return mp_const_empty_bytes; } vstr.len = ret; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { // What to do if sz < -1? Python docs don't specify this case. // CPython does a readall, but here we silently let negatives through, // and they will cause a MemoryError. mp_int_t sz; if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) { return stream_readall(args[0]); } const mp_stream_p_t *stream_p = mp_get_stream(args[0]); #if MICROPY_PY_BUILTINS_STR_UNICODE if (stream_p->is_text) { // We need to read sz number of unicode characters. Because we don't have any // buffering, and because the stream API can only read bytes, we must read here // in units of bytes and must never over read. If we want sz chars, then reading // sz bytes will never over-read, so we follow this approach, in a loop to keep // reading until we have exactly enough chars. This will be 1 read for text // with ASCII-only chars, and about 2 reads for text with a couple of non-ASCII // chars. For text with lots of non-ASCII chars, it'll be pretty inefficient // in time and memory. vstr_t vstr; vstr_init(&vstr, sz); mp_uint_t more_bytes = sz; mp_uint_t last_buf_offset = 0; while (more_bytes > 0) { char *p = vstr_add_len(&vstr, more_bytes); int error; mp_uint_t out_sz = mp_stream_read_exactly(args[0], p, more_bytes, &error); if (error != 0) { vstr_cut_tail_bytes(&vstr, more_bytes); if (mp_is_nonblocking_error(error)) { // With non-blocking streams, we read as much as we can. // If we read nothing, return None, just like read(). // Otherwise, return data read so far. // TODO what if we have read only half a non-ASCII char? if (vstr.len == 0) { vstr_clear(&vstr); return mp_const_none; } break; } mp_raise_OSError(error); } if (out_sz < more_bytes) { // Finish reading. // TODO what if we have read only half a non-ASCII char? vstr_cut_tail_bytes(&vstr, more_bytes - out_sz); if (out_sz == 0) { break; } } // count chars from bytes just read for (mp_uint_t off = last_buf_offset;;) { byte b = vstr.buf[off]; int n; if (!UTF8_IS_NONASCII(b)) { // 1-byte ASCII char n = 1; } else if ((b & 0xe0) == 0xc0) { // 2-byte char n = 2; } else if ((b & 0xf0) == 0xe0) { // 3-byte char n = 3; } else if ((b & 0xf8) == 0xf0) { // 4-byte char n = 4; } else { // TODO n = 5; } if (off + n <= vstr.len) { // got a whole char in n bytes off += n; sz -= 1; last_buf_offset = off; if (off >= vstr.len) { more_bytes = sz; break; } } else { // didn't get a whole char, so work out how many extra bytes are needed for // this partial char, plus bytes for additional chars that we want more_bytes = (off + n - vstr.len) + (sz - 1); break; } } } return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } #endif vstr_t vstr; vstr_init_len(&vstr, sz); int error; mp_uint_t out_sz = mp_stream_rw(args[0], vstr.buf, sz, &error, flags); if (error != 0) { vstr_clear(&vstr); if (mp_is_nonblocking_error(error)) { // https://docs.python.org/3.4/library/io.html#io.RawIOBase.read // "If the object is in non-blocking mode and no bytes are available, // None is returned." // This is actually very weird, as naive truth check will treat // this as EOF. return mp_const_none; } mp_raise_OSError(error); } else { vstr.len = out_sz; return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); } }