Review Board 1.7.16


Support a hint on a queue.

Review Request #1619 - Created Dec. 12, 2011 and submitted

Alec Davis
trunk
Reviewers
asterisk-dev
Asterisk
Note: the 2 debug print lines will go.

Picking up queues is possible, but knowing that a queue is ringing is useful,
particulary when you are not logged in to that queue, or not a member of it.

Non BLF users, dial 72# and then are connected with caller.
If they forget to press # or the SEND button they think the pickup hasn't worked.
Not understanding there is a 3-4 second delay before the SIP call is placed.

Example 1: Night Queue with a permanent member (specifcially just bells):

exten => 72,hint,Queue:night_queue ;queue NIGHT BELL

exten => _72,1,NoOp(Pickup Night Bell)
exten => _72,n,Pickup(4999@isdn)    ;direct call pickup to local Asterisk
exten => _72,n,NoOp(PICKUPRESULT=${PICKUPRESULT})
exten => _72,n,Hangup()

exten => **72,1,Goto(72,1)


Example 2: Queue with Dynamic Users:
Note: we use '_' in the queue names, and '-' for the context 

[trusted]
exten => 8501,hint,Queue:itg_queue        ;Provide a hint for the queue
exten => _**8501,1,Pickup(itg@trusted)    ;Pickup the queue

exten => 8501,1,Goto(itg-queue,itg,1)     ;Ring the queue

[itg-queue]
exten => itg,1,Queue(itg_queue,crhH,,,127)

In use for months on a 1.8.5 production box.

NightBell usage:

Users with BLFs configured hear the nightbells, and see the BLF flash, press the BLF and are immediately connected with caller.

Changes between revision 1 and 2

1 2
1 2

  1. trunk/apps/app_queue.c: Loading...
trunk/apps/app_queue.c
Diff Revision 1 Diff Revision 2
[20] 132 lines
[+20] [+] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
133
						<para>Continue in the dialplan if the callee hangs up.</para>
133
						<para>Continue in the dialplan if the callee hangs up.</para>
134
					</option>
134
					</option>
135
					<option name="d">
135
					<option name="d">
136
						<para>data-quality (modem) call (minimum delay).</para>
136
						<para>data-quality (modem) call (minimum delay).</para>
137
					</option>
137
					</option>

    
   
138
					<option name="F" argsep="^">

    
   
139
						<argument name="context" required="false" />

    
   
140
						<argument name="exten" required="false" />

    
   
141
						<argument name="priority" required="true" />

    
   
142
						<para>When the caller hangs up, transfer the <emphasis>called member</emphasis>

    
   
143
						to the specified destination and <emphasis>start</emphasis> execution at that location.</para>

    
   
144
						<note>

    
   
145
							<para>Any channel variables you want the called channel to inherit from the caller channel must be

    
   
146
							prefixed with one or two underbars ('_').</para>

    
   
147
						</note>

    
   
148
					</option>

    
   
149
					<option name="F">

    
   
150
						<para>When the caller hangs up, transfer the <emphasis>called member</emphasis> to the next priority of

    
   
151
						the current extension and <emphasis>start</emphasis> execution at that location.</para>

    
   
152
						<note>

    
   
153
							<para>Any channel variables you want the called channel to inherit from the caller channel must be

    
   
154
							prefixed with one or two underbars ('_').</para>

    
   
155
						</note>

    
   
156
						<note>

    
   
157
							<para>Using this option from a Macro() or GoSub() might not make sense as there would be no return points.</para>

    
   
158
						</note>

    
   
159
					</option>
138
					<option name="h">
160
					<option name="h">
139
						<para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
161
						<para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
140
					</option>
162
					</option>
141
					<option name="H">
163
					<option name="H">
142
						<para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
164
						<para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
[+20] [20] 159 lines
[+20] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
302
			Dynamically removes queue members.
324
			Dynamically removes queue members.
303
		</synopsis>
325
		</synopsis>
304
		<syntax>
326
		<syntax>
305
			<parameter name="queuename" required="true" />
327
			<parameter name="queuename" required="true" />
306
			<parameter name="interface" />
328
			<parameter name="interface" />
307
			<parameter name="options" />

   
308
		</syntax>
329
		</syntax>
309
		<description>
330
		<description>
310
			<para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
331
			<para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
311
			<para>This application sets the following channel variable upon completion:</para>
332
			<para>This application sets the following channel variable upon completion:</para>
312
			<variablelist>
333
			<variablelist>
313
				<variable name="RQMSTATUS">
334
				<variable name="RQMSTATUS">
314
					<value name="REMOVED" />
335
					<value name="REMOVED" />
315
					<value name="NOTINQUEUE" />
336
					<value name="NOTINQUEUE" />
316
					<value name="NOSUCHQUEUE" />
337
					<value name="NOSUCHQUEUE" />

    
   
338
					<value name="NOTDYNAMIC" />
317
				</variable>
339
				</variable>
318
			</variablelist>
340
			</variablelist>
319
			<para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
341
			<para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
320
		</description>
342
		</description>
321
		<see-also>
343
		<see-also>
[+20] [20] 206 lines
[+20] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
528
						<para>Gets or sets queue member penalty.</para>
550
						<para>Gets or sets queue member penalty.</para>
529
					</enum>
551
					</enum>
530
					<enum name="paused">
552
					<enum name="paused">
531
						<para>Gets or sets queue member paused status.</para>
553
						<para>Gets or sets queue member paused status.</para>
532
					</enum>
554
					</enum>
533
					<enum name="ignorebusy">
555
					<enum name="ringinuse">
534
						<para>Gets or sets queue member ignorebusy.</para>
556
						<para>Gets or sets queue member ringinuse.</para>
535
					</enum>
557
					</enum>
536
				</enumlist>
558
				</enumlist>
537
			</parameter>
559
			</parameter>
538
			<parameter name="interface" required="false" />
560
			<parameter name="interface" required="false" />
539
		</syntax>
561
		</syntax>
[+20] [20] 253 lines
[+20] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
793
			<parameter name="Queue" />
815
			<parameter name="Queue" />
794
		</syntax>
816
		</syntax>
795
		<description>
817
		<description>
796
		</description>
818
		</description>
797
	</manager>
819
	</manager>

    
   
820

   

    
   
821
	<manager name="QueueMemberRingInUse" language="en_US">

    
   
822
		<synopsis>

    
   
823
			Set the ringinuse value for a queue member.

    
   
824
		</synopsis>

    
   
825
		<syntax>

    
   
826
			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />

    
   
827
			<parameter name="Interface" required="true" />

    
   
828
			<parameter name="RingInUse" required="true" />

    
   
829
			<parameter name="Queue" />

    
   
830
		</syntax>

    
   
831
		<description>

    
   
832
		</description>

    
   
833
	</manager>

    
   
834

   
798
	<manager name="QueueRule" language="en_US">
835
	<manager name="QueueRule" language="en_US">
799
		<synopsis>
836
		<synopsis>
800
			Queue Rules.
837
			Queue Rules.
801
		</synopsis>
838
		</synopsis>
802
		<syntax>
839
		<syntax>
[+20] [20] 44 lines
[+20] ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
847
		</description>
884
		</description>
848
	</manager>
885
	</manager>
849
 ***/
886
 ***/
850

    
   
887

   
851
enum {
888
enum {

    
   
889
	OPT_MARK_AS_ANSWERED =       (1 << 0),

    
   
890
	OPT_GO_ON =                  (1 << 1),

    
   
891
	OPT_DATA_QUALITY =           (1 << 2),

    
   
892
	OPT_CALLEE_GO_ON =           (1 << 3),

    
   
893
	OPT_CALLEE_HANGUP =          (1 << 4),

    
   
894
	OPT_CALLER_HANGUP =          (1 << 5),

    
   
895
	OPT_IGNORE_CALL_FW =         (1 << 6),

    
   
896
	OPT_IGNORE_CONNECTEDLINE =   (1 << 7),

    
   
897
	OPT_CALLEE_PARK =            (1 << 8),

    
   
898
	OPT_CALLER_PARK =            (1 << 9),

    
   
899
	OPT_NO_RETRY =               (1 << 10),

    
   
900
	OPT_RINGING =                (1 << 11),

    
   
901
	OPT_RING_WHEN_RINGING =      (1 << 12),

    
   
902
	OPT_CALLEE_TRANSFER =        (1 << 13),

    
   
903
	OPT_CALLER_TRANSFER =        (1 << 14),

    
   
904
	OPT_CALLEE_AUTOMIXMON =      (1 << 15),

    
   
905
	OPT_CALLER_AUTOMIXMON =      (1 << 16),

    
   
906
	OPT_CALLEE_AUTOMON =         (1 << 17),

    
   
907
	OPT_CALLER_AUTOMON =         (1 << 18),

    
   
908
};

    
   
909

   

    
   
910
enum {

    
   
911
	OPT_ARG_CALLEE_GO_ON = 0,

    
   
912
	/* note: this entry _MUST_ be the last one in the enum */

    
   
913
	OPT_ARG_ARRAY_SIZE

    
   
914
};

    
   
915

   

    
   
916
AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS

    
   
917
	AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),

    
   
918
	AST_APP_OPTION('c', OPT_GO_ON),

    
   
919
	AST_APP_OPTION('d', OPT_DATA_QUALITY),

    
   
920
	AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),

    
   
921
	AST_APP_OPTION('h', OPT_CALLEE_HANGUP),

    
   
922
	AST_APP_OPTION('H', OPT_CALLER_HANGUP),

    
   
923
	AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),

    
   
924
	AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),

    
   
925
	AST_APP_OPTION('k', OPT_CALLEE_PARK),

    
   
926
	AST_APP_OPTION('K', OPT_CALLER_PARK),

    
   
927
	AST_APP_OPTION('n', OPT_NO_RETRY),

    
   
928
	AST_APP_OPTION('r', OPT_RINGING),

    
   
929
	AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),

    
   
930
	AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),

    
   
931
	AST_APP_OPTION('T', OPT_CALLER_TRANSFER),

    
   
932
	AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),

    
   
933
	AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),

    
   
934
	AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),

    
   
935
	AST_APP_OPTION('W', OPT_CALLER_AUTOMON),

    
   
936
END_OPTIONS);

    
   
937

   

    
   
938
enum {
852
	QUEUE_STRATEGY_RINGALL = 0,
939
	QUEUE_STRATEGY_RINGALL = 0,
853
	QUEUE_STRATEGY_LEASTRECENT,
940
	QUEUE_STRATEGY_LEASTRECENT,
854
	QUEUE_STRATEGY_FEWESTCALLS,
941
	QUEUE_STRATEGY_FEWESTCALLS,
855
	QUEUE_STRATEGY_RANDOM,
942
	QUEUE_STRATEGY_RANDOM,
856
	QUEUE_STRATEGY_RRMEMORY,
943
	QUEUE_STRATEGY_RRMEMORY,
[+20] [20] 101 lines
[+20] [+] static int negative_penalty_invalid = 0;
958
static int log_membername_as_agent = 0;
1045
static int log_membername_as_agent = 0;
959

    
   
1046

   
960
/*! \brief queues.conf [general] option */
1047
/*! \brief queues.conf [general] option */
961
static int check_state_unknown = 0;
1048
static int check_state_unknown = 0;
962

    
   
1049

   

    
   
1050
/*! \brief name of the ringinuse field in the realtime database */

    
   
1051
static char *realtime_ringinuse_field;

    
   
1052

   
963
enum queue_result {
1053
enum queue_result {
964
	QUEUE_UNKNOWN = 0,
1054
	QUEUE_UNKNOWN = 0,
965
	QUEUE_TIMEOUT = 1,
1055
	QUEUE_TIMEOUT = 1,
966
	QUEUE_JOINEMPTY = 2,
1056
	QUEUE_JOINEMPTY = 2,
967
	QUEUE_LEAVEEMPTY = 3,
1057
	QUEUE_LEAVEEMPTY = 3,
[+20] [20] 36 lines
[+20] [+] enum queue_timeout_priority {
1004

    
   
1094

   
1005
struct callattempt {
1095
struct callattempt {
1006
	struct callattempt *q_next;
1096
	struct callattempt *q_next;
1007
	struct callattempt *call_next;
1097
	struct callattempt *call_next;
1008
	struct ast_channel *chan;
1098
	struct ast_channel *chan;
1009
	char interface[256];
1099
	char interface[256];			/*!< An Asterisk dial string (not a channel name) */
1010
	int stillgoing;

   
1011
	int metric;
1100
	int metric;
1012
	time_t lastcall;
1101
	time_t lastcall;
1013
	struct call_queue *lastqueue;
1102
	struct call_queue *lastqueue;
1014
	struct member *member;
1103
	struct member *member;
1015
	/*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
1104
	/*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
1016
	struct ast_party_connected_line connected;
1105
	struct ast_party_connected_line connected;
1017
	/*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
1106
	/*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
1018
	unsigned int pending_connected_update:1;
1107
	unsigned int pending_connected_update:1;

    
   
1108
	/*! TRUE if the connected line update is blocked. */

    
   
1109
	unsigned int block_connected_update:1;
1019
	/*! TRUE if caller id is not available for connected line */
1110
	/*! TRUE if caller id is not available for connected line */
1020
	unsigned int dial_callerid_absent:1;
1111
	unsigned int dial_callerid_absent:1;

    
   
1112
	/*! TRUE if the call is still active */

    
   
1113
	unsigned int stillgoing:1;
1021
	struct ast_aoc_decoded *aoc_s_rate_list;
1114
	struct ast_aoc_decoded *aoc_s_rate_list;
1022
};
1115
};
1023

    
   
1116

   
1024

    
   
1117

   
1025
struct queue_ent {
1118
struct queue_ent {
1026
	struct call_queue *parent;             /*!< What queue is our parent */
1119
	struct call_queue *parent;             /*!< What queue is our parent */
1027
	char moh[80];                          /*!< Name of musiconhold to be used */
1120
	char moh[MAX_MUSICCLASS];              /*!< Name of musiconhold to be used */
1028
	char announce[PATH_MAX];               /*!< Announcement to play for member when call is answered */
1121
	char announce[PATH_MAX];               /*!< Announcement to play for member when call is answered */
1029
	char context[AST_MAX_CONTEXT];         /*!< Context when user exits queue */
1122
	char context[AST_MAX_CONTEXT];         /*!< Context when user exits queue */
1030
	char digits[AST_MAX_EXTENSION];        /*!< Digits entered while in queue */
1123
	char digits[AST_MAX_EXTENSION];        /*!< Digits entered while in queue */
1031
	int valid_digits;                      /*!< Digits entered correspond to valid extension. Exited */
1124
	int valid_digits;                      /*!< Digits entered correspond to valid extension. Exited */
1032
	int pos;                               /*!< Where we are in the queue */
1125
	int pos;                               /*!< Where we are in the queue */
[+20] [20] 18 lines
[+20] struct queue_ent {
1051
	struct penalty_rule *pr;               /*!< Pointer to the next penalty rule to implement */
1144
	struct penalty_rule *pr;               /*!< Pointer to the next penalty rule to implement */
1052
	struct queue_ent *next;                /*!< The next queue entry */
1145
	struct queue_ent *next;                /*!< The next queue entry */
1053
};
1146
};
1054

    
   
1147

   
1055
struct member {
1148
struct member {
1056
	char interface[80];                  /*!< Technology/Location to dial to reach this member*/
1149
	char interface[AST_CHANNEL_NAME];    /*!< Technology/Location to dial to reach this member*/
1057
	char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
1150
	char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
1058
	char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
1151
	char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
1059
	char state_interface[80];            /*!< Technology/Location from which to read devicestate changes */
1152
	char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
1060
	char membername[80];                 /*!< Member name to use in queue logs */
1153
	char membername[80];                 /*!< Member name to use in queue logs */
1061
	int penalty;                         /*!< Are we a last resort? */
1154
	int penalty;                         /*!< Are we a last resort? */
1062
	int calls;                           /*!< Number of calls serviced by this member */
1155
	int calls;                           /*!< Number of calls serviced by this member */
1063
	int dynamic;                         /*!< Are we dynamically added? */
1156
	int dynamic;                         /*!< Are we dynamically added? */
1064
	int realtime;                        /*!< Is this member realtime? */
1157
	int realtime;                        /*!< Is this member realtime? */
1065
	int status;                          /*!< Status of queue member */
1158
	int status;                          /*!< Status of queue member */
1066
	int paused;                          /*!< Are we paused (not accepting calls)? */
1159
	int paused;                          /*!< Are we paused (not accepting calls)? */
1067
	time_t lastcall;                     /*!< When last successful call was hungup */
1160
	time_t lastcall;                     /*!< When last successful call was hungup */
1068
	struct call_queue *lastqueue;	     /*!< Last queue we received a call */
1161
	struct call_queue *lastqueue;	     /*!< Last queue we received a call */
1069
	unsigned int dead:1;                 /*!< Used to detect members deleted in realtime */
1162
	unsigned int dead:1;                 /*!< Used to detect members deleted in realtime */
1070
	unsigned int delme:1;                /*!< Flag to delete entry on reload */
1163
	unsigned int delme:1;                /*!< Flag to delete entry on reload */
1071
	char rt_uniqueid[80];                /*!< Unique id of realtime member entry */
1164
	char rt_uniqueid[80];                /*!< Unique id of realtime member entry */
1072
	unsigned int ignorebusy:1;           /*!< Flag to ignore member if the status is not available */
1165
	unsigned int ringinuse:1;            /*!< Flag to ring queue members even if their status is 'inuse' */
1073
};
1166
};
1074

    
   
1167

   
1075
enum empty_conditions {
1168
enum empty_conditions {
1076
	QUEUE_EMPTY_PENALTY = (1 << 0),
1169
	QUEUE_EMPTY_PENALTY = (1 << 0),
1077
	QUEUE_EMPTY_PAUSED = (1 << 1),
1170
	QUEUE_EMPTY_PAUSED = (1 << 1),
1078
	QUEUE_EMPTY_INUSE = (1 << 2),
1171
	QUEUE_EMPTY_INUSE = (1 << 2),
1079
	QUEUE_EMPTY_RINGING = (1 << 3),
1172
	QUEUE_EMPTY_RINGING = (1 << 3),
1080
	QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
1173
	QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
1081
	QUEUE_EMPTY_INVALID = (1 << 5),
1174
	QUEUE_EMPTY_INVALID = (1 << 5),
1082
	QUEUE_EMPTY_UNKNOWN = (1 << 6),
1175
	QUEUE_EMPTY_UNKNOWN = (1 << 6),
1083
	QUEUE_EMPTY_WRAPUP = (1 << 7),
1176
	QUEUE_EMPTY_WRAPUP = (1 << 7),
1084
};
1177
};
1085

    
   
1178

   

    
   
1179
enum member_properties {

    
   
1180
	MEMBER_PENALTY = 0,

    
   
1181
	MEMBER_RINGINUSE = 1,

    
   
1182
};

    
   
1183

   
1086
/* values used in multi-bit flags in call_queue */
1184
/* values used in multi-bit flags in call_queue */
1087
#define ANNOUNCEHOLDTIME_ALWAYS 1
1185
#define ANNOUNCEHOLDTIME_ALWAYS 1
1088
#define ANNOUNCEHOLDTIME_ONCE 2
1186
#define ANNOUNCEHOLDTIME_ONCE 2
1089
#define QUEUE_EVENT_VARIABLES 3
1187
#define QUEUE_EVENT_VARIABLES 3
1090

    
   
1188

   
[+20] [20] 145 lines
[+20] [+] static void set_queue_result(struct ast_channel *chan, enum queue_result res)
1236
static const char *int2strat(int strategy)
1334
static const char *int2strat(int strategy)
1237
{
1335
{
1238
	int x;
1336
	int x;
1239

    
   
1337

   
1240
	for (x = 0; x < ARRAY_LEN(strategies); x++) {
1338
	for (x = 0; x < ARRAY_LEN(strategies); x++) {
1241
		if (strategy == strategies[x].strategy)
1339
		if (strategy == strategies[x].strategy) {
1242
			return strategies[x].name;
1340
			return strategies[x].name;
1243
	}
1341
		}

    
   
1342
	}
1244

    
   
1343

   
1245
	return "<unknown>";
1344
	return "<unknown>";
1246
}
1345
}
1247

    
   
1346

   
1248
static int strat2int(const char *strategy)
1347
static int strat2int(const char *strategy)
1249
{
1348
{
1250
	int x;
1349
	int x;
1251

    
   
1350

   
1252
	for (x = 0; x < ARRAY_LEN(strategies); x++) {
1351
	for (x = 0; x < ARRAY_LEN(strategies); x++) {
1253
		if (!strcasecmp(strategy, strategies[x].name))
1352
		if (!strcasecmp(strategy, strategies[x].name)) {
1254
			return strategies[x].strategy;
1353
			return strategies[x].strategy;
1255
	}
1354
		}

    
   
1355
	}
1256

    
   
1356

   
1257
	return -1;
1357
	return -1;
1258
}
1358
}
1259

    
   
1359

   
1260
static int autopause2int(const char *autopause)
1360
static int autopause2int(const char *autopause)
1261
{
1361
{
1262
	int x;
1362
	int x;
1263
	/*This 'double check' that default value is OFF */
1363
	/*This 'double check' that default value is OFF */
1264
	if (ast_strlen_zero(autopause))
1364
	if (ast_strlen_zero(autopause)) {
1265
		return QUEUE_AUTOPAUSE_OFF;
1365
		return QUEUE_AUTOPAUSE_OFF;

    
   
1366
	}
1266

    
   
1367

   
1267
	/*This 'double check' is to ensure old values works */
1368
	/*This 'double check' is to ensure old values works */
1268
	if(ast_true(autopause))
1369
	if(ast_true(autopause)) {
1269
		return QUEUE_AUTOPAUSE_ON;
1370
		return QUEUE_AUTOPAUSE_ON;

    
   
1371
	}
1270

    
   
1372

   
1271
	for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1373
	for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1272
		if (!strcasecmp(autopause, autopausesmodes[x].name))
1374
		if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1273
			return autopausesmodes[x].autopause;
1375
			return autopausesmodes[x].autopause;
1274
	}
1376
		}

    
   
1377
	}
1275

    
   
1378

   
1276
	/*This 'double check' that default value is OFF */
1379
	/*This 'double check' that default value is OFF */
1277
	return QUEUE_AUTOPAUSE_OFF;
1380
	return QUEUE_AUTOPAUSE_OFF;
1278
}
1381
}
1279

    
   
1382

   
[+20] [20] 9 lines
[+20] [+] static int queue_cmp_cb(void *obj, void *arg, int flags)
1289
	struct call_queue *q = obj, *q2 = arg;
1392
	struct call_queue *q = obj, *q2 = arg;
1290
	return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1393
	return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
1291
}
1394
}
1292

    
   
1395

   
1293
#ifdef REF_DEBUG_ONLY_QUEUES
1396
#ifdef REF_DEBUG_ONLY_QUEUES
1294
#define queue_ref(a)	__ao2_ref_debug(a,1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__)
1397
#define queue_ref(q)				_queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
1295
#define queue_unref(a)	__ao2_ref_debug(a,-1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__)
1398
#define queue_unref(q)				_queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
1296
#define queue_t_ref(a,b)	__ao2_ref_debug(a,1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1399
#define queue_t_ref(q, tag)			_queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1297
#define queue_t_unref(a,b)	__ao2_ref_debug(a,-1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1400
#define queue_t_unref(q, tag)		_queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1298
#define queues_t_link(c,q,tag)	__ao2_link_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1401
#define queues_t_link(c, q, tag)	__ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1299
#define queues_t_unlink(c,q,tag)	__ao2_unlink_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1402
#define queues_t_unlink(c, q, tag)	__ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)

    
   
1403

   

    
   
1404
static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)

    
   
1405
{

    
   
1406
	__ao2_ref_debug(q, 1, tag, file, line, filename);

    
   
1407
	return q;

    
   
1408
}

    
   
1409

   

    
   
1410
static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)

    
   
1411
{

    
   
1412
	__ao2_ref_debug(q, -1, tag, file, line, filename);

    
   
1413
	return NULL;

    
   
1414
}

    
   
1415

   
1300
#else
1416
#else
1301
#define queue_t_ref(a,b)	queue_ref(a)
1417

   
1302
#define queue_t_unref(a,b)	queue_unref(a)
1418
#define queue_t_ref(q, tag)			queue_ref(q)
1303
#define queues_t_link(c,q,tag)	ao2_t_link(c,q,tag)
1419
#define queue_t_unref(q, tag)		queue_unref(q)
1304
#define queues_t_unlink(c,q,tag)	ao2_t_unlink(c,q,tag)
1420
#define queues_t_link(c, q, tag)	ao2_t_link(c, q, tag)

    
   
