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