init
Embed:
(wiki syntax)
Show/hide line numbers
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 13:24:59 by
1.7.2