2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @author Florian Dold
24 * @brief general purpose request queue
29 #include "gnunet_common.h"
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.
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
43 #define GNUNET_MQ_msg_extra(mvar, esize, type) GNUNET_MQ_msg_((((void)(mvar)->header), (struct GNUNET_MessageHeader**) &(mvar)), (esize) + sizeof *(mvar), (type))
46 * Allocate a GNUNET_MQ_Message.
47 * The allocated message will already have the type and size field set.
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
54 #define GNUNET_MQ_msg(mvar, type) GNUNET_MQ_msg_extra(mvar, 0, type)
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)
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
70 #define GNUNET_MQ_nest(mqm, src, len) GNUNET_MQ_nest_ (&mqm, src, len)
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)
81 * @param mqm MQ message to augment with additional data
82 * @param mh the message to append, must be of type 'struct GNUNET_MessageHeader *'
84 #define GNUNET_MQ_nest_mh(mqm, mh) ((NULL == mh) ? (GNUNET_OK) : GNUNET_MQ_nest((mqm), (mh), ntohs ((mh)->size)))
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.
91 * @param type type of the message
93 #define GNUNET_MQ_msg_header(type) GNUNET_MQ_msg_ (NULL, sizeof (struct GNUNET_MessageHeader), type)
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.
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
104 #define GNUNET_MQ_msg_header_extra(mh, esize, type) GNUNET_MQ_msg_ (&mh, (esize) + sizeof (struct GNUNET_MessageHeader), type)
108 * End-marker for the handlers array
110 #define GNUNET_MQ_HANDLERS_END {NULL, 0, 0}
113 struct GNUNET_MQ_MessageQueue;
115 struct GNUNET_MQ_Message;
119 GNUNET_MQ_ERROR_READ = 1,
120 GNUNET_MQ_ERROR_WRITE = 2,
121 GNUNET_MQ_ERROR_TIMEOUT = 4
126 * Called when a message has been received.
129 * @param msg the received message
131 typedef void (*GNUNET_MQ_MessageCallback) (void *cls, const struct GNUNET_MessageHeader *msg);
135 * Signature of functions implementing the
136 * sending part of a message queue
138 * @param q the message queue
139 * @param m the message
142 (*GNUNET_MQ_SendImpl) (struct GNUNET_MQ_MessageQueue *q, struct GNUNET_MQ_Message *m);
146 (*GNUNET_MQ_DestroyImpl) (struct GNUNET_MQ_MessageQueue *q);
150 * Callback used for notifications
154 typedef void (*GNUNET_MQ_NotifyCallback) (void *cls);
157 typedef void (*GNUNET_MQ_ErrorHandler) (void *cls, enum GNUNET_MQ_Error error);
160 struct GNUNET_MQ_Message
163 * Messages are stored in a linked list
165 struct GNUNET_MQ_Message *next;
168 * Messages are stored in a linked list
170 struct GNUNET_MQ_Message *prev;
173 * Actual allocated message header,
174 * usually points to the end of the containing GNUNET_MQ_Message
176 struct GNUNET_MessageHeader *mh;
179 * Queue the message is queued in, NULL if message is not queued.
181 struct GNUNET_MQ_MessageQueue *parent_queue;
184 * Called after the message was sent irrevokably
186 GNUNET_MQ_NotifyCallback sent_cb;
189 * Closure for send_cb
196 * Handle to a message queue.
198 struct GNUNET_MQ_MessageQueue
201 * Handlers array, or NULL if the queue should not receive messages
203 const struct GNUNET_MQ_Handler *handlers;
206 * Closure for the handler callbacks,
207 * as well as for the error handler.
212 * Actual implementation of message sending,
213 * called when a message is added
215 GNUNET_MQ_SendImpl send_impl;
218 * Implementation-dependent queue destruction function
220 GNUNET_MQ_DestroyImpl destroy_impl;
223 * Implementation-specific state
228 * Callback will be called when an error occurs.
230 GNUNET_MQ_ErrorHandler error_handler;
233 * Linked list of messages pending to be sent
235 struct GNUNET_MQ_Message *msg_head;
238 * Linked list of messages pending to be sent
240 struct GNUNET_MQ_Message *msg_tail;
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.
247 struct GNUNET_MQ_Message *current_msg;
250 * Map of associations, lazily allocated
252 struct GNUNET_CONTAINER_MultiHashMap32 *assoc_map;
255 * Next id that should be used for the assoc_map,
256 * initialized lazily to a random value together with
264 * Message handler for a specific message type.
266 struct GNUNET_MQ_Handler
269 * Callback, called every time a new message of
270 * the specified type has been receied.
272 GNUNET_MQ_MessageCallback cb;
276 * Type of the message this handler covers.
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.
286 uint16_t expected_size;
291 * Create a new message for MQ.
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
298 struct GNUNET_MQ_Message *
299 GNUNET_MQ_msg_ (struct GNUNET_MessageHeader **mhp, uint16_t size, uint16_t type);
303 * Resize the the mq message pointed to by mqmp,
304 * and append the given data to it.
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)
313 GNUNET_MQ_nest_ (struct GNUNET_MQ_Message **mqmp,
314 const void *src, uint16_t len);
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.
322 * @param mqm the message to discard
325 GNUNET_MQ_discard (struct GNUNET_MQ_Message *mqm);
329 * Send a message with the give message queue.
330 * May only be called once per message.
332 * @param mq message queue
333 * @param mqm the message to send.
336 GNUNET_MQ_send (struct GNUNET_MQ_MessageQueue *mq, struct GNUNET_MQ_Message *mqm);
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
343 * @param mqm queued message to cancel
346 GNUNET_MQ_send_cancel (struct GNUNET_MQ_Message *mqm);
350 * Associate the assoc_data in mq with a unique request id.
352 * @param mq message queue, id will be unique for the queue
353 * @param mqm message to associate
354 * @param assoc_data to associate
357 GNUNET_MQ_assoc_add (struct GNUNET_MQ_MessageQueue *mq,
358 struct GNUNET_MQ_Message *mqm,
362 * Get the data associated with a request id in a queue
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
369 GNUNET_MQ_assoc_get (struct GNUNET_MQ_MessageQueue *mq, uint32_t request_id);
373 * Remove the association for a request id
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
380 GNUNET_MQ_assoc_remove (struct GNUNET_MQ_MessageQueue *mq, uint32_t request_id);
385 * Create a message queue for a GNUNET_CLIENT_Connection.
386 * If handlers are specfied, receive messages from the connection.
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
393 struct GNUNET_MQ_MessageQueue *
394 GNUNET_MQ_queue_for_connection_client (struct GNUNET_CLIENT_Connection *connection,
395 const struct GNUNET_MQ_Handler *handlers,
400 * Create a message queue for a GNUNET_STREAM_Socket.
402 * @param client the client
403 * @return the message queue
405 struct GNUNET_MQ_MessageQueue *
406 GNUNET_MQ_queue_for_server_client (struct GNUNET_SERVER_Client *client);
410 * Create a message queue for the specified handlers.
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
419 struct GNUNET_MQ_MessageQueue *
420 GNUNET_MQ_queue_for_callbacks (GNUNET_MQ_SendImpl send,
421 GNUNET_MQ_DestroyImpl destroy,
423 struct GNUNET_MQ_Handler *handlers,
424 GNUNET_MQ_ErrorHandler error_handler,
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.
434 * @param mq message queue
435 * @param new_handlers new handlers
436 * @param cls new closure for the handlers
439 GNUNET_MQ_replace_handlers (struct GNUNET_MQ_MessageQueue *mq,
440 const struct GNUNET_MQ_Handler *new_handlers,
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.
449 * @param mqm message to call the notify callback for
450 * @param cb the notify callback
451 * @param cls closure for the callback
454 GNUNET_MQ_notify_sent (struct GNUNET_MQ_Message *mqm,
455 GNUNET_MQ_NotifyCallback cb,
460 * Destroy the message queue.
462 * @param mq message queue to destroy
465 GNUNET_MQ_destroy (struct GNUNET_MQ_MessageQueue *mq);
469 * Call the right callback for a message.
471 * @param mq message queue with the handlers
472 * @param mh message to dispatch
475 GNUNET_MQ_dispatch (struct GNUNET_MQ_MessageQueue *mq,
476 const struct GNUNET_MessageHeader *mh);