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: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
lwip_stack.c
00001 /* LWIP implementation of NetworkInterfaceAPI 00002 * Copyright (c) 2015 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 00017 #include "nsapi.h" 00018 #include "mbed_interface.h" 00019 #include <stdio.h> 00020 #include <stdbool.h> 00021 #include <string.h> 00022 00023 #include "eth_arch.h" 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/dns.h" 00034 #include "lwip/udp.h" 00035 00036 #include "emac_api.h" 00037 00038 #if DEVICE_EMAC 00039 #define MBED_NETIF_INIT_FN emac_lwip_if_init 00040 #else 00041 #define MBED_NETIF_INIT_FN eth_arch_enetif_init 00042 #endif 00043 00044 #define DHCP_TIMEOUT 15000 00045 00046 /* Static arena of sockets */ 00047 static struct lwip_socket { 00048 bool in_use; 00049 00050 struct netconn *conn; 00051 struct netbuf *buf; 00052 u16_t offset; 00053 00054 void (*cb)(void *); 00055 void *data; 00056 } lwip_arena[MEMP_NUM_NETCONN]; 00057 00058 static bool lwip_connected = false; 00059 00060 static void mbed_lwip_arena_init(void) 00061 { 00062 memset(lwip_arena, 0, sizeof lwip_arena); 00063 } 00064 00065 static struct lwip_socket *mbed_lwip_arena_alloc(void) 00066 { 00067 sys_prot_t prot = sys_arch_protect(); 00068 00069 for (int i = 0; i < MEMP_NUM_NETCONN; i++) { 00070 if (!lwip_arena[i].in_use) { 00071 struct lwip_socket *s = &lwip_arena[i]; 00072 memset(s, 0, sizeof *s); 00073 s->in_use = true; 00074 sys_arch_unprotect(prot); 00075 return s; 00076 } 00077 } 00078 00079 sys_arch_unprotect(prot); 00080 return 0; 00081 } 00082 00083 static void mbed_lwip_arena_dealloc(struct lwip_socket *s) 00084 { 00085 s->in_use = false; 00086 } 00087 00088 static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) 00089 { 00090 // Filter send minus events 00091 if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) { 00092 return; 00093 } 00094 00095 sys_prot_t prot = sys_arch_protect(); 00096 00097 for (int i = 0; i < MEMP_NUM_NETCONN; i++) { 00098 if (lwip_arena[i].in_use 00099 && lwip_arena[i].conn == nc 00100 && lwip_arena[i].cb) { 00101 lwip_arena[i].cb(lwip_arena[i].data); 00102 } 00103 } 00104 00105 sys_arch_unprotect(prot); 00106 } 00107 00108 00109 /* TCP/IP and Network Interface Initialisation */ 00110 static struct netif lwip_netif; 00111 static bool lwip_dhcp = false; 00112 static char lwip_mac_address[NSAPI_MAC_SIZE]; 00113 00114 #if !LWIP_IPV4 || !LWIP_IPV6 00115 static bool all_zeros(const uint8_t *p, int len) 00116 { 00117 for (int i = 0; i < len; i++) { 00118 if (p[i]) { 00119 return false; 00120 } 00121 } 00122 00123 return true; 00124 } 00125 #endif 00126 00127 static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in) 00128 { 00129 #if LWIP_IPV6 00130 if (in->version == NSAPI_IPv6 ) { 00131 IP_SET_TYPE(out, IPADDR_TYPE_V6); 00132 MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t)); 00133 return true; 00134 } 00135 #if !LWIP_IPV4 00136 /* For bind() and other purposes, need to accept "null" of other type */ 00137 /* (People use IPv4 0.0.0.0 as a general null) */ 00138 if (in->version == NSAPI_UNSPEC || 00139 (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) { 00140 ip_addr_set_zero_ip6(out); 00141 return true; 00142 } 00143 #endif 00144 #endif 00145 00146 #if LWIP_IPV4 00147 if (in->version == NSAPI_IPv4 ) { 00148 IP_SET_TYPE(out, IPADDR_TYPE_V4); 00149 MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t)); 00150 return true; 00151 } 00152 #if !LWIP_IPV6 00153 /* For symmetry with above, accept IPv6 :: as a general null */ 00154 if (in->version == NSAPI_UNSPEC || 00155 (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) { 00156 ip_addr_set_zero_ip4(out); 00157 return true; 00158 } 00159 #endif 00160 #endif 00161 00162 #if LWIP_IPV4 && LWIP_IPV6 00163 if (in->version == NSAPI_UNSPEC ) { 00164 #if IP_VERSION_PREF == PREF_IPV4 00165 ip_addr_set_zero_ip4(out); 00166 #else 00167 ip_addr_set_zero_ip6(out); 00168 #endif 00169 return true; 00170 } 00171 #endif 00172 00173 return false; 00174 } 00175 00176 static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in) 00177 { 00178 #if LWIP_IPV6 00179 if (IP_IS_V6(in)) { 00180 out->version = NSAPI_IPv6 ; 00181 MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t)); 00182 return true; 00183 } 00184 #endif 00185 #if LWIP_IPV4 00186 if (IP_IS_V4(in)) { 00187 out->version = NSAPI_IPv4 ; 00188 MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t)); 00189 return true; 00190 } 00191 #endif 00192 return false; 00193 } 00194 00195 static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif) 00196 { 00197 #if LWIP_IPV4 00198 if (!netif_is_up(netif)) { 00199 return NULL; 00200 } 00201 00202 if (!ip4_addr_isany(netif_ip4_addr(netif))) { 00203 return netif_ip_addr4(netif); 00204 } 00205 #endif 00206 00207 return NULL; 00208 } 00209 00210 static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif) 00211 { 00212 #if LWIP_IPV6 00213 if (!netif_is_up(netif)) { 00214 return NULL; 00215 } 00216 00217 for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00218 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00219 !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { 00220 return netif_ip_addr6(netif, i); 00221 } 00222 } 00223 #endif 00224 00225 return NULL; 00226 00227 } 00228 00229 const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif) 00230 { 00231 const ip_addr_t *pref_ip_addr = 0; 00232 const ip_addr_t *npref_ip_addr = 0; 00233 00234 #if IP_VERSION_PREF == PREF_IPV4 00235 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif); 00236 npref_ip_addr = mbed_lwip_get_ipv6_addr(netif); 00237 #else 00238 pref_ip_addr = mbed_lwip_get_ipv6_addr(netif); 00239 npref_ip_addr = mbed_lwip_get_ipv4_addr(netif); 00240 #endif 00241 00242 if (pref_ip_addr) { 00243 return pref_ip_addr; 00244 } else if (npref_ip_addr && any_addr) { 00245 return npref_ip_addr; 00246 } 00247 00248 return NULL; 00249 } 00250 00251 void add_dns_addr(struct netif *lwip_netif) 00252 { 00253 // Do nothing if not brought up 00254 const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif); 00255 if (!ip_addr) { 00256 return; 00257 } 00258 00259 // Check for existing dns server 00260 for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) { 00261 const ip_addr_t *dns_ip_addr = dns_getserver(numdns); 00262 if (!ip_addr_isany(dns_ip_addr)) { 00263 return; 00264 } 00265 } 00266 00267 #if LWIP_IPV6 00268 if (IP_IS_V6(ip_addr)) { 00269 /* 2001:4860:4860::8888 google */ 00270 ip_addr_t ipv6_dns_addr = IPADDR6_INIT( 00271 PP_HTONL(0x20014860UL), 00272 PP_HTONL(0x48600000UL), 00273 PP_HTONL(0x00000000UL), 00274 PP_HTONL(0x00008888UL)); 00275 dns_setserver(0, &ipv6_dns_addr); 00276 } 00277 #endif 00278 00279 #if LWIP_IPV4 00280 if (IP_IS_V4(ip_addr)) { 00281 /* 8.8.8.8 google */ 00282 ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808); 00283 dns_setserver(0, &ipv4_dns_addr); 00284 } 00285 #endif 00286 } 00287 00288 static sys_sem_t lwip_tcpip_inited; 00289 static void mbed_lwip_tcpip_init_irq(void *eh) 00290 { 00291 sys_sem_signal(&lwip_tcpip_inited); 00292 } 00293 00294 static sys_sem_t lwip_netif_linked; 00295 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif) 00296 { 00297 if (netif_is_link_up(lwip_netif)) { 00298 sys_sem_signal(&lwip_netif_linked); 00299 } 00300 } 00301 00302 static sys_sem_t lwip_netif_has_addr; 00303 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif) 00304 { 00305 static bool any_addr = true; 00306 00307 if (netif_is_up(lwip_netif)) { 00308 // Indicates that has address 00309 if (any_addr == true && mbed_lwip_get_ip_addr(true, lwip_netif)) { 00310 sys_sem_signal(&lwip_netif_has_addr); 00311 any_addr = false; 00312 return; 00313 } 00314 00315 // Indicates that has preferred address 00316 if (mbed_lwip_get_ip_addr(false, lwip_netif)) { 00317 sys_sem_signal(&lwip_netif_has_addr); 00318 } 00319 } else { 00320 any_addr = true; 00321 } 00322 } 00323 00324 static void mbed_lwip_set_mac_address(void) 00325 { 00326 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) 00327 snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", 00328 MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2, 00329 MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5); 00330 #else 00331 char mac[6]; 00332 mbed_mac_address(mac); 00333 snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", 00334 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 00335 #endif 00336 } 00337 00338 /* LWIP interface implementation */ 00339 const char *mbed_lwip_get_mac_address(void) 00340 { 00341 return lwip_mac_address[0] ? lwip_mac_address : 0; 00342 } 00343 00344 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen) 00345 { 00346 const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00347 if (!addr) { 00348 return NULL; 00349 } 00350 #if LWIP_IPV6 00351 if (IP_IS_V6(addr)) { 00352 return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen); 00353 } 00354 #endif 00355 #if LWIP_IPV4 00356 if (IP_IS_V4(addr)) { 00357 return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen); 00358 } 00359 #endif 00360 return NULL; 00361 } 00362 00363 const char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen) 00364 { 00365 #if LWIP_IPV4 00366 const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif); 00367 if (!ip4_addr_isany(addr)) { 00368 return ip4addr_ntoa_r(addr, buf, buflen); 00369 } else { 00370 return NULL; 00371 } 00372 #else 00373 return NULL; 00374 #endif 00375 } 00376 00377 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen) 00378 { 00379 #if LWIP_IPV4 00380 const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif); 00381 if (!ip4_addr_isany(addr)) { 00382 return ip4addr_ntoa_r(addr, buf, buflen); 00383 } else { 00384 return NULL; 00385 } 00386 #else 00387 return NULL; 00388 #endif 00389 } 00390 00391 nsapi_error_t mbed_lwip_init(emac_interface_t *emac) 00392 { 00393 // Check if we've already brought up lwip 00394 if (!mbed_lwip_get_mac_address()) { 00395 // Set up network 00396 mbed_lwip_set_mac_address(); 00397 00398 sys_sem_new(&lwip_tcpip_inited, 0); 00399 sys_sem_new(&lwip_netif_linked, 0); 00400 sys_sem_new(&lwip_netif_has_addr, 0); 00401 00402 tcpip_init(mbed_lwip_tcpip_init_irq, NULL); 00403 sys_arch_sem_wait(&lwip_tcpip_inited, 0); 00404 00405 memset(&lwip_netif, 0, sizeof lwip_netif); 00406 if (!netif_add(&lwip_netif, 00407 #if LWIP_IPV4 00408 0, 0, 0, 00409 #endif 00410 emac, MBED_NETIF_INIT_FN, tcpip_input)) { 00411 return NSAPI_ERROR_DEVICE_ERROR ; 00412 } 00413 00414 netif_set_default(&lwip_netif); 00415 00416 netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq); 00417 netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq); 00418 00419 #if !DEVICE_EMAC 00420 eth_arch_enable_interrupts(); 00421 #endif 00422 } 00423 00424 return NSAPI_ERROR_OK ; 00425 } 00426 00427 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw) 00428 { 00429 // Check if we've already connected 00430 if (lwip_connected) { 00431 return NSAPI_ERROR_PARAMETER ; 00432 } 00433 00434 if(mbed_lwip_init(NULL) != NSAPI_ERROR_OK ) { 00435 return NSAPI_ERROR_DEVICE_ERROR ; 00436 } 00437 00438 // Zero out socket set 00439 mbed_lwip_arena_init(); 00440 00441 #if LWIP_IPV6 00442 netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/); 00443 #if LWIP_IPV6_MLD 00444 /* 00445 * For hardware/netifs that implement MAC filtering. 00446 * All-nodes link-local is handled by default, so we must let the hardware know 00447 * to allow multicast packets in. 00448 * Should set mld_mac_filter previously. */ 00449 if (lwip_netif.mld_mac_filter != NULL) { 00450 ip6_addr_t ip6_allnodes_ll; 00451 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); 00452 lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); 00453 } 00454 #endif /* LWIP_IPV6_MLD */ 00455 00456 #if LWIP_IPV6_AUTOCONFIG 00457 /* IPv6 address autoconfiguration not enabled by default */ 00458 lwip_netif.ip6_autoconfig_enabled = 1; 00459 #endif /* LWIP_IPV6_AUTOCONFIG */ 00460 00461 #endif 00462 00463 u32_t ret; 00464 00465 if (!netif_is_link_up(&lwip_netif)) { 00466 ret = sys_arch_sem_wait(&lwip_netif_linked, 15000); 00467 00468 if (ret == SYS_ARCH_TIMEOUT) { 00469 return NSAPI_ERROR_NO_CONNECTION ; 00470 } 00471 } 00472 00473 #if LWIP_IPV4 00474 if (!dhcp) { 00475 ip4_addr_t ip_addr; 00476 ip4_addr_t netmask_addr; 00477 ip4_addr_t gw_addr; 00478 00479 if (!inet_aton(ip, &ip_addr) || 00480 !inet_aton(netmask, &netmask_addr) || 00481 !inet_aton(gw, &gw_addr)) { 00482 return NSAPI_ERROR_PARAMETER ; 00483 } 00484 00485 netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr); 00486 } 00487 #endif 00488 00489 netif_set_up(&lwip_netif); 00490 00491 #if LWIP_IPV4 00492 // Connect to the network 00493 lwip_dhcp = dhcp; 00494 00495 if (lwip_dhcp) { 00496 err_t err = dhcp_start(&lwip_netif); 00497 if (err) { 00498 return NSAPI_ERROR_DHCP_FAILURE ; 00499 } 00500 } 00501 #endif 00502 00503 // If doesn't have address 00504 if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) { 00505 ret = sys_arch_sem_wait(&lwip_netif_has_addr, 15000); 00506 if (ret == SYS_ARCH_TIMEOUT) { 00507 return NSAPI_ERROR_DHCP_FAILURE ; 00508 } 00509 } 00510 00511 #if ADDR_TIMEOUT 00512 // If address is not for preferred stack waits a while to see 00513 // if preferred stack address is acquired 00514 if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) { 00515 ret = sys_arch_sem_wait(&lwip_netif_has_addr, ADDR_TIMEOUT * 1000); 00516 } 00517 #endif 00518 00519 add_dns_addr(&lwip_netif); 00520 00521 lwip_connected = true; 00522 return 0; 00523 } 00524 00525 #if LWIP_IPV6 00526 void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif) 00527 { 00528 for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00529 netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID); 00530 } 00531 } 00532 #endif 00533 00534 nsapi_error_t mbed_lwip_bringdown(void) 00535 { 00536 // Check if we've connected 00537 if (!lwip_connected) { 00538 return NSAPI_ERROR_PARAMETER ; 00539 } 00540 00541 #if LWIP_IPV4 00542 // Disconnect from the network 00543 if (lwip_dhcp) { 00544 dhcp_release(&lwip_netif); 00545 dhcp_stop(&lwip_netif); 00546 lwip_dhcp = false; 00547 } 00548 #endif 00549 00550 netif_set_down(&lwip_netif); 00551 00552 #if LWIP_IPV6 00553 mbed_lwip_clear_ipv6_addresses(&lwip_netif); 00554 #endif 00555 00556 sys_sem_free(&lwip_netif_has_addr); 00557 sys_sem_new(&lwip_netif_has_addr, 0); 00558 lwip_connected = false; 00559 return 0; 00560 } 00561 00562 /* LWIP error remapping */ 00563 static nsapi_error_t mbed_lwip_err_remap(err_t err) { 00564 switch (err) { 00565 case ERR_OK: 00566 case ERR_CLSD: 00567 return 0; 00568 case ERR_MEM: 00569 return NSAPI_ERROR_NO_MEMORY ; 00570 case ERR_CONN: 00571 case ERR_RST: 00572 case ERR_ABRT: 00573 return NSAPI_ERROR_NO_CONNECTION ; 00574 case ERR_TIMEOUT: 00575 case ERR_RTE: 00576 case ERR_INPROGRESS: 00577 case ERR_WOULDBLOCK: 00578 return NSAPI_ERROR_WOULD_BLOCK ; 00579 case ERR_VAL: 00580 case ERR_USE: 00581 case ERR_ISCONN: 00582 case ERR_ARG: 00583 return NSAPI_ERROR_PARAMETER ; 00584 default: 00585 return NSAPI_ERROR_DEVICE_ERROR ; 00586 } 00587 } 00588 00589 /* LWIP network stack implementation */ 00590 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) 00591 { 00592 ip_addr_t lwip_addr; 00593 00594 #if LWIP_IPV4 && LWIP_IPV6 00595 u8_t addr_type; 00596 if (version == NSAPI_UNSPEC ) { 00597 const ip_addr_t *ip_addr; 00598 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00599 if (IP_IS_V6(ip_addr)) { 00600 addr_type = NETCONN_DNS_IPV6; 00601 } else { 00602 addr_type = NETCONN_DNS_IPV4; 00603 } 00604 } else if (version == NSAPI_IPv4 ) { 00605 addr_type = NETCONN_DNS_IPV4; 00606 } else if (version == NSAPI_IPv6 ) { 00607 addr_type = NETCONN_DNS_IPV6; 00608 } 00609 err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); 00610 #elif LWIP_IPV4 00611 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC ) { 00612 return NSAPI_ERROR_DNS_FAILURE ; 00613 } 00614 err_t err = netconn_gethostbyname(host, &lwip_addr); 00615 #elif LWIP_IPV6 00616 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC ) { 00617 return NSAPI_ERROR_DNS_FAILURE ; 00618 } 00619 err_t err = netconn_gethostbyname(host, &lwip_addr); 00620 #endif 00621 00622 if (err != ERR_OK) { 00623 return NSAPI_ERROR_DNS_FAILURE ; 00624 } 00625 00626 convert_lwip_addr_to_mbed(addr, &lwip_addr); 00627 00628 return 0; 00629 } 00630 00631 static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr) 00632 { 00633 // Shift all dns servers down to give precedence to new server 00634 for (int i = DNS_MAX_SERVERS-1; i > 0; i--) { 00635 dns_setserver(i, dns_getserver(i-1)); 00636 } 00637 00638 ip_addr_t ip_addr; 00639 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00640 return NSAPI_ERROR_PARAMETER ; 00641 } 00642 00643 dns_setserver(0, &ip_addr); 00644 return 0; 00645 } 00646 00647 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) 00648 { 00649 // check if network is connected 00650 if (!lwip_connected) { 00651 return NSAPI_ERROR_NO_CONNECTION ; 00652 } 00653 00654 // allocate a socket 00655 struct lwip_socket *s = mbed_lwip_arena_alloc(); 00656 if (!s) { 00657 return NSAPI_ERROR_NO_SOCKET ; 00658 } 00659 00660 u8_t lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP; 00661 00662 #if LWIP_IPV6 && LWIP_IPV4 00663 const ip_addr_t *ip_addr; 00664 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00665 00666 if (IP_IS_V6(ip_addr)) { 00667 // Enable IPv6 (or dual-stack). LWIP dual-stack support is 00668 // currently incomplete as of 2.0.0rc2 - eg we will only be able 00669 // to do a UDP sendto to an address matching the type selected 00670 // here. Matching "get_ip_addr" and DNS logic, use v4 if 00671 // available. 00672 lwip_proto |= NETCONN_TYPE_IPV6; 00673 } 00674 #elif LWIP_IPV6 00675 lwip_proto |= NETCONN_TYPE_IPV6; 00676 #endif 00677 00678 s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback); 00679 00680 if (!s->conn) { 00681 mbed_lwip_arena_dealloc(s); 00682 return NSAPI_ERROR_NO_SOCKET ; 00683 } 00684 00685 netconn_set_recvtimeout(s->conn, 1); 00686 *(struct lwip_socket **)handle = s; 00687 return 0; 00688 } 00689 00690 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle) 00691 { 00692 struct lwip_socket *s = (struct lwip_socket *)handle; 00693 00694 netbuf_delete(s->buf); 00695 err_t err = netconn_delete(s->conn); 00696 mbed_lwip_arena_dealloc(s); 00697 return mbed_lwip_err_remap(err); 00698 } 00699 00700 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 00701 { 00702 struct lwip_socket *s = (struct lwip_socket *)handle; 00703 ip_addr_t ip_addr; 00704 00705 if ((s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || 00706 (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { 00707 return NSAPI_ERROR_PARAMETER ; 00708 } 00709 00710 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00711 return NSAPI_ERROR_PARAMETER ; 00712 } 00713 00714 err_t err = netconn_bind(s->conn, &ip_addr, port); 00715 return mbed_lwip_err_remap(err); 00716 } 00717 00718 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog) 00719 { 00720 struct lwip_socket *s = (struct lwip_socket *)handle; 00721 00722 err_t err = netconn_listen_with_backlog(s->conn, backlog); 00723 return mbed_lwip_err_remap(err); 00724 } 00725 00726 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 00727 { 00728 struct lwip_socket *s = (struct lwip_socket *)handle; 00729 ip_addr_t ip_addr; 00730 00731 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00732 return NSAPI_ERROR_PARAMETER ; 00733 } 00734 00735 netconn_set_nonblocking(s->conn, false); 00736 err_t err = netconn_connect(s->conn, &ip_addr, port); 00737 netconn_set_nonblocking(s->conn, true); 00738 00739 return mbed_lwip_err_remap(err); 00740 } 00741 00742 static nsapi_error_t mbed_lwip_socket_accept(nsapi_stack_t *stack, nsapi_socket_t server, nsapi_socket_t *handle, nsapi_addr_t *addr, uint16_t *port) 00743 { 00744 struct lwip_socket *s = (struct lwip_socket *)server; 00745 struct lwip_socket *ns = mbed_lwip_arena_alloc(); 00746 if (!ns) { 00747 return NSAPI_ERROR_NO_SOCKET ; 00748 } 00749 00750 err_t err = netconn_accept(s->conn, &ns->conn); 00751 if (err != ERR_OK) { 00752 mbed_lwip_arena_dealloc(ns); 00753 return mbed_lwip_err_remap(err); 00754 } 00755 00756 netconn_set_recvtimeout(ns->conn, 1); 00757 *(struct lwip_socket **)handle = ns; 00758 00759 ip_addr_t peer_addr; 00760 (void) netconn_peer(ns->conn, &peer_addr, port); 00761 convert_lwip_addr_to_mbed(addr, &peer_addr); 00762 00763 netconn_set_nonblocking(ns->conn, true); 00764 00765 return 0; 00766 } 00767 00768 static nsapi_size_or_error_t mbed_lwip_socket_send(nsapi_stack_t *stack, nsapi_socket_t handle, const void *data, nsapi_size_t size) 00769 { 00770 struct lwip_socket *s = (struct lwip_socket *)handle; 00771 size_t bytes_written = 0; 00772 00773 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written); 00774 if (err != ERR_OK) { 00775 return mbed_lwip_err_remap(err); 00776 } 00777 00778 return (nsapi_size_or_error_t)bytes_written; 00779 } 00780 00781 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size) 00782 { 00783 struct lwip_socket *s = (struct lwip_socket *)handle; 00784 00785 if (!s->buf) { 00786 err_t err = netconn_recv(s->conn, &s->buf); 00787 s->offset = 0; 00788 00789 if (err != ERR_OK) { 00790 return mbed_lwip_err_remap(err); 00791 } 00792 } 00793 00794 u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); 00795 s->offset += recv; 00796 00797 if (s->offset >= netbuf_len(s->buf)) { 00798 netbuf_delete(s->buf); 00799 s->buf = 0; 00800 } 00801 00802 return recv; 00803 } 00804 00805 static nsapi_size_or_error_t mbed_lwip_socket_sendto(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port, const void *data, nsapi_size_t size) 00806 { 00807 struct lwip_socket *s = (struct lwip_socket *)handle; 00808 ip_addr_t ip_addr; 00809 00810 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00811 return NSAPI_ERROR_PARAMETER ; 00812 } 00813 00814 struct netbuf *buf = netbuf_new(); 00815 err_t err = netbuf_ref(buf, data, (u16_t)size); 00816 if (err != ERR_OK) { 00817 netbuf_free(buf); 00818 return mbed_lwip_err_remap(err); 00819 } 00820 00821 err = netconn_sendto(s->conn, buf, &ip_addr, port); 00822 netbuf_delete(buf); 00823 if (err != ERR_OK) { 00824 return mbed_lwip_err_remap(err); 00825 } 00826 00827 return size; 00828 } 00829 00830 static nsapi_size_or_error_t mbed_lwip_socket_recvfrom(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t *addr, uint16_t *port, void *data, nsapi_size_t size) 00831 { 00832 struct lwip_socket *s = (struct lwip_socket *)handle; 00833 struct netbuf *buf; 00834 00835 err_t err = netconn_recv(s->conn, &buf); 00836 if (err != ERR_OK) { 00837 return mbed_lwip_err_remap(err); 00838 } 00839 00840 convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf)); 00841 *port = netbuf_fromport(buf); 00842 00843 u16_t recv = netbuf_copy(buf, data, (u16_t)size); 00844 netbuf_delete(buf); 00845 00846 return recv; 00847 } 00848 00849 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) 00850 { 00851 struct lwip_socket *s = (struct lwip_socket *)handle; 00852 00853 switch (optname) { 00854 case NSAPI_KEEPALIVE : 00855 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00856 return NSAPI_ERROR_UNSUPPORTED ; 00857 } 00858 00859 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; 00860 return 0; 00861 00862 case NSAPI_KEEPIDLE : 00863 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00864 return NSAPI_ERROR_UNSUPPORTED ; 00865 } 00866 00867 s->conn->pcb.tcp->keep_idle = *(int*)optval; 00868 return 0; 00869 00870 case NSAPI_KEEPINTVL : 00871 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00872 return NSAPI_ERROR_UNSUPPORTED ; 00873 } 00874 00875 s->conn->pcb.tcp->keep_intvl = *(int*)optval; 00876 return 0; 00877 00878 case NSAPI_REUSEADDR : 00879 if (optlen != sizeof(int)) { 00880 return NSAPI_ERROR_UNSUPPORTED ; 00881 } 00882 00883 if (*(int *)optval) { 00884 s->conn->pcb.tcp->so_options |= SOF_REUSEADDR; 00885 } else { 00886 s->conn->pcb.tcp->so_options &= ~SOF_REUSEADDR; 00887 } 00888 return 0; 00889 00890 default: 00891 return NSAPI_ERROR_UNSUPPORTED ; 00892 } 00893 } 00894 00895 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data) 00896 { 00897 struct lwip_socket *s = (struct lwip_socket *)handle; 00898 00899 s->cb = callback; 00900 s->data = data; 00901 } 00902 00903 /* LWIP network stack */ 00904 const nsapi_stack_api_t lwip_stack_api = { 00905 .gethostbyname = mbed_lwip_gethostbyname, 00906 .add_dns_server = mbed_lwip_add_dns_server, 00907 .socket_open = mbed_lwip_socket_open, 00908 .socket_close = mbed_lwip_socket_close, 00909 .socket_bind = mbed_lwip_socket_bind, 00910 .socket_listen = mbed_lwip_socket_listen, 00911 .socket_connect = mbed_lwip_socket_connect, 00912 .socket_accept = mbed_lwip_socket_accept, 00913 .socket_send = mbed_lwip_socket_send, 00914 .socket_recv = mbed_lwip_socket_recv, 00915 .socket_sendto = mbed_lwip_socket_sendto, 00916 .socket_recvfrom = mbed_lwip_socket_recvfrom, 00917 .setsockopt = mbed_lwip_setsockopt, 00918 .socket_attach = mbed_lwip_socket_attach, 00919 }; 00920 00921 nsapi_stack_t lwip_stack = { 00922 .stack_api = &lwip_stack_api, 00923 };
Generated on Tue Jul 12 2022 11:02:28 by
1.7.2