b92d048bc091a9ce516c2925aab7c52df834b94e
[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                                 <bridge_snapshot/>
66                                 <parameter name="IsExternal">
67                                         <para>Indicates if the transfer was performed outside of Asterisk. For instance,
68                                         a channel protocol native transfer is external. A DTMF transfer is internal.</para>
69                                                 <enumlist>
70                                                         <enum name="Yes" />
71                                                         <enum name="No" />
72                                                 </enumlist>
73                                 </parameter>
74                                 <parameter name="Context">
75                                         <para>Destination context for the blind transfer.</para>
76                                 </parameter>
77                                 <parameter name="Extension">
78                                         <para>Destination extension for the blind transfer.</para>
79                                 </parameter>
80                         </syntax>
81                 </managerEventInstance>
82         </managerEvent>
83         <managerEvent language="en_US" name="AttendedTransfer">
84                 <managerEventInstance class="EVENT_FLAG_CALL">
85                         <synopsis>Raised when an attended transfer is complete.</synopsis>
86                         <syntax>
87                                 <xi:include xpointer="xpointer(docs/managerEvent[@name='BlindTransfer']/managerEventInstance/syntax/parameter[@name='Result'])" />
88                                 <channel_snapshot prefix="OrigTransferer"/>
89                                 <bridge_snapshot prefix="Orig"/>
90                                 <channel_snapshot prefix="SecondTransferer"/>
91                                 <bridge_snapshot prefix="Second"/>
92                                 <parameter name="DestType">
93                                         <para>Indicates the method by which the attended transfer completed.</para>
94                                         <enumlist>
95                                                 <enum name="Bridge"><para>The transfer was accomplished by merging two bridges into one.</para></enum>
96                                                 <enum name="App"><para>The transfer was accomplished by having a channel or bridge run a dialplan application.</para></enum>
97                                                 <enum name="Link"><para>The transfer was accomplished by linking two bridges together using a local channel pair.</para></enum>
98                                                 <enum name="Threeway"><para>The transfer was accomplished by placing all parties into a threeway call.</para></enum>
99                                                 <enum name="Fail"><para>The transfer failed.</para></enum>
100                                         </enumlist>
101                                 </parameter>
102                                 <parameter name="DestBridgeUniqueid">
103                                         <para>Indicates the surviving bridge when bridges were merged to complete the transfer</para>
104                                         <note><para>This header is only present when <replaceable>DestType</replaceable> is <literal>Bridge</literal> or <literal>Threeway</literal></para></note>
105                                 </parameter>
106                                 <parameter name="DestApp">
107                                         <para>Indicates the application that is running when the transfer completes</para>
108                                         <note><para>This header is only present when <replaceable>DestType</replaceable> is <literal>App</literal></para></note>
109                                 </parameter>
110                                 <channel_snapshot prefix="LocalOne"/>
111                                 <channel_snapshot prefix="LocalTwo"/>
112                                 <parameter name="DestTransfererChannel">
113                                         <para>The name of the surviving transferer channel when a transfer results in a threeway call</para>
114                                         <note><para>This header is only present when <replaceable>DestType</replaceable> is <literal>Threeway</literal></para></note>
115                                 </parameter>
116                         </syntax>
117                         <description>
118                                 <para>The headers in this event attempt to describe all the major details of the attended transfer. The two transferer channels
119                                 and the two bridges are determined based on their chronological establishment. So consider that Alice calls Bob, and then Alice
120                                 transfers the call to Voicemail. The transferer and bridge headers would be arranged as follows:</para>
121                                 <para>  <replaceable>OrigTransfererChannel</replaceable>: Alice's channel in the bridge with Bob.</para>
122                                 <para>  <replaceable>OrigBridgeUniqueid</replaceable>: The bridge between Alice and Bob.</para>
123                                 <para>  <replaceable>SecondTransfererChannel</replaceable>: Alice's channel that called Voicemail.</para>
124                                 <para>  <replaceable>SecondBridgeUniqueid</replaceable>: Not present, since a call to Voicemail has no bridge.</para>
125                                 <para>Now consider if the order were reversed; instead of having Alice call Bob and transfer him to Voicemail, Alice instead
126                                 calls her Voicemail and transfers that to Bob. The transferer and bridge headers would be arranged as follows:</para>
127                                 <para>  <replaceable>OrigTransfererChannel</replaceable>: Alice's channel that called Voicemail.</para>
128                                 <para>  <replaceable>OrigBridgeUniqueid</replaceable>: Not present, since a call to Voicemail has no bridge.</para>
129                                 <para>  <replaceable>SecondTransfererChannel</replaceable>: Alice's channel in the bridge with Bob.</para>
130                                 <para>  <replaceable>SecondBridgeUniqueid</replaceable>: The bridge between Alice and Bob.</para>
131                         </description>
132                 </managerEventInstance>
133         </managerEvent>
134  ***/
135
136 static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *message);
137 static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *message);
138 static struct ast_json *ast_channel_entered_bridge_to_json(
139         struct stasis_message *msg,
140         const struct stasis_message_sanitizer *sanitize);
141 static struct ast_json *ast_channel_left_bridge_to_json(
142         struct stasis_message *msg,
143         const struct stasis_message_sanitizer *sanitize);
144 static struct ast_json *ast_bridge_merge_message_to_json(
145         struct stasis_message *msg,
146         const struct stasis_message_sanitizer *sanitize);
147
148 static struct stasis_cp_all *bridge_cache_all;
149
150 /*!
151  * @{ \brief Define bridge message types.
152  */
153 STASIS_MESSAGE_TYPE_DEFN(ast_bridge_snapshot_type);
154 STASIS_MESSAGE_TYPE_DEFN(ast_bridge_merge_message_type,
155         .to_json = ast_bridge_merge_message_to_json);
156 STASIS_MESSAGE_TYPE_DEFN(ast_channel_entered_bridge_type,
157         .to_json = ast_channel_entered_bridge_to_json);
158 STASIS_MESSAGE_TYPE_DEFN(ast_channel_left_bridge_type,
159         .to_json = ast_channel_left_bridge_to_json);
160 STASIS_MESSAGE_TYPE_DEFN(ast_blind_transfer_type, .to_ami = blind_transfer_to_ami);
161 STASIS_MESSAGE_TYPE_DEFN(ast_attended_transfer_type, .to_ami = attended_transfer_to_ami);
162 /*! @} */
163
164 struct stasis_cache *ast_bridge_cache(void)
165 {
166         return stasis_cp_all_cache(bridge_cache_all);
167 }
168
169 struct stasis_topic *ast_bridge_topic_all(void)
170 {
171         return stasis_cp_all_topic(bridge_cache_all);
172 }
173
174 struct stasis_topic *ast_bridge_topic_all_cached(void)
175 {
176         return stasis_cp_all_topic_cached(bridge_cache_all);
177 }
178
179 int bridge_topics_init(struct ast_bridge *bridge)
180 {
181         if (ast_strlen_zero(bridge->uniqueid)) {
182                 ast_log(LOG_ERROR, "Bridge id initialization required\n");
183                 return -1;
184         }
185         bridge->topics = stasis_cp_single_create(bridge_cache_all,
186                 bridge->uniqueid);
187         if (!bridge->topics) {
188                 return -1;
189         }
190         return 0;
191 }
192
193 struct stasis_topic *ast_bridge_topic(struct ast_bridge *bridge)
194 {
195         if (!bridge) {
196                 return ast_bridge_topic_all();
197         }
198
199         return stasis_cp_single_topic(bridge->topics);
200 }
201
202 struct stasis_topic *ast_bridge_topic_cached(struct ast_bridge *bridge)
203 {
204         if (!bridge) {
205                 return ast_bridge_topic_all_cached();
206         }
207
208         return stasis_cp_single_topic_cached(bridge->topics);
209 }
210
211 /*! \brief Destructor for bridge snapshots */
212 static void bridge_snapshot_dtor(void *obj)
213 {
214         struct ast_bridge_snapshot *snapshot = obj;
215         ast_string_field_free_memory(snapshot);
216         ao2_cleanup(snapshot->channels);
217         snapshot->channels = NULL;
218 }
219
220 struct ast_bridge_snapshot *ast_bridge_snapshot_create(struct ast_bridge *bridge)
221 {
222         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
223         struct ast_bridge_channel *bridge_channel;
224
225         snapshot = ao2_alloc(sizeof(*snapshot), bridge_snapshot_dtor);
226         if (!snapshot || ast_string_field_init(snapshot, 128)) {
227                 return NULL;
228         }
229
230         snapshot->channels = ast_str_container_alloc(SNAPSHOT_CHANNELS_BUCKETS);
231         if (!snapshot->channels) {
232                 return NULL;
233         }
234
235         AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
236                 if (ast_str_container_add(snapshot->channels,
237                                 ast_channel_uniqueid(bridge_channel->chan))) {
238                         return NULL;
239                 }
240         }
241
242         ast_string_field_set(snapshot, uniqueid, bridge->uniqueid);
243         ast_string_field_set(snapshot, technology, bridge->technology->name);
244         ast_string_field_set(snapshot, subclass, bridge->v_table->name);
245
246         snapshot->feature_flags = bridge->feature_flags;
247         snapshot->capabilities = bridge->technology->capabilities;
248         snapshot->num_channels = bridge->num_channels;
249         snapshot->num_active = bridge->num_active;
250
251         ao2_ref(snapshot, +1);
252         return snapshot;
253 }
254
255 void ast_bridge_publish_state(struct ast_bridge *bridge)
256 {
257         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
258         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
259
260         ast_assert(bridge != NULL);
261
262         snapshot = ast_bridge_snapshot_create(bridge);
263         if (!snapshot) {
264                 return;
265         }
266
267         msg = stasis_message_create(ast_bridge_snapshot_type(), snapshot);
268         if (!msg) {
269                 return;
270         }
271
272         stasis_publish(ast_bridge_topic(bridge), msg);
273 }
274
275 static void bridge_publish_state_from_blob(struct ast_bridge *bridge,
276         struct ast_bridge_blob *obj)
277 {
278         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
279
280         ast_assert(obj != NULL);
281
282         msg = stasis_message_create(ast_bridge_snapshot_type(), obj->bridge);
283         if (!msg) {
284                 return;
285         }
286
287         stasis_publish(ast_bridge_topic(bridge), msg);
288 }
289
290 /*! \brief Destructor for bridge merge messages */
291 static void bridge_merge_message_dtor(void *obj)
292 {
293         struct ast_bridge_merge_message *msg = obj;
294
295         ao2_cleanup(msg->to);
296         msg->to = NULL;
297         ao2_cleanup(msg->from);
298         msg->from = NULL;
299 }
300
301 /*! \brief Bridge merge message creation helper */
302 static struct ast_bridge_merge_message *bridge_merge_message_create(struct ast_bridge *to, struct ast_bridge *from)
303 {
304         RAII_VAR(struct ast_bridge_merge_message *, msg, NULL, ao2_cleanup);
305
306         msg = ao2_alloc(sizeof(*msg), bridge_merge_message_dtor);
307         if (!msg) {
308                 return NULL;
309         }
310
311         msg->to = ast_bridge_snapshot_create(to);
312         if (!msg->to) {
313                 return NULL;
314         }
315
316         msg->from = ast_bridge_snapshot_create(from);
317         if (!msg->from) {
318                 return NULL;
319         }
320
321         ao2_ref(msg, +1);
322         return msg;
323 }
324
325 static struct ast_json *ast_bridge_merge_message_to_json(
326         struct stasis_message *msg,
327         const struct stasis_message_sanitizer *sanitize)
328 {
329         struct ast_bridge_merge_message *merge = stasis_message_data(msg);
330         RAII_VAR(struct ast_json *, json_bridge_to,
331                 ast_bridge_snapshot_to_json(merge->to, sanitize), ast_json_unref);
332         RAII_VAR(struct ast_json *, json_bridge_from,
333                 ast_bridge_snapshot_to_json(merge->from, sanitize), ast_json_unref);
334
335         if (!json_bridge_to || !json_bridge_from) {
336                 return NULL;
337         }
338
339         return ast_json_pack("{s: s, s: o, s: O, s: O}",
340                 "type", "BridgeMerged",
341                 "timestamp", ast_json_timeval(*stasis_message_timestamp(msg), NULL),
342                 "bridge", json_bridge_to,
343                 "bridge_from", json_bridge_from);
344 }
345
346 void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from)
347 {
348         RAII_VAR(struct ast_bridge_merge_message *, merge_msg, NULL, ao2_cleanup);
349         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
350
351         ast_assert(to != NULL);
352         ast_assert(from != NULL);
353
354         merge_msg = bridge_merge_message_create(to, from);
355         if (!merge_msg) {
356                 return;
357         }
358
359         msg = stasis_message_create(ast_bridge_merge_message_type(), merge_msg);
360         if (!msg) {
361                 return;
362         }
363
364         stasis_publish(ast_bridge_topic_all(), msg);
365 }
366
367 static void bridge_blob_dtor(void *obj)
368 {
369         struct ast_bridge_blob *event = obj;
370         ao2_cleanup(event->bridge);
371         event->bridge = NULL;
372         ao2_cleanup(event->channel);
373         event->channel = NULL;
374         ast_json_unref(event->blob);
375         event->blob = NULL;
376 }
377
378 struct stasis_message *ast_bridge_blob_create(
379         struct stasis_message_type *message_type,
380         struct ast_bridge *bridge,
381         struct ast_channel *chan,
382         struct ast_json *blob)
383 {
384         RAII_VAR(struct ast_bridge_blob *, obj, NULL, ao2_cleanup);
385         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
386
387         obj = ao2_alloc(sizeof(*obj), bridge_blob_dtor);
388         if (!obj) {
389                 return NULL;
390         }
391
392         if (bridge) {
393                 obj->bridge = ast_bridge_snapshot_create(bridge);
394                 if (obj->bridge == NULL) {
395                         return NULL;
396                 }
397         }
398
399         if (chan) {
400                 obj->channel = ast_channel_snapshot_create(chan);
401                 if (obj->channel == NULL) {
402                         return NULL;
403                 }
404         }
405
406         if (blob) {
407                 obj->blob = ast_json_ref(blob);
408         }
409
410         msg = stasis_message_create(message_type, obj);
411         if (!msg) {
412                 return NULL;
413         }
414
415         ao2_ref(msg, +1);
416         return msg;
417 }
418
419 void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *chan,
420                 struct ast_channel *swap)
421 {
422         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
423         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
424
425         if (swap) {
426                 blob = ast_json_pack("{s: s}", "swap", ast_channel_uniqueid(swap));
427                 if (!blob) {
428                         return;
429                 }
430         }
431
432         msg = ast_bridge_blob_create(ast_channel_entered_bridge_type(), bridge, chan, blob);
433         if (!msg) {
434                 return;
435         }
436
437         /* enter blob first, then state */
438         stasis_publish(ast_bridge_topic(bridge), msg);
439         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
440 }
441
442 void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *chan)
443 {
444         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
445
446         msg = ast_bridge_blob_create(ast_channel_left_bridge_type(), bridge, chan, NULL);
447         if (!msg) {
448                 return;
449         }
450
451         /* state first, then leave blob (opposite of enter, preserves nesting of events) */
452         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
453         stasis_publish(ast_bridge_topic(bridge), msg);
454 }
455
456 static struct ast_json *simple_bridge_channel_event(
457         const char *type,
458         struct ast_bridge_snapshot *bridge_snapshot,
459         struct ast_channel_snapshot *channel_snapshot,
460         const struct timeval *tv,
461         const struct stasis_message_sanitizer *sanitize)
462 {
463         RAII_VAR(struct ast_json *, json_bridge,
464                 ast_bridge_snapshot_to_json(bridge_snapshot, sanitize), ast_json_unref);
465         RAII_VAR(struct ast_json *, json_channel,
466                 ast_channel_snapshot_to_json(channel_snapshot, sanitize), ast_json_unref);
467
468         if (!json_bridge || !json_channel) {
469                 return NULL;
470         }
471
472         return ast_json_pack("{s: s, s: o, s: O, s: O}",
473                 "type", type,
474                 "timestamp", ast_json_timeval(*tv, NULL),
475                 "bridge", json_bridge,
476                 "channel", json_channel);
477 }
478
479 struct ast_json *ast_channel_entered_bridge_to_json(
480         struct stasis_message *msg,
481         const struct stasis_message_sanitizer *sanitize)
482 {
483         struct ast_bridge_blob *obj = stasis_message_data(msg);
484
485         return simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
486                 obj->channel, stasis_message_timestamp(msg), sanitize);
487 }
488
489 struct ast_json *ast_channel_left_bridge_to_json(
490         struct stasis_message *msg,
491         const struct stasis_message_sanitizer *sanitize)
492 {
493         struct ast_bridge_blob *obj = stasis_message_data(msg);
494
495         return simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
496                 obj->channel, stasis_message_timestamp(msg), sanitize);
497 }
498
499 static struct ast_json *container_to_json_array(struct ao2_container *items,
500         const struct stasis_message_sanitizer *sanitize)
501 {
502         RAII_VAR(struct ast_json *, json_items, ast_json_array_create(), ast_json_unref);
503         char *item;
504         struct ao2_iterator it;
505         if (!json_items) {
506                 return NULL;
507         }
508
509         for (it = ao2_iterator_init(items, 0);
510                 (item = ao2_iterator_next(&it)); ao2_cleanup(item)) {
511                 if (sanitize && sanitize->channel_id && sanitize->channel_id(item)) {
512                         continue;
513                 }
514
515                 if (ast_json_array_append(json_items, ast_json_string_create(item))) {
516                         ao2_cleanup(item);
517                         ao2_iterator_destroy(&it);
518                         return NULL;
519                 }
520         }
521         ao2_iterator_destroy(&it);
522
523         return ast_json_ref(json_items);
524 }
525
526 static const char *capability2str(uint32_t capabilities)
527 {
528         if (capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
529                 return "holding";
530         } else {
531                 return "mixing";
532         }
533 }
534
535 struct ast_json *ast_bridge_snapshot_to_json(
536         const struct ast_bridge_snapshot *snapshot,
537         const struct stasis_message_sanitizer *sanitize)
538 {
539         RAII_VAR(struct ast_json *, json_bridge, NULL, ast_json_unref);
540         struct ast_json *json_channels;
541
542         if (snapshot == NULL) {
543                 return NULL;
544         }
545
546         json_channels = container_to_json_array(snapshot->channels, sanitize);
547         if (!json_channels) {
548                 return NULL;
549         }
550
551         json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
552                 "id", snapshot->uniqueid,
553                 "technology", snapshot->technology,
554                 "bridge_type", capability2str(snapshot->capabilities),
555                 "bridge_class", snapshot->subclass,
556                 "channels", json_channels);
557         if (!json_bridge) {
558                 return NULL;
559         }
560
561         return ast_json_ref(json_bridge);
562 }
563
564 /*!
565  * \internal
566  * \brief Allocate the fields of an \ref ast_bridge_channel_snapshot_pair.
567  *
568  * \param pair A bridge and channel to get snapshots of
569  * \param[out] snapshot_pair An allocated snapshot pair.
570  * \retval 0 Success
571  * \retval non-zero Failure
572  */
573 static int bridge_channel_snapshot_pair_init(struct ast_bridge_channel_pair *pair, struct ast_bridge_channel_snapshot_pair *snapshot_pair)
574 {
575         if (pair->bridge) {
576                 snapshot_pair->bridge_snapshot = ast_bridge_snapshot_create(pair->bridge);
577                 if (!snapshot_pair->bridge_snapshot) {
578                         return -1;
579                 }
580         }
581
582         snapshot_pair->channel_snapshot = ast_channel_snapshot_create(pair->channel);
583         if (!snapshot_pair->channel_snapshot) {
584                 return -1;
585         }
586
587         return 0;
588 }
589
590 /*!
591  * \internal
592  * \brief Free the fields of an \ref ast_bridge_channel_snapshot_pair.
593  *
594  * \param pair The snapshot pair whose fields are to be cleaned up
595  */
596 static void bridge_channel_snapshot_pair_cleanup(struct ast_bridge_channel_snapshot_pair *pair)
597 {
598         ao2_cleanup(pair->bridge_snapshot);
599         ao2_cleanup(pair->channel_snapshot);
600 }
601
602 static const char *result_strs[] = {
603         [AST_BRIDGE_TRANSFER_FAIL] = "Fail",
604         [AST_BRIDGE_TRANSFER_INVALID] = "Invalid",
605         [AST_BRIDGE_TRANSFER_NOT_PERMITTED] = "Not Permitted",
606         [AST_BRIDGE_TRANSFER_SUCCESS] = "Success",
607 };
608
609 static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *msg)
610 {
611         RAII_VAR(struct ast_str *, channel_state, NULL, ast_free_ptr);
612         RAII_VAR(struct ast_str *, bridge_state, NULL, ast_free_ptr);
613         struct ast_bridge_blob *blob = stasis_message_data(msg);
614         const char *exten;
615         const char *context;
616         enum ast_transfer_result result;
617         int is_external;
618
619         if (!blob) {
620                 return NULL;
621         }
622
623         channel_state = ast_manager_build_channel_state_string_prefix(blob->channel, "Transferer");
624         if (!channel_state) {
625                 return NULL;
626         }
627
628         if (blob->bridge) {
629                 bridge_state = ast_manager_build_bridge_state_string(blob->bridge);
630                 if (!bridge_state) {
631                         return NULL;
632                 }
633         }
634
635         exten = ast_json_string_get(ast_json_object_get(blob->blob, "exten"));
636         context = ast_json_string_get(ast_json_object_get(blob->blob, "context"));
637         result = ast_json_integer_get(ast_json_object_get(blob->blob, "result"));
638         is_external = ast_json_integer_get(ast_json_object_get(blob->blob, "is_external"));
639
640         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "BlindTransfer",
641                         "Result: %s\r\n"
642                         "%s"
643                         "%s"
644                         "IsExternal: %s\r\n"
645                         "Context: %s\r\n"
646                         "Extension: %s\r\n",
647                         result_strs[result],
648                         ast_str_buffer(channel_state),
649                         bridge_state ? ast_str_buffer(bridge_state) : "",
650                         is_external ? "Yes" : "No",
651                         context,
652                         exten);
653 }
654
655 void ast_bridge_publish_blind_transfer(int is_external, enum ast_transfer_result result,
656                 struct ast_bridge_channel_pair *transferer, const char *context, const char *exten)
657 {
658         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
659         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
660
661         json_object = ast_json_pack("{s: s, s: s, s: i, s: i}",
662                         "context", context, "exten", exten, "result", result, "is_external", is_external);
663
664         if (!json_object) {
665                 ast_log(LOG_NOTICE, "Failed to create json bridge blob\n");
666                 return;
667         }
668
669         msg = ast_bridge_blob_create(ast_blind_transfer_type(),
670                         transferer->bridge, transferer->channel, json_object);
671
672         if (!msg) {
673                 ast_log(LOG_NOTICE, "Failed to create blob msg\n");
674                 return;
675         }
676
677         stasis_publish(ast_bridge_topic_all(), msg);
678 }
679
680 static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *msg)
681 {
682         RAII_VAR(struct ast_str *, variable_data, ast_str_create(64), ast_free_ptr);
683         RAII_VAR(struct ast_str *, transferer1_state, NULL, ast_free_ptr);
684         RAII_VAR(struct ast_str *, bridge1_state, NULL, ast_free_ptr);
685         RAII_VAR(struct ast_str *, transferer2_state, NULL, ast_free_ptr);
686         RAII_VAR(struct ast_str *, bridge2_state, NULL, ast_free_ptr);
687         RAII_VAR(struct ast_str *, local1_state, NULL, ast_free_ptr);
688         RAII_VAR(struct ast_str *, local2_state, NULL, ast_free_ptr);
689         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
690
691         if (!variable_data) {
692                 return NULL;
693         }
694
695         transferer1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transferee.channel_snapshot, "OrigTransferer");
696         transferer2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transfer_target.channel_snapshot, "SecondTransferer");
697         if (!transferer1_state || !transferer2_state) {
698                 return NULL;
699         }
700
701         if (transfer_msg->to_transferee.bridge_snapshot) {
702                 bridge1_state = ast_manager_build_bridge_state_string_prefix(
703                         transfer_msg->to_transferee.bridge_snapshot, "Orig");
704                 if (!bridge1_state) {
705                         return NULL;
706                 }
707         }
708
709         if (transfer_msg->to_transfer_target.bridge_snapshot) {
710                 bridge2_state = ast_manager_build_bridge_state_string_prefix(
711                         transfer_msg->to_transfer_target.bridge_snapshot, "Second");
712                 if (!bridge2_state) {
713                         return NULL;
714                 }
715         }
716
717         switch (transfer_msg->dest_type) {
718         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
719                 ast_str_append(&variable_data, 0, "DestType: Bridge\r\n");
720                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.bridge);
721                 break;
722         case AST_ATTENDED_TRANSFER_DEST_APP:
723                 ast_str_append(&variable_data, 0, "DestType: App\r\n");
724                 ast_str_append(&variable_data, 0, "DestApp: %s\r\n", transfer_msg->dest.app);
725                 break;
726         case AST_ATTENDED_TRANSFER_DEST_LINK:
727                 local1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[0], "LocalOne");
728                 local2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[1], "LocalTwo");
729                 if (!local1_state || !local2_state) {
730                         return NULL;
731                 }
732                 ast_str_append(&variable_data, 0, "DestType: Link\r\n");
733                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local1_state));
734                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local2_state));
735                 break;
736         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
737                 ast_str_append(&variable_data, 0, "DestType: Threeway\r\n");
738                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.threeway.bridge_snapshot->uniqueid);
739                 ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->name);
740                 break;
741         case AST_ATTENDED_TRANSFER_DEST_FAIL:
742                 ast_str_append(&variable_data, 0, "DestType: Fail\r\n");
743                 break;
744         }
745
746         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "AttendedTransfer",
747                         "Result: %s\r\n"
748                         "%s"
749                         "%s"
750                         "%s"
751                         "%s"
752                         "IsExternal: %s\r\n"
753                         "%s",
754                         result_strs[transfer_msg->result],
755                         ast_str_buffer(transferer1_state),
756                         bridge1_state ? ast_str_buffer(bridge1_state) : "",
757                         ast_str_buffer(transferer2_state),
758                         bridge2_state ? ast_str_buffer(bridge2_state) : "",
759                         transfer_msg->is_external ? "Yes" : "No",
760                         ast_str_buffer(variable_data));
761 }
762
763 static void attended_transfer_dtor(void *obj)
764 {
765         struct ast_attended_transfer_message *msg = obj;
766         int i;
767
768         bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
769         bridge_channel_snapshot_pair_cleanup(&msg->to_transfer_target);
770
771         if (msg->dest_type != AST_ATTENDED_TRANSFER_DEST_LINK) {
772                 return;
773         }
774
775         for (i = 0; i < ARRAY_LEN(msg->dest.links); ++i) {
776                 ao2_cleanup(msg->dest.links[i]);
777         }
778 }
779
780 static struct ast_attended_transfer_message *attended_transfer_message_create(int is_external, enum ast_transfer_result result,
781                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target)
782 {
783         RAII_VAR(struct ast_attended_transfer_message *, msg, NULL, ao2_cleanup);
784
785         msg = ao2_alloc(sizeof(*msg), attended_transfer_dtor);
786         if (!msg) {
787                 return NULL;
788         }
789
790         if (bridge_channel_snapshot_pair_init(transferee, &msg->to_transferee) ||
791                         bridge_channel_snapshot_pair_init(target, &msg->to_transfer_target)) {
792                 return NULL;
793         }
794
795         msg->is_external = is_external;
796         msg->result = result;
797
798         ao2_ref(msg, +1);
799         return msg;
800 }
801
802 void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfer_result result,
803                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target)
804 {
805         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
806         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
807
808         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
809         if (!transfer_msg) {
810                 return;
811         }
812
813         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_FAIL;
814
815         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
816         if (!msg) {
817                 return;
818         }
819
820         stasis_publish(ast_bridge_topic_all(), msg);
821 }
822
823 void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast_transfer_result result,
824                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
825                 struct ast_bridge *final_bridge)
826 {
827         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
828         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
829
830         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
831         if (!transfer_msg) {
832                 return;
833         }
834
835         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE;
836         ast_copy_string(transfer_msg->dest.bridge, final_bridge->uniqueid,
837                         sizeof(transfer_msg->dest.bridge));
838
839         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
840         if (!msg) {
841                 return;
842         }
843
844         stasis_publish(ast_bridge_topic_all(), msg);
845 }
846
847 void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_transfer_result result,
848                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
849                 struct ast_bridge_channel_pair *final_pair)
850 {
851         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
852         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
853
854         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
855         if (!transfer_msg) {
856                 return;
857         }
858
859         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_THREEWAY;
860         if (final_pair->channel == transferee->channel) {
861                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transferee.channel_snapshot;
862         } else {
863                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transfer_target.channel_snapshot;
864         }
865
866         if (final_pair->bridge == transferee->bridge) {
867                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transferee.bridge_snapshot;
868         } else {
869                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transfer_target.bridge_snapshot;
870         }
871
872         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
873         if (!msg) {
874                 return;
875         }
876
877         stasis_publish(ast_bridge_topic_all(), msg);
878 }
879
880 void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer_result result,
881                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
882                 const char *dest_app)
883 {
884         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
885         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
886
887         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
888         if (!transfer_msg) {
889                 return;
890         }
891
892         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_APP;
893         ast_copy_string(transfer_msg->dest.app, dest_app, sizeof(transfer_msg->dest.app));
894
895         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
896         if (!msg) {
897                 return;
898         }
899
900         stasis_publish(ast_bridge_topic_all(), msg);
901 }
902
903 void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfer_result result,
904                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
905                 struct ast_channel *locals[2])
906 {
907         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
908         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
909         int i;
910
911         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
912         if (!transfer_msg) {
913                 return;
914         }
915
916         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
917         for (i = 0; i < 2; ++i) {
918                 transfer_msg->dest.links[i] = ast_channel_snapshot_create(locals[i]);
919                 if (!transfer_msg->dest.links[i]) {
920                         return;
921                 }
922         }
923
924         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
925         if (!msg) {
926                 return;
927         }
928
929         stasis_publish(ast_bridge_topic_all(), msg);
930 }
931
932 struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
933 {
934         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
935         struct ast_bridge_snapshot *snapshot;
936
937         ast_assert(!ast_strlen_zero(uniqueid));
938
939         message = stasis_cache_get(ast_bridge_cache(),
940                         ast_bridge_snapshot_type(),
941                         uniqueid);
942         if (!message) {
943                 return NULL;
944         }
945
946         snapshot = stasis_message_data(message);
947         if (!snapshot) {
948                 return NULL;
949         }
950         ao2_ref(snapshot, +1);
951         return snapshot;
952 }
953
954 /*! \brief snapshot ID getter for caching topic */
955 static const char *bridge_snapshot_get_id(struct stasis_message *msg)
956 {
957         struct ast_bridge_snapshot *snapshot;
958         if (stasis_message_type(msg) != ast_bridge_snapshot_type()) {
959                 return NULL;
960         }
961         snapshot = stasis_message_data(msg);
962         return snapshot->uniqueid;
963 }
964
965 static void stasis_bridging_cleanup(void)
966 {
967         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);
968         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_merge_message_type);
969         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_entered_bridge_type);
970         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_left_bridge_type);
971         STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);
972         STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);
973
974         ao2_cleanup(bridge_cache_all);
975         bridge_cache_all = NULL;
976 }
977
978 int ast_stasis_bridging_init(void)
979 {
980         int res = 0;
981
982         ast_register_cleanup(stasis_bridging_cleanup);
983
984         bridge_cache_all = stasis_cp_all_create("ast_bridge_topic_all",
985                 bridge_snapshot_get_id);
986
987         if (!bridge_cache_all) {
988                 return -1;
989         }
990
991         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_snapshot_type);
992         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_merge_message_type);
993         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_entered_bridge_type);
994         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_left_bridge_type);
995         res |= STASIS_MESSAGE_TYPE_INIT(ast_blind_transfer_type);
996         res |= STASIS_MESSAGE_TYPE_INIT(ast_attended_transfer_type);
997
998         return res;
999 }