don't run set with valgrind per default
[oweals/gnunet.git] / src / include / gnunet_mq_lib.h
index 35313263ddb56560ee2ceb281cf80e31cd01a482..b05128ccc3bd8314abe892c91ee495145175ffd3 100644 (file)
@@ -32,8 +32,8 @@
  *
  * @{
  */
-#ifndef GNUNET_MQ_H
-#define GNUNET_MQ_H
+#ifndef GNUNET_MQ_LIB_H
+#define GNUNET_MQ_LIB_H
 
 
 /**
@@ -42,7 +42,8 @@
  * The allocated message will already have the type and size field set.
  *
  * @param mvar variable to store the allocated message in;
- *             must have a header field
+ *             must have a header field;
+ *             can be NULL
  * @param esize extra space to allocate after the message
  * @param type type of the message
  * @return the MQ message
@@ -54,7 +55,8 @@
  * The contained message will already have the type and size field set.
  *
  * @param mvar variable to store the allocated message in;
- *             must have a header field
+ *             must have a header field;
+ *             can be NULL
  * @param type type of the message
  * @return the allocated envelope
  */
  * @param mh message to nest
  * @return a newly allocated 'struct GNUNET_MQ_Envelope *'
  */
-#define GNUNET_MQ_msg_nested_mh(mvar, type, mh) GNUNET_MQ_msg_nested_mh_((((void)(mvar)->header), (struct GNUNET_MessageHeader**) &(mvar)), sizeof (*(mvar)), (type), mh)
+#define GNUNET_MQ_msg_nested_mh(mvar, type, mh) \
+  ({struct GNUNET_MQ_Envelope *_ev;\
+    _ev = GNUNET_MQ_msg_nested_mh_((struct GNUNET_MessageHeader**) &(mvar),\
+                                   sizeof (*(mvar)),\
+                                   (type),\
+                                   (mh));\
+   (void)(mvar)->header; /* type check */\
+   _ev;})
 
 
 /**
  * @param mh message header to extract nested message header from
  * @param base_size size of the message before the nested message's header appears
  * @return pointer to the nested message, does not copy the message
+ *         OR NULL in case of a malformed message.
  */
 const struct GNUNET_MessageHeader *
 GNUNET_MQ_extract_nested_mh_ (const struct GNUNET_MessageHeader *mh,
@@ -171,7 +181,13 @@ enum GNUNET_MQ_Error
    * We received a message that was malformed and thus
    * could not be passed to its handler.
    */
-  GNUNET_MQ_ERROR_MALFORMED = 8
+  GNUNET_MQ_ERROR_MALFORMED = 8,
+
+  /**
+   * We received a message for which we have no matching
+   * handler.
+   */
+  GNUNET_MQ_ERROR_NO_MATCH = 16
 };
 
 
@@ -238,15 +254,6 @@ typedef void
                          void *impl_state);
 
 
