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