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.
Dependencies: nRF51_Vdd TextLCD BME280
Nanostack.cpp
00001 /* 00002 * Copyright (c) 2016-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* Nanostack implementation of NetworkSocketAPI */ 00019 00020 #include "Nanostack.h" 00021 #include "NanostackLockGuard.h" 00022 00023 #include "ns_address.h" 00024 #include "nsdynmemLIB.h" 00025 #include "eventOS_scheduler.h" 00026 #include "eventOS_event_timer.h" 00027 #include "randLIB.h" 00028 #include "ip6string.h" 00029 00030 #include "mesh_system.h" // from inside mbed-mesh-api 00031 #include "socket_api.h" 00032 #include "net_interface.h" 00033 00034 // Uncomment to enable trace 00035 //#define HAVE_DEBUG 00036 #include "ns_trace.h" 00037 #define TRACE_GROUP "nsif" 00038 00039 #define NS_INTERFACE_SOCKETS_MAX 16 //same as NanoStack SOCKET_MAX 00040 00041 #define MALLOC ns_dyn_mem_alloc 00042 #define FREE ns_dyn_mem_free 00043 00044 // Socket state progressions: 00045 // UDP: UNOPENED -> DATAGRAM 00046 // TCP client: UNOPENED -> OPENED -> CONNECTING -> STREAM -> CLOSED 00047 // TCP server: UNOPENED -> OPENED -> LISTENING 00048 // TCP accept: UNOPENED -> STREAM -> CLOSED 00049 enum socket_mode_t { 00050 SOCKET_MODE_UNOPENED, // No socket ID 00051 SOCKET_MODE_DATAGRAM, // Socket is datagram type 00052 SOCKET_MODE_OPENED, // Socket ID but no assigned use yet 00053 SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet 00054 SOCKET_MODE_STREAM, // Socket has an open stream 00055 SOCKET_MODE_CLOSED, // Socket is closed and resources are freed 00056 SOCKET_MODE_LISTENING, // Socket is listening for connections 00057 }; 00058 00059 #define CALL_EVENT 0x12 00060 00061 class NanostackSocket { 00062 public: 00063 static void socket_callback(void *cb); 00064 static void* operator new(std::size_t sz); 00065 static void operator delete(void* ptr); 00066 00067 NanostackSocket(int8_t protocol); 00068 ~NanostackSocket(void); 00069 bool open(void); 00070 int accept(NanostackSocket *accepted_socket, ns_address_t *addr); 00071 void close(void); 00072 bool closed(void) {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 Nanostack::Nanostack() 00448 : call_event_tasklet(-1) 00449 { 00450 mesh_system_init(); 00451 } 00452 00453 void Nanostack::call_event_tasklet_main(arm_event_s *event) 00454 { 00455 if (event->event_id == CALL_EVENT) { 00456 nanostack_callback *cb = static_cast<nanostack_callback *>(event->data_ptr); 00457 cb->callback(); 00458 delete cb; 00459 } 00460 } 00461 00462 nsapi_error_t Nanostack::call_in(int delay, mbed::Callback<void()> func) 00463 { 00464 if (call_event_tasklet < 0) { 00465 call_event_tasklet = eventOS_event_handler_create(&call_event_tasklet_main, 0); 00466 if (call_event_tasklet < 0) { 00467 return NSAPI_ERROR_NO_MEMORY ; 00468 } 00469 } 00470 00471 nanostack_callback *cb = new nanostack_callback; 00472 if (!cb) { 00473 return NSAPI_ERROR_NO_MEMORY ; 00474 } 00475 00476 cb->callback = func; 00477 00478 arm_event_s event; 00479 00480 event.sender = call_event_tasklet, 00481 event.event_id = CALL_EVENT, 00482 event.receiver = call_event_tasklet, 00483 event.data_ptr = cb; 00484 event.event_type = APPLICATION_EVENT; 00485 event.priority = ARM_LIB_LOW_PRIORITY_EVENT; 00486 00487 if (delay) { 00488 uint32_t ticks = eventOS_event_timer_ms_to_ticks(delay); 00489 if (!eventOS_event_send_in(&event, ticks)) { 00490 delete cb; 00491 return NSAPI_ERROR_NO_MEMORY ; 00492 } 00493 } else { 00494 if (eventOS_event_send(&event) < 0) { 00495 delete cb; 00496 return NSAPI_ERROR_NO_MEMORY ; 00497 } 00498 } 00499 00500 return NSAPI_ERROR_OK ; 00501 } 00502 00503 Nanostack::call_in_callback_cb_t Nanostack::get_call_in_callback() 00504 { 00505 call_in_callback_cb_t cb(this, &Nanostack::call_in); 00506 return cb; 00507 } 00508 00509 const char * Nanostack::get_ip_address() 00510 { 00511 NanostackLockGuard lock; 00512 00513 for (int if_id = 1; if_id <= 127; if_id++) { 00514 uint8_t address[16]; 00515 int ret = arm_net_address_get(if_id, ADDR_IPV6_GP, address); 00516 if (ret == 0) { 00517 ip6tos(address, text_ip_address); 00518 return text_ip_address; 00519 } 00520 } 00521 // Must result a valid IPv6 address 00522 // For gethostbyname() to detect IP version. 00523 return "::"; 00524 } 00525 00526 nsapi_error_t Nanostack::socket_open(void **handle, nsapi_protocol_t protocol) 00527 { 00528 // Validate parameters 00529 if (NULL == handle) { 00530 MBED_ASSERT(false); 00531 return NSAPI_ERROR_NO_SOCKET ; 00532 } 00533 int8_t ns_proto; 00534 if (NSAPI_UDP == protocol) { 00535 ns_proto = SOCKET_UDP; 00536 } else if (NSAPI_TCP == protocol) { 00537 ns_proto = SOCKET_TCP; 00538 } else { 00539 MBED_ASSERT(false); 00540 return NSAPI_ERROR_UNSUPPORTED ; 00541 } 00542 *handle = (void*)NULL; 00543 00544 NanostackLockGuard lock; 00545 00546 NanostackSocket * socket = new NanostackSocket(ns_proto); 00547 if (socket == NULL) { 00548 tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY ); 00549 return NSAPI_ERROR_NO_MEMORY ; 00550 } 00551 if (!socket->open()) { 00552 delete socket; 00553 tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY ); 00554 return NSAPI_ERROR_NO_MEMORY ; 00555 } 00556 *handle = (void*)socket; 00557 00558 tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id); 00559 00560 return NSAPI_ERROR_OK ; 00561 } 00562 00563 nsapi_error_t Nanostack::socket_close(void *handle) 00564 { 00565 NanostackLockGuard lock; 00566 // Validate parameters 00567 NanostackSocket * socket = static_cast<NanostackSocket *>(handle); 00568 if (NULL == handle) { 00569 MBED_ASSERT(false); 00570 return NSAPI_ERROR_NO_SOCKET ; 00571 } 00572 tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id); 00573 00574 delete socket; 00575 00576 return 0; 00577 00578 } 00579 00580 nsapi_size_or_error_t Nanostack::do_sendto(void *handle, const ns_address_t *address, const void *data, nsapi_size_t size) 00581 { 00582 // Validate parameters 00583 NanostackSocket * socket = static_cast<NanostackSocket *>(handle); 00584 if (handle == NULL) { 00585 MBED_ASSERT(false); 00586 return NSAPI_ERROR_NO_SOCKET ; 00587 } 00588 00589 nsapi_size_or_error_t ret; 00590 00591 NanostackLockGuard lock; 00592 00593 if (socket->closed() || (!address && !socket->is_connected())) { 00594 ret = NSAPI_ERROR_NO_CONNECTION ; 00595 goto out; 00596 } 00597 00598 if (address && socket->proto == SOCKET_TCP) { 00599 tr_error("socket_sendto() not supported with TCP!"); 00600 ret = NSAPI_ERROR_IS_CONNECTED ; 00601 goto out; 00602 } 00603 00604 int retcode; 00605 #if 0 00606 retcode = ::socket_sendto(socket->socket_id, address, 00607 data, size); 00608 #else 00609 // Use sendmsg purely to get the new return style 00610 // of returning data written rather than 0 on success, 00611 // which means TCP can do partial writes. (Sadly, 00612 // it's the only call which takes flags so we can 00613 // leave the NS_MSG_LEGACY0 flag clear). 00614 ns_msghdr_t msg; 00615 ns_iovec_t iov; 00616 iov.iov_base = const_cast<void *>(data); 00617 iov.iov_len = size; 00618 msg.msg_name = const_cast<ns_address_t *>(address); 00619 msg.msg_namelen = address ? sizeof *address : 0; 00620 msg.msg_iov = &iov; 00621 msg.msg_iovlen = 1; 00622 msg.msg_control = NULL; 00623 msg.msg_controllen = 0; 00624 retcode = ::socket_sendmsg(socket->socket_id, &msg, 0); 00625 #endif 00626 00627 /* 00628 * \return length if entire amount written (which could be 0) 00629 * \return value >0 and <length if partial amount written (stream only) 00630 * \return NS_EWOULDBLOCK if nothing written due to lack of queue space. 00631 * \return -1 Invalid socket ID or message structure. 00632 * \return -2 Socket memory allocation fail. 00633 * \return -3 TCP state not established or address scope not defined . 00634 * \return -4 Socket TX process busy or unknown interface. 00635 * \return -5 Socket not connected 00636 * \return -6 Packet too short (ICMP raw socket error). 00637 * */ 00638 if (retcode == NS_EWOULDBLOCK) { 00639 ret = NSAPI_ERROR_WOULD_BLOCK ; 00640 } else if (retcode < 0) { 00641 tr_error("socket_sendmsg: error=%d", retcode); 00642 ret = NSAPI_ERROR_DEVICE_ERROR ; 00643 } else { 00644 ret = retcode; 00645 } 00646 00647 out: 00648 tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); 00649 00650 return ret; 00651 } 00652 00653 nsapi_size_or_error_t Nanostack::socket_sendto(void *handle, const SocketAddress &address, const void *data, nsapi_size_t size) 00654 { 00655 if (address.get_ip_version() != NSAPI_IPv6 ) { 00656 return NSAPI_ERROR_UNSUPPORTED ; 00657 } 00658 00659 ns_address_t ns_address; 00660 convert_mbed_addr_to_ns(&ns_address, &address); 00661 /*No lock gaurd needed here as do_sendto() will handle locks.*/ 00662 return do_sendto(handle, &ns_address, data, size); 00663 } 00664 00665 nsapi_size_or_error_t Nanostack::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size) 00666 { 00667 // Validate parameters 00668 NanostackSocket *socket = static_cast<NanostackSocket *>(handle); 00669 if (handle == NULL) { 00670 MBED_ASSERT(false); 00671 return NSAPI_ERROR_NO_SOCKET ; 00672 } 00673 00674 nsapi_size_or_error_t ret; 00675 00676 NanostackLockGuard lock; 00677 00678 if (socket->closed()) { 00679 ret = NSAPI_ERROR_NO_CONNECTION ; 00680 goto out; 00681 } 00682 00683 ns_address_t ns_address; 00684 00685 int retcode; 00686 retcode = ::socket_recvfrom(socket->socket_id, buffer, size, 0, &ns_address); 00687 00688 if (retcode == NS_EWOULDBLOCK) { 00689 ret = NSAPI_ERROR_WOULD_BLOCK ; 00690 } else if (retcode < 0) { 00691 ret = NSAPI_ERROR_PARAMETER ; 00692 } else { 00693 ret = retcode; 00694 if (address != NULL) { 00695 convert_ns_addr_to_mbed(address, &ns_address); 00696 } 00697 } 00698 00699 out: 00700 if (address) { 00701 tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i, addr=[%s]:%i", socket, socket->socket_id, ret, 00702 trace_ipv6(address->get_ip_bytes()), address->get_port()); 00703 } else { 00704 tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); 00705 } 00706 00707 return ret; 00708 } 00709 00710 nsapi_error_t Nanostack::socket_bind(void *handle, const SocketAddress &address) 00711 { 00712 // Validate parameters 00713 NanostackSocket *socket = static_cast<NanostackSocket *>(handle); 00714 if (handle == NULL) { 00715 MBED_ASSERT(false); 00716 return NSAPI_ERROR_NO_SOCKET ; 00717 } 00718 00719 const void *addr_field; 00720 switch (address.get_ip_version()) { 00721 case NSAPI_IPv6 : 00722 addr_field = address.get_ip_bytes(); 00723 break; 00724 case NSAPI_UNSPEC : 00725 addr_field = &ns_in6addr_any; 00726 break; 00727 default: 00728 return NSAPI_ERROR_UNSUPPORTED ; 00729 } 00730 00731 NanostackLockGuard lock; 00732 00733 ns_address_t ns_address; 00734 ns_address.type = ADDRESS_IPV6; 00735 memcpy(ns_address.address, addr_field, sizeof ns_address.address); 00736 ns_address.identifier = address.get_port(); 00737 nsapi_error_t ret; 00738 int retcode = ::socket_bind(socket->socket_id, &ns_address); 00739 00740 if (retcode == 0) { 00741 ret = NSAPI_ERROR_OK ; 00742 } else { 00743 ret = NSAPI_ERROR_PARAMETER ; 00744 } 00745 00746 tr_debug("socket_bind(socket=%p) sock_id=%d, retcode=%i, ret=%i", socket, socket->socket_id, retcode, ret); 00747 00748 return ret; 00749 } 00750 00751 nsapi_error_t Nanostack::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen) 00752 { 00753 NanostackSocket *socket = static_cast<NanostackSocket *>(handle); 00754 if (handle == NULL) { 00755 MBED_ASSERT(false); 00756 return NSAPI_ERROR_NO_SOCKET ; 00757 } 00758 00759 NanostackLockGuard lock; 00760 00761 ns_ipv6_mreq_t ns_mreq; 00762 00763 if (level == NSAPI_SOCKET ) { 00764 switch (optname) { 00765 case NSAPI_ADD_MEMBERSHIP : 00766 case NSAPI_DROP_MEMBERSHIP : { 00767 if (optlen != sizeof(nsapi_ip_mreq_t)) { 00768 return NSAPI_ERROR_PARAMETER ; 00769 } 00770 const nsapi_ip_mreq_t *imr = static_cast<const nsapi_ip_mreq_t *>(optval); 00771 00772 /* Check address types are IPv6, or unspecified for interface */ 00773 if (imr->imr_multiaddr.version != NSAPI_IPv6 || 00774 (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != NSAPI_IPv6 )) { 00775 return NSAPI_ERROR_PARAMETER ; 00776 } 00777 00778 /* Convert all parameters to Nanostack native, and proceed with setsockopt */ 00779 memcpy(ns_mreq.ipv6mr_multiaddr, imr->imr_multiaddr.bytes, 16); 00780 if (imr->imr_interface.version == NSAPI_UNSPEC || memcmp(imr->imr_interface.bytes, ns_in6addr_any, 16) == 0) { 00781 ns_mreq.ipv6mr_interface = 0; 00782 } else { 00783 // If this fails, Nanostack will itself fault the invalid -1 interface ID 00784 ns_mreq.ipv6mr_interface = find_interface_by_address(imr->imr_interface.bytes); 00785 } 00786 00787 level = SOCKET_IPPROTO_IPV6; 00788 optname = optname == NSAPI_ADD_MEMBERSHIP ? SOCKET_IPV6_JOIN_GROUP : SOCKET_IPV6_LEAVE_GROUP; 00789 optval = &ns_mreq; 00790 optlen = sizeof ns_mreq; 00791 break; 00792 } 00793 default: 00794 return NSAPI_ERROR_UNSUPPORTED ; 00795 } 00796 } 00797 00798 int retcode = ::socket_setsockopt(socket->socket_id, level, optname, optval, optlen); 00799 if (retcode == 0) { 00800 return NSAPI_ERROR_OK ; 00801 } else if (retcode == -2) { 00802 return NSAPI_ERROR_UNSUPPORTED ; 00803 } else { 00804 return NSAPI_ERROR_PARAMETER ; 00805 } 00806 } 00807 00808 nsapi_error_t Nanostack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen) 00809 { 00810 NanostackSocket *socket = static_cast<NanostackSocket *>(handle); 00811 if (handle == NULL) { 00812 MBED_ASSERT(false); 00813 return NSAPI_ERROR_NO_SOCKET ; 00814 } 00815 00816 NanostackLockGuard lock; 00817 00818 uint16_t optlen16 = *optlen; 00819 00820 int retcode = ::socket_getsockopt(socket->socket_id, level, optname, optval, &optlen16); 00821 if (retcode == 0) { 00822 *optlen = optlen16; 00823 return NSAPI_ERROR_OK ; 00824 } else if (retcode == -2) { 00825 return NSAPI_ERROR_UNSUPPORTED ; 00826 } else { 00827 return NSAPI_ERROR_PARAMETER ; 00828 } 00829 } 00830 00831 nsapi_error_t Nanostack::socket_listen(void *handle, int backlog) 00832 { 00833 //Check if socket exists 00834 NanostackSocket *socket = static_cast<NanostackSocket *>(handle); 00835 if (handle == NULL) { 00836 MBED_ASSERT(false); 00837 return NSAPI_ERROR_NO_SOCKET ; 00838 } 00839 00840 nsapi_error_t ret = NSAPI_ERROR_OK ; 00841 00842 NanostackLockGuard lock; 00843 00844 if(::socket_listen(socket->socket_id, backlog) < 0) { 00845 ret = NSAPI_ERROR_PARAMETER ; 00846 } else { 00847 socket->set_listening(); 00848 } 00849 00850 return ret; 00851 } 00852 00853 nsapi_error_t Nanostack::socket_connect(void *handle, const SocketAddress &addr) 00854 { 00855 // Validate parameters 00856 NanostackSocket *socket = static_cast<NanostackSocket *>(handle); 00857 nsapi_error_t ret; 00858 if (handle == NULL) { 00859 MBED_ASSERT(false); 00860 return NSAPI_ERROR_NO_SOCKET ; 00861 } 00862 00863 NanostackLockGuard lock; 00864 00865 if (addr.get_ip_version() != NSAPI_IPv6 ) { 00866 ret = NSAPI_ERROR_UNSUPPORTED ; 00867 goto out; 00868 } 00869 00870 if (socket->closed()) { 00871 ret = NSAPI_ERROR_NO_CONNECTION ; 00872 goto out; 00873 } 00874 00875 if (socket->is_connecting()) { 00876 ret = NSAPI_ERROR_ALREADY ; 00877 goto out; 00878 } 00879 00880 if (socket->is_connected()) { 00881 ret = NSAPI_ERROR_IS_CONNECTED ; 00882 goto out; 00883 } 00884 00885 ns_address_t ns_addr; 00886 00887 convert_mbed_addr_to_ns(&ns_addr, &addr); 00888 if (::socket_connect(socket->socket_id, &ns_addr, 0) == 0) { 00889 if (socket->proto == SOCKET_TCP) { 00890 socket->set_connecting(&ns_addr); 00891 ret = NSAPI_ERROR_IN_PROGRESS ; 00892 } else { 00893 ret = NSAPI_ERROR_OK ; 00894 } 00895 } else { 00896 ret = NSAPI_ERROR_DEVICE_ERROR ; 00897 } 00898 00899 out: 00900 tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret); 00901 00902 return ret; 00903 } 00904 00905 nsapi_error_t Nanostack::socket_accept(void *server, void **handle, SocketAddress *address) 00906 { 00907 NanostackSocket * socket = static_cast<NanostackSocket *>(server); 00908 NanostackSocket *accepted_sock = NULL; 00909 nsapi_error_t ret; 00910 00911 if (handle == NULL) { 00912 MBED_ASSERT(false); 00913 return NSAPI_ERROR_NO_SOCKET ; 00914 } 00915 00916 NanostackLockGuard lock; 00917 00918 if (!socket->is_listening()) { 00919 ret = NSAPI_ERROR_PARAMETER ; 00920 goto out; 00921 } 00922 00923 accepted_sock = new NanostackSocket(socket->proto); 00924 if (accepted_sock == NULL) { 00925 ret = NSAPI_ERROR_NO_MEMORY ; 00926 goto out; 00927 } 00928 00929 ns_address_t ns_addr; 00930 int retcode; 00931 retcode = socket->accept(accepted_sock, &ns_addr); 00932 if (retcode < 0) { 00933 delete accepted_sock; 00934 if (retcode == NS_EWOULDBLOCK) { 00935 ret = NSAPI_ERROR_WOULD_BLOCK ; 00936 } else { 00937 ret = NSAPI_ERROR_DEVICE_ERROR ; 00938 } 00939 goto out; 00940 } 00941 ret = NSAPI_ERROR_OK ; 00942 00943 if (address) { 00944 convert_ns_addr_to_mbed(address, &ns_addr); 00945 } 00946 00947 *handle = accepted_sock; 00948 00949 out: 00950 tr_debug("socket_accept() socket=%p, sock_id=%d, ret=%i", accepted_sock, accepted_sock ? accepted_sock->socket_id : -1, ret); 00951 00952 return ret; 00953 } 00954 00955 nsapi_size_or_error_t Nanostack::socket_send(void *handle, const void *data, nsapi_size_t size) 00956 { 00957 return do_sendto(handle, NULL, data, size); 00958 } 00959 00960 nsapi_size_or_error_t Nanostack::socket_recv(void *handle, void *data, nsapi_size_t size) 00961 { 00962 return socket_recvfrom(handle, NULL, data, size); 00963 } 00964 00965 void Nanostack::socket_attach(void *handle, void (*callback)(void *), void *id) 00966 { 00967 // Validate parameters 00968 NanostackSocket * socket = static_cast<NanostackSocket *>(handle); 00969 if (handle == NULL) { 00970 MBED_ASSERT(false); 00971 return; 00972 } 00973 00974 NanostackLockGuard lock; 00975 00976 socket->callback = callback; 00977 socket->callback_data = id; 00978 00979 tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id); 00980 } 00981 00982 Nanostack &Nanostack::get_instance() { 00983 static Nanostack nanostack; 00984 return nanostack; 00985 } 00986 00987 // This works as long as it's not ever set to something which corresponds to 00988 // a macro defined as a non-integer. Eg `#define Nanostack "Foo"` 00989 #define NANOSTACK 0x99119911 00990 #if MBED_CONF_NSAPI_DEFAULT_STACK == NANOSTACK 00991 #undef NANOSTACK 00992 OnboardNetworkStack &OnboardNetworkStack::get_default_instance() { 00993 return Nanostack::get_instance(); 00994 } 00995 #endif
Generated on Tue Jul 12 2022 15:15:53 by
