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