-/**
- * Callback used for notifications
- *
- * @param cls closure
- */
-typedef void
-(*GNUNET_MQ_NotifyCallback) (void *cls);
-
-
 /**
  * Generic error handler, called with the appropriate
  * error code and the same closure specified at the creation of
@@ -261,6 +268,66 @@ typedef void
                            enum GNUNET_MQ_Error error);
 
 
+/**
+ * Insert @a env into the envelope DLL starting at @a env_head
+ * Note that @a env must not be in any MQ while this function
+ * is used with DLLs defined outside of the MQ module.  This
+ * is just in case some application needs to also manage a
+ * FIFO of envelopes independent of MQ itself and wants to
+ * re-use the pointers internal to @a env.  Use with caution.
+ *
+ * @param[in|out] env_head of envelope DLL
+ * @param[in|out] env_tail tail of envelope DLL
+ * @param[in|out] env element to insert at the tail
+ */
+void
+GNUNET_MQ_dll_insert_tail (struct GNUNET_MQ_Envelope **env_head,
+                           struct GNUNET_MQ_Envelope **env_tail,
+                           struct GNUNET_MQ_Envelope *env);
+
+
+/**
+ * Remove @a env from the envelope DLL starting at @a env_head.
+ * Note that @a env must not be in any MQ while this function
+ * is used with DLLs defined outside of the MQ module. This
+ * is just in case some application needs to also manage a
+ * FIFO of envelopes independent of MQ itself and wants to
+ * re-use the pointers internal to @a env.  Use with caution.
+ *
+ * @param[in|out] env_head of envelope DLL
+ * @param[in|out] env_tail tail of envelope DLL
+ * @param[in|out] env element to remove from the DLL
+ */
+void
+GNUNET_MQ_dll_remove (struct GNUNET_MQ_Envelope **env_head,
+                      struct GNUNET_MQ_Envelope **env_tail,
+                      struct GNUNET_MQ_Envelope *env);
+
+
+/**
+ * Copy an array of handlers.
+ *
+ * Useful if the array has been delared in local memory and needs to be
+ * persisted for future use.
+ *
+ * @param handlers Array of handlers to be copied.
+ * @return A newly allocated array of handlers.
+ *         Needs to be freed with #GNUNET_free.
+ */
+struct GNUNET_MQ_MessageHandler *
+GNUNET_MQ_copy_handlers (const struct GNUNET_MQ_MessageHandler *handlers);
+
+
+/**
+ * Count the handlers in a handler array.
+ *
+ * @param handlers Array of handlers to be counted.
+ * @return The number of handlers in the array.
+ */
+unsigned int
+GNUNET_MQ_count_handlers (const struct GNUNET_MQ_MessageHandler *handlers);
+
+
 /**
  * Message handler for a specific message type.
  */
@@ -323,27 +390,26 @@ struct GNUNET_MQ_MessageHandler
  *                      const struct GNUNET_MessageTest *msg)
  * { ... }
  *
- * GNUNET_MQ_hd_fixed_size(test_message,
- *                         GNUNET_MESSAGE_TYPE_TEST,
- *                         struct GNUNET_MessageTest);
  * struct GNUNET_MQ_MessageHandler handlers[] = {
- *   make_test_message_handler (),
+ *   GNUNET_MQ_hd_fixed_size(test_message,
+ *                           GNUNET_MESSAGE_TYPE_TEST,
+ *                           struct GNUNET_MessageTest,
+ *                           "context"),
  *   GNUNET_MQ_handler_end()
  * };
  *
  * @param name unique basename for the functions
  * @param code message type constant
  * @param str type of the message (a struct)
+ * @param ctx context for the callbacks
  */
-#define GNUNET_MQ_hd_fixed_size(name,code,str)   \
-  struct GNUNET_MQ_MessageHandler                           \
-  make_##name##_handler (void *cls) {                        \
-    void (*cb)(void *cls, const str *msg) = &handle_##name;  \
-    struct GNUNET_MQ_MessageHandler mh = {                  \
-      NULL, (GNUNET_MQ_MessageCallback) cb,                  \
-      cls, code, sizeof (str) };                             \
-    return mh;                                               \
-  }
+#define GNUNET_MQ_hd_fixed_size(name,code,str,ctx)           \
+  ({                                                         \
+    void (*_cb)(void *cls, const str *msg) = &handle_##name; \
+    ((struct GNUNET_MQ_MessageHandler) {                     \
+      NULL, (GNUNET_MQ_MessageCallback) _cb,                 \
+      (ctx), (code), sizeof (str) });                        \
+  })
 
 
 /**
@@ -356,9 +422,6 @@ struct GNUNET_MQ_MessageHandler
  * The macro is to be used as follows:
  * <code>
  * struct GNUNET_MessageTest { ... }; // can be variable size
- * GNUNET_MQ_hd_var_size(test_message,
- *                       GNUNET_MESSAGE_TYPE_TEST,
- *                       struct GNUNET_MessageTest);
  * static int
  * check_test (void *cls,
  *             const struct GNUNET_MessageTest *msg)
@@ -377,25 +440,27 @@ struct GNUNET_MQ_MessageHandler
  * }
  *
  * struct GNUNET_MQ_MessageHandler handlers[] = {
- *   make_test_message_handler ("context"),
+ *   GNUNET_MQ_hd_var_size(test_message,
+ *                         GNUNET_MESSAGE_TYPE_TEST,
+ *                         struct GNUNET_MessageTest,
+ *                         "context"),
  *   GNUNET_MQ_handler_end()
  * };
  *
  * @param name unique basename for the functions
  * @param code message type constant
  * @param str type of the message (a struct)
+ * @param ctx context for the callbacks
  */
