Nathan Yonkee / Mbed 2 deprecated Nucleo_sinewave_output_copy

Dependencies:   mbed

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 "mbed_assert.h"
00020 #include <stdio.h>
00021 #include <stdbool.h>
00022 #include <string.h>
00023 #include "lwip_stack.h"
00024 
00025 #include "eth_arch.h"
00026 #include "lwip/opt.h"
00027 #include "lwip/api.h"
00028 #include "lwip/inet.h"
00029 #include "lwip/netif.h"
00030 #include "lwip/dhcp.h"
00031 #include "lwip/tcpip.h"
00032 #include "lwip/tcp.h"
00033 #include "lwip/ip.h"
00034 #include "lwip/mld6.h"
00035 #include "lwip/igmp.h"
00036 #include "lwip/dns.h"
00037 #include "lwip/udp.h"
00038 #include "lwip_errno.h"
00039 #include "netif/lwip_ethernet.h"
00040 #include "emac_api.h"
00041 #include "ppp_lwip.h"
00042 
00043 static nsapi_error_t mbed_lwip_err_remap(err_t err);
00044 
00045 #if DEVICE_EMAC
00046     #define MBED_NETIF_INIT_FN emac_lwip_if_init
00047 #else
00048     #define MBED_NETIF_INIT_FN eth_arch_enetif_init
00049 #endif
00050 
00051 #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
00052     #define LWIP_SOCKET_MAX_MEMBERSHIPS 4
00053 #endif
00054 
00055 /* Static arena of sockets */
00056 static struct lwip_socket {
00057     bool in_use;
00058 
00059     struct netconn *conn;
00060     struct netbuf *buf;
00061     u16_t offset;
00062 
00063     void (*cb)(void *);
00064     void *data;
00065 
00066     // Track multicast addresses subscribed to by this socket
00067     nsapi_ip_mreq_t *multicast_memberships;
00068     uint32_t         multicast_memberships_count;
00069     uint32_t         multicast_memberships_registry;
00070 
00071 } lwip_arena[MEMP_NUM_NETCONN];
00072 
00073 static bool lwip_inited = false;
00074 static nsapi_connection_status_t lwip_connected = NSAPI_STATUS_DISCONNECTED ;
00075 static bool netif_inited = false;
00076 static bool netif_is_ppp = false;
00077 
00078 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen);
00079 
00080 static inline uint32_t next_registered_multicast_member(const struct lwip_socket *s, uint32_t index) {
00081     while (!(s->multicast_memberships_registry & (0x0001 << index))) { index++; }
00082     return index;
00083 }
00084 
00085 static inline uint32_t next_free_multicast_member(const struct lwip_socket *s, uint32_t index) {
00086     while ((s->multicast_memberships_registry & (0x0001 << index))) { index++; }
00087     return index;
00088 }
00089 
00090 static inline void set_multicast_member_registry_bit(struct lwip_socket *s, uint32_t index) {
00091     s->multicast_memberships_registry |= (0x0001 << index);
00092 }
00093 
00094 static inline void clear_multicast_member_registry_bit(struct lwip_socket *s, uint32_t index) {
00095     s->multicast_memberships_registry &= ~(0x0001 << index);
00096 }
00097 
00098 static struct lwip_socket *mbed_lwip_arena_alloc(void)
00099 {
00100     sys_prot_t prot = sys_arch_protect();
00101 
00102     for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
00103         if (!lwip_arena[i].in_use) {
00104             struct lwip_socket *s = &lwip_arena[i];
00105             memset(s, 0, sizeof *s);
00106             s->in_use = true;
00107             sys_arch_unprotect(prot);
00108             return s;
00109         }
00110     }
00111 
00112     sys_arch_unprotect(prot);
00113     return 0;
00114 }
00115 
00116 static void mbed_lwip_arena_dealloc(struct lwip_socket *s)
00117 {
00118     s->in_use = false;
00119 
00120     while (s->multicast_memberships_count > 0) {
00121         uint32_t index = 0;
00122         index = next_registered_multicast_member(s, index);
00123 
00124         mbed_lwip_setsockopt(NULL, s, NSAPI_SOCKET , NSAPI_DROP_MEMBERSHIP , &s->multicast_memberships[index],
00125             sizeof(s->multicast_memberships[index]));
00126         index++;
00127     }
00128 
00129     free(s->multicast_memberships);
00130     s->multicast_memberships = NULL;
00131 }
00132 
00133 static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
00134 {
00135     // Filter send minus events
00136     if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) {
00137         return;
00138     }
00139 
00140     sys_prot_t prot = sys_arch_protect();
00141 
00142     for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
00143         if (lwip_arena[i].in_use
00144             && lwip_arena[i].conn == nc
00145             && lwip_arena[i].cb) {
00146             lwip_arena[i].cb(lwip_arena[i].data);
00147         }
00148     }
00149 
00150     sys_arch_unprotect(prot);
00151 }
00152 
00153 
00154 /* TCP/IP and Network Interface Initialisation */
00155 static struct netif lwip_netif;
00156 #if LWIP_DHCP
00157 static bool lwip_dhcp = false;
00158 static bool lwip_dhcp_has_to_be_set = false;
00159 #endif
00160 static char lwip_mac_address[NSAPI_MAC_SIZE];
00161 
00162 #if !LWIP_IPV4 || !LWIP_IPV6
00163 static bool all_zeros(const uint8_t *p, int len)
00164 {
00165     for (int i = 0; i < len; i++) {
00166         if (p[i]) {
00167             return false;
00168         }
00169     }
00170 
00171     return true;
00172 }
00173 #endif
00174 
00175 static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in)
00176 {
00177 #if LWIP_IPV6
00178     if (in->version == NSAPI_IPv6 ) {
00179          IP_SET_TYPE(out, IPADDR_TYPE_V6);
00180          MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t));
00181          return true;
00182     }
00183 #if !LWIP_IPV4
00184     /* For bind() and other purposes, need to accept "null" of other type */
00185     /* (People use IPv4 0.0.0.0 as a general null) */
00186     if (in->version == NSAPI_UNSPEC  ||
00187         (in->version == NSAPI_IPv4  && all_zeros(in->bytes, 4))) {
00188         ip_addr_set_zero_ip6(out);
00189         return true;
00190     }
00191 #endif
00192 #endif
00193 
00194 #if LWIP_IPV4
00195     if (in->version == NSAPI_IPv4 ) {
00196          IP_SET_TYPE(out, IPADDR_TYPE_V4);
00197          MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t));
00198          return true;
00199     }
00200 #if !LWIP_IPV6
00201     /* For symmetry with above, accept IPv6 :: as a general null */
00202     if (in->version == NSAPI_UNSPEC  ||
00203         (in->version == NSAPI_IPv6  && all_zeros(in->bytes, 16))) {
00204         ip_addr_set_zero_ip4(out);
00205         return true;
00206     }
00207 #endif
00208 #endif
00209 
00210 #if LWIP_IPV4 && LWIP_IPV6
00211     if (in->version == NSAPI_UNSPEC ) {
00212 #if IP_VERSION_PREF == PREF_IPV4
00213         ip_addr_set_zero_ip4(out);
00214 #else
00215         ip_addr_set_zero_ip6(out);
00216 #endif
00217         return true;
00218     }
00219 #endif
00220 
00221     return false;
00222 }
00223 
00224 static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in)
00225 {
00226 #if LWIP_IPV6
00227     if (IP_IS_V6(in)) {
00228         out->version = NSAPI_IPv6 ;
00229         MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t));
00230         return true;
00231     }
00232 #endif
00233 #if LWIP_IPV4
00234     if (IP_IS_V4(in)) {
00235         out->version = NSAPI_IPv4 ;
00236         MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t));
00237         return true;
00238     }
00239 #endif
00240 #if LWIP_IPV6 && LWIP_IPV4
00241     return false;
00242 #endif
00243 }
00244 
00245 #if LWIP_IPV4
00246 static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif)
00247 {
00248     if (!netif_is_up(netif)) {
00249         return NULL;
00250     }
00251 
00252     if (!ip4_addr_isany(netif_ip4_addr(netif))) {
00253         return netif_ip_addr4(netif);
00254     }
00255 
00256     return NULL;
00257 }
00258 #endif
00259 
00260 #if LWIP_IPV6
00261 static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif)
00262 {
00263 
00264     if (!netif_is_up(netif)) {
00265         return NULL;
00266     }
00267 
00268     for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00269         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00270                 !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
00271             return netif_ip_addr6(netif, i);
00272         }
00273     }
00274 
00275     return NULL;
00276 }
00277 #endif
00278 
00279 static bool mbed_lwip_is_local_addr(const ip_addr_t *ip_addr)
00280 {
00281     struct netif *netif;
00282 
00283     for (netif = netif_list; netif != NULL; netif = netif->next) {
00284         if (!netif_is_up(netif)) {
00285             continue;
00286         }
00287 #if LWIP_IPV6
00288         if (IP_IS_V6(ip_addr)) {
00289             for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00290                 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00291                     ip6_addr_cmp(netif_ip6_addr(netif, i), ip_2_ip6(ip_addr))) {
00292                     return true;
00293                 }
00294             }
00295         }
00296 #endif
00297 
00298 #if LWIP_IPV4
00299         if (IP_IS_V4(ip_addr)) {
00300             if (!ip4_addr_isany(netif_ip4_addr(netif)) &&
00301                 ip4_addr_cmp(netif_ip4_addr(netif), ip_2_ip4(ip_addr))) {
00302                 return true;
00303             }
00304         }
00305 #endif
00306     }
00307     return false;
00308 }
00309 
00310 const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif)
00311 {
00312     const ip_addr_t *pref_ip_addr = 0;
00313     const ip_addr_t *npref_ip_addr = 0;
00314 
00315 #if LWIP_IPV4 && LWIP_IPV6
00316 #if IP_VERSION_PREF == PREF_IPV4
00317     pref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
00318     npref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
00319 #else
00320     pref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
00321     npref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
00322 #endif
00323 #elif LWIP_IPV6
00324     pref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
00325 #elif LWIP_IPV4
00326     pref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
00327 #endif
00328 
00329     if (pref_ip_addr) {
00330         return pref_ip_addr;
00331     } else if (npref_ip_addr && any_addr) {
00332         return npref_ip_addr;
00333     }
00334 
00335     return NULL;
00336 }
00337 
00338 static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index)
00339 {
00340 #if LWIP_IPV6
00341     if (addr_type == IPADDR_TYPE_V6) {
00342         /* 2001:4860:4860::8888 google */
00343         ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
00344                 PP_HTONL(0x20014860UL),
00345                 PP_HTONL(0x48600000UL),
00346                 PP_HTONL(0x00000000UL),
00347                 PP_HTONL(0x00008888UL));
00348         dns_setserver(index, &ipv6_dns_addr);
00349     }
00350 #endif
00351 #if LWIP_IPV4
00352     if (addr_type == IPADDR_TYPE_V4) {
00353         /* 8.8.8.8 google */
00354         ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808);
00355         dns_setserver(index, &ipv4_dns_addr);
00356     }
00357 #endif
00358 }
00359 
00360 static int get_ip_addr_type(const ip_addr_t *ip_addr)
00361 {
00362 #if LWIP_IPV6
00363     if (IP_IS_V6(ip_addr)) {
00364         return IPADDR_TYPE_V6;
00365     }
00366 #endif
00367 #if LWIP_IPV4
00368     if (IP_IS_V4(ip_addr)) {
00369         return IPADDR_TYPE_V4;
00370     }
00371 #endif
00372 #if LWIP_IPV6 && LWIP_IPV4
00373     return IPADDR_TYPE_ANY;
00374 #endif
00375 }
00376 
00377 void add_dns_addr(struct netif *lwip_netif)
00378 {
00379     // Check for existing dns address
00380     for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
00381         const ip_addr_t *dns_ip_addr = dns_getserver(numdns);
00382         if (!ip_addr_isany(dns_ip_addr)) {
00383             return;
00384         }
00385     }
00386 
00387     // Get preferred ip version
00388     const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(false, lwip_netif);
00389     u8_t addr_type = IPADDR_TYPE_ANY;
00390 
00391     // Add preferred ip version dns address to index 0
00392     if (ip_addr) {
00393         addr_type = get_ip_addr_type(ip_addr);
00394         add_dns_addr_to_dns_list_index(addr_type, 0);
00395     }
00396 
00397 #if LWIP_IPV4 && LWIP_IPV6
00398     if (!ip_addr) {
00399         // Get address for any ip version
00400         ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif);
00401         if (!ip_addr) {
00402             return;
00403         }
00404         addr_type = get_ip_addr_type(ip_addr);
00405         // Add the dns address to index 0
00406         add_dns_addr_to_dns_list_index(addr_type, 0);
00407     }
00408 
00409     if (addr_type == IPADDR_TYPE_V4) {
00410         // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1
00411         ip_addr = mbed_lwip_get_ipv6_addr(lwip_netif);
00412     } else if (addr_type == IPADDR_TYPE_V6) {
00413         // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1
00414         ip_addr = mbed_lwip_get_ipv4_addr(lwip_netif);
00415     } else {
00416         ip_addr = NULL;
00417     }
00418 
00419     if (ip_addr) {
00420         addr_type = get_ip_addr_type(ip_addr);
00421         add_dns_addr_to_dns_list_index(addr_type, 1);
00422     }
00423 #endif
00424 }
00425 
00426 static sys_sem_t lwip_tcpip_inited;
00427 static void mbed_lwip_tcpip_init_irq(void *eh)
00428 {
00429     sys_sem_signal(&lwip_tcpip_inited);
00430 }
00431 
00432 /** This is a pointer to an Ethernet IF, whose callback will be called in case
00433  *  of network connection status changes
00434  */
00435 static void *lwip_status_cb_handle = NULL;
00436 /** This function is called when the netif state is set to up or down
00437  */
00438 static mbed_lwip_client_callback lwip_client_callback = NULL;
00439 /** The blocking status of the if
00440  */
00441 static bool lwip_blocking = true; 
00442 static bool lwip_ppp = false;
00443 
00444 
00445 static nsapi_error_t mbed_set_dhcp(struct netif *lwip_netif)
00446 {
00447     if (!lwip_ppp) {
00448         netif_set_up(lwip_netif);
00449     }
00450 
00451 #if LWIP_DHCP
00452     if (lwip_dhcp && lwip_dhcp_has_to_be_set) {
00453         err_t err = dhcp_start(lwip_netif);
00454         lwip_dhcp_has_to_be_set = false;
00455         if (err) {
00456             lwip_connected = NSAPI_STATUS_DISCONNECTED ;
00457             if (lwip_client_callback) {
00458                 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00459             }
00460             return NSAPI_ERROR_DHCP_FAILURE ;
00461         }
00462     }
00463 #endif
00464 
00465     return NSAPI_ERROR_OK ;
00466 }
00467 
00468 static sys_sem_t lwip_netif_linked;
00469 static sys_sem_t lwip_netif_unlinked;
00470 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif)
00471 {
00472     if (netif_is_link_up(lwip_netif)) {
00473 
00474         nsapi_error_t dhcp_status = mbed_set_dhcp(lwip_netif);
00475 
00476         if (lwip_blocking && dhcp_status == NSAPI_ERROR_OK ) {
00477             sys_sem_signal(&lwip_netif_linked);
00478         } else if (dhcp_status != NSAPI_ERROR_OK ) {
00479             netif_set_down(lwip_netif);
00480         }
00481 
00482 
00483     } else {
00484         sys_sem_signal(&lwip_netif_unlinked);
00485         netif_set_down(lwip_netif);
00486     }
00487 }
00488 
00489 
00490 
00491 
00492 static char lwip_has_addr_state = 0;
00493 
00494 #define HAS_ANY_ADDR  1
00495 static sys_sem_t lwip_netif_has_any_addr;
00496 #if PREF_ADDR_TIMEOUT
00497 #define HAS_PREF_ADDR 2
00498 static sys_sem_t lwip_netif_has_pref_addr;
00499 #endif
00500 #if BOTH_ADDR_TIMEOUT
00501 #define HAS_BOTH_ADDR 4
00502 static sys_sem_t lwip_netif_has_both_addr;
00503 #endif
00504 
00505 
00506 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif)
00507 {
00508     if (netif_is_up(lwip_netif)) {
00509         bool dns_addr_has_to_be_added = false;
00510         if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) {
00511             if (lwip_blocking) {
00512                 sys_sem_signal(&lwip_netif_has_any_addr);
00513             }
00514             lwip_has_addr_state |= HAS_ANY_ADDR;
00515             dns_addr_has_to_be_added = true;
00516         }
00517 #if PREF_ADDR_TIMEOUT
00518         if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) {
00519             if (lwip_blocking) {
00520                 sys_sem_signal(&lwip_netif_has_pref_addr);
00521             }
00522             lwip_has_addr_state |= HAS_PREF_ADDR;
00523             dns_addr_has_to_be_added = true;
00524         }
00525 #endif
00526 #if BOTH_ADDR_TIMEOUT
00527         if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) {
00528             if (lwip_blocking) {
00529                 sys_sem_signal(&lwip_netif_has_both_addr);
00530             }
00531             lwip_has_addr_state |= HAS_BOTH_ADDR;
00532             dns_addr_has_to_be_added = true;
00533         }
00534 #endif
00535 
00536         if (dns_addr_has_to_be_added && !lwip_blocking) {
00537             add_dns_addr(lwip_netif);
00538         }
00539 
00540     
00541         if (lwip_has_addr_state & HAS_ANY_ADDR) {
00542             lwip_connected = NSAPI_STATUS_GLOBAL_UP ;
00543         }
00544     } else {
00545         lwip_connected = NSAPI_STATUS_DISCONNECTED ;
00546     }
00547 
00548     if (lwip_client_callback) {
00549         lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , lwip_connected);
00550     }
00551 }
00552 
00553 void mbed_lwip_set_blocking(bool blocking)
00554 {
00555     lwip_blocking = blocking;
00556 }
00557 
00558 void mbed_lwip_attach(mbed_lwip_client_callback client_callback, void *status_cb_handle)
00559 {
00560     lwip_client_callback = client_callback;
00561     lwip_status_cb_handle = status_cb_handle;
00562 }
00563 
00564 nsapi_connection_status_t mbed_lwip_netif_status_check(void)
00565 {
00566     return lwip_connected;
00567 }
00568 
00569 
00570 #if LWIP_ETHERNET
00571 static void mbed_lwip_set_mac_address(struct netif *netif)
00572 {
00573 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
00574     netif->hwaddr[0] = MBED_MAC_ADDR_0;
00575     netif->hwaddr[1] = MBED_MAC_ADDR_1;
00576     netif->hwaddr[2] = MBED_MAC_ADDR_2;
00577     netif->hwaddr[3] = MBED_MAC_ADDR_3;
00578     netif->hwaddr[4] = MBED_MAC_ADDR_4;
00579     netif->hwaddr[5] = MBED_MAC_ADDR_5;
00580 #else
00581     mbed_mac_address((char *)netif->hwaddr);
00582 #endif
00583 
00584     netif->hwaddr_len = ETH_HWADDR_LEN;
00585 
00586     /* Use mac address as additional seed to random number generator */
00587     uint64_t seed = netif->hwaddr[0];
00588     for (uint8_t i = 1; i < 8; i++) {
00589         seed <<= 8;
00590         seed |= netif->hwaddr[i % 6];
00591     }
00592     lwip_add_random_seed(seed);
00593 }
00594 
00595 static void mbed_lwip_record_mac_address(const struct netif *netif)
00596 {
00597     const u8_t *mac = netif->hwaddr;
00598     snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
00599              mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00600 }
00601 #endif // LWIP_ETHERNET
00602 
00603 /* LWIP interface implementation */
00604 const char *mbed_lwip_get_mac_address(void)
00605 {
00606     return lwip_mac_address[0] ? lwip_mac_address : NULL;
00607 }
00608 
00609 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen)
00610 {
00611     const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
00612     if (!addr) {
00613         return NULL;
00614     }
00615 #if LWIP_IPV6
00616     if (IP_IS_V6(addr)) {
00617         return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
00618     }
00619 #endif
00620 #if LWIP_IPV4
00621     if (IP_IS_V4(addr)) {
00622         return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
00623     }
00624 #endif
00625 #if LWIP_IPV6 && LWIP_IPV4
00626     return NULL;
00627 #endif
00628 }
00629 
00630 char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen)
00631 {
00632 #if LWIP_IPV4
00633     const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif);
00634     if (!ip4_addr_isany(addr)) {
00635         return ip4addr_ntoa_r(addr, buf, buflen);
00636     } else {
00637         return NULL;
00638     }
00639 #else
00640     return NULL;
00641 #endif
00642 }
00643 
00644 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen)
00645 {
00646 #if LWIP_IPV4
00647     const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif);
00648     if (!ip4_addr_isany(addr)) {
00649         return ip4addr_ntoa_r(addr, buf, buflen);
00650     } else {
00651         return NULL;
00652     }
00653 #else
00654     return NULL;
00655 #endif
00656 }
00657 
00658 static void mbed_lwip_core_init(void)
00659 {
00660 
00661     // Check if we've already brought up lwip
00662     if (!lwip_inited) {
00663     // Seed lwip random
00664         lwip_seed_random();
00665 
00666         // Initialise TCP sequence number
00667         uint32_t tcp_isn_secret[4];
00668         for (int i = 0; i < 4; i++) {
00669             tcp_isn_secret[i] = LWIP_RAND();
00670         }
00671         lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret);
00672 
00673         sys_sem_new(&lwip_tcpip_inited, 0);
00674         sys_sem_new(&lwip_netif_linked, 0);
00675         sys_sem_new(&lwip_netif_unlinked, 0);
00676         sys_sem_new(&lwip_netif_has_any_addr, 0);
00677 #if PREF_ADDR_TIMEOUT
00678         sys_sem_new(&lwip_netif_has_pref_addr, 0);
00679 #endif
00680 #if BOTH_ADDR_TIMEOUT
00681         sys_sem_new(&lwip_netif_has_both_addr, 0);
00682 #endif
00683         tcpip_init(mbed_lwip_tcpip_init_irq, NULL);
00684         sys_arch_sem_wait(&lwip_tcpip_inited, 0);
00685 
00686         lwip_inited = true;
00687     }
00688 }
00689 
00690 nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac)
00691 {
00692 #if LWIP_ETHERNET
00693     // Choose a MAC address - driver can override
00694     mbed_lwip_set_mac_address(&lwip_netif);
00695     // Set up network
00696     if (!netif_add(&lwip_netif,
00697 #if LWIP_IPV4
00698                    0, 0, 0,
00699 #endif
00700                    emac, MBED_NETIF_INIT_FN, tcpip_input)) {
00701         return NSAPI_ERROR_DEVICE_ERROR ;
00702     }
00703     // Note the MAC address actually in use
00704     mbed_lwip_record_mac_address(&lwip_netif);
00705 #if !DEVICE_EMAC
00706     eth_arch_enable_interrupts();
00707 #endif
00708 
00709     return NSAPI_ERROR_OK ;
00710 #else
00711     return NSAPI_ERROR_UNSUPPORTED ;
00712 #endif //LWIP_ETHERNET
00713 }
00714 
00715 // Backwards compatibility with people using DEVICE_EMAC
00716 nsapi_error_t mbed_lwip_init(emac_interface_t *emac)
00717 {
00718     nsapi_error_t ret;
00719     mbed_lwip_core_init();
00720     ret = mbed_lwip_emac_init(emac);
00721     if (ret == NSAPI_ERROR_OK ) {
00722         netif_inited = true;
00723     }
00724     return ret;
00725 }
00726 
00727 
00728 // Backwards compatibility with people using DEVICE_EMAC
00729 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
00730 {
00731     return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw, DEFAULT_STACK);
00732 }
00733 
00734 nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, 
00735     const nsapi_ip_stack_t stack)
00736 {
00737     // Check if we've already connected
00738  
00739     if (lwip_connected == NSAPI_STATUS_GLOBAL_UP ) {
00740         return NSAPI_ERROR_IS_CONNECTED ;
00741     } else if (lwip_connected == NSAPI_STATUS_CONNECTING ) {
00742         return NSAPI_ERROR_ALREADY ;
00743     }
00744 
00745     lwip_connected = NSAPI_STATUS_CONNECTING ;
00746     lwip_ppp = ppp;
00747 #if LWIP_DHCP
00748     lwip_dhcp_has_to_be_set = true;
00749     if (stack != IPV6_STACK) {
00750         lwip_dhcp = dhcp;
00751     } else {
00752         lwip_dhcp = false;
00753     }
00754 #endif
00755     mbed_lwip_core_init();
00756 
00757     nsapi_error_t ret;
00758     if (netif_inited) {
00759         /* Can't cope with changing mode */
00760         if (netif_is_ppp == ppp) {
00761             ret = NSAPI_ERROR_OK ;
00762         } else {
00763             ret = NSAPI_ERROR_PARAMETER ;
00764         }
00765     } else {
00766         if (ppp) {
00767             ret = ppp_lwip_if_init(&lwip_netif, stack);
00768         } else {
00769             ret = mbed_lwip_emac_init(NULL);
00770         }
00771     }
00772 
00773     if (ret != NSAPI_ERROR_OK ) {
00774         lwip_connected = NSAPI_STATUS_DISCONNECTED ;
00775         return ret;
00776     }
00777 
00778     
00779     if (lwip_client_callback) {
00780         lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_CONNECTING );
00781     }
00782 
00783     netif_inited = true;
00784     if (ppp) {
00785         netif_is_ppp = ppp;
00786     }
00787 
00788     netif_set_default(&lwip_netif);
00789     netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq);
00790     netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq);
00791 
00792 #if LWIP_IPV6
00793     if (stack != IPV4_STACK) {
00794         if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) {
00795             netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/);
00796         }
00797 
00798 #if LWIP_IPV6_MLD
00799         /*
00800          * For hardware/netifs that implement MAC filtering.
00801          * All-nodes link-local is handled by default, so we must let the hardware know
00802          * to allow multicast packets in.
00803          * Should set mld_mac_filter previously. */
00804         if (lwip_netif.mld_mac_filter != NULL) {
00805             ip6_addr_t ip6_allnodes_ll;
00806             ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
00807             lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
00808         }
00809 #endif /* LWIP_IPV6_MLD */
00810 
00811 #if LWIP_IPV6_AUTOCONFIG
00812         /* IPv6 address autoconfiguration not enabled by default */
00813         lwip_netif.ip6_autoconfig_enabled = 1;
00814     } else {
00815         // Disable router solidifications
00816         lwip_netif.rs_count = 0;
00817     }
00818 #endif /* LWIP_IPV6_AUTOCONFIG */
00819 #endif // LWIP_IPV6
00820 
00821 #if LWIP_IPV4
00822     if (stack != IPV6_STACK) {
00823         if (!dhcp && !ppp) {
00824             ip4_addr_t ip_addr;
00825             ip4_addr_t netmask_addr;
00826             ip4_addr_t gw_addr;
00827 
00828             if (!inet_aton(ip, &ip_addr) ||
00829                 !inet_aton(netmask, &netmask_addr) ||
00830                 !inet_aton(gw, &gw_addr)) {
00831                 lwip_connected = NSAPI_STATUS_DISCONNECTED ;
00832                 if (lwip_client_callback) {
00833                     lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00834                 }
00835                 return NSAPI_ERROR_PARAMETER ;
00836             }
00837 
00838             netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
00839         }
00840     }
00841 #endif
00842 
00843     if (ppp) {
00844        err_t err = ppp_lwip_connect();
00845        if (err) {
00846            lwip_connected = NSAPI_STATUS_DISCONNECTED ;
00847            if (lwip_client_callback) {
00848                lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00849            }
00850            return mbed_lwip_err_remap(err);
00851        }
00852     }
00853 
00854 
00855 
00856     if (!netif_is_link_up(&lwip_netif)) {
00857         if (lwip_blocking) {
00858             if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) {
00859                 if (ppp) {
00860                     ppp_lwip_disconnect();
00861                 }
00862                 return NSAPI_ERROR_NO_CONNECTION ;
00863             }
00864         }
00865     } else {
00866         ret = mbed_set_dhcp(&lwip_netif);
00867         if (ret != NSAPI_ERROR_OK ) {
00868             return ret;
00869         }
00870     }
00871         
00872     if (lwip_blocking) {
00873         // If doesn't have address
00874         if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) {
00875             if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) {
00876                 if (ppp) {
00877                     ppp_lwip_disconnect();
00878                 }
00879                 return NSAPI_ERROR_DHCP_FAILURE ;
00880             }
00881         }
00882     } else {
00883         return NSAPI_ERROR_OK ;
00884     }
00885 
00886 #if PREF_ADDR_TIMEOUT
00887     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00888         // If address is not for preferred stack waits a while to see
00889         // if preferred stack address is acquired
00890         if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) {
00891             sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
00892         }
00893     }
00894 #endif
00895 #if BOTH_ADDR_TIMEOUT
00896     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00897         // If addresses for both stacks are not available waits a while to
00898         // see if address for both stacks are acquired
00899         if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) {
00900             sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
00901         }
00902     }
00903 #endif
00904 
00905     add_dns_addr(&lwip_netif);
00906 
00907     return NSAPI_ERROR_OK ;
00908 }
00909 
00910 #if LWIP_IPV6
00911 void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif)
00912 {
00913     for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00914         netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID);
00915     }
00916 }
00917 #endif
00918 
00919 // Backwards compatibility with people using DEVICE_EMAC
00920 nsapi_error_t mbed_lwip_bringdown(void)
00921 {
00922     return mbed_lwip_bringdown_2(false);
00923 }
00924 
00925 nsapi_error_t mbed_lwip_bringdown_2(bool ppp)
00926 {
00927     // Check if we've connected
00928     if (lwip_connected == NSAPI_STATUS_DISCONNECTED ) {
00929         return NSAPI_ERROR_PARAMETER ;
00930     }
00931 
00932 #if LWIP_DHCP
00933     // Disconnect from the network
00934     if (lwip_dhcp) {
00935         dhcp_release(&lwip_netif);
00936         dhcp_stop(&lwip_netif);
00937         lwip_dhcp = false;
00938         lwip_dhcp_has_to_be_set = false;
00939     }
00940 #endif
00941 
00942     if (ppp) {
00943         /* this is a blocking call, returns when PPP is properly closed */
00944        err_t err = ppp_lwip_disconnect();
00945        if (err) {
00946            return mbed_lwip_err_remap(err);
00947        }
00948        MBED_ASSERT(!netif_is_link_up(&lwip_netif));
00949        /*if (netif_is_link_up(&lwip_netif)) {
00950            if (sys_arch_sem_wait(&lwip_netif_unlinked, 15000) == SYS_ARCH_TIMEOUT) {
00951                return NSAPI_ERROR_DEVICE_ERROR;
00952            }
00953        }*/
00954     } else {
00955         netif_set_down(&lwip_netif);
00956     }
00957 
00958 #if LWIP_IPV6
00959     mbed_lwip_clear_ipv6_addresses(&lwip_netif);
00960 #endif
00961 
00962     sys_sem_free(&lwip_netif_has_any_addr);
00963     sys_sem_new(&lwip_netif_has_any_addr, 0);
00964 #if PREF_ADDR_TIMEOUT
00965     sys_sem_free(&lwip_netif_has_pref_addr);
00966     sys_sem_new(&lwip_netif_has_pref_addr, 0);
00967 #endif
00968 #if BOTH_ADDR_TIMEOUT
00969     sys_sem_free(&lwip_netif_has_both_addr);
00970     sys_sem_new(&lwip_netif_has_both_addr, 0);
00971 #endif
00972     lwip_has_addr_state = 0;
00973     lwip_connected = NSAPI_STATUS_DISCONNECTED ;
00974     return 0;
00975 }
00976 
00977 /* LWIP error remapping */
00978 static nsapi_error_t mbed_lwip_err_remap(err_t err) {
00979     switch (err) {
00980         case ERR_OK:
00981         case ERR_CLSD:
00982             return 0;
00983         case ERR_MEM:
00984         case ERR_BUF:
00985             return NSAPI_ERROR_NO_MEMORY ;
00986         case ERR_CONN:
00987         case ERR_RST:
00988         case ERR_ABRT:
00989             return NSAPI_ERROR_NO_CONNECTION ;
00990         case ERR_TIMEOUT:
00991         case ERR_RTE:
00992         case ERR_WOULDBLOCK:
00993             return NSAPI_ERROR_WOULD_BLOCK ;
00994         case ERR_VAL:
00995         case ERR_USE:
00996         case ERR_ARG:
00997             return NSAPI_ERROR_PARAMETER ;
00998         case ERR_INPROGRESS:
00999             return NSAPI_ERROR_IN_PROGRESS ;
01000         case ERR_ALREADY:
01001             return NSAPI_ERROR_ALREADY ;
01002         case ERR_ISCONN:
01003             return NSAPI_ERROR_IS_CONNECTED ;
01004         default:
01005             return NSAPI_ERROR_DEVICE_ERROR ;
01006     }
01007 }
01008 
01009 /* LWIP network stack implementation */
01010 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version)
01011 {
01012     ip_addr_t lwip_addr;
01013 
01014 #if LWIP_IPV4 && LWIP_IPV6
01015     u8_t addr_type;
01016     if (version == NSAPI_UNSPEC ) {
01017         const ip_addr_t *ip_addr;
01018         ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
01019         // Prefer IPv6
01020         if (IP_IS_V6(ip_addr)) {
01021             // If IPv4 is available use it as backup
01022             if (mbed_lwip_get_ipv4_addr(&lwip_netif)) {
01023                 addr_type = NETCONN_DNS_IPV6_IPV4;
01024             } else {
01025                 addr_type = NETCONN_DNS_IPV6;
01026             }
01027         // Prefer IPv4
01028         } else {
01029             // If IPv6 is available use it as backup
01030             if (mbed_lwip_get_ipv6_addr(&lwip_netif)) {
01031                 addr_type = NETCONN_DNS_IPV4_IPV6;
01032             } else {
01033                 addr_type = NETCONN_DNS_IPV4;
01034             }
01035         }
01036     } else if (version == NSAPI_IPv4 ) {
01037         addr_type = NETCONN_DNS_IPV4;
01038     } else if (version == NSAPI_IPv6 ) {
01039         addr_type = NETCONN_DNS_IPV6;
01040     } else {
01041         return NSAPI_ERROR_DNS_FAILURE ;
01042     }
01043     err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type);
01044 #elif LWIP_IPV4
01045     if (version != NSAPI_IPv4  && version != NSAPI_UNSPEC ) {
01046         return NSAPI_ERROR_DNS_FAILURE ;
01047     }
01048     err_t err = netconn_gethostbyname(host, &lwip_addr);
01049 #elif LWIP_IPV6
01050     if (version != NSAPI_IPv6  && version != NSAPI_UNSPEC ) {
01051         return NSAPI_ERROR_DNS_FAILURE ;
01052     }
01053     err_t err = netconn_gethostbyname(host, &lwip_addr);
01054 #endif
01055 
01056     if (err != ERR_OK) {
01057         return NSAPI_ERROR_DNS_FAILURE ;
01058     }
01059 
01060     convert_lwip_addr_to_mbed(addr, &lwip_addr);
01061 
01062     return 0;
01063 }
01064 
01065 static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr)
01066 {
01067     // Shift all dns servers down to give precedence to new server
01068     for (int i = DNS_MAX_SERVERS-1; i > 0; i--) {
01069         dns_setserver(i, dns_getserver(i-1));
01070     }
01071 
01072     ip_addr_t ip_addr;
01073     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
01074         return NSAPI_ERROR_PARAMETER ;
01075     }
01076 
01077     dns_setserver(0, &ip_addr);
01078     return 0;
01079 }
01080 
01081 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto)
01082 {
01083     // check if network is connected
01084     if (lwip_connected == NSAPI_STATUS_DISCONNECTED ) {
01085         return NSAPI_ERROR_NO_CONNECTION ;
01086     }
01087 
01088     // allocate a socket
01089     struct lwip_socket *s = mbed_lwip_arena_alloc();
01090     if (!s) {
01091         return NSAPI_ERROR_NO_SOCKET ;
01092     }
01093 
01094     enum netconn_type lwip_proto = proto == NSAPI_TCP  ? NETCONN_TCP : NETCONN_UDP;
01095 
01096 #if LWIP_IPV6
01097     // Enable IPv6 (or dual-stack)
01098     lwip_proto |= NETCONN_TYPE_IPV6;
01099 #endif
01100 
01101     s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback);
01102 
01103     if (!s->conn) {
01104         mbed_lwip_arena_dealloc(s);
01105         return NSAPI_ERROR_NO_SOCKET ;
01106     }
01107 
01108     netconn_set_recvtimeout(s->conn, 1);
01109     *(struct lwip_socket **)handle = s;
01110     return 0;
01111 }
01112 
01113 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle)
01114 {
01115     struct lwip_socket *s = (struct lwip_socket *)handle;
01116 
01117     netbuf_delete(s->buf);
01118     err_t err = netconn_delete(s->conn);
01119     mbed_lwip_arena_dealloc(s);
01120     return mbed_lwip_err_remap(err);
01121 }
01122 
01123 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
01124 {
01125     struct lwip_socket *s = (struct lwip_socket *)handle;
01126     ip_addr_t ip_addr;
01127 
01128     if (
01129 #if LWIP_TCP
01130         (s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) ||
01131 #endif
01132         (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) {
01133         return NSAPI_ERROR_PARAMETER ;
01134     }
01135 
01136     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
01137         return NSAPI_ERROR_PARAMETER ;
01138     }
01139 
01140     if (!ip_addr_isany(&ip_addr) && !mbed_lwip_is_local_addr(&ip_addr)) {
01141         return NSAPI_ERROR_PARAMETER ;
01142     }
01143 
01144     err_t err = netconn_bind(s->conn, &ip_addr, port);
01145     return mbed_lwip_err_remap(err);
01146 }
01147 
01148 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog)
01149 {
01150     struct lwip_socket *s = (struct lwip_socket *)handle;
01151 
01152     if (s->conn->pcb.tcp->local_port == 0) {
01153         return NSAPI_ERROR_PARAMETER ;
01154     }
01155 
01156     err_t err = netconn_listen_with_backlog(s->conn, backlog);
01157     return mbed_lwip_err_remap(err);
01158 }
01159 
01160 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
01161 {
01162     struct lwip_socket *s = (struct lwip_socket *)handle;
01163     ip_addr_t ip_addr;
01164 
01165     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
01166         return NSAPI_ERROR_PARAMETER ;
01167     }
01168 
01169     netconn_set_nonblocking(s->conn, false);
01170     err_t err = netconn_connect(s->conn, &ip_addr, port);
01171     netconn_set_nonblocking(s->conn, true);
01172 
01173     return mbed_lwip_err_remap(err);
01174 }
01175 
01176 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)
01177 {
01178     struct lwip_socket *s = (struct lwip_socket *)server;
01179     struct lwip_socket *ns = mbed_lwip_arena_alloc();
01180     if (!ns) {
01181         return NSAPI_ERROR_NO_SOCKET ;
01182     }
01183 
01184     if (s->conn->pcb.tcp->state != LISTEN) {
01185         return NSAPI_ERROR_PARAMETER ;
01186     }
01187 
01188     err_t err = netconn_accept(s->conn, &ns->conn);
01189     if (err != ERR_OK) {
01190         mbed_lwip_arena_dealloc(ns);
01191         return mbed_lwip_err_remap(err);
01192     }
01193 
01194     netconn_set_recvtimeout(ns->conn, 1);
01195     *(struct lwip_socket **)handle = ns;
01196 
01197     ip_addr_t peer_addr;
01198     (void) netconn_peer(ns->conn, &peer_addr, port);
01199     convert_lwip_addr_to_mbed(addr, &peer_addr);
01200 
01201     netconn_set_nonblocking(ns->conn, true);
01202 
01203     return 0;
01204 }
01205 
01206 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)
01207 {
01208     struct lwip_socket *s = (struct lwip_socket *)handle;
01209     size_t bytes_written = 0;
01210 
01211     err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written);
01212     if (err != ERR_OK) {
01213         return mbed_lwip_err_remap(err);
01214     }
01215 
01216     return (nsapi_size_or_error_t)bytes_written;
01217 }
01218 
01219 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size)
01220 {
01221     struct lwip_socket *s = (struct lwip_socket *)handle;
01222 
01223     if (!s->buf) {
01224         err_t err = netconn_recv(s->conn, &s->buf);
01225         s->offset = 0;
01226 
01227         if (err != ERR_OK) {
01228             return mbed_lwip_err_remap(err);
01229         }
01230     }
01231 
01232     u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset);
01233     s->offset += recv;
01234 
01235     if (s->offset >= netbuf_len(s->buf)) {
01236         netbuf_delete(s->buf);
01237         s->buf = 0;
01238     }
01239 
01240     return recv;
01241 }
01242 
01243 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)
01244 {
01245     struct lwip_socket *s = (struct lwip_socket *)handle;
01246     ip_addr_t ip_addr;
01247 
01248     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
01249         return NSAPI_ERROR_PARAMETER ;
01250     }
01251 
01252     struct netbuf *buf = netbuf_new();
01253     err_t err = netbuf_ref(buf, data, (u16_t)size);
01254     if (err != ERR_OK) {
01255         netbuf_free(buf);
01256         return mbed_lwip_err_remap(err);
01257     }
01258 
01259     err = netconn_sendto(s->conn, buf, &ip_addr, port);
01260     netbuf_delete(buf);
01261     if (err != ERR_OK) {
01262         return mbed_lwip_err_remap(err);
01263     }
01264 
01265     return size;
01266 }
01267 
01268 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)
01269 {
01270     struct lwip_socket *s = (struct lwip_socket *)handle;
01271     struct netbuf *buf;
01272 
01273     err_t err = netconn_recv(s->conn, &buf);
01274     if (err != ERR_OK) {
01275         return mbed_lwip_err_remap(err);
01276     }
01277 
01278     convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf));
01279     *port = netbuf_fromport(buf);
01280 
01281     u16_t recv = netbuf_copy(buf, data, (u16_t)size);
01282     netbuf_delete(buf);
01283 
01284     return recv;
01285 }
01286 
01287 static int32_t find_multicast_member(const struct lwip_socket *s, const nsapi_ip_mreq_t *imr) {
01288     uint32_t count = 0;
01289     uint32_t index = 0;
01290     // Set upper limit on while loop, should break out when the membership pair is found
01291     while (count < s->multicast_memberships_count) {
01292         index = next_registered_multicast_member(s, index);
01293 
01294         if (memcmp(&s->multicast_memberships[index].imr_multiaddr, &imr->imr_multiaddr, sizeof(nsapi_addr_t)) == 0 &&
01295            memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) {
01296             return index;
01297         }
01298         count++;
01299         index++;
01300     }
01301 
01302     return -1;
01303 }
01304 
01305 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
01306 {
01307     struct lwip_socket *s = (struct lwip_socket *)handle;
01308 
01309     switch (optname) {
01310 #if LWIP_TCP
01311         case NSAPI_KEEPALIVE :
01312             if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
01313                 return NSAPI_ERROR_UNSUPPORTED ;
01314             }
01315 
01316             s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE;
01317             return 0;
01318 
01319         case NSAPI_KEEPIDLE :
01320             if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
01321                 return NSAPI_ERROR_UNSUPPORTED ;
01322             }
01323 
01324             s->conn->pcb.tcp->keep_idle = *(int*)optval;
01325             return 0;
01326 
01327         case NSAPI_KEEPINTVL :
01328             if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
01329                 return NSAPI_ERROR_UNSUPPORTED ;
01330             }
01331 
01332             s->conn->pcb.tcp->keep_intvl = *(int*)optval;
01333             return 0;
01334 #endif
01335 
01336         case NSAPI_REUSEADDR :
01337             if (optlen != sizeof(int)) {
01338                 return NSAPI_ERROR_UNSUPPORTED ;
01339             }
01340 
01341             if (*(int *)optval) {
01342                 ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR);
01343             } else {
01344                 ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR);
01345             }
01346             return 0;
01347 
01348         case NSAPI_ADD_MEMBERSHIP :
01349         case NSAPI_DROP_MEMBERSHIP : {
01350             if (optlen != sizeof(nsapi_ip_mreq_t)) {
01351                 return NSAPI_ERROR_PARAMETER ;
01352             }
01353             err_t igmp_err;
01354             const nsapi_ip_mreq_t *imr = optval;
01355 
01356             /* Check interface address type matches group, or is unspecified */
01357             if (imr->imr_interface.version != NSAPI_UNSPEC  && imr->imr_interface.version != imr->imr_multiaddr.version) {
01358                 return NSAPI_ERROR_PARAMETER ;
01359             }
01360 
01361             ip_addr_t if_addr;
01362             ip_addr_t multi_addr;
01363 
01364             /* Convert the group address */
01365             if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) {
01366                 return NSAPI_ERROR_PARAMETER ;
01367             }
01368 
01369             /* Convert the interface address, or make sure it's the correct sort of "any" */
01370             if (imr->imr_interface.version != NSAPI_UNSPEC ) {
01371                 if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) {
01372                     return NSAPI_ERROR_PARAMETER ;
01373                 }
01374             } else {
01375                 ip_addr_set_any(IP_IS_V6(&if_addr), &if_addr);
01376             }
01377 
01378             igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED
01379             int32_t member_pair_index = find_multicast_member(s, imr);
01380 
01381             if (optname == NSAPI_ADD_MEMBERSHIP ) {
01382                 if (!s->multicast_memberships) {
01383                     // First multicast join on this socket, allocate space for membership tracking
01384                     s->multicast_memberships = malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS);
01385                     if (!s->multicast_memberships) {
01386                         return NSAPI_ERROR_NO_MEMORY ;
01387                     }
01388                 } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) {
01389                     return NSAPI_ERROR_NO_MEMORY ;
01390                 }
01391 
01392                 if (member_pair_index != -1) {
01393                     return NSAPI_ERROR_ADDRESS_IN_USE ;
01394                 }
01395 
01396                 member_pair_index = next_free_multicast_member(s, 0);
01397 
01398                 sys_prot_t prot = sys_arch_protect();
01399 
01400                 #if LWIP_IPV4
01401                 if (IP_IS_V4(&if_addr)) {
01402                     igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
01403                 }
01404                 #endif
01405                 #if LWIP_IPV6
01406                 if (IP_IS_V6(&if_addr)) {
01407                     igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
01408                 }
01409                 #endif
01410 
01411                 sys_arch_unprotect(prot);
01412 
01413                 if (igmp_err == ERR_OK) {
01414                     set_multicast_member_registry_bit(s, member_pair_index);
01415                     s->multicast_memberships[member_pair_index] = *imr;
01416                     s->multicast_memberships_count++;
01417                 }
01418             } else {
01419                 if (member_pair_index == -1) {
01420                     return NSAPI_ERROR_NO_ADDRESS ;
01421                 }
01422 
01423                 clear_multicast_member_registry_bit(s, member_pair_index);
01424                 s->multicast_memberships_count--;
01425 
01426                 sys_prot_t prot = sys_arch_protect();
01427 
01428                 #if LWIP_IPV4
01429                 if (IP_IS_V4(&if_addr)) {
01430                     igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
01431                 }
01432                 #endif
01433                 #if LWIP_IPV6
01434                 if (IP_IS_V6(&if_addr)) {
01435                     igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
01436                 }
01437                 #endif
01438 
01439                 sys_arch_unprotect(prot);
01440             }
01441 
01442             return mbed_lwip_err_remap(igmp_err);
01443          }
01444 
01445         default:
01446             return NSAPI_ERROR_UNSUPPORTED ;
01447     }
01448 }
01449 
01450 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data)
01451 {
01452     struct lwip_socket *s = (struct lwip_socket *)handle;
01453 
01454     s->cb = callback;
01455     s->data = data;
01456 }
01457 
01458 /* LWIP network stack */
01459 const nsapi_stack_api_t lwip_stack_api = {
01460     .gethostbyname      = mbed_lwip_gethostbyname,
01461     .add_dns_server     = mbed_lwip_add_dns_server,
01462     .socket_open        = mbed_lwip_socket_open,
01463     .socket_close       = mbed_lwip_socket_close,
01464     .socket_bind        = mbed_lwip_socket_bind,
01465     .socket_listen      = mbed_lwip_socket_listen,
01466     .socket_connect     = mbed_lwip_socket_connect,
01467     .socket_accept      = mbed_lwip_socket_accept,
01468     .socket_send        = mbed_lwip_socket_send,
01469     .socket_recv        = mbed_lwip_socket_recv,
01470     .socket_sendto      = mbed_lwip_socket_sendto,
01471     .socket_recvfrom    = mbed_lwip_socket_recvfrom,
01472     .setsockopt         = mbed_lwip_setsockopt,
01473     .socket_attach      = mbed_lwip_socket_attach,
01474 };
01475 
01476 nsapi_stack_t lwip_stack = {
01477     .stack_api = &lwip_stack_api,
01478 };