Review Board 1.7.16


Backport of state_interface for app_queue in Asterisk 1.4

Review Request #116 - Created Jan. 5, 2009 and submitted

Mark Michelson
1.4
Reviewers
asterisk-dev
Asterisk
This is a backport of functionality that is already in all releases of Asterisk 1.6.

The functionality being added here is the ability to associate an interface with a queue member which is used to determine that member's device state.
A common usage for such functionality is to accurately determine the device state of a queue member who is called via the Agent or Local channel 
technologies. By specifying a more "concrete" interface to watch for device state, the queue application can more accurately decide the availability
of the queue member.

The policy for Asterisk 1.4 is to not introduce new functionality, and only make bug fixes. This case is one where the line has been blurred significantly
and so community feedback would be helpful. From a development standpoint, this violates the policy since most of what is being added is a new option for
queue members. From many users' perspectives, however, this is a means of solving a deficiency in the basic operations of queues. Please take a look at the
diff attached and comment on whether this would be problematic. It is implemented in such a way that any old dialplans, CLI commands, manager commands, etc.
will not need to be updated unless you are making use of this new functionality.

In internal discussions, the only point that was brought up was a possible problem that could aris if using persistent members. If you upgraded to a version 
that had the state interface functionality in it and then downgraded to a version which did not have state interface functionality, then the queue members' 
names loaded from the database would be wrong (they would have a semicolon and the state interface appended). Since the members' names are only used for display 
purposes, since the error may be easily corrected by reloading the queue configuration,and since the number of people likely to be affected by this is very 
small, I feel it's a risk worth taking.

Another potential problem I have thought of is that Asterisk 1.4 does not contain func_devstate. This means that this solution will only work if
you know for sure what endpoint will be dialed when a call is placed from a queue. To give an example, if you know that calling Local/2000 will always 
end up dialing SIP/2000, then this functionality will work great for you. If calling Local/2000 may end up dialing SIP/2000 or potentially SIP/3000 based 
on some dialplan logic, then this new functionality will not help you since you cannot use custom device states in the dialplan.
I used the scenario of issue 12970 as a basis for creating a test.

For the test, I created an Agent channel, Agent/1000, and had this line in the
dialplan:

exten => 1006,1,AgentCallbackLogin(1000,,1000@internal)

In the context "internal," extension 1000 is as follows:

exten => 1000,1,Dial(SIP/1000)

If it is not clear, All calls to Agent/1000 will eventually go to SIP/1000. I added
a line to my queues.conf file for my queue:

member => Agent/1000,,,SIP/1000

When I place an outbound call from SIP/1000, issuing the "queue show" command shows that
Agent/1000 is "in use." Attempting to place a call to the queue will not cause SIP/1000 to
ring since I have ringinuse=no for my queue. When SIP/1000 hangs up, the status returns to 
"not in use."



As another test, I tried implementing a common problem. In my queues.conf file, I added this
to my queue:

member => Local/1000,,,SIP/1000

As you may be able to guess, Local/1000 always dials SIP/1000. I placed a call to my queue
and answered with SIP/1000. At this point, issuing a "queue show" command showed that the
member Local/1000 was "in use." Then, from SIP/1000 I transferred the call to another endpoint.
Issuing a "queue show" command then showed Local/1000 as being "not in use."

Changes between revision 2 and 3

1 2 3
1 2 3

  1. /branches/1.4/apps/app_queue.c: Loading...
/branches/1.4/apps/app_queue.c
Diff Revision 2 Diff Revision 3
[20] 919 lines
[+20] [+] static int interface_exists_global(const char *interface)
920
			if (!strcasecmp(mem->state_interface, interface)) {
920
			if (!strcasecmp(mem->state_interface, interface)) {
921
				ao2_ref(mem, -1);
921
				ao2_ref(mem, -1);
922
				ret = 1;
922
				ret = 1;
923
				break;
923
				break;
924
			}
924
			}

    
   
925
			ao2_ref(mem, -1);
925
		}
926
		}
926
		ast_mutex_unlock(&q->lock);
927
		ast_mutex_unlock(&q->lock);
927
		if (ret)
928
		if (ret)
928
			break;
929
			break;
929
	}
930
	}
[+20] [20] 3466 lines
[+20] [+] static int reload_queues(void)
4396
						
4397
						
4397
						AST_NONSTANDARD_APP_ARGS(args, parse, ',');
4398
						AST_NONSTANDARD_APP_ARGS(args, parse, ',');
4398

    
   
4399

   
4399
						interface = args.interface;
4400
						interface = args.interface;
4400
						if (!ast_strlen_zero(args.penalty)) {
4401
						if (!ast_strlen_zero(args.penalty)) {
4401
							tmp = args.penalty;
4402
							tmp = ast_skip_blanks(args.penalty);
4402
							while (*tmp && *tmp < 33) tmp++;

   
4403
							penalty = atoi(tmp);
4403
							penalty = atoi(tmp);
4404
							if (penalty < 0) {
4404
							if (penalty < 0) {
4405
								penalty = 0;
4405
								penalty = 0;
4406
							}
4406
							}
4407
						} else
4407
						} else
4408
							penalty = 0;
4408
							penalty = 0;
4409

    
   
4409

   
4410
						if (!ast_strlen_zero(args.membername)) {
4410
						if (!ast_strlen_zero(args.membername)) {
4411
							membername = args.membername;
4411
							membername = ast_skip_blanks(args.membername);
4412
							while (*membername && *membername < 33) membername++;

   
4413
						}
4412
						}
4414

    
   
4413

   
4415
						if (!ast_strlen_zero(args.state_interface)) {
4414
						if (!ast_strlen_zero(args.state_interface)) {
4416
							state_interface = args.state_interface;
4415
							state_interface = ast_skip_blanks(args.state_interface);
4417
							while (*state_interface && *state_interface < 33) state_interface++;

   
4418
						} else {
4416
						} else {
4419
							state_interface = interface;
4417
							state_interface = interface;
4420
						}
4418
						}
4421

    
   
4419

   
4422
						/* Find the old position in the list */
4420
						/* Find the old position in the list */
[+20] [20] 466 lines
[+20] [+] static int manager_pause_queue_member(struct mansession *s, const struct message *m)
4889
	else
4887
	else
4890
		astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
4888
		astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
4891
	return 0;
4889
	return 0;
4892
}
4890
}
4893

    
   
4891

   
4894
/* Check out BE... */

   
4895
static int handle_queue_add_member(int fd, int argc, char *argv[])
4892
static int handle_queue_add_member(int fd, int argc, char *argv[])
4896
{
4893
{
4897
	char *queuename, *interface, *membername = NULL, *state_interface = NULL;
4894
	char *queuename, *interface, *membername = NULL, *state_interface = NULL;
4898
	int penalty;
4895
	int penalty;
4899

    
   
4896

   
[+20] [20] 287 lines
  1. /branches/1.4/apps/app_queue.c: 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.