ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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