1421
#define queues_t_unlink(c, q, tag)	ao2_t_unlink(c, q, tag)

    
   
1422

   
1305
static inline struct call_queue *queue_ref(struct call_queue *q)
1423
static inline struct call_queue *queue_ref(struct call_queue *q)
1306
{
1424
{
1307
	ao2_ref(q, 1);
1425
	ao2_ref(q, 1);
1308
	return q;
1426
	return q;
1309
}
1427
}
[+20] [20] 13 lines
[+20] [+] static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
1323

    
   
1441

   
1324
	ao2_lock(q);
1442
	ao2_lock(q);
1325

    
   
1443

   
1326
	if (q->setqueuevar) {
1444
	if (q->setqueuevar) {
1327
		sl = 0;
1445
		sl = 0;
1328
		if (q->callscompleted > 0) 
1446
		if (q->callscompleted > 0) {
1329
			sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
1447
			sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);

    
   
1448
		}
1330

    
   
1449

   
1331
		snprintf(interfacevar, sizeof(interfacevar),
1450
		snprintf(interfacevar, sizeof(interfacevar),
1332
			"QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
1451
			"QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
1333
			q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned,  q->servicelevel, sl);
1452
			q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned,  q->servicelevel, sl);
1334

    
   
1453

   
[+20] [20] 89 lines
[+20] [+] static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions)
1424
				break;
1543
				break;
1425
			} else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
1544
			} else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
1426
				ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
1545
				ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
1427
				break;
1546
				break;
1428
			} else {
1547
			} else {
1429
				ao2_unlock(q);

   
1430
				ao2_ref(member, -1);
1548
				ao2_ref(member, -1);
1431
				ao2_iterator_destroy(&mem_iter);
1549
				ao2_iterator_destroy(&mem_iter);

    
   
1550
				ao2_unlock(q);
1432
				ast_debug(4, "%s is available.\n", member->membername);
1551
				ast_debug(4, "%s is available.\n", member->membername);
1433
				return 0;
1552
				return 0;
1434
			}
1553
			}
1435
			break;
1554
			break;
1436
		}
1555
		}
[+20] [20] 17 lines
[+20] [+] struct statechange {
1454
*/
1573
*/
1455
static int update_status(struct call_queue *q, struct member *m, const int status)
1574
static int update_status(struct call_queue *q, struct member *m, const int status)
1456
{
1575
{
1457
	m->status = status;
1576
	m->status = status;
1458

    
   
1577

   
1459
	if (q->maskmemberstatus)
1578
	if (q->maskmemberstatus) {
1460
		return 0;
1579
		return 0;

    
   
1580
	}
1461

    
   
1581

   

    
   
1582
	/*** DOCUMENTATION

    
   
1583
	<managerEventInstance>

    
   
1584
		<synopsis>Raised when a Queue member's status has changed.</synopsis>

    
   
1585
		<syntax>

    
   
1586
			<parameter name="Queue">

    
   
1587
				<para>The name of the queue.</para>

    
   
1588
			</parameter>

    
   
1589
			<parameter name="Location">

    
   
1590
				<para>The queue member's channel technology or location.</para>

    
   
1591
			</parameter>

    
   
1592
			<parameter name="MemberName">

    
   
1593
				<para>The name of the queue member.</para>

    
   
1594
			</parameter>

    
   
1595
			<parameter name="StateInterface">

    
   
1596
				<para>Channel technology or location from which to read device state changes.</para>

    
   
1597
			</parameter>

    
   
1598
			<parameter name="Membership">

    
   
1599
				<enumlist>

    
   
1600
					<enum name="dynamic"/>

    
   
1601
					<enum name="realtime"/>

    
   
1602
					<enum name="static"/>

    
   
1603
				</enumlist>

    
   
1604
			</parameter>

    
   
1605
			<parameter name="Penalty">

    
   
1606
				<para>The penalty associated with the queue member.</para>

    
   
1607
			</parameter>

    
   
1608
			<parameter name="CallsTaken">

    
   
1609
				<para>The number of calls this queue member has serviced.</para>

    
   
1610
			</parameter>

    
   
1611
			<parameter name="LastCall">

    
   
1612
				<para>The time this member last took call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>

    
   
1613
			</parameter>

    
   
1614
			<parameter name="Status">

    
   
1615
				<para>The numeric device state status of the queue member.</para>

    
   
1616
				<enumlist>

    
   
1617
					<enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>

    
   
1618
					<enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>

    
   
1619
					<enum name="2"><para>AST_DEVICE_INUSE</para></enum>

    
   
1620
					<enum name="3"><para>AST_DEVICE_BUSY</para></enum>

    
   
1621
					<enum name="4"><para>AST_DEVICE_INVALID</para></enum>

    
   
1622
					<enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>

    
   
1623
					<enum name="6"><para>AST_DEVICE_RINGING</para></enum>

    
   
1624
					<enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>

    
   
1625
					<enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>

    
   
1626
				</enumlist>

    
   
1627
			</parameter>

    
   
1628
			<parameter name="Paused">

    
   
1629
				<enumlist>

    
   
1630
					<enum name="0"/>

    
   
1631
					<enum name="1"/>

    
   
1632
				</enumlist>

    
   
1633
			</parameter>

    
   
1634
		</syntax>

    
   
1635
	</managerEventInstance>

    
   
1636
	***/
1462
	manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1637
	manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
1463
		"Queue: %s\r\n"
1638
		"Queue: %s\r\n"
1464
		"Location: %s\r\n"
1639
		"Location: %s\r\n"
1465
		"MemberName: %s\r\n"
1640
		"MemberName: %s\r\n"
1466
		"StateInterface: %s\r\n"
1641
		"StateInterface: %s\r\n"
[+20] [20] 26 lines
[+20] [+] static int handle_statechange(void *datap)
1493

    
   
1668

   
1494
		miter = ao2_iterator_init(q->members, 0);
1669
		miter = ao2_iterator_init(q->members, 0);
1495
		for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
1670
		for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
1496
			ast_copy_string(interface, m->state_interface, sizeof(interface));
1671
			ast_copy_string(interface, m->state_interface, sizeof(interface));
1497

    
   
1672

   
1498
			if ((slash_pos = strchr(interface, '/')))
1673
			if ((slash_pos = strchr(interface, '/'))) {
1499
				if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/')))
1674
				if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
1500
					*slash_pos = '\0';
1675
					*slash_pos = '\0';

    
   
1676
				}

    
   
1677
			}
1501

    
   
1678

   
1502
			if (!strcasecmp(interface, sc->dev)) {
1679
			if (!strcasecmp(interface, sc->dev)) {
1503
				found = 1;
1680
				found = 1;
1504
				update_status(q, m, sc->state);
1681
				update_status(q, m, sc->state);
1505
				ao2_ref(m, -1);
1682
				ao2_ref(m, -1);
[+20] [20] 5 lines
[+20] static int handle_statechange(void *datap)
1511
		ao2_unlock(q);
1688
		ao2_unlock(q);
1512
		queue_t_unref(q, "Done with iterator");
1689
		queue_t_unref(q, "Done with iterator");
1513
	}
1690
	}
1514
	ao2_iterator_destroy(&qiter);
1691
	ao2_iterator_destroy(&qiter);
1515

    
   
1692

   
1516
	if (found)
1693
	if (found) {
1517
		ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", sc->dev, sc->state, ast_devstate2str(sc->state));
1694
		ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", sc->dev, sc->state, ast_devstate2str(sc->state));
1518
	else
1695
	} else {
1519
		ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", sc->dev, sc->state, ast_devstate2str(sc->state));
1696
		ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", sc->dev, sc->state, ast_devstate2str(sc->state));

    
   
1697
	}
1520

    
   
1698

   
1521
	ast_free(sc);
1699
	ast_free(sc);
1522
	return 0;
1700
	return 0;
1523
}
1701
}
1524

    
   
1702

   
[+20] [20] 53 lines
[+20] [+] static int extensionstate2devicestate(int state)
1578
	}
1756
	}
1579

    
   
1757

   
1580
	return state;
1758
	return state;
1581
}
1759
}
1582

    
   
1760

   
1583
static int extension_state_cb(const char *context, const char *exten, enum ast_extension_states state, void *data)
1761
static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
1584
{
1762
{
1585
	struct ao2_iterator miter, qiter;
1763
	struct ao2_iterator miter, qiter;
1586
	struct member *m;
1764
	struct member *m;
1587
	struct call_queue *q;
1765
	struct call_queue *q;

    
   
1766
	int state = info->exten_state;
1588
	int found = 0, device_state = extensionstate2devicestate(state);
1767
	int found = 0, device_state = extensionstate2devicestate(state);
1589

    
   
1768

   

    
   
1769
	/* only interested in extension state updates involving device states */

    
   
1770
	if (info->reason != AST_HINT_UPDATE_DEVICE) {
Moved from 1874

    
   
1771
		return 0;
Moved from 1875

    
   
1772
	}

    
   
1773

   
1590
	qiter = ao2_iterator_init(queues, 0);
1774
	qiter = ao2_iterator_init(queues, 0);
1591
	while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
1775
	while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
1592
		ao2_lock(q);
1776
		ao2_lock(q);
1593

    
   
1777

   
1594
		miter = ao2_iterator_init(q->members, 0);
1778
		miter = ao2_iterator_init(q->members, 0);
[+20] [20] 27 lines
[+20] static int extension_state_cb(const char *context, const char *exten, enum ast_extension_states state, void *data) [+] static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
1622
{
1806
{
1623
	return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
1807
	return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
1624
}
1808
}
1625

    
   
1809

   
1626
/*! \brief allocate space for new queue member and set fields based on parameters passed */
1810
/*! \brief allocate space for new queue member and set fields based on parameters passed */
1627
static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
1811
static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
1628
{
1812
{
1629
	struct member *cur;
1813
	struct member *cur;
1630

    
   
1814

   
1631
	if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
1815
	if ((cur = ao2_alloc(sizeof(*cur), NULL))) {

    
   
1816
		cur->ringinuse = ringinuse;
1632
		cur->penalty = penalty;
1817
		cur->penalty = penalty;
1633
		cur->paused = paused;
1818
		cur->paused = paused;
1634
		ast_copy_string(cur->interface, interface, sizeof(cur->interface));
1819
		ast_copy_string(cur->interface, interface, sizeof(cur->interface));
1635
		if (!ast_strlen_zero(state_interface)) {
1820
		if (!ast_strlen_zero(state_interface)) {
1636
			ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
1821
			ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
[+20] [20] 22 lines
[+20] static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface) [+] static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
1659
}
1844
}
1660

    
   
1845

   
1661

    
   
1846

   
1662
static int compress_char(const char c)
1847
static int compress_char(const char c)
1663
{
1848
{
1664
	if (c < 32)
1849
	if (c < 32) {
1665
		return 0;
1850
		return 0;
1666
	else if (c > 96)
1851
	} else if (c > 96) {
1667
		return c - 64;
1852
		return c - 64;
1668
	else
1853
	} 
1669
		return c - 32;
1854
	return c - 32;
1670
}
1855
}
1671

    
   
1856

   
1672
static int member_hash_fn(const void *obj, const int flags)
1857
static int member_hash_fn(const void *obj, const int flags)
1673
{
1858
{
[+20] [20] 62 lines
[+20] [+] static void init_queue(struct call_queue *q)
1736
	q->numperiodicannounce = 0;
1921
	q->numperiodicannounce = 0;
1737
	q->autopause = QUEUE_AUTOPAUSE_OFF;
1922
	q->autopause = QUEUE_AUTOPAUSE_OFF;
1738
	q->timeoutpriority = TIMEOUT_PRIORITY_APP;
1923
	q->timeoutpriority = TIMEOUT_PRIORITY_APP;
1739
	q->autopausedelay = 0;
1924
	q->autopausedelay = 0;
1740
	if (!q->members) {
1925
	if (!q->members) {
1741
		if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED)
1926
		if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
1742
			/* linear strategy depends on order, so we have to place all members in a single bucket */
1927
			/* linear strategy depends on order, so we have to place all members in a single bucket */
1743
			q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
1928
			q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
1744
		else
1929
		} else {
1745
			q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
1930
			q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
1746
	}
1931
		}

    
   
1932
	}
1747
	q->found = 1;
1933
	q->found = 1;
1748

    
   
1934

   
1749
	ast_string_field_set(q, sound_next, "queue-youarenext");
1935
	ast_string_field_set(q, sound_next, "queue-youarenext");
1750
	ast_string_field_set(q, sound_thereare, "queue-thereare");
1936
	ast_string_field_set(q, sound_thereare, "queue-thereare");
1751
	ast_string_field_set(q, sound_calls, "queue-callswaiting");
1937
	ast_string_field_set(q, sound_calls, "queue-callswaiting");
[+20] [20] 13 lines
[+20] static void init_queue(struct call_queue *q)
1765
	if (q->sound_periodicannounce[0]) {
1951
	if (q->sound_periodicannounce[0]) {
1766
		ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
1952
		ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
1767
	}
1953
	}
1768

    
   
1954

   
1769
	for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1955
	for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
1770
		if (q->sound_periodicannounce[i])
1956
		if (q->sound_periodicannounce[i]) {
1771
			ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
1957
			ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
1772
	}
1958
		}

    
   
1959
	}
1773

    
   
1960

   
1774
	while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list)))
1961
	while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
1775
		ast_free(pr_iter);
1962
		ast_free(pr_iter);
1776
}
1963
	}

    
   
1964
}
1777

    
   
1965

   
1778
static void clear_queue(struct call_queue *q)
1966
static void clear_queue(struct call_queue *q)
1779
{
1967
{
1780
	q->holdtime = 0;
1968
	q->holdtime = 0;
1781
	q->callscompleted = 0;
1969
	q->callscompleted = 0;
[+20] [20] 50 lines
[+20] [+] static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
1832
		return -1;
2020
		return -1;
1833
	}
2021
	}
1834

    
   
2022

   
1835
	rule->time = penaltychangetime;
2023
	rule->time = penaltychangetime;
1836

    
   
2024

   
1837
	if ((minstr = strchr(maxstr,',')))
2025
	if ((minstr = strchr(maxstr,','))) {
1838
		*minstr++ = '\0';
2026
		*minstr++ = '\0';

    
   
2027
	}
1839
	
2028
	
1840
	/* The last check will evaluate true if either no penalty change is indicated for a given rule
2029
	/* The last check will evaluate true if either no penalty change is indicated for a given rule
1841
	 * OR if a min penalty change is indicated but no max penalty change is */
2030
	 * OR if a min penalty change is indicated but no max penalty change is */
1842
	if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
2031
	if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
1843
		rule->max_relative = 1;
2032
		rule->max_relative = 1;
1844
	}
2033
	}
1845

    
   
2034

   
1846
	rule->max_value = atoi(maxstr);
2035
	rule->max_value = atoi(maxstr);
1847

    
   
2036

   
1848
	if (!ast_strlen_zero(minstr)) {
2037
	if (!ast_strlen_zero(minstr)) {
1849
		if (*minstr == '+' || *minstr == '-')
2038
		if (*minstr == '+' || *minstr == '-') {
1850
			rule->min_relative = 1;
2039
			rule->min_relative = 1;

    
   
2040
		}
1851
		rule->min_value = atoi(minstr);
2041
		rule->min_value = atoi(minstr);
1852
	} else /*there was no minimum specified, so assume this means no change*/
2042
	} else { /*there was no minimum specified, so assume this means no change*/
1853
		rule->min_relative = 1;
2043
		rule->min_relative = 1;

    
   
2044
	}
1854

    
   
2045

   
1855
	/*We have the rule made, now we need to insert it where it belongs*/
2046
	/*We have the rule made, now we need to insert it where it belongs*/
1856
	AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
2047
	AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
1857
		if (strcasecmp(rl_iter->name, list_name))
2048
		if (strcasecmp(rl_iter->name, list_name)) {
1858
			continue;
2049
			continue;

    
   
2050
		}
1859

    
   
2051

   
1860
		AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
2052
		AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
1861
			if (rule->time < rule_iter->time) {
2053
			if (rule->time < rule_iter->time) {
1862
				AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
2054
				AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
1863
				inserted = 1;
2055
				inserted = 1;
1864
				break;
2056
				break;
1865
			}
2057
			}
1866
		}
2058
		}
1867
		AST_LIST_TRAVERSE_SAFE_END;
2059
		AST_LIST_TRAVERSE_SAFE_END;
1868
	
2060
	
1869
		if (!inserted) {
2061
		if (!inserted) {
1870
			AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
2062
			AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);

    
   
2063
			inserted = 1;
1871
		}
2064
		}
1872
	}

   
1873

    
   

   
1874
	return 0;

   
1875
}

   
1876

    
   
2065

   
1877
static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
2066
		break;
1878
{

   
1879
	char *value_copy = ast_strdupa(value);

   
1880
	char *option = NULL;

   
1881
	while ((option = strsep(&value_copy, ","))) {

   
1882
		if (!strcasecmp(option, "paused")) {

   
1883
			*empty |= QUEUE_EMPTY_PAUSED;

   
1884
		} else if (!strcasecmp(option, "penalty")) {

   
1885
			*empty |= QUEUE_EMPTY_PENALTY;

   
1886
		} else if (!strcasecmp(option, "inuse")) {

   
1887
			*empty |= QUEUE_EMPTY_INUSE;

   
1888
		} else if (!strcasecmp(option, "ringing")) {

   
1889
			*empty |= QUEUE_EMPTY_RINGING;

   
1890
		} else if (!strcasecmp(option, "invalid")) {

   
1891
			*empty |= QUEUE_EMPTY_INVALID;

   
1892
		} else if (!strcasecmp(option, "wrapup")) {

   
1893
			*empty |= QUEUE_EMPTY_WRAPUP;

   
1894
		} else if (!strcasecmp(option, "unavailable")) {

   
1895
			*empty |= QUEUE_EMPTY_UNAVAILABLE;

   
1896
		} else if (!strcasecmp(option, "unknown")) {

   
1897
			*empty |= QUEUE_EMPTY_UNKNOWN;

   
1898
		} else if (!strcasecmp(option, "loose")) {

   
1899
			*empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);

   
1900
		} else if (!strcasecmp(option, "strict")) {

   
1901
			*empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);

   
1902
		} else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {

   
1903
			*empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);

   
1904
		} else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {

   
1905
			*empty = 0;

   
1906
		} else {

   
1907
			ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");

   
1908
		}

   
1909
	}

   
1910
}
2067
	}
1911

    
   
2068

   
1912
/*! \brief Configure a queue parameter.
2069
	if (!inserted) {
1913
 * 
2070
		ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
1914
 * The failunknown flag is set for config files (and static realtime) to show
2071
		ast_free(rule);
1915
 * errors for unknown parameters. It is cleared for dynamic realtime to allow
2072
		return -1;
1916
 *  extra fields in the tables.
2073
	}
1917
 * \note For error reporting, line number is passed for .conf static configuration,
2074
	return 0;
1918
 * for Realtime queues, linenum is -1.
2075
}
1919
*/
2076

   
1920
static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
2077
static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
1921
{
2078
{
1922
	if (!strcasecmp(param, "musicclass") || 
2079
	char *value_copy = ast_strdupa(value);
1923
		!strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
2080
	char *option = NULL;
1924
		ast_string_field_set(q, moh, val);
2081
	while ((option = strsep(&value_copy, ","))) {
1925
	} else if (!strcasecmp(param, "announce")) {
2082
		if (!strcasecmp(option, "paused")) {
1926
		ast_string_field_set(q, announce, val);
2083
			*empty |= QUEUE_EMPTY_PAUSED;
1927
	} else if (!strcasecmp(param, "context")) {
2084
		} else if (!strcasecmp(option, "penalty")) {
1928
		ast_string_field_set(q, context, val);
2085
			*empty |= QUEUE_EMPTY_PENALTY;
1929
	} else if (!strcasecmp(param, "timeout")) {
2086
		} else if (!strcasecmp(option, "inuse")) {
1930
		q->timeout = atoi(val);
2087
			*empty |= QUEUE_EMPTY_INUSE;
1931
		if (q->timeout < 0)
2088
		} else if (!strcasecmp(option, "ringing")) {
1932
			q->timeout = DEFAULT_TIMEOUT;
2089
			*empty |= QUEUE_EMPTY_RINGING;
1933
	} else if (!strcasecmp(param, "ringinuse")) {
2090
		} else if (!strcasecmp(option, "invalid")) {
1934
		q->ringinuse = ast_true(val);
2091
			*empty |= QUEUE_EMPTY_INVALID;
1935
	} else if (!strcasecmp(param, "setinterfacevar")) {
2092
		} else if (!strcasecmp(option, "wrapup")) {
1936
		q->setinterfacevar = ast_true(val);
2093
			*empty |= QUEUE_EMPTY_WRAPUP;
1937
	} else if (!strcasecmp(param, "setqueuevar")) {
2094
		} else if (!strcasecmp(option, "unavailable")) {
1938
		q->setqueuevar = ast_true(val);
2095
			*empty |= QUEUE_EMPTY_UNAVAILABLE;
1939
	} else if (!strcasecmp(param, "setqueueentryvar")) {
2096
		} else if (!strcasecmp(option, "unknown")) {
1940
		q->setqueueentryvar = ast_true(val);
2097
			*empty |= QUEUE_EMPTY_UNKNOWN;
1941
	} else if (!strcasecmp(param, "monitor-format")) {
2098
		} else if (!strcasecmp(option, "loose")) {
1942
		ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
2099
			*empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
1943
	} else if (!strcasecmp(param, "membermacro")) {
2100
		} else if (!strcasecmp(option, "strict")) {
1944
		ast_string_field_set(q, membermacro, val);
2101
			*empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
1945
	} else if (!strcasecmp(param, "membergosub")) {
2102
		} else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
1946
		ast_string_field_set(q, membergosub, val);
2103
			*empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
1947
	} else if (!strcasecmp(param, "queue-youarenext")) {
2104
		} else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
1948
		ast_string_field_set(q, sound_next, val);
2105
			*empty = 0;
1949
	} else if (!strcasecmp(param, "queue-thereare")) {
2106
		} else {
1950
		ast_string_field_set(q, sound_thereare, val);
2107
			ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
1951
	} else if (!strcasecmp(param, "queue-callswaiting")) {
2108
		}
1952
		ast_string_field_set(q, sound_calls, val);
2109
	}
1953
	} else if (!strcasecmp(param, "queue-quantity1")) {
2110
}
1954
		ast_string_field_set(q, queue_quantity1, val);
