Rizky Ardi Maulana / mbed-os
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 #include "ip6string.h"
00032 // Uncomment to enable trace
00033 //#define HAVE_DEBUG
00034 #include "ns_trace.h"
00035 #define TRACE_GROUP "nsif"
00036 
00037 #define NS_INTERFACE_SOCKETS_MAX  16  //same as NanoStack SOCKET_MAX
00038 #define NANOSTACK_SOCKET_UDP 17 // same as nanostack SOCKET_UDP
00039 #define NANOSTACK_SOCKET_TCP 6  // same as nanostack SOCKET_TCP
00040 
00041 #define MALLOC  ns_dyn_mem_alloc
00042 #define FREE    ns_dyn_mem_free
00043 
00044 #define nanostack_lock()            eventOS_scheduler_mutex_wait()
00045 #define nanostack_unlock()          eventOS_scheduler_mutex_release()
00046 #define nanostack_assert_locked()   //MBED_ASSERT(eventOS_scheduler_mutex_is_owner())
00047 
00048 enum socket_mode_t {
00049     SOCKET_MODE_UNOPENED,   // No socket ID
00050     SOCKET_MODE_OPENED,     // Socket ID but no assigned use yet
00051     SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet
00052     SOCKET_MODE_DATAGRAM,   // Socket is bound to a port and listening for datagrams
00053     SOCKET_MODE_STREAM,     // Socket has an open stream
00054     SOCKET_MODE_CLOSED,     // Socket is closed and resources are freed
00055 };
00056 
00057 class NanostackBuffer {
00058 public:
00059     NanostackBuffer *next;      /*<! next buffer */
00060     ns_address_t ns_address;    /*<! address where data is received */
00061     uint16_t length;            /*<! data length in this buffer */
00062     uint8_t payload[1];          /*<! Trailing buffer data */
00063 };
00064 
00065 class NanostackSocket {
00066 public:
00067     static void socket_callback(void *cb);
00068     static void* operator new(std::size_t sz);
00069     static void operator delete(void* ptr);
00070 
00071     NanostackSocket(int8_t protocol);
00072     ~NanostackSocket(void);
00073     bool open(void);
00074     void close(void);
00075     bool closed(void) {return SOCKET_MODE_CLOSED == mode;}
00076     bool is_bound(void);
00077     void set_bound(void);
00078     bool is_connecting(void);
00079     void set_connecting(ns_address_t *addr);
00080     void set_connected(void);
00081 
00082     // Socket events from nanostack
00083     void event_data(socket_callback_t *sock_cb);
00084     void event_bind_done(socket_callback_t *sock_cb);
00085     void event_connnect_closed(socket_callback_t *sock_cb);
00086     void event_tx_done(socket_callback_t *sock_cb);
00087 
00088     // Run callback to signal the next layer of the NSAPI
00089     void signal_event(void);
00090 
00091     // Add or remove a socket to the listening socket
00092     void accept_list_add(NanostackSocket *socket);
00093     NanostackSocket * accept_list_remove(void);
00094 
00095     bool data_available(void);
00096     size_t data_copy_and_free(void *dest, size_t len, SocketAddress *address, bool stream);
00097     void data_free_all(void);
00098     void data_attach(NanostackBuffer *data_buf);
00099 
00100     void (*callback)(void *);
00101     void *callback_data;
00102     int8_t socket_id;           /*!< allocated socket ID */
00103     int8_t proto;               /*!< UDP or TCP */
00104     bool addr_valid;
00105     ns_address_t ns_address;
00106 private:
00107     NanostackBuffer *rxBufChain;    /*!< Receive buffers */
00108     socket_mode_t mode;
00109 };
00110 
00111 static NanostackSocket * socket_tbl[NS_INTERFACE_SOCKETS_MAX];
00112 
00113 static int map_mesh_error(mesh_error_t err)
00114 {
00115     switch (err) {
00116         case MESH_ERROR_NONE: return 0;
00117         case MESH_ERROR_MEMORY: return NSAPI_ERROR_NO_MEMORY ;
00118         case MESH_ERROR_PARAM: return NSAPI_ERROR_UNSUPPORTED ;
00119         case MESH_ERROR_STATE: return NSAPI_ERROR_DEVICE_ERROR ;
00120         default: return NSAPI_ERROR_DEVICE_ERROR ;
00121     }
00122 }
00123 
00124 static void convert_mbed_addr_to_ns(ns_address_t *ns_addr,
00125                              const SocketAddress *s_addr)
00126 {
00127     ns_addr->type = ADDRESS_IPV6;
00128     ns_addr->identifier = s_addr->get_port();
00129     const char *str = s_addr->get_ip_address();
00130     stoip6(str, strlen(str), ns_addr->address);
00131 }
00132 
00133 static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *ns_addr)
00134 {
00135     char str[40];
00136     ip6tos(ns_addr->address, str);
00137     s_addr->set_port(ns_addr->identifier);
00138     s_addr->set_ip_address(str);
00139 }
00140 
00141 void* NanostackSocket::operator new(std::size_t sz) {
00142     return MALLOC(sz);
00143 }
00144 void NanostackSocket::operator delete(void* ptr) {
00145     FREE(ptr);
00146 }
00147 
00148 NanostackSocket::NanostackSocket(int8_t protocol)
00149 {
00150     nanostack_assert_locked();
00151 
00152     callback = NULL;
00153     callback_data = NULL;
00154     socket_id = -1;
00155     rxBufChain = NULL;
00156     proto = protocol;
00157     addr_valid = false;
00158     memset(&ns_address, 0, sizeof(ns_address));
00159     mode = SOCKET_MODE_UNOPENED;
00160 }
00161 
00162 NanostackSocket::~NanostackSocket()
00163 {
00164     nanostack_assert_locked();
00165 
00166     if (mode != SOCKET_MODE_CLOSED) {
00167         close();
00168     }
00169     if (socket_id >= 0) {
00170         int ret = socket_free(socket_id);
00171         MBED_ASSERT(0 == ret);
00172         MBED_ASSERT(socket_tbl[socket_id] == this);
00173         socket_tbl[socket_id] = NULL;
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 MeshInterfaceNanostack::MeshInterfaceNanostack()
00457     : phy(NULL), mesh_api(NULL), rf_device_id(-1), eui64(),
00458       ip_addr_str(), mac_addr_str(), connect_semaphore(0)
00459 {
00460     // Nothing to do
00461 }
00462 
00463 MeshInterfaceNanostack::MeshInterfaceNanostack(NanostackRfPhy *phy)
00464     : phy(phy), mesh_api(NULL), rf_device_id(-1), connect_semaphore(0)
00465 {
00466     // Nothing to do
00467 }
00468 
00469 int MeshInterfaceNanostack::initialize(NanostackRfPhy *phy)
00470 {
00471     if (this->phy != NULL) {
00472         error("Phy already set");
00473     }
00474     this->phy = phy;
00475     return 0;
00476 }
00477 
00478 void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t status)
00479 {
00480     nanostack_lock();
00481 
00482     if (status == MESH_CONNECTED) {
00483         connect_semaphore.release();
00484     }
00485 
00486     nanostack_unlock();
00487 }
00488 
00489 int MeshInterfaceNanostack::register_rf()
00490 {
00491     nanostack_lock();
00492 
00493     rf_device_id = phy->rf_register();
00494     if (rf_device_id < 0) {
00495         nanostack_unlock();
00496         return -1;
00497     }
00498     // Read mac address after registering the device.
00499     phy->get_mac_address(eui64);
00500     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]);
00501 
00502     nanostack_unlock();
00503 
00504     return 0;
00505 }
00506 
00507 int MeshInterfaceNanostack::actual_connect()
00508 {
00509     nanostack_assert_locked();
00510 
00511     mesh_error_t status = mesh_api->connect();
00512     if (status != MESH_ERROR_NONE) {
00513         nanostack_unlock();
00514         return map_mesh_error(status);
00515     }
00516 
00517     // Release mutex before blocking
00518     nanostack_unlock();
00519 
00520     int32_t count = connect_semaphore.wait(30000);
00521 
00522     nanostack_lock();
00523 
00524     if (count <= 0) {
00525         return NSAPI_ERROR_DHCP_FAILURE ; // sort of...
00526     }
00527     return 0;
00528 }
00529 
00530 NetworkStack * MeshInterfaceNanostack::get_stack()
00531 {
00532     return NanostackInterface::get_stack();
00533 }
00534 
00535 int MeshInterfaceNanostack::disconnect()
00536 {
00537     nanostack_lock();
00538 
00539     mesh_error_t status = mesh_api->disconnect();
00540 
00541     nanostack_unlock();
00542 
00543     return map_mesh_error(status);
00544 }
00545 
00546 const char *MeshInterfaceNanostack::get_ip_address()
00547 {
00548     nanostack_lock();
00549 
00550     const char *ret = NULL;
00551     if (mesh_api && mesh_api->getOwnIpAddress(ip_addr_str, sizeof ip_addr_str)) {
00552         ret = ip_addr_str;
00553     }
00554 
00555     nanostack_unlock();
00556 
00557     return ret;
00558 }
00559 
00560 const char *MeshInterfaceNanostack::get_mac_address()
00561 {
00562     return mac_addr_str;
00563 }
00564 
00565 int ThreadInterface::connect()
00566 {
00567     // initialize mesh networking resources, memory, timers, etc...
00568     mesh_system_init();
00569     nanostack_lock();
00570 
00571     mesh_api = MeshInterfaceFactory::createInterface(MESH_TYPE_THREAD);
00572     if (!mesh_api) {
00573         nanostack_unlock();
00574         return NSAPI_ERROR_NO_MEMORY ;
00575     }
00576     if (register_rf() < 0) {
00577         nanostack_unlock();
00578         return NSAPI_ERROR_DEVICE_ERROR ;
00579     }
00580 
00581     // After the RF is up, we can seed the random from it.
00582     randLIB_seed_random();
00583 
00584     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);
00585     if (status != MESH_ERROR_NONE) {
00586         nanostack_unlock();
00587         return map_mesh_error(status);
00588     }
00589     int ret = this->actual_connect();
00590 
00591     nanostack_unlock();
00592 
00593     return ret;
00594 }
00595 
00596 int LoWPANNDInterface::connect()
00597 {
00598     // initialize mesh networking resources, memory, timers, etc...
00599     mesh_system_init();
00600     nanostack_lock();
00601 
00602     mesh_api = MeshInterfaceFactory::createInterface(MESH_TYPE_6LOWPAN_ND);
00603     if (!mesh_api) {
00604         nanostack_unlock();
00605         return NSAPI_ERROR_NO_MEMORY ;
00606     }
00607     if (register_rf() < 0) {
00608         nanostack_unlock();
00609         return NSAPI_ERROR_DEVICE_ERROR ;
00610     }
00611 
00612     // After the RF is up, we can seed the random from it.
00613     randLIB_seed_random();
00614 
00615     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));
00616     if (status != MESH_ERROR_NONE) {
00617         nanostack_unlock();
00618         return map_mesh_error(status);
00619     }
00620     int ret = this->actual_connect();
00621 
00622     nanostack_unlock();
00623 
00624     return ret;
00625 }
00626 
00627 NanostackInterface * NanostackInterface::_ns_interface;
00628 
00629 NanostackInterface * NanostackInterface::get_stack()
00630 {
00631     nanostack_lock();
00632 
00633     if (NULL == _ns_interface) {
00634         _ns_interface = new NanostackInterface();
00635     }
00636 
00637     nanostack_unlock();
00638 
00639     return _ns_interface;
00640 }
00641 
00642 
00643 const char * NanostackInterface::get_ip_address()
00644 {
00645     // Unsupported
00646     return NULL;
00647 }
00648 
00649 int NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol)
00650 {
00651     // Validate parameters
00652     if (NULL == handle) {
00653         MBED_ASSERT(false);
00654         return NSAPI_ERROR_NO_SOCKET ;
00655     }
00656     int8_t ns_proto;
00657     if (NSAPI_UDP  == protocol) {
00658         ns_proto = SOCKET_UDP;
00659     } else if (NSAPI_TCP  == protocol) {
00660         ns_proto = SOCKET_TCP;
00661     } else {
00662         MBED_ASSERT(false);
00663         return NSAPI_ERROR_UNSUPPORTED ;
00664     }
00665     *handle = (void*)NULL;
00666 
00667     nanostack_lock();
00668 
00669     NanostackSocket * socket = new NanostackSocket(ns_proto);
00670     if (NULL == socket) {
00671         nanostack_unlock();
00672         tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY );
00673         return NSAPI_ERROR_NO_MEMORY ;
00674     }
00675     if (!socket->open()) {
00676         delete socket;
00677         nanostack_unlock();
00678         tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR );
00679         return NSAPI_ERROR_DEVICE_ERROR ;
00680     }
00681     *handle = (void*)socket;
00682 
00683     nanostack_unlock();
00684 
00685     tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);
00686 
00687     return 0;
00688 }
00689 
00690 int NanostackInterface::socket_close(void *handle)
00691 {
00692     // Validate parameters
00693     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00694     if (NULL == handle) {
00695         MBED_ASSERT(false);
00696         return NSAPI_ERROR_NO_SOCKET ;
00697     }
00698     tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id);
00699 
00700     nanostack_lock();
00701 
00702     delete socket;
00703 
00704     nanostack_unlock();
00705 
00706     return 0;
00707 
00708 }
00709 
00710 int NanostackInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned int size)
00711 {
00712     // Validate parameters
00713     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00714     if (NULL == handle) {
00715         MBED_ASSERT(false);
00716         return NSAPI_ERROR_NO_SOCKET ;
00717     }
00718 
00719     nanostack_lock();
00720 
00721     int 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 int NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned 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     int 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 int 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 
00809     nanostack_lock();
00810 
00811     ns_address_t ns_address;
00812     ns_address.type = ADDRESS_IPV6;
00813     memset(ns_address.address, 0, sizeof ns_address.address);
00814     ns_address.identifier = address.get_port();
00815     int ret = NSAPI_ERROR_DEVICE_ERROR ;
00816     if (0 == ::socket_bind(socket->socket_id, &ns_address)) {
00817         socket->set_bound();
00818         ret = 0;
00819     }
00820 
00821     nanostack_unlock();
00822 
00823     tr_debug("socket_bind(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00824 
00825     return ret;
00826 }
00827 
00828 int NanostackInterface::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
00829 {
00830     return NSAPI_ERROR_UNSUPPORTED ;
00831 }
00832 
00833 int NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
00834 {
00835     return NSAPI_ERROR_UNSUPPORTED ;
00836 }
00837 
00838 int NanostackInterface::socket_listen(void *handle, int backlog)
00839 {
00840     return NSAPI_ERROR_UNSUPPORTED ;
00841 }
00842 
00843 int NanostackInterface::socket_connect(void *handle, const SocketAddress &addr)
00844 {
00845     // Validate parameters
00846     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00847     if (NULL == handle) {
00848         MBED_ASSERT(false);
00849         return NSAPI_ERROR_NO_SOCKET ;
00850     }
00851 
00852     nanostack_lock();
00853 
00854     int ret;
00855     ns_address_t ns_addr;
00856     int random_port = socket->is_bound() ? 0 : 1;
00857     convert_mbed_addr_to_ns(&ns_addr, &addr);
00858     if (0 == ::socket_connect(socket->socket_id, &ns_addr, random_port)) {
00859         socket->set_connecting(&ns_addr);
00860         ret = 0;
00861     } else {
00862         ret = NSAPI_ERROR_DEVICE_ERROR ;
00863     }
00864 
00865     nanostack_unlock();
00866 
00867     tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00868 
00869     return ret;
00870 }
00871 
00872 int NanostackInterface::socket_accept(void *server, void **handle, SocketAddress *address)
00873 {
00874     return NSAPI_ERROR_UNSUPPORTED ;
00875 }
00876 
00877 int NanostackInterface::socket_send(void *handle, const void *p, unsigned size)
00878 {
00879     // Validate parameters
00880     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00881     if (NULL == handle) {
00882         MBED_ASSERT(false);
00883         return NSAPI_ERROR_NO_SOCKET ;
00884     }
00885 
00886     nanostack_lock();
00887 
00888     int ret;
00889     if (socket->closed()) {
00890         ret = NSAPI_ERROR_NO_CONNECTION ;
00891     } else if (socket->is_connecting()) {
00892         ret = NSAPI_ERROR_WOULD_BLOCK ;
00893     } else {
00894         ret = ::socket_sendto(socket->socket_id,  &socket->ns_address, (uint8_t*)p, size);
00895         /*
00896          * \return 0 on success.
00897          * \return -1 invalid socket id.
00898          * \return -2 Socket memory allocation fail.
00899          * \return -3 TCP state not established.
00900          * \return -4 Socket tx process busy.
00901          * \return -5 TLS authentication not ready.
00902          * \return -6 Packet too short.
00903          * */
00904         if (-4 == ret) {
00905             ret = NSAPI_ERROR_WOULD_BLOCK ;
00906         } else if (ret != 0) {
00907             tr_warning("socket_sendto ret %i, socket_id %i", ret, socket->socket_id);
00908             ret = NSAPI_ERROR_DEVICE_ERROR ;
00909         } else {
00910             ret = size;
00911         }
00912     }
00913 
00914     nanostack_unlock();
00915 
00916     tr_debug("socket_send(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00917 
00918     return ret;
00919 }
00920 
00921 int NanostackInterface::socket_recv(void *handle, void *data, unsigned size)
00922 {
00923     // Validate parameters
00924     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00925     if (NULL == handle) {
00926         MBED_ASSERT(false);
00927         return NSAPI_ERROR_NO_SOCKET ;
00928     }
00929 
00930     nanostack_lock();
00931 
00932     int ret;
00933     if (socket->closed()) {
00934         ret = NSAPI_ERROR_NO_CONNECTION ;
00935     } else if (socket->data_available()) {
00936         ret = socket->data_copy_and_free(data, size, NULL, true);
00937     } else {
00938         ret = NSAPI_ERROR_WOULD_BLOCK ;
00939     }
00940 
00941     nanostack_unlock();
00942 
00943     tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00944 
00945     return ret;
00946 }
00947 
00948 void NanostackInterface::socket_attach(void *handle, void (*callback)(void *), void *id)
00949 {
00950     // Validate parameters
00951     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00952     if (NULL == handle) {
00953         MBED_ASSERT(false);
00954         return;
00955     }
00956 
00957     nanostack_lock();
00958 
00959     socket->callback = callback;
00960     socket->callback_data = id;
00961 
00962     nanostack_unlock();
00963 
00964     tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id);
00965 }