From bc1676b599937cd37d5fd625362ceea6f78fa42a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 May 2016 06:11:57 +0000 Subject: [PATCH] add implementation of scheduler integration of curl context --- src/curl/Makefile.am | 3 +- src/curl/curl_reschedule.c | 149 ++++++++++++++++++++++++++++++++++ src/include/gnunet_curl_lib.h | 40 +++++++++ 3 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 src/curl/curl_reschedule.c diff --git a/src/curl/Makefile.am b/src/curl/Makefile.am index 9867ba634..c716abe52 100644 --- a/src/curl/Makefile.am +++ b/src/curl/Makefile.am @@ -13,7 +13,8 @@ libgnunetcurl_la_LDFLAGS = \ -version-info 0:0:0 \ -no-undefined libgnunetcurl_la_SOURCES = \ - curl.c + curl.c \ + curl_reschedule.c libgnunetcurl_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -ljansson \ diff --git a/src/curl/curl_reschedule.c b/src/curl/curl_reschedule.c new file mode 100644 index 000000000..3e6c887f3 --- /dev/null +++ b/src/curl/curl_reschedule.c @@ -0,0 +1,149 @@ +/* + This file is part of GNUnet + Copyright (C) 2015, 2016 GNUnet e.V. + + GNUnet is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNUnet; see the file COPYING. If not, If not, see + +*/ +/** + * @file curl/curl_reschedule.c + * @brief API for event loop integration with GNUnet SCHEDULER. + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_curl_lib.h" +#include "gnunet_util_lib.h" + + +/** + * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ +struct GNUNET_CURL_RescheduleContext +{ + /** + * Just the task. + */ + struct GNUNET_SCHEDULER_Task *task; + + /** + * Context we manage. + */ + struct GNUNET_CURL_Context *ctx; +}; + + +/** + * Initialize reschedule context. + * + * @param ctx context to manage + * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ +struct GNUNET_CURL_RescheduleContext * +GNUNET_CURL_gnunet_rc_create (struct GNUNET_CURL_Context *ctx) +{ + struct GNUNET_CURL_RescheduleContext *rc; + + rc = GNUNET_new (struct GNUNET_CURL_RescheduleContext); + rc->ctx = ctx; + return rc; +} + + +/** + * Destroy reschedule context. + * + * @param rc context to destroy + */ +void +GNUNET_CURL_gnunet_rc_destroy (struct GNUNET_CURL_RescheduleContext *rc) +{ + if (NULL != rc->task) + GNUNET_SCHEDULER_cancel (rc->task); + GNUNET_free (rc); +} + + +/** + * Task that runs the context's event loop with the GNUnet scheduler. + * + * @param cls the `struct GNUNET_CURL_RescheduleContext` + */ +static void +context_task (void *cls) +{ + struct GNUNET_CURL_RescheduleContext *rc = cls; + long timeout; + int max_fd; + fd_set read_fd_set; + fd_set write_fd_set; + fd_set except_fd_set; + struct GNUNET_NETWORK_FDSet *rs; + struct GNUNET_NETWORK_FDSet *ws; + struct GNUNET_TIME_Relative delay; + + rc->task = NULL; + GNUNET_CURL_perform (rc->ctx); + max_fd = -1; + timeout = -1; + FD_ZERO (&read_fd_set); + FD_ZERO (&write_fd_set); + FD_ZERO (&except_fd_set); + GNUNET_CURL_get_select_info (rc->ctx, + &read_fd_set, + &write_fd_set, + &except_fd_set, + &max_fd, + &timeout); + if (timeout >= 0) + delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, + timeout); + else + delay = GNUNET_TIME_UNIT_FOREVER_REL; + rs = GNUNET_NETWORK_fdset_create (); + GNUNET_NETWORK_fdset_copy_native (rs, + &read_fd_set, + max_fd + 1); + ws = GNUNET_NETWORK_fdset_create (); + GNUNET_NETWORK_fdset_copy_native (ws, + &write_fd_set, + max_fd + 1); + rc->task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, + delay, + rs, + ws, + &context_task, + rc); + GNUNET_NETWORK_fdset_destroy (rs); + GNUNET_NETWORK_fdset_destroy (ws); +} + + +/** + * Implementation of the #GNUNET_CURL_RescheduleCallback for GNUnet's + * scheduler. Will run the CURL context using GNUnet's scheduler. + * Note that you MUST immediately destroy the reschedule context after + * calling #GNUNET_CURL_fini(). + * + * @param cls must point to a `struct GNUNET_CURL_RescheduleContext` + */ +void +GNUNET_CURL_gnunet_scheduler_reschedule (void *cls) +{ + struct GNUNET_CURL_RescheduleContext *rc = cls; + + if (NULL != rc->task) + GNUNET_SCHEDULER_cancel (rc->task); + rc->task = GNUNET_SCHEDULER_add_now (&context_task, + rc); +} + +/* end of curl_reschedule.c */ diff --git a/src/include/gnunet_curl_lib.h b/src/include/gnunet_curl_lib.h index c57b9ed3b..500434d82 100644 --- a/src/include/gnunet_curl_lib.h +++ b/src/include/gnunet_curl_lib.h @@ -170,6 +170,46 @@ GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx, void GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job); + +/* ******* GNUnet SCHEDULER integration ************ */ + + +/** + * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ +struct GNUNET_CURL_RescheduleContext; + + +/** + * Initialize reschedule context. + * + * @param ctx context to manage + * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ +struct GNUNET_CURL_RescheduleContext * +GNUNET_CURL_gnunet_rc_create (struct GNUNET_CURL_Context *ctx); + +/** + * Destroy reschedule context. + * + * @param rc context to destroy + */ +void +GNUNET_CURL_gnunet_rc_destroy (struct GNUNET_CURL_RescheduleContext *rc); + + +/** + * Implementation of the #GNUNET_CURL_RescheduleCallback for GNUnet's + * scheduler. Will run the CURL context using GNUnet's scheduler. + * Note that you MUST immediately destroy the reschedule context after + * calling #GNUNET_CURL_fini(). + * + * @param cls must point to a `struct GNUNET_CURL_RescheduleContext` + */ +void +GNUNET_CURL_gnunet_scheduler_reschedule (void *cls); + + #endif /** @} */ /* end of group */ -- 2.25.1