diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-05-08 19:17:03 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-05-08 19:17:03 +0000 |
commit | 6623d76dcb3659204935e462a8d0d415c7748a99 (patch) | |
tree | 9d89e4f33b7c60bbd08d2ed85a7d439b963044e6 /src/util/helper.c | |
parent | 31adadd3c4ca45d147392d6fa5ee839be1037740 (diff) | |
download | gnunet-6623d76dcb3659204935e462a8d0d415c7748a99.tar.gz gnunet-6623d76dcb3659204935e462a8d0d415c7748a99.zip |
-allow helper send to be cancelled
Diffstat (limited to 'src/util/helper.c')
-rw-r--r-- | src/util/helper.c | 135 |
1 files changed, 84 insertions, 51 deletions
diff --git a/src/util/helper.c b/src/util/helper.c index 9cf39bbfd..146a2e20d 100644 --- a/src/util/helper.c +++ b/src/util/helper.c | |||
@@ -31,24 +31,29 @@ | |||
31 | /** | 31 | /** |
32 | * Entry in the queue of messages we need to transmit to the helper. | 32 | * Entry in the queue of messages we need to transmit to the helper. |
33 | */ | 33 | */ |
34 | struct HelperMessageQueueEntry | 34 | struct GNUNET_HELPER_SendHandle |
35 | { | 35 | { |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * This is an entry in a DLL. | 38 | * This is an entry in a DLL. |
39 | */ | 39 | */ |
40 | struct HelperMessageQueueEntry *next; | 40 | struct GNUNET_HELPER_SendHandle *next; |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * This is an entry in a DLL. | 43 | * This is an entry in a DLL. |
44 | */ | 44 | */ |
45 | struct HelperMessageQueueEntry *prev; | 45 | struct GNUNET_HELPER_SendHandle *prev; |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * Message to transmit (allocated at the end of this struct) | 48 | * Message to transmit (allocated at the end of this struct) |
49 | */ | 49 | */ |
50 | const struct GNUNET_MessageHeader *msg; | 50 | const struct GNUNET_MessageHeader *msg; |
51 | 51 | ||
52 | /** | ||
53 | * The handle to a helper process. | ||
54 | */ | ||
55 | struct GNUNET_HELPER_Handle *h; | ||
56 | |||
52 | /** | 57 | /** |
53 | * Function to call upon completion. | 58 | * Function to call upon completion. |
54 | */ | 59 | */ |
@@ -106,12 +111,12 @@ struct GNUNET_HELPER_Handle | |||
106 | /** | 111 | /** |
107 | * First message queued for transmission to helper. | 112 | * First message queued for transmission to helper. |
108 | */ | 113 | */ |
109 | struct HelperMessageQueueEntry *mq_head; | 114 | struct GNUNET_HELPER_SendHandle *sh_head; |
110 | 115 | ||
111 | /** | 116 | /** |
112 | * Last message queued for transmission to helper. | 117 | * Last message queued for transmission to helper. |
113 | */ | 118 | */ |
114 | struct HelperMessageQueueEntry *mq_tail; | 119 | struct GNUNET_HELPER_SendHandle *sh_tail; |
115 | 120 | ||
116 | /** | 121 | /** |
117 | * Binary to run. | 122 | * Binary to run. |
@@ -148,7 +153,7 @@ struct GNUNET_HELPER_Handle | |||
148 | static void | 153 | static void |
149 | stop_helper (struct GNUNET_HELPER_Handle *h) | 154 | stop_helper (struct GNUNET_HELPER_Handle *h) |
150 | { | 155 | { |
151 | struct HelperMessageQueueEntry *qe; | 156 | struct GNUNET_HELPER_SendHandle *sh; |
152 | 157 | ||
153 | if (NULL != h->helper_proc) | 158 | if (NULL != h->helper_proc) |
154 | { | 159 | { |
@@ -184,14 +189,14 @@ stop_helper (struct GNUNET_HELPER_Handle *h) | |||
184 | h->helper_out = NULL; | 189 | h->helper_out = NULL; |
185 | h->fh_from_helper = NULL; | 190 | h->fh_from_helper = NULL; |
186 | } | 191 | } |
187 | while (NULL != (qe = h->mq_head)) | 192 | while (NULL != (sh = h->sh_head)) |
188 | { | 193 | { |
189 | GNUNET_CONTAINER_DLL_remove (h->mq_head, | 194 | GNUNET_CONTAINER_DLL_remove (h->sh_head, |
190 | h->mq_tail, | 195 | h->sh_tail, |
191 | qe); | 196 | sh); |
192 | if (NULL != qe->cont) | 197 | if (NULL != sh->cont) |
193 | qe->cont (qe->cont_cls, GNUNET_NO); | 198 | sh->cont (sh->cont_cls, GNUNET_NO); |
194 | GNUNET_free (qe); | 199 | GNUNET_free (sh); |
195 | } | 200 | } |
196 | /* purge MST buffer */ | 201 | /* purge MST buffer */ |
197 | (void) GNUNET_SERVER_mst_receive (h->mst, NULL, NULL, 0, GNUNET_YES, GNUNET_NO); | 202 | (void) GNUNET_SERVER_mst_receive (h->mst, NULL, NULL, 0, GNUNET_YES, GNUNET_NO); |
@@ -380,17 +385,17 @@ GNUNET_HELPER_start (const char *binary_name, | |||
380 | void | 385 | void |
381 | GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h) | 386 | GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h) |
382 | { | 387 | { |
383 | struct HelperMessageQueueEntry *qe; | 388 | struct GNUNET_HELPER_SendHandle *sh; |
384 | 389 | ||
385 | /* signal pending writes that we were stopped */ | 390 | /* signal pending writes that we were stopped */ |
386 | while (NULL != (qe = h->mq_head)) | 391 | while (NULL != (sh = h->sh_head)) |
387 | { | 392 | { |
388 | GNUNET_CONTAINER_DLL_remove (h->mq_head, | 393 | GNUNET_CONTAINER_DLL_remove (h->sh_head, |
389 | h->mq_tail, | 394 | h->sh_tail, |
390 | qe); | 395 | sh); |
391 | if (NULL != qe->cont) | 396 | if (NULL != sh->cont) |
392 | qe->cont (qe->cont_cls, GNUNET_SYSERR); | 397 | sh->cont (sh->cont_cls, GNUNET_SYSERR); |
393 | GNUNET_free (qe); | 398 | GNUNET_free (sh); |
394 | } | 399 | } |
395 | stop_helper (h); | 400 | stop_helper (h); |
396 | GNUNET_SERVER_mst_destroy (h->mst); | 401 | GNUNET_SERVER_mst_destroy (h->mst); |
@@ -409,7 +414,7 @@ helper_write (void *cls, | |||
409 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 414 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
410 | { | 415 | { |
411 | struct GNUNET_HELPER_Handle *h = cls; | 416 | struct GNUNET_HELPER_Handle *h = cls; |
412 | struct HelperMessageQueueEntry *qe; | 417 | struct GNUNET_HELPER_SendHandle *sh; |
413 | const char *buf; | 418 | const char *buf; |
414 | ssize_t t; | 419 | ssize_t t; |
415 | 420 | ||
@@ -421,10 +426,10 @@ helper_write (void *cls, | |||
421 | h->fh_to_helper, &helper_write, h); | 426 | h->fh_to_helper, &helper_write, h); |
422 | return; | 427 | return; |
423 | } | 428 | } |
424 | if (NULL == (qe = h->mq_head)) | 429 | if (NULL == (sh = h->sh_head)) |
425 | return; /* how did this happen? */ | 430 | return; /* how did this happen? */ |
426 | buf = (const char*) qe->msg; | 431 | buf = (const char*) sh->msg; |
427 | t = GNUNET_DISK_file_write (h->fh_to_helper, &buf[qe->wpos], ntohs (qe->msg->size) - qe->wpos); | 432 | t = GNUNET_DISK_file_write (h->fh_to_helper, &buf[sh->wpos], ntohs (sh->msg->size) - sh->wpos); |
428 | if (t <= 0) | 433 | if (t <= 0) |
429 | { | 434 | { |
430 | /* On write-error, restart the helper */ | 435 | /* On write-error, restart the helper */ |
@@ -439,17 +444,17 @@ helper_write (void *cls, | |||
439 | &restart_task, h); | 444 | &restart_task, h); |
440 | return; | 445 | return; |
441 | } | 446 | } |
442 | qe->wpos += t; | 447 | sh->wpos += t; |
443 | if (qe->wpos == ntohs (qe->msg->size)) | 448 | if (sh->wpos == ntohs (sh->msg->size)) |
444 | { | 449 | { |
445 | GNUNET_CONTAINER_DLL_remove (h->mq_head, | 450 | GNUNET_CONTAINER_DLL_remove (h->sh_head, |
446 | h->mq_tail, | 451 | h->sh_tail, |
447 | qe); | 452 | sh); |
448 | if (NULL != qe->cont) | 453 | if (NULL != sh->cont) |
449 | qe->cont (qe->cont_cls, GNUNET_YES); | 454 | sh->cont (sh->cont_cls, GNUNET_YES); |
450 | GNUNET_free (qe); | 455 | GNUNET_free (sh); |
451 | } | 456 | } |
452 | if (NULL != h->mq_head) | 457 | if (NULL != h->sh_head) |
453 | h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, | 458 | h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, |
454 | h->fh_to_helper, | 459 | h->fh_to_helper, |
455 | &helper_write, | 460 | &helper_write, |
@@ -466,40 +471,68 @@ helper_write (void *cls, | |||
466 | * @param cont continuation to run once the message is out (PREREQ_DONE on succees, CANCEL | 471 | * @param cont continuation to run once the message is out (PREREQ_DONE on succees, CANCEL |
467 | * if the helper process died, NULL during GNUNET_HELPER_stop). | 472 | * if the helper process died, NULL during GNUNET_HELPER_stop). |
468 | * @param cont_cls closure for 'cont' | 473 | * @param cont_cls closure for 'cont' |
469 | * @return GNUNET_YES if the message will be sent | 474 | * @return NULL if the message was dropped, |
470 | * GNUNET_NO if the message was dropped | 475 | * otherwise handle to cancel *cont* (actual transmission may |
476 | * not be abortable) | ||
471 | */ | 477 | */ |
472 | int | 478 | struct GNUNET_HELPER_SendHandle * |
473 | GNUNET_HELPER_send (struct GNUNET_HELPER_Handle *h, | 479 | GNUNET_HELPER_send (struct GNUNET_HELPER_Handle *h, |
474 | const struct GNUNET_MessageHeader *msg, | 480 | const struct GNUNET_MessageHeader *msg, |
475 | int can_drop, | 481 | int can_drop, |
476 | GNUNET_HELPER_Continuation cont, | 482 | GNUNET_HELPER_Continuation cont, |
477 | void *cont_cls) | 483 | void *cont_cls) |
478 | { | 484 | { |
479 | struct HelperMessageQueueEntry *qe; | 485 | struct GNUNET_HELPER_SendHandle *sh; |
480 | uint16_t mlen; | 486 | uint16_t mlen; |
481 | 487 | ||
482 | if (NULL == h->fh_to_helper) | 488 | if (NULL == h->fh_to_helper) |
483 | return GNUNET_NO; | 489 | return NULL; |
484 | if ( (GNUNET_YES == can_drop) && | 490 | if ( (GNUNET_YES == can_drop) && |
485 | (h->mq_head != NULL) ) | 491 | (NULL != h->sh_head) ) |
486 | return GNUNET_NO; | 492 | return NULL; |
487 | mlen = ntohs (msg->size); | 493 | mlen = ntohs (msg->size); |
488 | qe = GNUNET_malloc (sizeof (struct HelperMessageQueueEntry) + mlen); | 494 | sh = GNUNET_malloc (sizeof (struct GNUNET_HELPER_SendHandle) + mlen); |
489 | qe->msg = (const struct GNUNET_MessageHeader*) &qe[1]; | 495 | sh->msg = (const struct GNUNET_MessageHeader*) &sh[1]; |
490 | memcpy (&qe[1], msg, mlen); | 496 | memcpy (&sh[1], msg, mlen); |
491 | qe->cont = cont; | 497 | sh->h = h; |
492 | qe->cont_cls = cont_cls; | 498 | sh->cont = cont; |
493 | GNUNET_CONTAINER_DLL_insert_tail (h->mq_head, | 499 | sh->cont_cls = cont_cls; |
494 | h->mq_tail, | 500 | GNUNET_CONTAINER_DLL_insert_tail (h->sh_head, |
495 | qe); | 501 | h->sh_tail, |
502 | sh); | ||
496 | if (GNUNET_SCHEDULER_NO_TASK == h->write_task) | 503 | if (GNUNET_SCHEDULER_NO_TASK == h->write_task) |
497 | h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, | 504 | h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, |
498 | h->fh_to_helper, | 505 | h->fh_to_helper, |
499 | &helper_write, | 506 | &helper_write, |
500 | h); | 507 | h); |
501 | 508 | ||
502 | return GNUNET_YES; | 509 | return sh; |
510 | } | ||
511 | |||
512 | /** | ||
513 | * Cancel a 'send' operation. If possible, transmitting the | ||
514 | * message is also aborted, but at least 'cont' won't be | ||
515 | * called. | ||
516 | * | ||
517 | * @param sh operation to cancel | ||
518 | */ | ||
519 | void | ||
520 | GNUNET_HELPER_send_cancel (struct GNUNET_HELPER_SendHandle *sh) | ||
521 | { | ||
522 | struct GNUNET_HELPER_Handle *h = sh->h; | ||
523 | |||
524 | sh->cont = NULL; | ||
525 | sh->cont_cls = NULL; | ||
526 | if (0 == sh->wpos) | ||
527 | { | ||
528 | GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh); | ||
529 | if (NULL == h->sh_head) | ||
530 | { | ||
531 | GNUNET_SCHEDULER_cancel (h->write_task); | ||
532 | h->write_task = GNUNET_SCHEDULER_NO_TASK; | ||
533 | } | ||
534 | GNUNET_free (sh); | ||
535 | } | ||
503 | } | 536 | } |
504 | 537 | ||
505 | 538 | ||