2111

   
1955
	} else if (!strcasecmp(param, "queue-quantity2")) {
2112
/*! \brief Configure a queue parameter.
1956
		ast_string_field_set(q, queue_quantity2, val);
2113
 * 
1957
	} else if (!strcasecmp(param, "queue-holdtime")) {
2114
 * The failunknown flag is set for config files (and static realtime) to show
1958
		ast_string_field_set(q, sound_holdtime, val);
2115
 * errors for unknown parameters. It is cleared for dynamic realtime to allow
1959
	} else if (!strcasecmp(param, "queue-minutes")) {
2116
 *  extra fields in the tables.
1960
		ast_string_field_set(q, sound_minutes, val);
2117
 * \note For error reporting, line number is passed for .conf static configuration,
1961
	} else if (!strcasecmp(param, "queue-minute")) {
2118
 * for Realtime queues, linenum is -1.
1962
		ast_string_field_set(q, sound_minute, val);
2119
*/
1963
	} else if (!strcasecmp(param, "queue-seconds")) {
2120
static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
1964
		ast_string_field_set(q, sound_seconds, val);
2121
{
1965
	} else if (!strcasecmp(param, "queue-thankyou")) {
2122
	if (!strcasecmp(param, "musicclass") || 
1966
		ast_string_field_set(q, sound_thanks, val);
2123
		!strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
1967
	} else if (!strcasecmp(param, "queue-callerannounce")) {
2124
		ast_string_field_set(q, moh, val);
1968
		ast_string_field_set(q, sound_callerannounce, val);
2125
	} else if (!strcasecmp(param, "announce")) {
1969
	} else if (!strcasecmp(param, "queue-reporthold")) {
2126
		ast_string_field_set(q, announce, val);
1970
		ast_string_field_set(q, sound_reporthold, val);
2127
	} else if (!strcasecmp(param, "context")) {
1971
	} else if (!strcasecmp(param, "announce-frequency")) {
2128
		ast_string_field_set(q, context, val);
1972
		q->announcefrequency = atoi(val);
2129
	} else if (!strcasecmp(param, "timeout")) {
1973
	} else if (!strcasecmp(param, "min-announce-frequency")) {
2130
		q->timeout = atoi(val);
1974
		q->minannouncefrequency = atoi(val);
2131
		if (q->timeout < 0) {
1975
		ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
2132
			q->timeout = DEFAULT_TIMEOUT;
1976
	} else if (!strcasecmp(param, "announce-round-seconds")) {
2133
		}
1977
		q->roundingseconds = atoi(val);
2134
	} else if (!strcasecmp(param, "ringinuse")) {
1978
		/* Rounding to any other values just doesn't make sense... */
2135
		q->ringinuse = ast_true(val);
1979
		if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
2136
	} else if (!strcasecmp(param, "setinterfacevar")) {
1980
			|| q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
2137
		q->setinterfacevar = ast_true(val);
1981
			if (linenum >= 0) {
2138
	} else if (!strcasecmp(param, "setqueuevar")) {
1982
				ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
2139
		q->setqueuevar = ast_true(val);
1983
					"using 0 instead for queue '%s' at line %d of queues.conf\n",
2140
	} else if (!strcasecmp(param, "setqueueentryvar")) {
1984
					val, param, q->name, linenum);
2141
		q->setqueueentryvar = ast_true(val);
1985
			} else {
2142
	} else if (!strcasecmp(param, "monitor-format")) {
1986
				ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
2143
		ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
1987
					"using 0 instead for queue '%s'\n", val, param, q->name);
2144
	} else if (!strcasecmp(param, "membermacro")) {

    
   
2145
		ast_string_field_set(q, membermacro, val);

    
   
2146
	} else if (!strcasecmp(param, "membergosub")) {

    
   
2147
		ast_string_field_set(q, membergosub, val);

    
   
2148
	} else if (!strcasecmp(param, "queue-youarenext")) {

    
   
2149
		ast_string_field_set(q, sound_next, val);

    
   
2150
	} else if (!strcasecmp(param, "queue-thereare")) {

    
   
2151
		ast_string_field_set(q, sound_thereare, val);

    
   
2152
	} else if (!strcasecmp(param, "queue-callswaiting")) {

    
   
2153
		ast_string_field_set(q, sound_calls, val);

    
   
2154
	} else if (!strcasecmp(param, "queue-quantity1")) {

    
   
2155
		ast_string_field_set(q, queue_quantity1, val);

    
   
2156
	} else if (!strcasecmp(param, "queue-quantity2")) {

    
   
2157
		ast_string_field_set(q, queue_quantity2, val);

    
   
2158
	} else if (!strcasecmp(param, "queue-holdtime")) {

    
   
2159
		ast_string_field_set(q, sound_holdtime, val);

    
   
2160
	} else if (!strcasecmp(param, "queue-minutes")) {

    
   
2161
		ast_string_field_set(q, sound_minutes, val);

    
   
2162
	} else if (!strcasecmp(param, "queue-minute")) {

    
   
2163
		ast_string_field_set(q, sound_minute, val);

    
   
2164
	} else if (!strcasecmp(param, "queue-seconds")) {

    
   
2165
		ast_string_field_set(q, sound_seconds, val);

    
   
2166
	} else if (!strcasecmp(param, "queue-thankyou")) {

    
   
2167
		ast_string_field_set(q, sound_thanks, val);

    
   
2168
	} else if (!strcasecmp(param, "queue-callerannounce")) {

    
   
2169
		ast_string_field_set(q, sound_callerannounce, val);

    
   
2170
	} else if (!strcasecmp(param, "queue-reporthold")) {

    
   
2171
		ast_string_field_set(q, sound_reporthold, val);

    
   
2172
	} else if (!strcasecmp(param, "announce-frequency")) {

    
   
2173
		q->announcefrequency = atoi(val);

    
   
2174
	} else if (!strcasecmp(param, "min-announce-frequency")) {

    
   
2175
		q->minannouncefrequency = atoi(val);

    
   
2176
		ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);

    
   
2177
	} else if (!strcasecmp(param, "announce-round-seconds")) {

    
   
2178
		q->roundingseconds = atoi(val);

    
   
2179
		/* Rounding to any other values just doesn't make sense... */

    
   
2180
		if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10

    
   
2181
			|| q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {

    
   
2182
			if (linenum >= 0) {

    
   
2183
				ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "

    
   
2184
					"using 0 instead for queue '%s' at line %d of queues.conf\n",

    
   
2185
					val, param, q->name, linenum);

    
   
2186
			} else {

    
   
2187
				ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "

    
   
2188
					"using 0 instead for queue '%s'\n", val, param, q->name);
1988
			}
2189
			}
1989
			q->roundingseconds=0;
2190
			q->roundingseconds=0;
1990
		}
2191
		}
1991
	} else if (!strcasecmp(param, "announce-holdtime")) {
2192
	} else if (!strcasecmp(param, "announce-holdtime")) {
1992
		if (!strcasecmp(val, "once"))
2193
		if (!strcasecmp(val, "once")) {
1993
			q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
2194
			q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
1994
		else if (ast_true(val))
2195
		} else if (ast_true(val)) {
1995
			q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
2196
			q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
1996
		else
2197
		} else {
1997
			q->announceholdtime = 0;
2198
			q->announceholdtime = 0;

    
   
2199
		}
1998
	} else if (!strcasecmp(param, "announce-position")) {
2200
	} else if (!strcasecmp(param, "announce-position")) {
1999
		if (!strcasecmp(val, "limit"))
2201
		if (!strcasecmp(val, "limit")) {
2000
			q->announceposition = ANNOUNCEPOSITION_LIMIT;
2202
			q->announceposition = ANNOUNCEPOSITION_LIMIT;
2001
		else if (!strcasecmp(val, "more"))
2203
		} else if (!strcasecmp(val, "more")) {
2002
			q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
2204
			q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
2003
		else if (ast_true(val))
2205
		} else if (ast_true(val)) {
2004
			q->announceposition = ANNOUNCEPOSITION_YES;
2206
			q->announceposition = ANNOUNCEPOSITION_YES;
2005
		else
2207
		} else {
2006
			q->announceposition = ANNOUNCEPOSITION_NO;
2208
			q->announceposition = ANNOUNCEPOSITION_NO;

    
   
2209
		}
2007
	} else if (!strcasecmp(param, "announce-position-limit")) {
2210
	} else if (!strcasecmp(param, "announce-position-limit")) {
2008
		q->announcepositionlimit = atoi(val);
2211
		q->announcepositionlimit = atoi(val);
2009
	} else if (!strcasecmp(param, "periodic-announce")) {
2212
	} else if (!strcasecmp(param, "periodic-announce")) {
2010
		if (strchr(val, ',')) {
2213
		if (strchr(val, ',')) {
2011
			char *s, *buf = ast_strdupa(val);
2214
			char *s, *buf = ast_strdupa(val);
2012
			unsigned int i = 0;
2215
			unsigned int i = 0;
2013

    
   
2216

   
2014
			while ((s = strsep(&buf, ",|"))) {
2217
			while ((s = strsep(&buf, ",|"))) {
2015
				if (!q->sound_periodicannounce[i])
2218
				if (!q->sound_periodicannounce[i]) {
2016
					q->sound_periodicannounce[i] = ast_str_create(16);
2219
					q->sound_periodicannounce[i] = ast_str_create(16);

    
   
2220
				}
2017
				ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
2221
				ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
2018
				i++;
2222
				i++;
2019
				if (i == MAX_PERIODIC_ANNOUNCEMENTS)
2223
				if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
2020
					break;
2224
					break;
2021
			}
2225
				}

    
   
2226
			}
2022
			q->numperiodicannounce = i;
2227
			q->numperiodicannounce = i;
2023
		} else {
2228
		} else {
2024
			ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
2229
			ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
2025
			q->numperiodicannounce = 1;
2230
			q->numperiodicannounce = 1;
2026
		}
2231
		}
2027
	} else if (!strcasecmp(param, "periodic-announce-frequency")) {
2232
	} else if (!strcasecmp(param, "periodic-announce-frequency")) {
2028
		q->periodicannouncefrequency = atoi(val);
2233
		q->periodicannouncefrequency = atoi(val);
2029
	} else if (!strcasecmp(param, "relative-periodic-announce")) {
2234
	} else if (!strcasecmp(param, "relative-periodic-announce")) {
2030
		q->relativeperiodicannounce = ast_true(val);
2235
		q->relativeperiodicannounce = ast_true(val);
2031
	} else if (!strcasecmp(param, "random-periodic-announce")) {
2236
	} else if (!strcasecmp(param, "random-periodic-announce")) {
2032
		q->randomperiodicannounce = ast_true(val);
2237
		q->randomperiodicannounce = ast_true(val);
2033
	} else if (!strcasecmp(param, "retry")) {
2238
	} else if (!strcasecmp(param, "retry")) {
2034
		q->retry = atoi(val);
2239
		q->retry = atoi(val);
2035
		if (q->retry <= 0)
2240
		if (q->retry <= 0) {
2036
			q->retry = DEFAULT_RETRY;
2241
			q->retry = DEFAULT_RETRY;

    
   
2242
		}
2037
	} else if (!strcasecmp(param, "wrapuptime")) {
2243
	} else if (!strcasecmp(param, "wrapuptime")) {
2038
		q->wrapuptime = atoi(val);
2244
		q->wrapuptime = atoi(val);
2039
	} else if (!strcasecmp(param, "penaltymemberslimit")) {
2245
	} else if (!strcasecmp(param, "penaltymemberslimit")) {
2040
		if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
2246
		if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
2041
			q->penaltymemberslimit = 0;
2247
			q->penaltymemberslimit = 0;
2042
		}
2248
		}
2043
	} else if (!strcasecmp(param, "autofill")) {
2249
	} else if (!strcasecmp(param, "autofill")) {
2044
		q->autofill = ast_true(val);
2250
		q->autofill = ast_true(val);
2045
	} else if (!strcasecmp(param, "monitor-type")) {
2251
	} else if (!strcasecmp(param, "monitor-type")) {
2046
		if (!strcasecmp(val, "mixmonitor"))
2252
		if (!strcasecmp(val, "mixmonitor")) {
2047
			q->montype = 1;
2253
			q->montype = 1;

    
   
2254
		}
2048
	} else if (!strcasecmp(param, "autopause")) {
2255
	} else if (!strcasecmp(param, "autopause")) {
2049
		q->autopause = autopause2int(val);
2256
		q->autopause = autopause2int(val);
2050
	} else if (!strcasecmp(param, "autopausedelay")) {
2257
	} else if (!strcasecmp(param, "autopausedelay")) {
2051
		q->autopausedelay = atoi(val);
2258
		q->autopausedelay = atoi(val);
2052
	} else if (!strcasecmp(param, "autopausebusy")) {
2259
	} else if (!strcasecmp(param, "autopausebusy")) {
2053
		q->autopausebusy = ast_true(val);
2260
		q->autopausebusy = ast_true(val);
2054
	} else if (!strcasecmp(param, "autopauseunavail")) {
2261
	} else if (!strcasecmp(param, "autopauseunavail")) {
2055
		q->autopauseunavail = ast_true(val);
2262
		q->autopauseunavail = ast_true(val);
2056
	} else if (!strcasecmp(param, "maxlen")) {
2263
	} else if (!strcasecmp(param, "maxlen")) {
2057
		q->maxlen = atoi(val);
2264
		q->maxlen = atoi(val);
2058
		if (q->maxlen < 0)
2265
		if (q->maxlen < 0) {
2059
			q->maxlen = 0;
2266
			q->maxlen = 0;

    
   
2267
		}
2060
	} else if (!strcasecmp(param, "servicelevel")) {
2268
	} else if (!strcasecmp(param, "servicelevel")) {
2061
		q->servicelevel= atoi(val);
2269
		q->servicelevel= atoi(val);
2062
	} else if (!strcasecmp(param, "strategy")) {
2270
	} else if (!strcasecmp(param, "strategy")) {
2063
		int strategy;
2271
		int strategy;
2064

    
   
2272

   
[+20] [20] 64 lines
[+20] [+] static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
2129
	struct member *m;
2337
	struct member *m;
2130
	struct ao2_iterator mem_iter;
2338
	struct ao2_iterator mem_iter;
2131
	int penalty = 0;
2339
	int penalty = 0;
2132
	int paused  = 0;
2340
	int paused  = 0;
2133
	int found = 0;
2341
	int found = 0;
2134
	int ignorebusy = 0;
2342
	int ringinuse = q->ringinuse;
2135

    
   
2343

   
2136
	const char *config_val;
2344
	const char *config_val;
2137
	const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
2345
	const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
2138
	const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
2346
	const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
2139
	const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
2347
	const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
[+20] [20] 19 lines
[+20] static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
2159
		if (paused < 0) {
2367
		if (paused < 0) {
2160
			paused = 0;
2368
			paused = 0;
2161
		}
2369
		}
2162
	}
2370
	}
2163

    
   
2371

   
2164
	if ((config_val = ast_variable_retrieve(member_config, interface, "ignorebusy"))) {
2372
	if ((config_val = ast_variable_retrieve(member_config, interface, realtime_ringinuse_field))) {
2165
		ignorebusy = ast_true(config_val);
2373
		if (ast_true(config_val)) {

    
   
2374
			ringinuse = 1;

    
   
2375
		} else if (ast_false(config_val)) {

    
   
2376
			ringinuse = 0;
2166
	} else {
2377
		} else {
2167
		ignorebusy = 1;
2378
			ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);

    
   
2379
		}
2168
	}
2380
	}
2169

    
   
2381

   
2170
	/* Find member by realtime uniqueid and update */
2382
	/* Find member by realtime uniqueid and update */
2171
	mem_iter = ao2_iterator_init(q->members, 0);
2383
	mem_iter = ao2_iterator_init(q->members, 0);
2172
	while ((m = ao2_iterator_next(&mem_iter))) {
2384
	while ((m = ao2_iterator_next(&mem_iter))) {
[+20] [20] 5 lines
[+20] static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
2178
			}
2390
			}
2179
			if (strcasecmp(state_interface, m->state_interface)) {
2391
			if (strcasecmp(state_interface, m->state_interface)) {
2180
				ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
2392
				ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
2181
			}
2393
			}
2182
			m->penalty = penalty;
2394
			m->penalty = penalty;
2183
			m->ignorebusy = ignorebusy;
2395
			m->ringinuse = ringinuse;
2184
			found = 1;
2396
			found = 1;
2185
			ao2_ref(m, -1);
2397
			ao2_ref(m, -1);
2186
			break;
2398
			break;
2187
		}
2399
		}
2188
		ao2_ref(m, -1);
2400
		ao2_ref(m, -1);
2189
	}
2401
	}
2190
	ao2_iterator_destroy(&mem_iter);
2402
	ao2_iterator_destroy(&mem_iter);
2191

    
   
2403

   
2192
	/* Create a new member */
2404
	/* Create a new member */
2193
	if (!found) {
2405
	if (!found) {
2194
		if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
2406
		if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse))) {
2195
			m->dead = 0;
2407
			m->dead = 0;
2196
			m->realtime = 1;
2408
			m->realtime = 1;
2197
			m->ignorebusy = ignorebusy;

   
2198
			ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
2409
			ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
2199
			if (!log_membername_as_agent) {
2410
			if (!log_membername_as_agent) {
2200
				ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
2411
				ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
2201
			} else {
2412
			} else {
2202
				ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
2413
				ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
[+20] [20] 28 lines
[+20] [+] static void destroy_queue(void *obj)
2231
	int i;
2442
	int i;
2232

    
   
2443

   
2233
	free_members(q, 1);
2444
	free_members(q, 1);
2234
	ast_string_field_free_memory(q);
2445
	ast_string_field_free_memory(q);
2235
	for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
2446
	for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
2236
		if (q->sound_periodicannounce[i])
2447
		if (q->sound_periodicannounce[i]) {
2237
			free(q->sound_periodicannounce[i]);
2448
			free(q->sound_periodicannounce[i]);
2238
	}
2449
		}

    
   
2450
	}
2239
	ao2_ref(q->members, -1);
2451
	ao2_ref(q->members, -1);
2240
}
2452
}
2241

    
   
2453

   
2242
static struct call_queue *alloc_queue(const char *queuename)
2454
static struct call_queue *alloc_queue(const char *queuename)
2243
{
2455
{
[+20] [20] 38 lines
[+20] [+] static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
2282
		if (!q->realtime) {
2494
		if (!q->realtime) {
2283
			if (q->dead) {
2495
			if (q->dead) {
2284
				ao2_unlock(q);
2496
				ao2_unlock(q);
2285
				queue_t_unref(q, "Queue is dead; can't return it");
2497
				queue_t_unref(q, "Queue is dead; can't return it");
2286
				return NULL;
2498
				return NULL;
2287
			} else {
2499
			} 
2288
				ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
2500
			ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
2289
				ao2_unlock(q);
2501
			ao2_unlock(q);
2290
				return q;
2502
			return q;
2291
			}
2503
		}
2292
		}

   
2293
	} else if (!member_config) {
2504
	} else if (!member_config) {
2294
		/* Not found in the list, and it's not realtime ... */
2505
		/* Not found in the list, and it's not realtime ... */
2295
		return NULL;
2506
		return NULL;
2296
	}
2507
	}
2297
	/* Check if queue is defined in realtime. */
2508
	/* Check if queue is defined in realtime. */
[+20] [20] 46 lines
[+20] static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
2344
	init_queue(q);		/* Ensure defaults for all parameters not set explicitly. */
2555
	init_queue(q);		/* Ensure defaults for all parameters not set explicitly. */
2345

    
   
2556

   
2346
	memset(tmpbuf, 0, sizeof(tmpbuf));
2557
	memset(tmpbuf, 0, sizeof(tmpbuf));
2347
	for (v = queue_vars; v; v = v->next) {
2558
	for (v = queue_vars; v; v = v->next) {
2348
		/* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
2559
		/* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
2349
		if ((tmp = strchr(v->name, '_'))) {
2560
		if (strchr(v->name, '_')) {
2350
			ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
2561
			ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
2351
			tmp_name = tmpbuf;
2562
			tmp_name = tmpbuf;
2352
			tmp = tmpbuf;
2563
			tmp = tmpbuf;
2353
			while ((tmp = strchr(tmp, '_')))
2564
			while ((tmp = strchr(tmp, '_'))) {
2354
				*tmp++ = '-';
2565
				*tmp++ = '-';
2355
		} else
2566
			}

    
   
2567
		} else {
2356
			tmp_name = v->name;
2568
			tmp_name = v->name;

    
   
2569
		}
2357

    
   
2570

   
2358
		/* NULL values don't get returned from realtime; blank values should
2571
		/* NULL values don't get returned from realtime; blank values should
2359
		 * still get set.  If someone doesn't want a value to be set, they
2572
		 * still get set.  If someone doesn't want a value to be set, they
2360
		 * should set the realtime column to NULL, not blank. */
2573
		 * should set the realtime column to NULL, not blank. */
2361
		queue_set_param(q, tmp_name, v->value, -1, 0);
2574
		queue_set_param(q, tmp_name, v->value, -1, 0);
[+20] [20] 68 lines
[+20] [+] static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
2430

    
   
2643

   
2431
		queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
2644
		queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
2432
		if (queue_vars) {
2645
		if (queue_vars) {
2433
			member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
2646
			member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
2434
			if (!member_config) {
2647
			if (!member_config) {
2435
				ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
2648
				ast_debug(1, "No queue_members defined in config extconfig.conf\n");
2436
				ast_variables_destroy(queue_vars);
2649
				member_config = ast_config_new();
2437
				return NULL;

   
2438
			}
2650
			}
2439
		}
2651
		}
2440
		if (q) {
2652
		if (q) {
2441
			prev_weight = q->weight ? 1 : 0;
2653
			prev_weight = q->weight ? 1 : 0;
2442
			queue_t_unref(q, "Need to find realtime queue");
2654
			queue_t_unref(q, "Need to find realtime queue");
[+20] [20] 21 lines
[+20] static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
2464

    
   
2676

   
2465
static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
2677
static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
2466
{
2678
{
2467
	int ret = -1;
2679
	int ret = -1;
2468

    
   
2680

   
2469
	if (ast_strlen_zero(mem->rt_uniqueid))
2681
	if (ast_strlen_zero(mem->rt_uniqueid)) {
2470
 		return ret;
2682
 		return ret;

    
   
2683
	}
2471

    
   
2684

   
2472
	if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0)
2685
	if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0) {
2473
		ret = 0;
2686
		ret = 0;

    
   
2687
	}
2474

    
   
2688

   
2475
	return ret;
2689
	return ret;
2476
}
2690
}
2477

    
   
2691

   
2478

    
   
2692

   
2479
static void update_realtime_members(struct call_queue *q)
2693
static void update_realtime_members(struct call_queue *q)
2480
{
2694
{
2481
	struct ast_config *member_config = NULL;
2695
	struct ast_config *member_config = NULL;
2482
	struct member *m;
2696
	struct member *m;
2483
	char *interface = NULL;
2697
	char *interface = NULL;
2484
	struct ao2_iterator mem_iter;
2698
	struct ao2_iterator mem_iter;
2485

    
   
2699

   
2486
	if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
2700
	if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
2487
		/*This queue doesn't have realtime members*/
2701
		/* This queue doesn't have realtime members. If the queue still has any realtime

    
   
2702
		 * members in memory, they need to be removed.

    
   
2703
		 */

    
   
2704
		ao2_lock(q);

    
   
2705
		mem_iter = ao2_iterator_init(q->members, 0);

    
   
2706
		while ((m = ao2_iterator_next(&mem_iter))) {

    
   
2707
			if (m->realtime) {

    
   
2708
				ao2_unlink(q->members, m);

    
   
2709
			}

    
   
2710
			ao2_ref(m, -1);

    
   
2711
		}
2488
		ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
2712
		ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);

    
   
2713
		ao2_unlock(q);
2489
		return;
2714
		return;
2490
	}
2715
	}
2491

    
   
2716

   
2492
	ao2_lock(q);
2717
	ao2_lock(q);
2493

    
   
2718

   
2494
	/* Temporarily set realtime  members dead so we can detect deleted ones.*/
2719
	/* Temporarily set realtime  members dead so we can detect deleted ones.*/
2495
	mem_iter = ao2_iterator_init(q->members, 0);
2720
	mem_iter = ao2_iterator_init(q->members, 0);
2496
	while ((m = ao2_iterator_next(&mem_iter))) {
2721
	while ((m = ao2_iterator_next(&mem_iter))) {
2497
		if (m->realtime)
2722
		if (m->realtime) {
2498
			m->dead = 1;
2723
			m->dead = 1;

    
   
2724
		}
2499
		ao2_ref(m, -1);
2725
		ao2_ref(m, -1);
2500
	}
2726
	}
2501
	ao2_iterator_destroy(&mem_iter);
2727
	ao2_iterator_destroy(&mem_iter);
2502

    
   
2728

   
2503
	while ((interface = ast_category_browse(member_config, interface))) {
2729
	while ((interface = ast_category_browse(member_config, interface))) {
[+20] [20] 39 lines
[+20] [+] static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
2543
			ao2_unlock(q);
2769
			ao2_unlock(q);
2544
			queue_t_unref(q, "Done with realtime queue");
2770
			queue_t_unref(q, "Done with realtime queue");
2545
			return res;
2771
			return res;
2546
		}
2772
		}
2547
	}
2773
	}
2548
	if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen))
2774
	if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
2549
		*reason = QUEUE_FULL;
2775
		*reason = QUEUE_FULL;
2550
	else if (*reason == QUEUE_UNKNOWN) {
2776
	} else if (*reason == QUEUE_UNKNOWN) {
2551
		/* There's space for us, put us at the right position inside
2777
		/* There's space for us, put us at the right position inside
2552
		 * the queue.
2778
		 * the queue.
2553
		 * Take into account the priority of the calling user */
2779
		 * Take into account the priority of the calling user */
2554
		inserted = 0;
2780
		inserted = 0;
2555
		prev = NULL;
2781
		prev = NULL;
[+20] [20] 9 lines
[+20] static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
2565
			/* <= is necessary for the position comparison because it may not be possible to enter
2791
			/* <= is necessary for the position comparison because it may not be possible to enter
2566
			 * at our desired position since higher-priority callers may have taken the position we want
2792
			 * at our desired position since higher-priority callers may have taken the position we want
2567
			 */
2793
			 */
2568
			if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
2794
			if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
2569
				insert_entry(q, prev, qe, &pos);
2795
				insert_entry(q, prev, qe, &pos);

    
   
2796
				inserted = 1;
2570
				/*pos is incremented inside insert_entry, so don't need to add 1 here*/
2797
				/*pos is incremented inside insert_entry, so don't need to add 1 here*/
2571
				if (position < pos) {
2798
				if (position < pos) {
2572
					ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
2799
					ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
2573
				}
2800
				}
2574
				inserted = 1;

   
2575
			}
