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