Made some bridging API calls void. Some bridging comments updated.
[asterisk/asterisk.git] / bridges / bridge_builtin_features.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@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 Built in bridging features
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  *
25  * \ingroup bridges
26  */
27
28 /*** MODULEINFO
29         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41
42 #include "asterisk/module.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/bridging.h"
45 #include "asterisk/bridging_technology.h"
46 #include "asterisk/frame.h"
47 #include "asterisk/file.h"
48 #include "asterisk/app.h"
49 #include "asterisk/astobj2.h"
50
51 /*! \brief Helper function that presents dialtone and grabs extension */
52 static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
53 {
54         int res;
55
56         /* Play the simple "transfer" prompt out and wait */
57         res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
58         ast_stopstream(chan);
59
60         /* If the person hit a DTMF digit while the above played back stick it into the buffer */
61         if (res) {
62                 exten[0] = (char)res;
63         }
64
65         /* Drop to dialtone so they can enter the extension they want to transfer to */
66         res = ast_app_dtget(chan, context, exten, exten_len, 100, 1000);
67
68         return res;
69 }
70
71 /*! \brief Helper function that creates an outgoing channel and returns it immediately */
72 static struct ast_channel *dial_transfer(struct ast_channel *caller, const char *exten, const char *context)
73 {
74         char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
75         struct ast_channel *chan;
76         int cause;
77
78         /* Fill the variable with the extension and context we want to call */
79         snprintf(destination, sizeof(destination), "%s@%s", exten, context);
80
81         /* Now we request that chan_local prepare to call the destination */
82         if (!(chan = ast_request("Local", ast_channel_nativeformats(caller), caller, destination, &cause))) {
83                 return NULL;
84         }
85
86         /* Before we actually dial out let's inherit appropriate information. */
87         ast_channel_lock_both(caller, chan);
88         ast_connected_line_copy_from_caller(ast_channel_connected(chan), ast_channel_caller(caller));
89         ast_channel_inherit_variables(caller, chan);
90         ast_channel_datastore_inherit(caller, chan);
91         ast_channel_unlock(chan);
92         ast_channel_unlock(caller);
93
94         /* Since the above worked fine now we actually call it and return the channel */
95         if (ast_call(chan, destination, 0)) {
96                 ast_hangup(chan);
97                 return NULL;
98         }
99
100         return chan;
101 }
102
103 /*! \brief Internal built in feature for blind transfers */
104 static int feature_blind_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
105 {
106         char exten[AST_MAX_EXTENSION] = "";
107         struct ast_channel *chan = NULL;
108         struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
109         const char *context = (blind_transfer && !ast_strlen_zero(blind_transfer->context) ? blind_transfer->context : ast_channel_context(bridge_channel->chan));
110
111         /* Grab the extension to transfer to */
112         if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
113                 ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
114                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
115                 return 0;
116         }
117
118         /* Get a channel that is the destination we wish to call */
119         if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
120                 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
121                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
122                 return 0;
123         }
124
125         /* This is sort of the fun part. We impart the above channel onto the bridge, and have it take our place. */
126         ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL, 1);
127
128         return 0;
129 }
130
131 /*! \brief Attended transfer feature to turn it into a threeway call */
132 static int attended_threeway_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
133 {
134         /*
135          * This is sort of abusing the depart state but in this instance
136          * it is only going to be handled by feature_attended_transfer()
137          * so it is okay.
138          */
139         ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
140         return 0;
141 }
142
143 /*! \brief Attended transfer abort feature */
144 static int attended_abort_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
145 {
146         struct ast_bridge_channel *called_bridge_channel = NULL;
147
148         /* It is possible (albeit unlikely) that the bridge channels list may change, so we have to ensure we do all of our magic while locked */
149         ao2_lock(bridge);
150
151         if (AST_LIST_FIRST(&bridge->channels) != bridge_channel) {
152                 called_bridge_channel = AST_LIST_FIRST(&bridge->channels);
153         } else {
154                 called_bridge_channel = AST_LIST_LAST(&bridge->channels);
155         }
156
157         /* Now we basically eject the other channel from the bridge. This will cause their thread to hang them up, and our own code to consider the transfer failed. */
158         if (called_bridge_channel) {
159                 ast_bridge_change_state(called_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
160         }
161
162         ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
163
164         ao2_unlock(bridge);
165
166         return 0;
167 }
168
169 /*! \brief Internal built in feature for attended transfers */
170 static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
171 {
172         char exten[AST_MAX_EXTENSION] = "";
173         struct ast_channel *chan = NULL;
174         struct ast_bridge *attended_bridge = NULL;
175         struct ast_bridge_features caller_features, called_features;
176         enum ast_bridge_channel_state attended_bridge_result;
177         struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
178         const char *context = (attended_transfer && !ast_strlen_zero(attended_transfer->context) ? attended_transfer->context : ast_channel_context(bridge_channel->chan));
179
180         /* Grab the extension to transfer to */
181         if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
182                 ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
183                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
184                 return 0;
185         }
186
187         /* Get a channel that is the destination we wish to call */
188         if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
189                 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
190                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
191                 return 0;
192         }
193
194         /* Create a bridge to use to talk to the person we are calling */
195         if (!(attended_bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) {
196                 ast_hangup(chan);
197                 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
198                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
199                 return 0;
200         }
201
202         /* Setup our called features structure so that if they hang up we immediately get thrown out of the bridge */
203         ast_bridge_features_init(&called_features);
204         ast_bridge_features_set_flag(&called_features, AST_BRIDGE_FLAG_DISSOLVE);
205
206         /* This is how this is going down, we are imparting the channel we called above into this bridge first */
207         ast_bridge_impart(attended_bridge, chan, NULL, &called_features, 1);
208
209         /* Before we join setup a features structure with the hangup option, just in case they want to use DTMF */
210         ast_bridge_features_init(&caller_features);
211         ast_bridge_features_enable(&caller_features, AST_BRIDGE_BUILTIN_HANGUP,
212                                    (attended_transfer && !ast_strlen_zero(attended_transfer->complete) ? attended_transfer->complete : "*1"), NULL);
213         ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->threeway) ? attended_transfer->threeway : "*2"),
214                                  attended_threeway_transfer, NULL, NULL);
215         ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->abort) ? attended_transfer->abort : "*3"),
216                                  attended_abort_transfer, NULL, NULL);
217
218         /* But for the caller we want to join the bridge in a blocking fashion so we don't spin around in this function doing nothing while waiting */
219         attended_bridge_result = ast_bridge_join(attended_bridge, bridge_channel->chan, NULL, &caller_features, NULL);
220
221         /* Since the above returned the caller features structure is of no more use */
222         ast_bridge_features_cleanup(&caller_features);
223
224         /* Drop the channel we are transferring to out of the above bridge since it has ended */
225         if ((attended_bridge_result != AST_BRIDGE_CHANNEL_STATE_HANGUP) && !ast_bridge_depart(attended_bridge, chan)) {
226                 /* If the user wants to turn this into a threeway transfer then do so, otherwise they take our place */
227                 if (attended_bridge_result == AST_BRIDGE_CHANNEL_STATE_DEPART) {
228                         /* We want to impart them upon the bridge and just have us return to it as normal */
229                         ast_bridge_impart(bridge, chan, NULL, NULL, 1);
230                 } else {
231                         ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL, 1);
232                 }
233         } else {
234                 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
235                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
236         }
237
238         /* Now that all channels are out of it we can destroy the bridge and the called features structure */
239         ast_bridge_features_cleanup(&called_features);
240         ast_bridge_destroy(attended_bridge);
241
242         return 0;
243 }
244
245 /*! \brief Internal built in feature for hangup */
246 static int feature_hangup(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
247 {
248         /*
249          * This is very simple, we simply change the state on the
250          * bridge_channel to force the channel out of the bridge and the
251          * core takes care of the rest.
252          */
253         ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
254         return 0;
255 }
256
257 static int unload_module(void)
258 {
259         return 0;
260 }
261
262 static int load_module(void)
263 {
264         ast_bridge_features_register(AST_BRIDGE_BUILTIN_BLINDTRANSFER, feature_blind_transfer, NULL);
265         ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, feature_attended_transfer, NULL);
266         ast_bridge_features_register(AST_BRIDGE_BUILTIN_HANGUP, feature_hangup, NULL);
267
268         /* Bump up our reference count so we can't be unloaded */
269         ast_module_ref(ast_module_info->self);
270
271         return AST_MODULE_LOAD_SUCCESS;
272 }
273
274 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Built in bridging features");