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

Changes between revision 5 and 15

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
Diff Revision 5 Diff Revision 15
[20] 97 lines
[+20] [+] static const char app[] = "Pickup";
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
/* 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 */
101
static int can_pickup(struct ast_channel *chan)
101
static int can_pickup(struct ast_channel *chan)
102
{
102
{
103
	if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
103
	if (!chan->pbx && !chan->masq &&

    
   
104
		!ast_test_flag(chan, AST_FLAG_ZOMBIE) &&

    
   
105
		(chan->_state == AST_STATE_RINGING ||

    
   
106
		 chan->_state == AST_STATE_RING ||

    
   
107
		 chan->_state == AST_STATE_DOWN)) {
104
		return 1;
108
		return 1;
105
	else
109
	}
106
		return 0;
110
	return 0;
107
}
111
}
108

    
   
112

   
109
struct pickup_by_name_args {
113
struct pickup_by_name_args {
110
	const char *name;
114
	const char *name;
[+20] [20] 55 lines
[+20] [+] static int pickup_by_channel(struct ast_channel *chan, char *pickup)
166

    
   
170

   
167
	/* Just check that we are not picking up the SAME as target */
171
	/* Just check that we are not picking up the SAME as target */
168
	if (chan != target) {
172
	if (chan != target) {
169
		res = ast_do_pickup(chan, target);
173
		res = ast_do_pickup(chan, target);
170
	}
174
	}
171

    
   

   
172
	ast_channel_unlock(target);
175
	ast_channel_unlock(target);
173
	target = ast_channel_unref(target);
176
	target = ast_channel_unref(target);
174

    
   
177

   
175
	return res;
178
	return res;
176
}
179
}
[+20] [20] 10 lines
[+20] [+] static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
187
	}
190
	}
188

    
   
191

   
189
	while ((target = ast_channel_iterator_next(iter))) {
192
	while ((target = ast_channel_iterator_next(iter))) {
190
		ast_channel_lock(target);
193
		ast_channel_lock(target);
191
		if ((chan != target) && can_pickup(target)) {
194
		if ((chan != target) && can_pickup(target)) {

    
   
195
			ast_log(LOG_NOTICE, "%s pickup by %s\n", target->name, chan->name);
192
			break;
196
			break;
193
		}
197
		}
194
		ast_channel_unlock(target);
198
		ast_channel_unlock(target);
195
		target = ast_channel_unref(target);
199
		target = ast_channel_unref(target);
196
	}
200
	}
