Review Board 1.7.16


[18801] - features reload does not clear old configuration and always include 700 on parkedcalls : patch

Review Request #1161 - Created April 6, 2011 and submitted

Jonathan Rose
18801
Reviewers
asterisk-dev
dvossel, rbyrant
Asterisk
This fix follows a completely different approach from the other one, so I created a new review request.
This fix involves wiping all the parking lots in the parkinglots ao2_container while purging their extensions so that they have to be rebuilt when features reload is performed.

I have a bit more confidence in this one.  It's much more additive and much less destructive than the last one.
Tested with multiple parking lots, changing multiple parking lots, with and without [general], with general and then without general and then with general again (which showed a need for an additional change), and mixes of all the above.

Diff revision 2 (Latest)

1 2
1 2

  1. /trunk/main/features.c: Loading...
/trunk/main/features.c
Revision 312991 New Change
1
/*
1
/*
2
 * Asterisk -- An open source telephony toolkit.
2
 * Asterisk -- An open source telephony toolkit.
3
 *
3
 *
4
 * Copyright (C) 1999 - 2008, Digium, Inc.
4
 * Copyright (C) 1999 - 2008, Digium, Inc.
5
 *
5
 *
6
 * Mark Spencer <markster@digium.com>
6
 * Mark Spencer <markster@digium.com>
7
 *
7
 *
8
 * See http://www.asterisk.org for more information about
8
 * See http://www.asterisk.org for more information about
9
 * the Asterisk project. Please do not directly contact
9
 * the Asterisk project. Please do not directly contact
10
 * any of the maintainers of this project for assistance;
10
 * any of the maintainers of this project for assistance;
11
 * the project provides a web site, mailing lists and IRC
11
 * the project provides a web site, mailing lists and IRC
12
 * channels for your use.
12
 * channels for your use.
13
 *
13
 *
14
 * This program is free software, distributed under the terms of
14
 * This program is free software, distributed under the terms of
15
 * the GNU General Public License Version 2. See the LICENSE file
15
 * the GNU General Public License Version 2. See the LICENSE file
16
 * at the top of the source tree.
16
 * at the top of the source tree.
17
 */
17
 */
18

    
   
18

   
19
/*! \file
19
/*! \file
20
 *
20
 *
21
 * \brief Routines implementing call features as call pickup, parking and transfer
21
 * \brief Routines implementing call features as call pickup, parking and transfer
22
 *
22
 *
23
 * \author Mark Spencer <markster@digium.com> 
23
 * \author Mark Spencer <markster@digium.com> 
24
 */
24
 */
25

    
   
25

   
26
#include "asterisk.h"
26
#include "asterisk.h"
27

    
   
27

   
28
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
28
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29

    
   
29

   
30
#include "asterisk/_private.h"
30
#include "asterisk/_private.h"
31

    
   
31

   
32
#include <pthread.h>
32
#include <pthread.h>
33
#include <signal.h>
33
#include <signal.h>
34
#include <sys/time.h>
34
#include <sys/time.h>
35
#include <sys/signal.h>
35
#include <sys/signal.h>
36
#include <netinet/in.h>
36
#include <netinet/in.h>
37

    
   
37

   
38
#include "asterisk/lock.h"
38
#include "asterisk/lock.h"
39
#include "asterisk/file.h"
39
#include "asterisk/file.h"
40
#include "asterisk/channel.h"
40
#include "asterisk/channel.h"
41
#include "asterisk/pbx.h"
41
#include "asterisk/pbx.h"
42
#include "asterisk/causes.h"
42
#include "asterisk/causes.h"
43
#include "asterisk/module.h"
43
#include "asterisk/module.h"
44
#include "asterisk/translate.h"
44
#include "asterisk/translate.h"
45
#include "asterisk/app.h"
45
#include "asterisk/app.h"
46
#include "asterisk/say.h"
46
#include "asterisk/say.h"
47
#include "asterisk/features.h"
47
#include "asterisk/features.h"
48
#include "asterisk/musiconhold.h"
48
#include "asterisk/musiconhold.h"
49
#include "asterisk/config.h"
49
#include "asterisk/config.h"
50
#include "asterisk/cli.h"
50
#include "asterisk/cli.h"
51
#include "asterisk/manager.h"
51
#include "asterisk/manager.h"
52
#include "asterisk/utils.h"
52
#include "asterisk/utils.h"
53
#include "asterisk/adsi.h"
53
#include "asterisk/adsi.h"
54
#include "asterisk/devicestate.h"
54
#include "asterisk/devicestate.h"
55
#include "asterisk/monitor.h"
55
#include "asterisk/monitor.h"
56
#include "asterisk/audiohook.h"
56
#include "asterisk/audiohook.h"
57
#include "asterisk/global_datastores.h"
57
#include "asterisk/global_datastores.h"
58
#include "asterisk/astobj2.h"
58
#include "asterisk/astobj2.h"
59
#include "asterisk/cel.h"
59
#include "asterisk/cel.h"
60
#include "asterisk/test.h"
60
#include "asterisk/test.h"
61

    
   
61

   
62
/*
62
/*
63
 * Party A - transferee
63
 * Party A - transferee
64
 * Party B - transferer
64
 * Party B - transferer
65
 * Party C - target of transfer
65
 * Party C - target of transfer
66
 *
66
 *
67
 * DTMF attended transfer works within the channel bridge.
67
 * DTMF attended transfer works within the channel bridge.
68
 * Unfortunately, when either party A or B in the channel bridge
68
 * Unfortunately, when either party A or B in the channel bridge
69
 * hangs up, that channel is not completely hung up until the
69
 * hangs up, that channel is not completely hung up until the
70
 * transfer completes.  This is a real problem depending upon
70
 * transfer completes.  This is a real problem depending upon
71
 * the channel technology involved.
71
 * the channel technology involved.
72
 *
72
 *
73
 * For chan_dahdi, the channel is crippled until the hangup is
73
 * For chan_dahdi, the channel is crippled until the hangup is
74
 * complete.  Either the channel is not useable (analog) or the
74
 * complete.  Either the channel is not useable (analog) or the
75
 * protocol disconnect messages are held up (PRI/BRI/SS7) and
75
 * protocol disconnect messages are held up (PRI/BRI/SS7) and
76
 * the media is not released.
76
 * the media is not released.
77
 *
77
 *
78
 * For chan_sip, a call limit of one is going to block that
78
 * For chan_sip, a call limit of one is going to block that
79
 * endpoint from any further calls until the hangup is complete.
79
 * endpoint from any further calls until the hangup is complete.
80
 *
80
 *
81
 * For party A this is a minor problem.  The party A channel
81
 * For party A this is a minor problem.  The party A channel
82
 * will only be in this condition while party B is dialing and
82
 * will only be in this condition while party B is dialing and
83
 * when party B and C are conferring.  The conversation between
83
 * when party B and C are conferring.  The conversation between
84
 * party B and C is expected to be a short one.  Party B is
84
 * party B and C is expected to be a short one.  Party B is
85
 * either asking a question of party C or announcing party A.
85
 * either asking a question of party C or announcing party A.
86
 * Also party A does not have much incentive to hangup at this
86
 * Also party A does not have much incentive to hangup at this
87
 * point.
87
 * point.
88
 *
88
 *
89
 * For party B this can be a major problem during a blonde
89
 * For party B this can be a major problem during a blonde
90
 * transfer.  (A blonde transfer is our term for an attended
90
 * transfer.  (A blonde transfer is our term for an attended
91
 * transfer that is converted into a blind transfer. :))  Party
91
 * transfer that is converted into a blind transfer. :))  Party
92
 * B could be the operator.  When party B hangs up, he assumes
92
 * B could be the operator.  When party B hangs up, he assumes
93
 * that he is out of the original call entirely.  The party B
93
 * that he is out of the original call entirely.  The party B
94
 * channel will be in this condition while party C is ringing,
94
 * channel will be in this condition while party C is ringing,
95
 * while attempting to recall party B, and while waiting between
95
 * while attempting to recall party B, and while waiting between
96
 * call attempts.
96
 * call attempts.
97
 *
97
 *
98
 * WARNING:
98
 * WARNING:
99
 * The ATXFER_NULL_TECH conditional is a hack to fix the
99
 * The ATXFER_NULL_TECH conditional is a hack to fix the
100
 * problem.  It will replace the party B channel technology with
100
 * problem.  It will replace the party B channel technology with
101
 * a NULL channel driver.  The consequences of this code is that
101
 * a NULL channel driver.  The consequences of this code is that
102
 * the 'h' extension will not be able to access any channel
102
 * the 'h' extension will not be able to access any channel
103
 * technology specific information like SIP statistics for the
103
 * technology specific information like SIP statistics for the
104
 * call.
104
 * call.
105
 *
105
 *
106
 * Uncomment the ATXFER_NULL_TECH define below to replace the
106
 * Uncomment the ATXFER_NULL_TECH define below to replace the
107
 * party B channel technology in the channel bridge to complete
107
 * party B channel technology in the channel bridge to complete
108
 * hanging up the channel technology.
108
 * hanging up the channel technology.
109
 */
109
 */
110
//#define ATXFER_NULL_TECH	1
110
//#define ATXFER_NULL_TECH	1
111

    
   
111

   
112
/*** DOCUMENTATION
112
/*** DOCUMENTATION
113
	<application name="Bridge" language="en_US">
113
	<application name="Bridge" language="en_US">
114
		<synopsis>
114
		<synopsis>
115
			Bridge two channels.
115
			Bridge two channels.
116
		</synopsis>
116
		</synopsis>
117
		<syntax>
117
		<syntax>
118
			<parameter name="channel" required="true">
118
			<parameter name="channel" required="true">
119
				<para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
119
				<para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
120
			</parameter>
120
			</parameter>
121
			<parameter name="options">
121
			<parameter name="options">
122
				<optionlist>
122
				<optionlist>
123
					<option name="p">
123
					<option name="p">
124
						<para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
124
						<para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
125
					</option>
125
					</option>
126
					<option name="h">
126
					<option name="h">
127
						<para>Allow the called party to hang up by sending the
127
						<para>Allow the called party to hang up by sending the
128
						<replaceable>*</replaceable> DTMF digit.</para>
128
						<replaceable>*</replaceable> DTMF digit.</para>
129
					</option>
129
					</option>
130
					<option name="H">
130
					<option name="H">
131
						<para>Allow the calling party to hang up by pressing the
131
						<para>Allow the calling party to hang up by pressing the
132
						<replaceable>*</replaceable> DTMF digit.</para>
132
						<replaceable>*</replaceable> DTMF digit.</para>
133
					</option>
133
					</option>
134
					<option name="k">
134
					<option name="k">
135
						<para>Allow the called party to enable parking of the call by sending
135
						<para>Allow the called party to enable parking of the call by sending
136
						the DTMF sequence defined for call parking in features.conf.</para>
136
						the DTMF sequence defined for call parking in features.conf.</para>
137
					</option>
137
					</option>
138
					<option name="K">
138
					<option name="K">
139
						<para>Allow the calling party to enable parking of the call by sending
139
						<para>Allow the calling party to enable parking of the call by sending
140
						 the DTMF sequence defined for call parking in features.conf.</para>
140
						 the DTMF sequence defined for call parking in features.conf.</para>
141
					</option>
141
					</option>
142
					<option name="L(x[:y][:z])">
142
					<option name="L(x[:y][:z])">
143
						<para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
143
						<para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
144
						when <replaceable>y</replaceable> ms are left. Repeat the warning every
144
						when <replaceable>y</replaceable> ms are left. Repeat the warning every
145
						<replaceable>z</replaceable> ms. The following special variables can be
145
						<replaceable>z</replaceable> ms. The following special variables can be
146
						used with this option:</para>
146
						used with this option:</para>
147
						<variablelist>
147
						<variablelist>
148
							<variable name="LIMIT_PLAYAUDIO_CALLER">
148
							<variable name="LIMIT_PLAYAUDIO_CALLER">
149
								<para>Play sounds to the caller. yes|no (default yes)</para>
149
								<para>Play sounds to the caller. yes|no (default yes)</para>
150
							</variable>
150
							</variable>
151
							<variable name="LIMIT_PLAYAUDIO_CALLEE">   
151
							<variable name="LIMIT_PLAYAUDIO_CALLEE">   
152
								<para>Play sounds to the callee. yes|no</para>
152
								<para>Play sounds to the callee. yes|no</para>
153
							</variable>
153
							</variable>
154
							<variable name="LIMIT_TIMEOUT_FILE">
154
							<variable name="LIMIT_TIMEOUT_FILE">
155
								<para>File to play when time is up.</para>
155
								<para>File to play when time is up.</para>
156
							</variable>
156
							</variable>
157
							<variable name="LIMIT_CONNECT_FILE">
157
							<variable name="LIMIT_CONNECT_FILE">
158
								<para>File to play when call begins.</para>
158
								<para>File to play when call begins.</para>
159
							</variable>
159
							</variable>
160
							<variable name="LIMIT_WARNING_FILE">
160
							<variable name="LIMIT_WARNING_FILE">
161
								<para>File to play as warning if <replaceable>y</replaceable> is
161
								<para>File to play as warning if <replaceable>y</replaceable> is
162
								defined. The default is to say the time remaining.</para>
162
								defined. The default is to say the time remaining.</para>
163
							</variable>
163
							</variable>
164
						</variablelist>
164
						</variablelist>
165
					</option>
165
					</option>
166
					<option name="S(x)">
166
					<option name="S(x)">
167
						<para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
167
						<para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
168
					</option>
168
					</option>
169
					<option name="t">
169
					<option name="t">
170
						<para>Allow the called party to transfer the calling party by sending the
170
						<para>Allow the called party to transfer the calling party by sending the
171
						DTMF sequence defined in features.conf.</para>
171
						DTMF sequence defined in features.conf.</para>
172
					</option>
172
					</option>
173
					<option name="T">
173
					<option name="T">
174
						<para>Allow the calling party to transfer the called party by sending the
174
						<para>Allow the calling party to transfer the called party by sending the
175
						DTMF sequence defined in features.conf.</para>
175
						DTMF sequence defined in features.conf.</para>
176
					</option>
176
					</option>
177
					<option name="w">
177
					<option name="w">
178
						<para>Allow the called party to enable recording of the call by sending
178
						<para>Allow the called party to enable recording of the call by sending
179
						the DTMF sequence defined for one-touch recording in features.conf.</para>
179
						the DTMF sequence defined for one-touch recording in features.conf.</para>
180
					</option>
180
					</option>
181
					<option name="W">
181
					<option name="W">
182
						<para>Allow the calling party to enable recording of the call by sending
182
						<para>Allow the calling party to enable recording of the call by sending
183
						the DTMF sequence defined for one-touch recording in features.conf.</para>
183
						the DTMF sequence defined for one-touch recording in features.conf.</para>
184
					</option>
184
					</option>
185
					<option name="x">
185
					<option name="x">
186
						<para>Cause the called party to be hung up after the bridge, instead of being
186
						<para>Cause the called party to be hung up after the bridge, instead of being
187
						restarted in the dialplan.</para>
187
						restarted in the dialplan.</para>
188
					</option>
188
					</option>
189
				</optionlist>
189
				</optionlist>
190
			</parameter>
190
			</parameter>
191
		</syntax>
191
		</syntax>
192
		<description>
192
		<description>
193
			<para>Allows the ability to bridge two channels via the dialplan.</para>
193
			<para>Allows the ability to bridge two channels via the dialplan.</para>
194
			<para>This application sets the following channel variable upon completion:</para>
194
			<para>This application sets the following channel variable upon completion:</para>
195
			<variablelist>
195
			<variablelist>
196
				<variable name="BRIDGERESULT">
196
				<variable name="BRIDGERESULT">
197
					<para>The result of the bridge attempt as a text string.</para>
197
					<para>The result of the bridge attempt as a text string.</para>
198
					<value name="SUCCESS" />
198
					<value name="SUCCESS" />
199
					<value name="FAILURE" />
199
					<value name="FAILURE" />
200
					<value name="LOOP" />
200
					<value name="LOOP" />
201
					<value name="NONEXISTENT" />
201
					<value name="NONEXISTENT" />
202
					<value name="INCOMPATIBLE" />
202
					<value name="INCOMPATIBLE" />
203
				</variable>
203
				</variable>
204
			</variablelist>
204
			</variablelist>
205
		</description>
205
		</description>
206
	</application>
206
	</application>
207
	<application name="ParkedCall" language="en_US">
207
	<application name="ParkedCall" language="en_US">
208
		<synopsis>
208
		<synopsis>
209
			Answer a parked call.
209
			Answer a parked call.
210
		</synopsis>
210
		</synopsis>
211
		<syntax>
211
		<syntax>
212
			<parameter name="exten" required="true" />
212
			<parameter name="exten" required="true" />
213
		</syntax>
213
		</syntax>
214
		<description>
214
		<description>
215
			<para>Used to connect to a parked call. This application is always
215
			<para>Used to connect to a parked call. This application is always
216
			registered internally and does not need to be explicitly added
216
			registered internally and does not need to be explicitly added
217
			into the dialplan, although you should include the <literal>parkedcalls</literal>
217
			into the dialplan, although you should include the <literal>parkedcalls</literal>
218
			context. If no extension is provided, then the first available
218
			context. If no extension is provided, then the first available
219
			parked call will be acquired.</para>
219
			parked call will be acquired.</para>
220
		</description>
220
		</description>
221
		<see-also>
221
		<see-also>
222
			<ref type="application">Park</ref>
222
			<ref type="application">Park</ref>
223
			<ref type="application">ParkAndAnnounce</ref>
223
			<ref type="application">ParkAndAnnounce</ref>
224
		</see-also>
224
		</see-also>
225
	</application>
225
	</application>
226
	<application name="Park" language="en_US">
226
	<application name="Park" language="en_US">
227
		<synopsis>
227
		<synopsis>
228
			Park yourself.
228
			Park yourself.
229
		</synopsis>
229
		</synopsis>
230
		<syntax>
230
		<syntax>
231
			<parameter name="timeout">
231
			<parameter name="timeout">
232
				<para>A custom parking timeout for this parked call. Value in milliseconds.</para>
232
				<para>A custom parking timeout for this parked call. Value in milliseconds.</para>
233
			</parameter>
233
			</parameter>
234
			<parameter name="return_context">
234
			<parameter name="return_context">
235
				<para>The context to return the call to after it times out.</para>
235
				<para>The context to return the call to after it times out.</para>
236
			</parameter>
236
			</parameter>
237
			<parameter name="return_exten">
237
			<parameter name="return_exten">
238
				<para>The extension to return the call to after it times out.</para>
238
				<para>The extension to return the call to after it times out.</para>
239
			</parameter>
239
			</parameter>
240
			<parameter name="return_priority">
240
			<parameter name="return_priority">
241
				<para>The priority to return the call to after it times out.</para>
241
				<para>The priority to return the call to after it times out.</para>
242
			</parameter>
242
			</parameter>
243
			<parameter name="options">
243
			<parameter name="options">
244
				<para>A list of options for this parked call.</para>
244
				<para>A list of options for this parked call.</para>
245
				<optionlist>
245
				<optionlist>
246
					<option name="r">
246
					<option name="r">
247
						<para>Send ringing instead of MOH to the parked call.</para>
247
						<para>Send ringing instead of MOH to the parked call.</para>
248
					</option>
248
					</option>
249
					<option name="R">
249
					<option name="R">
250
						<para>Randomize the selection of a parking space.</para>
250
						<para>Randomize the selection of a parking space.</para>
251
					</option>
251
					</option>
252
					<option name="s">
252
					<option name="s">
253
						<para>Silence announcement of the parking space number.</para>
253
						<para>Silence announcement of the parking space number.</para>
254
					</option>
254
					</option>
255
				</optionlist>
255
				</optionlist>
256
			</parameter>
256
			</parameter>
257
		</syntax>
257
		</syntax>
258
		<description>
258
		<description>
259
			<para>Used to park yourself (typically in combination with a supervised
259
			<para>Used to park yourself (typically in combination with a supervised
260
			transfer to know the parking space). This application is always
260
			transfer to know the parking space). This application is always
261
			registered internally and does not need to be explicitly added
261
			registered internally and does not need to be explicitly added
262
			into the dialplan, although you should include the <literal>parkedcalls</literal>
262
			into the dialplan, although you should include the <literal>parkedcalls</literal>
263
			context (or the context specified in <filename>features.conf</filename>).</para>
263
			context (or the context specified in <filename>features.conf</filename>).</para>
264
			<para>If you set the <variable>PARKINGLOT</variable> variable, the call will be parked
264
			<para>If you set the <variable>PARKINGLOT</variable> variable, the call will be parked
265
			in the specifed parking context. Note setting this variable overrides the <variable>
265
			in the specifed parking context. Note setting this variable overrides the <variable>
266
			PARKINGLOT</variable> set by the <literal>CHANNEL</literal> function.</para>
266
			PARKINGLOT</variable> set by the <literal>CHANNEL</literal> function.</para>
267
			<para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
267
			<para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
268
			parking context, Park() will park the call on that extension, unless
268
			parking context, Park() will park the call on that extension, unless
269
			it already exists. In that case, execution will continue at next priority.</para>
269
			it already exists. In that case, execution will continue at next priority.</para>
270
			<para>If you set the <variable>PARKINGLOT</variable> variable, Park() will park the call
270
			<para>If you set the <variable>PARKINGLOT</variable> variable, Park() will park the call
271
			in that parkinglot.</para>
271
			in that parkinglot.</para>
272
			<para>If you set the <variable>PARKINGDYNAMIC</variable> variable, this parkinglot from features.conf
272
			<para>If you set the <variable>PARKINGDYNAMIC</variable> variable, this parkinglot from features.conf
273
			will be used as template for the newly created dynamic lot.</para>
273
			will be used as template for the newly created dynamic lot.</para>
274
			<para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable the newly created dynamic
274
			<para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable the newly created dynamic
275
			parking lot will use this context.</para>
275
			parking lot will use this context.</para>
276
			<para>If you set the <variable>PARKINGDYNPOS</variable> variable the newly created dynamic parkinglot
276
			<para>If you set the <variable>PARKINGDYNPOS</variable> variable the newly created dynamic parkinglot
277
			will use those parking postitions.</para>
277
			will use those parking postitions.</para>
278
		</description>
278
		</description>
279
		<see-also>
279
		<see-also>
280
			<ref type="application">ParkAndAnnounce</ref>
280
			<ref type="application">ParkAndAnnounce</ref>
281
			<ref type="application">ParkedCall</ref>
281
			<ref type="application">ParkedCall</ref>
282
		</see-also>
282
		</see-also>
283
	</application>
283
	</application>
284
	<manager name="ParkedCalls" language="en_US">
284
	<manager name="ParkedCalls" language="en_US">
285
		<synopsis>
285
		<synopsis>
286
			List parked calls.
286
			List parked calls.
287
		</synopsis>
287
		</synopsis>
288
		<syntax>
288
		<syntax>
289
			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
289
			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
290
		</syntax>
290
		</syntax>
291
		<description>
291
		<description>
292
			<para>List parked calls.</para>
292
			<para>List parked calls.</para>
293
		</description>
293
		</description>
294
	</manager>
294
	</manager>
295
	<manager name="Park" language="en_US">
295
	<manager name="Park" language="en_US">
296
		<synopsis>
296
		<synopsis>
297
			Park a channel.
297
			Park a channel.
298
		</synopsis>
298
		</synopsis>
299
		<syntax>
299
		<syntax>
300
			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
300
			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
301
			<parameter name="Channel" required="true">
301
			<parameter name="Channel" required="true">
302
				<para>Channel name to park.</para>
302
				<para>Channel name to park.</para>
303
			</parameter>
303
			</parameter>
304
			<parameter name="Channel2" required="true">
304
			<parameter name="Channel2" required="true">
305
				<para>Channel to announce park info to (and return to if timeout).</para>
305
				<para>Channel to announce park info to (and return to if timeout).</para>
306
			</parameter>
306
			</parameter>
307
			<parameter name="Timeout">
307
			<parameter name="Timeout">
308
				<para>Number of milliseconds to wait before callback.</para>
308
				<para>Number of milliseconds to wait before callback.</para>
309
			</parameter>
309
			</parameter>
310
			<parameter name="Parkinglot">
310
			<parameter name="Parkinglot">
311
				<para>Parking lot to park channel in.</para>
311
				<para>Parking lot to park channel in.</para>
312
			</parameter>
312
			</parameter>
313
		</syntax>
313
		</syntax>
314
		<description>
314
		<description>
315
			<para>Park a channel.</para>
315
			<para>Park a channel.</para>
316
		</description>
316
		</description>
317
	</manager>
317
	</manager>
318
	<manager name="Bridge" language="en_US">
318
	<manager name="Bridge" language="en_US">
319
		<synopsis>
319
		<synopsis>
320
			Bridge two channels already in the PBX.
320
			Bridge two channels already in the PBX.
321
		</synopsis>
321
		</synopsis>
322
		<syntax>
322
		<syntax>
323
			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
323
			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
324
			<parameter name="Channel1" required="true">
324
			<parameter name="Channel1" required="true">
325
				<para>Channel to Bridge to Channel2.</para>
325
				<para>Channel to Bridge to Channel2.</para>
326
			</parameter>
326
			</parameter>
327
			<parameter name="Channel2" required="true">
327
			<parameter name="Channel2" required="true">
328
				<para>Channel to Bridge to Channel1.</para>
328
				<para>Channel to Bridge to Channel1.</para>
329
			</parameter>
329
			</parameter>
330
			<parameter name="Tone">
330
			<parameter name="Tone">
331
				<para>Play courtesy tone to Channel 2.</para>
331
				<para>Play courtesy tone to Channel 2.</para>
332
				<enumlist>
332
				<enumlist>
333
					<enum name="yes" />
333
					<enum name="yes" />
334
					<enum name="no" />
334
					<enum name="no" />
335
				</enumlist>
335
				</enumlist>
336
			</parameter>
336
			</parameter>
337
		</syntax>
337
		</syntax>
338
		<description>
338
		<description>
339
			<para>Bridge together two channels already in the PBX.</para>
339
			<para>Bridge together two channels already in the PBX.</para>
340
		</description>
340
		</description>
341
	</manager>
341
	</manager>
342
 ***/
342
 ***/
343

    
   
343

   
344
#define DEFAULT_PARK_TIME							45000	/*!< ms */
344
#define DEFAULT_PARK_TIME							45000	/*!< ms */
345
#define DEFAULT_PARK_EXTENSION						"700"
345
#define DEFAULT_PARK_EXTENSION						"700"
346
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT				3000	/*!< ms */
346
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT				3000	/*!< ms */
347
#define DEFAULT_FEATURE_DIGIT_TIMEOUT				1000	/*!< ms */
347
#define DEFAULT_FEATURE_DIGIT_TIMEOUT				1000	/*!< ms */
348
#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER	15000	/*!< ms */
348
#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER	15000	/*!< ms */
349
#define DEFAULT_ATXFER_DROP_CALL					0		/*!< Do not drop call. */
349
#define DEFAULT_ATXFER_DROP_CALL					0		/*!< Do not drop call. */
350
#define DEFAULT_ATXFER_LOOP_DELAY					10000	/*!< ms */
350
#define DEFAULT_ATXFER_LOOP_DELAY					10000	/*!< ms */
351
#define DEFAULT_ATXFER_CALLBACK_RETRIES				2
351
#define DEFAULT_ATXFER_CALLBACK_RETRIES				2
352

    
   
352

   
353
#define AST_MAX_WATCHERS 256
353
#define AST_MAX_WATCHERS 256
354
#define MAX_DIAL_FEATURE_OPTIONS 30
354
#define MAX_DIAL_FEATURE_OPTIONS 30
355

    
   
355

   
356
struct feature_group_exten {
356
struct feature_group_exten {
357
	AST_LIST_ENTRY(feature_group_exten) entry;
357
	AST_LIST_ENTRY(feature_group_exten) entry;
358
	AST_DECLARE_STRING_FIELDS(
358
	AST_DECLARE_STRING_FIELDS(
359
		AST_STRING_FIELD(exten);
359
		AST_STRING_FIELD(exten);
360
	);
360
	);
361
	struct ast_call_feature *feature;
361
	struct ast_call_feature *feature;
362
};
362
};
363

    
   
363

   
364
struct feature_group {
364
struct feature_group {
365
	AST_LIST_ENTRY(feature_group) entry;
365
	AST_LIST_ENTRY(feature_group) entry;
366
	AST_DECLARE_STRING_FIELDS(
366
	AST_DECLARE_STRING_FIELDS(
367
		AST_STRING_FIELD(gname);
367
		AST_STRING_FIELD(gname);
368
	);
368
	);
369
	AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
369
	AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
370
};
370
};
371

    
   
371

   
372
static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
372
static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
373

    
   
373

   
374
typedef enum {
374
typedef enum {
375
	FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
375
	FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
376
	FEATURE_INTERPRET_DO,     /* Used by feature_interpret */
376
	FEATURE_INTERPRET_DO,     /* Used by feature_interpret */
377
	FEATURE_INTERPRET_CHECK,  /* Used by feature_check */
377
	FEATURE_INTERPRET_CHECK,  /* Used by feature_check */
378
} feature_interpret_op;
378
} feature_interpret_op;
379

    
   
379

   
380
static char *parkedcall = "ParkedCall";
380
static char *parkedcall = "ParkedCall";
381

    
   
381

   
382
static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
382
static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
383

    
   
383

   
384
/*! \brief Description of one parked call, added to a list while active, then removed.
384
/*! \brief Description of one parked call, added to a list while active, then removed.
385
	The list belongs to a parkinglot 
385
	The list belongs to a parkinglot 
386
*/
386
*/
387
struct parkeduser {
387
struct parkeduser {
388
	struct ast_channel *chan;                   /*!< Parking channel */
388
	struct ast_channel *chan;                   /*!< Parking channel */
389
	struct timeval start;                       /*!< Time the parking started */
389
	struct timeval start;                       /*!< Time the parking started */
390
	int parkingnum;                             /*!< Parking lot */
390
	int parkingnum;                             /*!< Parking lot */
391
	char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
391
	char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
392
	char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
392
	char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
393
	char exten[AST_MAX_EXTENSION];
393
	char exten[AST_MAX_EXTENSION];
394
	int priority;
394
	int priority;
395
	int parkingtime;                            /*!< Maximum length in parking lot before return */
395
	int parkingtime;                            /*!< Maximum length in parking lot before return */
396
	unsigned int notquiteyet:1;
396
	unsigned int notquiteyet:1;
397
	unsigned int options_specified:1;
397
	unsigned int options_specified:1;
398
	char peername[1024];
398
	char peername[1024];
399
	unsigned char moh_trys;
399
	unsigned char moh_trys;
400
	struct ast_parkinglot *parkinglot;
400
	struct ast_parkinglot *parkinglot;
401
	AST_LIST_ENTRY(parkeduser) list;
401
	AST_LIST_ENTRY(parkeduser) list;
402
};
402
};
403

    
   
