Add vtable and methods for to_json and to_ami for Stasis messages
[asterisk/asterisk.git] / include / asterisk / stasis.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 #ifndef _ASTERISK_STASIS_H
20 #define _ASTERISK_STASIS_H
21
22 /*! \file
23  *
24  * \brief Stasis Message Bus API. See \ref stasis "Stasis Message Bus API" for
25  * detailed documentation.
26  *
27  * \author David M. Lee, II <dlee@digium.com>
28  * \since 12
29  *
30  * \page stasis Stasis Message Bus API
31  *
32  * \par Intro
33  *
34  * The Stasis Message Bus is a loosely typed mechanism for distributing messages
35  * within Asterisk. It is designed to be:
36  *  - Loosely coupled; new message types can be added in seperate modules.
37  *  - Easy to use; publishing and subscribing are straightforward operations.
38  *
39  * There are three main concepts for using the Stasis Message Bus:
40  *  - \ref stasis_message
41  *  - \ref stasis_topic
42  *  - \ref stasis_subscription
43  *
44  * \par stasis_message
45  *
46  * Central to the Stasis Message Bus is the \ref stasis_message, the messages
47  * that are sent on the bus. These messages have:
48  *  - a type (as defined by a \ref stasis_message_type)
49  *  - a value - a \c void pointer to an AO2 object
50  *  - a timestamp when it was created
51  *
52  * Once a \ref stasis_message has been created, it is immutable and cannot
53  * change. The same goes for the value of the message (although this cannot be
54  * enforced in code). Messages themselves are reference-counted, AO2 objects,
55  * along with their values. By being both reference counted and immutable,
56  * messages can be shared throughout the system without any concerns for
57  * threading.
58  *
59  * The type of a message is defined by an instance of \ref stasis_message_type,
60  * which can be created by calling stasis_message_type_create(). Message types
61  * are named, which is useful in debugging. It is recommended that the string
62  * name for a message type match the name of the struct that's stored in the
63  * message. For example, name for \ref stasis_cache_update's message type is \c
64  * "stasis_cache_update".
65  *
66  * \par stasis_topic
67  *
68  * A \ref stasis_topic is an object to which \ref stasis_subscriber's may be
69  * subscribed, and \ref stasis_message's may be published. Any message published
70  * to the topic is dispatched to all of its subscribers. The topic itself may be
71  * named, which is useful in debugging.
72  *
73  * Topics themselves are reference counted objects. Since topics are referred to
74  * by their subscibers, they will not be freed until all of their subscribers
75  * have unsubscribed. Topics are also thread safe, so no worries about
76  * publishing/subscribing/unsubscribing to a topic concurrently from multiple
77  * threads. It's also designed to handle the case of unsubscribing from a topic
78  * from within the subscription handler.
79  *
80  * \par Forwarding
81  *
82  * There is one special case of topics that's worth noting: forwarding
83  * messages. It's a fairly common use case to want to forward all the messages
84  * published on one topic to another one (for example, an aggregator topic that
85  * publishes all the events from a set of other topics). This can be
86  * accomplished easily using stasis_forward_all(). This sets up the forwarding
87  * between the two topics, and returns a \ref stasis_subscription, which can be
88  * unsubscribed to stop the forwarding.
89  *
90  * \par Caching
91  *
92  * Another common use case is to want to cache certain messages that are
93  * published on the bus. Usually these events are snapshots of the current state
94  * in the system, and it's desirable to query that state from the cache without
95  * locking the original object. It's also desirable for subscribers of the
96  * caching topic to receive messages that have both the old cache value and the
97  * new value being put into the cache. For this, we have
98  * stasis_caching_topic_create(), providing it with the topic which publishes
99  * the messages that you wish to cache, and a function that can identify
100  * cacheable messages.
101  *
102  * The returned \ref stasis_caching_topic provides a topic that forwards
103  * non-cacheable messages unchanged. A cacheable message is wrapped in a \ref
104  * stasis_cache_update message which provides the old snapshot (or \c NULL if
105  * this is a new cache entry), and the new snapshot (or \c NULL if the entry was
106  * removed from the cache). A stasis_cache_clear_create() message must be sent
107  * to the topic in order to remove entries from the cache.
108  *
109  * In order to unsubscribe a \ref stasis_caching_topic from the upstream topic,
110  * call stasis_caching_unsubscribe(). Due to cyclic references, the \ref
111  * stasis_caching_topic will not be freed until after it has been unsubscribed,
112  * and all other ao2_ref()'s have been cleaned up.
113  *
114  * \par stasis_subscriber
115  *
116  * Any topic may be subscribed to by simply providing stasis_subscribe() the
117  * \ref stasis_topic to subscribe to, a handler function and \c void pointer to
118  * data that is passed back to the handler. Invocations on the subscription's
119  * handler are serialized, but different invocations may occur on different
120  * threads (this usually isn't important unless you use thread locals or
121  * something similar).
122  *
123  * In order to stop receiving messages, call stasis_unsubscribe() with your \ref
124  * stasis_subscription. Due to cyclic references, the \ref
125  * stasis_subscription will not be freed until after it has been unsubscribed,
126  * and all other ao2_ref()'s have been cleaned up.
127  *
128  * \par Shutdown
129  *
130  * Subscriptions have two options for unsubscribing, depending upon the context
131  * in which you need to unsubscribe.
132  *
133  * If your subscription is owned by a module, and you must unsubscribe from the
134  * module_unload() function, then you'll want to use the
135  * stasis_unsubscribe_and_join() function. This will block until the final
136  * message has been received on the subscription. Otherwise, there's the danger
137  * of invoking the callback function after it has been unloaded.
138  *
139  * If your subscription is owned by an object, then your object should have an
140  * explicit shutdown() function, which calls stasis_unsubscribe(). In your
141  * subscription handler, when the stasis_subscription_final_message() has been
142  * received, decrement the refcount on your object. In your object's destructor,
143  * you may assert that stasis_subscription_is_done() to validate that the
144  * subscription's callback will no longer be invoked.
145  *
146  * \b Note: You may be tempted to simply call stasis_unsubscribe_and_join() from
147  * an object's destructor. While code that does this may work most of the time,
148  * it's got one big downside. There's a general assumption that object
149  * destruction is non-blocking. If you block the destruction waiting for the
150  * subscription to complete, there's the danger that the subscription may
151  * process a message which will bump the refcount up by one. Then it does
152  * whatever it does, decrements the refcount, which then proceeds to re-destroy
153  * the object. Now you've got hard to reproduce bugs that only show up under
154  * certain loads.
155  */
156
157 #include "asterisk/json.h"
158 #include "asterisk/manager.h"
159 #include "asterisk/utils.h"
160
161 /*! @{ */
162
163 /*!
164  * \brief Metadata about a \ref stasis_message.
165  * \since 12
166  */
167 struct stasis_message_type;
168
169 /*!
170  * \brief Opaque type for a Stasis message.
171  * \since 12
172  */
173 struct stasis_message;
174
175 /*!
176  * \brief Virtual table providing methods for messages.
177  * \since 12
178  */
179 struct stasis_message_vtable {
180         /*!
181          * \brief Build the JSON representation of the message.
182          *
183          * May be \c NULL, or may return \c NULL, to indicate no representation.
184          * The returned object should be ast_json_unref()'ed.
185          *
186          * \param message Message to convert to JSON string.
187          * \return Newly allocated JSON message.
188          * \return \c NULL on error.
189          * \return \c NULL if JSON format is not supported.
190          */
191         struct ast_json *(*to_json)(struct stasis_message *message);
192
193         /*!
194          * \brief Build the AMI representation of the message.
195          *
196          * May be \c NULL, or may return \c NULL, to indicate no representation.
197          * The returned object should be ao2_cleankup()'ed.
198          *
199          * \param message Message to convert to AMI string.
200          * \return Newly allocated \ref ast_manager_event_blob.
201          * \return \c NULL on error.
202          * \return \c NULL if AMI format is not supported.
203          */
204         struct ast_manager_event_blob *(*to_ami)(
205                 struct stasis_message *message);
206 };
207
208 /*!
209  * \brief Create a new message type.
210  *
211  * \ref stasis_message_type is an AO2 object, so ao2_cleanup() when you're done
212  * with it.
213  *
214  * \param name Name of the new type.
215  * \param vtable Virtual table of message methods. May be \c NULL.
216  * \return Pointer to the new type.
217  * \return \c NULL on error.
218  * \since 12
219  */
220 struct stasis_message_type *stasis_message_type_create(const char *name,
221         struct stasis_message_vtable *vtable);
222
223 /*!
224  * \brief Gets the name of a given message type
225  * \param type The type to get.
226  * \return Name of the type.
227  * \return \c NULL if \a type is \c NULL.
228  * \since 12
229  */
230 const char *stasis_message_type_name(const struct stasis_message_type *type);
231
232 /*!
233  * \brief Create a new message.
234  *
235  * This message is an \c ao2 object, and must be ao2_cleanup()'ed when you are done
236  * with it. Messages are also immutable, and must not be modified after they
237  * are initialized. Especially the \a data in the message.
238  *
239  * \param type Type of the message
240  * \param data Immutable data that is the actual contents of the message
241  * \return New message
242  * \return \c NULL on error
243  * \since 12
244  */
245 struct stasis_message *stasis_message_create(struct stasis_message_type *type, void *data);
246
247 /*!
248  * \brief Get the message type for a \ref stasis_message.
249  * \param msg Message to type
250  * \return Type of \a msg
251  * \return \c NULL if \a msg is \c NULL.
252  * \since 12
253  */
254 struct stasis_message_type *stasis_message_type(const struct stasis_message *msg);
255
256 /*!
257  * \brief Get the data contained in a message.
258  * \param msg Message.
259  * \return Immutable data pointer
260  * \return \c NULL if msg is \c NULL.
261  * \since 12
262  */
263 void *stasis_message_data(const struct stasis_message *msg);
264
265 /*!
266  * \brief Get the time when a message was created.
267  * \param msg Message.
268  * \return Pointer to the \a timeval when the message was created.
269  * \return \c NULL if msg is \c NULL.
270  * \since 12
271  */
272 const struct timeval *stasis_message_timestamp(const struct stasis_message *msg);
273
274 /*!
275  * \brief Build the JSON representation of the message.
276  *
277  * May return \c NULL, to indicate no representation. The returned object should
278  * be ast_json_unref()'ed.
279  *
280  * \param message Message to convert to JSON string.
281  * \return Newly allocated string with JSON message.
282  * \return \c NULL on error.
283  * \return \c NULL if JSON format is not supported.
284  */
285 struct ast_json *stasis_message_to_json(struct stasis_message *message);
286
287 /*!
288  * \brief Build the AMI representation of the message.
289  *
290  * May return \c NULL, to indicate no representation. The returned object should
291  * be ao2_cleanup()'ed.
292  *
293  * \param message Message to convert to AMI.
294  * \return \c NULL on error.
295  * \return \c NULL if AMI format is not supported.
296  */
297 struct ast_manager_event_blob *stasis_message_to_ami(
298         struct stasis_message *message);
299
300 /*! @} */
301
302 /*! @{ */
303
304 /*!
305  * \brief A topic to which messages may be posted, and subscribers, well, subscribe
306  * \since 12
307  */
308 struct stasis_topic;
309
310 /*!
311  * \brief Create a new topic.
312  * \param name Name of the new topic.
313  * \return New topic instance.
314  * \return \c NULL on error.
315  * \since 12
316  */
317 struct stasis_topic *stasis_topic_create(const char *name);
318
319 /*!
320  * \brief Return the name of a topic.
321  * \param topic Topic.
322  * \return Name of the topic.
323  * \return \c NULL if topic is \c NULL.
324  * \since 12
325  */
326 const char *stasis_topic_name(const struct stasis_topic *topic);
327
328 /*!
329  * \brief Publish a message to a topic's subscribers.
330  * \param topic Topic.
331  * \param message Message to publish.
332  * \since 12
333  */
334 void stasis_publish(struct stasis_topic *topic, struct stasis_message *message);
335
336 /*!
337  * \brief Publish a message from a specified topic to all the subscribers of a
338  * possibly different topic.
339  * \param topic Topic to publish message to.
340  * \param topic Original topic message was from.
341  * \param message Message
342  * \since 12
343  */
344 void stasis_forward_message(struct stasis_topic *topic,
345                             struct stasis_topic *publisher_topic,
346                             struct stasis_message *message);
347
348 /*! @} */
349
350 /*! @{ */
351
352 /*!
353  * \brief Opaque type for a Stasis subscription.
354  * \since 12
355  */
356 struct stasis_subscription;
357
358 /*!
359  * \brief Callback function type for Stasis subscriptions.
360  * \param data Data field provided with subscription.
361  * \param topic Topic to which the message was published.
362  * \param message Published message.
363  * \since 12
364  */
365 typedef void (*stasis_subscription_cb)(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message);
366
367 /*!
368  * \brief Create a subscription.
369  *
370  * In addition to being AO2 managed memory (requiring an ao2_cleanup() to free
371  * up this reference), the subscription must be explicitly unsubscribed from its
372  * topic using stasis_unsubscribe().
373  *
374  * The invocations of the callback are serialized, but may not always occur on
375  * the same thread. The invocation order of different subscriptions is
376  * unspecified.
377  *
378  * \param topic Topic to subscribe to.
379  * \param callback Callback function for subscription messages.
380  * \param data Data to be passed to the callback, in addition to the message.
381  * \return New \ref stasis_subscription object.
382  * \return \c NULL on error.
383  * \since 12
384  */
385 struct stasis_subscription *stasis_subscribe(struct stasis_topic *topic,
386         stasis_subscription_cb callback, void *data);
387
388 /*!
389  * \brief Cancel a subscription.
390  *
391  * Note that in an asynchronous system, there may still be messages queued or
392  * in transit to the subscription's callback. These will still be delivered.
393  * There will be a final 'SubscriptionCancelled' message, indicating the
394  * delivery of the final message.
395  *
396  * \param subscription Subscription to cancel.
397  * \return \c NULL for convenience
398  * \since 12
399  */
400 struct stasis_subscription *stasis_unsubscribe(
401         struct stasis_subscription *subscription);
402
403 /*!
404  * \brief Block until the last message is processed on a subscription.
405  *
406  * This function will not return until the \a subscription's callback for the
407  * stasis_subscription_final_message() completes. This allows cleanup routines
408  * to run before unblocking the joining thread.
409  *
410  * \param subscription Subscription to block on.
411  * \since 12
412  */
413 void stasis_subscription_join(struct stasis_subscription *subscription);
414
415 /*!
416  * \brief Returns whether \a subscription has received its final message.
417  *
418  * Note that a subscription is considered done even while the
419  * stasis_subscription_final_message() is being processed. This allows cleanup
420  * routines to check the status of the subscription.
421  *
422  * \param subscription Subscription.
423  * \return True (non-zero) if stasis_subscription_final_message() has been
424  *         received.
425  * \return False (zero) if waiting for the end.
426  */
427 int stasis_subscription_is_done(struct stasis_subscription *subscription);
428
429 /*!
430  * \brief Cancel a subscription, blocking until the last message is processed.
431  *
432  * While normally it's recommended to stasis_unsubscribe() and wait for
433  * stasis_subscription_final_message(), there are times (like during a module
434  * unload) where you have to wait for the final message (otherwise you'll call
435  * a function in a shared module that no longer exists).
436  *
437  * \param subscription Subscription to cancel.
438  * \return \c NULL for convenience
439  * \since 12
440  */
441 struct stasis_subscription *stasis_unsubscribe_and_join(
442         struct stasis_subscription *subscription);
443
444 /*!
445  * \brief Create a subscription which forwards all messages from one topic to
446  * another.
447  *
448  * Note that the \a topic parameter of the invoked callback will the be \a topic
449  * the message was sent to, not the topic the subscriber subscribed to.
450  *
451  * \param from_topic Topic to forward.
452  * \param to_topic Destination topic of forwarded messages.
453  * \return New forwarding subscription.
454  * \return \c NULL on error.
455  * \since 12
456  */
457 struct stasis_subscription *stasis_forward_all(struct stasis_topic *from_topic,
458         struct stasis_topic *to_topic);
459
460 /*!
461  * \brief Get the unique ID for the subscription.
462  *
463  * \param sub Subscription for which to get the unique ID.
464  * \return Unique ID for the subscription.
465  * \since 12
466  */
467 const char *stasis_subscription_uniqueid(const struct stasis_subscription *sub);
468
469 /*!
470  * \brief Returns whether a subscription is currently subscribed.
471  *
472  * Note that there may still be messages queued up to be dispatched to this
473  * subscription, but the stasis_subscription_final_message() has been enqueued.
474  *
475  * \param sub Subscription to check
476  * \return False (zero) if subscription is not subscribed.
477  * \return True (non-zero) if still subscribed.
478  */
479 int stasis_subscription_is_subscribed(const struct stasis_subscription *sub);
480
481 /*!
482  * \brief Determine whether a message is the final message to be received on a subscription.
483  *
484  * \param sub Subscription on which the message was received.
485  * \param msg Message to check.
486  * \return zero if the provided message is not the final message.
487  * \return non-zero if the provided message is the final message.
488  * \since 12
489  */
490 int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg);
491
492 /*! \addtogroup StasisTopicsAndMessages
493  * @{
494  */
495
496 /*!
497  * \brief Holds details about changes to subscriptions for the specified topic
498  * \since 12
499  */
500 struct stasis_subscription_change {
501         AST_DECLARE_STRING_FIELDS(
502                 AST_STRING_FIELD(uniqueid);     /*!< The unique ID associated with this subscription */
503                 AST_STRING_FIELD(description);  /*!< The description of the change to the subscription associated with the uniqueid */
504         );
505         struct stasis_topic *topic;             /*!< The topic the subscription is/was subscribing to */
506 };
507
508 /*!
509  * \brief Gets the message type for subscription change notices
510  * \return The stasis_message_type for subscription change notices
511  * \since 12
512  */
513 struct stasis_message_type *stasis_subscription_change_type(void);
514
515 /*! @} */
516
517 /*!
518  * \brief Pool for topic aggregation
519  */
520 struct stasis_topic_pool;
521
522 /*!
523  * \brief Create a topic pool that routes messages from dynamically generated topics to the given topic
524  * \param pooled_topic Topic to which messages will be routed
525  * \return the new stasis_topic_pool
526  * \return \c NULL on failure
527  */
528 struct stasis_topic_pool *stasis_topic_pool_create(struct stasis_topic *pooled_topic);
529
530 /*!
531  * \brief Find or create a topic in the pool
532  * \param pool Pool for which to get the topic
533  * \param topic_name Name of the topic to get
534  * \return The already stored or newly allocated topic
535  * \return \c NULL if the topic was not found and could not be allocated
536  */
537 struct stasis_topic *stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, const char *topic_name);
538
539 /*! @} */
540
541 /*! \addtogroup StasisTopicsAndMessages
542  * @{
543  */
544
545 /*!
546  * \brief Message type for cache update messages.
547  * \return Message type for cache update messages.
548  * \since 12
549  */
550 struct stasis_message_type *stasis_cache_update_type(void);
551
552 /*!
553  * \brief Cache update message
554  * \since 12
555  */
556 struct stasis_cache_update {
557         /*! \brief Topic that published \c new_snapshot */
558         struct stasis_topic *topic;
559         /*! \brief Convenience reference to snapshot type */
560         struct stasis_message_type *type;
561         /*! \brief Old value from the cache */
562         struct stasis_message *old_snapshot;
563         /*! \brief New value */
564         struct stasis_message *new_snapshot;
565 };
566
567 /*!
568  * \brief Message type for clearing a message from a stasis cache.
569  * \since 12
570  */
571 struct stasis_message_type *stasis_cache_clear_type(void);
572
573 /*! @} */
574
575 /*! @{ */
576
577 /*!
578  * \brief A topic wrapper, which caches certain messages.
579  * \since 12
580  */
581 struct stasis_caching_topic;
582
583 /*!
584  * \brief A message which instructs the caching topic to remove an entry from its cache.
585  *
586  * \param message Message representative of the cache entry that should be cleared.
587  *     This will become the data held in the stasis_cache_clear message.
588  *
589  * \return Message which, when sent to the \a topic, will clear the item from the cache.
590  * \return \c NULL on error.
591  * \since 12
592  */
593 struct stasis_message *stasis_cache_clear_create(struct stasis_message *message);
594
595 /*!
596  * \brief Callback extract a unique identity from a snapshot message.
597  *
598  * This identity is unique to the underlying object of the snapshot, such as the
599  * UniqueId field of a channel.
600  *
601  * \param message Message to extract id from.
602  * \return String representing the snapshot's id.
603  * \return \c NULL if the message_type of the message isn't a handled snapshot.
604  * \since 12
605  */
606 typedef const char *(*snapshot_get_id)(struct stasis_message *message);
607
608 /*!
609  * \brief Create a topic which monitors and caches messages from another topic.
610  *
611  * The idea is that some topics publish 'snapshots' of some other object's state
612  * that should be cached. When these snapshot messages are received, the cache
613  * is updated, and a stasis_cache_update() message is forwarded, which has both
614  * the original snapshot message and the new message.
615  *
616  * \param original_topic Topic publishing snapshot messages.
617  * \param id_fn Callback to extract the id from a snapshot message.
618  * \return New topic which changes snapshot messages to stasis_cache_update()
619  *         messages, and forwards all other messages from the original topic.
620  * \since 12
621  */
622 struct stasis_caching_topic *stasis_caching_topic_create(struct stasis_topic *original_topic, snapshot_get_id id_fn);
623
624 /*!
625  * \brief Unsubscribes a caching topic from its upstream topic.
626  *
627  * This function returns immediately, so be sure to cleanup when
628  * stasis_subscription_final_message() is received.
629  *
630  * \param caching_topic Caching topic to unsubscribe
631  * \return \c NULL for convenience
632  * \since 12
633  */
634 struct stasis_caching_topic *stasis_caching_unsubscribe(
635         struct stasis_caching_topic *caching_topic);
636
637 /*!
638  * \brief Unsubscribes a caching topic from its upstream topic, blocking until
639  * all messages have been forwarded.
640  *
641  * See stasis_unsubscriben_and_join() for more info on when to use this as
642  * opposed to stasis_caching_unsubscribe().
643  *
644  * \param caching_topic Caching topic to unsubscribe
645  * \return \c NULL for convenience
646  * \since 12
647  */
648 struct stasis_caching_topic *stasis_caching_unsubscribe_and_join(
649         struct stasis_caching_topic *caching_topic);
650
651 /*!
652  * \brief Returns the topic of cached events from a caching topics.
653  * \param caching_topic The caching topic.
654  * \return The topic that publishes cache update events, along with passthrough events
655  *         from the underlying topic.
656  * \return \c NULL if \a caching_topic is \c NULL.
657  * \since 12
658  */
659 struct stasis_topic *stasis_caching_get_topic(struct stasis_caching_topic *caching_topic);
660
661 /*!
662  * \brief Retrieve an item from the cache.
663  *
664  * The returned item is AO2 managed, so ao2_cleanup() when you're done with it.
665  *
666  * \param caching_topic The topic returned from stasis_caching_topic_create().
667  * \param type Type of message to retrieve.
668  * \param id Identity of the snapshot to retrieve.
669  * \return Message from the cache.
670  * \return \c NULL if message is not found.
671  * \since 12
672  */
673 struct stasis_message *stasis_cache_get(struct stasis_caching_topic *caching_topic,
674                                         struct stasis_message_type *type,
675                                         const char *id);
676
677 /*!
678  * \brief Dump cached items to a subscription
679  * \param caching_topic The topic returned from stasis_caching_topic_create().
680  * \param type Type of message to dump (any type if \c NULL).
681  * \return ao2_container containing all matches (must be unreffed by caller)
682  * \return \c NULL on allocation error
683  * \since 12
684  */
685 struct ao2_container *stasis_cache_dump(struct stasis_caching_topic *caching_topic,
686                                         struct stasis_message_type *type);
687
688 /*! @} */
689
690 /*! @{ */
691
692 /*!
693  * \internal
694  * \brief Log a message about invalid attempt to access a type.
695  */
696 void stasis_log_bad_type_access(const char *name);
697
698 /*!
699  * \brief Boiler-plate removing macro for defining message types.
700  *
701  * \code
702  *      STASIS_MESSAGE_TYPE_DEFN(ast_foo_type,
703  *              .to_ami = foo_to_ami,
704  *              .to_json = foo_to_json,
705  *              );
706  * \endcode
707  *
708  * \param name Name of message type.
709  * \param ... Virtual table methods for messages of this type.
710  * \since 12
711  */
712 #define STASIS_MESSAGE_TYPE_DEFN(name, ...)                             \
713         static struct stasis_message_vtable _priv_ ## name ## _v = {    \
714                 __VA_ARGS__                                             \
715         };                                                              \
716         static struct stasis_message_type *_priv_ ## name;              \
717         struct stasis_message_type *name(void) {                        \
718                 if (_priv_ ## name == NULL) {                           \
719                         stasis_log_bad_type_access(#name);              \
720                 }                                                       \
721                 return _priv_ ## name;                                  \
722         }
723
724 /*!
725 * \brief Boiler-plate removing macro for initializing message types.
726  *
727  * \code
728  *      if (STASIS_MESSAGE_TYPE_INIT(ast_foo_type) != 0) {
729  *              return -1;
730  *      }
731  * \endcode
732  *
733  * \param name Name of message type.
734  * \return 0 if initialization is successful.
735  * \return Non-zero on failure.
736  * \since 12
737  */
738 #define STASIS_MESSAGE_TYPE_INIT(name)                                  \
739         ({                                                              \
740                 ast_assert(_priv_ ## name == NULL);                     \
741                 _priv_ ## name = stasis_message_type_create(#name,      \
742                         &_priv_ ## name ## _v);                         \
743                 _priv_ ## name ? 0 : -1;                                \
744         })
745
746 /*!
747  * \brief Boiler-plate removing macro for cleaning up message types.
748  *
749  * Note that if your type is defined in core instead of a loadable module, you
750  * should call message type cleanup from an ast_register_cleanup() handler
751  * instead of an ast_register_atexit() handler.
752  *
753  * The reason is that during an immediate shutdown, loadable modules (which may
754  * refer to core message types) are not unloaded. While the atexit handlers are
755  * run, there's a window of time where a module subscription might reference a
756  * core message type after it's been cleaned up. Which is bad.
757  *
758  * \param name Name of message type.
759  * \since 12
760  */
761 #define STASIS_MESSAGE_TYPE_CLEANUP(name)       \
762         ({                                      \
763                 ao2_cleanup(_priv_ ## name);    \
764                 _priv_ ## name = NULL;          \
765         })
766
767 /*! @} */
768
769 /*! @{ */
770
771 /*!
772  * \brief Initialize the Stasis subsystem
773  * \return 0 on success.
774  * \return Non-zero on error.
775  * \since 12
776  */
777 int stasis_init(void);
778
779 /*!
780  * \private
781  * \brief called by stasis_init() for cache initialization.
782  * \return 0 on success.
783  * \return Non-zero on error.
784  * \since 12
785  */
786 int stasis_cache_init(void);
787
788 /*! @} */
789
790 /*!
791  * \defgroup StasisTopicsAndMessages Stasis topics, and their messages.
792  *
793  * This group contains the topics, messages and corresponding message types
794  * found within Asterisk.
795  */
796
797 #endif /* _ASTERISK_STASIS_H */