Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_stack.c Source File

lwip_stack.c

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