403

   
404
/*! \brief Structure for parking lots which are put in a container. */
404
/*! \brief Structure for parking lots which are put in a container. */
405
struct ast_parkinglot {
405
struct ast_parkinglot {
406
	char name[AST_MAX_CONTEXT];
406
	char name[AST_MAX_CONTEXT];
407
	char parkext[AST_MAX_EXTENSION];				/*!< Parkingextension */
407
	char parkext[AST_MAX_EXTENSION];				/*!< Parkingextension */
408
	char parking_con[AST_MAX_EXTENSION];		/*!< Context for which parking is made accessible */
408
	char parking_con[AST_MAX_EXTENSION];		/*!< Context for which parking is made accessible */
409
	char parking_con_dial[AST_MAX_EXTENSION];	/*!< Context for dialback for parking (KLUDGE) */
409
	char parking_con_dial[AST_MAX_EXTENSION];	/*!< Context for dialback for parking (KLUDGE) */
410
	int parking_start;				/*!< First available extension for parking */
410
	int parking_start;				/*!< First available extension for parking */
411
	int parking_stop;				/*!< Last available extension for parking */
411
	int parking_stop;				/*!< Last available extension for parking */
412
	int parking_offset;
412
	int parking_offset;
413
	int parkfindnext;
413
	int parkfindnext;
414
	int parkingtime;				/*!< Default parking time */
414
	int parkingtime;				/*!< Default parking time */
415
	char mohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
415
	char mohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
416
	int parkaddhints;                               /*!< Add parking hints automatically */
416
	int parkaddhints;                               /*!< Add parking hints automatically */
417
	int parkedcalltransfers;                        /*!< Enable DTMF based transfers on bridge when picking up parked calls */
417
	int parkedcalltransfers;                        /*!< Enable DTMF based transfers on bridge when picking up parked calls */
418
	int parkedcallreparking;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
418
	int parkedcallreparking;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
419
	int parkedcallhangup;                           /*!< Enable DTMF based hangup on a bridge when pickup up parked calls */
419
	int parkedcallhangup;                           /*!< Enable DTMF based hangup on a bridge when pickup up parked calls */
420
	int parkedcallrecording;                        /*!< Enable DTMF based recording on a bridge when picking up parked calls */
420
	int parkedcallrecording;                        /*!< Enable DTMF based recording on a bridge when picking up parked calls */
421
	unsigned short the_mark:1;                      /*!< Used during reloads, that which bears the_mark shall be deleted! */
421
	unsigned short the_mark:1;                      /*!< Used during reloads, that which bears the_mark shall be deleted! */
422
	AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
422
	AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
423
};
423
};
424

    
   
424

   
425
/*! \brief The list of parking lots configured. Always at least one  - the default parking lot */
425
/*! \brief The list of parking lots configured. Always at least one  - the default parking lot */
426
static struct ao2_container *parkinglots;
426
static struct ao2_container *parkinglots;
427
 
427
 
428
struct ast_parkinglot *default_parkinglot;
428
struct ast_parkinglot *default_parkinglot;
429
char parking_ext[AST_MAX_EXTENSION];            /*!< Extension you type to park the call */
429
char parking_ext[AST_MAX_EXTENSION];            /*!< Extension you type to park the call */
430

    
   
430

   
431
static char courtesytone[256];                             /*!< Courtesy tone */
431
static char courtesytone[256];                             /*!< Courtesy tone */
432
static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
432
static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
433
static int parkeddynamic = 0;                              /*!< Enable creation of parkinglots dynamically */
433
static int parkeddynamic = 0;                              /*!< Enable creation of parkinglots dynamically */
434
static char xfersound[256];                                /*!< Call transfer sound */
434
static char xfersound[256];                                /*!< Call transfer sound */
435
static char xferfailsound[256];                            /*!< Call transfer failure sound */
435
static char xferfailsound[256];                            /*!< Call transfer failure sound */
436
static char pickupsound[256];                              /*!< Pickup sound */
436
static char pickupsound[256];                              /*!< Pickup sound */
437
static char pickupfailsound[256];                          /*!< Pickup failure sound */
437
static char pickupfailsound[256];                          /*!< Pickup failure sound */
438

    
   
438

   
439
static int adsipark;
439
static int adsipark;
440

    
   
440

   
441
static int transferdigittimeout;
441
static int transferdigittimeout;
442
static int featuredigittimeout;
442
static int featuredigittimeout;
443
static int comebacktoorigin = 1;
443
static int comebacktoorigin = 1;
444

    
   
444

   
445
static int atxfernoanswertimeout;
445
static int atxfernoanswertimeout;
446
static unsigned int atxferdropcall;
446
static unsigned int atxferdropcall;
447
static unsigned int atxferloopdelay;
447
static unsigned int atxferloopdelay;
448
static unsigned int atxfercallbackretries;
448
static unsigned int atxfercallbackretries;
449

    
   
449

   
450
static char *registrar = "features";		   /*!< Registrar for operations */
450
static char *registrar = "features";		   /*!< Registrar for operations */
451

    
   
451

   
452
/* module and CLI command definitions */
452
/* module and CLI command definitions */
453
static char *parkcall = PARK_APP_NAME;
453
static char *parkcall = PARK_APP_NAME;
454

    
   
454

   
455
static struct ast_app *monitor_app = NULL;
455
static struct ast_app *monitor_app = NULL;
456
static int monitor_ok = 1;
456
static int monitor_ok = 1;
457

    
   
457

   
458
static struct ast_app *mixmonitor_app = NULL;
458
static struct ast_app *mixmonitor_app = NULL;
459
static int mixmonitor_ok = 1;
459
static int mixmonitor_ok = 1;
460

    
   
460

   
461
static struct ast_app *stopmixmonitor_app = NULL;
461
static struct ast_app *stopmixmonitor_app = NULL;
462
static int stopmixmonitor_ok = 1;
462
static int stopmixmonitor_ok = 1;
463

    
   
463

   
464
static pthread_t parking_thread;
464
static pthread_t parking_thread;
465
struct ast_dial_features {
465
struct ast_dial_features {
466
	struct ast_flags features_caller;
466
	struct ast_flags features_caller;
467
	struct ast_flags features_callee;
467
	struct ast_flags features_callee;
468
	int is_caller;
468
	int is_caller;
469
};
469
};
470

    
   
470

   
471
#if defined(ATXFER_NULL_TECH)
471
#if defined(ATXFER_NULL_TECH)
472
static struct ast_frame *null_read(struct ast_channel *chan)
472
static struct ast_frame *null_read(struct ast_channel *chan)
473
{
473
{
474
	/* Hangup channel. */
474
	/* Hangup channel. */
475
	return NULL;
475
	return NULL;
476
}
476
}
477

    
   
477

   
478
static struct ast_frame *null_exception(struct ast_channel *chan)
478
static struct ast_frame *null_exception(struct ast_channel *chan)
479
{
479
{
480
	/* Hangup channel. */
480
	/* Hangup channel. */
481
	return NULL;
481
	return NULL;
482
}
482
}
483

    
   
483

   
484
static int null_write(struct ast_channel *chan, struct ast_frame *frame)
484
static int null_write(struct ast_channel *chan, struct ast_frame *frame)
485
{
485
{
486
	/* Hangup channel. */
486
	/* Hangup channel. */
487
	return -1;
487
	return -1;
488
}
488
}
489

    
   
489

   
490
static int null_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
490
static int null_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
491
{
491
{
492
	/* No problem fixing up the channel. */
492
	/* No problem fixing up the channel. */
493
	return 0;
493
	return 0;
494
}
494
}
495

    
   
495

   
496
static int null_hangup(struct ast_channel *chan)
496
static int null_hangup(struct ast_channel *chan)
497
{
497
{
498
	chan->tech_pvt = NULL;
498
	chan->tech_pvt = NULL;
499
	return 0;
499
	return 0;
500
}
500
}
501

    
   
501

   
502
static const struct ast_channel_tech null_tech = {
502
static const struct ast_channel_tech null_tech = {
503
	.type = "NULL",
503
	.type = "NULL",
504
	.description = "NULL channel driver for atxfer",
504
	.description = "NULL channel driver for atxfer",
505
	.capabilities = -1,
505
	.capabilities = -1,
506
	.read = null_read,
506
	.read = null_read,
507
	.exception = null_exception,
507
	.exception = null_exception,
508
	.write = null_write,
508
	.write = null_write,
509
	.fixup = null_fixup,
509
	.fixup = null_fixup,
510
	.hangup = null_hangup,
510
	.hangup = null_hangup,
511
};
511
};
512
#endif	/* defined(ATXFER_NULL_TECH) */
512
#endif	/* defined(ATXFER_NULL_TECH) */
513

    
   
513

   
514
#if defined(ATXFER_NULL_TECH)
514
#if defined(ATXFER_NULL_TECH)
515
/*!
515
/*!
516
 * \internal
516
 * \internal
517
 * \brief Set the channel technology to the NULL technology.
517
 * \brief Set the channel technology to the NULL technology.
518
 *
518
 *
519
 * \param chan Channel to change technology.
519
 * \param chan Channel to change technology.
520
 *
520
 *
521
 * \return Nothing
521
 * \return Nothing
522
 */
522
 */
523
static void set_null_chan_tech(struct ast_channel *chan)
523
static void set_null_chan_tech(struct ast_channel *chan)
524
{
524
{
525
	int idx;
525
	int idx;
526

    
   
526

   
527
	ast_channel_lock(chan);
527
	ast_channel_lock(chan);
528

    
   
528

   
529
	/* Hangup the channel's physical side */
529
	/* Hangup the channel's physical side */
530
	if (chan->tech->hangup) {
530
	if (chan->tech->hangup) {
531
		chan->tech->hangup(chan);
531
		chan->tech->hangup(chan);
532
	}
532
	}
533
	if (chan->tech_pvt) {
533
	if (chan->tech_pvt) {
534
		ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n",
534
		ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n",
535
			chan->name);
535
			chan->name);
536
		ast_free(chan->tech_pvt);
536
		ast_free(chan->tech_pvt);
537
		chan->tech_pvt = NULL;
537
		chan->tech_pvt = NULL;
538
	}
538
	}
539

    
   
539

   
540
	/* Install the NULL technology and wake up anyone waiting on it. */
540
	/* Install the NULL technology and wake up anyone waiting on it. */
541
	chan->tech = &null_tech;
541
	chan->tech = &null_tech;
542
	for (idx = 0; idx < AST_MAX_FDS; ++idx) {
542
	for (idx = 0; idx < AST_MAX_FDS; ++idx) {
543
		switch (idx) {
543
		switch (idx) {
544
		case AST_ALERT_FD:
544
		case AST_ALERT_FD:
545
		case AST_TIMING_FD:
545
		case AST_TIMING_FD:
546
		case AST_GENERATOR_FD:
546
		case AST_GENERATOR_FD:
547
			/* Don't clear these fd's. */
547
			/* Don't clear these fd's. */
548
			break;
548
			break;
549
		default:
549
		default:
550
			ast_channel_set_fd(chan, idx, -1);
550
			ast_channel_set_fd(chan, idx, -1);
551
			break;
551
			break;
552
		}
552
		}
553
	}
553
	}
554
	ast_queue_frame(chan, &ast_null_frame);
554
	ast_queue_frame(chan, &ast_null_frame);
555

    
   
555

   
556
	ast_channel_unlock(chan);
556
	ast_channel_unlock(chan);
557
}
557
}
558
#endif	/* defined(ATXFER_NULL_TECH) */
558
#endif	/* defined(ATXFER_NULL_TECH) */
559

    
   
559

   
560
#if defined(ATXFER_NULL_TECH)
560
#if defined(ATXFER_NULL_TECH)
561
/*!
561
/*!
562
 * \internal
562
 * \internal
563
 * \brief Set the channel name to something unique.
563
 * \brief Set the channel name to something unique.
564
 *
564
 *
565
 * \param chan Channel to change name.
565
 * \param chan Channel to change name.
566
 *
566
 *
567
 * \return Nothing
567
 * \return Nothing
568
 */
568
 */
569
static void set_new_chan_name(struct ast_channel *chan)
569
static void set_new_chan_name(struct ast_channel *chan)
570
{
570
{
571
	static int seq_num_last;
571
	static int seq_num_last;
572
	int seq_num;
572
	int seq_num;
573
	int len;
573
	int len;
574
	char *chan_name;
574
	char *chan_name;
575
	char dummy[1];
575
	char dummy[1];
576

    
   
576

   
577
	/* Create the new channel name string. */
577
	/* Create the new channel name string. */
578
	ast_channel_lock(chan);
578
	ast_channel_lock(chan);
579
	seq_num = ast_atomic_fetchadd_int(&seq_num_last, +1);
579
	seq_num = ast_atomic_fetchadd_int(&seq_num_last, +1);
580
	len = snprintf(dummy, sizeof(dummy), "%s<XFER_%x>", chan->name, seq_num) + 1;
580
	len = snprintf(dummy, sizeof(dummy), "%s<XFER_%x>", chan->name, seq_num) + 1;
581
	chan_name = alloca(len);
581
	chan_name = alloca(len);
582
	snprintf(chan_name, len, "%s<XFER_%x>", chan->name, seq_num);
582
	snprintf(chan_name, len, "%s<XFER_%x>", chan->name, seq_num);
583
	ast_channel_unlock(chan);
583
	ast_channel_unlock(chan);
584

    
   
584

   
585
	ast_change_name(chan, chan_name);
585
	ast_change_name(chan, chan_name);
586
}
586
}
587
#endif	/* defined(ATXFER_NULL_TECH) */
587
#endif	/* defined(ATXFER_NULL_TECH) */
588

    
   
588

   
589
static void *dial_features_duplicate(void *data)
589
static void *dial_features_duplicate(void *data)
590
{
590
{
591
	struct ast_dial_features *df = data, *df_copy;
591
	struct ast_dial_features *df = data, *df_copy;
592
 
592
 
593
 	if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
593
 	if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
594
 		return NULL;
594
 		return NULL;
595
 	}
595
 	}
596
 
596
 
597
 	memcpy(df_copy, df, sizeof(*df));
597
 	memcpy(df_copy, df, sizeof(*df));
598
 
598
 
599
 	return df_copy;
599
 	return df_copy;
600
}
600
}
601

    
   
601

   
602
static void dial_features_destroy(void *data)
602
static void dial_features_destroy(void *data)
603
{
603
{
604
 	struct ast_dial_features *df = data;
604
 	struct ast_dial_features *df = data;
605
 	if (df) {
605
 	if (df) {
606
 		ast_free(df);
606
 		ast_free(df);
607
 	}
607
 	}
608
}
608
}
609

    
   
609

   
610
static const struct ast_datastore_info dial_features_info = {
610
static const struct ast_datastore_info dial_features_info = {
611
 	.type = "dial-features",
611
 	.type = "dial-features",
612
 	.destroy = dial_features_destroy,
612
 	.destroy = dial_features_destroy,
613
 	.duplicate = dial_features_duplicate,
613
 	.duplicate = dial_features_duplicate,
614
 };
614
 };
615
 
615
 
616
/* Forward declarations */
616
/* Forward declarations */
617
static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
617
static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
618
static void parkinglot_unref(struct ast_parkinglot *parkinglot);
618
static void parkinglot_unref(struct ast_parkinglot *parkinglot);
619
static void parkinglot_destroy(void *obj);
619
static void parkinglot_destroy(void *obj);
620
int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *fs);
620
int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *fs);
621
struct ast_parkinglot *find_parkinglot(const char *name);
621
struct ast_parkinglot *find_parkinglot(const char *name);
622
static struct ast_parkinglot *create_parkinglot(const char *name);
622
static struct ast_parkinglot *create_parkinglot(const char *name);
623
static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
623
static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
624

    
   
624

   
625
static int find_parkinglot_by_position_cb(void *obj, void *args, int flags)
625
static int find_parkinglot_by_position_cb(void *obj, void *args, int flags)
626
{
626
{
627
	struct ast_parkinglot *parkinglot = obj;
627
	struct ast_parkinglot *parkinglot = obj;
628
	int *parkpos = args;
628
	int *parkpos = args;
629

    
   
629

   
630
	if (*parkpos >= parkinglot->parking_start && *parkpos <= parkinglot->parking_stop) {
630
	if (*parkpos >= parkinglot->parking_start && *parkpos <= parkinglot->parking_stop) {
631
		return CMP_MATCH | CMP_STOP;
631
		return CMP_MATCH | CMP_STOP;
632
	}
632
	}
633

    
   
633

   
634
	return 0;
634
	return 0;
635
}
635
}
636

    
   
636

   
637
static int find_parkinglot_by_exten_cb(void *obj, void *args, int flags)
637
static int find_parkinglot_by_exten_cb(void *obj, void *args, int flags)
638
{
638
{
639
	struct ast_parkinglot *parkinglot = obj;
639
	struct ast_parkinglot *parkinglot = obj;
640
	const char *parkext = args;
640
	const char *parkext = args;
641

    
   
641

   
642
	if (!strcmp(parkinglot->parkext, parkext)) {
642
	if (!strcmp(parkinglot->parkext, parkext)) {
643
		return CMP_MATCH | CMP_STOP;
643
		return CMP_MATCH | CMP_STOP;
644
	}
644
	}
645

    
   
645

   
646
	return 0;
646
	return 0;
647
}
647
}
648

    
   
648

   
649
int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
649
int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
650
{
650
{
651
	struct ast_exten *exten;
651
	struct ast_exten *exten;
652
	struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
652
	struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
653
	const char *app_at_exten;
653
	const char *app_at_exten;
654

    
   
654

   
655
	exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL, E_MATCH);
655
	exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL, E_MATCH);
656
	if (!exten) {
656
	if (!exten) {
657
		return 0;
657
		return 0;
658
	}
658
	}
659

    
   
659

   
660
	app_at_exten = ast_get_extension_app(exten);
660
	app_at_exten = ast_get_extension_app(exten);
661
	if (!app_at_exten || strcmp(PARK_APP_NAME, app_at_exten)) {
661
	if (!app_at_exten || strcmp(PARK_APP_NAME, app_at_exten)) {
662
		return 0;
662
		return 0;
663
	}
663
	}
664

    
   
664

   
665
	return 1;
665
	return 1;
666
}
666
}
667

    
   
667

   
668
const char *ast_pickup_ext(void)
668
const char *ast_pickup_ext(void)
669
{
669
{
670
	return pickup_ext;
670
	return pickup_ext;
671
}
671
}
672

    
   
672

   
673
struct ast_bridge_thread_obj 
673
struct ast_bridge_thread_obj 
674
{
674
{
675
	struct ast_bridge_config bconfig;
675
	struct ast_bridge_config bconfig;
676
	struct ast_channel *chan;
676
	struct ast_channel *chan;
677
	struct ast_channel *peer;
677
	struct ast_channel *peer;
678
	unsigned int return_to_pbx:1;
678
	unsigned int return_to_pbx:1;
679
};
679
};
680

    
   
680

   
681
static int parkinglot_hash_cb(const void *obj, const int flags)
681
static int parkinglot_hash_cb(const void *obj, const int flags)
682
{
682
{
683
	const struct ast_parkinglot *parkinglot = obj;
683
	const struct ast_parkinglot *parkinglot = obj;
684

    
   
684

   
685
	return ast_str_case_hash(parkinglot->name);
685
	return ast_str_case_hash(parkinglot->name);
686
}
686
}
687

    
   
687

   
688
static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
688
static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
689
{
689
{
690
	struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
690
	struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
691

    
   
691

   
692
	return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
692
	return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
693
}
693
}
694

    
   
694

   
695
/*!
695
/*!
696
 * \brief store context, extension and priority 
696
 * \brief store context, extension and priority 
697
 * \param chan, context, ext, pri
697
 * \param chan, context, ext, pri
698
*/
698
*/
699
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
699
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
700
{
700
{
701
	ast_copy_string(chan->context, context, sizeof(chan->context));
701
	ast_copy_string(chan->context, context, sizeof(chan->context));
702
	ast_copy_string(chan->exten, ext, sizeof(chan->exten));
702
	ast_copy_string(chan->exten, ext, sizeof(chan->exten));
703
	chan->priority = pri;
703
	chan->priority = pri;
704
}
704
}
705

    
   
705

   
706
/*!
706
/*!
707
 * \brief Check goto on transfer
707
 * \brief Check goto on transfer
708
 * \param chan
708
 * \param chan
709
 *
709
 *
710
 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
710
 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
711
 * When found make sure the types are compatible. Check if channel is valid
711
 * When found make sure the types are compatible. Check if channel is valid
712
 * if so start the new channel else hangup the call. 
712
 * if so start the new channel else hangup the call. 
713
*/
713
*/
714
static void check_goto_on_transfer(struct ast_channel *chan) 
714
static void check_goto_on_transfer(struct ast_channel *chan) 
715
{
715
{
716
	struct ast_channel *xferchan;
716
	struct ast_channel *xferchan;
717
	const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
717
	const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
718
	char *x, *goto_on_transfer;
718
	char *x, *goto_on_transfer;
719
	struct ast_frame *f;
719
	struct ast_frame *f;
720

    
   
720

   
721
	if (ast_strlen_zero(val))
721
	if (ast_strlen_zero(val))
722
		return;
722
		return;
723

    
   
723

   
724
	goto_on_transfer = ast_strdupa(val);
724
	goto_on_transfer = ast_strdupa(val);
725

    
   
725

   
726
	if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0, "%s", chan->name)))
726
	if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0, "%s", chan->name)))
727
		return;
727
		return;
728

    
   
728

   
729
	for (x = goto_on_transfer; x && *x; x++) {
729
	for (x = goto_on_transfer; x && *x; x++) {
730
		if (*x == '^')
730
		if (*x == '^')
731
			*x = ',';
731
			*x = ',';
732
	}
732
	}
733
	/* Make formats okay */
733
	/* Make formats okay */
734
	xferchan->readformat = chan->readformat;
734
	xferchan->readformat = chan->readformat;
735
	xferchan->writeformat = chan->writeformat;
735
	xferchan->writeformat = chan->writeformat;
736
	ast_channel_masquerade(xferchan, chan);
736
	ast_channel_masquerade(xferchan, chan);
737
	ast_parseable_goto(xferchan, goto_on_transfer);
737
	ast_parseable_goto(xferchan, goto_on_transfer);
738
	xferchan->_state = AST_STATE_UP;
738
	xferchan->_state = AST_STATE_UP;
739
	ast_clear_flag(xferchan, AST_FLAGS_ALL);	
739
	ast_clear_flag(xferchan, AST_FLAGS_ALL);	
740
	ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
740
	ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
741
	if ((f = ast_read(xferchan))) {
741
	if ((f = ast_read(xferchan))) {
742
		ast_frfree(f);
742
		ast_frfree(f);
743
		f = NULL;
743
		f = NULL;
744
		ast_pbx_start(xferchan);
744
		ast_pbx_start(xferchan);
745
	} else {
745
	} else {
746
		ast_hangup(xferchan);
746
		ast_hangup(xferchan);
747
	}
747
	}
748
}
748
}
749

    
   
749

   
750
static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
750
static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
751
	const char *caller_name, struct ast_channel *requestor,
751
	const char *caller_name, struct ast_channel *requestor,
752
	struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data,
752
	struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data,
753
	int timeout, int *outstate, const char *language);
753
	int timeout, int *outstate, const char *language);
754

    
   
754

   
755
/*!
755
/*!
756
 * \brief bridge the call 
756
 * \brief bridge the call 
757
 * \param data thread bridge.
757
 * \param data thread bridge.
758
 *
758
 *
759
 * Set Last Data for respective channels, reset cdr for channels
759
 * Set Last Data for respective channels, reset cdr for channels
760
 * bridge call, check if we're going back to dialplan
760
 * bridge call, check if we're going back to dialplan
761
 * if not hangup both legs of the call
761
 * if not hangup both legs of the call
762
*/
762
*/
763
static void *bridge_call_thread(void *data)
763
static void *bridge_call_thread(void *data)
764
{
764
{
765
	struct ast_bridge_thread_obj *tobj = data;
765
	struct ast_bridge_thread_obj *tobj = data;
766
	int res;
766
	int res;
767

    
   
767

   
768
	tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
768
	tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
769
	tobj->chan->data = tobj->peer->name;
769
	tobj->chan->data = tobj->peer->name;
770
	tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
770
	tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
771
	tobj->peer->data = tobj->chan->name;
771
	tobj->peer->data = tobj->chan->name;
772

    
   
772

   
773
	ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
773
	ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
774

    
   
774

   
775
	if (tobj->return_to_pbx) {
775
	if (tobj->return_to_pbx) {
776
		if (!ast_check_hangup(tobj->peer)) {
776
		if (!ast_check_hangup(tobj->peer)) {
777
			ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
777
			ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
778
			res = ast_pbx_start(tobj->peer);
778
			res = ast_pbx_start(tobj->peer);
779
			if (res != AST_PBX_SUCCESS)
779
			if (res != AST_PBX_SUCCESS)
780
				ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
780
				ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
781
		} else
781
		} else
782
			ast_hangup(tobj->peer);
782
			ast_hangup(tobj->peer);
783
		if (!ast_check_hangup(tobj->chan)) {
783
		if (!ast_check_hangup(tobj->chan)) {
784
			ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
784
			ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
785
			res = ast_pbx_start(tobj->chan);
785
			res = ast_pbx_start(tobj->chan);
786
			if (res != AST_PBX_SUCCESS)
786
			if (res != AST_PBX_SUCCESS)
787
				ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
787
				ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
788
		} else
788
		} else
789
			ast_hangup(tobj->chan);
789
			ast_hangup(tobj->chan);
790
	} else {
790
	} else {
791
		ast_hangup(tobj->chan);
791
		ast_hangup(tobj->chan);
792
		ast_hangup(tobj->peer);
792
		ast_hangup(tobj->peer);
793
	}
793
	}
794

    
   
794

   
795
	ast_free(tobj);
795
	ast_free(tobj);
796

    
   
796

   
797
	return NULL;
797
	return NULL;
798
}
798
}
799

    
   
799

   
800
/*!
800
/*!
801
 * \brief create thread for the parked call
801
 * \brief create thread for the parked call
802
 * \param data
802
 * \param data
803
 *
803
 *
804
 * Create thread and attributes, call bridge_call_thread
804
 * Create thread and attributes, call bridge_call_thread
805
*/
805
*/
806
static void bridge_call_thread_launch(void *data) 
806
static void bridge_call_thread_launch(void *data) 
807
{
807
{
808
	pthread_t thread;
808
	pthread_t thread;
809
	pthread_attr_t attr;
809
	pthread_attr_t attr;
810
	struct sched_param sched;
810
	struct sched_param sched;
811

    
   
811

   
812
	pthread_attr_init(&attr);
812
	pthread_attr_init(&attr);
813
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
813
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
814
	ast_pthread_create(&thread, &attr, bridge_call_thread, data);
814
	ast_pthread_create(&thread, &attr, bridge_call_thread, data);
815
	pthread_attr_destroy(&attr);
815
	pthread_attr_destroy(&attr);
816
	memset(&sched, 0, sizeof(sched));
816
	memset(&sched, 0, sizeof(sched));
817
	pthread_setschedparam(thread, SCHED_RR, &sched);
817
	pthread_setschedparam(thread, SCHED_RR, &sched);
818
}
818
}
819

    
   
819

   
820
/*!
820
/*!
821
 * \brief Announce call parking by ADSI
821
 * \brief Announce call parking by ADSI
822
 * \param chan .
822
 * \param chan .
823
 * \param parkingexten .
823
 * \param parkingexten .
824
 * Create message to show for ADSI, display message.
824
 * Create message to show for ADSI, display message.
825
 * \retval 0 on success.
825
 * \retval 0 on success.
826
 * \retval -1 on failure.
826
 * \retval -1 on failure.
827
*/
827
*/
828
static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
828
static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
829
{
829
{
830
	int res;
830
	int res;
831
	int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
831
	int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
832
	char tmp[256];
832
	char tmp[256];
833
	char *message[5] = {NULL, NULL, NULL, NULL, NULL};
833
	char *message[5] = {NULL, NULL, NULL, NULL, NULL};
834

    
   
834

   
835
	snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
835
	snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
836
	message[0] = tmp;
836
	message[0] = tmp;
837
	res = ast_adsi_load_session(chan, NULL, 0, 1);
837
	res = ast_adsi_load_session(chan, NULL, 0, 1);
838
	if (res == -1)
838
	if (res == -1)
839
		return res;
839
		return res;
840
	return ast_adsi_print(chan, message, justify, 1);
840
	return ast_adsi_print(chan, message, justify, 1);
841
}
841
}
842

    
   
