diff options
Diffstat (limited to 'src/include/gnunet_mq_lib.h')
-rw-r--r-- | src/include/gnunet_mq_lib.h | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h new file mode 100644 index 000000000..59b692cf0 --- /dev/null +++ b/src/include/gnunet_mq_lib.h | |||
@@ -0,0 +1,478 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Florian Dold | ||
23 | * @file set/mq.h | ||
24 | * @brief general purpose request queue | ||
25 | */ | ||
26 | #ifndef GNUNET_MQ_H | ||
27 | #define GNUNET_MQ_H | ||
28 | |||
29 | #include "gnunet_common.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * Allocate a GNUNET_MQ_Message, with extra space allocated after the space needed | ||
34 | * by the message struct. | ||
35 | * The allocated message will already have the type and size field set. | ||
36 | * | ||
37 | * @param mvar variable to store the allocated message in; | ||
38 | * must have a header field | ||
39 | * @param esize extra space to allocate after the message | ||
40 | * @param type type of the message | ||
41 | * @return the MQ message | ||
42 | */ | ||
43 | #define GNUNET_MQ_msg_extra(mvar, esize, type) GNUNET_MQ_msg_((((void)(mvar)->header), (struct GNUNET_MessageHeader**) &(mvar)), (esize) + sizeof *(mvar), (type)) | ||
44 | |||
45 | /** | ||
46 | * Allocate a GNUNET_MQ_Message. | ||
47 | * The allocated message will already have the type and size field set. | ||
48 | * | ||
49 | * @param mvar variable to store the allocated message in; | ||
50 | * must have a header field | ||
51 | * @param type type of the message | ||
52 | * @return the MQ message | ||
53 | */ | ||
54 | #define GNUNET_MQ_msg(mvar, type) GNUNET_MQ_msg_extra(mvar, 0, type) | ||
55 | |||
56 | /** | ||
57 | * Append data to the end of an existing MQ message. | ||
58 | * If the operation is successful, mqm is changed to point to the new MQ message, | ||
59 | * and GNUNET_OK is returned. | ||
60 | * On failure, GNUNET_SYSERR is returned, and the pointer mqm is not changed, | ||
61 | * the user of this API must take care of disposing the already allocated message | ||
62 | * (either by sending it, or by using GNUNET_MQ_discard) | ||
63 | * | ||
64 | * @param mqm MQ message to augment with additional data | ||
65 | * @param src source buffer for the additional data | ||
66 | * @param len length of the additional data | ||
67 | * @return GNUNET_SYSERR if nesting the message failed, | ||
68 | * GNUNET_OK on success | ||
69 | */ | ||
70 | #define GNUNET_MQ_nest(mqm, src, len) GNUNET_MQ_nest_ (&mqm, src, len) | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Append a message to the end of an existing MQ message. | ||
75 | * If the operation is successful, mqm is changed to point to the new MQ message, | ||
76 | * and GNUNET_OK is returned. | ||
77 | * On failure, GNUNET_SYSERR is returned, and the pointer mqm is not changed, | ||
78 | * the user of this API must take care of disposing the already allocated message | ||
79 | * (either by sending it, or by using GNUNET_MQ_discard) | ||
80 | * | ||
81 | * @param mqm MQ message to augment with additional data | ||
82 | * @param mh the message to append, must be of type 'struct GNUNET_MessageHeader *' | ||
83 | */ | ||
84 | #define GNUNET_MQ_nest_mh(mqm, mh) ((NULL == mh) ? (GNUNET_OK) : GNUNET_MQ_nest((mqm), (mh), ntohs ((mh)->size))) | ||
85 | |||
86 | |||
87 | /** | ||
88 | * Allocate a GNUNET_MQ_Message, where the message only consists of a header. | ||
89 | * The allocated message will already have the type and size field set. | ||
90 | * | ||
91 | * @param type type of the message | ||
92 | */ | ||
93 | #define GNUNET_MQ_msg_header(type) GNUNET_MQ_msg_ (NULL, sizeof (struct GNUNET_MessageHeader), type) | ||
94 | |||
95 | |||
96 | /** | ||
97 | * Allocate a GNUNET_MQ_Message, where the message only consists of a header and extra space. | ||
98 | * The allocated message will already have the type and size field set. | ||
99 | * | ||
100 | * @param mh pointer that will changed to point at to the allocated message header | ||
101 | * @param esize extra space to allocate after the message header | ||
102 | * @param type type of the message | ||
103 | */ | ||
104 | #define GNUNET_MQ_msg_header_extra(mh, esize, type) GNUNET_MQ_msg_ (&mh, (esize) + sizeof (struct GNUNET_MessageHeader), type) | ||
105 | |||
106 | |||
107 | /** | ||
108 | * End-marker for the handlers array | ||
109 | */ | ||
110 | #define GNUNET_MQ_HANDLERS_END {NULL, 0, 0} | ||
111 | |||
112 | |||
113 | struct GNUNET_MQ_MessageQueue; | ||
114 | |||
115 | struct GNUNET_MQ_Message; | ||
116 | |||
117 | enum GNUNET_MQ_Error | ||
118 | { | ||
119 | GNUNET_MQ_ERROR_READ = 1, | ||
120 | GNUNET_MQ_ERROR_WRITE = 2, | ||
121 | GNUNET_MQ_ERROR_TIMEOUT = 4 | ||
122 | }; | ||
123 | |||
124 | |||
125 | /** | ||
126 | * Called when a message has been received. | ||
127 | * | ||
128 | * @param cls closure | ||
129 | * @param msg the received message | ||
130 | */ | ||
131 | typedef void (*GNUNET_MQ_MessageCallback) (void *cls, const struct GNUNET_MessageHeader *msg); | ||
132 | |||
133 | |||
134 | /** | ||
135 | * Signature of functions implementing the | ||
136 | * sending part of a message queue | ||
137 | * | ||
138 | * @param q the message queue | ||
139 | * @param m the message | ||
140 | */ | ||
141 | typedef void | ||
142 | (*GNUNET_MQ_SendImpl) (struct GNUNET_MQ_MessageQueue *q, struct GNUNET_MQ_Message *m); | ||
143 | |||
144 | |||
145 | typedef void | ||
146 | (*GNUNET_MQ_DestroyImpl) (struct GNUNET_MQ_MessageQueue *q); | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Callback used for notifications | ||
151 | * | ||
152 | * @param cls closure | ||
153 | */ | ||
154 | typedef void (*GNUNET_MQ_NotifyCallback) (void *cls); | ||
155 | |||
156 | |||
157 | typedef void (*GNUNET_MQ_ErrorHandler) (void *cls, enum GNUNET_MQ_Error error); | ||
158 | |||
159 | |||
160 | struct GNUNET_MQ_Message | ||
161 | { | ||
162 | /** | ||
163 | * Messages are stored in a linked list | ||
164 | */ | ||
165 | struct GNUNET_MQ_Message *next; | ||
166 | |||
167 | /** | ||
168 | * Messages are stored in a linked list | ||
169 | */ | ||
170 | struct GNUNET_MQ_Message *prev; | ||
171 | |||
172 | /** | ||
173 | * Actual allocated message header, | ||
174 | * usually points to the end of the containing GNUNET_MQ_Message | ||
175 | */ | ||
176 | struct GNUNET_MessageHeader *mh; | ||
177 | |||
178 | /** | ||
179 | * Queue the message is queued in, NULL if message is not queued. | ||
180 | */ | ||
181 | struct GNUNET_MQ_MessageQueue *parent_queue; | ||
182 | |||
183 | /** | ||
184 | * Called after the message was sent irrevokably | ||
185 | */ | ||
186 | GNUNET_MQ_NotifyCallback sent_cb; | ||
187 | |||
188 | /** | ||
189 | * Closure for send_cb | ||
190 | */ | ||
191 | void *sent_cls; | ||
192 | }; | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Handle to a message queue. | ||
197 | */ | ||
198 | struct GNUNET_MQ_MessageQueue | ||
199 | { | ||
200 | /** | ||
201 | * Handlers array, or NULL if the queue should not receive messages | ||
202 | */ | ||
203 | const struct GNUNET_MQ_Handler *handlers; | ||
204 | |||
205 | /** | ||
206 | * Closure for the handler callbacks, | ||
207 | * as well as for the error handler. | ||
208 | */ | ||
209 | void *handlers_cls; | ||
210 | |||
211 | /** | ||
212 | * Actual implementation of message sending, | ||
213 | * called when a message is added | ||
214 | */ | ||
215 | GNUNET_MQ_SendImpl send_impl; | ||
216 | |||
217 | /** | ||
218 | * Implementation-dependent queue destruction function | ||
219 | */ | ||
220 | GNUNET_MQ_DestroyImpl destroy_impl; | ||
221 | |||
222 | /** | ||
223 | * Implementation-specific state | ||
224 | */ | ||
225 | void *impl_state; | ||
226 | |||
227 | /** | ||
228 | * Callback will be called when an error occurs. | ||
229 | */ | ||
230 | GNUNET_MQ_ErrorHandler error_handler; | ||
231 | |||
232 | /** | ||
233 | * Linked list of messages pending to be sent | ||
234 | */ | ||
235 | struct GNUNET_MQ_Message *msg_head; | ||
236 | |||
237 | /** | ||
238 | * Linked list of messages pending to be sent | ||
239 | */ | ||
240 | struct GNUNET_MQ_Message *msg_tail; | ||
241 | |||
242 | /** | ||
243 | * Message that is currently scheduled to be | ||
244 | * sent. Not the head of the message queue, as the implementation | ||
245 | * needs to know if sending has been already scheduled or not. | ||
246 | */ | ||
247 | struct GNUNET_MQ_Message *current_msg; | ||
248 | |||
249 | /** | ||
250 | * Map of associations, lazily allocated | ||
251 | */ | ||
252 | struct GNUNET_CONTAINER_MultiHashMap32 *assoc_map; | ||
253 | |||
254 | /** | ||
255 | * Next id that should be used for the assoc_map, | ||
256 | * initialized lazily to a random value together with | ||
257 | * assoc_map | ||
258 | */ | ||
259 | uint32_t assoc_id; | ||
260 | }; | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Message handler for a specific message type. | ||
265 | */ | ||
266 | struct GNUNET_MQ_Handler | ||
267 | { | ||
268 | /** | ||
269 | * Callback, called every time a new message of | ||
270 | * the specified type has been receied. | ||
271 | */ | ||
272 | GNUNET_MQ_MessageCallback cb; | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Type of the message this handler covers. | ||
277 | */ | ||
278 | uint16_t type; | ||
279 | |||
280 | /** | ||
281 | * Expected size of messages of this type. Use 0 for | ||
282 | * variable-size. If non-zero, messages of the given | ||
283 | * type will be discarded (and the connection closed) | ||
284 | * if they do not have the right size. | ||
285 | */ | ||
286 | uint16_t expected_size; | ||
287 | }; | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Create a new message for MQ. | ||
292 | * | ||
293 | * @param mhp message header to store the allocated message header in, can be NULL | ||
294 | * @param size size of the message to allocate | ||
295 | * @param type type of the message, will be set in the allocated message | ||
296 | * @return the allocated MQ message | ||
297 | */ | ||
298 | struct GNUNET_MQ_Message * | ||
299 | GNUNET_MQ_msg_ (struct GNUNET_MessageHeader **mhp, uint16_t size, uint16_t type); | ||
300 | |||
301 | |||
302 | /** | ||
303 | * Resize the the mq message pointed to by mqmp, | ||
304 | * and append the given data to it. | ||
305 | * | ||
306 | * @param mqmp pointer to a mq message pointer | ||
307 | * @param src source of the data to append | ||
308 | * @param len length of the data to append | ||
309 | * @return GNUNET_OK on success, | ||
310 | * GNUNET_SYSERR on error (e.g. if len is too large) | ||
311 | */ | ||
312 | int | ||
313 | GNUNET_MQ_nest_ (struct GNUNET_MQ_Message **mqmp, | ||
314 | const void *src, uint16_t len); | ||
315 | |||
316 | |||
317 | /** | ||
318 | * Discard the message queue message, free all | ||
319 | * allocated resources. Must be called in the event | ||
320 | * that a message is created but should not actually be sent. | ||
321 | * | ||
322 | * @param mqm the message to discard | ||
323 | */ | ||
324 | void | ||
325 | GNUNET_MQ_discard (struct GNUNET_MQ_Message *mqm); | ||
326 | |||
327 | |||
328 | /** | ||
329 | * Send a message with the give message queue. | ||
330 | * May only be called once per message. | ||
331 | * | ||
332 | * @param mq message queue | ||
333 | * @param mqm the message to send. | ||
334 | */ | ||
335 | void | ||
336 | GNUNET_MQ_send (struct GNUNET_MQ_MessageQueue *mq, struct GNUNET_MQ_Message *mqm); | ||
337 | |||
338 | |||
339 | /** | ||
340 | * Cancel sending the message. Message must have been sent with GNUNET_MQ_send before. | ||
341 | * May not be called after the notify sent callback has been called | ||
342 | * | ||
343 | * @param mqm queued message to cancel | ||
344 | */ | ||
345 | void | ||
346 | GNUNET_MQ_send_cancel (struct GNUNET_MQ_Message *mqm); | ||
347 | |||
348 | |||
349 | /** | ||
350 | * Associate the assoc_data in mq with a unique request id. | ||
351 | * | ||
352 | * @param mq message queue, id will be unique for the queue | ||
353 | * @param mqm message to associate | ||
354 | * @param assoc_data to associate | ||
355 | */ | ||
356 | uint32_t | ||
357 | GNUNET_MQ_assoc_add (struct GNUNET_MQ_MessageQueue *mq, | ||
358 | struct GNUNET_MQ_Message *mqm, | ||
359 | void *assoc_data); | ||
360 | |||
361 | /** | ||
362 | * Get the data associated with a request id in a queue | ||
363 | * | ||
364 | * @param mq the message queue with the association | ||
365 | * @param request_id the request id we are interested in | ||
366 | * @return the associated data | ||
367 | */ | ||
368 | void * | ||
369 | GNUNET_MQ_assoc_get (struct GNUNET_MQ_MessageQueue *mq, uint32_t request_id); | ||
370 | |||
371 | |||
372 | /** | ||
373 | * Remove the association for a request id | ||
374 | * | ||
375 | * @param mq the message queue with the association | ||
376 | * @param request_id the request id we want to remove | ||
377 | * @return the associated data | ||
378 | */ | ||
379 | void * | ||
380 | GNUNET_MQ_assoc_remove (struct GNUNET_MQ_MessageQueue *mq, uint32_t request_id); | ||
381 | |||
382 | |||
383 | |||
384 | /** | ||
385 | * Create a message queue for a GNUNET_CLIENT_Connection. | ||
386 | * If handlers are specfied, receive messages from the connection. | ||
387 | * | ||
388 | * @param connection the client connection | ||
389 | * @param handlers handlers for receiving messages | ||
390 | * @param cls closure for the handlers | ||
391 | * @return the message queue | ||
392 | */ | ||
393 | struct GNUNET_MQ_MessageQueue * | ||
394 | GNUNET_MQ_queue_for_connection_client (struct GNUNET_CLIENT_Connection *connection, | ||
395 | const struct GNUNET_MQ_Handler *handlers, | ||
396 | void *cls); | ||
397 | |||
398 | |||
399 | /** | ||
400 | * Create a message queue for a GNUNET_STREAM_Socket. | ||
401 | * | ||
402 | * @param client the client | ||
403 | * @return the message queue | ||
404 | */ | ||
405 | struct GNUNET_MQ_MessageQueue * | ||
406 | GNUNET_MQ_queue_for_server_client (struct GNUNET_SERVER_Client *client); | ||
407 | |||
408 | |||
409 | /** | ||
410 | * Create a message queue for the specified handlers. | ||
411 | * | ||
412 | * @param send function the implements sending messages | ||
413 | * @param destroy function that implements destroying the queue | ||
414 | * @param state for the queue, passed to 'send' and 'destroy' | ||
415 | * @param handlers array of message handlers | ||
416 | * @param error_handler handler for read and write errors | ||
417 | * @return a new message queue | ||
418 | */ | ||
419 | struct GNUNET_MQ_MessageQueue * | ||
420 | GNUNET_MQ_queue_for_callbacks (GNUNET_MQ_SendImpl send, | ||
421 | GNUNET_MQ_DestroyImpl destroy, | ||
422 | void *impl_state, | ||
423 | struct GNUNET_MQ_Handler *handlers, | ||
424 | GNUNET_MQ_ErrorHandler error_handler, | ||
425 | void *cls); | ||
426 | |||
427 | |||
428 | |||
429 | /** | ||
430 | * Replace the handlers of a message queue with new handlers. | ||
431 | * Takes effect immediately, even for messages that already have been received, but for | ||
432 | * with the handler has not been called. | ||
433 | * | ||
434 | * @param mq message queue | ||
435 | * @param new_handlers new handlers | ||
436 | * @param cls new closure for the handlers | ||
437 | */ | ||
438 | void | ||
439 | GNUNET_MQ_replace_handlers (struct GNUNET_MQ_MessageQueue *mq, | ||
440 | const struct GNUNET_MQ_Handler *new_handlers, | ||
441 | void *cls); | ||
442 | |||
443 | |||
444 | /** | ||
445 | * Call a callback once the message has been sent, that is, the message | ||
446 | * can not be canceled anymore. | ||
447 | * There can be only one notify sent callback per message. | ||
448 | * | ||
449 | * @param mqm message to call the notify callback for | ||
450 | * @param cb the notify callback | ||
451 | * @param cls closure for the callback | ||
452 | */ | ||
453 | void | ||
454 | GNUNET_MQ_notify_sent (struct GNUNET_MQ_Message *mqm, | ||
455 | GNUNET_MQ_NotifyCallback cb, | ||
456 | void *cls); | ||
457 | |||
458 | |||
459 | /** | ||
460 | * Destroy the message queue. | ||
461 | * | ||
462 | * @param mq message queue to destroy | ||
463 | */ | ||
464 | void | ||
465 | GNUNET_MQ_destroy (struct GNUNET_MQ_MessageQueue *mq); | ||
466 | |||
467 | |||
468 | /** | ||
469 | * Call the right callback for a message. | ||
470 | * | ||
471 | * @param mq message queue with the handlers | ||
472 | * @param mh message to dispatch | ||
473 | */ | ||
474 | void | ||
475 | GNUNET_MQ_dispatch (struct GNUNET_MQ_MessageQueue *mq, | ||
476 | const struct GNUNET_MessageHeader *mh); | ||
477 | |||
478 | #endif | ||