nsapi_error_t LWIP::Interface::set_dhcp() { netif_set_up(&netif); #if LWIP_DHCP if (dhcp_has_to_be_set) { err_t err = dhcp_start(&netif); dhcp_has_to_be_set = false; if (err) { connected = NSAPI_STATUS_DISCONNECTED; if (client_callback) { client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); } return NSAPI_ERROR_DHCP_FAILURE; } dhcp_started = true; } #endif return NSAPI_ERROR_OK; }
static void * iio_device_failover_thread(void *args) { struct iio_device *device = (struct iio_device *)args; struct iio_vdisk_hostinfo *hostinfo = device->hostinfo; struct iio_vdisk_hostinfo *new_hostinfo; struct channel *new_channel; struct qnio_msg *msg; time_t start_t, end_t; double diff_t; time(&start_t); nioDbg("Starting failover on device %s", device->devid); read_hostinfo: new_hostinfo = iio_read_hostinfo(device->devid); if (new_hostinfo) { free(hostinfo); device->hostinfo = new_hostinfo; hostinfo = new_hostinfo; } hostinfo->failover_idx = -1; retry_nexthost: /* * Find next host */ hostinfo->failover_idx ++; if (hostinfo->failover_idx == hostinfo->nhosts) { goto read_hostinfo; } /* * Open channel to the new host */ new_channel = iio_channel_open(hostinfo->hosts[hostinfo->failover_idx], device->channel->cacert, device->channel->client_key, device->channel->client_cert); if (new_channel == NULL) { time(&end_t); diff_t = difftime(end_t, start_t); if (diff_t > FAILOVER_TIMEOUT) { nioDbg("Failover timedout"); goto err; } usleep(FAILOVER_RETRY_WAIT); goto retry_nexthost; } /* * Close the old channel. */ device->channel->cd->chdrv_close(device->channel); device->channel = new_channel; if (!iio_check_failover_ready(device)) { goto retry_nexthost; } /* * Restart messages */ ck_spinlock_lock(&device->slock); device->state = IIO_DEVICE_ACTIVE; while (!LIST_EMPTY(&device->retryq)) { msg = LIST_ENTRY(device->retryq.next, struct qnio_msg, lnode); LIST_DEL(&msg->lnode); device->retry_msg_count --; ck_spinlock_unlock(&device->slock); nioDbg("Restarting message, msgid=%ld %p", msg->hinfo.cookie, msg); iio_msg_resubmit(device, msg); ck_spinlock_lock(&device->slock); } ck_spinlock_unlock(&device->slock); pthread_exit(0); return NULL; err: /* * Fail all messages. */ ck_spinlock_lock(&device->slock); device->state = IIO_DEVICE_FAILED; while (!LIST_EMPTY(&device->retryq)) { msg = LIST_ENTRY(device->retryq.next, struct qnio_msg, lnode); LIST_DEL(&msg->lnode); nioDbg("No host found failing message, msgid=%ld %p", msg->hinfo.cookie, msg); device->retry_msg_count --; ck_spinlock_unlock(&device->slock); msg->hinfo.err = QNIOERROR_NOCONN; if (msg->hinfo.flags & QNIO_FLAG_SYNC_REQ) { ck_pr_store_int(&msg->resp_ready, 1); } else { client_callback(msg); } } ck_spinlock_unlock(&device->slock); pthread_exit(0); return NULL; }
nsapi_error_t LWIP::Interface::bringdown() { // Check if we've connected if (connected == NSAPI_STATUS_DISCONNECTED) { return NSAPI_ERROR_NO_CONNECTION; } #if LWIP_DHCP // Disconnect from the network if (dhcp_started) { dhcp_release(&netif); dhcp_stop(&netif); dhcp_started = false; dhcp_has_to_be_set = false; } #endif if (ppp) { /* this is a blocking call, returns when PPP is properly closed */ err_t err = ppp_lwip_disconnect(hw); if (err) { return err_remap(err); } MBED_ASSERT(!netif_is_link_up(&netif)); /*if (netif_is_link_up(&netif)) { if (sys_arch_sem_wait(&unlinked, 15000) == SYS_ARCH_TIMEOUT) { return NSAPI_ERROR_DEVICE_ERROR; } }*/ } else { netif_set_down(&netif); } #if LWIP_IPV6 mbed_lwip_clear_ipv6_addresses(&netif); #endif #if LWIP_IPV4 ip_addr_set_zero(&(netif.ip_addr)); ip_addr_set_zero(&(netif.netmask)); ip_addr_set_zero(&(netif.gw)); #endif osSemaphoreDelete(has_any_addr); osSemaphoreAttr_t attr; attr.name = NULL; attr.attr_bits = 0; attr.cb_mem = &has_any_addr_sem; attr.cb_size = sizeof has_any_addr_sem; has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr); #if PREF_ADDR_TIMEOUT osSemaphoreDelete(has_pref_addr); attr.cb_mem = &has_pref_addr_sem; attr.cb_size = sizeof has_pref_addr_sem; has_pref_addr = osSemaphoreNew(UINT16_MAX, 0, &attr); #endif #if BOTH_ADDR_TIMEOUT osSemaphoreDelete(has_both_addr); attr.cb_mem = &has_both_addr_sem; attr.cb_size = sizeof has_both_addr_sem; has_both_addr = osSemaphoreNew(UINT16_MAX, 0, &attr); #endif has_addr_state = 0; connected = NSAPI_STATUS_DISCONNECTED; if (client_callback) { client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, connected); } return 0; }
nsapi_error_t LWIP::Interface::bringup(bool dhcp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack, bool block) { // Check if we've already connected if (connected == NSAPI_STATUS_GLOBAL_UP) { return NSAPI_ERROR_IS_CONNECTED; } else if (connected == NSAPI_STATUS_CONNECTING) { return NSAPI_ERROR_ALREADY; } connected = NSAPI_STATUS_CONNECTING; blocking = block; #if LWIP_DHCP if (stack != IPV6_STACK && dhcp) { dhcp_has_to_be_set = true; } #endif #if LWIP_IPV6 if (stack != IPV4_STACK) { if (netif.hwaddr_len == 6) { netif_create_ip6_linklocal_address(&netif, 1/*from MAC*/); } #if LWIP_IPV6_MLD /* * For hardware/netifs that implement MAC filtering. * All-nodes link-local is handled by default, so we must let the hardware know * to allow multicast packets in. * Should set mld_mac_filter previously. */ if (netif.mld_mac_filter != NULL) { ip6_addr_t ip6_allnodes_ll; ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); netif.mld_mac_filter(&netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); } #endif /* LWIP_IPV6_MLD */ #if LWIP_IPV6_AUTOCONFIG /* IPv6 address autoconfiguration not enabled by default */ netif.ip6_autoconfig_enabled = 1; #endif /* LWIP_IPV6_AUTOCONFIG */ } else { // Disable rourter solicitations netif.rs_count = 0; } #endif /* LWIP_IPV6 */ #if LWIP_IPV4 if (stack != IPV6_STACK) { if (!dhcp && !ppp) { ip4_addr_t ip_addr; ip4_addr_t netmask_addr; ip4_addr_t gw_addr; if (!inet_aton(ip, &ip_addr) || !inet_aton(netmask, &netmask_addr) || !inet_aton(gw, &gw_addr)) { return NSAPI_ERROR_PARAMETER; } netif_set_addr(&netif, &ip_addr, &netmask_addr, &gw_addr); } } #endif if (client_callback) { client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING); } if (ppp) { err_t err = ppp_lwip_connect(hw); if (err) { connected = NSAPI_STATUS_DISCONNECTED; if (client_callback) { client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); } return err_remap(err); } } if (!netif_is_link_up(&netif)) { if (blocking) { if (osSemaphoreAcquire(linked, 15000) != osOK) { if (ppp) { (void) ppp_lwip_disconnect(hw); } return NSAPI_ERROR_NO_CONNECTION; } } } else { nsapi_error_t ret = set_dhcp(); if (ret != NSAPI_ERROR_OK) { return ret; } } if (!blocking) { // Done enough - as addresses are acquired, there will be // connected callbacks. // XXX shouldn't this be NSAPI_ERROR_IN_PROGRESS if in CONNECTING state? return NSAPI_ERROR_OK; } // If doesn't have address if (!LWIP::get_ip_addr(true, &netif)) { if (osSemaphoreAcquire(has_any_addr, DHCP_TIMEOUT * 1000) != osOK) { if (ppp) { (void) ppp_lwip_disconnect(hw); } return NSAPI_ERROR_DHCP_FAILURE; } } #if PREF_ADDR_TIMEOUT if (stack != IPV4_STACK && stack != IPV6_STACK) { // If address is not for preferred stack waits a while to see // if preferred stack address is acquired if (!LWIP::get_ip_addr(false, &netif)) { osSemaphoreAcquire(has_pref_addr, PREF_ADDR_TIMEOUT * 1000); } } #endif #if BOTH_ADDR_TIMEOUT if (stack != IPV4_STACK && stack != IPV6_STACK) { // If addresses for both stacks are not available waits a while to // see if address for both stacks are acquired if (!(LWIP::get_ipv4_addr(&netif) && LWIP::get_ipv6_addr(&netif))) { osSemaphoreAcquire(has_both_addr, BOTH_ADDR_TIMEOUT * 1000); } } #endif add_dns_addr(&netif); return NSAPI_ERROR_OK; }
int main(int argc, char **argv) { char *url = NULL; char *address = "queue"; char *mechanism = "ANONYMOUS"; int count = 1; bool quiet = false; int high = 100; int low = 50; int size = 32; int opt; while ((opt = getopt(argc, argv, "c:a:m:n:s:u:l:qhVXY")) != -1) { switch (opt) { case 'c': if (url) pn_fatal("multiple connect urls not allowed\n"); url = optarg; break; case 'a': address = optarg; break; case 'm': mechanism = optarg; break; case 'n': count = atoi(optarg); break; case 's': size = atoi(optarg); break; case 'u': high = atoi(optarg); break; case 'l': low = atoi(optarg); break; case 'q': quiet = true; break; case 'V': printf("proton version %i.%i\n", PN_VERSION_MAJOR, PN_VERSION_MINOR); exit(EXIT_SUCCESS); case 'X': value(argc, argv); exit(EXIT_SUCCESS); case 'Y': buffer(argc, argv); exit(EXIT_SUCCESS); case 'h': printf("Usage: %s [-h] [-c [user[:password]@]host[:port]] [-a <address>] [-m <sasl-mech>]\n", argv[0]); printf("\n"); printf(" -c The connect url.\n"); printf(" -a The AMQP address.\n"); printf(" -m The SASL mechanism.\n"); printf(" -n The number of messages.\n"); printf(" -s Message size.\n"); printf(" -u Upper flow threshold.\n"); printf(" -l Lower flow threshold.\n"); printf(" -q Supress printouts.\n"); printf(" -h Print this help.\n"); exit(EXIT_SUCCESS); default: /* '?' */ pn_fatal("Usage: %s -h\n", argv[0]); } } char *user = NULL; char *pass = NULL; char *host = "0.0.0.0"; char *port = "5672"; parse_url(url, &user, &pass, &host, &port); pn_driver_t *drv = pn_driver(); if (url) { struct client_context ctx = {false, false, count, count, drv, quiet, size, high, low}; ctx.username = user; ctx.password = pass; ctx.mechanism = mechanism; ctx.hostname = host; ctx.address = address; pn_connector_t *ctor = pn_connector(drv, host, port, &ctx); if (!ctor) pn_fatal("connector failed\n"); pn_connector_set_connection(ctor, pn_connection()); while (!ctx.done) { pn_driver_wait(drv, -1); pn_connector_t *c; while ((c = pn_driver_connector(drv))) { pn_connector_process(c); client_callback(c); if (pn_connector_closed(c)) { pn_connection_free(pn_connector_connection(c)); pn_connector_free(c); } else { pn_connector_process(c); } } } } else { struct server_context ctx = {0, quiet, size}; if (!pn_listener(drv, host, port, &ctx)) pn_fatal("listener failed\n"); while (true) { pn_driver_wait(drv, -1); pn_listener_t *l; pn_connector_t *c; while ((l = pn_driver_listener(drv))) { c = pn_listener_accept(l); pn_connector_set_context(c, &ctx); } while ((c = pn_driver_connector(drv))) { pn_connector_process(c); server_callback(c); if (pn_connector_closed(c)) { pn_connection_free(pn_connector_connection(c)); pn_connector_free(c); } else { pn_connector_process(c); } } } } pn_driver_free(drv); return 0; }