842

   
843
/*! \brief Find parking lot name from channel */
843
/*! \brief Find parking lot name from channel */
844
static const char *findparkinglotname(struct ast_channel *chan)
844
static const char *findparkinglotname(struct ast_channel *chan)
845
{
845
{
846
	const char *temp, *parkinglot = NULL;
846
	const char *temp, *parkinglot = NULL;
847

    
   
847

   
848
	/* Check if the channel has a parking lot */
848
	/* Check if the channel has a parking lot */
849
	if (!ast_strlen_zero(chan->parkinglot))
849
	if (!ast_strlen_zero(chan->parkinglot))
850
		parkinglot = chan->parkinglot;
850
		parkinglot = chan->parkinglot;
851

    
   
851

   
852
	/* Channel variables override everything */
852
	/* Channel variables override everything */
853

    
   
853

   
854
	if ((temp  = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
854
	if ((temp  = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
855
		return temp;
855
		return temp;
856

    
   
856

   
857
	return parkinglot;
857
	return parkinglot;
858
}
858
}
859

    
   
859

   
860
/*! \brief Notify metermaids that we've changed an extension */
860
/*! \brief Notify metermaids that we've changed an extension */
861
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
861
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
862
{
862
{
863
	ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
863
	ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
864
		exten, context, ast_devstate2str(state));
864
		exten, context, ast_devstate2str(state));
865

    
   
865

   
866
	ast_devstate_changed(state, "park:%s@%s", exten, context);
866
	ast_devstate_changed(state, "park:%s@%s", exten, context);
867
}
867
}
868

    
   
868

   
869
/*! \brief metermaids callback from devicestate.c */
869
/*! \brief metermaids callback from devicestate.c */
870
static enum ast_device_state metermaidstate(const char *data)
870
static enum ast_device_state metermaidstate(const char *data)
871
{
871
{
872
	char *context;
872
	char *context;
873
	char *exten;
873
	char *exten;
874

    
   
874

   
875
	context = ast_strdupa(data);
875
	context = ast_strdupa(data);
876

    
   
876

   
877
	exten = strsep(&context, "@");
877
	exten = strsep(&context, "@");
878
	if (!context)
878
	if (!context)
879
		return AST_DEVICE_INVALID;
879
		return AST_DEVICE_INVALID;
880

    
   
880

   
881
	ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
881
	ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
882

    
   
882

   
883
	if (!ast_exists_extension(NULL, context, exten, 1, NULL))
883
	if (!ast_exists_extension(NULL, context, exten, 1, NULL))
884
		return AST_DEVICE_NOT_INUSE;
884
		return AST_DEVICE_NOT_INUSE;
885

    
   
885

   
886
	return AST_DEVICE_INUSE;
886
	return AST_DEVICE_INUSE;
887
}
887
}
888

    
   
888

   
889
/*! Options to pass to park_call_full */
889
/*! Options to pass to park_call_full */
890
enum ast_park_call_options {
890
enum ast_park_call_options {
891
	/*! Provide ringing to the parked caller instead of music on hold */
891
	/*! Provide ringing to the parked caller instead of music on hold */
892
	AST_PARK_OPT_RINGING =   (1 << 0),
892
	AST_PARK_OPT_RINGING =   (1 << 0),
893
	/*! Randomly choose a parking spot for the caller instead of choosing
893
	/*! Randomly choose a parking spot for the caller instead of choosing
894
	 *  the first one that is available. */
894
	 *  the first one that is available. */
895
	AST_PARK_OPT_RANDOMIZE = (1 << 1),
895
	AST_PARK_OPT_RANDOMIZE = (1 << 1),
896
	/*! Do not announce the parking number */
896
	/*! Do not announce the parking number */
897
	AST_PARK_OPT_SILENCE = (1 << 2),
897
	AST_PARK_OPT_SILENCE = (1 << 2),
898
};
898
};
899

    
   
899

   
900
struct ast_park_call_args {
900
struct ast_park_call_args {
901
	/*! How long to wait in the parking lot before the call gets sent back
901
	/*! How long to wait in the parking lot before the call gets sent back
902
	 *  to the specified return extension (or a best guess at where it came
902
	 *  to the specified return extension (or a best guess at where it came
903
	 *  from if not explicitly specified). */
903
	 *  from if not explicitly specified). */
904
	int timeout;
904
	int timeout;
905
	/*! An output parameter to store the parking space where the parked caller
905
	/*! An output parameter to store the parking space where the parked caller
906
	 *  was placed. */
906
	 *  was placed. */
907
	int *extout;
907
	int *extout;
908
	const char *orig_chan_name;
908
	const char *orig_chan_name;
909
	const char *return_con;
909
	const char *return_con;
910
	const char *return_ext;
910
	const char *return_ext;
911
	int return_pri;
911
	int return_pri;
912
	uint32_t flags;
912
	uint32_t flags;
913
	/*! Parked user that has already obtained a parking space */
913
	/*! Parked user that has already obtained a parking space */
914
	struct parkeduser *pu;
914
	struct parkeduser *pu;
915
	struct ast_parkinglot *parkinglot; /*! parkinglot to be parked in, based on parkext */
915
	struct ast_parkinglot *parkinglot; /*! parkinglot to be parked in, based on parkext */
916
};
916
};
917

    
   
917

   
918
static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
918
static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
919
{
919
{
920
	struct parkeduser *pu;
920
	struct parkeduser *pu;
921
	int i, parking_space = -1, parking_range;
921
	int i, parking_space = -1, parking_range;
922
	const char *parkinglotname = NULL;
922
	const char *parkinglotname = NULL;
923
	const char *parkingexten;
923
	const char *parkingexten;
924
	struct ast_parkinglot *parkinglot = NULL;
924
	struct ast_parkinglot *parkinglot = NULL;
925

    
   
925

   
926
	if (args->parkinglot) {
926
	if (args->parkinglot) {
927
		parkinglot = args->parkinglot;
927
		parkinglot = args->parkinglot;
928
		parkinglotname = parkinglot->name;
928
		parkinglotname = parkinglot->name;
929
	} else if (peer) {
929
	} else if (peer) {
930
		parkinglotname = findparkinglotname(peer);
930
		parkinglotname = findparkinglotname(peer);
931
	} else { /* peer was NULL, check chan (ParkAndAnnounce / res_agi) */
931
	} else { /* peer was NULL, check chan (ParkAndAnnounce / res_agi) */
932
		parkinglotname = findparkinglotname(chan);
932
		parkinglotname = findparkinglotname(chan);
933
	}
933
	}
934

    
   
934

   
935
	if (!args->parkinglot) {
935
	if (!args->parkinglot) {
936
		if (parkinglotname) {
936
		if (parkinglotname) {
937
			parkinglot = find_parkinglot(parkinglotname);
937
			parkinglot = find_parkinglot(parkinglotname);
938
		} else {
938
		} else {
939
			ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
939
			ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
940
			parkinglot = parkinglot_addref(default_parkinglot);
940
			parkinglot = parkinglot_addref(default_parkinglot);
941
		}
941
		}
942
		ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglot->name);
942
		ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglot->name);
943
	}
943
	}
944

    
   
944

   
945
	/* Dynamically create parkinglot */
945
	/* Dynamically create parkinglot */
946
	if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
946
	if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
947
		const char *dyn_context, *dyn_range;
947
		const char *dyn_context, *dyn_range;
948
		const char *parkinglotname_copy = NULL;
948
		const char *parkinglotname_copy = NULL;
949
		struct ast_parkinglot *parkinglot_copy = NULL;
949
		struct ast_parkinglot *parkinglot_copy = NULL;
950
		int dyn_start, dyn_end;
950
		int dyn_start, dyn_end;
951

    
   
951

   
952
		ast_channel_lock(chan);
952
		ast_channel_lock(chan);
953
		parkinglotname_copy = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
953
		parkinglotname_copy = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
954
		dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
954
		dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
955
		dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
955
		dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
956
		ast_channel_unlock(chan);
956
		ast_channel_unlock(chan);
957

    
   
957

   
958
		if (!ast_strlen_zero(parkinglotname_copy)) {
958
		if (!ast_strlen_zero(parkinglotname_copy)) {
959
			parkinglot_copy = find_parkinglot(parkinglotname_copy);
959
			parkinglot_copy = find_parkinglot(parkinglotname_copy);
960
		}
960
		}
961
		if (!parkinglot_copy) {
961
		if (!parkinglot_copy) {
962
			parkinglot_copy = parkinglot_addref(default_parkinglot);
962
			parkinglot_copy = parkinglot_addref(default_parkinglot);
963
			ast_debug(1, "Using default parking lot for copy\n");
963
			ast_debug(1, "Using default parking lot for copy\n");
964
		}
964
		}
965
		if (!(parkinglot = copy_parkinglot(parkinglotname, parkinglot_copy))) {
965
		if (!(parkinglot = copy_parkinglot(parkinglotname, parkinglot_copy))) {
966
			ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
966
			ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
967
		} else {
967
		} else {
968
			if (!ast_strlen_zero(dyn_context)) {
968
			if (!ast_strlen_zero(dyn_context)) {
969
				ast_copy_string(parkinglot->parking_con, dyn_context, sizeof(parkinglot->parking_con));
969
				ast_copy_string(parkinglot->parking_con, dyn_context, sizeof(parkinglot->parking_con));
970
			}
970
			}
971
			if (!ast_strlen_zero(dyn_range)) {
971
			if (!ast_strlen_zero(dyn_range)) {
972
				if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
972
				if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
973
					ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers\n");
973
					ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers\n");
974
				} else {
974
				} else {
975
					parkinglot->parking_start = dyn_start;
975
					parkinglot->parking_start = dyn_start;
976
					parkinglot->parking_stop = dyn_end;
976
					parkinglot->parking_stop = dyn_end;
977
				}
977
				}
978
			}
978
			}
979
			ao2_link(parkinglots, parkinglot);
979
			ao2_link(parkinglots, parkinglot);
980
		}
980
		}
981

    
   
981

   
982
		if (parkinglot_copy) {
982
		if (parkinglot_copy) {
983
			/* unref our tempory copy */
983
			/* unref our tempory copy */
984
			parkinglot_unref(parkinglot_copy);
984
			parkinglot_unref(parkinglot_copy);
985
			parkinglot_copy = NULL;
985
			parkinglot_copy = NULL;
986
		}
986
		}
987
	}
987
	}
988

    
   
988

   
989
	if (!parkinglot) {
989
	if (!parkinglot) {
990
		parkinglot = parkinglot_addref(default_parkinglot);
990
		parkinglot = parkinglot_addref(default_parkinglot);
991
	}
991
	}
992

    
   
992

   
993
	ast_debug(1, "Parkinglot: %s\n", parkinglot->name);
993
	ast_debug(1, "Parkinglot: %s\n", parkinglot->name);
994

    
   
994

   
995
	/* Allocate memory for parking data */
995
	/* Allocate memory for parking data */
996
	if (!(pu = ast_calloc(1, sizeof(*pu)))) {
996
	if (!(pu = ast_calloc(1, sizeof(*pu)))) {
997
		parkinglot_unref(parkinglot);
997
		parkinglot_unref(parkinglot);
998
		return NULL;
998
		return NULL;
999
	}
999
	}
1000

    
   
1000

   
1001
	/* Lock parking list */
1001
	/* Lock parking list */
1002
	AST_LIST_LOCK(&parkinglot->parkings);
1002
	AST_LIST_LOCK(&parkinglot->parkings);
1003
	/* Check for channel variable PARKINGEXTEN */
1003
	/* Check for channel variable PARKINGEXTEN */
1004
	ast_channel_lock(chan);
1004
	ast_channel_lock(chan);
1005
	parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), ""));
1005
	parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), ""));
1006
	ast_channel_unlock(chan);
1006
	ast_channel_unlock(chan);
1007
	if (!ast_strlen_zero(parkingexten)) {
1007
	if (!ast_strlen_zero(parkingexten)) {
1008
		/*!\note The API forces us to specify a numeric parking slot, even
1008
		/*!\note The API forces us to specify a numeric parking slot, even
1009
		 * though the architecture would tend to support non-numeric extensions
1009
		 * though the architecture would tend to support non-numeric extensions
1010
		 * (as are possible with SIP, for example).  Hence, we enforce that
1010
		 * (as are possible with SIP, for example).  Hence, we enforce that
1011
		 * limitation here.  If extout was not numeric, we could permit
1011
		 * limitation here.  If extout was not numeric, we could permit
1012
		 * arbitrary non-numeric extensions.
1012
		 * arbitrary non-numeric extensions.
1013
		 */
1013
		 */
1014
	if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space < 0) {
1014
	if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space < 0) {
1015
			AST_LIST_UNLOCK(&parkinglot->parkings);
1015
			AST_LIST_UNLOCK(&parkinglot->parkings);
1016
			parkinglot_unref(parkinglot);
1016
			parkinglot_unref(parkinglot);
1017
	    free(pu);
1017
	    free(pu);
1018
	    ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
1018
	    ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
1019
	    return NULL;
1019
	    return NULL;
1020
	}
1020
	}
1021
	snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1021
	snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1022

    
   
1022

   
1023
		if (ast_exists_extension(NULL, parkinglot->parking_con, pu->parkingexten, 1, NULL)) {
1023
		if (ast_exists_extension(NULL, parkinglot->parking_con, pu->parkingexten, 1, NULL)) {
1024
			ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
1024
			ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
1025
			AST_LIST_UNLOCK(&parkinglot->parkings);
1025
			AST_LIST_UNLOCK(&parkinglot->parkings);
1026
			parkinglot_unref(parkinglot);
1026
			parkinglot_unref(parkinglot);
1027
			ast_free(pu);
1027
			ast_free(pu);
1028
			return NULL;
1028
			return NULL;
1029
		}
1029
		}
1030
	} else {
1030
	} else {
1031
		int start;
1031
		int start;
1032
		struct parkeduser *cur = NULL;
1032
		struct parkeduser *cur = NULL;
1033

    
   
1033

   
1034
		/* Select parking space within range */
1034
		/* Select parking space within range */
1035
		parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
1035
		parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
1036

    
   
1036

   
1037
		if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
1037
		if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
1038
			start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1);
1038
			start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1);
1039
		} else {
1039
		} else {
1040
			start = parkinglot->parking_start;
1040
			start = parkinglot->parking_start;
1041
		}
1041
		}
1042

    
   
1042

   
1043
		for (i = start; 1; i++) {
1043
		for (i = start; 1; i++) {
1044
			if (i == parkinglot->parking_stop + 1) {
1044
			if (i == parkinglot->parking_stop + 1) {
1045
				i = parkinglot->parking_start - 1;
1045
				i = parkinglot->parking_start - 1;
1046
				break;
1046
				break;
1047
			}
1047
			}
1048

    
   
1048

   
1049
			AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1049
			AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1050
				if (cur->parkingnum == i) {
1050
				if (cur->parkingnum == i) {
1051
					break;
1051
					break;
1052
				}
1052
				}
1053
			}
1053
			}
1054
			if (!cur) {
1054
			if (!cur) {
1055
				parking_space = i;
1055
				parking_space = i;
1056
				break;
1056
				break;
1057
			}
1057
			}
1058
		}
1058
		}
1059

    
   
1059

   
1060
		if (i == start - 1 && cur) {
1060
		if (i == start - 1 && cur) {
1061
			ast_log(LOG_WARNING, "No more parking spaces\n");
1061
			ast_log(LOG_WARNING, "No more parking spaces\n");
1062
			ast_free(pu);
1062
			ast_free(pu);
1063
			AST_LIST_UNLOCK(&parkinglot->parkings);
1063
			AST_LIST_UNLOCK(&parkinglot->parkings);
1064
			parkinglot_unref(parkinglot);
1064
			parkinglot_unref(parkinglot);
1065
			return NULL;
1065
			return NULL;
1066
		}
1066
		}
1067
		/* Set pointer for next parking */
1067
		/* Set pointer for next parking */
1068
		if (parkinglot->parkfindnext) 
1068
		if (parkinglot->parkfindnext) 
1069
			parkinglot->parking_offset = parking_space - parkinglot->parking_start + 1;
1069
			parkinglot->parking_offset = parking_space - parkinglot->parking_start + 1;
1070
		snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1070
		snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1071
	}
1071
	}
1072

    
   
1072

   
1073
	pu->notquiteyet = 1;
1073
	pu->notquiteyet = 1;
1074
	pu->parkingnum = parking_space;
1074
	pu->parkingnum = parking_space;
1075
	pu->parkinglot = parkinglot;
1075
	pu->parkinglot = parkinglot;
1076
	AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
1076
	AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
1077

    
   
1077

   
1078
	return pu;
1078
	return pu;
1079
}
1079
}
1080

    
   
1080

   
1081
/* Park a call */
1081
/* Park a call */
1082
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
1082
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
1083
{
1083
{
1084
	struct ast_context *con;
1084
	struct ast_context *con;
1085
	int parkingnum_copy;
1085
	int parkingnum_copy;
1086
	struct parkeduser *pu = args->pu;
1086
	struct parkeduser *pu = args->pu;
1087
	const char *event_from;
1087
	const char *event_from;
1088

    
   
1088

   
1089
	if (pu == NULL)
1089
	if (pu == NULL)
1090
		args->pu = pu = park_space_reserve(chan, peer, args);
1090
		args->pu = pu = park_space_reserve(chan, peer, args);
1091
	if (pu == NULL)
1091
	if (pu == NULL)
1092
		return 1; /* Continue execution if possible */
1092
		return 1; /* Continue execution if possible */
1093

    
   
1093

   
1094
	snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", pu->parkingnum);
1094
	snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", pu->parkingnum);
1095

    
   
1095

   
1096
	chan->appl = "Parked Call";
1096
	chan->appl = "Parked Call";
1097
	chan->data = NULL;
1097
	chan->data = NULL;
1098

    
   
1098

   
1099
	pu->chan = chan;
1099
	pu->chan = chan;
1100

    
   
1100

   
1101
	/* Put the parked channel on hold if we have two different channels */
1101
	/* Put the parked channel on hold if we have two different channels */
1102
	if (chan != peer) {
1102
	if (chan != peer) {
1103
		if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1103
		if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1104
			ast_indicate(pu->chan, AST_CONTROL_RINGING);
1104
			ast_indicate(pu->chan, AST_CONTROL_RINGING);
1105
		} else {
1105
		} else {
1106
			ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
1106
			ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
1107
				S_OR(pu->parkinglot->mohclass, NULL),
1107
				S_OR(pu->parkinglot->mohclass, NULL),
1108
				!ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
1108
				!ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
1109
		}
1109
		}
1110
	}
1110
	}
1111
	
1111
	
1112
	pu->start = ast_tvnow();
1112
	pu->start = ast_tvnow();
1113
	pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->parkingtime;
1113
	pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->parkingtime;
1114
	parkingnum_copy = pu->parkingnum;
1114
	parkingnum_copy = pu->parkingnum;
1115
	if (args->extout)
1115
	if (args->extout)
1116
		*(args->extout) = pu->parkingnum;
1116
		*(args->extout) = pu->parkingnum;
1117

    
   
1117

   
1118
	if (peer) { 
1118
	if (peer) { 
1119
		/* This is so ugly that it hurts, but implementing get_base_channel() on local channels
1119
		/* This is so ugly that it hurts, but implementing get_base_channel() on local channels
1120
			could have ugly side effects.  We could have transferer<->local,1<->local,2<->parking
1120
			could have ugly side effects.  We could have transferer<->local,1<->local,2<->parking
1121
			and we need the callback name to be that of transferer.  Since local,1/2 have the same
1121
			and we need the callback name to be that of transferer.  Since local,1/2 have the same
1122
			name we can be tricky and just grab the bridged channel from the other side of the local
1122
			name we can be tricky and just grab the bridged channel from the other side of the local
1123
		*/
1123
		*/
1124
		if (!strcasecmp(peer->tech->type, "Local")) {
1124
		if (!strcasecmp(peer->tech->type, "Local")) {
1125
			struct ast_channel *tmpchan, *base_peer;
1125
			struct ast_channel *tmpchan, *base_peer;
1126
			char other_side[AST_CHANNEL_NAME];
1126
			char other_side[AST_CHANNEL_NAME];
1127
			char *c;
1127
			char *c;
1128
			ast_copy_string(other_side, S_OR(args->orig_chan_name, peer->name), sizeof(other_side));
1128
			ast_copy_string(other_side, S_OR(args->orig_chan_name, peer->name), sizeof(other_side));
1129
			if ((c = strrchr(other_side, ';'))) {
1129
			if ((c = strrchr(other_side, ';'))) {
1130
				*++c = '1';
1130
				*++c = '1';
1131
			}
1131
			}
1132
			if ((tmpchan = ast_channel_get_by_name(other_side))) {
1132
			if ((tmpchan = ast_channel_get_by_name(other_side))) {
1133
				ast_channel_lock(tmpchan);
1133
				ast_channel_lock(tmpchan);
1134
				if ((base_peer = ast_bridged_channel(tmpchan))) {
1134
				if ((base_peer = ast_bridged_channel(tmpchan))) {
1135
					ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
1135
					ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
1136
				}
1136
				}
1137
				ast_channel_unlock(tmpchan);
1137
				ast_channel_unlock(tmpchan);
1138
				tmpchan = ast_channel_unref(tmpchan);
1138
				tmpchan = ast_channel_unref(tmpchan);
1139
			}
1139
			}
1140
		} else {
1140
		} else {
1141
			ast_copy_string(pu->peername, S_OR(args->orig_chan_name, peer->name), sizeof(pu->peername));
1141
			ast_copy_string(pu->peername, S_OR(args->orig_chan_name, peer->name), sizeof(pu->peername));
1142
		}
1142
		}
1143
	}
1143
	}
1144

    
   
1144

   
1145
	/* Remember what had been dialed, so that if the parking
1145
	/* Remember what had been dialed, so that if the parking
1146
	   expires, we try to come back to the same place */
1146
	   expires, we try to come back to the same place */
1147

    
   
1147

   
1148
	pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
1148
	pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
1149

    
   
1149

   
1150
	/* If extension has options specified, they override all other possibilities
1150
	/* If extension has options specified, they override all other possibilities
1151
	such as the returntoorigin flag and transferred context. Information on
1151
	such as the returntoorigin flag and transferred context. Information on
1152
	extension options is lost here, so we set a flag */
1152
	extension options is lost here, so we set a flag */
1153

    
   
1153

   
1154
	ast_copy_string(pu->context, 
1154
	ast_copy_string(pu->context, 
1155
		S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)), 
1155
		S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)), 
1156
		sizeof(pu->context));
1156
		sizeof(pu->context));
1157
	ast_copy_string(pu->exten, 
1157
	ast_copy_string(pu->exten, 
1158
		S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)), 
1158
		S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)), 
1159
		sizeof(pu->exten));
1159
		sizeof(pu->exten));
1160
	pu->priority = args->return_pri ? args->return_pri : 
1160
	pu->priority = args->return_pri ? args->return_pri : 
1161
		(chan->macropriority ? chan->macropriority : chan->priority);
1161
		(chan->macropriority ? chan->macropriority : chan->priority);
1162

    
   
1162

   
1163
	/* If parking a channel directly, don't quiet yet get parking running on it.
1163
	/* If parking a channel directly, don't quiet yet get parking running on it.
1164
	 * All parking lot entries are put into the parking lot with notquiteyet on. */
1164
	 * All parking lot entries are put into the parking lot with notquiteyet on. */
1165
	if (peer != chan) 
1165
	if (peer != chan) 
1166
		pu->notquiteyet = 0;
1166
		pu->notquiteyet = 0;
1167

    
   
1167

   
1168
	/* Wake up the (presumably select()ing) thread */
1168
	/* Wake up the (presumably select()ing) thread */
1169
	pthread_kill(parking_thread, SIGURG);
1169
	pthread_kill(parking_thread, SIGURG);
1170
	ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
1170
	ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
1171

    
   
1171

   
1172
	ast_cel_report_event(pu->chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
1172
	ast_cel_report_event(pu->chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
1173

    
   
1173

   
1174
	if (peer) {
1174
	if (peer) {
1175
		event_from = peer->name;
1175
		event_from = peer->name;
1176
	} else {
1176
	} else {
1177
		event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
1177
		event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
1178
	}
1178
	}
1179

    
   
1179

   
1180
	ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
1180
	ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
1181
		"Exten: %s\r\n"
1181
		"Exten: %s\r\n"
1182
		"Channel: %s\r\n"
1182
		"Channel: %s\r\n"
1183
		"Parkinglot: %s\r\n"
1183
		"Parkinglot: %s\r\n"
1184
		"From: %s\r\n"
1184
		"From: %s\r\n"
1185
		"Timeout: %ld\r\n"
1185
		"Timeout: %ld\r\n"
1186
		"CallerIDNum: %s\r\n"
1186
		"CallerIDNum: %s\r\n"
1187
		"CallerIDName: %s\r\n"
1187
		"CallerIDName: %s\r\n"
1188
		"Uniqueid: %s\r\n",
1188
		"Uniqueid: %s\r\n",
1189
		pu->parkingexten, pu->chan->name, pu->parkinglot->name, event_from ? event_from : "",
1189
		pu->parkingexten, pu->chan->name, pu->parkinglot->name, event_from ? event_from : "",
1190
		(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
1190
		(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
1191
		S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
1191
		S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
1192
		S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
1192
		S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
1193
		pu->chan->uniqueid
1193
		pu->chan->uniqueid
1194
		);
1194
		);
1195

    
   
1195

   
1196
	if (peer && adsipark && ast_adsi_available(peer)) {
1196
	if (peer && adsipark && ast_adsi_available(peer)) {
1197
		adsi_announce_park(peer, pu->parkingexten);	/* Only supports parking numbers */
1197
		adsi_announce_park(peer, pu->parkingexten);	/* Only supports parking numbers */
1198
		ast_adsi_unload_session(peer);
1198
		ast_adsi_unload_session(peer);
1199
	}
1199
	}
1200

    
   
1200

   
1201
	con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con, registrar);
1201
	con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con, registrar);
1202
	if (!con)	/* Still no context? Bad */
1202
	if (!con)	/* Still no context? Bad */
1203
		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con);
1203
		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con);
1204
	if (con) {
1204
	if (con) {
1205
		if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
1205
		if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
1206
			notify_metermaids(pu->parkingexten, pu->parkinglot->parking_con, AST_DEVICE_INUSE);
1206
			notify_metermaids(pu->parkingexten, pu->parkinglot->parking_con, AST_DEVICE_INUSE);
1207
	}
1207
	}
1208

    
   
1208

   
1209
	AST_LIST_UNLOCK(&pu->parkinglot->parkings);
1209
	AST_LIST_UNLOCK(&pu->parkinglot->parkings);
1210

    
   
1210

   
1211
	/* Only say number if it's a number and the channel hasn't been masqueraded away */
1211
	/* Only say number if it's a number and the channel hasn't been masqueraded away */
1212
	if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE) && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
1212
	if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE) && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
1213
		/* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
1213
		/* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
1214
		ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1214
		ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1215
		/* Tell the peer channel the number of the parking space */
1215
		/* Tell the peer channel the number of the parking space */
1216
		ast_say_digits(peer, pu->parkingnum, "", peer->language);
1216
		ast_say_digits(peer, pu->parkingnum, "", peer->language);
1217
		ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1217
		ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1218
	}
1218
	}
1219
	if (peer == chan) { /* pu->notquiteyet = 1 */
1219
	if (peer == chan) { /* pu->notquiteyet = 1 */
1220
		/* Wake up parking thread if we're really done */
1220
		/* Wake up parking thread if we're really done */
1221
		ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
1221
		ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
1222
			S_OR(pu->parkinglot->mohclass, NULL),
1222
			S_OR(pu->parkinglot->mohclass, NULL),
1223
			!ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
1223
			!ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
1224
		pu->notquiteyet = 0;
1224
		pu->notquiteyet = 0;
1225
		pthread_kill(parking_thread, SIGURG);
1225
		pthread_kill(parking_thread, SIGURG);
1226
	}
1226
	}
1227
	return 0;
1227
	return 0;
1228
}
1228
}
1229

    
   
1229

   
1230
/*! \brief Park a call */
1230
/*! \brief Park a call */
1231
int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, const char *parkexten, int *extout)
1231
int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, const char *parkexten, int *extout)
1232
{
1232
{
1233
	struct ast_parkinglot *found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, (void *) parkexten);
1233
	struct ast_parkinglot *found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, (void *) parkexten);
1234

    
   
1234

   
1235
	struct ast_park_call_args args = {
1235
	struct ast_park_call_args args = {
1236
		.timeout = timeout,
1236
		.timeout = timeout,
1237
		.extout = extout,
1237
		.extout = extout,
1238
		.parkinglot = found_lot,
1238
		.parkinglot = found_lot,
1239
	};
1239
	};
1240

    
   
1240

   
1241
	return park_call_full(chan, peer, &args);
1241
	return park_call_full(chan, peer, &args);
1242
}
1242
}
1243

    
   
1243

   
1244
/*!
1244
/*!
1245
 * \param rchan is the transferee
1245
 * \param rchan is the transferee
1246
 * \param peer is the transferer
1246
 * \param peer is the transferer
1247
 */
1247
 */
1248
static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement, struct ast_park_call_args *args)
1248
static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement, struct ast_park_call_args *args)
1249
{
1249
{
1250
	struct ast_channel *chan;
1250
	struct ast_channel *chan;
1251
	struct ast_frame *f;
1251
	struct ast_frame *f;
1252
	struct ast_park_call_args park_args = {0,};
1252
	struct ast_park_call_args park_args = {0,};
1253

    
   
1253

   
1254
	if (!args) {
1254
	if (!args) {
1255
		args = &park_args;
1255
		args = &park_args;
1256
		args->timeout = timeout;
1256
		args->timeout = timeout;
1257
		args->extout = extout;
1257
		args->extout = extout;
1258
	}
1258
	}
1259

    
   
1259

   
1260
	if ((args->pu = park_space_reserve(rchan, peer, args)) == NULL) {
1260
	if ((args->pu = park_space_reserve(rchan, peer, args)) == NULL) {
1261
		if (peer) {
1261
		if (peer) {
1262
			ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1262
			ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1263
		}
1263
		}
1264
		return AST_FEATURE_RETURN_PARKFAILED;
1264
		return AST_FEATURE_RETURN_PARKFAILED;
1265
	}
1265
	}
1266

    
   
1266

   
1267
	/* Make a new, fake channel that we'll use to masquerade in the real one */
1267
	/* Make a new, fake channel that we'll use to masquerade in the real one */
1268
	if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->linkedid, rchan->amaflags, "Parked/%s",rchan->name))) {
1268
	if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->linkedid, rchan->amaflags, "Parked/%s",rchan->name))) {
1269
		ast_log(LOG_WARNING, "Unable to create parked channel\n");
1269
		ast_log(LOG_WARNING, "Unable to create parked channel\n");
1270
		return -1;
1270
		return -1;
1271
	}
1271
	}
1272

    
   
1272

   
1273
	/* Make formats okay */
1273
	/* Make formats okay */
1274
	chan->readformat = rchan->readformat;
1274
	chan->readformat = rchan->readformat;
1275
	chan->writeformat = rchan->writeformat;
1275
	chan->writeformat = rchan->writeformat;
1276
	ast_channel_masquerade(chan, rchan);
1276
	ast_channel_masquerade(chan, rchan);
1277

    
   
1277

   
1278
	/* Setup the extensions and such */
1278
	/* Setup the extensions and such */
1279
	set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
1279
	set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
1280

    
   
1280

   
1281
	/* Setup the macro extension and such */
1281
	/* Setup the macro extension and such */
1282
	ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
1282
	ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
1283
	ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
1283
	ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
1284
	chan->macropriority = rchan->macropriority;
1284
	chan->macropriority = rchan->macropriority;
1285

    
   
1285

   
1286
	/* Make the masq execute */
1286
	/* Make the masq execute */
1287
	if ((f = ast_read(chan)))
1287
	if ((f = ast_read(chan)))
1288
		ast_frfree(f);
1288
		ast_frfree(f);
1289

    
   
1289

   
1290
	if (peer == rchan) {
1290
	if (peer == rchan) {
1291
		peer = chan;
1291
		peer = chan;
1292
	}
1292
	}
1293

    
   
1293

   
1294
	if (peer && (!play_announcement && args == &park_args)) {
1294
	if (peer && (!play_announcement && args == &park_args)) {
1295
		args->orig_chan_name = ast_strdupa(peer->name);
1295
		args->orig_chan_name = ast_strdupa(peer->name);
1296
	}
1296
	}
1297

    
   
1297

   
1298
	/* parking space reserved, return code check unnecessary */
1298
	/* parking space reserved, return code check unnecessary */
1299
	park_call_full(chan, peer, args);
1299
	park_call_full(chan, peer, args);
1300

    
   
1300

   
1301
	return 0;
1301
	return 0;
1302
}
1302
}
1303

    
   
1303

   
1304
/* Park call via masqueraded channel */
1304
/* Park call via masqueraded channel */
1305
int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
1305
int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
1306
{
1306
{
1307
	return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
1307
	return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
1308
}
1308
}
1309

    
   
1309

   
1310
static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
1310
static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
1311
{
1311
{
1312
	return masq_park_call(rchan, peer, 0, NULL, 1, args);
1312
	return masq_park_call(rchan, peer, 0, NULL, 1, args);
1313
}
1313
}
1314

    
   
1314

   
1315
#ifdef TEST_FRAMEWORK
1315
#ifdef TEST_FRAMEWORK
1316
static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
1316
static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
1317
{
1317
{
1318
	return 0;
1318
	return 0;
1319
}
1319
}
1320

    
   
1320

   
1321
static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech)
1321
static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech)
1322
{
1322
{
1323
	struct ast_channel *test_channel1;
1323
	struct ast_channel *test_channel1;
1324
	struct ast_format tmp_fmt;
1324
	struct ast_format tmp_fmt;
1325
	if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
1325
	if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
1326
	NULL, NULL, 0, 0, "TestChannel1"))) {
1326
	NULL, NULL, 0, 0, "TestChannel1"))) {
1327
		return NULL;
1327
		return NULL;
1328
	}
1328
	}
1329

    
   
1329

   
1330
	/* normally this is done in the channel driver */
1330
	/* normally this is done in the channel driver */
