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
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 15:15:51 by
