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