ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackInterface.cpp Source File

NanostackInterface.cpp

00001 /* Nanostack implementation of NetworkSocketAPI
00002  * Copyright (c) 2016 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "rtos.h"
00019 #include "NanostackInterface.h"
00020 
00021 #include "ns_address.h"
00022 #include "nsdynmemLIB.h"
00023 #include "eventOS_scheduler.h"
00024 #include "randLIB.h"
00025 
00026 #include "mesh_system.h" // from inside mbed-mesh-api
00027 #include "socket_api.h"
00028 #include "net_interface.h"
00029 
00030 // Uncomment to enable trace
00031 //#define HAVE_DEBUG
00032 #include "ns_trace.h"
00033 #define TRACE_GROUP "nsif"
00034 
00035 #define NS_INTERFACE_SOCKETS_MAX  16  //same as NanoStack SOCKET_MAX
00036 #define NANOSTACK_SOCKET_UDP 17 // same as nanostack SOCKET_UDP
00037 #define NANOSTACK_SOCKET_TCP 6  // same as nanostack SOCKET_TCP
00038 
00039 #define MALLOC  ns_dyn_mem_alloc
00040 #define FREE    ns_dyn_mem_free
00041 
00042 enum socket_mode_t {
00043     SOCKET_MODE_UNOPENED,   // No socket ID
00044     SOCKET_MODE_OPENED,     // Socket ID but no assigned use yet
00045     SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet
00046     SOCKET_MODE_DATAGRAM,   // Socket is bound to a port and listening for datagrams
00047     SOCKET_MODE_STREAM,     // Socket has an open stream
00048     SOCKET_MODE_CLOSED,     // Socket is closed and resources are freed
00049 };
00050 
00051 class NanostackBuffer {
00052 public:
00053     NanostackBuffer *next;      /*<! next buffer */
00054     ns_address_t ns_address;    /*<! address where data is received */
00055     uint16_t length;            /*<! data length in this buffer */
00056     uint8_t payload[1];          /*<! Trailing buffer data */
00057 };
00058 
00059 class NanostackSocket {
00060 public:
00061     static void socket_callback(void *cb);
00062     static void* operator new(std::size_t sz);
00063     static void operator delete(void* ptr);
00064 
00065     NanostackSocket(int8_t protocol);
00066     ~NanostackSocket(void);
00067     bool open(void);
00068     void close(void);
00069     bool closed(void) {return SOCKET_MODE_CLOSED == mode;}
00070     bool is_bound(void);
00071     void set_bound(void);
00072     bool is_connecting(void);
00073     void set_connecting(ns_address_t *addr);
00074     void set_connected(void);
00075 
00076     // Socket events from nanostack
00077     void event_data(socket_callback_t *sock_cb);
00078     void event_bind_done(socket_callback_t *sock_cb);
00079     void event_connnect_closed(socket_callback_t *sock_cb);
00080     void event_tx_done(socket_callback_t *sock_cb);
00081 
00082     // Run callback to signal the next layer of the NSAPI
00083     void signal_event(void);
00084 
00085     // Add or remove a socket to the listening socket
00086     void accept_list_add(NanostackSocket *socket);
00087     NanostackSocket * accept_list_remove(void);
00088 
00089     bool data_available(void);
00090     size_t data_copy_and_free(void *dest, size_t len, SocketAddress *address, bool stream);
00091     void data_free_all(void);
00092     void data_attach(NanostackBuffer *data_buf);
00093 
00094     void (*callback)(void *);
00095     void *callback_data;
00096     int8_t socket_id;           /*!< allocated socket ID */
00097     int8_t proto;               /*!< UDP or TCP */
00098     bool addr_valid;
00099     ns_address_t ns_address;
00100 private:
00101     NanostackBuffer *rxBufChain;    /*!< Receive buffers */
00102     socket_mode_t mode;
00103 };
00104 
00105 static NanostackSocket * socket_tbl[NS_INTERFACE_SOCKETS_MAX];
00106 
00107 nsapi_error_t map_mesh_error(mesh_error_t err)
00108 {
00109     switch (err) {
00110         case MESH_ERROR_NONE: return 0;
00111         case MESH_ERROR_MEMORY: return NSAPI_ERROR_NO_MEMORY ;
00112         case MESH_ERROR_PARAM: return NSAPI_ERROR_UNSUPPORTED ;
00113         case MESH_ERROR_STATE: return NSAPI_ERROR_DEVICE_ERROR ;
00114         default: return NSAPI_ERROR_DEVICE_ERROR ;
00115     }
00116 }
00117 
00118 static void convert_mbed_addr_to_ns(ns_address_t *ns_addr,
00119                              const SocketAddress *s_addr)
00120 {
00121     ns_addr->type = ADDRESS_IPV6;
00122     ns_addr->identifier = s_addr->get_port();
00123     memcpy(ns_addr->address, s_addr->get_ip_bytes(), 16);
00124 }
00125 
00126 static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *ns_addr)
00127 {
00128     s_addr->set_port(ns_addr->identifier);
00129     s_addr->set_ip_bytes(ns_addr->address, NSAPI_IPv6 );
00130 }
00131 
00132 void* NanostackSocket::operator new(std::size_t sz) {
00133     return MALLOC(sz);
00134 }
00135 void NanostackSocket::operator delete(void* ptr) {
00136     FREE(ptr);
00137 }
00138 
00139 NanostackSocket::NanostackSocket(int8_t protocol)
00140 {
00141     nanostack_assert_locked();
00142 
00143     callback = NULL;
00144     callback_data = NULL;
00145     socket_id = -1;
00146     rxBufChain = NULL;
00147     proto = protocol;
00148     addr_valid = false;
00149     memset(&ns_address, 0, sizeof(ns_address));
00150     mode = SOCKET_MODE_UNOPENED;
00151 }
00152 
00153 NanostackSocket::~NanostackSocket()
00154 {
00155     nanostack_assert_locked();
00156 
00157     if (mode != SOCKET_MODE_CLOSED) {
00158         close();
00159     }
00160     data_free_all();
00161 }
00162 
00163 bool NanostackSocket::open(void)
00164 {
00165     nanostack_assert_locked();
00166     MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
00167 
00168     int temp_socket = socket_open(proto, 0, socket_callback);
00169 
00170     if (temp_socket < 0) {
00171         tr_error("NanostackSocket::open() failed");
00172         return false;
00173     }
00174     if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) {
00175         MBED_ASSERT(false);
00176         return false;
00177     }
00178     if (socket_tbl[temp_socket] != NULL) {
00179         MBED_ASSERT(false);
00180         return false;
00181     }
00182     socket_id = temp_socket;
00183     socket_tbl[socket_id] = this;
00184     mode = SOCKET_MODE_OPENED;
00185     return true;
00186 
00187 }
00188 
00189 void NanostackSocket::close()
00190 {
00191     nanostack_assert_locked();
00192     MBED_ASSERT(mode != SOCKET_MODE_CLOSED);
00193 
00194     if (socket_id >= 0) {
00195         nsapi_error_t ret = socket_close(socket_id);
00196         MBED_ASSERT(0 == ret);
00197         MBED_ASSERT(socket_tbl[socket_id] == this);
00198         socket_tbl[socket_id] = NULL;
00199         socket_id = -1;
00200     } else {
00201         MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
00202     }
00203 
00204     data_free_all();
00205 
00206     mode = SOCKET_MODE_CLOSED;
00207     signal_event();
00208 }
00209 
00210 bool NanostackSocket::is_bound()
00211 {
00212     return SOCKET_MODE_DATAGRAM == mode;
00213 }
00214 
00215 void NanostackSocket::set_bound()
00216 {
00217     nanostack_assert_locked();
00218     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00219     if (SOCKET_UDP == proto) {
00220         mode = SOCKET_MODE_DATAGRAM;
00221     }
00222 }
00223 
00224 bool NanostackSocket::is_connecting()
00225 {
00226     return SOCKET_MODE_CONNECTING == mode;
00227 }
00228 
00229 void NanostackSocket::set_connecting(ns_address_t *addr)
00230 {
00231     nanostack_assert_locked();
00232     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00233 
00234     memcpy(&ns_address, addr, sizeof(ns_address_t));
00235     mode = SOCKET_MODE_CONNECTING;
00236 }
00237 
00238 void NanostackSocket::set_connected()
00239 {
00240     nanostack_assert_locked();
00241     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00242 
00243     mode = SOCKET_MODE_STREAM;
00244 }
00245 
00246 void NanostackSocket::signal_event()
00247 {
00248     nanostack_assert_locked();
00249 
00250     if (callback != NULL) {
00251         callback(callback_data);
00252     }
00253 }
00254 
00255 void NanostackSocket::socket_callback(void *cb) {
00256     nanostack_assert_locked();
00257 
00258     socket_callback_t *sock_cb = (socket_callback_t *) cb;
00259     NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
00260     MBED_ASSERT(socket != NULL);
00261 
00262     tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
00263                      sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);
00264 
00265     switch (sock_cb->event_type) {
00266         case SOCKET_DATA:
00267             tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
00268             socket->event_data(sock_cb);
00269             break;
00270         case SOCKET_BIND_DONE:
00271             tr_debug("SOCKET_BIND_DONE");
00272             socket->event_bind_done(sock_cb);
00273             break;
00274         case SOCKET_BIND_FAIL:
00275             tr_debug("SOCKET_BIND_FAIL");
00276             break;
00277         case SOCKET_BIND_AUTH_FAIL:
00278             tr_debug("SOCKET_BIND_AUTH_FAIL");
00279             break;
00280         case SOCKET_INCOMING_CONNECTION:
00281             tr_debug("SOCKET_INCOMING_CONNECTION");
00282             break;
00283         case SOCKET_TX_FAIL:
00284             tr_debug("SOCKET_TX_FAIL");
00285             break;
00286         case SOCKET_CONNECT_CLOSED:
00287             tr_debug("SOCKET_CONNECT_CLOSED");
00288             socket->event_connnect_closed(sock_cb);
00289             break;
00290         case SOCKET_CONNECTION_RESET:
00291             tr_debug("SOCKET_CONNECTION_RESET");
00292             break;
00293         case SOCKET_NO_ROUTE:
00294             tr_debug("SOCKET_NO_ROUTE");
00295             break;
00296         case SOCKET_TX_DONE:
00297             tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len);
00298             socket->event_tx_done(sock_cb);
00299             break;
00300         default:
00301             // SOCKET_NO_RAM, error case for SOCKET_TX_DONE
00302             break;
00303     }
00304 }
00305 
00306 
00307 bool NanostackSocket::data_available()
00308 {
00309     nanostack_assert_locked();
00310     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00311                 (SOCKET_MODE_CONNECTING == mode) ||
00312                 (SOCKET_MODE_STREAM == mode));
00313 
00314     return (NULL == rxBufChain) ? false : true;
00315 }
00316 
00317 size_t NanostackSocket::data_copy_and_free(void *dest, size_t len,
00318                                                   SocketAddress *address, bool stream)
00319 {
00320     nanostack_assert_locked();
00321     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00322                 (mode == SOCKET_MODE_STREAM));
00323 
00324     NanostackBuffer *data_buf = rxBufChain;
00325     if (NULL == data_buf) {
00326         // No data
00327         return 0;
00328     }
00329 
00330     if (address) {
00331         convert_ns_addr_to_mbed(address, &data_buf->ns_address);
00332     }
00333 
00334     size_t copy_size = (len > data_buf->length) ? data_buf->length : len;
00335     memcpy(dest, data_buf->payload, copy_size);
00336 
00337     if (stream && (copy_size < data_buf->length)) {
00338         // Update the size in the buffer
00339         size_t new_buf_size = data_buf->length - copy_size;
00340         memmove(data_buf->payload, data_buf->payload + copy_size, new_buf_size);
00341         data_buf->length = new_buf_size;
00342     } else {
00343         // Entire packet used so free it
00344         rxBufChain = data_buf->next;
00345         FREE(data_buf);
00346     }
00347 
00348     return copy_size;
00349 }
00350 
00351 void NanostackSocket::data_free_all(void)
00352 {
00353     nanostack_assert_locked();
00354     // No mode requirement
00355 
00356     NanostackBuffer *buffer = rxBufChain;
00357     rxBufChain = NULL;
00358     while (buffer != NULL) {
00359         NanostackBuffer *next_buffer = buffer->next;
00360         FREE(buffer);
00361         buffer = next_buffer;
00362     }
00363 }
00364 
00365 void NanostackSocket::data_attach(NanostackBuffer *data_buf)
00366 {
00367     nanostack_assert_locked();
00368     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00369                 (SOCKET_MODE_STREAM == mode));
00370 
00371     // Add to linked list
00372     tr_debug("data_attach socket=%p", this);
00373     if (NULL == rxBufChain) {
00374         rxBufChain = data_buf;
00375     } else {
00376         NanostackBuffer *buf_tmp = rxBufChain;
00377         while (NULL != buf_tmp->next) {
00378             buf_tmp = buf_tmp->next;
00379         }
00380         buf_tmp->next = data_buf;
00381     }
00382     signal_event();
00383 }
00384 
00385 void NanostackSocket::event_data(socket_callback_t *sock_cb)
00386 {
00387     nanostack_assert_locked();
00388     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00389                 (SOCKET_MODE_STREAM == mode));
00390 
00391     // Allocate buffer
00392     NanostackBuffer *recv_buff = (NanostackBuffer *) MALLOC(
00393                                  sizeof(NanostackBuffer) + sock_cb->d_len);
00394     if (NULL == recv_buff) {
00395         tr_error("alloc failed!");
00396         return;
00397     }
00398     recv_buff->next = NULL;
00399 
00400     // Write data to buffer
00401     int16_t length = socket_read(sock_cb->socket_id,
00402                                  &recv_buff->ns_address, recv_buff->payload,
00403                                  sock_cb->d_len);
00404     if (length < 0) {
00405         tr_error("socket_read failed!");
00406         FREE(recv_buff);
00407         return;
00408     }
00409     recv_buff->length = length;
00410 
00411     data_attach(recv_buff);
00412 }
00413 
00414 void NanostackSocket::event_tx_done(socket_callback_t *sock_cb)
00415 {
00416     nanostack_assert_locked();
00417     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00418                 (SOCKET_MODE_DATAGRAM == mode));
00419 
00420     signal_event();
00421 }
00422 
00423 void NanostackSocket::event_bind_done(socket_callback_t *sock_cb)
00424 {
00425     nanostack_assert_locked();
00426     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00427 
00428     set_connected();
00429     signal_event();
00430 }
00431 
00432 void NanostackSocket::event_connnect_closed(socket_callback_t *sock_cb)
00433 {
00434     nanostack_assert_locked();
00435 
00436     // Only TCP sockets can be closed by the remote end
00437     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00438                 (SOCKET_MODE_CONNECTING == mode));
00439     close();
00440 }
00441 
00442 NanostackInterface * NanostackInterface::_ns_interface;
00443 
00444 NanostackInterface * NanostackInterface::get_stack()
00445 {
00446     nanostack_lock();
00447 
00448     if (NULL == _ns_interface) {
00449         _ns_interface = new NanostackInterface();
00450     }
00451 
00452     nanostack_unlock();
00453 
00454     return _ns_interface;
00455 }
00456 
00457 
00458 const char * NanostackInterface::get_ip_address()
00459 {
00460     // Must result a valid IPv6 address
00461     // For gethostbyname() to detect IP version.
00462     static const char localhost[] = "::";
00463     return localhost;
00464 }
00465 
00466 nsapi_error_t NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol)
00467 {
00468     // Validate parameters
00469     if (NULL == handle) {
00470         MBED_ASSERT(false);
00471         return NSAPI_ERROR_NO_SOCKET ;
00472     }
00473     int8_t ns_proto;
00474     if (NSAPI_UDP  == protocol) {
00475         ns_proto = SOCKET_UDP;
00476     } else if (NSAPI_TCP  == protocol) {
00477         ns_proto = SOCKET_TCP;
00478     } else {
00479         MBED_ASSERT(false);
00480         return NSAPI_ERROR_UNSUPPORTED ;
00481     }
00482     *handle = (void*)NULL;
00483 
00484     nanostack_lock();
00485 
00486     NanostackSocket * socket = new NanostackSocket(ns_proto);
00487     if (NULL == socket) {
00488         nanostack_unlock();
00489         tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY );
00490         return NSAPI_ERROR_NO_MEMORY ;
00491     }
00492     if (!socket->open()) {
00493         delete socket;
00494         nanostack_unlock();
00495         tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR );
00496         return NSAPI_ERROR_DEVICE_ERROR ;
00497     }
00498     *handle = (void*)socket;
00499 
00500     nanostack_unlock();
00501 
00502     tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);
00503 
00504     return 0;
00505 }
00506 
00507 nsapi_error_t NanostackInterface::socket_close(void *handle)
00508 {
00509     // Validate parameters
00510     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00511     if (NULL == handle) {
00512         MBED_ASSERT(false);
00513         return NSAPI_ERROR_NO_SOCKET ;
00514     }
00515     tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id);
00516 
00517     nanostack_lock();
00518 
00519     delete socket;
00520 
00521     nanostack_unlock();
00522 
00523     return 0;
00524 
00525 }
00526 
00527 nsapi_size_or_error_t NanostackInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, nsapi_size_t size)
00528 {
00529     // Validate parameters
00530     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00531     if (NULL == handle) {
00532         MBED_ASSERT(false);
00533         return NSAPI_ERROR_NO_SOCKET ;
00534     }
00535 
00536     if (address.get_ip_version() != NSAPI_IPv6 ) {
00537         return NSAPI_ERROR_UNSUPPORTED ;
00538     }
00539 
00540     nanostack_lock();
00541 
00542     nsapi_size_or_error_t ret;
00543     if (socket->closed()) {
00544         ret = NSAPI_ERROR_NO_CONNECTION ;
00545     } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
00546         tr_error("socket_sendto() not supported with SOCKET_STREAM!");
00547         ret = NSAPI_ERROR_UNSUPPORTED ;
00548     } else {
00549         ns_address_t ns_address;
00550         convert_mbed_addr_to_ns(&ns_address, &address);
00551         if (!socket->is_bound()) {
00552             socket->set_bound();
00553         }
00554         int8_t send_to_status = ::socket_sendto(socket->socket_id, &ns_address,
00555                                        (uint8_t *)data, size);
00556         /*
00557          * \return 0 on success.
00558          * \return -1 invalid socket id.
00559          * \return -2 Socket memory allocation fail.
00560          * \return -3 TCP state not established.
00561          * \return -4 Socket tx process busy.
00562          * \return -5 TLS authentication not ready.
00563          * \return -6 Packet too short.
00564          * */
00565         if (-4 == send_to_status) {
00566             ret = NSAPI_ERROR_WOULD_BLOCK ;
00567         } else if (0 != send_to_status) {
00568             tr_error("socket_sendto: error=%d", send_to_status);
00569             ret = NSAPI_ERROR_DEVICE_ERROR ;
00570         } else {
00571             ret = size;
00572         }
00573     }
00574 
00575     nanostack_unlock();
00576 
00577     tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00578 
00579     return ret;
00580 }
00581 
00582 nsapi_size_or_error_t NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size)
00583 {
00584     // Validate parameters
00585     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00586     if (NULL == handle) {
00587         MBED_ASSERT(false);
00588         return NSAPI_ERROR_NO_SOCKET ;
00589     }
00590     if (NULL == buffer) {
00591         MBED_ASSERT(false);
00592         return NSAPI_ERROR_PARAMETER ;
00593     }
00594     if (0 == size) {
00595         MBED_ASSERT(false);
00596         return NSAPI_ERROR_PARAMETER ;
00597     }
00598 
00599     nanostack_lock();
00600 
00601     nsapi_size_or_error_t ret;
00602     if (socket->closed()) {
00603         ret = NSAPI_ERROR_NO_CONNECTION ;
00604     } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
00605         tr_error("recv_from() not supported with SOCKET_STREAM!");
00606         ret = NSAPI_ERROR_UNSUPPORTED ;
00607     } else if (!socket->data_available()) {
00608         ret = NSAPI_ERROR_WOULD_BLOCK ;
00609     } else {
00610         ret = socket->data_copy_and_free(buffer, size, address, false);
00611     }
00612 
00613     nanostack_unlock();
00614 
00615     tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00616 
00617     return ret;
00618 }
00619 
00620 nsapi_error_t NanostackInterface::socket_bind(void *handle, const SocketAddress &address)
00621 {
00622     // Validate parameters
00623     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00624     if (NULL == handle) {
00625         MBED_ASSERT(false);
00626         return NSAPI_ERROR_NO_SOCKET ;
00627     }
00628 
00629     const void *addr_field;
00630     switch (address.get_ip_version()) {
00631         case NSAPI_IPv6 :
00632             addr_field = address.get_ip_bytes();
00633             break;
00634         case NSAPI_UNSPEC :
00635             addr_field = &ns_in6addr_any;
00636             break;
00637         default:
00638             return NSAPI_ERROR_UNSUPPORTED ;
00639     }
00640 
00641     nanostack_lock();
00642 
00643     ns_address_t ns_address;
00644     ns_address.type = ADDRESS_IPV6;
00645     memcpy(ns_address.address, addr_field, sizeof ns_address.address);
00646     ns_address.identifier = address.get_port();
00647     nsapi_error_t ret = NSAPI_ERROR_DEVICE_ERROR ;
00648     if (0 == ::socket_bind(socket->socket_id, &ns_address)) {
00649         socket->set_bound();
00650         ret = 0;
00651     }
00652 
00653     nanostack_unlock();
00654 
00655     tr_debug("socket_bind(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00656 
00657     return ret;
00658 }
00659 
00660 nsapi_error_t NanostackInterface::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
00661 {
00662     return NSAPI_ERROR_UNSUPPORTED ;
00663 }
00664 
00665 nsapi_error_t NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
00666 {
00667     return NSAPI_ERROR_UNSUPPORTED ;
00668 }
00669 
00670 nsapi_error_t NanostackInterface::socket_listen(void *handle, int backlog)
00671 {
00672     return NSAPI_ERROR_UNSUPPORTED ;
00673 }
00674 
00675 nsapi_error_t NanostackInterface::socket_connect(void *handle, const SocketAddress &addr)
00676 {
00677     // Validate parameters
00678     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00679     if (NULL == handle) {
00680         MBED_ASSERT(false);
00681         return NSAPI_ERROR_NO_SOCKET ;
00682     }
00683 
00684     if (addr.get_ip_version() != NSAPI_IPv6 ) {
00685         return NSAPI_ERROR_UNSUPPORTED ;
00686     }
00687 
00688     nanostack_lock();
00689 
00690     nsapi_error_t ret;
00691     ns_address_t ns_addr;
00692     int random_port = socket->is_bound() ? 0 : 1;
00693     convert_mbed_addr_to_ns(&ns_addr, &addr);
00694     if (0 == ::socket_connect(socket->socket_id, &ns_addr, random_port)) {
00695         socket->set_connecting(&ns_addr);
00696         ret = 0;
00697     } else {
00698         ret = NSAPI_ERROR_DEVICE_ERROR ;
00699     }
00700 
00701     nanostack_unlock();
00702 
00703     tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00704 
00705     return ret;
00706 }
00707 
00708 nsapi_error_t NanostackInterface::socket_accept(void *server, void **handle, SocketAddress *address)
00709 {
00710     return NSAPI_ERROR_UNSUPPORTED ;
00711 }
00712 
00713 nsapi_size_or_error_t NanostackInterface::socket_send(void *handle, const void *p, nsapi_size_t size)
00714 {
00715     // Validate parameters
00716     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00717     if (NULL == handle) {
00718         MBED_ASSERT(false);
00719         return NSAPI_ERROR_NO_SOCKET ;
00720     }
00721 
00722     nanostack_lock();
00723 
00724     nsapi_size_or_error_t ret;
00725     if (socket->closed()) {
00726         ret = NSAPI_ERROR_NO_CONNECTION ;
00727     } else if (socket->is_connecting()) {
00728         ret = NSAPI_ERROR_WOULD_BLOCK ;
00729     } else {
00730         ret = ::socket_sendto(socket->socket_id,  &socket->ns_address, (uint8_t*)p, size);
00731         /*
00732          * \return 0 on success.
00733          * \return -1 invalid socket id.
00734          * \return -2 Socket memory allocation fail.
00735          * \return -3 TCP state not established.
00736          * \return -4 Socket tx process busy.
00737          * \return -5 TLS authentication not ready.
00738          * \return -6 Packet too short.
00739          * */
00740         if (-4 == ret) {
00741             ret = NSAPI_ERROR_WOULD_BLOCK ;
00742         } else if (ret != 0) {
00743             tr_warning("socket_sendto ret %i, socket_id %i", ret, socket->socket_id);
00744             ret = NSAPI_ERROR_DEVICE_ERROR ;
00745         } else {
00746             ret = size;
00747         }
00748     }
00749 
00750     nanostack_unlock();
00751 
00752     tr_debug("socket_send(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00753 
00754     return ret;
00755 }
00756 
00757 nsapi_size_or_error_t NanostackInterface::socket_recv(void *handle, void *data, nsapi_size_t size)
00758 {
00759     // Validate parameters
00760     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00761     if (NULL == handle) {
00762         MBED_ASSERT(false);
00763         return NSAPI_ERROR_NO_SOCKET ;
00764     }
00765 
00766     nanostack_lock();
00767 
00768     nsapi_size_or_error_t ret;
00769     if (socket->closed()) {
00770         ret = NSAPI_ERROR_NO_CONNECTION ;
00771     } else if (socket->data_available()) {
00772         ret = socket->data_copy_and_free(data, size, NULL, true);
00773     } else {
00774         ret = NSAPI_ERROR_WOULD_BLOCK ;
00775     }
00776 
00777     nanostack_unlock();
00778 
00779     tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00780 
00781     return ret;
00782 }
00783 
00784 void NanostackInterface::socket_attach(void *handle, void (*callback)(void *), void *id)
00785 {
00786     // Validate parameters
00787     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00788     if (NULL == handle) {
00789         MBED_ASSERT(false);
00790         return;
00791     }
00792 
00793     nanostack_lock();
00794 
00795     socket->callback = callback;
00796     socket->callback_data = id;
00797 
00798     nanostack_unlock();
00799 
00800     tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id);
00801 }