Review Board 1.7.16


Fix directed group pickup feature code *8 with pickupsounds enabled , deadlock and segfault, affects 1.8.0 and trunk

Review Request #1185 - Created April 17, 2011 and submitted

Alec Davis
trunk
18654
Reviewers
asterisk-dev
rmudgett
Asterisk
Since 1.8, the new pickupsound and pickupfailsound in features.conf cause many issues.

1). chan_sip:handle_request_invite() shouldn't be playing out the fail/success audio, as it has 'netlock' locked.
2). dialplan applications for directed_pickups shouldn't beep.
3). feature code for directed pickup should beep on success/failure if configured.

Moved app_directed:pickup_do() to features:ast_do_pickup().

Functions below, all now use the new ast_do_pickup()
app_directed_pickup.c:
   pickup_by_channel()
   pickup_by_exten()
   pickup_by_mark()
   pickup_by_part()
features.c:
   ast_pickup_call()

Created a sip_pickup() thread to handle the pickup and playout the audio, spawned from handle_request_invite.
pickup using *8 feature code, with pickup sounds enabled/disabled

exten => 71,1,Pickup()           ; any ringing extension in same pickupgroup 
exten => 72,1,Pickup(85@phones)  ; dahdi extension
exten => 73,1,Pickup(823@phones) ; sip extension

Diff revision 5

This is not the most recent revision of the diff. The latest diff is revision 16. See what's changed.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

  1. trunk/apps/app_directed_pickup.c: Loading...
  2. trunk/channels/chan_sip.c: Loading...
  3. trunk/include/asterisk/features.h: Loading...
  4. trunk/main/features.c: Loading...
  5. trunk/res/res_features.exports.in: Loading...
trunk/apps/app_directed_pickup.c
Revision 316037 New Change
[20] 94 lines
[+20] [+] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
95

    
   
95

   
96
static const char app[] = "Pickup";
96
static const char app[] = "Pickup";
97
static const char app2[] = "PickupChan";
97
static const char app2[] = "PickupChan";
98
/*! \todo This application should return a result code, like PICKUPRESULT */
98
/*! \todo This application should return a result code, like PICKUPRESULT */
99

    
   
99

   
100
/* Perform actual pickup between two channels */

   
101
static int pickup_do(struct ast_channel *chan, struct ast_channel *target)

   
102
{

   
103
	int res = 0;

   
104
	struct ast_party_connected_line connected_caller;

   
105
	struct ast_channel *chans[2] = { chan, target };

   
106

    
   

   
107
	ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);

   
108
	ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);

   
109

    
   

   
110
	ast_party_connected_line_init(&connected_caller);

   
111
	ast_party_connected_line_copy(&connected_caller, &target->connected);

   
112
	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;

   
113
	if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {

   
114
		ast_channel_update_connected_line(chan, &connected_caller, NULL);

   
115
	}

   
116
	ast_party_connected_line_free(&connected_caller);

   
117

    
   

   
118
	ast_channel_lock(chan);

   
119
	ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);

   
120
	ast_channel_unlock(chan);

   
121
	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;

   
122
	ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);

   
123
	ast_party_connected_line_free(&connected_caller);

   
124

    
   

   
125
	if ((res = ast_answer(chan))) {

   
126
		ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);

   
127
		return -1;

   
128
	}

   
129

    
   

   
130
	if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {

   
131
		ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);

   
132
		return -1;

   
133
	}

   
134

    
   

   
135
	if ((res = ast_channel_masquerade(target, chan))) {

   
136
		ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);

   
137
		return -1;

   
138
	}

   
139

    
   

   
140
	/* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */

   
141
	ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,

   
142
		"Channel: %s\r\nTargetChannel: %s\r\n", chan->name, target->name);

   
143

    
   

   
144
	return res;

   
145
}

   
146

    
   

   
147
/* Helper function that determines whether a channel is capable of being picked up */
100
/* Helper function that determines whether a channel is capable of being picked up */
148
static int can_pickup(struct ast_channel *chan)
101
static int can_pickup(struct ast_channel *chan)
149
{
102
{
150
	if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
103
	if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
151
		return 1;
104
		return 1;
[+20] [20] 59 lines
[+20] [+] static int pickup_by_channel(struct ast_channel *chan, char *pickup)
211
		return -1;
164
		return -1;
212
	}
165
	}
213

    
   
166

   
214
	/* Just check that we are not picking up the SAME as target */
167
	/* Just check that we are not picking up the SAME as target */
215
	if (chan != target) {
168
	if (chan != target) {
216
		res = pickup_do(chan, target);
169
		res = ast_do_pickup(chan, target);
217
	}
170
	}
218

    
   
171

   
219
	ast_channel_unlock(target);
172
	ast_channel_unlock(target);
220
	target = ast_channel_unref(target);
173
	target = ast_channel_unref(target);
