Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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