aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorGabor X Toth <*@tg-x.net>2015-05-07 12:15:32 +0000
committerGabor X Toth <*@tg-x.net>2015-05-07 12:15:32 +0000
commita5edf8ac9f03a368c87ea6163994d4ac3d62af06 (patch)
tree4daeaa2561d3edf5c0a6f2298054970e27928a0b /src/util
parent26dbd65eff8dc627697a1ee5c3b755c2951ac013 (diff)
downloadgnunet-a5edf8ac9f03a368c87ea6163994d4ac3d62af06.tar.gz
gnunet-a5edf8ac9f03a368c87ea6163994d4ac3d62af06.zip
client_manager: add API for async operations
Diffstat (limited to 'src/util')
-rw-r--r--src/util/client_manager.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/src/util/client_manager.c b/src/util/client_manager.c
index 662d6d061..a3c851bfa 100644
--- a/src/util/client_manager.c
+++ b/src/util/client_manager.c
@@ -33,6 +33,28 @@
33#define LOG(kind,...) GNUNET_log_from (kind, "util-client-mgr", __VA_ARGS__) 33#define LOG(kind,...) GNUNET_log_from (kind, "util-client-mgr", __VA_ARGS__)
34 34
35 35
36struct OperationListItem
37{
38 struct OperationListItem *prev;
39 struct OperationListItem *next;
40
41 /**
42 * Operation ID.
43 */
44 uint64_t op_id;
45
46 /**
47 * Continuation to invoke with the result of an operation.
48 */
49 GNUNET_ResultCallback result_cb;
50
51 /**
52 * Closure for @a result_cb.
53 */
54 void *cls;
55};
56
57
36/** 58/**
37 * List of arrays of message handlers. 59 * List of arrays of message handlers.
38 */ 60 */
@@ -94,6 +116,21 @@ struct GNUNET_CLIENT_MANAGER_Connection
94 const struct GNUNET_CLIENT_MANAGER_MessageHandler *handlers; 116 const struct GNUNET_CLIENT_MANAGER_MessageHandler *handlers;
95 117
96 /** 118 /**
119 * First operation in the linked list.
120 */
121 struct OperationListItem *op_head;
122
123 /**
124 * Last operation in the linked list.
125 */
126 struct OperationListItem *op_tail;
127
128 /**
129 * Last operation ID used.
130 */
131 uint64_t last_op_id;
132
133 /**
97 * Disconnect callback. 134 * Disconnect callback.
98 */ 135 */
99 void (*disconnect_cb)(void *); 136 void (*disconnect_cb)(void *);
@@ -559,3 +596,204 @@ GNUNET_CLIENT_MANAGER_set_user_context_ (struct GNUNET_CLIENT_MANAGER_Connection
559 mgr->user_ctx_size = size; 596 mgr->user_ctx_size = size;
560 mgr->user_ctx = ctx; 597 mgr->user_ctx = ctx;
561} 598}
599
600
601/**
602 * Get a unique operation ID to distinguish between asynchronous requests.
603 *
604 * @param mgr
605 * Client manager connection.
606 *
607 * @return Operation ID to use.
608 */
609uint64_t
610GNUNET_CLIENT_MANAGER_op_get_next_id (struct GNUNET_CLIENT_MANAGER_Connection *mgr)
611{
612 return ++mgr->last_op_id;
613}
614
615
616/**
617 * Find operation by ID.
618 *
619 * @param mgr
620 * Client manager connection.
621 * @param op_id
622 * Operation ID to look up.
623 *
624 * @return Operation, or NULL if not found.
625 */
626static struct OperationListItem *
627op_find (struct GNUNET_CLIENT_MANAGER_Connection *mgr, uint64_t op_id)
628{
629 struct OperationListItem *op = mgr->op_head;
630 while (NULL != op)
631 {
632 if (op->op_id == op_id)
633 return op;
634 op = op->next;
635 }
636 return NULL;
637}
638
639
640/**
641 * Find operation by ID.
642 *
643 * @param mgr
644 * Client manager connection.
645 * @param op_id
646 * Operation ID to look up.
647 * @param[out] result_cb
648 * If an operation was found, its result callback is returned here.
649 * @param[out] cls
650 * If an operation was found, its closure is returned here.
651 *
652 * @return #GNUNET_YES if an operation was found,
653 * #GNUNET_NO if not found.
654 */
655int
656GNUNET_CLIENT_MANAGER_op_find (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
657 uint64_t op_id,
658 GNUNET_ResultCallback *result_cb,
659 void **cls)
660{
661 struct OperationListItem *op = op_find (mgr, op_id);
662 if (NULL != op)
663 {
664 *result_cb = op->result_cb;
665 *cls = op->cls;
666 return GNUNET_YES;
667 }
668 return GNUNET_NO;
669}
670
671
672/**
673 * Add a new operation.
674 *
675 * @param mgr
676 * Client manager connection.
677 * @param result_cb
678 * Function to call with the result of the operation.
679 * @param cls
680 * Closure for @a result_cb.
681 *
682 * @return ID of the new operation.
683 */
684uint64_t
685GNUNET_CLIENT_MANAGER_op_add (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
686 GNUNET_ResultCallback result_cb,
687 void *cls)
688{
689 if (NULL == result_cb)
690 return 0;
691
692 struct OperationListItem *op = GNUNET_malloc (sizeof (*op));
693 op->op_id = GNUNET_CLIENT_MANAGER_op_get_next_id (mgr);
694 op->result_cb = result_cb;
695 op->cls = cls;
696 GNUNET_CONTAINER_DLL_insert_tail (mgr->op_head, mgr->op_tail, op);
697
698 LOG (GNUNET_ERROR_TYPE_DEBUG,
699 "%p Added operation #%" PRIu64 "\n", mgr, op->op_id);
700 return op->op_id;
701}
702
703
704/**
705 * Remove an operation, and call its result callback (unless it was cancelled).
706 *
707 *
708 * @param mgr
709 * Client manager connection.
710 * @param op_id
711 * Operation ID.
712 * @param result_code
713 * Result of the operation.
714 * @param data
715 * Data result of the operation.
716 * @param data_size
717 * Size of @a data.
718 * @param cancel
719 * Is the operation cancelled?
720 * #GNUNET_NO Not cancelled, result callback is called.
721 * #GNUNET_YES Cancelled, result callback is not called.
722 *
723 * @return #GNUNET_YES if the operation was found and removed,
724 * #GNUNET_NO if the operation was not found.
725 */
726static int
727op_result (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
728 uint64_t op_id, int64_t result_code,
729 const void *data, uint16_t data_size, uint8_t cancel)
730{
731 if (0 == op_id)
732 return GNUNET_NO;
733
734 struct OperationListItem *op = op_find (mgr, op_id);
735 if (NULL == op)
736 {
737 LOG (GNUNET_ERROR_TYPE_WARNING,
738 "Could not find operation #%" PRIu64 "\n", op_id);
739 return GNUNET_NO;
740 }
741
742 GNUNET_CONTAINER_DLL_remove (mgr->op_head, mgr->op_tail, op);
743
744 if (GNUNET_YES != cancel && NULL != op->result_cb)
745 op->result_cb (op->cls, result_code, data, data_size);
746
747 GNUNET_free (op);
748 return GNUNET_YES;
749}
750
751
752/**
753 * Call the result callback of an operation and remove it.
754 *
755 * @param mgr
756 * Client manager connection.
757 * @param op_id
758 * Operation ID.
759 * @param result_code
760 * Result of the operation.
761 * @param data
762 * Data result of the operation.
763 * @param data_size
764 * Size of @a data.
765 *
766 * @return #GNUNET_YES if the operation was found and removed,
767 * #GNUNET_NO if the operation was not found.
768 */
769int
770GNUNET_CLIENT_MANAGER_op_result (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
771 uint64_t op_id, int64_t result_code,
772 const void *data, uint16_t data_size)
773{
774 LOG (GNUNET_ERROR_TYPE_DEBUG,
775 "%p Received result for operation #%" PRIu64 ": %" PRId64 " (size: %u)\n",
776 mgr, op_id, result_code, data_size);
777 return op_result (mgr, op_id, result_code, data, data_size, GNUNET_NO);
778}
779
780
781/**
782 * Cancel an operation.
783 *
784 * @param mgr
785 * Client manager connection.
786 * @param op_id
787 * Operation ID.
788 *
789 * @return #GNUNET_YES if the operation was found and removed,
790 * #GNUNET_NO if the operation was not found.
791 */
792int
793GNUNET_CLIENT_MANAGER_op_cancel (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
794 uint64_t op_id)
795{
796 LOG (GNUNET_ERROR_TYPE_DEBUG,
797 "%p Cancelling operation #%" PRIu64 "\n", mgr, op_id);
798 return op_result (mgr, op_id, 0, NULL, 0, GNUNET_YES);
799}