[+20] [20] 31 lines
[+20] [+] static int find_by_mark(void *obj, void *arg, void *data, int flags)
228
static int pickup_by_mark(struct ast_channel *chan, const char *mark)
232
static int pickup_by_mark(struct ast_channel *chan, const char *mark)
229
{
233
{
230
	struct ast_channel *target;
234
	struct ast_channel *target;
231
	int res = -1;
235
	int res = -1;
232

    
   
236

   
233
	if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
237
	if (!(target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {

    
   
238
		return res;

    
   
239
	}

    
   
240

   
234
		ast_channel_lock(target);
241
	ast_channel_lock(target);

    
   
242
	if (can_pickup(target)) {
235
		res = ast_do_pickup(chan, target);
243
		res = ast_do_pickup(chan, target);

    
   
244
	} else {

    
   
245
		ast_log(LOG_WARNING, "target has gone, or not ringing anymore for %s\n", chan->name);

    
   
246
	}
236
		ast_channel_unlock(target);
247
	ast_channel_unlock(target);
237
		target = ast_channel_unref(target);
248
	target = ast_channel_unref(target);
238
	}

   
239

    
   
249

   
240
	return res;
250
	return res;
241
}
251
}
242

    
   
252

   
243
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
253
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
244
{
254
{
245
	struct ast_channel *chan = obj;
255
	struct ast_channel *chan = obj;
246
	struct ast_channel *c = data;
256
	struct ast_channel *c = data;

    
   
257
	int i;
247

    
   
258

   
248
	ast_channel_lock(chan);
259
	ast_channel_lock(chan);
249
	int i = (c != chan) &&
260
	i = (c != chan) && (chan->pickupgroup & c->callgroup) &&
250
		(chan->pickupgroup & c->callgroup) &&
261
		can_pickup(chan);
251
		!c->masq && can_pickup(chan);

   
252

    
   
262

   
253
	ast_channel_unlock(chan);
263
	ast_channel_unlock(chan);
254
	return i ? CMP_MATCH | CMP_STOP : 0;
264
	return i ? CMP_MATCH | CMP_STOP : 0;
255
}
265
}
256

    
   
266

   
257
static int pickup_by_group(struct ast_channel *chan)
267
static int pickup_by_group(struct ast_channel *chan)
258
{
268
{
259
	struct ast_channel *target;
269
	struct ast_channel *target;
260
	int res = -1;
270
	int res = -1;
261
	if ((target = ast_channel_callback(find_channel_by_group, NULL, chan, 0))) {
271

   

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

    
   
273
		return res;

    
   
274
	}

    
   
275

   

    
   
276
	ast_log(LOG_NOTICE, "%s, pickup attempt by %s\n", target->name, chan->name);
262
		ast_channel_lock(target);
277
	ast_channel_lock(target);

    
   
278
	if (can_pickup(target)) {
263
		res = ast_do_pickup(chan, target);
279
		res = ast_do_pickup(chan, target);

    
   
280
	} else {

    
   
281
		ast_log(LOG_WARNING, "target has gone, or not ringing anymore for %s\n", chan->name);

    
   
282
	}
264
		ast_channel_unlock(target);
283
	ast_channel_unlock(target);
265
		target = ast_channel_unref(target);
284
	target = ast_channel_unref(target);
266
	}
285

   
267
	return res;
286
	return res;
268
}
287
}
269

    
   
288

   
270
/* application entry point for Pickup() */
289
/* application entry point for Pickup() */
271
static int pickup_exec(struct ast_channel *chan, const char *data)
290
static int pickup_exec(struct ast_channel *chan, const char *data)
[+20] [20] 4 lines
[+20] static int pickup_by_group(struct ast_channel *chan)
276

    
   
295

   
277
	if (ast_strlen_zero(data)) {
296
	if (ast_strlen_zero(data)) {
278
		res = pickup_by_group(chan);
297
		res = pickup_by_group(chan);
279
		return res;
298
		return res;
280
	}
299
	}
281
	
300

   
282
	/* Parse extension (and context if there) */
301
	/* Parse extension (and context if there) */
283
	while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
302
	while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
284
		if ((context = strchr(exten, '@')))
303
		if ((context = strchr(exten, '@')))
285
			*context++ = '\0';
304
			*context++ = '\0';
286
		if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
305
		if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
[+20] [20] 32 lines
[+20] [+] static int pickup_by_part(struct ast_channel *chan, const char *part)
319
	struct ast_channel *target;
338
	struct ast_channel *target;
320
	int res = -1;
339
	int res = -1;
321

    
   
340

   
322
	if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) {
341
	if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) {
323
		ast_channel_lock(target);
342
		ast_channel_lock(target);

    
   
343
		if (can_pickup(target)) {
324
		res = ast_do_pickup(chan, target);
344
			res = ast_do_pickup(chan, target);

    
   
345
		} else {

    
   
346
			ast_log(LOG_WARNING, "target has gone, or not ringing anymore for %s\n", chan->name);

    
   
347
		}
325
		ast_channel_unlock(target);
348
		ast_channel_unlock(target);
326
		target = ast_channel_unref(target);
349
		target = ast_channel_unref(target);
327
	}
350
	}
328

    
   
351

   
329
	return res;
352
	return res;
[+20] [20] 64 lines
trunk/channels/chan_sip.c
Diff Revision 5 Diff Revision 15
 
trunk/include/asterisk/features.h
Diff Revision 5 Diff Revision 15
 
trunk/main/features.c
Diff Revision 5 Diff Revision 15
 
trunk/res/res_features.exports.in
Diff Revision 5 Diff Revision 15 - File Reverted
 
  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.