aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_client_manager_lib.h91
-rw-r--r--src/include/gnunet_common.h40
-rw-r--r--src/util/client_manager.c238
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 */
260uint64_t
261GNUNET_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 */
279int
280GNUNET_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 */
298uint64_t
299GNUNET_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 */
321int
322GNUNET_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 */
338int
339GNUNET_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 */
255struct 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
251GNUNET_NETWORK_STRUCT_END 274GNUNET_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 */
311typedef 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
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}