2801
			}
2576
			cur->pos = ++pos;
2802
			cur->pos = ++pos;
2577
			prev = cur;
2803
			prev = cur;
2578
			cur = cur->next;
2804
			cur = cur->next;
2579
		}
2805
		}
2580
		/* No luck, join at the end of the queue */
2806
		/* No luck, join at the end of the queue */
2581
		if (!inserted)
2807
		if (!inserted) {
2582
			insert_entry(q, prev, qe, &pos);
2808
			insert_entry(q, prev, qe, &pos);

    
   
2809
		}
2583
		ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
2810
		ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
2584
		ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
2811
		ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
2585
		ast_copy_string(qe->context, q->context, sizeof(qe->context));
2812
		ast_copy_string(qe->context, q->context, sizeof(qe->context));
2586
		q->count++;
2813
		q->count++;

    
   
2814
		if (q->count == 1) {
2587
		ast_devstate_changed(AST_DEVICE_RINGING, "Queue:%s", q->name);
2815
			ast_devstate_changed(AST_DEVICE_RINGING, "Queue:%s", q->name);
2588
		ast_log(LOG_NOTICE,"ALEC queue=%s count++ =%d\n", q->name, q->count);
2816
		}
2589

    
   
2817

   
2590
		res = 0;
2818
		res = 0;

    
   
2819
		/*** DOCUMENTATION

    
   
2820
		<managerEventInstance>

    
   
2821
			<synopsis>Raised when a channel joins a Queue.</synopsis>

    
   
2822
			<syntax>

    
   
2823
				<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />

    
   
2824
				<parameter name="Position">

    
   
2825
					<para>This channel's current position in the queue.</para>

    
   
2826
				</parameter>

    
   
2827
				<parameter name="Count">

    
   
2828
					<para>The total number of channels in the queue.</para>

    
   
2829
				</parameter>

    
   
2830
			</syntax>

    
   
2831
			<see-also>

    
   
2832
				<ref type="managerEvent">Leave</ref>

    
   
2833
				<ref type="application">Queue</ref>

    
   
2834
			</see-also>

    
   
2835
		</managerEventInstance>

    
   
2836
		***/
2591
		ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
2837
		ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
2592
			"Channel: %s\r\n"
2838
			"Channel: %s\r\n"
2593
			"CallerIDNum: %s\r\n"
2839
			"CallerIDNum: %s\r\n"
2594
			"CallerIDName: %s\r\n"
2840
			"CallerIDName: %s\r\n"
2595
			"ConnectedLineNum: %s\r\n"
2841
			"ConnectedLineNum: %s\r\n"
2596
			"ConnectedLineName: %s\r\n"
2842
			"ConnectedLineName: %s\r\n"
2597
			"Queue: %s\r\n"
2843
			"Queue: %s\r\n"
2598
			"Position: %d\r\n"
2844
			"Position: %d\r\n"
2599
			"Count: %d\r\n"
2845
			"Count: %d\r\n"
2600
			"Uniqueid: %s\r\n",
2846
			"Uniqueid: %s\r\n",
2601
			qe->chan->name,
2847
			ast_channel_name(qe->chan),
2602
			S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
2848
			S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
2603
			S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
2849
			S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
2604
			S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
2850
			S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
2605
			S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
2851
			S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
2606
			q->name, qe->pos, q->count, qe->chan->uniqueid );
2852
			q->name, qe->pos, q->count, ast_channel_uniqueid(qe->chan));
2607
		ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
2853
		ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
2608
	}
2854
	}
2609
	ao2_unlock(q);
2855
	ao2_unlock(q);
2610
	queue_t_unref(q, "Done with realtime queue");
2856
	queue_t_unref(q, "Done with realtime queue");
2611

    
   
2857

   
2612
	return res;
2858
	return res;
[+20] [20] 5 lines
[+20] [+] static int play_file(struct ast_channel *chan, const char *filename)
2618

    
   
2864

   
2619
	if (ast_strlen_zero(filename)) {
2865
	if (ast_strlen_zero(filename)) {
2620
		return 0;
2866
		return 0;
2621
	}
2867
	}
2622

    
   
2868

   
2623
	if (!ast_fileexists(filename, NULL, chan->language)) {
2869
	if (!ast_fileexists(filename, NULL, ast_channel_language(chan))) {
2624
		return 0;
2870
		return 0;
2625
	}
2871
	}
2626

    
   
2872

   
2627
	ast_stopstream(chan);
2873
	ast_stopstream(chan);
2628

    
   
2874

   
2629
	res = ast_streamfile(chan, filename, chan->language);
2875
	res = ast_streamfile(chan, filename, ast_channel_language(chan));
2630
	if (!res)
2876
	if (!res) {
2631
		res = ast_waitstream(chan, AST_DIGIT_ANY);
2877
		res = ast_waitstream(chan, AST_DIGIT_ANY);

    
   
2878
	}
2632

    
   
2879

   
2633
	ast_stopstream(chan);
2880
	ast_stopstream(chan);
2634

    
   
2881

   
2635
	return res;
2882
	return res;
2636
}
2883
}
[+20] [20] 15 lines
[+20] [+] static int valid_exit(struct queue_ent *qe, char digit)
2652
		qe->digits[0] = '\0';
2899
		qe->digits[0] = '\0';
2653
		return 0;
2900
		return 0;
2654
	}
2901
	}
2655

    
   
2902

   
2656
	/* If there's no context to goto, short-circuit */
2903
	/* If there's no context to goto, short-circuit */
2657
	if (ast_strlen_zero(qe->context))
2904
	if (ast_strlen_zero(qe->context)) {
2658
		return 0;
2905
		return 0;

    
   
2906
	}
2659

    
   
2907

   
2660
	/* If the extension is bad, then reset the digits to blank */
2908
	/* If the extension is bad, then reset the digits to blank */
2661
	if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
2909
	if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
2662
		S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, NULL))) {
2910
		S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, NULL))) {
2663
		qe->digits[0] = '\0';
2911
		qe->digits[0] = '\0';
2664
		return 0;
2912
		return 0;
2665
	}
2913
	}
2666

    
   
2914

   
2667
	/* We have an exact match */
2915
	/* We have an exact match */
[+20] [20] 12 lines
[+20] [+] static int say_position(struct queue_ent *qe, int ringing)
2680
	int say_thanks = 1;
2928
	int say_thanks = 1;
2681
	time_t now;
2929
	time_t now;
2682

    
   
2930

   
2683
	/* Let minannouncefrequency seconds pass between the start of each position announcement */
2931
	/* Let minannouncefrequency seconds pass between the start of each position announcement */
2684
	time(&now);
2932
	time(&now);
2685
	if ((now - qe->last_pos) < qe->parent->minannouncefrequency)
2933
	if ((now - qe->last_pos) < qe->parent->minannouncefrequency) {
2686
		return 0;
2934
		return 0;

    
   
2935
	}
2687

    
   
2936

   
2688
	/* If either our position has changed, or we are over the freq timer, say position */
2937
	/* If either our position has changed, or we are over the freq timer, say position */
2689
	if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
2938
	if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency)) {
2690
		return 0;
2939
		return 0;

    
   
2940
	}
2691

    
   
2941

   
2692
	if (ringing) {
2942
	if (ringing) {
2693
		ast_indicate(qe->chan,-1);
2943
		ast_indicate(qe->chan,-1);
2694
	} else {
2944
	} else {
2695
		ast_moh_stop(qe->chan);
2945
		ast_moh_stop(qe->chan);
2696
	}
2946
	}
2697

    
   
2947

   
2698
	if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
2948
	if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
2699
		qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
2949
		qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
2700
		(qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
2950
		(qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
2701
		qe->pos <= qe->parent->announcepositionlimit))
2951
		qe->pos <= qe->parent->announcepositionlimit)) {
2702
			announceposition = 1;
2952
			announceposition = 1;

    
   
2953
	}
2703

    
   
2954

   
2704

    
   
2955

   
2705
	if (announceposition == 1) {
2956
	if (announceposition == 1) {
2706
		/* Say we're next, if we are */
2957
		/* Say we're next, if we are */
2707
		if (qe->pos == 1) {
2958
		if (qe->pos == 1) {
2708
			res = play_file(qe->chan, qe->parent->sound_next);
2959
			res = play_file(qe->chan, qe->parent->sound_next);
2709
			if (res)
2960
			if (res) {
2710
				goto playout;
2961
				goto playout;
2711
			else
2962
			}
2712
				goto posout;
2963
			goto posout;
2713
		} else {
2964
		} else {
2714
			if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
2965
			if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
2715
				/* More than Case*/
2966
				/* More than Case*/
2716
				res = play_file(qe->chan, qe->parent->queue_quantity1);
2967
				res = play_file(qe->chan, qe->parent->queue_quantity1);
2717
				if (res)
2968
				if (res) {
2718
					goto playout;
2969
					goto playout;
2719
				res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
2970
				}
2720
				if (res)
2971
				res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */

    
   
2972
				if (res) {
2721
					goto playout;
2973
					goto playout;

    
   
2974
				}
2722
			} else {
2975
			} else {
2723
				/* Normal Case */
2976
				/* Normal Case */
2724
				res = play_file(qe->chan, qe->parent->sound_thereare);
2977
				res = play_file(qe->chan, qe->parent->sound_thereare);
2725
				if (res)
2978
				if (res) {
2726
					goto playout;
2979
					goto playout;
2727
				res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
2980
				}
2728
				if (res)
2981
				res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */

    
   
2982
				if (res) {
2729
					goto playout;
2983
					goto playout;
2730
			}
2984
				}

    
   
2985
			}
2731
			if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
2986
			if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
2732
				/* More than Case*/
2987
				/* More than Case*/
2733
				res = play_file(qe->chan, qe->parent->queue_quantity2);
2988
				res = play_file(qe->chan, qe->parent->queue_quantity2);
2734
				if (res)
2989
				if (res) {
2735
					goto playout;
2990
					goto playout;

    
   
2991
				}
2736
			} else {
2992
			} else {
2737
				res = play_file(qe->chan, qe->parent->sound_calls);
2993
				res = play_file(qe->chan, qe->parent->sound_calls);
2738
				if (res)
2994
				if (res) {
2739
					goto playout;
2995
					goto playout;
2740
			}
2996
				}
2741
		}
2997
			}
2742
	}
2998
		}

    
   
2999
	}
2743
	/* Round hold time to nearest minute */
3000
	/* Round hold time to nearest minute */
2744
	avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
3001
	avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
2745

    
   
3002

   
2746
	/* If they have specified a rounding then round the seconds as well */
3003
	/* If they have specified a rounding then round the seconds as well */
2747
	if (qe->parent->roundingseconds) {
3004
	if (qe->parent->roundingseconds) {
[+20] [20] 9 lines
[+20] static int say_position(struct queue_ent *qe, int ringing)
2757
	   supposed to be only once and we have already said it, say it */
3014
	   supposed to be only once and we have already said it, say it */
2758
    if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
3015
    if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
2759
        ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
3016
        ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
2760
        !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
3017
        !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
2761
		res = play_file(qe->chan, qe->parent->sound_holdtime);
3018
		res = play_file(qe->chan, qe->parent->sound_holdtime);
2762
		if (res)
3019
		if (res) {
2763
			goto playout;
3020
			goto playout;

    
   
3021
		}
2764

    
   
3022

   
2765
		if (avgholdmins >= 1) {
3023
		if (avgholdmins >= 1) {
2766
			res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language, NULL);
3024
			res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
2767
			if (res)
3025
			if (res) {
2768
				goto playout;
3026
				goto playout;

    
   
3027
			}
2769

    
   
3028

   
2770
			if (avgholdmins == 1) {
3029
			if (avgholdmins == 1) {
2771
				res = play_file(qe->chan, qe->parent->sound_minute);
3030
				res = play_file(qe->chan, qe->parent->sound_minute);
2772
				if (res)
3031
				if (res) {
2773
					goto playout;
3032
					goto playout;

    
   
3033
				}
2774
			} else {
3034
			} else {
2775
				res = play_file(qe->chan, qe->parent->sound_minutes);
3035
				res = play_file(qe->chan, qe->parent->sound_minutes);
2776
				if (res)
3036
				if (res) {
2777
					goto playout;
3037
					goto playout;
2778
			}
3038
				}
2779
		}
3039
			}

    
   
3040
		}
2780
		if (avgholdsecs >= 1) {
3041
		if (avgholdsecs >= 1) {
2781
			res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, qe->chan->language, NULL);
3042
			res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
2782
			if (res)
3043
			if (res) {
2783
				goto playout;
3044
				goto playout;

    
   
3045
			}
2784

    
   
3046

   
2785
			res = play_file(qe->chan, qe->parent->sound_seconds);
3047
			res = play_file(qe->chan, qe->parent->sound_seconds);
2786
			if (res)
3048
			if (res) {
2787
				goto playout;
3049
				goto playout;
2788
		}
3050
			}

    
   
3051
		}
2789
	} else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
3052
	} else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
2790
		say_thanks = 0;
3053
		say_thanks = 0;
2791
	}
3054
	}
2792

    
   
3055

   
2793
posout:
3056
posout:
2794
	if (qe->parent->announceposition) {
3057
	if (qe->parent->announceposition) {
2795
		ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
3058
		ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
2796
			qe->chan->name, qe->parent->name, qe->pos);
3059
			ast_channel_name(qe->chan), qe->parent->name, qe->pos);
2797
	}
3060
	}
2798
	if (say_thanks) {
3061
	if (say_thanks) {
2799
		res = play_file(qe->chan, qe->parent->sound_thanks);
3062
		res = play_file(qe->chan, qe->parent->sound_thanks);
2800
	}
3063
	}
2801
playout:
3064
playout:
2802

    
   
3065

   
2803
	if ((res > 0 && !valid_exit(qe, res)))
3066
	if ((res > 0 && !valid_exit(qe, res))) {
2804
		res = 0;
3067
		res = 0;

    
   
3068
	}
2805

    
   
3069

   
2806
	/* Set our last_pos indicators */
3070
	/* Set our last_pos indicators */
2807
	qe->last_pos = now;
3071
	qe->last_pos = now;
2808
	qe->last_pos_said = qe->pos;
3072
	qe->last_pos_said = qe->pos;
2809

    
   
3073

   
[+20] [20] 46 lines
[+20] [+] static void leave_queue(struct queue_ent *qe)
2856
			char posstr[20];
3120
			char posstr[20];
2857
			q->count--;
3121
			q->count--;
2858
			if (!q->count) {
3122
			if (!q->count) {
2859
				ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Queue:%s", q->name);
3123
				ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Queue:%s", q->name);
2860
			}
3124
			}
2861
			ast_log(LOG_NOTICE,"ALEC queue=%s count-- =%d\n", q->name, q->count);

   
2862

    
   
3125

   
2863
			/* Take us out of the queue */
3126
			/* Take us out of the queue */

    
   
3127
			/*** DOCUMENTATION

    
   
3128
			<managerEventInstance>

    
   
3129
				<synopsis>Raised when a channel leaves a Queue.</synopsis>

    
   
3130
				<syntax>

    
   
3131
					<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />

    
   
3132
					<xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Count'])" />

    
   
3133
					<xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Position'])" />

    
   
3134
				</syntax>

    
   
3135
				<see-also>

    
   
3136
					<ref type="managerEvent">Join</ref>

    
   
3137
				</see-also>

    
   
3138
			</managerEventInstance>

    
   
3139
			***/
2864
			ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
3140
			ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
2865
				"Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
3141
				"Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
2866
				qe->chan->name, q->name,  q->count, qe->pos, qe->chan->uniqueid);
3142
				ast_channel_name(qe->chan), q->name,  q->count, qe->pos, ast_channel_uniqueid(qe->chan));
2867
			ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
3143
			ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
2868
			/* Take us out of the queue */
3144
			/* Take us out of the queue */
2869
			if (prev)
3145
			if (prev) {
2870
				prev->next = current->next;
3146
				prev->next = current->next;
2871
			else
3147
			} else {
2872
				q->head = current->next;
3148
				q->head = current->next;

    
   
3149
			}
2873
			/* Free penalty rules */
3150
			/* Free penalty rules */
2874
			while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list)))
3151
			while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list))) {
2875
				ast_free(pr_iter);
3152
				ast_free(pr_iter);

    
   
3153
			}
2876
			snprintf(posstr, sizeof(posstr), "%d", qe->pos);
3154
			snprintf(posstr, sizeof(posstr), "%d", qe->pos);
2877
			pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
3155
			pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
2878
		} else {
3156
		} else {
2879
			/* Renumber the people after us in the queue based on a new count */
3157
			/* Renumber the people after us in the queue based on a new count */
2880
			current->pos = ++pos;
3158
			current->pos = ++pos;
[+20] [20] 45 lines
[+20] [+] static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
2926

    
   
3204

   
2927
	while (outgoing) {
3205
	while (outgoing) {
2928
		/* If someone else answered the call we should indicate this in the CANCEL */
3206
		/* If someone else answered the call we should indicate this in the CANCEL */
2929
		/* Hangup any existing lines we have open */
3207
		/* Hangup any existing lines we have open */
2930
		if (outgoing->chan && (outgoing->chan != exception)) {
3208
		if (outgoing->chan && (outgoing->chan != exception)) {
2931
			if (exception || cancel_answered_elsewhere)
3209
			if (exception || cancel_answered_elsewhere) {
2932
				ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE);
3210
				ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);

    
   
3211
			}
2933
			ast_hangup(outgoing->chan);
3212
			ast_hangup(outgoing->chan);
2934
		}
3213
		}
2935
		oo = outgoing;
3214
		oo = outgoing;
2936
		outgoing = outgoing->q_next;
3215
		outgoing = outgoing->q_next;
2937
		ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
3216
		ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
[+20] [20] 24 lines
[+20] [+] static int num_available_members(struct call_queue *q)
2962
			case AST_DEVICE_INUSE:
3241
			case AST_DEVICE_INUSE:
2963
			case AST_DEVICE_BUSY:
3242
			case AST_DEVICE_BUSY:
2964
			case AST_DEVICE_RINGING:
3243
			case AST_DEVICE_RINGING:
2965
			case AST_DEVICE_RINGINUSE:
3244
			case AST_DEVICE_RINGINUSE:
2966
			case AST_DEVICE_ONHOLD:
3245
			case AST_DEVICE_ONHOLD:
2967
				if ((!q->ringinuse) || (!mem->ignorebusy)) {
3246
				if (!mem->ringinuse) {
2968
					break;
3247
					break;
2969
				}
3248
				}
2970
				/* else fall through */
3249
				/* else fall through */
2971
			case AST_DEVICE_NOT_INUSE:
3250
			case AST_DEVICE_NOT_INUSE:
2972
			case AST_DEVICE_UNKNOWN:
3251
			case AST_DEVICE_UNKNOWN:
[+20] [20] 81 lines
[+20] [+] static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
3054
		tmp = ast_str_buffer(buf);
3333
		tmp = ast_str_buffer(buf);
3055

    
   
3334

   
3056
		for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
3335
		for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
3057
			vars[j] = tmp[i];
3336
			vars[j] = tmp[i];
3058

    
   
3337

   
3059
			if (tmp[i + 1] == '\0')
3338
			if (tmp[i + 1] == '\0') {
3060
				break;
3339
				break;

    
   
3340
			}
3061
			if (tmp[i] == '\n') {
3341
			if (tmp[i] == '\n') {
3062
				vars[j++] = '\r';
3342
				vars[j++] = '\r';
3063
				vars[j++] = '\n';
3343
				vars[j++] = '\n';
3064

    
   
3344

   
3065
				ast_copy_string(&(vars[j]), "Variable: ", len - j);
3345
				ast_copy_string(&(vars[j]), "Variable: ", len - j);
3066
				j += 9;
3346
				j += 9;
3067
			}
3347
			}
3068
		}
3348
		}
3069
		if (j > len - 3)
3349
		if (j > len - 3) {
3070
			j = len - 3;
3350
			j = len - 3;

    
   
3351
		}
3071
		vars[j++] = '\r';
3352
		vars[j++] = '\r';
3072
		vars[j++] = '\n';
3353
		vars[j++] = '\n';
3073
		vars[j] = '\0';
3354
		vars[j] = '\0';
