Fix race condition that could result in ARI transfer messages not being sent.
[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_channel *channel, struct ast_bridge *bridge,
600                 struct ast_bridge_channel_snapshot_pair *snapshot_pair)
601 {
602         if (bridge) {
603                 ast_bridge_lock(bridge);
604                 snapshot_pair->bridge_snapshot = ast_bridge_snapshot_create(bridge);
605                 ast_bridge_unlock(bridge);
606                 if (!snapshot_pair->bridge_snapshot) {
607                         return -1;
608                 }
609         }
610
611         snapshot_pair->channel_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(channel));
612         if (!snapshot_pair->channel_snapshot) {
613                 return -1;
614         }
615
616         return 0;
617 }
618
619 /*!
620  * \internal
621  * \brief Free the fields of an \ref ast_bridge_channel_snapshot_pair.
622  *
623  * \param pair The snapshot pair whose fields are to be cleaned up
624  */
625 static void bridge_channel_snapshot_pair_cleanup(struct ast_bridge_channel_snapshot_pair *pair)
626 {
627         ao2_cleanup(pair->bridge_snapshot);
628         ao2_cleanup(pair->channel_snapshot);
629 }
630
631 static const char *result_strs[] = {
632         [AST_BRIDGE_TRANSFER_FAIL] = "Fail",
633         [AST_BRIDGE_TRANSFER_INVALID] = "Invalid",
634         [AST_BRIDGE_TRANSFER_NOT_PERMITTED] = "Not Permitted",
635         [AST_BRIDGE_TRANSFER_SUCCESS] = "Success",
636 };
637
638 static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
639         const struct stasis_message_sanitizer *sanitize)
640 {
641         struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
642         struct ast_json *json_transferer;
643         struct ast_json *json_transferee = NULL;
644         struct ast_json *out;
645         struct ast_json *json_replace = NULL;
646         const struct timeval *tv = stasis_message_timestamp(msg);
647
648         json_transferer = ast_channel_snapshot_to_json(transfer_msg->transferer, sanitize);
649         if (!json_transferer) {
650                 return NULL;
651         }
652
653         if (transfer_msg->transferee) {
654                 json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
655                 if (!json_transferee) {
656                         ast_json_unref(json_transferer);
657                         return NULL;
658                 }
659         }
660
661         if (transfer_msg->replace_channel) {
662                 json_replace = ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize);
663                 if (!json_replace) {
664                         ast_json_unref(json_transferee);
665                         ast_json_unref(json_transferer);
666                         return NULL;
667                 }
668         }
669
670         out = ast_json_pack("{s: s, s: o, s: o, s: s, s: s, s: s, s: o}",
671                 "type", "BridgeBlindTransfer",
672                 "timestamp", ast_json_timeval(*tv, NULL),
673                 "channel", json_transferer,
674                 "exten", transfer_msg->exten,
675                 "context", transfer_msg->context,
676                 "result", result_strs[transfer_msg->result],
677                 "is_external", ast_json_boolean(transfer_msg->is_external));
678
679         if (!out) {
680                 ast_json_unref(json_transferee);
681                 ast_json_unref(json_replace);
682                 return NULL;
683         }
684
685         if (json_transferee && ast_json_object_set(out, "transferee", json_transferee)) {
686                 ast_json_unref(out);
687                 ast_json_unref(json_replace);
688                 return NULL;
689         }
690
691         if (json_replace && ast_json_object_set(out, "replace_channel", json_replace)) {
692                 ast_json_unref(out);
693                 return NULL;
694         }
695
696         if (transfer_msg->bridge) {
697                 struct ast_json *json_bridge = ast_bridge_snapshot_to_json(
698                                 transfer_msg->bridge, sanitize);
699
700                 if (!json_bridge || ast_json_object_set(out, "bridge", json_bridge)) {
701                         ast_json_unref(out);
702                         return NULL;
703                 }
704         }
705
706         return out;
707 }
708
709 static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *msg)
710 {
711         RAII_VAR(struct ast_str *, transferer_state, NULL, ast_free_ptr);
712         RAII_VAR(struct ast_str *, bridge_state, NULL, ast_free_ptr);
713         RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
714         struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
715
716         if (!transfer_msg) {
717                 return NULL;
718         }
719
720         transferer_state = ast_manager_build_channel_state_string_prefix(
721                         transfer_msg->transferer, "Transferer");
722         if (!transferer_state) {
723                 return NULL;
724         }
725
726         if (transfer_msg->bridge) {
727                 bridge_state = ast_manager_build_bridge_state_string(transfer_msg->bridge);
728                 if (!bridge_state) {
729                         return NULL;
730                 }
731         }
732
733         if (transfer_msg->transferee) {
734                 transferee_state = ast_manager_build_channel_state_string_prefix(
735                                 transfer_msg->transferee, "Transferee");
736                 if (!transferee_state) {
737                         return NULL;
738                 }
739         }
740
741         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "BlindTransfer",
742                         "Result: %s\r\n"
743                         "%s"
744                         "%s"
745                         "%s"
746                         "IsExternal: %s\r\n"
747                         "Context: %s\r\n"
748                         "Extension: %s\r\n",
749                         result_strs[transfer_msg->result],
750                         ast_str_buffer(transferer_state),
751                         transferee_state ? ast_str_buffer(transferee_state) : "",
752                         bridge_state ? ast_str_buffer(bridge_state) : "",
753                         transfer_msg->is_external ? "Yes" : "No",
754                         transfer_msg->context,
755                         transfer_msg->exten);
756 }
757
758 static void blind_transfer_dtor(void *obj)
759 {
760         struct ast_blind_transfer_message *msg = obj;
761
762         ao2_cleanup(msg->transferer);
763         ao2_cleanup(msg->bridge);
764         ao2_cleanup(msg->transferee);
765         ao2_cleanup(msg->replace_channel);
766 }
767
768 struct ast_blind_transfer_message *ast_blind_transfer_message_create(int is_external,
769                 struct ast_channel *transferer, const char *exten, const char *context)
770 {
771         struct ast_blind_transfer_message *msg;
772
773         msg = ao2_alloc(sizeof(*msg), blind_transfer_dtor);
774         if (!msg) {
775                 return NULL;
776         }
777
778         msg->transferer = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferer));
779         if (!msg->transferer) {
780                 ao2_cleanup(msg);
781                 return NULL;
782         }
783
784         msg->is_external = is_external;
785         ast_copy_string(msg->context, context, sizeof(msg->context));
786         ast_copy_string(msg->exten, exten, sizeof(msg->exten));
787
788         return msg;
789 }
790
791
792 void ast_bridge_publish_blind_transfer(struct ast_blind_transfer_message *transfer_message)
793 {
794         struct stasis_message *stasis;
795
796         stasis = stasis_message_create(ast_blind_transfer_type(), transfer_message);
797         if (!stasis) {
798                 return;
799         }
800
801         stasis_publish(ast_bridge_topic_all(), stasis);
802
803         ao2_cleanup(stasis);
804 }
805
806 static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
807         const struct stasis_message_sanitizer *sanitize)
808 {
809         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
810         RAII_VAR(struct ast_json *, out, NULL, ast_json_unref);
811         struct ast_json *json_transferer1, *json_transferer2, *json_bridge, *json_channel;
812         struct ast_json *json_transferee = NULL, *json_target = NULL;
813         const struct timeval *tv = stasis_message_timestamp(msg);
814         int res = 0;
815
816         json_transferer1 = ast_channel_snapshot_to_json(transfer_msg->to_transferee.channel_snapshot, sanitize);
817         if (!json_transferer1) {
818                 return NULL;
819         }
820
821         json_transferer2 = ast_channel_snapshot_to_json(transfer_msg->to_transfer_target.channel_snapshot, sanitize);
822         if (!json_transferer2) {
823                 ast_json_unref(json_transferer1);
824                 return NULL;
825         }
826
827         if (transfer_msg->transferee) {
828                 json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
829                 if (!json_transferee) {
830                         return NULL;
831                 }
832         }
833
834         if (transfer_msg->target) {
835                 json_target = ast_channel_snapshot_to_json(transfer_msg->target, sanitize);
836                 if (!json_target) {
837                         return NULL;
838                 }
839         }
840
841         out = ast_json_pack("{s: s, s: o, s: o, s: o, s: s, s: o}",
842                 "type", "BridgeAttendedTransfer",
843                 "timestamp", ast_json_timeval(*tv, NULL),
844                 "transferer_first_leg", json_transferer1,
845                 "transferer_second_leg", json_transferer2,
846                 "result", result_strs[transfer_msg->result],
847                 "is_external", ast_json_boolean(transfer_msg->is_external));
848         if (!out) {
849                 return NULL;
850         }
851         if (json_transferee && ast_json_object_set(out, "transferee", json_transferee)) {
852                 return NULL;
853         }
854         if (json_target && ast_json_object_set(out, "transfer_target", json_target)) {
855                 return NULL;
856         }
857
858         if (transfer_msg->to_transferee.bridge_snapshot) {
859                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->to_transferee.bridge_snapshot, sanitize);
860
861                 if (!json_bridge) {
862                         return NULL;
863                 }
864
865                 res |= ast_json_object_set(out, "transferer_first_leg_bridge", json_bridge);
866         }
867
868         if (transfer_msg->to_transfer_target.bridge_snapshot) {
869                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->to_transfer_target.bridge_snapshot, sanitize);
870
871                 if (!json_bridge) {
872                         return NULL;
873                 }
874
875                 res |= ast_json_object_set(out, "transferer_second_leg_bridge", json_bridge);
876         }
877
878         switch (transfer_msg->dest_type) {
879         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
880                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("bridge"));
881                 res |= ast_json_object_set(out, "destination_bridge", ast_json_string_create(transfer_msg->dest.bridge));
882                 break;
883         case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
884                 res |= ast_json_object_set(out, "replace_channel", ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize));
885                 /* fallthrough */
886         case AST_ATTENDED_TRANSFER_DEST_APP:
887                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("application"));
888                 res |= ast_json_object_set(out, "destination_application", ast_json_string_create(transfer_msg->dest.app));
889                 break;
890         case AST_ATTENDED_TRANSFER_DEST_LINK:
891                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("link"));
892
893                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.links[0], sanitize);
894                 if (!json_channel) {
895                         return NULL;
896                 }
897                 res |= ast_json_object_set(out, "destination_link_first_leg", json_channel);
898
899                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.links[1], sanitize);
900                 if (!json_channel) {
901                         return NULL;
902                 }
903                 res |= ast_json_object_set(out, "destination_link_second_leg", json_channel);
904
905                 break;
906         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
907                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("threeway"));
908
909                 json_channel = ast_channel_snapshot_to_json(transfer_msg->dest.threeway.channel_snapshot, sanitize);
910                 if (!json_channel) {
911                         return NULL;
912                 }
913                 res |= ast_json_object_set(out, "destination_threeway_channel", json_channel);
914
915                 json_bridge = ast_bridge_snapshot_to_json(transfer_msg->dest.threeway.bridge_snapshot, sanitize);
916                 if (!json_bridge) {
917                         return NULL;
918                 }
919                 res |= ast_json_object_set(out, "destination_threeway_bridge", json_bridge);
920
921                 break;
922         case AST_ATTENDED_TRANSFER_DEST_FAIL:
923                 res |= ast_json_object_set(out, "destination_type", ast_json_string_create("fail"));
924                 break;
925         }
926
927         if (res) {
928                 return NULL;
929         }
930
931         return ast_json_ref(out);
932 }
933
934 static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *msg)
935 {
936         RAII_VAR(struct ast_str *, variable_data, ast_str_create(64), ast_free_ptr);
937         RAII_VAR(struct ast_str *, transferer1_state, NULL, ast_free_ptr);
938         RAII_VAR(struct ast_str *, bridge1_state, NULL, ast_free_ptr);
939         RAII_VAR(struct ast_str *, transferer2_state, NULL, ast_free_ptr);
940         RAII_VAR(struct ast_str *, bridge2_state, NULL, ast_free_ptr);
941         RAII_VAR(struct ast_str *, local1_state, NULL, ast_free_ptr);
942         RAII_VAR(struct ast_str *, local2_state, NULL, ast_free_ptr);
943         RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
944         RAII_VAR(struct ast_str *, target_state, NULL, ast_free_ptr);
945         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
946
947         if (!variable_data) {
948                 return NULL;
949         }
950
951         transferer1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transferee.channel_snapshot, "OrigTransferer");
952         transferer2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transfer_target.channel_snapshot, "SecondTransferer");
953         if (!transferer1_state || !transferer2_state) {
954                 return NULL;
955         }
956         if (transfer_msg->transferee) {
957                 transferee_state = ast_manager_build_channel_state_string_prefix(transfer_msg->transferee, "Transferee");
958                 if (!transferee_state) {
959                         return NULL;
960                 }
961         }
962
963         if (transfer_msg->target) {
964                 target_state = ast_manager_build_channel_state_string_prefix(transfer_msg->target, "TransferTarget");
965                 if (!target_state) {
966                         return NULL;
967                 }
968         }
969
970         if (transfer_msg->to_transferee.bridge_snapshot) {
971                 bridge1_state = ast_manager_build_bridge_state_string_prefix(
972                         transfer_msg->to_transferee.bridge_snapshot, "Orig");
973                 if (!bridge1_state) {
974                         return NULL;
975                 }
976         }
977
978         if (transfer_msg->to_transfer_target.bridge_snapshot) {
979                 bridge2_state = ast_manager_build_bridge_state_string_prefix(
980                         transfer_msg->to_transfer_target.bridge_snapshot, "Second");
981                 if (!bridge2_state) {
982                         return NULL;
983                 }
984         }
985
986         switch (transfer_msg->dest_type) {
987         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
988                 ast_str_append(&variable_data, 0, "DestType: Bridge\r\n");
989                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.bridge);
990                 break;
991         case AST_ATTENDED_TRANSFER_DEST_APP:
992         case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
993                 ast_str_append(&variable_data, 0, "DestType: App\r\n");
994                 ast_str_append(&variable_data, 0, "DestApp: %s\r\n", transfer_msg->dest.app);
995                 break;
996         case AST_ATTENDED_TRANSFER_DEST_LINK:
997                 local1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[0], "LocalOne");
998                 local2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[1], "LocalTwo");
999                 if (!local1_state || !local2_state) {
1000                         return NULL;
1001                 }
1002                 ast_str_append(&variable_data, 0, "DestType: Link\r\n");
1003                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local1_state));
1004                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local2_state));
1005                 break;
1006         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
1007                 ast_str_append(&variable_data, 0, "DestType: Threeway\r\n");
1008                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.threeway.bridge_snapshot->uniqueid);
1009                 ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->name);
1010                 break;
1011         case AST_ATTENDED_TRANSFER_DEST_FAIL:
1012                 ast_str_append(&variable_data, 0, "DestType: Fail\r\n");
1013                 break;
1014         }
1015
1016         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "AttendedTransfer",
1017                         "Result: %s\r\n"
1018                         "%s"
1019                         "%s"
1020                         "%s"
1021                         "%s"
1022                         "%s"
1023                         "%s"
1024                         "IsExternal: %s\r\n"
1025                         "%s",
1026                         result_strs[transfer_msg->result],
1027                         ast_str_buffer(transferer1_state),
1028                         bridge1_state ? ast_str_buffer(bridge1_state) : "",
1029                         ast_str_buffer(transferer2_state),
1030                         bridge2_state ? ast_str_buffer(bridge2_state) : "",
1031                         transferee_state ? ast_str_buffer(transferee_state) : "",
1032                         target_state ? ast_str_buffer(target_state) : "",
1033                         transfer_msg->is_external ? "Yes" : "No",
1034                         ast_str_buffer(variable_data));
1035 }
1036
1037 static void attended_transfer_dtor(void *obj)
1038 {
1039         struct ast_attended_transfer_message *msg = obj;
1040         int i;
1041
1042         bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
1043         bridge_channel_snapshot_pair_cleanup(&msg->to_transfer_target);
1044         ao2_cleanup(msg->replace_channel);
1045         ao2_cleanup(msg->transferee);
1046         ao2_cleanup(msg->target);
1047
1048         if (msg->dest_type != AST_ATTENDED_TRANSFER_DEST_LINK) {
1049                 return;
1050         }
1051
1052         for (i = 0; i < ARRAY_LEN(msg->dest.links); ++i) {
1053                 ao2_cleanup(msg->dest.links[i]);
1054         }
1055 }
1056
1057 struct ast_attended_transfer_message *ast_attended_transfer_message_create(int is_external,
1058                 struct ast_channel *to_transferee, struct ast_bridge *transferee_bridge,
1059                 struct ast_channel *to_transfer_target, struct ast_bridge *target_bridge,
1060                 struct ast_channel *transferee, struct ast_channel *transfer_target)
1061 {
1062         struct ast_attended_transfer_message *transfer_msg;
1063
1064         transfer_msg = ao2_alloc(sizeof(*transfer_msg), attended_transfer_dtor);
1065         if (!transfer_msg) {
1066                 return NULL;
1067         }
1068
1069         if (bridge_channel_snapshot_pair_init(to_transferee, transferee_bridge, &transfer_msg->to_transferee) ||
1070                         bridge_channel_snapshot_pair_init(to_transfer_target, target_bridge, &transfer_msg->to_transfer_target)) {
1071                 ao2_cleanup(transfer_msg);
1072                 return NULL;
1073         }
1074
1075         if (transferee) {
1076                 transfer_msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee));
1077                 if (!transfer_msg->transferee) {
1078                         ao2_cleanup(transfer_msg);
1079                         return NULL;
1080                 }
1081         } else if (transferee_bridge) {
1082                 transferee = ast_bridge_peer(transferee_bridge, to_transferee);
1083                 if (transferee) {
1084                         transfer_msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee));
1085                         ao2_cleanup(transferee);
1086                         if (!transfer_msg->transferee) {
1087                                 ao2_cleanup(transfer_msg);
1088                                 return NULL;
1089                         }
1090                 }
1091         }
1092
1093         if (transfer_target) {
1094                 transfer_msg->target = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transfer_target));
1095                 if (!transfer_msg->target) {
1096                         ao2_cleanup(transfer_msg);
1097                         return NULL;
1098                 }
1099         } else if (target_bridge) {
1100                 transfer_target = ast_bridge_peer(target_bridge, to_transfer_target);
1101                 if (transfer_target) {
1102                         transfer_msg->target = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transfer_target));
1103                         ao2_cleanup(transfer_target);
1104                         if (!transfer_msg->target) {
1105                                 ao2_cleanup(transfer_msg);
1106                                 return NULL;
1107                         }
1108                 }
1109         }
1110
1111         return transfer_msg;
1112 }
1113
1114 int ast_attended_transfer_message_add_merge(struct ast_attended_transfer_message *transfer_msg,
1115                 struct ast_bridge *final_bridge)
1116 {
1117         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE;
1118         ast_copy_string(transfer_msg->dest.bridge, final_bridge->uniqueid,
1119                         sizeof(transfer_msg->dest.bridge));
1120
1121         return 0;
1122 }
1123
1124 int ast_attended_transfer_message_add_threeway(struct ast_attended_transfer_message *transfer_msg,
1125                 struct ast_channel *survivor_channel, struct ast_bridge *survivor_bridge)
1126 {
1127         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_THREEWAY;
1128
1129         if (!strcmp(ast_channel_uniqueid(survivor_channel), transfer_msg->to_transferee.channel_snapshot->uniqueid)) {
1130                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transferee.channel_snapshot;
1131         } else {
1132                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transfer_target.channel_snapshot;
1133         }
1134
1135         if (!strcmp(survivor_bridge->uniqueid, transfer_msg->to_transferee.bridge_snapshot->uniqueid)) {
1136                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transferee.bridge_snapshot;
1137         } else {
1138                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transfer_target.bridge_snapshot;
1139         }
1140
1141         return 0;
1142 }
1143
1144 int ast_attended_transfer_message_add_app(struct ast_attended_transfer_message *transfer_msg,
1145                 const char *app, struct ast_channel *replace_channel)
1146 {
1147         transfer_msg->dest_type = replace_channel ? AST_ATTENDED_TRANSFER_DEST_LOCAL_APP : AST_ATTENDED_TRANSFER_DEST_APP;
1148
1149         if (replace_channel) {
1150                 transfer_msg->replace_channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(replace_channel));
1151                 if (!transfer_msg->replace_channel) {
1152                         return -1;
1153                 }
1154         }
1155
1156         ast_copy_string(transfer_msg->dest.app, app, sizeof(transfer_msg->dest.app));
1157
1158         return 0;
1159 }
1160
1161 int ast_attended_transfer_message_add_link(struct ast_attended_transfer_message *transfer_msg,
1162                 struct ast_channel *locals[2])
1163 {
1164         int i;
1165
1166         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
1167         for (i = 0; i < 2; ++i) {
1168                 transfer_msg->dest.links[i] = ast_channel_snapshot_get_latest(ast_channel_uniqueid(locals[i]));
1169                 if (!transfer_msg->dest.links[i]) {
1170                         return -1;
1171                 }
1172         }
1173
1174         return 0;
1175 }
1176
1177 void ast_bridge_publish_attended_transfer(struct ast_attended_transfer_message *transfer_msg)
1178 {
1179         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1180
1181         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
1182         if (!msg) {
1183                 return;
1184         }
1185
1186         stasis_publish(ast_bridge_topic_all(), msg);
1187 }
1188
1189 struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
1190 {
1191         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
1192         struct ast_bridge_snapshot *snapshot;
1193
1194         ast_assert(!ast_strlen_zero(uniqueid));
1195
1196         message = stasis_cache_get(ast_bridge_cache(),
1197                         ast_bridge_snapshot_type(),
1198                         uniqueid);
1199         if (!message) {
1200                 return NULL;
1201         }
1202
1203         snapshot = stasis_message_data(message);
1204         if (!snapshot) {
1205                 return NULL;
1206         }
1207         ao2_ref(snapshot, +1);
1208         return snapshot;
1209 }
1210
1211 /*! \brief snapshot ID getter for caching topic */
1212 static const char *bridge_snapshot_get_id(struct stasis_message *msg)
1213 {
1214         struct ast_bridge_snapshot *snapshot;
1215         if (stasis_message_type(msg) != ast_bridge_snapshot_type()) {
1216                 return NULL;
1217         }
1218         snapshot = stasis_message_data(msg);
1219         return snapshot->uniqueid;
1220 }
1221
1222 static void stasis_bridging_cleanup(void)
1223 {
1224         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);
1225         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_merge_message_type);
1226         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_entered_bridge_type);
1227         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_left_bridge_type);
1228         STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);
1229         STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);
1230
1231         ao2_cleanup(bridge_cache_all);
1232         bridge_cache_all = NULL;
1233 }
1234
1235 int ast_stasis_bridging_init(void)
1236 {
1237         int res = 0;
1238
1239         ast_register_cleanup(stasis_bridging_cleanup);
1240
1241         bridge_cache_all = stasis_cp_all_create("ast_bridge_topic_all",
1242                 bridge_snapshot_get_id);
1243
1244         if (!bridge_cache_all) {
1245                 return -1;
1246         }
1247
1248         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_snapshot_type);
1249         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_merge_message_type);
1250         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_entered_bridge_type);
1251         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_left_bridge_type);
1252         res |= STASIS_MESSAGE_TYPE_INIT(ast_blind_transfer_type);
1253         res |= STASIS_MESSAGE_TYPE_INIT(ast_attended_transfer_type);
1254
1255         return res;
1256 }