diff options
author | Gabor X Toth <*@tg-x.net> | 2015-05-07 12:15:32 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2015-05-07 12:15:32 +0000 |
commit | a5edf8ac9f03a368c87ea6163994d4ac3d62af06 (patch) | |
tree | 4daeaa2561d3edf5c0a6f2298054970e27928a0b /src/util | |
parent | 26dbd65eff8dc627697a1ee5c3b755c2951ac013 (diff) | |
download | gnunet-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.c | 238 |
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 | ||
36 | struct 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 | */ | ||
609 | uint64_t | ||
610 | GNUNET_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 | */ | ||
626 | static struct OperationListItem * | ||
627 | op_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 | */ | ||
655 | int | ||
656 | GNUNET_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 | */ | ||
684 | uint64_t | ||
685 | GNUNET_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 | */ | ||
726 | static int | ||
727 | op_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 | */ | ||
769 | int | ||
770 | GNUNET_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 | */ | ||
792 | int | ||
793 | GNUNET_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 | } | ||