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.
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 17:34:46 by
1.7.2