1331
	ast_format_cap_add(test_channel1->nativeformats, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
1331
	ast_format_cap_add(test_channel1->nativeformats, ast_format_set(&tmp_fmt, AST_FORMAT_GSM, 0));
1332

    
   
1332

   
1333
	ast_format_set(&test_channel1->writeformat, AST_FORMAT_GSM, 0);
1333
	ast_format_set(&test_channel1->writeformat, AST_FORMAT_GSM, 0);
1334
	ast_format_set(&test_channel1->rawwriteformat, AST_FORMAT_GSM, 0);
1334
	ast_format_set(&test_channel1->rawwriteformat, AST_FORMAT_GSM, 0);
1335
	ast_format_set(&test_channel1->readformat, AST_FORMAT_GSM, 0);
1335
	ast_format_set(&test_channel1->readformat, AST_FORMAT_GSM, 0);
1336
	ast_format_set(&test_channel1->rawreadformat, AST_FORMAT_GSM, 0);
1336
	ast_format_set(&test_channel1->rawreadformat, AST_FORMAT_GSM, 0);
1337

    
   
1337

   
1338
	test_channel1->tech = fake_tech;
1338
	test_channel1->tech = fake_tech;
1339

    
   
1339

   
1340
	return test_channel1;
1340
	return test_channel1;
1341
}
1341
}
1342

    
   
1342

   
1343
static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
1343
static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
1344
{
1344
{
1345
	struct ast_context *con;
1345
	struct ast_context *con;
1346
	struct parkeduser *pu_toremove;
1346
	struct parkeduser *pu_toremove;
1347
	args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
1347
	args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
1348
	AST_LIST_LOCK(&args->pu->parkinglot->parkings);
1348
	AST_LIST_LOCK(&args->pu->parkinglot->parkings);
1349
	AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
1349
	AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
1350
		con = ast_context_find(args->pu->parkinglot->parking_con);
1350
		con = ast_context_find(args->pu->parkinglot->parking_con);
1351
		if (con) {
1351
		if (con) {
1352
			if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
1352
			if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
1353
				ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
1353
				ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
1354
				return -1;
1354
				return -1;
1355
			} else {
1355
			} else {
1356
				notify_metermaids(args->pu->parkingexten, pu_toremove->parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
1356
				notify_metermaids(args->pu->parkingexten, pu_toremove->parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
1357
			}
1357
			}
1358
		} else {
1358
		} else {
1359
			ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1359
			ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1360
			return -1;
1360
			return -1;
1361
		}
1361
		}
1362
		if (pu_toremove == args->pu) {
1362
		if (pu_toremove == args->pu) {
1363
			AST_LIST_REMOVE_CURRENT(list);
1363
			AST_LIST_REMOVE_CURRENT(list);
1364
			break;
1364
			break;
1365
		}
1365
		}
1366
	}
1366
	}
1367
	AST_LIST_TRAVERSE_SAFE_END;
1367
	AST_LIST_TRAVERSE_SAFE_END;
1368
	AST_LIST_UNLOCK(&args->pu->parkinglot->parkings);
1368
	AST_LIST_UNLOCK(&args->pu->parkinglot->parkings);
1369

    
   
1369

   
1370
	/* the only way this would be unsafe is if a timeout occurred, which is set at 45 sec */
1370
	/* the only way this would be unsafe is if a timeout occurred, which is set at 45 sec */
1371
	ast_free(args->pu);
1371
	ast_free(args->pu);
1372
	args->pu = NULL;
1372
	args->pu = NULL;
1373

    
   
1373

   
1374
	ast_hangup(toremove);
1374
	ast_hangup(toremove);
1375
	return 0;
1375
	return 0;
1376
}
1376
}
1377

    
   
1377

   
1378
AST_TEST_DEFINE(features_test)
1378
AST_TEST_DEFINE(features_test)
1379
{
1379
{
1380
	int saved_parkeddynamic;
1380
	int saved_parkeddynamic;
1381
	struct ast_channel *test_channel1 = NULL;
1381
	struct ast_channel *test_channel1 = NULL;
1382
	struct ast_channel *parked_chan = NULL;
1382
	struct ast_channel *parked_chan = NULL;
1383
	struct ast_parkinglot *dynlot = NULL;
1383
	struct ast_parkinglot *dynlot = NULL;
1384
	struct ast_park_call_args args = {
1384
	struct ast_park_call_args args = {
1385
		.timeout = DEFAULT_PARK_TIME,
1385
		.timeout = DEFAULT_PARK_TIME,
1386
	};
1386
	};
1387

    
   
1387

   
1388
	int res = -1;
1388
	int res = -1;
1389

    
   
1389

   
1390
	static const struct ast_channel_tech fake_tech = {
1390
	static const struct ast_channel_tech fake_tech = {
1391
		.fixup = fake_fixup, /* silence warning from masquerade */
1391
		.fixup = fake_fixup, /* silence warning from masquerade */
1392
	};
1392
	};
1393

    
   
1393

   
1394
	static const char unique_parkinglot[] = "myuniquetestparkinglot3141592654";
1394
	static const char unique_parkinglot[] = "myuniquetestparkinglot3141592654";
1395
	static const char parkinglot_range[] = "750-760";
1395
	static const char parkinglot_range[] = "750-760";
1396

    
   
1396

   
1397
	switch (cmd) {
1397
	switch (cmd) {
1398
	case TEST_INIT:
1398
	case TEST_INIT:
1399
		info->name = "features_test";
1399
		info->name = "features_test";
1400
		info->category = "/main/features/";
1400
		info->category = "/main/features/";
1401
		info->summary = "Features unit test";
1401
		info->summary = "Features unit test";
1402
		info->description =
1402
		info->description =
1403
			"Tests whether parking respects PARKINGLOT settings";
1403
			"Tests whether parking respects PARKINGLOT settings";
1404
		return AST_TEST_NOT_RUN;
1404
		return AST_TEST_NOT_RUN;
1405
	case TEST_EXECUTE:
1405
	case TEST_EXECUTE:
1406
		break;
1406
		break;
1407
	}
1407
	}
1408

    
   
1408

   
1409
	/* changing a config option is a bad practice, but must be done in this case */
1409
	/* changing a config option is a bad practice, but must be done in this case */
1410
	saved_parkeddynamic = parkeddynamic;
1410
	saved_parkeddynamic = parkeddynamic;
1411
	parkeddynamic = 1;
1411
	parkeddynamic = 1;
1412

    
   
1412

   
1413
	if (!(test_channel1 = create_test_channel(&fake_tech))) {
1413
	if (!(test_channel1 = create_test_channel(&fake_tech))) {
1414
		goto exit_features_test;
1414
		goto exit_features_test;
1415
	}
1415
	}
1416

    
   
1416

   
1417
	ast_test_status_update(test, "Test parking functionality with defaults\n");
1417
	ast_test_status_update(test, "Test parking functionality with defaults\n");
1418
	if (park_call_full(test_channel1, NULL, &args)) {
1418
	if (park_call_full(test_channel1, NULL, &args)) {
1419
		goto exit_features_test;
1419
		goto exit_features_test;
1420
	}
1420
	}
1421
	if (unpark_test_channel(test_channel1, &args)) {
1421
	if (unpark_test_channel(test_channel1, &args)) {
1422
		goto exit_features_test;
1422
		goto exit_features_test;
1423
	}
1423
	}
1424

    
   
1424

   
1425
	ast_test_status_update(test, "Check that certain parking options are respected\n");
1425
	ast_test_status_update(test, "Check that certain parking options are respected\n");
1426
	if (!(test_channel1 = create_test_channel(&fake_tech))) {
1426
	if (!(test_channel1 = create_test_channel(&fake_tech))) {
1427
		goto exit_features_test;
1427
		goto exit_features_test;
1428
	}
1428
	}
1429
	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
1429
	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
1430
	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
1430
	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
1431
	if (park_call_full(test_channel1, NULL, &args)) {
1431
	if (park_call_full(test_channel1, NULL, &args)) {
1432
		goto exit_features_test;
1432
		goto exit_features_test;
1433
	}
1433
	}
1434
	/* grab newly created parking lot for destruction in the end */
1434
	/* grab newly created parking lot for destruction in the end */
1435
	dynlot = args.pu->parkinglot;
1435
	dynlot = args.pu->parkinglot;
1436
	if (!args.pu->parkingnum == 750 || strcasecmp(args.pu->parkinglot->name, unique_parkinglot)) {
1436
	if (!args.pu->parkingnum == 750 || strcasecmp(args.pu->parkinglot->name, unique_parkinglot)) {
1437
		ast_test_status_update(test, "Parking settings were not respected\n");
1437
		ast_test_status_update(test, "Parking settings were not respected\n");
1438
		goto exit_features_test;
1438
		goto exit_features_test;
1439
	} else {
1439
	} else {
1440
		ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
1440
		ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
1441
	}
1441
	}
1442
	if (unpark_test_channel(test_channel1, &args)) {
1442
	if (unpark_test_channel(test_channel1, &args)) {
1443
		goto exit_features_test;
1443
		goto exit_features_test;
1444
	}
1444
	}
1445

    
   
1445

   
1446
	ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
1446
	ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
1447
	if (!(test_channel1 = create_test_channel(&fake_tech))) {
1447
	if (!(test_channel1 = create_test_channel(&fake_tech))) {
1448
		goto exit_features_test;
1448
		goto exit_features_test;
1449
	}
1449
	}
1450
	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
1450
	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
1451
	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
1451
	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
1452
	if (masq_park_call(test_channel1, NULL, 0, NULL, 0, &args) == AST_FEATURE_RETURN_PARKFAILED) {
1452
	if (masq_park_call(test_channel1, NULL, 0, NULL, 0, &args) == AST_FEATURE_RETURN_PARKFAILED) {
1453
		goto exit_features_test;
1453
		goto exit_features_test;
1454
	}
1454
	}
1455
	/* hangup zombie channel */
1455
	/* hangup zombie channel */
1456
	ast_hangup(test_channel1);
1456
	ast_hangup(test_channel1);
1457
	test_channel1 = NULL;
1457
	test_channel1 = NULL;
1458
	if (!args.pu->parkingnum == 750 || strcasecmp(args.pu->parkinglot->name, unique_parkinglot)) {
1458
	if (!args.pu->parkingnum == 750 || strcasecmp(args.pu->parkinglot->name, unique_parkinglot)) {
1459
		ast_test_status_update(test, "Parking settings were not respected\n");
1459
		ast_test_status_update(test, "Parking settings were not respected\n");
1460
		goto exit_features_test;
1460
		goto exit_features_test;
1461
	} else {
1461
	} else {
1462
		ast_test_status_update(test, "Parking settings for masquerading park verified\n");
1462
		ast_test_status_update(test, "Parking settings for masquerading park verified\n");
1463
	}
1463
	}
1464
	/* find the real channel */
1464
	/* find the real channel */
1465
	parked_chan = ast_channel_get_by_name("TestChannel1");
1465
	parked_chan = ast_channel_get_by_name("TestChannel1");
1466
	if (unpark_test_channel(parked_chan, &args)) {
1466
	if (unpark_test_channel(parked_chan, &args)) {
1467
		goto exit_features_test;
1467
		goto exit_features_test;
1468
	}
1468
	}
1469

    
   
1469

   
1470
	res = 0;
1470
	res = 0;
1471

    
   
1471

   
1472
exit_features_test:
1472
exit_features_test:
1473

    
   
1473

   
1474
	if (test_channel1) {
1474
	if (test_channel1) {
1475
		ast_hangup(test_channel1);
1475
		ast_hangup(test_channel1);
1476
	}
1476
	}
1477

    
   
1477

   
1478
	/* careful, if PARKINGDYNCONTEXT is tested, need to delete context */
1478
	/* careful, if PARKINGDYNCONTEXT is tested, need to delete context */
1479
	ao2_unlink(parkinglots, dynlot);
1479
	ao2_unlink(parkinglots, dynlot);
1480
	parkeddynamic = saved_parkeddynamic;
1480
	parkeddynamic = saved_parkeddynamic;
1481
	return res ? AST_TEST_FAIL : AST_TEST_PASS;
1481
	return res ? AST_TEST_FAIL : AST_TEST_PASS;
1482
}
1482
}
1483
#endif
1483
#endif
1484

    
   
1484

   
1485

    
   
1485

   
1486
/*!
1486
/*!
1487
 * \brief set caller and callee according to the direction
1487
 * \brief set caller and callee according to the direction
1488
 * \param caller, callee, peer, chan, sense
1488
 * \param caller, callee, peer, chan, sense
1489
 *
1489
 *
1490
 * Detect who triggered feature and set callee/caller variables accordingly
1490
 * Detect who triggered feature and set callee/caller variables accordingly
1491
*/
1491
*/
1492
static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
1492
static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
1493
	struct ast_channel *peer, struct ast_channel *chan, int sense)
1493
	struct ast_channel *peer, struct ast_channel *chan, int sense)
1494
{
1494
{
1495
	if (sense == FEATURE_SENSE_PEER) {
1495
	if (sense == FEATURE_SENSE_PEER) {
1496
		*caller = peer;
1496
		*caller = peer;
1497
		*callee = chan;
1497
		*callee = chan;
1498
	} else {
1498
	} else {
1499
		*callee = peer;
1499
		*callee = peer;
1500
		*caller = chan;
1500
		*caller = chan;
1501
	}
1501
	}
1502
}
1502
}
1503

    
   
1503

   
1504
static int parkcall_helper(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, struct ast_park_call_args *args)
1504
static int parkcall_helper(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, struct ast_park_call_args *args)
1505
{
1505
{
1506
	int res = 0;
1506
	int res = 0;
1507

    
   
1507

   
1508
	if (args) {
1508
	if (args) {
1509
		ast_debug(1, "Parkinglot specified for builtin_parkcall: %s\n", args->parkinglot->name);
1509
		ast_debug(1, "Parkinglot specified for builtin_parkcall: %s\n", args->parkinglot->name);
1510
	}
1510
	}
1511

    
   
1511

   
1512
	/* we used to set chan's exten and priority to "s" and 1
1512
	/* we used to set chan's exten and priority to "s" and 1
1513
	   here, but this generates (in some cases) an invalid
1513
	   here, but this generates (in some cases) an invalid
1514
	   extension, and if "s" exists, could errantly
1514
	   extension, and if "s" exists, could errantly
1515
	   cause execution of extensions you don't expect. It
1515
	   cause execution of extensions you don't expect. It
1516
	   makes more sense to let nature take its course
1516
	   makes more sense to let nature take its course
1517
	   when chan finishes, and let the pbx do its thing
1517
	   when chan finishes, and let the pbx do its thing
1518
	   and hang up when the park is over.
1518
	   and hang up when the park is over.
1519
	*/
1519
	*/
1520
	if (chan->_state != AST_STATE_UP)
1520
	if (chan->_state != AST_STATE_UP)
1521
		res = ast_answer(chan);
1521
		res = ast_answer(chan);
1522
	if (!res)
1522
	if (!res)
1523
		res = ast_safe_sleep(chan, 1000);
1523
		res = ast_safe_sleep(chan, 1000);
1524

    
   
1524

   
1525
	if (!res) { /* one direction used to call park_call.... */
1525
	if (!res) { /* one direction used to call park_call.... */
1526
		struct ast_channel *parker;
1526
		struct ast_channel *parker;
1527
		struct ast_channel *parkee;
1527
		struct ast_channel *parkee;
1528
		set_peers(&parker, &parkee, peer, chan, sense);
1528
		set_peers(&parker, &parkee, peer, chan, sense);
1529
		res = masq_park_call_announce(parkee, parker, args);
1529
		res = masq_park_call_announce(parkee, parker, args);
1530
		/* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
1530
		/* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
1531
	}
1531
	}
1532

    
   
1532

   
1533
	return res;
1533
	return res;
1534
}
1534
}
1535

    
   
1535

   
1536
/*! 
1536
/*! 
1537
 * \brief support routing for one touch call parking
1537
 * \brief support routing for one touch call parking
1538
 * \param chan channel parking call
1538
 * \param chan channel parking call
1539
 * \param peer channel to be parked
1539
 * \param peer channel to be parked
1540
 * \param config unsed
1540
 * \param config unsed
1541
 * \param code unused
1541
 * \param code unused
1542
 * \param sense feature options
1542
 * \param sense feature options
1543
 *
1543
 *
1544
 * \param data
1544
 * \param data
1545
 * Setup channel, set return exten,priority to 's,1'
1545
 * Setup channel, set return exten,priority to 's,1'
1546
 * answer chan, sleep chan, park call
1546
 * answer chan, sleep chan, park call
1547
*/
1547
*/
1548
static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1548
static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1549
{
1549
{
1550
	return parkcall_helper(chan, peer, config, code, sense, NULL);
1550
	return parkcall_helper(chan, peer, config, code, sense, NULL);
1551
}
1551
}
1552

    
   
1552

   
1553
/*! \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
1553
/*! \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
1554
	other channel during the message, so please don't use this for very long messages
1554
	other channel during the message, so please don't use this for very long messages
1555
 */
1555
 */
1556
static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
1556
static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
1557
{
1557
{
1558
	/* First play for caller, put other channel on auto service */
1558
	/* First play for caller, put other channel on auto service */
1559
	if (ast_autoservice_start(callee_chan))
1559
	if (ast_autoservice_start(callee_chan))
1560
		return -1;
1560
		return -1;
1561
	ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
1561
	ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
1562
	if (ast_stream_and_wait(caller_chan, audiofile, "")) {
1562
	if (ast_stream_and_wait(caller_chan, audiofile, "")) {
1563
		ast_log(LOG_WARNING, "Failed to play automon message!\n");
1563
		ast_log(LOG_WARNING, "Failed to play automon message!\n");
1564
		ast_autoservice_stop(callee_chan);
1564
		ast_autoservice_stop(callee_chan);
1565
		return -1;
1565
		return -1;
1566
	}
1566
	}
1567
	if (ast_autoservice_stop(callee_chan))
1567
	if (ast_autoservice_stop(callee_chan))
1568
		return -1;
1568
		return -1;
1569
	/* Then play for callee, put other channel on auto service */
1569
	/* Then play for callee, put other channel on auto service */
1570
	if (ast_autoservice_start(caller_chan))
1570
	if (ast_autoservice_start(caller_chan))
1571
		return -1;
1571
		return -1;
1572
	ast_autoservice_ignore(caller_chan, AST_FRAME_DTMF_END);
1572
	ast_autoservice_ignore(caller_chan, AST_FRAME_DTMF_END);
1573
	if (ast_stream_and_wait(callee_chan, audiofile, "")) {
1573
	if (ast_stream_and_wait(callee_chan, audiofile, "")) {
1574
		ast_log(LOG_WARNING, "Failed to play automon message !\n");
1574
		ast_log(LOG_WARNING, "Failed to play automon message !\n");
1575
		ast_autoservice_stop(caller_chan);
1575
		ast_autoservice_stop(caller_chan);
1576
		return -1;
1576
		return -1;
1577
	}
1577
	}
1578
	if (ast_autoservice_stop(caller_chan))
1578
	if (ast_autoservice_stop(caller_chan))
1579
		return -1;
1579
		return -1;
1580
	return(0);
1580
	return(0);
1581
}
1581
}
1582

    
   
1582

   
1583
/*!
1583
/*!
1584
 * \brief Monitor a channel by DTMF
1584
 * \brief Monitor a channel by DTMF
1585
 * \param chan channel requesting monitor
1585
 * \param chan channel requesting monitor
1586
 * \param peer channel to be monitored
1586
 * \param peer channel to be monitored
1587
 * \param config
1587
 * \param config
1588
 * \param code
1588
 * \param code
1589
 * \param sense feature options
1589
 * \param sense feature options
1590
 *
1590
 *
1591
 * \param data
1591
 * \param data
1592
 * Check monitor app enabled, setup channels, both caller/callee chans not null
1592
 * Check monitor app enabled, setup channels, both caller/callee chans not null
1593
 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
1593
 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
1594
 * \retval AST_FEATURE_RETURN_SUCCESS on success.
1594
 * \retval AST_FEATURE_RETURN_SUCCESS on success.
1595
 * \retval -1 on error.
1595
 * \retval -1 on error.
1596
*/
1596
*/
1597
static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1597
static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1598
{
1598
{
1599
	char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1599
	char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1600
	int x = 0;
1600
	int x = 0;
1601
	size_t len;
1601
	size_t len;
1602
	struct ast_channel *caller_chan, *callee_chan;
1602
	struct ast_channel *caller_chan, *callee_chan;
1603
	const char *automon_message_start = NULL;
1603
	const char *automon_message_start = NULL;
1604
	const char *automon_message_stop = NULL;
1604
	const char *automon_message_stop = NULL;
1605

    
   
1605

   
1606
	if (!monitor_ok) {
1606
	if (!monitor_ok) {
1607
		ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1607
		ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1608
		return -1;
1608
		return -1;
1609
	}
1609
	}
1610

    
   
1610

   
1611
	if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
1611
	if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
1612
		monitor_ok = 0;
1612
		monitor_ok = 0;
1613
		ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1613
		ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1614
		return -1;
1614
		return -1;
1615
	}
1615
	}
1616

    
   
1616

   
1617
	set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1617
	set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1618
	if (caller_chan) {	/* Find extra messages */
1618
	if (caller_chan) {	/* Find extra messages */
1619
		automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
1619
		automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
1620
		automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
1620
		automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
1621
	}
1621
	}
1622

    
   
1622

   
1623
	if (!ast_strlen_zero(courtesytone)) {	/* Play courtesy tone if configured */
1623
	if (!ast_strlen_zero(courtesytone)) {	/* Play courtesy tone if configured */
1624
		if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
1624
		if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
1625
			return -1;
1625
			return -1;
1626
		}
1626
		}
1627
	}
1627
	}
1628
	
1628
	
1629
	if (callee_chan->monitor) {
1629
	if (callee_chan->monitor) {
1630
		ast_verb(4, "User hit '%s' to stop recording call.\n", code);
1630
		ast_verb(4, "User hit '%s' to stop recording call.\n", code);
1631
		if (!ast_strlen_zero(automon_message_stop)) {
1631
		if (!ast_strlen_zero(automon_message_stop)) {
1632
			play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
1632
			play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
1633
		}
1633
		}
1634
		callee_chan->monitor->stop(callee_chan, 1);
1634
		callee_chan->monitor->stop(callee_chan, 1);
1635
		return AST_FEATURE_RETURN_SUCCESS;
1635
		return AST_FEATURE_RETURN_SUCCESS;
1636
	}
1636
	}
1637

    
   
1637

   
1638
	if (caller_chan && callee_chan) {
1638
	if (caller_chan && callee_chan) {
1639
		const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
1639
		const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
1640
		const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
1640
		const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
1641
		const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
1641
		const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
1642

    
   
1642

   
1643
		if (!touch_format)
1643
		if (!touch_format)
1644
			touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
1644
			touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
1645

    
   
1645

   
1646
		if (!touch_monitor)
1646
		if (!touch_monitor)
1647
			touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
1647
			touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
1648
	
1648
	
1649
		if (!touch_monitor_prefix)
1649
		if (!touch_monitor_prefix)
1650
			touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
1650
			touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
1651
	
1651
	
1652
		if (touch_monitor) {
1652
		if (touch_monitor) {
1653
			len = strlen(touch_monitor) + 50;
1653
			len = strlen(touch_monitor) + 50;
1654
			args = alloca(len);
1654
			args = alloca(len);
1655
			touch_filename = alloca(len);
1655
			touch_filename = alloca(len);
1656
			snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
1656
			snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
1657
			snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1657
			snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1658
		} else {
1658
		} else {
1659
			caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
1659
			caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
1660
				caller_chan->caller.id.number.str, caller_chan->name));
1660
				caller_chan->caller.id.number.str, caller_chan->name));
1661
			callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
1661
			callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
1662
				callee_chan->caller.id.number.str, callee_chan->name));
1662
				callee_chan->caller.id.number.str, callee_chan->name));
1663
			len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
1663
			len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
1664
			args = alloca(len);
1664
			args = alloca(len);
1665
			touch_filename = alloca(len);
1665
			touch_filename = alloca(len);
1666
			snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
1666
			snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
1667
			snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1667
			snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1668
		}
1668
		}
1669

    
   
1669

   
1670
		for(x = 0; x < strlen(args); x++) {
1670
		for(x = 0; x < strlen(args); x++) {
1671
			if (args[x] == '/')
1671
			if (args[x] == '/')
1672
				args[x] = '-';
1672
				args[x] = '-';
1673
		}
1673
		}
1674
		
1674
		
1675
		ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
1675
		ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
1676

    
   
1676

   
1677
		pbx_exec(callee_chan, monitor_app, args);
1677
		pbx_exec(callee_chan, monitor_app, args);
1678
		pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1678
		pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1679
		pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1679
		pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1680

    
   
1680

   
1681
		if (!ast_strlen_zero(automon_message_start)) {	/* Play start message for both channels */
1681
		if (!ast_strlen_zero(automon_message_start)) {	/* Play start message for both channels */
1682
			play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
1682
			play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
1683
		}
1683
		}
1684
	
1684
	
1685
		return AST_FEATURE_RETURN_SUCCESS;
1685
		return AST_FEATURE_RETURN_SUCCESS;
1686
	}
1686
	}
1687
	
1687
	
1688
	ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");	
1688
	ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");	
1689
	return -1;
1689
	return -1;
1690
}
1690
}
1691

    
   
1691

   
1692
static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1692
static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1693
{
1693
{
1694
	char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1694
	char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1695
	int x = 0;
1695
	int x = 0;
1696
	size_t len;
1696
	size_t len;
1697
	struct ast_channel *caller_chan, *callee_chan;
1697
	struct ast_channel *caller_chan, *callee_chan;
1698
	const char *mixmonitor_spy_type = "MixMonitor";
1698
	const char *mixmonitor_spy_type = "MixMonitor";
1699
	int count = 0;
1699
	int count = 0;
1700

    
   
1700

   
1701
	if (!mixmonitor_ok) {
1701
	if (!mixmonitor_ok) {
1702
		ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1702
		ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1703
		return -1;
1703
		return -1;
1704
	}
1704
	}
1705

    
   
1705

   
1706
	if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
1706
	if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
1707
		mixmonitor_ok = 0;
1707
		mixmonitor_ok = 0;
1708
		ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1708
		ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1709
		return -1;
1709
		return -1;
1710
	}
1710
	}
1711

    
   
1711

   
1712
	set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1712
	set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1713

    
   
1713

   
1714
	if (!ast_strlen_zero(courtesytone)) {
1714
	if (!ast_strlen_zero(courtesytone)) {
1715
		if (ast_autoservice_start(callee_chan))
1715
		if (ast_autoservice_start(callee_chan))
1716
			return -1;
1716
			return -1;
1717
		ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
1717
		ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
1718
		if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
1718
		if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
1719
			ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1719
			ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1720
			ast_autoservice_stop(callee_chan);
1720
			ast_autoservice_stop(callee_chan);
1721
			return -1;
1721
			return -1;
1722
		}
1722
		}
1723
		if (ast_autoservice_stop(callee_chan))
1723
		if (ast_autoservice_stop(callee_chan))
1724
			return -1;
1724
			return -1;
1725
	}
1725
	}
1726

    
   
1726

   
1727
	ast_channel_lock(callee_chan);
1727
	ast_channel_lock(callee_chan);
1728
	count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
1728
	count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
1729
	ast_channel_unlock(callee_chan);
1729
	ast_channel_unlock(callee_chan);
1730

    
   
1730

   
1731
	/* This means a mixmonitor is attached to the channel, running or not is unknown. */
1731
	/* This means a mixmonitor is attached to the channel, running or not is unknown. */
1732
	if (count > 0) {
1732
	if (count > 0) {
1733
		
1733
		
1734
		ast_verb(3, "User hit '%s' to stop recording call.\n", code);
1734
		ast_verb(3, "User hit '%s' to stop recording call.\n", code);
1735

    
   
1735

   
1736
		/* Make sure they are running */
1736
		/* Make sure they are running */
1737
		ast_channel_lock(callee_chan);
1737
		ast_channel_lock(callee_chan);
1738
		count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
1738
		count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
1739
		ast_channel_unlock(callee_chan);
1739
		ast_channel_unlock(callee_chan);
1740
		if (count > 0) {
1740
		if (count > 0) {
1741
			if (!stopmixmonitor_ok) {
1741
			if (!stopmixmonitor_ok) {
1742
				ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
1742
				ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
1743
				return -1;
1743
				return -1;
1744
			}
1744
			}
1745
			if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
1745
			if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
1746
				stopmixmonitor_ok = 0;
1746
				stopmixmonitor_ok = 0;
1747
				ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
1747
				ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
1748
				return -1;
1748
				return -1;
1749
			} else {
1749
			} else {
1750
				pbx_exec(callee_chan, stopmixmonitor_app, "");
1750
				pbx_exec(callee_chan, stopmixmonitor_app, "");
1751
				return AST_FEATURE_RETURN_SUCCESS;
1751
				return AST_FEATURE_RETURN_SUCCESS;
1752
			}
1752
			}
1753
		}
1753
		}
1754
		
1754
		
1755
		ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");	
1755
		ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");	
1756
	}			
1756
	}			
1757

    
   
1757

   
1758
	if (caller_chan && callee_chan) {
1758
	if (caller_chan && callee_chan) {
1759
		const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
1759
		const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
1760
		const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
1760
		const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
1761

    
   
1761

   
1762
		if (!touch_format)
1762
		if (!touch_format)
1763
			touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
1763
			touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
1764

    
   
1764

   
1765
		if (!touch_monitor)
1765
		if (!touch_monitor)
1766
			touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
1766
			touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
1767

    
   
1767

   
1768
		if (touch_monitor) {
1768
		if (touch_monitor) {
1769
			len = strlen(touch_monitor) + 50;
1769
			len = strlen(touch_monitor) + 50;
1770
			args = alloca(len);
1770
			args = alloca(len);
1771
			touch_filename = alloca(len);
1771
			touch_filename = alloca(len);
1772
			snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
1772
			snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
1773
			snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
1773
			snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
1774
		} else {
1774
		} else {
1775
			caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
1775
			caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
1776
				caller_chan->caller.id.number.str, caller_chan->name));
1776
				caller_chan->caller.id.number.str, caller_chan->name));
1777
			callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
1777
			callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
1778
				callee_chan->caller.id.number.str, callee_chan->name));
1778
				callee_chan->caller.id.number.str, callee_chan->name));
1779
			len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
1779
			len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
1780
			args = alloca(len);
1780
			args = alloca(len);
1781
			touch_filename = alloca(len);
1781
			touch_filename = alloca(len);
1782
			snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
1782
			snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
1783
			snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
1783
			snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
1784
		}
1784
		}
1785

    
   
1785

   
1786
		for( x = 0; x < strlen(args); x++) {
1786
		for( x = 0; x < strlen(args); x++) {
1787
			if (args[x] == '/')
1787
			if (args[x] == '/')
1788
				args[x] = '-';
1788
				args[x] = '-';
1789
		}
1789
		}
1790

    
   
1790

   
1791
		ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
1791
		ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
1792

    
   
1792

   
1793
		pbx_exec(callee_chan, mixmonitor_app, args);
1793
		pbx_exec(callee_chan, mixmonitor_app, args);
1794
		pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1794
		pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1795
		pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1795
		pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1796
		return AST_FEATURE_RETURN_SUCCESS;
