Greg Steiert / pegasus_dev

Dependents:   blinky_max32630fthr

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 "mbed-mesh-api/MeshInterfaceFactory.h"
00027 
00028 #include "mesh_system.h" // from inside mbed-mesh-api
00029 #include "socket_api.h"
00030 #include "net_interface.h"
00031 // Uncomment to enable trace
00032 //#define HAVE_DEBUG
00033 #include "ns_trace.h"
00034 #define TRACE_GROUP "nsif"
00035 
00036 #define NS_INTERFACE_SOCKETS_MAX  16  //same as NanoStack SOCKET_MAX
00037 #define NANOSTACK_SOCKET_UDP 17 // same as nanostack SOCKET_UDP
00038 #define NANOSTACK_SOCKET_TCP 6  // same as nanostack SOCKET_TCP
00039 
00040 #define MALLOC  ns_dyn_mem_alloc
00041 #define FREE    ns_dyn_mem_free
00042 
00043 #define nanostack_lock()            eventOS_scheduler_mutex_wait()
00044 #define nanostack_unlock()          eventOS_scheduler_mutex_release()
00045 #define nanostack_assert_locked()   //MBED_ASSERT(eventOS_scheduler_mutex_is_owner())
00046 
00047 enum socket_mode_t {
00048     SOCKET_MODE_UNOPENED,   // No socket ID
00049     SOCKET_MODE_OPENED,     // Socket ID but no assigned use yet
00050     SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet
00051     SOCKET_MODE_DATAGRAM,   // Socket is bound to a port and listening for datagrams
00052     SOCKET_MODE_STREAM,     // Socket has an open stream
00053     SOCKET_MODE_CLOSED,     // Socket is closed and resources are freed
00054 };
00055 
00056 class NanostackBuffer {
00057 public:
00058     NanostackBuffer *next;      /*<! next buffer */
00059     ns_address_t ns_address;    /*<! address where data is received */
00060     uint16_t length;            /*<! data length in this buffer */
00061     uint8_t payload[1];          /*<! Trailing buffer data */
00062 };
00063 
00064 class NanostackSocket {
00065 public:
00066     static void socket_callback(void *cb);
00067     static void* operator new(std::size_t sz);
00068     static void operator delete(void* ptr);
00069 
00070     NanostackSocket(int8_t protocol);
00071     ~NanostackSocket(void);
00072     bool open(void);
00073     void close(void);
00074     bool closed(void) {return SOCKET_MODE_CLOSED == mode;}
00075     bool is_bound(void);
00076     void set_bound(void);
00077     bool is_connecting(void);
00078     void set_connecting(ns_address_t *addr);
00079     void set_connected(void);
00080 
00081     // Socket events from nanostack
00082     void event_data(socket_callback_t *sock_cb);
00083     void event_bind_done(socket_callback_t *sock_cb);
00084     void event_connnect_closed(socket_callback_t *sock_cb);
00085     void event_tx_done(socket_callback_t *sock_cb);
00086 
00087     // Run callback to signal the next layer of the NSAPI
00088     void signal_event(void);
00089 
00090     // Add or remove a socket to the listening socket
00091     void accept_list_add(NanostackSocket *socket);
00092     NanostackSocket * accept_list_remove(void);
00093 
00094     bool data_available(void);
00095     size_t data_copy_and_free(void *dest, size_t len, SocketAddress *address, bool stream);
00096     void data_free_all(void);
00097     void data_attach(NanostackBuffer *data_buf);
00098 
00099     void (*callback)(void *);
00100     void *callback_data;
00101     int8_t socket_id;           /*!< allocated socket ID */
00102     int8_t proto;               /*!< UDP or TCP */
00103     bool addr_valid;
00104     ns_address_t ns_address;
00105 private:
00106     NanostackBuffer *rxBufChain;    /*!< Receive buffers */
00107     socket_mode_t mode;
00108 };
00109 
00110 static NanostackSocket * socket_tbl[NS_INTERFACE_SOCKETS_MAX];
00111 
00112 static nsapi_error_t map_mesh_error(mesh_error_t err)
00113 {
00114     switch (err) {
00115         case MESH_ERROR_NONE: return 0;
00116         case MESH_ERROR_MEMORY: return NSAPI_ERROR_NO_MEMORY ;
00117         case MESH_ERROR_PARAM: return NSAPI_ERROR_UNSUPPORTED ;
00118         case MESH_ERROR_STATE: return NSAPI_ERROR_DEVICE_ERROR ;
00119         default: return NSAPI_ERROR_DEVICE_ERROR ;
00120     }
00121 }
00122 
00123 static void convert_mbed_addr_to_ns(ns_address_t *ns_addr,
00124                              const SocketAddress *s_addr)
00125 {
00126     ns_addr->type = ADDRESS_IPV6;
00127     ns_addr->identifier = s_addr->get_port();
00128     memcpy(ns_addr->address, s_addr->get_ip_bytes(), 16);
00129 }
00130 
00131 static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *ns_addr)
00132 {
00133     s_addr->set_port(ns_addr->identifier);
00134     s_addr->set_ip_bytes(ns_addr->address, NSAPI_IPv6 );
00135 }
00136 
00137 void* NanostackSocket::operator new(std::size_t sz) {
00138     return MALLOC(sz);
00139 }
00140 void NanostackSocket::operator delete(void* ptr) {
00141     FREE(ptr);
00142 }
00143 
00144 NanostackSocket::NanostackSocket(int8_t protocol)
00145 {
00146     nanostack_assert_locked();
00147 
00148     callback = NULL;
00149     callback_data = NULL;
00150     socket_id = -1;
00151     rxBufChain = NULL;
00152     proto = protocol;
00153     addr_valid = false;
00154     memset(&ns_address, 0, sizeof(ns_address));
00155     mode = SOCKET_MODE_UNOPENED;
00156 }
00157 
00158 NanostackSocket::~NanostackSocket()
00159 {
00160     nanostack_assert_locked();
00161 
00162     if (mode != SOCKET_MODE_CLOSED) {
00163         close();
00164     }
00165     if (socket_id >= 0) {
00166         nsapi_error_t ret = socket_free(socket_id);
00167         MBED_ASSERT(0 == ret);
00168         MBED_ASSERT(socket_tbl[socket_id] == this);
00169         socket_tbl[socket_id] = NULL;
00170         socket_id = -1;
00171         data_free_all();
00172     }
00173 
00174 }
00175 
00176 bool NanostackSocket::open(void)
00177 {
00178     nanostack_assert_locked();
00179     MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
00180 
00181     int temp_socket = socket_open(proto, 0, socket_callback);
00182 
00183     if (temp_socket < 0) {
00184         tr_error("NanostackSocket::open() failed");
00185         return false;
00186     }
00187     if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) {
00188         MBED_ASSERT(false);
00189         return false;
00190     }
00191     if (socket_tbl[temp_socket] != NULL) {
00192         MBED_ASSERT(false);
00193         return false;
00194     }
00195     socket_id = temp_socket;
00196     socket_tbl[socket_id] = this;
00197     mode = SOCKET_MODE_OPENED;
00198     return true;
00199 
00200 }
00201 
00202 void NanostackSocket::close()
00203 {
00204     nanostack_assert_locked();
00205     MBED_ASSERT(mode != SOCKET_MODE_CLOSED);
00206 
00207     if (socket_id >= 0) {
00208         nsapi_error_t ret = socket_close(socket_id, (addr_valid ? &ns_address : NULL));
00209         MBED_ASSERT(0 == ret);
00210     } else {
00211         MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
00212     }
00213 
00214     data_free_all();
00215 
00216     mode = SOCKET_MODE_CLOSED;
00217     signal_event();
00218 }
00219 
00220 bool NanostackSocket::is_bound()
00221 {
00222     return SOCKET_MODE_DATAGRAM == mode;
00223 }
00224 
00225 void NanostackSocket::set_bound()
00226 {
00227     nanostack_assert_locked();
00228     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00229     if (SOCKET_UDP == proto) {
00230         mode = SOCKET_MODE_DATAGRAM;
00231     }
00232 }
00233 
00234 bool NanostackSocket::is_connecting()
00235 {
00236     return SOCKET_MODE_CONNECTING == mode;
00237 }
00238 
00239 void NanostackSocket::set_connecting(ns_address_t *addr)
00240 {
00241     nanostack_assert_locked();
00242     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00243 
00244     memcpy(&ns_address, addr, sizeof(ns_address_t));
00245     mode = SOCKET_MODE_CONNECTING;
00246 }
00247 
00248 void NanostackSocket::set_connected()
00249 {
00250     nanostack_assert_locked();
00251     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00252 
00253     mode = SOCKET_MODE_STREAM;
00254 }
00255 
00256 void NanostackSocket::signal_event()
00257 {
00258     nanostack_assert_locked();
00259 
00260     if (callback != NULL) {
00261         callback(callback_data);
00262     }
00263 }
00264 
00265 void NanostackSocket::socket_callback(void *cb) {
00266     nanostack_assert_locked();
00267 
00268     socket_callback_t *sock_cb = (socket_callback_t *) cb;
00269     NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
00270     MBED_ASSERT(socket != NULL);
00271 
00272     tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
00273                      sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);
00274 
00275     switch (sock_cb->event_type) {
00276         case SOCKET_DATA:
00277             tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
00278             socket->event_data(sock_cb);
00279             break;
00280         case SOCKET_BIND_DONE:
00281             tr_debug("SOCKET_BIND_DONE");
00282             socket->event_bind_done(sock_cb);
00283             break;
00284         case SOCKET_BIND_FAIL: // Not used in NS
00285             tr_debug("SOCKET_BIND_FAIL");
00286             break;
00287         case SOCKET_BIND_AUTH_FAIL: // Not used in NS
00288             tr_debug("SOCKET_BIND_AUTH_FAIL");
00289             break;
00290         case SOCKET_SERVER_CONNECT_TO_CLIENT: // Not used in NS
00291             tr_debug("SOCKET_SERVER_CONNECT_TO_CLIENT");
00292             break;
00293         case SOCKET_TX_FAIL:
00294             tr_debug("SOCKET_TX_FAIL");
00295             break;
00296         case SOCKET_CONNECT_CLOSED:
00297             tr_debug("SOCKET_CONNECT_CLOSED");
00298             socket->event_connnect_closed(sock_cb);
00299             break;
00300         case SOCKET_CONNECT_FAIL_CLOSED: // Not used in NS
00301             tr_debug("SOCKET_CONNECT_FAIL_CLOSED");
00302             break;
00303         case SOCKET_NO_ROUTE:
00304             tr_debug("SOCKET_NO_ROUTE");
00305             break;
00306         case SOCKET_TX_DONE:
00307             tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len);
00308             socket->event_tx_done(sock_cb);
00309             break;
00310         default:
00311             // SOCKET_NO_RAM, error case for SOCKET_TX_DONE
00312             break;
00313     }
00314 }
00315 
00316 
00317 bool NanostackSocket::data_available()
00318 {
00319     nanostack_assert_locked();
00320     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00321                 (SOCKET_MODE_CONNECTING == mode) ||
00322                 (SOCKET_MODE_STREAM == mode));
00323 
00324     return (NULL == rxBufChain) ? false : true;
00325 }
00326 
00327 size_t NanostackSocket::data_copy_and_free(void *dest, size_t len,
00328                                                   SocketAddress *address, bool stream)
00329 {
00330     nanostack_assert_locked();
00331     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00332                 (mode == SOCKET_MODE_STREAM));
00333 
00334     NanostackBuffer *data_buf = rxBufChain;
00335     if (NULL == data_buf) {
00336         // No data
00337         return 0;
00338     }
00339 
00340     if (address) {
00341         convert_ns_addr_to_mbed(address, &data_buf->ns_address);
00342     }
00343 
00344     size_t copy_size = (len > data_buf->length) ? data_buf->length : len;
00345     memcpy(dest, data_buf->payload, copy_size);
00346 
00347     if (stream && (copy_size < data_buf->length)) {
00348         // Update the size in the buffer
00349         size_t new_buf_size = data_buf->length - copy_size;
00350         memmove(data_buf->payload, data_buf->payload + copy_size, new_buf_size);
00351         data_buf->length = new_buf_size;
00352     } else {
00353         // Entire packet used so free it
00354         rxBufChain = data_buf->next;
00355         FREE(data_buf);
00356     }
00357 
00358     return copy_size;
00359 }
00360 
00361 void NanostackSocket::data_free_all(void)
00362 {
00363     nanostack_assert_locked();
00364     // No mode requirement
00365 
00366     NanostackBuffer *buffer = rxBufChain;
00367     rxBufChain = NULL;
00368     while (buffer != NULL) {
00369         NanostackBuffer *next_buffer = buffer->next;
00370         FREE(buffer);
00371         buffer = next_buffer;
00372     }
00373 }
00374 
00375 void NanostackSocket::data_attach(NanostackBuffer *data_buf)
00376 {
00377     nanostack_assert_locked();
00378     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00379                 (SOCKET_MODE_STREAM == mode));
00380 
00381     // Add to linked list
00382     tr_debug("data_attach socket=%p", this);
00383     if (NULL == rxBufChain) {
00384         rxBufChain = data_buf;
00385     } else {
00386         NanostackBuffer *buf_tmp = rxBufChain;
00387         while (NULL != buf_tmp->next) {
00388             buf_tmp = buf_tmp->next;
00389         }
00390         buf_tmp->next = data_buf;
00391     }
00392     signal_event();
00393 }
00394 
00395 void NanostackSocket::event_data(socket_callback_t *sock_cb)
00396 {
00397     nanostack_assert_locked();
00398     MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
00399                 (SOCKET_MODE_STREAM == mode));
00400 
00401     // Allocate buffer
00402     NanostackBuffer *recv_buff = (NanostackBuffer *) MALLOC(
00403                                  sizeof(NanostackBuffer) + sock_cb->d_len);
00404     if (NULL == recv_buff) {
00405         tr_error("alloc failed!");
00406         return;
00407     }
00408     recv_buff->next = NULL;
00409 
00410     // Write data to buffer
00411     int16_t length = socket_read(sock_cb->socket_id,
00412                                  &recv_buff->ns_address, recv_buff->payload,
00413                                  sock_cb->d_len);
00414     if (length < 0) {
00415         tr_error("socket_read failed!");
00416         FREE(recv_buff);
00417         return;
00418     }
00419     recv_buff->length = length;
00420 
00421     data_attach(recv_buff);
00422 }
00423 
00424 void NanostackSocket::event_tx_done(socket_callback_t *sock_cb)
00425 {
00426     nanostack_assert_locked();
00427     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00428                 (SOCKET_MODE_DATAGRAM == mode));
00429 
00430     signal_event();
00431 }
00432 
00433 void NanostackSocket::event_bind_done(socket_callback_t *sock_cb)
00434 {
00435     nanostack_assert_locked();
00436     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00437 
00438     set_connected();
00439     signal_event();
00440 }
00441 
00442 void NanostackSocket::event_connnect_closed(socket_callback_t *sock_cb)
00443 {
00444     nanostack_assert_locked();
00445 
00446     // Only TCP sockets can be closed by the remote end
00447     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00448                 (SOCKET_MODE_CONNECTING == mode));
00449     close();
00450 }
00451 
00452 MeshInterfaceNanostack::MeshInterfaceNanostack()
00453     : phy(NULL), mesh_api(NULL), rf_device_id(-1), eui64(),
00454       ip_addr_str(), mac_addr_str(), connect_semaphore(0)
00455 {
00456     // Nothing to do
00457 }
00458 
00459 MeshInterfaceNanostack::MeshInterfaceNanostack(NanostackRfPhy *phy)
00460     : phy(phy), mesh_api(NULL), rf_device_id(-1), connect_semaphore(0)
00461 {
00462     // Nothing to do
00463 }
00464 
00465 nsapi_error_t MeshInterfaceNanostack::initialize(NanostackRfPhy *phy)
00466 {
00467     if (this->phy != NULL) {
00468         error("Phy already set");
00469     }
00470     this->phy = phy;
00471     return 0;
00472 }
00473 
00474 void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t status)
00475 {
00476     nanostack_lock();
00477 
00478     if (status == MESH_CONNECTED) {
00479         connect_semaphore.release();
00480     }
00481 
00482     nanostack_unlock();
00483 }
00484 
00485 nsapi_error_t MeshInterfaceNanostack::register_rf()
00486 {
00487     nanostack_lock();
00488 
00489     rf_device_id = phy->rf_register();
00490     if (rf_device_id < 0) {
00491         nanostack_unlock();
00492         return -1;
00493     }
00494     // Read mac address after registering the device.
00495     phy->get_mac_address(eui64);
00496     sprintf(mac_addr_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", eui64[0], eui64[1], eui64[2], eui64[3], eui64[4], eui64[5], eui64[6], eui64[7]);
00497 
00498     nanostack_unlock();
00499 
00500     return 0;
00501 }
00502 
00503 nsapi_error_t MeshInterfaceNanostack::actual_connect()
00504 {
00505     nanostack_assert_locked();
00506 
00507     mesh_error_t status = mesh_api->connect();
00508     if (status != MESH_ERROR_NONE) {
00509         nanostack_unlock();
00510         return map_mesh_error(status);
00511     }
00512 
00513     // Release mutex before blocking
00514     nanostack_unlock();
00515 
00516     int32_t count = connect_semaphore.wait(30000);
00517 
00518     nanostack_lock();
00519 
00520     if (count <= 0) {
00521         return NSAPI_ERROR_DHCP_FAILURE ; // sort of...
00522     }
00523     return 0;
00524 }
00525 
00526 NetworkStack * MeshInterfaceNanostack::get_stack()
00527 {
00528     return NanostackInterface::get_stack();
00529 }
00530 
00531 nsapi_error_t MeshInterfaceNanostack::disconnect()
00532 {
00533     nanostack_lock();
00534 
00535     mesh_error_t status = mesh_api->disconnect();
00536 
00537     nanostack_unlock();
00538 
00539     return map_mesh_error(status);
00540 }
00541 
00542 const char *MeshInterfaceNanostack::get_ip_address()
00543 {
00544     nanostack_lock();
00545 
00546     const char *ret = NULL;
00547     if (mesh_api && mesh_api->getOwnIpAddress(ip_addr_str, sizeof ip_addr_str)) {
00548         ret = ip_addr_str;
00549     }
00550 
00551     nanostack_unlock();
00552 
00553     return ret;
00554 }
00555 
00556 const char *MeshInterfaceNanostack::get_mac_address()
00557 {
00558     return mac_addr_str;
00559 }
00560 
00561 nsapi_error_t ThreadInterface::connect()
00562 {
00563     // initialize mesh networking resources, memory, timers, etc...
00564     mesh_system_init();
00565     nanostack_lock();
00566 
00567     mesh_api = MeshInterfaceFactory::createInterface(MESH_TYPE_THREAD);
00568     if (!mesh_api) {
00569         nanostack_unlock();
00570         return NSAPI_ERROR_NO_MEMORY ;
00571     }
00572     if (register_rf() < 0) {
00573         nanostack_unlock();
00574         return NSAPI_ERROR_DEVICE_ERROR ;
00575     }
00576 
00577     // After the RF is up, we can seed the random from it.
00578     randLIB_seed_random();
00579 
00580     mesh_error_t status = ((MeshThread *)mesh_api)->init(rf_device_id, AbstractMesh::mesh_network_handler_t(static_cast<MeshInterfaceNanostack *>(this), &ThreadInterface::mesh_network_handler), eui64, NULL);
00581     if (status != MESH_ERROR_NONE) {
00582         nanostack_unlock();
00583         return map_mesh_error(status);
00584     }
00585     nsapi_error_t ret = this->actual_connect();
00586 
00587     nanostack_unlock();
00588 
00589     return ret;
00590 }
00591 
00592 nsapi_error_t LoWPANNDInterface::connect()
00593 {
00594     // initialize mesh networking resources, memory, timers, etc...
00595     mesh_system_init();
00596     nanostack_lock();
00597 
00598     mesh_api = MeshInterfaceFactory::createInterface(MESH_TYPE_6LOWPAN_ND);
00599     if (!mesh_api) {
00600         nanostack_unlock();
00601         return NSAPI_ERROR_NO_MEMORY ;
00602     }
00603     if (register_rf() < 0) {
00604         nanostack_unlock();
00605         return NSAPI_ERROR_DEVICE_ERROR ;
00606     }
00607 
00608     // After the RF is up, we can seed the random from it.
00609     randLIB_seed_random();
00610 
00611     mesh_error_t status = ((Mesh6LoWPAN_ND *)mesh_api)->init(rf_device_id, AbstractMesh::mesh_network_handler_t(static_cast<MeshInterfaceNanostack *>(this), &LoWPANNDInterface::mesh_network_handler));
00612     if (status != MESH_ERROR_NONE) {
00613         nanostack_unlock();
00614         return map_mesh_error(status);
00615     }
00616     nsapi_error_t ret = this->actual_connect();
00617 
00618     nanostack_unlock();
00619 
00620     return ret;
00621 }
00622 
00623 NanostackInterface * NanostackInterface::_ns_interface;
00624 
00625 NanostackInterface * NanostackInterface::get_stack()
00626 {
00627     nanostack_lock();
00628 
00629     if (NULL == _ns_interface) {
00630         _ns_interface = new NanostackInterface();
00631     }
00632 
00633     nanostack_unlock();
00634 
00635     return _ns_interface;
00636 }
00637 
00638 
00639 const char * NanostackInterface::get_ip_address()
00640 {
00641     // Unsupported
00642     return NULL;
00643 }
00644 
00645 nsapi_error_t NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol)
00646 {
00647     // Validate parameters
00648     if (NULL == handle) {
00649         MBED_ASSERT(false);
00650         return NSAPI_ERROR_NO_SOCKET ;
00651     }
00652     int8_t ns_proto;
00653     if (NSAPI_UDP  == protocol) {
00654         ns_proto = SOCKET_UDP;
00655     } else if (NSAPI_TCP  == protocol) {
00656         ns_proto = SOCKET_TCP;
00657     } else {
00658         MBED_ASSERT(false);
00659         return NSAPI_ERROR_UNSUPPORTED ;
00660     }
00661     *handle = (void*)NULL;
00662 
00663     nanostack_lock();
00664 
00665     NanostackSocket * socket = new NanostackSocket(ns_proto);
00666     if (NULL == socket) {
00667         nanostack_unlock();
00668         tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY );
00669         return NSAPI_ERROR_NO_MEMORY ;
00670     }
00671     if (!socket->open()) {
00672         delete socket;
00673         nanostack_unlock();
00674         tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR );
00675         return NSAPI_ERROR_DEVICE_ERROR ;
00676     }
00677     *handle = (void*)socket;
00678 
00679     nanostack_unlock();
00680 
00681     tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);
00682 
00683     return 0;
00684 }
00685 
00686 nsapi_error_t NanostackInterface::socket_close(void *handle)
00687 {
00688     // Validate parameters
00689     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00690     if (NULL == handle) {
00691         MBED_ASSERT(false);
00692         return NSAPI_ERROR_NO_SOCKET ;
00693     }
00694     tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id);
00695 
00696     nanostack_lock();
00697 
00698     delete socket;
00699 
00700     nanostack_unlock();
00701 
00702     return 0;
00703 
00704 }
00705 
00706 nsapi_size_or_error_t NanostackInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, nsapi_size_t size)
00707 {
00708     // Validate parameters
00709     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00710     if (NULL == handle) {
00711         MBED_ASSERT(false);
00712         return NSAPI_ERROR_NO_SOCKET ;
00713     }
00714 
00715     if (address.get_ip_version() != NSAPI_IPv6 ) {
00716         return NSAPI_ERROR_UNSUPPORTED ;
00717     }
00718 
00719     nanostack_lock();
00720 
00721     nsapi_size_or_error_t ret;
00722     if (socket->closed()) {
00723         ret = NSAPI_ERROR_NO_CONNECTION ;
00724     } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
00725         tr_error("socket_sendto() not supported with SOCKET_STREAM!");
00726         ret = NSAPI_ERROR_UNSUPPORTED ;
00727     } else {
00728         ns_address_t ns_address;
00729         convert_mbed_addr_to_ns(&ns_address, &address);
00730         if (!socket->is_bound()) {
00731             socket->set_bound();
00732         }
00733         int8_t send_to_status = ::socket_sendto(socket->socket_id, &ns_address,
00734                                        (uint8_t *)data, size);
00735         /*
00736          * \return 0 on success.
00737          * \return -1 invalid socket id.
00738          * \return -2 Socket memory allocation fail.
00739          * \return -3 TCP state not established.
00740          * \return -4 Socket tx process busy.
00741          * \return -5 TLS authentication not ready.
00742          * \return -6 Packet too short.
00743          * */
00744         if (-4 == send_to_status) {
00745             ret = NSAPI_ERROR_WOULD_BLOCK ;
00746         } else if (0 != send_to_status) {
00747             tr_error("socket_sendto: error=%d", send_to_status);
00748             ret = NSAPI_ERROR_DEVICE_ERROR ;
00749         } else {
00750             ret = size;
00751         }
00752     }
00753 
00754     nanostack_unlock();
00755 
00756     tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00757 
00758     return ret;
00759 }
00760 
00761 nsapi_size_or_error_t NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size)
00762 {
00763     // Validate parameters
00764     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00765     if (NULL == handle) {
00766         MBED_ASSERT(false);
00767         return NSAPI_ERROR_NO_SOCKET ;
00768     }
00769     if (NULL == buffer) {
00770         MBED_ASSERT(false);
00771         return NSAPI_ERROR_PARAMETER ;
00772     }
00773     if (0 == size) {
00774         MBED_ASSERT(false);
00775         return NSAPI_ERROR_PARAMETER ;
00776     }
00777 
00778     nanostack_lock();
00779 
00780     nsapi_size_or_error_t ret;
00781     if (socket->closed()) {
00782         ret = NSAPI_ERROR_NO_CONNECTION ;
00783     } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
00784         tr_error("recv_from() not supported with SOCKET_STREAM!");
00785         ret = NSAPI_ERROR_UNSUPPORTED ;
00786     } else if (!socket->data_available()) {
00787         ret = NSAPI_ERROR_WOULD_BLOCK ;
00788     } else {
00789         ret = socket->data_copy_and_free(buffer, size, address, false);
00790     }
00791 
00792     nanostack_unlock();
00793 
00794     tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00795 
00796     return ret;
00797 }
00798 
00799 nsapi_error_t NanostackInterface::socket_bind(void *handle, const SocketAddress &address)
00800 {
00801     // Validate parameters
00802     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00803     if (NULL == handle) {
00804         MBED_ASSERT(false);
00805         return NSAPI_ERROR_NO_SOCKET ;
00806     }
00807 
00808     const void *addr_field;
00809     switch (address.get_ip_version()) {
00810         case NSAPI_IPv6 :
00811             addr_field = address.get_ip_bytes();
00812             break;
00813         case NSAPI_UNSPEC :
00814             addr_field = &ns_in6addr_any;
00815             break;
00816         default:
00817             return NSAPI_ERROR_UNSUPPORTED ;
00818     }
00819 
00820     nanostack_lock();
00821 
00822     ns_address_t ns_address;
00823     ns_address.type = ADDRESS_IPV6;
00824     memcpy(ns_address.address, addr_field, sizeof ns_address.address);
00825     ns_address.identifier = address.get_port();
00826     nsapi_error_t ret = NSAPI_ERROR_DEVICE_ERROR ;
00827     if (0 == ::socket_bind(socket->socket_id, &ns_address)) {
00828         socket->set_bound();
00829         ret = 0;
00830     }
00831 
00832     nanostack_unlock();
00833 
00834     tr_debug("socket_bind(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00835 
00836     return ret;
00837 }
00838 
00839 nsapi_error_t NanostackInterface::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
00840 {
00841     return NSAPI_ERROR_UNSUPPORTED ;
00842 }
00843 
00844 nsapi_error_t NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
00845 {
00846     return NSAPI_ERROR_UNSUPPORTED ;
00847 }
00848 
00849 nsapi_error_t NanostackInterface::socket_listen(void *handle, int backlog)
00850 {
00851     return NSAPI_ERROR_UNSUPPORTED ;
00852 }
00853 
00854 nsapi_error_t NanostackInterface::socket_connect(void *handle, const SocketAddress &addr)
00855 {
00856     // Validate parameters
00857     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00858     if (NULL == handle) {
00859         MBED_ASSERT(false);
00860         return NSAPI_ERROR_NO_SOCKET ;
00861     }
00862 
00863     if (addr.get_ip_version() != NSAPI_IPv6 ) {
00864         return NSAPI_ERROR_UNSUPPORTED ;
00865     }
00866 
00867     nanostack_lock();
00868 
00869     nsapi_error_t ret;
00870     ns_address_t ns_addr;
00871     int random_port = socket->is_bound() ? 0 : 1;
00872     convert_mbed_addr_to_ns(&ns_addr, &addr);
00873     if (0 == ::socket_connect(socket->socket_id, &ns_addr, random_port)) {
00874         socket->set_connecting(&ns_addr);
00875         ret = 0;
00876     } else {
00877         ret = NSAPI_ERROR_DEVICE_ERROR ;
00878     }
00879 
00880     nanostack_unlock();
00881 
00882     tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00883 
00884     return ret;
00885 }
00886 
00887 nsapi_error_t NanostackInterface::socket_accept(void *server, void **handle, SocketAddress *address)
00888 {
00889     return NSAPI_ERROR_UNSUPPORTED ;
00890 }
00891 
00892 nsapi_size_or_error_t NanostackInterface::socket_send(void *handle, const void *p, nsapi_size_t size)
00893 {
00894     // Validate parameters
00895     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00896     if (NULL == handle) {
00897         MBED_ASSERT(false);
00898         return NSAPI_ERROR_NO_SOCKET ;
00899     }
00900 
00901     nanostack_lock();
00902 
00903     nsapi_size_or_error_t ret;
00904     if (socket->closed()) {
00905         ret = NSAPI_ERROR_NO_CONNECTION ;
00906     } else if (socket->is_connecting()) {
00907         ret = NSAPI_ERROR_WOULD_BLOCK ;
00908     } else {
00909         ret = ::socket_sendto(socket->socket_id,  &socket->ns_address, (uint8_t*)p, size);
00910         /*
00911          * \return 0 on success.
00912          * \return -1 invalid socket id.
00913          * \return -2 Socket memory allocation fail.
00914          * \return -3 TCP state not established.
00915          * \return -4 Socket tx process busy.
00916          * \return -5 TLS authentication not ready.
00917          * \return -6 Packet too short.
00918          * */
00919         if (-4 == ret) {
00920             ret = NSAPI_ERROR_WOULD_BLOCK ;
00921         } else if (ret != 0) {
00922             tr_warning("socket_sendto ret %i, socket_id %i", ret, socket->socket_id);
00923             ret = NSAPI_ERROR_DEVICE_ERROR ;
00924         } else {
00925             ret = size;
00926         }
00927     }
00928 
00929     nanostack_unlock();
00930 
00931     tr_debug("socket_send(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00932 
00933     return ret;
00934 }
00935 
00936 nsapi_size_or_error_t NanostackInterface::socket_recv(void *handle, void *data, nsapi_size_t size)
00937 {
00938     // Validate parameters
00939     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00940     if (NULL == handle) {
00941         MBED_ASSERT(false);
00942         return NSAPI_ERROR_NO_SOCKET ;
00943     }
00944 
00945     nanostack_lock();
00946 
00947     nsapi_size_or_error_t ret;
00948     if (socket->closed()) {
00949         ret = NSAPI_ERROR_NO_CONNECTION ;
00950     } else if (socket->data_available()) {
00951         ret = socket->data_copy_and_free(data, size, NULL, true);
00952     } else {
00953         ret = NSAPI_ERROR_WOULD_BLOCK ;
00954     }
00955 
00956     nanostack_unlock();
00957 
00958     tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00959 
00960     return ret;
00961 }
00962 
00963 void NanostackInterface::socket_attach(void *handle, void (*callback)(void *), void *id)
00964 {
00965     // Validate parameters
00966     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00967     if (NULL == handle) {
00968         MBED_ASSERT(false);
00969         return;
00970     }
00971 
00972     nanostack_lock();
00973 
00974     socket->callback = callback;
00975     socket->callback_data = id;
00976 
00977     nanostack_unlock();
00978 
00979     tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id);
00980 }