Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackInterface.cpp Source File

NanostackInterface.cpp

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