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