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; }
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; }