3074
	} else {
3355
	} else {
3075
		/* there are no channel variables; leave it blank */
3356
		/* there are no channel variables; leave it blank */
[+20] [20] 26 lines
[+20] [+] static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
3102
	enum ast_device_state newstate;
3383
	enum ast_device_state newstate;
3103

    
   
3384

   
3104
	/* on entry here, we know that tmp->chan == NULL */
3385
	/* on entry here, we know that tmp->chan == NULL */
3105
	if (tmp->member->paused) {
3386
	if (tmp->member->paused) {
3106
		ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
3387
		ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
3107
		if (qe->chan->cdr) {
3388
		if (ast_channel_cdr(qe->chan)) {
3108
			ast_cdr_busy(qe->chan->cdr);
3389
			ast_cdr_busy(ast_channel_cdr(qe->chan));
3109
		}
3390
		}
3110
		tmp->stillgoing = 0;
3391
		tmp->stillgoing = 0;
3111
		return 0;
3392
		return 0;
3112
	}
3393
	}
3113

    
   
3394

   
3114
	if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
3395
	if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
3115
		(!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
3396
		(!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
3116
		ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
3397
		ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
3117
				(tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
3398
				(tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
3118
		if (qe->chan->cdr) {
3399
		if (ast_channel_cdr(qe->chan)) {
3119
			ast_cdr_busy(qe->chan->cdr);
3400
			ast_cdr_busy(ast_channel_cdr(qe->chan));
3120
		}
3401
		}
3121
		tmp->stillgoing = 0;
3402
		tmp->stillgoing = 0;
3122
		(*busies)++;
3403
		(*busies)++;
3123
		return 0;
3404
		return 0;
3124
	}
3405
	}
3125

    
   
3406

   
3126
	if (!qe->parent->ringinuse || !tmp->member->ignorebusy) {
3407
	if (!tmp->member->ringinuse) {
3127
		if (check_state_unknown && (tmp->member->status == AST_DEVICE_UNKNOWN)) {
3408
		if (check_state_unknown && (tmp->member->status == AST_DEVICE_UNKNOWN)) {
3128
			newstate = ast_device_state(tmp->member->interface);
3409
			newstate = ast_device_state(tmp->member->interface);
3129
			if (newstate != tmp->member->status) {
3410
			if (newstate != tmp->member->status) {
3130
				ast_log(LOG_WARNING, "Found a channel matching iterface %s while status was %s changed to %s\n",
3411
				ast_log(LOG_WARNING, "Found a channel matching iterface %s while status was %s changed to %s\n",
3131
					tmp->member->interface, ast_devstate2str(tmp->member->status), ast_devstate2str(newstate));
3412
					tmp->member->interface, ast_devstate2str(tmp->member->status), ast_devstate2str(newstate));
3132
				ast_devstate_changed_literal(newstate, tmp->member->interface);
3413
				ast_devstate_changed_literal(newstate, tmp->member->interface);
3133
			}
3414
			}
3134
		}
3415
		}
3135
		if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
3416
		if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
3136
			ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
3417
			ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
3137
			if (qe->chan->cdr) {
3418
			if (ast_channel_cdr(qe->chan)) {
3138
				ast_cdr_busy(qe->chan->cdr);
3419
				ast_cdr_busy(ast_channel_cdr(qe->chan));
3139
			}
3420
			}
3140
			tmp->stillgoing = 0;
3421
			tmp->stillgoing = 0;
3141
			return 0;
3422
			return 0;
3142
		}
3423
		}
3143
	}
3424
	}
3144

    
   
3425

   
3145
	if (use_weight && compare_weight(qe->parent,tmp->member)) {
3426
	if (use_weight && compare_weight(qe->parent,tmp->member)) {
3146
		ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
3427
		ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
3147
		if (qe->chan->cdr) {
3428
		if (ast_channel_cdr(qe->chan)) {
3148
			ast_cdr_busy(qe->chan->cdr);
3429
			ast_cdr_busy(ast_channel_cdr(qe->chan));
3149
		}
3430
		}
3150
		tmp->stillgoing = 0;
3431
		tmp->stillgoing = 0;
3151
		(*busies)++;
3432
		(*busies)++;
3152
		return 0;
3433
		return 0;
3153
	}
3434
	}
3154

    
   
3435

   
3155
	ast_copy_string(tech, tmp->interface, sizeof(tech));
3436
	ast_copy_string(tech, tmp->interface, sizeof(tech));
3156
	if ((location = strchr(tech, '/')))
3437
	if ((location = strchr(tech, '/'))) {
3157
		*location++ = '\0';
3438
		*location++ = '\0';
3158
	else
3439
	} else {
3159
		location = "";
3440
		location = "";

    
   
3441
	}
3160

    
   
3442

   
3161
	/* Request the peer */
3443
	/* Request the peer */
3162
	tmp->chan = ast_request(tech, qe->chan->nativeformats, qe->chan, location, &status);
3444
	tmp->chan = ast_request(tech, ast_channel_nativeformats(qe->chan), qe->chan, location, &status);
3163
	if (!tmp->chan) {			/* If we can't, just go on to the next call */
3445
	if (!tmp->chan) {			/* If we can't, just go on to the next call */
3164
		if (qe->chan->cdr) {
3446
		if (ast_channel_cdr(qe->chan)) {
3165
			ast_cdr_busy(qe->chan->cdr);
3447
			ast_cdr_busy(ast_channel_cdr(qe->chan));
3166
		}
3448
		}
3167
		tmp->stillgoing = 0;
3449
		tmp->stillgoing = 0;
3168

    
   
3450

   
3169
		ao2_lock(qe->parent);
3451
		ao2_lock(qe->parent);
3170
		update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
3452
		update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
[+20] [20] 6 lines
[+20] static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
3177
	}
3459
	}
3178

    
   
3460

   
3179
	ast_channel_lock_both(tmp->chan, qe->chan);
3461
	ast_channel_lock_both(tmp->chan, qe->chan);
3180

    
   
3462

   
3181
	if (qe->cancel_answered_elsewhere) {
3463
	if (qe->cancel_answered_elsewhere) {
3182
		ast_set_flag(tmp->chan, AST_FLAG_ANSWERED_ELSEWHERE);
3464
		ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
3183
	}
3465
	}
3184
	tmp->chan->appl = "AppQueue";
3466
	ast_channel_appl_set(tmp->chan, "AppQueue");
3185
	tmp->chan->data = "(Outgoing Line)";
3467
	ast_channel_data_set(tmp->chan, "(Outgoing Line)");
3186
	memset(&tmp->chan->whentohangup, 0, sizeof(tmp->chan->whentohangup));
3468
	memset(ast_channel_whentohangup(tmp->chan), 0, sizeof(*ast_channel_whentohangup(tmp->chan)));
3187

    
   
3469

   
3188
	/* If the new channel has no callerid, try to guess what it should be */
3470
	/* If the new channel has no callerid, try to guess what it should be */
3189
	if (!tmp->chan->caller.id.number.valid) {
3471
	if (!ast_channel_caller(tmp->chan)->id.number.valid) {
3190
		if (qe->chan->connected.id.number.valid) {
3472
		if (ast_channel_connected(qe->chan)->id.number.valid) {
3191
			struct ast_party_caller caller;
3473
			struct ast_party_caller caller;
3192

    
   
3474

   
3193
			ast_party_caller_set_init(&caller, &tmp->chan->caller);
3475
			ast_party_caller_set_init(&caller, ast_channel_caller(tmp->chan));
3194
			caller.id = qe->chan->connected.id;
3476
			caller.id = ast_channel_connected(qe->chan)->id;
3195
			caller.ani = qe->chan->connected.ani;
3477
			caller.ani = ast_channel_connected(qe->chan)->ani;
3196
			ast_channel_set_caller_event(tmp->chan, &caller, NULL);
3478
			ast_channel_set_caller_event(tmp->chan, &caller, NULL);
3197
		} else if (!ast_strlen_zero(qe->chan->dialed.number.str)) {
3479
		} else if (!ast_strlen_zero(ast_channel_dialed(qe->chan)->number.str)) {
3198
			ast_set_callerid(tmp->chan, qe->chan->dialed.number.str, NULL, NULL);
3480
			ast_set_callerid(tmp->chan, ast_channel_dialed(qe->chan)->number.str, NULL, NULL);
3199
		} else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
3481
		} else if (!ast_strlen_zero(S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)))) {
3200
			ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL); 
3482
			ast_set_callerid(tmp->chan, S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)), NULL, NULL); 
3201
		}
3483
		}
3202
		tmp->dial_callerid_absent = 1;
3484
		tmp->dial_callerid_absent = 1;
3203
	}
3485
	}
3204

    
   
3486

   
3205
	ast_party_redirecting_copy(&tmp->chan->redirecting, &qe->chan->redirecting);
3487
	ast_party_redirecting_copy(ast_channel_redirecting(tmp->chan), ast_channel_redirecting(qe->chan));
3206

    
   
3488

   
3207
	tmp->chan->dialed.transit_network_select = qe->chan->dialed.transit_network_select;
3489
	ast_channel_dialed(tmp->chan)->transit_network_select = ast_channel_dialed(qe->chan)->transit_network_select;
3208

    
   
3490

   
3209
	ast_connected_line_copy_from_caller(&tmp->chan->connected, &qe->chan->caller);
3491
	ast_connected_line_copy_from_caller(ast_channel_connected(tmp->chan), ast_channel_caller(qe->chan));
3210

    
   
3492

   
3211
	/* Inherit specially named variables from parent channel */
3493
	/* Inherit specially named variables from parent channel */
3212
	ast_channel_inherit_variables(qe->chan, tmp->chan);
3494
	ast_channel_inherit_variables(qe->chan, tmp->chan);
3213
	ast_channel_datastore_inherit(qe->chan, tmp->chan);
3495
	ast_channel_datastore_inherit(qe->chan, tmp->chan);
3214

    
   
3496

   
3215
	/* Presense of ADSI CPE on outgoing channel follows ours */
3497
	/* Presense of ADSI CPE on outgoing channel follows ours */
3216
	tmp->chan->adsicpe = qe->chan->adsicpe;
3498
	ast_channel_adsicpe_set(tmp->chan, ast_channel_adsicpe(qe->chan));
3217

    
   
3499

   
3218
	/* Inherit context and extension */
3500
	/* Inherit context and extension */
3219
	macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
3501
	macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
3220
	ast_string_field_set(tmp->chan, dialcontext, ast_strlen_zero(macrocontext) ? qe->chan->context : macrocontext);
3502
	ast_channel_dialcontext_set(tmp->chan, ast_strlen_zero(macrocontext) ? ast_channel_context(qe->chan) : macrocontext);
3221
	macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
3503
	macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
3222
	if (!ast_strlen_zero(macroexten))
3504
	if (!ast_strlen_zero(macroexten)) {
3223
		ast_copy_string(tmp->chan->exten, macroexten, sizeof(tmp->chan->exten));
3505
		ast_channel_exten_set(tmp->chan, macroexten);
3224
	else
3506
	} else {
3225
		ast_copy_string(tmp->chan->exten, qe->chan->exten, sizeof(tmp->chan->exten));
3507
		ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan));

    
   
3508
	}
3226
	if (ast_cdr_isset_unanswered()) {
3509
	if (ast_cdr_isset_unanswered()) {
3227
		/* they want to see the unanswered dial attempts! */
3510
		/* they want to see the unanswered dial attempts! */
3228
		/* set up the CDR fields on all the CDRs to give sensical information */
3511
		/* set up the CDR fields on all the CDRs to give sensical information */
3229
		ast_cdr_setdestchan(tmp->chan->cdr, tmp->chan->name);
3512
		ast_cdr_setdestchan(ast_channel_cdr(tmp->chan), ast_channel_name(tmp->chan));
3230
		strcpy(tmp->chan->cdr->clid, qe->chan->cdr->clid);
3513
		strcpy(ast_channel_cdr(tmp->chan)->clid, ast_channel_cdr(qe->chan)->clid);
3231
		strcpy(tmp->chan->cdr->channel, qe->chan->cdr->channel);
3514
		strcpy(ast_channel_cdr(tmp->chan)->channel, ast_channel_cdr(qe->chan)->channel);
3232
		strcpy(tmp->chan->cdr->src, qe->chan->cdr->src);
3515
		strcpy(ast_channel_cdr(tmp->chan)->src, ast_channel_cdr(qe->chan)->src);
3233
		strcpy(tmp->chan->cdr->dst, qe->chan->exten);
3516
		strcpy(ast_channel_cdr(tmp->chan)->dst, ast_channel_exten(qe->chan));
3234
		strcpy(tmp->chan->cdr->dcontext, qe->chan->context);
3517
		strcpy(ast_channel_cdr(tmp->chan)->dcontext, ast_channel_context(qe->chan));
3235
		strcpy(tmp->chan->cdr->lastapp, qe->chan->cdr->lastapp);
3518
		strcpy(ast_channel_cdr(tmp->chan)->lastapp, ast_channel_cdr(qe->chan)->lastapp);
3236
		strcpy(tmp->chan->cdr->lastdata, qe->chan->cdr->lastdata);
3519
		strcpy(ast_channel_cdr(tmp->chan)->lastdata, ast_channel_cdr(qe->chan)->lastdata);
3237
		tmp->chan->cdr->amaflags = qe->chan->cdr->amaflags;
3520
		ast_channel_cdr(tmp->chan)->amaflags = ast_channel_cdr(qe->chan)->amaflags;
3238
		strcpy(tmp->chan->cdr->accountcode, qe->chan->cdr->accountcode);
3521
		strcpy(ast_channel_cdr(tmp->chan)->accountcode, ast_channel_cdr(qe->chan)->accountcode);
3239
		strcpy(tmp->chan->cdr->userfield, qe->chan->cdr->userfield);
3522
		strcpy(ast_channel_cdr(tmp->chan)->userfield, ast_channel_cdr(qe->chan)->userfield);
3240
	}
3523
	}
3241

    
   
3524

   
3242
	ast_channel_unlock(tmp->chan);
3525
	ast_channel_unlock(tmp->chan);
3243
	ast_channel_unlock(qe->chan);
3526
	ast_channel_unlock(qe->chan);
3244

    
   
3527

   

    
   
3528
	ao2_lock(tmp->member);

    
   
3529
	update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));

    
   
3530
	if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {

    
   
3531
		ast_verb(1, "Member %s is busy, cannot dial", tmp->member->interface);
Moved from 5003

    
   
3532
		res = -1;
Moved from 5004

    
   
3533
	}

    
   
3534
	else {
3245
	/* Place the call, but don't wait on the answer */
3535
		/* Place the call, but don't wait on the answer */
3246
	if ((res = ast_call(tmp->chan, location, 0))) {
3536
		res = ast_call(tmp->chan, location, 0);

    
   
3537
	}

    
   
3538
	ao2_unlock(tmp->member);

    
   
3539
	if (res) {
3247
		/* Again, keep going even if there's an error */
3540
		/* Again, keep going even if there's an error */
3248
		ast_debug(1, "ast call on peer returned %d\n", res);

   
3249
		ast_verb(3, "Couldn't call %s\n", tmp->interface);
3541
		ast_verb(3, "Couldn't call %s\n", tmp->interface);
3250
		do_hang(tmp);
3542
		do_hang(tmp);
3251
		(*busies)++;
3543
		(*busies)++;
3252
		update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
3544
		update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
3253
		return 0;
3545
		return 0;
3254
	} else if (qe->parent->eventwhencalled) {
3546
	} else if (qe->parent->eventwhencalled) {
3255
		char vars[2048];
3547
		char vars[2048];
3256

    
   
3548

   
3257
		ast_channel_lock_both(tmp->chan, qe->chan);
3549
		ast_channel_lock_both(tmp->chan, qe->chan);
3258

    
   
3550

   

    
   
3551
		/*** DOCUMENTATION

    
   
3552
		<managerEventInstance>

    
   
3553
			<synopsis>Raised when an Agent is notified of a member in the queue.</synopsis>

    
   
3554
			<syntax>

    
   
3555
				<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />

    
   
3556
				<parameter name="AgentCalled">

    
   
3557
					<para>The agent's technology or location.</para>

    
   
3558
				</parameter>

    
   
3559
				<parameter name="AgentName">

    
   
3560
					<para>The name of the agent.</para>

    
   
3561
				</parameter>

    
   
3562
				<parameter name="Variable" required="no" multiple="yes">

    
   
3563
					<para>Optional channel variables from the ChannelCalling channel</para>

    
   
3564
				</parameter>

    
   
3565
			</syntax>

    
   
3566
			<see-also>

    
   
3567
				<ref type="managerEvent">AgentRingNoAnswer</ref>

    
   
3568
				<ref type="managerEvent">AgentComplete</ref>

    
   
3569
				<ref type="managerEvent">AgentConnect</ref>

    
   
3570
			</see-also>

    
   
3571
		</managerEventInstance>

    
   
3572
		***/
3259
		manager_event(EVENT_FLAG_AGENT, "AgentCalled",
3573
		manager_event(EVENT_FLAG_AGENT, "AgentCalled",
3260
			"Queue: %s\r\n"
3574
			"Queue: %s\r\n"
3261
			"AgentCalled: %s\r\n"
3575
			"AgentCalled: %s\r\n"
3262
			"AgentName: %s\r\n"
3576
			"AgentName: %s\r\n"
3263
			"ChannelCalling: %s\r\n"
3577
			"ChannelCalling: %s\r\n"
[+20] [20] 5 lines
[+20] static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
3269
			"Context: %s\r\n"
3583
			"Context: %s\r\n"
3270
			"Extension: %s\r\n"
3584
			"Extension: %s\r\n"
3271
			"Priority: %d\r\n"
3585
			"Priority: %d\r\n"
3272
			"Uniqueid: %s\r\n"
3586
			"Uniqueid: %s\r\n"
3273
			"%s",
3587
			"%s",
3274
			qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
3588
			qe->parent->name, tmp->interface, tmp->member->membername, ast_channel_name(qe->chan), ast_channel_name(tmp->chan),
3275
			S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),
3589
			S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
3276
			S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
3590
			S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
3277
			S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),
3591
			S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
3278
			S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
3592
			S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
3279
			qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
3593
			ast_channel_context(qe->chan), ast_channel_exten(qe->chan), ast_channel_priority(qe->chan), ast_channel_uniqueid(qe->chan),
3280
			qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3594
			qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3281

    
   
3595

   
3282
		ast_channel_unlock(tmp->chan);
3596
		ast_channel_unlock(tmp->chan);
3283
		ast_channel_unlock(qe->chan);
3597
		ast_channel_unlock(qe->chan);
3284

    
   
3598

   
[+20] [20] 122 lines
[+20] [+] static int say_periodic_announcement(struct queue_ent *qe, int ringing)
3407

    
   
3721

   
3408
	/* Get the current time */
3722
	/* Get the current time */
3409
	time(&now);
3723
	time(&now);
3410

    
   
3724

   
3411
	/* Check to see if it is time to announce */
3725
	/* Check to see if it is time to announce */
3412
	if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
3726
	if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency) {
3413
		return 0;
3727
		return 0;

    
   
3728
	}
3414

    
   
3729

   
3415
	/* Stop the music on hold so we can play our own file */
3730
	/* Stop the music on hold so we can play our own file */
3416
	if (ringing)
3731
	if (ringing) {
3417
		ast_indicate(qe->chan,-1);
3732
		ast_indicate(qe->chan,-1);
3418
	else
3733
	} else {
3419
		ast_moh_stop(qe->chan);
3734
		ast_moh_stop(qe->chan);

    
   
3735
	}
3420

    
   
3736

   
3421
	ast_verb(3, "Playing periodic announcement\n");
3737
	ast_verb(3, "Playing periodic announcement\n");
3422
	
3738
	
3423
	if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
3739
	if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
3424
		qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
3740
		qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
3425
	} else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce || 
3741
	} else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce || 
3426
		ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
3742
		ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
3427
		qe->last_periodic_announce_sound = 0;
3743
		qe->last_periodic_announce_sound = 0;
3428
	}
3744
	}
3429
	
3745
	
3430
	/* play the announcement */
3746
	/* play the announcement */
3431
	res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
3747
	res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
3432

    
   
3748

   
3433
	if (res > 0 && !valid_exit(qe, res))
3749
	if (res > 0 && !valid_exit(qe, res)) {
3434
		res = 0;
3750
		res = 0;

    
   
3751
	}
3435

    
   
3752

   
3436
	/* Resume Music on Hold if the caller is going to stay in the queue */
3753
	/* Resume Music on Hold if the caller is going to stay in the queue */
3437
	if (!res) {
3754
	if (!res) {
3438
		if (ringing)
3755
		if (ringing) {
3439
			ast_indicate(qe->chan, AST_CONTROL_RINGING);
3756
			ast_indicate(qe->chan, AST_CONTROL_RINGING);
3440
		else
3757
		} else {
3441
			ast_moh_start(qe->chan, qe->moh, NULL);
3758
			ast_moh_start(qe->chan, qe->moh, NULL);
3442
	}
3759
		}

    
   
3760
	}
3443

    
   
3761

   
3444
	/* update last_periodic_announce_time */
3762
	/* update last_periodic_announce_time */
3445
	if (qe->parent->relativeperiodicannounce)
3763
	if (qe->parent->relativeperiodicannounce) {
3446
		time(&qe->last_periodic_announce_time);
3764
		time(&qe->last_periodic_announce_time);
3447
	else
3765
	} else {
3448
		qe->last_periodic_announce_time = now;
3766
		qe->last_periodic_announce_time = now;

    
   
3767
	}
3449

    
   
3768

   
3450
	/* Update the current periodic announcement to the next announcement */
3769
	/* Update the current periodic announcement to the next announcement */
3451
	if (!qe->parent->randomperiodicannounce) {
3770
	if (!qe->parent->randomperiodicannounce) {
3452
		qe->last_periodic_announce_sound++;
3771
		qe->last_periodic_announce_sound++;
3453
	}
3772
	}
[+20] [20] 4 lines
[+20] static int say_periodic_announcement(struct queue_ent *qe, int ringing)
3458
/*! \brief Record that a caller gave up on waiting in queue */
3777
/*! \brief Record that a caller gave up on waiting in queue */
3459
static void record_abandoned(struct queue_ent *qe)
3778
static void record_abandoned(struct queue_ent *qe)
3460
{
3779
{
3461
	set_queue_variables(qe->parent, qe->chan);
3780
	set_queue_variables(qe->parent, qe->chan);
3462
	ao2_lock(qe->parent);
3781
	ao2_lock(qe->parent);

    
   
3782
	/*** DOCUMENTATION

    
   
3783
	<managerEventInstance>

    
   
3784
		<synopsis>Raised when an caller abandons the queue.</synopsis>

    
   
3785
		<syntax>

    
   
3786
			<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />

    
   
3787
			<xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Position'])" />

    
   
3788
			<parameter name="OriginalPosition">

    
   
3789
				<para>The channel's original position in the queue.</para>

    
   
3790
			</parameter>

    
   
3791
			<parameter name="HoldTime">

    
   
3792
				<para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>

    
   
3793
			</parameter>

    
   
3794
		</syntax>

    
   
3795
	</managerEventInstance>

    
   
3796
	***/
3463
	manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
3797
	manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
3464
		"Queue: %s\r\n"
3798
		"Queue: %s\r\n"
3465
		"Uniqueid: %s\r\n"
3799
		"Uniqueid: %s\r\n"
3466
		"Position: %d\r\n"
3800
		"Position: %d\r\n"
3467
		"OriginalPosition: %d\r\n"
3801
		"OriginalPosition: %d\r\n"
3468
		"HoldTime: %d\r\n",
3802
		"HoldTime: %d\r\n",
3469
		qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
3803
		qe->parent->name, ast_channel_uniqueid(qe->chan), qe->pos, qe->opos, (int)(time(NULL) - qe->start));
3470

    
   
3804

   
3471
	qe->parent->callsabandoned++;
3805
	qe->parent->callsabandoned++;
3472
	ao2_unlock(qe->parent);
3806
	ao2_unlock(qe->parent);
3473
}
3807
}
3474

    
   
3808

   
3475
/*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
3809
/*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
3476
static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int pause)
3810
static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int autopause)
3477
{
3811
{
3478
	ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
3812
	ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
3479

    
   
3813

   
3480
	/* Stop ringing, and resume MOH if specified */
3814
	/* Stop ringing, and resume MOH if specified */
3481
	if (qe->ring_when_ringing) {
3815
	if (qe->ring_when_ringing) {
3482
		ast_indicate(qe->chan, -1);
3816
		ast_indicate(qe->chan, -1);
3483
		ast_moh_start(qe->chan, qe->moh, NULL);
3817
		ast_moh_start(qe->chan, qe->moh, NULL);
3484
	}
3818
	}
3485

    
   
3819

   
3486
	if (qe->parent->eventwhencalled) {
3820
	if (qe->parent->eventwhencalled) {
3487
		char vars[2048];
3821
		char vars[2048];
3488

    
   
3822
		/*** DOCUMENTATION

    
   
3823
		<managerEventInstance>

    
   
3824
			<synopsis>Raised when an agent is notified of a member in the queue and fails to answer.</synopsis>

    
   
3825
			<syntax>

    
   
3826
				<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />

    
   
3827
				<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />

    
   
3828
				<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />

    
   
3829
				<parameter name="Member">

    
   
3830
					<para>The queue member's channel technology or location.</para>

    
   
3831
				</parameter>

    
   
3832
				<parameter name="RingTime">

    
   
3833
					<para>The time the agent was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>

    
   
3834
				</parameter>

    
   
3835
			</syntax>

    
   
3836
			<see-also>

    
   
3837
				<ref type="managerEvent">AgentCalled</ref>

    
   
3838
			</see-also>

    
   
3839
		</managerEventInstance>

    
   
3840
		***/
3489
		manager_event(EVENT_FLAG_AGENT, "AgentRingNoAnswer",
3841
		manager_event(EVENT_FLAG_AGENT, "AgentRingNoAnswer",
3490
						"Queue: %s\r\n"
3842
						"Queue: %s\r\n"
3491
						"Uniqueid: %s\r\n"
3843
						"Uniqueid: %s\r\n"
3492
						"Channel: %s\r\n"
3844
						"Channel: %s\r\n"
3493
						"Member: %s\r\n"
3845
						"Member: %s\r\n"
3494
						"MemberName: %s\r\n"
3846
						"MemberName: %s\r\n"
3495
						"Ringtime: %d\r\n"
3847
						"RingTime: %d\r\n"
3496
						"%s",
3848
						"%s",
3497
						qe->parent->name,
3849
						qe->parent->name,
3498
						qe->chan->uniqueid,
3850
						ast_channel_uniqueid(qe->chan),
3499
						qe->chan->name,
3851
						ast_channel_name(qe->chan),
3500
						interface,
3852
						interface,
3501
						membername,
3853
						membername,
3502
						rnatime,
3854
						rnatime,
3503
						qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3855
						qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
3504
	}
3856
	}
3505
	ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
3857
	ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), membername, "RINGNOANSWER", "%d", rnatime);