-#define GNUNET_MQ_hd_var_size(name,code,str)               \
-  struct GNUNET_MQ_MessageHandler                         \
-  make_##name##_handler (void *ctx) {                     \
-    int (*mv)(void *cls, const str *msg) = &check_##name;  \
-    void (*cb)(void *cls, const str *msg) = &handle_##name;\
-    struct GNUNET_MQ_MessageHandler mh =                   \
-      { (GNUNET_MQ_MessageValidationCallback) mv,          \
-       (GNUNET_MQ_MessageCallback) cb,                    \
-       ctx, code, sizeof (str) };                         \
-    return mh;                                             \
-  }
+#define GNUNET_MQ_hd_var_size(name,code,str,ctx)             \
+  __extension__ ({                                           \
+    int (*_mv)(void *cls, const str *msg) = &check_##name;   \
+    void (*_cb)(void *cls, const str *msg) = &handle_##name; \
+    ((struct GNUNET_MQ_MessageHandler)                       \
+      { (GNUNET_MQ_MessageValidationCallback) _mv,           \
+        (GNUNET_MQ_MessageCallback) _cb,                     \
+        (ctx), (code), sizeof (str) });                      \
+  })
 
 
 /**
@@ -434,8 +499,8 @@ GNUNET_MQ_discard (struct GNUNET_MQ_Envelope *mqm);
 
 
 /**
- * Function to obtain the current envelope from
- * within #GNUNET_MQ_SendImpl implementations.
+ * Function to obtain the current envelope
+ * from within #GNUNET_MQ_SendImpl implementations.
  *
  * @param mq message queue to interrogate
  * @return the current envelope
@@ -444,6 +509,27 @@ struct GNUNET_MQ_Envelope *
 GNUNET_MQ_get_current_envelope (struct GNUNET_MQ_Handle *mq);
 
 
+/**
+ * Function to copy an envelope.  The envelope must not yet
+ * be in any queue or have any options or callbacks set.
+ *
+ * @param env envelope to copy
+ * @return copy of @a env
+ */
+struct GNUNET_MQ_Envelope *
+GNUNET_MQ_env_copy (struct GNUNET_MQ_Envelope *env);
+
+
+/**
+ * Function to obtain the last envelope in the queue.
+ *
+ * @param mq message queue to interrogate
+ * @return the last envelope in the queue
+ */
+struct GNUNET_MQ_Envelope *
+GNUNET_MQ_get_last_envelope (struct GNUNET_MQ_Handle *mq);
+
+
 /**
  * Set application-specific options for this envelope.
  * Overrides the options set for the queue with
@@ -471,6 +557,17 @@ GNUNET_MQ_env_get_options (struct GNUNET_MQ_Envelope *env,
                           uint64_t *flags);
 
 
+/**
+ * Remove the first envelope that has not yet been sent from the message
+ * queue and return it.
+ *
+ * @param mq queue to remove envelope from
+ * @return NULL if queue is empty (or has no envelope that is not under transmission)
+ */
+struct GNUNET_MQ_Envelope *
+GNUNET_MQ_unsent_head (struct GNUNET_MQ_Handle *mq);
+
+
 /**
  * Set application-specific options for this queue.
  *
@@ -605,12 +702,12 @@ GNUNET_MQ_set_handlers_closure (struct GNUNET_MQ_Handle *mq,
  *
  * @param ev message to call the notify callback for
  * @param cb the notify callback
- * @param cls closure for the callback
+ * @param cb_cls closure for the callback
  */
 void
 GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *ev,
