2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013, Digium, Inc.
6 * Matt Jordan <mjordan@digium.com>
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.
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.
21 * \brief Stasis Messages and Data Types for Channel Objects
23 * \author \verbatim Matt Jordan <mjordan@digium.com> \endverbatim
28 <support_level>core</support_level>
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35 #include "asterisk/stasis.h"
36 #include "asterisk/astobj2.h"
37 #include "asterisk/stasis_channels.h"
39 #define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7
42 * @{ \brief Define channel message types.
44 STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type);
45 STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type);
46 STASIS_MESSAGE_TYPE_DEFN(ast_channel_varset_type);
47 STASIS_MESSAGE_TYPE_DEFN(ast_channel_user_event_type);
48 STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_request_type);
49 STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_begin_type);
50 STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_end_type);
51 STASIS_MESSAGE_TYPE_DEFN(ast_channel_hold_type);
52 STASIS_MESSAGE_TYPE_DEFN(ast_channel_unhold_type);
53 STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_start_type);
54 STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_stop_type);
55 STASIS_MESSAGE_TYPE_DEFN(ast_channel_fax_type);
56 STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_handler_type);
57 STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_start_type);
58 STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_stop_type);
59 STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_start_type);
60 STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_stop_type);
63 /*! \brief Topic for all channels */
64 struct stasis_topic *channel_topic_all;
66 /*! \brief Caching topic for all channels */
67 struct stasis_caching_topic *channel_topic_all_cached;
69 /*! \brief Caching topic for all channels indexed by name */
70 struct stasis_caching_topic *channel_topic_all_cached_by_name;
72 struct stasis_topic *ast_channel_topic_all(void)
74 return channel_topic_all;
77 struct stasis_caching_topic *ast_channel_topic_all_cached(void)
79 return channel_topic_all_cached;
82 static const char *channel_snapshot_get_id(struct stasis_message *message)
84 struct ast_channel_snapshot *snapshot;
85 if (ast_channel_snapshot_type() != stasis_message_type(message)) {
88 snapshot = stasis_message_data(message);
89 return snapshot->uniqueid;
92 struct stasis_caching_topic *ast_channel_topic_all_cached_by_name(void)
94 return channel_topic_all_cached_by_name;
97 static const char *channel_snapshot_get_name(struct stasis_message *message)
99 struct ast_channel_snapshot *snapshot;
100 if (ast_channel_snapshot_type() != stasis_message_type(message)) {
103 snapshot = stasis_message_data(message);
104 return snapshot->name;
107 /*! \internal \brief Hash function for \ref ast_channel_snapshot objects */
108 static int channel_snapshot_hash_cb(const void *obj, const int flags)
110 const struct ast_channel_snapshot *snapshot = obj;
111 const char *name = (flags & OBJ_KEY) ? obj : snapshot->name;
112 return ast_str_case_hash(name);
115 /*! \internal \brief Comparison function for \ref ast_channel_snapshot objects */
116 static int channel_snapshot_cmp_cb(void *obj, void *arg, int flags)
118 struct ast_channel_snapshot *left = obj;
119 struct ast_channel_snapshot *right = arg;
120 const char *match = (flags & OBJ_KEY) ? arg : right->name;
121 return strcasecmp(left->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
124 static void channel_snapshot_dtor(void *obj)
126 struct ast_channel_snapshot *snapshot = obj;
127 ast_string_field_free_memory(snapshot);
130 struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
132 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
134 snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor);
135 if (!snapshot || ast_string_field_init(snapshot, 1024)) {
139 ast_string_field_set(snapshot, name, ast_channel_name(chan));
140 ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan));
141 ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan));
142 ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan));
143 ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan));
144 ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan));
145 ast_string_field_set(snapshot, parkinglot, ast_channel_parkinglot(chan));
146 ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan));
147 if (ast_channel_appl(chan)) {
148 ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
150 if (ast_channel_data(chan)) {
151 ast_string_field_set(snapshot, data, ast_channel_data(chan));
153 ast_string_field_set(snapshot, context, ast_channel_context(chan));
154 ast_string_field_set(snapshot, exten, ast_channel_exten(chan));
156 ast_string_field_set(snapshot, caller_name,
157 S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
158 ast_string_field_set(snapshot, caller_number,
159 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
161 ast_string_field_set(snapshot, connected_name,
162 S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
163 ast_string_field_set(snapshot, connected_number,
164 S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
165 ast_string_field_set(snapshot, language, ast_channel_language(chan));
167 snapshot->creationtime = ast_channel_creationtime(chan);
168 snapshot->state = ast_channel_state(chan);
169 snapshot->priority = ast_channel_priority(chan);
170 snapshot->amaflags = ast_channel_amaflags(chan);
171 snapshot->hangupcause = ast_channel_hangupcause(chan);
172 snapshot->flags = *ast_channel_flags(chan);
173 snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
175 snapshot->manager_vars = ast_channel_get_manager_vars(chan);
177 ao2_ref(snapshot, +1);
181 static void publish_message_for_channel_topics(struct stasis_message *message, struct ast_channel *chan)
184 stasis_publish(ast_channel_topic(chan), message);
186 stasis_publish(ast_channel_topic_all(), message);
190 static void channel_blob_dtor(void *obj)
192 struct ast_channel_blob *event = obj;
193 ao2_cleanup(event->snapshot);
194 ast_json_unref(event->blob);
197 void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
199 RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
200 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
201 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
202 struct ast_channel_snapshot *caller_snapshot;
203 struct ast_channel_snapshot *peer_snapshot;
205 ast_assert(peer != NULL);
206 blob = ast_json_pack("{s: s, s: s}",
207 "dialstatus", S_OR(dialstatus, ""),
208 "dialstring", S_OR(dialstring, ""));
212 payload = ast_multi_channel_blob_create(blob);
218 caller_snapshot = ast_channel_snapshot_create(caller);
219 if (!caller_snapshot) {
222 ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
225 peer_snapshot = ast_channel_snapshot_create(peer);
226 if (!peer_snapshot) {
229 ast_multi_channel_blob_add_channel(payload, "peer", peer_snapshot);
231 msg = stasis_message_create(ast_channel_dial_type(), payload);
236 publish_message_for_channel_topics(msg, caller);
239 static struct stasis_message *create_channel_blob_message(struct ast_channel_snapshot *snapshot,
240 struct stasis_message_type *type,
241 struct ast_json *blob)
244 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
245 RAII_VAR(struct ast_channel_blob *, obj, NULL, ao2_cleanup);
248 blob = ast_json_null();
251 obj = ao2_alloc(sizeof(*obj), channel_blob_dtor);
257 obj->snapshot = snapshot;
258 ao2_ref(obj->snapshot, +1);
260 obj->blob = ast_json_ref(blob);
262 msg = stasis_message_create(type, obj);
271 struct stasis_message *ast_channel_blob_create_from_cache(const char *channel_id,
272 struct stasis_message_type *type,
273 struct ast_json *blob)
275 RAII_VAR(struct ast_channel_snapshot *, snapshot,
276 ast_channel_snapshot_get_latest(channel_id),
279 return create_channel_blob_message(snapshot, type, blob);
282 struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
283 struct stasis_message_type *type, struct ast_json *blob)
285 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
288 snapshot = ast_channel_snapshot_create(chan);
291 return create_channel_blob_message(snapshot, type, blob);
294 /*! \brief A channel snapshot wrapper object used in \ref ast_multi_channel_blob objects */
295 struct channel_role_snapshot {
296 struct ast_channel_snapshot *snapshot; /*!< A channel snapshot */
297 char role[0]; /*!< The role assigned to the channel */
300 /*! \brief A multi channel blob data structure for multi_channel_blob stasis messages */
301 struct ast_multi_channel_blob {
302 struct ao2_container *channel_snapshots; /*!< A container holding the snapshots */
303 struct ast_json *blob; /*< A blob of JSON data */
306 /*! \internal \brief Standard comparison function for \ref channel_role_snapshot objects */
307 static int channel_role_single_cmp_cb(void *obj, void *arg, int flags)
309 struct channel_role_snapshot *left = obj;
310 struct channel_role_snapshot *right = arg;
311 const char *match = (flags & OBJ_KEY) ? arg : right->role;
312 return strcasecmp(left->role, match) ? 0 : (CMP_MATCH | CMP_STOP);
315 /*! \internal \brief Multi comparison function for \ref channel_role_snapshot objects */
316 static int channel_role_multi_cmp_cb(void *obj, void *arg, int flags)
318 struct channel_role_snapshot *left = obj;
319 struct channel_role_snapshot *right = arg;
320 const char *match = (flags & OBJ_KEY) ? arg : right->role;
321 return strcasecmp(left->role, match) ? 0 : (CMP_MATCH);
324 /*! \internal \brief Hash function for \ref channel_role_snapshot objects */
325 static int channel_role_hash_cb(const void *obj, const int flags)
327 const struct channel_role_snapshot *snapshot = obj;
328 const char *name = (flags & OBJ_KEY) ? obj : snapshot->role;
329 return ast_str_case_hash(name);
332 /*! \internal \brief Destructor for \ref ast_multi_channel_blob objects */
333 static void multi_channel_blob_dtor(void *obj)
335 struct ast_multi_channel_blob *multi_blob = obj;
337 ao2_cleanup(multi_blob->channel_snapshots);
338 ast_json_unref(multi_blob->blob);
341 struct ast_multi_channel_blob *ast_multi_channel_blob_create(struct ast_json *blob)
343 RAII_VAR(struct ast_multi_channel_blob *, obj,
344 ao2_alloc(sizeof(*obj), multi_channel_blob_dtor),
347 ast_assert(blob != NULL);
353 obj->channel_snapshots = ao2_container_alloc(NUM_MULTI_CHANNEL_BLOB_BUCKETS,
354 channel_role_hash_cb, channel_role_single_cmp_cb);
355 if (!obj->channel_snapshots) {
359 obj->blob = ast_json_ref(blob);
365 struct ast_channel_snapshot *ast_channel_snapshot_get_latest(const char *uniqueid)
367 RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
368 struct ast_channel_snapshot *snapshot;
370 ast_assert(!ast_strlen_zero(uniqueid));
372 message = stasis_cache_get(ast_channel_topic_all_cached(),
373 ast_channel_snapshot_type(),
379 snapshot = stasis_message_data(message);
383 ao2_ref(snapshot, +1);
387 struct ast_channel_snapshot *ast_channel_snapshot_get_latest_by_name(const char *name)
389 RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
390 struct ast_channel_snapshot *snapshot;
392 ast_assert(!ast_strlen_zero(name));
394 message = stasis_cache_get(ast_channel_topic_all_cached_by_name(),
395 ast_channel_snapshot_type(),
401 snapshot = stasis_message_data(message);
405 ao2_ref(snapshot, +1);
409 static void channel_role_snapshot_dtor(void *obj)
411 struct channel_role_snapshot *role_snapshot = obj;
412 ao2_cleanup(role_snapshot->snapshot);
415 void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
417 RAII_VAR(struct channel_role_snapshot *, role_snapshot, NULL, ao2_cleanup);
418 int role_len = strlen(role) + 1;
420 if (!obj || ast_strlen_zero(role) || !snapshot) {
424 role_snapshot = ao2_alloc(sizeof(*role_snapshot) + role_len, channel_role_snapshot_dtor);
425 if (!role_snapshot) {
428 ast_copy_string(role_snapshot->role, role, role_len);
429 role_snapshot->snapshot = snapshot;
430 ao2_ref(role_snapshot->snapshot, +1);
431 ao2_link(obj->channel_snapshots, role_snapshot);
434 struct ast_channel_snapshot *ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
436 struct channel_role_snapshot *role_snapshot;
438 if (!obj || ast_strlen_zero(role)) {
441 role_snapshot = ao2_find(obj->channel_snapshots, role, OBJ_KEY);
442 /* Note that this function does not increase the ref count on snapshot */
443 if (!role_snapshot) {
446 ao2_ref(role_snapshot, -1);
447 return role_snapshot->snapshot;
450 struct ao2_container *ast_multi_channel_blob_get_channels(struct ast_multi_channel_blob *obj, const char *role)
452 RAII_VAR(struct ao2_container *, ret_container,
453 ao2_container_alloc(NUM_MULTI_CHANNEL_BLOB_BUCKETS, channel_snapshot_hash_cb, channel_snapshot_cmp_cb),
455 struct ao2_iterator *it_role_snapshots;
456 struct channel_role_snapshot *role_snapshot;
459 if (!obj || ast_strlen_zero(role) || !ret_container) {
462 arg = ast_strdupa(role);
464 it_role_snapshots = ao2_callback(obj->channel_snapshots, OBJ_MULTIPLE | OBJ_KEY, channel_role_multi_cmp_cb, arg);
465 if (!it_role_snapshots) {
469 while ((role_snapshot = ao2_iterator_next(it_role_snapshots))) {
470 ao2_link(ret_container, role_snapshot->snapshot);
471 ao2_ref(role_snapshot, -1);
473 ao2_iterator_destroy(it_role_snapshots);
475 ao2_ref(ret_container, +1);
476 return ret_container;
479 struct ast_json *ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
487 void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
489 RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
492 blob = ast_json_null();
495 message = ast_channel_blob_create(chan, type, blob);
497 stasis_publish(ast_channel_topic(chan), message);
501 void ast_channel_publish_snapshot(struct ast_channel *chan)
503 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
504 RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
506 snapshot = ast_channel_snapshot_create(chan);
511 message = stasis_message_create(ast_channel_snapshot_type(), snapshot);
516 ast_assert(ast_channel_topic(chan) != NULL);
517 stasis_publish(ast_channel_topic(chan), message);
520 void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value)
522 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
524 ast_assert(name != NULL);
525 ast_assert(value != NULL);
527 blob = ast_json_pack("{s: s, s: s}",
531 ast_log(LOG_ERROR, "Error creating message\n");
535 ast_channel_publish_blob(chan, ast_channel_varset_type(), blob);
538 void ast_publish_channel_state(struct ast_channel *chan)
540 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
541 RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
543 ast_assert(chan != NULL);
548 snapshot = ast_channel_snapshot_create(chan);
553 message = stasis_message_create(ast_channel_snapshot_type(), snapshot);
558 ast_assert(ast_channel_topic(chan) != NULL);
559 stasis_publish(ast_channel_topic(chan), message);
562 struct ast_json *ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot)
564 RAII_VAR(struct ast_json *, json_chan, NULL, ast_json_unref);
566 if (snapshot == NULL) {
570 json_chan = ast_json_pack("{ s: s, s: s, s: s, s: s, s: s, s: s, s: s,"
571 " s: s, s: s, s: s, s: s, s: o, s: o, s: o,"
574 "name", snapshot->name,
575 "state", ast_state2str(snapshot->state),
576 "accountcode", snapshot->accountcode,
577 "peeraccount", snapshot->peeraccount,
578 "userfield", snapshot->userfield,
579 "uniqueid", snapshot->uniqueid,
580 "linkedid", snapshot->linkedid,
581 "parkinglot", snapshot->parkinglot,
582 "hangupsource", snapshot->hangupsource,
583 "appl", snapshot->appl,
584 "data", snapshot->data,
585 "dialplan", ast_json_dialplan_cep(snapshot->context, snapshot->exten, snapshot->priority),
586 "caller", ast_json_name_number(snapshot->caller_name, snapshot->caller_number),
587 "connected", ast_json_name_number(snapshot->connected_name, snapshot->connected_number),
588 "creationtime", ast_json_timeval(snapshot->creationtime, NULL));
590 return ast_json_ref(json_chan);
593 int ast_channel_snapshot_cep_equal(
594 const struct ast_channel_snapshot *old_snapshot,
595 const struct ast_channel_snapshot *new_snapshot)
597 ast_assert(old_snapshot != NULL);
598 ast_assert(new_snapshot != NULL);
600 /* We actually get some snapshots with CEP set, but before the
601 * application is set. Since empty application is invalid, we treat
602 * setting the application from nothing as a CEP change.
604 if (ast_strlen_zero(old_snapshot->appl) &&
605 !ast_strlen_zero(new_snapshot->appl)) {
609 return old_snapshot->priority == new_snapshot->priority &&
610 strcmp(old_snapshot->context, new_snapshot->context) == 0 &&
611 strcmp(old_snapshot->exten, new_snapshot->exten) == 0;
614 int ast_channel_snapshot_caller_id_equal(
615 const struct ast_channel_snapshot *old_snapshot,
616 const struct ast_channel_snapshot *new_snapshot)
618 ast_assert(old_snapshot != NULL);
619 ast_assert(new_snapshot != NULL);
620 return strcmp(old_snapshot->caller_number, new_snapshot->caller_number) == 0 &&
621 strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
624 static void stasis_channels_cleanup(void)
626 channel_topic_all_cached = stasis_caching_unsubscribe_and_join(channel_topic_all_cached);
627 channel_topic_all_cached_by_name = stasis_caching_unsubscribe_and_join(channel_topic_all_cached_by_name);
628 ao2_cleanup(channel_topic_all);
629 channel_topic_all = NULL;
630 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_snapshot_type);
631 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dial_type);
632 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_varset_type);
633 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_user_event_type);
634 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hangup_request_type);
635 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_begin_type);
636 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_end_type);
637 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hold_type);
638 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_unhold_type);
639 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_chanspy_start_type);
640 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_chanspy_stop_type);
641 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_fax_type);
642 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hangup_handler_type);
643 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_moh_start_type);
644 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_moh_stop_type);
645 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_start_type);
646 STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_stop_type);
649 void ast_stasis_channels_init(void)
651 ast_register_cleanup(stasis_channels_cleanup);
653 STASIS_MESSAGE_TYPE_INIT(ast_channel_snapshot_type);
654 STASIS_MESSAGE_TYPE_INIT(ast_channel_dial_type);
655 STASIS_MESSAGE_TYPE_INIT(ast_channel_varset_type);
656 STASIS_MESSAGE_TYPE_INIT(ast_channel_user_event_type);
657 STASIS_MESSAGE_TYPE_INIT(ast_channel_hangup_request_type);
658 STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_begin_type);
659 STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_end_type);
660 STASIS_MESSAGE_TYPE_INIT(ast_channel_hold_type);
661 STASIS_MESSAGE_TYPE_INIT(ast_channel_unhold_type);
662 STASIS_MESSAGE_TYPE_INIT(ast_channel_chanspy_start_type);
663 STASIS_MESSAGE_TYPE_INIT(ast_channel_chanspy_stop_type);
664 STASIS_MESSAGE_TYPE_INIT(ast_channel_fax_type);
665 STASIS_MESSAGE_TYPE_INIT(ast_channel_hangup_handler_type);
666 STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_start_type);
667 STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_stop_type);
668 STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_start_type);
669 STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_stop_type);
671 channel_topic_all = stasis_topic_create("ast_channel_topic_all");
672 channel_topic_all_cached = stasis_caching_topic_create(channel_topic_all, channel_snapshot_get_id);
673 channel_topic_all_cached_by_name = stasis_caching_topic_create(channel_topic_all, channel_snapshot_get_name);