channel locking: Add locking for channel snapshot creation
[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         ast_string_field_set(snapshot, creator, bridge->creator);
246         ast_string_field_set(snapshot, name, bridge->name);
247
248         snapshot->feature_flags = bridge->feature_flags;
249         snapshot->capabilities = bridge->technology->capabilities;
250         snapshot->num_channels = bridge->num_channels;
251         snapshot->num_active = bridge->num_active;
252
253         ao2_ref(snapshot, +1);
254         return snapshot;
255 }
256
257 void ast_bridge_publish_state(struct ast_bridge *bridge)
258 {
259         RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
260         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
261
262         ast_assert(bridge != NULL);
263
264         snapshot = ast_bridge_snapshot_create(bridge);
265         if (!snapshot) {
266                 return;
267         }
268
269         msg = stasis_message_create(ast_bridge_snapshot_type(), snapshot);
270         if (!msg) {
271                 return;
272         }
273
274         stasis_publish(ast_bridge_topic(bridge), msg);
275 }
276
277 static void bridge_publish_state_from_blob(struct ast_bridge *bridge,
278         struct ast_bridge_blob *obj)
279 {
280         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
281
282         ast_assert(obj != NULL);
283
284         msg = stasis_message_create(ast_bridge_snapshot_type(), obj->bridge);
285         if (!msg) {
286                 return;
287         }
288
289         stasis_publish(ast_bridge_topic(bridge), msg);
290 }
291
292 /*! \brief Destructor for bridge merge messages */
293 static void bridge_merge_message_dtor(void *obj)
294 {
295         struct ast_bridge_merge_message *msg = obj;
296
297         ao2_cleanup(msg->to);
298         msg->to = NULL;
299         ao2_cleanup(msg->from);
300         msg->from = NULL;
301 }
302
303 /*! \brief Bridge merge message creation helper */
304 static struct ast_bridge_merge_message *bridge_merge_message_create(struct ast_bridge *to, struct ast_bridge *from)
305 {
306         RAII_VAR(struct ast_bridge_merge_message *, msg, NULL, ao2_cleanup);
307
308         msg = ao2_alloc(sizeof(*msg), bridge_merge_message_dtor);
309         if (!msg) {
310                 return NULL;
311         }
312
313         msg->to = ast_bridge_snapshot_create(to);
314         if (!msg->to) {
315                 return NULL;
316         }
317
318         msg->from = ast_bridge_snapshot_create(from);
319         if (!msg->from) {
320                 return NULL;
321         }
322
323         ao2_ref(msg, +1);
324         return msg;
325 }
326
327 static struct ast_json *ast_bridge_merge_message_to_json(
328         struct stasis_message *msg,
329         const struct stasis_message_sanitizer *sanitize)
330 {
331         struct ast_bridge_merge_message *merge = stasis_message_data(msg);
332         RAII_VAR(struct ast_json *, json_bridge_to,
333                 ast_bridge_snapshot_to_json(merge->to, sanitize), ast_json_unref);
334         RAII_VAR(struct ast_json *, json_bridge_from,
335                 ast_bridge_snapshot_to_json(merge->from, sanitize), ast_json_unref);
336
337         if (!json_bridge_to || !json_bridge_from) {
338                 return NULL;
339         }
340
341         return ast_json_pack("{s: s, s: o, s: O, s: O}",
342                 "type", "BridgeMerged",
343                 "timestamp", ast_json_timeval(*stasis_message_timestamp(msg), NULL),
344                 "bridge", json_bridge_to,
345                 "bridge_from", json_bridge_from);
346 }
347
348 void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from)
349 {
350         RAII_VAR(struct ast_bridge_merge_message *, merge_msg, NULL, ao2_cleanup);
351         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
352
353         ast_assert(to != NULL);
354         ast_assert(from != NULL);
355
356         merge_msg = bridge_merge_message_create(to, from);
357         if (!merge_msg) {
358                 return;
359         }
360
361         msg = stasis_message_create(ast_bridge_merge_message_type(), merge_msg);
362         if (!msg) {
363                 return;
364         }
365
366         stasis_publish(ast_bridge_topic_all(), msg);
367 }
368
369 static void bridge_blob_dtor(void *obj)
370 {
371         struct ast_bridge_blob *event = obj;
372         ao2_cleanup(event->bridge);
373         event->bridge = NULL;
374         ao2_cleanup(event->channel);
375         event->channel = NULL;
376         ast_json_unref(event->blob);
377         event->blob = NULL;
378 }
379
380 struct stasis_message *ast_bridge_blob_create(
381         struct stasis_message_type *message_type,
382         struct ast_bridge *bridge,
383         struct ast_channel *chan,
384         struct ast_json *blob)
385 {
386         RAII_VAR(struct ast_bridge_blob *, obj, NULL, ao2_cleanup);
387         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
388
389         obj = ao2_alloc(sizeof(*obj), bridge_blob_dtor);
390         if (!obj) {
391                 return NULL;
392         }
393
394         if (bridge) {
395                 obj->bridge = ast_bridge_snapshot_create(bridge);
396                 if (obj->bridge == NULL) {
397                         return NULL;
398                 }
399         }
400
401         if (chan) {
402                 ast_channel_lock(chan);
403                 obj->channel = ast_channel_snapshot_create(chan);
404                 ast_channel_unlock(chan);
405                 if (obj->channel == NULL) {
406                         return NULL;
407                 }
408         }
409
410         if (blob) {
411                 obj->blob = ast_json_ref(blob);
412         }
413
414         msg = stasis_message_create(message_type, obj);
415         if (!msg) {
416                 return NULL;
417         }
418
419         ao2_ref(msg, +1);
420         return msg;
421 }
422
423 void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *chan,
424                 struct ast_channel *swap)
425 {
426         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
427         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
428
429         if (swap) {
430                 blob = ast_json_pack("{s: s}", "swap", ast_channel_uniqueid(swap));
431                 if (!blob) {
432                         return;
433                 }
434         }
435
436         msg = ast_bridge_blob_create(ast_channel_entered_bridge_type(), bridge, chan, blob);
437         if (!msg) {
438                 return;
439         }
440
441         /* enter blob first, then state */
442         stasis_publish(ast_bridge_topic(bridge), msg);
443         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
444 }
445
446 void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *chan)
447 {
448         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
449
450         msg = ast_bridge_blob_create(ast_channel_left_bridge_type(), bridge, chan, NULL);
451         if (!msg) {
452                 return;
453         }
454
455         /* state first, then leave blob (opposite of enter, preserves nesting of events) */
456         bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
457         stasis_publish(ast_bridge_topic(bridge), msg);
458 }
459
460 static struct ast_json *simple_bridge_channel_event(
461         const char *type,
462         struct ast_bridge_snapshot *bridge_snapshot,
463         struct ast_channel_snapshot *channel_snapshot,
464         const struct timeval *tv,
465         const struct stasis_message_sanitizer *sanitize)
466 {
467         RAII_VAR(struct ast_json *, json_bridge,
468                 ast_bridge_snapshot_to_json(bridge_snapshot, sanitize), ast_json_unref);
469         RAII_VAR(struct ast_json *, json_channel,
470                 ast_channel_snapshot_to_json(channel_snapshot, sanitize), ast_json_unref);
471
472         if (!json_bridge || !json_channel) {
473                 return NULL;
474         }
475
476         return ast_json_pack("{s: s, s: o, s: O, s: O}",
477                 "type", type,
478                 "timestamp", ast_json_timeval(*tv, NULL),
479                 "bridge", json_bridge,
480                 "channel", json_channel);
481 }
482
483 struct ast_json *ast_channel_entered_bridge_to_json(
484         struct stasis_message *msg,
485         const struct stasis_message_sanitizer *sanitize)
486 {
487         struct ast_bridge_blob *obj = stasis_message_data(msg);
488
489         return simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
490                 obj->channel, stasis_message_timestamp(msg), sanitize);
491 }
492
493 struct ast_json *ast_channel_left_bridge_to_json(
494         struct stasis_message *msg,
495         const struct stasis_message_sanitizer *sanitize)
496 {
497         struct ast_bridge_blob *obj = stasis_message_data(msg);
498
499         return simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
500                 obj->channel, stasis_message_timestamp(msg), sanitize);
501 }
502
503 static struct ast_json *container_to_json_array(struct ao2_container *items,
504         const struct stasis_message_sanitizer *sanitize)
505 {
506         RAII_VAR(struct ast_json *, json_items, ast_json_array_create(), ast_json_unref);
507         char *item;
508         struct ao2_iterator it;
509         if (!json_items) {
510                 return NULL;
511         }
512
513         for (it = ao2_iterator_init(items, 0);
514                 (item = ao2_iterator_next(&it)); ao2_cleanup(item)) {
515                 if (sanitize && sanitize->channel_id && sanitize->channel_id(item)) {
516                         continue;
517                 }
518
519                 if (ast_json_array_append(json_items, ast_json_string_create(item))) {
520                         ao2_cleanup(item);
521                         ao2_iterator_destroy(&it);
522                         return NULL;
523                 }
524         }
525         ao2_iterator_destroy(&it);
526
527         return ast_json_ref(json_items);
528 }
529
530 static const char *capability2str(uint32_t capabilities)
531 {
532         if (capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
533                 return "holding";
534         } else {
535                 return "mixing";
536         }
537 }
538
539 struct ast_json *ast_bridge_snapshot_to_json(
540         const struct ast_bridge_snapshot *snapshot,
541         const struct stasis_message_sanitizer *sanitize)
542 {
543         RAII_VAR(struct ast_json *, json_bridge, NULL, ast_json_unref);
544         struct ast_json *json_channels;
545
546         if (snapshot == NULL) {
547                 return NULL;
548         }
549
550         json_channels = container_to_json_array(snapshot->channels, sanitize);
551         if (!json_channels) {
552                 return NULL;
553         }
554
555         json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
556                 "id", snapshot->uniqueid,
557                 "technology", snapshot->technology,
558                 "bridge_type", capability2str(snapshot->capabilities),
559                 "bridge_class", snapshot->subclass,
560                 "creator", snapshot->creator,
561                 "name", snapshot->name,
562                 "channels", json_channels);
563         if (!json_bridge) {
564                 return NULL;
565         }
566
567         return ast_json_ref(json_bridge);
568 }
569
570 /*!
571  * \internal
572  * \brief Allocate the fields of an \ref ast_bridge_channel_snapshot_pair.
573  *
574  * \param pair A bridge and channel to get snapshots of
575  * \param[out] snapshot_pair An allocated snapshot pair.
576  * \retval 0 Success
577  * \retval non-zero Failure
578  */
579 static int bridge_channel_snapshot_pair_init(struct ast_bridge_channel_pair *pair, struct ast_bridge_channel_snapshot_pair *snapshot_pair)
580 {
581         if (pair->bridge) {
582                 snapshot_pair->bridge_snapshot = ast_bridge_snapshot_create(pair->bridge);
583                 if (!snapshot_pair->bridge_snapshot) {
584                         return -1;
585                 }
586         }
587
588         ast_channel_lock(pair->channel);
589         snapshot_pair->channel_snapshot = ast_channel_snapshot_create(pair->channel);
590         ast_channel_unlock(pair->channel);
591         if (!snapshot_pair->channel_snapshot) {
592                 return -1;
593         }
594
595         return 0;
596 }
597
598 /*!
599  * \internal
600  * \brief Free the fields of an \ref ast_bridge_channel_snapshot_pair.
601  *
602  * \param pair The snapshot pair whose fields are to be cleaned up
603  */
604 static void bridge_channel_snapshot_pair_cleanup(struct ast_bridge_channel_snapshot_pair *pair)
605 {
606         ao2_cleanup(pair->bridge_snapshot);
607         ao2_cleanup(pair->channel_snapshot);
608 }
609
610 static const char *result_strs[] = {
611         [AST_BRIDGE_TRANSFER_FAIL] = "Fail",
612         [AST_BRIDGE_TRANSFER_INVALID] = "Invalid",
613         [AST_BRIDGE_TRANSFER_NOT_PERMITTED] = "Not Permitted",
614         [AST_BRIDGE_TRANSFER_SUCCESS] = "Success",
615 };
616
617 static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *msg)
618 {
619         RAII_VAR(struct ast_str *, channel_state, NULL, ast_free_ptr);
620         RAII_VAR(struct ast_str *, bridge_state, NULL, ast_free_ptr);
621         struct ast_bridge_blob *blob = stasis_message_data(msg);
622         const char *exten;
623         const char *context;
624         enum ast_transfer_result result;
625         int is_external;
626
627         if (!blob) {
628                 return NULL;
629         }
630
631         channel_state = ast_manager_build_channel_state_string_prefix(blob->channel, "Transferer");
632         if (!channel_state) {
633                 return NULL;
634         }
635
636         if (blob->bridge) {
637                 bridge_state = ast_manager_build_bridge_state_string(blob->bridge);
638                 if (!bridge_state) {
639                         return NULL;
640                 }
641         }
642
643         exten = ast_json_string_get(ast_json_object_get(blob->blob, "exten"));
644         context = ast_json_string_get(ast_json_object_get(blob->blob, "context"));
645         result = ast_json_integer_get(ast_json_object_get(blob->blob, "result"));
646         is_external = ast_json_integer_get(ast_json_object_get(blob->blob, "is_external"));
647
648         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "BlindTransfer",
649                         "Result: %s\r\n"
650                         "%s"
651                         "%s"
652                         "IsExternal: %s\r\n"
653                         "Context: %s\r\n"
654                         "Extension: %s\r\n",
655                         result_strs[result],
656                         ast_str_buffer(channel_state),
657                         bridge_state ? ast_str_buffer(bridge_state) : "",
658                         is_external ? "Yes" : "No",
659                         context,
660                         exten);
661 }
662
663 void ast_bridge_publish_blind_transfer(int is_external, enum ast_transfer_result result,
664                 struct ast_bridge_channel_pair *transferer, const char *context, const char *exten)
665 {
666         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
667         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
668
669         json_object = ast_json_pack("{s: s, s: s, s: i, s: i}",
670                         "context", context, "exten", exten, "result", result, "is_external", is_external);
671
672         if (!json_object) {
673                 ast_log(LOG_NOTICE, "Failed to create json bridge blob\n");
674                 return;
675         }
676
677         msg = ast_bridge_blob_create(ast_blind_transfer_type(),
678                         transferer->bridge, transferer->channel, json_object);
679
680         if (!msg) {
681                 ast_log(LOG_NOTICE, "Failed to create blob msg\n");
682                 return;
683         }
684
685         stasis_publish(ast_bridge_topic_all(), msg);
686 }
687
688 static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *msg)
689 {
690         RAII_VAR(struct ast_str *, variable_data, ast_str_create(64), ast_free_ptr);
691         RAII_VAR(struct ast_str *, transferer1_state, NULL, ast_free_ptr);
692         RAII_VAR(struct ast_str *, bridge1_state, NULL, ast_free_ptr);
693         RAII_VAR(struct ast_str *, transferer2_state, NULL, ast_free_ptr);
694         RAII_VAR(struct ast_str *, bridge2_state, NULL, ast_free_ptr);
695         RAII_VAR(struct ast_str *, local1_state, NULL, ast_free_ptr);
696         RAII_VAR(struct ast_str *, local2_state, NULL, ast_free_ptr);
697         struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
698
699         if (!variable_data) {
700                 return NULL;
701         }
702
703         transferer1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transferee.channel_snapshot, "OrigTransferer");
704         transferer2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->to_transfer_target.channel_snapshot, "SecondTransferer");
705         if (!transferer1_state || !transferer2_state) {
706                 return NULL;
707         }
708
709         if (transfer_msg->to_transferee.bridge_snapshot) {
710                 bridge1_state = ast_manager_build_bridge_state_string_prefix(
711                         transfer_msg->to_transferee.bridge_snapshot, "Orig");
712                 if (!bridge1_state) {
713                         return NULL;
714                 }
715         }
716
717         if (transfer_msg->to_transfer_target.bridge_snapshot) {
718                 bridge2_state = ast_manager_build_bridge_state_string_prefix(
719                         transfer_msg->to_transfer_target.bridge_snapshot, "Second");
720                 if (!bridge2_state) {
721                         return NULL;
722                 }
723         }
724
725         switch (transfer_msg->dest_type) {
726         case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
727                 ast_str_append(&variable_data, 0, "DestType: Bridge\r\n");
728                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.bridge);
729                 break;
730         case AST_ATTENDED_TRANSFER_DEST_APP:
731                 ast_str_append(&variable_data, 0, "DestType: App\r\n");
732                 ast_str_append(&variable_data, 0, "DestApp: %s\r\n", transfer_msg->dest.app);
733                 break;
734         case AST_ATTENDED_TRANSFER_DEST_LINK:
735                 local1_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[0], "LocalOne");
736                 local2_state = ast_manager_build_channel_state_string_prefix(transfer_msg->dest.links[1], "LocalTwo");
737                 if (!local1_state || !local2_state) {
738                         return NULL;
739                 }
740                 ast_str_append(&variable_data, 0, "DestType: Link\r\n");
741                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local1_state));
742                 ast_str_append(&variable_data, 0, "%s", ast_str_buffer(local2_state));
743                 break;
744         case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
745                 ast_str_append(&variable_data, 0, "DestType: Threeway\r\n");
746                 ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.threeway.bridge_snapshot->uniqueid);
747                 ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->name);
748                 break;
749         case AST_ATTENDED_TRANSFER_DEST_FAIL:
750                 ast_str_append(&variable_data, 0, "DestType: Fail\r\n");
751                 break;
752         }
753
754         return ast_manager_event_blob_create(EVENT_FLAG_CALL, "AttendedTransfer",
755                         "Result: %s\r\n"
756                         "%s"
757                         "%s"
758                         "%s"
759                         "%s"
760                         "IsExternal: %s\r\n"
761                         "%s",
762                         result_strs[transfer_msg->result],
763                         ast_str_buffer(transferer1_state),
764                         bridge1_state ? ast_str_buffer(bridge1_state) : "",
765                         ast_str_buffer(transferer2_state),
766                         bridge2_state ? ast_str_buffer(bridge2_state) : "",
767                         transfer_msg->is_external ? "Yes" : "No",
768                         ast_str_buffer(variable_data));
769 }
770
771 static void attended_transfer_dtor(void *obj)
772 {
773         struct ast_attended_transfer_message *msg = obj;
774         int i;
775
776         bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
777         bridge_channel_snapshot_pair_cleanup(&msg->to_transfer_target);
778
779         if (msg->dest_type != AST_ATTENDED_TRANSFER_DEST_LINK) {
780                 return;
781         }
782
783         for (i = 0; i < ARRAY_LEN(msg->dest.links); ++i) {
784                 ao2_cleanup(msg->dest.links[i]);
785         }
786 }
787
788 static struct ast_attended_transfer_message *attended_transfer_message_create(int is_external, enum ast_transfer_result result,
789                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target)
790 {
791         RAII_VAR(struct ast_attended_transfer_message *, msg, NULL, ao2_cleanup);
792
793         msg = ao2_alloc(sizeof(*msg), attended_transfer_dtor);
794         if (!msg) {
795                 return NULL;
796         }
797
798         if (bridge_channel_snapshot_pair_init(transferee, &msg->to_transferee) ||
799                         bridge_channel_snapshot_pair_init(target, &msg->to_transfer_target)) {
800                 return NULL;
801         }
802
803         msg->is_external = is_external;
804         msg->result = result;
805
806         ao2_ref(msg, +1);
807         return msg;
808 }
809
810 void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfer_result result,
811                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target)
812 {
813         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
814         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
815
816         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
817         if (!transfer_msg) {
818                 return;
819         }
820
821         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_FAIL;
822
823         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
824         if (!msg) {
825                 return;
826         }
827
828         stasis_publish(ast_bridge_topic_all(), msg);
829 }
830
831 void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast_transfer_result result,
832                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
833                 struct ast_bridge *final_bridge)
834 {
835         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
836         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
837
838         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
839         if (!transfer_msg) {
840                 return;
841         }
842
843         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE;
844         ast_copy_string(transfer_msg->dest.bridge, final_bridge->uniqueid,
845                         sizeof(transfer_msg->dest.bridge));
846
847         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
848         if (!msg) {
849                 return;
850         }
851
852         stasis_publish(ast_bridge_topic_all(), msg);
853 }
854
855 void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_transfer_result result,
856                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
857                 struct ast_bridge_channel_pair *final_pair)
858 {
859         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
860         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
861
862         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
863         if (!transfer_msg) {
864                 return;
865         }
866
867         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_THREEWAY;
868         if (final_pair->channel == transferee->channel) {
869                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transferee.channel_snapshot;
870         } else {
871                 transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transfer_target.channel_snapshot;
872         }
873
874         if (final_pair->bridge == transferee->bridge) {
875                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transferee.bridge_snapshot;
876         } else {
877                 transfer_msg->dest.threeway.bridge_snapshot = transfer_msg->to_transfer_target.bridge_snapshot;
878         }
879
880         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
881         if (!msg) {
882                 return;
883         }
884
885         stasis_publish(ast_bridge_topic_all(), msg);
886 }
887
888 void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer_result result,
889                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
890                 const char *dest_app)
891 {
892         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
893         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
894
895         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
896         if (!transfer_msg) {
897                 return;
898         }
899
900         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_APP;
901         ast_copy_string(transfer_msg->dest.app, dest_app, sizeof(transfer_msg->dest.app));
902
903         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
904         if (!msg) {
905                 return;
906         }
907
908         stasis_publish(ast_bridge_topic_all(), msg);
909 }
910
911 void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfer_result result,
912                 struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
913                 struct ast_channel *locals[2])
914 {
915         RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
916         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
917         int i;
918
919         transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
920         if (!transfer_msg) {
921                 return;
922         }
923
924         transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
925         for (i = 0; i < 2; ++i) {
926                 ast_channel_lock(locals[i]);
927                 transfer_msg->dest.links[i] = ast_channel_snapshot_create(locals[i]);
928                 ast_channel_unlock(locals[i]);
929                 if (!transfer_msg->dest.links[i]) {
930                         return;
931                 }
932         }
933
934         msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
935         if (!msg) {
936                 return;
937         }
938
939         stasis_publish(ast_bridge_topic_all(), msg);
940 }
941
942 struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
943 {
944         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
945         struct ast_bridge_snapshot *snapshot;
946
947         ast_assert(!ast_strlen_zero(uniqueid));
948
949         message = stasis_cache_get(ast_bridge_cache(),
950                         ast_bridge_snapshot_type(),
951                         uniqueid);
952         if (!message) {
953                 return NULL;
954         }
955
956         snapshot = stasis_message_data(message);
957         if (!snapshot) {
958                 return NULL;
959         }
960         ao2_ref(snapshot, +1);
961         return snapshot;
962 }
963
964 /*! \brief snapshot ID getter for caching topic */
965 static const char *bridge_snapshot_get_id(struct stasis_message *msg)
966 {
967         struct ast_bridge_snapshot *snapshot;
968         if (stasis_message_type(msg) != ast_bridge_snapshot_type()) {
969                 return NULL;
970         }
971         snapshot = stasis_message_data(msg);
972         return snapshot->uniqueid;
973 }
974
975 static void stasis_bridging_cleanup(void)
976 {
977         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);
978         STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_merge_message_type);
979         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_entered_bridge_type);
980         STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_left_bridge_type);
981         STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);
982         STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);
983
984         ao2_cleanup(bridge_cache_all);
985         bridge_cache_all = NULL;
986 }
987
988 int ast_stasis_bridging_init(void)
989 {
990         int res = 0;
991
992         ast_register_cleanup(stasis_bridging_cleanup);
993
994         bridge_cache_all = stasis_cp_all_create("ast_bridge_topic_all",
995                 bridge_snapshot_get_id);
996
997         if (!bridge_cache_all) {
998                 return -1;
999         }
1000
1001         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_snapshot_type);
1002         res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_merge_message_type);
1003         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_entered_bridge_type);
1004         res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_left_bridge_type);
1005         res |= STASIS_MESSAGE_TYPE_INIT(ast_blind_transfer_type);
1006         res |= STASIS_MESSAGE_TYPE_INIT(ast_attended_transfer_type);
1007
1008         return res;
1009 }