aboutsummaryrefslogtreecommitdiff
path: root/src/util/helper.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-05-08 19:17:03 +0000
committerChristian Grothoff <christian@grothoff.org>2012-05-08 19:17:03 +0000
commit6623d76dcb3659204935e462a8d0d415c7748a99 (patch)
tree9d89e4f33b7c60bbd08d2ed85a7d439b963044e6 /src/util/helper.c
parent31adadd3c4ca45d147392d6fa5ee839be1037740 (diff)
downloadgnunet-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.c135
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 */
34struct HelperMessageQueueEntry 34struct 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
148static void 153static void
149stop_helper (struct GNUNET_HELPER_Handle *h) 154stop_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,
380void 385void
381GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h) 386GNUNET_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 */
472int 478struct GNUNET_HELPER_SendHandle *
473GNUNET_HELPER_send (struct GNUNET_HELPER_Handle *h, 479GNUNET_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 */
519void
520GNUNET_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