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: blinky_max32630fthr
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] = "\0"; 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 #if LWIP_IPV6 00247 void add_dns_addr(struct netif *lwip_netif) 00248 { 00249 const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif); 00250 if (ip_addr) { 00251 if (IP_IS_V6(ip_addr)) { 00252 const ip_addr_t *dns_ip_addr; 00253 bool dns_addr_exists = false; 00254 00255 for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) { 00256 dns_ip_addr = dns_getserver(numdns); 00257 if (!ip_addr_isany(dns_ip_addr)) { 00258 dns_addr_exists = true; 00259 break; 00260 } 00261 } 00262 00263 if (!dns_addr_exists) { 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 } 00273 } 00274 } 00275 #endif 00276 00277 static sys_sem_t lwip_tcpip_inited; 00278 static void mbed_lwip_tcpip_init_irq(void *eh) 00279 { 00280 sys_sem_signal(&lwip_tcpip_inited); 00281 } 00282 00283 static sys_sem_t lwip_netif_linked; 00284 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif) 00285 { 00286 if (netif_is_link_up(lwip_netif)) { 00287 sys_sem_signal(&lwip_netif_linked); 00288 } 00289 } 00290 00291 static sys_sem_t lwip_netif_has_addr; 00292 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif) 00293 { 00294 static bool any_addr = true; 00295 00296 // Indicates that has address 00297 if (any_addr == true && mbed_lwip_get_ip_addr(true, lwip_netif)) { 00298 sys_sem_signal(&lwip_netif_has_addr); 00299 any_addr = false; 00300 return; 00301 } 00302 00303 // Indicates that has preferred address 00304 if (mbed_lwip_get_ip_addr(false, lwip_netif)) { 00305 sys_sem_signal(&lwip_netif_has_addr); 00306 } 00307 } 00308 00309 static void mbed_lwip_set_mac_address(void) 00310 { 00311 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) 00312 snprintf(lwip_mac_address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", 00313 MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2, 00314 MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5); 00315 #else 00316 char mac[6]; 00317 mbed_mac_address(mac); 00318 snprintf(lwip_mac_address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", 00319 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 00320 #endif 00321 } 00322 00323 /* LWIP interface implementation */ 00324 const char *mbed_lwip_get_mac_address(void) 00325 { 00326 return lwip_mac_address[0] ? lwip_mac_address : 0; 00327 } 00328 00329 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen) 00330 { 00331 const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00332 if (!addr) { 00333 return NULL; 00334 } 00335 #if LWIP_IPV6 00336 if (IP_IS_V6(addr)) { 00337 return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen); 00338 } 00339 #endif 00340 #if LWIP_IPV4 00341 if (IP_IS_V4(addr)) { 00342 return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen); 00343 } 00344 #endif 00345 return NULL; 00346 } 00347 00348 const char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen) 00349 { 00350 #if LWIP_IPV4 00351 const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif); 00352 if (!ip4_addr_isany(addr)) { 00353 return ip4addr_ntoa_r(addr, buf, buflen); 00354 } else { 00355 return NULL; 00356 } 00357 #else 00358 return NULL; 00359 #endif 00360 } 00361 00362 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen) 00363 { 00364 #if LWIP_IPV4 00365 const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif); 00366 if (!ip4_addr_isany(addr)) { 00367 return ip4addr_ntoa_r(addr, buf, buflen); 00368 } else { 00369 return NULL; 00370 } 00371 #else 00372 return NULL; 00373 #endif 00374 } 00375 00376 nsapi_error_t mbed_lwip_init(emac_interface_t *emac) 00377 { 00378 // Check if we've already brought up lwip 00379 if (!mbed_lwip_get_mac_address()) { 00380 // Set up network 00381 mbed_lwip_set_mac_address(); 00382 00383 sys_sem_new(&lwip_tcpip_inited, 0); 00384 sys_sem_new(&lwip_netif_linked, 0); 00385 sys_sem_new(&lwip_netif_has_addr, 0); 00386 00387 tcpip_init(mbed_lwip_tcpip_init_irq, NULL); 00388 sys_arch_sem_wait(&lwip_tcpip_inited, 0); 00389 00390 memset(&lwip_netif, 0, sizeof lwip_netif); 00391 if (!netif_add(&lwip_netif, 00392 #if LWIP_IPV4 00393 0, 0, 0, 00394 #endif 00395 emac, MBED_NETIF_INIT_FN, tcpip_input)) { 00396 return NSAPI_ERROR_DEVICE_ERROR ; 00397 } 00398 00399 netif_set_default(&lwip_netif); 00400 00401 netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq); 00402 netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq); 00403 00404 #if !DEVICE_EMAC 00405 eth_arch_enable_interrupts(); 00406 #endif 00407 } 00408 00409 return NSAPI_ERROR_OK ; 00410 } 00411 00412 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw) 00413 { 00414 // Check if we've already connected 00415 if (lwip_connected) { 00416 return NSAPI_ERROR_PARAMETER ; 00417 } 00418 00419 if(mbed_lwip_init(NULL) != NSAPI_ERROR_OK ) { 00420 return NSAPI_ERROR_DEVICE_ERROR ; 00421 } 00422 00423 // Zero out socket set 00424 mbed_lwip_arena_init(); 00425 00426 #if LWIP_IPV6 00427 netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/); 00428 #if LWIP_IPV6_MLD 00429 /* 00430 * For hardware/netifs that implement MAC filtering. 00431 * All-nodes link-local is handled by default, so we must let the hardware know 00432 * to allow multicast packets in. 00433 * Should set mld_mac_filter previously. */ 00434 if (lwip_netif.mld_mac_filter != NULL) { 00435 ip6_addr_t ip6_allnodes_ll; 00436 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); 00437 lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, MLD6_ADD_MAC_FILTER); 00438 } 00439 #endif /* LWIP_IPV6_MLD */ 00440 00441 #if LWIP_IPV6_AUTOCONFIG 00442 /* IPv6 address autoconfiguration not enabled by default */ 00443 lwip_netif.ip6_autoconfig_enabled = 1; 00444 #endif /* LWIP_IPV6_AUTOCONFIG */ 00445 00446 #endif 00447 00448 u32_t ret; 00449 00450 if (!netif_is_link_up(&lwip_netif)) { 00451 ret = sys_arch_sem_wait(&lwip_netif_linked, 15000); 00452 00453 if (ret == SYS_ARCH_TIMEOUT) { 00454 return NSAPI_ERROR_NO_CONNECTION ; 00455 } 00456 } 00457 00458 #if LWIP_IPV4 00459 if (!dhcp) { 00460 ip4_addr_t ip_addr; 00461 ip4_addr_t netmask_addr; 00462 ip4_addr_t gw_addr; 00463 00464 if (!inet_aton(ip, &ip_addr) || 00465 !inet_aton(netmask, &netmask_addr) || 00466 !inet_aton(gw, &gw_addr)) { 00467 return NSAPI_ERROR_PARAMETER ; 00468 } 00469 00470 netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr); 00471 } 00472 #endif 00473 00474 netif_set_up(&lwip_netif); 00475 00476 #if LWIP_IPV4 00477 // Connect to the network 00478 lwip_dhcp = dhcp; 00479 00480 if (lwip_dhcp) { 00481 err_t err = dhcp_start(&lwip_netif); 00482 if (err) { 00483 return NSAPI_ERROR_DHCP_FAILURE ; 00484 } 00485 } 00486 #endif 00487 00488 // If doesn't have address 00489 if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) { 00490 ret = sys_arch_sem_wait(&lwip_netif_has_addr, 15000); 00491 if (ret == SYS_ARCH_TIMEOUT) { 00492 return NSAPI_ERROR_DHCP_FAILURE ; 00493 } 00494 lwip_connected = true; 00495 } 00496 00497 #if ADDR_TIMEOUT 00498 // If address is not for preferred stack waits a while to see 00499 // if preferred stack address is acquired 00500 if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) { 00501 ret = sys_arch_sem_wait(&lwip_netif_has_addr, ADDR_TIMEOUT * 1000); 00502 } 00503 #endif 00504 00505 #if LWIP_IPV6 00506 add_dns_addr(&lwip_netif); 00507 #endif 00508 00509 return 0; 00510 } 00511 00512 nsapi_error_t mbed_lwip_bringdown(void) 00513 { 00514 // Check if we've connected 00515 if (!lwip_connected) { 00516 return NSAPI_ERROR_PARAMETER ; 00517 } 00518 00519 #if LWIP_IPV4 00520 // Disconnect from the network 00521 if (lwip_dhcp) { 00522 dhcp_release(&lwip_netif); 00523 dhcp_stop(&lwip_netif); 00524 lwip_dhcp = false; 00525 } else { 00526 netif_set_down(&lwip_netif); 00527 } 00528 #endif 00529 00530 lwip_connected = false; 00531 // TO DO - actually remove addresses from stack, and shut down properly 00532 return 0; 00533 } 00534 00535 /* LWIP error remapping */ 00536 static nsapi_error_t mbed_lwip_err_remap(err_t err) { 00537 switch (err) { 00538 case ERR_OK: 00539 case ERR_CLSD: 00540 case ERR_RST: 00541 return 0; 00542 case ERR_MEM: 00543 return NSAPI_ERROR_NO_MEMORY ; 00544 case ERR_CONN: 00545 return NSAPI_ERROR_NO_CONNECTION ; 00546 case ERR_TIMEOUT: 00547 case ERR_RTE: 00548 case ERR_INPROGRESS: 00549 case ERR_WOULDBLOCK: 00550 return NSAPI_ERROR_WOULD_BLOCK ; 00551 case ERR_VAL: 00552 case ERR_USE: 00553 case ERR_ISCONN: 00554 case ERR_ARG: 00555 return NSAPI_ERROR_PARAMETER ; 00556 default: 00557 return NSAPI_ERROR_DEVICE_ERROR ; 00558 } 00559 } 00560 00561 /* LWIP network stack implementation */ 00562 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) 00563 { 00564 ip_addr_t lwip_addr; 00565 00566 #if LWIP_IPV4 && LWIP_IPV6 00567 u8_t addr_type; 00568 if (version == NSAPI_UNSPEC ) { 00569 const ip_addr_t *ip_addr; 00570 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00571 if (IP_IS_V6(ip_addr)) { 00572 addr_type = NETCONN_DNS_IPV6; 00573 } else { 00574 addr_type = NETCONN_DNS_IPV4; 00575 } 00576 } else if (version == NSAPI_IPv4 ) { 00577 addr_type = NETCONN_DNS_IPV4; 00578 } else if (version == NSAPI_IPv6 ) { 00579 addr_type = NETCONN_DNS_IPV6; 00580 } 00581 err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); 00582 #elif LWIP_IPV4 00583 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC ) { 00584 return NSAPI_ERROR_DNS_FAILURE ; 00585 } 00586 err_t err = netconn_gethostbyname(host, &lwip_addr); 00587 #elif LWIP_IPV6 00588 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC ) { 00589 return NSAPI_ERROR_DNS_FAILURE ; 00590 } 00591 err_t err = netconn_gethostbyname(host, &lwip_addr); 00592 #endif 00593 00594 if (err != ERR_OK) { 00595 return NSAPI_ERROR_DNS_FAILURE ; 00596 } 00597 00598 convert_lwip_addr_to_mbed(addr, &lwip_addr); 00599 00600 return 0; 00601 } 00602 00603 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) 00604 { 00605 // check if network is connected 00606 if (!lwip_connected) { 00607 return NSAPI_ERROR_NO_CONNECTION ; 00608 } 00609 00610 // allocate a socket 00611 struct lwip_socket *s = mbed_lwip_arena_alloc(); 00612 if (!s) { 00613 return NSAPI_ERROR_NO_SOCKET ; 00614 } 00615 00616 u8_t lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP; 00617 00618 #if LWIP_IPV6 && LWIP_IPV4 00619 const ip_addr_t *ip_addr; 00620 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00621 00622 if (IP_IS_V6(ip_addr)) { 00623 // Enable IPv6 (or dual-stack). LWIP dual-stack support is 00624 // currently incomplete as of 2.0.0rc2 - eg we will only be able 00625 // to do a UDP sendto to an address matching the type selected 00626 // here. Matching "get_ip_addr" and DNS logic, use v4 if 00627 // available. 00628 lwip_proto |= NETCONN_TYPE_IPV6; 00629 } 00630 #elif LWIP_IPV6 00631 lwip_proto |= NETCONN_TYPE_IPV6; 00632 #endif 00633 00634 s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback); 00635 00636 if (!s->conn) { 00637 mbed_lwip_arena_dealloc(s); 00638 return NSAPI_ERROR_NO_SOCKET ; 00639 } 00640 00641 netconn_set_recvtimeout(s->conn, 1); 00642 *(struct lwip_socket **)handle = s; 00643 return 0; 00644 } 00645 00646 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle) 00647 { 00648 struct lwip_socket *s = (struct lwip_socket *)handle; 00649 00650 err_t err = netconn_delete(s->conn); 00651 mbed_lwip_arena_dealloc(s); 00652 return mbed_lwip_err_remap(err); 00653 } 00654 00655 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 00656 { 00657 struct lwip_socket *s = (struct lwip_socket *)handle; 00658 ip_addr_t ip_addr; 00659 00660 if ((s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || 00661 (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { 00662 return NSAPI_ERROR_PARAMETER ; 00663 } 00664 00665 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00666 return NSAPI_ERROR_PARAMETER ; 00667 } 00668 00669 err_t err = netconn_bind(s->conn, &ip_addr, port); 00670 return mbed_lwip_err_remap(err); 00671 } 00672 00673 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog) 00674 { 00675 struct lwip_socket *s = (struct lwip_socket *)handle; 00676 00677 err_t err = netconn_listen_with_backlog(s->conn, backlog); 00678 return mbed_lwip_err_remap(err); 00679 } 00680 00681 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 00682 { 00683 struct lwip_socket *s = (struct lwip_socket *)handle; 00684 ip_addr_t ip_addr; 00685 00686 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00687 return NSAPI_ERROR_PARAMETER ; 00688 } 00689 00690 netconn_set_nonblocking(s->conn, false); 00691 err_t err = netconn_connect(s->conn, &ip_addr, port); 00692 netconn_set_nonblocking(s->conn, true); 00693 00694 return mbed_lwip_err_remap(err); 00695 } 00696 00697 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) 00698 { 00699 struct lwip_socket *s = (struct lwip_socket *)server; 00700 struct lwip_socket *ns = mbed_lwip_arena_alloc(); 00701 if (!ns) { 00702 return NSAPI_ERROR_NO_SOCKET ; 00703 } 00704 00705 err_t err = netconn_accept(s->conn, &ns->conn); 00706 if (err != ERR_OK) { 00707 mbed_lwip_arena_dealloc(ns); 00708 return mbed_lwip_err_remap(err); 00709 } 00710 00711 netconn_set_recvtimeout(ns->conn, 1); 00712 *(struct lwip_socket **)handle = ns; 00713 00714 ip_addr_t peer_addr; 00715 (void) netconn_peer(ns->conn, &peer_addr, port); 00716 convert_lwip_addr_to_mbed(addr, &peer_addr); 00717 00718 return 0; 00719 } 00720 00721 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) 00722 { 00723 struct lwip_socket *s = (struct lwip_socket *)handle; 00724 size_t bytes_written = 0; 00725 00726 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written); 00727 if (err != ERR_OK) { 00728 return mbed_lwip_err_remap(err); 00729 } 00730 00731 return (nsapi_size_or_error_t)bytes_written; 00732 } 00733 00734 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size) 00735 { 00736 struct lwip_socket *s = (struct lwip_socket *)handle; 00737 00738 if (!s->buf) { 00739 err_t err = netconn_recv(s->conn, &s->buf); 00740 s->offset = 0; 00741 00742 if (err != ERR_OK) { 00743 return mbed_lwip_err_remap(err); 00744 } 00745 } 00746 00747 u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); 00748 s->offset += recv; 00749 00750 if (s->offset >= netbuf_len(s->buf)) { 00751 netbuf_delete(s->buf); 00752 s->buf = 0; 00753 } 00754 00755 return recv; 00756 } 00757 00758 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) 00759 { 00760 struct lwip_socket *s = (struct lwip_socket *)handle; 00761 ip_addr_t ip_addr; 00762 00763 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 00764 return NSAPI_ERROR_PARAMETER ; 00765 } 00766 00767 struct netbuf *buf = netbuf_new(); 00768 err_t err = netbuf_ref(buf, data, (u16_t)size); 00769 if (err != ERR_OK) { 00770 netbuf_free(buf); 00771 return mbed_lwip_err_remap(err); 00772 } 00773 00774 err = netconn_sendto(s->conn, buf, &ip_addr, port); 00775 netbuf_delete(buf); 00776 if (err != ERR_OK) { 00777 return mbed_lwip_err_remap(err); 00778 } 00779 00780 return size; 00781 } 00782 00783 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) 00784 { 00785 struct lwip_socket *s = (struct lwip_socket *)handle; 00786 struct netbuf *buf; 00787 00788 err_t err = netconn_recv(s->conn, &buf); 00789 if (err != ERR_OK) { 00790 return mbed_lwip_err_remap(err); 00791 } 00792 00793 convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf)); 00794 *port = netbuf_fromport(buf); 00795 00796 u16_t recv = netbuf_copy(buf, data, (u16_t)size); 00797 netbuf_delete(buf); 00798 00799 return recv; 00800 } 00801 00802 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) 00803 { 00804 struct lwip_socket *s = (struct lwip_socket *)handle; 00805 00806 switch (optname) { 00807 case NSAPI_KEEPALIVE : 00808 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00809 return NSAPI_ERROR_UNSUPPORTED ; 00810 } 00811 00812 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; 00813 return 0; 00814 00815 case NSAPI_KEEPIDLE : 00816 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00817 return NSAPI_ERROR_UNSUPPORTED ; 00818 } 00819 00820 s->conn->pcb.tcp->keep_idle = *(int*)optval; 00821 return 0; 00822 00823 case NSAPI_KEEPINTVL : 00824 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00825 return NSAPI_ERROR_UNSUPPORTED ; 00826 } 00827 00828 s->conn->pcb.tcp->keep_intvl = *(int*)optval; 00829 return 0; 00830 00831 case NSAPI_REUSEADDR : 00832 if (optlen != sizeof(int)) { 00833 return NSAPI_ERROR_UNSUPPORTED ; 00834 } 00835 00836 if (*(int *)optval) { 00837 s->conn->pcb.tcp->so_options |= SOF_REUSEADDR; 00838 } else { 00839 s->conn->pcb.tcp->so_options &= ~SOF_REUSEADDR; 00840 } 00841 return 0; 00842 00843 default: 00844 return NSAPI_ERROR_UNSUPPORTED ; 00845 } 00846 } 00847 00848 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data) 00849 { 00850 struct lwip_socket *s = (struct lwip_socket *)handle; 00851 00852 s->cb = callback; 00853 s->data = data; 00854 } 00855 00856 /* LWIP network stack */ 00857 const nsapi_stack_api_t lwip_stack_api = { 00858 .gethostbyname = mbed_lwip_gethostbyname, 00859 .socket_open = mbed_lwip_socket_open, 00860 .socket_close = mbed_lwip_socket_close, 00861 .socket_bind = mbed_lwip_socket_bind, 00862 .socket_listen = mbed_lwip_socket_listen, 00863 .socket_connect = mbed_lwip_socket_connect, 00864 .socket_accept = mbed_lwip_socket_accept, 00865 .socket_send = mbed_lwip_socket_send, 00866 .socket_recv = mbed_lwip_socket_recv, 00867 .socket_sendto = mbed_lwip_socket_sendto, 00868 .socket_recvfrom = mbed_lwip_socket_recvfrom, 00869 .setsockopt = mbed_lwip_setsockopt, 00870 .socket_attach = mbed_lwip_socket_attach, 00871 }; 00872 00873 nsapi_stack_t lwip_stack = { 00874 .stack_api = &lwip_stack_api, 00875 };
Generated on Tue Jul 12 2022 14:21:12 by
1.7.2