1796
		return AST_FEATURE_RETURN_SUCCESS;
1797
	
1797
	
1798
	}
1798
	}
1799

    
   
1799

   
1800
	ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
1800
	ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
1801
	return -1;
1801
	return -1;
1802

    
   
1802

   
1803
}
1803
}
1804

    
   
1804

   
1805
static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1805
static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1806
{
1806
{
1807
	ast_verb(4, "User hit '%s' to disconnect call.\n", code);
1807
	ast_verb(4, "User hit '%s' to disconnect call.\n", code);
1808
	return AST_FEATURE_RETURN_HANGUP;
1808
	return AST_FEATURE_RETURN_HANGUP;
1809
}
1809
}
1810

    
   
1810

   
1811
static int finishup(struct ast_channel *chan)
1811
static int finishup(struct ast_channel *chan)
1812
{
1812
{
1813
	ast_indicate(chan, AST_CONTROL_UNHOLD);
1813
	ast_indicate(chan, AST_CONTROL_UNHOLD);
1814

    
   
1814

   
1815
	return ast_autoservice_stop(chan);
1815
	return ast_autoservice_stop(chan);
1816
}
1816
}
1817

    
   
1817

   
1818
/*!
1818
/*!
1819
 * \brief Find the context for the transfer
1819
 * \brief Find the context for the transfer
1820
 * \param transferer
1820
 * \param transferer
1821
 * \param transferee
1821
 * \param transferee
1822
 * 
1822
 * 
1823
 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
1823
 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
1824
 * \return a context string
1824
 * \return a context string
1825
*/
1825
*/
1826
static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
1826
static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
1827
{
1827
{
1828
	const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
1828
	const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
1829
	if (ast_strlen_zero(s)) {
1829
	if (ast_strlen_zero(s)) {
1830
		s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
1830
		s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
1831
	}
1831
	}
1832
	if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
1832
	if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
1833
		s = transferer->macrocontext;
1833
		s = transferer->macrocontext;
1834
	}
1834
	}
1835
	if (ast_strlen_zero(s)) {
1835
	if (ast_strlen_zero(s)) {
1836
		s = transferer->context;
1836
		s = transferer->context;
1837
	}
1837
	}
1838
	return s;  
1838
	return s;  
1839
}
1839
}
1840

    
   
1840

   
1841
/*!
1841
/*!
1842
 * \brief Blind transfer user to another extension
1842
 * \brief Blind transfer user to another extension
1843
 * \param chan channel to be transfered
1843
 * \param chan channel to be transfered
1844
 * \param peer channel initiated blind transfer
1844
 * \param peer channel initiated blind transfer
1845
 * \param config
1845
 * \param config
1846
 * \param code
1846
 * \param code
1847
 * \param data
1847
 * \param data
1848
 * \param sense  feature options
1848
 * \param sense  feature options
1849
 * 
1849
 * 
1850
 * Place chan on hold, check if transferred to parkinglot extension,
1850
 * Place chan on hold, check if transferred to parkinglot extension,
1851
 * otherwise check extension exists and transfer caller.
1851
 * otherwise check extension exists and transfer caller.
1852
 * \retval AST_FEATURE_RETURN_SUCCESS.
1852
 * \retval AST_FEATURE_RETURN_SUCCESS.
1853
 * \retval -1 on failure.
1853
 * \retval -1 on failure.
1854
*/
1854
*/
1855
static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1855
static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1856
{
1856
{
1857
	struct ast_channel *transferer;
1857
	struct ast_channel *transferer;
1858
	struct ast_channel *transferee;
1858
	struct ast_channel *transferee;
1859
	const char *transferer_real_context;
1859
	const char *transferer_real_context;
1860
	struct ast_parkinglot *found_lot = NULL;
1860
	struct ast_parkinglot *found_lot = NULL;
1861
	char xferto[256];
1861
	char xferto[256];
1862
	int res, parkstatus = 0;
1862
	int res, parkstatus = 0;
1863

    
   
1863

   
1864
	set_peers(&transferer, &transferee, peer, chan, sense);
1864
	set_peers(&transferer, &transferee, peer, chan, sense);
1865
	transferer_real_context = real_ctx(transferer, transferee);
1865
	transferer_real_context = real_ctx(transferer, transferee);
1866
	/* Start autoservice on chan while we talk to the originator */
1866
	/* Start autoservice on chan while we talk to the originator */
1867
	ast_autoservice_start(transferee);
1867
	ast_autoservice_start(transferee);
1868
	ast_autoservice_ignore(transferee, AST_FRAME_DTMF_END);
1868
	ast_autoservice_ignore(transferee, AST_FRAME_DTMF_END);
1869
	ast_indicate(transferee, AST_CONTROL_HOLD);
1869
	ast_indicate(transferee, AST_CONTROL_HOLD);
1870

    
   
1870

   
1871
	memset(xferto, 0, sizeof(xferto));
1871
	memset(xferto, 0, sizeof(xferto));
1872

    
   
1872

   
1873
	/* Transfer */
1873
	/* Transfer */
1874
	res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1874
	res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1875
	if (res < 0) {
1875
	if (res < 0) {
1876
		finishup(transferee);
1876
		finishup(transferee);
1877
		return -1; /* error ? */
1877
		return -1; /* error ? */
1878
	}
1878
	}
1879
	if (res > 0)	/* If they've typed a digit already, handle it */
1879
	if (res > 0)	/* If they've typed a digit already, handle it */
1880
		xferto[0] = (char) res;
1880
		xferto[0] = (char) res;
1881

    
   
1881

   
1882
	ast_stopstream(transferer);
1882
	ast_stopstream(transferer);
1883
	res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1883
	res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1884
	if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
1884
	if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
1885
		finishup(transferee);
1885
		finishup(transferee);
1886
		return -1;
1886
		return -1;
1887
	}
1887
	}
1888
	if (res == 0) {
1888
	if (res == 0) {
1889
		if (xferto[0]) {
1889
		if (xferto[0]) {
1890
			ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
1890
			ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
1891
				xferto, transferer_real_context);
1891
				xferto, transferer_real_context);
1892
		} else {
1892
		} else {
1893
			/* Does anyone care about this case? */
1893
			/* Does anyone care about this case? */
1894
			ast_log(LOG_WARNING, "No digits dialed.\n");
1894
			ast_log(LOG_WARNING, "No digits dialed.\n");
1895
		}
1895
		}
1896
		ast_stream_and_wait(transferer, "pbx-invalid", "");
1896
		ast_stream_and_wait(transferer, "pbx-invalid", "");
1897
		finishup(transferee);
1897
		finishup(transferee);
1898
		return AST_FEATURE_RETURN_SUCCESS;
1898
		return AST_FEATURE_RETURN_SUCCESS;
1899
	}
1899
	}
1900

    
   
1900

   
1901
	found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
1901
	found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
1902
	if (found_lot) {
1902
	if (found_lot) {
1903
		struct ast_park_call_args args = {
1903
		struct ast_park_call_args args = {
1904
			.parkinglot = found_lot,
1904
			.parkinglot = found_lot,
1905
		};
1905
		};
1906
		res = finishup(transferee);
1906
		res = finishup(transferee);
1907
		if (res) {
1907
		if (res) {
1908
		} else if (!(parkstatus = masq_park_call_announce(transferee, transferer, &args))) {	/* success */
1908
		} else if (!(parkstatus = masq_park_call_announce(transferee, transferer, &args))) {	/* success */
1909
			/* We return non-zero, but tell the PBX not to hang the channel when
1909
			/* We return non-zero, but tell the PBX not to hang the channel when
1910
			   the thread dies -- We have to be careful now though.  We are responsible for 
1910
			   the thread dies -- We have to be careful now though.  We are responsible for 
1911
			   hanging up the channel, else it will never be hung up! */
1911
			   hanging up the channel, else it will never be hung up! */
1912

    
   
1912

   
1913
			return 0;
1913
			return 0;
1914
		} else {
1914
		} else {
1915
			ast_log(LOG_WARNING, "Unable to park call %s, parkstatus = %d\n", transferee->name, parkstatus);
1915
			ast_log(LOG_WARNING, "Unable to park call %s, parkstatus = %d\n", transferee->name, parkstatus);
1916
		}
1916
		}
1917
		ast_autoservice_start(transferee);
1917
		ast_autoservice_start(transferee);
1918
	} else {
1918
	} else {
1919
		ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
1919
		ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
1920
		pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
1920
		pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
1921
		pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
1921
		pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
1922
		res=finishup(transferee);
1922
		res=finishup(transferee);
1923
		if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
1923
		if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
1924
			transferer->cdr=ast_cdr_alloc();
1924
			transferer->cdr=ast_cdr_alloc();
1925
			if (transferer->cdr) {
1925
			if (transferer->cdr) {
1926
				ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
1926
				ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
1927
				ast_cdr_start(transferer->cdr);
1927
				ast_cdr_start(transferer->cdr);
1928
			}
1928
			}
1929
		}
1929
		}
1930
		if (transferer->cdr) {
1930
		if (transferer->cdr) {
1931
			struct ast_cdr *swap = transferer->cdr;
1931
			struct ast_cdr *swap = transferer->cdr;
1932
			ast_debug(1, "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
1932
			ast_debug(1, "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
1933
					transferer->name, transferee->name, transferer->cdr->lastapp, transferer->cdr->lastdata, 
1933
					transferer->name, transferee->name, transferer->cdr->lastapp, transferer->cdr->lastdata, 
1934
					transferer->cdr->channel, transferer->cdr->dstchannel);
1934
					transferer->cdr->channel, transferer->cdr->dstchannel);
1935
			ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
1935
			ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
1936
					transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel, transferee->cdr->dstchannel);
1936
					transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel, transferee->cdr->dstchannel);
1937
			ast_debug(1, "transferer_real_context=%s; xferto=%s\n", transferer_real_context, xferto);
1937
			ast_debug(1, "transferer_real_context=%s; xferto=%s\n", transferer_real_context, xferto);
1938
			/* swap cdrs-- it will save us some time & work */
1938
			/* swap cdrs-- it will save us some time & work */
1939
			transferer->cdr = transferee->cdr;
1939
			transferer->cdr = transferee->cdr;
1940
			transferee->cdr = swap;
1940
			transferee->cdr = swap;
1941
		}
1941
		}
1942
		if (!transferee->pbx) {
1942
		if (!transferee->pbx) {
1943
			/* Doh!  Use our handy async_goto functions */
1943
			/* Doh!  Use our handy async_goto functions */
1944
			ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
1944
			ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
1945
								,transferee->name, xferto, transferer_real_context);
1945
								,transferee->name, xferto, transferer_real_context);
1946
			if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
1946
			if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
1947
				ast_log(LOG_WARNING, "Async goto failed :-(\n");
1947
				ast_log(LOG_WARNING, "Async goto failed :-(\n");
1948
		} else {
1948
		} else {
1949
			/* Set the channel's new extension, since it exists, using transferer context */
1949
			/* Set the channel's new extension, since it exists, using transferer context */
1950
			ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
1950
			ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
1951
			ast_debug(1, "ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
1951
			ast_debug(1, "ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
1952
			if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
1952
			if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
1953
				ast_channel_update_connected_line(transferer, &transferer->connected, NULL);
1953
				ast_channel_update_connected_line(transferer, &transferer->connected, NULL);
1954
			}
1954
			}
1955
			set_c_e_p(transferee, transferer_real_context, xferto, 0);
1955
			set_c_e_p(transferee, transferer_real_context, xferto, 0);
1956
		}
1956
		}
1957
		check_goto_on_transfer(transferer);
1957
		check_goto_on_transfer(transferer);
1958
		return res;
1958
		return res;
1959
	}
1959
	}
1960
	if (parkstatus != AST_FEATURE_RETURN_PARKFAILED
1960
	if (parkstatus != AST_FEATURE_RETURN_PARKFAILED
1961
		&& ast_stream_and_wait(transferer, xferfailsound, "")) {
1961
		&& ast_stream_and_wait(transferer, xferfailsound, "")) {
1962
		finishup(transferee);
1962
		finishup(transferee);
1963
		return -1;
1963
		return -1;
1964
	}
1964
	}
1965
	ast_stopstream(transferer);
1965
	ast_stopstream(transferer);
1966
	res = finishup(transferee);
1966
	res = finishup(transferee);
1967
	if (res) {
1967
	if (res) {
1968
		ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
1968
		ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
1969
		return res;
1969
		return res;
1970
	}
1970
	}
1971
	return AST_FEATURE_RETURN_SUCCESS;
1971
	return AST_FEATURE_RETURN_SUCCESS;
1972
}
1972
}
1973

    
   
1973

   
1974
/*!
1974
/*!
1975
 * \brief make channels compatible
1975
 * \brief make channels compatible
1976
 * \param c
1976
 * \param c
1977
 * \param newchan
1977
 * \param newchan
1978
 * \retval 0 on success.
1978
 * \retval 0 on success.
1979
 * \retval -1 on failure.
1979
 * \retval -1 on failure.
1980
*/
1980
*/
1981
static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
1981
static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
1982
{
1982
{
1983
	if (ast_channel_make_compatible(c, newchan) < 0) {
1983
	if (ast_channel_make_compatible(c, newchan) < 0) {
1984
		ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
1984
		ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
1985
			c->name, newchan->name);
1985
			c->name, newchan->name);
1986
		ast_hangup(newchan);
1986
		ast_hangup(newchan);
1987
		return -1;
1987
		return -1;
1988
	}
1988
	}
1989
	return 0;
1989
	return 0;
1990
}
1990
}
1991

    
   
1991

   
1992
/*!
1992
/*!
1993
 * \internal
1993
 * \internal
1994
 * \brief Builtin attended transfer failed cleanup.
1994
 * \brief Builtin attended transfer failed cleanup.
1995
 * \since 1.10
1995
 * \since 1.10
1996
 *
1996
 *
1997
 * \param transferee Party A in the transfer.
1997
 * \param transferee Party A in the transfer.
1998
 * \param transferer Party B in the transfer.
1998
 * \param transferer Party B in the transfer.
1999
 * \param connected_line Saved connected line info about party A.
1999
 * \param connected_line Saved connected line info about party A.
2000
 *
2000
 *
2001
 * \note The connected_line data is freed.
2001
 * \note The connected_line data is freed.
2002
 *
2002
 *
2003
 * \return Nothing
2003
 * \return Nothing
2004
 */
2004
 */
2005
static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
2005
static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
2006
{
2006
{
2007
	finishup(transferee);
2007
	finishup(transferee);
2008

    
   
2008

   
2009
	/*
2009
	/*
2010
	 * Restore party B connected line info about party A.
2010
	 * Restore party B connected line info about party A.
2011
	 *
2011
	 *
2012
	 * Party B was the caller to party C and is the last known mode
2012
	 * Party B was the caller to party C and is the last known mode
2013
	 * for party B.
2013
	 * for party B.
2014
	 */
2014
	 */
2015
	if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
2015
	if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
2016
		ast_channel_update_connected_line(transferer, connected_line, NULL);
2016
		ast_channel_update_connected_line(transferer, connected_line, NULL);
2017
	}
2017
	}
2018
	ast_party_connected_line_free(connected_line);
2018
	ast_party_connected_line_free(connected_line);
2019
}
2019
}
2020

    
   
2020

   
2021
/*!
2021
/*!
2022
 * \brief Attended transfer
2022
 * \brief Attended transfer
2023
 * \param chan transfered user
2023
 * \param chan transfered user
2024
 * \param peer person transfering call
2024
 * \param peer person transfering call
2025
 * \param config
2025
 * \param config
2026
 * \param code
2026
 * \param code
2027
 * \param sense feature options
2027
 * \param sense feature options
2028
 *
2028
 *
2029
 * \param data
2029
 * \param data
2030
 * Get extension to transfer to, if you cannot generate channel (or find extension)
2030
 * Get extension to transfer to, if you cannot generate channel (or find extension)
2031
 * return to host channel. After called channel answered wait for hangup of transferer,
2031
 * return to host channel. After called channel answered wait for hangup of transferer,
2032
 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
2032
 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
2033
 *
2033
 *
2034
 * \return -1 on failure
2034
 * \return -1 on failure
2035
*/
2035
*/
2036
static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2036
static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2037
{
2037
{
2038
	struct ast_channel *transferer;/* Party B */
2038
	struct ast_channel *transferer;/* Party B */
2039
	struct ast_channel *transferee;/* Party A */
2039
	struct ast_channel *transferee;/* Party A */
2040
	const char *transferer_real_context;
2040
	const char *transferer_real_context;
2041
	char xferto[256] = "";
2041
	char xferto[256] = "";
2042
	int res;
2042
	int res;
2043
	int outstate=0;
2043
	int outstate=0;
2044
	struct ast_channel *newchan;
2044
	struct ast_channel *newchan;
2045
	struct ast_channel *xferchan;
2045
	struct ast_channel *xferchan;
2046
	struct ast_bridge_thread_obj *tobj;
2046
	struct ast_bridge_thread_obj *tobj;
2047
	struct ast_bridge_config bconfig;
2047
	struct ast_bridge_config bconfig;
2048
	int l;
2048
	int l;
2049
	struct ast_party_connected_line connected_line;
2049
	struct ast_party_connected_line connected_line;
2050
	struct ast_datastore *features_datastore;
2050
	struct ast_datastore *features_datastore;
2051
	struct ast_dial_features *dialfeatures = NULL;
2051
	struct ast_dial_features *dialfeatures = NULL;
2052
	struct ast_parkinglot *parkinglot;
2052
	struct ast_parkinglot *parkinglot;
2053
	char *transferer_tech;
2053
	char *transferer_tech;
2054
	char *transferer_name;
2054
	char *transferer_name;
2055
	char *transferer_name_orig;
2055
	char *transferer_name_orig;
2056
	char *dash;
2056
	char *dash;
2057

    
   
2057

   
2058
	ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2058
	ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2059
	set_peers(&transferer, &transferee, peer, chan, sense);
2059
	set_peers(&transferer, &transferee, peer, chan, sense);
2060
	transferer_real_context = real_ctx(transferer, transferee);
2060
	transferer_real_context = real_ctx(transferer, transferee);
2061

    
   
2061

   
2062
	/* Start autoservice on transferee while we talk to the transferer */
2062
	/* Start autoservice on transferee while we talk to the transferer */
2063
	ast_autoservice_start(transferee);
2063
	ast_autoservice_start(transferee);
2064
	ast_indicate(transferee, AST_CONTROL_HOLD);
2064
	ast_indicate(transferee, AST_CONTROL_HOLD);
2065

    
   
2065

   
2066
	/* Transfer */
2066
	/* Transfer */
2067
	res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2067
	res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2068
	if (res < 0) {
2068
	if (res < 0) {
2069
		finishup(transferee);
2069
		finishup(transferee);
2070
		return -1;
2070
		return -1;
2071
	}
2071
	}
2072
	if (res > 0) /* If they've typed a digit already, handle it */
2072
	if (res > 0) /* If they've typed a digit already, handle it */
2073
		xferto[0] = (char) res;
2073
		xferto[0] = (char) res;
2074

    
   
2074

   
2075
	/* this is specific of atxfer */
2075
	/* this is specific of atxfer */
2076
	res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2076
	res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2077
	if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
2077
	if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
2078
		finishup(transferee);
2078
		finishup(transferee);
2079
		return -1;
2079
		return -1;
2080
	}
2080
	}
2081
	l = strlen(xferto);
2081
	l = strlen(xferto);
2082
	if (res == 0) {
2082
	if (res == 0) {
2083
		if (l) {
2083
		if (l) {
2084
			ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2084
			ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2085
				xferto, transferer_real_context);
2085
				xferto, transferer_real_context);
2086
		} else {
2086
		} else {
2087
			/* Does anyone care about this case? */
2087
			/* Does anyone care about this case? */
2088
			ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
2088
			ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
2089
		}
2089
		}
2090
		ast_stream_and_wait(transferer, "pbx-invalid", "");
2090
		ast_stream_and_wait(transferer, "pbx-invalid", "");
2091
		finishup(transferee);
2091
		finishup(transferee);
2092
		return AST_FEATURE_RETURN_SUCCESS;
2092
		return AST_FEATURE_RETURN_SUCCESS;
2093
	}
2093
	}
2094

    
   
2094

   
2095
	/* If we are attended transfering to parking, just use parkcall_helper instead of trying to track all of
2095
	/* If we are attended transfering to parking, just use parkcall_helper instead of trying to track all of
2096
	 * the different variables for handling this properly with a builtin_atxfer */
2096
	 * the different variables for handling this properly with a builtin_atxfer */
2097
	parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
2097
	parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
2098
	if (parkinglot) {
2098
	if (parkinglot) {
2099
		struct ast_park_call_args args = {
2099
		struct ast_park_call_args args = {
2100
			.parkinglot = parkinglot,
2100
			.parkinglot = parkinglot,
2101
		};
2101
		};
2102
		finishup(transferee);
2102
		finishup(transferee);
2103
		return parkcall_helper(chan, peer, config, code, sense, &args);
2103
		return parkcall_helper(chan, peer, config, code, sense, &args);
2104
	}
2104
	}
2105

    
   
2105

   
2106
	/* Append context to dialed transfer number. */
2106
	/* Append context to dialed transfer number. */
2107
	snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
2107
	snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
2108

    
   
2108

   
2109
	/* If we are performing an attended transfer and we have two channels involved then
2109
	/* If we are performing an attended transfer and we have two channels involved then
2110
	   copy sound file information to play upon attended transfer completion */
2110
	   copy sound file information to play upon attended transfer completion */
2111
	if (transferee) {
2111
	if (transferee) {
2112
		const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2112
		const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2113
		const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2113
		const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2114

    
   
2114

   
2115
		if (!ast_strlen_zero(chan1_attended_sound)) {
2115
		if (!ast_strlen_zero(chan1_attended_sound)) {
2116
			pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
2116
			pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
2117
		}
2117
		}
2118
		if (!ast_strlen_zero(chan2_attended_sound)) {
2118
		if (!ast_strlen_zero(chan2_attended_sound)) {
2119
			pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
2119
			pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
2120
		}
2120
		}
2121
	}
2121
	}
2122

    
   
2122

   
2123
	/* Extract redial transferer information from the channel name. */
2123
	/* Extract redial transferer information from the channel name. */
2124
	transferer_name_orig = ast_strdupa(transferer->name);
2124
	transferer_name_orig = ast_strdupa(transferer->name);
2125
	transferer_name = ast_strdupa(transferer_name_orig);
2125
	transferer_name = ast_strdupa(transferer_name_orig);
2126
	transferer_tech = strsep(&transferer_name, "/");
2126
	transferer_tech = strsep(&transferer_name, "/");
2127
	dash = strrchr(transferer_name, '-');
2127
	dash = strrchr(transferer_name, '-');
2128
	if (dash) {
2128
	if (dash) {
2129
		/* Trim off channel name sequence/serial number. */
2129
		/* Trim off channel name sequence/serial number. */
2130
		*dash = '\0';
2130
		*dash = '\0';
2131
	}
2131
	}
2132

    
   
2132

   
2133
	/* Stop autoservice so we can monitor all parties involved in the transfer. */
2133
	/* Stop autoservice so we can monitor all parties involved in the transfer. */
2134
	if (ast_autoservice_stop(transferee) < 0) {
2134
	if (ast_autoservice_stop(transferee) < 0) {
2135
		ast_indicate(transferee, AST_CONTROL_UNHOLD);
2135
		ast_indicate(transferee, AST_CONTROL_UNHOLD);
2136
		return -1;
2136
		return -1;
2137
	}
2137
	}
2138

    
   
2138

   
2139
	/* Save connected line info for party B about party A in case transfer fails. */
2139
	/* Save connected line info for party B about party A in case transfer fails. */
2140
	ast_party_connected_line_init(&connected_line);
2140
	ast_party_connected_line_init(&connected_line);
2141
	ast_channel_lock(transferer);
2141
	ast_channel_lock(transferer);
2142
	ast_party_connected_line_copy(&connected_line, &transferer->connected);
2142
	ast_party_connected_line_copy(&connected_line, &transferer->connected);
2143
	ast_channel_unlock(transferer);
2143
	ast_channel_unlock(transferer);
2144
	connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2144
	connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2145

    
   
2145

   
2146
	/* Dial party C */
2146
	/* Dial party C */
2147
	newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
2147
	newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
2148
		transferee, "Local", transferer->nativeformats, xferto,
2148
		transferee, "Local", transferer->nativeformats, xferto,
2149
		atxfernoanswertimeout, &outstate, transferer->language);
2149
		atxfernoanswertimeout, &outstate, transferer->language);
2150
	ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
2150
	ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
2151

    
   
2151

   
2152
	if (!ast_check_hangup(transferer)) {
2152
	if (!ast_check_hangup(transferer)) {
2153
		int hangup_dont = 0;
2153
		int hangup_dont = 0;
2154

    
   
2154

   
2155
		/* Transferer (party B) is up */
2155
		/* Transferer (party B) is up */
2156
		ast_debug(1, "Actually doing an attended transfer.\n");
2156
		ast_debug(1, "Actually doing an attended transfer.\n");
2157

    
   
2157

   
2158
		/* Start autoservice on transferee while the transferer deals with party C. */
2158
		/* Start autoservice on transferee while the transferer deals with party C. */
2159
		ast_autoservice_start(transferee);
2159
		ast_autoservice_start(transferee);
2160

    
   
2160

   
2161
		ast_indicate(transferer, -1);
2161
		ast_indicate(transferer, -1);
2162
		if (!newchan) {
2162
		if (!newchan) {
2163
			/* any reason besides user requested cancel and busy triggers the failed sound */
2163
			/* any reason besides user requested cancel and busy triggers the failed sound */
2164
			switch (outstate) {
2164
			switch (outstate) {
2165
			case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
2165
			case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
2166
			case AST_CONTROL_BUSY:
2166
			case AST_CONTROL_BUSY:
2167
			case AST_CONTROL_CONGESTION:
2167
			case AST_CONTROL_CONGESTION:
2168
				if (ast_stream_and_wait(transferer, xfersound, "")) {
2168
				if (ast_stream_and_wait(transferer, xfersound, "")) {
2169
					ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2169
					ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2170
				}
2170
				}
2171
				break;
2171
				break;
2172
			default:
2172
			default:
2173
				if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2173
				if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2174
					ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2174
					ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2175
				}
2175
				}
2176
				break;
2176
				break;
2177
			}
2177
			}
2178
			atxfer_fail_cleanup(transferee, transferer, &connected_line);
2178
			atxfer_fail_cleanup(transferee, transferer, &connected_line);
2179
			return AST_FEATURE_RETURN_SUCCESS;
2179
			return AST_FEATURE_RETURN_SUCCESS;
2180
		}
2180
		}
2181

    
   
2181

   
2182
		if (check_compat(transferer, newchan)) {
2182
		if (check_compat(transferer, newchan)) {
2183
			if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2183
			if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2184
				ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2184
				ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2185
			}
2185
			}
2186
			atxfer_fail_cleanup(transferee, transferer, &connected_line);
2186
			atxfer_fail_cleanup(transferee, transferer, &connected_line);
2187
			return AST_FEATURE_RETURN_SUCCESS;
2187
			return AST_FEATURE_RETURN_SUCCESS;
2188
		}
2188
		}
2189
		memset(&bconfig,0,sizeof(struct ast_bridge_config));
2189
		memset(&bconfig,0,sizeof(struct ast_bridge_config));
2190
		ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
2190
		ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
2191
		ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
2191
		ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
2192

    
   
2192

   
2193
		/* ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we don't
2193
		/* ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we don't
2194
		   want that to happen here because we're also in another bridge already
2194
		   want that to happen here because we're also in another bridge already
2195
		 */
2195
		 */
2196
		if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
2196
		if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
2197
			hangup_dont = 1;
2197
			hangup_dont = 1;
2198
		}
2198
		}
2199
		/* Let party B and party C talk as long as they want. */
2199
		/* Let party B and party C talk as long as they want. */
2200
		ast_bridge_call(transferer, newchan, &bconfig);
2200
		ast_bridge_call(transferer, newchan, &bconfig);
2201
		if (hangup_dont) {
2201
		if (hangup_dont) {
2202
			ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
2202
			ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
2203
		}
2203
		}
2204

    
   
2204

   
2205
		if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
2205
		if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
2206
			ast_hangup(newchan);
2206
			ast_hangup(newchan);
2207
			if (ast_stream_and_wait(transferer, xfersound, "")) {
2207
			if (ast_stream_and_wait(transferer, xfersound, "")) {
2208
				ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2208
				ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2209
			}
2209
			}
2210
			atxfer_fail_cleanup(transferee, transferer, &connected_line);
2210
			atxfer_fail_cleanup(transferee, transferer, &connected_line);
2211
			return AST_FEATURE_RETURN_SUCCESS;
2211
			return AST_FEATURE_RETURN_SUCCESS;
2212
		}
2212
		}
2213

    
   
2213

   
2214
		/* Transferer (party B) is confirmed hung up at this point. */
2214
		/* Transferer (party B) is confirmed hung up at this point. */
2215
		if (check_compat(transferee, newchan)) {
2215
		if (check_compat(transferee, newchan)) {
2216
			finishup(transferee);
2216
			finishup(transferee);
2217
			ast_party_connected_line_free(&connected_line);
2217
			ast_party_connected_line_free(&connected_line);
2218
			return -1;
2218
			return -1;
2219
		}
2219
		}
2220

    
   
2220

   
2221
		ast_indicate(transferee, AST_CONTROL_UNHOLD);
2221
		ast_indicate(transferee, AST_CONTROL_UNHOLD);
2222
		if ((ast_autoservice_stop(transferee) < 0)
2222
		if ((ast_autoservice_stop(transferee) < 0)
2223
			|| (ast_waitfordigit(transferee, 100) < 0)
2223
			|| (ast_waitfordigit(transferee, 100) < 0)
2224
			|| (ast_waitfordigit(newchan, 100) < 0)
2224
			|| (ast_waitfordigit(newchan, 100) < 0)
2225
			|| ast_check_hangup(transferee)
2225
			|| ast_check_hangup(transferee)
2226
			|| ast_check_hangup(newchan)) {
2226
			|| ast_check_hangup(newchan)) {
2227
			ast_hangup(newchan);
2227
			ast_hangup(newchan);
2228
			ast_party_connected_line_free(&connected_line);
2228
			ast_party_connected_line_free(&connected_line);
2229
			return -1;
2229
			return -1;
2230
		}
2230
		}
