aboutsummaryrefslogtreecommitdiff
path: root/src/include/gnunet_mq_lib.h
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-05-04 22:16:24 +0200
committerChristian Grothoff <christian@grothoff.org>2019-05-04 22:16:24 +0200
commit80f480c752fd8dfa1be51d78fce314d9f0650b50 (patch)
tree459c21a3fde3b5f66194ac9960632de53586c5f0 /src/include/gnunet_mq_lib.h
parent3d2a951fa12546c09809f0a4d7e789ef8e971b03 (diff)
downloadgnunet-80f480c752fd8dfa1be51d78fce314d9f0650b50.tar.gz
gnunet-80f480c752fd8dfa1be51d78fce314d9f0650b50.zip
simplify MQ logic to always carry the same kinds of flags, and extend transport API to pass them to (TNG) service
Diffstat (limited to 'src/include/gnunet_mq_lib.h')
-rw-r--r--src/include/gnunet_mq_lib.h288
1 files changed, 187 insertions, 101 deletions
diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h
index 2a459636a..498567ec2 100644
--- a/src/include/gnunet_mq_lib.h
+++ b/src/include/gnunet_mq_lib.h
@@ -49,7 +49,10 @@
49 * @param type type of the message 49 * @param type type of the message
50 * @return the MQ message 50 * @return the MQ message
51 */ 51 */
52#define GNUNET_MQ_msg_extra(mvar, esize, type) GNUNET_MQ_msg_(((struct GNUNET_MessageHeader**) &(mvar)), (esize) + sizeof *(mvar), (type)) 52#define GNUNET_MQ_msg_extra(mvar, esize, type) \
53 GNUNET_MQ_msg_ (((struct GNUNET_MessageHeader **) &(mvar)), \
54 (esize) + sizeof *(mvar), \
55 (type))
53 56
54/** 57/**
55 * Allocate a GNUNET_MQ_Envelope. 58 * Allocate a GNUNET_MQ_Envelope.
@@ -61,7 +64,7 @@
61 * @param type type of the message 64 * @param type type of the message
62 * @return the allocated envelope 65 * @return the allocated envelope
63 */ 66 */
64#define GNUNET_MQ_msg(mvar, type) GNUNET_MQ_msg_extra(mvar, 0, type) 67#define GNUNET_MQ_msg(mvar, type) GNUNET_MQ_msg_extra (mvar, 0, type)
65 68
66 69
67/** 70/**
@@ -70,7 +73,8 @@
70 * 73 *
71 * @param type type of the message 74 * @param type type of the message
72 */ 75 */
73#define GNUNET_MQ_msg_header(type) GNUNET_MQ_msg_ (NULL, sizeof (struct GNUNET_MessageHeader), type) 76#define GNUNET_MQ_msg_header(type) \
77 GNUNET_MQ_msg_ (NULL, sizeof (struct GNUNET_MessageHeader), type)
74 78
75 79
76/** 80/**
@@ -81,7 +85,8 @@
81 * @param esize extra space to allocate after the message header 85 * @param esize extra space to allocate after the message header
82 * @param type type of the message 86 * @param type type of the message
83 */ 87 */
84#define GNUNET_MQ_msg_header_extra(mh, esize, type) GNUNET_MQ_msg_ (&mh, (esize) + sizeof (struct GNUNET_MessageHeader), type) 88#define GNUNET_MQ_msg_header_extra(mh, esize, type) \
89 GNUNET_MQ_msg_ (&mh, (esize) + sizeof (struct GNUNET_MessageHeader), type)
85 90
86 91
87/** 92/**
@@ -94,14 +99,16 @@
94 * @param mh message to nest 99 * @param mh message to nest
95 * @return a newly allocated 'struct GNUNET_MQ_Envelope *' 100 * @return a newly allocated 'struct GNUNET_MQ_Envelope *'
96 */ 101 */
97#define GNUNET_MQ_msg_nested_mh(mvar, type, mh) \ 102#define GNUNET_MQ_msg_nested_mh(mvar, type, mh) \
98 ({struct GNUNET_MQ_Envelope *_ev;\ 103 ({ \
99 _ev = GNUNET_MQ_msg_nested_mh_((struct GNUNET_MessageHeader**) &(mvar),\ 104 struct GNUNET_MQ_Envelope *_ev; \
100 sizeof (*(mvar)),\ 105 _ev = GNUNET_MQ_msg_nested_mh_ ((struct GNUNET_MessageHeader **) &(mvar), \
101 (type),\ 106 sizeof (*(mvar)), \
102 (mh));\ 107 (type), \
103 (void)(mvar)->header; /* type check */\ 108 (mh)); \
104 _ev;}) 109 (void) (mvar)->header; /* type check */ \
110 _ev; \
111 })
105 112
106 113
107/** 114/**
@@ -112,7 +119,9 @@
112 * @return a 'struct GNUNET_MessageHeader *' that points at the nested message of the given message, 119 * @return a 'struct GNUNET_MessageHeader *' that points at the nested message of the given message,
113 * or NULL if the given message in @a var does not have any space after the message struct 120 * or NULL if the given message in @a var does not have any space after the message struct
114 */ 121 */
115#define GNUNET_MQ_extract_nested_mh(var) GNUNET_MQ_extract_nested_mh_ ((struct GNUNET_MessageHeader *) (var), sizeof (*(var))) 122#define GNUNET_MQ_extract_nested_mh(var) \
123 GNUNET_MQ_extract_nested_mh_ ((struct GNUNET_MessageHeader *) (var), \
124 sizeof (*(var)))
116 125
117 126
118/** 127/**
@@ -213,14 +222,89 @@ enum GNUNET_MQ_Error
213 222
214 223
215/** 224/**
225 * Per envelope preferences and priorities.
226 */
227enum GNUNET_MQ_PriorityPreferences
228{
229
230 /**
231 * Lowest priority, i.e. background traffic (i.e. NSE, FS).
232 * This is the default!
233 */
234 GNUNET_MQ_PRIO_BACKGROUND = 0,
235
236 /**
237 * Best-effort traffic (i.e. CADET relay, DHT)
238 */
239 GNUNET_MQ_PRIO_BEST_EFFORT = 1,
240
241 /**
242 * Urgent traffic (local peer, i.e. Conversation).
243 */
244 GNUNET_MQ_PRIO_URGENT = 2,
245
246 /**
247 * Highest priority, control traffic (i.e. CORE/CADET KX).
248 */
249 GNUNET_MQ_PRIO_CRITICAL_CONTROL = 3,
250
251 /**
252 * Bit mask to apply to extract the priority bits.
253 */
254 GNUNET_MQ_PRIORITY_MASK = 3,
255
256 /**
257 * Flag to indicate that unreliable delivery is acceptable. This
258 * means TRANSPORT will not attempt to receive an
259 * acknowledgment. CORE will just pass this flag through. CADET
260 * will use unreliable delivery if this flag is set.
261 *
262 * Note that even without this flag, messages may be lost by
263 * TRANSPORT and CORE.
264 *
265 * Thus, how "strong" the semantics of reliable delivery are depends
266 * on the layer!
267 */
268 GNUNET_MQ_PREF_UNRELIABLE = 16,
269
270 /**
271 * Flag to indicate that low latency is important. This flag must
272 * generally not be used in combination with
273 * #GNUNET_MQ_PREF_CORKING_ALLOWED as it would be a contradiction.
274 * When this flags is set, the envelope may skip forward in the
275 * queue (depending on priority) and also TRANSPORT should attempt
276 * to pick a communicator with particularly low latency.
277 */
278 GNUNET_MQ_PREF_LOW_LATENCY = 32,
279
280 /**
281 * Flag to indicate that CORKing is acceptable. This allows the
282 * receiver to delay transmission in hope of combining this message
283 * with other messages into a larger transmission with less
284 * per-message overhead.
285 */
286 GNUNET_MQ_PREF_CORK_ALLOWED = 64,
287
288 /**
289 * Flag to indicate that high bandwidth is desired. This flag
290 * indicates that the method chosen for transmission should focus on
291 * overall goodput. It rarely makes sense to combine this flag with
292 * #GNUNET_MQ_PREF_LOW_LATENCY.
293 */
294 GNUNET_MQ_PREF_GOODPUT = 128
295
296};
297
298
299/**
216 * Called when a message has been received. 300 * Called when a message has been received.
217 * 301 *
218 * @param cls closure 302 * @param cls closure
219 * @param msg the received message 303 * @param msg the received message
220 */ 304 */
221typedef void 305typedef void (*GNUNET_MQ_MessageCallback) (
222(*GNUNET_MQ_MessageCallback) (void *cls, 306 void *cls,
223 const struct GNUNET_MessageHeader *msg); 307 const struct GNUNET_MessageHeader *msg);
224 308
225 309
226/** 310/**
@@ -231,9 +315,9 @@ typedef void
231 * @return #GNUNET_OK if the message is well-formed, 315 * @return #GNUNET_OK if the message is well-formed,
232 * #GNUNET_SYSERR if not 316 * #GNUNET_SYSERR if not
233 */ 317 */
234typedef int 318typedef int (*GNUNET_MQ_MessageValidationCallback) (
235(*GNUNET_MQ_MessageValidationCallback) (void *cls, 319 void *cls,
236 const struct GNUNET_MessageHeader *msg); 320 const struct GNUNET_MessageHeader *msg);
237 321
238 322
239/** 323/**
@@ -244,10 +328,9 @@ typedef int
244 * @param msg the message to send 328 * @param msg the message to send
245 * @param impl_state state of the implementation 329 * @param impl_state state of the implementation
246 */ 330 */
247typedef void 331typedef void (*GNUNET_MQ_SendImpl) (struct GNUNET_MQ_Handle *mq,
248(*GNUNET_MQ_SendImpl) (struct GNUNET_MQ_Handle *mq, 332 const struct GNUNET_MessageHeader *msg,
249 const struct GNUNET_MessageHeader *msg, 333 void *impl_state);
250 void *impl_state);
251 334
252 335
253/** 336/**
@@ -259,9 +342,8 @@ typedef void
259 * @param mq the message queue to destroy 342 * @param mq the message queue to destroy
260 * @param impl_state state of the implementation 343 * @param impl_state state of the implementation
261 */ 344 */
262typedef void 345typedef void (*GNUNET_MQ_DestroyImpl) (struct GNUNET_MQ_Handle *mq,
263(*GNUNET_MQ_DestroyImpl) (struct GNUNET_MQ_Handle *mq, 346 void *impl_state);
264 void *impl_state);
265 347
266 348
267/** 349/**
@@ -270,9 +352,8 @@ typedef void
270 * @param mq message queue 352 * @param mq message queue
271 * @param impl_state state specific to the implementation 353 * @param impl_state state specific to the implementation
272 */ 354 */
273typedef void 355typedef void (*GNUNET_MQ_CancelImpl) (struct GNUNET_MQ_Handle *mq,
274(*GNUNET_MQ_CancelImpl) (struct GNUNET_MQ_Handle *mq, 356 void *impl_state);
275 void *impl_state);
276 357
277 358
278/** 359/**
@@ -284,9 +365,7 @@ typedef void
284 * @param cls closure 365 * @param cls closure
285 * @param error error code 366 * @param error error code
286 */ 367 */
287typedef void 368typedef void (*GNUNET_MQ_ErrorHandler) (void *cls, enum GNUNET_MQ_Error error);
288(*GNUNET_MQ_ErrorHandler) (void *cls,
289 enum GNUNET_MQ_Error error);
290 369
291 370
292/** 371/**
@@ -411,7 +490,10 @@ struct GNUNET_MQ_MessageHandler
411/** 490/**
412 * End-marker for the handlers array 491 * End-marker for the handlers array
413 */ 492 */
414#define GNUNET_MQ_handler_end() { NULL, NULL, NULL, 0, 0 } 493#define GNUNET_MQ_handler_end() \
494 { \
495 NULL, NULL, NULL, 0, 0 \
496 }
415 497
416 498
417/** 499/**
@@ -442,12 +524,14 @@ struct GNUNET_MQ_MessageHandler
442 * @param str type of the message (a struct) 524 * @param str type of the message (a struct)
443 * @param ctx context for the callbacks 525 * @param ctx context for the callbacks
444 */ 526 */
445#define GNUNET_MQ_hd_fixed_size(name,code,str,ctx) \ 527#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx) \
446 ({ \ 528 ({ \
447 void (*_cb)(void *cls, const str *msg) = &handle_##name; \ 529 void (*_cb) (void *cls, const str *msg) = &handle_##name; \
448 ((struct GNUNET_MQ_MessageHandler) { \ 530 ((struct GNUNET_MQ_MessageHandler){NULL, \
449 NULL, (GNUNET_MQ_MessageCallback) _cb, \ 531 (GNUNET_MQ_MessageCallback) _cb, \
450 (ctx), (code), sizeof (str) }); \ 532 (ctx), \
533 (code), \
534 sizeof (str)}); \
451 }) 535 })
452 536
453 537
@@ -491,14 +575,16 @@ struct GNUNET_MQ_MessageHandler
491 * @param str type of the message (a struct) 575 * @param str type of the message (a struct)
492 * @param ctx context for the callbacks 576 * @param ctx context for the callbacks
493 */ 577 */
494#define GNUNET_MQ_hd_var_size(name,code,str,ctx) \ 578#define GNUNET_MQ_hd_var_size(name, code, str, ctx) \
495 __extension__ ({ \ 579 __extension__({ \
496 int (*_mv)(void *cls, const str *msg) = &check_##name; \ 580 int (*_mv) (void *cls, const str *msg) = &check_##name; \
497 void (*_cb)(void *cls, const str *msg) = &handle_##name; \ 581 void (*_cb) (void *cls, const str *msg) = &handle_##name; \
498 ((struct GNUNET_MQ_MessageHandler) \ 582 ((struct GNUNET_MQ_MessageHandler){(GNUNET_MQ_MessageValidationCallback) \
499 { (GNUNET_MQ_MessageValidationCallback) _mv, \ 583 _mv, \
500 (GNUNET_MQ_MessageCallback) _cb, \ 584 (GNUNET_MQ_MessageCallback) _cb, \
501 (ctx), (code), sizeof (str) }); \ 585 (ctx), \
586 (code), \
587 sizeof (str)}); \
502 }) 588 })
503 589
504 590
@@ -512,18 +598,17 @@ struct GNUNET_MQ_MessageHandler
512 * @param an IPC message with proper type to determine 598 * @param an IPC message with proper type to determine
513 * the size, starting with a `struct GNUNET_MessageHeader` 599 * the size, starting with a `struct GNUNET_MessageHeader`
514 */ 600 */
515#define GNUNET_MQ_check_zero_termination(m) \ 601#define GNUNET_MQ_check_zero_termination(m) \
516 { \ 602 { \
517 const char *str = (const char *) &m[1]; \ 603 const char *str = (const char *) &m[1]; \
518 const struct GNUNET_MessageHeader *hdr = \ 604 const struct GNUNET_MessageHeader *hdr = \
519 (const struct GNUNET_MessageHeader *) m; \ 605 (const struct GNUNET_MessageHeader *) m; \
520 uint16_t slen = ntohs (hdr->size) - sizeof (*m); \ 606 uint16_t slen = ntohs (hdr->size) - sizeof (*m); \
521 if ( (0 == slen) || \ 607 if ((0 == slen) || (memchr (str, 0, slen) != &str[slen - 1])) \
522 (memchr (str, 0, slen) != &str[slen - 1]) ) \ 608 { \
523 { \ 609 GNUNET_break (0); \
524 GNUNET_break (0); \ 610 return GNUNET_NO; \
525 return GNUNET_NO; \ 611 } \
526 } \
527 } 612 }
528 613
529 614
@@ -539,19 +624,19 @@ struct GNUNET_MQ_MessageHandler
539 * @param an IPC message with proper type to determine 624 * @param an IPC message with proper type to determine
540 * the size, starting with a `struct GNUNET_MessageHeader` 625 * the size, starting with a `struct GNUNET_MessageHeader`
541 */ 626 */
542#define GNUNET_MQ_check_boxed_message(m) \ 627#define GNUNET_MQ_check_boxed_message(m) \
543 { \ 628 { \
544 const struct GNUNET_MessageHeader *inbox = \ 629 const struct GNUNET_MessageHeader *inbox = \
545 (const struct GNUNET_MessageHeader *) &m[1]; \ 630 (const struct GNUNET_MessageHeader *) &m[1]; \
546 const struct GNUNET_MessageHeader *hdr = \ 631 const struct GNUNET_MessageHeader *hdr = \
547 (const struct GNUNET_MessageHeader *) m; \ 632 (const struct GNUNET_MessageHeader *) m; \
548 uint16_t slen = ntohs (hdr->size) - sizeof (*m); \ 633 uint16_t slen = ntohs (hdr->size) - sizeof (*m); \
549 if ( (slen < sizeof (struct GNUNET_MessageHeader))||\ 634 if ((slen < sizeof (struct GNUNET_MessageHeader)) || \
550 (slen != ntohs (inbox->size)) ) \ 635 (slen != ntohs (inbox->size))) \
551 { \ 636 { \
552 GNUNET_break (0); \ 637 GNUNET_break (0); \
553 return GNUNET_NO; \ 638 return GNUNET_NO; \
554 } \ 639 } \
555 } 640 }
556 641
557 642
@@ -645,25 +730,34 @@ GNUNET_MQ_get_last_envelope (struct GNUNET_MQ_Handle *mq);
645 * #GNUNET_MQ_set_options() for this message only. 730 * #GNUNET_MQ_set_options() for this message only.
646 * 731 *
647 * @param env message to set options for 732 * @param env message to set options for
648 * @param flags flags to use (meaning is queue-specific) 733 * @param pp priority and preferences to set for @a env
649 * @param extra additional buffer for further data (also queue-specific)
650 */ 734 */
651void 735void
652GNUNET_MQ_env_set_options (struct GNUNET_MQ_Envelope *env, 736GNUNET_MQ_env_set_options (struct GNUNET_MQ_Envelope *env,
653 uint64_t flags, 737 enum GNUNET_MQ_PriorityPreferences pp);
654 const void *extra);
655 738
656 739
657/** 740/**
658 * Get application-specific options for this envelope. 741 * Get performance preferences set for this envelope.
659 * 742 *
660 * @param env message to set options for 743 * @param env message to set options for
661 * @param[out] flags set to flags to use (meaning is queue-specific) 744 * @return priority and preferences to use
662 * @return extra additional buffer for further data (also queue-specific) 745 */
746enum GNUNET_MQ_PriorityPreferences
747GNUNET_MQ_env_get_options (struct GNUNET_MQ_Envelope *env);
748
749
750/**
751 * Combine performance preferences set for different
752 * envelopes that are being combined into one larger envelope.
753 *
754 * @param p1 one set of preferences
755 * @param p2 second set of preferences
756 * @return combined priority and preferences to use
663 */ 757 */
664const void * 758enum GNUNET_MQ_PriorityPreferences
665GNUNET_MQ_env_get_options (struct GNUNET_MQ_Envelope *env, 759GNUNET_MQ_env_combine_options (enum GNUNET_MQ_PriorityPreferences p1,
666 uint64_t *flags); 760 enum GNUNET_MQ_PriorityPreferences p2);
667 761
668 762
669/** 763/**
@@ -681,13 +775,11 @@ GNUNET_MQ_unsent_head (struct GNUNET_MQ_Handle *mq);
681 * Set application-specific options for this queue. 775 * Set application-specific options for this queue.
682 * 776 *
683 * @param mq message queue to set options for 777 * @param mq message queue to set options for
684 * @param flags flags to use (meaning is queue-specific) 778 * @param pp priority and preferences to use by default
685 * @param extra additional buffer for further data (also queue-specific)
686 */ 779 */
687void 780void
688GNUNET_MQ_set_options (struct GNUNET_MQ_Handle *mq, 781GNUNET_MQ_set_options (struct GNUNET_MQ_Handle *mq,
689 uint64_t flags, 782 enum GNUNET_MQ_PriorityPreferences pp);
690 const void *extra);
691 783
692 784
693/** 785/**
@@ -708,8 +800,7 @@ GNUNET_MQ_get_length (struct GNUNET_MQ_Handle *mq);
708 * @param ev the envelope with the message to send. 800 * @param ev the envelope with the message to send.
709 */ 801 */
710void 802void
711GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq, 803GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev);
712 struct GNUNET_MQ_Envelope *ev);
713 804
714 805
715/** 806/**
@@ -742,8 +833,7 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev);
742 * @param assoc_data to associate 833 * @param assoc_data to associate
743 */ 834 */
744uint32_t 835uint32_t
745GNUNET_MQ_assoc_add (struct GNUNET_MQ_Handle *mq, 836GNUNET_MQ_assoc_add (struct GNUNET_MQ_Handle *mq, void *assoc_data);
746 void *assoc_data);
747 837
748 838
749/** 839/**
@@ -754,8 +844,7 @@ GNUNET_MQ_assoc_add (struct GNUNET_MQ_Handle *mq,
754 * @return the associated data 844 * @return the associated data
755 */ 845 */
756void * 846void *
757GNUNET_MQ_assoc_get (struct GNUNET_MQ_Handle *mq, 847GNUNET_MQ_assoc_get (struct GNUNET_MQ_Handle *mq, uint32_t request_id);
758 uint32_t request_id);
759 848
760 849
761/** 850/**
@@ -766,8 +855,7 @@ GNUNET_MQ_assoc_get (struct GNUNET_MQ_Handle *mq,
766 * @return the associated data 855 * @return the associated data
767 */ 856 */
768void * 857void *
769GNUNET_MQ_assoc_remove (struct GNUNET_MQ_Handle *mq, 858GNUNET_MQ_assoc_remove (struct GNUNET_MQ_Handle *mq, uint32_t request_id);
770 uint32_t request_id);
771 859
772 860
773/** 861/**
@@ -846,8 +934,8 @@ struct GNUNET_MQ_DestroyNotificationHandle;
846 */ 934 */
847struct GNUNET_MQ_DestroyNotificationHandle * 935struct GNUNET_MQ_DestroyNotificationHandle *
848GNUNET_MQ_destroy_notify (struct GNUNET_MQ_Handle *mq, 936GNUNET_MQ_destroy_notify (struct GNUNET_MQ_Handle *mq,
849 GNUNET_SCHEDULER_TaskCallback cb, 937 GNUNET_SCHEDULER_TaskCallback cb,
850 void *cb_cls); 938 void *cb_cls);
851 939
852/** 940/**
853 * Cancel registration from #GNUNET_MQ_destroy_notify(). 941 * Cancel registration from #GNUNET_MQ_destroy_notify().
@@ -855,7 +943,8 @@ GNUNET_MQ_destroy_notify (struct GNUNET_MQ_Handle *mq,
855 * @param dnh handle for registration to cancel 943 * @param dnh handle for registration to cancel
856 */ 944 */
857void 945void
858GNUNET_MQ_destroy_notify_cancel (struct GNUNET_MQ_DestroyNotificationHandle *dnh); 946GNUNET_MQ_destroy_notify_cancel (
947 struct GNUNET_MQ_DestroyNotificationHandle *dnh);
859 948
860 949
861/** 950/**
@@ -947,7 +1036,6 @@ const struct GNUNET_MessageHeader *
947GNUNET_MQ_impl_current (struct GNUNET_MQ_Handle *mq); 1036GNUNET_MQ_impl_current (struct GNUNET_MQ_Handle *mq);
948 1037
949 1038
950
951/** 1039/**
952 * Enum defining all known preference categories. 1040 * Enum defining all known preference categories.
953 */ 1041 */
@@ -977,7 +1065,7 @@ enum GNUNET_MQ_PreferenceKind
977 */ 1065 */
978 GNUNET_MQ_PREFERENCE_RELIABILITY = 3 1066 GNUNET_MQ_PREFERENCE_RELIABILITY = 3
979 1067
980 /** 1068/**
981 * Number of preference values allowed. 1069 * Number of preference values allowed.
982 */ 1070 */
983#define GNUNET_MQ_PREFERENCE_COUNT 4 1071#define GNUNET_MQ_PREFERENCE_COUNT 4
@@ -995,8 +1083,6 @@ const char *
995GNUNET_MQ_preference_to_string (enum GNUNET_MQ_PreferenceKind type); 1083GNUNET_MQ_preference_to_string (enum GNUNET_MQ_PreferenceKind type);
996 1084
997 1085
998
999
1000#endif 1086#endif
1001 1087
1002/** @} */ /* end of group mq */ 1088/** @} */ /* end of group mq */