diff options
author | Phil <phil.buschmann@tum.de> | 2018-02-26 17:02:29 +0100 |
---|---|---|
committer | Phil <phil.buschmann@tum.de> | 2018-02-26 17:02:29 +0100 |
commit | 699ff34b7203eb99d7ff1a45ff6b8309676c1102 (patch) | |
tree | 43ac45b55e3de8aa96d5ea53727154dcc3fbc594 /src | |
parent | 2363773d8a81d253614fa3892cead6ebab69c246 (diff) | |
parent | 56a9d4001b0844287ecc55b103549370676646a8 (diff) | |
download | gnunet-699ff34b7203eb99d7ff1a45ff6b8309676c1102.tar.gz gnunet-699ff34b7203eb99d7ff1a45ff6b8309676c1102.zip |
-Merge branch 'master' into identity_oidc
Diffstat (limited to 'src')
-rw-r--r-- | src/consensus/gnunet-service-consensus.c | 2 | ||||
-rw-r--r-- | src/datastore/plugin_datastore_sqlite.c | 13 | ||||
-rw-r--r-- | src/exit/gnunet-daemon-exit.c | 4 | ||||
-rw-r--r-- | src/gns/Makefile.am | 2 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns.c | 133 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns.h | 41 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns_interceptor.c | 4 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns_resolver.c | 7 | ||||
-rw-r--r-- | src/include/gnunet_scheduler_lib.h | 196 | ||||
-rw-r--r-- | src/multicast/gnunet-service-multicast.c | 26 | ||||
-rw-r--r-- | src/psyc/gnunet-service-psyc.c | 22 | ||||
-rw-r--r-- | src/rps/gnunet-service-rps.c | 28 | ||||
-rw-r--r-- | src/rps/rps-test_util.h | 2 | ||||
-rw-r--r-- | src/rps/test_rps.c | 104 | ||||
-rw-r--r-- | src/social/gnunet-service-social.c | 31 | ||||
-rw-r--r-- | src/util/mq.c | 4 | ||||
-rw-r--r-- | src/util/scheduler.c | 491 |
17 files changed, 787 insertions, 323 deletions
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c index 84b1cbe55..90a3a36f1 100644 --- a/src/consensus/gnunet-service-consensus.c +++ b/src/consensus/gnunet-service-consensus.c | |||
@@ -21,7 +21,7 @@ | |||
21 | /** | 21 | /** |
22 | * @file consensus/gnunet-service-consensus.c | 22 | * @file consensus/gnunet-service-consensus.c |
23 | * @brief multi-peer set reconciliation | 23 | * @brief multi-peer set reconciliation |
24 | * @author Florian Dold | 24 | * @author Florian Dold <flo@dold.me> |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include "platform.h" | 27 | #include "platform.h" |
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c index d51fd3e01..4980f8109 100644 --- a/src/datastore/plugin_datastore_sqlite.c +++ b/src/datastore/plugin_datastore_sqlite.c | |||
@@ -908,6 +908,19 @@ sqlite_plugin_get_key (void *cls, | |||
908 | GNUNET_SQ_query_param_end | 908 | GNUNET_SQ_query_param_end |
909 | }; | 909 | }; |
910 | 910 | ||
911 | /* SQLite doesn't like it when you try to bind a parameter greater than the | ||
912 | * last numbered parameter, but unused parameters in the middle are OK. | ||
913 | */ | ||
914 | if (! use_type) | ||
915 | { | ||
916 | params[3] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end; | ||
917 | if (! use_key) | ||
918 | { | ||
919 | params[2] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end; | ||
920 | if (! use_rvalue) | ||
921 | params[1] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end; | ||
922 | } | ||
923 | } | ||
911 | if (random) | 924 | if (random) |
912 | { | 925 | { |
913 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | 926 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, |
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c index d9a5dd684..c624e083e 100644 --- a/src/exit/gnunet-daemon-exit.c +++ b/src/exit/gnunet-daemon-exit.c | |||
@@ -3373,10 +3373,10 @@ add_services (int proto, | |||
3373 | 3373 | ||
3374 | 3374 | ||
3375 | /** | 3375 | /** |
3376 | * Reads the configuration servicecfg and populates udp_services | 3376 | * Reads the configuration and populates #udp_services and #tcp_services |
3377 | * | 3377 | * |
3378 | * @param cls unused | 3378 | * @param cls unused |
3379 | * @param section name of section in config, equal to hostname | 3379 | * @param section name of section in config |
3380 | */ | 3380 | */ |
3381 | static void | 3381 | static void |
3382 | read_service_conf (void *cls, | 3382 | read_service_conf (void *cls, |
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 977eb87e3..e89192414 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am | |||
@@ -185,7 +185,7 @@ w32nsp_resolve_SOURCES = \ | |||
185 | w32nsp_resolve_LDADD = -lws2_32 | 185 | w32nsp_resolve_LDADD = -lws2_32 |
186 | 186 | ||
187 | gnunet_service_gns_SOURCES = \ | 187 | gnunet_service_gns_SOURCES = \ |
188 | gnunet-service-gns.c \ | 188 | gnunet-service-gns.c gnunet-service-gns.h \ |
189 | gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ | 189 | gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ |
190 | gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h | 190 | gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h |
191 | gnunet_service_gns_LDADD = \ | 191 | gnunet_service_gns_LDADD = \ |
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c index 0ca25ac19..e13beb889 100644 --- a/src/gns/gnunet-service-gns.c +++ b/src/gns/gnunet-service-gns.c | |||
@@ -101,6 +101,38 @@ struct GnsClient | |||
101 | 101 | ||
102 | 102 | ||
103 | /** | 103 | /** |
104 | * Representation of a TLD, mapping the respective TLD string | ||
105 | * (i.e. ".gnu") to the respective public key of the zone. | ||
106 | */ | ||
107 | struct GNS_TopLevelDomain | ||
108 | { | ||
109 | |||
110 | /** | ||
111 | * Kept in a DLL, as there are unlikely enough of these to | ||
112 | * warrant a hash map. | ||
113 | */ | ||
114 | struct GNS_TopLevelDomain *next; | ||
115 | |||
116 | /** | ||
117 | * Kept in a DLL, as there are unlikely enough of these to | ||
118 | * warrant a hash map. | ||
119 | */ | ||
120 | struct GNS_TopLevelDomain *prev; | ||
121 | |||
122 | /** | ||
123 | * Public key associated with the @a tld. | ||
124 | */ | ||
125 | struct GNUNET_CRYPTO_EddsaPublicKey pkey; | ||
126 | |||
127 | /** | ||
128 | * Top-level domain as a string, including leading ".". | ||
129 | */ | ||
130 | char *tld; | ||
131 | |||
132 | }; | ||
133 | |||
134 | |||
135 | /** | ||
104 | * Our handle to the DHT | 136 | * Our handle to the DHT |
105 | */ | 137 | */ |
106 | static struct GNUNET_DHT_Handle *dht_handle; | 138 | static struct GNUNET_DHT_Handle *dht_handle; |
@@ -136,6 +168,50 @@ static int v4_enabled; | |||
136 | */ | 168 | */ |
137 | static struct GNUNET_STATISTICS_Handle *statistics; | 169 | static struct GNUNET_STATISTICS_Handle *statistics; |
138 | 170 | ||
171 | /** | ||
172 | * Head of DLL of TLDs we map to GNS zones. | ||
173 | */ | ||
174 | static struct GNS_TopLevelDomain *tld_head; | ||
175 | |||
176 | /** | ||
177 | * Tail of DLL of TLDs we map to GNS zones. | ||
178 | */ | ||
179 | static struct GNS_TopLevelDomain *tld_tail; | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Find GNS zone belonging to TLD @a tld. | ||
184 | * | ||
185 | * @param tld_str top-level domain to look up | ||
186 | * @param[out] pkey public key to set | ||
187 | * @return #GNUNET_YES if @a tld was found #GNUNET_NO if not | ||
188 | */ | ||
189 | int | ||
190 | GNS_find_tld (const char *tld_str, | ||
191 | struct GNUNET_CRYPTO_EddsaPublicKey *pkey) | ||
192 | { | ||
193 | if ('\0' == *tld_str) | ||
194 | return GNUNET_NO; | ||
195 | for (struct GNS_TopLevelDomain *tld = tld_head; | ||
196 | NULL != tld; | ||
197 | tld = tld->next) | ||
198 | { | ||
199 | if (0 == strcasecmp (tld_str, | ||
200 | tld->tld)) | ||
201 | { | ||
202 | *pkey = tld->pkey; | ||
203 | return GNUNET_YES; | ||
204 | } | ||
205 | } | ||
206 | if (GNUNET_OK == | ||
207 | GNUNET_STRINGS_string_to_data (tld_str + 1, | ||
208 | strlen (tld_str + 1), | ||
209 | pkey, | ||
210 | sizeof (*pkey))) | ||
211 | return GNUNET_YES; /* TLD string *was* the public key */ | ||
212 | return GNUNET_NO; | ||
213 | } | ||
214 | |||
139 | 215 | ||
140 | /** | 216 | /** |
141 | * Task run during shutdown. | 217 | * Task run during shutdown. |
@@ -146,6 +222,7 @@ static struct GNUNET_STATISTICS_Handle *statistics; | |||
146 | static void | 222 | static void |
147 | shutdown_task (void *cls) | 223 | shutdown_task (void *cls) |
148 | { | 224 | { |
225 | struct GNS_TopLevelDomain *tld; | ||
149 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 226 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
150 | "Shutting down!\n"); | 227 | "Shutting down!\n"); |
151 | GNS_interceptor_done (); | 228 | GNS_interceptor_done (); |
@@ -176,6 +253,14 @@ shutdown_task (void *cls) | |||
176 | GNUNET_DHT_disconnect (dht_handle); | 253 | GNUNET_DHT_disconnect (dht_handle); |
177 | dht_handle = NULL; | 254 | dht_handle = NULL; |
178 | } | 255 | } |
256 | while (NULL != (tld = tld_head)) | ||
257 | { | ||
258 | GNUNET_CONTAINER_DLL_remove (tld_head, | ||
259 | tld_tail, | ||
260 | tld); | ||
261 | GNUNET_free (tld->tld); | ||
262 | GNUNET_free (tld); | ||
263 | } | ||
179 | } | 264 | } |
180 | 265 | ||
181 | 266 | ||
@@ -420,6 +505,47 @@ identity_intercept_cb (void *cls, | |||
420 | 505 | ||
421 | 506 | ||
422 | /** | 507 | /** |
508 | * Reads the configuration and populates TLDs | ||
509 | * | ||
510 | * @param cls unused | ||
511 | * @param section name of section in config, always "gns" | ||
512 | * @param option name of the option, TLDs start with "." | ||
513 | * @param value value for the option, public key for TLDs | ||
514 | */ | ||
515 | static void | ||
516 | read_service_conf (void *cls, | ||
517 | const char *section, | ||
518 | const char *option, | ||
519 | const char *value) | ||
520 | { | ||
521 | struct GNUNET_CRYPTO_EddsaPublicKey pk; | ||
522 | struct GNS_TopLevelDomain *tld; | ||
523 | |||
524 | if (option[0] != '.') | ||
525 | return; | ||
526 | if (GNUNET_OK != | ||
527 | GNUNET_STRINGS_string_to_data (value, | ||
528 | strlen (value), | ||
529 | &pk, | ||
530 | sizeof (pk))) | ||
531 | { | ||
532 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
533 | section, | ||
534 | option, | ||
535 | _("Properly base32-encoded public key required")); | ||
536 | return; | ||
537 | } | ||
538 | tld = GNUNET_new (struct GNS_TopLevelDomain); | ||
539 | tld->tld = GNUNET_strdup (option); | ||
540 | tld->pkey = pk; | ||
541 | GNUNET_CONTAINER_DLL_insert (tld_head, | ||
542 | tld_tail, | ||
543 | tld); | ||
544 | } | ||
545 | |||
546 | |||
547 | |||
548 | /** | ||
423 | * Process GNS requests. | 549 | * Process GNS requests. |
424 | * | 550 | * |
425 | * @param cls closure | 551 | * @param cls closure |
@@ -433,6 +559,10 @@ run (void *cls, | |||
433 | { | 559 | { |
434 | unsigned long long max_parallel_bg_queries = 16; | 560 | unsigned long long max_parallel_bg_queries = 16; |
435 | 561 | ||
562 | GNUNET_CONFIGURATION_iterate_section_values (c, | ||
563 | "gns", | ||
564 | &read_service_conf, | ||
565 | NULL); | ||
436 | v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); | 566 | v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); |
437 | v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); | 567 | v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); |
438 | namecache_handle = GNUNET_NAMECACHE_connect (c); | 568 | namecache_handle = GNUNET_NAMECACHE_connect (c); |
@@ -459,7 +589,8 @@ run (void *cls, | |||
459 | { | 589 | { |
460 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 590 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
461 | _("Could not connect to DHT!\n")); | 591 | _("Could not connect to DHT!\n")); |
462 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | 592 | GNUNET_SCHEDULER_add_now (&shutdown_task, |
593 | NULL); | ||
463 | return; | 594 | return; |
464 | } | 595 | } |
465 | 596 | ||
diff --git a/src/gns/gnunet-service-gns.h b/src/gns/gnunet-service-gns.h new file mode 100644 index 000000000..3662c945d --- /dev/null +++ b/src/gns/gnunet-service-gns.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file gns/gnunet-service-gns.h | ||
22 | * @brief GNU Name System (main service) | ||
23 | * @author Martin Schanzenbach | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #ifndef GNUNET_SERVICE_GNS_H | ||
28 | #define GNUNET_SERVICE_GNS_H | ||
29 | |||
30 | /** | ||
31 | * Find GNS zone belonging to TLD @a tld. | ||
32 | * | ||
33 | * @param tld_str top-level domain to look up | ||
34 | * @param[out] pkey public key to set | ||
35 | * @return #GNUNET_YES if @a tld was found #GNUNET_NO if not | ||
36 | */ | ||
37 | int | ||
38 | GNS_find_tld (const char *tld_str, | ||
39 | struct GNUNET_CRYPTO_EddsaPublicKey *pkey); | ||
40 | |||
41 | #endif | ||
diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c index a9e207891..71aa08dc5 100644 --- a/src/gns/gnunet-service-gns_interceptor.c +++ b/src/gns/gnunet-service-gns_interceptor.c | |||
@@ -327,7 +327,9 @@ handle_dns_request (void *cls, | |||
327 | { | 327 | { |
328 | /* Start resolution in GNS */ | 328 | /* Start resolution in GNS */ |
329 | ilh = GNUNET_new (struct InterceptLookupHandle); | 329 | ilh = GNUNET_new (struct InterceptLookupHandle); |
330 | GNUNET_CONTAINER_DLL_insert (ilh_head, ilh_tail, ilh); | 330 | GNUNET_CONTAINER_DLL_insert (ilh_head, |
331 | ilh_tail, | ||
332 | ilh); | ||
331 | ilh->packet = p; | 333 | ilh->packet = p; |
332 | ilh->request_handle = rh; | 334 | ilh->request_handle = rh; |
333 | ilh->lookup = GNS_resolver_lookup (&zone, | 335 | ilh->lookup = GNS_resolver_lookup (&zone, |
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c index 5bf443267..533c0cada 100644 --- a/src/gns/gnunet-service-gns_resolver.c +++ b/src/gns/gnunet-service-gns_resolver.c | |||
@@ -2252,7 +2252,7 @@ recursive_resolution (void *cls) | |||
2252 | * Begin the resolution process from 'name', starting with | 2252 | * Begin the resolution process from 'name', starting with |
2253 | * the identification of the zone specified by 'name'. | 2253 | * the identification of the zone specified by 'name'. |
2254 | * | 2254 | * |
2255 | * @param cls the `struct GNS_ResolverHandle` | 2255 | * @param cls the `struct GNS_ResolverHandle` |
2256 | */ | 2256 | */ |
2257 | static void | 2257 | static void |
2258 | start_resolver_lookup (void *cls) | 2258 | start_resolver_lookup (void *cls) |
@@ -2595,10 +2595,11 @@ GNS_resolver_done () | |||
2595 | * | 2595 | * |
2596 | * @param name the name to check | 2596 | * @param name the name to check |
2597 | * @param tld the TLD to check for | 2597 | * @param tld the TLD to check for |
2598 | * @return GNUNET_YES or GNUNET_NO | 2598 | * @return #GNUNET_YES or #GNUNET_NO |
2599 | */ | 2599 | */ |
2600 | int | 2600 | int |
2601 | is_tld (const char* name, const char* tld) | 2601 | is_tld (const char* name, |
2602 | const char* tld) | ||
2602 | { | 2603 | { |
2603 | size_t offset = 0; | 2604 | size_t offset = 0; |
2604 | 2605 | ||
diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index d2805a685..f9b2736e4 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h | |||
@@ -237,29 +237,32 @@ struct GNUNET_SCHEDULER_Handle; | |||
237 | 237 | ||
238 | 238 | ||
239 | /** | 239 | /** |
240 | * Function called by the driver to tell the scheduler to run some of | 240 | * Function called by external event loop implementations to tell the |
241 | * the tasks that are ready. This function may return even though | 241 | * scheduler to run some of the tasks that are ready. Must be called |
242 | * there are tasks left to run just to give other tasks a chance as | 242 | * only after #GNUNET_SCHEDULER_driver_init has been called and before |
243 | * well. If we return #GNUNET_YES, the driver should call this | 243 | * #GNUNET_SCHEDULER_driver_done is called. |
244 | * function again as soon as possible, while if we return #GNUNET_NO | 244 | * This function may return even though there are tasks left to run |
245 | * it must block until either the operating system has more work (the | 245 | * just to give other tasks a chance as well. If we return #GNUNET_YES, |
246 | * scheduler has no more work to do right now) or the timeout set by | 246 | * the event loop implementation should call this function again as |
247 | * the scheduler (using the set_wakeup callback) is reached. | 247 | * soon as possible, while if we return #GNUNET_NO it must block until |
248 | * | 248 | * either the operating system has more work (the scheduler has no more |
249 | * @param sh scheduler handle that was given to the `loop` | 249 | * work to do right now) or the timeout set by the scheduler (using the |
250 | * @return #GNUNET_OK if there are more tasks that are ready, | 250 | * set_wakeup callback) is reached. |
251 | * and thus we would like to run more (yield to avoid | 251 | * |
252 | * blocking other activities for too long) | 252 | * @param sh scheduler handle that was returned by |
253 | * #GNUNET_NO if we are done running tasks (yield to block) | 253 | * #GNUNET_SCHEDULER_driver_init |
254 | * #GNUNET_SYSERR on error, e.g. no tasks were ready | 254 | * @return #GNUNET_YES if there are more tasks that are ready, |
255 | * and thus we would like to run more (yield to avoid | ||
256 | * blocking other activities for too long) #GNUNET_NO | ||
257 | * if we are done running tasks (yield to block) | ||
255 | */ | 258 | */ |
256 | int | 259 | int |
257 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh); | 260 | GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh); |
258 | 261 | ||
259 | 262 | ||
260 | /** | 263 | /** |
261 | * API a driver has to implement for | 264 | * API an external event loop has to implement for |
262 | * #GNUNET_SCHEDULER_run_with_driver(). | 265 | * #GNUNET_SCHEDULER_driver_init. |
263 | */ | 266 | */ |
264 | struct GNUNET_SCHEDULER_Driver | 267 | struct GNUNET_SCHEDULER_Driver |
265 | { | 268 | { |
@@ -311,23 +314,6 @@ struct GNUNET_SCHEDULER_Driver | |||
311 | (*set_wakeup)(void *cls, | 314 | (*set_wakeup)(void *cls, |
312 | struct GNUNET_TIME_Absolute dt); | 315 | struct GNUNET_TIME_Absolute dt); |
313 | 316 | ||
314 | /** | ||
315 | * Event loop's "main" function, to be called from | ||
316 | * #GNUNET_SCHEDULER_run_with_driver() to actually | ||
317 | * launch the loop. The loop should run as long as | ||
318 | * tasks (added by the add callback) are available | ||
319 | * OR the wakeup time (added by the set_wakeup | ||
320 | * callback) is not FOREVER. | ||
321 | * | ||
322 | * @param cls closure | ||
323 | * @param sh scheduler handle to pass to | ||
324 | * #GNUNET_SCHEDULER_run_from_driver() | ||
325 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
326 | */ | ||
327 | int | ||
328 | (*loop)(void *cls, | ||
329 | struct GNUNET_SCHEDULER_Handle *sh); | ||
330 | |||
331 | }; | 317 | }; |
332 | 318 | ||
333 | 319 | ||
@@ -341,25 +327,56 @@ typedef void | |||
341 | 327 | ||
342 | 328 | ||
343 | /** | 329 | /** |
344 | * Initialize and run scheduler. This function will return when all | 330 | * Function called by external event loop implementations to initialize |
345 | * tasks have completed. On systems with signals, receiving a SIGTERM | 331 | * the scheduler. An external implementation has to provide @a driver |
346 | * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown | 332 | * which contains callbacks for the scheduler (see definition of struct |
347 | * to be run after the active task is complete. As a result, SIGTERM | 333 | * #GNUNET_SCHEDULER_Driver). The callbacks are used to instruct the |
348 | * causes all shutdown tasks to be scheduled with reason | 334 | * external implementation to watch for events. If it detects any of |
349 | * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added | 335 | * those events it is expected to call #GNUNET_SCHEDULER_do_work to let |
350 | * afterwards will execute normally!). Note that any particular | 336 | * the scheduler handle it. If an event is related to a specific task |
351 | * signal will only shut down one scheduler; applications should | 337 | * (e.g. the scheduler gave instructions to watch a file descriptor), |
352 | * always only create a single scheduler. | 338 | * the external implementation is expected to mark that task ready |
339 | * before by calling #GNUNET_SCHEDULER_task_ready. | ||
353 | * | 340 | * |
354 | * @param driver drive to use for the event loop | 341 | * This function has to be called before any tasks are scheduled and |
355 | * @param task task to run first (and immediately) | 342 | * before GNUNET_SCHEDULER_do_work is called for the first time. It |
356 | * @param task_cls closure of @a task | 343 | * allocates resources that have to be freed again by calling |
357 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | 344 | * #GNUNET_SCHEDULER_driver_done. |
345 | * | ||
346 | * This function installs the same signal handlers as | ||
347 | * #GNUNET_SCHEDULER_run. This means SIGTERM (and other similar signals) | ||
348 | * will induce a call to #GNUNET_SCHEDULER_shutdown during the next | ||
349 | * call to #GNUNET_SCHEDULER_do_work. As a result, SIGTERM causes all | ||
350 | * active tasks to be scheduled with reason | ||
351 | * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added afterwards | ||
352 | * will execute normally!). Note that any particular signal will only | ||
353 | * shut down one scheduler; applications should always only create a | ||
354 | * single scheduler. | ||
355 | * | ||
356 | * @param driver to use for the event loop | ||
357 | * @return handle to be passed to #GNUNET_SCHEDULER_do_work and | ||
358 | * #GNUNET_SCHEDULER_driver_done | ||
358 | */ | 359 | */ |
359 | int | 360 | struct GNUNET_SCHEDULER_Handle * |
360 | GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | 361 | GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver); |
361 | GNUNET_SCHEDULER_TaskCallback task, | 362 | |
362 | void *task_cls); | 363 | |
364 | /** | ||
365 | * Counter-part of #GNUNET_SCHEDULER_driver_init. Has to be called | ||
366 | * by external event loop implementations after the scheduler has | ||
367 | * shut down. This is the case if both of the following conditions | ||
368 | * are met: | ||
369 | * | ||
370 | * - all tasks the scheduler has added through the driver's add | ||
371 | * callback have been removed again through the driver's del | ||
372 | * callback | ||
373 | * - the timeout the scheduler has set through the driver's | ||
374 | * add_wakeup callback is FOREVER | ||
375 | * | ||
376 | * @param sh the handle returned by #GNUNET_SCHEDULER_driver_init | ||
377 | */ | ||
378 | void | ||
379 | GNUNET_SCHEDULER_driver_done (struct GNUNET_SCHEDULER_Handle *sh); | ||
363 | 380 | ||
364 | 381 | ||
365 | /** | 382 | /** |
@@ -462,10 +479,15 @@ GNUNET_SCHEDULER_get_task_context (void); | |||
462 | 479 | ||
463 | /** | 480 | /** |
464 | * Cancel the task with the specified identifier. | 481 | * Cancel the task with the specified identifier. |
465 | * The task must not yet have run. | 482 | * The task must not yet have run. Only allowed to be called as long as the |
483 | * scheduler is running, that is one of the following conditions is met: | ||
484 | * | ||
485 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
486 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
487 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
466 | * | 488 | * |
467 | * @param task id of the task to cancel | 489 | * @param task id of the task to cancel |
468 | * @return the closure of the callback of the cancelled task | 490 | * @return original closure of the task |
469 | */ | 491 | */ |
470 | void * | 492 | void * |
471 | GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task); | 493 | GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task); |
@@ -634,6 +656,12 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, | |||
634 | * used as a timeout on the socket being ready. The task will be | 656 | * used as a timeout on the socket being ready. The task will be |
635 | * scheduled for execution once either the delay has expired or the | 657 | * scheduled for execution once either the delay has expired or the |
636 | * socket operation is ready. It will be run with the DEFAULT priority. | 658 | * socket operation is ready. It will be run with the DEFAULT priority. |
659 | * Only allowed to be called as long as the scheduler is running, that | ||
660 | * is one of the following conditions is met: | ||
661 | * | ||
662 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
663 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
664 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
637 | * | 665 | * |
638 | * @param delay when should this operation time out? | 666 | * @param delay when should this operation time out? |
639 | * @param rfd read file-descriptor | 667 | * @param rfd read file-descriptor |
@@ -656,6 +684,12 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, | |||
656 | * socket being ready. The task will be scheduled for execution once | 684 | * socket being ready. The task will be scheduled for execution once |
657 | * either the delay has expired or the socket operation is ready. It | 685 | * either the delay has expired or the socket operation is ready. It |
658 | * will be run with the DEFAULT priority. | 686 | * will be run with the DEFAULT priority. |
687 | * Only allowed to be called as long as the scheduler is running, that | ||
688 | * is one of the following conditions is met: | ||
689 | * | ||
690 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
691 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
692 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
659 | * | 693 | * |
660 | * @param delay when should this operation time out? | 694 | * @param delay when should this operation time out? |
661 | * @param priority priority to use for the task | 695 | * @param priority priority to use for the task |
@@ -678,9 +712,16 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
678 | * specified file descriptor is ready for writing. The delay can be | 712 | * specified file descriptor is ready for writing. The delay can be |
679 | * used as a timeout on the socket being ready. The task will be | 713 | * used as a timeout on the socket being ready. The task will be |
680 | * scheduled for execution once either the delay has expired or the | 714 | * scheduled for execution once either the delay has expired or the |
681 | * socket operation is ready. It will be run with the DEFAULT priority. | 715 | * socket operation is ready. It will be run with the priority of |
716 | * the calling task. | ||
717 | * Only allowed to be called as long as the scheduler is running, that | ||
718 | * is one of the following conditions is met: | ||
719 | * | ||
720 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
721 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
722 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
682 | * | 723 | * |
683 | * * @param delay when should this operation time out? | 724 | * @param delay when should this operation time out? |
684 | * @param wfd write file-descriptor | 725 | * @param wfd write file-descriptor |
685 | * @param task main function of the task | 726 | * @param task main function of the task |
686 | * @param task_cls closure of @a task | 727 | * @param task_cls closure of @a task |
@@ -700,6 +741,12 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | |||
700 | * used as a timeout on the socket being ready. The task will be | 741 | * used as a timeout on the socket being ready. The task will be |
701 | * scheduled for execution once either the delay has expired or the | 742 | * scheduled for execution once either the delay has expired or the |
702 | * socket operation is ready. | 743 | * socket operation is ready. |
744 | * Only allowed to be called as long as the scheduler is running, that | ||
745 | * is one of the following conditions is met: | ||
746 | * | ||
747 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
748 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
749 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
703 | * | 750 | * |
704 | * @param delay when should this operation time out? | 751 | * @param delay when should this operation time out? |
705 | * @param priority priority of the task | 752 | * @param priority priority of the task |
@@ -707,7 +754,7 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | |||
707 | * @param on_read whether to poll the file-descriptor for readability | 754 | * @param on_read whether to poll the file-descriptor for readability |
708 | * @param on_write whether to poll the file-descriptor for writability | 755 | * @param on_write whether to poll the file-descriptor for writability |
709 | * @param task main function of the task | 756 | * @param task main function of the task |
710 | * @param task_cls closure of @a task | 757 | * @param task_cls closure of task |
711 | * @return unique task identifier for the job | 758 | * @return unique task identifier for the job |
712 | * only valid until "task" is started! | 759 | * only valid until "task" is started! |
713 | */ | 760 | */ |
@@ -720,19 +767,26 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
720 | GNUNET_SCHEDULER_TaskCallback task, | 767 | GNUNET_SCHEDULER_TaskCallback task, |
721 | void *task_cls); | 768 | void *task_cls); |
722 | 769 | ||
770 | |||
723 | /** | 771 | /** |
724 | * Schedule a new task to be run with a specified delay or when the | 772 | * Schedule a new task to be run with a specified delay or when the |
725 | * specified file descriptor is ready for reading. The delay can be | 773 | * specified file descriptor is ready for reading. The delay can be |
726 | * used as a timeout on the socket being ready. The task will be | 774 | * used as a timeout on the socket being ready. The task will be |
727 | * scheduled for execution once either the delay has expired or the | 775 | * scheduled for execution once either the delay has expired or the |
728 | * socket operation is ready. It will be run with the DEFAULT priority. | 776 | * socket operation is ready. It will be run with the DEFAULT priority. |
777 | * Only allowed to be called as long as the scheduler is running, that | ||
778 | * is one of the following conditions is met: | ||
779 | * | ||
780 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
781 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
782 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
729 | * | 783 | * |
730 | * * @param delay when should this operation time out? | 784 | * @param delay when should this operation time out? |
731 | * @param rfd read file-descriptor | 785 | * @param rfd read file-descriptor |
732 | * @param task main function of the task | 786 | * @param task main function of the task |
733 | * @param task_cls closure of @a task | 787 | * @param task_cls closure of @a task |
734 | * @return unique task identifier for the job | 788 | * @return unique task identifier for the job |
735 | * only valid until "task" is started! | 789 | * only valid until @a task is started! |
736 | */ | 790 | */ |
737 | struct GNUNET_SCHEDULER_Task * | 791 | struct GNUNET_SCHEDULER_Task * |
738 | GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, | 792 | GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, |
@@ -747,8 +801,14 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, | |||
747 | * used as a timeout on the socket being ready. The task will be | 801 | * used as a timeout on the socket being ready. The task will be |
748 | * scheduled for execution once either the delay has expired or the | 802 | * scheduled for execution once either the delay has expired or the |
749 | * socket operation is ready. It will be run with the DEFAULT priority. | 803 | * socket operation is ready. It will be run with the DEFAULT priority. |
804 | * Only allowed to be called as long as the scheduler is running, that | ||
805 | * is one of the following conditions is met: | ||
806 | * | ||
807 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
808 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
809 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
750 | * | 810 | * |
751 | * * @param delay when should this operation time out? | 811 | * @param delay when should this operation time out? |
752 | * @param wfd write file-descriptor | 812 | * @param wfd write file-descriptor |
753 | * @param task main function of the task | 813 | * @param task main function of the task |
754 | * @param task_cls closure of @a task | 814 | * @param task_cls closure of @a task |
@@ -768,6 +828,12 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, | |||
768 | * used as a timeout on the socket being ready. The task will be | 828 | * used as a timeout on the socket being ready. The task will be |
769 | * scheduled for execution once either the delay has expired or the | 829 | * scheduled for execution once either the delay has expired or the |
770 | * socket operation is ready. | 830 | * socket operation is ready. |
831 | * Only allowed to be called as long as the scheduler is running, that | ||
832 | * is one of the following conditions is met: | ||
833 | * | ||
834 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
835 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
836 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
771 | * | 837 | * |
772 | * @param delay when should this operation time out? | 838 | * @param delay when should this operation time out? |
773 | * @param priority priority of the task | 839 | * @param priority priority of the task |
@@ -801,8 +867,14 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, | |||
801 | * (prerequisite-run) | 867 | * (prerequisite-run) |
802 | * && (delay-ready | 868 | * && (delay-ready |
803 | * || any-rs-ready | 869 | * || any-rs-ready |
804 | * || any-ws-ready) | 870 | * || any-ws-ready) ) |
805 | * </code> | 871 | * </code> |
872 | * Only allowed to be called as long as the scheduler is running, that | ||
873 | * is one of the following conditions is met: | ||
874 | * | ||
875 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
876 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
877 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
806 | * | 878 | * |
807 | * @param prio how important is this task? | 879 | * @param prio how important is this task? |
808 | * @param delay how long should we wait? | 880 | * @param delay how long should we wait? |
@@ -811,7 +883,7 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, | |||
811 | * @param task main function of the task | 883 | * @param task main function of the task |
812 | * @param task_cls closure of @a task | 884 | * @param task_cls closure of @a task |
813 | * @return unique task identifier for the job | 885 | * @return unique task identifier for the job |
814 | * only valid until "task" is started! | 886 | * only valid until @a task is started! |
815 | */ | 887 | */ |
816 | struct GNUNET_SCHEDULER_Task * | 888 | struct GNUNET_SCHEDULER_Task * |
817 | GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | 889 | GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, |
diff --git a/src/multicast/gnunet-service-multicast.c b/src/multicast/gnunet-service-multicast.c index d01227e2c..819212388 100644 --- a/src/multicast/gnunet-service-multicast.c +++ b/src/multicast/gnunet-service-multicast.c | |||
@@ -1450,7 +1450,12 @@ check_client_member_join (void *cls, | |||
1450 | uint16_t msg_size = ntohs (msg->header.size); | 1450 | uint16_t msg_size = ntohs (msg->header.size); |
1451 | struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1]; | 1451 | struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1]; |
1452 | uint32_t relay_count = ntohl (msg->relay_count); | 1452 | uint32_t relay_count = ntohl (msg->relay_count); |
1453 | uint16_t relay_size = relay_count * sizeof (*relays); | 1453 | if (UINT32_MAX / relay_count > sizeof (*relays)){ |
1454 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1455 | "relay_size exceeds UINT32_MAX!"); | ||
1456 | return GNUNET_SYSERR; | ||
1457 | } | ||
1458 | uint32_t relay_size = relay_count * sizeof (*relays); | ||
1454 | struct GNUNET_MessageHeader *join_msg = NULL; | 1459 | struct GNUNET_MessageHeader *join_msg = NULL; |
1455 | uint16_t join_msg_size = 0; | 1460 | uint16_t join_msg_size = 0; |
1456 | if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader) | 1461 | if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader) |
@@ -1459,11 +1464,19 @@ check_client_member_join (void *cls, | |||
1459 | join_msg = (struct GNUNET_MessageHeader *) | 1464 | join_msg = (struct GNUNET_MessageHeader *) |
1460 | (((char *) &msg[1]) + relay_size); | 1465 | (((char *) &msg[1]) + relay_size); |
1461 | join_msg_size = ntohs (join_msg->size); | 1466 | join_msg_size = ntohs (join_msg->size); |
1467 | if (UINT16_MAX - join_msg_size > sizeof (struct MulticastJoinRequestMessage)){ | ||
1468 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1469 | "join_msg_size exceeds UINT16_MAX!"); | ||
1470 | return GNUNET_SYSERR; | ||
1471 | } | ||
1472 | } | ||
1473 | if (msg_size != (sizeof (*msg) + relay_size + join_msg_size)){ | ||
1474 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1475 | "msg_size does not match real size of message!"); | ||
1476 | return GNUNET_SYSERR; | ||
1477 | }else{ | ||
1478 | return GNUNET_OK; | ||
1462 | } | 1479 | } |
1463 | return | ||
1464 | msg_size == (sizeof (*msg) + relay_size + join_msg_size) | ||
1465 | ? GNUNET_OK | ||
1466 | : GNUNET_SYSERR; | ||
1467 | } | 1480 | } |
1468 | 1481 | ||
1469 | 1482 | ||
@@ -1887,6 +1900,7 @@ handle_client_replay_request (void *cls, | |||
1887 | else | 1900 | else |
1888 | { | 1901 | { |
1889 | /* FIXME: not yet connected to origin */ | 1902 | /* FIXME: not yet connected to origin */ |
1903 | |||
1890 | GNUNET_assert (0); | 1904 | GNUNET_assert (0); |
1891 | GNUNET_SERVICE_client_drop (client); | 1905 | GNUNET_SERVICE_client_drop (client); |
1892 | return; | 1906 | return; |
@@ -1975,7 +1989,7 @@ static int | |||
1975 | check_client_replay_response (void *cls, | 1989 | check_client_replay_response (void *cls, |
1976 | const struct MulticastReplayResponseMessage *res) | 1990 | const struct MulticastReplayResponseMessage *res) |
1977 | { | 1991 | { |
1978 | const struct GNUNET_MessageHeader *msg = &res->header; | 1992 | const struct GNUNET_MessageHeader *msg; |
1979 | if (GNUNET_MULTICAST_REC_OK == res->error_code) | 1993 | if (GNUNET_MULTICAST_REC_OK == res->error_code) |
1980 | { | 1994 | { |
1981 | msg = GNUNET_MQ_extract_nested_mh (res); | 1995 | msg = GNUNET_MQ_extract_nested_mh (res); |
diff --git a/src/psyc/gnunet-service-psyc.c b/src/psyc/gnunet-service-psyc.c index cf161435a..49779ef2c 100644 --- a/src/psyc/gnunet-service-psyc.c +++ b/src/psyc/gnunet-service-psyc.c | |||
@@ -2185,13 +2185,11 @@ master_transmit_message (struct Master *mst) | |||
2185 | return; | 2185 | return; |
2186 | if (NULL == mst->tmit_handle) | 2186 | if (NULL == mst->tmit_handle) |
2187 | { | 2187 | { |
2188 | mst->tmit_handle = (void *) &mst->tmit_handle; | 2188 | mst->tmit_handle = GNUNET_MULTICAST_origin_to_all (mst->origin, |
2189 | struct GNUNET_MULTICAST_OriginTransmitHandle * | 2189 | tmit_msg->id, |
2190 | tmit_handle = GNUNET_MULTICAST_origin_to_all (mst->origin, tmit_msg->id, | 2190 | mst->max_group_generation, |
2191 | mst->max_group_generation, | 2191 | &master_transmit_notify, |
2192 | master_transmit_notify, mst); | 2192 | mst); |
2193 | if (NULL != mst->tmit_handle) | ||
2194 | mst->tmit_handle = tmit_handle; | ||
2195 | } | 2193 | } |
2196 | else | 2194 | else |
2197 | { | 2195 | { |
@@ -2210,12 +2208,10 @@ slave_transmit_message (struct Slave *slv) | |||
2210 | return; | 2208 | return; |
2211 | if (NULL == slv->tmit_handle) | 2209 | if (NULL == slv->tmit_handle) |
2212 | { | 2210 | { |
2213 | slv->tmit_handle = (void *) &slv->tmit_handle; | 2211 | slv->tmit_handle = GNUNET_MULTICAST_member_to_origin (slv->member, |
2214 | struct GNUNET_MULTICAST_MemberTransmitHandle * | 2212 | slv->channel.tmit_head->id, |
2215 | tmit_handle = GNUNET_MULTICAST_member_to_origin (slv->member, slv->channel.tmit_head->id, | 2213 | &slave_transmit_notify, |
2216 | slave_transmit_notify, slv); | 2214 | slv); |
2217 | if (NULL != slv->tmit_handle) | ||
2218 | slv->tmit_handle = tmit_handle; | ||
2219 | } | 2215 | } |
2220 | else | 2216 | else |
2221 | { | 2217 | { |
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c index aeb0eabc2..56c3c52b6 100644 --- a/src/rps/gnunet-service-rps.c +++ b/src/rps/gnunet-service-rps.c | |||
@@ -3727,14 +3727,36 @@ do_round (void *cls) | |||
3727 | } else { | 3727 | } else { |
3728 | LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n"); | 3728 | LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n"); |
3729 | GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO); | 3729 | GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO); |
3730 | if (CustomPeerMap_size (push_map) > alpha * View_size ()) | 3730 | if (CustomPeerMap_size (push_map) > alpha * View_size () && |
3731 | !(0 >= CustomPeerMap_size (pull_map))) | ||
3731 | GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes", 1, GNUNET_NO); | 3732 | GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes", 1, GNUNET_NO); |
3732 | if (0 >= CustomPeerMap_size (push_map)) | 3733 | if (CustomPeerMap_size (push_map) > alpha * View_size () && |
3734 | (0 >= CustomPeerMap_size (pull_map))) | ||
3735 | GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes, no pull replies", 1, GNUNET_NO); | ||
3736 | if (0 >= CustomPeerMap_size (push_map) && | ||
3737 | !(0 >= CustomPeerMap_size (pull_map))) | ||
3733 | GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes", 1, GNUNET_NO); | 3738 | GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes", 1, GNUNET_NO); |
3734 | if (0 >= CustomPeerMap_size (pull_map)) | 3739 | if (0 >= CustomPeerMap_size (push_map) && |
3740 | (0 >= CustomPeerMap_size (pull_map))) | ||
3741 | GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes, no pull replies", 1, GNUNET_NO); | ||
3742 | if (0 >= CustomPeerMap_size (pull_map) && | ||
3743 | CustomPeerMap_size (push_map) > alpha * View_size () && | ||
3744 | 0 >= CustomPeerMap_size (push_map)) | ||
3735 | GNUNET_STATISTICS_update(stats, "# rounds blocked - no pull replies", 1, GNUNET_NO); | 3745 | GNUNET_STATISTICS_update(stats, "# rounds blocked - no pull replies", 1, GNUNET_NO); |
3736 | } | 3746 | } |
3737 | // TODO independent of that also get some peers from CADET_get_peers()? | 3747 | // TODO independent of that also get some peers from CADET_get_peers()? |
3748 | GNUNET_STATISTICS_set (stats, | ||
3749 | "# peers in push map at end of round", | ||
3750 | CustomPeerMap_size (push_map), | ||
3751 | GNUNET_NO); | ||
3752 | GNUNET_STATISTICS_set (stats, | ||
3753 | "# peers in pull map at end of round", | ||
3754 | CustomPeerMap_size (pull_map), | ||
3755 | GNUNET_NO); | ||
3756 | GNUNET_STATISTICS_set (stats, | ||
3757 | "# peers in view at end of round", | ||
3758 | View_size (), | ||
3759 | GNUNET_NO); | ||
3738 | 3760 | ||
3739 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 3761 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
3740 | "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (%u) = %.2f)\n", | 3762 | "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (%u) = %.2f)\n", |
diff --git a/src/rps/rps-test_util.h b/src/rps/rps-test_util.h index 209152151..225db4b1d 100644 --- a/src/rps/rps-test_util.h +++ b/src/rps/rps-test_util.h | |||
@@ -53,7 +53,7 @@ create_file (const char *name); | |||
53 | int size;\ | 53 | int size;\ |
54 | size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\ | 54 | size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\ |
55 | if (0 > size)\ | 55 | if (0 > size)\ |
56 | LOG (GNUNET_ERROR_TYPE_WARNING,\ | 56 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING,\ |
57 | "Failed to create tmp_buf\n");\ | 57 | "Failed to create tmp_buf\n");\ |
58 | else\ | 58 | else\ |
59 | to_file_(file_name,tmp_buf);\ | 59 | to_file_(file_name,tmp_buf);\ |
diff --git a/src/rps/test_rps.c b/src/rps/test_rps.c index c5a2c0458..4ef97ad92 100644 --- a/src/rps/test_rps.c +++ b/src/rps/test_rps.c | |||
@@ -253,24 +253,31 @@ struct RPSPeer | |||
253 | * Used to check whether we are able to shutdown. | 253 | * Used to check whether we are able to shutdown. |
254 | */ | 254 | */ |
255 | uint32_t stat_collected_flags; | 255 | uint32_t stat_collected_flags; |
256 | |||
257 | /** | ||
258 | * @brief File name of the file the stats are finally written to | ||
259 | */ | ||
260 | char *file_name_stats; | ||
256 | }; | 261 | }; |
257 | 262 | ||
258 | enum STAT_TYPE | 263 | enum STAT_TYPE |
259 | { | 264 | { |
260 | STAT_TYPE_ROUNDS = 0x1, /* 1 */ | 265 | STAT_TYPE_ROUNDS = 0x1, /* 1 */ |
261 | STAT_TYPE_BLOCKS = 0x2, /* 2 */ | 266 | STAT_TYPE_BLOCKS = 0x2, /* 2 */ |
262 | STAT_TYPE_BLOCKS_MANY_PUSH = 0x4, /* 3 */ | 267 | STAT_TYPE_BLOCKS_MANY_PUSH = 0x4, /* 3 */ |
263 | STAT_TYPE_BLOCKS_FEW_PUSH = 0x8, /* 4 */ | 268 | STAT_TYPE_BLOCKS_NO_PUSH = 0x8, /* 4 */ |
264 | STAT_TYPE_BLOCKS_FEW_PULL = 0x10, /* 5 */ | 269 | STAT_TYPE_BLOCKS_NO_PULL = 0x10, /* 5 */ |
265 | STAT_TYPE_ISSUED_PUSH_SEND = 0x20, /* 6 */ | 270 | STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL = 0x20, /* 6 */ |
266 | STAT_TYPE_ISSUED_PULL_REQ = 0x40, /* 7 */ | 271 | STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL = 0x40, /* 7 */ |
267 | STAT_TYPE_ISSUED_PULL_REP = 0x80, /* 8 */ | 272 | STAT_TYPE_ISSUED_PUSH_SEND = 0x80, /* 8 */ |
268 | STAT_TYPE_SENT_PUSH_SEND = 0x100, /* 9 */ | 273 | STAT_TYPE_ISSUED_PULL_REQ = 0x100, /* 9 */ |
269 | STAT_TYPE_SENT_PULL_REQ = 0x200, /* 10 */ | 274 | STAT_TYPE_ISSUED_PULL_REP = 0x200, /* 10 */ |
270 | STAT_TYPE_SENT_PULL_REP = 0x400, /* 11 */ | 275 | STAT_TYPE_SENT_PUSH_SEND = 0x400, /* 11 */ |
271 | STAT_TYPE_RECV_PUSH_SEND = 0x800, /* 12 */ | 276 | STAT_TYPE_SENT_PULL_REQ = 0x800, /* 12 */ |
272 | STAT_TYPE_RECV_PULL_REQ = 0x1000, /* 13 */ | 277 | STAT_TYPE_SENT_PULL_REP = 0x1000, /* 13 */ |
273 | STAT_TYPE_RECV_PULL_REP = 0x2000, /* 14 */ | 278 | STAT_TYPE_RECV_PUSH_SEND = 0x2000, /* 14 */ |
279 | STAT_TYPE_RECV_PULL_REQ = 0x4000, /* 15 */ | ||
280 | STAT_TYPE_RECV_PULL_REP = 0x8000, /* 16 */ | ||
274 | STAT_TYPE_MAX = 0x80000000, /* 32 */ | 281 | STAT_TYPE_MAX = 0x80000000, /* 32 */ |
275 | }; | 282 | }; |
276 | 283 | ||
@@ -1527,8 +1534,8 @@ manage_service_wrapper (unsigned int i, unsigned int j, | |||
1527 | &churn_cb, | 1534 | &churn_cb, |
1528 | entry, | 1535 | entry, |
1529 | (PEER_GO_OFFLINE == delta) ? 0 : 1); | 1536 | (PEER_GO_OFFLINE == delta) ? 0 : 1); |
1537 | rps_peers[j].entry_op_manage = entry; | ||
1530 | } | 1538 | } |
1531 | rps_peers[j].entry_op_manage = entry; | ||
1532 | } | 1539 | } |
1533 | 1540 | ||
1534 | 1541 | ||
@@ -1738,6 +1745,50 @@ profiler_eval (void) | |||
1738 | } | 1745 | } |
1739 | 1746 | ||
1740 | /** | 1747 | /** |
1748 | * @brief Try to ensure that `/tmp/rps` exists. | ||
1749 | * | ||
1750 | * @return #GNUNET_YES on success | ||
1751 | * #GNUNET_SYSERR on failure | ||
1752 | */ | ||
1753 | static int ensure_folder_exist (void) | ||
1754 | { | ||
1755 | if (GNUNET_NO == GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO)) | ||
1756 | { | ||
1757 | GNUNET_DISK_directory_create ("/tmp/rps"); | ||
1758 | } | ||
1759 | if (GNUNET_YES != GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO)) | ||
1760 | { | ||
1761 | return GNUNET_SYSERR; | ||
1762 | } | ||
1763 | return GNUNET_YES; | ||
1764 | } | ||
1765 | |||
1766 | static void | ||
1767 | store_stats_file_name (struct RPSPeer *rps_peer) | ||
1768 | { | ||
1769 | unsigned int len_file_name; | ||
1770 | unsigned int out_size; | ||
1771 | char *file_name; | ||
1772 | |||
1773 | if (GNUNET_SYSERR == ensure_folder_exist()) return; | ||
1774 | len_file_name = (14 + strlen (GNUNET_i2s_full (rps_peer->peer_id)) + 1) * sizeof (char); | ||
1775 | file_name = GNUNET_malloc (len_file_name); | ||
1776 | out_size = GNUNET_snprintf (file_name, | ||
1777 | len_file_name, | ||
1778 | "/tmp/rps/stat-%s", | ||
1779 | GNUNET_i2s_full (rps_peer->peer_id)); | ||
1780 | if (len_file_name < out_size || | ||
1781 | 0 > out_size) | ||
1782 | { | ||
1783 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1784 | "Failed to write string to buffer (size: %i, out_size: %i)\n", | ||
1785 | len_file_name, | ||
1786 | out_size); | ||
1787 | } | ||
1788 | rps_peer->file_name_stats = file_name; | ||
1789 | } | ||
1790 | |||
1791 | /** | ||
1741 | * Continuation called by #GNUNET_STATISTICS_get() functions. | 1792 | * Continuation called by #GNUNET_STATISTICS_get() functions. |
1742 | * | 1793 | * |
1743 | * Remembers that this specific statistics value was received for this peer. | 1794 | * Remembers that this specific statistics value was received for this peer. |
@@ -1801,10 +1852,14 @@ char* stat_type_2_str (enum STAT_TYPE stat_type) | |||
1801 | return "# rounds blocked"; | 1852 | return "# rounds blocked"; |
1802 | case STAT_TYPE_BLOCKS_MANY_PUSH: | 1853 | case STAT_TYPE_BLOCKS_MANY_PUSH: |
1803 | return "# rounds blocked - too many pushes"; | 1854 | return "# rounds blocked - too many pushes"; |
1804 | case STAT_TYPE_BLOCKS_FEW_PUSH: | 1855 | case STAT_TYPE_BLOCKS_NO_PUSH: |
1805 | return "# rounds blocked - no pushes"; | 1856 | return "# rounds blocked - no pushes"; |
1806 | case STAT_TYPE_BLOCKS_FEW_PULL: | 1857 | case STAT_TYPE_BLOCKS_NO_PULL: |
1807 | return "# rounds blocked - no pull replies"; | 1858 | return "# rounds blocked - no pull replies"; |
1859 | case STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL: | ||
1860 | return "# rounds blocked - too many pushes, no pull replies"; | ||
1861 | case STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL: | ||
1862 | return "# rounds blocked - no pushes, no pull replies"; | ||
1808 | case STAT_TYPE_ISSUED_PUSH_SEND: | 1863 | case STAT_TYPE_ISSUED_PUSH_SEND: |
1809 | return "# push send issued"; | 1864 | return "# push send issued"; |
1810 | case STAT_TYPE_ISSUED_PULL_REQ: | 1865 | case STAT_TYPE_ISSUED_PULL_REQ: |
@@ -1848,9 +1903,15 @@ stat_iterator (void *cls, | |||
1848 | int is_persistent) | 1903 | int is_persistent) |
1849 | { | 1904 | { |
1850 | const struct STATcls *stat_cls = (const struct STATcls *) cls; | 1905 | const struct STATcls *stat_cls = (const struct STATcls *) cls; |
1906 | const struct RPSPeer *rps_peer = (const struct RPSPeer *) stat_cls->rps_peer; | ||
1851 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got stat value: %s - %" PRIu64 "\n", | 1907 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got stat value: %s - %" PRIu64 "\n", |
1852 | stat_type_2_str (stat_cls->stat_type), | 1908 | //stat_type_2_str (stat_cls->stat_type), |
1909 | name, | ||
1853 | value); | 1910 | value); |
1911 | to_file (rps_peer->file_name_stats, | ||
1912 | "%s: %" PRIu64 "\n", | ||
1913 | name, | ||
1914 | value); | ||
1854 | return GNUNET_OK; | 1915 | return GNUNET_OK; |
1855 | } | 1916 | } |
1856 | 1917 | ||
@@ -1876,6 +1937,7 @@ void post_profiler (struct RPSPeer *rps_peer) | |||
1876 | stat_cls = GNUNET_malloc (sizeof (struct STATcls)); | 1937 | stat_cls = GNUNET_malloc (sizeof (struct STATcls)); |
1877 | stat_cls->rps_peer = rps_peer; | 1938 | stat_cls->rps_peer = rps_peer; |
1878 | stat_cls->stat_type = stat_type; | 1939 | stat_cls->stat_type = stat_type; |
1940 | store_stats_file_name (rps_peer); | ||
1879 | GNUNET_STATISTICS_get (rps_peer->stats_h, | 1941 | GNUNET_STATISTICS_get (rps_peer->stats_h, |
1880 | "rps", | 1942 | "rps", |
1881 | stat_type_2_str (stat_type), | 1943 | stat_type_2_str (stat_type), |
@@ -2141,8 +2203,10 @@ main (int argc, char *argv[]) | |||
2141 | cur_test_run.stat_collect_flags = STAT_TYPE_ROUNDS | | 2203 | cur_test_run.stat_collect_flags = STAT_TYPE_ROUNDS | |
2142 | STAT_TYPE_BLOCKS | | 2204 | STAT_TYPE_BLOCKS | |
2143 | STAT_TYPE_BLOCKS_MANY_PUSH | | 2205 | STAT_TYPE_BLOCKS_MANY_PUSH | |
2144 | STAT_TYPE_BLOCKS_FEW_PUSH | | 2206 | STAT_TYPE_BLOCKS_NO_PUSH | |
2145 | STAT_TYPE_BLOCKS_FEW_PULL | | 2207 | STAT_TYPE_BLOCKS_NO_PULL | |
2208 | STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL | | ||
2209 | STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL | | ||
2146 | STAT_TYPE_ISSUED_PUSH_SEND | | 2210 | STAT_TYPE_ISSUED_PUSH_SEND | |
2147 | STAT_TYPE_ISSUED_PULL_REQ | | 2211 | STAT_TYPE_ISSUED_PULL_REQ | |
2148 | STAT_TYPE_ISSUED_PULL_REP | | 2212 | STAT_TYPE_ISSUED_PULL_REP | |
diff --git a/src/social/gnunet-service-social.c b/src/social/gnunet-service-social.c index 31e3a3dc2..bac08ae9d 100644 --- a/src/social/gnunet-service-social.c +++ b/src/social/gnunet-service-social.c | |||
@@ -1774,12 +1774,13 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) | |||
1774 | plc_gst, | 1774 | plc_gst, |
1775 | gst); | 1775 | gst); |
1776 | 1776 | ||
1777 | new_guest = GNUNET_NO; | ||
1778 | if (NULL == gst) | 1777 | if (NULL == gst) |
1779 | { | 1778 | { |
1780 | gst = GNUNET_new (struct Guest); | 1779 | gst = GNUNET_new (struct Guest); |
1781 | new_guest = GNUNET_YES; | 1780 | new_guest = GNUNET_YES; |
1782 | } | 1781 | } |
1782 | else new_guest = GNUNET_NO; | ||
1783 | |||
1783 | if (NULL == gst->slave) | 1784 | if (NULL == gst->slave) |
1784 | { | 1785 | { |
1785 | gst->origin = greq->origin; | 1786 | gst->origin = greq->origin; |
@@ -1878,7 +1879,7 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst) | |||
1878 | ret = GNUNET_YES; | 1879 | ret = GNUNET_YES; |
1879 | } | 1880 | } |
1880 | 1881 | ||
1881 | // TODO: explain why free(gst) not necessary | 1882 | // TODO: explain to automatic code scanners why free(gst) not necessary |
1882 | if (NULL != ret_gst) | 1883 | if (NULL != ret_gst) |
1883 | *ret_gst = gst; | 1884 | *ret_gst = gst; |
1884 | return ret; | 1885 | return ret; |
@@ -3598,30 +3599,34 @@ identity_recv_ego (void *cls, struct GNUNET_IDENTITY_Ego *id_ego, | |||
3598 | GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash); | 3599 | GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash); |
3599 | 3600 | ||
3600 | struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash); | 3601 | struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash); |
3602 | if (NULL == ego && NULL == name) | ||
3603 | { | ||
3604 | // an ego that is none of our business has been deleted | ||
3605 | return; | ||
3606 | } | ||
3601 | if (NULL != ego) | 3607 | if (NULL != ego) |
3602 | { | 3608 | { |
3609 | // one of our egos has been changed | ||
3603 | GNUNET_free (ego->name); | 3610 | GNUNET_free (ego->name); |
3604 | if (NULL == name) // deleted | 3611 | if (NULL == name) |
3605 | { | 3612 | { |
3613 | // one of our egos has been deleted | ||
3606 | GNUNET_CONTAINER_multihashmap_remove (egos, &ego_pub_hash, ego); | 3614 | GNUNET_CONTAINER_multihashmap_remove (egos, &ego_pub_hash, ego); |
3607 | GNUNET_free (ego); | 3615 | GNUNET_free (ego); |
3608 | ego = NULL; | 3616 | return; |
3609 | } | 3617 | } |
3610 | } | 3618 | } |
3611 | else | 3619 | else |
3612 | { | 3620 | { |
3613 | ego = GNUNET_malloc (sizeof (*ego)); | 3621 | ego = GNUNET_malloc (sizeof (*ego)); |
3614 | } | 3622 | } |
3615 | if (NULL != ego) | 3623 | ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego)); |
3616 | { | 3624 | size_t name_size = strlen (name) + 1; |
3617 | ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego)); | 3625 | ego->name = GNUNET_malloc (name_size); |
3618 | size_t name_size = strlen (name) + 1; | 3626 | GNUNET_memcpy (ego->name, name, name_size); |
3619 | ego->name = GNUNET_malloc (name_size); | ||
3620 | GNUNET_memcpy (ego->name, name, name_size); | ||
3621 | 3627 | ||
3622 | GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego, | 3628 | GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego, |
3623 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | 3629 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); |
3624 | } | ||
3625 | 3630 | ||
3626 | // FIXME: notify clients about changed ego | 3631 | // FIXME: notify clients about changed ego |
3627 | } | 3632 | } |
diff --git a/src/util/mq.c b/src/util/mq.c index 8d71359ac..33bbaa6ad 100644 --- a/src/util/mq.c +++ b/src/util/mq.c | |||
@@ -851,7 +851,7 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq) | |||
851 | ev); | 851 | ev); |
852 | GNUNET_assert (0 < mq->queue_length); | 852 | GNUNET_assert (0 < mq->queue_length); |
853 | mq->queue_length--; | 853 | mq->queue_length--; |
854 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 854 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
855 | "MQ destroy drops message of type %u\n", | 855 | "MQ destroy drops message of type %u\n", |
856 | ntohs (ev->mh->type)); | 856 | ntohs (ev->mh->type)); |
857 | GNUNET_MQ_discard (ev); | 857 | GNUNET_MQ_discard (ev); |
@@ -861,7 +861,7 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq) | |||
861 | /* we can only discard envelopes that | 861 | /* we can only discard envelopes that |
862 | * are not queued! */ | 862 | * are not queued! */ |
863 | mq->current_envelope->parent_queue = NULL; | 863 | mq->current_envelope->parent_queue = NULL; |
864 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 864 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
865 | "MQ destroy drops current message of type %u\n", | 865 | "MQ destroy drops current message of type %u\n", |
866 | ntohs (mq->current_envelope->mh->type)); | 866 | ntohs (mq->current_envelope->mh->type)); |
867 | GNUNET_MQ_discard (mq->current_envelope); | 867 | GNUNET_MQ_discard (mq->current_envelope); |
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 6cf5e1168..51afc85e5 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include "platform.h" | 25 | #include "platform.h" |
26 | #include "gnunet_util_lib.h" | 26 | #include "gnunet_util_lib.h" |
27 | #include "disk.h" | 27 | #include "disk.h" |
28 | // DEBUG | ||
29 | #include <inttypes.h> | ||
28 | 30 | ||
29 | #define LOG(kind,...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__) | 31 | #define LOG(kind,...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__) |
30 | 32 | ||
@@ -71,7 +73,7 @@ | |||
71 | 73 | ||
72 | /** | 74 | /** |
73 | * Argument to be passed from the driver to | 75 | * Argument to be passed from the driver to |
74 | * #GNUNET_SCHEDULER_run_from_driver(). Contains the | 76 | * #GNUNET_SCHEDULER_do_work(). Contains the |
75 | * scheduler's internal state. | 77 | * scheduler's internal state. |
76 | */ | 78 | */ |
77 | struct GNUNET_SCHEDULER_Handle | 79 | struct GNUNET_SCHEDULER_Handle |
@@ -89,6 +91,40 @@ struct GNUNET_SCHEDULER_Handle | |||
89 | * @deprecated | 91 | * @deprecated |
90 | */ | 92 | */ |
91 | struct GNUNET_NETWORK_FDSet *ws; | 93 | struct GNUNET_NETWORK_FDSet *ws; |
94 | |||
95 | /** | ||
96 | * context of the SIGINT handler | ||
97 | */ | ||
98 | struct GNUNET_SIGNAL_Context *shc_int; | ||
99 | |||
100 | /** | ||
101 | * context of the SIGTERM handler | ||
102 | */ | ||
103 | struct GNUNET_SIGNAL_Context *shc_term; | ||
104 | |||
105 | #if (SIGTERM != GNUNET_TERM_SIG) | ||
106 | /** | ||
107 | * context of the TERM_SIG handler | ||
108 | */ | ||
109 | struct GNUNET_SIGNAL_Context *shc_gterm; | ||
110 | #endif | ||
111 | |||
112 | #ifndef MINGW | ||
113 | /** | ||
114 | * context of the SIGQUIT handler | ||
115 | */ | ||
116 | struct GNUNET_SIGNAL_Context *shc_quit; | ||
117 | |||
118 | /** | ||
119 | * context of the SIGHUP handler | ||
120 | */ | ||
121 | struct GNUNET_SIGNAL_Context *shc_hup; | ||
122 | |||
123 | /** | ||
124 | * context of hte SIGPIPE handler | ||
125 | */ | ||
126 | struct GNUNET_SIGNAL_Context *shc_pipe; | ||
127 | #endif | ||
92 | }; | 128 | }; |
93 | 129 | ||
94 | 130 | ||
@@ -254,16 +290,16 @@ struct DriverContext | |||
254 | struct Scheduled *scheduled_tail; | 290 | struct Scheduled *scheduled_tail; |
255 | 291 | ||
256 | /** | 292 | /** |
257 | * the time until the select driver will wake up again (after | 293 | * the time when the select driver will wake up again (after |
258 | * calling select) | 294 | * calling select) |
259 | */ | 295 | */ |
260 | struct GNUNET_TIME_Relative timeout; | 296 | struct GNUNET_TIME_Absolute timeout; |
261 | }; | 297 | }; |
262 | 298 | ||
263 | 299 | ||
264 | /** | 300 | /** |
265 | * The driver used for the event loop. Will be handed over to | 301 | * The driver used for the event loop. Will be handed over to |
266 | * the scheduler in #GNUNET_SCHEDULER_run_from_driver(), peristed | 302 | * the scheduler in #GNUNET_SCHEDULER_do_work(), persisted |
267 | * there in this variable for later use in functions like | 303 | * there in this variable for later use in functions like |
268 | * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and | 304 | * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and |
269 | * #GNUNET_SCHEDULER_cancel(). | 305 | * #GNUNET_SCHEDULER_cancel(). |
@@ -380,11 +416,6 @@ static struct GNUNET_SCHEDULER_TaskContext tc; | |||
380 | */ | 416 | */ |
381 | static void *scheduler_select_cls; | 417 | static void *scheduler_select_cls; |
382 | 418 | ||
383 | /** | ||
384 | * Scheduler handle used for the driver functions | ||
385 | */ | ||
386 | static struct GNUNET_SCHEDULER_Handle sh; | ||
387 | |||
388 | 419 | ||
389 | /** | 420 | /** |
390 | * Sets the select function to use in the scheduler (scheduler_select). | 421 | * Sets the select function to use in the scheduler (scheduler_select). |
@@ -657,6 +688,10 @@ shutdown_if_no_lifeness () | |||
657 | } | 688 | } |
658 | 689 | ||
659 | 690 | ||
691 | int | ||
692 | select_loop (struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context); | ||
693 | |||
694 | |||
660 | /** | 695 | /** |
661 | * Initialize and run scheduler. This function will return when all | 696 | * Initialize and run scheduler. This function will return when all |
662 | * tasks have completed. On systems with signals, receiving a SIGTERM | 697 | * tasks have completed. On systems with signals, receiving a SIGTERM |
@@ -675,16 +710,21 @@ void | |||
675 | GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, | 710 | GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, |
676 | void *task_cls) | 711 | void *task_cls) |
677 | { | 712 | { |
713 | struct GNUNET_SCHEDULER_Handle *sh; | ||
678 | struct GNUNET_SCHEDULER_Driver *driver; | 714 | struct GNUNET_SCHEDULER_Driver *driver; |
679 | struct DriverContext context = {.scheduled_head = NULL, | 715 | struct DriverContext context = {.scheduled_head = NULL, |
680 | .scheduled_tail = NULL, | 716 | .scheduled_tail = NULL, |
681 | .timeout = GNUNET_TIME_UNIT_FOREVER_REL}; | 717 | .timeout = GNUNET_TIME_absolute_get ()}; |
682 | 718 | ||
683 | driver = GNUNET_SCHEDULER_driver_select (); | 719 | driver = GNUNET_SCHEDULER_driver_select (); |
684 | driver->cls = &context; | 720 | driver->cls = &context; |
685 | 721 | sh = GNUNET_SCHEDULER_driver_init (driver); | |
686 | GNUNET_SCHEDULER_run_with_driver (driver, task, task_cls); | 722 | GNUNET_SCHEDULER_add_with_reason_and_priority (task, |
687 | 723 | task_cls, | |
724 | GNUNET_SCHEDULER_REASON_STARTUP, | ||
725 | GNUNET_SCHEDULER_PRIORITY_DEFAULT); | ||
726 | select_loop (sh, &context); | ||
727 | GNUNET_SCHEDULER_driver_done (sh); | ||
688 | GNUNET_free (driver); | 728 | GNUNET_free (driver); |
689 | } | 729 | } |
690 | 730 | ||
@@ -898,8 +938,11 @@ shutdown_pipe_cb (void *cls) | |||
898 | /** | 938 | /** |
899 | * Cancel the task with the specified identifier. | 939 | * Cancel the task with the specified identifier. |
900 | * The task must not yet have run. Only allowed to be called as long as the | 940 | * The task must not yet have run. Only allowed to be called as long as the |
901 | * scheduler is running (#GNUNET_SCHEDULER_run or | 941 | * scheduler is running, that is one of the following conditions is met: |
902 | * #GNUNET_SCHEDULER_run_with_driver has been called and has not returned yet). | 942 | * |
943 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
944 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
945 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
903 | * | 946 | * |
904 | * @param task id of the task to cancel | 947 | * @param task id of the task to cancel |
905 | * @return original closure of the task | 948 | * @return original closure of the task |
@@ -1085,9 +1128,7 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, | |||
1085 | pos = pending_timeout_head; | 1128 | pos = pending_timeout_head; |
1086 | else | 1129 | else |
1087 | pos = prev->next; | 1130 | pos = prev->next; |
1088 | while ( (NULL != pos) && | 1131 | while ((NULL != pos) && (pos->timeout.abs_value_us <= t->timeout.abs_value_us)) |
1089 | ( (pos->timeout.abs_value_us <= t->timeout.abs_value_us) || | ||
1090 | (0 != pos->reason) ) ) | ||
1091 | { | 1132 | { |
1092 | prev = pos; | 1133 | prev = pos; |
1093 | pos = pos->next; | 1134 | pos = pos->next; |
@@ -1401,9 +1442,12 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1401 | * used as a timeout on the socket being ready. The task will be | 1442 | * used as a timeout on the socket being ready. The task will be |
1402 | * scheduled for execution once either the delay has expired or the | 1443 | * scheduled for execution once either the delay has expired or the |
1403 | * socket operation is ready. It will be run with the DEFAULT priority. | 1444 | * socket operation is ready. It will be run with the DEFAULT priority. |
1404 | * Only allowed to be called as long as the scheduler is running | 1445 | * Only allowed to be called as long as the scheduler is running, that |
1405 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1446 | * is one of the following conditions is met: |
1406 | * called and has not returned yet). | 1447 | * |
1448 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1449 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1450 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1407 | * | 1451 | * |
1408 | * @param delay when should this operation time out? | 1452 | * @param delay when should this operation time out? |
1409 | * @param rfd read file-descriptor | 1453 | * @param rfd read file-descriptor |
@@ -1431,9 +1475,12 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, | |||
1431 | * socket being ready. The task will be scheduled for execution once | 1475 | * socket being ready. The task will be scheduled for execution once |
1432 | * either the delay has expired or the socket operation is ready. It | 1476 | * either the delay has expired or the socket operation is ready. It |
1433 | * will be run with the DEFAULT priority. | 1477 | * will be run with the DEFAULT priority. |
1434 | * Only allowed to be called as long as the scheduler is running | 1478 | * Only allowed to be called as long as the scheduler is running, that |
1435 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1479 | * is one of the following conditions is met: |
1436 | * called and has not returned yet). | 1480 | * |
1481 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1482 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1483 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1437 | * | 1484 | * |
1438 | * @param delay when should this operation time out? | 1485 | * @param delay when should this operation time out? |
1439 | * @param priority priority to use for the task | 1486 | * @param priority priority to use for the task |
@@ -1465,9 +1512,12 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1465 | * scheduled for execution once either the delay has expired or the | 1512 | * scheduled for execution once either the delay has expired or the |
1466 | * socket operation is ready. It will be run with the priority of | 1513 | * socket operation is ready. It will be run with the priority of |
1467 | * the calling task. | 1514 | * the calling task. |
1468 | * Only allowed to be called as long as the scheduler is running | 1515 | * Only allowed to be called as long as the scheduler is running, that |
1469 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1516 | * is one of the following conditions is met: |
1470 | * called and has not returned yet). | 1517 | * |
1518 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1519 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1520 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1471 | * | 1521 | * |
1472 | * @param delay when should this operation time out? | 1522 | * @param delay when should this operation time out? |
1473 | * @param wfd write file-descriptor | 1523 | * @param wfd write file-descriptor |
@@ -1495,9 +1545,12 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | |||
1495 | * used as a timeout on the socket being ready. The task will be | 1545 | * used as a timeout on the socket being ready. The task will be |
1496 | * scheduled for execution once either the delay has expired or the | 1546 | * scheduled for execution once either the delay has expired or the |
1497 | * socket operation is ready. | 1547 | * socket operation is ready. |
1498 | * Only allowed to be called as long as the scheduler is running | 1548 | * Only allowed to be called as long as the scheduler is running, that |
1499 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1549 | * is one of the following conditions is met: |
1500 | * called and has not returned yet). | 1550 | * |
1551 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1552 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1553 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1501 | * | 1554 | * |
1502 | * @param delay when should this operation time out? | 1555 | * @param delay when should this operation time out? |
1503 | * @param priority priority of the task | 1556 | * @param priority priority of the task |
@@ -1554,9 +1607,12 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1554 | * used as a timeout on the socket being ready. The task will be | 1607 | * used as a timeout on the socket being ready. The task will be |
1555 | * scheduled for execution once either the delay has expired or the | 1608 | * scheduled for execution once either the delay has expired or the |
1556 | * socket operation is ready. It will be run with the DEFAULT priority. | 1609 | * socket operation is ready. It will be run with the DEFAULT priority. |
1557 | * Only allowed to be called as long as the scheduler is running | 1610 | * Only allowed to be called as long as the scheduler is running, that |
1558 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1611 | * is one of the following conditions is met: |
1559 | * called and has not returned yet). | 1612 | * |
1613 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1614 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1615 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1560 | * | 1616 | * |
1561 | * @param delay when should this operation time out? | 1617 | * @param delay when should this operation time out? |
1562 | * @param rfd read file-descriptor | 1618 | * @param rfd read file-descriptor |
@@ -1583,9 +1639,12 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, | |||
1583 | * used as a timeout on the socket being ready. The task will be | 1639 | * used as a timeout on the socket being ready. The task will be |
1584 | * scheduled for execution once either the delay has expired or the | 1640 | * scheduled for execution once either the delay has expired or the |
1585 | * socket operation is ready. It will be run with the DEFAULT priority. | 1641 | * socket operation is ready. It will be run with the DEFAULT priority. |
1586 | * Only allowed to be called as long as the scheduler is running | 1642 | * Only allowed to be called as long as the scheduler is running, that |
1587 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1643 | * is one of the following conditions is met: |
1588 | * called and has not returned yet). | 1644 | * |
1645 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1646 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1647 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1589 | * | 1648 | * |
1590 | * @param delay when should this operation time out? | 1649 | * @param delay when should this operation time out? |
1591 | * @param wfd write file-descriptor | 1650 | * @param wfd write file-descriptor |
@@ -1612,9 +1671,12 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, | |||
1612 | * used as a timeout on the socket being ready. The task will be | 1671 | * used as a timeout on the socket being ready. The task will be |
1613 | * scheduled for execution once either the delay has expired or the | 1672 | * scheduled for execution once either the delay has expired or the |
1614 | * socket operation is ready. | 1673 | * socket operation is ready. |
1615 | * Only allowed to be called as long as the scheduler is running | 1674 | * Only allowed to be called as long as the scheduler is running, that |
1616 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1675 | * is one of the following conditions is met: |
1617 | * called and has not returned yet). | 1676 | * |
1677 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1678 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1679 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1618 | * | 1680 | * |
1619 | * @param delay when should this operation time out? | 1681 | * @param delay when should this operation time out? |
1620 | * @param priority priority of the task | 1682 | * @param priority priority of the task |
@@ -1729,9 +1791,12 @@ extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, | |||
1729 | * || any-rs-ready | 1791 | * || any-rs-ready |
1730 | * || any-ws-ready) ) | 1792 | * || any-ws-ready) ) |
1731 | * </code> | 1793 | * </code> |
1732 | * Only allowed to be called as long as the scheduler is running | 1794 | * Only allowed to be called as long as the scheduler is running, that |
1733 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1795 | * is one of the following conditions is met: |
1734 | * called and has not returned yet). | 1796 | * |
1797 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1798 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1799 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1735 | * | 1800 | * |
1736 | * @param prio how important is this task? | 1801 | * @param prio how important is this task? |
1737 | * @param delay how long should we wait? | 1802 | * @param delay how long should we wait? |
@@ -1886,24 +1951,27 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, | |||
1886 | 1951 | ||
1887 | 1952 | ||
1888 | /** | 1953 | /** |
1889 | * Function called by the driver to tell the scheduler to run some of | 1954 | * Function called by external event loop implementations to tell the |
1890 | * the tasks that are ready. This function may return even though | 1955 | * scheduler to run some of the tasks that are ready. Must be called |
1891 | * there are tasks left to run just to give other tasks a chance as | 1956 | * only after #GNUNET_SCHEDULER_driver_init has been called and before |
1892 | * well. If we return #GNUNET_YES, the driver should call this | 1957 | * #GNUNET_SCHEDULER_driver_done is called. |
1893 | * function again as soon as possible, while if we return #GNUNET_NO | 1958 | * This function may return even though there are tasks left to run |
1894 | * it must block until either the operating system has more work (the | 1959 | * just to give other tasks a chance as well. If we return #GNUNET_YES, |
1895 | * scheduler has no more work to do right now) or the timeout set by | 1960 | * the event loop implementation should call this function again as |
1896 | * the scheduler (using the set_wakeup callback) is reached. | 1961 | * soon as possible, while if we return #GNUNET_NO it must block until |
1962 | * either the operating system has more work (the scheduler has no more | ||
1963 | * work to do right now) or the timeout set by the scheduler (using the | ||
1964 | * set_wakeup callback) is reached. | ||
1897 | * | 1965 | * |
1898 | * @param sh scheduler handle that was given to the `loop` | 1966 | * @param sh scheduler handle that was returned by |
1899 | * @return #GNUNET_OK if there are more tasks that are ready, | 1967 | * #GNUNET_SCHEDULER_driver_init |
1900 | * and thus we would like to run more (yield to avoid | 1968 | * @return #GNUNET_YES if there are more tasks that are ready, |
1901 | * blocking other activities for too long) | 1969 | * and thus we would like to run more (yield to avoid |
1902 | * #GNUNET_NO if we are done running tasks (yield to block) | 1970 | * blocking other activities for too long) #GNUNET_NO |
1903 | * #GNUNET_SYSERR on error, e.g. no tasks were ready | 1971 | * if we are done running tasks (yield to block) |
1904 | */ | 1972 | */ |
1905 | int | 1973 | int |
1906 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | 1974 | GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh) |
1907 | { | 1975 | { |
1908 | enum GNUNET_SCHEDULER_Priority p; | 1976 | enum GNUNET_SCHEDULER_Priority p; |
1909 | struct GNUNET_SCHEDULER_Task *pos; | 1977 | struct GNUNET_SCHEDULER_Task *pos; |
@@ -1944,9 +2012,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
1944 | 2012 | ||
1945 | if (0 == ready_count) | 2013 | if (0 == ready_count) |
1946 | { | 2014 | { |
1947 | LOG (GNUNET_ERROR_TYPE_ERROR, | 2015 | struct GNUNET_TIME_Absolute timeout = get_timeout (); |
1948 | "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n"); | 2016 | |
1949 | return GNUNET_SYSERR; | 2017 | if (timeout.abs_value_us > now.abs_value_us) |
2018 | { | ||
2019 | /** | ||
2020 | * The driver called this function before the current timeout was | ||
2021 | * reached (and no FD tasks are ready). This can happen in the | ||
2022 | * rare case when the system time is changed while the driver is | ||
2023 | * waiting for the timeout, so we handle this gracefully. It might | ||
2024 | * also be a programming error in the driver though. | ||
2025 | */ | ||
2026 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2027 | "GNUNET_SCHEDULER_do_work did not find any ready " | ||
2028 | "tasks and timeout has not been reached yet."); | ||
2029 | return GNUNET_NO; | ||
2030 | } | ||
2031 | /** | ||
2032 | * the current timeout was reached but no ready tasks were found, | ||
2033 | * internal scheduler error! | ||
2034 | */ | ||
2035 | GNUNET_assert (0); | ||
1950 | } | 2036 | } |
1951 | 2037 | ||
1952 | /* find out which task priority level we are going to | 2038 | /* find out which task priority level we are going to |
@@ -2034,48 +2120,52 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
2034 | } | 2120 | } |
2035 | scheduler_driver->set_wakeup (scheduler_driver->cls, | 2121 | scheduler_driver->set_wakeup (scheduler_driver->cls, |
2036 | GNUNET_TIME_absolute_get ()); | 2122 | GNUNET_TIME_absolute_get ()); |
2037 | return GNUNET_OK; | 2123 | return GNUNET_YES; |
2038 | } | 2124 | } |
2039 | 2125 | ||
2040 | 2126 | ||
2041 | /** | 2127 | /** |
2042 | * Initialize and run scheduler. This function will return when all | 2128 | * Function called by external event loop implementations to initialize |
2043 | * tasks have completed. On systems with signals, receiving a SIGTERM | 2129 | * the scheduler. An external implementation has to provide @a driver |
2044 | * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown | 2130 | * which contains callbacks for the scheduler (see definition of struct |
2045 | * to be run after the active task is complete. As a result, SIGTERM | 2131 | * #GNUNET_SCHEDULER_Driver). The callbacks are used to instruct the |
2046 | * causes all shutdown tasks to be scheduled with reason | 2132 | * external implementation to watch for events. If it detects any of |
2047 | * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added | 2133 | * those events it is expected to call #GNUNET_SCHEDULER_do_work to let |
2048 | * afterwards will execute normally!). Note that any particular | 2134 | * the scheduler handle it. If an event is related to a specific task |
2049 | * signal will only shut down one scheduler; applications should | 2135 | * (e.g. the scheduler gave instructions to watch a file descriptor), |
2050 | * always only create a single scheduler. | 2136 | * the external implementation is expected to mark that task ready |
2137 | * before by calling #GNUNET_SCHEDULER_task_ready. | ||
2138 | |||
2139 | * This function has to be called before any tasks are scheduled and | ||
2140 | * before GNUNET_SCHEDULER_do_work is called for the first time. It | ||
2141 | * allocates resources that have to be freed again by calling | ||
2142 | * #GNUNET_SCHEDULER_driver_done. | ||
2051 | * | 2143 | * |
2052 | * @param driver drive to use for the event loop | 2144 | * This function installs the same signal handlers as |
2053 | * @param task task to run first (and immediately) | 2145 | * #GNUNET_SCHEDULER_run. This means SIGTERM (and other similar signals) |
2054 | * @param task_cls closure of @a task | 2146 | * will induce a call to #GNUNET_SCHEDULER_shutdown during the next |
2055 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | 2147 | * call to #GNUNET_SCHEDULER_do_work. As a result, SIGTERM causes all |
2148 | * active tasks to be scheduled with reason | ||
2149 | * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added afterwards | ||
2150 | * will execute normally!). Note that any particular signal will only | ||
2151 | * shut down one scheduler; applications should always only create a | ||
2152 | * single scheduler. | ||
2153 | * | ||
2154 | * @param driver to use for the event loop | ||
2155 | * @return handle to be passed to #GNUNET_SCHEDULER_do_work and | ||
2156 | * #GNUNET_SCHEDULER_driver_done | ||
2056 | */ | 2157 | */ |
2057 | int | 2158 | struct GNUNET_SCHEDULER_Handle * |
2058 | GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | 2159 | GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver) |
2059 | GNUNET_SCHEDULER_TaskCallback task, | ||
2060 | void *task_cls) | ||
2061 | { | 2160 | { |
2062 | int ret; | 2161 | struct GNUNET_SCHEDULER_Handle *sh; |
2063 | struct GNUNET_SIGNAL_Context *shc_int; | ||
2064 | struct GNUNET_SIGNAL_Context *shc_term; | ||
2065 | #if (SIGTERM != GNUNET_TERM_SIG) | ||
2066 | struct GNUNET_SIGNAL_Context *shc_gterm; | ||
2067 | #endif | ||
2068 | #ifndef MINGW | ||
2069 | struct GNUNET_SIGNAL_Context *shc_quit; | ||
2070 | struct GNUNET_SIGNAL_Context *shc_hup; | ||
2071 | struct GNUNET_SIGNAL_Context *shc_pipe; | ||
2072 | #endif | ||
2073 | struct GNUNET_SCHEDULER_Task tsk; | 2162 | struct GNUNET_SCHEDULER_Task tsk; |
2074 | const struct GNUNET_DISK_FileHandle *pr; | 2163 | const struct GNUNET_DISK_FileHandle *pr; |
2075 | 2164 | ||
2076 | /* general set-up */ | 2165 | /* general set-up */ |
2077 | GNUNET_assert (NULL == active_task); | 2166 | GNUNET_assert (NULL == active_task); |
2078 | GNUNET_assert (NULL == shutdown_pipe_handle); | 2167 | GNUNET_assert (NULL == shutdown_pipe_handle); |
2168 | sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle); | ||
2079 | shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, | 2169 | shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, |
2080 | GNUNET_NO, | 2170 | GNUNET_NO, |
2081 | GNUNET_NO, | 2171 | GNUNET_NO, |
@@ -2089,21 +2179,21 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | |||
2089 | /* install signal handlers */ | 2179 | /* install signal handlers */ |
2090 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2180 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2091 | "Registering signal handlers\n"); | 2181 | "Registering signal handlers\n"); |
2092 | shc_int = GNUNET_SIGNAL_handler_install (SIGINT, | 2182 | sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT, |
2093 | &sighandler_shutdown); | 2183 | &sighandler_shutdown); |
2094 | shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, | 2184 | sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, |
2095 | &sighandler_shutdown); | 2185 | &sighandler_shutdown); |
2096 | #if (SIGTERM != GNUNET_TERM_SIG) | 2186 | #if (SIGTERM != GNUNET_TERM_SIG) |
2097 | shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, | 2187 | sh->shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, |
2098 | &sighandler_shutdown); | 2188 | &sighandler_shutdown); |
2099 | #endif | 2189 | #endif |
2100 | #ifndef MINGW | 2190 | #ifndef MINGW |
2101 | shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, | 2191 | sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, |
2102 | &sighandler_pipe); | 2192 | &sighandler_pipe); |
2103 | shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, | 2193 | sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, |
2104 | &sighandler_shutdown); | 2194 | &sighandler_shutdown); |
2105 | shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, | 2195 | sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, |
2106 | &sighandler_shutdown); | 2196 | &sighandler_shutdown); |
2107 | #endif | 2197 | #endif |
2108 | 2198 | ||
2109 | /* Setup initial tasks */ | 2199 | /* Setup initial tasks */ |
@@ -2122,19 +2212,33 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | |||
2122 | &shutdown_pipe_cb, | 2212 | &shutdown_pipe_cb, |
2123 | NULL); | 2213 | NULL); |
2124 | current_lifeness = GNUNET_YES; | 2214 | current_lifeness = GNUNET_YES; |
2125 | GNUNET_SCHEDULER_add_with_reason_and_priority (task, | ||
2126 | task_cls, | ||
2127 | GNUNET_SCHEDULER_REASON_STARTUP, | ||
2128 | GNUNET_SCHEDULER_PRIORITY_DEFAULT); | ||
2129 | active_task = NULL; | 2215 | active_task = NULL; |
2130 | scheduler_driver->set_wakeup (scheduler_driver->cls, | 2216 | scheduler_driver->set_wakeup (scheduler_driver->cls, |
2131 | get_timeout ()); | 2217 | get_timeout ()); |
2132 | /* begin main event loop */ | 2218 | /* begin main event loop */ |
2133 | sh.rs = GNUNET_NETWORK_fdset_create (); | 2219 | sh->rs = GNUNET_NETWORK_fdset_create (); |
2134 | sh.ws = GNUNET_NETWORK_fdset_create (); | 2220 | sh->ws = GNUNET_NETWORK_fdset_create (); |
2135 | GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); | 2221 | GNUNET_NETWORK_fdset_handle_set (sh->rs, pr); |
2136 | ret = driver->loop (driver->cls, | 2222 | return sh; |
2137 | &sh); | 2223 | } |
2224 | |||
2225 | |||
2226 | /** | ||
2227 | * Counter-part of #GNUNET_SCHEDULER_driver_init. Has to be called | ||
2228 | * by external event loop implementations after the scheduler has | ||
2229 | * shut down. This is the case if both of the following conditions | ||
2230 | * are met: | ||
2231 | * | ||
2232 | * - all tasks the scheduler has added through the driver's add | ||
2233 | * callback have been removed again through the driver's del | ||
2234 | * callback | ||
2235 | * - the timeout the scheduler has set through the driver's | ||
2236 | * add_wakeup callback is FOREVER | ||
2237 | * | ||
2238 | * @param sh the handle returned by #GNUNET_SCHEDULER_driver_init | ||
2239 | */ | ||
2240 | void GNUNET_SCHEDULER_driver_done (struct GNUNET_SCHEDULER_Handle *sh) | ||
2241 | { | ||
2138 | GNUNET_assert (NULL == pending_head); | 2242 | GNUNET_assert (NULL == pending_head); |
2139 | GNUNET_assert (NULL == pending_timeout_head); | 2243 | GNUNET_assert (NULL == pending_timeout_head); |
2140 | GNUNET_assert (NULL == shutdown_head); | 2244 | GNUNET_assert (NULL == shutdown_head); |
@@ -2142,108 +2246,43 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | |||
2142 | { | 2246 | { |
2143 | GNUNET_assert (NULL == ready_head[i]); | 2247 | GNUNET_assert (NULL == ready_head[i]); |
2144 | } | 2248 | } |
2145 | GNUNET_NETWORK_fdset_destroy (sh.rs); | 2249 | GNUNET_NETWORK_fdset_destroy (sh->rs); |
2146 | GNUNET_NETWORK_fdset_destroy (sh.ws); | 2250 | GNUNET_NETWORK_fdset_destroy (sh->ws); |
2147 | 2251 | ||
2148 | /* uninstall signal handlers */ | 2252 | /* uninstall signal handlers */ |
2149 | GNUNET_SIGNAL_handler_uninstall (shc_int); | 2253 | GNUNET_SIGNAL_handler_uninstall (sh->shc_int); |
2150 | GNUNET_SIGNAL_handler_uninstall (shc_term); | 2254 | GNUNET_SIGNAL_handler_uninstall (sh->shc_term); |
2151 | #if (SIGTERM != GNUNET_TERM_SIG) | 2255 | #if (SIGTERM != GNUNET_TERM_SIG) |
2152 | GNUNET_SIGNAL_handler_uninstall (shc_gterm); | 2256 | GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm); |
2153 | #endif | 2257 | #endif |
2154 | #ifndef MINGW | 2258 | #ifndef MINGW |
2155 | GNUNET_SIGNAL_handler_uninstall (shc_pipe); | 2259 | GNUNET_SIGNAL_handler_uninstall (sh->shc_pipe); |
2156 | GNUNET_SIGNAL_handler_uninstall (shc_quit); | 2260 | GNUNET_SIGNAL_handler_uninstall (sh->shc_quit); |
2157 | GNUNET_SIGNAL_handler_uninstall (shc_hup); | 2261 | GNUNET_SIGNAL_handler_uninstall (sh->shc_hup); |
2158 | #endif | 2262 | #endif |
2159 | GNUNET_DISK_pipe_close (shutdown_pipe_handle); | 2263 | GNUNET_DISK_pipe_close (shutdown_pipe_handle); |
2160 | shutdown_pipe_handle = NULL; | 2264 | shutdown_pipe_handle = NULL; |
2161 | scheduler_driver = NULL; | 2265 | scheduler_driver = NULL; |
2162 | return ret; | 2266 | GNUNET_free (sh); |
2163 | } | ||
2164 | |||
2165 | |||
2166 | int | ||
2167 | select_add (void *cls, | ||
2168 | struct GNUNET_SCHEDULER_Task *task, | ||
2169 | struct GNUNET_SCHEDULER_FdInfo *fdi) | ||
2170 | { | ||
2171 | struct DriverContext *context = cls; | ||
2172 | GNUNET_assert (NULL != context); | ||
2173 | GNUNET_assert (NULL != task); | ||
2174 | GNUNET_assert (NULL != fdi); | ||
2175 | GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) || | ||
2176 | 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)); | ||
2177 | |||
2178 | if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0)) | ||
2179 | { | ||
2180 | /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ | ||
2181 | return GNUNET_SYSERR; | ||
2182 | } | ||
2183 | |||
2184 | struct Scheduled *scheduled = GNUNET_new (struct Scheduled); | ||
2185 | scheduled->task = task; | ||
2186 | scheduled->fdi = fdi; | ||
2187 | scheduled->et = fdi->et; | ||
2188 | |||
2189 | GNUNET_CONTAINER_DLL_insert (context->scheduled_head, | ||
2190 | context->scheduled_tail, | ||
2191 | scheduled); | ||
2192 | return GNUNET_OK; | ||
2193 | } | 2267 | } |
2194 | 2268 | ||
2195 | 2269 | ||
2196 | int | 2270 | int |
2197 | select_del (void *cls, | 2271 | select_loop (struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context) |
2198 | struct GNUNET_SCHEDULER_Task *task) | ||
2199 | { | ||
2200 | struct DriverContext *context; | ||
2201 | struct Scheduled *pos; | ||
2202 | int ret; | ||
2203 | |||
2204 | GNUNET_assert (NULL != cls); | ||
2205 | |||
2206 | context = cls; | ||
2207 | ret = GNUNET_SYSERR; | ||
2208 | pos = context->scheduled_head; | ||
2209 | while (NULL != pos) | ||
2210 | { | ||
2211 | struct Scheduled *next = pos->next; | ||
2212 | if (pos->task == task) | ||
2213 | { | ||
2214 | GNUNET_CONTAINER_DLL_remove (context->scheduled_head, | ||
2215 | context->scheduled_tail, | ||
2216 | pos); | ||
2217 | GNUNET_free (pos); | ||
2218 | ret = GNUNET_OK; | ||
2219 | } | ||
2220 | pos = next; | ||
2221 | } | ||
2222 | return ret; | ||
2223 | } | ||
2224 | |||
2225 | |||
2226 | int | ||
2227 | select_loop (void *cls, | ||
2228 | struct GNUNET_SCHEDULER_Handle *sh) | ||
2229 | { | 2272 | { |
2230 | struct GNUNET_NETWORK_FDSet *rs; | 2273 | struct GNUNET_NETWORK_FDSet *rs; |
2231 | struct GNUNET_NETWORK_FDSet *ws; | 2274 | struct GNUNET_NETWORK_FDSet *ws; |
2232 | struct DriverContext *context; | ||
2233 | int select_result; | 2275 | int select_result; |
2234 | int tasks_ready; | ||
2235 | 2276 | ||
2236 | context = cls; | ||
2237 | GNUNET_assert (NULL != context); | 2277 | GNUNET_assert (NULL != context); |
2238 | rs = GNUNET_NETWORK_fdset_create (); | 2278 | rs = GNUNET_NETWORK_fdset_create (); |
2239 | ws = GNUNET_NETWORK_fdset_create (); | 2279 | ws = GNUNET_NETWORK_fdset_create (); |
2240 | tasks_ready = GNUNET_NO; | ||
2241 | while (NULL != context->scheduled_head || | 2280 | while (NULL != context->scheduled_head || |
2242 | GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != context->timeout.rel_value_us) | 2281 | GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != context->timeout.abs_value_us) |
2243 | { | 2282 | { |
2244 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2283 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2245 | "select timeout = %s\n", | 2284 | "select timeout = %s\n", |
2246 | GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO)); | 2285 | GNUNET_STRINGS_absolute_time_to_string (context->timeout)); |
2247 | 2286 | ||
2248 | GNUNET_NETWORK_fdset_zero (rs); | 2287 | GNUNET_NETWORK_fdset_zero (rs); |
2249 | GNUNET_NETWORK_fdset_zero (ws); | 2288 | GNUNET_NETWORK_fdset_zero (ws); |
@@ -2259,12 +2298,14 @@ select_loop (void *cls, | |||
2259 | GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); | 2298 | GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); |
2260 | } | 2299 | } |
2261 | } | 2300 | } |
2301 | struct GNUNET_TIME_Relative time_remaining = | ||
2302 | GNUNET_TIME_absolute_get_remaining (context->timeout); | ||
2262 | if (NULL == scheduler_select) | 2303 | if (NULL == scheduler_select) |
2263 | { | 2304 | { |
2264 | select_result = GNUNET_NETWORK_socket_select (rs, | 2305 | select_result = GNUNET_NETWORK_socket_select (rs, |
2265 | ws, | 2306 | ws, |
2266 | NULL, | 2307 | NULL, |
2267 | context->timeout); | 2308 | time_remaining); |
2268 | } | 2309 | } |
2269 | else | 2310 | else |
2270 | { | 2311 | { |
@@ -2272,7 +2313,7 @@ select_loop (void *cls, | |||
2272 | rs, | 2313 | rs, |
2273 | ws, | 2314 | ws, |
2274 | NULL, | 2315 | NULL, |
2275 | context->timeout); | 2316 | time_remaining); |
2276 | } | 2317 | } |
2277 | if (select_result == GNUNET_SYSERR) | 2318 | if (select_result == GNUNET_SYSERR) |
2278 | { | 2319 | { |
@@ -2333,8 +2374,11 @@ select_loop (void *cls, | |||
2333 | } | 2374 | } |
2334 | } | 2375 | } |
2335 | } | 2376 | } |
2336 | tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); | 2377 | if (GNUNET_YES == GNUNET_SCHEDULER_do_work (sh)) |
2337 | GNUNET_assert (GNUNET_SYSERR != tasks_ready); | 2378 | { |
2379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2380 | "scheduler has more tasks ready!\n"); | ||
2381 | } | ||
2338 | } | 2382 | } |
2339 | GNUNET_NETWORK_fdset_destroy (rs); | 2383 | GNUNET_NETWORK_fdset_destroy (rs); |
2340 | GNUNET_NETWORK_fdset_destroy (ws); | 2384 | GNUNET_NETWORK_fdset_destroy (ws); |
@@ -2342,14 +2386,74 @@ select_loop (void *cls, | |||
2342 | } | 2386 | } |
2343 | 2387 | ||
2344 | 2388 | ||
2389 | int | ||
2390 | select_add (void *cls, | ||
2391 | struct GNUNET_SCHEDULER_Task *task, | ||
2392 | struct GNUNET_SCHEDULER_FdInfo *fdi) | ||
2393 | { | ||
2394 | struct DriverContext *context = cls; | ||
2395 | GNUNET_assert (NULL != context); | ||
2396 | GNUNET_assert (NULL != task); | ||
2397 | GNUNET_assert (NULL != fdi); | ||
2398 | GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) || | ||
2399 | 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)); | ||
2400 | |||
2401 | if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0)) | ||
2402 | { | ||
2403 | /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ | ||
2404 | return GNUNET_SYSERR; | ||
2405 | } | ||
2406 | |||
2407 | struct Scheduled *scheduled = GNUNET_new (struct Scheduled); | ||
2408 | scheduled->task = task; | ||
2409 | scheduled->fdi = fdi; | ||
2410 | scheduled->et = fdi->et; | ||
2411 | |||
2412 | GNUNET_CONTAINER_DLL_insert (context->scheduled_head, | ||
2413 | context->scheduled_tail, | ||
2414 | scheduled); | ||
2415 | return GNUNET_OK; | ||
2416 | } | ||
2417 | |||
2418 | |||
2419 | int | ||
2420 | select_del (void *cls, | ||
2421 | struct GNUNET_SCHEDULER_Task *task) | ||
2422 | { | ||
2423 | struct DriverContext *context; | ||
2424 | struct Scheduled *pos; | ||
2425 | int ret; | ||
2426 | |||
2427 | GNUNET_assert (NULL != cls); | ||
2428 | |||
2429 | context = cls; | ||
2430 | ret = GNUNET_SYSERR; | ||
2431 | pos = context->scheduled_head; | ||
2432 | while (NULL != pos) | ||
2433 | { | ||
2434 | struct Scheduled *next = pos->next; | ||
2435 | if (pos->task == task) | ||
2436 | { | ||
2437 | GNUNET_CONTAINER_DLL_remove (context->scheduled_head, | ||
2438 | context->scheduled_tail, | ||
2439 | pos); | ||
2440 | GNUNET_free (pos); | ||
2441 | ret = GNUNET_OK; | ||
2442 | } | ||
2443 | pos = next; | ||
2444 | } | ||
2445 | return ret; | ||
2446 | } | ||
2447 | |||
2448 | |||
2345 | void | 2449 | void |
2346 | select_set_wakeup (void *cls, | 2450 | select_set_wakeup (void *cls, |
2347 | struct GNUNET_TIME_Absolute dt) | 2451 | struct GNUNET_TIME_Absolute dt) |
2348 | { | 2452 | { |
2349 | struct DriverContext *context = cls; | 2453 | struct DriverContext *context = cls; |
2454 | |||
2350 | GNUNET_assert (NULL != context); | 2455 | GNUNET_assert (NULL != context); |
2351 | 2456 | context->timeout = dt; | |
2352 | context->timeout = GNUNET_TIME_absolute_get_remaining (dt); | ||
2353 | } | 2457 | } |
2354 | 2458 | ||
2355 | 2459 | ||
@@ -2364,7 +2468,6 @@ GNUNET_SCHEDULER_driver_select () | |||
2364 | struct GNUNET_SCHEDULER_Driver *select_driver; | 2468 | struct GNUNET_SCHEDULER_Driver *select_driver; |
2365 | select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver); | 2469 | select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver); |
2366 | 2470 | ||
2367 | select_driver->loop = &select_loop; | ||
2368 | select_driver->add = &select_add; | 2471 | select_driver->add = &select_add; |
2369 | select_driver->del = &select_del; | 2472 | select_driver->del = &select_del; |
2370 | select_driver->set_wakeup = &select_set_wakeup; | 2473 | select_driver->set_wakeup = &select_set_wakeup; |