/** * Function setting up file descriptors and scheduling task to run * * @param plugin plugin as closure * @param now schedule task in 1ms, regardless of what curl may say * @return GNUNET_SYSERR for hard failure, GNUNET_OK for ok */ static int client_schedule (struct Plugin *plugin, int now) { fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet *grs; struct GNUNET_NETWORK_FDSet *gws; long to; CURLMcode mret; struct GNUNET_TIME_Relative timeout; /* Cancel previous scheduled task */ if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } max = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); mret = curl_multi_fdset (plugin->client_mh, &rs, &ws, &es, &max); if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_fdset", __FILE__, __LINE__, curl_multi_strerror (mret)); return GNUNET_SYSERR; } mret = curl_multi_timeout (plugin->client_mh, &to); if (to == -1) timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1); else timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to); if (now == GNUNET_YES) timeout = GNUNET_TIME_UNIT_MILLISECONDS; if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_timeout", __FILE__, __LINE__, curl_multi_strerror (mret)); return GNUNET_SYSERR; } grs = GNUNET_NETWORK_fdset_create (); gws = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); plugin->client_perform_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, timeout, grs, gws, &client_run, plugin); GNUNET_NETWORK_fdset_destroy (gws); GNUNET_NETWORK_fdset_destroy (grs); return GNUNET_OK; }
/** * Start listening to stdin */ static void listen_stdio (void) { struct GNUNET_NETWORK_FDSet *rs; rs = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_set_native (rs, 0); GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_FOREVER_REL, rs, NULL, &read_stdio, NULL); GNUNET_NETWORK_fdset_destroy (rs); }
/** * Function that queries MHD's select sets and * starts the task waiting for them. */ static struct GNUNET_SCHEDULER_Task * prepare_daemon (struct MHD_Daemon *daemon_handle) { struct GNUNET_SCHEDULER_Task * ret; fd_set rs; fd_set ws; fd_set es; struct GNUNET_NETWORK_FDSet *wrs; struct GNUNET_NETWORK_FDSet *wws; int max; MHD_UNSIGNED_LONG_LONG timeout; int haveto; struct GNUNET_TIME_Relative tv; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); wrs = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); max = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max)); haveto = MHD_get_timeout (daemon_handle, &timeout); if (haveto == MHD_YES) tv.rel_value_us = (uint64_t) timeout * 1000LL; else tv = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, tv, wrs, wws, &run_daemon, daemon_handle); GNUNET_NETWORK_fdset_destroy (wrs); GNUNET_NETWORK_fdset_destroy (wws); return ret; }
/** * Get a socket of the specified address family to send out a * UDP DNS request to the Internet. * * @param ctx the DNSSTUB context * @param af desired address family * @return NULL on error (given AF not "supported") */ static struct GNUNET_DNSSTUB_RequestSocket * get_request_socket (struct GNUNET_DNSSTUB_Context *ctx, int af) { struct GNUNET_DNSSTUB_RequestSocket *rs; struct GNUNET_NETWORK_FDSet *rset; rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, DNS_SOCKET_MAX)]; rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT); switch (af) { case AF_INET: if (NULL == rs->dnsout4) rs->dnsout4 = open_socket (AF_INET); break; case AF_INET6: if (NULL == rs->dnsout6) rs->dnsout6 = open_socket (AF_INET6); break; default: return NULL; } if (GNUNET_SCHEDULER_NO_TASK != rs->read_task) { GNUNET_SCHEDULER_cancel (rs->read_task); rs->read_task = GNUNET_SCHEDULER_NO_TASK; } if ( (NULL == rs->dnsout4) && (NULL == rs->dnsout6) ) return NULL; rset = GNUNET_NETWORK_fdset_create (); if (NULL != rs->dnsout4) GNUNET_NETWORK_fdset_set (rset, rs->dnsout4); if (NULL != rs->dnsout6) GNUNET_NETWORK_fdset_set (rset, rs->dnsout6); rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, REQUEST_TIMEOUT, rset, NULL, &read_response, rs); GNUNET_NETWORK_fdset_destroy (rset); return rs; }
/** * Read a DNS response from the (unhindered) UDP-Socket * * @param cls socket to read from * @param tc scheduler context (must be shutdown or read ready) */ static void read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DNSSTUB_RequestSocket *rs = cls; struct GNUNET_NETWORK_FDSet *rset; rs->read_task = GNUNET_SCHEDULER_NO_TASK; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) { /* timeout or shutdown */ cleanup_rs (rs); return; } /* read and process ready sockets */ if ((NULL != rs->dnsout4) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout4)) && (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout4))) rs->dnsout4 = NULL; if ((NULL != rs->dnsout6) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout6)) && (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout6))) rs->dnsout6 = NULL; /* re-schedule read task */ rset = GNUNET_NETWORK_fdset_create (); if (NULL != rs->dnsout4) GNUNET_NETWORK_fdset_set (rset, rs->dnsout4); if (NULL != rs->dnsout6) GNUNET_NETWORK_fdset_set (rset, rs->dnsout6); rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_absolute_get_remaining (rs->timeout), rset, NULL, &read_response, rs); GNUNET_NETWORK_fdset_destroy (rset); }