16fda2d491411ebbfe002582906b292f671329a4
[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(sizeof(*snapshot), bridge_snapshot_dtor);
236         if (!snapshot || ast_string_field_init(snapshot, 128)) {
237                 return NULL;
238         }
239
240         snapshot->channels = ast_str_container_alloc(SNAPSHOT_CHANNELS_BUCKETS);
241         if (!snapshot->channels) {
242                 return NULL;
243         }
244
245         AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
246                 if (ast_str_container_add(snapshot->channels,
247                                 ast_channel_uniqueid(bridge_channel->chan))) {
248                         return NULL;
249                 }
250         }
251
252         ast_string_field_set(snapshot, uniqueid, bridge->uniqueid);
253         ast_string_field_set(snapshot, technology, bridge->technology->name);
254         ast_string_field_set(snapshot, subclass, bridge->v_table->name);
255         ast_string_field_set(snapshot, creator, bridge->creator);
256         ast_string_field_set(snapshot, name, bridge->name);
257
258         snapshot->feature_flags = bridge->feature_flags;
259         snapshot->capabilities = bridge->technology->capabilities;
260         snapshot->num_channels = bridge->num_channels;
261         snapshot->num_active = bridge->num_active;
262
263         ao2_ref(snapshot, +1);
264         return snapshot;
265 }
266
267 void ast_bridge_publish_state(struct ast_bridge *bridge)
268 {
269         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
270         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
271
272         if (!ast_bridge_snapshot_type()) {
273                 return;
274         }
275
276         ast_assert(bridge != NULL);
277
278         snapshot = ast_bridge_snapshot_create(bridge);
279         if (!snapshot) {
280                 return;
281         }
282
283         msg = stasis_message_create(ast_bridge_snapshot_type(), snapshot);
284         if (!msg) {
285                 return;
286         }
287
288         stasis_publish(ast_bridge_topic(bridge), msg);
289 }
290
291 static void bridge_publish_state_from_blob(struct ast_bridge *bridge,
292         struct ast_bridge_blob *obj)
293 {
294         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
295
296         ast_assert(obj != NULL);
297
298         msg = stasis_message_create(ast_bridge_snapshot_type(), obj->bridge);
299         if (!msg) {
300                 return;
301         }
302
303         stasis_publish(ast_bridge_topic(bridge), msg);
304 }
305
306 /*! \brief Destructor for bridge merge messages */
307 static void bridge_merge_message_dtor(void *obj)
308 {
309         struct ast_bridge_merge_message *msg = obj;
310
311         ao2_cleanup(msg->to);
312         msg->to = NULL;
313         ao2_cleanup(msg->from);
314         msg->from = NULL;
315 }
316
317 /*! \brief Bridge merge message creation helper */
318 static struct ast_bridge_merge_message *bridge_merge_message_create(struct ast_bridge *to, struct ast_bridge *from)
319 {
320         RAII_VAR(struct ast_bridge_merge_message *, msg, NULL, ao2_cleanup);
321
322         msg = ao2_alloc(sizeof(*msg), bridge_merge_message_dtor);
323         if (!msg) {
324                 return NULL;
325         }
326
327         msg->to = ast_bridge_snapshot_create(to);
328         if (!msg->to) {
329                 return NULL;
330         }
331
332         msg->from = ast_bridge_snapshot_create(from);
333         if (!msg->from) {
334                 return NULL;
335         }
336
337         ao2_ref(msg, +1);
338         return msg;
339 }
340
341 static struct ast_json *ast_bridge_merge_message_to_json(
342         struct stasis_message *msg,
343         const struct stasis_message_sanitizer *sanitize)
344 {
345         struct ast_bridge_merge_message *merge = stasis_message_data(msg);
346         RAII_VAR(struct ast_json *, json_bridge_to,
347                 ast_bridge_snapshot_to_json(merge->to, sanitize), ast_json_unref);
348         RAII_VAR(struct ast_json *, json_bridge_from,
349                 ast_bridge_snapshot_to_json(merge->from, sanitize), ast_json_unref);
350
351         if (!json_bridge_to || !json_bridge_from) {
352                 return NULL;
353         }
354
355         return ast_json_pack("{s: s, s: o, s: O, s: O}",
356                 "type", "BridgeMerged",
357                 "timestamp", ast_json_timeval(*stasis_message_timestamp(msg), NULL),
358                 "bridge", json_bridge_to,
359                 "bridge_from", json_bridge_from);
360 }
361
362 void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from)
363 {
364         RAII_VAR(struct ast_bridge_merge_message *, merge_msg, NULL, ao2_cleanup);
365         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
366
367         if (!ast_bridge_merge_message_type()) {
368                 return;
369         }
370
371         ast_assert(to != NULL);
372         ast_assert(from != NULL);
373
374         merge_msg = bridge_merge_message_create(to, from);
375         if (!merge_msg) {
376                 return;
377         }
378
379         msg = stasis_message_create(ast_bridge_merge_message_type(), merge_msg);
380         if (!msg) {
381                 return;
382         }
383
384         stasis_publish(ast_bridge_topic_all(), msg);
385 }
386
387 static void bridge_blob_dtor(void *obj)
388 {
389         struct ast_bridge_blob *event = obj;
390         ao2_cleanup(event->bridge);
391         event->bridge = NULL;
392         ao2_cleanup(event->channel);
393         event->channel = NULL;
394         ast_json_unref(event->blob);
395         event->blob = NULL;
396 }
397
398 struct stasis_message *ast_bridge_blob_create(
399         struct stasis_message_type *message_type,
400         struct ast_bridge *bridge,
401         struct ast_channel *chan,
402         struct ast_json *blob)
403 {
404         RAII_VAR(struct ast_bridge_blob *, obj, NULL, ao2_cleanup);
405         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
406
407         if (!message_type) {
408                 return NULL;
409         }
410
411         obj = ao2_alloc(sizeof(*obj), bridge_blob_dtor);
412         if (!obj) {
413                 return NULL;
414         }
415
416         if (bridge) {
417                 obj->bridge = ast_bridge_snapshot_create(bridge);
418                 if (obj->bridge == NULL) {
419                         return NULL;
420                 }
421         }
422
423         if (chan) {
424                 obj->channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
425                 if (obj->channel == NULL) {
426                         return NULL;
427                 }
428         }
429
430         if (blob) {
431                 obj->blob = ast_json_ref(blob);
432         }
433
434         msg = stasis_message_create(message_type, obj);
435         if (!msg) {
436                 return NULL;
437         }
438
439         ao2_ref(msg, +1);
440         return msg;
441 }
442
443 void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *chan,
444                 struct ast_channel *swap)
445 {
446         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
447         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
448
449         if (swap) {
450                 blob = ast_json_pack("{s: s}", "swap", ast_channel_uniqueid(swap));
451                 if (!blob) {
452                         return;
453                 }
454         }
455
456         msg = ast_bridge_blob_create(ast_channel_entered_bridge_type(), bridge, chan, blob);
457         if (!msg) {
458                 return;
459         }
460
461         /* enter blob first, then state */
462         stasis_publish(ast_bridge_topic(bridge), msg);
463         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
464 }
465
466 void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *chan)
467 {
468         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
469
470         msg = ast_bridge_blob_create(ast_channel_left_bridge_type(), bridge, chan, NULL);
471         if (!msg) {
472                 return;
473         }
474
475         /* state first, then leave blob (opposite of enter, preserves nesting of events) */
476         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
477         stasis_publish(ast_bridge_topic(bridge), msg);
478 }
479
480 static struct ast_json *simple_bridge_channel_event(
481         const char *type,
482         struct ast_bridge_snapshot *bridge_snapshot,
483         struct ast_channel_snapshot *channel_snapshot,
484         const struct timeval *tv,
485         const struct stasis_message_sanitizer *sanitize)
486 {
487         RAII_VAR(struct ast_json *, json_bridge,
488                 ast_bridge_snapshot_to_json(bridge_snapshot, sanitize), ast_json_unref);
489         RAII_VAR(struct ast_json *, json_channel,
490                 ast_channel_snapshot_to_json(channel_snapshot, sanitize), ast_json_unref);
491
492         if (!json_bridge || !json_channel) {
493                 return NULL;
494         }
495
496         return ast_json_pack("{s: s, s: o, s: O, s: O}",
497                 "type", type,
498                 "timestamp", ast_json_timeval(*tv, NULL),
499                 "bridge", json_bridge,
500                 "channel", json_channel);
501 }
502
503 struct ast_json *ast_channel_entered_bridge_to_json(
504         struct stasis_message *msg,
505         const struct stasis_message_sanitizer *sanitize)
506 {
507         struct ast_bridge_blob *obj = stasis_message_data(msg);
508
509         return simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
510                 obj->channel, stasis_message_timestamp(msg), sanitize);
511 }
512
513 struct ast_json *ast_channel_left_bridge_to_json(
514         struct stasis_message *msg,
515         const struct stasis_message_sanitizer *sanitize)
516 {
517         struct ast_bridge_blob *obj = stasis_message_data(msg);
518
519         return simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
520                 obj->channel, stasis_message_timestamp(msg), sanitize);
521 }
522
523 static struct ast_json *container_to_json_array(struct ao2_container *items,
524         const struct stasis_message_sanitizer *sanitize)
525 {
526         RAII_VAR(struct ast_json *, json_items, ast_json_array_create(), ast_json_unref);
527         char *item;
528         struct ao2_iterator it;
529         if (!json_items) {
530                 return NULL;
531         }
532
533         for (it = ao2_iterator_init(items, 0);
534                 (item = ao2_iterator_next(&it)); ao2_cleanup(item)) {
535                 if (sanitize && sanitize->channel_id && sanitize->channel_id(item)) {
536                         continue;
537                 }
538
539                 if (ast_json_array_append(json_items, ast_json_string_create(item))) {
540                         ao2_cleanup(item);
541                         ao2_iterator_destroy(&it);
542                         return NULL;
543                 }
544         }
545         ao2_iterator_destroy(&it);
546
547         return ast_json_ref(json_items);
548 }
549
550 static const char *capability2str(uint32_t capabilities)
551 {
552         if (capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
553                 return "holding";
554         } else {
555                 return "mixing";
556         }
557 }
558
559 struct ast_json *ast_bridge_snapshot_to_json(
560         const struct ast_bridge_snapshot *snapshot,
561         const struct stasis_message_sanitizer *sanitize)
562 {
563         RAII_VAR(struct ast_json *, json_bridge, NULL, ast_json_unref);
564         struct ast_json *json_channels;
565
566         if (snapshot == NULL) {
567                 return NULL;
568         }
569
570         json_channels = container_to_json_array(snapshot->channels, sanitize);
571         if (!json_channels) {
572                 return NULL;
573         }
574
575         json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
576                 "id", snapshot->uniqueid,
577                 "technology", snapshot->technology,
578                 "bridge_type", capability2str(snapshot->capabilities),
579                 "bridge_class", snapshot->subclass,
580                 "creator", snapshot->creator,
581                 "name", snapshot->name,
582                 "channels", json_channels);
583         if (!json_bridge) {
584                 return NULL;
585         }
586
587         return ast_json_ref(json_bridge);
588 }
589
590 /*!
591  * \internal
592  * \brief Allocate the fields of an \ref ast_bridge_channel_snapshot_pair.
593  *
594  * \param pair A bridge and channel to get snapshots of
595  * \param[out] snapshot_pair An allocated snapshot pair.
596  * \retval 0 Success
597  * \retval non-zero Failure
598  */
599 static int bridge_channel_snapshot_pair_init(struct ast_bridge_channel_pair *pair, struct ast_bridge_channel_snapshot_pair *snapshot_pair)
600 {
601         if (pair->bridge) {
602                 snapshot_pair->bridge_snapshot = ast_bridge_snapshot_create(pair->bridge);
603                 if (!snapshot_pair->bridge_snapshot) {
604                         return -1;
605                 }
606         }
607
608         snapshot_pair->channel_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(pair->channel));
609         if (!snapshot_pair->channel_snapshot) {
610                 return -1;
611         }
612
613         return 0;
614 }
615
616 /*!
617  * \internal
618  * \brief Free the fields of an \ref ast_bridge_channel_snapshot_pair.
619  *
620  * \param pair The snapshot pair whose fields are to be cleaned up
621  */
622 static void bridge_channel_snapshot_pair_cleanup(struct ast_bridge_channel_snapshot_pair *pair)
623 {
624         ao2_cleanup(pair->bridge_snapshot);
625         ao2_cleanup(pair->channel_snapshot);
626 }
627
628 static const char *result_strs[] = {
629         [AST_BRIDGE_TRANSFER_FAIL] = "Fail",
630         [AST_BRIDGE_TRANSFER_INVALID] = "Invalid",
631         [AST_BRIDGE_TRANSFER_NOT_PERMITTED] = "Not Permitted",
632         [AST_BRIDGE_TRANSFER_SUCCESS] = "Success",
633 };
634
635 static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
636         const struct stasis_message_sanitizer *sanitize)
637 {
638         struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
639         struct ast_json *json_transferer;
640         struct ast_json *json_transferee = NULL;
641         struct ast_json *out;
642         struct ast_json *json_replace = NULL;
643         const struct timeval *tv = stasis_message_timestamp(msg);
644
645         json_transferer = ast_channel_snapshot_to_json(transfer_msg->to_transferee.channel_snapshot, sanitize);
646         if (!json_transferer) {
647                 return NULL;
648         }
649
650         if (transfer_msg->transferee) {
651                 json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
652                 if (!json_transferee) {
653                         ast_json_unref(json_transferer);
654                         return NULL;
655                 }
656         }
657
658         if (transfer_msg->replace_channel) {
659                 json_replace = ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize);
660                 if (!json_replace) {
661                         ast_json_unref(json_transferee);
662                         ast_json_unref(json_transferer);
663                         return NULL;
664                 }
665         }
666
667         out = ast_json_pack("{s: s, s: o, s: o, s: s, s: s, s: s, s: o}",
668                 "type", "BridgeBlindTransfer",
669                 "timestamp", ast_json_timeval(*tv, NULL),
670                 "channel", json_transferer,
671                 "exten", transfer_msg->exten,
672                 "context", transfer_msg->context,
673                 "result", result_strs[transfer_msg->result],
674                 "is_external", ast_json_boolean(transfer_msg->is_external));
675
676         if (!out) {
677                 ast_json_unref(json_transferee);
678                 ast_json_unref(json_replace);
679                 return NULL;
680         }
681
682         if (json_transferee && ast_json_object_set(out, "transferee", json_transferee)) {
683                 ast_json_unref(out);
684                 ast_json_unref(json_replace);
685                 return NULL;
686         }
687
688         if (json_replace && ast_json_object_set(out, "replace_channel", json_replace)) {
689                 ast_json_unref(out);
690                 return NULL;
691         }
692
693         if (transfer_msg->to_transferee.bridge_snapshot) {
694                 struct ast_json *json_bridge = ast_bridge_snapshot_to_json(
695                                 transfer_msg->to_transferee.bridge_snapshot, sanitize);
696
697                 if (!json_bridge || ast_json_object_set(out, "bridge", json_bridge)) {
698                         ast_json_unref(out);
699                         return NULL;
700                 }
701         }
702
703         return out;
704 }
705
706 static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *msg)
707 {
708         RAII_VAR(struct ast_str *, transferer_state, NULL, ast_free_ptr);
709         RAII_VAR(struct ast_str *, bridge_state, NULL, ast_free_ptr);
710         RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
711         struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
712
713         if (!transfer_msg) {
714                 return NULL;
715         }
716
717         transferer_state = ast_manager_build_channel_state_string_prefix(
718                         transfer_msg->to_transferee.channel_snapshot, "Transferer");
719         if (!transferer_state) {
720                 return NULL;
721         }
722
723         if (transfer_msg->to_transferee.bridge_snapshot) {
724                 bridge_state = ast_manager_build_bridge_state_string(transfer_msg->to_transferee.bridge_snapshot);
725                 if (!bridge_state) {
726                         return NULL;
727                 }
728         }
729
730         if (transfer_msg->transferee) {
731                 transferee_state = ast_manager_build_channel_state_string_prefix(
732                                 transfer_msg->transferee, "Transferee");
733                 if (!transferee_state) {
734                         return NULL;
735                 }
736         }
737
738         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "BlindTransfer",
739                         "Result: %s\r\n"
740                         "%s"
741                         "%s"
742                         "%s"
743                         "IsExternal: %s\r\n"
744                         "Context: %s\r\n"
745                         "Extension: %s\r\n",
746                         result_strs[transfer_msg->result],
747                         ast_str_buffer(transferer_state),
748                         transferee_state ? ast_str_buffer(transferee_state) : "",
749                         bridge_state ? ast_str_buffer(bridge_state) : "",
750                         transfer_msg->is_external ? "Yes" : "No",
751                         transfer_msg->context,
752                         transfer_msg->exten);
753 }
754
755 static void blind_transfer_dtor(void *obj)
756 {
757         struct ast_blind_transfer_message *msg = obj;
758
759         bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
760         ao2_cleanup(msg->transferee);
761 }
762
763 void ast_bridge_publish_blind_transfer(int is_external, enum ast_transfer_result result,
764                 struct ast_bridge_channel_pair *transferer, const char *context, const char *exten,
765                 struct ast_channel *transferee_channel, struct ast_channel *replace_channel)
766 {
767         struct ast_blind_transfer_message *msg;
768         struct stasis_message *stasis;
769
770         msg = ao2_alloc(sizeof(*msg), blind_transfer_dtor);
771         if (!msg) {
772                 return;
773         }
774
775         if (bridge_channel_snapshot_pair_init(transferer, &msg->to_transferee)) {
776                 ao2_cleanup(msg);
777                 return;
778         }
779
780         if (transferee_channel) {
781                 msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee_channel));
782         }
783         if (replace_channel) {
784                 msg->replace_channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(replace_channel));
785         }
786         msg->is_external = is_external;
787         msg->result = result;
788         ast_copy_string(msg->context, context, sizeof(msg->context));
789         ast_copy_string(msg->exten, exten, sizeof(msg->exten));
790
791         stasis = stasis_message_create(ast_blind_transfer_type(), msg);
792         if (!stasis) {
793                 ao2_cleanup(msg);
794                 return;
795         }
796
797         stasis_publish(ast_bridge_topic_all(), stasis);
798
799         ao2_cleanup(stasis);
800         ao2_cleanup(msg);
801 }
802
803 static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
804         const struct stasis_message_sanitizer *sanitize)
805 {
806         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
807         RAII_VAR(struct ast_json *, out, NULL, ast_json_unref);
808         struct ast_json *json_transferer1, *json_transferer2, *json_bridge, *json_channel;
809         struct ast_json *json_transferee = NULL, *json_target = NULL;
810         const struct timeval *tv = stasis_message_timestamp(msg);
811         int res = 0;
812
813         json_transferer1 = ast_channel_snapshot_to_json(transfer_msg->to_transferee.channel_snapshot, sanitize);
814         if (!json_transferer1) {
815                 return NULL;
816         }
817
818         json_transferer2 = ast_channel_snapshot_to_json(transfer_msg->to_transfer_target.channel_snapshot, sanitize);
819         if (!json_transferer2) {
820                 ast_json_unref(json_transferer1);
821                 return NULL;
822         }
823
824         if (transfer_msg->transferee) {
825                 json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
826                 if (!json_transferee) {
827                         return NULL;
828                 }
829         }
830
831         if (transfer_msg->target) {
832                 json_target = ast_channel_snapshot_to_json(transfer_msg->target, sanitize);
833                 if (!json_target) {
834                         return NULL;
835                 }
836         }
837
838         out = ast_json_pack("{s: s, s: o, s: o, s: o, s: s, s: o}",
839                 "type", "BridgeAttendedTransfer",
840                 "timestamp", ast_json_timeval(*tv, NULL),
841                 "transferer_first_leg", json_transferer1,
842                 "transferer_second_leg", json_transferer2,
843                 "result", result_strs[transfer_msg->result],
844                 "is_external", ast_json_boolean(transfer_msg->is_external));
845         if (!out) {
846                 return NULL;
847         }
848         if (json_transferee && ast_json_object_set(out, "transferee", json_transferee)) {
849                 return NULL;
850         }
851         if (json_target && ast_json_object_set(out, "transfer_target", json_target)) {
852                 return NULL;
853         }
854
855         if (transfer_msg->to_transferee.bridge_snapshot) {
856                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->to_transferee.bridge_snapshot, sanitize);
857
858                 if (!json_bridge) {
859                         return NULL;
860                 }
861
862                 res |= ast_json_object_set(out, "transferer_first_leg_bridge", json_bridge);
863         }
864
865         if (transfer_msg->to_transfer_target.bridge_snapshot) {
866                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->to_transfer_target.bridge_snapshot, sanitize);
867
868                 if (!json_bridge) {
869                         return NULL;
870                 }
871
872                 res |= ast_json_object_set(out, "transferer_second_leg_bridge", json_bridge);
873         }
874
875         switch (transfer_msg->dest_type) {
876         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
877                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("bridge"));
878                 res |= ast_json_object_set(out, "destination_bridge", ast_json_string_create(transfer_msg->dest.bridge));
879                 break;
880         case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
881                 res |= ast_json_object_set(out, "replace_channel", ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize));
882                 /* fallthrough */
883         case AST_ATTENDED_TRANSFER_DEST_APP:
884                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("application"));
885                 res |= ast_json_object_set(out, "destination_application", ast_json_string_create(transfer_msg->dest.app));
886                 break;
887         case AST_ATTENDED_TRANSFER_DEST_LINK:
888                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("link"));
889
890                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.links[0], sanitize);
891                 if (!json_channel) {
892                         return NULL;
893                 }
894                 res |= ast_json_object_set(out, "destination_link_first_leg", json_channel);
895
896                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.links[1], sanitize);
897                 if (!json_channel) {
898                         return NULL;
899                 }
900                 res |= ast_json_object_set(out, "destination_link_second_leg", json_channel);
901
902                 break;
903         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
904                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("threeway"));
905
906                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.threeway.channel_snapshot, sanitize);
907                 if (!json_channel) {
908                         return NULL;
909                 }
910                 res |= ast_json_object_set(out, "destination_threeway_channel", json_channel);
911
912                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->dest.threeway.bridge_snapshot, sanitize);
913                 if (!json_bridge) {
914                         return NULL;
915                 }
916                 res |= ast_json_object_set(out, "destination_threeway_bridge", json_bridge);
917
918                 break;
919         case AST_ATTENDED_TRANSFER_DEST_FAIL:
920                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("fail"));
921                 break;
922         }
923
924         if (res) {
925                 return NULL;
926         }
927
928         return ast_json_ref(out);
929 }
930
931 static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *msg)
932 {
933         RAII_VAR(struct ast_str *, variable_data, ast_str_create(64), ast_free_ptr);
934         RAII_VAR(struct ast_str *, transferer1_state, NULL, ast_free_ptr);
935         RAII_VAR(struct ast_str *, bridge1_state, NULL, ast_free_ptr);
936         RAII_VAR(struct ast_str *, transferer2_state, NULL, ast_free_ptr);
937         RAII_VAR(struct ast_str *, bridge2_state, NULL, ast_free_ptr);
938         RAII_VAR(struct ast_str *, local1_state, NULL, ast_free_ptr);
939         RAII_VAR(struct ast_str *, local2_state, NULL, ast_free_ptr);
940         RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
941         RAII_VAR(struct ast_str *, target_state, NULL, ast_free_ptr);
942         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
943
944         if (!variable_data) {
945                 return NULL;
946         }
947
948         transferer1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transferee.channel_snapshot, "OrigTransferer");
949         transferer2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transfer_target.channel_snapshot, "SecondTransferer");
950         if (!transferer1_state || !transferer2_state) {
951                 return NULL;
952         }
953         if (transfer_msg->transferee) {
954                 transferee_state = ast_manager_build_channel_state_string_prefix(transfer_msg->transferee, "Transferee");
955                 if (!transferee_state) {
956                         return NULL;
957                 }
958         }
959
960         if (transfer_msg->target) {
961                 target_state = ast_manager_build_channel_state_string_prefix(transfer_msg->target, "TransferTarget");
962                 if (!target_state) {
963                         return NULL;
964                 }
965         }
966
967         if (transfer_msg->to_transferee.bridge_snapshot) {
968                 bridge1_state = ast_manager_build_bridge_state_string_prefix(
969                         transfer_msg->to_transferee.bridge_snapshot, "Orig");
970                 if (!bridge1_state) {
971                         return NULL;
972                 }
973         }
974
975         if (transfer_msg->to_transfer_target.bridge_snapshot) {
976                 bridge2_state = ast_manager_build_bridge_state_string_prefix(
977                         transfer_msg->to_transfer_target.bridge_snapshot, "Second");
978                 if (!bridge2_state) {
979                         return NULL;
980                 }
981         }
982
983         switch (transfer_msg->dest_type) {
984         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
985                 ast_str_append(&variable_data, 0, "DestType: Bridge\r\n");
986                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.bridge);
987                 break;
988         case AST_ATTENDED_TRANSFER_DEST_APP:
989         case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
990                 ast_str_append(&variable_data, 0, "DestType: App\r\n");
991                 ast_str_append(&variable_data, 0, "DestApp: %s\r\n", transfer_msg->dest.app);
992                 break;
993         case AST_ATTENDED_TRANSFER_DEST_LINK:
994                 local1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[0], "LocalOne");
995                 local2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[1], "LocalTwo");
996                 if (!local1_state || !local2_state) {
997                         return NULL;
998                 }
999                 ast_str_append(&variable_data, 0, "DestType: Link\r\n");
1000                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local1_state));
1001                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local2_state));
1002                 break;
1003         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
1004                 ast_str_append(&variable_data, 0, "DestType: Threeway\r\n");
1005                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.threeway.bridge_snapshot->uniqueid);
1006                 ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->name);
1007                 break;
1008         case AST_ATTENDED_TRANSFER_DEST_FAIL:
1009                 ast_str_append(&variable_data, 0, "DestType: Fail\r\n");
1010                 break;
1011         }
1012
1013         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "AttendedTransfer",
1014                         "Result: %s\r\n"
1015                         "%s"
1016                         "%s"
1017                         "%s"
1018                         "%s"
1019                         "%s"
1020                         "%s"
1021                         "IsExternal: %s\r\n"
1022                         "%s",
1023                         result_strs[transfer_msg->result],
1024                         ast_str_buffer(transferer1_state),
1025                         bridge1_state ? ast_str_buffer(bridge1_state) : "",
1026                         ast_str_buffer(transferer2_state),
1027                         bridge2_state ? ast_str_buffer(bridge2_state) : "",
1028                         transferee_state ? ast_str_buffer(transferee_state) : "",
1029                         target_state ? ast_str_buffer(target_state) : "",
1030                         transfer_msg->is_external ? "Yes" : "No",
1031                         ast_str_buffer(variable_data));
1032 }
1033
1034 static void attended_transfer_dtor(void *obj)
1035 {
1036         struct ast_attended_transfer_message *msg = obj;
1037         int i;
1038
1039         bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
1040         bridge_channel_snapshot_pair_cleanup(&msg->to_transfer_target);
1041         ao2_cleanup(msg->replace_channel);
1042         ao2_cleanup(msg->transferee);
1043         ao2_cleanup(msg->target);
1044
1045         if (msg->dest_type != AST_ATTENDED_TRANSFER_DEST_LINK) {
1046                 return;
1047         }
1048
1049         for (i = 0; i < ARRAY_LEN(msg->dest.links); ++i) {
1050                 ao2_cleanup(msg->dest.links[i]);
1051         }
1052 }
1053
1054 static struct ast_attended_transfer_message *attended_transfer_message_create(int is_external,
1055                 enum ast_transfer_result result, struct ast_bridge_channel_pair *transferee,
1056                 struct ast_bridge_channel_pair *target, struct ast_channel *replace_channel,
1057                 struct ast_channel *transferee_channel, struct ast_channel *target_channel)
1058 {
1059         RAII_VAR(struct ast_attended_transfer_message *, msg, NULL, ao2_cleanup);
1060
1061         msg = ao2_alloc(sizeof(*msg), attended_transfer_dtor);
1062         if (!msg) {
1063                 return NULL;
1064         }
1065
1066         if (bridge_channel_snapshot_pair_init(transferee, &msg->to_transferee) ||
1067                         bridge_channel_snapshot_pair_init(target, &msg->to_transfer_target)) {
1068                 return NULL;
1069         }
1070
1071         if (replace_channel) {
1072                 msg->replace_channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(replace_channel));
1073                 if (!msg->replace_channel) {
1074                         return NULL;
1075                 }
1076         }
1077
1078         if (transferee_channel) {
1079                 msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee_channel));
1080         }
1081         if (target_channel) {
1082                 msg->target = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target_channel));
1083         }
1084         msg->is_external = is_external;
1085         msg->result = result;
1086
1087         ao2_ref(msg, +1);
1088         return msg;
1089 }
1090
1091 void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfer_result result,
1092                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
1093                 struct ast_channel *transferee_channel, struct ast_channel *target_channel)
1094 {
1095         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
1096         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1097
1098         if (!ast_attended_transfer_type()) {
1099                 return;
1100         }
1101
1102         transfer_msg = attended_transfer_message_create(is_external, result,
1103                         transferee, target, NULL, transferee_channel, target_channel);
1104         if (!transfer_msg) {
1105                 return;
1106         }
1107
1108         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_FAIL;
1109
1110         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
1111         if (!msg) {
1112                 return;
1113         }
1114
1115         stasis_publish(ast_bridge_topic_all(), msg);
1116 }
1117
1118 void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast_transfer_result result,
1119                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
1120                 struct ast_bridge *final_bridge, struct ast_channel *transferee_channel,
1121                 struct ast_channel *target_channel)
1122 {
1123         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
1124         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1125
1126         if (!ast_attended_transfer_type()) {
1127                 return;
1128         }
1129
1130         transfer_msg = attended_transfer_message_create(is_external, result,
1131                         transferee, target, NULL, transferee_channel, target_channel);
1132         if (!transfer_msg) {
1133                 return;
1134         }
1135
1136         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE;
1137         ast_copy_string(transfer_msg->dest.bridge, final_bridge->uniqueid,
1138                         sizeof(transfer_msg->dest.bridge));
1139
1140         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
1141         if (!msg) {
1142                 return;
1143         }
1144
1145         stasis_publish(ast_bridge_topic_all(), msg);
1146 }
1147
1148 void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_transfer_result result,
1149                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
1150                 struct ast_bridge_channel_pair *final_pair, struct ast_channel *transferee_channel,
1151                 struct ast_channel *target_channel)
1152 {
1153         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
1154         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1155
1156         if (!ast_attended_transfer_type()) {
1157                 return;
1158         }
1159
1160         transfer_msg = attended_transfer_message_create(is_external, result,
1161                         transferee, target, NULL, transferee_channel, target_channel);
1162         if (!transfer_msg) {
1163                 return;
1164         }
1165
1166         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_THREEWAY;
1167         if (final_pair->channel == transferee->channel) {
1168                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transferee.channel_snapshot;
1169         } else {
1170                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transfer_target.channel_snapshot;
1171         }
1172
1173         if (final_pair->bridge == transferee->bridge) {
1174                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transferee.bridge_snapshot;
1175         } else {
1176                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transfer_target.bridge_snapshot;
1177         }
1178
1179         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
1180         if (!msg) {
1181                 return;
1182         }
1183
1184         stasis_publish(ast_bridge_topic_all(), msg);
1185 }
1186
1187 void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer_result result,
1188                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
1189                 struct ast_channel *replace_channel, const char *dest_app,
1190                 struct ast_channel *transferee_channel, struct ast_channel *target_channel)
1191 {
1192         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
1193         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1194
1195         if (!ast_attended_transfer_type()) {
1196                 return;
1197         }
1198
1199         transfer_msg = attended_transfer_message_create(is_external, result,
1200                         transferee, target, replace_channel, transferee_channel, target_channel);
1201         if (!transfer_msg) {
1202                 return;
1203         }
1204
1205         transfer_msg->dest_type = replace_channel ? AST_ATTENDED_TRANSFER_DEST_LOCAL_APP : AST_ATTENDED_TRANSFER_DEST_APP;
1206         ast_copy_string(transfer_msg->dest.app, dest_app, sizeof(transfer_msg->dest.app));
1207
1208         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
1209         if (!msg) {
1210                 return;
1211         }
1212
1213         stasis_publish(ast_bridge_topic_all(), msg);
1214 }
1215
1216 void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfer_result result,
1217                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
1218                 struct ast_channel *locals[2], struct ast_channel *transferee_channel,
1219                 struct ast_channel *target_channel)
1220 {
1221         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
1222         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1223         int i;
1224
1225         if (!ast_attended_transfer_type()) {
1226                 return;
1227         }
1228
1229         transfer_msg = attended_transfer_message_create(is_external, result,
1230                         transferee, target, NULL, transferee_channel, target_channel);
1231         if (!transfer_msg) {
1232                 return;
1233         }
1234
1235         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
1236         for (i = 0; i < 2; ++i) {
1237                 transfer_msg->dest.links[i] = ast_channel_snapshot_get_latest(ast_channel_uniqueid(locals[i]));
1238                 if (!transfer_msg->dest.links[i]) {
1239                         return;
1240                 }
1241         }
1242
1243         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
1244         if (!msg) {
1245                 return;
1246         }
1247
1248         stasis_publish(ast_bridge_topic_all(), msg);
1249 }
1250
1251 struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
1252 {
1253         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
1254         struct ast_bridge_snapshot *snapshot;
1255
1256         ast_assert(!ast_strlen_zero(uniqueid));
1257
1258         message = stasis_cache_get(ast_bridge_cache(),
1259                         ast_bridge_snapshot_type(),
1260                         uniqueid);
1261         if (!message) {
1262                 return NULL;
1263         }
1264
1265         snapshot = stasis_message_data(message);
1266         if (!snapshot) {
1267                 return NULL;
1268         }
1269         ao2_ref(snapshot, +1);
1270         return snapshot;
1271 }
1272
1273 /*! \brief snapshot ID getter for caching topic */
1274 static const char *bridge_snapshot_get_id(struct stasis_message *msg)
1275 {
1276         struct ast_bridge_snapshot *snapshot;
1277         if (stasis_message_type(msg) != ast_bridge_snapshot_type()) {
1278                 return NULL;
1279         }
1280         snapshot = stasis_message_data(msg);
1281         return snapshot->uniqueid;
1282 }
1283
1284 static void stasis_bridging_cleanup(void)
1285 {
1286         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);
1287         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_merge_message_type);
1288         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_entered_bridge_type);
1289         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_left_bridge_type);
1290         STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);
1291         STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);
1292
1293         ao2_cleanup(bridge_cache_all);
1294         bridge_cache_all = NULL;
1295 }
1296
1297 int ast_stasis_bridging_init(void)
1298 {
1299         int res = 0;
1300
1301         ast_register_cleanup(stasis_bridging_cleanup);
1302
1303         bridge_cache_all = stasis_cp_all_create("ast_bridge_topic_all",
1304                 bridge_snapshot_get_id);
1305
1306         if (!bridge_cache_all) {
1307                 return -1;
1308         }
1309
1310         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_snapshot_type);
1311         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_merge_message_type);
1312         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_entered_bridge_type);
1313         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_left_bridge_type);
1314         res |= STASIS_MESSAGE_TYPE_INIT(ast_blind_transfer_type);
1315         res |= STASIS_MESSAGE_TYPE_INIT(ast_attended_transfer_type);
1316
1317         return res;
1318 }