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