3506
	if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && pause) {
3858
	if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && autopause) {
3507
		if (qe->parent->autopausedelay > 0) {
3859
		if (qe->parent->autopausedelay > 0) {
3508
			struct member *mem;
3860
			struct member *mem;
3509
			ao2_lock(qe->parent);
3861
			ao2_lock(qe->parent);
3510
			if ((mem = interface_exists(qe->parent, interface))) {
3862
			if ((mem = interface_exists(qe->parent, interface))) {
3511
				time_t idletime = time(&idletime)-mem->lastcall;
3863
				time_t idletime = time(&idletime)-mem->lastcall;
[+20] [20] 36 lines
[+20] static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int pause) [+] static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int autopause)
3548
 * \param[in] to the amount of time (in milliseconds) to wait for a response
3900
 * \param[in] to the amount of time (in milliseconds) to wait for a response
3549
 * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
3901
 * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
3550
 * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
3902
 * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
3551
 * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
3903
 * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
3552
 * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
3904
 * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
3553
 * \param[in] update_connectedline Allow connected line and redirecting updates to pass through.

   
3554
 *
3905
 *
3555
 * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
3906
 * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
3556
 */
3907
 */
3557
static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline)
3908
static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3558
{
3909
{
3559
	const char *queue = qe->parent->name;
3910
	const char *queue = qe->parent->name;
3560
	struct callattempt *o, *start = NULL, *prev = NULL;
3911
	struct callattempt *o, *start = NULL, *prev = NULL;
3561
	int res;

   
3562
	int status;
3912
	int status;
3563
	int numbusies = prebusies;
3913
	int numbusies = prebusies;
3564
	int numnochan = 0;
3914
	int numnochan = 0;
3565
	int stillgoing = 0;
3915
	int stillgoing = 0;
3566
	int orig = *to;
3916
	int orig = *to;
[+20] [20] 12 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3579
	char *inchan_name;
3929
	char *inchan_name;
3580

    
   
3930

   
3581
	ast_party_connected_line_init(&connected_caller);
3931
	ast_party_connected_line_init(&connected_caller);
3582

    
   
3932

   
3583
	ast_channel_lock(qe->chan);
3933
	ast_channel_lock(qe->chan);
3584
	inchan_name = ast_strdupa(qe->chan->name);
3934
	inchan_name = ast_strdupa(ast_channel_name(qe->chan));
3585
	ast_channel_unlock(qe->chan);
3935
	ast_channel_unlock(qe->chan);
3586

    
   
3936

   
3587
	starttime = (long) time(NULL);
3937
	starttime = (long) time(NULL);
3588
#ifdef HAVE_EPOLL
3938
#ifdef HAVE_EPOLL
3589
	for (epollo = outgoing; epollo; epollo = epollo->q_next) {
3939
	for (epollo = outgoing; epollo; epollo = epollo->q_next) {
3590
		if (epollo->chan)
3940
		if (epollo->chan) {
3591
			ast_poll_channel_add(in, epollo->chan);
3941
			ast_poll_channel_add(in, epollo->chan);
3592
	}
3942
		}

    
   
3943
	}
3593
#endif
3944
#endif
3594
	
3945
	
3595
	while (*to && !peer) {
3946
	while (*to && !peer) {
3596
		int numlines, retry, pos = 1;
3947
		int numlines, retry, pos = 1;
3597
		struct ast_channel *watchers[AST_MAX_WATCHERS];
3948
		struct ast_channel *watchers[AST_MAX_WATCHERS];
[+20] [20] 7 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3605
					stillgoing = 1;
3956
					stillgoing = 1;
3606
					if (o->chan) {
3957
					if (o->chan) {
3607
						if (pos < AST_MAX_WATCHERS) {
3958
						if (pos < AST_MAX_WATCHERS) {
3608
							watchers[pos++] = o->chan;
3959
							watchers[pos++] = o->chan;
3609
						}
3960
						}
3610
						if (!start)
3961
						if (!start) {
3611
							start = o;
3962
							start = o;
3612
						else
3963
						} else {
3613
							prev->call_next = o;
3964
							prev->call_next = o;

    
   
3965
						}
3614
						prev = o;
3966
						prev = o;
3615
					}
3967
					}
3616
				}
3968
				}
3617
				numlines++;
3969
				numlines++;
3618
			}
3970
			}
3619
			if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
3971
			if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
3620
				(qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */)
3972
				(qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */) {
3621
				break;
3973
				break;

    
   
3974
			}
3622
			/* On "ringall" strategy we only move to the next penalty level
3975
			/* On "ringall" strategy we only move to the next penalty level
3623
			   when *all* ringing phones are done in the current penalty level */
3976
			   when *all* ringing phones are done in the current penalty level */
3624
			ring_one(qe, outgoing, &numbusies);
3977
			ring_one(qe, outgoing, &numbusies);
3625
			/* and retry... */
3978
			/* and retry... */
3626
		}
3979
		}
[+20] [20] 10 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3637
		/* Poll for events from both the incoming channel as well as any outgoing channels */
3990
		/* Poll for events from both the incoming channel as well as any outgoing channels */
3638
		winner = ast_waitfor_n(watchers, pos, to);
3991
		winner = ast_waitfor_n(watchers, pos, to);
3639

    
   
3992

   
3640
		/* Service all of the outgoing channels */
3993
		/* Service all of the outgoing channels */
3641
		for (o = start; o; o = o->call_next) {
3994
		for (o = start; o; o = o->call_next) {
3642
			/* We go with a static buffer here instead of using ast_strdupa. Using
3995
			/* We go with a fixed buffer here instead of using ast_strdupa. Using
3643
			 * ast_strdupa in a loop like this one can cause a stack overflow
3996
			 * ast_strdupa in a loop like this one can cause a stack overflow
3644
			 */
3997
			 */
3645
			char ochan_name[AST_CHANNEL_NAME];
3998
			char ochan_name[AST_CHANNEL_NAME];

    
   
3999

   
3646
			if (o->chan) {
4000
			if (o->chan) {
3647
				ast_channel_lock(o->chan);
4001
				ast_channel_lock(o->chan);
3648
				ast_copy_string(ochan_name, o->chan->name, sizeof(ochan_name));
4002
				ast_copy_string(ochan_name, ast_channel_name(o->chan), sizeof(ochan_name));
3649
				ast_channel_unlock(o->chan);
4003
				ast_channel_unlock(o->chan);
3650
			}
4004
			}
3651
			if (o->stillgoing && (o->chan) &&  (o->chan->_state == AST_STATE_UP)) {
4005
			if (o->stillgoing && (o->chan) &&  (ast_channel_state(o->chan) == AST_STATE_UP)) {
3652
				if (!peer) {
4006
				if (!peer) {
3653
					ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
4007
					ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
3654
					if (update_connectedline) {
4008
					if (!o->block_connected_update) {
3655
						if (o->pending_connected_update) {
4009
						if (o->pending_connected_update) {
3656
							if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
4010
							if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&

    
   
4011
								ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
3657
								ast_channel_update_connected_line(in, &o->connected, NULL);
4012
								ast_channel_update_connected_line(in, &o->connected, NULL);
3658
							}
4013
							}
3659
						} else if (!o->dial_callerid_absent) {
4014
						} else if (!o->dial_callerid_absent) {
3660
							ast_channel_lock(o->chan);
4015
							ast_channel_lock(o->chan);
3661
							ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
4016
							ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
3662
							ast_channel_unlock(o->chan);
4017
							ast_channel_unlock(o->chan);
3663
							connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
4018
							connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;

    
   
4019
							if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&

    
   
4020
								ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
3664
							ast_channel_update_connected_line(in, &connected_caller, NULL);
4021
								ast_channel_update_connected_line(in, &connected_caller, NULL);

    
   
4022
							}
3665
							ast_party_connected_line_free(&connected_caller);
4023
							ast_party_connected_line_free(&connected_caller);
3666
						}
4024
						}
3667
					}
4025
					}
3668
					if (o->aoc_s_rate_list) {
4026
					if (o->aoc_s_rate_list) {
3669
						size_t encoded_size;
4027
						size_t encoded_size;
[+20] [20] 8 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3678
			} else if (o->chan && (o->chan == winner)) {
4036
			} else if (o->chan && (o->chan == winner)) {
3679

    
   
4037

   
3680
				ast_copy_string(on, o->member->interface, sizeof(on));
4038
				ast_copy_string(on, o->member->interface, sizeof(on));
3681
				ast_copy_string(membername, o->member->membername, sizeof(membername));
4039
				ast_copy_string(membername, o->member->membername, sizeof(membername));
3682

    
   
4040

   
3683
				if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
4041
				/* Before processing channel, go ahead and check for forwarding */
3684
					ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, o->chan->call_forward);
4042
				if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {

    
   
4043
					ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
3685
					numnochan++;
4044
					numnochan++;
3686
					do_hang(o);
4045
					do_hang(o);
3687
					winner = NULL;
4046
					winner = NULL;
3688
					continue;
4047
					continue;
3689
				} else if (!ast_strlen_zero(o->chan->call_forward)) {
4048
				} else if (!ast_strlen_zero(ast_channel_call_forward(o->chan))) {
3690
					struct ast_channel *original = o->chan;
4049
					struct ast_channel *original = o->chan;
3691
					char tmpchan[256];
4050
					char tmpchan[256];
3692
					char *stuff;
4051
					char *stuff;
3693
					char *tech;
4052
					char *tech;
3694

    
   
4053

   
3695
					ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
4054
					ast_copy_string(tmpchan, ast_channel_call_forward(o->chan), sizeof(tmpchan));
3696
					if ((stuff = strchr(tmpchan, '/'))) {
4055
					if ((stuff = strchr(tmpchan, '/'))) {
3697
						*stuff++ = '\0';
4056
						*stuff++ = '\0';
3698
						tech = tmpchan;
4057
						tech = tmpchan;
3699
					} else {
4058
					} else {
3700
						snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
4059
						snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), ast_channel_context(o->chan));
3701
						stuff = tmpchan;
4060
						stuff = tmpchan;
3702
						tech = "Local";
4061
						tech = "Local";
3703
					}
4062
					}

    
   
4063
					if (!strcasecmp(tech, "Local")) {

    
   
4064
						/*

    
   
4065
						 * Drop the connected line update block for local channels since

    
   
4066
						 * this is going to run dialplan and the user can change his

    
   
4067
						 * mind about what connected line information he wants to send.

    
   
4068
						 */

    
   
4069
						o->block_connected_update = 0;

    
   
4070
					}
3704

    
   
4071

   
3705
					ast_cel_report_event(in, AST_CEL_FORWARD, NULL, o->chan->call_forward, NULL);
4072
					ast_cel_report_event(in, AST_CEL_FORWARD, NULL, ast_channel_call_forward(o->chan), NULL);
3706

    
   
4073

   
3707
					/* Before processing channel, go ahead and check for forwarding */

   
3708
					ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
4074
					ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
3709
					/* Setup parameters */
4075
					/* Setup parameters */
3710
					o->chan = ast_request(tech, in->nativeformats, in, stuff, &status);
4076
					o->chan = ast_request(tech, ast_channel_nativeformats(in), in, stuff, &status);
3711
					if (!o->chan) {
4077
					if (!o->chan) {
3712
						ast_log(LOG_NOTICE,
4078
						ast_log(LOG_NOTICE,
3713
							"Forwarding failed to create channel to dial '%s/%s'\n",
4079
							"Forwarding failed to create channel to dial '%s/%s'\n",
3714
							tech, stuff);
4080
							tech, stuff);
3715
						o->stillgoing = 0;
4081
						o->stillgoing = 0;
3716
						numnochan++;
4082
						numnochan++;
3717
					} else {
4083
					} else {
3718
						struct ast_party_redirecting redirecting;
4084
						ast_channel_lock_both(o->chan, original);

    
   
4085
						ast_party_redirecting_copy(ast_channel_redirecting(o->chan),

    
   
4086
							ast_channel_redirecting(original));

    
   
4087
						ast_channel_unlock(o->chan);

    
   
4088
						ast_channel_unlock(original);
3719

    
   
4089

   
3720
						ast_channel_lock_both(o->chan, in);
4090
						ast_channel_lock_both(o->chan, in);
3721
						ast_channel_inherit_variables(in, o->chan);
4091
						ast_channel_inherit_variables(in, o->chan);
3722
						ast_channel_datastore_inherit(in, o->chan);
4092
						ast_channel_datastore_inherit(in, o->chan);
3723

    
   
4093

   
3724
						ast_string_field_set(o->chan, accountcode, in->accountcode);
4094
						if (o->pending_connected_update) {

    
   
4095
							/*

    
   
4096
							 * Re-seed the callattempt's connected line information with

    
   
4097
							 * previously acquired connected line info from the queued

    
   
4098
							 * channel.  The previously acquired connected line info could

    
   
4099
							 * have been set through the CONNECTED_LINE dialplan function.

    
   
4100
							 */

    
   
4101
							o->pending_connected_update = 0;

    
   
4102
							ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));

    
   
4103
						}

    
   
4104

   

    
   
4105
						ast_channel_accountcode_set(o->chan, ast_channel_accountcode(in));
3725

    
   
4106

   
3726
						ast_channel_set_redirecting(o->chan, &original->redirecting, NULL);
4107
						if (!ast_channel_redirecting(o->chan)->from.number.valid
3727
						if (!o->chan->redirecting.from.number.valid
4108
							|| ast_strlen_zero(ast_channel_redirecting(o->chan)->from.number.str)) {
3728
							|| ast_strlen_zero(o->chan->redirecting.from.number.str)) {

   
3729
							/*
4109
							/*
3730
							 * The call was not previously redirected so it is
4110
							 * The call was not previously redirected so it is
3731
							 * now redirected from this number.
4111
							 * now redirected from this number.
3732
							 */
4112
							 */
3733
							ast_party_number_free(&o->chan->redirecting.from.number);
4113
							ast_party_number_free(&ast_channel_redirecting(o->chan)->from.number);
3734
							ast_party_number_init(&o->chan->redirecting.from.number);
4114
							ast_party_number_init(&ast_channel_redirecting(o->chan)->from.number);
3735
							o->chan->redirecting.from.number.valid = 1;
4115
							ast_channel_redirecting(o->chan)->from.number.valid = 1;
3736
							o->chan->redirecting.from.number.str =
4116
							ast_channel_redirecting(o->chan)->from.number.str =
3737
								ast_strdup(S_OR(in->macroexten, in->exten));
4117
								ast_strdup(S_OR(ast_channel_macroexten(in), ast_channel_exten(in)));
3738
						}
4118
						}
3739

    
   
4119

   
3740
						o->chan->dialed.transit_network_select = in->dialed.transit_network_select;
4120
						ast_channel_dialed(o->chan)->transit_network_select = ast_channel_dialed(in)->transit_network_select;

    
   
4121

   

    
   
4122
						o->dial_callerid_absent = !ast_channel_caller(o->chan)->id.number.valid

    
   
4123
							|| ast_strlen_zero(ast_channel_caller(o->chan)->id.number.str);

    
   
4124
						ast_connected_line_copy_from_caller(ast_channel_connected(o->chan),

    
   
4125
							ast_channel_caller(in));
3741

    
   
4126

   
3742
						ast_party_caller_copy(&o->chan->caller, &in->caller);
4127
						ast_channel_unlock(in);
3743
						ast_party_connected_line_copy(&o->chan->connected, &original->connected);
4128
						if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL

    
   
4129
							&& !o->block_connected_update) {

    
   
4130
							struct ast_party_redirecting redirecting;
3744

    
   
4131

   
3745
						/*
4132
							/*

    
   
4133
							 * Redirecting updates to the caller make sense only on single

    
   
4134
							 * call at a time strategies.

    
   
4135
							 *
3746
						 * We must unlock o->chan before calling
4136
							 * We must unlock o->chan before calling
3747
						 * ast_channel_redirecting_macro, because we put o->chan into
4137
							 * ast_channel_redirecting_macro, because we put o->chan into
3748
						 * autoservice there.  That is pretty much a guaranteed
4138
							 * autoservice there.  That is pretty much a guaranteed
3749
						 * deadlock.  This is why the handling of o->chan's lock may
4139
							 * deadlock.  This is why the handling of o->chan's lock may
3750
						 * seem a bit unusual here.
4140
							 * seem a bit unusual here.
3751
						 */
4141
							 */
3752
						ast_party_redirecting_init(&redirecting);
4142
							ast_party_redirecting_init(&redirecting);
3753
						ast_party_redirecting_copy(&redirecting, &o->chan->redirecting);
4143
							ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(o->chan));
3754
						ast_channel_unlock(o->chan);
4144
							ast_channel_unlock(o->chan);
3755
						res = ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0);
4145
							if (ast_channel_redirecting_sub(o->chan, in, &redirecting, 0) &&
3756
						if (res) {
4146
								ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0)) {
3757
							ast_channel_update_redirecting(in, &redirecting, NULL);
4147
								ast_channel_update_redirecting(in, &redirecting, NULL);
3758
						}
4148
							}
3759
						ast_party_redirecting_free(&redirecting);
4149
							ast_party_redirecting_free(&redirecting);
3760
						ast_channel_unlock(in);
4150
						} else {
3761

    
   
4151
							ast_channel_unlock(o->chan);
3762
						update_connectedline = 1;
4152
						}
3763

    
   
4153

   
3764
						if (ast_call(o->chan, stuff, 0)) {
4154
						if (ast_call(o->chan, stuff, 0)) {
3765
							ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
4155
							ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
3766
								tech, stuff);
4156
								tech, stuff);
3767
							do_hang(o);
4157
							do_hang(o);
[+20] [20] 10 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3778
						switch (f->subclass.integer) {
4168
						switch (f->subclass.integer) {
3779
						case AST_CONTROL_ANSWER:
4169
						case AST_CONTROL_ANSWER:
3780
							/* This is our guy if someone answered. */
4170
							/* This is our guy if someone answered. */
3781
							if (!peer) {
4171
							if (!peer) {
3782
								ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
4172
								ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
3783
								if (update_connectedline) {
4173
								if (!o->block_connected_update) {
3784
									if (o->pending_connected_update) {
4174
									if (o->pending_connected_update) {
3785
										if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
4175
										if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&

    
   
4176
											ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
3786
											ast_channel_update_connected_line(in, &o->connected, NULL);
4177
											ast_channel_update_connected_line(in, &o->connected, NULL);
3787
										}
4178
										}
3788
									} else if (!o->dial_callerid_absent) {
4179
									} else if (!o->dial_callerid_absent) {
3789
										ast_channel_lock(o->chan);
4180
										ast_channel_lock(o->chan);
3790
										ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
4181
										ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
3791
										ast_channel_unlock(o->chan);
4182
										ast_channel_unlock(o->chan);
3792
										connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
4183
										connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;

    
   
4184
										if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&

    
   
4185
											ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
3793
										ast_channel_update_connected_line(in, &connected_caller, NULL);
4186
											ast_channel_update_connected_line(in, &connected_caller, NULL);

    
   
4187
										}
3794
										ast_party_connected_line_free(&connected_caller);
4188
										ast_party_connected_line_free(&connected_caller);
3795
									}
4189
									}
3796
								}
4190
								}
3797
								if (o->aoc_s_rate_list) {
4191
								if (o->aoc_s_rate_list) {
3798
									size_t encoded_size;
4192
									size_t encoded_size;
[+20] [20] 6 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3805
								peer = o;
4199
								peer = o;
3806
							}
4200
							}
3807
							break;
4201
							break;
3808
						case AST_CONTROL_BUSY:
4202
						case AST_CONTROL_BUSY:
3809
							ast_verb(3, "%s is busy\n", ochan_name);
4203
							ast_verb(3, "%s is busy\n", ochan_name);
3810
							if (in->cdr)
4204
							if (ast_channel_cdr(in)) {
3811
								ast_cdr_busy(in->cdr);
4205
								ast_cdr_busy(ast_channel_cdr(in));

    
   
4206
							}
3812
							do_hang(o);
4207
							do_hang(o);
3813
							endtime = (long) time(NULL);
4208
							endtime = (long) time(NULL);
3814
							endtime -= starttime;
4209
							endtime -= starttime;
3815
							rna(endtime * 1000, qe, on, membername, qe->parent->autopausebusy);
4210
							rna(endtime * 1000, qe, on, membername, qe->parent->autopausebusy);
3816
							if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
4211
							if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
3817
								if (qe->parent->timeoutrestart)
4212
								if (qe->parent->timeoutrestart) {
3818
									*to = orig;
4213
									*to = orig;

    
   
4214
								}
3819
								/* Have enough time for a queue member to answer? */
4215
								/* Have enough time for a queue member to answer? */
3820
								if (*to > 500) {
4216
								if (*to > 500) {
3821
									ring_one(qe, outgoing, &numbusies);
4217
									ring_one(qe, outgoing, &numbusies);
3822
									starttime = (long) time(NULL);
4218
									starttime = (long) time(NULL);
3823
								}
4219
								}
3824
							}
4220
							}
3825
							numbusies++;
4221
							numbusies++;
3826
							break;
4222
							break;
3827
						case AST_CONTROL_CONGESTION:
4223
						case AST_CONTROL_CONGESTION:
3828
							ast_verb(3, "%s is circuit-busy\n", ochan_name);
4224
							ast_verb(3, "%s is circuit-busy\n", ochan_name);
3829
							if (in->cdr)
4225
							if (ast_channel_cdr(in)) {
3830
								ast_cdr_busy(in->cdr);
4226
								ast_cdr_busy(ast_channel_cdr(in));

    
   
4227
							}
3831
							endtime = (long) time(NULL);
4228
							endtime = (long) time(NULL);
3832
							endtime -= starttime;
4229
							endtime -= starttime;
3833
							rna(endtime * 1000, qe, on, membername, qe->parent->autopauseunavail);
4230
							rna(endtime * 1000, qe, on, membername, qe->parent->autopauseunavail);
3834
							do_hang(o);
4231
							do_hang(o);
3835
							if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
4232
							if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
3836
								if (qe->parent->timeoutrestart)
4233
								if (qe->parent->timeoutrestart) {
3837
									*to = orig;
4234
									*to = orig;

    
   
4235
								}
3838
								if (*to > 500) {
4236
								if (*to > 500) {
3839
									ring_one(qe, outgoing, &numbusies);
4237
									ring_one(qe, outgoing, &numbusies);
3840
									starttime = (long) time(NULL);
4238
									starttime = (long) time(NULL);
3841
								}
4239
								}
3842
							}
4240
							}
[+20] [20] 10 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3853
							break;
4251
							break;
3854
						case AST_CONTROL_OFFHOOK:
4252
						case AST_CONTROL_OFFHOOK:
3855
							/* Ignore going off hook */
4253
							/* Ignore going off hook */
3856
							break;
4254
							break;
3857
						case AST_CONTROL_CONNECTED_LINE:
4255
						case AST_CONTROL_CONNECTED_LINE:
3858
							if (!update_connectedline) {
4256
							if (o->block_connected_update) {
3859
								ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
4257
								ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
3860
							} else if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
4258
								break;

    
   
4259
							}

    
   
4260
							if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
3861
								struct ast_party_connected_line connected;
4261
								struct ast_party_connected_line connected;

    
   
4262

   
3862
								ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
4263
								ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
3863
								ast_party_connected_line_set_init(&connected, &o->connected);
4264
								ast_party_connected_line_set_init(&connected, &o->connected);
3864
								ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
4265
								ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
3865
								ast_party_connected_line_set(&o->connected, &connected, NULL);
4266
								ast_party_connected_line_set(&o->connected, &connected, NULL);
3866
								ast_party_connected_line_free(&connected);
4267
								ast_party_connected_line_free(&connected);
3867
								o->pending_connected_update = 1;
4268
								o->pending_connected_update = 1;
3868
							} else {
4269
								break;
3869
								if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {

   
3870
									ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);

   
3871
								}
4270
							}

    
   
4271

   

    
   
4272
							/*

    
   
4273
							 * Prevent using the CallerID from the outgoing channel since we

    
   
4274
							 * got a connected line update from it.

    
   
4275
							 */

    
   
4276
							o->dial_callerid_absent = 1;

    
   
4277

   

    
   
4278
							if (ast_channel_connected_line_sub(o->chan, in, f, 1) &&

    
   
4279
								ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {

    
   
4280
								ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
3872
							}
4281
							}
3873
							break;
4282
							break;
3874
						case AST_CONTROL_AOC:
4283
						case AST_CONTROL_AOC:
3875
							{
4284
							{
3876
								struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
4285
								struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
[+20] [20] 4 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) [+] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3881
									ast_aoc_destroy_decoded(decoded);
4290
									ast_aoc_destroy_decoded(decoded);
3882
								}
4291
								}
3883
							}
4292
							}
3884
							break;
4293
							break;
3885
						case AST_CONTROL_REDIRECTING:
4294
						case AST_CONTROL_REDIRECTING:
3886
							if (!update_connectedline) {
4295
							if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
3887
								ast_verb(3, "Redirecting update to %s prevented\n", inchan_name);
4296
								/*
3888
							} else if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
4297
								 * Redirecting updates to the caller make sense only on single
3889
								ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ochan_name, inchan_name);
4298
								 * call at a time strategies.
3890
								if (ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
4299
								 */
3891
									ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
4300
								break;

    
   
4301
							}

    
   
4302
							if (o->block_connected_update) {

    
   
4303
								ast_verb(3, "Redirecting update to %s prevented\n",

    
   
4304
									inchan_name);

    
   
4305
								break;
3892
								}
4306
							}

    
   
4307
							ast_verb(3, "%s redirecting info has changed, passing it to %s\n",

    
   
4308
								ochan_name, inchan_name);

    
   
4309
							if (ast_channel_redirecting_sub(o->chan, in, f, 1) &&

    
   
4310
								ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {

    
   
4311
								ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
3893
							}
4312
							}
3894
							break;
4313
							break;

    
   
4314
						case AST_CONTROL_PVT_CAUSE_CODE:

    
   
4315
							ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);

    
   
4316
							break;
3895
						default:
4317
						default:
3896
							ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
4318
							ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
3897
							break;
4319
							break;
3898
						}
4320
						}
3899
					}
4321
					}
3900
					ast_frfree(f);
4322
					ast_frfree(f);
