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