123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- 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 Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- 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
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file curl/curl_reschedule.c
- * @brief API for event loop integration with GNUnet SCHEDULER.
- * @author Christian Grothoff
- */
- #include "platform.h"
- #include <jansson.h>
- #include "gnunet_curl_lib.h"
- #include "gnunet_util_lib.h"
- extern void *
- GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db,
- CURL *eh,
- long *response_code);
- /**
- * 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;
- /**
- * Parser of the raw response.
- */
- GNUNET_CURL_RawParser parser;
- /**
- * Deallocate the response object.
- */
- GNUNET_CURL_ResponseCleaner cleaner;
- };
- /**
- * Initialize reschedule context; with custom response parser
- *
- * @param ctx context to manage
- * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
- */
- struct GNUNET_CURL_RescheduleContext *
- GNUNET_CURL_gnunet_rc_create_with_parser (struct GNUNET_CURL_Context *ctx,
- GNUNET_CURL_RawParser rp,
- GNUNET_CURL_ResponseCleaner rc)
- {
- struct GNUNET_CURL_RescheduleContext *rctx;
- rctx = GNUNET_new (struct GNUNET_CURL_RescheduleContext);
- rctx->ctx = ctx;
- rctx->parser = rp;
- rctx->cleaner = rc;
- return rctx;
- }
- /**
- * Just a wrapper to avoid casting of function pointers.
- *
- * @param response the (JSON) response to clean.
- */
- static void
- clean_result (void *response)
- {
- json_decref (response);
- }
- /**
- * 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;
- rc->parser = &GNUNET_CURL_download_get_result_;
- rc->cleaner = &clean_result;
- 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 a `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_perform2 (rc->ctx, rc->parser, rc->cleaner);
- 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);
- if (NULL == rc->task)
- 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 *`
- * (pointer to a pointer!)
- */
- void
- GNUNET_CURL_gnunet_scheduler_reschedule (void *cls)
- {
- struct GNUNET_CURL_RescheduleContext *rc = *(void **) cls;
- if (NULL != rc->task)
- GNUNET_SCHEDULER_cancel (rc->task);
- rc->task = GNUNET_SCHEDULER_add_now (&context_task, rc);
- }
- /* end of curl_reschedule.c */
|