// method socket.accept() STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mod_network_socket_obj_t *self = self_in; // create new socket object mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); // the new socket inherits all properties from its parent memcpy (socket2, self, sizeof(mod_network_socket_obj_t)); // accept the incoming connection uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; mp_uint_t port; int _errno; if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); } // add the socket to the list modusocket_socket_add(socket2->sock_base.sd, true); // make the return value mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = socket2; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); return client; }
// 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 < 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))); } 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); }
// function usocket.getaddrinfo(host, port) STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { size_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); // find a NIC that can do a name lookup for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); if (nic_type->gethostbyname != NULL) { uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE]; int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); if (ret != 0) { // TODO CPython raises: socket.gaierror: [Errno -2] Name or service not known mp_raise_OSError(ret); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG); return mp_obj_new_list(1, (mp_obj_t*)&tuple); } } nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); }
// 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; if (self->nic == MP_OBJ_NULL) { // not connected mp_raise_OSError(MP_ENOTCONN); } 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 = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); 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); }
// method socket.accept() STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mod_network_socket_obj_t *self = self_in; // create new socket object // starts with empty NIC so that finaliser doesn't run close() method if accept() fails mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); socket2->base.type = (mp_obj_t)&socket_type; socket2->nic = MP_OBJ_NULL; socket2->nic_type = NULL; // accept incoming connection uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; mp_uint_t port; int _errno; if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) { mp_raise_OSError(_errno); } // new socket has valid state, so set the NIC to the same as parent socket2->nic = self->nic; socket2->nic_type = self->nic_type; // make the return value mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = socket2; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return client; }
STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); struct sockaddr addr; socklen_t addr_len = sizeof(addr); int new_fd = -1; for (int i=0; i<=self->retries; i++) { MP_THREAD_GIL_EXIT(); new_fd = lwip_accept_r(self->fd, &addr, &addr_len); MP_THREAD_GIL_ENTER(); if (new_fd >= 0) break; if (errno != EAGAIN) exception_from_errno(errno); check_for_exceptions(); } if (new_fd < 0) mp_raise_OSError(MP_ETIMEDOUT); // create new socket object socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t); sock->base.type = self->base.type; sock->fd = new_fd; sock->domain = self->domain; sock->type = self->type; sock->proto = self->proto; _socket_settimeout(sock, UINT64_MAX); // make the return value uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&addr)->sin_addr; mp_uint_t port = lwip_ntohs(((struct sockaddr_in*)&addr)->sin_port); mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = sock; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return client; }
STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { struct sockaddr from; socklen_t fromlen = sizeof(from); mp_obj_t tuple[2]; tuple[0] = _socket_recvfrom(self_in, len_in, &from, &fromlen); uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&from)->sin_addr; mp_uint_t port = lwip_ntohs(((struct sockaddr_in*)&from)->sin_port); tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); 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; 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); byte ip[4]; mp_uint_t port; mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { memcpy(ip, &socket->peer, 4); 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) { 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; 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); }
// function usocket.getaddrinfo(host, port) /// \function getaddrinfo(host, port) STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); // ipv4 only uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET); if (result != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(result))); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE); return mp_obj_new_list(1, (mp_obj_t*)&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); }
// lwip.getaddrinfo STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); getaddrinfo_state_t state; state.status = 0; err_t ret = dns_gethostbyname(host, (ip_addr_t*)&state.ipaddr, lwip_getaddrinfo_cb, &state); switch (ret) { case ERR_OK: // cached state.status = 1; break; case ERR_INPROGRESS: while (state.status == 0) { poll_sockets(); } break; default: state.status = ret; } if (state.status < 0) { // TODO: CPython raises gaierror, we raise with native lwIP negative error // values, to differentiate from normal errno's at least in such way. nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(state.status))); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr((uint8_t*)&state.ipaddr, port, NETUTILS_BIG); return mp_obj_new_list(1, (mp_obj_t*)&tuple); }
// lwip.getaddrinfo STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); ip_addr_t result; lwip_dns_returned = 0; switch (dns_gethostbyname(host, &result, _lwip_dns_incoming, NULL)) { case ERR_OK: { break; } case ERR_INPROGRESS: { while(!lwip_dns_returned) { mp_hal_delay_ms(100); } if (lwip_dns_returned == 2) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT))); } break; } default: { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT))); } } uint8_t out_ip[NETUTILS_IPV4ADDR_BUFSIZE]; memcpy(out_ip, lwip_dns_result, 4); mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG); return mp_obj_new_list(1, (mp_obj_t*)&tuple); }
STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) { lwip_socket_obj_t *socket = self_in; if (socket->pcb == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF))); } if (socket->type != MOD_NETWORK_SOCK_STREAM) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP))); } // I need to do this because "tcp_accepted", later, is a macro. struct tcp_pcb *listener = (struct tcp_pcb*)socket->pcb; if (listener->state != LISTEN) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL))); } // accept incoming connection if (socket->incoming == NULL) { if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); if (socket->incoming != NULL) break; } if (socket->incoming == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT))); } } else { while (socket->incoming == NULL) { mp_hal_delay_ms(100); } } } // create new socket object lwip_socket_obj_t *socket2 = m_new_obj_with_finaliser(lwip_socket_obj_t); socket2->base.type = (mp_obj_t)&lwip_socket_type; // We get a new pcb handle... socket2->pcb = socket->incoming; socket->incoming = NULL; // ...and set up the new socket for it. socket2->domain = MOD_NETWORK_AF_INET; socket2->type = MOD_NETWORK_SOCK_STREAM; socket2->incoming = NULL; socket2->timeout = socket->timeout; socket2->connected = 2; socket2->leftover_count = 0; tcp_arg((struct tcp_pcb*)socket2->pcb, (void*)socket2); tcp_err((struct tcp_pcb*)socket2->pcb, _lwip_tcp_error); tcp_recv((struct tcp_pcb*)socket2->pcb, _lwip_tcp_recv); tcp_accepted(listener); // make the return value uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE]; memcpy(ip, &(((struct tcp_pcb*)socket2->pcb)->remote_ip), 4); mp_uint_t port = (mp_uint_t)((struct tcp_pcb*)socket2->pcb)->remote_port; mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = socket2; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return client; }
STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) { lwip_socket_obj_t *socket = self_in; if (socket->pcb.tcp == NULL) { mp_raise_OSError(MP_EBADF); } if (socket->type != MOD_NETWORK_SOCK_STREAM) { mp_raise_OSError(MP_EOPNOTSUPP); } // I need to do this because "tcp_accepted", later, is a macro. struct tcp_pcb *listener = socket->pcb.tcp; if (listener->state != LISTEN) { mp_raise_OSError(MP_EINVAL); } // accept incoming connection if (socket->incoming.connection == NULL) { if (socket->timeout == 0) { mp_raise_OSError(MP_EAGAIN); } else if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); if (socket->incoming.connection != NULL) break; } if (socket->incoming.connection == NULL) { mp_raise_OSError(MP_ETIMEDOUT); } } else { while (socket->incoming.connection == NULL) { poll_sockets(); } } } // create new socket object lwip_socket_obj_t *socket2 = m_new_obj_with_finaliser(lwip_socket_obj_t); socket2->base.type = (mp_obj_t)&lwip_socket_type; // We get a new pcb handle... socket2->pcb.tcp = socket->incoming.connection; socket->incoming.connection = NULL; // ...and set up the new socket for it. socket2->domain = MOD_NETWORK_AF_INET; socket2->type = MOD_NETWORK_SOCK_STREAM; socket2->incoming.pbuf = NULL; socket2->timeout = socket->timeout; socket2->state = STATE_CONNECTED; socket2->recv_offset = 0; socket2->callback = MP_OBJ_NULL; tcp_arg(socket2->pcb.tcp, (void*)socket2); tcp_err(socket2->pcb.tcp, _lwip_tcp_error); tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv); tcp_accepted(listener); // make the return value uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE]; memcpy(ip, &(socket2->pcb.tcp->remote_ip), sizeof(ip)); mp_uint_t port = (mp_uint_t)socket2->pcb.tcp->remote_port; mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = socket2; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); return client; }