aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhil <phil.buschmann@tum.de>2018-02-26 17:02:29 +0100
committerPhil <phil.buschmann@tum.de>2018-02-26 17:02:29 +0100
commit699ff34b7203eb99d7ff1a45ff6b8309676c1102 (patch)
tree43ac45b55e3de8aa96d5ea53727154dcc3fbc594 /src
parent2363773d8a81d253614fa3892cead6ebab69c246 (diff)
parent56a9d4001b0844287ecc55b103549370676646a8 (diff)
downloadgnunet-699ff34b7203eb99d7ff1a45ff6b8309676c1102.tar.gz
gnunet-699ff34b7203eb99d7ff1a45ff6b8309676c1102.zip
-Merge branch 'master' into identity_oidc
Diffstat (limited to 'src')
-rw-r--r--src/consensus/gnunet-service-consensus.c2
-rw-r--r--src/datastore/plugin_datastore_sqlite.c13
-rw-r--r--src/exit/gnunet-daemon-exit.c4
-rw-r--r--src/gns/Makefile.am2
-rw-r--r--src/gns/gnunet-service-gns.c133
-rw-r--r--src/gns/gnunet-service-gns.h41
-rw-r--r--src/gns/gnunet-service-gns_interceptor.c4
-rw-r--r--src/gns/gnunet-service-gns_resolver.c7
-rw-r--r--src/include/gnunet_scheduler_lib.h196
-rw-r--r--src/multicast/gnunet-service-multicast.c26
-rw-r--r--src/psyc/gnunet-service-psyc.c22
-rw-r--r--src/rps/gnunet-service-rps.c28
-rw-r--r--src/rps/rps-test_util.h2
-rw-r--r--src/rps/test_rps.c104
-rw-r--r--src/social/gnunet-service-social.c31
-rw-r--r--src/util/mq.c4
-rw-r--r--src/util/scheduler.c491
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 */
3381static void 3381static void
3382read_service_conf (void *cls, 3382read_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 = \
185w32nsp_resolve_LDADD = -lws2_32 185w32nsp_resolve_LDADD = -lws2_32
186 186
187gnunet_service_gns_SOURCES = \ 187gnunet_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
191gnunet_service_gns_LDADD = \ 191gnunet_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 */
107struct 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 */
106static struct GNUNET_DHT_Handle *dht_handle; 138static struct GNUNET_DHT_Handle *dht_handle;
@@ -136,6 +168,50 @@ static int v4_enabled;
136 */ 168 */
137static struct GNUNET_STATISTICS_Handle *statistics; 169static struct GNUNET_STATISTICS_Handle *statistics;
138 170
171/**
172 * Head of DLL of TLDs we map to GNS zones.
173 */
174static struct GNS_TopLevelDomain *tld_head;
175
176/**
177 * Tail of DLL of TLDs we map to GNS zones.
178 */
179static 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 */
189int
190GNS_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;
146static void 222static void
147shutdown_task (void *cls) 223shutdown_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 */
515static void
516read_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 */
37int
38GNS_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 */
2257static void 2257static void
2258start_resolver_lookup (void *cls) 2258start_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 */
2600int 2600int
2601is_tld (const char* name, const char* tld) 2601is_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 */
256int 259int
257GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh); 260GNUNET_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 */
264struct GNUNET_SCHEDULER_Driver 267struct 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 */
359int 360struct GNUNET_SCHEDULER_Handle *
360GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, 361GNUNET_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 */
378void
379GNUNET_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 */
470void * 492void *
471GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task); 493GNUNET_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 */
737struct GNUNET_SCHEDULER_Task * 791struct GNUNET_SCHEDULER_Task *
738GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, 792GNUNET_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 */
816struct GNUNET_SCHEDULER_Task * 888struct GNUNET_SCHEDULER_Task *
817GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, 889GNUNET_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
1975check_client_replay_response (void *cls, 1989check_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
258enum STAT_TYPE 263enum 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 */
1753static 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
1766static void
1767store_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 */
77struct GNUNET_SCHEDULER_Handle 79struct 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 */
381static void *scheduler_select_cls; 417static void *scheduler_select_cls;
382 418
383/**
384 * Scheduler handle used for the driver functions
385 */
386static 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
691int
692select_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
675GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, 710GNUNET_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 */
1905int 1973int
1906GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) 1974GNUNET_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 */
2057int 2158struct GNUNET_SCHEDULER_Handle *
2058GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, 2159GNUNET_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 */
2240void 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
2166int
2167select_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
2196int 2270int
2197select_del (void *cls, 2271select_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
2226int
2227select_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
2389int
2390select_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
2419int
2420select_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
2345void 2449void
2346select_set_wakeup (void *cls, 2450select_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;