221

    
   
174

   
[+20] [20] 21 lines
[+20] [+] static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
243
	}
196
	}
244

    
   
197

   
245
	ast_channel_iterator_destroy(iter);
198
	ast_channel_iterator_destroy(iter);
246

    
   
199

   
247
	if (target) {
200
	if (target) {
248
		res = pickup_do(chan, target);
201
		res = ast_do_pickup(chan, target);
249
		ast_channel_unlock(target);
202
		ast_channel_unlock(target);
250
		target = ast_channel_unref(target);
203
		target = ast_channel_unref(target);
251
	}
204
	}
252

    
   
205

   
253
	return res;
206
	return res;
[+20] [20] 23 lines
[+20] [+] static int pickup_by_mark(struct ast_channel *chan, const char *mark)
277
	struct ast_channel *target;
230
	struct ast_channel *target;
278
	int res = -1;
231
	int res = -1;
279

    
   
232

   
280
	if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
233
	if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
281
		ast_channel_lock(target);
234
		ast_channel_lock(target);
282
		res = pickup_do(chan, target);
235
		res = ast_do_pickup(chan, target);
283
		ast_channel_unlock(target);
236
		ast_channel_unlock(target);
284
		target = ast_channel_unref(target);
237
		target = ast_channel_unref(target);
285
	}
238
	}
286

    
   
239

   
287
	return res;
240
	return res;
288
}
241
}
289

    
   
242

   

    
   
243
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)

    
   
244
{

    
   
245
	struct ast_channel *chan = obj;

    
   
246
	struct ast_channel *c = data;

    
   
247

   

    
   
248
	ast_channel_lock(chan);

    
   
249
	int i = (c != chan) &&

    
   
250
		(chan->pickupgroup & c->callgroup) &&

    
   
251
		!c->masq && can_pickup(chan);

    
   
252

   

    
   
253
	ast_channel_unlock(chan);

    
   
254
	return i ? CMP_MATCH | CMP_STOP : 0;

    
   
255
}

    
   
256

   

    
   
257
static int pickup_by_group(struct ast_channel *chan)

    
   
258
{

    
   
259
	struct ast_channel *target;

    
   
260
	int res = -1;

    
   
261
	if ((target = ast_channel_callback(find_channel_by_group, NULL, chan, 0))) {

    
   
262
		ast_channel_lock(target);

    
   
263
		res = ast_do_pickup(chan, target);

    
   
264
		ast_channel_unlock(target);

    
   
265
		target = ast_channel_unref(target);

    
   
266
	}

    
   
267
	return res;

    
   
268
}

    
   
269

   
290
/* application entry point for Pickup() */
270
/* application entry point for Pickup() */
291
static int pickup_exec(struct ast_channel *chan, const char *data)
271
static int pickup_exec(struct ast_channel *chan, const char *data)
292
{
272
{
293
	int res = 0;
273
	int res = 0;
294
	char *tmp = ast_strdupa(data);
274
	char *tmp = ast_strdupa(data);
295
	char *exten = NULL, *context = NULL;
275
	char *exten = NULL, *context = NULL;
296

    
   
276

   
297
	if (ast_strlen_zero(data)) {
277
	if (ast_strlen_zero(data)) {
298
		res = ast_pickup_call(chan);
278
		res = pickup_by_group(chan);
299
		return res;
279
		return res;
300
	}
280
	}
301
	
281
	
302
	/* Parse extension (and context if there) */
282
	/* Parse extension (and context if there) */
303
	while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
283
	while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
[+20] [20] 35 lines
[+20] [+] static int pickup_by_part(struct ast_channel *chan, const char *part)
339
	struct ast_channel *target;
319
	struct ast_channel *target;
340
	int res = -1;
320
	int res = -1;
341

    
   
321

   
342
	if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) {
322
	if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) {
343
		ast_channel_lock(target);
323
		ast_channel_lock(target);
344
		res = pickup_do(chan, target);
324
		res = ast_do_pickup(chan, target);
345
		ast_channel_unlock(target);
325
		ast_channel_unlock(target);
346
		target = ast_channel_unref(target);
326
		target = ast_channel_unref(target);
347
	}
327
	}
348

    
   
328

   
349
	return res;
329
	return res;
[+20] [20] 64 lines
trunk/channels/chan_sip.c
Revision 316037 New Change
 
trunk/include/asterisk/features.h
Revision 316037 New Change
 
trunk/main/features.c
Revision 316037 New Change
 
trunk/res/res_features.exports.in
Revision 316037 New Change
 
  1. trunk/apps/app_directed_pickup.c: Loading...
  2. trunk/channels/chan_sip.c: Loading...
  3. trunk/include/asterisk/features.h: Loading...
  4. trunk/main/features.c: Loading...
  5. trunk/res/res_features.exports.in: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.