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 | |
parent | 26dbd65eff8dc627697a1ee5c3b755c2951ac013 (diff) | |
download | gnunet-a5edf8ac9f03a368c87ea6163994d4ac3d62af06.tar.gz gnunet-a5edf8ac9f03a368c87ea6163994d4ac3d62af06.zip |
client_manager: add API for async operations
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_client_manager_lib.h | 91 | ||||
-rw-r--r-- | src/include/gnunet_common.h | 40 | ||||
-rw-r--r-- | src/util/client_manager.c | 238 |
3 files changed, 369 insertions, 0 deletions
diff --git a/src/include/gnunet_client_manager_lib.h b/src/include/gnunet_client_manager_lib.h index 6623c2ba1..4b267c98f 100644 --- a/src/include/gnunet_client_manager_lib.h +++ b/src/include/gnunet_client_manager_lib.h | |||
@@ -249,6 +249,97 @@ GNUNET_CLIENT_MANAGER_set_user_context_ (struct GNUNET_CLIENT_MANAGER_Connection | |||
249 | GNUNET_CLIENT_MANAGER_set_user_context_ (mgr, ctx, sizeof (*ctx)) | 249 | GNUNET_CLIENT_MANAGER_set_user_context_ (mgr, ctx, sizeof (*ctx)) |
250 | 250 | ||
251 | 251 | ||
252 | /** | ||
253 | * Get a unique operation ID to distinguish between asynchronous requests. | ||
254 | * | ||
255 | * @param mgr | ||
256 | * Client manager connection. | ||
257 | * | ||
258 | * @return Operation ID to use. | ||
259 | */ | ||
260 | uint64_t | ||
261 | GNUNET_CLIENT_MANAGER_op_get_next_id (struct GNUNET_CLIENT_MANAGER_Connection *mgr); | ||
262 | |||
263 | |||
264 | /** | ||
265 | * Find operation by ID. | ||
266 | * | ||
267 | * @param mgr | ||
268 | * Client manager connection. | ||
269 | * @param op_id | ||
270 | * Operation ID to look up. | ||
271 | * @param[out] result_cb | ||
272 | * If an operation was found, its result callback is returned here. | ||
273 | * @param[out] cls | ||
274 | * If an operation was found, its closure is returned here. | ||
275 | * | ||
276 | * @return #GNUNET_YES if an operation was found, | ||
277 | * #GNUNET_NO if not found. | ||
278 | */ | ||
279 | int | ||
280 | GNUNET_CLIENT_MANAGER_op_find (struct GNUNET_CLIENT_MANAGER_Connection *mgr, | ||
281 | uint64_t op_id, | ||
282 | GNUNET_ResultCallback *result_cb, | ||
283 | void **cls); | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Add a new operation. | ||
288 | * | ||
289 | * @param mgr | ||
290 | * Client manager connection. | ||
291 | * @param result_cb | ||
292 | * Function to call with the result of the operation. | ||
293 | * @param cls | ||
294 | * Closure for @a result_cb. | ||
295 | * | ||
296 | * @return ID of the new operation. | ||
297 | */ | ||
298 | uint64_t | ||
299 | GNUNET_CLIENT_MANAGER_op_add (struct GNUNET_CLIENT_MANAGER_Connection *mgr, | ||
300 | GNUNET_ResultCallback result_cb, | ||
301 | void *cls); | ||
302 | |||
303 | |||
304 | /** | ||
305 | * Call the result callback and remove the operation. | ||
306 | * | ||
307 | * @param mgr | ||
308 | * Client manager connection. | ||
309 | * @param op_id | ||
310 | * Operation ID. | ||
311 | * @param result_code | ||
312 | * Result of the operation. | ||
313 | * @param data | ||
314 | * Data result of the operation. | ||
315 | * @param data_size | ||
316 | * Size of @a data. | ||
317 | * | ||
318 | * @return #GNUNET_YES if the operation was found and removed, | ||
319 | * #GNUNET_NO if the operation was not found. | ||
320 | */ | ||
321 | int | ||
322 | GNUNET_CLIENT_MANAGER_op_result (struct GNUNET_CLIENT_MANAGER_Connection *mgr, | ||
323 | uint64_t op_id, int64_t result_code, | ||
324 | const void *data, uint16_t data_size); | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Cancel an operation. | ||
329 | * | ||
330 | * @param mgr | ||
331 | * Client manager connection. | ||
332 | * @param op_id | ||
333 | * Operation ID. | ||
334 | * | ||
335 | * @return #GNUNET_YES if the operation was found and removed, | ||
336 | * #GNUNET_NO if the operation was not found. | ||
337 | */ | ||
338 | int | ||
339 | GNUNET_CLIENT_MANAGER_op_cancel (struct GNUNET_CLIENT_MANAGER_Connection *mgr, | ||
340 | uint64_t op_id); | ||
341 | |||
342 | |||
252 | #if 0 /* keep Emacsens' auto-indent happy */ | 343 | #if 0 /* keep Emacsens' auto-indent happy */ |
253 | { | 344 | { |
254 | #endif | 345 | #endif |
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h index 880fc1fee..6a02190cc 100644 --- a/src/include/gnunet_common.h +++ b/src/include/gnunet_common.h | |||
@@ -248,6 +248,29 @@ struct GNUNET_MessageHeader | |||
248 | 248 | ||
249 | }; | 249 | }; |
250 | 250 | ||
251 | |||
252 | /** | ||
253 | * Answer from service to client about last operation. | ||
254 | */ | ||
255 | struct GNUNET_OperationResultMessage | ||
256 | { | ||
257 | struct GNUNET_MessageHeader header; | ||
258 | |||
259 | uint32_t reserved GNUNET_PACKED; | ||
260 | |||
261 | /** | ||
262 | * Operation ID. | ||
263 | */ | ||
264 | uint64_t op_id GNUNET_PACKED; | ||
265 | |||
266 | /** | ||
267 | * Status code for the operation. | ||
268 | */ | ||
269 | uint64_t result_code GNUNET_PACKED; | ||
270 | |||
271 | /* Followed by data. */ | ||
272 | }; | ||
273 | |||
251 | GNUNET_NETWORK_STRUCT_END | 274 | GNUNET_NETWORK_STRUCT_END |
252 | 275 | ||
253 | /** | 276 | /** |
@@ -273,6 +296,23 @@ typedef void | |||
273 | (*GNUNET_ContinuationCallback) (void *cls); | 296 | (*GNUNET_ContinuationCallback) (void *cls); |
274 | 297 | ||
275 | 298 | ||
299 | /** | ||
300 | * Function called with the result of an asynchronous operation. | ||
301 | * | ||
302 | * @param cls | ||
303 | * Closure. | ||
304 | * @param result_code | ||
305 | * Result code for the operation. | ||
306 | * @param data | ||
307 | * Data result for the operation. | ||
308 | * @param data_size | ||
309 | * Size of @a data. | ||
310 | */ | ||
311 | typedef void | ||
312 | (*GNUNET_ResultCallback) (void *cls, int64_t result_code, | ||
313 | const void *data, uint16_t data_size); | ||
314 | |||
315 | |||
276 | /* ****************************** logging ***************************** */ | 316 | /* ****************************** logging ***************************** */ |
277 | 317 | ||
278 | /** | 318 | /** |
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 | } | ||