int NanostackInterface::socket_recv(void *handle, void *data, unsigned size) { // Validate parameters NanostackSocket * socket = static_cast<NanostackSocket *>(handle); if (NULL == handle) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nanostack_lock(); int ret; if (socket->closed()) { ret = NSAPI_ERROR_NO_CONNECTION; } else if (socket->data_available()) { ret = socket->data_copy_and_free(data, size, NULL, true); } else { ret = NSAPI_ERROR_WOULD_BLOCK; } nanostack_unlock(); tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
int NanostackInterface::socket_connect(void *handle, const SocketAddress &addr) { // Validate parameters NanostackSocket * socket = static_cast<NanostackSocket *>(handle); if (NULL == handle) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nanostack_lock(); int ret; ns_address_t ns_addr; int random_port = socket->is_bound() ? 0 : 1; convert_mbed_addr_to_ns(&ns_addr, &addr); if (0 == ::socket_connect(socket->socket_id, &ns_addr, random_port)) { socket->set_connecting(&ns_addr); ret = 0; } else { ret = NSAPI_ERROR_DEVICE_ERROR; } nanostack_unlock(); tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
int NanostackInterface::socket_bind(void *handle, const SocketAddress &address) { // Validate parameters NanostackSocket * socket = static_cast<NanostackSocket *>(handle); if (NULL == handle) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nanostack_lock(); ns_address_t ns_address; ns_address.type = ADDRESS_IPV6; memset(ns_address.address, 0, sizeof ns_address.address); ns_address.identifier = address.get_port(); int ret = NSAPI_ERROR_DEVICE_ERROR; if (0 == ::socket_bind(socket->socket_id, &ns_address)) { socket->set_bound(); ret = 0; } nanostack_unlock(); tr_debug("socket_bind(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
nsapi_error_t NanostackInterface::socket_connect(void *handle, const SocketAddress &addr) { // Validate parameters NanostackSocket *socket = static_cast<NanostackSocket *>(handle); nsapi_error_t ret; if (handle == NULL) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } NanostackLockGuard lock; if (addr.get_ip_version() != NSAPI_IPv6) { ret = NSAPI_ERROR_UNSUPPORTED; goto out; } if (socket->closed()) { ret = NSAPI_ERROR_NO_CONNECTION; goto out; } if (socket->is_connecting()) { ret = NSAPI_ERROR_ALREADY; goto out; } if (socket->is_connected()) { ret = NSAPI_ERROR_IS_CONNECTED; goto out; } ns_address_t ns_addr; convert_mbed_addr_to_ns(&ns_addr, &addr); if (::socket_connect(socket->socket_id, &ns_addr, 0) == 0) { if (socket->proto == SOCKET_TCP) { socket->set_connecting(&ns_addr); ret = NSAPI_ERROR_IN_PROGRESS; } else { ret = NSAPI_ERROR_OK; } } else { ret = NSAPI_ERROR_DEVICE_ERROR; } out: tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
int NanostackInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned int size) { // Validate parameters NanostackSocket * socket = static_cast<NanostackSocket *>(handle); if (NULL == handle) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nanostack_lock(); int ret; if (socket->closed()) { ret = NSAPI_ERROR_NO_CONNECTION; } else if (NANOSTACK_SOCKET_TCP == socket->proto) { tr_error("socket_sendto() not supported with SOCKET_STREAM!"); ret = NSAPI_ERROR_UNSUPPORTED; } else { ns_address_t ns_address; convert_mbed_addr_to_ns(&ns_address, &address); if (!socket->is_bound()) { socket->set_bound(); } int8_t send_to_status = ::socket_sendto(socket->socket_id, &ns_address, (uint8_t *)data, size); /* * \return 0 on success. * \return -1 invalid socket id. * \return -2 Socket memory allocation fail. * \return -3 TCP state not established. * \return -4 Socket tx process busy. * \return -5 TLS authentication not ready. * \return -6 Packet too short. * */ if (-4 == send_to_status) { ret = NSAPI_ERROR_WOULD_BLOCK; } else if (0 != send_to_status) { tr_error("socket_sendto: error=%d", send_to_status); ret = NSAPI_ERROR_DEVICE_ERROR; } else { ret = size; } } nanostack_unlock(); tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
void NanostackSocket::socket_callback(void *cb) { nanostack_assert_locked(); socket_callback_t *sock_cb = (socket_callback_t *) cb; NanostackSocket *socket = socket_tbl[sock_cb->socket_id]; MBED_ASSERT(socket != NULL); tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d", sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len); switch (sock_cb->event_type) { case SOCKET_DATA: tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len); socket->event_data(sock_cb); break; case SOCKET_BIND_DONE: tr_debug("SOCKET_BIND_DONE"); socket->event_bind_done(sock_cb); break; case SOCKET_BIND_FAIL: // Not used in NS tr_debug("SOCKET_BIND_FAIL"); break; case SOCKET_BIND_AUTH_FAIL: // Not used in NS tr_debug("SOCKET_BIND_AUTH_FAIL"); break; case SOCKET_SERVER_CONNECT_TO_CLIENT: // Not used in NS tr_debug("SOCKET_SERVER_CONNECT_TO_CLIENT"); break; case SOCKET_TX_FAIL: tr_debug("SOCKET_TX_FAIL"); break; case SOCKET_CONNECT_CLOSED: tr_debug("SOCKET_CONNECT_CLOSED"); socket->event_connnect_closed(sock_cb); break; case SOCKET_CONNECT_FAIL_CLOSED: // Not used in NS tr_debug("SOCKET_CONNECT_FAIL_CLOSED"); break; case SOCKET_NO_ROUTE: tr_debug("SOCKET_NO_ROUTE"); break; case SOCKET_TX_DONE: tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len); socket->event_tx_done(sock_cb); break; default: // SOCKET_NO_RAM, error case for SOCKET_TX_DONE break; } }
nsapi_error_t NanostackInterface::socket_accept(void *server, void **handle, SocketAddress *address) { NanostackSocket * socket = static_cast<NanostackSocket *>(server); NanostackSocket *accepted_sock = NULL; nsapi_error_t ret; if (handle == NULL) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } NanostackLockGuard lock; if (!socket->is_listening()) { ret = NSAPI_ERROR_PARAMETER; goto out; } accepted_sock = new NanostackSocket(socket->proto); if (accepted_sock == NULL) { ret = NSAPI_ERROR_NO_MEMORY; goto out; } ns_address_t ns_addr; int retcode; retcode = socket->accept(accepted_sock, &ns_addr); if (retcode < 0) { delete accepted_sock; if (retcode == NS_EWOULDBLOCK) { ret = NSAPI_ERROR_WOULD_BLOCK; } else { ret = NSAPI_ERROR_DEVICE_ERROR; } goto out; } ret = NSAPI_ERROR_OK; if (address) { convert_ns_addr_to_mbed(address, &ns_addr); } *handle = accepted_sock; out: tr_debug("socket_accept() socket=%p, sock_id=%d, ret=%i", accepted_sock, accepted_sock ? accepted_sock->socket_id : -1, ret); return ret; }
nsapi_size_or_error_t NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size) { // Validate parameters NanostackSocket *socket = static_cast<NanostackSocket *>(handle); if (handle == NULL) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nsapi_size_or_error_t ret; NanostackLockGuard lock; if (socket->closed()) { ret = NSAPI_ERROR_NO_CONNECTION; goto out; } ns_address_t ns_address; int retcode; retcode = ::socket_recvfrom(socket->socket_id, buffer, size, 0, &ns_address); if (retcode == NS_EWOULDBLOCK) { ret = NSAPI_ERROR_WOULD_BLOCK; } else if (retcode < 0) { ret = NSAPI_ERROR_PARAMETER; } else { ret = retcode; if (address != NULL) { convert_ns_addr_to_mbed(address, &ns_address); } } out: if (address) { tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i, addr=[%s]:%i", socket, socket->socket_id, ret, trace_ipv6(address->get_ip_bytes()), address->get_port()); } else { tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); } return ret; }
int NanostackInterface::socket_send(void *handle, const void *p, unsigned size) { // Validate parameters NanostackSocket * socket = static_cast<NanostackSocket *>(handle); if (NULL == handle) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nanostack_lock(); int ret; if (socket->closed()) { ret = NSAPI_ERROR_NO_CONNECTION; } else if (socket->is_connecting()) { ret = NSAPI_ERROR_WOULD_BLOCK; } else { ret = ::socket_sendto(socket->socket_id, &socket->ns_address, (uint8_t*)p, size); /* * \return 0 on success. * \return -1 invalid socket id. * \return -2 Socket memory allocation fail. * \return -3 TCP state not established. * \return -4 Socket tx process busy. * \return -5 TLS authentication not ready. * \return -6 Packet too short. * */ if (-4 == ret) { ret = NSAPI_ERROR_WOULD_BLOCK; } else if (ret != 0) { tr_warning("socket_sendto ret %i, socket_id %i", ret, socket->socket_id); ret = NSAPI_ERROR_DEVICE_ERROR; } else { ret = size; } } nanostack_unlock(); tr_debug("socket_send(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
nsapi_error_t NanostackInterface::socket_listen(void *handle, int backlog) { //Check if socket exists NanostackSocket *socket = static_cast<NanostackSocket *>(handle); if (handle == NULL) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nsapi_error_t ret = NSAPI_ERROR_OK; NanostackLockGuard lock; if(::socket_listen(socket->socket_id, backlog) < 0) { ret = NSAPI_ERROR_PARAMETER; } else { socket->set_listening(); } return ret; }
int NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol) { // Validate parameters if (NULL == handle) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } int8_t ns_proto; if (NSAPI_UDP == protocol) { ns_proto = SOCKET_UDP; } else if (NSAPI_TCP == protocol) { ns_proto = SOCKET_TCP; } else { MBED_ASSERT(false); return NSAPI_ERROR_UNSUPPORTED; } *handle = (void*)NULL; nanostack_lock(); NanostackSocket * socket = new NanostackSocket(ns_proto); if (NULL == socket) { nanostack_unlock(); tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY); return NSAPI_ERROR_NO_MEMORY; } if (!socket->open()) { delete socket; nanostack_unlock(); tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR); return NSAPI_ERROR_DEVICE_ERROR; } *handle = (void*)socket; nanostack_unlock(); tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id); return 0; }
int NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size) { // Validate parameters NanostackSocket * socket = static_cast<NanostackSocket *>(handle); if (NULL == handle) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } if (NULL == buffer) { MBED_ASSERT(false); return NSAPI_ERROR_PARAMETER; } if (0 == size) { MBED_ASSERT(false); return NSAPI_ERROR_PARAMETER; } nanostack_lock(); int ret; if (socket->closed()) { ret = NSAPI_ERROR_NO_CONNECTION; } else if (NANOSTACK_SOCKET_TCP == socket->proto) { tr_error("recv_from() not supported with SOCKET_STREAM!"); ret = NSAPI_ERROR_UNSUPPORTED; } else if (!socket->data_available()) { ret = NSAPI_ERROR_WOULD_BLOCK; } else { ret = socket->data_copy_and_free(buffer, size, address, false); } nanostack_unlock(); tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
nsapi_size_or_error_t NanostackInterface::do_sendto(void *handle, const ns_address_t *address, const void *data, nsapi_size_t size) { // Validate parameters NanostackSocket * socket = static_cast<NanostackSocket *>(handle); if (handle == NULL) { MBED_ASSERT(false); return NSAPI_ERROR_NO_SOCKET; } nsapi_size_or_error_t ret; NanostackLockGuard lock; if (socket->closed() || (!address && !socket->is_connected())) { ret = NSAPI_ERROR_NO_CONNECTION; goto out; } if (address && socket->proto == SOCKET_TCP) { tr_error("socket_sendto() not supported with TCP!"); ret = NSAPI_ERROR_IS_CONNECTED; goto out; } int retcode; #if 0 retcode = ::socket_sendto(socket->socket_id, address, data, size); #else // Use sendmsg purely to get the new return style // of returning data written rather than 0 on success, // which means TCP can do partial writes. (Sadly, // it's the only call which takes flags so we can // leave the NS_MSG_LEGACY0 flag clear). ns_msghdr_t msg; ns_iovec_t iov; iov.iov_base = const_cast<void *>(data); iov.iov_len = size; msg.msg_name = const_cast<ns_address_t *>(address); msg.msg_namelen = address ? sizeof *address : 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; retcode = ::socket_sendmsg(socket->socket_id, &msg, 0); #endif /* * \return length if entire amount written (which could be 0) * \return value >0 and <length if partial amount written (stream only) * \return NS_EWOULDBLOCK if nothing written due to lack of queue space. * \return -1 Invalid socket ID or message structure. * \return -2 Socket memory allocation fail. * \return -3 TCP state not established or address scope not defined . * \return -4 Socket TX process busy or unknown interface. * \return -5 Socket not connected * \return -6 Packet too short (ICMP raw socket error). * */ if (retcode == NS_EWOULDBLOCK) { ret = NSAPI_ERROR_WOULD_BLOCK; } else if (retcode < 0) { tr_error("socket_sendmsg: error=%d", retcode); ret = NSAPI_ERROR_DEVICE_ERROR; } else { ret = retcode; } out: tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); return ret; }
void NanostackSocket::socket_callback(void *cb) { nanostack_assert_locked(); socket_callback_t *sock_cb = (socket_callback_t *) cb; NanostackSocket *socket = socket_tbl[sock_cb->socket_id]; MBED_ASSERT(socket != NULL); tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d", sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len); switch (sock_cb->event_type) { case SOCKET_DATA: tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len); socket->event_data(sock_cb); break; case SOCKET_CONNECT_DONE: tr_debug("SOCKET_CONNECT_DONE"); socket->event_connect_done(sock_cb); break; case SOCKET_CONNECT_FAIL: tr_debug("SOCKET_CONNECT_FAIL"); socket->event_connect_fail(sock_cb); break; case SOCKET_CONNECT_AUTH_FAIL: tr_debug("SOCKET_CONNECT_AUTH_FAIL"); break; case SOCKET_INCOMING_CONNECTION: tr_debug("SOCKET_INCOMING_CONNECTION"); socket->event_incoming_connection(sock_cb); break; case SOCKET_TX_FAIL: tr_debug("SOCKET_TX_FAIL"); socket->event_tx_fail(sock_cb); break; case SOCKET_CONNECT_CLOSED: tr_debug("SOCKET_CONNECT_CLOSED"); socket->event_connect_closed(sock_cb); break; case SOCKET_CONNECTION_RESET: tr_debug("SOCKET_CONNECTION_RESET"); socket->event_connection_reset(sock_cb); break; case SOCKET_NO_ROUTE: tr_debug("SOCKET_NO_ROUTE"); socket->event_tx_fail(sock_cb); break; case SOCKET_TX_DONE: socket->event_tx_done(sock_cb); break; case SOCKET_NO_RAM: tr_debug("SOCKET_NO_RAM"); socket->event_tx_fail(sock_cb); break; case SOCKET_CONNECTION_PROBLEM: tr_debug("SOCKET_CONNECTION_PROBLEM"); break; default: break; } }