Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Nanostack.cpp Source File

Nanostack.cpp

00001 /*
00002  * Copyright (c) 2016-2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /* Nanostack implementation of NetworkSocketAPI */
00019 
00020 #include "mbed.h"
00021 #include "rtos.h"
00022 #include "Nanostack.h"
00023 #include "NanostackLockGuard.h"
00024 
00025 #include "ns_address.h"
00026 #include "nsdynmemLIB.h"
00027 #include "eventOS_scheduler.h"
00028 #include "eventOS_event_timer.h"
00029 #include "randLIB.h"
00030 #include "ip6string.h"
00031 
00032 #include "mesh_system.h" // from inside mbed-mesh-api
00033 #include "socket_api.h"
00034 #include "net_interface.h"
00035 
00036 // Uncomment to enable trace
00037 //#define HAVE_DEBUG
00038 #include "ns_trace.h"
00039 #define TRACE_GROUP "nsif"
00040 
00041 #define NS_INTERFACE_SOCKETS_MAX  16  //same as NanoStack SOCKET_MAX
00042 
00043 #define MALLOC  ns_dyn_mem_alloc
00044 #define FREE    ns_dyn_mem_free
00045 
00046 // Socket state progressions:
00047 // UDP: UNOPENED -> DATAGRAM
00048 // TCP client: UNOPENED -> OPENED -> CONNECTING -> STREAM -> CLOSED
00049 // TCP server: UNOPENED -> OPENED -> LISTENING
00050 // TCP accept: UNOPENED -> STREAM -> CLOSED
00051 enum socket_mode_t {
00052     SOCKET_MODE_UNOPENED,   // No socket ID
00053     SOCKET_MODE_DATAGRAM,   // Socket is datagram type
00054     SOCKET_MODE_OPENED,     // Socket ID but no assigned use yet
00055     SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet
00056     SOCKET_MODE_STREAM,     // Socket has an open stream
00057     SOCKET_MODE_CLOSED,     // Socket is closed and resources are freed
00058     SOCKET_MODE_LISTENING,  // Socket is listening for connections
00059 };
00060 
00061 #define CALL_EVENT   0x12
00062 
00063 class NanostackSocket {
00064 public:
00065     static void socket_callback(void *cb);
00066     static void* operator new(std::size_t sz);
00067     static void operator delete(void* ptr);
00068 
00069     NanostackSocket(int8_t protocol);
00070     ~NanostackSocket(void);
00071     bool open(void);
00072     int accept(NanostackSocket *accepted_socket, ns_address_t *addr);
00073     void close(void);
00074     bool closed(void) {return SOCKET_MODE_CLOSED == mode;}
00075     bool is_connecting(void);
00076     void set_connecting(ns_address_t *addr);
00077     bool is_connected(void);
00078     void set_connected(void);
00079     bool is_listening(void);
00080     void set_listening(void);
00081 
00082     // Socket events from nanostack
00083     void event_data(socket_callback_t *sock_cb);
00084     void event_connect_done(socket_callback_t *sock_cb);
00085     void event_connect_fail(socket_callback_t *sock_cb);
00086     void event_connect_closed(socket_callback_t *sock_cb);
00087     void event_connection_reset(socket_callback_t *sock_cb);
00088     void event_tx_done(socket_callback_t *sock_cb);
00089     void event_tx_fail(socket_callback_t *sock_cb);
00090     void event_incoming_connection(socket_callback_t *sock_cb);
00091 
00092     // Run callback to signal the next layer of the NSAPI
00093     void signal_event(void);
00094 
00095     void (*callback)(void *);
00096     void *callback_data;
00097     int8_t socket_id;           /*!< allocated socket ID */
00098     int8_t proto;               /*!< UDP or TCP */
00099     bool addr_valid;
00100     ns_address_t ns_address;
00101 private:
00102     bool attach(int8_t socket_id);
00103     socket_mode_t mode;
00104 };
00105 
00106 static NanostackSocket * socket_tbl[NS_INTERFACE_SOCKETS_MAX];
00107 
00108 nsapi_error_t map_mesh_error(mesh_error_t err)
00109 {
00110     switch (err) {
00111         case MESH_ERROR_NONE: return 0;
00112         case MESH_ERROR_MEMORY: return NSAPI_ERROR_NO_MEMORY ;
00113         case MESH_ERROR_PARAM: return NSAPI_ERROR_UNSUPPORTED ;
00114         case MESH_ERROR_STATE: return NSAPI_ERROR_DEVICE_ERROR ;
00115         default: return NSAPI_ERROR_DEVICE_ERROR ;
00116     }
00117 }
00118 
00119 static void convert_mbed_addr_to_ns(ns_address_t *ns_addr,
00120                              const SocketAddress *s_addr)
00121 {
00122     ns_addr->type = ADDRESS_IPV6;
00123     ns_addr->identifier = s_addr->get_port();
00124     memcpy(ns_addr->address, s_addr->get_ip_bytes(), 16);
00125 }
00126 
00127 static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *ns_addr)
00128 {
00129     s_addr->set_port(ns_addr->identifier);
00130     s_addr->set_ip_bytes(ns_addr->address, NSAPI_IPv6 );
00131 }
00132 
00133 static int8_t find_interface_by_address(const uint8_t target_addr[16])
00134 {
00135     for (int if_id = 1; if_id <= 127; if_id++) {
00136         int i = 0;
00137         uint8_t if_addr[16];
00138         while (arm_net_address_list_get_next(if_id, &i, if_addr) == 0) {
00139             if (memcmp(target_addr, if_addr, 16) == 0) {
00140                 return if_id;
00141             }
00142         }
00143     }
00144     return -1;
00145 }
00146 
00147 void* NanostackSocket::operator new(std::size_t sz) {
00148     return MALLOC(sz);
00149 }
00150 void NanostackSocket::operator delete(void* ptr) {
00151     FREE(ptr);
00152 }
00153 
00154 NanostackSocket::NanostackSocket(int8_t protocol)
00155 {
00156     nanostack_assert_locked();
00157 
00158     callback = NULL;
00159     callback_data = NULL;
00160     socket_id = -1;
00161     proto = protocol;
00162     addr_valid = false;
00163     memset(&ns_address, 0, sizeof(ns_address));
00164     mode = SOCKET_MODE_UNOPENED;
00165 }
00166 
00167 NanostackSocket::~NanostackSocket()
00168 {
00169     nanostack_assert_locked();
00170 
00171     if (mode != SOCKET_MODE_CLOSED) {
00172         close();
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 
00188     if (proto == SOCKET_TCP) {
00189         /* Receive and send buffers enabled by default */
00190         mode = SOCKET_MODE_OPENED;
00191     } else {
00192         static const int32_t rcvbuf_size = 2048;
00193         socket_setsockopt(temp_socket, SOCKET_SOL_SOCKET, SOCKET_SO_RCVBUF, &rcvbuf_size, sizeof rcvbuf_size);
00194         mode = SOCKET_MODE_DATAGRAM;
00195     }
00196 
00197     return attach(temp_socket);
00198 }
00199 
00200 int NanostackSocket::accept(NanostackSocket *accepted_socket, ns_address_t *addr)
00201 {
00202     nanostack_assert_locked();
00203     MBED_ASSERT(SOCKET_MODE_LISTENING == mode && SOCKET_MODE_UNOPENED == accepted_socket->mode);
00204 
00205     int temp_socket = socket_accept(socket_id, addr, socket_callback);
00206     if (temp_socket < 0) {
00207         tr_error("NanostackSocket::accept() failed");
00208         return temp_socket;
00209     }
00210     if (!accepted_socket->attach(temp_socket)) {
00211         return -1;
00212     }
00213     accepted_socket->mode = SOCKET_MODE_STREAM;
00214     return temp_socket;
00215 }
00216 
00217 bool NanostackSocket::attach(int8_t temp_socket)
00218 {
00219     nanostack_assert_locked();
00220     if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) {
00221         MBED_ASSERT(false);
00222         return false;
00223     }
00224     if (socket_tbl[temp_socket] != NULL) {
00225         MBED_ASSERT(false);
00226         return false;
00227     }
00228     socket_id = temp_socket;
00229     socket_tbl[socket_id] = this;
00230     return true;
00231 }
00232 
00233 void NanostackSocket::close()
00234 {
00235     nanostack_assert_locked();
00236     MBED_ASSERT(mode != SOCKET_MODE_CLOSED);
00237 
00238     if (socket_id >= 0) {
00239         nsapi_error_t ret = socket_close(socket_id);
00240         MBED_ASSERT(0 == ret);
00241         MBED_ASSERT(socket_tbl[socket_id] == this);
00242         socket_tbl[socket_id] = NULL;
00243         socket_id = -1;
00244     } else {
00245         MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
00246     }
00247 
00248     mode = SOCKET_MODE_CLOSED;
00249     signal_event();
00250 }
00251 
00252 bool NanostackSocket::is_connecting()
00253 {
00254     return SOCKET_MODE_CONNECTING == mode;
00255 }
00256 
00257 void NanostackSocket::set_connecting(ns_address_t *addr)
00258 {
00259     nanostack_assert_locked();
00260     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00261 
00262     memcpy(&ns_address, addr, sizeof(ns_address_t));
00263     mode = SOCKET_MODE_CONNECTING;
00264 }
00265 
00266 bool NanostackSocket::is_connected()
00267 {
00268     return SOCKET_MODE_STREAM == mode;
00269 }
00270 
00271 void NanostackSocket::set_connected()
00272 {
00273     nanostack_assert_locked();
00274     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00275 
00276     mode = SOCKET_MODE_STREAM;
00277 }
00278 
00279 bool NanostackSocket::is_listening()
00280 {
00281     return SOCKET_MODE_LISTENING == mode;
00282 }
00283 
00284 void NanostackSocket::set_listening()
00285 {
00286     nanostack_assert_locked();
00287     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00288 
00289     mode = SOCKET_MODE_LISTENING;
00290 }
00291 
00292 void NanostackSocket::signal_event()
00293 {
00294     nanostack_assert_locked();
00295 
00296     if (callback != NULL) {
00297         callback(callback_data);
00298     }
00299 }
00300 
00301 void NanostackSocket::socket_callback(void *cb) {
00302     nanostack_assert_locked();
00303 
00304     socket_callback_t *sock_cb = (socket_callback_t *) cb;
00305     NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
00306     MBED_ASSERT(socket != NULL);
00307 
00308     tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
00309                      sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);
00310 
00311     switch (sock_cb->event_type) {
00312         case SOCKET_DATA:
00313             tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
00314             socket->event_data(sock_cb);
00315             break;
00316         case SOCKET_CONNECT_DONE:
00317             tr_debug("SOCKET_CONNECT_DONE");
00318             socket->event_connect_done(sock_cb);
00319             break;
00320         case SOCKET_CONNECT_FAIL:
00321             tr_debug("SOCKET_CONNECT_FAIL");
00322             socket->event_connect_fail(sock_cb);
00323             break;
00324         case SOCKET_CONNECT_AUTH_FAIL:
00325             tr_debug("SOCKET_CONNECT_AUTH_FAIL");
00326             break;
00327         case SOCKET_INCOMING_CONNECTION:
00328             tr_debug("SOCKET_INCOMING_CONNECTION");
00329             socket->event_incoming_connection(sock_cb);
00330             break;
00331         case SOCKET_TX_FAIL:
00332             tr_debug("SOCKET_TX_FAIL");
00333             socket->event_tx_fail(sock_cb);
00334             break;
00335         case SOCKET_CONNECT_CLOSED:
00336             tr_debug("SOCKET_CONNECT_CLOSED");
00337             socket->event_connect_closed(sock_cb);
00338             break;
00339         case SOCKET_CONNECTION_RESET:
00340             tr_debug("SOCKET_CONNECTION_RESET");
00341             socket->event_connection_reset(sock_cb);
00342             break;
00343         case SOCKET_NO_ROUTE:
00344             tr_debug("SOCKET_NO_ROUTE");
00345             socket->event_tx_fail(sock_cb);
00346             break;
00347         case SOCKET_TX_DONE:
00348             socket->event_tx_done(sock_cb);
00349             break;
00350         case SOCKET_NO_RAM:
00351             tr_debug("SOCKET_NO_RAM");
00352             socket->event_tx_fail(sock_cb);
00353             break;
00354         case SOCKET_CONNECTION_PROBLEM:
00355             tr_debug("SOCKET_CONNECTION_PROBLEM");
00356             break;
00357         default:
00358             break;
00359     }
00360 }
00361 
00362 
00363 void NanostackSocket::event_data(socket_callback_t *sock_cb)
00364 {
00365     nanostack_assert_locked();
00366     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00367                 (SOCKET_MODE_DATAGRAM == mode));
00368 
00369     signal_event();
00370 }
00371 
00372 void NanostackSocket::event_tx_done(socket_callback_t *sock_cb)
00373 {
00374     nanostack_assert_locked();
00375     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00376                 (SOCKET_MODE_DATAGRAM == mode));
00377 
00378     if (mode == SOCKET_MODE_DATAGRAM) {
00379         tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len);
00380     } else if (mode == SOCKET_MODE_STREAM) {
00381         tr_debug("SOCKET_TX_DONE, %d bytes remaining", sock_cb->d_len);
00382     }
00383 
00384     signal_event();
00385 }
00386 
00387 void NanostackSocket::event_connect_done(socket_callback_t *sock_cb)
00388 {
00389     nanostack_assert_locked();
00390     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00391 
00392     set_connected();
00393     signal_event();
00394 }
00395 
00396 void NanostackSocket::event_connect_fail(socket_callback_t *sock_cb)
00397 {
00398     nanostack_assert_locked();
00399     MBED_ASSERT(mode == SOCKET_MODE_CONNECTING);
00400     close();
00401 }
00402 
00403 void NanostackSocket::event_incoming_connection(socket_callback_t *sock_cb)
00404 {
00405     nanostack_assert_locked();
00406     MBED_ASSERT(mode == SOCKET_MODE_LISTENING);
00407     signal_event();
00408 }
00409 
00410 void NanostackSocket::event_connect_closed(socket_callback_t *sock_cb)
00411 {
00412     nanostack_assert_locked();
00413 
00414     // Can happen if we have an orderly close()
00415     // Might never happen as we have not implemented shutdown() in abstraction layer.
00416     MBED_ASSERT(mode == SOCKET_MODE_STREAM);
00417     close();
00418 }
00419 
00420 void NanostackSocket::event_tx_fail(socket_callback_t *sock_cb)
00421 {
00422     nanostack_assert_locked();
00423 
00424     switch (mode) {
00425         case SOCKET_MODE_CONNECTING:
00426         case SOCKET_MODE_STREAM:
00427             // TX_FAIL is fatal for stream sockets
00428             close();
00429             break;
00430         case SOCKET_MODE_DATAGRAM:
00431             // TX_FAIL is non-fatal for datagram sockets
00432             break;
00433         default:
00434             MBED_ASSERT(false);
00435             break;
00436     }
00437 }
00438 
00439 void NanostackSocket::event_connection_reset(socket_callback_t *sock_cb)
00440 {
00441     nanostack_assert_locked();
00442 
00443     // Only TCP sockets can be closed by the remote end
00444     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00445                 (SOCKET_MODE_CONNECTING == mode));
00446     close();
00447 }
00448 
00449 Nanostack::Nanostack()
00450     : call_event_tasklet(-1)
00451 {
00452     mesh_system_init();
00453 }
00454 
00455 void Nanostack::call_event_tasklet_main(arm_event_s *event)
00456 {
00457     if (event->event_id == CALL_EVENT) {
00458         nanostack_callback *cb = static_cast<nanostack_callback *>(event->data_ptr);
00459         cb->callback();
00460         delete cb;
00461     }
00462 }
00463 
00464 nsapi_error_t Nanostack::call_in(int delay, mbed::Callback<void()> func)
00465 {
00466     if (call_event_tasklet < 0) {
00467         call_event_tasklet = eventOS_event_handler_create(&call_event_tasklet_main, 0);
00468         if (call_event_tasklet < 0) {
00469             return NSAPI_ERROR_NO_MEMORY ;
00470         }
00471     }
00472 
00473     nanostack_callback *cb = new nanostack_callback;
00474     if (!cb) {
00475         return NSAPI_ERROR_NO_MEMORY ;
00476     }
00477 
00478     cb->callback = func;
00479 
00480     arm_event_s event;
00481 
00482     event.sender =  call_event_tasklet,
00483     event.event_id = CALL_EVENT,
00484     event.receiver = call_event_tasklet,
00485     event.data_ptr = cb;
00486     event.event_type = APPLICATION_EVENT;
00487     event.priority = ARM_LIB_LOW_PRIORITY_EVENT;
00488 
00489     if (delay) {
00490         uint32_t ticks = eventOS_event_timer_ms_to_ticks(delay);
00491         if (!eventOS_event_send_in(&event, ticks)) {
00492             delete cb;
00493             return NSAPI_ERROR_NO_MEMORY ;
00494         }
00495     } else {
00496         if (eventOS_event_send(&event) < 0) {
00497             delete cb;
00498             return NSAPI_ERROR_NO_MEMORY ;
00499         }
00500     }
00501 
00502     return NSAPI_ERROR_OK ;
00503 }
00504 
00505 Nanostack::call_in_callback_cb_t Nanostack::get_call_in_callback()
00506 {
00507     call_in_callback_cb_t cb(this, &Nanostack::call_in);
00508     return cb;
00509 }
00510 
00511 const char * Nanostack::get_ip_address()
00512 {
00513     NanostackLockGuard lock;
00514 
00515     for (int if_id = 1; if_id <= 127; if_id++) {
00516         uint8_t address[16];
00517         int ret = arm_net_address_get(if_id, ADDR_IPV6_GP, address);
00518         if (ret == 0) {
00519             ip6tos(address, text_ip_address);
00520             return text_ip_address;
00521         }
00522     }
00523     // Must result a valid IPv6 address
00524     // For gethostbyname() to detect IP version.
00525     return "::";
00526 }
00527 
00528 nsapi_error_t Nanostack::socket_open(void **handle, nsapi_protocol_t protocol)
00529 {
00530     // Validate parameters
00531     if (NULL == handle) {
00532         MBED_ASSERT(false);
00533         return NSAPI_ERROR_NO_SOCKET ;
00534     }
00535     int8_t ns_proto;
00536     if (NSAPI_UDP  == protocol) {
00537         ns_proto = SOCKET_UDP;
00538     } else if (NSAPI_TCP  == protocol) {
00539         ns_proto = SOCKET_TCP;
00540     } else {
00541         MBED_ASSERT(false);
00542         return NSAPI_ERROR_UNSUPPORTED ;
00543     }
00544     *handle = (void*)NULL;
00545 
00546     NanostackLockGuard lock;
00547 
00548     NanostackSocket * socket = new NanostackSocket(ns_proto);
00549     if (socket == NULL) {
00550         tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY );
00551         return NSAPI_ERROR_NO_MEMORY ;
00552     }
00553     if (!socket->open()) {
00554         delete socket;
00555         tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR );
00556         return NSAPI_ERROR_DEVICE_ERROR ;
00557     }
00558     *handle = (void*)socket;
00559 
00560     tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);
00561 
00562     return NSAPI_ERROR_OK ;
00563 }
00564 
00565 nsapi_error_t Nanostack::socket_close(void *handle)
00566 {
00567     NanostackLockGuard lock;
00568     // Validate parameters
00569     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00570     if (NULL == handle) {
00571         MBED_ASSERT(false);
00572         return NSAPI_ERROR_NO_SOCKET ;
00573     }
00574     tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id);
00575 
00576     delete socket;
00577 
00578     return 0;
00579 
00580 }
00581 
00582 nsapi_size_or_error_t Nanostack::do_sendto(void *handle, const ns_address_t *address, const void *data, nsapi_size_t size)
00583 {
00584     // Validate parameters
00585     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00586     if (handle == NULL) {
00587         MBED_ASSERT(false);
00588         return NSAPI_ERROR_NO_SOCKET ;
00589     }
00590 
00591     nsapi_size_or_error_t ret;
00592 
00593     NanostackLockGuard lock;
00594 
00595     if (socket->closed() || (!address && !socket->is_connected())) {
00596         ret = NSAPI_ERROR_NO_CONNECTION ;
00597         goto out;
00598     }
00599 
00600     if (address && socket->proto == SOCKET_TCP) {
00601         tr_error("socket_sendto() not supported with TCP!");
00602         ret = NSAPI_ERROR_IS_CONNECTED ;
00603         goto out;
00604     }
00605 
00606     int retcode;
00607 #if 0
00608     retcode = ::socket_sendto(socket->socket_id, address,
00609                                             data, size);
00610 #else
00611     // Use sendmsg purely to get the new return style
00612     // of returning data written rather than 0 on success,
00613     // which means TCP can do partial writes. (Sadly,
00614     // it's the only call which takes flags so we can
00615     // leave the NS_MSG_LEGACY0 flag clear).
00616     ns_msghdr_t msg;
00617     ns_iovec_t iov;
00618     iov.iov_base = const_cast<void *>(data);
00619     iov.iov_len = size;
00620     msg.msg_name = const_cast<ns_address_t *>(address);
00621     msg.msg_namelen = address ? sizeof *address : 0;
00622     msg.msg_iov = &iov;
00623     msg.msg_iovlen = 1;
00624     msg.msg_control = NULL;
00625     msg.msg_controllen = 0;
00626     retcode = ::socket_sendmsg(socket->socket_id, &msg, 0);
00627 #endif
00628 
00629     /*
00630      * \return length if entire amount written (which could be 0)
00631      * \return value >0 and <length if partial amount written (stream only)
00632      * \return NS_EWOULDBLOCK if nothing written due to lack of queue space.
00633      * \return -1 Invalid socket ID or message structure.
00634      * \return -2 Socket memory allocation fail.
00635      * \return -3 TCP state not established or address scope not defined .
00636      * \return -4 Socket TX process busy or unknown interface.
00637      * \return -5 Socket not connected
00638      * \return -6 Packet too short (ICMP raw socket error).
00639      * */
00640     if (retcode == NS_EWOULDBLOCK) {
00641         ret = NSAPI_ERROR_WOULD_BLOCK ;
00642     } else if (retcode < 0) {
00643         tr_error("socket_sendmsg: error=%d", retcode);
00644         ret = NSAPI_ERROR_DEVICE_ERROR ;
00645     } else {
00646         ret = retcode;
00647     }
00648 
00649 out:
00650     tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00651 
00652     return ret;
00653 }
00654 
00655 nsapi_size_or_error_t Nanostack::socket_sendto(void *handle, const SocketAddress &address, const void *data, nsapi_size_t size)
00656 {
00657     if (address.get_ip_version() != NSAPI_IPv6 ) {
00658         return NSAPI_ERROR_UNSUPPORTED ;
00659     }
00660 
00661     ns_address_t ns_address;
00662     convert_mbed_addr_to_ns(&ns_address, &address);
00663     /*No lock gaurd needed here as do_sendto() will handle locks.*/
00664     return do_sendto(handle, &ns_address, data, size);
00665 }
00666 
00667 nsapi_size_or_error_t Nanostack::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size)
00668 {
00669     // Validate parameters
00670     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00671     if (handle == NULL) {
00672         MBED_ASSERT(false);
00673         return NSAPI_ERROR_NO_SOCKET ;
00674     }
00675 
00676     nsapi_size_or_error_t ret;
00677 
00678     NanostackLockGuard lock;
00679 
00680     if (socket->closed()) {
00681         ret = NSAPI_ERROR_NO_CONNECTION ;
00682         goto out;
00683     }
00684 
00685     ns_address_t ns_address;
00686 
00687     int retcode;
00688     retcode = ::socket_recvfrom(socket->socket_id, buffer, size, 0, &ns_address);
00689 
00690     if (retcode == NS_EWOULDBLOCK) {
00691         ret = NSAPI_ERROR_WOULD_BLOCK ;
00692     } else if (retcode < 0) {
00693         ret = NSAPI_ERROR_PARAMETER ;
00694     } else {
00695         ret = retcode;
00696         if (address != NULL) {
00697             convert_ns_addr_to_mbed(address, &ns_address);
00698         }
00699     }
00700 
00701 out:
00702     if (address) {
00703         tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i, addr=[%s]:%i", socket, socket->socket_id, ret,
00704                  trace_ipv6(address->get_ip_bytes()), address->get_port());
00705     } else {
00706         tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00707     }
00708 
00709     return ret;
00710 }
00711 
00712 nsapi_error_t Nanostack::socket_bind(void *handle, const SocketAddress &address)
00713 {
00714     // Validate parameters
00715     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00716     if (handle == NULL) {
00717         MBED_ASSERT(false);
00718         return NSAPI_ERROR_NO_SOCKET ;
00719     }
00720 
00721     const void *addr_field;
00722     switch (address.get_ip_version()) {
00723         case NSAPI_IPv6 :
00724             addr_field = address.get_ip_bytes();
00725             break;
00726         case NSAPI_UNSPEC :
00727             addr_field = &ns_in6addr_any;
00728             break;
00729         default:
00730             return NSAPI_ERROR_UNSUPPORTED ;
00731     }
00732 
00733     NanostackLockGuard lock;
00734 
00735     ns_address_t ns_address;
00736     ns_address.type = ADDRESS_IPV6;
00737     memcpy(ns_address.address, addr_field, sizeof ns_address.address);
00738     ns_address.identifier = address.get_port();
00739     nsapi_error_t ret;
00740     int retcode = ::socket_bind(socket->socket_id, &ns_address);
00741 
00742     if (retcode == 0) {
00743         ret = NSAPI_ERROR_OK ;
00744     } else {
00745         ret = NSAPI_ERROR_PARAMETER ;
00746     }
00747 
00748     tr_debug("socket_bind(socket=%p) sock_id=%d, retcode=%i, ret=%i", socket, socket->socket_id, retcode, ret);
00749 
00750     return ret;
00751 }
00752 
00753 nsapi_error_t Nanostack::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
00754 {
00755     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00756     if (handle == NULL) {
00757         MBED_ASSERT(false);
00758         return NSAPI_ERROR_NO_SOCKET ;
00759     }
00760 
00761     NanostackLockGuard lock;
00762 
00763     ns_ipv6_mreq_t ns_mreq;
00764 
00765     if (level == NSAPI_SOCKET ) {
00766         switch (optname) {
00767             case NSAPI_ADD_MEMBERSHIP :
00768             case NSAPI_DROP_MEMBERSHIP : {
00769                 if (optlen != sizeof(nsapi_ip_mreq_t)) {
00770                     return NSAPI_ERROR_PARAMETER ;
00771                 }
00772                 const nsapi_ip_mreq_t *imr = static_cast<const nsapi_ip_mreq_t *>(optval);
00773 
00774                 /* Check address types are IPv6, or unspecified for interface */
00775                 if (imr->imr_multiaddr.version != NSAPI_IPv6  ||
00776                     (imr->imr_interface.version != NSAPI_UNSPEC  && imr->imr_interface.version != NSAPI_IPv6 )) {
00777                     return NSAPI_ERROR_PARAMETER ;
00778                 }
00779 
00780                 /* Convert all parameters to Nanostack native, and proceed with setsockopt */
00781                 memcpy(ns_mreq.ipv6mr_multiaddr, imr->imr_multiaddr.bytes, 16);
00782                 if (imr->imr_interface.version == NSAPI_UNSPEC  || memcmp(imr->imr_interface.bytes, ns_in6addr_any, 16) == 0) {
00783                     ns_mreq.ipv6mr_interface = 0;
00784                 } else {
00785                     // If this fails, Nanostack will itself fault the invalid -1 interface ID
00786                     ns_mreq.ipv6mr_interface = find_interface_by_address(imr->imr_interface.bytes);
00787                 }
00788 
00789                 level = SOCKET_IPPROTO_IPV6;
00790                 optname = optname == NSAPI_ADD_MEMBERSHIP  ? SOCKET_IPV6_JOIN_GROUP : SOCKET_IPV6_LEAVE_GROUP;
00791                 optval = &ns_mreq;
00792                 optlen = sizeof ns_mreq;
00793                 break;
00794             }
00795             default:
00796                 return NSAPI_ERROR_PARAMETER ;
00797         }
00798     }
00799 
00800     if (::socket_setsockopt(socket->socket_id, level, optname, optval, optlen) == 0) {
00801         return NSAPI_ERROR_OK ;
00802     } else {
00803         return NSAPI_ERROR_PARAMETER ;
00804     }
00805 }
00806 
00807 nsapi_error_t Nanostack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
00808 {
00809     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00810     if (handle == NULL) {
00811         MBED_ASSERT(false);
00812         return NSAPI_ERROR_NO_SOCKET ;
00813     }
00814 
00815     nsapi_error_t ret;
00816 
00817     NanostackLockGuard lock;
00818 
00819     uint16_t optlen16 = *optlen;
00820     if (::socket_getsockopt(socket->socket_id, level, optname, optval, &optlen16) == 0) {
00821         ret = NSAPI_ERROR_OK ;
00822         *optlen = optlen16;
00823     } else {
00824         ret = NSAPI_ERROR_PARAMETER ;
00825     }
00826 
00827     return ret;
00828 }
00829 
00830 nsapi_error_t Nanostack::socket_listen(void *handle, int backlog)
00831 {
00832     //Check if socket exists
00833     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00834     if (handle == NULL) {
00835         MBED_ASSERT(false);
00836         return NSAPI_ERROR_NO_SOCKET ;
00837     }
00838 
00839     nsapi_error_t ret = NSAPI_ERROR_OK ;
00840 
00841     NanostackLockGuard lock;
00842 
00843     if(::socket_listen(socket->socket_id, backlog) < 0) {
00844         ret = NSAPI_ERROR_PARAMETER ;
00845     } else {
00846         socket->set_listening();
00847     }
00848 
00849     return ret;
00850 }
00851 
00852 nsapi_error_t Nanostack::socket_connect(void *handle, const SocketAddress &addr)
00853 {
00854     // Validate parameters
00855     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00856     nsapi_error_t ret;
00857     if (handle == NULL) {
00858         MBED_ASSERT(false);
00859         return NSAPI_ERROR_NO_SOCKET ;
00860     }
00861 
00862     NanostackLockGuard lock;
00863 
00864     if (addr.get_ip_version() != NSAPI_IPv6 ) {
00865         ret = NSAPI_ERROR_UNSUPPORTED ;
00866         goto out;
00867     }
00868 
00869     if (socket->closed()) {
00870         ret = NSAPI_ERROR_NO_CONNECTION ;
00871         goto out;
00872     }
00873 
00874     if (socket->is_connecting()) {
00875         ret = NSAPI_ERROR_ALREADY ;
00876         goto out;
00877     }
00878 
00879     if (socket->is_connected()) {
00880         ret = NSAPI_ERROR_IS_CONNECTED ;
00881         goto out;
00882     }
00883 
00884     ns_address_t ns_addr;
00885 
00886     convert_mbed_addr_to_ns(&ns_addr, &addr);
00887     if (::socket_connect(socket->socket_id, &ns_addr, 0) == 0) {
00888         if (socket->proto == SOCKET_TCP) {
00889             socket->set_connecting(&ns_addr);
00890             ret = NSAPI_ERROR_IN_PROGRESS ;
00891         } else {
00892             ret = NSAPI_ERROR_OK ;
00893         }
00894     } else {
00895         ret = NSAPI_ERROR_DEVICE_ERROR ;
00896     }
00897 
00898 out:
00899     tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00900 
00901     return ret;
00902 }
00903 
00904 nsapi_error_t Nanostack::socket_accept(void *server, void **handle, SocketAddress *address)
00905 {
00906     NanostackSocket * socket = static_cast<NanostackSocket *>(server);
00907     NanostackSocket *accepted_sock = NULL;
00908     nsapi_error_t ret;
00909 
00910     if (handle == NULL) {
00911         MBED_ASSERT(false);
00912         return NSAPI_ERROR_NO_SOCKET ;
00913     }
00914 
00915     NanostackLockGuard lock;
00916 
00917     if (!socket->is_listening()) {
00918         ret = NSAPI_ERROR_PARAMETER ;
00919         goto out;
00920     }
00921 
00922     accepted_sock = new NanostackSocket(socket->proto);
00923     if (accepted_sock == NULL) {
00924         ret = NSAPI_ERROR_NO_MEMORY ;
00925         goto out;
00926     }
00927 
00928     ns_address_t ns_addr;
00929     int retcode;
00930     retcode = socket->accept(accepted_sock, &ns_addr);
00931     if (retcode < 0) {
00932         delete accepted_sock;
00933         if (retcode == NS_EWOULDBLOCK) {
00934             ret = NSAPI_ERROR_WOULD_BLOCK ;
00935         } else {
00936             ret = NSAPI_ERROR_DEVICE_ERROR ;
00937         }
00938         goto out;
00939     }
00940     ret = NSAPI_ERROR_OK ;
00941 
00942     if (address) {
00943         convert_ns_addr_to_mbed(address, &ns_addr);
00944     }
00945 
00946     *handle = accepted_sock;
00947 
00948 out:
00949     tr_debug("socket_accept() socket=%p, sock_id=%d, ret=%i", accepted_sock, accepted_sock ? accepted_sock->socket_id : -1, ret);
00950 
00951     return ret;
00952 }
00953 
00954 nsapi_size_or_error_t Nanostack::socket_send(void *handle, const void *data, nsapi_size_t size)
00955 {
00956     return do_sendto(handle, NULL, data, size);
00957 }
00958 
00959 nsapi_size_or_error_t Nanostack::socket_recv(void *handle, void *data, nsapi_size_t size)
00960 {
00961     return socket_recvfrom(handle, NULL, data, size);
00962 }
00963 
00964 void Nanostack::socket_attach(void *handle, void (*callback)(void *), void *id)
00965 {
00966     // Validate parameters
00967     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00968     if (handle == NULL) {
00969         MBED_ASSERT(false);
00970         return;
00971     }
00972 
00973     NanostackLockGuard lock;
00974 
00975     socket->callback = callback;
00976     socket->callback_data = id;
00977 
00978     tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id);
00979 }
00980 
00981 Nanostack &Nanostack::get_instance() {
00982     static Nanostack nanostack;
00983     return nanostack;
00984 }
00985 
00986 // This works as long as it's not ever set to something which corresponds to
00987 // a macro defined as a non-integer. Eg `#define Nanostack "Foo"`
00988 #define NANOSTACK 0x99119911
00989 #if MBED_CONF_NSAPI_DEFAULT_STACK == NANOSTACK
00990 #undef NANOSTACK
00991 OnboardNetworkStack &OnboardNetworkStack::get_default_instance() {
00992     return Nanostack::get_instance();
00993 }
00994 #endif