EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackInterface.cpp Source File

NanostackInterface.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 "NanostackInterface.h"
00023 #include "NanostackLockGuard.h"
00024 
00025 #include "ns_address.h"
00026 #include "nsdynmemLIB.h"
00027 #include "eventOS_scheduler.h"
00028 #include "randLIB.h"
00029 #include "ip6string.h"
00030 
00031 #include "mesh_system.h" // from inside mbed-mesh-api
00032 #include "socket_api.h"
00033 #include "net_interface.h"
00034 
00035 // Uncomment to enable trace
00036 //#define HAVE_DEBUG
00037 #include "ns_trace.h"
00038 #define TRACE_GROUP "nsif"
00039 
00040 #define NS_INTERFACE_SOCKETS_MAX  16  //same as NanoStack SOCKET_MAX
00041 
00042 #define MALLOC  ns_dyn_mem_alloc
00043 #define FREE    ns_dyn_mem_free
00044 
00045 // Socket state progressions:
00046 // UDP: UNOPENED -> DATAGRAM
00047 // TCP client: UNOPENED -> OPENED -> CONNECTING -> STREAM -> CLOSED
00048 // TCP server: UNOPENED -> OPENED -> LISTENING
00049 // TCP accept: UNOPENED -> STREAM -> CLOSED
00050 enum socket_mode_t {
00051     SOCKET_MODE_UNOPENED,   // No socket ID
00052     SOCKET_MODE_DATAGRAM,   // Socket is datagram type
00053     SOCKET_MODE_OPENED,     // Socket ID but no assigned use yet
00054     SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet
00055     SOCKET_MODE_STREAM,     // Socket has an open stream
00056     SOCKET_MODE_CLOSED,     // Socket is closed and resources are freed
00057     SOCKET_MODE_LISTENING,  // Socket is listening for connections
00058 };
00059 
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 void* NanostackSocket::operator new(std::size_t sz) {
00132     return MALLOC(sz);
00133 }
00134 void NanostackSocket::operator delete(void* ptr) {
00135     FREE(ptr);
00136 }
00137 
00138 NanostackSocket::NanostackSocket(int8_t protocol)
00139 {
00140     nanostack_assert_locked();
00141 
00142     callback = NULL;
00143     callback_data = NULL;
00144     socket_id = -1;
00145     proto = protocol;
00146     addr_valid = false;
00147     memset(&ns_address, 0, sizeof(ns_address));
00148     mode = SOCKET_MODE_UNOPENED;
00149 }
00150 
00151 NanostackSocket::~NanostackSocket()
00152 {
00153     nanostack_assert_locked();
00154 
00155     if (mode != SOCKET_MODE_CLOSED) {
00156         close();
00157     }
00158 }
00159 
00160 bool NanostackSocket::open(void)
00161 {
00162     nanostack_assert_locked();
00163     MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
00164 
00165     int temp_socket = socket_open(proto, 0, socket_callback);
00166 
00167     if (temp_socket < 0) {
00168         tr_error("NanostackSocket::open() failed");
00169         return false;
00170     }
00171 
00172     if (proto == SOCKET_TCP) {
00173         /* Receive and send buffers enabled by default */
00174         mode = SOCKET_MODE_OPENED;
00175     } else {
00176         static const int32_t rcvbuf_size = 2048;
00177         socket_setsockopt(temp_socket, SOCKET_SOL_SOCKET, SOCKET_SO_RCVBUF, &rcvbuf_size, sizeof rcvbuf_size);
00178         mode = SOCKET_MODE_DATAGRAM;
00179     }
00180 
00181     return attach(temp_socket);
00182 }
00183 
00184 int NanostackSocket::accept(NanostackSocket *accepted_socket, ns_address_t *addr)
00185 {
00186     nanostack_assert_locked();
00187     MBED_ASSERT(SOCKET_MODE_LISTENING == mode && SOCKET_MODE_UNOPENED == accepted_socket->mode);
00188 
00189     int temp_socket = socket_accept(socket_id, addr, socket_callback);
00190     if (temp_socket < 0) {
00191         tr_error("NanostackSocket::accept() failed");
00192         return temp_socket;
00193     }
00194     if (!accepted_socket->attach(temp_socket)) {
00195         return -1;
00196     }
00197     accepted_socket->mode = SOCKET_MODE_STREAM;
00198     return temp_socket;
00199 }
00200 
00201 bool NanostackSocket::attach(int8_t temp_socket)
00202 {
00203     nanostack_assert_locked();
00204     if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) {
00205         MBED_ASSERT(false);
00206         return false;
00207     }
00208     if (socket_tbl[temp_socket] != NULL) {
00209         MBED_ASSERT(false);
00210         return false;
00211     }
00212     socket_id = temp_socket;
00213     socket_tbl[socket_id] = this;
00214     return true;
00215 }
00216 
00217 void NanostackSocket::close()
00218 {
00219     nanostack_assert_locked();
00220     MBED_ASSERT(mode != SOCKET_MODE_CLOSED);
00221 
00222     if (socket_id >= 0) {
00223         nsapi_error_t ret = socket_close(socket_id);
00224         MBED_ASSERT(0 == ret);
00225         MBED_ASSERT(socket_tbl[socket_id] == this);
00226         socket_tbl[socket_id] = NULL;
00227         socket_id = -1;
00228     } else {
00229         MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
00230     }
00231 
00232     mode = SOCKET_MODE_CLOSED;
00233     signal_event();
00234 }
00235 
00236 bool NanostackSocket::is_connecting()
00237 {
00238     return SOCKET_MODE_CONNECTING == mode;
00239 }
00240 
00241 void NanostackSocket::set_connecting(ns_address_t *addr)
00242 {
00243     nanostack_assert_locked();
00244     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00245 
00246     memcpy(&ns_address, addr, sizeof(ns_address_t));
00247     mode = SOCKET_MODE_CONNECTING;
00248 }
00249 
00250 bool NanostackSocket::is_connected()
00251 {
00252     return SOCKET_MODE_STREAM == mode;
00253 }
00254 
00255 void NanostackSocket::set_connected()
00256 {
00257     nanostack_assert_locked();
00258     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00259 
00260     mode = SOCKET_MODE_STREAM;
00261 }
00262 
00263 bool NanostackSocket::is_listening()
00264 {
00265     return SOCKET_MODE_LISTENING == mode;
00266 }
00267 
00268 void NanostackSocket::set_listening()
00269 {
00270     nanostack_assert_locked();
00271     MBED_ASSERT(SOCKET_MODE_OPENED == mode);
00272 
00273     mode = SOCKET_MODE_LISTENING;
00274 }
00275 
00276 void NanostackSocket::signal_event()
00277 {
00278     nanostack_assert_locked();
00279 
00280     if (callback != NULL) {
00281         callback(callback_data);
00282     }
00283 }
00284 
00285 void NanostackSocket::socket_callback(void *cb) {
00286     nanostack_assert_locked();
00287 
00288     socket_callback_t *sock_cb = (socket_callback_t *) cb;
00289     NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
00290     MBED_ASSERT(socket != NULL);
00291 
00292     tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
00293                      sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);
00294 
00295     switch (sock_cb->event_type) {
00296         case SOCKET_DATA:
00297             tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
00298             socket->event_data(sock_cb);
00299             break;
00300         case SOCKET_CONNECT_DONE:
00301             tr_debug("SOCKET_CONNECT_DONE");
00302             socket->event_connect_done(sock_cb);
00303             break;
00304         case SOCKET_CONNECT_FAIL:
00305             tr_debug("SOCKET_CONNECT_FAIL");
00306             socket->event_connect_fail(sock_cb);
00307             break;
00308         case SOCKET_CONNECT_AUTH_FAIL:
00309             tr_debug("SOCKET_CONNECT_AUTH_FAIL");
00310             break;
00311         case SOCKET_INCOMING_CONNECTION:
00312             tr_debug("SOCKET_INCOMING_CONNECTION");
00313             socket->event_incoming_connection(sock_cb);
00314             break;
00315         case SOCKET_TX_FAIL:
00316             tr_debug("SOCKET_TX_FAIL");
00317             socket->event_tx_fail(sock_cb);
00318             break;
00319         case SOCKET_CONNECT_CLOSED:
00320             tr_debug("SOCKET_CONNECT_CLOSED");
00321             socket->event_connect_closed(sock_cb);
00322             break;
00323         case SOCKET_CONNECTION_RESET:
00324             tr_debug("SOCKET_CONNECTION_RESET");
00325             socket->event_connection_reset(sock_cb);
00326             break;
00327         case SOCKET_NO_ROUTE:
00328             tr_debug("SOCKET_NO_ROUTE");
00329             socket->event_tx_fail(sock_cb);
00330             break;
00331         case SOCKET_TX_DONE:
00332             socket->event_tx_done(sock_cb);
00333             break;
00334         case SOCKET_NO_RAM:
00335             tr_debug("SOCKET_NO_RAM");
00336             socket->event_tx_fail(sock_cb);
00337             break;
00338         case SOCKET_CONNECTION_PROBLEM:
00339             tr_debug("SOCKET_CONNECTION_PROBLEM");
00340             break;
00341         default:
00342             break;
00343     }
00344 }
00345 
00346 
00347 void NanostackSocket::event_data(socket_callback_t *sock_cb)
00348 {
00349     nanostack_assert_locked();
00350     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00351                 (SOCKET_MODE_DATAGRAM == mode));
00352 
00353     signal_event();
00354 }
00355 
00356 void NanostackSocket::event_tx_done(socket_callback_t *sock_cb)
00357 {
00358     nanostack_assert_locked();
00359     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00360                 (SOCKET_MODE_DATAGRAM == mode));
00361 
00362     if (mode == SOCKET_MODE_DATAGRAM) {
00363         tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len);
00364     } else if (mode == SOCKET_MODE_STREAM) {
00365         tr_debug("SOCKET_TX_DONE, %d bytes remaining", sock_cb->d_len);
00366     }
00367 
00368     signal_event();
00369 }
00370 
00371 void NanostackSocket::event_connect_done(socket_callback_t *sock_cb)
00372 {
00373     nanostack_assert_locked();
00374     MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
00375 
00376     set_connected();
00377     signal_event();
00378 }
00379 
00380 void NanostackSocket::event_connect_fail(socket_callback_t *sock_cb)
00381 {
00382     nanostack_assert_locked();
00383     MBED_ASSERT(mode == SOCKET_MODE_CONNECTING);
00384     close();
00385 }
00386 
00387 void NanostackSocket::event_incoming_connection(socket_callback_t *sock_cb)
00388 {
00389     nanostack_assert_locked();
00390     MBED_ASSERT(mode == SOCKET_MODE_LISTENING);
00391     signal_event();
00392 }
00393 
00394 void NanostackSocket::event_connect_closed(socket_callback_t *sock_cb)
00395 {
00396     nanostack_assert_locked();
00397 
00398     // Can happen if we have an orderly close()
00399     // Might never happen as we have not implemented shutdown() in abstraction layer.
00400     MBED_ASSERT(mode == SOCKET_MODE_STREAM);
00401     close();
00402 }
00403 
00404 void NanostackSocket::event_tx_fail(socket_callback_t *sock_cb)
00405 {
00406     nanostack_assert_locked();
00407 
00408     switch (mode) {
00409         case SOCKET_MODE_CONNECTING:
00410         case SOCKET_MODE_STREAM:
00411             // TX_FAIL is fatal for stream sockets
00412             close();
00413             break;
00414         case SOCKET_MODE_DATAGRAM:
00415             // TX_FAIL is non-fatal for datagram sockets
00416             break;
00417         default:
00418             MBED_ASSERT(false);
00419             break;
00420     }
00421 }
00422 
00423 void NanostackSocket::event_connection_reset(socket_callback_t *sock_cb)
00424 {
00425     nanostack_assert_locked();
00426 
00427     // Only TCP sockets can be closed by the remote end
00428     MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
00429                 (SOCKET_MODE_CONNECTING == mode));
00430     close();
00431 }
00432 
00433 NanostackInterface *NanostackInterface::_ns_interface;
00434 
00435 NanostackInterface *NanostackInterface::get_stack()
00436 {
00437     NanostackLockGuard lock;
00438 
00439     if (NULL == _ns_interface) {
00440         _ns_interface = new NanostackInterface();
00441     }
00442 
00443     return _ns_interface;
00444 }
00445 
00446 const char * NanostackInterface::get_ip_address()
00447 {
00448     NanostackLockGuard lock;
00449 
00450     for (int if_id = 1; if_id <= 127; if_id++) {
00451         uint8_t address[16];
00452         int ret = arm_net_address_get(if_id, ADDR_IPV6_GP, address);
00453         if (ret == 0) {
00454             ip6tos(address, text_ip_address);
00455             return text_ip_address;
00456         }
00457     }
00458     // Must result a valid IPv6 address
00459     // For gethostbyname() to detect IP version.
00460     return "::";
00461 }
00462 
00463 nsapi_error_t NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol)
00464 {
00465     // Validate parameters
00466     if (NULL == handle) {
00467         MBED_ASSERT(false);
00468         return NSAPI_ERROR_NO_SOCKET ;
00469     }
00470     int8_t ns_proto;
00471     if (NSAPI_UDP  == protocol) {
00472         ns_proto = SOCKET_UDP;
00473     } else if (NSAPI_TCP  == protocol) {
00474         ns_proto = SOCKET_TCP;
00475     } else {
00476         MBED_ASSERT(false);
00477         return NSAPI_ERROR_UNSUPPORTED ;
00478     }
00479     *handle = (void*)NULL;
00480 
00481     NanostackLockGuard lock;
00482 
00483     NanostackSocket * socket = new NanostackSocket(ns_proto);
00484     if (socket == NULL) {
00485         tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY );
00486         return NSAPI_ERROR_NO_MEMORY ;
00487     }
00488     if (!socket->open()) {
00489         delete socket;
00490         tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR );
00491         return NSAPI_ERROR_DEVICE_ERROR ;
00492     }
00493     *handle = (void*)socket;
00494 
00495     tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);
00496 
00497     return NSAPI_ERROR_OK ;
00498 }
00499 
00500 nsapi_error_t NanostackInterface::socket_close(void *handle)
00501 {
00502     NanostackLockGuard lock;
00503     // Validate parameters
00504     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00505     if (NULL == handle) {
00506         MBED_ASSERT(false);
00507         return NSAPI_ERROR_NO_SOCKET ;
00508     }
00509     tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id);
00510 
00511     delete socket;
00512 
00513     return 0;
00514 
00515 }
00516 
00517 nsapi_size_or_error_t NanostackInterface::do_sendto(void *handle, const ns_address_t *address, const void *data, nsapi_size_t size)
00518 {
00519     // Validate parameters
00520     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00521     if (handle == NULL) {
00522         MBED_ASSERT(false);
00523         return NSAPI_ERROR_NO_SOCKET ;
00524     }
00525 
00526     nsapi_size_or_error_t ret;
00527 
00528     NanostackLockGuard lock;
00529 
00530     if (socket->closed() || (!address && !socket->is_connected())) {
00531         ret = NSAPI_ERROR_NO_CONNECTION ;
00532         goto out;
00533     }
00534 
00535     if (address && socket->proto == SOCKET_TCP) {
00536         tr_error("socket_sendto() not supported with TCP!");
00537         ret = NSAPI_ERROR_IS_CONNECTED ;
00538         goto out;
00539     }
00540 
00541     int retcode;
00542 #if 0
00543     retcode = ::socket_sendto(socket->socket_id, address,
00544                                             data, size);
00545 #else
00546     // Use sendmsg purely to get the new return style
00547     // of returning data written rather than 0 on success,
00548     // which means TCP can do partial writes. (Sadly,
00549     // it's the only call which takes flags so we can
00550     // leave the NS_MSG_LEGACY0 flag clear).
00551     ns_msghdr_t msg;
00552     ns_iovec_t iov;
00553     iov.iov_base = const_cast<void *>(data);
00554     iov.iov_len = size;
00555     msg.msg_name = const_cast<ns_address_t *>(address);
00556     msg.msg_namelen = address ? sizeof *address : 0;
00557     msg.msg_iov = &iov;
00558     msg.msg_iovlen = 1;
00559     msg.msg_control = NULL;
00560     msg.msg_controllen = 0;
00561     retcode = ::socket_sendmsg(socket->socket_id, &msg, 0);
00562 #endif
00563 
00564     /*
00565      * \return length if entire amount written (which could be 0)
00566      * \return value >0 and <length if partial amount written (stream only)
00567      * \return NS_EWOULDBLOCK if nothing written due to lack of queue space.
00568      * \return -1 Invalid socket ID or message structure.
00569      * \return -2 Socket memory allocation fail.
00570      * \return -3 TCP state not established or address scope not defined .
00571      * \return -4 Socket TX process busy or unknown interface.
00572      * \return -5 Socket not connected
00573      * \return -6 Packet too short (ICMP raw socket error).
00574      * */
00575     if (retcode == NS_EWOULDBLOCK) {
00576         ret = NSAPI_ERROR_WOULD_BLOCK ;
00577     } else if (retcode < 0) {
00578         tr_error("socket_sendmsg: error=%d", retcode);
00579         ret = NSAPI_ERROR_DEVICE_ERROR ;
00580     } else {
00581         ret = retcode;
00582     }
00583 
00584 out:
00585     tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00586 
00587     return ret;
00588 }
00589 
00590 nsapi_size_or_error_t NanostackInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, nsapi_size_t size)
00591 {
00592     if (address.get_ip_version() != NSAPI_IPv6 ) {
00593         return NSAPI_ERROR_UNSUPPORTED ;
00594     }
00595 
00596     ns_address_t ns_address;
00597     convert_mbed_addr_to_ns(&ns_address, &address);
00598     /*No lock gaurd needed here as do_sendto() will handle locks.*/
00599     return do_sendto(handle, &ns_address, data, size);
00600 }
00601 
00602 nsapi_size_or_error_t NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size)
00603 {
00604     // Validate parameters
00605     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00606     if (handle == NULL) {
00607         MBED_ASSERT(false);
00608         return NSAPI_ERROR_NO_SOCKET ;
00609     }
00610 
00611     nsapi_size_or_error_t ret;
00612 
00613     NanostackLockGuard lock;
00614 
00615     if (socket->closed()) {
00616         ret = NSAPI_ERROR_NO_CONNECTION ;
00617         goto out;
00618     }
00619 
00620     ns_address_t ns_address;
00621 
00622     int retcode;
00623     retcode = ::socket_recvfrom(socket->socket_id, buffer, size, 0, &ns_address);
00624 
00625     if (retcode == NS_EWOULDBLOCK) {
00626         ret = NSAPI_ERROR_WOULD_BLOCK ;
00627     } else if (retcode < 0) {
00628         ret = NSAPI_ERROR_PARAMETER ;
00629     } else {
00630         ret = retcode;
00631         if (address != NULL) {
00632             convert_ns_addr_to_mbed(address, &ns_address);
00633         }
00634     }
00635 
00636 out:
00637     if (address) {
00638         tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i, addr=[%s]:%i", socket, socket->socket_id, ret,
00639                  trace_ipv6(address->get_ip_bytes()), address->get_port());
00640     } else {
00641         tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00642     }
00643 
00644     return ret;
00645 }
00646 
00647 nsapi_error_t NanostackInterface::socket_bind(void *handle, const SocketAddress &address)
00648 {
00649     // Validate parameters
00650     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00651     if (handle == NULL) {
00652         MBED_ASSERT(false);
00653         return NSAPI_ERROR_NO_SOCKET ;
00654     }
00655 
00656     const void *addr_field;
00657     switch (address.get_ip_version()) {
00658         case NSAPI_IPv6 :
00659             addr_field = address.get_ip_bytes();
00660             break;
00661         case NSAPI_UNSPEC :
00662             addr_field = &ns_in6addr_any;
00663             break;
00664         default:
00665             return NSAPI_ERROR_UNSUPPORTED ;
00666     }
00667 
00668     NanostackLockGuard lock;
00669 
00670     ns_address_t ns_address;
00671     ns_address.type = ADDRESS_IPV6;
00672     memcpy(ns_address.address, addr_field, sizeof ns_address.address);
00673     ns_address.identifier = address.get_port();
00674     nsapi_error_t ret;
00675     int retcode = ::socket_bind(socket->socket_id, &ns_address);
00676 
00677     if (retcode == 0) {
00678         ret = NSAPI_ERROR_OK ;
00679     } else {
00680         ret = NSAPI_ERROR_PARAMETER ;
00681     }
00682 
00683     tr_debug("socket_bind(socket=%p) sock_id=%d, retcode=%i, ret=%i", socket, socket->socket_id, retcode, ret);
00684 
00685     return ret;
00686 }
00687 
00688 nsapi_error_t NanostackInterface::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
00689 {
00690     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00691     if (handle == NULL) {
00692         MBED_ASSERT(false);
00693         return NSAPI_ERROR_NO_SOCKET ;
00694     }
00695 
00696     nsapi_error_t ret;
00697 
00698     NanostackLockGuard lock;
00699 
00700     if (::socket_setsockopt(socket->socket_id, level, optname, optval, optlen) == 0) {
00701         ret = NSAPI_ERROR_OK ;
00702     } else {
00703         ret = NSAPI_ERROR_PARAMETER ;
00704     }
00705 
00706     return ret;
00707 }
00708 
00709 nsapi_error_t NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
00710 {
00711     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00712     if (handle == NULL) {
00713         MBED_ASSERT(false);
00714         return NSAPI_ERROR_NO_SOCKET ;
00715     }
00716 
00717     nsapi_error_t ret;
00718 
00719     NanostackLockGuard lock;
00720 
00721     uint16_t optlen16 = *optlen;
00722     if (::socket_getsockopt(socket->socket_id, level, optname, optval, &optlen16) == 0) {
00723         ret = NSAPI_ERROR_OK ;
00724         *optlen = optlen16;
00725     } else {
00726         ret = NSAPI_ERROR_PARAMETER ;
00727     }
00728 
00729     return ret;
00730 }
00731 
00732 nsapi_error_t NanostackInterface::socket_listen(void *handle, int backlog)
00733 {
00734     //Check if socket exists
00735     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00736     if (handle == NULL) {
00737         MBED_ASSERT(false);
00738         return NSAPI_ERROR_NO_SOCKET ;
00739     }
00740 
00741     nsapi_error_t ret = NSAPI_ERROR_OK ;
00742 
00743     NanostackLockGuard lock;
00744 
00745     if(::socket_listen(socket->socket_id, backlog) < 0) {
00746         ret = NSAPI_ERROR_PARAMETER ;
00747     } else {
00748         socket->set_listening();
00749     }
00750 
00751     return ret;
00752 }
00753 
00754 nsapi_error_t NanostackInterface::socket_connect(void *handle, const SocketAddress &addr)
00755 {
00756     // Validate parameters
00757     NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
00758     nsapi_error_t ret;
00759     if (handle == NULL) {
00760         MBED_ASSERT(false);
00761         return NSAPI_ERROR_NO_SOCKET ;
00762     }
00763 
00764     NanostackLockGuard lock;
00765 
00766     if (addr.get_ip_version() != NSAPI_IPv6 ) {
00767         ret = NSAPI_ERROR_UNSUPPORTED ;
00768         goto out;
00769     }
00770 
00771     if (socket->closed()) {
00772         ret = NSAPI_ERROR_NO_CONNECTION ;
00773         goto out;
00774     }
00775 
00776     if (socket->is_connecting()) {
00777         ret = NSAPI_ERROR_ALREADY ;
00778         goto out;
00779     }
00780 
00781     if (socket->is_connected()) {
00782         ret = NSAPI_ERROR_IS_CONNECTED ;
00783         goto out;
00784     }
00785 
00786     ns_address_t ns_addr;
00787 
00788     convert_mbed_addr_to_ns(&ns_addr, &addr);
00789     if (::socket_connect(socket->socket_id, &ns_addr, 0) == 0) {
00790         if (socket->proto == SOCKET_TCP) {
00791             socket->set_connecting(&ns_addr);
00792             ret = NSAPI_ERROR_IN_PROGRESS ;
00793         } else {
00794             ret = NSAPI_ERROR_OK ;
00795         }
00796     } else {
00797         ret = NSAPI_ERROR_DEVICE_ERROR ;
00798     }
00799 
00800 out:
00801     tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
00802 
00803     return ret;
00804 }
00805 
00806 nsapi_error_t NanostackInterface::socket_accept(void *server, void **handle, SocketAddress *address)
00807 {
00808     NanostackSocket * socket = static_cast<NanostackSocket *>(server);
00809     NanostackSocket *accepted_sock = NULL;
00810     nsapi_error_t ret;
00811 
00812     if (handle == NULL) {
00813         MBED_ASSERT(false);
00814         return NSAPI_ERROR_NO_SOCKET ;
00815     }
00816 
00817     NanostackLockGuard lock;
00818 
00819     if (!socket->is_listening()) {
00820         ret = NSAPI_ERROR_PARAMETER ;
00821         goto out;
00822     }
00823 
00824     accepted_sock = new NanostackSocket(socket->proto);
00825     if (accepted_sock == NULL) {
00826         ret = NSAPI_ERROR_NO_MEMORY ;
00827         goto out;
00828     }
00829 
00830     ns_address_t ns_addr;
00831     int retcode;
00832     retcode = socket->accept(accepted_sock, &ns_addr);
00833     if (retcode < 0) {
00834         delete accepted_sock;
00835         if (retcode == NS_EWOULDBLOCK) {
00836             ret = NSAPI_ERROR_WOULD_BLOCK ;
00837         } else {
00838             ret = NSAPI_ERROR_DEVICE_ERROR ;
00839         }
00840         goto out;
00841     }
00842     ret = NSAPI_ERROR_OK ;
00843 
00844     if (address) {
00845         convert_ns_addr_to_mbed(address, &ns_addr);
00846     }
00847 
00848     *handle = accepted_sock;
00849 
00850 out:
00851     tr_debug("socket_accept() socket=%p, sock_id=%d, ret=%i", accepted_sock, accepted_sock ? accepted_sock->socket_id : -1, ret);
00852 
00853     return ret;
00854 }
00855 
00856 nsapi_size_or_error_t NanostackInterface::socket_send(void *handle, const void *data, nsapi_size_t size)
00857 {
00858     return do_sendto(handle, NULL, data, size);
00859 }
00860 
00861 nsapi_size_or_error_t NanostackInterface::socket_recv(void *handle, void *data, nsapi_size_t size)
00862 {
00863     return socket_recvfrom(handle, NULL, data, size);
00864 }
00865 
00866 void NanostackInterface::socket_attach(void *handle, void (*callback)(void *), void *id)
00867 {
00868     // Validate parameters
00869     NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
00870     if (handle == NULL) {
00871         MBED_ASSERT(false);
00872         return;
00873     }
00874 
00875     NanostackLockGuard lock;
00876 
00877     socket->callback = callback;
00878     socket->callback_data = id;
00879 
00880     tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id);
00881 }