-                       GNUNET_MQ_NotifyCallback cb,
-                       void *cls);
+                       GNUNET_SCHEDULER_TaskCallback cb,
+                       void *cb_cls);
 
 
 /**
@@ -622,6 +719,36 @@ void
 GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq);
 
 
+/**
+ * Handle we return for callbacks registered to be
+ * notified when #GNUNET_MQ_destroy() is called on a queue.
+ */
+struct GNUNET_MQ_DestroyNotificationHandle;
+
+
+/**
+ * Register function to be called whenever @a mq is being
+ * destroyed.
+ *
+ * @param mq message queue to watch
+ * @param cb function to call on @a mq destruction
+ * @param cb_cls closure for @a cb
+ * @return handle for #GNUNET_MQ_destroy_notify_cancel().
+ */
+struct GNUNET_MQ_DestroyNotificationHandle *
+GNUNET_MQ_destroy_notify (struct GNUNET_MQ_Handle *mq,
+                         GNUNET_SCHEDULER_TaskCallback cb,
+                         void *cb_cls);
+
+/**
+ * Cancel registration from #GNUNET_MQ_destroy_notify().
+ *
+ * @param dnh handle for registration to cancel
+ */
+void
+GNUNET_MQ_destroy_notify_cancel (struct GNUNET_MQ_DestroyNotificationHandle *dnh);
+
+
 /**
  * Call the message message handler that was registered
  * for the type of the given message in the given message queue.
@@ -654,6 +781,9 @@ GNUNET_MQ_inject_error (struct GNUNET_MQ_Handle *mq,
 
 /**
  * Call the send implementation for the next queued message, if any.
+ * Calls the send notification for the current message unless
+ * #GNUNET_MQ_impl_send_in_flight was called for this envelope.
+ *
  * Only useful for implementing message queues, results in undefined
  * behavior if not used carefully.
  *
@@ -664,18 +794,17 @@ GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq);
 
 
 /**
- * Get the message that should currently be sent.  The returned
- * message is only valid until #GNUNET_MQ_impl_send_continue is
- * called.  Fails if there is no current message.  Only useful for
- * implementing message queues, results in undefined behavior if not
- * used carefully.
+ * Call the send notification for the current message, but do not
+ * try to send the next message until #gnunet_mq_impl_send_continue
+ * is called.
  *
- * @param mq message queue with the current message, only valid
- *        until #GNUNET_MQ_impl_send_continue() is called
- * @return message to send, never NULL
+ * Only useful for implementing message queues, results in undefined
+ * behavior if not used carefully.
+ *
+ * @param mq message queue to send the next message with
  */
-const struct GNUNET_MessageHeader *
-GNUNET_MQ_impl_current (struct GNUNET_MQ_Handle *mq);
+void
+GNUNET_MQ_impl_send_in_flight (struct GNUNET_MQ_Handle *mq);
 
 
 /**
@@ -696,6 +825,19 @@ void *
 GNUNET_MQ_impl_state (struct GNUNET_MQ_Handle *mq);
 
 
+/**
+ * Get the message that should currently be sent.
+ * Fails if there is no current message.
+ * Only useful for implementing message queues,
+ * results in undefined behavior if not used carefully.
+ *
+ * @param mq message queue with the current message
+ * @return message to send, never NULL
+ */
+const struct GNUNET_MessageHeader *
+GNUNET_MQ_impl_current (struct GNUNET_MQ_Handle *mq);
+
+
 #endif
 
 /** @} */ /* end of group mq */