joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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