diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-05-03 09:24:06 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-05-03 09:24:06 +0000 |
commit | 3fa11d0813d624a080039bb65786100ae626f854 (patch) | |
tree | 0c909d65e60bf35d57e1647d4f1df1ddd379549e /src/peerinfo | |
parent | 115e8f7ff84e503ce97ea1f985c1474c866eb6d4 (diff) | |
download | gnunet-3fa11d0813d624a080039bb65786100ae626f854.tar.gz gnunet-3fa11d0813d624a080039bb65786100ae626f854.zip |
-fixing #2298
Diffstat (limited to 'src/peerinfo')
-rw-r--r-- | src/peerinfo/peerinfo_api.c | 319 |
1 files changed, 182 insertions, 137 deletions
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c index 5eb58af44..4564df727 100644 --- a/src/peerinfo/peerinfo_api.c +++ b/src/peerinfo/peerinfo_api.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 Christian Grothoff (and other contributing authors) | 3 | (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010, 2012 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -31,7 +31,7 @@ | |||
31 | #include "gnunet_time_lib.h" | 31 | #include "gnunet_time_lib.h" |
32 | #include "peerinfo.h" | 32 | #include "peerinfo.h" |
33 | 33 | ||
34 | #define LOG(kind,...) GNUNET_log_from (kind, "nse-api",__VA_ARGS__) | 34 | #define LOG(kind,...) GNUNET_log_from (kind, "peerinfo-api",__VA_ARGS__) |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * Function to call after transmission has succeeded. | 37 | * Function to call after transmission has succeeded. |
@@ -69,15 +69,63 @@ struct TransmissionQueueEntry | |||
69 | void *cont_cls; | 69 | void *cont_cls; |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * Number of bytes of the request message (follows after this struct). | ||
73 | */ | ||
74 | size_t size; | ||
75 | |||
76 | }; | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Context for an iteration request. | ||
81 | */ | ||
82 | struct GNUNET_PEERINFO_IteratorContext | ||
83 | { | ||
84 | |||
85 | /** | ||
86 | * Kept in a DLL. | ||
87 | */ | ||
88 | struct GNUNET_PEERINFO_IteratorContext *next; | ||
89 | |||
90 | /** | ||
91 | * Kept in a DLL. | ||
92 | */ | ||
93 | struct GNUNET_PEERINFO_IteratorContext *prev; | ||
94 | |||
95 | /** | ||
96 | * Handle to the PEERINFO service. | ||
97 | */ | ||
98 | struct GNUNET_PEERINFO_Handle *h; | ||
99 | |||
100 | /** | ||
101 | * Function to call with the results. | ||
102 | */ | ||
103 | GNUNET_PEERINFO_Processor callback; | ||
104 | |||
105 | /** | ||
106 | * Closure for 'callback'. | ||
107 | */ | ||
108 | void *callback_cls; | ||
109 | |||
110 | /** | ||
111 | * Our entry in the transmission queue. | ||
112 | */ | ||
113 | struct TransmissionQueueEntry *tqe; | ||
114 | |||
115 | /** | ||
116 | * Task responsible for timeout. | ||
117 | */ | ||
118 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
119 | |||
120 | /** | ||
72 | * Timeout for the operation. | 121 | * Timeout for the operation. |
73 | */ | 122 | */ |
74 | struct GNUNET_TIME_Absolute timeout; | 123 | struct GNUNET_TIME_Absolute timeout; |
75 | 124 | ||
76 | /** | 125 | /** |
77 | * Number of bytes of the request message (follows after this struct). | 126 | * Are we now receiving? |
78 | */ | 127 | */ |
79 | size_t size; | 128 | int in_receive; |
80 | |||
81 | }; | 129 | }; |
82 | 130 | ||
83 | 131 | ||
@@ -112,6 +160,16 @@ struct GNUNET_PEERINFO_Handle | |||
112 | struct GNUNET_CLIENT_TransmitHandle *th; | 160 | struct GNUNET_CLIENT_TransmitHandle *th; |
113 | 161 | ||
114 | /** | 162 | /** |
163 | * Head of iterator DLL. | ||
164 | */ | ||
165 | struct GNUNET_PEERINFO_IteratorContext *ic_head; | ||
166 | |||
167 | /** | ||
168 | * Tail of iterator DLL. | ||
169 | */ | ||
170 | struct GNUNET_PEERINFO_IteratorContext *ic_tail; | ||
171 | |||
172 | /** | ||
115 | * ID for a reconnect task. | 173 | * ID for a reconnect task. |
116 | */ | 174 | */ |
117 | GNUNET_SCHEDULER_TaskIdentifier r_task; | 175 | GNUNET_SCHEDULER_TaskIdentifier r_task; |
@@ -135,12 +193,12 @@ struct GNUNET_PEERINFO_Handle | |||
135 | struct GNUNET_PEERINFO_Handle * | 193 | struct GNUNET_PEERINFO_Handle * |
136 | GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | 194 | GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) |
137 | { | 195 | { |
138 | struct GNUNET_PEERINFO_Handle *ret; | 196 | struct GNUNET_PEERINFO_Handle *h; |
139 | 197 | ||
140 | ret = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle)); | 198 | h = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle)); |
141 | ret->client = GNUNET_CLIENT_connect ("peerinfo", cfg); | 199 | h->client = GNUNET_CLIENT_connect ("peerinfo", cfg); |
142 | ret->cfg = cfg; | 200 | h->cfg = cfg; |
143 | return ret; | 201 | return h; |
144 | } | 202 | } |
145 | 203 | ||
146 | 204 | ||
@@ -157,7 +215,14 @@ void | |||
157 | GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h) | 215 | GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h) |
158 | { | 216 | { |
159 | struct TransmissionQueueEntry *tqe; | 217 | struct TransmissionQueueEntry *tqe; |
218 | struct GNUNET_PEERINFO_IteratorContext *ic; | ||
160 | 219 | ||
220 | while (NULL != (ic = h->ic_head)) | ||
221 | { | ||
222 | GNUNET_break (GNUNET_YES == ic->in_receive); | ||
223 | ic->in_receive = GNUNET_NO; | ||
224 | GNUNET_PEERINFO_iterate_cancel (ic); | ||
225 | } | ||
161 | while (NULL != (tqe = h->tq_head)) | 226 | while (NULL != (tqe = h->tq_head)) |
162 | { | 227 | { |
163 | GNUNET_CONTAINER_DLL_remove (h->tq_head, h->tq_tail, tqe); | 228 | GNUNET_CONTAINER_DLL_remove (h->tq_head, h->tq_tail, tqe); |
@@ -165,7 +230,7 @@ GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h) | |||
165 | tqe->cont (tqe->cont_cls, GNUNET_SYSERR); | 230 | tqe->cont (tqe->cont_cls, GNUNET_SYSERR); |
166 | GNUNET_free (tqe); | 231 | GNUNET_free (tqe); |
167 | } | 232 | } |
168 | if (h->th != NULL) | 233 | if (NULL != h->th) |
169 | { | 234 | { |
170 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | 235 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); |
171 | h->th = NULL; | 236 | h->th = NULL; |
@@ -202,6 +267,7 @@ trigger_transmit (struct GNUNET_PEERINFO_Handle *h); | |||
202 | static void | 267 | static void |
203 | reconnect (struct GNUNET_PEERINFO_Handle *h); | 268 | reconnect (struct GNUNET_PEERINFO_Handle *h); |
204 | 269 | ||
270 | |||
205 | /** | 271 | /** |
206 | * Task scheduled to re-try connecting to the peerinfo service. | 272 | * Task scheduled to re-try connecting to the peerinfo service. |
207 | * | 273 | * |
@@ -226,7 +292,7 @@ reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
226 | static void | 292 | static void |
227 | reconnect (struct GNUNET_PEERINFO_Handle *h) | 293 | reconnect (struct GNUNET_PEERINFO_Handle *h) |
228 | { | 294 | { |
229 | if (h->r_task != GNUNET_SCHEDULER_NO_TASK) | 295 | if (GNUNET_SCHEDULER_NO_TASK != h->r_task) |
230 | { | 296 | { |
231 | GNUNET_SCHEDULER_cancel (h->r_task); | 297 | GNUNET_SCHEDULER_cancel (h->r_task); |
232 | h->r_task = GNUNET_SCHEDULER_NO_TASK; | 298 | h->r_task = GNUNET_SCHEDULER_NO_TASK; |
@@ -241,6 +307,7 @@ reconnect (struct GNUNET_PEERINFO_Handle *h) | |||
241 | GNUNET_CLIENT_disconnect (h->client); | 307 | GNUNET_CLIENT_disconnect (h->client); |
242 | h->client = NULL; | 308 | h->client = NULL; |
243 | } | 309 | } |
310 | h->in_receive = GNUNET_NO; | ||
244 | h->client = GNUNET_CLIENT_connect ("peerinfo", h->cfg); | 311 | h->client = GNUNET_CLIENT_connect ("peerinfo", h->cfg); |
245 | if (NULL == h->client) | 312 | if (NULL == h->client) |
246 | { | 313 | { |
@@ -270,26 +337,32 @@ do_transmit (void *cls, size_t size, void *buf) | |||
270 | size_t ret; | 337 | size_t ret; |
271 | 338 | ||
272 | h->th = NULL; | 339 | h->th = NULL; |
273 | if (tqe == NULL) | 340 | if (NULL == tqe) |
274 | return 0; | 341 | return 0; /* request was cancelled in the meantime */ |
275 | if (buf == NULL) | 342 | if (NULL == buf) |
276 | { | 343 | { |
344 | /* peerinfo service died */ | ||
277 | LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | 345 | LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, |
278 | _("Failed to transmit message to `%s' service.\n"), "PEERINFO"); | 346 | "Failed to transmit message to `%s' service.\n", "PEERINFO"); |
279 | GNUNET_CONTAINER_DLL_remove (h->tq_head, h->tq_tail, tqe); | 347 | GNUNET_CONTAINER_DLL_remove (h->tq_head, h->tq_tail, tqe); |
280 | reconnect (h); | 348 | reconnect (h); |
281 | if (tqe->cont != NULL) | 349 | if (NULL != tqe->cont) |
282 | tqe->cont (tqe->cont_cls, GNUNET_SYSERR); | 350 | tqe->cont (tqe->cont_cls, GNUNET_SYSERR); |
283 | GNUNET_free (tqe); | 351 | GNUNET_free (tqe); |
284 | return 0; | 352 | return 0; |
285 | } | 353 | } |
286 | ret = tqe->size; | 354 | ret = tqe->size; |
287 | GNUNET_assert (size >= ret); | 355 | if (size < ret) |
288 | memcpy (buf, &tqe[1], ret); | 356 | { |
357 | /* change in head of queue (i.e. cancel + add), try again */ | ||
358 | trigger_transmit (h); | ||
359 | return 0; | ||
360 | } | ||
289 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 361 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
290 | "Transmitting request of size %u to `%s' service.\n", ret, "PEERINFO"); | 362 | "Transmitting request of size %u to `%s' service.\n", ret, "PEERINFO"); |
363 | memcpy (buf, &tqe[1], ret); | ||
291 | GNUNET_CONTAINER_DLL_remove (h->tq_head, h->tq_tail, tqe); | 364 | GNUNET_CONTAINER_DLL_remove (h->tq_head, h->tq_tail, tqe); |
292 | if (tqe->cont != NULL) | 365 | if (NULL != tqe->cont) |
293 | tqe->cont (tqe->cont_cls, GNUNET_OK); | 366 | tqe->cont (tqe->cont_cls, GNUNET_OK); |
294 | else | 367 | else |
295 | trigger_transmit (h); | 368 | trigger_transmit (h); |
@@ -310,21 +383,22 @@ trigger_transmit (struct GNUNET_PEERINFO_Handle *h) | |||
310 | struct TransmissionQueueEntry *tqe; | 383 | struct TransmissionQueueEntry *tqe; |
311 | 384 | ||
312 | if (NULL == (tqe = h->tq_head)) | 385 | if (NULL == (tqe = h->tq_head)) |
313 | return; | 386 | return; /* no requests queued */ |
314 | if (h->th != NULL) | 387 | if (NULL != h->th) |
315 | return; | 388 | return; /* request already pending */ |
316 | if (h->in_receive == GNUNET_YES) | 389 | if (GNUNET_YES == h->in_receive) |
317 | return; | 390 | return; /* still reading replies from last request */ |
318 | if (NULL == h->client) | 391 | if (NULL == h->client) |
319 | { | 392 | { |
393 | /* disconnected, try to reconnect */ | ||
320 | reconnect (h); | 394 | reconnect (h); |
321 | return; | 395 | return; |
322 | } | 396 | } |
323 | h->th = | 397 | h->th = |
324 | GNUNET_CLIENT_notify_transmit_ready (h->client, tqe->size, | 398 | GNUNET_CLIENT_notify_transmit_ready (h->client, tqe->size, |
325 | GNUNET_TIME_absolute_get_remaining | 399 | GNUNET_TIME_UNIT_FOREVER_REL, |
326 | (tqe->timeout), GNUNET_YES, | 400 | GNUNET_YES, |
327 | &do_transmit, h); | 401 | &do_transmit, h); |
328 | } | 402 | } |
329 | 403 | ||
330 | 404 | ||
@@ -353,7 +427,6 @@ GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h, | |||
353 | GNUNET_i2s (&peer), hs, "HELLO"); | 427 | GNUNET_i2s (&peer), hs, "HELLO"); |
354 | tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) + hs); | 428 | tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) + hs); |
355 | tqe->size = hs; | 429 | tqe->size = hs; |
356 | tqe->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
357 | memcpy (&tqe[1], hello, hs); | 430 | memcpy (&tqe[1], hello, hs); |
358 | GNUNET_CONTAINER_DLL_insert_after (h->tq_head, h->tq_tail, h->tq_tail, tqe); | 431 | GNUNET_CONTAINER_DLL_insert_after (h->tq_head, h->tq_tail, h->tq_tail, tqe); |
359 | trigger_transmit (h); | 432 | trigger_transmit (h); |
@@ -361,50 +434,10 @@ GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h, | |||
361 | 434 | ||
362 | 435 | ||
363 | /** | 436 | /** |
364 | * Context for an iteration request. | 437 | * Type of a function to call when we receive a message from the |
365 | */ | 438 | * service. Call the iterator with the result and (if applicable) |
366 | struct GNUNET_PEERINFO_IteratorContext | 439 | * continue to receive more messages or trigger processing the next |
367 | { | 440 | * event (if applicable). |
368 | /** | ||
369 | * Handle to the PEERINFO service. | ||
370 | */ | ||
371 | struct GNUNET_PEERINFO_Handle *h; | ||
372 | |||
373 | /** | ||
374 | * Function to call with the results. | ||
375 | */ | ||
376 | GNUNET_PEERINFO_Processor callback; | ||
377 | |||
378 | /** | ||
379 | * Closure for 'callback'. | ||
380 | */ | ||
381 | void *callback_cls; | ||
382 | |||
383 | /** | ||
384 | * Our entry in the transmission queue. | ||
385 | */ | ||
386 | struct TransmissionQueueEntry *tqe; | ||
387 | |||
388 | /** | ||
389 | * Task responsible for timeout. | ||
390 | */ | ||
391 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
392 | |||
393 | /** | ||
394 | * Timeout for the operation. | ||
395 | */ | ||
396 | struct GNUNET_TIME_Absolute timeout; | ||
397 | |||
398 | /** | ||
399 | * Are we now receiving? | ||
400 | */ | ||
401 | int in_receive; | ||
402 | }; | ||
403 | |||
404 | |||
405 | /** | ||
406 | * Type of a function to call when we receive a message | ||
407 | * from the service. | ||
408 | * | 441 | * |
409 | * @param cls closure | 442 | * @param cls closure |
410 | * @param msg message received, NULL on timeout or fatal error | 443 | * @param msg message received, NULL on timeout or fatal error |
@@ -413,46 +446,49 @@ static void | |||
413 | peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) | 446 | peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) |
414 | { | 447 | { |
415 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; | 448 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; |
449 | struct GNUNET_PEERINFO_Handle *h = ic->h; | ||
416 | const struct InfoMessage *im; | 450 | const struct InfoMessage *im; |
417 | const struct GNUNET_HELLO_Message *hello; | 451 | const struct GNUNET_HELLO_Message *hello; |
452 | GNUNET_PEERINFO_Processor cb; | ||
453 | void *cb_cls; | ||
418 | uint16_t ms; | 454 | uint16_t ms; |
419 | 455 | ||
420 | ic->h->in_receive = GNUNET_NO; | 456 | h->in_receive = GNUNET_NO; |
421 | if (msg == NULL) | 457 | ic->in_receive = GNUNET_NO; |
458 | cb = ic->callback; | ||
459 | cb_cls = ic->callback_cls; | ||
460 | if (NULL == msg) | ||
422 | { | 461 | { |
423 | reconnect (ic->h); | 462 | /* peerinfo service died, signal error */ |
424 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 463 | GNUNET_PEERINFO_iterate_cancel (ic); |
425 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 464 | reconnect (h); |
426 | if (ic->callback != NULL) | 465 | if (NULL != cb) |
427 | ic->callback (ic->callback_cls, NULL, NULL, | 466 | cb (cb_cls, NULL, NULL, |
428 | _("Failed to receive response from `PEERINFO' service.")); | 467 | _("Failed to receive response from `PEERINFO' service.")); |
429 | GNUNET_free (ic); | ||
430 | return; | 468 | return; |
431 | } | 469 | } |
432 | if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END) | 470 | if (GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END == ntohs (msg->type)) |
433 | { | 471 | { |
472 | /* normal end of list of peers, signal end, process next pending request */ | ||
434 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 473 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
435 | "Received end of list of peers from `%s' service\n", "PEERINFO"); | 474 | "Received end of list of peers from `%s' service\n", "PEERINFO"); |
436 | trigger_transmit (ic->h); | 475 | GNUNET_PEERINFO_iterate_cancel (ic); |
437 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 476 | trigger_transmit (h); |
438 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 477 | if (NULL != cb) |
439 | if (ic->callback != NULL) | 478 | cb (cb_cls, NULL, NULL, NULL); |
440 | ic->callback (ic->callback_cls, NULL, NULL, NULL); | ||
441 | GNUNET_free (ic); | ||
442 | return; | 479 | return; |
443 | } | 480 | } |
444 | ms = ntohs (msg->size); | 481 | ms = ntohs (msg->size); |
445 | if ((ms < sizeof (struct InfoMessage)) || | 482 | if ((ms < sizeof (struct InfoMessage)) || |
446 | (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO)) | 483 | (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO)) |
447 | { | 484 | { |
485 | /* malformed message */ | ||
448 | GNUNET_break (0); | 486 | GNUNET_break (0); |
449 | reconnect (ic->h); | 487 | GNUNET_PEERINFO_iterate_cancel (ic); |
450 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 488 | reconnect (h); |
451 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 489 | if (NULL != cb) |
452 | if (ic->callback != NULL) | 490 | cb (cb_cls, NULL, NULL, |
453 | ic->callback (ic->callback_cls, NULL, NULL, | 491 | _("Received invalid message from `PEERINFO' service.")); |
454 | _("Received invalid message from `PEERINFO' service.")); | ||
455 | GNUNET_free (ic); | ||
456 | return; | 492 | return; |
457 | } | 493 | } |
458 | im = (const struct InfoMessage *) msg; | 494 | im = (const struct InfoMessage *) msg; |
@@ -463,26 +499,27 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) | |||
463 | hello = (const struct GNUNET_HELLO_Message *) &im[1]; | 499 | hello = (const struct GNUNET_HELLO_Message *) &im[1]; |
464 | if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello)) | 500 | if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello)) |
465 | { | 501 | { |
502 | /* malformed message */ | ||
466 | GNUNET_break (0); | 503 | GNUNET_break (0); |
467 | reconnect (ic->h); | 504 | GNUNET_PEERINFO_iterate_cancel (ic); |
468 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 505 | reconnect (h); |
469 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 506 | if (NULL != cb) |
470 | if (ic->callback != NULL) | 507 | cb (cb_cls, NULL, NULL, |
471 | ic->callback (ic->callback_cls, NULL, NULL, | 508 | _("Received invalid message from `PEERINFO' service.")); |
472 | _("Received invalid message from `PEERINFO' service.")); | ||
473 | GNUNET_free (ic); | ||
474 | return; | 509 | return; |
475 | } | 510 | } |
476 | } | 511 | } |
512 | /* normal data message */ | ||
477 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 513 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
478 | "Received %u bytes of `%s' information about peer `%s' from `%s' service\n", | 514 | "Received %u bytes of `%s' information about peer `%s' from `%s' service\n", |
479 | (hello == NULL) ? 0 : (unsigned int) GNUNET_HELLO_size (hello), "HELLO", | 515 | (hello == NULL) ? 0 : (unsigned int) GNUNET_HELLO_size (hello), "HELLO", |
480 | GNUNET_i2s (&im->peer), "PEERINFO"); | 516 | GNUNET_i2s (&im->peer), "PEERINFO"); |
481 | ic->h->in_receive = GNUNET_YES; | 517 | h->in_receive = GNUNET_YES; |
482 | if (ic->callback != NULL) | 518 | ic->in_receive = GNUNET_YES; |
483 | ic->callback (ic->callback_cls, &im->peer, hello, NULL); | 519 | GNUNET_CLIENT_receive (h->client, &peerinfo_handler, ic, |
484 | GNUNET_CLIENT_receive (ic->h->client, &peerinfo_handler, ic, | ||
485 | GNUNET_TIME_absolute_get_remaining (ic->timeout)); | 520 | GNUNET_TIME_absolute_get_remaining (ic->timeout)); |
521 | if (NULL != cb) | ||
522 | cb (cb_cls, &im->peer, hello, NULL); | ||
486 | } | 523 | } |
487 | 524 | ||
488 | 525 | ||
@@ -497,28 +534,27 @@ static void | |||
497 | iterator_start_receive (void *cls, int transmit_success) | 534 | iterator_start_receive (void *cls, int transmit_success) |
498 | { | 535 | { |
499 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; | 536 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; |
537 | struct GNUNET_PEERINFO_Handle *h = ic->h; | ||
538 | GNUNET_PEERINFO_Processor cb; | ||
539 | void *cb_cls; | ||
500 | 540 | ||
541 | ic->tqe = NULL; | ||
501 | if (GNUNET_OK != transmit_success) | 542 | if (GNUNET_OK != transmit_success) |
502 | { | 543 | { |
503 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 544 | cb = ic->callback; |
504 | { | 545 | cb_cls = ic->callback_cls; |
505 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 546 | GNUNET_PEERINFO_iterate_cancel (ic); |
506 | ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 547 | reconnect (h); |
507 | } | 548 | if (NULL != cb) |
508 | reconnect (ic->h); | 549 | cb (cb_cls, NULL, NULL, |
509 | if (ic->callback != NULL) | 550 | _("Failed to transmit iteration request to `PEERINFO' service")); |
510 | ic->callback (ic->callback_cls, NULL, NULL, | ||
511 | _ | ||
512 | ("Failed to transmit iteration request to `PEERINFO' service")); | ||
513 | GNUNET_free (ic); | ||
514 | return; | 551 | return; |
515 | } | 552 | } |
516 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for response from `%s' service.\n", | 553 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for response from `%s' service.\n", |
517 | "PEERINFO"); | 554 | "PEERINFO"); |
518 | ic->h->in_receive = GNUNET_YES; | 555 | h->in_receive = GNUNET_YES; |
519 | ic->in_receive = GNUNET_YES; | 556 | ic->in_receive = GNUNET_YES; |
520 | ic->tqe = NULL; | 557 | GNUNET_CLIENT_receive (h->client, &peerinfo_handler, ic, |
521 | GNUNET_CLIENT_receive (ic->h->client, &peerinfo_handler, ic, | ||
522 | GNUNET_TIME_absolute_get_remaining (ic->timeout)); | 558 | GNUNET_TIME_absolute_get_remaining (ic->timeout)); |
523 | } | 559 | } |
524 | 560 | ||
@@ -533,18 +569,16 @@ static void | |||
533 | signal_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 569 | signal_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
534 | { | 570 | { |
535 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; | 571 | struct GNUNET_PEERINFO_IteratorContext *ic = cls; |
572 | GNUNET_PEERINFO_Processor cb; | ||
573 | void *cb_cls; | ||
536 | 574 | ||
537 | ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 575 | ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
538 | if (!ic->in_receive) | 576 | cb = ic->callback; |
539 | GNUNET_CONTAINER_DLL_remove (ic->h->tq_head, ic->h->tq_tail, ic->tqe); | 577 | cb_cls = ic->callback_cls; |
540 | else | 578 | GNUNET_PEERINFO_iterate_cancel (ic); |
541 | reconnect (ic->h); | 579 | if (NULL != cb) |
542 | ic->callback (ic->callback_cls, NULL, NULL, | 580 | cb (cb_cls, NULL, NULL, |
543 | _ | 581 | _("Timeout transmitting iteration request to `PEERINFO' service.")); |
544 | ("Timeout transmitting iteration request to `PEERINFO' service.")); | ||
545 | ic->callback = NULL; | ||
546 | GNUNET_free_non_null (ic->tqe); | ||
547 | GNUNET_free (ic); | ||
548 | } | 582 | } |
549 | 583 | ||
550 | 584 | ||
@@ -575,7 +609,7 @@ GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, | |||
575 | struct GNUNET_PEERINFO_IteratorContext *ic; | 609 | struct GNUNET_PEERINFO_IteratorContext *ic; |
576 | struct TransmissionQueueEntry *tqe; | 610 | struct TransmissionQueueEntry *tqe; |
577 | 611 | ||
578 | if (peer == NULL) | 612 | if (NULL == peer) |
579 | { | 613 | { |
580 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 614 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
581 | "Requesting list of peers from PEERINFO service\n"); | 615 | "Requesting list of peers from PEERINFO service\n"); |
@@ -609,10 +643,12 @@ GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, | |||
609 | ic->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 643 | ic->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
610 | ic->timeout_task = | 644 | ic->timeout_task = |
611 | GNUNET_SCHEDULER_add_delayed (timeout, &signal_timeout, ic); | 645 | GNUNET_SCHEDULER_add_delayed (timeout, &signal_timeout, ic); |
612 | tqe->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
613 | tqe->cont = &iterator_start_receive; | 646 | tqe->cont = &iterator_start_receive; |
614 | tqe->cont_cls = ic; | 647 | tqe->cont_cls = ic; |
615 | GNUNET_CONTAINER_DLL_insert_after (h->tq_head, h->tq_tail, h->tq_tail, tqe); | 648 | GNUNET_CONTAINER_DLL_insert_after (h->tq_head, h->tq_tail, h->tq_tail, tqe); |
649 | GNUNET_CONTAINER_DLL_insert (h->ic_head, | ||
650 | h->ic_tail, | ||
651 | ic); | ||
616 | trigger_transmit (h); | 652 | trigger_transmit (h); |
617 | return ic; | 653 | return ic; |
618 | } | 654 | } |
@@ -626,7 +662,13 @@ GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, | |||
626 | void | 662 | void |
627 | GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic) | 663 | GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic) |
628 | { | 664 | { |
629 | if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK) | 665 | struct GNUNET_PEERINFO_Handle *h; |
666 | |||
667 | h = ic->h; | ||
668 | GNUNET_CONTAINER_DLL_remove (h->ic_head, | ||
669 | h->ic_tail, | ||
670 | ic); | ||
671 | if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task) | ||
630 | { | 672 | { |
631 | GNUNET_SCHEDULER_cancel (ic->timeout_task); | 673 | GNUNET_SCHEDULER_cancel (ic->timeout_task); |
632 | ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 674 | ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
@@ -634,8 +676,11 @@ GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic) | |||
634 | ic->callback = NULL; | 676 | ic->callback = NULL; |
635 | if (GNUNET_YES == ic->in_receive) | 677 | if (GNUNET_YES == ic->in_receive) |
636 | return; /* need to finish processing */ | 678 | return; /* need to finish processing */ |
637 | GNUNET_CONTAINER_DLL_remove (ic->h->tq_head, ic->h->tq_tail, ic->tqe); | 679 | if (NULL != ic->tqe) |
638 | GNUNET_free (ic->tqe); | 680 | { |
681 | GNUNET_CONTAINER_DLL_remove (h->tq_head, h->tq_tail, ic->tqe); | ||
682 | GNUNET_free (ic->tqe); | ||
683 | } | ||
639 | GNUNET_free (ic); | 684 | GNUNET_free (ic); |
640 | } | 685 | } |
641 | 686 | ||