glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / curl / curl_reschedule.c
1 /*
2   This file is part of GNUnet
3   Copyright (C) 2015, 2016 GNUnet e.V.
4
5   GNUnet is free software: you can redistribute it and/or modify it
6   under the terms of the GNU Affero General Public License as published
7   by the Free Software Foundation, either version 3 of the License,
8   or (at your option) any later version.
9
10   GNUnet is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Affero General Public License for more details.
14 */
15 /**
16  * @file curl/curl_reschedule.c
17  * @brief API for event loop integration with GNUnet SCHEDULER.
18  * @author Christian Grothoff
19  */
20 #include "platform.h"
21 #include "gnunet_curl_lib.h"
22 #include "gnunet_util_lib.h"
23
24
25 /**
26  * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
27  */
28 struct GNUNET_CURL_RescheduleContext
29 {
30   /**
31    * Just the task.
32    */
33   struct GNUNET_SCHEDULER_Task *task;
34
35   /**
36    * Context we manage.
37    */
38   struct GNUNET_CURL_Context *ctx;
39 };
40
41
42 /**
43  * Initialize reschedule context.
44  *
45  * @param ctx context to manage
46  * @return closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
47  */
48 struct GNUNET_CURL_RescheduleContext *
49 GNUNET_CURL_gnunet_rc_create (struct GNUNET_CURL_Context *ctx)
50 {
51   struct GNUNET_CURL_RescheduleContext *rc;
52
53   rc = GNUNET_new (struct GNUNET_CURL_RescheduleContext);
54   rc->ctx = ctx;
55   return rc;
56 }
57
58
59 /**
60  * Destroy reschedule context.
61  *
62  * @param rc context to destroy
63  */
64 void
65 GNUNET_CURL_gnunet_rc_destroy (struct GNUNET_CURL_RescheduleContext *rc)
66 {
67   if (NULL != rc->task)
68     GNUNET_SCHEDULER_cancel (rc->task);
69   GNUNET_free (rc);
70 }
71
72
73 /**
74  * Task that runs the context's event loop with the GNUnet scheduler.
75  *
76  * @param cls a `struct GNUNET_CURL_RescheduleContext *`
77  */
78 static void
79 context_task (void *cls)
80 {
81   struct GNUNET_CURL_RescheduleContext *rc = cls;
82   long timeout;
83   int max_fd;
84   fd_set read_fd_set;
85   fd_set write_fd_set;
86   fd_set except_fd_set;
87   struct GNUNET_NETWORK_FDSet *rs;
88   struct GNUNET_NETWORK_FDSet *ws;
89   struct GNUNET_TIME_Relative delay;
90
91   rc->task = NULL;
92   GNUNET_CURL_perform (rc->ctx);
93   max_fd = -1;
94   timeout = -1;
95   FD_ZERO (&read_fd_set);
96   FD_ZERO (&write_fd_set);
97   FD_ZERO (&except_fd_set);
98   GNUNET_CURL_get_select_info (rc->ctx,
99                                &read_fd_set,
100                                &write_fd_set,
101                                &except_fd_set,
102                                &max_fd,
103                                &timeout);
104   if (timeout >= 0)
105     delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
106                                            timeout);
107   else
108     delay = GNUNET_TIME_UNIT_FOREVER_REL;
109   rs = GNUNET_NETWORK_fdset_create ();
110   GNUNET_NETWORK_fdset_copy_native (rs,
111                                     &read_fd_set,
112                                     max_fd + 1);
113   ws = GNUNET_NETWORK_fdset_create ();
114   GNUNET_NETWORK_fdset_copy_native (ws,
115                                     &write_fd_set,
116                                     max_fd + 1);
117   if (NULL == rc->task)
118     rc->task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
119                                             delay,
120                                             rs,
121                                             ws,
122                                             &context_task,
123                                             rc);
124   GNUNET_NETWORK_fdset_destroy (rs);
125   GNUNET_NETWORK_fdset_destroy (ws);
126 }
127
128
129 /**
130  * Implementation of the #GNUNET_CURL_RescheduleCallback for GNUnet's
131  * scheduler.  Will run the CURL context using GNUnet's scheduler.
132  * Note that you MUST immediately destroy the reschedule context after
133  * calling #GNUNET_CURL_fini().
134  *
135  * @param cls must point to a `struct GNUNET_CURL_RescheduleContext *`
136  *           (pointer to a pointer!)
137  */
138 void
139 GNUNET_CURL_gnunet_scheduler_reschedule (void *cls)
140 {
141   struct GNUNET_CURL_RescheduleContext *rc = *(void**) cls;
142
143   if (NULL != rc->task)
144     GNUNET_SCHEDULER_cancel (rc->task);
145   rc->task = GNUNET_SCHEDULER_add_now (&context_task,
146                                        rc);
147 }
148
149 /* end of curl_reschedule.c */