3901
				} else { /* ast_read() returned NULL */
4323
				} else { /* ast_read() returned NULL */
3902
					endtime = (long) time(NULL) - starttime;
4324
					endtime = (long) time(NULL) - starttime;
3903
					rna(endtime * 1000, qe, on, membername, 1);
4325
					rna(endtime * 1000, qe, on, membername, 1);
3904
					do_hang(o);
4326
					do_hang(o);
3905
					if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
4327
					if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
3906
						if (qe->parent->timeoutrestart)
4328
						if (qe->parent->timeoutrestart) {
3907
							*to = orig;
4329
							*to = orig;

    
   
4330
						}
3908
						if (*to > 500) {
4331
						if (*to > 500) {
3909
							ring_one(qe, outgoing, &numbusies);
4332
							ring_one(qe, outgoing, &numbusies);
3910
							starttime = (long) time(NULL);
4333
							starttime = (long) time(NULL);
3911
						}
4334
						}
3912
					}
4335
					}
[+20] [20] 7 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3920
			if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
4343
			if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
3921
				/* Got hung up */
4344
				/* Got hung up */
3922
				*to = -1;
4345
				*to = -1;
3923
				if (f) {
4346
				if (f) {
3924
					if (f->data.uint32) {
4347
					if (f->data.uint32) {
3925
						in->hangupcause = f->data.uint32;
4348
						ast_channel_hangupcause_set(in, f->data.uint32);
3926
					}
4349
					}
3927
					ast_frfree(f);
4350
					ast_frfree(f);
3928
				}
4351
				}
3929
				return NULL;
4352
				return NULL;
3930
			}
4353
			}

    
   
4354

   

    
   
4355
			/*!

    
   
4356
			 * \todo

    
   
4357
			 * XXX Queue like Dial really should send any connected line

    
   
4358
			 * updates (AST_CONTROL_CONNECTED_LINE) from the caller to each

    
   
4359
			 * ringing queue member.

    
   
4360
			 */

    
   
4361

   
3931
			if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
4362
			if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
3932
				ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
4363
				ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
3933
				*to = 0;
4364
				*to = 0;
3934
				ast_frfree(f);
4365
				ast_frfree(f);
3935
				return NULL;
4366
				return NULL;
[+20] [20] 6 lines
[+20] static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline) static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
3942
				return NULL;
4373
				return NULL;
3943
			}
4374
			}
3944
			ast_frfree(f);
4375
			ast_frfree(f);
3945
		}
4376
		}
3946
		if (!*to) {
4377
		if (!*to) {
3947
			for (o = start; o; o = o->call_next)
4378
			for (o = start; o; o = o->call_next) {
3948
				rna(orig, qe, o->interface, o->member->membername, 1);
4379
				rna(orig, qe, o->interface, o->member->membername, 1);
3949
		}
4380
			}
3950
	}
4381
		}

    
   
4382
	}
3951

    
   
4383

   
3952
#ifdef HAVE_EPOLL
4384
#ifdef HAVE_EPOLL
3953
	for (epollo = outgoing; epollo; epollo = epollo->q_next) {
4385
	for (epollo = outgoing; epollo; epollo = epollo->q_next) {
3954
		if (epollo->chan)
4386
		if (epollo->chan) {
3955
			ast_poll_channel_del(in, epollo->chan);
4387
			ast_poll_channel_del(in, epollo->chan);
3956
	}
4388
		}

    
   
4389
	}
3957
#endif
4390
#endif
3958

    
   
4391

   
3959
	return peer;
4392
	return peer;
3960
}
4393
}
3961

    
   
4394

   
[+20] [20] 22 lines
[+20] [+] static int is_our_turn(struct queue_ent *qe)
3984
	ch = qe->parent->head;
4417
	ch = qe->parent->head;
3985

    
   
4418

   
3986
	ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
4419
	ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
3987

    
   
4420

   
3988
	while ((idx < avl) && (ch) && (ch != qe)) {
4421
	while ((idx < avl) && (ch) && (ch != qe)) {
3989
		if (!ch->pending)
4422
		if (!ch->pending) {
3990
			idx++;
4423
			idx++;

    
   
4424
		}
3991
		ch = ch->next;			
4425
		ch = ch->next;			
3992
	}
4426
	}
3993

    
   
4427

   
3994
	ao2_unlock(qe->parent);
4428
	ao2_unlock(qe->parent);
3995
	/* If the queue entry is within avl [the number of available members] calls from the top ... 
4429
	/* If the queue entry is within avl [the number of available members] calls from the top ... 
3996
	 * Autofill and position check added to support autofill=no (as only calls
4430
	 * Autofill and position check added to support autofill=no (as only calls
3997
	 * from the front of the queue are valid when autofill is disabled)
4431
	 * from the front of the queue are valid when autofill is disabled)
3998
	 */
4432
	 */
3999
	if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
4433
	if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
4000
		ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
4434
		ast_debug(1, "It's our turn (%s).\n", ast_channel_name(qe->chan));
4001
		res = 1;
4435
		res = 1;
4002
	} else {
4436
	} else {
4003
		ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
4437
		ast_debug(1, "It's not our turn (%s).\n", ast_channel_name(qe->chan));
4004
		res = 0;
4438
		res = 0;
4005
	}
4439
	}
4006

    
   
4440

   
4007
	return res;
4441
	return res;
4008
}
4442
}
[+20] [20] 8 lines
[+20] static int is_our_turn(struct queue_ent *qe)
4017
{
4451
{
4018
	int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
4452
	int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
4019
	int min_penalty = qe->pr->min_relative ? qe->min_penalty + qe->pr->min_value : qe->pr->min_value;
4453
	int min_penalty = qe->pr->min_relative ? qe->min_penalty + qe->pr->min_value : qe->pr->min_value;
4020
	char max_penalty_str[20], min_penalty_str[20]; 
4454
	char max_penalty_str[20], min_penalty_str[20]; 
4021
	/* a relative change to the penalty could put it below 0 */
4455
	/* a relative change to the penalty could put it below 0 */
4022
	if (max_penalty < 0)
4456
	if (max_penalty < 0) {
4023
		max_penalty = 0;
4457
		max_penalty = 0;
4024
	if (min_penalty < 0)
4458
	}

    
   
4459
	if (min_penalty < 0) {
4025
		min_penalty = 0;
4460
		min_penalty = 0;
4026
	if (min_penalty > max_penalty)
4461
	}

    
   
4462
	if (min_penalty > max_penalty) {
4027
		min_penalty = max_penalty;
4463
		min_penalty = max_penalty;

    
   
4464
	}
4028
	snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
4465
	snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
4029
	snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
4466
	snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
4030
	pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
4467
	pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
4031
	pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
4468
	pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
4032
	qe->max_penalty = max_penalty;
4469
	qe->max_penalty = max_penalty;
4033
	qe->min_penalty = min_penalty;
4470
	qe->min_penalty = min_penalty;
4034
	ast_debug(3, "Setting max penalty to %d and min penalty to %d for caller %s since %d seconds have elapsed\n", qe->max_penalty, qe->min_penalty, qe->chan->name, qe->pr->time);
4471
	ast_debug(3, "Setting max penalty to %d and min penalty to %d for caller %s since %d seconds have elapsed\n", qe->max_penalty, qe->min_penalty, ast_channel_name(qe->chan), qe->pr->time);
4035
	qe->pr = AST_LIST_NEXT(qe->pr, list);
4472
	qe->pr = AST_LIST_NEXT(qe->pr, list);
4036
}
4473
}
4037

    
   
4474

   
4038
/*! \brief The waiting areas for callers who are not actively calling members
4475
/*! \brief The waiting areas for callers who are not actively calling members
4039
 *
4476
 *
[+20] [20] 10 lines
[+20] [+] static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
4050
	int res = 0;
4487
	int res = 0;
4051

    
   
4488

   
4052
	/* This is the holding pen for callers 2 through maxlen */
4489
	/* This is the holding pen for callers 2 through maxlen */
4053
	for (;;) {
4490
	for (;;) {
4054

    
   
4491

   
4055
		if (is_our_turn(qe))
4492
		if (is_our_turn(qe)) {
4056
			break;
4493
			break;

    
   
4494
		}
4057

    
   
4495

   
4058
		/* If we have timed out, break out */
4496
		/* If we have timed out, break out */
4059
		if (qe->expire && (time(NULL) >= qe->expire)) {
4497
		if (qe->expire && (time(NULL) >= qe->expire)) {
4060
			*reason = QUEUE_TIMEOUT;
4498
			*reason = QUEUE_TIMEOUT;
4061
			break;
4499
			break;
4062
		}
4500
		}
4063

    
   
4501

   
4064
		if (qe->parent->leavewhenempty) {
4502
		if (qe->parent->leavewhenempty) {
4065
			int status = 0;
4503
			int status = 0;
4066

    
   
4504

   
4067
			if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty))) {
4505
			if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty))) {
4068
				*reason = QUEUE_LEAVEEMPTY;
4506
				*reason = QUEUE_LEAVEEMPTY;
4069
				ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
4507
				ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
4070
				leave_queue(qe);
4508
				leave_queue(qe);
4071
				break;
4509
				break;
4072
			}
4510
			}
4073
		}
4511
		}
4074

    
   
4512

   
4075
		/* Make a position announcement, if enabled */
4513
		/* Make a position announcement, if enabled */
4076
		if (qe->parent->announcefrequency &&
4514
		if (qe->parent->announcefrequency &&
4077
			(res = say_position(qe,ringing)))
4515
			(res = say_position(qe,ringing))) {
4078
			break;
4516
			break;

    
   
4517
		}
4079

    
   
4518

   
4080
		/* If we have timed out, break out */
4519
		/* If we have timed out, break out */
4081
		if (qe->expire && (time(NULL) >= qe->expire)) {
4520
		if (qe->expire && (time(NULL) >= qe->expire)) {
4082
			*reason = QUEUE_TIMEOUT;
4521
			*reason = QUEUE_TIMEOUT;
4083
			break;
4522
			break;
[+20] [20] 15 lines
[+20] static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
4099
			break;
4538
			break;
4100
		}
4539
		}
4101
		
4540
		
4102
		/* Wait a second before checking again */
4541
		/* Wait a second before checking again */
4103
		if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
4542
		if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
4104
			if (res > 0 && !valid_exit(qe, res))
4543
			if (res > 0 && !valid_exit(qe, res)) {
4105
				res = 0;
4544
				res = 0;
4106
			else
4545
			} else {
4107
				break;
4546
				break;
4108
		}
4547
			}

    
   
4548
		}
4109
		
4549
		
4110
		/* If we have timed out, break out */
4550
		/* If we have timed out, break out */
4111
		if (qe->expire && (time(NULL) >= qe->expire)) {
4551
		if (qe->expire && (time(NULL) >= qe->expire)) {
4112
			*reason = QUEUE_TIMEOUT;
4552
			*reason = QUEUE_TIMEOUT;
4113
			break;
4553
			break;
[+20] [20] 36 lines
[+20] [+] static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, int newtalktime)
4150
		member->lastqueue = q;
4590
		member->lastqueue = q;
4151
		ao2_unlock(q);
4591
		ao2_unlock(q);
4152
	}	
4592
	}	
4153
	ao2_lock(q);
4593
	ao2_lock(q);
4154
	q->callscompleted++;
4594
	q->callscompleted++;
4155
	if (callcompletedinsl)
4595
	if (callcompletedinsl) {
4156
		q->callscompletedinsl++;
4596
		q->callscompletedinsl++;

    
   
4597
	}
4157
	/* Calculate talktime using the same exponential average as holdtime code*/
4598
	/* Calculate talktime using the same exponential average as holdtime code*/
4158
	oldtalktime = q->talktime;
4599
	oldtalktime = q->talktime;
4159
	q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
4600
	q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
4160
	ao2_unlock(q);
4601
	ao2_unlock(q);
4161
	return 0;
4602
	return 0;
[+20] [20] 30 lines
[+20] [+] static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
4192
		break;
4633
		break;
4193
	case QUEUE_STRATEGY_LINEAR:
4634
	case QUEUE_STRATEGY_LINEAR:
4194
		if (pos < qe->linpos) {
4635
		if (pos < qe->linpos) {
4195
			tmp->metric = 1000 + pos;
4636
			tmp->metric = 1000 + pos;
4196
		} else {
4637
		} else {
4197
			if (pos > qe->linpos)
4638
			if (pos > qe->linpos) {
4198
				/* Indicate there is another priority */
4639
				/* Indicate there is another priority */
4199
				qe->linwrapped = 1;
4640
				qe->linwrapped = 1;

    
   
4641
			}
4200
			tmp->metric = pos;
4642
			tmp->metric = pos;
4201
		}
4643
		}
4202
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4644
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4203
		break;
4645
		break;
4204
	case QUEUE_STRATEGY_RRORDERED:
4646
	case QUEUE_STRATEGY_RRORDERED:
4205
	case QUEUE_STRATEGY_RRMEMORY:
4647
	case QUEUE_STRATEGY_RRMEMORY:
4206
		if (pos < q->rrpos) {
4648
		if (pos < q->rrpos) {
4207
			tmp->metric = 1000 + pos;
4649
			tmp->metric = 1000 + pos;
4208
		} else {
4650
		} else {
4209
			if (pos > q->rrpos)
4651
			if (pos > q->rrpos) {
4210
				/* Indicate there is another priority */
4652
				/* Indicate there is another priority */
4211
				q->wrapped = 1;
4653
				q->wrapped = 1;

    
   
4654
			}
4212
			tmp->metric = pos;
4655
			tmp->metric = pos;
4213
		}
4656
		}
4214
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4657
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4215
		break;
4658
		break;
4216
	case QUEUE_STRATEGY_RANDOM:
4659
	case QUEUE_STRATEGY_RANDOM:
[+20] [20] 6 lines
[+20] static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
4223
	case QUEUE_STRATEGY_FEWESTCALLS:
4666
	case QUEUE_STRATEGY_FEWESTCALLS:
4224
		tmp->metric = mem->calls;
4667
		tmp->metric = mem->calls;
4225
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4668
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4226
		break;
4669
		break;
4227
	case QUEUE_STRATEGY_LEASTRECENT:
4670
	case QUEUE_STRATEGY_LEASTRECENT:
4228
		if (!mem->lastcall)
4671
		if (!mem->lastcall) {
4229
			tmp->metric = 0;
4672
			tmp->metric = 0;
4230
		else
4673
		} else {
4231
			tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
4674
			tmp->metric = 1000000 - (time(NULL) - mem->lastcall);

    
   
4675
		}
4232
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4676
		tmp->metric += mem->penalty * 1000000 * usepenalty;
4233
		break;
4677
		break;
4234
	default:
4678
	default:
4235
		ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
4679
		ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
4236
		break;
4680
		break;
[+20] [20] 12 lines
[+20] [+] enum agent_complete_reason {
4249
	const struct ast_channel *peer, const struct member *member, time_t callstart,
4693
	const struct ast_channel *peer, const struct member *member, time_t callstart,
4250
	char *vars, size_t vars_len, enum agent_complete_reason rsn)
4694
	char *vars, size_t vars_len, enum agent_complete_reason rsn)
4251
{
4695
{
4252
	const char *reason = NULL;	/* silence dumb compilers */
4696
	const char *reason = NULL;	/* silence dumb compilers */
4253

    
   
4697

   
4254
	if (!qe->parent->eventwhencalled)
4698
	if (!qe->parent->eventwhencalled) {
4255
		return;
4699
		return;

    
   
4700
	}
4256

    
   
4701

   
4257
	switch (rsn) {
4702
	switch (rsn) {
4258
	case CALLER:
4703
	case CALLER:
4259
		reason = "caller";
4704
		reason = "caller";
4260
		break;
4705
		break;
4261
	case AGENT:
4706
	case AGENT:
4262
		reason = "agent";
4707
		reason = "agent";
4263
		break;
4708
		break;
4264
	case TRANSFER:
4709
	case TRANSFER:
4265
		reason = "transfer";
4710
		reason = "transfer";
4266
		break;
4711
		break;
4267
	}
4712
	}
4268

    
   
4713

   

    
   
4714
	/*** DOCUMENTATION

    
   
4715
	<managerEventInstance>

    
   
4716
		<synopsis>Raised when an agent has finished servicing a member in the queue.</synopsis>

    
   
4717
		<syntax>

    
   
4718
			<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />

    
   
4719
			<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='Member'])" />

    
   
4720
			<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />

    
   
4721
			<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />

    
   
4722
			<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />

    
   
4723
			<parameter name="TalkTime">

    
   
4724
				<para>The time the agent talked with the member in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>

    
   
4725
			</parameter>

    
   
4726
			<parameter name="Reason">

    
   
4727
				<enumlist>

    
   
4728
					<enum name="caller"/>

    
   
4729
					<enum name="agent"/>

    
   
4730
					<enum name="transfer"/>

    
   
4731
				</enumlist>

    
   
4732
			</parameter>

    
   
4733
		</syntax>

    
   
4734
		<see-also>

    
   
4735
			<ref type="managerEvent">AgentCalled</ref>

    
   
4736
			<ref type="managerEvent">AgentConnect</ref>

    
   
4737
		</see-also>

    
   
4738
	</managerEventInstance>

    
   
4739
	***/
4269
	manager_event(EVENT_FLAG_AGENT, "AgentComplete",
4740
	manager_event(EVENT_FLAG_AGENT, "AgentComplete",
4270
		"Queue: %s\r\n"
4741
		"Queue: %s\r\n"
4271
		"Uniqueid: %s\r\n"
4742
		"Uniqueid: %s\r\n"
4272
		"Channel: %s\r\n"
4743
		"Channel: %s\r\n"
4273
		"Member: %s\r\n"
4744
		"Member: %s\r\n"
4274
		"MemberName: %s\r\n"
4745
		"MemberName: %s\r\n"
4275
		"HoldTime: %ld\r\n"
4746
		"HoldTime: %ld\r\n"
4276
		"TalkTime: %ld\r\n"
4747
		"TalkTime: %ld\r\n"
4277
		"Reason: %s\r\n"
4748
		"Reason: %s\r\n"
4278
		"%s",
4749
		"%s",
4279
		queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
4750
		queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
4280
		(long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
4751
		(long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
4281
		qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
4752
		qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
4282
}
4753
}
4283

    
   
4754

   
4284
struct queue_transfer_ds {
4755
struct queue_transfer_ds {
[+20] [20] 33 lines
[+20] [+] static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
4318
	struct member *member = qtds->member;
4789
	struct member *member = qtds->member;
4319
	time_t callstart = qtds->starttime;
4790
	time_t callstart = qtds->starttime;
4320
	int callcompletedinsl = qtds->callcompletedinsl;
4791
	int callcompletedinsl = qtds->callcompletedinsl;
4321
	struct ast_datastore *datastore;
4792
	struct ast_datastore *datastore;
4322

    
   
4793

   
4323
	ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
4794
	ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
4324
				new_chan->exten, new_chan->context, (long) (callstart - qe->start),
4795
				ast_channel_exten(new_chan), ast_channel_context(new_chan), (long) (callstart - qe->start),
4325
				(long) (time(NULL) - callstart), qe->opos);
4796
				(long) (time(NULL) - callstart), qe->opos);
4326

    
   
4797

   
4327
	update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
4798
	update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
4328
	
4799
	
4329
	/* No need to lock the channels because they are already locked in ast_do_masquerade */
4800
	/* No need to lock the channels because they are already locked in ast_do_masquerade */
[+20] [20] 30 lines
[+20] [+] static struct ast_datastore *setup_transfer_datastore(struct queue_ent *qe, struct member *member, time_t starttime, int callcompletedinsl)
4360
	}
4831
	}
4361

    
   
4832

   
4362
	ast_channel_lock(qe->chan);
4833
	ast_channel_lock(qe->chan);
4363
	if (!(ds = ast_datastore_alloc(&queue_transfer_info, NULL))) {
4834
	if (!(ds = ast_datastore_alloc(&queue_transfer_info, NULL))) {
4364
		ast_channel_unlock(qe->chan);
4835
		ast_channel_unlock(qe->chan);

    
   
4836
		ast_free(qtds);
4365
		ast_log(LOG_WARNING, "Unable to create transfer datastore. queue_log will not show attended transfer\n");
4837
		ast_log(LOG_WARNING, "Unable to create transfer datastore. queue_log will not show attended transfer\n");
4366
		return NULL;
4838
		return NULL;
4367
	}
4839
	}
4368

    
   
4840

   
4369
	qtds->qe = qe;
4841
	qtds->qe = qe;
[+20] [20] 30 lines
[+20] [+] static void end_bridge_callback(void *data)
4400
		/* This unrefs the reference we made in try_calling when we allocated qeb */
4872
		/* This unrefs the reference we made in try_calling when we allocated qeb */
4401
		queue_t_unref(q, "Expire bridge_config reference");
4873
		queue_t_unref(q, "Expire bridge_config reference");
4402
	}
4874
	}
4403
}
4875
}
4404

    
   
4876

   
4405
/*! \brief A large function which calls members, updates statistics, and bridges the caller and a member
4877
/*!

    
   
4878
 * \internal

    
   
4879
 * \brief A large function which calls members, updates statistics, and bridges the caller and a member
4406
 *
4880
 *
4407
 * Here is the process of this function
4881
 * Here is the process of this function
4408
 * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
4882
 * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
4409
 * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
4883
 * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
4410
 *    iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
4884
 *    iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
[+20] [20] 6 lines
[+20] static void end_bridge_callback(void *data)
4417
 * 7. Remove the caller from the queue to allow other callers to advance
4891
 * 7. Remove the caller from the queue to allow other callers to advance
4418
 * 8. Bridge the call.
4892
 * 8. Bridge the call.
4419
 * 9. Do any post processing after the call has disconnected.
4893
 * 9. Do any post processing after the call has disconnected.
4420
 *
4894
 *
4421
 * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
4895
 * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
4422
 * \param[in] options the options passed as the third parameter to the Queue() application
4896
 * \param[in] opts the options passed as the third parameter to the Queue() application

    
   
4897
 * \param[in] opt_args the options passed as the third parameter to the Queue() application
4423
 * \param[in] announceoverride filename to play to user when waiting 
4898
 * \param[in] announceoverride filename to play to user when waiting 
4424
 * \param[in] url the url passed as the fourth parameter to the Queue() application
4899
 * \param[in] url the url passed as the fourth parameter to the Queue() application
4425
 * \param[in,out] tries the number of times we have tried calling queue members
4900
 * \param[in,out] tries the number of times we have tried calling queue members
4426
 * \param[out] noption set if the call to Queue() has the 'n' option set.
4901
 * \param[out] noption set if the call to Queue() has the 'n' option set.
4427
 * \param[in] agi the agi passed as the fifth parameter to the Queue() application
4902
 * \param[in] agi the agi passed as the fifth parameter to the Queue() application
4428
 * \param[in] macro the macro passed as the sixth parameter to the Queue() application
4903
 * \param[in] macro the macro passed as the sixth parameter to the Queue() application
4429
 * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
4904
 * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
4430
 * \param[in] ringing 1 if the 'r' option is set, otherwise 0
4905
 * \param[in] ringing 1 if the 'r' option is set, otherwise 0
4431
 */
4906
 */
4432
static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4907
static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4433
{
4908
{
4434
	struct member *cur;
4909
	struct member *cur;
4435
	struct callattempt *outgoing = NULL; /* the list of calls we are building */
4910
	struct callattempt *outgoing = NULL; /* the list of calls we are building */
4436
	int to, orig;
4911
	int to, orig;
4437
	char oldexten[AST_MAX_EXTENSION]="";
4912
	char oldexten[AST_MAX_EXTENSION]="";
[+20] [20] 25 lines
[+20] static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing) [+] static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4463
	char mixmonargs[1512];
4938
	char mixmonargs[1512];
4464
	struct ast_app *mixmonapp = NULL;
4939
	struct ast_app *mixmonapp = NULL;
4465
	char *p;
4940
	char *p;
4466
	char vars[2048];
4941
	char vars[2048];
4467
	int forwardsallowed = 1;
4942
	int forwardsallowed = 1;
4468
	int update_connectedline = 1;
4943
	int block_connected_line = 0;
4469
	int callcompletedinsl;
4944
	int callcompletedinsl;
4470
	struct ao2_iterator memi;
4945
	struct ao2_iterator memi;
4471
	struct ast_datastore *datastore, *transfer_ds;
4946
	struct ast_datastore *datastore, *transfer_ds;
4472
	struct queue_end_bridge *queue_end_bridge = NULL;
4947
	struct queue_end_bridge *queue_end_bridge = NULL;
4473

    
   
4948

   
[+20] [20] 12 lines
[+20] static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing) [+] static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4486
	 */