2231
	} else if (!ast_check_hangup(transferee)) {
2231
	} else if (!ast_check_hangup(transferee)) {
2232
		/* Transferer (party B) has hung up at this point.  Doing blonde transfer. */
2232
		/* Transferer (party B) has hung up at this point.  Doing blonde transfer. */
2233
		ast_debug(1, "Actually doing a blonde transfer.\n");
2233
		ast_debug(1, "Actually doing a blonde transfer.\n");
2234

    
   
2234

   
2235
		if (!newchan && !atxferdropcall) {
2235
		if (!newchan && !atxferdropcall) {
2236
			/* Party C is not available, try to call party B back. */
2236
			/* Party C is not available, try to call party B back. */
2237
			unsigned int tries = 0;
2237
			unsigned int tries = 0;
2238

    
   
2238

   
2239
			if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
2239
			if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
2240
				ast_log(LOG_WARNING,
2240
				ast_log(LOG_WARNING,
2241
					"Transferer channel name: '%s' cannot be used for callback.\n",
2241
					"Transferer channel name: '%s' cannot be used for callback.\n",
2242
					transferer_name_orig);
2242
					transferer_name_orig);
2243
				ast_indicate(transferee, AST_CONTROL_UNHOLD);
2243
				ast_indicate(transferee, AST_CONTROL_UNHOLD);
2244
				ast_party_connected_line_free(&connected_line);
2244
				ast_party_connected_line_free(&connected_line);
2245
				return -1;
2245
				return -1;
2246
			}
2246
			}
2247

    
   
2247

   
2248
			tries = 0;
2248
			tries = 0;
2249
			for (;;) {
2249
			for (;;) {
2250
				/* Try to get party B back. */
2250
				/* Try to get party B back. */
2251
				ast_debug(1, "We're trying to callback %s/%s\n",
2251
				ast_debug(1, "We're trying to callback %s/%s\n",
2252
					transferer_tech, transferer_name);
2252
					transferer_tech, transferer_name);
2253
				newchan = feature_request_and_dial(transferer, transferer_name_orig,
2253
				newchan = feature_request_and_dial(transferer, transferer_name_orig,
2254
					transferee, transferee, transferer_tech,
2254
					transferee, transferee, transferer_tech,
2255
					transferee->nativeformats, transferer_name,
2255
					transferee->nativeformats, transferer_name,
2256
					atxfernoanswertimeout, &outstate, transferer->language);
2256
					atxfernoanswertimeout, &outstate, transferer->language);
2257
				ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
2257
				ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
2258
					!!newchan, outstate);
2258
					!!newchan, outstate);
2259
				if (newchan || ast_check_hangup(transferee)) {
2259
				if (newchan || ast_check_hangup(transferee)) {
2260
					break;
2260
					break;
2261
				}
2261
				}
2262
				++tries;
2262
				++tries;
2263
				if (atxfercallbackretries <= tries) {
2263
				if (atxfercallbackretries <= tries) {
2264
					/* No more callback tries remaining. */
2264
					/* No more callback tries remaining. */
2265
					break;
2265
					break;
2266
				}
2266
				}
2267

    
   
2267

   
2268
				if (atxferloopdelay) {
2268
				if (atxferloopdelay) {
2269
					/* Transfer failed, sleeping */
2269
					/* Transfer failed, sleeping */
2270
					ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
2270
					ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
2271
						atxferloopdelay);
2271
						atxferloopdelay);
2272
					ast_safe_sleep(transferee, atxferloopdelay);
2272
					ast_safe_sleep(transferee, atxferloopdelay);
2273
					if (ast_check_hangup(transferee)) {
2273
					if (ast_check_hangup(transferee)) {
2274
						ast_party_connected_line_free(&connected_line);
2274
						ast_party_connected_line_free(&connected_line);
2275
						return -1;
2275
						return -1;
2276
					}
2276
					}
2277
				}
2277
				}
2278

    
   
2278

   
2279
				/* Retry dialing party C. */
2279
				/* Retry dialing party C. */
2280
				ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
2280
				ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
2281
				newchan = feature_request_and_dial(transferer, transferer_name_orig,
2281
				newchan = feature_request_and_dial(transferer, transferer_name_orig,
2282
					transferer, transferee, "Local",
2282
					transferer, transferee, "Local",
2283
					transferee->nativeformats, xferto,
2283
					transferee->nativeformats, xferto,
2284
					atxfernoanswertimeout, &outstate, transferer->language);
2284
					atxfernoanswertimeout, &outstate, transferer->language);
2285
				ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
2285
				ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
2286
					!!newchan, outstate);
2286
					!!newchan, outstate);
2287
				if (newchan || ast_check_hangup(transferee)) {
2287
				if (newchan || ast_check_hangup(transferee)) {
2288
					break;
2288
					break;
2289
				}
2289
				}
2290
			}
2290
			}
2291
		}
2291
		}
2292
		ast_indicate(transferee, AST_CONTROL_UNHOLD);
2292
		ast_indicate(transferee, AST_CONTROL_UNHOLD);
2293
		if (!newchan) {
2293
		if (!newchan) {
2294
			/* No party C or could not callback party B. */
2294
			/* No party C or could not callback party B. */
2295
			ast_party_connected_line_free(&connected_line);
2295
			ast_party_connected_line_free(&connected_line);
2296
			return -1;
2296
			return -1;
2297
		}
2297
		}
2298

    
   
2298

   
2299
		/* newchan is up, we should prepare transferee and bridge them */
2299
		/* newchan is up, we should prepare transferee and bridge them */
2300
		if (ast_check_hangup(newchan)) {
2300
		if (ast_check_hangup(newchan)) {
2301
			ast_hangup(newchan);
2301
			ast_hangup(newchan);
2302
			ast_party_connected_line_free(&connected_line);
2302
			ast_party_connected_line_free(&connected_line);
2303
			return -1;
2303
			return -1;
2304
		}
2304
		}
2305
		if (check_compat(transferee, newchan)) {
2305
		if (check_compat(transferee, newchan)) {
2306
			ast_party_connected_line_free(&connected_line);
2306
			ast_party_connected_line_free(&connected_line);
2307
			return -1;
2307
			return -1;
2308
		}
2308
		}
2309
	} else {
2309
	} else {
2310
		/*
2310
		/*
2311
		 * Both the transferer and transferee have hungup.  If newchan
2311
		 * Both the transferer and transferee have hungup.  If newchan
2312
		 * is up, hang it up as it has no one to talk to.
2312
		 * is up, hang it up as it has no one to talk to.
2313
		 */
2313
		 */
2314
		ast_debug(1, "Everyone is hungup.\n");
2314
		ast_debug(1, "Everyone is hungup.\n");
2315
		if (newchan) {
2315
		if (newchan) {
2316
			ast_hangup(newchan);
2316
			ast_hangup(newchan);
2317
		}
2317
		}
2318
		ast_party_connected_line_free(&connected_line);
2318
		ast_party_connected_line_free(&connected_line);
2319
		return -1;
2319
		return -1;
2320
	}
2320
	}
2321

    
   
2321

   
2322
	/* Initiate the channel transfer of party A to party C (or recalled party B). */
2322
	/* Initiate the channel transfer of party A to party C (or recalled party B). */
2323
	ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
2323
	ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
2324

    
   
2324

   
2325
	xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
2325
	xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
2326
	if (!xferchan) {
2326
	if (!xferchan) {
2327
		ast_hangup(newchan);
2327
		ast_hangup(newchan);
2328
		ast_party_connected_line_free(&connected_line);
2328
		ast_party_connected_line_free(&connected_line);
2329
		return -1;
2329
		return -1;
2330
	}
2330
	}
2331

    
   
2331

   
2332
	/* Give party A a momentary ringback tone during transfer. */
2332
	/* Give party A a momentary ringback tone during transfer. */
2333
	xferchan->visible_indication = AST_CONTROL_RINGING;
2333
	xferchan->visible_indication = AST_CONTROL_RINGING;
2334

    
   
2334

   
2335
	/* Make formats okay */
2335
	/* Make formats okay */
2336
	xferchan->readformat = transferee->readformat;
2336
	xferchan->readformat = transferee->readformat;
2337
	xferchan->writeformat = transferee->writeformat;
2337
	xferchan->writeformat = transferee->writeformat;
2338

    
   
2338

   
2339
	ast_channel_masquerade(xferchan, transferee);
2339
	ast_channel_masquerade(xferchan, transferee);
2340
	ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
2340
	ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
2341
	xferchan->_state = AST_STATE_UP;
2341
	xferchan->_state = AST_STATE_UP;
2342
	ast_clear_flag(xferchan, AST_FLAGS_ALL);
2342
	ast_clear_flag(xferchan, AST_FLAGS_ALL);
2343

    
   
2343

   
2344
	/* Do the masquerade manually to make sure that is is completed. */
2344
	/* Do the masquerade manually to make sure that is is completed. */
2345
	ast_do_masquerade(xferchan);
2345
	ast_do_masquerade(xferchan);
2346

    
   
2346

   
2347
	newchan->_state = AST_STATE_UP;
2347
	newchan->_state = AST_STATE_UP;
2348
	ast_clear_flag(newchan, AST_FLAGS_ALL);
2348
	ast_clear_flag(newchan, AST_FLAGS_ALL);
2349
	tobj = ast_calloc(1, sizeof(*tobj));
2349
	tobj = ast_calloc(1, sizeof(*tobj));
2350
	if (!tobj) {
2350
	if (!tobj) {
2351
		ast_hangup(xferchan);
2351
		ast_hangup(xferchan);
2352
		ast_hangup(newchan);
2352
		ast_hangup(newchan);
2353
		ast_party_connected_line_free(&connected_line);
2353
		ast_party_connected_line_free(&connected_line);
2354
		return -1;
2354
		return -1;
2355
	}
2355
	}
2356

    
   
2356

   
2357
	ast_channel_lock(newchan);
2357
	ast_channel_lock(newchan);
2358
	if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
2358
	if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
2359
		dialfeatures = features_datastore->data;
2359
		dialfeatures = features_datastore->data;
2360
	}
2360
	}
2361
	ast_channel_unlock(newchan);
2361
	ast_channel_unlock(newchan);
2362

    
   
2362

   
2363
	if (dialfeatures) {
2363
	if (dialfeatures) {
2364
		/* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
2364
		/* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
2365
		   I don't currently understand, the abilities of newchan seem to be stored on the caller side */
2365
		   I don't currently understand, the abilities of newchan seem to be stored on the caller side */
2366
		ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2366
		ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2367
		dialfeatures = NULL;
2367
		dialfeatures = NULL;
2368
	}
2368
	}
2369

    
   
2369

   
2370
	ast_channel_lock(xferchan);
2370
	ast_channel_lock(xferchan);
2371
	if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
2371
	if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
2372
		dialfeatures = features_datastore->data;
2372
		dialfeatures = features_datastore->data;
2373
	}
2373
	}
2374
	ast_channel_unlock(xferchan);
2374
	ast_channel_unlock(xferchan);
2375

    
   
2375

   
2376
	if (dialfeatures) {
2376
	if (dialfeatures) {
2377
		ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2377
		ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2378
	}
2378
	}
2379

    
   
2379

   
2380
	tobj->chan = newchan;
2380
	tobj->chan = newchan;
2381
	tobj->peer = xferchan;
2381
	tobj->peer = xferchan;
2382
	tobj->bconfig = *config;
2382
	tobj->bconfig = *config;
2383

    
   
2383

   
2384
	if (tobj->bconfig.end_bridge_callback_data_fixup) {
2384
	if (tobj->bconfig.end_bridge_callback_data_fixup) {
2385
		tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
2385
		tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
2386
	}
2386
	}
2387

    
   
2387

   
2388
	/*
2388
	/*
2389
	 * xferchan is transferee, and newchan is the transfer target
2389
	 * xferchan is transferee, and newchan is the transfer target
2390
	 * So...in a transfer, who is the caller and who is the callee?
2390
	 * So...in a transfer, who is the caller and who is the callee?
2391
	 *
2391
	 *
2392
	 * When the call is originally made, it is clear who is caller and callee.
2392
	 * When the call is originally made, it is clear who is caller and callee.
2393
	 * When a transfer occurs, it is my humble opinion that the transferee becomes
2393
	 * When a transfer occurs, it is my humble opinion that the transferee becomes
2394
	 * the caller, and the transfer target is the callee.
2394
	 * the caller, and the transfer target is the callee.
2395
	 *
2395
	 *
2396
	 * The problem is that these macros were set with the intention of the original
2396
	 * The problem is that these macros were set with the intention of the original
2397
	 * caller and callee taking those roles.  A transfer can totally mess things up,
2397
	 * caller and callee taking those roles.  A transfer can totally mess things up,
2398
	 * to be technical.  What sucks even more is that you can't effectively change
2398
	 * to be technical.  What sucks even more is that you can't effectively change
2399
	 * the macros in the dialplan during the call from the transferer to the transfer
2399
	 * the macros in the dialplan during the call from the transferer to the transfer
2400
	 * target because the transferee is stuck with whatever role he originally had.
2400
	 * target because the transferee is stuck with whatever role he originally had.
2401
	 *
2401
	 *
2402
	 * I think the answer here is just to make sure that it is well documented that
2402
	 * I think the answer here is just to make sure that it is well documented that
2403
	 * during a transfer, the transferee is the "caller" and the transfer target
2403
	 * during a transfer, the transferee is the "caller" and the transfer target
2404
	 * is the "callee."
2404
	 * is the "callee."
2405
	 *
2405
	 *
2406
	 * This means that if party B calls party A, and party B transfers party A to
2406
	 * This means that if party B calls party A, and party B transfers party A to
2407
	 * party C, then A has switched roles for the call.  Now party A will have the
2407
	 * party C, then A has switched roles for the call.  Now party A will have the
2408
	 * caller macro called on his channel instead of the callee macro.
2408
	 * caller macro called on his channel instead of the callee macro.
2409
	 *
2409
	 *
2410
	 * Luckily, the method by which the party B to party C bridge is
2410
	 * Luckily, the method by which the party B to party C bridge is
2411
	 * launched above ensures that the transferee is the "chan" on
2411
	 * launched above ensures that the transferee is the "chan" on
2412
	 * the bridge and the transfer target is the "peer," so my idea
2412
	 * the bridge and the transfer target is the "peer," so my idea
2413
	 * for the roles post-transfer does not require extensive code
2413
	 * for the roles post-transfer does not require extensive code
2414
	 * changes.
2414
	 * changes.
2415
	 */
2415
	 */
2416

    
   
2416

   
2417
	/* Transfer party C connected line to party A */
2417
	/* Transfer party C connected line to party A */
2418
	ast_channel_lock(transferer);
2418
	ast_channel_lock(transferer);
2419
	/*
2419
	/*
2420
	 * Due to a limitation regarding when callerID is set on a Local channel,
2420
	 * Due to a limitation regarding when callerID is set on a Local channel,
2421
	 * we use the transferer's connected line information here.
2421
	 * we use the transferer's connected line information here.
2422
	 */
2422
	 */
2423
	ast_party_connected_line_copy(&connected_line, &transferer->connected);
2423
	ast_party_connected_line_copy(&connected_line, &transferer->connected);
2424
	ast_channel_unlock(transferer);
2424
	ast_channel_unlock(transferer);
2425
	connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2425
	connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2426
	if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
2426
	if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
2427
		ast_channel_update_connected_line(xferchan, &connected_line, NULL);
2427
		ast_channel_update_connected_line(xferchan, &connected_line, NULL);
2428
	}
2428
	}
2429

    
   
2429

   
2430
	/* Transfer party A connected line to party C */
2430
	/* Transfer party A connected line to party C */
2431
	ast_channel_lock(xferchan);
2431
	ast_channel_lock(xferchan);
2432
	ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
2432
	ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
2433
	ast_channel_unlock(xferchan);
2433
	ast_channel_unlock(xferchan);
2434
	connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2434
	connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2435
	if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
2435
	if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
2436
		ast_channel_update_connected_line(newchan, &connected_line, NULL);
2436
		ast_channel_update_connected_line(newchan, &connected_line, NULL);
2437
	}
2437
	}
2438

    
   
2438

   
2439
	if (ast_stream_and_wait(newchan, xfersound, ""))
2439
	if (ast_stream_and_wait(newchan, xfersound, ""))
2440
		ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2440
		ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2441
	bridge_call_thread_launch(tobj);
2441
	bridge_call_thread_launch(tobj);
2442

    
   
2442

   
2443
	ast_party_connected_line_free(&connected_line);
2443
	ast_party_connected_line_free(&connected_line);
2444
	return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
2444
	return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
2445
}
2445
}
2446

    
   
2446

   
2447
/* add atxfer and automon as undefined so you can only use em if you configure them */
2447
/* add atxfer and automon as undefined so you can only use em if you configure them */
2448
#define FEATURES_COUNT ARRAY_LEN(builtin_features)
2448
#define FEATURES_COUNT ARRAY_LEN(builtin_features)
2449

    
   
2449

   
2450
AST_RWLOCK_DEFINE_STATIC(features_lock);
2450
AST_RWLOCK_DEFINE_STATIC(features_lock);
2451

    
   
2451

   
2452
static struct ast_call_feature builtin_features[] = {
2452
static struct ast_call_feature builtin_features[] = {
2453
	{ AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2453
	{ AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2454
	{ AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2454
	{ AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2455
	{ AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2455
	{ AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2456
	{ AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2456
	{ AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2457
	{ AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2457
	{ AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2458
	{ AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2458
	{ AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2459
};
2459
};
2460

    
   
2460

   
2461

    
   
2461

   
2462
static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
2462
static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
2463

    
   
2463

   
2464
/*! \brief register new feature into feature_list*/
2464
/*! \brief register new feature into feature_list*/
2465
void ast_register_feature(struct ast_call_feature *feature)
2465
void ast_register_feature(struct ast_call_feature *feature)
2466
{
2466
{
2467
	if (!feature) {
2467
	if (!feature) {
2468
		ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
2468
		ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
2469
		return;
2469
		return;
2470
	}
2470
	}
2471
  
2471
  
2472
	AST_RWLIST_WRLOCK(&feature_list);
2472
	AST_RWLIST_WRLOCK(&feature_list);
2473
	AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
2473
	AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
2474
	AST_RWLIST_UNLOCK(&feature_list);
2474
	AST_RWLIST_UNLOCK(&feature_list);
2475

    
   
2475

   
2476
	ast_verb(2, "Registered Feature '%s'\n",feature->sname);
2476
	ast_verb(2, "Registered Feature '%s'\n",feature->sname);
2477
}
2477
}
2478

    
   
2478

   
2479
/*! 
2479
/*! 
2480
 * \brief Add new feature group
2480
 * \brief Add new feature group
2481
 * \param fgname feature group name.
2481
 * \param fgname feature group name.
2482
 *
2482
 *
2483
 * Add new feature group to the feature group list insert at head of list.
2483
 * Add new feature group to the feature group list insert at head of list.
2484
 * \note This function MUST be called while feature_groups is locked.
2484
 * \note This function MUST be called while feature_groups is locked.
2485
*/
2485
*/
2486
static struct feature_group *register_group(const char *fgname)
2486
static struct feature_group *register_group(const char *fgname)
2487
{
2487
{
2488
	struct feature_group *fg;
2488
	struct feature_group *fg;
2489

    
   
2489

   
2490
	if (!fgname) {
2490
	if (!fgname) {
2491
		ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
2491
		ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
2492
		return NULL;
2492
		return NULL;
2493
	}
2493
	}
2494

    
   
2494

   
2495
	if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
2495
	if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
2496
		return NULL;
2496
		return NULL;
2497
	}
2497
	}
2498

    
   
2498

   
2499
	ast_string_field_set(fg, gname, fgname);
2499
	ast_string_field_set(fg, gname, fgname);
2500

    
   
2500

   
2501
	AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
2501
	AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
2502

    
   
2502

   
2503
	ast_verb(2, "Registered group '%s'\n", fg->gname);
2503
	ast_verb(2, "Registered group '%s'\n", fg->gname);
2504

    
   
2504

   
2505
	return fg;
2505
	return fg;
2506
}
2506
}
2507

    
   
2507

   
2508
/*! 
2508
/*! 
2509
 * \brief Add feature to group
2509
 * \brief Add feature to group
2510
 * \param fg feature group
2510
 * \param fg feature group
2511
 * \param exten
2511
 * \param exten
2512
 * \param feature feature to add.
2512
 * \param feature feature to add.
2513
 *
2513
 *
2514
 * Check fg and feature specified, add feature to list
2514
 * Check fg and feature specified, add feature to list
2515
 * \note This function MUST be called while feature_groups is locked. 
2515
 * \note This function MUST be called while feature_groups is locked. 
2516
*/
2516
*/
2517
static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
2517
static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
2518
{
2518
{
2519
	struct feature_group_exten *fge;
2519
	struct feature_group_exten *fge;
2520

    
   
2520

   
2521
	if (!fg) {
2521
	if (!fg) {
2522
		ast_log(LOG_NOTICE, "You didn't pass a group!\n");
2522
		ast_log(LOG_NOTICE, "You didn't pass a group!\n");
2523
		return;
2523
		return;
2524
	}
2524
	}
2525

    
   
2525

   
2526
	if (!feature) {
2526
	if (!feature) {
2527
		ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
2527
		ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
2528
		return;
2528
		return;
2529
	}
2529
	}
2530

    
   
2530

   
2531
	if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
2531
	if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
2532
		return;
2532
		return;
2533
	}
2533
	}
2534

    
   
2534

   
2535
	ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
2535
	ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
2536

    
   
2536

   
2537
	fge->feature = feature;
2537
	fge->feature = feature;
2538

    
   
2538

   
2539
	AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
2539
	AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
2540

    
   
2540

   
2541
	ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
2541
	ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
2542
					feature->sname, fg->gname, fge->exten);
2542
					feature->sname, fg->gname, fge->exten);
2543
}
2543
}
2544

    
   
2544

   
2545
void ast_unregister_feature(struct ast_call_feature *feature)
2545
void ast_unregister_feature(struct ast_call_feature *feature)
2546
{
2546
{
2547
	if (!feature) {
2547
	if (!feature) {
2548
		return;
2548
		return;
2549
	}
2549
	}
2550

    
   
2550

   
2551
	AST_RWLIST_WRLOCK(&feature_list);
2551
	AST_RWLIST_WRLOCK(&feature_list);
2552
	AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
2552
	AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
2553
	AST_RWLIST_UNLOCK(&feature_list);
2553
	AST_RWLIST_UNLOCK(&feature_list);
2554

    
   
2554

   
2555
	ast_free(feature);
2555
	ast_free(feature);
2556
}
2556
}
2557

    
   
2557

   
2558
/*! \brief Remove all features in the list */
2558
/*! \brief Remove all features in the list */
2559
static void ast_unregister_features(void)
2559
static void ast_unregister_features(void)
2560
{
2560
{
2561
	struct ast_call_feature *feature;
2561
	struct ast_call_feature *feature;
2562

    
   
2562

   
2563
	AST_RWLIST_WRLOCK(&feature_list);
2563
	AST_RWLIST_WRLOCK(&feature_list);
2564
	while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
2564
	while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
2565
		ast_free(feature);
2565
		ast_free(feature);
2566
	}
2566
	}
2567
	AST_RWLIST_UNLOCK(&feature_list);
2567
	AST_RWLIST_UNLOCK(&feature_list);
2568
}
2568
}
2569

    
   
2569

   
2570
/*! \brief find a call feature by name */
2570
/*! \brief find a call feature by name */
2571
static struct ast_call_feature *find_dynamic_feature(const char *name)
2571
static struct ast_call_feature *find_dynamic_feature(const char *name)
2572
{
2572
{
2573
	struct ast_call_feature *tmp;
2573
	struct ast_call_feature *tmp;
2574

    
   
2574

   
2575
	AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
2575
	AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
2576
		if (!strcasecmp(tmp->sname, name)) {
2576
		if (!strcasecmp(tmp->sname, name)) {
2577
			break;
2577
			break;
2578
		}
2578
		}
2579
	}
2579
	}
2580

    
   
2580

   
2581
	return tmp;
2581
	return tmp;
2582
}
2582
}
2583

    
   
2583

   
2584
/*! \brief Remove all feature groups in the list */
2584
/*! \brief Remove all feature groups in the list */
2585
static void ast_unregister_groups(void)
2585
static void ast_unregister_groups(void)
2586
{
2586
{
2587
	struct feature_group *fg;
2587
	struct feature_group *fg;
2588
	struct feature_group_exten *fge;
2588
	struct feature_group_exten *fge;
2589

    
   
2589

   
2590
	AST_RWLIST_WRLOCK(&feature_groups);
2590
	AST_RWLIST_WRLOCK(&feature_groups);
2591
	while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
2591
	while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
2592
		while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
2592
		while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
2593
			ast_string_field_free_memory(fge);
2593
			ast_string_field_free_memory(fge);
2594
			ast_free(fge);
2594
			ast_free(fge);
2595
		}
2595
		}
2596

    
   
2596

   
2597
		ast_string_field_free_memory(fg);
2597
		ast_string_field_free_memory(fg);
2598
		ast_free(fg);
2598
		ast_free(fg);
2599
	}
2599
	}
2600
	AST_RWLIST_UNLOCK(&feature_groups);
2600
	AST_RWLIST_UNLOCK(&feature_groups);
2601
}
2601
}
2602

    
   
2602

   
2603
/*! 
2603
/*! 
2604
 * \brief Find a group by name 
2604
 * \brief Find a group by name 
2605
 * \param name feature name
2605
 * \param name feature name
2606
 * \retval feature group on success.
2606
 * \retval feature group on success.
2607
 * \retval NULL on failure.
2607
 * \retval NULL on failure.
2608
*/
2608
*/
2609
static struct feature_group *find_group(const char *name)
2609
static struct feature_group *find_group(const char *name)
2610
{
2610
{
2611
	struct feature_group *fg = NULL;
2611
	struct feature_group *fg = NULL;
2612

    
   
2612

   
2613
	AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
2613
	AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
2614
		if (!strcasecmp(fg->gname, name))
2614
		if (!strcasecmp(fg->gname, name))
2615
			break;
2615
			break;
2616
	}
2616
	}
2617

    
   
2617

   
2618
	return fg;
2618
	return fg;
2619
}
2619
}
2620

    
   
2620

   
2621
void ast_rdlock_call_features(void)
2621
void ast_rdlock_call_features(void)
2622
{
2622
{
2623
	ast_rwlock_rdlock(&features_lock);
2623
	ast_rwlock_rdlock(&features_lock);
2624
}
2624
}
2625

    
   
2625

   
2626
void ast_unlock_call_features(void)
2626
void ast_unlock_call_features(void)
2627
{
2627
{
2628
	ast_rwlock_unlock(&features_lock);
2628
	ast_rwlock_unlock(&features_lock);
2629
}
2629
}
2630

    
   
2630

   
2631
struct ast_call_feature *ast_find_call_feature(const char *name)
2631
struct ast_call_feature *ast_find_call_feature(const char *name)
2632
{
2632
{
2633
	int x;
2633
	int x;
2634
	for (x = 0; x < FEATURES_COUNT; x++) {
2634
	for (x = 0; x < FEATURES_COUNT; x++) {
2635
		if (!strcasecmp(name, builtin_features[x].sname))
2635
		if (!strcasecmp(name, builtin_features[x].sname))
2636
			return &builtin_features[x];
2636
			return &builtin_features[x];
2637
	}
2637
	}
2638
	return NULL;
2638
	return NULL;
2639
}
2639
}
2640

    
   
2640

   
2641
/*!
2641
/*!
2642
 * \brief exec an app by feature 
2642
 * \brief exec an app by feature 
2643
 * \param chan,peer,config,code,sense,data
2643
 * \param chan,peer,config,code,sense,data
2644
 *
2644
 *
2645
 * Find a feature, determine which channel activated
2645
 * Find a feature, determine which channel activated
2646
 * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
2646
 * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
2647
 * \retval -1 error.
2647
 * \retval -1 error.
2648
 * \retval -2 when an application cannot be found.
2648
 * \retval -2 when an application cannot be found.
2649
*/
2649
*/
2650
static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2650
static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2651
{
2651
{
2652
	struct ast_app *app;
2652
	struct ast_app *app;
2653
	struct ast_call_feature *feature = data;
2653
	struct ast_call_feature *feature = data;
2654
	struct ast_channel *work, *idle;
2654
	struct ast_channel *work, *idle;
2655
	int res;
2655
	int res;
2656

    
   
2656

   
2657
	if (!feature) { /* shouldn't ever happen! */
2657
	if (!feature) { /* shouldn't ever happen! */
2658
		ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
2658
		ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
2659
		return -1; 
2659
		return -1; 
2660
	}
2660
	}
2661

    
   
2661

   
2662
	if (sense == FEATURE_SENSE_CHAN) {
2662
	if (sense == FEATURE_SENSE_CHAN) {
2663
		if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
2663
		if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
2664
			return AST_FEATURE_RETURN_KEEPTRYING;
2664
			return AST_FEATURE_RETURN_KEEPTRYING;
2665
		if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2665
		if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2666
			work = chan;
2666
			work = chan;
2667
			idle = peer;
2667
			idle = peer;
2668
		} else {
2668
		} else {
2669
			work = peer;
2669
			work = peer;
2670
			idle = chan;
2670
			idle = chan;
2671
		}
2671
		}
2672
	} else {
2672
	} else {
2673
		if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
2673
		if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
2674
			return AST_FEATURE_RETURN_KEEPTRYING;
2674
			return AST_FEATURE_RETURN_KEEPTRYING;
2675
		if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2675
		if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2676
			work = peer;
2676
			work = peer;
2677
			idle = chan;
2677
			idle = chan;
2678
		} else {
2678
		} else {
2679
			work = chan;
2679
			work = chan;
2680
			idle = peer;
2680
			idle = peer;
2681
		}
2681
		}
2682
	}
2682
	}
2683

    
   
2683

   
2684
	if (!(app = pbx_findapp(feature->app))) {
2684
	if (!(app = pbx_findapp(feature->app))) {
2685
		ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
2685
		ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
2686
		return -2;
2686
		return -2;
2687
	}
2687
	}
2688

    
   
2688

   
2689
	ast_autoservice_start(idle);
2689
	ast_autoservice_start(idle);
2690
	ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
2690
	ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
2691
	
2691
	
2692
	if(work && idle) {
2692
	if(work && idle) {
2693
		pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
2693
		pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
2694
		pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
2694
		pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
2695
		pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
2695
		pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
2696
		pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
2696
		pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
2697
	}
2697
	}
2698

    
   
2698

   
2699
	if (!ast_strlen_zero(feature->moh_class))
2699
	if (!ast_strlen_zero(feature->moh_class))
2700
		ast_moh_start(idle, feature->moh_class, NULL);
2700
		ast_moh_start(idle, feature->moh_class, NULL);
2701

    
   
2701

   
2702
	res = pbx_exec(work, app, feature->app_args);
2702
	res = pbx_exec(work, app, feature->app_args);
2703

    
   
2703

   
2704
	if (!ast_strlen_zero(feature->moh_class))
2704
	if (!ast_strlen_zero(feature->moh_class))
2705
		ast_moh_stop(idle);
2705
		ast_moh_stop(idle);
2706

    
   
2706

   
2707
	ast_autoservice_stop(idle);
2707
	ast_autoservice_stop(idle);
2708

    
   
2708

   
2709
	if (res) {
2709
	if (res) {
2710
		return AST_FEATURE_RETURN_SUCCESSBREAK;
2710
		return AST_FEATURE_RETURN_SUCCESSBREAK;
2711
	}
2711
	}
2712
	return AST_FEATURE_RETURN_SUCCESS;	/*! \todo XXX should probably return res */
2712
	return AST_FEATURE_RETURN_SUCCESS;	/*! \todo XXX should probably return res */
2713
}
2713
}
2714

    
   
2714

   
2715
static void unmap_features(void)
2715
static void unmap_features(void)
2716
{
2716
{
2717
	int x;
2717
	int x;
2718

    
   
2718

   
2719
	ast_rwlock_wrlock(&features_lock);
2719
	ast_rwlock_wrlock(&features_lock);
2720
	for (x = 0; x < FEATURES_COUNT; x++)
2720
	for (x = 0; x < FEATURES_COUNT; x++)
2721
		strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
2721
		strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
2722
	ast_rwlock_unlock(&features_lock);
2722
	ast_rwlock_unlock(&features_lock);
2723
}
2723
}
2724

    
   
