2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
18 * Asynchronous operations; register callbacks for operations and call them when a response arrives.
20 * @author Gabor X Toth
26 #include "gnunet_util_lib.h"
28 #define LOG(kind,...) GNUNET_log_from (kind, "util-op", __VA_ARGS__)
30 struct OperationListItem
32 struct OperationListItem *prev;
33 struct OperationListItem *next;
41 * Continuation to invoke with the result of an operation.
43 GNUNET_ResultCallback result_cb;
46 * Closure for @a result_cb.
61 struct GNUNET_OP_Handle
64 * First operation in the linked list.
66 struct OperationListItem *op_head;
69 * Last operation in the linked list.
71 struct OperationListItem *op_tail;
74 * Last operation ID used.
81 * Create new operations handle.
83 struct GNUNET_OP_Handle *
86 return GNUNET_new (struct GNUNET_OP_Handle);
91 * Destroy operations handle.
94 GNUNET_OP_destroy (struct GNUNET_OP_Handle *h)
101 * Get a unique operation ID to distinguish between asynchronous requests.
106 * @return Operation ID to use.
109 GNUNET_OP_get_next_id (struct GNUNET_OP_Handle *h)
111 return ++h->last_op_id;
116 * Find operation by ID.
121 * Operation ID to look up.
123 * @return Operation, or NULL if not found.
125 static struct OperationListItem *
126 op_find (struct GNUNET_OP_Handle *h,
129 struct OperationListItem *op;
131 for (op = h->op_head; NULL != op; op = op->next)
132 if (op->op_id == op_id)
139 * Find operation by ID.
144 * Operation ID to look up.
145 * @param[out] result_cb
146 * If an operation was found, its result callback is returned here.
148 * If an operation was found, its closure is returned here.
150 * If an operation was found, its user context is returned here.
152 * @return #GNUNET_YES if an operation was found,
153 * #GNUNET_NO if not found.
156 GNUNET_OP_get (struct GNUNET_OP_Handle *h,
158 GNUNET_ResultCallback *result_cb,
162 struct OperationListItem *op = op_find (h, op_id);
165 if (NULL != result_cb)
166 *result_cb = op->result_cb;
178 * Add a new operation.
183 * Function to call with the result of the operation.
185 * Closure for @a result_cb.
189 * @return ID of the new operation.
192 GNUNET_OP_add (struct GNUNET_OP_Handle *h,
193 GNUNET_ResultCallback result_cb,
197 struct OperationListItem *op;
199 op = GNUNET_new (struct OperationListItem);
200 op->op_id = GNUNET_OP_get_next_id (h);
201 op->result_cb = result_cb;
204 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
207 LOG (GNUNET_ERROR_TYPE_DEBUG,
208 "%p Added operation #%" PRIu64 "\n",
215 * Remove an operation, and call its result callback (unless it was cancelled).
223 * Result of the operation.
225 * Data result of the operation.
231 * Is the operation cancelled?
232 * #GNUNET_NO Not cancelled, result callback is called.
233 * #GNUNET_YES Cancelled, result callback is not called.
235 * @return #GNUNET_YES if the operation was found and removed,
236 * #GNUNET_NO if the operation was not found.
239 op_result (struct GNUNET_OP_Handle *h,
250 struct OperationListItem *op = op_find (h, op_id);
253 LOG (GNUNET_ERROR_TYPE_WARNING,
254 "Could not find operation #%" PRIu64 "\n", op_id);
261 GNUNET_CONTAINER_DLL_remove (h->op_head,
265 if ( (GNUNET_YES != cancel) &&
266 (NULL != op->result_cb) )
267 op->result_cb (op->cls,
276 * Call the result callback of an operation and remove it.
283 * Result of the operation.
285 * Data result of the operation.
291 * @return #GNUNET_YES if the operation was found and removed,
292 * #GNUNET_NO if the operation was not found.
295 GNUNET_OP_result (struct GNUNET_OP_Handle *h,
302 LOG (GNUNET_ERROR_TYPE_DEBUG,
303 "%p Received result for operation #%" PRIu64 ": %" PRId64 " (size: %u)\n",
304 h, op_id, result_code, data_size);
305 return op_result (h, op_id, result_code, data, data_size, ctx, GNUNET_NO);
310 * Remove / cancel an operation.
317 * @return #GNUNET_YES if the operation was found and removed,
318 * #GNUNET_NO if the operation was not found.
321 GNUNET_OP_remove (struct GNUNET_OP_Handle *h,
324 LOG (GNUNET_ERROR_TYPE_DEBUG,
325 "%p Cancelling operation #%" PRIu64 "\n",
327 return op_result (h, op_id, 0, NULL, 0, NULL, GNUNET_YES);