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