4961
	 */
4487
	if (qe->expire && now >= qe->expire) {
4962
	if (qe->expire && now >= qe->expire) {
4488
		res = 0;
4963
		res = 0;
4489
		goto out;
4964
		goto out;
4490
	}
4965
	}
4491
		
4966

   
4492
	for (; options && *options; options++)
4967
	if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER)) {
4493
		switch (*options) {

   
4494
		case 't':

   
4495
			ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
4968
		ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
4496
			break;
4969
	}
4497
		case 'T':
4970
	if (ast_test_flag(&opts, OPT_CALLER_TRANSFER)) {
4498
			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
4971
		ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
4499
			break;
4972
	}
4500
		case 'w':
4973
	if (ast_test_flag(&opts, OPT_CALLEE_AUTOMON)) {
4501
			ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
4974
		ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
4502
			break;
4975
	}
4503
		case 'W':
4976
	if (ast_test_flag(&opts, OPT_CALLER_AUTOMON)) {
4504
			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
4977
		ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
4505
			break;
4978
	}
4506
		case 'c':
4979
	if (ast_test_flag(&opts, OPT_GO_ON)) {
4507
			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_NO_H_EXTEN);
4980
		ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_NO_H_EXTEN);
4508
			break;
4981
	}
4509
		case 'd':
4982
	if (ast_test_flag(&opts, OPT_DATA_QUALITY)) {
4510
			nondataquality = 0;
4983
		nondataquality = 0;
4511
			break;
4984
	}
4512
		case 'h':
4985
	if (ast_test_flag(&opts, OPT_CALLEE_HANGUP)) {
4513
			ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
4986
		ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
4514
			break;
4987
	}
4515
		case 'H':
4988
	if (ast_test_flag(&opts, OPT_CALLER_HANGUP)) {
4516
			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
4989
		ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
4517
			break;
4990
	}
4518
		case 'k':
4991
	if (ast_test_flag(&opts, OPT_CALLEE_PARK)) {
4519
			ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
4992
		ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
4520
			break;
4993
	}
4521
		case 'K':
4994
	if (ast_test_flag(&opts, OPT_CALLER_PARK)) {
4522
			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
4995
		ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
4523
			break;
4996
	}
4524
		case 'n':
4997
	if (ast_test_flag(&opts, OPT_NO_RETRY)) {
4525
			if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED)
4998
		if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR 

    
   
4999
			|| qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
4526
				(*tries)++;
5000
			(*tries)++;
4527
			else
5001
		} else {
4528
				*tries = ao2_container_count(qe->parent->members);
5002
			*tries = ao2_container_count(qe->parent->members);

    
   
5003
		}
4529
			*noption = 1;
5004
		*noption = 1;
4530
			break;
5005
	}
4531
		case 'i':
5006
	if (ast_test_flag(&opts, OPT_IGNORE_CALL_FW)) {
4532
			forwardsallowed = 0;
5007
		forwardsallowed = 0;
4533
			break;
5008
	}
4534
		case 'I':
5009
	if (ast_test_flag(&opts, OPT_IGNORE_CONNECTEDLINE)) {
4535
			update_connectedline = 0;
5010
		block_connected_line = 1;
4536
			break;
5011
	}
4537
		case 'x':
5012
	if (ast_test_flag(&opts, OPT_CALLEE_AUTOMIXMON)) {
4538
			ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
5013
		ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
4539
			break;
5014
	}
4540
		case 'X':
5015
	if (ast_test_flag(&opts, OPT_CALLER_AUTOMIXMON)) {
4541
			ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
5016
		ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
4542
			break;
5017
	}
4543
		case 'C':
5018
	if (ast_test_flag(&opts, OPT_MARK_AS_ANSWERED)) {
4544
			qe->cancel_answered_elsewhere = 1;
5019
		qe->cancel_answered_elsewhere = 1;
4545
			break;

   
4546
		}
5020
	}
4547

    
   
5021

   
4548
	/* if the calling channel has the ANSWERED_ELSEWHERE flag set, make sure this is inherited. 
5022
	/* if the calling channel has AST_CAUSE_ANSWERED_ELSEWHERE set, make sure this is inherited.
4549
		(this is mainly to support chan_local)
5023
		(this is mainly to support chan_local)
4550
	*/
5024
	*/
4551
	if (ast_test_flag(qe->chan, AST_FLAG_ANSWERED_ELSEWHERE)) {
5025
	if (ast_channel_hangupcause(qe->chan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
4552
		qe->cancel_answered_elsewhere = 1;
5026
		qe->cancel_answered_elsewhere = 1;
4553
	}
5027
	}
4554

    
   
5028

   
4555
	ao2_lock(qe->parent);
5029
	ao2_lock(qe->parent);
4556
	ast_debug(1, "%s is trying to call a queue member.\n",
5030
	ast_debug(1, "%s is trying to call a queue member.\n",
4557
							qe->chan->name);
5031
							ast_channel_name(qe->chan));
4558
	ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
5032
	ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
4559
	if (!ast_strlen_zero(qe->announce))
5033
	if (!ast_strlen_zero(qe->announce)) {
4560
		announce = qe->announce;
5034
		announce = qe->announce;
4561
	if (!ast_strlen_zero(announceoverride))
5035
	}

    
   
5036
	if (!ast_strlen_zero(announceoverride)) {
4562
		announce = announceoverride;
5037
		announce = announceoverride;

    
   
5038
	}
4563

    
   
5039

   
4564
	memi = ao2_iterator_init(qe->parent->members, 0);
5040
	memi = ao2_iterator_init(qe->parent->members, 0);
4565
	while ((cur = ao2_iterator_next(&memi))) {
5041
	while ((cur = ao2_iterator_next(&memi))) {
4566
		struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
5042
		struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
4567
		struct ast_dialed_interface *di;
5043
		struct ast_dialed_interface *di;
4568
		AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
5044
		AST_LIST_HEAD(,ast_dialed_interface) *dialed_interfaces;
4569
		if (!tmp) {
5045
		if (!tmp) {
4570
			ao2_ref(cur, -1);
5046
			ao2_ref(cur, -1);
4571
			ao2_unlock(qe->parent);

   
4572
			ao2_iterator_destroy(&memi);
5047
			ao2_iterator_destroy(&memi);

    
   
5048
			ao2_unlock(qe->parent);
4573
			goto out;
5049
			goto out;
4574
		}
5050
		}
4575
		if (!datastore) {
5051
		if (!datastore) {
4576
			if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
5052
			if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {

    
   
5053
				callattempt_free(tmp);
4577
				ao2_ref(cur, -1);
5054
				ao2_ref(cur, -1);
4578
				ao2_unlock(qe->parent);

   
4579
				ao2_iterator_destroy(&memi);
5055
				ao2_iterator_destroy(&memi);
4580
				callattempt_free(tmp);
5056
				ao2_unlock(qe->parent);
4581
				goto out;
5057
				goto out;
4582
			}
5058
			}
4583
			datastore->inheritance = DATASTORE_INHERIT_FOREVER;
5059
			datastore->inheritance = DATASTORE_INHERIT_FOREVER;
4584
			if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
5060
			if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {

    
   
5061
				callattempt_free(tmp);
4585
				ao2_ref(cur, -1);
5062
				ao2_ref(cur, -1);
4586
				ao2_unlock(&qe->parent);

   
4587
				ao2_iterator_destroy(&memi);
5063
				ao2_iterator_destroy(&memi);
4588
				callattempt_free(tmp);
5064
				ao2_unlock(qe->parent);
4589
				goto out;
5065
				goto out;
4590
			}
5066
			}
4591
			datastore->data = dialed_interfaces;
5067
			datastore->data = dialed_interfaces;
4592
			AST_LIST_HEAD_INIT(dialed_interfaces);
5068
			AST_LIST_HEAD_INIT(dialed_interfaces);
4593

    
   
5069

   
[+20] [20] 13 lines
[+20] static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing) [+] static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4607
		}
5083
		}
4608
		AST_LIST_UNLOCK(dialed_interfaces);
5084
		AST_LIST_UNLOCK(dialed_interfaces);
4609

    
   
5085

   
4610
		if (di) {
5086
		if (di) {
4611
			callattempt_free(tmp);
5087
			callattempt_free(tmp);

    
   
5088
			ao2_ref(cur, -1);
4612
			continue;
5089
			continue;
4613
		}
5090
		}
4614

    
   
5091

   
4615
		/* It is always ok to dial a Local interface.  We only keep track of
5092
		/* It is always ok to dial a Local interface.  We only keep track of
4616
		 * which "real" interfaces have been dialed.  The Local channel will
5093
		 * which "real" interfaces have been dialed.  The Local channel will
4617
		 * inherit this list so that if it ends up dialing a real interface,
5094
		 * inherit this list so that if it ends up dialing a real interface,
4618
		 * it won't call one that has already been called. */
5095
		 * it won't call one that has already been called. */
4619
		if (strncasecmp(cur->interface, "Local/", 6)) {
5096
		if (strncasecmp(cur->interface, "Local/", 6)) {
4620
			if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
5097
			if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {

    
   
5098
				callattempt_free(tmp);
4621
				ao2_ref(cur, -1);
5099
				ao2_ref(cur, -1);
4622
				ao2_unlock(qe->parent);

   
4623
				ao2_iterator_destroy(&memi);
5100
				ao2_iterator_destroy(&memi);
4624
				callattempt_free(tmp);
5101
				ao2_unlock(qe->parent);
4625
				goto out;
5102
				goto out;
4626
			}
5103
			}
4627
			strcpy(di->interface, cur->interface);
5104
			strcpy(di->interface, cur->interface);
4628

    
   
5105

   
4629
			AST_LIST_LOCK(dialed_interfaces);
5106
			AST_LIST_LOCK(dialed_interfaces);
4630
			AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
5107
			AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
4631
			AST_LIST_UNLOCK(dialed_interfaces);
5108
			AST_LIST_UNLOCK(dialed_interfaces);
4632
		}
5109
		}
4633

    
   
5110

   
4634
		ast_channel_lock(qe->chan);

   
4635
		/*
5111
		/*
4636
		 * Seed the callattempt's connected line information with previously
5112
		 * Seed the callattempt's connected line information with previously
4637
		 * acquired connected line info from the queued channel.  The
5113
		 * acquired connected line info from the queued channel.  The
4638
		 * previously acquired connected line info could have been set
5114
		 * previously acquired connected line info could have been set
4639
		 * through the CONNECTED_LINE dialplan function.
5115
		 * through the CONNECTED_LINE dialplan function.
4640
		 */
5116
		 */
4641
		ast_party_connected_line_copy(&tmp->connected, &qe->chan->connected);
5117
		ast_channel_lock(qe->chan);

    
   
5118
		ast_party_connected_line_copy(&tmp->connected, ast_channel_connected(qe->chan));
4642
		ast_channel_unlock(qe->chan);
5119
		ast_channel_unlock(qe->chan);
4643

    
   
5120

   
4644
		tmp->stillgoing = -1;
5121
		tmp->block_connected_update = block_connected_line;

    
   
5122
		tmp->stillgoing = 1;
4645
		tmp->member = cur;/* Place the reference for cur into callattempt. */
5123
		tmp->member = cur;/* Place the reference for cur into callattempt. */
4646
		tmp->lastcall = cur->lastcall;
5124
		tmp->lastcall = cur->lastcall;
4647
		tmp->lastqueue = cur->lastqueue;
5125
		tmp->lastqueue = cur->lastqueue;
4648
		ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
5126
		ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
4649
		/* Special case: If we ring everyone, go ahead and ring them, otherwise
5127
		/* Special case: If we ring everyone, go ahead and ring them, otherwise
4650
		   just calculate their metric for the appropriate strategy */
5128
		   just calculate their metric for the appropriate strategy */
4651
		if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
5129
		if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
4652
			/* Put them in the list of outgoing thingies...  We're ready now.
5130
			/* Put them in the list of outgoing thingies...  We're ready now.
4653
			   XXX If we're forcibly removed, these outgoing calls won't get
5131
			   XXX If we're forcibly removed, these outgoing calls won't get
4654
			   hung up XXX */
5132
			   hung up XXX */
4655
			tmp->q_next = outgoing;
5133
			tmp->q_next = outgoing;
4656
			outgoing = tmp;		
5134
			outgoing = tmp;		
4657
			/* If this line is up, don't try anybody else */
5135
			/* If this line is up, don't try anybody else */
4658
			if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
5136
			if (outgoing->chan && (ast_channel_state(outgoing->chan) == AST_STATE_UP))
4659
				break;
5137
				break;
4660
		} else {
5138
		} else {
4661
			callattempt_free(tmp);
5139
			callattempt_free(tmp);
4662
		}
5140
		}
4663
	}
5141
	}
4664
	ao2_iterator_destroy(&memi);
5142
	ao2_iterator_destroy(&memi);
4665

    
   
5143

   
4666
	if (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP) {
5144
	if (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP) {
4667
		/* Application arguments have higher timeout priority (behaviour for <=1.6) */
5145
		/* Application arguments have higher timeout priority (behaviour for <=1.6) */
4668
		if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
5146
		if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout)) {
4669
			to = (qe->expire - now) * 1000;
5147
			to = (qe->expire - now) * 1000;
4670
		else
5148
		} else {
4671
			to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
5149
			to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;

    
   
5150
		}
4672
	} else {
5151
	} else {
4673
		/* Config timeout is higher priority thatn application timeout */
5152
		/* Config timeout is higher priority thatn application timeout */
4674
		if (qe->expire && qe->expire<=now) {
5153
		if (qe->expire && qe->expire<=now) {
4675
			to = 0;
5154
			to = 0;
4676
		} else if (qe->parent->timeout) {
5155
		} else if (qe->parent->timeout) {
[+20] [20] 4 lines
[+20] static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing) [+] static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4681
	}
5160
	}
4682
	orig = to;
5161
	orig = to;
4683
	++qe->pending;
5162
	++qe->pending;
4684
	ao2_unlock(qe->parent);
5163
	ao2_unlock(qe->parent);
4685
	ring_one(qe, outgoing, &numbusies);
5164
	ring_one(qe, outgoing, &numbusies);
4686
	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, update_connectedline);
5165
	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,

    
   
5166
		ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),

    
   
5167
		forwardsallowed);
4687
	/* The ast_channel_datastore_remove() function could fail here if the
5168
	/* The ast_channel_datastore_remove() function could fail here if the
4688
	 * datastore was moved to another channel during a masquerade. If this is
5169
	 * datastore was moved to another channel during a masquerade. If this is
4689
	 * the case, don't free the datastore here because later, when the channel
5170
	 * the case, don't free the datastore here because later, when the channel
4690
	 * to which the datastore was moved hangs up, it will attempt to free this
5171
	 * to which the datastore was moved hangs up, it will attempt to free this
4691
	 * datastore again, causing a crash
5172
	 * datastore again, causing a crash
[+20] [20] 20 lines
[+20] static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing) [+] static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4712
			res = -1;
5193
			res = -1;
4713
		} else {
5194
		} else {
4714
			/* User exited by pressing a digit */
5195
			/* User exited by pressing a digit */
4715
			res = digit;
5196
			res = digit;
4716
		}
5197
		}
4717
		if (res == -1)
5198
		if (res == -1) {
4718
			ast_debug(1, "%s: Nobody answered.\n", qe->chan->name);
5199
			ast_debug(1, "%s: Nobody answered.\n", ast_channel_name(qe->chan));

    
   
5200
		}
4719
		if (ast_cdr_isset_unanswered()) {
5201
		if (ast_cdr_isset_unanswered()) {
4720
			/* channel contains the name of one of the outgoing channels
5202
			/* channel contains the name of one of the outgoing channels
4721
			   in its CDR; zero out this CDR to avoid a dual-posting */
5203
			   in its CDR; zero out this CDR to avoid a dual-posting */
4722
			struct callattempt *o;
5204
			struct callattempt *o;
4723
			for (o = outgoing; o; o = o->q_next) {
5205
			for (o = outgoing; o; o = o->q_next) {
4724
				if (!o->chan) {
5206
				if (!o->chan) {
4725
					continue;
5207
					continue;
4726
				}
5208
				}
4727
				if (strcmp(o->chan->cdr->dstchannel, qe->chan->cdr->dstchannel) == 0) {
5209
				if (strcmp(ast_channel_cdr(o->chan)->dstchannel, ast_channel_cdr(qe->chan)->dstchannel) == 0) {
4728
					ast_set_flag(o->chan->cdr, AST_CDR_FLAG_POST_DISABLED);
5210
					ast_set_flag(ast_channel_cdr(o->chan), AST_CDR_FLAG_POST_DISABLED);
4729
					break;
5211
					break;
4730
				}
5212
				}
4731
			}
5213
			}
4732
		}
5214
		}
4733
	} else { /* peer is valid */
5215
	} else { /* peer is valid */

    
   
5216
		/* These variables are used with the F option without arguments (callee jumps to next priority after queue) */

    
   
5217
		char *caller_context;

    
   
5218
		char *caller_extension;

    
   
5219
		int caller_priority;

    
   
5220

   
4734
		/* Ah ha!  Someone answered within the desired timeframe.  Of course after this
5221
		/* Ah ha!  Someone answered within the desired timeframe.  Of course after this
4735
		   we will always return with -1 so that it is hung up properly after the
5222
		   we will always return with -1 so that it is hung up properly after the
4736
		   conversation.  */
5223
		   conversation.  */
4737
		if (!strcmp(qe->chan->tech->type, "DAHDI"))
5224
		if (!strcmp(ast_channel_tech(qe->chan)->type, "DAHDI")) {
4738
			ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
5225
			ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
4739
		if (!strcmp(peer->tech->type, "DAHDI"))
5226
		}

    
   
5227
		if (!strcmp(ast_channel_tech(peer)->type, "DAHDI")) {
4740
			ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
5228
			ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);

    
   
5229
		}
4741
		/* Update parameters for the queue */
5230
		/* Update parameters for the queue */
4742
		time(&now);
5231
		time(&now);
4743
		recalc_holdtime(qe, (now - qe->start));
5232
		recalc_holdtime(qe, (now - qe->start));
4744
		ao2_lock(qe->parent);
5233
		ao2_lock(qe->parent);
4745
		callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
5234
		callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
[+20] [20] 8 lines
[+20] static int try_calling(struct queue_ent *qe, const char *options, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing) [+] static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
4754

    
   
5243

   
4755
			res2 = ast_autoservice_start(qe->chan);
5244
			res2 = ast_autoservice_start(qe->chan);
4756
			if (!res2) {
5245
			if (!res2) {
4757
				if (qe->parent->memberdelay) {
5246
				if (qe->parent->memberdelay) {
4758
					ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
5247
					ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
4759
					res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
5248
					res2 = ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
4760
				}
5249
				}
4761
				if (!res2 && announce) {
5250
				if (!res2 && announce) {
4762
					play_file(peer, announce);
5251
					if (play_file(peer, announce) < 0) {

    
   
5252
						ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", announce, ast_channel_name(peer));

    
   
5253
					}
4763
				}
5254
				}
4764
				if (!res2 && qe->parent->reportholdtime) {
5255
				if (!res2 && qe->parent->reportholdtime) {
4765
					if (!play_file(peer, qe->parent->sound_reporthold)) {
5256
					if (!play_file(peer, qe->parent->sound_reporthold)) {
4766
						int holdtime, holdtimesecs;
5257
						int holdtime, holdtimesecs;
4767

    
   
5258

   
4768
						time(&now);
5259
						time(&now);
4769
						holdtime = abs((now - qe->start) / 60);
5260
						holdtime = abs((now - qe->start) / 60);
4770
						holdtimesecs = abs((now - qe->start) % 60);
5261
						holdtimesecs = abs((now - qe->start) % 60);
4771
						if (holdtime > 0) {
5262
						if (holdtime > 0) {
4772
							ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
5263
							ast_say_number(peer, holdtime, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
4773
							play_file(peer, qe->parent->sound_minutes);
5264
							if (play_file(peer, qe->parent->sound_minutes) < 0) {

    
   
5265
								ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, ast_channel_name(peer));

    
   
5266
							}
4774
						}
5267
						}
4775
						if (holdtimesecs > 1) {
5268
						if (holdtimesecs > 1) {
4776
							ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, peer->language, NULL);
5269
							ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
4777
							play_file(peer, qe->parent->sound_seconds);
5270
							if (play_file(peer, qe->parent->sound_seconds) < 0) {

    
   
5271
								ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, ast_channel_name(peer));
4778
						}
5272
							}
4779
					}
5273
						}
4780
				}
5274
					}
4781
			}
5275
				}
4782
			res2 |= ast_autoservice_stop(qe->chan);
5276
				ast_autoservice_stop(qe->chan);

    
   
5277
			}
4783
			if (ast_check_hangup(peer)) {
5278
			if (ast_check_hangup(peer)) {
4784
				/* Agent must have hung up */
5279
				/* Agent must have hung up */
4785
				ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
5280
				ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", ast_channel_name(peer));
4786
				ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
5281
				ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "AGENTDUMP", "%s", "");
4787
				if (qe->parent->eventwhencalled)
5282
				if (qe->parent->eventwhencalled)

    
   
5283
					/*** DOCUMENTATION

    
   
5284
					<managerEventInstance>

    
   
5285
						<synopsis>Raised when an agent hangs up on a member in the queue.</synopsis>

    
   
5286
						<syntax>

    
   
5287
							<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />

    
   
5288
							<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='Member'])" />

    
   
5289
							<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />

    
   
5290
							<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />

    
   
5291
						</syntax>

    
   
5292
						<see-also>

    
   
5293
							<ref type="managerEvent">AgentCalled</ref>

    
   
5294
							<ref type="managerEvent">AgentConnect</ref>

    
   
5295
						</see-also>

    
   
5296
					</managerEventInstance>

    
   
5297
					***/
4788
					manager_event(EVENT_FLAG_AGENT, "AgentDump",
5298
					manager_event(EVENT_FLAG_AGENT, "AgentDump",
4789
							"Queue: %s\r\n"
5299
							"Queue: %s\r\n"
4790
							"Uniqueid: %s\r\n"
5300
							"Uniqueid: %s\r\n"
4791
							"Channel: %s\r\n"
5301
							"Channel: %s\r\n"
4792
							"Member: %s\r\n"
5302
							"Member: %s\r\n"
4793
							"MemberName: %s\r\n"
5303
							"MemberName: %s\r\n"
4794
							"%s",
5304
							"%s",
4795
							queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
5305
							queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
4796
							qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
5306
							qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
4797
				ast_hangup(peer);
5307
				ast_autoservice_chan_hangup_peer(qe->chan, peer);
4798
				ao2_ref(member, -1);
5308
				ao2_ref(member, -1);
4799
				goto out;
5309
				goto out;
4800
			} else if (res2) {
5310
			} else if (ast_check_hangup(qe->chan)) {
4801
				/* Caller must have hung up just before being connected*/
5311
				/* Caller must have hung up just before being connected */
4802
				ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
5312
				ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", ast_channel_name(peer));
4803
				ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
5313
				ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
4804
				record_abandoned(qe);
5314
				record_abandoned(qe);
4805
				ast_hangup(peer);
5315
				ast_autoservice_chan_hangup_peer(qe->chan, peer);
4806
				ao2_ref(member, -1);
5316
				ao2_ref(member, -1);
4807
				return -1;
5317
				return -1;
4808
			}
5318
			}
4809
		}
5319
		}
4810
		/* Stop music on hold */
5320
		/* Stop music on hold */
4811
		if (ringing)
5321
		if (ringing) {
4812
			ast_indicate(qe->chan,-1);
5322
			ast_indicate(qe->chan,-1);
4813
		else
5323
		} else {
4814
			ast_moh_stop(qe->chan);
5324
			ast_moh_stop(qe->chan);

    
   
5325
		}
4815
		/* If appropriate, log that we have a destination channel */
5326
		/* If appropriate, log that we have a destination channel */
4816
		if (qe->chan->cdr) {
5327
		if (ast_channel_cdr(qe->chan)) {
4817
			ast_cdr_setdestchan(qe->chan->cdr, peer->name);
5328
			ast_cdr_setdestchan(ast_channel_cdr(qe->chan), ast_channel_name(peer));
4818
		}
5329
		}
4819
		/* Make sure channels are compatible */
5330
		/* Make sure channels are compatible */
4820
		res = ast_channel_make_compatible(qe->chan, peer);
5331
		res = ast_channel_make_compatible(qe->chan, peer);
4821
		if (res < 0) {
5332
		if (res < 0) {
4822
			ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
5333
			ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "SYSCOMPAT", "%s", "");
4823
			ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n"