Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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