2724

   
2725
static int remap_feature(const char *name, const char *value)
2725
static int remap_feature(const char *name, const char *value)
2726
{
2726
{
2727
	int x, res = -1;
2727
	int x, res = -1;
2728

    
   
2728

   
2729
	ast_rwlock_wrlock(&features_lock);
2729
	ast_rwlock_wrlock(&features_lock);
2730
	for (x = 0; x < FEATURES_COUNT; x++) {
2730
	for (x = 0; x < FEATURES_COUNT; x++) {
2731
		if (strcasecmp(builtin_features[x].sname, name))
2731
		if (strcasecmp(builtin_features[x].sname, name))
2732
			continue;
2732
			continue;
2733

    
   
2733

   
2734
		ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
2734
		ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
2735
		res = 0;
2735
		res = 0;
2736
		break;
2736
		break;
2737
	}
2737
	}
2738
	ast_rwlock_unlock(&features_lock);
2738
	ast_rwlock_unlock(&features_lock);
2739

    
   
2739

   
2740
	return res;
2740
	return res;
2741
}
2741
}
2742

    
   
2742

   
2743
/*!
2743
/*!
2744
 * \brief Helper function for feature_interpret and ast_feature_detect
2744
 * \brief Helper function for feature_interpret and ast_feature_detect
2745
 * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
2745
 * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
2746
 *
2746
 *
2747
 * Lock features list, browse for code, unlock list
2747
 * Lock features list, browse for code, unlock list
2748
 * If a feature is found and the operation variable is set, that feature's
2748
 * If a feature is found and the operation variable is set, that feature's
2749
 * operation is executed.  The first feature found is copied to the feature parameter.
2749
 * operation is executed.  The first feature found is copied to the feature parameter.
2750
 * \retval res on success.
2750
 * \retval res on success.
2751
 * \retval -1 on failure.
2751
 * \retval -1 on failure.
2752
*/
2752
*/
2753
static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
2753
static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
2754
	struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
2754
	struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
2755
	struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
2755
	struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
2756
{
2756
{
2757
	int x;
2757
	int x;
2758
	struct feature_group *fg = NULL;
2758
	struct feature_group *fg = NULL;
2759
	struct feature_group_exten *fge;
2759
	struct feature_group_exten *fge;
2760
	struct ast_call_feature *tmpfeature;
2760
	struct ast_call_feature *tmpfeature;
2761
	char *tmp, *tok;
2761
	char *tmp, *tok;
2762
	int res = AST_FEATURE_RETURN_PASSDIGITS;
2762
	int res = AST_FEATURE_RETURN_PASSDIGITS;
2763
	int feature_detected = 0;
2763
	int feature_detected = 0;
2764

    
   
2764

   
2765
	if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
2765
	if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
2766
		return -1; /* can not run feature operation */
2766
		return -1; /* can not run feature operation */
2767
	}
2767
	}
2768

    
   
2768

   
2769
	ast_rwlock_rdlock(&features_lock);
2769
	ast_rwlock_rdlock(&features_lock);
2770
	for (x = 0; x < FEATURES_COUNT; x++) {
2770
	for (x = 0; x < FEATURES_COUNT; x++) {
2771
		if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
2771
		if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
2772
		    !ast_strlen_zero(builtin_features[x].exten)) {
2772
		    !ast_strlen_zero(builtin_features[x].exten)) {
2773
			/* Feature is up for consideration */
2773
			/* Feature is up for consideration */
2774
			if (!strcmp(builtin_features[x].exten, code)) {
2774
			if (!strcmp(builtin_features[x].exten, code)) {
2775
				ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
2775
				ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
2776
				if (operation == FEATURE_INTERPRET_CHECK) {
2776
				if (operation == FEATURE_INTERPRET_CHECK) {
2777
					res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
2777
					res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
2778
				} else if (operation == FEATURE_INTERPRET_DO) {
2778
				} else if (operation == FEATURE_INTERPRET_DO) {
2779
					res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
2779
					res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
2780
				}
2780
				}
2781
				if (feature) {
2781
				if (feature) {
2782
					memcpy(feature, &builtin_features[x], sizeof(feature));
2782
					memcpy(feature, &builtin_features[x], sizeof(feature));
2783
				}
2783
				}
2784
				feature_detected = 1;
2784
				feature_detected = 1;
2785
				break;
2785
				break;
2786
			} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
2786
			} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
2787
				if (res == AST_FEATURE_RETURN_PASSDIGITS) {
2787
				if (res == AST_FEATURE_RETURN_PASSDIGITS) {
2788
					res = AST_FEATURE_RETURN_STOREDIGITS;
2788
					res = AST_FEATURE_RETURN_STOREDIGITS;
2789
				}
2789
				}
2790
			}
2790
			}
2791
		}
2791
		}
2792
	}
2792
	}
2793
	ast_rwlock_unlock(&features_lock);
2793
	ast_rwlock_unlock(&features_lock);
2794

    
   
2794

   
2795
	if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
2795
	if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
2796
		return res;
2796
		return res;
2797
	}
2797
	}
2798

    
   
2798

   
2799
	tmp = dynamic_features_buf;
2799
	tmp = dynamic_features_buf;
2800

    
   
2800

   
2801
	while ((tok = strsep(&tmp, "#"))) {
2801
	while ((tok = strsep(&tmp, "#"))) {
2802
		AST_RWLIST_RDLOCK(&feature_groups);
2802
		AST_RWLIST_RDLOCK(&feature_groups);
2803

    
   
2803

   
2804
		fg = find_group(tok);
2804
		fg = find_group(tok);
2805

    
   
2805

   
2806
		if (fg) {
2806
		if (fg) {
2807
			AST_LIST_TRAVERSE(&fg->features, fge, entry) {
2807
			AST_LIST_TRAVERSE(&fg->features, fge, entry) {
2808
				if (!strcmp(fge->exten, code)) {
2808
				if (!strcmp(fge->exten, code)) {
2809
					if (operation) {
2809
					if (operation) {
2810
						res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
2810
						res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
2811
					}
2811
					}
2812
					memcpy(feature, fge->feature, sizeof(feature));
2812
					memcpy(feature, fge->feature, sizeof(feature));
2813
					if (res != AST_FEATURE_RETURN_KEEPTRYING) {
2813
					if (res != AST_FEATURE_RETURN_KEEPTRYING) {
2814
						AST_RWLIST_UNLOCK(&feature_groups);
2814
						AST_RWLIST_UNLOCK(&feature_groups);
2815
						break;
2815
						break;
2816
					}
2816
					}
2817
					res = AST_FEATURE_RETURN_PASSDIGITS;
2817
					res = AST_FEATURE_RETURN_PASSDIGITS;
2818
				} else if (!strncmp(fge->exten, code, strlen(code))) {
2818
				} else if (!strncmp(fge->exten, code, strlen(code))) {
2819
					res = AST_FEATURE_RETURN_STOREDIGITS;
2819
					res = AST_FEATURE_RETURN_STOREDIGITS;
2820
				}
2820
				}
2821
			}
2821
			}
2822
			if (fge) {
2822
			if (fge) {
2823
				break;
2823
				break;
2824
			}
2824
			}
2825
		}
2825
		}
2826

    
   
2826

   
2827
		AST_RWLIST_UNLOCK(&feature_groups);
2827
		AST_RWLIST_UNLOCK(&feature_groups);
2828

    
   
2828

   
2829
		AST_RWLIST_RDLOCK(&feature_list);
2829
		AST_RWLIST_RDLOCK(&feature_list);
2830

    
   
2830

   
2831
		if (!(tmpfeature = find_dynamic_feature(tok))) {
2831
		if (!(tmpfeature = find_dynamic_feature(tok))) {
2832
			AST_RWLIST_UNLOCK(&feature_list);
2832
			AST_RWLIST_UNLOCK(&feature_list);
2833
			continue;
2833
			continue;
2834
		}
2834
		}
2835

    
   
2835

   
2836
		/* Feature is up for consideration */
2836
		/* Feature is up for consideration */
2837
		if (!strcmp(tmpfeature->exten, code)) {
2837
		if (!strcmp(tmpfeature->exten, code)) {
2838
			ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
2838
			ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
2839
			if (operation == FEATURE_INTERPRET_CHECK) {
2839
			if (operation == FEATURE_INTERPRET_CHECK) {
2840
				res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
2840
				res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
2841
			} else if (operation == FEATURE_INTERPRET_DO) {
2841
			} else if (operation == FEATURE_INTERPRET_DO) {
2842
				res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
2842
				res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
2843
			}
2843
			}
2844
			if (feature) {
2844
			if (feature) {
2845
				memcpy(feature, tmpfeature, sizeof(feature));
2845
				memcpy(feature, tmpfeature, sizeof(feature));
2846
			}
2846
			}
2847
			if (res != AST_FEATURE_RETURN_KEEPTRYING) {
2847
			if (res != AST_FEATURE_RETURN_KEEPTRYING) {
2848
				AST_RWLIST_UNLOCK(&feature_list);
2848
				AST_RWLIST_UNLOCK(&feature_list);
2849
				break;
2849
				break;
2850
			}
2850
			}
2851
			res = AST_FEATURE_RETURN_PASSDIGITS;
2851
			res = AST_FEATURE_RETURN_PASSDIGITS;
2852
		} else if (!strncmp(tmpfeature->exten, code, strlen(code)))
2852
		} else if (!strncmp(tmpfeature->exten, code, strlen(code)))
2853
			res = AST_FEATURE_RETURN_STOREDIGITS;
2853
			res = AST_FEATURE_RETURN_STOREDIGITS;
2854

    
   
2854

   
2855
		AST_RWLIST_UNLOCK(&feature_list);
2855
		AST_RWLIST_UNLOCK(&feature_list);
2856
	}
2856
	}
2857

    
   
2857

   
2858
	return res;
2858
	return res;
2859
}
2859
}
2860

    
   
2860

   
2861
/*!
2861
/*!
2862
 * \brief Check the dynamic features
2862
 * \brief Check the dynamic features
2863
 * \param chan,peer,config,code,sense
2863
 * \param chan,peer,config,code,sense
2864
 *
2864
 *
2865
 * \retval res on success.
2865
 * \retval res on success.
2866
 * \retval -1 on failure.
2866
 * \retval -1 on failure.
2867
*/
2867
*/
2868

    
   
2868

   
2869
static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
2869
static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
2870

    
   
2870

   
2871
	char dynamic_features_buf[128];
2871
	char dynamic_features_buf[128];
2872
	const char *peer_dynamic_features, *chan_dynamic_features;
2872
	const char *peer_dynamic_features, *chan_dynamic_features;
2873
	struct ast_flags features;
2873
	struct ast_flags features;
2874
	struct ast_call_feature feature;
2874
	struct ast_call_feature feature;
2875
	if (sense == FEATURE_SENSE_CHAN) {
2875
	if (sense == FEATURE_SENSE_CHAN) {
2876
		ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
2876
		ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
2877
	}
2877
	}
2878
	else {
2878
	else {
2879
		ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
2879
		ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
2880
	}
2880
	}
2881

    
   
2881

   
2882
	ast_channel_lock(peer);
2882
	ast_channel_lock(peer);
2883
	peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
2883
	peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
2884
	ast_channel_unlock(peer);
2884
	ast_channel_unlock(peer);
2885

    
   
2885

   
2886
	ast_channel_lock(chan);
2886
	ast_channel_lock(chan);
2887
	chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
2887
	chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
2888
	ast_channel_unlock(chan);
2888
	ast_channel_unlock(chan);
2889

    
   
2889

   
2890
	snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
2890
	snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
2891

    
   
2891

   
2892
	ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
2892
	ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
2893

    
   
2893

   
2894
	return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, FEATURE_INTERPRET_DO, &feature);
2894
	return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, FEATURE_INTERPRET_DO, &feature);
2895
}
2895
}
2896

    
   
2896

   
2897

    
   
2897

   
2898
int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
2898
int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
2899

    
   
2899

   
2900
	return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature);
2900
	return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature);
2901
}
2901
}
2902

    
   
2902

   
2903
/*! \brief Check if a feature exists */
2903
/*! \brief Check if a feature exists */
2904
static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code) {
2904
static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code) {
2905

    
   
2905

   
2906
	return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_CHECK, NULL);
2906
	return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_CHECK, NULL);
2907
}
2907
}
2908

    
   
2908

   
2909
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
2909
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
2910
{
2910
{
2911
	int x;
2911
	int x;
2912

    
   
2912

   
2913
	ast_clear_flag(config, AST_FLAGS_ALL);
2913
	ast_clear_flag(config, AST_FLAGS_ALL);
2914

    
   
2914

   
2915
	ast_rwlock_rdlock(&features_lock);
2915
	ast_rwlock_rdlock(&features_lock);
2916
	for (x = 0; x < FEATURES_COUNT; x++) {
2916
	for (x = 0; x < FEATURES_COUNT; x++) {
2917
		if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
2917
		if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
2918
			continue;
2918
			continue;
2919

    
   
2919

   
2920
		if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
2920
		if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
2921
			ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
2921
			ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
2922

    
   
2922

   
2923
		if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
2923
		if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
2924
			ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
2924
			ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
2925
	}
2925
	}
2926
	ast_rwlock_unlock(&features_lock);
2926
	ast_rwlock_unlock(&features_lock);
2927

    
   
2927

   
2928
	if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
2928
	if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
2929
		const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
2929
		const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
2930

    
   
2930

   
2931
		if (dynamic_features) {
2931
		if (dynamic_features) {
2932
			char *tmp = ast_strdupa(dynamic_features);
2932
			char *tmp = ast_strdupa(dynamic_features);
2933
			char *tok;
2933
			char *tok;
2934
			struct ast_call_feature *feature;
2934
			struct ast_call_feature *feature;
2935

    
   
2935

   
2936
			/* while we have a feature */
2936
			/* while we have a feature */
2937
			while ((tok = strsep(&tmp, "#"))) {
2937
			while ((tok = strsep(&tmp, "#"))) {
2938
				struct feature_group *fg;
2938
				struct feature_group *fg;
2939

    
   
2939

   
2940
				AST_RWLIST_RDLOCK(&feature_groups);
2940
				AST_RWLIST_RDLOCK(&feature_groups);
2941
				AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
2941
				AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
2942
					struct feature_group_exten *fge;
2942
					struct feature_group_exten *fge;
2943

    
   
2943

   
2944
					AST_LIST_TRAVERSE(&fg->features, fge, entry) {
2944
					AST_LIST_TRAVERSE(&fg->features, fge, entry) {
2945
						if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLER)) {
2945
						if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLER)) {
2946
							ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
2946
							ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
2947
						}
2947
						}
2948
						if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLEE)) {
2948
						if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLEE)) {
2949
							ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
2949
							ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
2950
						}
2950
						}
2951
					}
2951
					}
2952
				}
2952
				}
2953
				AST_RWLIST_UNLOCK(&feature_groups);
2953
				AST_RWLIST_UNLOCK(&feature_groups);
2954

    
   
2954

   
2955
				AST_RWLIST_RDLOCK(&feature_list);
2955
				AST_RWLIST_RDLOCK(&feature_list);
2956
				if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
2956
				if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
2957
					if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
2957
					if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
2958
						ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
2958
						ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
2959
					}
2959
					}
2960
					if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
2960
					if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
2961
						ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
2961
						ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
2962
					}
2962
					}
2963
				}
2963
				}
2964
				AST_RWLIST_UNLOCK(&feature_list);
2964
				AST_RWLIST_UNLOCK(&feature_list);
2965
			}
2965
			}
2966
		}
2966
		}
2967
	}
2967
	}
2968
}
2968
}
2969

    
   
2969

   
2970
/*!
2970
/*!
2971
 * \internal
2971
 * \internal
2972
 * \brief Get feature and dial.
2972
 * \brief Get feature and dial.
2973
 *
2973
 *
2974
 * \param caller Channel to represent as the calling channel for the dialed channel.
2974
 * \param caller Channel to represent as the calling channel for the dialed channel.
2975
 * \param caller_name Original caller channel name.
2975
 * \param caller_name Original caller channel name.
2976
 * \param requestor Channel to say is requesting the dial (usually the caller).
2976
 * \param requestor Channel to say is requesting the dial (usually the caller).
2977
 * \param transferee Channel that the dialed channel will be transferred to.
2977
 * \param transferee Channel that the dialed channel will be transferred to.
2978
 * \param type Channel technology type to dial.
2978
 * \param type Channel technology type to dial.
2979
 * \param format Codec formats for dialed channel.
2979
 * \param format Codec formats for dialed channel.
2980
 * \param data Dialed channel extra parameters for ast_request() and ast_call().
2980
 * \param data Dialed channel extra parameters for ast_request() and ast_call().
2981
 * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
2981
 * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
2982
 * \param outstate Status of dialed channel if unsuccessful.
2982
 * \param outstate Status of dialed channel if unsuccessful.
2983
 * \param language Language of the caller.
2983
 * \param language Language of the caller.
2984
 *
2984
 *
2985
 * \note
2985
 * \note
2986
 * outstate can be:
2986
 * outstate can be:
2987
 * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
2987
 * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
2988
 * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD.  If
2988
 * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD.  If
2989
 * AST_CONTROL_UNHOLD then the caller channel cancelled the
2989
 * AST_CONTROL_UNHOLD then the caller channel cancelled the
2990
 * transfer or the dialed channel did not answer before the
2990
 * transfer or the dialed channel did not answer before the
2991
 * timeout.
2991
 * timeout.
2992
 *
2992
 *
2993
 * \details
2993
 * \details
2994
 * Request channel, set channel variables, initiate call,
2994
 * Request channel, set channel variables, initiate call,
2995
 * check if they want to disconnect, go into loop, check if timeout has elapsed,
2995
 * check if they want to disconnect, go into loop, check if timeout has elapsed,
2996
 * check if person to be transfered hung up, check for answer break loop,
2996
 * check if person to be transfered hung up, check for answer break loop,
2997
 * set cdr return channel.
2997
 * set cdr return channel.
2998
 *
2998
 *
2999
 * \retval Channel Connected channel for transfer.
2999
 * \retval Channel Connected channel for transfer.
3000
 * \retval NULL on failure to get third party connected.
3000
 * \retval NULL on failure to get third party connected.
3001
 *
3001
 *
3002
 * \note This is similar to __ast_request_and_dial() in channel.c
3002
 * \note This is similar to __ast_request_and_dial() in channel.c
3003
 */
3003
 */
3004
static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
3004
static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
3005
	const char *caller_name, struct ast_channel *requestor,
3005
	const char *caller_name, struct ast_channel *requestor,
3006
	struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data,
3006
	struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data,
3007
	int timeout, int *outstate, const char *language)
3007
	int timeout, int *outstate, const char *language)
3008
{
3008
{
3009
	int state = 0;
3009
	int state = 0;
3010
	int cause = 0;
3010
	int cause = 0;
3011
	int to;
3011
	int to;
3012
	int caller_hungup;
3012
	int caller_hungup;
3013
	int transferee_hungup;
3013
	int transferee_hungup;
3014
	struct ast_channel *chan;
3014
	struct ast_channel *chan;
3015
	struct ast_channel *monitor_chans[3];
3015
	struct ast_channel *monitor_chans[3];
3016
	struct ast_channel *active_channel;
3016
	struct ast_channel *active_channel;
3017
	int res;
3017
	int res;
3018
	int ready = 0;
3018
	int ready = 0;
3019
	struct timeval started;
3019
	struct timeval started;
3020
	int x, len = 0;
3020
	int x, len = 0;
3021
	char *disconnect_code = NULL, *dialed_code = NULL;
3021
	char *disconnect_code = NULL, *dialed_code = NULL;
3022
	struct ast_format_cap *tmp_cap;
3022
	struct ast_format_cap *tmp_cap;
3023
	struct ast_format best_audio_fmt;
3023
	struct ast_format best_audio_fmt;
3024
	struct ast_frame *f;
3024
	struct ast_frame *f;
3025
	AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
3025
	AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
3026

    
   
3026

   
3027
	tmp_cap = ast_format_cap_alloc_nolock();
3027
	tmp_cap = ast_format_cap_alloc_nolock();
3028
	if (!tmp_cap) {
3028
	if (!tmp_cap) {
3029
		return NULL;
3029
		return NULL;
3030
	}
3030
	}
3031
	ast_best_codec(cap, &best_audio_fmt);
3031
	ast_best_codec(cap, &best_audio_fmt);
3032
	ast_format_cap_add(tmp_cap, &best_audio_fmt);
3032
	ast_format_cap_add(tmp_cap, &best_audio_fmt);
3033

    
   
3033

   
3034
	caller_hungup = ast_check_hangup(caller);
3034
	caller_hungup = ast_check_hangup(caller);
3035

    
   
3035

   
3036
	if (!(chan = ast_request(type, tmp_cap, requestor, data, &cause))) {
3036
	if (!(chan = ast_request(type, tmp_cap, requestor, data, &cause))) {
3037
		ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
3037
		ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
3038
		switch (cause) {
3038
		switch (cause) {
3039
		case AST_CAUSE_BUSY:
3039
		case AST_CAUSE_BUSY:
3040
			state = AST_CONTROL_BUSY;
3040
			state = AST_CONTROL_BUSY;
3041
			break;
3041
			break;
3042
		case AST_CAUSE_CONGESTION:
3042
		case AST_CAUSE_CONGESTION:
3043
			state = AST_CONTROL_CONGESTION;
3043
			state = AST_CONTROL_CONGESTION;
3044
			break;
3044
			break;
3045
		default:
3045
		default:
3046
			state = 0;
3046
			state = 0;
3047
			break;
3047
			break;
3048
		}
3048
		}
3049
		goto done;
3049
		goto done;
3050
	}
3050
	}
3051

    
   
3051

   
3052
	ast_string_field_set(chan, language, language);
3052
	ast_string_field_set(chan, language, language);
3053
	ast_channel_inherit_variables(caller, chan);
3053
	ast_channel_inherit_variables(caller, chan);
3054
	pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
3054
	pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
3055

    
   
3055

   
3056
	ast_channel_lock(chan);
3056
	ast_channel_lock(chan);
3057
	ast_connected_line_copy_from_caller(&chan->connected, &requestor->caller);
3057
	ast_connected_line_copy_from_caller(&chan->connected, &requestor->caller);
3058
	ast_channel_unlock(chan);
3058
	ast_channel_unlock(chan);
3059

    
   
3059

   
3060
	if (ast_call(chan, data, timeout)) {
3060
	if (ast_call(chan, data, timeout)) {
3061
		ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
3061
		ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
3062
		switch (chan->hangupcause) {
3062
		switch (chan->hangupcause) {
3063
		case AST_CAUSE_BUSY:
3063
		case AST_CAUSE_BUSY:
3064
			state = AST_CONTROL_BUSY;
3064
			state = AST_CONTROL_BUSY;
3065
			break;
3065
			break;
3066
		case AST_CAUSE_CONGESTION:
3066
		case AST_CAUSE_CONGESTION:
3067
			state = AST_CONTROL_CONGESTION;
3067
			state = AST_CONTROL_CONGESTION;
3068
			break;
3068
			break;
3069
		default:
3069
		default:
3070
			state = 0;
3070
			state = 0;
3071
			break;
3071
			break;
3072
		}
3072
		}
3073
		goto done;
3073
		goto done;
3074
	}
3074
	}
3075

    
   
3075

   
3076
	/* support dialing of the featuremap disconnect code while performing an attended tranfer */
3076
	/* support dialing of the featuremap disconnect code while performing an attended tranfer */
3077
	ast_rwlock_rdlock(&features_lock);
3077
	ast_rwlock_rdlock(&features_lock);
3078
	for (x = 0; x < FEATURES_COUNT; x++) {
3078
	for (x = 0; x < FEATURES_COUNT; x++) {
3079
		if (strcasecmp(builtin_features[x].sname, "disconnect"))
3079
		if (strcasecmp(builtin_features[x].sname, "disconnect"))
3080
			continue;
3080
			continue;
3081

    
   
3081

   
3082
		disconnect_code = builtin_features[x].exten;
3082
		disconnect_code = builtin_features[x].exten;
3083
		len = strlen(disconnect_code) + 1;
3083
		len = strlen(disconnect_code) + 1;
3084
		dialed_code = alloca(len);
3084
		dialed_code = alloca(len);
3085
		memset(dialed_code, 0, len);
3085
		memset(dialed_code, 0, len);
3086
		break;
3086
		break;
3087
	}
3087
	}
3088
	ast_rwlock_unlock(&features_lock);
3088
	ast_rwlock_unlock(&features_lock);
3089
	x = 0;
3089
	x = 0;
3090
	started = ast_tvnow();
3090
	started = ast_tvnow();
3091
	to = timeout;
3091
	to = timeout;
3092
	AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
3092
	AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
3093

    
   
3093

   
3094
	ast_poll_channel_add(caller, chan);
3094
	ast_poll_channel_add(caller, chan);
3095

    
   
3095

   
3096
	transferee_hungup = 0;
3096
	transferee_hungup = 0;
3097
	while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
3097
	while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
3098
		int num_chans = 0;
3098
		int num_chans = 0;
3099

    
   
3099

   
3100
		monitor_chans[num_chans++] = transferee;
3100
		monitor_chans[num_chans++] = transferee;
3101
		monitor_chans[num_chans++] = chan;
3101
		monitor_chans[num_chans++] = chan;
3102
		if (!caller_hungup) {
3102
		if (!caller_hungup) {
3103
			if (ast_check_hangup(caller)) {
3103
			if (ast_check_hangup(caller)) {
3104
				caller_hungup = 1;
3104
				caller_hungup = 1;
3105

    
   
3105

   
3106
#if defined(ATXFER_NULL_TECH)
3106
#if defined(ATXFER_NULL_TECH)
3107
				/* Change caller's name to ensure that it will remain unique. */
3107
				/* Change caller's name to ensure that it will remain unique. */
3108
				set_new_chan_name(caller);
3108
				set_new_chan_name(caller);
3109

    
   
3109

   
3110
				/*
3110
				/*
3111
				 * Get rid of caller's physical technology so it is free for
3111
				 * Get rid of caller's physical technology so it is free for
3112
				 * other calls.
3112
				 * other calls.
3113
				 */
3113
				 */
3114
				set_null_chan_tech(caller);
3114
				set_null_chan_tech(caller);
3115
#endif	/* defined(ATXFER_NULL_TECH) */
3115
#endif	/* defined(ATXFER_NULL_TECH) */
3116
			} else {
3116
			} else {
3117
				/* caller is not hungup so monitor it. */
3117
				/* caller is not hungup so monitor it. */
3118
				monitor_chans[num_chans++] = caller;
3118
				monitor_chans[num_chans++] = caller;
3119
			}
3119
			}
3120
		}
3120
		}
3121

    
   
3121

   
3122
		/* see if the timeout has been violated */
3122
		/* see if the timeout has been violated */
3123
		if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
3123
		if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
3124
			state = AST_CONTROL_UNHOLD;
3124
			state = AST_CONTROL_UNHOLD;
3125
			ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", chan->name);
3125
			ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", chan->name);
3126
			break; /*doh! timeout*/
3126
			break; /*doh! timeout*/
3127
		}
3127
		}
3128

    
   
3128

   
3129
		active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
3129
		active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
3130
		if (!active_channel)
3130
		if (!active_channel)
3131
			continue;
3131
			continue;
3132

    
   
3132

   
3133
		f = NULL;
3133
		f = NULL;
3134
		if (transferee == active_channel) {
3134
		if (transferee == active_channel) {
3135
			struct ast_frame *dup_f;
3135
			struct ast_frame *dup_f;
3136

    
   
3136

   
3137
			f = ast_read(transferee);
3137
			f = ast_read(transferee);
3138
			if (f == NULL) { /*doh! where'd he go?*/
3138
			if (f == NULL) { /*doh! where'd he go?*/
3139
				transferee_hungup = 1;
3139
				transferee_hungup = 1;
3140
				state = 0;
3140
				state = 0;
3141
				break;
3141
				break;
3142
			}
3142
			}
3143
			if (ast_is_deferrable_frame(f)) {
3143
			if (ast_is_deferrable_frame(f)) {
3144
				dup_f = ast_frisolate(f);
3144
				dup_f = ast_frisolate(f);
3145
				if (dup_f) {
3145
				if (dup_f) {
3146
					if (dup_f == f) {
3146
					if (dup_f == f) {
3147
						f = NULL;
3147
						f = NULL;
3148
					}
3148
					}
3149
					AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
3149
					AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
3150
				}
3150
				}
3151
			}
3151
			}
3152
		} else if (chan == active_channel) {
3152
		} else if (chan == active_channel) {
3153
			if (!ast_strlen_zero(chan->call_forward)) {
3153
			if (!ast_strlen_zero(chan->call_forward)) {
3154
				chan = ast_call_forward(caller, chan, NULL, tmp_cap, NULL, &state);
3154
				chan = ast_call_forward(caller, chan, NULL, tmp_cap, NULL, &state);
3155
				if (!chan) {
3155
				if (!chan) {
3156
					break;
3156
					break;
3157
				}
3157
				}
3158
				continue;
3158
				continue;
3159
			}
3159
			}
3160
			f = ast_read(chan);
3160
			f = ast_read(chan);
3161
			if (f == NULL) { /*doh! where'd he go?*/
3161
			if (f == NULL) { /*doh! where'd he go?*/
3162
				switch (chan->hangupcause) {
3162
				switch (chan->hangupcause) {
3163
				case AST_CAUSE_BUSY:
3163
				case AST_CAUSE_BUSY:
3164
					state = AST_CONTROL_BUSY;
3164
					state = AST_CONTROL_BUSY;
3165
					break;
3165
					break;
3166
				case AST_CAUSE_CONGESTION:
3166
				case AST_CAUSE_CONGESTION:
3167
					state = AST_CONTROL_CONGESTION;
3167
					state = AST_CONTROL_CONGESTION;
3168
					break;
3168
					break;
3169
				default:
3169
				default:
3170
					state = 0;
3170
					state = 0;
3171
					break;
3171
					break;
3172
				}
3172
				}
3173
				break;
3173
				break;
3174
			}
3174
			}
3175

    
   
3175

   
3176
			if (f->frametype == AST_FRAME_CONTROL) {
3176
			if (f->frametype == AST_FRAME_CONTROL) {
3177
				if (f->subclass.integer == AST_CONTROL_RINGING) {
3177
				if (f->subclass.integer == AST_CONTROL_RINGING) {
3178
					ast_verb(3, "%s is ringing\n", chan->name);
3178
					ast_verb(3, "%s is ringing\n", chan->name);
3179
					ast_indicate(caller, AST_CONTROL_RINGING);
3179
					ast_indicate(caller, AST_CONTROL_RINGING);
3180
				} else if (f->subclass.integer == AST_CONTROL_BUSY) {
3180
				} else if (f->subclass.integer == AST_CONTROL_BUSY) {
3181
					state = f->subclass.integer;
3181
					state = f->subclass.integer;
3182
					ast_verb(3, "%s is busy\n", chan->name);
3182
					ast_verb(3, "%s is busy\n", chan->name);
3183
					ast_indicate(caller, AST_CONTROL_BUSY);
3183
					ast_indicate(caller, AST_CONTROL_BUSY);
3184
					ast_frfree(f);
3184
					ast_frfree(f);
3185
					break;
3185
					break;
3186
				} else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
3186
				} else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
3187
					state = f->subclass.integer;
3187
					state = f->subclass.integer;
3188
					ast_verb(3, "%s is congested\n", chan->name);
3188
					ast_verb(3, "%s is congested\n", chan->name);
3189
					ast_indicate(caller, AST_CONTROL_CONGESTION);
3189
					ast_indicate(caller, AST_CONTROL_CONGESTION);
3190
					ast_frfree(f);
3190
					ast_frfree(f);
3191
					break;
3191
					break;
3192
				} else if (f->subclass.integer == AST_CONTROL_ANSWER) {
3192
				} else if (f->subclass.integer == AST_CONTROL_ANSWER) {
3193
					/* This is what we are hoping for */
3193
					/* This is what we are hoping for */
3194
					state = f->subclass.integer;
3194
					state = f->subclass.integer;
3195
					ast_frfree(f);
3195
					ast_frfree(f);
3196
					ready=1;
3196
					ready=1;
3197
					break;
3197
					break;
3198
				} else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
3198
				} else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
3199
					if (caller_hungup) {
3199
					if (caller_hungup) {
3200
						struct ast_party_connected_line connected;
3200
						struct ast_party_connected_line connected;
3201

    
   
3201

   
3202
						/* Just save it for the transfer. */
3202
						/* Just save it for the transfer. */
3203
						ast_party_connected_line_set_init(&connected, &caller->connected);
3203
						ast_party_connected_line_set_init(&connected, &caller->connected);
3204
						res = ast_connected_line_parse_data(f->data.ptr, f->datalen,
3204
						res = ast_connected_line_parse_data(f->data.ptr, f->datalen,
3205
							&connected);
3205
							&connected);
3206
						if (!res) {
3206
						if (!res) {
3207
							ast_channel_set_connected_line(caller, &connected, NULL);
3207
							ast_channel_set_connected_line(caller, &connected, NULL);
3208
						}
3208
						}
3209
						ast_party_connected_line_free(&connected);
3209
						ast_party_connected_line_free(&connected);
3210
					} else {
3210
					} else {
3211
						ast_autoservice_start(transferee);
3211
						ast_autoservice_start(transferee);
3212
						if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
3212
						if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
3213
							ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
3213
							ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
3214
								f->data.ptr, f->datalen);
3214
								f->data.ptr, f->datalen);
3215
						}
3215
						}
