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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
LWIPStack.cpp
00001 /* LWIP implementation of NSAPI NetworkStack 00002 * Copyright (c) 2017 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 #include "nsapi.h" 00017 #include "mbed_interface.h" 00018 #include "mbed_assert.h" 00019 #include "Semaphore.h" 00020 #include <stdio.h> 00021 #include <stdbool.h> 00022 #include <string.h> 00023 00024 #include "lwip/opt.h" 00025 #include "lwip/api.h" 00026 #include "lwip/inet.h" 00027 #include "lwip/netif.h" 00028 #include "lwip/dhcp.h" 00029 #include "lwip/tcpip.h" 00030 #include "lwip/tcp.h" 00031 #include "lwip/ip.h" 00032 #include "lwip/mld6.h" 00033 #include "lwip/igmp.h" 00034 #include "lwip/dns.h" 00035 #include "lwip/udp.h" 00036 #include "lwip/raw.h" 00037 #include "lwip/netif.h" 00038 #include "lwip/lwip_errno.h" 00039 #include "lwip-sys/arch/sys_arch.h" 00040 00041 #include "LWIPStack.h" 00042 #include "lwip_tools.h" 00043 00044 #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS 00045 #define LWIP_SOCKET_MAX_MEMBERSHIPS 4 00046 #endif 00047 00048 void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) 00049 { 00050 // Filter send minus events 00051 if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) { 00052 return; 00053 } 00054 00055 LWIP &lwip = LWIP::get_instance(); 00056 lwip.adaptation.lock(); 00057 00058 if (eh == NETCONN_EVT_RCVPLUS && nc->state == NETCONN_NONE) { 00059 lwip._event_flag.set(TCP_CLOSED_FLAG); 00060 } 00061 00062 for (int i = 0; i < MEMP_NUM_NETCONN; i++) { 00063 if (lwip.arena[i].in_use 00064 && lwip.arena[i].conn == nc 00065 && lwip.arena[i].cb) { 00066 lwip.arena[i].cb(lwip.arena[i].data); 00067 } 00068 } 00069 00070 lwip.adaptation.unlock(); 00071 } 00072 00073 void LWIP::tcpip_init_irq(void *eh) 00074 { 00075 static_cast<rtos::Semaphore *>(eh)->release(); 00076 sys_tcpip_thread_set(); 00077 } 00078 00079 /* LWIP network stack implementation */ 00080 LWIP::LWIP() 00081 { 00082 default_interface = NULL; 00083 tcpip_thread_id = NULL; 00084 00085 // Seed lwip random 00086 lwip_seed_random(); 00087 00088 // Initialise TCP sequence number 00089 uint32_t tcp_isn_secret[4]; 00090 for (int i = 0; i < 4; i++) { 00091 tcp_isn_secret[i] = LWIP_RAND(); 00092 } 00093 lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret); 00094 00095 rtos::Semaphore tcpip_inited; 00096 00097 tcpip_init(&LWIP::tcpip_init_irq, &tcpip_inited); 00098 tcpip_inited.acquire(); 00099 00100 // Zero out socket set 00101 arena_init(); 00102 } 00103 00104 nsapi_error_t LWIP::get_dns_server(int index, SocketAddress *address, const char *interface_name) 00105 { 00106 int dns_entries = 0; 00107 00108 for (int i = 0; i < DNS_MAX_SERVERS; i++) { 00109 const ip_addr_t *ip_addr = dns_getserver(i, interface_name); 00110 if (!ip_addr_isany(ip_addr)) { 00111 if (index == dns_entries) { 00112 nsapi_addr_t addr; 00113 convert_lwip_addr_to_mbed(&addr, ip_addr); 00114 address->set_addr(addr); 00115 return NSAPI_ERROR_OK ; 00116 } 00117 dns_entries++; 00118 } 00119 } 00120 return NSAPI_ERROR_NO_ADDRESS ; 00121 } 00122 00123 nsapi_error_t LWIP::add_dns_server(const SocketAddress &address, const char *interface_name) 00124 { 00125 int index; 00126 nsapi_addr_t addr = address.get_addr(); 00127 const ip_addr_t *ip_addr_move; 00128 ip_addr_t ip_addr; 00129 00130 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00131 return NSAPI_ERROR_PARAMETER ; 00132 } 00133 00134 if (ip_addr_isany(&ip_addr)) { 00135 return NSAPI_ERROR_NO_ADDRESS ; 00136 } 00137 00138 if (interface_name == NULL) { 00139 for (index = DNS_MAX_SERVERS - 1; index > 0; index--) { 00140 ip_addr_move = dns_getserver(index - 1, NULL); 00141 if (!ip_addr_isany(ip_addr_move)) { 00142 dns_setserver(index, ip_addr_move, NULL); 00143 } 00144 } 00145 dns_setserver(0, &ip_addr, NULL); 00146 } else { 00147 for (index = DNS_MAX_SERVERS - 1; index > 0; index--) { 00148 ip_addr_move = dns_get_interface_server(index - 1, interface_name); 00149 if (!ip_addr_isany(ip_addr_move)) { 00150 dns_add_interface_server(index, interface_name, ip_addr_move); 00151 } 00152 } 00153 dns_add_interface_server(0, interface_name, &ip_addr); 00154 } 00155 return NSAPI_ERROR_OK ; 00156 } 00157 00158 void LWIP::tcpip_thread_callback(void *ptr) 00159 { 00160 lwip_callback *cb = static_cast<lwip_callback *>(ptr); 00161 00162 if (cb->delay) { 00163 sys_timeout(cb->delay, LWIP::tcpip_thread_callback, ptr); 00164 cb->delay = 0; 00165 } else { 00166 cb->callback(); 00167 delete cb; 00168 } 00169 } 00170 00171 nsapi_error_t LWIP::call_in(int delay, mbed::Callback<void()> func) 00172 { 00173 lwip_callback *cb = new (std::nothrow) lwip_callback; 00174 if (!cb) { 00175 return NSAPI_ERROR_NO_MEMORY ; 00176 } 00177 00178 cb->delay = delay; 00179 cb->callback = func; 00180 00181 if (tcpip_callback_with_block(LWIP::tcpip_thread_callback, cb, 1) != ERR_OK) { 00182 return NSAPI_ERROR_NO_MEMORY ; 00183 } 00184 00185 return NSAPI_ERROR_OK ; 00186 } 00187 00188 LWIP::call_in_callback_cb_t LWIP::get_call_in_callback() 00189 { 00190 call_in_callback_cb_t cb(this, &LWIP::call_in); 00191 return cb; 00192 } 00193 00194 const char *LWIP::get_ip_address() 00195 { 00196 if (!default_interface) { 00197 return NULL; 00198 } 00199 00200 const ip_addr_t *addr = get_ip_addr(true, &default_interface->netif); 00201 00202 if (!addr) { 00203 return NULL; 00204 } 00205 #if LWIP_IPV6 00206 if (IP_IS_V6(addr)) { 00207 return ip6addr_ntoa_r(ip_2_ip6(addr), ip_address, sizeof(ip_address)); 00208 } 00209 #endif 00210 #if LWIP_IPV4 00211 if (IP_IS_V4(addr)) { 00212 return ip4addr_ntoa_r(ip_2_ip4(addr), ip_address, sizeof(ip_address)); 00213 } 00214 #endif 00215 #if LWIP_IPV6 && LWIP_IPV4 00216 return NULL; 00217 #endif 00218 } 00219 00220 nsapi_error_t LWIP::get_ip_address_if(SocketAddress *address, const char *interface_name) 00221 { 00222 if (!address) { 00223 return NSAPI_ERROR_PARAMETER ; 00224 } 00225 00226 const ip_addr_t *addr; 00227 00228 if (interface_name == NULL) { 00229 addr = get_ip_addr(true, &default_interface->netif); 00230 } else { 00231 addr = get_ip_addr(true, netif_find(interface_name)); 00232 } 00233 #if LWIP_IPV6 00234 if (IP_IS_V6(addr)) { 00235 char buf[NSAPI_IPv6_SIZE]; 00236 address->set_ip_address(ip6addr_ntoa_r(ip_2_ip6(addr), buf, NSAPI_IPv6_SIZE)); 00237 return NSAPI_ERROR_OK ; 00238 } 00239 #endif 00240 #if LWIP_IPV4 00241 if (IP_IS_V4(addr)) { 00242 char buf[NSAPI_IPv4_SIZE]; 00243 address->set_ip_address(ip4addr_ntoa_r(ip_2_ip4(addr), buf, NSAPI_IPv4_SIZE)); 00244 return NSAPI_ERROR_OK ; 00245 } 00246 #endif 00247 return NSAPI_ERROR_UNSUPPORTED ; 00248 } 00249 00250 nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) 00251 { 00252 // check if network is connected 00253 // if (lwip_connected == NSAPI_STATUS_DISCONNECTED) { 00254 // return NSAPI_ERROR_NO_CONNECTION; 00255 // } 00256 00257 // allocate a socket 00258 struct mbed_lwip_socket *s = arena_alloc(); 00259 if (!s) { 00260 return NSAPI_ERROR_NO_SOCKET ; 00261 } 00262 00263 enum netconn_type netconntype; 00264 if (proto == NSAPI_TCP ) { 00265 netconntype = NETCONN_TCP; 00266 } else if (proto == NSAPI_UDP ) { 00267 netconntype = NETCONN_UDP; 00268 } else if (proto == NSAPI_ICMP ) { 00269 netconntype = NETCONN_RAW; 00270 } else { 00271 return NSAPI_ERROR_UNSUPPORTED ; 00272 } 00273 00274 #if LWIP_IPV6 00275 // Enable IPv6 (or dual-stack) 00276 netconntype = (enum netconn_type)(netconntype | NETCONN_TYPE_IPV6); 00277 #endif 00278 00279 if (proto == NSAPI_ICMP ) { 00280 s->conn = netconn_new_with_proto_and_callback(NETCONN_RAW, 00281 (u8_t)IP_PROTO_ICMP, &LWIP::socket_callback); 00282 } else { 00283 s->conn = netconn_new_with_callback(netconntype, &LWIP::socket_callback); 00284 } 00285 00286 if (!s->conn) { 00287 arena_dealloc(s); 00288 return NSAPI_ERROR_NO_SOCKET ; 00289 } 00290 00291 netconn_set_recvtimeout(s->conn, 1); 00292 *(struct mbed_lwip_socket **)handle = s; 00293 return 0; 00294 } 00295 00296 nsapi_error_t LWIP::socket_close(nsapi_socket_t handle) 00297 { 00298 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00299 #if LWIP_TCP 00300 /* Check if TCP FSM is in ESTABLISHED state. 00301 * Then give extra time for connection close handshaking until TIME_WAIT state. 00302 * The purpose is to prevent eth/wifi driver stop and FIN ACK corrupt. 00303 * This may happend if network interface disconnect follows immediately after socket_close.*/ 00304 if (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_TCP && s->conn->pcb.tcp->state == ESTABLISHED) { 00305 _event_flag.clear(TCP_CLOSED_FLAG); 00306 netconn_shutdown(s->conn, false, true); 00307 _event_flag.wait_any(TCP_CLOSED_FLAG, TCP_CLOSE_TIMEOUT); 00308 } 00309 #endif 00310 pbuf_free(s->buf); 00311 err_t err = netconn_delete(s->conn); 00312 arena_dealloc(s); 00313 return err_remap(err); 00314 } 00315 00316 nsapi_error_t LWIP::socket_bind(nsapi_socket_t handle, const SocketAddress &address) 00317 { 00318 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00319 ip_addr_t ip_addr; 00320 00321 if ( 00322 #if LWIP_TCP 00323 (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || 00324 #endif 00325 (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { 00326 return NSAPI_ERROR_PARAMETER ; 00327 } 00328 00329 nsapi_addr_t addr = address.get_addr(); 00330 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00331 return NSAPI_ERROR_PARAMETER ; 00332 } 00333 00334 if (!ip_addr_isany_val(ip_addr) && !is_local_addr(&ip_addr)) { 00335 return NSAPI_ERROR_PARAMETER ; 00336 } 00337 00338 err_t err = netconn_bind(s->conn, &ip_addr, address.get_port()); 00339 return err_remap(err); 00340 } 00341 00342 nsapi_error_t LWIP::socket_listen(nsapi_socket_t handle, int backlog) 00343 { 00344 #if LWIP_TCP 00345 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00346 00347 if (s->conn->pcb.tcp->local_port == 0) { 00348 return NSAPI_ERROR_PARAMETER ; 00349 } 00350 00351 err_t err = netconn_listen_with_backlog(s->conn, backlog); 00352 return err_remap(err); 00353 #else 00354 return NSAPI_ERROR_UNSUPPORTED ; 00355 #endif 00356 } 00357 00358 nsapi_error_t LWIP::socket_connect(nsapi_socket_t handle, const SocketAddress &address) 00359 { 00360 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00361 ip_addr_t ip_addr; 00362 00363 nsapi_addr_t addr = address.get_addr(); 00364 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00365 return NSAPI_ERROR_PARAMETER ; 00366 } 00367 00368 netconn_set_nonblocking(s->conn, false); 00369 err_t err = netconn_connect(s->conn, &ip_addr, address.get_port()); 00370 netconn_set_nonblocking(s->conn, true); 00371 00372 return err_remap(err); 00373 } 00374 00375 nsapi_error_t LWIP::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address) 00376 { 00377 #if LWIP_TCP 00378 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)server; 00379 struct mbed_lwip_socket *ns = arena_alloc(); 00380 if (!ns) { 00381 return NSAPI_ERROR_NO_SOCKET ; 00382 } 00383 00384 if (s->conn->pcb.tcp->state != LISTEN) { 00385 return NSAPI_ERROR_PARAMETER ; 00386 } 00387 00388 err_t err = netconn_accept(s->conn, &ns->conn); 00389 if (err != ERR_OK) { 00390 arena_dealloc(ns); 00391 return err_remap(err); 00392 } 00393 00394 netconn_set_recvtimeout(ns->conn, 1); 00395 *(struct mbed_lwip_socket **)handle = ns; 00396 00397 ip_addr_t peer_addr; 00398 nsapi_addr_t addr; 00399 u16_t port; 00400 (void) netconn_peer(ns->conn, &peer_addr, &port); 00401 convert_lwip_addr_to_mbed(&addr, &peer_addr); 00402 00403 if (address) { 00404 address->set_addr(addr); 00405 address->set_port(port); 00406 } 00407 00408 netconn_set_nonblocking(ns->conn, true); 00409 00410 return 0; 00411 #else 00412 return NSAPI_ERROR_UNSUPPORTED ; 00413 #endif 00414 } 00415 00416 nsapi_size_or_error_t LWIP::socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size) 00417 { 00418 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00419 size_t bytes_written = 0; 00420 00421 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written); 00422 if (err != ERR_OK) { 00423 return err_remap(err); 00424 } 00425 00426 return (nsapi_size_or_error_t)bytes_written; 00427 } 00428 00429 nsapi_size_or_error_t LWIP::socket_recv(nsapi_socket_t handle, void *data, nsapi_size_t size) 00430 { 00431 #if LWIP_TCP 00432 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00433 00434 if (!s->buf) { 00435 err_t err = netconn_recv_tcp_pbuf(s->conn, &s->buf); 00436 s->offset = 0; 00437 00438 if (err != ERR_OK) { 00439 return err_remap(err); 00440 } 00441 } 00442 00443 u16_t recv = pbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); 00444 s->offset += recv; 00445 00446 if (s->offset >= s->buf->tot_len) { 00447 pbuf_free(s->buf); 00448 s->buf = 0; 00449 } 00450 00451 return recv; 00452 #else 00453 return NSAPI_ERROR_UNSUPPORTED ; 00454 #endif 00455 } 00456 00457 nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size) 00458 { 00459 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00460 ip_addr_t ip_addr; 00461 00462 nsapi_addr_t addr = address.get_addr(); 00463 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00464 return NSAPI_ERROR_PARAMETER ; 00465 } 00466 struct netif *netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx); 00467 if (!netif_) { 00468 netif_ = &default_interface->netif; 00469 } 00470 if (netif_) { 00471 if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr(netif_)) || 00472 (addr.version == NSAPI_IPv6 && !get_ipv6_addr(netif_) && !get_ipv6_link_local_addr(netif_))) { 00473 return NSAPI_ERROR_PARAMETER ; 00474 } 00475 } 00476 struct netbuf *buf = netbuf_new(); 00477 00478 err_t err = netbuf_ref(buf, data, (u16_t)size); 00479 if (err != ERR_OK) { 00480 netbuf_free(buf); 00481 return err_remap(err); 00482 } 00483 00484 err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port()); 00485 netbuf_delete(buf); 00486 if (err != ERR_OK) { 00487 return err_remap(err); 00488 } 00489 00490 return size; 00491 } 00492 00493 nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size) 00494 { 00495 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00496 struct netbuf *buf; 00497 00498 err_t err = netconn_recv(s->conn, &buf); 00499 if (err != ERR_OK) { 00500 return err_remap(err); 00501 } 00502 00503 if (address) { 00504 nsapi_addr_t addr; 00505 convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf)); 00506 address->set_addr(addr); 00507 address->set_port(netbuf_fromport(buf)); 00508 } 00509 00510 u16_t recv = netbuf_copy(buf, data, (u16_t)size); 00511 netbuf_delete(buf); 00512 00513 return recv; 00514 } 00515 00516 int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr) 00517 { 00518 uint32_t count = 0; 00519 uint32_t index = 0; 00520 // Set upper limit on while loop, should break out when the membership pair is found 00521 while (count < s->multicast_memberships_count) { 00522 index = next_registered_multicast_member(s, index); 00523 00524 if (memcmp(&s->multicast_memberships[index].imr_multiaddr, &imr->imr_multiaddr, sizeof(nsapi_addr_t)) == 0 && 00525 memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) { 00526 return index; 00527 } 00528 count++; 00529 index++; 00530 } 00531 00532 return -1; 00533 } 00534 00535 nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) 00536 { 00537 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00538 00539 switch (optname) { 00540 case NSAPI_BIND_TO_DEVICE : 00541 if (optlen > NSAPI_INTERFACE_NAME_MAX_SIZE) { 00542 return NSAPI_ERROR_UNSUPPORTED ; 00543 } 00544 00545 netconn_bind_if(s->conn, netif_name_to_index((const char *)optval)); 00546 00547 return 0; 00548 #if LWIP_TCP 00549 case NSAPI_KEEPALIVE : 00550 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) { 00551 return NSAPI_ERROR_UNSUPPORTED ; 00552 } 00553 00554 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; 00555 return 0; 00556 00557 case NSAPI_KEEPIDLE : 00558 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) { 00559 return NSAPI_ERROR_UNSUPPORTED ; 00560 } 00561 00562 s->conn->pcb.tcp->keep_idle = *(int *)optval; 00563 return 0; 00564 00565 case NSAPI_KEEPINTVL : 00566 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) { 00567 return NSAPI_ERROR_UNSUPPORTED ; 00568 } 00569 00570 s->conn->pcb.tcp->keep_intvl = *(int *)optval; 00571 return 0; 00572 #endif 00573 00574 case NSAPI_REUSEADDR : 00575 if (optlen != sizeof(int)) { 00576 return NSAPI_ERROR_UNSUPPORTED ; 00577 } 00578 00579 if (*(int *)optval) { 00580 ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR); 00581 } else { 00582 ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR); 00583 } 00584 return 0; 00585 00586 case NSAPI_ADD_MEMBERSHIP : 00587 case NSAPI_DROP_MEMBERSHIP : { 00588 if (optlen != sizeof(nsapi_ip_mreq_t)) { 00589 return NSAPI_ERROR_PARAMETER ; 00590 } 00591 err_t igmp_err; 00592 const nsapi_ip_mreq_t *imr = static_cast<const nsapi_ip_mreq_t *>(optval); 00593 00594 /* Check interface address type matches group, or is unspecified */ 00595 if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) { 00596 return NSAPI_ERROR_PARAMETER ; 00597 } 00598 00599 ip_addr_t if_addr; 00600 ip_addr_t multi_addr; 00601 00602 /* Convert the group address */ 00603 if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) { 00604 return NSAPI_ERROR_PARAMETER ; 00605 } 00606 00607 if (imr->imr_interface.version != NSAPI_UNSPEC ) { 00608 /* Convert the interface address */ 00609 if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) { 00610 return NSAPI_ERROR_PARAMETER ; 00611 } 00612 } else { 00613 /* Set interface address to "any", matching the group address type */ 00614 ip_addr_set_any(IP_IS_V6(&multi_addr), &if_addr); 00615 } 00616 00617 igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED 00618 int32_t member_pair_index = find_multicast_member(s, imr); 00619 00620 if (optname == NSAPI_ADD_MEMBERSHIP ) { 00621 if (!s->multicast_memberships) { 00622 // First multicast join on this socket, allocate space for membership tracking 00623 s->multicast_memberships = (nsapi_ip_mreq_t *)malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS); 00624 if (!s->multicast_memberships) { 00625 return NSAPI_ERROR_NO_MEMORY ; 00626 } 00627 } else if (s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) { 00628 return NSAPI_ERROR_NO_MEMORY ; 00629 } 00630 00631 if (member_pair_index != -1) { 00632 return NSAPI_ERROR_ADDRESS_IN_USE ; 00633 } 00634 00635 member_pair_index = next_free_multicast_member(s, 0); 00636 00637 adaptation.lock(); 00638 00639 #if LWIP_IPV4 00640 if (IP_IS_V4(&if_addr)) { 00641 igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); 00642 } 00643 #endif 00644 #if LWIP_IPV6 00645 if (IP_IS_V6(&if_addr)) { 00646 igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); 00647 } 00648 #endif 00649 00650 adaptation.unlock(); 00651 00652 if (igmp_err == ERR_OK) { 00653 set_multicast_member_registry_bit(s, member_pair_index); 00654 s->multicast_memberships[member_pair_index] = *imr; 00655 s->multicast_memberships_count++; 00656 } 00657 } else { 00658 if (member_pair_index == -1) { 00659 return NSAPI_ERROR_NO_ADDRESS ; 00660 } 00661 00662 clear_multicast_member_registry_bit(s, member_pair_index); 00663 s->multicast_memberships_count--; 00664 00665 adaptation.lock(); 00666 00667 #if LWIP_IPV4 00668 if (IP_IS_V4(&if_addr)) { 00669 igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); 00670 } 00671 #endif 00672 #if LWIP_IPV6 00673 if (IP_IS_V6(&if_addr)) { 00674 igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); 00675 } 00676 #endif 00677 00678 adaptation.unlock(); 00679 } 00680 00681 return err_remap(igmp_err); 00682 } 00683 00684 default: 00685 return NSAPI_ERROR_UNSUPPORTED ; 00686 } 00687 } 00688 00689 nsapi_error_t LWIP::getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen) 00690 { 00691 return NSAPI_ERROR_UNSUPPORTED ; 00692 } 00693 00694 00695 void LWIP::socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) 00696 { 00697 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; 00698 00699 s->cb = callback; 00700 s->data = data; 00701 } 00702 00703 LWIP &LWIP::get_instance() 00704 { 00705 static LWIP lwip; 00706 return lwip; 00707 } 00708 00709 // This works as long as it's not ever set to something which corresponds to 00710 // a macro defined as a non-integer. Eg `#define Nanostack "Foo"` 00711 #define LWIP 0x11991199 00712 #if MBED_CONF_NSAPI_DEFAULT_STACK == LWIP 00713 #undef LWIP 00714 OnboardNetworkStack &OnboardNetworkStack::get_default_instance() 00715 { 00716 return LWIP::get_instance(); 00717 } 00718 #endif
Generated on Tue Jul 12 2022 13:54:31 by
1.7.2