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 4

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 314594 New Change
[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
/* Perform actual pickup between two channels */
100
/* Perform actual pickup between two channels */
101
static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
101
static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
102
{
102
{
103
	int res = 0;
103
	return ast_do_pickup(chan, target);
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
}
104
}
146

    
   
105

   
147
/* Helper function that determines whether a channel is capable of being picked up */
106
/* Helper function that determines whether a channel is capable of being picked up */
148
static int can_pickup(struct ast_channel *chan)
107
static int can_pickup(struct ast_channel *chan)
149
{
108
{
[+20] [20] 135 lines
[+20] [+] static int pickup_by_mark(struct ast_channel *chan, const char *mark)
285
	}
244
	}
286

    
   
245

   
287
	return res;
246
	return res;
288
}
247
}
289

    
   
248

   

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

    
   
250
{

    
   
251
	struct ast_channel *c = data;

    
   
252
	struct ast_channel *chan = obj;

    
   
253

   

    
   
254
	ast_channel_lock(chan);

    
   
255
	int i = !chan->pbx &&

    
   
256
		(c != chan) &&

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

    
   
258
		((chan->_state == AST_STATE_RINGING) || (chan->_state == AST_STATE_RING)) &&

    
   
259
		!c->masq;

    
   
260

   

    
   
261
	ast_channel_unlock(chan);

    
   
262
	return i ? CMP_MATCH | CMP_STOP : 0;

    
   
263
}

    
   
264

   

    
   
265
static int pickup_by_group(struct ast_channel *chan)

    
   
266
{

    
   
267
	struct ast_channel *target;

    
   
268
	int res = -1;

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

    
   
270
		ast_channel_lock(target);

    
   
271
		res = ast_do_pickup(chan, target);

    
   
272
		ast_channel_unlock(target);

    
   
273
		target = ast_channel_unref(target);

    
   
274
	}

    
   
275
	return res;

    
   
276
}

    
   
277

   
290
/* application entry point for Pickup() */
278
/* application entry point for Pickup() */
291
static int pickup_exec(struct ast_channel *chan, const char *data)
279
static int pickup_exec(struct ast_channel *chan, const char *data)
292
{
280
{
293
	int res = 0;
281
	int res = 0;
294
	char *tmp = ast_strdupa(data);
282
	char *tmp = ast_strdupa(data);
295
	char *exten = NULL, *context = NULL;
283
	char *exten = NULL, *context = NULL;
296

    
   
284

   
297
	if (ast_strlen_zero(data)) {
285
	if (ast_strlen_zero(data)) {
298
		res = ast_pickup_call(chan);
286
		res = pickup_by_group(chan);
299
		return res;
287
		return res;
300
	}
288
	}
301
	
289
	
302
	/* Parse extension (and context if there) */
290
	/* Parse extension (and context if there) */
303
	while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
291
	while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
[+20] [20] 110 lines
trunk/channels/chan_sip.c
Revision 314594 New Change
 
trunk/include/asterisk/features.h
Revision 314594 New Change
 
trunk/main/features.c
Revision 314594 New Change
 
trunk/res/res_features.exports.in
Revision 314594 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.