3216
						ast_autoservice_stop(transferee);
3216
						ast_autoservice_stop(transferee);
3217
					}
3217
					}
3218
				} else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
3218
				} else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
3219
					if (!caller_hungup) {
3219
					if (!caller_hungup) {
3220
						ast_autoservice_start(transferee);
3220
						ast_autoservice_start(transferee);
3221
						if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
3221
						if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
3222
							ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
3222
							ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
3223
								f->data.ptr, f->datalen);
3223
								f->data.ptr, f->datalen);
3224
						}
3224
						}
3225
						ast_autoservice_stop(transferee);
3225
						ast_autoservice_stop(transferee);
3226
					}
3226
					}
3227
				} else if (f->subclass.integer != -1 && f->subclass.integer != AST_CONTROL_PROGRESS) {
3227
				} else if (f->subclass.integer != -1 && f->subclass.integer != AST_CONTROL_PROGRESS) {
3228
					ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
3228
					ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
3229
				}
3229
				}
3230
				/* else who cares */
3230
				/* else who cares */
3231
			} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3231
			} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3232
				ast_write(caller, f);
3232
				ast_write(caller, f);
3233
			}
3233
			}
3234
		} else if (caller == active_channel) {
3234
		} else if (caller == active_channel) {
3235
			f = ast_read(caller);
3235
			f = ast_read(caller);
3236
			if (f) {
3236
			if (f) {
3237
				if (f->frametype == AST_FRAME_DTMF) {
3237
				if (f->frametype == AST_FRAME_DTMF) {
3238
					dialed_code[x++] = f->subclass.integer;
3238
					dialed_code[x++] = f->subclass.integer;
3239
					dialed_code[x] = '\0';
3239
					dialed_code[x] = '\0';
3240
					if (strlen(dialed_code) == len) {
3240
					if (strlen(dialed_code) == len) {
3241
						x = 0;
3241
						x = 0;
3242
					} else if (x && strncmp(dialed_code, disconnect_code, x)) {
3242
					} else if (x && strncmp(dialed_code, disconnect_code, x)) {
3243
						x = 0;
3243
						x = 0;
3244
						dialed_code[x] = '\0';
3244
						dialed_code[x] = '\0';
3245
					}
3245
					}
3246
					if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
3246
					if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
3247
						/* Caller Canceled the call */
3247
						/* Caller Canceled the call */
3248
						state = AST_CONTROL_UNHOLD;
3248
						state = AST_CONTROL_UNHOLD;
3249
						ast_frfree(f);
3249
						ast_frfree(f);
3250
						break;
3250
						break;
3251
					}
3251
					}
3252
				} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3252
				} else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3253
					ast_write(chan, f);
3253
					ast_write(chan, f);
3254
				}
3254
				}
3255
			}
3255
			}
3256
		}
3256
		}
3257
		if (f)
3257
		if (f)
3258
			ast_frfree(f);
3258
			ast_frfree(f);
3259
	} /* end while */
3259
	} /* end while */
3260

    
   
3260

   
3261
	ast_poll_channel_del(caller, chan);
3261
	ast_poll_channel_del(caller, chan);
3262

    
   
3262

   
3263
	/*
3263
	/*
3264
	 * We need to free all the deferred frames, but we only need to
3264
	 * We need to free all the deferred frames, but we only need to
3265
	 * queue the deferred frames if no hangup was received.
3265
	 * queue the deferred frames if no hangup was received.
3266
	 */
3266
	 */
3267
	ast_channel_lock(transferee);
3267
	ast_channel_lock(transferee);
3268
	transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
3268
	transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
3269
	while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
3269
	while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
3270
		if (!transferee_hungup) {
3270
		if (!transferee_hungup) {
3271
			ast_queue_frame_head(transferee, f);
3271
			ast_queue_frame_head(transferee, f);
3272
		}
3272
		}
3273
		ast_frfree(f);
3273
		ast_frfree(f);
3274
	}
3274
	}
3275
	ast_channel_unlock(transferee);
3275
	ast_channel_unlock(transferee);
3276

    
   
3276

   
3277
done:
3277
done:
3278
	ast_indicate(caller, -1);
3278
	ast_indicate(caller, -1);
3279
	if (chan && (ready || chan->_state == AST_STATE_UP)) {
3279
	if (chan && (ready || chan->_state == AST_STATE_UP)) {
3280
		state = AST_CONTROL_ANSWER;
3280
		state = AST_CONTROL_ANSWER;
3281
	} else if (chan) {
3281
	} else if (chan) {
3282
		ast_hangup(chan);
3282
		ast_hangup(chan);
3283
		chan = NULL;
3283
		chan = NULL;
3284
	}
3284
	}
3285

    
   
3285

   
3286
	tmp_cap = ast_format_cap_destroy(tmp_cap);
3286
	tmp_cap = ast_format_cap_destroy(tmp_cap);
3287

    
   
3287

   
3288
	if (outstate)
3288
	if (outstate)
3289
		*outstate = state;
3289
		*outstate = state;
3290

    
   
3290

   
3291
	return chan;
3291
	return chan;
3292
}
3292
}
3293

    
   
3293

   
3294
void ast_channel_log(char *title, struct ast_channel *chan);
3294
void ast_channel_log(char *title, struct ast_channel *chan);
3295

    
   
3295

   
3296
void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
3296
void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
3297
{
3297
{
3298
       ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long)chan);
3298
       ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long)chan);
3299
       ast_log(LOG_NOTICE, "CHAN: name: %s;  appl: %s; data: %s; contxt: %s;  exten: %s; pri: %d;\n",
3299
       ast_log(LOG_NOTICE, "CHAN: name: %s;  appl: %s; data: %s; contxt: %s;  exten: %s; pri: %d;\n",
3300
		       chan->name, chan->appl, chan->data, chan->context, chan->exten, chan->priority);
3300
		       chan->name, chan->appl, chan->data, chan->context, chan->exten, chan->priority);
3301
       ast_log(LOG_NOTICE, "CHAN: acctcode: %s;  dialcontext: %s; amaflags: %x; maccontxt: %s;  macexten: %s; macpri: %d;\n",
3301
       ast_log(LOG_NOTICE, "CHAN: acctcode: %s;  dialcontext: %s; amaflags: %x; maccontxt: %s;  macexten: %s; macpri: %d;\n",
3302
		       chan->accountcode, chan->dialcontext, chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
3302
		       chan->accountcode, chan->dialcontext, chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
3303
       ast_log(LOG_NOTICE, "CHAN: masq: %p;  masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
3303
       ast_log(LOG_NOTICE, "CHAN: masq: %p;  masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
3304
		       chan->masq, chan->masqr,
3304
		       chan->masq, chan->masqr,
3305
		       chan->_bridge, chan->uniqueid, chan->linkedid);
3305
		       chan->_bridge, chan->uniqueid, chan->linkedid);
3306
       if (chan->masqr)
3306
       if (chan->masqr)
3307
	       ast_log(LOG_NOTICE, "CHAN: masquerading as: %s;  cdr: %p;\n",
3307
	       ast_log(LOG_NOTICE, "CHAN: masquerading as: %s;  cdr: %p;\n",
3308
		               chan->masqr->name, chan->masqr->cdr);
3308
		               chan->masqr->name, chan->masqr->cdr);
3309
       if (chan->_bridge)
3309
       if (chan->_bridge)
3310
	       ast_log(LOG_NOTICE, "CHAN: Bridged to %s\n", chan->_bridge->name);
3310
	       ast_log(LOG_NOTICE, "CHAN: Bridged to %s\n", chan->_bridge->name);
3311

    
   
3311

   
3312
	ast_log(LOG_NOTICE, "===== done ====\n");
3312
	ast_log(LOG_NOTICE, "===== done ====\n");
3313
}
3313
}
3314

    
   
3314

   
3315
/*!
3315
/*!
3316
 * \brief return the first unlocked cdr in a possible chain
3316
 * \brief return the first unlocked cdr in a possible chain
3317
*/
3317
*/
3318
static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
3318
static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
3319
{
3319
{
3320
	struct ast_cdr *cdr_orig = cdr;
3320
	struct ast_cdr *cdr_orig = cdr;
3321
	while (cdr) {
3321
	while (cdr) {
3322
		if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
3322
		if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
3323
			return cdr;
3323
			return cdr;
3324
		cdr = cdr->next;
3324
		cdr = cdr->next;
3325
	}
3325
	}
3326
	return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
3326
	return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
3327
}
3327
}
3328

    
   
3328

   
3329
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
3329
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
3330
{
3330
{
3331
	const char *feature;
3331
	const char *feature;
3332

    
   
3332

   
3333
	if (ast_strlen_zero(features)) {
3333
	if (ast_strlen_zero(features)) {
3334
		return;
3334
		return;
3335
	}
3335
	}
3336

    
   
3336

   
3337
	for (feature = features; *feature; feature++) {
3337
	for (feature = features; *feature; feature++) {
3338
		switch (*feature) {
3338
		switch (*feature) {
3339
		case 'T' :
3339
		case 'T' :
3340
		case 't' :
3340
		case 't' :
3341
			ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
3341
			ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
3342
			break;
3342
			break;
3343
		case 'K' :
3343
		case 'K' :
3344
		case 'k' :
3344
		case 'k' :
3345
			ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
3345
			ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
3346
			break;
3346
			break;
3347
		case 'H' :
3347
		case 'H' :
3348
		case 'h' :
3348
		case 'h' :
3349
			ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
3349
			ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
3350
			break;
3350
			break;
3351
		case 'W' :
3351
		case 'W' :
3352
		case 'w' :
3352
		case 'w' :
3353
			ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
3353
			ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
3354
			break;
3354
			break;
3355
		default :
3355
		default :
3356
			ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
3356
			ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
3357
		}
3357
		}
3358
	}
3358
	}
3359
}
3359
}
3360

    
   
3360

   
3361
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
3361
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
3362
{
3362
{
3363
	struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
3363
	struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
3364
	struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
3364
	struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
3365

    
   
3365

   
3366
	ast_channel_lock(caller);
3366
	ast_channel_lock(caller);
3367
	ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
3367
	ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
3368
	ast_channel_unlock(caller);
3368
	ast_channel_unlock(caller);
3369
	if (!ds_caller_features) {
3369
	if (!ds_caller_features) {
3370
		if (!(ds_caller_features = ast_datastore_alloc(&dial_features_info, NULL))) {
3370
		if (!(ds_caller_features = ast_datastore_alloc(&dial_features_info, NULL))) {
3371
			ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
3371
			ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
3372
			return;
3372
			return;
3373
		}
3373
		}
3374
		if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
3374
		if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
3375
			ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
3375
			ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
3376
			ast_datastore_free(ds_caller_features);
3376
			ast_datastore_free(ds_caller_features);
3377
			return;
3377
			return;
3378
		}
3378
		}
3379
		ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
3379
		ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
3380
		caller_features->is_caller = 1;
3380
		caller_features->is_caller = 1;
3381
		ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
3381
		ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
3382
		ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
3382
		ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
3383
		ds_caller_features->data = caller_features;
3383
		ds_caller_features->data = caller_features;
3384
		ast_channel_lock(caller);
3384
		ast_channel_lock(caller);
3385
		ast_channel_datastore_add(caller, ds_caller_features);
3385
		ast_channel_datastore_add(caller, ds_caller_features);
3386
		ast_channel_unlock(caller);
3386
		ast_channel_unlock(caller);
3387
	} else {
3387
	} else {
3388
		/* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
3388
		/* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
3389
		 * flags over from the atxfer to the caller */
3389
		 * flags over from the atxfer to the caller */
3390
		return;
3390
		return;
3391
	}
3391
	}
3392

    
   
3392

   
3393
	ast_channel_lock(callee);
3393
	ast_channel_lock(callee);
3394
	ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
3394
	ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
3395
	ast_channel_unlock(callee);
3395
	ast_channel_unlock(callee);
3396
	if (!ds_callee_features) {
3396
	if (!ds_callee_features) {
3397
		if (!(ds_callee_features = ast_datastore_alloc(&dial_features_info, NULL))) {
3397
		if (!(ds_callee_features = ast_datastore_alloc(&dial_features_info, NULL))) {
3398
			ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
3398
			ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
3399
			return;
3399
			return;
3400
		}
3400
		}
3401
		if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
3401
		if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
3402
			ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
3402
			ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
3403
			ast_datastore_free(ds_callee_features);
3403
			ast_datastore_free(ds_callee_features);
3404
			return;
3404
			return;
3405
		}
3405
		}
3406
		ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
3406
		ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
3407
		callee_features->is_caller = 0;
3407
		callee_features->is_caller = 0;
3408
		ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
3408
		ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
3409
		ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
3409
		ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
3410
		ds_callee_features->data = callee_features;
3410
		ds_callee_features->data = callee_features;
3411
		ast_channel_lock(callee);
3411
		ast_channel_lock(callee);
3412
		ast_channel_datastore_add(callee, ds_callee_features);
3412
		ast_channel_datastore_add(callee, ds_callee_features);
3413
		ast_channel_unlock(callee);
3413
		ast_channel_unlock(callee);
3414
	}
3414
	}
3415

    
   
3415

   
3416
	return;
3416
	return;
3417
}
3417
}
3418

    
   
3418

   
3419
/*!
3419
/*!
3420
 * \brief bridge the call and set CDR
3420
 * \brief bridge the call and set CDR
3421
 * \param chan,peer,config
3421
 * \param chan,peer,config
3422
 * 
3422
 * 
3423
 * Set start time, check for two channels,check if monitor on
3423
 * Set start time, check for two channels,check if monitor on
3424
 * check for feature activation, create new CDR
3424
 * check for feature activation, create new CDR
3425
 * \retval res on success.
3425
 * \retval res on success.
3426
 * \retval -1 on failure to bridge.
3426
 * \retval -1 on failure to bridge.
3427
*/
3427
*/
3428
int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
3428
int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
3429
{
3429
{
3430
	/* Copy voice back and forth between the two channels.  Give the peer
3430
	/* Copy voice back and forth between the two channels.  Give the peer
3431
	   the ability to transfer calls with '#<extension' syntax. */
3431
	   the ability to transfer calls with '#<extension' syntax. */
3432
	struct ast_frame *f;
3432
	struct ast_frame *f;
3433
	struct ast_channel *who;
3433
	struct ast_channel *who;
3434
	char chan_featurecode[FEATURE_MAX_LEN + 1]="";
3434
	char chan_featurecode[FEATURE_MAX_LEN + 1]="";
3435
	char peer_featurecode[FEATURE_MAX_LEN + 1]="";
3435
	char peer_featurecode[FEATURE_MAX_LEN + 1]="";
3436
	char orig_channame[AST_MAX_EXTENSION];
3436
	char orig_channame[AST_MAX_EXTENSION];
3437
	char orig_peername[AST_MAX_EXTENSION];
3437
	char orig_peername[AST_MAX_EXTENSION];
3438
	int res;
3438
	int res;
3439
	int diff;
3439
	int diff;
3440
	int hasfeatures=0;
3440
	int hasfeatures=0;
3441
	int hadfeatures=0;
3441
	int hadfeatures=0;
3442
	int autoloopflag;
3442
	int autoloopflag;
3443
	int sendingdtmfdigit = 0;
3443
	int sendingdtmfdigit = 0;
3444
	int we_disabled_peer_cdr = 0;
3444
	int we_disabled_peer_cdr = 0;
3445
	struct ast_option_header *aoh;
3445
	struct ast_option_header *aoh;
3446
	struct ast_cdr *bridge_cdr = NULL;
3446
	struct ast_cdr *bridge_cdr = NULL;
3447
	struct ast_cdr *orig_peer_cdr = NULL;
3447
	struct ast_cdr *orig_peer_cdr = NULL;
3448
	struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
3448
	struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
3449
	struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
3449
	struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
3450
	struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3450
	struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3451
	struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3451
	struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3452
	struct ast_silence_generator *silgen = NULL;
3452
	struct ast_silence_generator *silgen = NULL;
3453

    
   
3453

   
3454
	if (chan && peer) {
3454
	if (chan && peer) {
3455
		pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
3455
		pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
3456
		pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
3456
		pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
3457
	} else if (chan) {
3457
	} else if (chan) {
3458
		pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
3458
		pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
3459
	}
3459
	}
3460

    
   
3460

   
3461
	set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
3461
	set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
3462
	add_features_datastores(chan, peer, config);
3462
	add_features_datastores(chan, peer, config);
3463

    
   
3463

   
3464
	/* This is an interesting case.  One example is if a ringing channel gets redirected to
3464
	/* This is an interesting case.  One example is if a ringing channel gets redirected to
3465
	 * an extension that picks up a parked call.  This will make sure that the call taken
3465
	 * an extension that picks up a parked call.  This will make sure that the call taken
3466
	 * out of parking gets told that the channel it just got bridged to is still ringing. */
3466
	 * out of parking gets told that the channel it just got bridged to is still ringing. */
3467
	if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
3467
	if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
3468
		ast_indicate(peer, AST_CONTROL_RINGING);
3468
		ast_indicate(peer, AST_CONTROL_RINGING);
3469
	}
3469
	}
3470

    
   
3470

   
3471
	if (monitor_ok) {
3471
	if (monitor_ok) {
3472
		const char *monitor_exec;
3472
		const char *monitor_exec;
3473
		struct ast_channel *src = NULL;
3473
		struct ast_channel *src = NULL;
3474
		if (!monitor_app) {
3474
		if (!monitor_app) {
3475
			if (!(monitor_app = pbx_findapp("Monitor")))
3475
			if (!(monitor_app = pbx_findapp("Monitor")))
3476
				monitor_ok=0;
3476
				monitor_ok=0;
3477
		}
3477
		}
3478
		if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
3478
		if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
3479
			src = chan;
3479
			src = chan;
3480
		else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
3480
		else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
3481
			src = peer;
3481
			src = peer;
3482
		if (monitor_app && src) {
3482
		if (monitor_app && src) {
3483
			char *tmp = ast_strdupa(monitor_exec);
3483
			char *tmp = ast_strdupa(monitor_exec);
3484
			pbx_exec(src, monitor_app, tmp);
3484
			pbx_exec(src, monitor_app, tmp);
3485
		}
3485
		}
3486
	}
3486
	}
3487

    
   
3487

   
3488
	set_config_flags(chan, peer, config);
3488
	set_config_flags(chan, peer, config);
3489

    
   
3489

   
3490
	/* Answer if need be */
3490
	/* Answer if need be */
3491
	if (chan->_state != AST_STATE_UP) {
3491
	if (chan->_state != AST_STATE_UP) {
3492
		if (ast_raw_answer(chan, 1)) {
3492
		if (ast_raw_answer(chan, 1)) {
3493
			return -1;
3493
			return -1;
3494
		}
3494
		}
3495
	}
3495
	}
3496

    
   
3496

   
3497
#ifdef FOR_DEBUG
3497
#ifdef FOR_DEBUG
3498
	/* show the two channels and cdrs involved in the bridge for debug & devel purposes */
3498
	/* show the two channels and cdrs involved in the bridge for debug & devel purposes */
3499
	ast_channel_log("Pre-bridge CHAN Channel info", chan);
3499
	ast_channel_log("Pre-bridge CHAN Channel info", chan);
3500
	ast_channel_log("Pre-bridge PEER Channel info", peer);
3500
	ast_channel_log("Pre-bridge PEER Channel info", peer);
3501
#endif
3501
#endif
3502
	/* two channels are being marked as linked here */
3502
	/* two channels are being marked as linked here */
3503
	ast_channel_set_linkgroup(chan,peer);
3503
	ast_channel_set_linkgroup(chan,peer);
3504

    
   
3504

   
3505
	/* copy the userfield from the B-leg to A-leg if applicable */
3505
	/* copy the userfield from the B-leg to A-leg if applicable */
3506
	if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
3506
	if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
3507
		char tmp[256];
3507
		char tmp[256];
3508
		if (!ast_strlen_zero(chan->cdr->userfield)) {
3508
		if (!ast_strlen_zero(chan->cdr->userfield)) {
3509
			snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
3509
			snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
3510
			ast_cdr_appenduserfield(chan, tmp);
3510
			ast_cdr_appenduserfield(chan, tmp);
3511
		} else
3511
		} else
3512
			ast_cdr_setuserfield(chan, peer->cdr->userfield);
3512
			ast_cdr_setuserfield(chan, peer->cdr->userfield);
3513
		/* Don't delete the CDR; just disable it. */
3513
		/* Don't delete the CDR; just disable it. */
3514
		ast_set_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
3514
		ast_set_flag(peer->cdr, AST_CDR_FLAG_POST_DISABLED);
3515
		we_disabled_peer_cdr = 1;
3515
		we_disabled_peer_cdr = 1;
3516
	}
3516
	}
3517
	ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
3517
	ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
3518
	ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
3518
	ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
3519
	orig_peer_cdr = peer_cdr;
3519
	orig_peer_cdr = peer_cdr;
3520
	
3520
	
3521
	if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
3521
	if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
3522
		
3522
		
3523
		if (chan_cdr) {
3523
		if (chan_cdr) {
3524
			ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
3524
			ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
3525
			ast_cdr_update(chan);
3525
			ast_cdr_update(chan);
3526
			bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
3526
			bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
3527
			/* rip any forked CDR's off of the chan_cdr and attach
3527
			/* rip any forked CDR's off of the chan_cdr and attach
3528
			 * them to the bridge_cdr instead */
3528
			 * them to the bridge_cdr instead */
3529
			bridge_cdr->next = chan_cdr->next;
3529
			bridge_cdr->next = chan_cdr->next;
3530
			chan_cdr->next = NULL;
3530
			chan_cdr->next = NULL;
3531
			ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
3531
			ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
3532
			ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
3532
			ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
3533
			if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
3533
			if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
3534
				ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
3534
				ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
3535
			}
3535
			}
3536
			ast_cdr_setaccount(peer, chan->accountcode);
3536
			ast_cdr_setaccount(peer, chan->accountcode);
3537

    
   
3537

   
3538
		} else {
3538
		} else {
3539
			/* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
3539
			/* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
3540
			bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
3540
			bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
3541
			ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
3541
			ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
3542
			ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
3542
			ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
3543
			ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
3543
			ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
3544
			ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
3544
			ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
3545
			ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
3545
			ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
3546
			ast_cdr_setcid(bridge_cdr, chan);
3546
			ast_cdr_setcid(bridge_cdr, chan);
3547
			bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
3547
			bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
3548
			bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
3548
			bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
3549
			ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
3549
			ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
3550
			/* Destination information */
3550
			/* Destination information */
3551
			ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
3551
			ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
3552
			ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
3552
			ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
3553
			if (peer_cdr) {
3553
			if (peer_cdr) {
3554
				bridge_cdr->start = peer_cdr->start;
3554
				bridge_cdr->start = peer_cdr->start;
3555
				ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
3555
				ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
3556
			} else {
3556
			} else {
3557
				ast_cdr_start(bridge_cdr);
3557
				ast_cdr_start(bridge_cdr);
3558
			}
3558
			}
3559
		}
3559
		}
3560
		ast_debug(4, "bridge answer set, chan answer set\n");
3560
		ast_debug(4, "bridge answer set, chan answer set\n");
3561
		/* peer_cdr->answer will be set when a macro runs on the peer;
3561
		/* peer_cdr->answer will be set when a macro runs on the peer;
3562
		   in that case, the bridge answer will be delayed while the
3562
		   in that case, the bridge answer will be delayed while the
3563
		   macro plays on the peer channel. The peer answered the call
3563
		   macro plays on the peer channel. The peer answered the call
3564
		   before the macro started playing. To the phone system,
3564
		   before the macro started playing. To the phone system,
3565
		   this is billable time for the call, even tho the caller
3565
		   this is billable time for the call, even tho the caller
3566
		   hears nothing but ringing while the macro does its thing. */
3566
		   hears nothing but ringing while the macro does its thing. */
3567

    
   
3567

   
3568
		/* Another case where the peer cdr's time will be set, is when
3568
		/* Another case where the peer cdr's time will be set, is when
3569
		   A self-parks by pickup up phone and dialing 700, then B
3569
		   A self-parks by pickup up phone and dialing 700, then B
3570
		   picks up A by dialing its parking slot; there may be more 
3570
		   picks up A by dialing its parking slot; there may be more 
3571
		   practical paths that get the same result, tho... in which
3571
		   practical paths that get the same result, tho... in which
3572
		   case you get the previous answer time from the Park... which
3572
		   case you get the previous answer time from the Park... which
3573
		   is before the bridge's start time, so I added in the 
3573
		   is before the bridge's start time, so I added in the 
3574
		   tvcmp check to the if below */
3574
		   tvcmp check to the if below */
3575

    
   
3575

   
3576
		if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
3576
		if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
3577
			ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
3577
			ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
3578
			ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
3578
			ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
3579
			if (chan_cdr) {
3579
			if (chan_cdr) {
3580
				ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
3580
				ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
3581
				ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
3581
				ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
3582
			}
3582
			}
3583
		} else {
3583
		} else {
3584
			ast_cdr_answer(bridge_cdr);
3584
			ast_cdr_answer(bridge_cdr);
3585
			if (chan_cdr) {
3585
			if (chan_cdr) {
3586
				ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
3586
				ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
3587
			}
3587
			}
3588
		}
3588
		}
3589
		if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
3589
		if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
3590
			if (chan_cdr) {
3590
			if (chan_cdr) {
3591
				ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
3591
				ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
3592
			}
3592
			}
3593
			if (peer_cdr) {
3593
			if (peer_cdr) {
3594
				ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
3594
				ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
3595
			}
3595
			}
3596
		}
3596
		}
3597
		/* the DIALED flag may be set if a dialed channel is transfered
3597
		/* the DIALED flag may be set if a dialed channel is transfered
3598
		 * and then bridged to another channel.  In order for the
3598
		 * and then bridged to another channel.  In order for the
3599
		 * bridge CDR to be written, the DIALED flag must not be
3599
		 * bridge CDR to be written, the DIALED flag must not be
3600
		 * present. */
3600
		 * present. */
3601
		ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
3601
		ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
3602
	}
3602
	}
3603
	ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, NULL);
3603
	ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, NULL);
3604
	for (;;) {
3604
	for (;;) {
3605
		struct ast_channel *other;	/* used later */
3605
		struct ast_channel *other;	/* used later */
3606
	
3606
	
3607
		res = ast_channel_bridge(chan, peer, config, &f, &who);
3607
		res = ast_channel_bridge(chan, peer, config, &f, &who);
3608
		
3608
		
3609
		/* When frame is not set, we are probably involved in a situation
3609
		/* When frame is not set, we are probably involved in a situation
3610
		   where we've timed out.
3610
		   where we've timed out.
3611
		   When frame is set, we'll come this code twice; once for DTMF_BEGIN
3611
		   When frame is set, we'll come this code twice; once for DTMF_BEGIN
3612
		   and also for DTMF_END. If we flow into the following 'if' for both, then 
3612
		   and also for DTMF_END. If we flow into the following 'if' for both, then 
3613
		   our wait times are cut in half, as both will subtract from the
3613
		   our wait times are cut in half, as both will subtract from the
3614
		   feature_timer. Not good!
3614
		   feature_timer. Not good!
3615
		*/
3615
		*/
3616
		if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
3616
		if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
3617
			/* Update feature timer for next pass */
3617
			/* Update feature timer for next pass */
3618
			diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
3618
			diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
3619
			if (res == AST_BRIDGE_RETRY) {
3619
			if (res == AST_BRIDGE_RETRY) {
3620
				/* The feature fully timed out but has not been updated. Skip
3620
				/* The feature fully timed out but has not been updated. Skip
3621
				 * the potential round error from the diff calculation and
3621
				 * the potential round error from the diff calculation and
3622
				 * explicitly set to expired. */
3622
				 * explicitly set to expired. */
3623
				config->feature_timer = -1;
3623
				config->feature_timer = -1;
3624
			} else {
3624
			} else {
3625
				config->feature_timer -= diff;
3625
				config->feature_timer -= diff;
3626
			}
3626
			}
3627

    
   
3627

   
3628
			if (hasfeatures) {
3628
			if (hasfeatures) {
3629
				if (config->feature_timer <= 0) {
3629
				if (config->feature_timer <= 0) {
3630
					/* Not *really* out of time, just out of time for
3630
					/* Not *really* out of time, just out of time for
3631
					   digits to come in for features. */
3631
					   digits to come in for features. */
3632
					ast_debug(1, "Timed out for feature!\n");
3632
					ast_debug(1, "Timed out for feature!\n");
3633
					if (!ast_strlen_zero(peer_featurecode)) {
3633
					if (!ast_strlen_zero(peer_featurecode)) {
3634
						ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
3634
						ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
3635
						memset(peer_featurecode, 0, sizeof(peer_featurecode));
3635
						memset(peer_featurecode, 0, sizeof(peer_featurecode));
3636
					}
3636
					}
3637
					if (!ast_strlen_zero(chan_featurecode)) {
3637
					if (!ast_strlen_zero(chan_featurecode)) {
3638
						ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
3638
						ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
3639
						memset(chan_featurecode, 0, sizeof