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