Replace most uses of ast_register_atexit with ast_register_cleanup.
[asterisk/asterisk.git] / main / stasis_bridges.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Kinsey Moore <kmoore@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 /*! \file
20  *
21  * \brief Stasis Messages and Data Types for Bridge Objects
22  *
23  * \author Kinsey Moore <kmoore@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/astobj2.h"
35 #include "asterisk/stasis.h"
36 #include "asterisk/stasis_cache_pattern.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/stasis_bridges.h"
39 #include "asterisk/stasis_channels.h"
40 #include "asterisk/bridge.h"
41 #include "asterisk/bridge_technology.h"
42
43 /* The container of channel snapshots in a bridge snapshot should always be
44    equivalent to a linked list; otherwise things (like CDRs) that depend on some
45    consistency in the ordering of channels in a bridge will break. */
46 #define SNAPSHOT_CHANNELS_BUCKETS 1
47
48 /*** DOCUMENTATION
49         <managerEvent language="en_US" name="BlindTransfer">
50                 <managerEventInstance class="EVENT_FLAG_CALL">
51                         <synopsis>Raised when a blind transfer is complete.</synopsis>
52                         <syntax>
53                                 <parameter name="Result">
54                                         <para>Indicates if the transfer was successful or if it failed.</para>
55                                         <enumlist>
56                                                 <enum name="Fail"><para>An internal error occurred.</para></enum>
57                                                 <enum name="Invalid"><para>Invalid configuration for transfer (e.g. Not bridged)</para></enum>
58                                                 <enum name="Not Permitted"><para>Bridge does not permit transfers</para></enum>
59                                                 <enum name="Success"><para>Transfer completed successfully</para></enum>
60                                         </enumlist>
61                                         <note><para>A result of <literal>Success</literal> does not necessarily mean that a target was succesfully
62                                         contacted. It means that a party was succesfully placed into the dialplan at the expected location.</para></note>
63                                 </parameter>
64                                 <channel_snapshot prefix="Transferer"/>
65                                 <channel_snapshot prefix="Transferee"/>
66                                 <bridge_snapshot/>
67                                 <parameter name="IsExternal">
68                                         <para>Indicates if the transfer was performed outside of Asterisk. For instance,
69                                         a channel protocol native transfer is external. A DTMF transfer is internal.</para>
70                                                 <enumlist>
71                                                         <enum name="Yes" />
72                                                         <enum name="No" />
73                                                 </enumlist>
74                                 </parameter>
75                                 <parameter name="Context">
76                                         <para>Destination context for the blind transfer.</para>
77                                 </parameter>
78                                 <parameter name="Extension">
79                                         <para>Destination extension for the blind transfer.</para>
80                                 </parameter>
81                         </syntax>
82                 </managerEventInstance>
83         </managerEvent>
84         <managerEvent language="en_US" name="AttendedTransfer">
85                 <managerEventInstance class="EVENT_FLAG_CALL">
86                         <synopsis>Raised when an attended transfer is complete.</synopsis>
87                         <syntax>
88                                 <xi:include xpointer="xpointer(docs/managerEvent[@name='BlindTransfer']/managerEventInstance/syntax/parameter[@name='Result'])" />
89                                 <channel_snapshot prefix="OrigTransferer"/>
90                                 <bridge_snapshot prefix="Orig"/>
91                                 <channel_snapshot prefix="SecondTransferer"/>
92                                 <bridge_snapshot prefix="Second"/>
93                                 <parameter name="DestType">
94                                         <para>Indicates the method by which the attended transfer completed.</para>
95                                         <enumlist>
96                                                 <enum name="Bridge"><para>The transfer was accomplished by merging two bridges into one.</para></enum>
97                                                 <enum name="App"><para>The transfer was accomplished by having a channel or bridge run a dialplan application.</para></enum>
98                                                 <enum name="Link"><para>The transfer was accomplished by linking two bridges together using a local channel pair.</para></enum>
99                                                 <enum name="Threeway"><para>The transfer was accomplished by placing all parties into a threeway call.</para></enum>
100                                                 <enum name="Fail"><para>The transfer failed.</para></enum>
101                                         </enumlist>
102                                 </parameter>
103                                 <parameter name="DestBridgeUniqueid">
104                                         <para>Indicates the surviving bridge when bridges were merged to complete the transfer</para>
105                                         <note><para>This header is only present when <replaceable>DestType</replaceable> is <literal>Bridge</literal> or <literal>Threeway</literal></para></note>
106                                 </parameter>
107                                 <parameter name="DestApp">
108                                         <para>Indicates the application that is running when the transfer completes</para>
109                                         <note><para>This header is only present when <replaceable>DestType</replaceable> is <literal>App</literal></para></note>
110                                 </parameter>
111                                 <channel_snapshot prefix="LocalOne"/>
112                                 <channel_snapshot prefix="LocalTwo"/>
113                                 <parameter name="DestTransfererChannel">
114                                         <para>The name of the surviving transferer channel when a transfer results in a threeway call</para>
115                                         <note><para>This header is only present when <replaceable>DestType</replaceable> is <literal>Threeway</literal></para></note>
116                                 </parameter>
117                                 <channel_snapshot prefix="Transferee" />
118                         </syntax>
119                         <description>
120                                 <para>The headers in this event attempt to describe all the major details of the attended transfer. The two transferer channels
121                                 and the two bridges are determined based on their chronological establishment. So consider that Alice calls Bob, and then Alice
122                                 transfers the call to Voicemail. The transferer and bridge headers would be arranged as follows:</para>
123                                 <para>  <replaceable>OrigTransfererChannel</replaceable>: Alice's channel in the bridge with Bob.</para>
124                                 <para>  <replaceable>OrigBridgeUniqueid</replaceable>: The bridge between Alice and Bob.</para>
125                                 <para>  <replaceable>SecondTransfererChannel</replaceable>: Alice's channel that called Voicemail.</para>
126                                 <para>  <replaceable>SecondBridgeUniqueid</replaceable>: Not present, since a call to Voicemail has no bridge.</para>
127                                 <para>Now consider if the order were reversed; instead of having Alice call Bob and transfer him to Voicemail, Alice instead
128                                 calls her Voicemail and transfers that to Bob. The transferer and bridge headers would be arranged as follows:</para>
129                                 <para>  <replaceable>OrigTransfererChannel</replaceable>: Alice's channel that called Voicemail.</para>
130                                 <para>  <replaceable>OrigBridgeUniqueid</replaceable>: Not present, since a call to Voicemail has no bridge.</para>
131                                 <para>  <replaceable>SecondTransfererChannel</replaceable>: Alice's channel in the bridge with Bob.</para>
132                                 <para>  <replaceable>SecondBridgeUniqueid</replaceable>: The bridge between Alice and Bob.</para>
133                         </description>
134                 </managerEventInstance>
135         </managerEvent>
136  ***/
137
138 static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
139         const struct stasis_message_sanitizer *sanitize);
140 static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *message);
141 static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
142         const struct stasis_message_sanitizer *sanitize);
143 static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *message);
144 static struct ast_json *ast_channel_entered_bridge_to_json(
145         struct stasis_message *msg,
146         const struct stasis_message_sanitizer *sanitize);
147 static struct ast_json *ast_channel_left_bridge_to_json(
148         struct stasis_message *msg,
149         const struct stasis_message_sanitizer *sanitize);
150 static struct ast_json *ast_bridge_merge_message_to_json(
151         struct stasis_message *msg,
152         const struct stasis_message_sanitizer *sanitize);
153
154 static struct stasis_cp_all *bridge_cache_all;
155
156 /*!
157  * @{ \brief Define bridge message types.
158  */
159 STASIS_MESSAGE_TYPE_DEFN(ast_bridge_snapshot_type);
160 STASIS_MESSAGE_TYPE_DEFN(ast_bridge_merge_message_type,
161         .to_json = ast_bridge_merge_message_to_json);
162 STASIS_MESSAGE_TYPE_DEFN(ast_channel_entered_bridge_type,
163         .to_json = ast_channel_entered_bridge_to_json);
164 STASIS_MESSAGE_TYPE_DEFN(ast_channel_left_bridge_type,
165         .to_json = ast_channel_left_bridge_to_json);
166 STASIS_MESSAGE_TYPE_DEFN(ast_blind_transfer_type,
167         .to_json = blind_transfer_to_json,
168         .to_ami = blind_transfer_to_ami);
169 STASIS_MESSAGE_TYPE_DEFN(ast_attended_transfer_type,
170         .to_json = attended_transfer_to_json,
171         .to_ami = attended_transfer_to_ami);
172 /*! @} */
173
174 struct stasis_cache *ast_bridge_cache(void)
175 {
176         return stasis_cp_all_cache(bridge_cache_all);
177 }
178
179 struct stasis_topic *ast_bridge_topic_all(void)
180 {
181         return stasis_cp_all_topic(bridge_cache_all);
182 }
183
184 struct stasis_topic *ast_bridge_topic_all_cached(void)
185 {
186         return stasis_cp_all_topic_cached(bridge_cache_all);
187 }
188
189 int bridge_topics_init(struct ast_bridge *bridge)
190 {
191         if (ast_strlen_zero(bridge->uniqueid)) {
192                 ast_log(LOG_ERROR, "Bridge id initialization required\n");
193                 return -1;
194         }
195         bridge->topics = stasis_cp_single_create(bridge_cache_all,
196                 bridge->uniqueid);
197         if (!bridge->topics) {
198                 return -1;
199         }
200         return 0;
201 }
202
203 struct stasis_topic *ast_bridge_topic(struct ast_bridge *bridge)
204 {
205         if (!bridge) {
206                 return ast_bridge_topic_all();
207         }
208
209         return stasis_cp_single_topic(bridge->topics);
210 }
211
212 struct stasis_topic *ast_bridge_topic_cached(struct ast_bridge *bridge)
213 {
214         if (!bridge) {
215                 return ast_bridge_topic_all_cached();
216         }
217
218         return stasis_cp_single_topic_cached(bridge->topics);
219 }
220
221 /*! \brief Destructor for bridge snapshots */
222 static void bridge_snapshot_dtor(void *obj)
223 {
224         struct ast_bridge_snapshot *snapshot = obj;
225         ast_string_field_free_memory(snapshot);
226         ao2_cleanup(snapshot->channels);
227         snapshot->channels = NULL;
228 }
229
230 struct ast_bridge_snapshot *ast_bridge_snapshot_create(struct ast_bridge *bridge)
231 {
232         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
233         struct ast_bridge_channel *bridge_channel;
234
235         snapshot = ao2_alloc_options(sizeof(*snapshot), bridge_snapshot_dtor,
236                 AO2_ALLOC_OPT_LOCK_NOLOCK);
237         if (!snapshot || ast_string_field_init(snapshot, 128)) {
238                 return NULL;
239         }
240
241         snapshot->channels = ast_str_container_alloc(SNAPSHOT_CHANNELS_BUCKETS);
242         if (!snapshot->channels) {
243                 return NULL;
244         }
245
246         AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
247                 if (ast_str_container_add(snapshot->channels,
248                                 ast_channel_uniqueid(bridge_channel->chan))) {
249                         return NULL;
250                 }
251         }
252
253         ast_string_field_set(snapshot, uniqueid, bridge->uniqueid);
254         ast_string_field_set(snapshot, technology, bridge->technology->name);
255         ast_string_field_set(snapshot, subclass, bridge->v_table->name);
256         ast_string_field_set(snapshot, creator, bridge->creator);
257         ast_string_field_set(snapshot, name, bridge->name);
258
259         snapshot->feature_flags = bridge->feature_flags;
260         snapshot->capabilities = bridge->technology->capabilities;
261         snapshot->num_channels = bridge->num_channels;
262         snapshot->num_active = bridge->num_active;
263
264         ao2_ref(snapshot, +1);
265         return snapshot;
266 }
267
268 void ast_bridge_publish_state(struct ast_bridge *bridge)
269 {
270         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
271         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
272
273         if (!ast_bridge_snapshot_type()) {
274                 return;
275         }
276
277         ast_assert(bridge != NULL);
278
279         snapshot = ast_bridge_snapshot_create(bridge);
280         if (!snapshot) {
281                 return;
282         }
283
284         msg = stasis_message_create(ast_bridge_snapshot_type(), snapshot);
285         if (!msg) {
286                 return;
287         }
288
289         stasis_publish(ast_bridge_topic(bridge), msg);
290 }
291
292 static void bridge_publish_state_from_blob(struct ast_bridge *bridge,
293         struct ast_bridge_blob *obj)
294 {
295         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
296
297         ast_assert(obj != NULL);
298
299         msg = stasis_message_create(ast_bridge_snapshot_type(), obj->bridge);
300         if (!msg) {
301                 return;
302         }
303
304         stasis_publish(ast_bridge_topic(bridge), msg);
305 }
306
307 /*! \brief Destructor for bridge merge messages */
308 static void bridge_merge_message_dtor(void *obj)
309 {
310         struct ast_bridge_merge_message *msg = obj;
311
312         ao2_cleanup(msg->to);
313         msg->to = NULL;
314         ao2_cleanup(msg->from);
315         msg->from = NULL;
316 }
317
318 /*! \brief Bridge merge message creation helper */
319 static struct ast_bridge_merge_message *bridge_merge_message_create(struct ast_bridge *to, struct ast_bridge *from)
320 {
321         RAII_VAR(struct ast_bridge_merge_message *, msg, NULL, ao2_cleanup);
322
323         msg = ao2_alloc(sizeof(*msg), bridge_merge_message_dtor);
324         if (!msg) {
325                 return NULL;
326         }
327
328         msg->to = ast_bridge_snapshot_create(to);
329         if (!msg->to) {
330                 return NULL;
331         }
332
333         msg->from = ast_bridge_snapshot_create(from);
334         if (!msg->from) {
335                 return NULL;
336         }
337
338         ao2_ref(msg, +1);
339         return msg;
340 }
341
342 static struct ast_json *ast_bridge_merge_message_to_json(
343         struct stasis_message *msg,
344         const struct stasis_message_sanitizer *sanitize)
345 {
346         struct ast_bridge_merge_message *merge = stasis_message_data(msg);
347         RAII_VAR(struct ast_json *, json_bridge_to,
348                 ast_bridge_snapshot_to_json(merge->to, sanitize), ast_json_unref);
349         RAII_VAR(struct ast_json *, json_bridge_from,
350                 ast_bridge_snapshot_to_json(merge->from, sanitize), ast_json_unref);
351
352         if (!json_bridge_to || !json_bridge_from) {
353                 return NULL;
354         }
355
356         return ast_json_pack("{s: s, s: o, s: O, s: O}",
357                 "type", "BridgeMerged",
358                 "timestamp", ast_json_timeval(*stasis_message_timestamp(msg), NULL),
359                 "bridge", json_bridge_to,
360                 "bridge_from", json_bridge_from);
361 }
362
363 void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from)
364 {
365         RAII_VAR(struct ast_bridge_merge_message *, merge_msg, NULL, ao2_cleanup);
366         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
367
368         if (!ast_bridge_merge_message_type()) {
369                 return;
370         }
371
372         ast_assert(to != NULL);
373         ast_assert(from != NULL);
374
375         merge_msg = bridge_merge_message_create(to, from);
376         if (!merge_msg) {
377                 return;
378         }
379
380         msg = stasis_message_create(ast_bridge_merge_message_type(), merge_msg);
381         if (!msg) {
382                 return;
383         }
384
385         stasis_publish(ast_bridge_topic_all(), msg);
386 }
387
388 static void bridge_blob_dtor(void *obj)
389 {
390         struct ast_bridge_blob *event = obj;
391         ao2_cleanup(event->bridge);
392         event->bridge = NULL;
393         ao2_cleanup(event->channel);
394         event->channel = NULL;
395         ast_json_unref(event->blob);
396         event->blob = NULL;
397 }
398
399 struct stasis_message *ast_bridge_blob_create(
400         struct stasis_message_type *message_type,
401         struct ast_bridge *bridge,
402         struct ast_channel *chan,
403         struct ast_json *blob)
404 {
405         RAII_VAR(struct ast_bridge_blob *, obj, NULL, ao2_cleanup);
406         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
407
408         if (!message_type) {
409                 return NULL;
410         }
411
412         obj = ao2_alloc(sizeof(*obj), bridge_blob_dtor);
413         if (!obj) {
414                 return NULL;
415         }
416
417         if (bridge) {
418                 obj->bridge = ast_bridge_snapshot_create(bridge);
419                 if (obj->bridge == NULL) {
420                         return NULL;
421                 }
422         }
423
424         if (chan) {
425                 obj->channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
426                 if (obj->channel == NULL) {
427                         return NULL;
428                 }
429         }
430
431         if (blob) {
432                 obj->blob = ast_json_ref(blob);
433         }
434
435         msg = stasis_message_create(message_type, obj);
436         if (!msg) {
437                 return NULL;
438         }
439
440         ao2_ref(msg, +1);
441         return msg;
442 }
443
444 void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *chan,
445                 struct ast_channel *swap)
446 {
447         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
448         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
449
450         if (swap) {
451                 blob = ast_json_pack("{s: s}", "swap", ast_channel_uniqueid(swap));
452                 if (!blob) {
453                         return;
454                 }
455         }
456
457         msg = ast_bridge_blob_create(ast_channel_entered_bridge_type(), bridge, chan, blob);
458         if (!msg) {
459                 return;
460         }
461
462         /* enter blob first, then state */
463         stasis_publish(ast_bridge_topic(bridge), msg);
464         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
465 }
466
467 void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *chan)
468 {
469         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
470
471         msg = ast_bridge_blob_create(ast_channel_left_bridge_type(), bridge, chan, NULL);
472         if (!msg) {
473                 return;
474         }
475
476         /* state first, then leave blob (opposite of enter, preserves nesting of events) */
477         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
478         stasis_publish(ast_bridge_topic(bridge), msg);
479 }
480
481 static struct ast_json *simple_bridge_channel_event(
482         const char *type,
483         struct ast_bridge_snapshot *bridge_snapshot,
484         struct ast_channel_snapshot *channel_snapshot,
485         const struct timeval *tv,
486         const struct stasis_message_sanitizer *sanitize)
487 {
488         RAII_VAR(struct ast_json *, json_bridge,
489                 ast_bridge_snapshot_to_json(bridge_snapshot, sanitize), ast_json_unref);
490         RAII_VAR(struct ast_json *, json_channel,
491                 ast_channel_snapshot_to_json(channel_snapshot, sanitize), ast_json_unref);
492
493         if (!json_bridge || !json_channel) {
494                 return NULL;
495         }
496
497         return ast_json_pack("{s: s, s: o, s: O, s: O}",
498                 "type", type,
499                 "timestamp", ast_json_timeval(*tv, NULL),
500                 "bridge", json_bridge,
501                 "channel", json_channel);
502 }
503
504 struct ast_json *ast_channel_entered_bridge_to_json(
505         struct stasis_message *msg,
506         const struct stasis_message_sanitizer *sanitize)
507 {
508         struct ast_bridge_blob *obj = stasis_message_data(msg);
509
510         return simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
511                 obj->channel, stasis_message_timestamp(msg), sanitize);
512 }
513
514 struct ast_json *ast_channel_left_bridge_to_json(
515         struct stasis_message *msg,
516         const struct stasis_message_sanitizer *sanitize)
517 {
518         struct ast_bridge_blob *obj = stasis_message_data(msg);
519
520         return simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
521                 obj->channel, stasis_message_timestamp(msg), sanitize);
522 }
523
524 static struct ast_json *container_to_json_array(struct ao2_container *items,
525         const struct stasis_message_sanitizer *sanitize)
526 {
527         RAII_VAR(struct ast_json *, json_items, ast_json_array_create(), ast_json_unref);
528         char *item;
529         struct ao2_iterator it;
530         if (!json_items) {
531                 return NULL;
532         }
533
534         for (it = ao2_iterator_init(items, 0);
535                 (item = ao2_iterator_next(&it)); ao2_cleanup(item)) {
536                 if (sanitize && sanitize->channel_id && sanitize->channel_id(item)) {
537                         continue;
538                 }
539
540                 if (ast_json_array_append(json_items, ast_json_string_create(item))) {
541                         ao2_cleanup(item);
542                         ao2_iterator_destroy(&it);
543                         return NULL;
544                 }
545         }
546         ao2_iterator_destroy(&it);
547
548         return ast_json_ref(json_items);
549 }
550
551 static const char *capability2str(uint32_t capabilities)
552 {
553         if (capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
554                 return "holding";
555         } else {
556                 return "mixing";
557         }
558 }
559
560 struct ast_json *ast_bridge_snapshot_to_json(
561         const struct ast_bridge_snapshot *snapshot,
562         const struct stasis_message_sanitizer *sanitize)
563 {
564         RAII_VAR(struct ast_json *, json_bridge, NULL, ast_json_unref);
565         struct ast_json *json_channels;
566
567         if (snapshot == NULL) {
568                 return NULL;
569         }
570
571         json_channels = container_to_json_array(snapshot->channels, sanitize);
572         if (!json_channels) {
573                 return NULL;
574         }
575
576         json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
577                 "id", snapshot->uniqueid,
578                 "technology", snapshot->technology,
579                 "bridge_type", capability2str(snapshot->capabilities),
580                 "bridge_class", snapshot->subclass,
581                 "creator", snapshot->creator,
582                 "name", snapshot->name,
583                 "channels", json_channels);
584         if (!json_bridge) {
585                 return NULL;
586         }
587
588         return ast_json_ref(json_bridge);
589 }
590
591 /*!
592  * \internal
593  * \brief Allocate the fields of an \ref ast_bridge_channel_snapshot_pair.
594  *
595  * \param pair A bridge and channel to get snapshots of
596  * \param[out] snapshot_pair An allocated snapshot pair.
597  * \retval 0 Success
598  * \retval non-zero Failure
599  */
600 static int bridge_channel_snapshot_pair_init(struct ast_channel *channel, struct ast_bridge *bridge,
601                 struct ast_bridge_channel_snapshot_pair *snapshot_pair)
602 {
603         if (bridge) {
604                 ast_bridge_lock(bridge);
605                 snapshot_pair->bridge_snapshot = ast_bridge_snapshot_create(bridge);
606                 ast_bridge_unlock(bridge);
607                 if (!snapshot_pair->bridge_snapshot) {
608                         return -1;
609                 }
610         }
611
612         snapshot_pair->channel_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(channel));
613         if (!snapshot_pair->channel_snapshot) {
614                 return -1;
615         }
616
617         return 0;
618 }
619
620 /*!
621  * \internal
622  * \brief Free the fields of an \ref ast_bridge_channel_snapshot_pair.
623  *
624  * \param pair The snapshot pair whose fields are to be cleaned up
625  */
626 static void bridge_channel_snapshot_pair_cleanup(struct ast_bridge_channel_snapshot_pair *pair)
627 {
628         ao2_cleanup(pair->bridge_snapshot);
629         ao2_cleanup(pair->channel_snapshot);
630 }
631
632 static const char *result_strs[] = {
633         [AST_BRIDGE_TRANSFER_FAIL] = "Fail",
634         [AST_BRIDGE_TRANSFER_INVALID] = "Invalid",
635         [AST_BRIDGE_TRANSFER_NOT_PERMITTED] = "Not Permitted",
636         [AST_BRIDGE_TRANSFER_SUCCESS] = "Success",
637 };
638
639 static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
640         const struct stasis_message_sanitizer *sanitize)
641 {
642         struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
643         struct ast_json *json_transferer;
644         struct ast_json *json_transferee = NULL;
645         struct ast_json *out;
646         struct ast_json *json_replace = NULL;
647         const struct timeval *tv = stasis_message_timestamp(msg);
648
649         json_transferer = ast_channel_snapshot_to_json(transfer_msg->transferer, sanitize);
650         if (!json_transferer) {
651                 return NULL;
652         }
653
654         if (transfer_msg->transferee) {
655                 json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
656                 if (!json_transferee) {
657                         ast_json_unref(json_transferer);
658                         return NULL;
659                 }
660         }
661
662         if (transfer_msg->replace_channel) {
663                 json_replace = ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize);
664                 if (!json_replace) {
665                         ast_json_unref(json_transferee);
666                         ast_json_unref(json_transferer);
667                         return NULL;
668                 }
669         }
670
671         out = ast_json_pack("{s: s, s: o, s: o, s: s, s: s, s: s, s: o}",
672                 "type", "BridgeBlindTransfer",
673                 "timestamp", ast_json_timeval(*tv, NULL),
674                 "channel", json_transferer,
675                 "exten", transfer_msg->exten,
676                 "context", transfer_msg->context,
677                 "result", result_strs[transfer_msg->result],
678                 "is_external", ast_json_boolean(transfer_msg->is_external));
679
680         if (!out) {
681                 ast_json_unref(json_transferee);
682                 ast_json_unref(json_replace);
683                 return NULL;
684         }
685
686         if (json_transferee && ast_json_object_set(out, "transferee", json_transferee)) {
687                 ast_json_unref(out);
688                 ast_json_unref(json_replace);
689                 return NULL;
690         }
691
692         if (json_replace && ast_json_object_set(out, "replace_channel", json_replace)) {
693                 ast_json_unref(out);
694                 return NULL;
695         }
696
697         if (transfer_msg->bridge) {
698                 struct ast_json *json_bridge = ast_bridge_snapshot_to_json(
699                                 transfer_msg->bridge, sanitize);
700
701                 if (!json_bridge || ast_json_object_set(out, "bridge", json_bridge)) {
702                         ast_json_unref(out);
703                         return NULL;
704                 }
705         }
706
707         return out;
708 }
709
710 static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *msg)
711 {
712         RAII_VAR(struct ast_str *, transferer_state, NULL, ast_free_ptr);
713         RAII_VAR(struct ast_str *, bridge_state, NULL, ast_free_ptr);
714         RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
715         struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
716
717         if (!transfer_msg) {
718                 return NULL;
719         }
720
721         transferer_state = ast_manager_build_channel_state_string_prefix(
722                         transfer_msg->transferer, "Transferer");
723         if (!transferer_state) {
724                 return NULL;
725         }
726
727         if (transfer_msg->bridge) {
728                 bridge_state = ast_manager_build_bridge_state_string(transfer_msg->bridge);
729                 if (!bridge_state) {
730                         return NULL;
731                 }
732         }
733
734         if (transfer_msg->transferee) {
735                 transferee_state = ast_manager_build_channel_state_string_prefix(
736                                 transfer_msg->transferee, "Transferee");
737                 if (!transferee_state) {
738                         return NULL;
739                 }
740         }
741
742         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "BlindTransfer",
743                         "Result: %s\r\n"
744                         "%s"
745                         "%s"
746                         "%s"
747                         "IsExternal: %s\r\n"
748                         "Context: %s\r\n"
749                         "Extension: %s\r\n",
750                         result_strs[transfer_msg->result],
751                         ast_str_buffer(transferer_state),
752                         transferee_state ? ast_str_buffer(transferee_state) : "",
753                         bridge_state ? ast_str_buffer(bridge_state) : "",
754                         transfer_msg->is_external ? "Yes" : "No",
755                         transfer_msg->context,
756                         transfer_msg->exten);
757 }
758
759 static void blind_transfer_dtor(void *obj)
760 {
761         struct ast_blind_transfer_message *msg = obj;
762
763         ao2_cleanup(msg->transferer);
764         ao2_cleanup(msg->bridge);
765         ao2_cleanup(msg->transferee);
766         ao2_cleanup(msg->replace_channel);
767 }
768
769 struct ast_blind_transfer_message *ast_blind_transfer_message_create(int is_external,
770                 struct ast_channel *transferer, const char *exten, const char *context)
771 {
772         struct ast_blind_transfer_message *msg;
773
774         msg = ao2_alloc(sizeof(*msg), blind_transfer_dtor);
775         if (!msg) {
776                 return NULL;
777         }
778
779         msg->transferer = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferer));
780         if (!msg->transferer) {
781                 ao2_cleanup(msg);
782                 return NULL;
783         }
784
785         msg->is_external = is_external;
786         ast_copy_string(msg->context, context, sizeof(msg->context));
787         ast_copy_string(msg->exten, exten, sizeof(msg->exten));
788
789         return msg;
790 }
791
792
793 void ast_bridge_publish_blind_transfer(struct ast_blind_transfer_message *transfer_message)
794 {
795         struct stasis_message *stasis;
796
797         stasis = stasis_message_create(ast_blind_transfer_type(), transfer_message);
798         if (!stasis) {
799                 return;
800         }
801
802         stasis_publish(ast_bridge_topic_all(), stasis);
803
804         ao2_cleanup(stasis);
805 }
806
807 static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
808         const struct stasis_message_sanitizer *sanitize)
809 {
810         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
811         RAII_VAR(struct ast_json *, out, NULL, ast_json_unref);
812         struct ast_json *json_transferer1, *json_transferer2, *json_bridge, *json_channel;
813         struct ast_json *json_transferee = NULL, *json_target = NULL;
814         const struct timeval *tv = stasis_message_timestamp(msg);
815         int res = 0;
816
817         json_transferer1 = ast_channel_snapshot_to_json(transfer_msg->to_transferee.channel_snapshot, sanitize);
818         if (!json_transferer1) {
819                 return NULL;
820         }
821
822         json_transferer2 = ast_channel_snapshot_to_json(transfer_msg->to_transfer_target.channel_snapshot, sanitize);
823         if (!json_transferer2) {
824                 ast_json_unref(json_transferer1);
825                 return NULL;
826         }
827
828         if (transfer_msg->transferee) {
829                 json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
830                 if (!json_transferee) {
831                         return NULL;
832                 }
833         }
834
835         if (transfer_msg->target) {
836                 json_target = ast_channel_snapshot_to_json(transfer_msg->target, sanitize);
837                 if (!json_target) {
838                         return NULL;
839                 }
840         }
841
842         out = ast_json_pack("{s: s, s: o, s: o, s: o, s: s, s: o}",
843                 "type", "BridgeAttendedTransfer",
844                 "timestamp", ast_json_timeval(*tv, NULL),
845                 "transferer_first_leg", json_transferer1,
846                 "transferer_second_leg", json_transferer2,
847                 "result", result_strs[transfer_msg->result],
848                 "is_external", ast_json_boolean(transfer_msg->is_external));
849         if (!out) {
850                 return NULL;
851         }
852         if (json_transferee && ast_json_object_set(out, "transferee", json_transferee)) {
853                 return NULL;
854         }
855         if (json_target && ast_json_object_set(out, "transfer_target", json_target)) {
856                 return NULL;
857         }
858
859         if (transfer_msg->to_transferee.bridge_snapshot) {
860                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->to_transferee.bridge_snapshot, sanitize);
861
862                 if (!json_bridge) {
863                         return NULL;
864                 }
865
866                 res |= ast_json_object_set(out, "transferer_first_leg_bridge", json_bridge);
867         }
868
869         if (transfer_msg->to_transfer_target.bridge_snapshot) {
870                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->to_transfer_target.bridge_snapshot, sanitize);
871
872                 if (!json_bridge) {
873                         return NULL;
874                 }
875
876                 res |= ast_json_object_set(out, "transferer_second_leg_bridge", json_bridge);
877         }
878
879         switch (transfer_msg->dest_type) {
880         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
881                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("bridge"));
882                 res |= ast_json_object_set(out, "destination_bridge", ast_json_string_create(transfer_msg->dest.bridge));
883                 break;
884         case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
885                 res |= ast_json_object_set(out, "replace_channel", ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize));
886                 /* fallthrough */
887         case AST_ATTENDED_TRANSFER_DEST_APP:
888                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("application"));
889                 res |= ast_json_object_set(out, "destination_application", ast_json_string_create(transfer_msg->dest.app));
890                 break;
891         case AST_ATTENDED_TRANSFER_DEST_LINK:
892                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("link"));
893
894                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.links[0], sanitize);
895                 if (!json_channel) {
896                         return NULL;
897                 }
898                 res |= ast_json_object_set(out, "destination_link_first_leg", json_channel);
899
900                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.links[1], sanitize);
901                 if (!json_channel) {
902                         return NULL;
903                 }
904                 res |= ast_json_object_set(out, "destination_link_second_leg", json_channel);
905
906                 break;
907         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
908                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("threeway"));
909
910                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.threeway.channel_snapshot, sanitize);
911                 if (!json_channel) {
912                         return NULL;
913                 }
914                 res |= ast_json_object_set(out, "destination_threeway_channel", json_channel);
915
916                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->dest.threeway.bridge_snapshot, sanitize);
917                 if (!json_bridge) {
918                         return NULL;
919                 }
920                 res |= ast_json_object_set(out, "destination_threeway_bridge", json_bridge);
921
922                 break;
923         case AST_ATTENDED_TRANSFER_DEST_FAIL:
924                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("fail"));
925                 break;
926         }
927
928         if (res) {
929                 return NULL;
930         }
931
932         return ast_json_ref(out);
933 }
934
935 static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *msg)
936 {
937         RAII_VAR(struct ast_str *, variable_data, ast_str_create(64), ast_free_ptr);
938         RAII_VAR(struct ast_str *, transferer1_state, NULL, ast_free_ptr);
939         RAII_VAR(struct ast_str *, bridge1_state, NULL, ast_free_ptr);
940         RAII_VAR(struct ast_str *, transferer2_state, NULL, ast_free_ptr);
941         RAII_VAR(struct ast_str *, bridge2_state, NULL, ast_free_ptr);
942         RAII_VAR(struct ast_str *, local1_state, NULL, ast_free_ptr);
943         RAII_VAR(struct ast_str *, local2_state, NULL, ast_free_ptr);
944         RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
945         RAII_VAR(struct ast_str *, target_state, NULL, ast_free_ptr);
946         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
947
948         if (!variable_data) {
949                 return NULL;
950         }
951
952         transferer1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transferee.channel_snapshot, "OrigTransferer");
953         transferer2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transfer_target.channel_snapshot, "SecondTransferer");
954         if (!transferer1_state || !transferer2_state) {
955                 return NULL;
956         }
957         if (transfer_msg->transferee) {
958                 transferee_state = ast_manager_build_channel_state_string_prefix(transfer_msg->transferee, "Transferee");
959                 if (!transferee_state) {
960                         return NULL;
961                 }
962         }
963
964         if (transfer_msg->target) {
965                 target_state = ast_manager_build_channel_state_string_prefix(transfer_msg->target, "TransferTarget");
966                 if (!target_state) {
967                         return NULL;
968                 }
969         }
970
971         if (transfer_msg->to_transferee.bridge_snapshot) {
972                 bridge1_state = ast_manager_build_bridge_state_string_prefix(
973                         transfer_msg->to_transferee.bridge_snapshot, "Orig");
974                 if (!bridge1_state) {
975                         return NULL;
976                 }
977         }
978
979         if (transfer_msg->to_transfer_target.bridge_snapshot) {
980                 bridge2_state = ast_manager_build_bridge_state_string_prefix(
981                         transfer_msg->to_transfer_target.bridge_snapshot, "Second");
982                 if (!bridge2_state) {
983                         return NULL;
984                 }
985         }
986
987         switch (transfer_msg->dest_type) {
988         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
989                 ast_str_append(&variable_data, 0, "DestType: Bridge\r\n");
990                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.bridge);
991                 break;
992         case AST_ATTENDED_TRANSFER_DEST_APP:
993         case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
994                 ast_str_append(&variable_data, 0, "DestType: App\r\n");
995                 ast_str_append(&variable_data, 0, "DestApp: %s\r\n", transfer_msg->dest.app);
996                 break;
997         case AST_ATTENDED_TRANSFER_DEST_LINK:
998                 local1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[0], "LocalOne");
999                 local2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[1], "LocalTwo");
1000                 if (!local1_state || !local2_state) {
1001                         return NULL;
1002                 }
1003                 ast_str_append(&variable_data, 0, "DestType: Link\r\n");
1004                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local1_state));
1005                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local2_state));
1006                 break;
1007         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
1008                 ast_str_append(&variable_data, 0, "DestType: Threeway\r\n");
1009                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.threeway.bridge_snapshot->uniqueid);
1010                 ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->name);
1011                 break;
1012         case AST_ATTENDED_TRANSFER_DEST_FAIL:
1013                 ast_str_append(&variable_data, 0, "DestType: Fail\r\n");
1014                 break;
1015         }
1016
1017         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "AttendedTransfer",
1018                         "Result: %s\r\n"
1019                         "%s"
1020                         "%s"
1021                         "%s"
1022                         "%s"
1023                         "%s"
1024                         "%s"
1025                         "IsExternal: %s\r\n"
1026                         "%s",
1027                         result_strs[transfer_msg->result],
1028                         ast_str_buffer(transferer1_state),
1029                         bridge1_state ? ast_str_buffer(bridge1_state) : "",
1030                         ast_str_buffer(transferer2_state),
1031                         bridge2_state ? ast_str_buffer(bridge2_state) : "",
1032                         transferee_state ? ast_str_buffer(transferee_state) : "",
1033                         target_state ? ast_str_buffer(target_state) : "",
1034                         transfer_msg->is_external ? "Yes" : "No",
1035                         ast_str_buffer(variable_data));
1036 }
1037
1038 static void attended_transfer_dtor(void *obj)
1039 {
1040         struct ast_attended_transfer_message *msg = obj;
1041         int i;
1042
1043         bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
1044         bridge_channel_snapshot_pair_cleanup(&msg->to_transfer_target);
1045         ao2_cleanup(msg->replace_channel);
1046         ao2_cleanup(msg->transferee);
1047         ao2_cleanup(msg->target);
1048
1049         if (msg->dest_type != AST_ATTENDED_TRANSFER_DEST_LINK) {
1050                 return;
1051         }
1052
1053         for (i = 0; i < ARRAY_LEN(msg->dest.links); ++i) {
1054                 ao2_cleanup(msg->dest.links[i]);
1055         }
1056 }
1057
1058 struct ast_attended_transfer_message *ast_attended_transfer_message_create(int is_external,
1059                 struct ast_channel *to_transferee, struct ast_bridge *transferee_bridge,
1060                 struct ast_channel *to_transfer_target, struct ast_bridge *target_bridge,
1061                 struct ast_channel *transferee, struct ast_channel *transfer_target)
1062 {
1063         struct ast_attended_transfer_message *transfer_msg;
1064
1065         transfer_msg = ao2_alloc(sizeof(*transfer_msg), attended_transfer_dtor);
1066         if (!transfer_msg) {
1067                 return NULL;
1068         }
1069
1070         if (bridge_channel_snapshot_pair_init(to_transferee, transferee_bridge, &transfer_msg->to_transferee) ||
1071                         bridge_channel_snapshot_pair_init(to_transfer_target, target_bridge, &transfer_msg->to_transfer_target)) {
1072                 ao2_cleanup(transfer_msg);
1073                 return NULL;
1074         }
1075
1076         if (transferee) {
1077                 transfer_msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee));
1078                 if (!transfer_msg->transferee) {
1079                         ao2_cleanup(transfer_msg);
1080                         return NULL;
1081                 }
1082         } else if (transferee_bridge) {
1083                 transferee = ast_bridge_peer(transferee_bridge, to_transferee);
1084                 if (transferee) {
1085                         transfer_msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee));
1086                         ao2_cleanup(transferee);
1087                         if (!transfer_msg->transferee) {
1088                                 ao2_cleanup(transfer_msg);
1089                                 return NULL;
1090                         }
1091                 }
1092         }
1093
1094         if (transfer_target) {
1095                 transfer_msg->target = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transfer_target));
1096                 if (!transfer_msg->target) {
1097                         ao2_cleanup(transfer_msg);
1098                         return NULL;
1099                 }
1100         } else if (target_bridge) {
1101                 transfer_target = ast_bridge_peer(target_bridge, to_transfer_target);
1102                 if (transfer_target) {
1103                         transfer_msg->target = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transfer_target));
1104                         ao2_cleanup(transfer_target);
1105                         if (!transfer_msg->target) {
1106                                 ao2_cleanup(transfer_msg);
1107                                 return NULL;
1108                         }
1109                 }
1110         }
1111
1112         return transfer_msg;
1113 }
1114
1115 int ast_attended_transfer_message_add_merge(struct ast_attended_transfer_message *transfer_msg,
1116                 struct ast_bridge *final_bridge)
1117 {
1118         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE;
1119         ast_copy_string(transfer_msg->dest.bridge, final_bridge->uniqueid,
1120                         sizeof(transfer_msg->dest.bridge));
1121
1122         return 0;
1123 }
1124
1125 int ast_attended_transfer_message_add_threeway(struct ast_attended_transfer_message *transfer_msg,
1126                 struct ast_channel *survivor_channel, struct ast_bridge *survivor_bridge)
1127 {
1128         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_THREEWAY;
1129
1130         if (!strcmp(ast_channel_uniqueid(survivor_channel), transfer_msg->to_transferee.channel_snapshot->uniqueid)) {
1131                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transferee.channel_snapshot;
1132         } else {
1133                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transfer_target.channel_snapshot;
1134         }
1135
1136         if (!strcmp(survivor_bridge->uniqueid, transfer_msg->to_transferee.bridge_snapshot->uniqueid)) {
1137                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transferee.bridge_snapshot;
1138         } else {
1139                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transfer_target.bridge_snapshot;
1140         }
1141
1142         return 0;
1143 }
1144
1145 int ast_attended_transfer_message_add_app(struct ast_attended_transfer_message *transfer_msg,
1146                 const char *app, struct ast_channel *replace_channel)
1147 {
1148         transfer_msg->dest_type = replace_channel ? AST_ATTENDED_TRANSFER_DEST_LOCAL_APP : AST_ATTENDED_TRANSFER_DEST_APP;
1149
1150         if (replace_channel) {
1151                 transfer_msg->replace_channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(replace_channel));
1152                 if (!transfer_msg->replace_channel) {
1153                         return -1;
1154                 }
1155         }
1156
1157         ast_copy_string(transfer_msg->dest.app, app, sizeof(transfer_msg->dest.app));
1158
1159         return 0;
1160 }
1161
1162 int ast_attended_transfer_message_add_link(struct ast_attended_transfer_message *transfer_msg,
1163                 struct ast_channel *locals[2])
1164 {
1165         int i;
1166
1167         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
1168         for (i = 0; i < 2; ++i) {
1169                 transfer_msg->dest.links[i] = ast_channel_snapshot_get_latest(ast_channel_uniqueid(locals[i]));
1170                 if (!transfer_msg->dest.links[i]) {
1171                         return -1;
1172                 }
1173         }
1174
1175         return 0;
1176 }
1177
1178 void ast_bridge_publish_attended_transfer(struct ast_attended_transfer_message *transfer_msg)
1179 {
1180         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1181
1182         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
1183         if (!msg) {
1184                 return;
1185         }
1186
1187         stasis_publish(ast_bridge_topic_all(), msg);
1188 }
1189
1190 struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
1191 {
1192         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
1193         struct ast_bridge_snapshot *snapshot;
1194
1195         ast_assert(!ast_strlen_zero(uniqueid));
1196
1197         message = stasis_cache_get(ast_bridge_cache(),
1198                         ast_bridge_snapshot_type(),
1199                         uniqueid);
1200         if (!message) {
1201                 return NULL;
1202         }
1203
1204         snapshot = stasis_message_data(message);
1205         if (!snapshot) {
1206                 return NULL;
1207         }
1208         ao2_ref(snapshot, +1);
1209         return snapshot;
1210 }
1211
1212 /*! \brief snapshot ID getter for caching topic */
1213 static const char *bridge_snapshot_get_id(struct stasis_message *msg)
1214 {
1215         struct ast_bridge_snapshot *snapshot;
1216         if (stasis_message_type(msg) != ast_bridge_snapshot_type()) {
1217                 return NULL;
1218         }
1219         snapshot = stasis_message_data(msg);
1220         return snapshot->uniqueid;
1221 }
1222
1223 static void stasis_bridging_cleanup(void)
1224 {
1225         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);
1226         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_merge_message_type);
1227         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_entered_bridge_type);
1228         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_left_bridge_type);
1229         STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);
1230         STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);
1231
1232         ao2_cleanup(bridge_cache_all);
1233         bridge_cache_all = NULL;
1234 }
1235
1236 int ast_stasis_bridging_init(void)
1237 {
1238         int res = 0;
1239
1240         ast_register_cleanup(stasis_bridging_cleanup);
1241
1242         bridge_cache_all = stasis_cp_all_create("ast_bridge_topic_all",
1243                 bridge_snapshot_get_id);
1244
1245         if (!bridge_cache_all) {
1246                 return -1;
1247         }
1248
1249         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_snapshot_type);
1250         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_merge_message_type);
1251         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_entered_bridge_type);
1252         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_left_bridge_type);
1253         res |= STASIS_MESSAGE_TYPE_INIT(ast_blind_transfer_type);
1254         res |= STASIS_MESSAGE_TYPE_INIT(ast_attended_transfer_type);
1255
1256         return res;
1257 }