/** * 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; }
static void mhd_main () { struct GNUNET_NETWORK_FDSet nrs; struct GNUNET_NETWORK_FDSet nws; fd_set rs; fd_set ws; fd_set es; int max_fd; unsigned MHD_LONG_LONG timeout; struct GNUNET_TIME_Relative delay; GNUNET_assert (NULL == mhd_task_id); FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); max_fd = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd)); if (MHD_YES == MHD_get_timeout (mhd, &timeout)) delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); else delay = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max_fd + 1); GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max_fd + 1); mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, &nrs, &nws, &mhd_task, NULL); }
/** * 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); }
/** * 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); }
/** * 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; }
static void curl_main () { fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet nrs; struct GNUNET_NETWORK_FDSet nws; struct GNUNET_TIME_Relative delay; long timeout; int running; struct CURLMsg *msg; max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); curl_multi_perform (multi, &running); if (running == 0) { GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running))); if (msg->msg == CURLMSG_DONE) { if (msg->data.result != CURLE_OK) { fprintf (stderr, "%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); global_ret = 1; } } curl_multi_remove_handle (multi, curl); curl_multi_cleanup (multi); curl_easy_cleanup (curl); curl = NULL; multi = NULL; if (cbc.pos != strlen ("/hello_world")) { GNUNET_break (0); global_ret = 2; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) { GNUNET_break (0); global_ret = 3; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download complete, shutting down!\n"); do_shutdown (); return; } GNUNET_assert (CURLM_OK == curl_multi_fdset (multi, &rs, &ws, &es, &max)); if ( (CURLM_OK != curl_multi_timeout (multi, &timeout)) || (-1 == timeout) ) delay = GNUNET_TIME_UNIT_SECONDS; else delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max + 1); curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, &nrs, &nws, &curl_task, NULL); }