Bug Summary

File:src/mod/applications/mod_fifo/mod_fifo.c
Location:line 3866, column 10
Description:Potential leak of memory pointed to by '__retval'

Annotated Source Code

1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Travis Cross <tc@traviscross.com>
28 *
29 * mod_fifo.c -- FIFO
30 *
31 */
32#include <switch.h>
33#define FIFO_APP_KEY"mod_fifo" "mod_fifo"
34
35SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)switch_status_t mod_fifo_shutdown (void);
36SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)switch_status_t mod_fifo_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
;
37SWITCH_MODULE_DEFINITION(mod_fifo, mod_fifo_load, mod_fifo_shutdown, NULL)static const char modname[] = "mod_fifo" ; __attribute__((visibility
("default"))) switch_loadable_module_function_table_t mod_fifo_module_interface
= { 5, mod_fifo_load, mod_fifo_shutdown, ((void*)0), SMODF_NONE
}
;
38
39/*!\file
40 * # Theory of operation
41 *
42 * ## Kinds of things
43 *
44 * The fifo systems deals in various kinds of things: /fifos nodes/,
45 * /queues/, /(inbound) callers/, /outbound callers/, /consumers/, and
46 * /(outbound) members/.
47 *
48 * /fifo nodes/ accept callers and work to deliver those callers to
49 * consumers and members. The nodes contain an array of /queues/
50 * indexed by a priority value.
51 *
52 * /queues/ contain an array of callers treated as a list.
53 *
54 * /callers/ are the channels placed into a fifo node's queue for
55 * eventual delivery to consumers and members.
56 *
57 * /outbound callers/ are persons waiting to be called back via a
58 * dial string.
59 *
60 * /consumers/ are channels for agents who have dialed in to one or
61 * more fifos and will have callers connected to them.
62 *
63 * /members/ are agents who we'll place calls to via a dial string to
64 * attempt to deliver callers.
65 *
66 * An /agent/ may refer to either a /consumer/ or an /member/.
67 *
68 * ## Outbound Strategies
69 *
70 * An outbound strategy defines the way in which we attempt to deliver
71 * callers to members.
72 *
73 * The default strategy, /ringall/, preserves the caller ID of the
74 * caller being delivered. Because this means we must choose a caller
75 * before we place the call to the member, this impacts the order in
76 * which calls are delivered and the rate at which we can deliver
77 * those calls.
78 *
79 * The /enterprise/ outbound strategy does not preserve the caller ID
80 * of the caller thereby allowing deliver of callers to agents at the
81 * fastest possible rate.
82 *
83 * outbound_per_cycle is used to define the maximum number of agents
84 * who will be available to answer a single caller. In ringall this
85 * maximum is the number who will be called, in enterprise the need defines
86 * how many agents will be called. outbound_per_cycle_min will define
87 * the minimum agents who will be called to answer a caller regardless of
88 * need, giving the enterprise strategy the ability to ring through more
89 * than one agent for one caller.
90
91 *
92 * ## Manual calls
93 *
94 * The fifo system provides a way to prevent members on non-fifo calls
95 * from receiving a call from the fifo system. We do this by tracking
96 * non-fifo calls in a special fifo named `manual_calls`. When
97 * creating a channel for an agent we set the channel variable
98 * `fifo_outbound_uuid` to an arbitrary unique value <= 32 characters
99 * for that agent, then call `fifo_track_call`. For the corresponding
100 * member we must also set `{fifo_outbound_uuid=}` to the same value.
101 * We expect the value of `fifo_outbound_uuid` to be the MD5 hash of
102 * the unique ID. Values longer than 32 characters will cause the
103 * mechanism to fail to work as expected.
104 *
105 * ## Importance
106 *
107 * Importance is a value 0-9 that can be associated with a fifo. The
108 * default value is 0. If the fifo is being dynamically created the
109 * importance of the fifo can be set when calling the `fifo`
110 * application. If the fifo already exists the importance value
111 * passed to the fifo application will be ignored.
112 */
113
114#define MANUAL_QUEUE_NAME"manual_calls" "manual_calls"
115#define FIFO_EVENT"fifo::info" "fifo::info"
116
117static switch_status_t load_config(int reload, int del_all);
118#define MAX_PRI10 10
119
120typedef enum {
121 NODE_STRATEGY_INVALID = -1,
122 NODE_STRATEGY_RINGALL = 0,
123 NODE_STRATEGY_ENTERPRISE
124} outbound_strategy_t;
125
126/*!\struct fifo_queue_t
127 * \brief Queue of callers
128 *
129 * Callers are placed into a queue as events in `data` which is an
130 * array of such events. The array size is hard-coded as 1000
131 * elements.
132 *
133 * Fifo nodes are composed of an array of these queues representing
134 * each priority level of the fifo.
135 */
136typedef struct {
137 int nelm;
138 int idx;
139 switch_event_t **data;
140 switch_memory_pool_t *pool;
141 switch_mutex_t *mutex;
142} fifo_queue_t;
143
144typedef enum {
145 FIFO_APP_BRIDGE_TAG = (1 << 0),
146 FIFO_APP_TRACKING = (1 << 1),
147 FIFO_APP_DID_HOOK = (1 << 2)
148} fifo_app_flag_t;
149
150static int check_caller_outbound_call(const char *key);
151static void add_caller_outbound_call(const char *key, switch_call_cause_t *cancel_cause);
152static void del_caller_outbound_call(const char *key);
153static void cancel_caller_outbound_call(const char *key, switch_call_cause_t cause);
154static int check_consumer_outbound_call(const char *key);
155static void add_consumer_outbound_call(const char *key, switch_call_cause_t *cancel_cause);
156static void del_consumer_outbound_call(const char *key);
157static void cancel_consumer_outbound_call(const char *key, switch_call_cause_t cause);
158
159static int check_bridge_call(const char *key);
160static void add_bridge_call(const char *key);
161static void del_bridge_call(const char *key);
162
163switch_status_t fifo_queue_create(fifo_queue_t **queue, int size, switch_memory_pool_t *pool)
164{
165 fifo_queue_t *q;
166
167 q = switch_core_alloc(pool, sizeof(*q))switch_core_perform_alloc(pool, sizeof(*q), "mod_fifo.c", (const
char *)__func__, 167)
;
168 q->pool = pool;
169 q->nelm = size - 1;
170 q->data = switch_core_alloc(pool, size * sizeof(switch_event_t *))switch_core_perform_alloc(pool, size * sizeof(switch_event_t *
), "mod_fifo.c", (const char *)__func__, 170)
;
171 switch_mutex_init(&q->mutex, SWITCH_MUTEX_NESTED0x1, pool);
172
173 *queue = q;
174
175 return SWITCH_STATUS_SUCCESS;
176}
177
178static void change_pos(switch_event_t *event, int pos)
179{
180 const char *uuid = switch_event_get_header(event, "unique-id")switch_event_get_header_idx(event, "unique-id", -1);
181 switch_core_session_t *session;
182 switch_channel_t *channel;
183 char tmp[30] = "";
184
185 if (zstr(uuid)_zstr(uuid)) return;
186 if (!(session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_fifo.c", (const
char *)__func__, 186)
)) {
187 return;
188 }
189 channel = switch_core_session_get_channel(session);
190 switch_snprintf(tmp, sizeof(tmp), "%d", pos);
191 switch_channel_set_variable(channel, "fifo_position", tmp)switch_channel_set_variable_var_check(channel, "fifo_position"
, tmp, SWITCH_TRUE)
;
192 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fifo_position", tmp);
193 switch_core_session_rwunlock(session);
194}
195
196static switch_status_t fifo_queue_push(fifo_queue_t *queue, switch_event_t *ptr)
197{
198 switch_mutex_lock(queue->mutex);
199 if (queue->idx == queue->nelm) {
200 switch_mutex_unlock(queue->mutex);
201 return SWITCH_STATUS_FALSE;
202 }
203 queue->data[queue->idx++] = ptr;
204 switch_mutex_unlock(queue->mutex);
205 return SWITCH_STATUS_SUCCESS;
206}
207
208static int fifo_queue_size(fifo_queue_t *queue)
209{
210 int s;
211 switch_mutex_lock(queue->mutex);
212 s = queue->idx;
213 switch_mutex_unlock(queue->mutex);
214 return s;
215}
216
217/*!
218 * \param remove Whether to remove the popped event from the queue
219 * If remove is 0, do not remove the popped event. If it is 1,
220 * remove it if it is not an event for an outbound caller. If it is
221 * 2, always remove it.
222 */
223static switch_status_t fifo_queue_pop(fifo_queue_t *queue, switch_event_t **pop, int remove)
224{
225 int i, j;
226
227 switch_mutex_lock(queue->mutex);
228
229 if (queue->idx == 0) {
230 switch_mutex_unlock(queue->mutex);
231 return SWITCH_STATUS_FALSE;
232 }
233
234 for (j = 0; j < queue->idx; j++) {
235 const char *uuid = switch_event_get_header(queue->data[j], "unique-id")switch_event_get_header_idx(queue->data[j], "unique-id", -
1)
;
236 if (uuid && (remove == 2 || !check_caller_outbound_call(uuid))) {
237 if (remove) {
238 *pop = queue->data[j];
239 } else {
240 switch_event_dup(pop, queue->data[j]);
241 }
242 break;
243 }
244 }
245
246 if (j == queue->idx) {
247 switch_mutex_unlock(queue->mutex);
248 return SWITCH_STATUS_FALSE;
249 }
250
251 if (remove) {
252 for (i = j+1; i < queue->idx; i++) {
253 queue->data[i-1] = queue->data[i];
254 queue->data[i] = NULL((void*)0);
255 change_pos(queue->data[i-1], i);
256 }
257
258 queue->idx--;
259 }
260
261 switch_mutex_unlock(queue->mutex);
262 return SWITCH_STATUS_SUCCESS;
263}
264
265/*!\brief Remove matching event from queue
266 *
267 * Each event in the queue will be checked to see whether it has a
268 * header equal to name whose value is equal to val. If it does, that
269 * event will be returned unless the event is for an outbound caller.
270 * If name starts with '+' or remove == 2 then forcing is enabled and
271 * the event will be returned in any case. If remove > 0 then the
272 * returned event will be removed from the queue and the remaining
273 * elements shifted to make them contiguous.
274 */
275static switch_status_t fifo_queue_pop_nameval(fifo_queue_t *queue, const char *name, const char *val, switch_event_t **pop, int remove)
276{
277 int i, j, force = 0;
278
279 switch_mutex_lock(queue->mutex);
280
281 if (name && *name == '+') {
282 name++;
283 force = 1;
284 }
285
286 if (remove == 2) {
287 force = 1;
288 }
289
290 if (queue->idx == 0 || zstr(name)_zstr(name) || zstr(val)_zstr(val)) {
291 switch_mutex_unlock(queue->mutex);
292 return SWITCH_STATUS_FALSE;
293 }
294
295 for (j = 0; j < queue->idx; j++) {
296 const char *j_val = switch_event_get_header(queue->data[j], name)switch_event_get_header_idx(queue->data[j], name, -1);
297 const char *uuid = switch_event_get_header(queue->data[j], "unique-id")switch_event_get_header_idx(queue->data[j], "unique-id", -
1)
;
298 if (j_val && val && !strcmp(j_val, val)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(j_val) && __builtin_constant_p (val) && (__s1_len
= __builtin_strlen (j_val), __s2_len = __builtin_strlen (val
), (!((size_t)(const void *)((j_val) + 1) - (size_t)(const void
*)(j_val) == 1) || __s1_len >= 4) && (!((size_t)(
const void *)((val) + 1) - (size_t)(const void *)(val) == 1) ||
__s2_len >= 4)) ? __builtin_strcmp (j_val, val) : (__builtin_constant_p
(j_val) && ((size_t)(const void *)((j_val) + 1) - (size_t
)(const void *)(j_val) == 1) && (__s1_len = __builtin_strlen
(j_val), __s1_len < 4) ? (__builtin_constant_p (val) &&
((size_t)(const void *)((val) + 1) - (size_t)(const void *)(
val) == 1) ? __builtin_strcmp (j_val, val) : (__extension__ (
{ const unsigned char *__s2 = (const unsigned char *) (const char
*) (val); int __result = (((const unsigned char *) (const char
*) (j_val))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
j_val))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
j_val))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (j_val
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
val) && ((size_t)(const void *)((val) + 1) - (size_t)
(const void *)(val) == 1) && (__s2_len = __builtin_strlen
(val), __s2_len < 4) ? (__builtin_constant_p (j_val) &&
((size_t)(const void *)((j_val) + 1) - (size_t)(const void *
)(j_val) == 1) ? __builtin_strcmp (j_val, val) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (j_val); int __result = (((const unsigned char *) (const
char *) (val))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (val))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (val))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (val))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(j_val, val)))); })
&& (force || !check_caller_outbound_call(uuid))) {
299 if (remove) {
300 *pop = queue->data[j];
301 } else {
302 switch_event_dup(pop, queue->data[j]);
303 }
304 break;
305 }
306 }
307
308 if (j == queue->idx) {
309 switch_mutex_unlock(queue->mutex);
310 return SWITCH_STATUS_FALSE;
311 }
312
313 if (remove) {
314 for (i = j+1; i < queue->idx; i++) {
315 queue->data[i-1] = queue->data[i];
316 queue->data[i] = NULL((void*)0);
317 change_pos(queue->data[i-1], i);
318 }
319
320 queue->idx--;
321 }
322
323 switch_mutex_unlock(queue->mutex);
324
325 return SWITCH_STATUS_SUCCESS;
326}
327
328/*!\brief Destroy event with given uuid and remove it from queue
329 *
330 * Elements of the queue are searched until a matching uuid is found.
331 * That uuid is then destroyed and removed from the queue. The
332 * remaining elements are shifted to make them contiguous.
333 */
334static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid)
335{
336 int i, j;
337
338 switch_mutex_lock(queue->mutex);
339
340 if (queue->idx == 0 || zstr(uuid)_zstr(uuid)) {
341 switch_mutex_unlock(queue->mutex);
342 return SWITCH_STATUS_FALSE;
343 }
344
345 for (j = 0; j < queue->idx; j++) {
346 const char *j_uuid = switch_event_get_header(queue->data[j], "unique-id")switch_event_get_header_idx(queue->data[j], "unique-id", -
1)
;
347 if (j_uuid && !strcmp(j_uuid, uuid)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(j_uuid) && __builtin_constant_p (uuid) && (
__s1_len = __builtin_strlen (j_uuid), __s2_len = __builtin_strlen
(uuid), (!((size_t)(const void *)((j_uuid) + 1) - (size_t)(const
void *)(j_uuid) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)((uuid) + 1) - (size_t)(const void *)(uuid) ==
1) || __s2_len >= 4)) ? __builtin_strcmp (j_uuid, uuid) :
(__builtin_constant_p (j_uuid) && ((size_t)(const void
*)((j_uuid) + 1) - (size_t)(const void *)(j_uuid) == 1) &&
(__s1_len = __builtin_strlen (j_uuid), __s1_len < 4) ? (__builtin_constant_p
(uuid) && ((size_t)(const void *)((uuid) + 1) - (size_t
)(const void *)(uuid) == 1) ? __builtin_strcmp (j_uuid, uuid)
: (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (uuid); int __result = (((const unsigned
char *) (const char *) (j_uuid))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (j_uuid))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (j_uuid))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (j_uuid))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (uuid) && ((size_t)(const
void *)((uuid) + 1) - (size_t)(const void *)(uuid) == 1) &&
(__s2_len = __builtin_strlen (uuid), __s2_len < 4) ? (__builtin_constant_p
(j_uuid) && ((size_t)(const void *)((j_uuid) + 1) - (
size_t)(const void *)(j_uuid) == 1) ? __builtin_strcmp (j_uuid
, uuid) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (j_uuid); int __result = (((
const unsigned char *) (const char *) (uuid))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (uuid))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (uuid))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (uuid))[3] - __s2[3]); } } __result; }))))
: __builtin_strcmp (j_uuid, uuid)))); })
) {
348 switch_event_destroy(&queue->data[j]);
349 break;
350 }
351 }
352
353 if (j == queue->idx) {
354 switch_mutex_unlock(queue->mutex);
355 return SWITCH_STATUS_FALSE;
356 }
357
358 for (i = j+1; i < queue->idx; i++) {
359 queue->data[i-1] = queue->data[i];
360 queue->data[i] = NULL((void*)0);
361 change_pos(queue->data[i-1], i);
362 }
363
364 queue->idx--;
365
366 switch_mutex_unlock(queue->mutex);
367
368 return SWITCH_STATUS_SUCCESS;
369}
370
371/*!\struct fifo_node
372 *
373 * \var fifo_node::outbound_name
374 * \brief Name of fifo in caller ID
375 *
376 * For the ringall strategy, this value is a prefix for the
377 * caller ID shown to agents. If the value starts with '=' then the
378 * actual caller ID is replaced completely.
379 *
380 * For the enterprise strategy, this value is used instead of the
381 * queue name in the caller ID.
382 */
383struct fifo_node {
384 char *name;
385 switch_mutex_t *mutex;
386 switch_mutex_t *update_mutex;
387 fifo_queue_t *fifo_list[MAX_PRI10];
388 switch_hash_t *consumer_hash;
389 int outbound_priority;
390 int caller_count;
391 int consumer_count;
392 int ring_consumer_count;
393 int member_count;
394 switch_time_t start_waiting;
395 uint32_t importance;
396 switch_thread_rwlock_t *rwlock;
397 switch_memory_pool_t *pool;
398 int has_outbound;
399 int ready;
400 long busy;
401 int is_static;
402 int outbound_per_cycle;
403 int outbound_per_cycle_min;
404 char *outbound_name;
405 outbound_strategy_t outbound_strategy;
406 int ring_timeout;
407 int default_lag;
408 char *domain_name;
409 int retry_delay;
410 struct fifo_node *next;
411};
412
413typedef struct fifo_node fifo_node_t;
414
415static void fifo_caller_add(fifo_node_t *node, switch_core_session_t *session);
416static void fifo_caller_del(const char *uuid);
417
418struct callback {
419 char *buf;
420 size_t len;
421 int matches;
422};
423typedef struct callback callback_t;
424
425static const char *print_strategy(outbound_strategy_t s)
426{
427 switch (s) {
428 case NODE_STRATEGY_RINGALL:
429 return "ringall";
430 case NODE_STRATEGY_ENTERPRISE:
431 return "enterprise";
432 default:
433 break;
434 }
435
436 return "invalid";
437}
438
439static outbound_strategy_t parse_strategy(const char *name)
440{
441 if (!strcasecmp(name, "ringall")) {
442 return NODE_STRATEGY_RINGALL;
443 }
444
445 if (!strcasecmp(name, "enterprise")) {
446 return NODE_STRATEGY_ENTERPRISE;
447 }
448
449 return NODE_STRATEGY_INVALID;
450}
451
452static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
453{
454 callback_t *cbt = (callback_t *) pArg;
455
456 switch_copy_string(cbt->buf, argv[0], cbt->len);
457 cbt->matches++;
458 return 0;
459}
460
461/*!\brief Handler for consumer DTMF
462 *
463 * When `fifo_consumer_exit_key` is pressed by the consumer we hangup
464 * on the caller (unless we've put the caller on hold). The default
465 * exit key is '*'.
466 *
467 * When the consumer presses '0' we put both legs on hold and play
468 * hold music as follows. To the caller we play `fifo_music` or the
469 * default hold music for the channel. To the consumer we play
470 * `fifo_hold_music`, or `fifo_music`, or the default hold music for
471 * the channel. The consumer can press '0' again to pick up the
472 * caller from hold.
473 */
474static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
475{
476 switch_core_session_t *bleg = (switch_core_session_t *) buf;
477
478 switch (itype) {
479 case SWITCH_INPUT_TYPE_DTMF:
480 {
481 switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
482 switch_channel_t *bchan = switch_core_session_get_channel(bleg);
483 switch_channel_t *channel = switch_core_session_get_channel(session);
484
485 if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_BRIDGE_ORIGINATOR)) {
486 const char *consumer_exit_key = switch_channel_get_variable(channel, "fifo_consumer_exit_key")switch_channel_get_variable_dup(channel, "fifo_consumer_exit_key"
, SWITCH_TRUE, -1)
;
487 if (!consumer_exit_key) consumer_exit_key = "*";
488 if (dtmf->digit == *consumer_exit_key) {
489 switch_channel_hangup(bchan, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(bchan, "mod_fifo.c", (const char
*)__func__, 489, SWITCH_CAUSE_NORMAL_CLEARING)
;
490 return SWITCH_STATUS_BREAK;
491 } else if (dtmf->digit == '0') {
492 const char *moh_a = NULL((void*)0), *moh_b = NULL((void*)0);
493
494 if (!(moh_b = switch_channel_get_variable(bchan, "fifo_music")switch_channel_get_variable_dup(bchan, "fifo_music", SWITCH_TRUE
, -1)
)) {
495 moh_b = switch_channel_get_hold_music(bchan);
496 }
497
498 if (!(moh_a = switch_channel_get_variable(channel, "fifo_hold_music")switch_channel_get_variable_dup(channel, "fifo_hold_music", SWITCH_TRUE
, -1)
)) {
499 if (!(moh_a = switch_channel_get_variable(channel, "fifo_music")switch_channel_get_variable_dup(channel, "fifo_music", SWITCH_TRUE
, -1)
)) {
500 moh_a = switch_channel_get_hold_music(channel);
501 }
502 }
503
504 switch_ivr_soft_hold(session, "0", moh_a, moh_b);
505 return SWITCH_STATUS_IGNORE;
506 }
507 }
508 }
509 break;
510 default:
511 break;
512 }
513
514 return SWITCH_STATUS_SUCCESS;
515}
516
517/*!\brief Handler for caller DTMF
518 *
519 * The channel variable `fifo_caller_exit_key` can be set to one or
520 * more digits that when pressed will cause the caller to exit from
521 * the fifo. We'll return via a single character in `buf` the digit
522 * that was pressed (not null-terminated).
523 */
524static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
525{
526 switch (itype) {
527 case SWITCH_INPUT_TYPE_DTMF:
528 {
529 switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
530 switch_channel_t *channel = switch_core_session_get_channel(session);
531 const char *caller_exit_key = switch_channel_get_variable(channel, "fifo_caller_exit_key")switch_channel_get_variable_dup(channel, "fifo_caller_exit_key"
, SWITCH_TRUE, -1)
;
532
533 if (caller_exit_key && dtmf->digit && strchr(caller_exit_key, dtmf->digit)(__extension__ (__builtin_constant_p (dtmf->digit) &&
!__builtin_constant_p (caller_exit_key) && (dtmf->
digit) == '\0' ? (char *) __rawmemchr (caller_exit_key, dtmf->
digit) : __builtin_strchr (caller_exit_key, dtmf->digit)))
) {
534 char *bp = buf;
535 *bp = dtmf->digit;
536 return SWITCH_STATUS_BREAK;
537 }
538 }
539 break;
540 default:
541 break;
542 }
543
544 return SWITCH_STATUS_SUCCESS;
545}
546
547static inline void cleanup_fifo_arg(const char **s) {
548 if (!zstr(*s)_zstr(*s) && !strcasecmp(*s, "undef")) *s = NULL((void*)0);
549}
550
551static int node_caller_count(fifo_node_t *node)
552{
553 int i, len = 0;
554
555 for (i = 0; i < MAX_PRI10; i++) {
556 len += fifo_queue_size(node->fifo_list[i]);
557 }
558
559 return len;
560}
561
562static void node_remove_uuid(fifo_node_t *node, const char *uuid)
563{
564 int i = 0;
565
566 for (i = 0; i < MAX_PRI10; i++) {
567 fifo_queue_popfly(node->fifo_list[i], uuid);
568 }
569
570 if (!node_caller_count(node)) {
571 node->start_waiting = 0;
572 }
573
574 fifo_caller_del(uuid);
575
576 return;
577}
578
579/*!\struct fifo_chime_data
580 *
581 * \var fifo_chime_data::list
582 * A list of strings representing things to play back to the caller
583 * while they are waiting to be connected with an agent.
584 */
585#define MAX_CHIME25 25
586struct fifo_chime_data {
587 char *list[MAX_CHIME25];
588 int total;
589 int index;
590 time_t next;
591 int freq;
592 int abort;
593 time_t orbit_timeout;
594 int do_orbit;
595 char *orbit_exten;
596 char *orbit_dialplan;
597 char *orbit_context;
598 char *exit_key;
599};
600
601typedef struct fifo_chime_data fifo_chime_data_t;
602
603/*!\brief Enforce the `fifo_orbit_timeout`
604 *
605 * If the caller has been waiting longer than the `fifo_orbit_timeout`
606 * we break out so the orbit can do something else with the call.
607 */
608static switch_status_t chime_read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
609{
610 fifo_chime_data_t *cd = (fifo_chime_data_t *) user_data;
611
612 if (cd && cd->orbit_timeout && switch_epoch_time_now(NULL((void*)0)) >= cd->orbit_timeout) {
613 cd->do_orbit = 1;
614 return SWITCH_STATUS_BREAK;
615 }
616
617 return SWITCH_STATUS_SUCCESS;
618}
619
620/*!\brief Handle chimes and timeouts for callers
621 *
622 * Play back the chimes in order spaced out by the given `freq` while
623 * ensuring that we don't exceed the `orbit_timeout`.
624 */
625static switch_status_t caller_read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
626{
627 fifo_chime_data_t *cd = (fifo_chime_data_t *) user_data;
628
629 if (!cd) {
630 return SWITCH_STATUS_SUCCESS;
631 }
632
633 if (cd->total && switch_epoch_time_now(NULL((void*)0)) >= cd->next) {
634 if (cd->index == MAX_CHIME25 || cd->index == cd->total || !cd->list[cd->index]) {
635 cd->index = 0;
636 }
637
638 if (cd->list[cd->index]) {
639 switch_input_args_t args = { 0 };
640 char buf[25] = "";
641 switch_status_t status;
642
643 args.input_callback = moh_on_dtmf;
644 args.buf = buf;
645 args.buflen = sizeof(buf);
646 args.read_frame_callback = chime_read_frame_callback;
647 args.user_data = user_data;
648
649 status = switch_ivr_play_file(session, NULL((void*)0), cd->list[cd->index], &args);
650
651 if (cd->exit_key && *buf && strchr(cd->exit_key, *buf)(__extension__ (__builtin_constant_p (*buf) && !__builtin_constant_p
(cd->exit_key) && (*buf) == '\0' ? (char *) __rawmemchr
(cd->exit_key, *buf) : __builtin_strchr (cd->exit_key,
*buf)))
) {
652 cd->abort = 1;
653 return SWITCH_STATUS_BREAK;
654 }
655
656 if (status != SWITCH_STATUS_SUCCESS) {
657 return SWITCH_STATUS_BREAK;
658 }
659
660 cd->next = switch_epoch_time_now(NULL((void*)0)) + cd->freq;
661 cd->index++;
662 }
663 }
664
665 return chime_read_frame_callback(session, frame, user_data);
666}
667
668/*!\brief Handler for waiting consumers
669 *
670 * In `user_data` we'll be passed an array of fifo_nodes representing
671 * the fifos for which this consumer will accept calls. If any of
672 * those fifos have a caller in them, we break out so we can accept
673 * the call.
674 */
675static switch_status_t consumer_read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
676{
677 fifo_node_t *node, **node_list = (fifo_node_t **) user_data;
678 int total = 0, i = 0;
679
680 for (i = 0;; i++) {
681 if (!(node = node_list[i])) {
682 break;
683 }
684 total += node_caller_count(node);
685 }
686
687 if (total) {
688 return SWITCH_STATUS_BREAK;
689 }
690
691 return SWITCH_STATUS_SUCCESS;
692}
693
694static struct {
695 switch_hash_t *caller_orig_hash;
696 switch_hash_t *consumer_orig_hash;
697 switch_hash_t *bridge_hash;
698 switch_hash_t *use_hash;
699 switch_mutex_t *use_mutex;
700 switch_mutex_t *caller_orig_mutex;
701 switch_mutex_t *consumer_orig_mutex;
702 switch_mutex_t *bridge_mutex;
703 switch_hash_t *fifo_hash;
704 switch_mutex_t *mutex;
705 switch_mutex_t *sql_mutex;
706 switch_memory_pool_t *pool;
707 int running;
708 switch_event_node_t *node;
709 char hostname[256];
710 char *dbname;
711 char odbc_dsn[1024];
712 int node_thread_running;
713 switch_odbc_handle_t *master_odbc;
714 int threads;
715 switch_thread_t *node_thread;
716 int debug;
717 struct fifo_node *nodes;
718 char *pre_trans_execute;
719 char *post_trans_execute;
720 char *inner_pre_trans_execute;
721 char *inner_post_trans_execute;
722 switch_sql_queue_manager_t *qm;
723 int allow_transcoding;
724 switch_bool_t delete_all_members_on_startup;
725 outbound_strategy_t default_strategy;
726} globals;
727
728static int fifo_dec_use_count(const char *outbound_id)
729{
730 int r = 0, *count;
731
732 switch_mutex_lock(globals.use_mutex);
733 if ((count = (int *) switch_core_hash_find(globals.use_hash, outbound_id))) {
734 if (*count > 0) {
735 r = --(*count);
736 }
737 }
738 switch_mutex_unlock(globals.use_mutex);
739
740 return r;
741}
742
743static int fifo_get_use_count(const char *outbound_id)
744{
745 int r = 0, *count;
746
747 switch_mutex_lock(globals.use_mutex);
748 if ((count = (int *) switch_core_hash_find(globals.use_hash, outbound_id))) {
749 r = *count;
750 }
751 switch_mutex_unlock(globals.use_mutex);
752
753 return r;
754}
755
756static int fifo_inc_use_count(const char *outbound_id)
757{
758 int r = 0, *count;
759
760 switch_mutex_lock(globals.use_mutex);
761 if (!(count = (int *) switch_core_hash_find(globals.use_hash, outbound_id))) {
762 count = switch_core_alloc(globals.pool, sizeof(int))switch_core_perform_alloc(globals.pool, sizeof(int), "mod_fifo.c"
, (const char *)__func__, 762)
;
763 switch_core_hash_insert(globals.use_hash, outbound_id, count)switch_core_hash_insert_destructor(globals.use_hash, outbound_id
, count, ((void*)0))
;
764 }
765
766 r = ++(*count);
767
768 switch_mutex_unlock(globals.use_mutex);
769
770 return r;
771}
772
773static void fifo_init_use_count(void)
774{
775 switch_mutex_lock(globals.use_mutex);
776 if (globals.use_hash) {
777 switch_core_hash_destroy(&globals.use_hash);
778 }
779 switch_core_hash_init(&globals.use_hash)switch_core_hash_init_case(&globals.use_hash, SWITCH_TRUE
)
;
780 switch_mutex_unlock(globals.use_mutex);
781}
782
783static int check_caller_outbound_call(const char *key)
784{
785 int x = 0;
786
787 if (!key) return x;
788
789 switch_mutex_lock(globals.caller_orig_mutex);
790 x = !!switch_core_hash_find(globals.caller_orig_hash, key);
791 switch_mutex_unlock(globals.caller_orig_mutex);
792 return x;
793}
794
795static void add_caller_outbound_call(const char *key, switch_call_cause_t *cancel_cause)
796{
797 if (!key) return;
798
799 switch_mutex_lock(globals.caller_orig_mutex);
800 switch_core_hash_insert(globals.caller_orig_hash, key, cancel_cause)switch_core_hash_insert_destructor(globals.caller_orig_hash, key
, cancel_cause, ((void*)0))
;
801 switch_mutex_unlock(globals.caller_orig_mutex);
802}
803
804static void del_caller_outbound_call(const char *key)
805{
806 if (!key) return;
807
808 switch_mutex_lock(globals.caller_orig_mutex);
809 switch_core_hash_delete(globals.caller_orig_hash, key);
810 switch_mutex_unlock(globals.caller_orig_mutex);
811}
812
813static void cancel_caller_outbound_call(const char *key, switch_call_cause_t cause)
814{
815 switch_call_cause_t *cancel_cause = NULL((void*)0);
816
817 if (!key) return;
818
819 switch_mutex_lock(globals.caller_orig_mutex);
820 if ((cancel_cause = (switch_call_cause_t *) switch_core_hash_find(globals.caller_orig_hash, key))) {
821 *cancel_cause = cause;
822 }
823 switch_mutex_unlock(globals.caller_orig_mutex);
824}
825
826static int check_bridge_call(const char *key)
827{
828 int x = 0;
829
830 if (!key) return x;
831
832 switch_mutex_lock(globals.bridge_mutex);
833 x = !!switch_core_hash_find(globals.bridge_hash, key);
834 switch_mutex_unlock(globals.bridge_mutex);
835 return x;
836}
837
838static void add_bridge_call(const char *key)
839{
840 static int marker = 1;
841 if (!key) return;
842
843 switch_mutex_lock(globals.bridge_mutex);
844 switch_core_hash_insert(globals.bridge_hash, key, (void *)&marker)switch_core_hash_insert_destructor(globals.bridge_hash, key, (
void *)&marker, ((void*)0))
;
845 switch_mutex_unlock(globals.bridge_mutex);
846}
847
848static void del_bridge_call(const char *key)
849{
850 switch_mutex_lock(globals.bridge_mutex);
851 switch_core_hash_delete(globals.bridge_hash, key);
852 switch_mutex_unlock(globals.bridge_mutex);
853}
854
855static int check_consumer_outbound_call(const char *key)
856{
857 int x = 0;
858
859 if (!key) return x;
860
861 switch_mutex_lock(globals.consumer_orig_mutex);
862 x = !!switch_core_hash_find(globals.consumer_orig_hash, key);
863 switch_mutex_unlock(globals.consumer_orig_mutex);
864 return x;
865}
866
867static void add_consumer_outbound_call(const char *key, switch_call_cause_t *cancel_cause)
868{
869 if (!key) return;
870
871 switch_mutex_lock(globals.consumer_orig_mutex);
872 switch_core_hash_insert(globals.consumer_orig_hash, key, cancel_cause)switch_core_hash_insert_destructor(globals.consumer_orig_hash
, key, cancel_cause, ((void*)0))
;
873 switch_mutex_unlock(globals.consumer_orig_mutex);
874}
875
876static void del_consumer_outbound_call(const char *key)
877{
878 if (!key) return;
879
880 switch_mutex_lock(globals.consumer_orig_mutex);
881 switch_core_hash_delete(globals.consumer_orig_hash, key);
882 switch_mutex_unlock(globals.consumer_orig_mutex);
883}
884
885static void cancel_consumer_outbound_call(const char *key, switch_call_cause_t cause)
886{
887 switch_call_cause_t *cancel_cause = NULL((void*)0);
888
889 if (!key) return;
890
891 switch_mutex_lock(globals.consumer_orig_mutex);
892 if ((cancel_cause = (switch_call_cause_t *) switch_core_hash_find(globals.consumer_orig_hash, key))) {
893 *cancel_cause = cause;
894 }
895 switch_mutex_unlock(globals.consumer_orig_mutex);
896}
897
898switch_cache_db_handle_t *fifo_get_db_handle(void)
899{
900 switch_cache_db_handle_t *dbh = NULL((void*)0);
901 char *dsn;
902
903 if (!zstr(globals.odbc_dsn)_zstr(globals.odbc_dsn)) {
904 dsn = globals.odbc_dsn;
905 } else {
906 dsn = globals.dbname;
907 }
908
909 if (switch_cache_db_get_db_handle_dsn(&dbh, dsn)_switch_cache_db_get_db_handle_dsn(&dbh, dsn, "mod_fifo.c"
, (const char *)__func__, 909)
!= SWITCH_STATUS_SUCCESS) {
910 dbh = NULL((void*)0);
911 }
912
913 return dbh;
914}
915
916static switch_status_t fifo_execute_sql_queued(char **sqlp, switch_bool_t sql_already_dynamic, switch_bool_t block)
917{
918 int index = 1;
919 char *sql;
920
921 switch_assert(sqlp && *sqlp)((sqlp && *sqlp) ? (void) (0) : __assert_fail ("sqlp && *sqlp"
, "mod_fifo.c", 921, __PRETTY_FUNCTION__))
;
922 sql = *sqlp;
923
924 if (switch_stristr("insert", sql)) {
925 index = 0;
926 }
927
928 if (block) {
929 switch_sql_queue_manager_push_confirm(globals.qm, sql, index, !sql_already_dynamic);
930 } else {
931 switch_sql_queue_manager_push(globals.qm, sql, index, !sql_already_dynamic);
932 }
933
934 if (sql_already_dynamic) {
935 *sqlp = NULL((void*)0);
936 }
937
938 return SWITCH_STATUS_SUCCESS;
939}
940#if 0
941static switch_status_t fifo_execute_sql(char *sql, switch_mutex_t *mutex)
942{
943 switch_cache_db_handle_t *dbh = NULL((void*)0);
944 switch_status_t status = SWITCH_STATUS_FALSE;
945
946 if (mutex) {
947 switch_mutex_lock(mutex);
948 }
949
950 if (!(dbh = fifo_get_db_handle())) {
951 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 951
, ((void*)0)
, SWITCH_LOG_ERROR, "Error Opening DB\n");
952 goto end;
953 }
954
955 if (globals.debug > 1) switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 955
, ((void*)0)
, SWITCH_LOG_CRIT, "sql: %s\n", sql);
956
957 status = switch_cache_db_execute_sql(dbh, sql, NULL((void*)0));
958
959 end:
960
961 switch_cache_db_release_db_handle(&dbh);
962
963 if (mutex) {
964 switch_mutex_unlock(mutex);
965 }
966
967 return status;
968}
969#endif
970
971static switch_bool_t fifo_execute_sql_callback(switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata)
972{
973 switch_bool_t ret = SWITCH_FALSE;
974 char *errmsg = NULL((void*)0);
975 switch_cache_db_handle_t *dbh = NULL((void*)0);
976
977 if (mutex) {
978 switch_mutex_lock(mutex);
979 }
980
981 if (!(dbh = fifo_get_db_handle())) {
982 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 982
, ((void*)0)
, SWITCH_LOG_ERROR, "Error Opening DB\n");
983 goto end;
984 }
985
986 if (globals.debug > 1) switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 986
, ((void*)0)
, SWITCH_LOG_CRIT, "sql: %s\n", sql);
987
988 switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, &errmsg);
989
990 if (errmsg) {
991 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 991
, ((void*)0)
, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
992 free(errmsg);
993 }
994
995 end:
996
997 switch_cache_db_release_db_handle(&dbh);
998
999 if (mutex) {
1000 switch_mutex_unlock(mutex);
1001 }
1002
1003 return ret;
1004}
1005
1006static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mutex_t *mutex)
1007{
1008 fifo_node_t *node;
1009 int x = 0;
1010 switch_memory_pool_t *pool;
1011 char outbound_count[80] = "";
1012 callback_t cbt = { 0 };
1013 char *sql = NULL((void*)0);
1014 if (!globals.running) {
1015 return NULL((void*)0);
1016 }
1017
1018 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "mod_fifo.c", (
const char *)__func__, 1018)
;
1019
1020 node = switch_core_alloc(pool, sizeof(*node))switch_core_perform_alloc(pool, sizeof(*node), "mod_fifo.c", (
const char *)__func__, 1020)
;
1021 node->pool = pool;
1022 node->outbound_strategy = globals.default_strategy;
1023 node->name = switch_core_strdup(node->pool, name)switch_core_perform_strdup(node->pool, name, "mod_fifo.c",
(const char *)__func__, 1023)
;
1024
1025 if (!strchr(name, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(name) && ('@') == '\0' ? (char *) __rawmemchr (name
, '@') : __builtin_strchr (name, '@')))
) {
1026 node->domain_name = switch_core_strdup(node->pool, switch_core_get_domain(SWITCH_FALSE))switch_core_perform_strdup(node->pool, switch_core_get_domain
(SWITCH_FALSE), "mod_fifo.c", (const char *)__func__, 1026)
;
1027 }
1028
1029 for (x = 0; x < MAX_PRI10; x++) {
1030 fifo_queue_create(&node->fifo_list[x], 1000, node->pool);
1031 switch_assert(node->fifo_list[x])((node->fifo_list[x]) ? (void) (0) : __assert_fail ("node->fifo_list[x]"
, "mod_fifo.c", 1031, __PRETTY_FUNCTION__))
;
1032 }
1033
1034 switch_core_hash_init(&node->consumer_hash)switch_core_hash_init_case(&node->consumer_hash, SWITCH_TRUE
)
;
1035 switch_thread_rwlock_create(&node->rwlock, node->pool);
1036 switch_mutex_init(&node->mutex, SWITCH_MUTEX_NESTED0x1, node->pool);
1037 switch_mutex_init(&node->update_mutex, SWITCH_MUTEX_NESTED0x1, node->pool);
1038 cbt.buf = outbound_count;
1039 cbt.len = sizeof(outbound_count);
1040 sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name);
1041 fifo_execute_sql_callback(mutex, sql, sql2str_callback, &cbt);
1042 node->member_count = atoi(outbound_count);
1043 node->has_outbound = (node->member_count > 0) ? 1 : 0;
1044 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1045
1046 node->importance = importance;
1047
1048 switch_mutex_lock(globals.mutex);
1049
1050 switch_core_hash_insert(globals.fifo_hash, name, node)switch_core_hash_insert_destructor(globals.fifo_hash, name, node
, ((void*)0))
;
1051 node->next = globals.nodes;
1052 globals.nodes = node;
1053 switch_mutex_unlock(globals.mutex);
1054
1055 return node;
1056}
1057
1058static int node_idle_consumers(fifo_node_t *node)
1059{
1060 switch_hash_index_t *hi;
1061 void *val;
1062 const void *var;
1063 switch_core_session_t *session;
1064 switch_channel_t *channel;
1065 int total = 0;
1066
1067 switch_mutex_lock(node->mutex);
1068 for (hi = switch_core_hash_first(node->consumer_hash)switch_core_hash_first_iter(node->consumer_hash, ((void*)0
))
; hi; hi = switch_core_hash_next(&hi)) {
1069 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
1070 session = (switch_core_session_t *) val;
1071 channel = switch_core_session_get_channel(session);
1072 if (!switch_channel_test_flag(channel, CF_BRIDGED)) {
1073 total++;
1074 }
1075 }
1076 switch_mutex_unlock(node->mutex);
1077
1078 return total;
1079}
1080
1081struct call_helper {
1082 char *uuid;
1083 char *node_name;
1084 char *originate_string;
1085 int timeout;
1086 switch_memory_pool_t *pool;
1087};
1088
1089#define MAX_ROWS250 250
1090struct callback_helper {
1091 int need;
1092 switch_memory_pool_t *pool;
1093 struct call_helper *rows[MAX_ROWS250];
1094 int rowcount;
1095 int ready;
1096};
1097
1098/*!\brief Handle unbridging of manually tracked calls
1099 */
1100static void do_unbridge(switch_core_session_t *consumer_session, switch_core_session_t *caller_session)
1101{
1102 switch_channel_t *consumer_channel = switch_core_session_get_channel(consumer_session);
1103 switch_channel_t *caller_channel = NULL((void*)0);
1104
1105 if (caller_session) {
1106 caller_channel = switch_core_session_get_channel(caller_session);
1107 }
1108
1109 if (switch_channel_test_app_flag_key(FIFO_APP_KEY"mod_fifo", consumer_channel, FIFO_APP_BRIDGE_TAG)) {
1110 char date[80] = "";
1111 switch_time_exp_t tm;
1112 switch_time_t ts = switch_micro_time_now();
1113 switch_size_t retsize;
1114 long epoch_start = 0, epoch_end = 0;
1115 const char *epoch_start_a = NULL((void*)0);
1116 char *sql;
1117 switch_event_t *event;
1118 const char *outbound_id = NULL((void*)0);
1119 int use_count = 0;
1120
1121 switch_channel_clear_app_flag_key(FIFO_APP_KEY"mod_fifo", consumer_channel, FIFO_APP_BRIDGE_TAG);
1122 switch_channel_set_variable(consumer_channel, "fifo_bridged", NULL)switch_channel_set_variable_var_check(consumer_channel, "fifo_bridged"
, ((void*)0), SWITCH_TRUE)
;
1123
1124 if ((outbound_id = switch_channel_get_variable(consumer_channel, "fifo_outbound_uuid")switch_channel_get_variable_dup(consumer_channel, "fifo_outbound_uuid"
, SWITCH_TRUE, -1)
)) {
1125 use_count = fifo_get_use_count(outbound_id);
1126 }
1127
1128 switch_time_exp_lt(&tm, ts);
1129 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
1130
1131 sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(consumer_session));
1132 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE);
1133
1134 switch_channel_set_variable(consumer_channel, "fifo_status", "WAITING")switch_channel_set_variable_var_check(consumer_channel, "fifo_status"
, "WAITING", SWITCH_TRUE)
;
1135 switch_channel_set_variable(consumer_channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(consumer_channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
1136
1137 if (caller_channel) {
1138 switch_channel_set_variable(caller_channel, "fifo_status", "DONE")switch_channel_set_variable_var_check(caller_channel, "fifo_status"
, "DONE", SWITCH_TRUE)
;
1139 switch_channel_set_variable(caller_channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(caller_channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
1140 }
1141
1142 if ((epoch_start_a = switch_channel_get_variable(consumer_channel, "fifo_epoch_start_bridge")switch_channel_get_variable_dup(consumer_channel, "fifo_epoch_start_bridge"
, SWITCH_TRUE, -1)
)) {
1143 epoch_start = atol(epoch_start_a);
1144 }
1145
1146 epoch_end = (long)switch_epoch_time_now(NULL((void*)0));
1147
1148 switch_channel_set_variable_printf(consumer_channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
1149 switch_channel_set_variable_printf(consumer_channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
1150
1151 if (caller_channel) {
1152 switch_channel_set_variable_printf(caller_channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
1153 switch_channel_set_variable_printf(caller_channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
1154 }
1155
1156 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1156, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1157 switch_channel_event_set_data(consumer_channel, event);
1158 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME"manual_calls");
1159 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-stop");
1160 if (outbound_id) {
1161 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
1162 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", use_count);
1163 }
1164 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1164, &event, ((void*)0))
;
1165 }
1166
1167 if (caller_channel) {
1168 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1168, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1169 switch_channel_event_set_data(caller_channel, event);
1170 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME"manual_calls");
1171 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-stop");
1172 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1172, &event, ((void*)0))
;
1173 }
1174 }
1175
1176 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1176, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1177 switch_channel_event_set_data(consumer_channel, event);
1178 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME"manual_calls");
1179 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_stop");
1180 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1180, &event, ((void*)0))
;
1181 }
1182 }
1183}
1184
1185/*!\brief Handle session messages for manually tracked calls
1186 */
1187static switch_status_t messagehook (switch_core_session_t *session, switch_core_session_message_t *msg)
1188{
1189 switch_event_t *event;
1190 switch_core_session_t *caller_session = NULL((void*)0), *consumer_session = NULL((void*)0);
1191 switch_channel_t *caller_channel = NULL((void*)0), *consumer_channel = NULL((void*)0);
1192 const char *outbound_id;
1193 char *sql;
1194
1195 consumer_session = session;
1196 consumer_channel = switch_core_session_get_channel(consumer_session);
1197 outbound_id = switch_channel_get_variable(consumer_channel, "fifo_outbound_uuid")switch_channel_get_variable_dup(consumer_channel, "fifo_outbound_uuid"
, SWITCH_TRUE, -1)
;
1198
1199 if (!outbound_id) return SWITCH_STATUS_SUCCESS;
1200
1201 switch (msg->message_id) {
1202 case SWITCH_MESSAGE_INDICATE_BRIDGE:
1203 case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
1204 if (msg->numeric_arg == 42) {
1205 /* See audio_bridge_thread() for source of 42 constant. */
1206 /* When a session is interrupted to execute an application
1207 (e.g. by uuid_execute) we need to tell everything in FS
1208 to unbridge the channel (e.g. to turn on the
1209 jitterbuffer) but we need mod_fifo not to see the
1210 unbridge because we don't want fifo to stop tracking
1211 the call. So this magic number is a complete hack to
1212 make this happen. So we ignore it here and simply fall
1213 through. */
1214 goto end;
1215 }
1216 if ((caller_session = switch_core_session_locate(msg->string_arg)switch_core_session_perform_locate(msg->string_arg, "mod_fifo.c"
, (const char *)__func__, 1216)
)) {
1217 caller_channel = switch_core_session_get_channel(caller_session);
1218 if (msg->message_id == SWITCH_MESSAGE_INDICATE_BRIDGE) {
1219 cancel_consumer_outbound_call(outbound_id, SWITCH_CAUSE_ORIGINATOR_CANCEL);
1220 switch_core_session_soft_lock(caller_session, 5);
1221 } else {
1222 switch_core_session_soft_unlock(caller_session);
1223 }
1224 }
1225 break;
1226 case SWITCH_MESSAGE_INDICATE_DISPLAY:
1227 sql = switch_mprintf("update fifo_bridge set caller_caller_id_name='%q', caller_caller_id_number='%q' where consumer_uuid='%q'",
1228 switch_str_nil(msg->string_array_arg[0])(msg->string_array_arg[0] ? msg->string_array_arg[0] : ""
)
,
1229 switch_str_nil(msg->string_array_arg[1])(msg->string_array_arg[1] ? msg->string_array_arg[1] : ""
)
,
1230 switch_core_session_get_uuid(session));
1231 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE);
1232 goto end;
1233 default:
1234 goto end;
1235 }
1236
1237 switch (msg->message_id) {
1238 case SWITCH_MESSAGE_INDICATE_BRIDGE:
1239 {
1240 long epoch_start = 0;
1241 char date[80] = "";
1242 switch_time_t ts;
1243 switch_time_exp_t tm;
1244 switch_size_t retsize;
1245 const char *ced_name, *ced_number, *cid_name, *cid_number, *outbound_id;
1246
1247 if (switch_channel_test_app_flag_key(FIFO_APP_KEY"mod_fifo", consumer_channel, FIFO_APP_BRIDGE_TAG)) {
1248 goto end;
1249 }
1250
1251 switch_channel_set_app_flag_key(FIFO_APP_KEY"mod_fifo", consumer_channel, FIFO_APP_BRIDGE_TAG);
1252
1253 switch_channel_set_variable(consumer_channel, "fifo_bridged", "true")switch_channel_set_variable_var_check(consumer_channel, "fifo_bridged"
, "true", SWITCH_TRUE)
;
1254 switch_channel_set_variable(consumer_channel, "fifo_manual_bridge", "true")switch_channel_set_variable_var_check(consumer_channel, "fifo_manual_bridge"
, "true", SWITCH_TRUE)
;
1255 switch_channel_set_variable(consumer_channel, "fifo_role", "consumer")switch_channel_set_variable_var_check(consumer_channel, "fifo_role"
, "consumer", SWITCH_TRUE)
;
1256 outbound_id = switch_channel_get_variable(consumer_channel, "fifo_outbound_uuid")switch_channel_get_variable_dup(consumer_channel, "fifo_outbound_uuid"
, SWITCH_TRUE, -1)
;
1257
1258 if (caller_channel) {
1259 switch_channel_set_variable(caller_channel, "fifo_role", "caller")switch_channel_set_variable_var_check(caller_channel, "fifo_role"
, "caller", SWITCH_TRUE)
;
1260 switch_process_import(consumer_session, caller_channel, "fifo_caller_consumer_import",
1261 switch_channel_get_variable(consumer_channel, "fifo_import_prefix")switch_channel_get_variable_dup(consumer_channel, "fifo_import_prefix"
, SWITCH_TRUE, -1)
);
1262 switch_process_import(caller_session, consumer_channel, "fifo_consumer_caller_import",
1263 switch_channel_get_variable(caller_channel, "fifo_import_prefix")switch_channel_get_variable_dup(caller_channel, "fifo_import_prefix"
, SWITCH_TRUE, -1)
);
1264 }
1265
1266 ced_name = switch_channel_get_variable(consumer_channel, "callee_id_name")switch_channel_get_variable_dup(consumer_channel, "callee_id_name"
, SWITCH_TRUE, -1)
;
1267 ced_number = switch_channel_get_variable(consumer_channel, "callee_id_number")switch_channel_get_variable_dup(consumer_channel, "callee_id_number"
, SWITCH_TRUE, -1)
;
1268
1269 cid_name = switch_channel_get_variable(consumer_channel, "caller_id_name")switch_channel_get_variable_dup(consumer_channel, "caller_id_name"
, SWITCH_TRUE, -1)
;
1270 cid_number = switch_channel_get_variable(consumer_channel, "caller_id_number")switch_channel_get_variable_dup(consumer_channel, "caller_id_number"
, SWITCH_TRUE, -1)
;
1271
1272 if (switch_channel_direction(consumer_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
1273 if (zstr(ced_name)_zstr(ced_name) || !strcmp(ced_name, cid_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(ced_name) && __builtin_constant_p (cid_name) &&
(__s1_len = __builtin_strlen (ced_name), __s2_len = __builtin_strlen
(cid_name), (!((size_t)(const void *)((ced_name) + 1) - (size_t
)(const void *)(ced_name) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((cid_name) + 1) - (size_t)(const void
*)(cid_name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (
ced_name, cid_name) : (__builtin_constant_p (ced_name) &&
((size_t)(const void *)((ced_name) + 1) - (size_t)(const void
*)(ced_name) == 1) && (__s1_len = __builtin_strlen (
ced_name), __s1_len < 4) ? (__builtin_constant_p (cid_name
) && ((size_t)(const void *)((cid_name) + 1) - (size_t
)(const void *)(cid_name) == 1) ? __builtin_strcmp (ced_name,
cid_name) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (cid_name); int __result = (
((const unsigned char *) (const char *) (ced_name))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (ced_name))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (ced_name))[2] - __s2
[2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (ced_name))[3] - __s2
[3]); } } __result; }))) : (__builtin_constant_p (cid_name) &&
((size_t)(const void *)((cid_name) + 1) - (size_t)(const void
*)(cid_name) == 1) && (__s2_len = __builtin_strlen (
cid_name), __s2_len < 4) ? (__builtin_constant_p (ced_name
) && ((size_t)(const void *)((ced_name) + 1) - (size_t
)(const void *)(ced_name) == 1) ? __builtin_strcmp (ced_name,
cid_name) : (- (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (ced_name); int __result
= (((const unsigned char *) (const char *) (cid_name))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (cid_name))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (cid_name))[2] - __s2
[2]); if (__s2_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (cid_name))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp (ced_name, cid_name
)))); })
) {
1274 ced_name = ced_number;
1275 }
1276
1277 if (zstr(ced_number)_zstr(ced_number) || !strcmp(ced_number, cid_number)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(ced_number) && __builtin_constant_p (cid_number) &&
(__s1_len = __builtin_strlen (ced_number), __s2_len = __builtin_strlen
(cid_number), (!((size_t)(const void *)((ced_number) + 1) - (
size_t)(const void *)(ced_number) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((cid_number) + 1) - (size_t)(const
void *)(cid_number) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(ced_number, cid_number) : (__builtin_constant_p (ced_number
) && ((size_t)(const void *)((ced_number) + 1) - (size_t
)(const void *)(ced_number) == 1) && (__s1_len = __builtin_strlen
(ced_number), __s1_len < 4) ? (__builtin_constant_p (cid_number
) && ((size_t)(const void *)((cid_number) + 1) - (size_t
)(const void *)(cid_number) == 1) ? __builtin_strcmp (ced_number
, cid_number) : (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (cid_number); int __result
= (((const unsigned char *) (const char *) (ced_number))[0] -
__s2[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (ced_number))[1] -
__s2[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (ced_number))[2] -
__s2[2]); if (__s1_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (ced_number))[3] -
__s2[3]); } } __result; }))) : (__builtin_constant_p (cid_number
) && ((size_t)(const void *)((cid_number) + 1) - (size_t
)(const void *)(cid_number) == 1) && (__s2_len = __builtin_strlen
(cid_number), __s2_len < 4) ? (__builtin_constant_p (ced_number
) && ((size_t)(const void *)((ced_number) + 1) - (size_t
)(const void *)(ced_number) == 1) ? __builtin_strcmp (ced_number
, cid_number) : (- (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (ced_number); int __result
= (((const unsigned char *) (const char *) (cid_number))[0] -
__s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (cid_number))[1] -
__s2[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (cid_number))[2] -
__s2[2]); if (__s2_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (cid_number))[3] -
__s2[3]); } } __result; })))) : __builtin_strcmp (ced_number
, cid_number)))); })
) {
1278 ced_name = switch_channel_get_variable(consumer_channel, "destination_number")switch_channel_get_variable_dup(consumer_channel, "destination_number"
, SWITCH_TRUE, -1)
;
1279 ced_number = ced_name;
1280 }
1281 } else {
1282 ced_name = cid_name;
1283 ced_number = cid_number;
1284 }
1285
1286 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1286, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1287 switch_channel_event_set_data(consumer_channel, event);
1288 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME"manual_calls");
1289 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-start");
1290 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", ced_name);
1291 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", ced_number);
1292 if (outbound_id) {
1293 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
1294 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
1295 }
1296 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1296, &event, ((void*)0))
;
1297 }
1298
1299 if (caller_channel) {
1300 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1300, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1301 switch_channel_event_set_data(caller_channel, event);
1302 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME"manual_calls");
1303 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-start");
1304 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1304, &event, ((void*)0))
;
1305 }
1306
1307 sql = switch_mprintf("insert into fifo_bridge "
1308 "(fifo_name,caller_uuid,caller_caller_id_name,caller_caller_id_number,consumer_uuid,consumer_outgoing_uuid,bridge_start) "
1309 "values ('%q','%q','%q','%q','%q','%q',%ld)",
1310 MANUAL_QUEUE_NAME"manual_calls",
1311 switch_core_session_get_uuid(caller_session),
1312 ced_name,
1313 ced_number,
1314 switch_core_session_get_uuid(session),
1315 switch_str_nil(outbound_id)(outbound_id ? outbound_id : ""),
1316 (long) switch_epoch_time_now(NULL((void*)0))
1317 );
1318 } else {
1319 sql = switch_mprintf("insert into fifo_bridge "
1320 "(fifo_name,caller_uuid,caller_caller_id_name,caller_caller_id_number,consumer_uuid,consumer_outgoing_uuid,bridge_start) "
1321 "values ('%q','%q','%q','%q','%q','%q',%ld)",
1322 MANUAL_QUEUE_NAME"manual_calls",
1323 (msg->string_arg && strchr(msg->string_arg, '-')(__extension__ (__builtin_constant_p ('-') && !__builtin_constant_p
(msg->string_arg) && ('-') == '\0' ? (char *) __rawmemchr
(msg->string_arg, '-') : __builtin_strchr (msg->string_arg
, '-')))
) ? msg->string_arg : "00000000-0000-0000-0000-000000000000",
1324 ced_name,
1325 ced_number,
1326 switch_core_session_get_uuid(session),
1327 switch_str_nil(outbound_id)(outbound_id ? outbound_id : ""),
1328 (long) switch_epoch_time_now(NULL((void*)0))
1329 );
1330 }
1331
1332 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE);
1333
1334 epoch_start = (long)switch_epoch_time_now(NULL((void*)0));
1335
1336 ts = switch_micro_time_now();
1337 switch_time_exp_lt(&tm, ts);
1338 epoch_start = (long)switch_epoch_time_now(NULL((void*)0));
1339 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
1340 switch_channel_set_variable(consumer_channel, "fifo_status", "TALKING")switch_channel_set_variable_var_check(consumer_channel, "fifo_status"
, "TALKING", SWITCH_TRUE)
;
1341 if (caller_session) {
1342 switch_channel_set_variable(consumer_channel, "fifo_target", switch_core_session_get_uuid(caller_session))switch_channel_set_variable_var_check(consumer_channel, "fifo_target"
, switch_core_session_get_uuid(caller_session), SWITCH_TRUE)
;
1343 }
1344 switch_channel_set_variable(consumer_channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(consumer_channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
1345 switch_channel_set_variable_printf(consumer_channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
1346 switch_channel_set_variable(consumer_channel, "fifo_role", "consumer")switch_channel_set_variable_var_check(consumer_channel, "fifo_role"
, "consumer", SWITCH_TRUE)
;
1347
1348 if (caller_channel) {
1349 switch_channel_set_variable(caller_channel, "fifo_status", "TALKING")switch_channel_set_variable_var_check(caller_channel, "fifo_status"
, "TALKING", SWITCH_TRUE)
;
1350 switch_channel_set_variable(caller_channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(caller_channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
1351 switch_channel_set_variable_printf(caller_channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
1352 switch_channel_set_variable(caller_channel, "fifo_target", switch_core_session_get_uuid(session))switch_channel_set_variable_var_check(caller_channel, "fifo_target"
, switch_core_session_get_uuid(session), SWITCH_TRUE)
;
1353 switch_channel_set_variable(caller_channel, "fifo_role", "caller")switch_channel_set_variable_var_check(caller_channel, "fifo_role"
, "caller", SWITCH_TRUE)
;
1354 }
1355 }
1356 break;
1357 case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
1358 {
1359 do_unbridge(consumer_session, caller_session);
1360 }
1361 break;
1362 default:
1363 break;
1364 }
1365
1366 end:
1367
1368 if (caller_session) {
1369 switch_core_session_rwunlock(caller_session);
1370 }
1371
1372 return SWITCH_STATUS_SUCCESS;
1373}
1374
1375/*!\brief Create calls to outbound members with ringall strategy
1376 *
1377 * A fifo node has been selected for us and we've been given a list of
1378 * outbound members to ring. We're going to pick a single caller by
1379 * searching through the fifo node queues in order of priority
1380 * (`fifo_priority`) from lowest to highest. We'll look first for
1381 * callers with fifo_vip=true. Finding none, we'll consider the
1382 * plebs.
1383 *
1384 * Once we have a caller to service, we'll set fifo_bridge_uuid for
1385 * that caller to let the fifo application in on our decision. Our
1386 * job being done, we'll let the fifo application deal with the
1387 * remaining details.
1388 */
1389static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thread, void *obj)
1390{
1391 struct callback_helper *cbh = (struct callback_helper *) obj;
1392 char *node_name;
1393 int i = 0;
1394 int timeout = 0;
1395 switch_stream_handle_t stream = { 0 };
1396 switch_stream_handle_t stream2 = { 0 };
1397 fifo_node_t *node = NULL((void*)0);
1398 char *originate_string = NULL((void*)0);
1399 switch_event_t *ovars = NULL((void*)0);
1400 switch_status_t status;
1401 switch_core_session_t *session = NULL((void*)0);
1402 switch_call_cause_t cause = SWITCH_CAUSE_NONE;
1403 char *app_name = NULL((void*)0), *arg = NULL((void*)0);
1404 switch_caller_extension_t *extension = NULL((void*)0);
1405 switch_channel_t *channel;
1406 char *caller_id_name = NULL((void*)0), *cid_num = NULL((void*)0), *id = NULL((void*)0);
1407 switch_event_t *pop = NULL((void*)0), *pop_dup = NULL((void*)0);
1408 fifo_queue_t *q = NULL((void*)0);
1409 int x = 0;
1410 switch_event_t *event;
1411 switch_uuid_t uuid;
1412 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH256 + 1];
1413 switch_call_cause_t cancel_cause = 0;
1414 char *uuid_list = NULL((void*)0);
1415 int total = 0;
1416 const char *codec;
1417 struct call_helper *rows[MAX_ROWS250] = { 0 };
1418 int rowcount = 0;
1419 switch_memory_pool_t *pool;
1420 char *export = NULL((void*)0);
1421
1422 switch_mutex_lock(globals.mutex);
1423 globals.threads++;
1424 switch_mutex_unlock(globals.mutex);
1425
1426 if (!globals.running) goto dpool;
1427
1428 switch_uuid_get(&uuid);
1429 switch_uuid_format(uuid_str, &uuid);
1430
1431 if (!cbh->rowcount) {
1432 goto end;
1433 }
1434
1435 node_name = cbh->rows[0]->node_name;
1436
1437 switch_mutex_lock(globals.mutex);
1438 if ((node = switch_core_hash_find(globals.fifo_hash, node_name))) {
1439 switch_thread_rwlock_rdlock(node->rwlock);
1440 }
1441 switch_mutex_unlock(globals.mutex);
1442
1443 if (!node) {
1444 goto end;
1445 }
1446
1447 for (i = 0; i < cbh->rowcount; i++) {
1448 struct call_helper *h = cbh->rows[i];
1449
1450 if (check_consumer_outbound_call(h->uuid) || check_bridge_call(h->uuid)) {
1451 continue;
1452 }
1453
1454 rows[rowcount++] = h;
1455 add_consumer_outbound_call(h->uuid, &cancel_cause);
1456 total++;
1457 }
1458
1459 for (i = 0; i < rowcount; i++) {
1460 struct call_helper *h = rows[i];
1461 cbh->rows[i] = h;
1462 }
1463
1464 cbh->rowcount = rowcount;
1465
1466 cbh->ready = 1;
1467
1468 if (!total) {
1469 goto end;
1470 }
1471
1472 switch_mutex_lock(node->update_mutex);
1473 node->busy = 0;
1474 node->ring_consumer_count = 1;
1475 switch_mutex_unlock(node->update_mutex);
1476
1477 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "mod_fifo.c", 1477, __PRETTY_FUNCTION__)); memset(stream.data
, 0, 1024); stream.end = stream.data; stream.data_size = 1024
; stream.write_function = switch_console_stream_write; stream
.raw_write_function = switch_console_stream_raw_write; stream
.alloc_len = 1024; stream.alloc_chunk = 1024
;
1478 SWITCH_STANDARD_STREAM(stream2)memset(&stream2, 0, sizeof(stream2)); stream2.data = malloc
(1024); ((stream2.data) ? (void) (0) : __assert_fail ("stream2.data"
, "mod_fifo.c", 1478, __PRETTY_FUNCTION__)); memset(stream2.data
, 0, 1024); stream2.end = stream2.data; stream2.data_size = 1024
; stream2.write_function = switch_console_stream_write; stream2
.raw_write_function = switch_console_stream_raw_write; stream2
.alloc_len = 1024; stream2.alloc_chunk = 1024
;
1479
1480 switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1480, &ovars, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
1481 switch_assert(ovars)((ovars) ? (void) (0) : __assert_fail ("ovars", "mod_fifo.c",
1481, __PRETTY_FUNCTION__))
;
1482
1483 for (i = 0; i < cbh->rowcount; i++) {
1484 struct call_helper *h = cbh->rows[i];
1485 char *parsed = NULL((void*)0);
1486 int use_ent = 0;
1487 char *expanded_originate_string = switch_event_expand_headers(ovars, h->originate_string)switch_event_expand_headers_check(ovars, h->originate_string
, ((void*)0), ((void*)0), 0)
;
1488
1489 switch_assert(expanded_originate_string)((expanded_originate_string) ? (void) (0) : __assert_fail ("expanded_originate_string"
, "mod_fifo.c", 1489, __PRETTY_FUNCTION__))
;
1490 if (strstr(expanded_originate_string, "user/")) {
1491 switch_event_create_brackets(expanded_originate_string, '<', '>', ',', &ovars, &parsed, SWITCH_TRUE);
1492 use_ent = 1;
1493 } else {
1494 switch_event_create_brackets(expanded_originate_string, '{', '}', ',', &ovars, &parsed, SWITCH_TRUE);
1495 }
1496
1497 switch_event_del_header(ovars, "fifo_outbound_uuid")switch_event_del_header_val(ovars, "fifo_outbound_uuid", ((void
*)0))
;
1498
1499 if (!h->timeout) h->timeout = node->ring_timeout;
1500 if (timeout < h->timeout) timeout = h->timeout;
1501
1502 if (use_ent) {
1503 stream.write_function(&stream, "{ignore_early_media=true,outbound_redirect_fatal=true,leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s}%s%s",
1504 h->timeout, h->uuid, node->name,
1505 parsed ? parsed : expanded_originate_string, (i == cbh->rowcount - 1) ? "" : SWITCH_ENT_ORIGINATE_DELIM":_:");
1506 } else {
1507 stream.write_function(&stream, "[leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s]%s,",
1508 h->timeout, h->uuid, node->name, parsed ? parsed : expanded_originate_string);
1509 }
1510
1511 stream2.write_function(&stream2, "%s,", h->uuid);
1512 switch_safe_free(parsed)if (parsed) {free(parsed);parsed=((void*)0);};
1513
1514 if (expanded_originate_string != h->originate_string) {
1515 switch_safe_free(expanded_originate_string)if (expanded_originate_string) {free(expanded_originate_string
);expanded_originate_string=((void*)0);}
;
1516 }
1517 }
1518
1519 originate_string = (char *) stream.data;
1520
1521 uuid_list = (char *) stream2.data;
1522
1523 if (uuid_list) {
1524 end_of(uuid_list)*(*uuid_list == '\0' ? uuid_list : uuid_list + strlen(uuid_list
) - 1)
= '\0';
1525 }
1526
1527 if (!timeout) timeout = 60;
1528
1529 pop = pop_dup = NULL((void*)0);
1530
1531 for (x = 0; x < MAX_PRI10; x++) {
1532 q = node->fifo_list[x];
1533 if (fifo_queue_pop_nameval(q, "variable_fifo_vip", "true", &pop_dup, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS && pop_dup) {
1534 pop = pop_dup;
1535 break;
1536 }
1537 }
1538
1539 if (!pop) {
1540 for (x = 0; x < MAX_PRI10; x++) {
1541 q = node->fifo_list[x];
1542 if (fifo_queue_pop(node->fifo_list[x], &pop_dup, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS && pop_dup) {
1543 pop = pop_dup;
1544 break;
1545 }
1546 }
1547 }
1548
1549 if (!pop) {
1550 goto end;
1551 }
1552
1553 if (!switch_event_get_header(ovars, "origination_caller_id_name")switch_event_get_header_idx(ovars, "origination_caller_id_name"
, -1)
) {
1554 if ((caller_id_name = switch_event_get_header(pop, "caller-caller-id-name")switch_event_get_header_idx(pop, "caller-caller-id-name", -1))) {
1555 if (!zstr(node->outbound_name)_zstr(node->outbound_name)) {
1556 if ( node->outbound_name[0] == '=' ) {
1557 switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", "%s", node->outbound_name + 1);
1558 } else {
1559 switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", "(%s) %s", node->outbound_name, caller_id_name);
1560 }
1561 } else {
1562 switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_name", caller_id_name);
1563 }
1564 }
1565 }
1566
1567 if (!switch_event_get_header(ovars, "origination_caller_id_number")switch_event_get_header_idx(ovars, "origination_caller_id_number"
, -1)
) {
1568 if ((cid_num = switch_event_get_header(pop, "caller-caller-id-number")switch_event_get_header_idx(pop, "caller-caller-id-number", -
1)
)) {
1569 switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "origination_caller_id_number", cid_num);
1570 }
1571 }
1572
1573 if ((id = switch_event_get_header(pop, "unique-id")switch_event_get_header_idx(pop, "unique-id", -1))) {
1574 switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "fifo_bridge_uuid", id);
1575 }
1576
1577 switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "fifo_originate_uuid", uuid_str);
1578
1579 if ((export = switch_event_get_header(pop, "variable_fifo_export")switch_event_get_header_idx(pop, "variable_fifo_export", -1))) {
1580 int argc;
1581 char *argv[100] = { 0 };
1582 char *mydata = strdup(export)(__extension__ (__builtin_constant_p (export) && ((size_t
)(const void *)((export) + 1) - (size_t)(const void *)(export
) == 1) ? (((const char *) (export))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (export)
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, export, __len
); __retval; })) : __strdup (export)))
;
1583 char *tmp;
1584
1585 argc = switch_split(mydata, ',', argv)switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof
(argv[0])))
;
1586
1587 for (x = 0; x < argc; x++) {
1588 char *name = switch_mprintf("variable_%s", argv[x]);
1589
1590 if ((tmp = switch_event_get_header(pop, name)switch_event_get_header_idx(pop, name, -1))) {
1591 switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, argv[x], tmp);
1592 }
1593
1594 free(name);
1595 }
1596
1597 switch_safe_free(mydata)if (mydata) {free(mydata);mydata=((void*)0);};
1598 }
1599
1600 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1600, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1601 switch_core_session_t *session;
1602 if (id && (session = switch_core_session_locate(id)switch_core_session_perform_locate(id, "mod_fifo.c", (const char
*)__func__, 1602)
)) {
1603 switch_channel_t *channel = switch_core_session_get_channel(session);
1604
1605 switch_channel_set_variable(channel, "fifo_originate_uuid", uuid_str)switch_channel_set_variable_var_check(channel, "fifo_originate_uuid"
, uuid_str, SWITCH_TRUE)
;
1606 switch_channel_event_set_data(channel, event);
1607 switch_core_session_rwunlock(session);
1608 }
1609
1610 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node->name);
1611 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "pre-dial");
1612 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "ringall");
1613 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller-uuid", id);
1614 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
1615 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID-List", uuid_list);
1616
1617 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1617, &event, ((void*)0))
;
1618 }
1619
1620 for (i = 0; i < cbh->rowcount; i++) {
1621 struct call_helper *h = cbh->rows[i];
1622 char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count+1 where uuid='%s'", h->uuid);
1623
1624 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
1625 }
1626
1627 if (!globals.allow_transcoding && !switch_true(switch_event_get_header(pop, "variable_fifo_allow_transcoding")switch_event_get_header_idx(pop, "variable_fifo_allow_transcoding"
, -1)
) &&
1628 (codec = switch_event_get_header(pop, "variable_rtp_use_codec_name")switch_event_get_header_idx(pop, "variable_rtp_use_codec_name"
, -1)
)) {
1629 const char *rate = switch_event_get_header(pop, "variable_rtp_use_codec_rate")switch_event_get_header_idx(pop, "variable_rtp_use_codec_rate"
, -1)
;
1630 const char *ptime = switch_event_get_header(pop, "variable_rtp_use_codec_ptime")switch_event_get_header_idx(pop, "variable_rtp_use_codec_ptime"
, -1)
;
1631 char nstr[256] = "";
1632
1633 if (strcasecmp(codec, "PCMU") && strcasecmp(codec, "PCMA")) {
1634 switch_snprintf(nstr, sizeof(nstr), "%s@%si@%sh,PCMU@%si,PCMA@%si", codec, ptime, rate, ptime, ptime);
1635 } else {
1636 switch_snprintf(nstr, sizeof(nstr), "%s@%si@%sh", codec, ptime, rate);
1637 }
1638
1639 switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "absolute_codec_string", nstr);
1640 }
1641
1642 add_caller_outbound_call(id, &cancel_cause);
1643
1644 if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 1644
, ((void*)0)
, SWITCH_LOG_DEBUG, "%s dialing: %s\n", node->name, originate_string);
1645
1646 status = switch_ivr_originate(NULL((void*)0), &session, &cause, originate_string, timeout, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), ovars, SOF_NONE, &cancel_cause);
1647
1648 del_caller_outbound_call(id);
1649
1650 if (status != SWITCH_STATUS_SUCCESS || cause != SWITCH_CAUSE_SUCCESS) {
1651 const char *acceptable = "false";
1652
1653 switch (cause) {
1654 case SWITCH_CAUSE_ORIGINATOR_CANCEL:
1655 case SWITCH_CAUSE_PICKED_OFF:
1656 {
1657 acceptable = "true";
1658
1659 for (i = 0; i < cbh->rowcount; i++) {
1660 struct call_helper *h = cbh->rows[i];
1661 char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1 "
1662 "where uuid='%q' and ring_count > 0", h->uuid);
1663 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
1664 }
1665 }
1666 break;
1667 default:
1668 {
1669 for (i = 0; i < cbh->rowcount; i++) {
1670 struct call_helper *h = cbh->rows[i];
1671 char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1, "
1672 "outbound_fail_count=outbound_fail_count+1, "
1673 "outbound_fail_total_count = outbound_fail_total_count+1, "
1674 "next_avail=%ld + lag + 1 where uuid='%q' and ring_count > 0",
1675 (long) switch_epoch_time_now(NULL((void*)0)) + node->retry_delay, h->uuid);
1676 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
1677 }
1678 }
1679 }
1680
1681 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1681, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1682 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node->name);
1683 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "post-dial");
1684 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "ringall");
1685 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller-uuid", id);
1686 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "result", "failure");
1687 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "acceptable", acceptable);
1688 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "cause", switch_channel_cause2str(cause));
1689 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
1690 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID-List", uuid_list);
1691 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1691, &event, ((void*)0))
;
1692 }
1693
1694 goto end;
1695 }
1696
1697 channel = switch_core_session_get_channel(session);
1698
1699 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1699, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1700 switch_channel_event_set_data(channel, event);
1701 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node->name);
1702 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "post-dial");
1703 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "ringall");
1704 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller-uuid", id);
1705 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID", switch_channel_get_variable(channel, "fifo_outbound_uuid")switch_channel_get_variable_dup(channel, "fifo_outbound_uuid"
, SWITCH_TRUE, -1)
);
1706 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID-List", uuid_list);
1707 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "result", "success");
1708 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
1709 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1709, &event, ((void*)0))
;
1710 }
1711
1712 switch_channel_set_variable(channel, "fifo_pop_order", NULL)switch_channel_set_variable_var_check(channel, "fifo_pop_order"
, ((void*)0), SWITCH_TRUE)
;
1713
1714 app_name = "fifo";
1715 arg = switch_core_session_sprintf(session, "%s out nowait", node_name);
1716 extension = switch_caller_extension_new(session, app_name, arg);
1717 switch_caller_extension_add_application(session, extension, app_name, arg);
1718 switch_channel_set_caller_extension(channel, extension);
1719 switch_channel_set_state(channel, CS_EXECUTE)switch_channel_perform_set_state(channel, "mod_fifo.c", (const
char *)__func__, 1719, CS_EXECUTE)
;
1720 switch_channel_wait_for_state(channel, NULL((void*)0), CS_EXECUTE);
1721 switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 5000, NULL((void*)0));
1722
1723 switch_core_session_rwunlock(session);
1724
1725 for (i = 0; i < cbh->rowcount; i++) {
1726 struct call_helper *h = cbh->rows[i];
1727 char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1 where uuid='%q' and ring_count > 0", h->uuid);
1728 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
1729 }
1730
1731 end:
1732
1733 cbh->ready = 1;
1734
1735 if (node) {
1736 switch_mutex_lock(node->update_mutex);
1737 node->ring_consumer_count = 0;
1738 node->busy = 0;
1739 switch_mutex_unlock(node->update_mutex);
1740 switch_thread_rwlock_unlock(node->rwlock);
1741 }
1742
1743 for (i = 0; i < cbh->rowcount; i++) {
1744 struct call_helper *h = cbh->rows[i];
1745 del_consumer_outbound_call(h->uuid);
1746 }
1747
1748 switch_safe_free(originate_string)if (originate_string) {free(originate_string);originate_string
=((void*)0);}
;
1749 switch_safe_free(uuid_list)if (uuid_list) {free(uuid_list);uuid_list=((void*)0);};
1750
1751 if (ovars) {
1752 switch_event_destroy(&ovars);
1753 }
1754
1755 if (pop_dup) {
1756 switch_event_destroy(&pop_dup);
1757 }
1758
1759 dpool:
1760
1761 pool = cbh->pool;
1762 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "mod_fifo.c"
, (const char *)__func__, 1762)
;
1763
1764 switch_mutex_lock(globals.mutex);
1765 globals.threads--;
1766 switch_mutex_unlock(globals.mutex);
1767
1768 return NULL((void*)0);
1769}
1770
1771/*!\brief Send a call to an outbound member with the enterprise strategy
1772 *
1773 * A fifo and an outbound member have been picked out for us and our
1774 * job is to create a channel to the member and deliver that channel
1775 * into the `fifo <fifo> out` application.
1776 *
1777 * We haven't picked a caller yet, and we won't do so here. We'll let
1778 * the fifo application take care of that work.
1779 */
1780static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t *thread, void *obj)
1781{
1782 struct call_helper *h = (struct call_helper *) obj;
1783
1784 switch_core_session_t *session = NULL((void*)0);
1785 switch_channel_t *channel;
1786 switch_call_cause_t cause = SWITCH_CAUSE_NONE;
1787 switch_caller_extension_t *extension = NULL((void*)0);
1788 char *app_name, *arg = NULL((void*)0), *originate_string = NULL((void*)0);
1789 const char *member_wait = NULL((void*)0);
1790 fifo_node_t *node = NULL((void*)0);
1791 switch_event_t *ovars = NULL((void*)0);
1792 switch_status_t status = SWITCH_STATUS_FALSE;
1793 switch_event_t *event = NULL((void*)0);
1794 char *sql = NULL((void*)0);
1795 char *expanded_originate_string = NULL((void*)0);
1796
1797 if (!globals.running) return NULL((void*)0);
1798
1799 switch_mutex_lock(globals.mutex);
1800 globals.threads++;
1801 switch_mutex_unlock(globals.mutex);
1802
1803 switch_mutex_lock(globals.mutex);
1804 node = switch_core_hash_find(globals.fifo_hash, h->node_name);
1805 if (node) switch_thread_rwlock_rdlock(node->rwlock);
1806 switch_mutex_unlock(globals.mutex);
1807
1808 if (node) {
1809 switch_mutex_lock(node->update_mutex);
1810 node->ring_consumer_count++;
1811 node->busy = 0;
1812 switch_mutex_unlock(node->update_mutex);
1813 }
1814
1815 switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1815, &ovars, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
1816 switch_assert(ovars)((ovars) ? (void) (0) : __assert_fail ("ovars", "mod_fifo.c",
1816, __PRETTY_FUNCTION__))
;
1817 switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "originate_timeout", "%d", h->timeout);
1818
1819 expanded_originate_string = switch_event_expand_headers(ovars, h->originate_string)switch_event_expand_headers_check(ovars, h->originate_string
, ((void*)0), ((void*)0), 0)
;
1820
1821 if (node && switch_stristr("origination_caller", expanded_originate_string)) {
1822 originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_name='%q',fifo_hangup_check='%q'}%s",
1823 node->name, node->name, expanded_originate_string);
1824 } else {
1825 if (node && !zstr(node->outbound_name)_zstr(node->outbound_name)) {
1826 originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_name='%q',fifo_hangup_check='%q',"
1827 "origination_caller_id_name=Queue,origination_caller_id_number='Queue: %q'}%s",
1828 node->name, node->name, node->outbound_name, expanded_originate_string);
1829 } else if (node) {
1830 originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_name='%q',fifo_hangup_check='%q',"
1831 "origination_caller_id_name=Queue,origination_caller_id_number='Queue: %q'}%s",
1832 node->name, node->name, node->name, expanded_originate_string);
1833 }
1834 }
1835
1836 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1836, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1837 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node ? node->name : "");
1838 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "pre-dial");
1839 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID", h->uuid);
1840 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "enterprise");
1841 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
1842 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1842, &event, ((void*)0))
;
1843 }
1844
1845 sql = switch_mprintf("update fifo_outbound set ring_count=ring_count+1 where uuid='%s'", h->uuid);
1846 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
1847
1848 status = switch_ivr_originate(NULL((void*)0), &session, &cause, originate_string, h->timeout, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), ovars, SOF_NONE, NULL((void*)0));
1849
1850 if (status != SWITCH_STATUS_SUCCESS) {
1851 sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1, "
1852 "outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag + 1 where uuid='%q'",
1853 (long) switch_epoch_time_now(NULL((void*)0)) + (node ? node->retry_delay : 0), h->uuid);
1854 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
1855
1856 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1856, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1857 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node ? node->name : "");
1858 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "post-dial");
1859 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID", h->uuid);
1860 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "enterprise");
1861 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "result", "failure");
1862 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "cause", switch_channel_cause2str(cause));
1863 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
1864 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1864, &event, ((void*)0))
;
1865 }
1866
1867 goto end;
1868 }
1869
1870 channel = switch_core_session_get_channel(session);
1871
1872 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 1872, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
1873 switch_channel_event_set_data(channel, event);
1874 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", node ? node->name : "");
1875 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "post-dial");
1876 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Outbound-UUID", h->uuid);
1877 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "outbound-strategy", "enterprise");
1878 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "result", "success");
1879 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "originate_string", originate_string);
1880 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 1880, &event, ((void*)0))
;
1881 }
1882
1883 if ((member_wait = switch_channel_get_variable(channel, "fifo_member_wait")switch_channel_get_variable_dup(channel, "fifo_member_wait", SWITCH_TRUE
, -1)
) || (member_wait = switch_channel_get_variable(channel, "member_wait")switch_channel_get_variable_dup(channel, "member_wait", SWITCH_TRUE
, -1)
)) {
1884 if (strcasecmp(member_wait, "wait") && strcasecmp(member_wait, "nowait")) {
1885 member_wait = NULL((void*)0);
1886 }
1887 }
1888
1889 switch_channel_set_variable(channel, "fifo_outbound_uuid", h->uuid)switch_channel_set_variable_var_check(channel, "fifo_outbound_uuid"
, h->uuid, SWITCH_TRUE)
;
1890 app_name = "fifo";
1891 arg = switch_core_session_sprintf(session, "%s out %s", h->node_name, member_wait ? member_wait : "wait");
1892 extension = switch_caller_extension_new(session, app_name, arg);
1893 switch_caller_extension_add_application(session, extension, app_name, arg);
1894 switch_channel_set_caller_extension(channel, extension);
1895 switch_channel_set_state(channel, CS_EXECUTE)switch_channel_perform_set_state(channel, "mod_fifo.c", (const
char *)__func__, 1895, CS_EXECUTE)
;
1896 switch_core_session_rwunlock(session);
1897
1898 sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1 where uuid='%q' and ring_count > 0", h->uuid);
1899 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
1900
1901 end:
1902
1903 if ( originate_string ){
1904 switch_safe_free(originate_string)if (originate_string) {free(originate_string);originate_string
=((void*)0);}
;
1905 }
1906
1907 if (expanded_originate_string && expanded_originate_string != h->originate_string) {
1908 switch_safe_free(expanded_originate_string)if (expanded_originate_string) {free(expanded_originate_string
);expanded_originate_string=((void*)0);}
;
1909 }
1910
1911 switch_event_destroy(&ovars);
1912 if (node) {
1913 switch_mutex_lock(node->update_mutex);
1914 if (node->ring_consumer_count-- < 0) {
1915 node->ring_consumer_count = 0;
1916 }
1917 node->busy = 0;
1918 switch_mutex_unlock(node->update_mutex);
1919 switch_thread_rwlock_unlock(node->rwlock);
1920 }
1921 switch_core_destroy_memory_pool(&h->pool)switch_core_perform_destroy_memory_pool(&h->pool, "mod_fifo.c"
, (const char *)__func__, 1921)
;
1922
1923 switch_mutex_lock(globals.mutex);
1924 globals.threads--;
1925 switch_mutex_unlock(globals.mutex);
1926
1927 return NULL((void*)0);
1928}
1929
1930/*!\brief Extract the outbound member results and accumulate them for
1931 * the ringall strategy handler
1932 */
1933static int place_call_ringall_callback(void *pArg, int argc, char **argv, char **columnNames)
1934{
1935 struct callback_helper *cbh = (struct callback_helper *) pArg;
1936 struct call_helper *h;
1937
1938 h = switch_core_alloc(cbh->pool, sizeof(*h))switch_core_perform_alloc(cbh->pool, sizeof(*h), "mod_fifo.c"
, (const char *)__func__, 1938)
;
1939 h->pool = cbh->pool;
1940 h->uuid = switch_core_strdup(h->pool, argv[0])switch_core_perform_strdup(h->pool, argv[0], "mod_fifo.c",
(const char *)__func__, 1940)
;
1941 h->node_name = switch_core_strdup(h->pool, argv[1])switch_core_perform_strdup(h->pool, argv[1], "mod_fifo.c",
(const char *)__func__, 1941)
;
1942 h->originate_string = switch_core_strdup(h->pool, argv[2])switch_core_perform_strdup(h->pool, argv[2], "mod_fifo.c",
(const char *)__func__, 1942)
;
1943 h->timeout = atoi(argv[5]);
1944
1945 cbh->rows[cbh->rowcount++] = h;
1946
1947 if (cbh->rowcount == MAX_ROWS250) return -1;
1948
1949 if (cbh->need) {
1950 cbh->need--;
1951 return cbh->need ? 0 : -1;
1952 }
1953
1954 return 0;
1955}
1956
1957/*!\brief Extract the outbound member results and invoke the
1958 * enterprise strategy handler
1959 */
1960static int place_call_enterprise_callback(void *pArg, int argc, char **argv, char **columnNames)
1961{
1962 int *need = (int *) pArg;
1963
1964 switch_thread_t *thread;
1965 switch_threadattr_t *thd_attr = NULL((void*)0);
1966 switch_memory_pool_t *pool;
1967 struct call_helper *h;
1968
1969 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "mod_fifo.c", (
const char *)__func__, 1969)
;
1970 h = switch_core_alloc(pool, sizeof(*h))switch_core_perform_alloc(pool, sizeof(*h), "mod_fifo.c", (const
char *)__func__, 1970)
;
1971 h->pool = pool;
1972 h->uuid = switch_core_strdup(h->pool, argv[0])switch_core_perform_strdup(h->pool, argv[0], "mod_fifo.c",
(const char *)__func__, 1972)
;
1973 h->node_name = switch_core_strdup(h->pool, argv[1])switch_core_perform_strdup(h->pool, argv[1], "mod_fifo.c",
(const char *)__func__, 1973)
;
1974 h->originate_string = switch_core_strdup(h->pool, argv[2])switch_core_perform_strdup(h->pool, argv[2], "mod_fifo.c",
(const char *)__func__, 1974)
;
1975 h->timeout = atoi(argv[5]);
1976
1977 switch_threadattr_create(&thd_attr, h->pool);
1978 switch_threadattr_detach_set(thd_attr, 1);
1979 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
1980 switch_thread_create(&thread, thd_attr, outbound_enterprise_thread_run, h, h->pool);
1981
1982 (*need)--;
1983
1984 return *need ? 0 : -1;
1985}
1986
1987/*!\brief Find outbound members to call for a given fifo node
1988 *
1989 * We're given a fifo node that has callers to be delivered to agents.
1990 * Our job is to find available outbound members and pass them to the
1991 * appropriate outbound strategy handler.
1992 *
1993 * The ringall strategy handler needs the full list of members to do
1994 * its job, so we first let `place_call_ringall_callback` accumulate
1995 * the results. The enterprise strategy handler can simply take each
1996 * member one at a time, so the `place_call_enterprise_callback` takes
1997 * care of invoking the handler.
1998 *
1999 * Within the ringall call strategy outbound_per_cycle is used to define
2000 * how many agents exactly are assigned to the caller. With ringall if
2001 * multiple callers are calling in and one is answered, because the call
2002 * is assigned to all agents the call to the agents that is not answered
2003 * will be lose raced and the other agents will drop the call before the
2004 * next one will begin to ring. When oubound_per_cycle is used in the
2005 * enterprise strategy it acts as a maximum value for how many agents
2006 * are rung at once on any call, the caller is not assigned to any agent
2007 * until the call is answered. Enterprise only rings the number of phones
2008 * that are needed, so outbound_per_cycle as a max does not give you the
2009 * effect of ringall. outbound_per_cycle_min defines how many agents minimum
2010 * will be rung by an incoming caller through fifo, which can give a ringall
2011 * effect. outbound_per_cycle and outbound_per_cycle_min both default to 1.
2012 *
2013 */
2014static void find_consumers(fifo_node_t *node)
2015{
2016 char *sql;
2017
2018 sql = switch_mprintf("select uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, "
2019 "next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname "
2020 "from fifo_outbound "
2021 "where taking_calls = 1 and (fifo_name = '%q') and ((use_count+ring_count) < simo_count) and (next_avail = 0 or next_avail <= %ld) "
2022 "order by next_avail, outbound_fail_count, outbound_call_count",
2023 node->name, (long) switch_epoch_time_now(NULL((void*)0))
2024 );
2025
2026 switch(node->outbound_strategy) {
2027 case NODE_STRATEGY_ENTERPRISE:
2028 {
2029 int need = node_caller_count(node);
2030
2031 if (node->outbound_per_cycle && node->outbound_per_cycle < need) {
2032 need = node->outbound_per_cycle;
2033 } else if (node->outbound_per_cycle_min && node->outbound_per_cycle_min > need) {
2034 need = node->outbound_per_cycle_min;
2035 }
2036
2037 fifo_execute_sql_callback(globals.sql_mutex, sql, place_call_enterprise_callback, &need);
2038 }
2039 break;
2040 case NODE_STRATEGY_RINGALL:
2041 {
2042 switch_thread_t *thread;
2043 switch_threadattr_t *thd_attr = NULL((void*)0);
2044 struct callback_helper *cbh = NULL((void*)0);
2045 switch_memory_pool_t *pool = NULL((void*)0);
2046
2047 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "mod_fifo.c", (
const char *)__func__, 2047)
;
2048 cbh = switch_core_alloc(pool, sizeof(*cbh))switch_core_perform_alloc(pool, sizeof(*cbh), "mod_fifo.c", (
const char *)__func__, 2048)
;
2049 cbh->pool = pool;
2050 cbh->need = 1;
2051
2052 if (node->outbound_per_cycle != cbh->need) {
2053 cbh->need = node->outbound_per_cycle;
2054 }
2055
2056 fifo_execute_sql_callback(globals.sql_mutex, sql, place_call_ringall_callback, cbh);
2057
2058 if (cbh->rowcount) {
2059 switch_threadattr_create(&thd_attr, cbh->pool);
2060 switch_threadattr_detach_set(thd_attr, 1);
2061 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
2062 switch_thread_create(&thread, thd_attr, outbound_ringall_thread_run, cbh, cbh->pool);
2063 } else {
2064 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "mod_fifo.c"
, (const char *)__func__, 2064)
;
2065 }
2066 }
2067 break;
2068 default:
2069 break;
2070 }
2071
2072 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
2073}
2074
2075/*\brief Continuously attempt to deliver calls to outbound members
2076 *
2077 * For each outbound priority level 1-10, find fifo nodes with a
2078 * matching priority. For each of those nodes with outbound members,
2079 * run `find_consumers()` if the fifo node has calls needing to be
2080 * delivered and not enough ready and waiting inbound consumers.
2081 *
2082 * In the event of nothing needing to be done, each cycle starts at
2083 * priority 1 and ends at priority 10, yielding for one second
2084 * afterward. We also yield after initiating outbound calls, starting
2085 * again where we left off on the next node.
2086 *
2087 * We also take care of cleaning up after nodes queued for deletion.
2088 */
2089static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *obj)
2090{
2091 fifo_node_t *node, *last, *this_node;
2092 int cur_priority = 1;
2093
2094 globals.node_thread_running = 1;
2095
2096 while (globals.node_thread_running == 1) {
2097 int ppl_waiting, consumer_total, idle_consumers, found = 0;
2098
2099 switch_mutex_lock(globals.mutex);
2100
2101 if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2101
, ((void*)0)
, SWITCH_LOG_DEBUG, "Trying priority: %d\n", cur_priority);
2102
2103 last = NULL((void*)0);
2104 node = globals.nodes;
2105
2106 while(node) {
2107 int x = 0;
2108 switch_event_t *pop;
2109
2110 this_node = node;
2111 node = node->next;
2112
2113 if (this_node->ready == 0) {
2114 for (x = 0; x < MAX_PRI10; x++) {
2115 while (fifo_queue_pop(this_node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
2116 const char *caller_uuid = switch_event_get_header(pop, "unique-id")switch_event_get_header_idx(pop, "unique-id", -1);
2117 switch_ivr_kill_uuid(caller_uuid, SWITCH_CAUSE_MANAGER_REQUEST);
2118 switch_event_destroy(&pop);
2119 }
2120 }
2121 }
2122
2123 if (this_node->ready == 0 && switch_thread_rwlock_trywrlock(this_node->rwlock) == SWITCH_STATUS_SUCCESS) {
2124 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2124
, ((void*)0)
, SWITCH_LOG_NOTICE, "%s removed.\n", this_node->name);
2125
2126 for (x = 0; x < MAX_PRI10; x++) {
2127 while (fifo_queue_pop(this_node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
2128 switch_event_destroy(&pop);
2129 }
2130 }
2131
2132 if (last) {
2133 last->next = this_node->next;
2134 } else {
2135 globals.nodes = this_node->next;
2136 }
2137
2138 switch_core_hash_destroy(&this_node->consumer_hash);
2139 switch_mutex_unlock(this_node->mutex);
2140 switch_mutex_unlock(this_node->update_mutex);
2141 switch_thread_rwlock_unlock(this_node->rwlock);
2142 switch_core_destroy_memory_pool(&this_node->pool)switch_core_perform_destroy_memory_pool(&this_node->pool
, "mod_fifo.c", (const char *)__func__, 2142)
;
2143 continue;
2144 }
2145
2146 last = this_node;
2147
2148 if (this_node->outbound_priority == 0) this_node->outbound_priority = 5;
2149
2150 if (this_node->has_outbound && !this_node->busy && this_node->outbound_priority == cur_priority) {
2151 ppl_waiting = node_caller_count(this_node);
2152 consumer_total = this_node->consumer_count;
2153 idle_consumers = node_idle_consumers(this_node);
2154
2155 if (globals.debug) {
2156 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2156
, ((void*)0)
, SWITCH_LOG_DEBUG,
2157 "%s waiting %d consumer_total %d idle_consumers %d ring_consumers %d pri %d\n",
2158 this_node->name, ppl_waiting, consumer_total, idle_consumers, this_node->ring_consumer_count, this_node->outbound_priority);
2159 }
2160
2161 if ((ppl_waiting - this_node->ring_consumer_count > 0) && (!consumer_total || !idle_consumers)) {
2162 found++;
2163 find_consumers(this_node);
2164 switch_yield(1000000)switch_sleep(1000000);;
2165 }
2166 }
2167 }
2168
2169 if (++cur_priority > 10) {
2170 cur_priority = 1;
2171 }
2172
2173 switch_mutex_unlock(globals.mutex);
2174
2175 if (cur_priority == 1) {
2176 switch_yield(1000000)switch_sleep(1000000);;
2177 }
2178 }
2179
2180 globals.node_thread_running = 0;
2181
2182 return NULL((void*)0);
2183}
2184
2185static void start_node_thread(switch_memory_pool_t *pool)
2186{
2187 switch_threadattr_t *thd_attr = NULL((void*)0);
2188
2189 switch_threadattr_create(&thd_attr, pool);
2190 //switch_threadattr_detach_set(thd_attr, 1);
2191 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
2192 switch_thread_create(&globals.node_thread, thd_attr, node_thread_run, pool, pool);
2193}
2194
2195static int stop_node_thread(void)
2196{
2197 switch_status_t st = SWITCH_STATUS_SUCCESS;
2198
2199 globals.node_thread_running = -1;
2200 switch_thread_join(&st, globals.node_thread);
2201
2202 return 0;
2203}
2204
2205static void check_cancel(fifo_node_t *node)
2206{
2207 int ppl_waiting;
2208
2209 if (node->outbound_strategy != NODE_STRATEGY_ENTERPRISE) {
2210 return;
2211 }
2212
2213 ppl_waiting = node_caller_count(node);
2214
2215 if (node->ring_consumer_count > 0 && ppl_waiting < 1) {
2216 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2216
, ((void*)0)
, SWITCH_LOG_DEBUG, "Outbound call count (%d) exceeds required value for queue %s (%d), "
2217 "Ending extraneous calls\n", node->ring_consumer_count, node->name, ppl_waiting);
2218
2219 switch_core_session_hupall_matching_var("fifo_hangup_check", node->name, SWITCH_CAUSE_ORIGINATOR_CANCEL)switch_core_session_hupall_matching_var_ans("fifo_hangup_check"
, node->name, SWITCH_CAUSE_ORIGINATOR_CANCEL, SHT_UNANSWERED
| SHT_ANSWERED)
;
2220 }
2221}
2222
2223static void send_presence(fifo_node_t *node)
2224{
2225 switch_event_t *event;
2226 int wait_count = 0;
2227
2228 if (!globals.running) {
2229 return;
2230 }
2231
2232 if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2232, &event, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2233 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "queue");
2234
2235 if (node->domain_name) {
2236 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s@%s", node->name, node->domain_name);
2237 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", node->name, node->domain_name);
2238 } else {
2239 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", node->name);
2240 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", node->name);
2241 }
2242
2243 if ((wait_count = node_caller_count(node)) > 0) {
2244 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d waiting)", wait_count);
2245 } else {
2246 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Idle");
2247 }
2248 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
2249 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
2250 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
2251 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", 0);
2252
2253 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", wait_count > 0 ? "CS_ROUTING" : "CS_HANGUP");
2254 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", node->name);
2255 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", wait_count > 0 ? "confirmed" : "terminated");
2256 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction", "inbound");
2257 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 2257, &event, ((void*)0))
;
2258 }
2259}
2260
2261static void pres_event_handler(switch_event_t *event)
2262{
2263 char *to = switch_event_get_header(event, "to")switch_event_get_header_idx(event, "to", -1);
2264 char *domain_name = NULL((void*)0);
2265 char *dup_to = NULL((void*)0), *node_name , *dup_node_name;
2266 fifo_node_t *node;
2267
2268 if (!globals.running) {
2269 return;
2270 }
2271
2272 if (!to || strncasecmp(to, "queue+", 6) || !strchr(to, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(to) && ('@') == '\0' ? (char *) __rawmemchr (to, '@'
) : __builtin_strchr (to, '@')))
) {
2273 return;
2274 }
2275
2276 dup_to = strdup(to)(__extension__ (__builtin_constant_p (to) && ((size_t
)(const void *)((to) + 1) - (size_t)(const void *)(to) == 1) ?
(((const char *) (to))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (to) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, to, __len); __retval; })) : __strdup
(to)))
;
2277 switch_assert(dup_to)((dup_to) ? (void) (0) : __assert_fail ("dup_to", "mod_fifo.c"
, 2277, __PRETTY_FUNCTION__))
;
2278
2279 node_name = dup_to + 6;
2280
2281 if ((domain_name = strchr(node_name, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(node_name) && ('@') == '\0' ? (char *) __rawmemchr (
node_name, '@') : __builtin_strchr (node_name, '@')))
)) {
2282 *domain_name++ = '\0';
2283 }
2284
2285 dup_node_name = switch_mprintf("%q@%q", node_name, domain_name);
2286
2287 switch_mutex_lock(globals.mutex);
2288 if (!(node = switch_core_hash_find(globals.fifo_hash, node_name)) && !(node = switch_core_hash_find(globals.fifo_hash, dup_node_name))) {
2289 node = create_node(node_name, 0, globals.sql_mutex);
2290 node->domain_name = switch_core_strdup(node->pool, domain_name)switch_core_perform_strdup(node->pool, domain_name, "mod_fifo.c"
, (const char *)__func__, 2290)
;
2291 node->ready = 1;
2292 }
2293
2294 switch_thread_rwlock_rdlock(node->rwlock);
2295 send_presence(node);
2296 switch_thread_rwlock_unlock(node->rwlock);
2297
2298 switch_mutex_unlock(globals.mutex);
2299
2300 switch_safe_free(dup_to)if (dup_to) {free(dup_to);dup_to=((void*)0);};
2301 switch_safe_free(dup_node_name)if (dup_node_name) {free(dup_node_name);dup_node_name=((void*
)0);}
;
2302}
2303
2304static uint32_t fifo_add_outbound(const char *node_name, const char *url, uint32_t priority)
2305{
2306 fifo_node_t *node;
2307 switch_event_t *call_event;
2308 uint32_t i = 0;
2309
2310 if (priority >= MAX_PRI10) {
2311 priority = MAX_PRI10 - 1;
2312 }
2313
2314 if (!node_name) return 0;
2315
2316 switch_mutex_lock(globals.mutex);
2317
2318 if (!(node = switch_core_hash_find(globals.fifo_hash, node_name))) {
2319 node = create_node(node_name, 0, globals.sql_mutex);
2320 }
2321
2322 switch_thread_rwlock_rdlock(node->rwlock);
2323
2324 switch_mutex_unlock(globals.mutex);
2325
2326 switch_event_create(&call_event, SWITCH_EVENT_CHANNEL_DATA)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2326, &call_event, SWITCH_EVENT_CHANNEL_DATA
, ((void*)0))
;
2327 switch_event_add_header_string(call_event, SWITCH_STACK_BOTTOM, "dial-url", url);
2328
2329 fifo_queue_push(node->fifo_list[priority], call_event);
2330 call_event = NULL((void*)0);
2331
2332 i = fifo_queue_size(node->fifo_list[priority]);
2333
2334 switch_thread_rwlock_unlock(node->rwlock);
2335
2336 return i;
2337}
2338
2339SWITCH_STANDARD_API(fifo_check_bridge_function)static switch_status_t fifo_check_bridge_function ( const char
*cmd, switch_core_session_t *session, switch_stream_handle_t
*stream)
2340{
2341 stream->write_function(stream, "%s", (cmd && check_bridge_call(cmd)) ? "true" : "false");
2342
2343 return SWITCH_STATUS_SUCCESS;
2344}
2345
2346SWITCH_STANDARD_API(fifo_add_outbound_function)static switch_status_t fifo_add_outbound_function ( const char
*cmd, switch_core_session_t *session, switch_stream_handle_t
*stream)
2347{
2348 char *data = NULL((void*)0), *argv[4] = { 0 };
2349 int argc;
2350 uint32_t priority = 0;
2351
2352 if (zstr(cmd)_zstr(cmd)) {
2353 goto fail;
2354 }
2355
2356 data = strdup(cmd)(__extension__ (__builtin_constant_p (cmd) && ((size_t
)(const void *)((cmd) + 1) - (size_t)(const void *)(cmd) == 1
) ? (((const char *) (cmd))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (cmd) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, cmd, __len); __retval
; })) : __strdup (cmd)))
;
2357
2358 if ((argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 2 || !argv[0]) {
2359 goto fail;
2360 }
2361
2362 if (argv[2]) {
2363 int tmp = atoi(argv[2]);
2364 if (tmp > 0) {
2365 priority = tmp;
2366 }
2367 }
2368
2369 stream->write_function(stream, "%d", fifo_add_outbound(argv[0], argv[1], priority));
2370
2371 free(data);
2372 return SWITCH_STATUS_SUCCESS;
2373
2374 fail:
2375
2376 free(data);
2377 stream->write_function(stream, "0");
2378 return SWITCH_STATUS_SUCCESS;
2379}
2380
2381static void dec_use_count(switch_core_session_t *session, const char *type)
2382{
2383 char *sql;
2384 const char *outbound_id = NULL((void*)0);
2385 switch_event_t *event;
2386 long now = (long) switch_epoch_time_now(NULL((void*)0));
2387 switch_channel_t *channel = switch_core_session_get_channel(session);
2388
2389 if ((outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid")switch_channel_get_variable_dup(channel, "fifo_outbound_uuid"
, SWITCH_TRUE, -1)
)) {
2390 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2390
, ((void*)0)
, SWITCH_LOG_DEBUG, "%s untracking call on uuid %s!\n", switch_channel_get_name(channel), outbound_id);
2391
2392 sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(session));
2393 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE);
2394
2395 del_bridge_call(outbound_id);
2396 sql = switch_mprintf("update fifo_outbound set use_count=use_count-1, stop_time=%ld, next_avail=%ld + lag + 1 where use_count > 0 and uuid='%q'",
2397 now, now, outbound_id);
2398 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
2399 fifo_dec_use_count(outbound_id);
2400 }
2401
2402 do_unbridge(session, NULL((void*)0));
2403
2404 if (type) {
2405 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2405, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
2406 uint64_t hold_usec = 0, tt_usec = 0;
2407 switch_caller_profile_t *originator_cp = NULL((void*)0);
2408
2409 originator_cp = switch_channel_get_caller_profile(channel);
2410 switch_channel_event_set_data(channel, event);
2411 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME"manual_calls");
2412 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-stop");
2413 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", type);
2414 if (outbound_id) {
2415 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
2416 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
2417 }
2418 hold_usec = originator_cp->times->hold_accum;
2419 tt_usec = (switch_micro_time_now() - originator_cp->times->bridged) - hold_usec;
2420 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Bridge-Time-us", "%"SWITCH_TIME_T_FMT"ld", originator_cp->times->bridged);
2421 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Bridge-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(originator_cp->times->bridged / 1000));
2422 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Bridge-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(originator_cp->times->bridged / 1000000));
2423 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Talk-Time-us", "%"SWITCH_TIME_T_FMT"ld", tt_usec);
2424 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Talk-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(tt_usec / 1000));
2425 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Talk-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(tt_usec / 1000000));
2426 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-us", "%"SWITCH_TIME_T_FMT"ld", hold_usec);
2427 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(hold_usec / 1000));
2428 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(hold_usec / 1000000));
2429
2430 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 2430, &event, ((void*)0))
;
2431 }
2432 }
2433}
2434
2435static switch_status_t hanguphook(switch_core_session_t *session)
2436{
2437 switch_channel_t *channel = switch_core_session_get_channel(session);
2438 switch_channel_state_t state = switch_channel_get_state(channel);
2439
2440 if (state >= CS_HANGUP && !switch_channel_test_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_DID_HOOK)) {
2441 dec_use_count(session, "manual");
2442 switch_core_event_hook_remove_state_change(session, hanguphook);
2443 switch_channel_set_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_DID_HOOK);
2444 }
2445
2446 return SWITCH_STATUS_SUCCESS;
2447}
2448
2449SWITCH_STANDARD_APP(fifo_track_call_function)static void fifo_track_call_function (switch_core_session_t *
session, const char *data)
2450{
2451 switch_channel_t *channel = switch_core_session_get_channel(session);
2452 char *sql;
2453 const char *col1 = NULL((void*)0), *col2 = NULL((void*)0), *cid_name, *cid_number;
2454 switch_event_t *event;
2455
2456 if (zstr(data)_zstr(data)) {
2457 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2457
, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid!\n");
2458 return;
2459 }
2460
2461 if (switch_channel_test_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_TRACKING)) {
2462 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2462
, ((void*)0)
, SWITCH_LOG_WARNING, "%s trying to double-track call!\n", switch_channel_get_name(channel));
2463 return;
2464 }
2465
2466 switch_channel_set_variable(channel, "fifo_outbound_uuid", data)switch_channel_set_variable_var_check(channel, "fifo_outbound_uuid"
, data, SWITCH_TRUE)
;
2467 switch_channel_set_variable(channel, "fifo_track_call", "true")switch_channel_set_variable_var_check(channel, "fifo_track_call"
, "true", SWITCH_TRUE)
;
2468
2469 add_bridge_call(data);
2470
2471 switch_channel_set_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_TRACKING);
2472
2473 switch_core_event_hook_add_receive_message(session, messagehook);
2474 switch_core_event_hook_add_state_run(session, hanguphook);
2475
2476 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 2476
, ((void*)0)
, SWITCH_LOG_DEBUG, "%s tracking call on uuid %s!\n", switch_channel_get_name(channel), data);
2477
2478 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
2479 col1 = "manual_calls_in_count";
2480 col2 = "manual_calls_in_total_count";
2481 } else {
2482 col1 = "manual_calls_out_count";
2483 col2 = "manual_calls_out_total_count";
2484 }
2485
2486 sql = switch_mprintf("update fifo_outbound set stop_time=0,start_time=%ld,outbound_fail_count=0,use_count=use_count+1,%s=%s+1,%s=%s+1 where uuid='%q'",
2487 (long) switch_epoch_time_now(NULL((void*)0)), col1, col1, col2, col2, data);
2488 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
2489 fifo_inc_use_count(data);
2490
2491 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2492 cid_name = switch_channel_get_variable(channel, "destination_number")switch_channel_get_variable_dup(channel, "destination_number"
, SWITCH_TRUE, -1)
;
2493 cid_number = cid_name;
2494 } else {
2495 cid_name = switch_channel_get_variable(channel, "caller_id_name")switch_channel_get_variable_dup(channel, "caller_id_name", SWITCH_TRUE
, -1)
;
2496 cid_number = switch_channel_get_variable(channel, "caller_id_number")switch_channel_get_variable_dup(channel, "caller_id_number", SWITCH_TRUE
, -1)
;
2497 }
2498
2499 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2499, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
2500 switch_channel_event_set_data(channel, event);
2501 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME"manual_calls");
2502 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-start");
2503 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", data);
2504 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(data));
2505 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "manual");
2506 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", cid_name);
2507 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number);
2508 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 2508, &event, ((void*)0))
;
2509 }
2510}
2511
2512static void fifo_caller_add(fifo_node_t *node, switch_core_session_t *session)
2513{
2514 char *sql;
2515 switch_channel_t *channel = switch_core_session_get_channel(session);
2516
2517 sql = switch_mprintf("insert into fifo_callers (fifo_name,uuid,caller_caller_id_name,caller_caller_id_number,timestamp) "
2518 "values ('%q','%q','%q','%q',%ld)",
2519 node->name,
2520 switch_core_session_get_uuid(session),
2521 switch_str_nil(switch_channel_get_variable(channel, "caller_id_name"))(switch_channel_get_variable_dup(channel, "caller_id_name", SWITCH_TRUE
, -1) ? switch_channel_get_variable_dup(channel, "caller_id_name"
, SWITCH_TRUE, -1) : "")
,
2522 switch_str_nil(switch_channel_get_variable(channel, "caller_id_number"))(switch_channel_get_variable_dup(channel, "caller_id_number",
SWITCH_TRUE, -1) ? switch_channel_get_variable_dup(channel, "caller_id_number"
, SWITCH_TRUE, -1) : "")
,
2523 switch_epoch_time_now(NULL((void*)0)));
2524
2525 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
2526}
2527
2528static void fifo_caller_del(const char *uuid)
2529{
2530 char *sql;
2531
2532 if (uuid) {
2533 sql = switch_mprintf("delete from fifo_callers where uuid='%q'", uuid);
2534 } else {
2535 sql = switch_mprintf("delete from fifo_callers");
2536 }
2537
2538 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
2539}
2540
2541typedef enum {
2542 STRAT_MORE_PPL,
2543 STRAT_WAITING_LONGER,
2544} fifo_strategy_t;
2545
2546#define MAX_NODES_PER_CONSUMER25 25
2547#define FIFO_DESC"Fifo for stacking parked calls." "Fifo for stacking parked calls."
2548#define FIFO_USAGE"<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]" "<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]"
2549SWITCH_STANDARD_APP(fifo_function)static void fifo_function (switch_core_session_t *session, const
char *data)
2550{
2551 int argc;
2552 char *mydata = NULL((void*)0), *argv[5] = { 0 };
2553 fifo_node_t *node = NULL((void*)0), *node_list[MAX_NODES_PER_CONSUMER25 + 1] = { 0 };
2554 switch_channel_t *channel = switch_core_session_get_channel(session);
2555 int do_destroy = 0, do_wait = 1, node_count = 0, i = 0;
2556 const char *moh = NULL((void*)0);
2557 const char *announce = NULL((void*)0);
2558 switch_event_t *event = NULL((void*)0);
2559 char date[80] = "";
2560 switch_time_exp_t tm;
2561 switch_time_t ts = switch_micro_time_now();
2562 switch_size_t retsize;
2563 char *list_string;
2564 int nlist_count;
2565 char *nlist[MAX_NODES_PER_CONSUMER25];
2566 int consumer = 0, in_table = 0;
2567 const char *arg_fifo_name = NULL((void*)0);
2568 const char *arg_inout = NULL((void*)0);
2569 const char *serviced_uuid = NULL((void*)0);
2570
2571 if (!globals.running) {
2572 return;
2573 }
2574
2575 if (zstr(data)_zstr(data)) {
2576 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 2576, (const char*)(session)
, SWITCH_LOG_ERROR, "No Args\n");
2577 return;
2578 }
2579
2580 switch_channel_set_variable(channel, "fifo_hangup_check", NULL)switch_channel_set_variable_var_check(channel, "fifo_hangup_check"
, ((void*)0), SWITCH_TRUE)
;
2581
2582 mydata = switch_core_session_strdup(session, data)switch_core_perform_session_strdup(session, data, "mod_fifo.c"
, (const char *)__func__, 2582)
;
2583 switch_assert(mydata)((mydata) ? (void) (0) : __assert_fail ("mydata", "mod_fifo.c"
, 2583, __PRETTY_FUNCTION__))
;
2584
2585 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2586 arg_fifo_name = argv[0];
2587 arg_inout = argv[1];
2588
2589 if (!(arg_fifo_name && arg_inout)) {
2590 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 2590, (const char*)(session)
, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE"<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]");
2591 return;
2592 }
2593
2594 if (!strcasecmp(arg_inout, "out")) {
2595 consumer = 1;
2596 } else if (strcasecmp(arg_inout, "in")) {
2597 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 2597, (const char*)(session)
, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE"<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]");
2598 return;
2599 }
2600
2601 list_string = switch_core_session_strdup(session, arg_fifo_name)switch_core_perform_session_strdup(session, arg_fifo_name, "mod_fifo.c"
, (const char *)__func__, 2601)
;
2602
2603 if (!(nlist_count = switch_separate_string(list_string, ',', nlist, (sizeof(nlist) / sizeof(nlist[0]))))) {
2604 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 2604, (const char*)(session)
, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE"<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]");
2605 return;
2606 }
2607
2608 if (!consumer && nlist_count > 1) {
2609 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 2609, (const char*)(session)
, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE"<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]");
2610 return;
2611 }
2612
2613 switch_mutex_lock(globals.mutex);
2614 for (i = 0; i < nlist_count; i++) {
2615 int importance = 0;
2616 char *p;
2617
2618 if ((p = strrchr(nlist[i], '!'))) {
2619 *p++ = '\0';
2620 importance = atoi(p);
2621 if (importance < 0) {
2622 importance = 0;
2623 }
2624 }
2625
2626 if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) {
2627 node = create_node(nlist[i], importance, globals.sql_mutex);
2628 node->ready = 1;
2629 }
2630
2631 switch_thread_rwlock_rdlock(node->rwlock);
2632 node_list[node_count++] = node;
2633 }
2634
2635 switch_mutex_unlock(globals.mutex);
2636
2637 moh = switch_channel_get_variable(channel, "fifo_music")switch_channel_get_variable_dup(channel, "fifo_music", SWITCH_TRUE
, -1)
;
2638 announce = switch_channel_get_variable(channel, "fifo_announce")switch_channel_get_variable_dup(channel, "fifo_announce", SWITCH_TRUE
, -1)
;
2639
2640 if (consumer) {
2641 if (argc > 3) {
2642 announce = argv[3];
2643 }
2644
2645 if (argc > 4) {
2646 moh = argv[4];
2647 }
2648 } else {
2649 if (argc > 2) {
2650 announce = argv[2];
2651 }
2652
2653 if (argc > 3) {
2654 moh = argv[3];
2655 }
2656 }
2657
2658 if (moh && !strcasecmp(moh, "silence")) {
2659 moh = NULL((void*)0);
2660 }
2661
2662 cleanup_fifo_arg(&announce);
2663 cleanup_fifo_arg(&moh);
2664 switch_assert(node)((node) ? (void) (0) : __assert_fail ("node", "mod_fifo.c", 2664
, __PRETTY_FUNCTION__))
;
2665
2666 switch_core_media_bug_pause(session);
2667
2668 if (!consumer) {
2669 switch_core_session_t *other_session;
2670 switch_channel_t *other_channel;
2671 const char *uuid = switch_core_session_get_uuid(session);
2672 const char *pri;
2673 char tmp[25] = "";
2674 int p = 0;
2675 int aborted = 0;
2676 fifo_chime_data_t cd = { {0} };
2677 const char *chime_list = switch_channel_get_variable(channel, "fifo_chime_list")switch_channel_get_variable_dup(channel, "fifo_chime_list", SWITCH_TRUE
, -1)
;
2678 const char *chime_freq = switch_channel_get_variable(channel, "fifo_chime_freq")switch_channel_get_variable_dup(channel, "fifo_chime_freq", SWITCH_TRUE
, -1)
;
2679 const char *orbit_exten = switch_channel_get_variable(channel, "fifo_orbit_exten")switch_channel_get_variable_dup(channel, "fifo_orbit_exten", SWITCH_TRUE
, -1)
;
2680 const char *orbit_dialplan = switch_channel_get_variable(channel, "fifo_orbit_dialplan")switch_channel_get_variable_dup(channel, "fifo_orbit_dialplan"
, SWITCH_TRUE, -1)
;
2681 const char *orbit_context = switch_channel_get_variable(channel, "fifo_orbit_context")switch_channel_get_variable_dup(channel, "fifo_orbit_context"
, SWITCH_TRUE, -1)
;
2682
2683 const char *orbit_ann = switch_channel_get_variable(channel, "fifo_orbit_announce")switch_channel_get_variable_dup(channel, "fifo_orbit_announce"
, SWITCH_TRUE, -1)
;
2684 const char *caller_exit_key = switch_channel_get_variable(channel, "fifo_caller_exit_key")switch_channel_get_variable_dup(channel, "fifo_caller_exit_key"
, SWITCH_TRUE, -1)
;
2685 int freq = 30;
2686 int ftmp = 0;
2687 int to = 60;
2688 switch_event_t *call_event;
2689
2690 if (orbit_exten) {
2691 char *ot;
2692 if ((cd.orbit_exten = switch_core_session_strdup(session, orbit_exten)switch_core_perform_session_strdup(session, orbit_exten, "mod_fifo.c"
, (const char *)__func__, 2692)
)) {
2693 if ((ot = strchr(cd.orbit_exten, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(cd.orbit_exten) && (':') == '\0' ? (char *) __rawmemchr
(cd.orbit_exten, ':') : __builtin_strchr (cd.orbit_exten, ':'
)))
)) {
2694 *ot++ = '\0';
2695 if ((to = atoi(ot)) < 0) {
2696 to = 60;
2697 }
2698 }
2699 cd.orbit_timeout = switch_epoch_time_now(NULL((void*)0)) + to;
2700 }
2701 cd.orbit_dialplan = switch_core_session_strdup(session, orbit_dialplan)switch_core_perform_session_strdup(session, orbit_dialplan, "mod_fifo.c"
, (const char *)__func__, 2701)
;
2702 cd.orbit_context = switch_core_session_strdup(session, orbit_context)switch_core_perform_session_strdup(session, orbit_context, "mod_fifo.c"
, (const char *)__func__, 2702)
;
2703 }
2704
2705 if (chime_freq) {
2706 ftmp = atoi(chime_freq);
2707 if (ftmp > 0) {
2708 freq = ftmp;
2709 }
2710 }
2711
2712 switch_channel_answer(channel)switch_channel_perform_answer(channel, "mod_fifo.c", (const char
*)__func__, 2712)
;
2713
2714 switch_mutex_lock(node->update_mutex);
2715
2716 if ((pri = switch_channel_get_variable(channel, "fifo_priority")switch_channel_get_variable_dup(channel, "fifo_priority", SWITCH_TRUE
, -1)
)) {
2717 p = atoi(pri);
2718 }
2719
2720 if (p >= MAX_PRI10) {
2721 p = MAX_PRI10 - 1;
2722 }
2723
2724 if (!node_caller_count(node)) {
2725 node->start_waiting = switch_micro_time_now();
2726 }
2727
2728 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2728, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
2729 switch_channel_event_set_data(channel, event);
2730 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
2731 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "push");
2732 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Slot", "%d", p);
2733 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 2733, &event, ((void*)0))
;
2734 }
2735
2736 switch_event_create(&call_event, SWITCH_EVENT_CHANNEL_DATA)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2736, &call_event, SWITCH_EVENT_CHANNEL_DATA
, ((void*)0))
;
2737 switch_channel_event_set_data(channel, call_event);
2738
2739 fifo_queue_push(node->fifo_list[p], call_event);
2740 fifo_caller_add(node, session);
2741 in_table = 1;
2742
2743 call_event = NULL((void*)0);
2744 switch_snprintf(tmp, sizeof(tmp), "%d", fifo_queue_size(node->fifo_list[p]));
2745 switch_channel_set_variable(channel, "fifo_position", tmp)switch_channel_set_variable_var_check(channel, "fifo_position"
, tmp, SWITCH_TRUE)
;
2746
2747 if (!pri) {
2748 switch_snprintf(tmp, sizeof(tmp), "%d", p);
2749 switch_channel_set_variable(channel, "fifo_priority", tmp)switch_channel_set_variable_var_check(channel, "fifo_priority"
, tmp, SWITCH_TRUE)
;
2750 }
2751
2752 switch_mutex_unlock(node->update_mutex);
2753
2754 ts = switch_micro_time_now();
2755 switch_time_exp_lt(&tm, ts);
2756 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
2757 switch_channel_set_variable(channel, "fifo_status", "WAITING")switch_channel_set_variable_var_check(channel, "fifo_status",
"WAITING", SWITCH_TRUE)
;
2758 switch_channel_set_variable(channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
2759 switch_channel_set_variable(channel, "fifo_serviced_uuid", NULL)switch_channel_set_variable_var_check(channel, "fifo_serviced_uuid"
, ((void*)0), SWITCH_TRUE)
;
2760
2761 switch_channel_set_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_BRIDGE_TAG);
2762
2763 if (chime_list) {
2764 char *list_dup = switch_core_session_strdup(session, chime_list)switch_core_perform_session_strdup(session, chime_list, "mod_fifo.c"
, (const char *)__func__, 2764)
;
2765 cd.total = switch_separate_string(list_dup, ',', cd.list, (sizeof(cd.list) / sizeof(cd.list[0])));
2766 cd.freq = freq;
2767 cd.next = switch_epoch_time_now(NULL((void*)0)) + cd.freq;
2768 cd.exit_key = (char *) switch_channel_get_variable(channel, "fifo_caller_exit_key")switch_channel_get_variable_dup(channel, "fifo_caller_exit_key"
, SWITCH_TRUE, -1)
;
2769 }
2770
2771 send_presence(node);
2772
2773 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
2774 switch_input_args_t args = { 0 };
2775 char buf[25] = "";
2776 switch_status_t rstatus;
2777
2778 args.input_callback = moh_on_dtmf;
2779 args.buf = buf;
2780 args.buflen = sizeof(buf);
2781
2782 if (cd.total || cd.orbit_timeout) {
2783 args.read_frame_callback = caller_read_frame_callback;
2784 args.user_data = &cd;
2785 }
2786
2787 if (cd.abort || cd.do_orbit) {
2788 aborted = 1;
2789 goto abort;
2790 }
2791
2792 if ((serviced_uuid = switch_channel_get_variable(channel, "fifo_serviced_uuid")switch_channel_get_variable_dup(channel, "fifo_serviced_uuid"
, SWITCH_TRUE, -1)
)) {
2793 break;
2794 }
2795
2796 switch_core_session_flush_private_events(session);
2797
2798 if (moh) {
2799 rstatus = switch_ivr_play_file(session, NULL((void*)0), moh, &args);
2800 } else {
2801 rstatus = switch_ivr_collect_digits_callback(session, &args, 0, 0);
2802 }
2803
2804 if (!SWITCH_READ_ACCEPTABLE(rstatus)(rstatus == SWITCH_STATUS_SUCCESS || rstatus == SWITCH_STATUS_BREAK
|| rstatus == SWITCH_STATUS_INUSE)
) {
2805 aborted = 1;
2806 goto abort;
2807 }
2808
2809 if (caller_exit_key && *buf && strchr(caller_exit_key, *buf)(__extension__ (__builtin_constant_p (*buf) && !__builtin_constant_p
(caller_exit_key) && (*buf) == '\0' ? (char *) __rawmemchr
(caller_exit_key, *buf) : __builtin_strchr (caller_exit_key,
*buf)))
) {
2810 switch_channel_set_variable(channel, "fifo_caller_exit_key", (char *)buf)switch_channel_set_variable_var_check(channel, "fifo_caller_exit_key"
, (char *)buf, SWITCH_TRUE)
;
2811 aborted = 1;
2812 goto abort;
2813 }
2814 }
2815
2816 if (!serviced_uuid && switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
2817 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(channel, "mod_fifo.c", (const char
*)__func__, 2817, SWITCH_CAUSE_NORMAL_CLEARING)
;
2818 } else if ((other_session = switch_core_session_locate(serviced_uuid)switch_core_session_perform_locate(serviced_uuid, "mod_fifo.c"
, (const char *)__func__, 2818)
)) {
2819 int ready;
2820 other_channel = switch_core_session_get_channel(other_session);
2821 ready = switch_channel_ready(other_channel)switch_channel_test_ready(other_channel, SWITCH_TRUE, SWITCH_FALSE
)
;
2822 switch_core_session_rwunlock(other_session);
2823 if (!ready) {
2824 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(channel, "mod_fifo.c", (const char
*)__func__, 2824, SWITCH_CAUSE_NORMAL_CLEARING)
;
2825 }
2826 }
2827
2828 switch_core_session_flush_private_events(session);
2829
2830 if (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
2831 if (announce) {
2832 switch_ivr_play_file(session, NULL((void*)0), announce, NULL((void*)0));
2833 }
2834 }
2835
2836 abort:
2837
2838 switch_channel_clear_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_BRIDGE_TAG);
2839
2840 if (!aborted && switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
2841 switch_channel_set_state(channel, CS_HIBERNATE)switch_channel_perform_set_state(channel, "mod_fifo.c", (const
char *)__func__, 2841, CS_HIBERNATE)
;
2842 goto done;
2843 } else {
2844 ts = switch_micro_time_now();
2845 switch_time_exp_lt(&tm, ts);
2846 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
2847 switch_channel_set_variable(channel, "fifo_status", cd.do_orbit ? "TIMEOUT" : "ABORTED")switch_channel_set_variable_var_check(channel, "fifo_status",
cd.do_orbit ? "TIMEOUT" : "ABORTED", SWITCH_TRUE)
;
2848 switch_channel_set_variable(channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
2849
2850 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2850, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
2851 switch_channel_event_set_data(channel, event);
2852 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
2853 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", cd.do_orbit ? "timeout" : "abort");
2854 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 2854, &event, ((void*)0))
;
2855 }
2856
2857 switch_mutex_lock(globals.mutex);
2858 switch_mutex_lock(node->update_mutex);
2859 node_remove_uuid(node, uuid);
2860 switch_mutex_unlock(node->update_mutex);
2861 send_presence(node);
2862 check_cancel(node);
2863 switch_mutex_unlock(globals.mutex);
2864 }
2865
2866 if ((switch_true(switch_channel_get_variable(channel, "fifo_caller_exit_to_orbit")switch_channel_get_variable_dup(channel, "fifo_caller_exit_to_orbit"
, SWITCH_TRUE, -1)
) || cd.do_orbit) && cd.orbit_exten) {
2867 if (orbit_ann) {
2868 switch_ivr_play_file(session, NULL((void*)0), orbit_ann, NULL((void*)0));
2869 }
2870
2871 if (strcmp(cd.orbit_exten, "_continue_")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(cd.orbit_exten) && __builtin_constant_p ("_continue_"
) && (__s1_len = __builtin_strlen (cd.orbit_exten), __s2_len
= __builtin_strlen ("_continue_"), (!((size_t)(const void *)
((cd.orbit_exten) + 1) - (size_t)(const void *)(cd.orbit_exten
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)(("_continue_") + 1) - (size_t)(const void *)("_continue_"
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (cd.orbit_exten
, "_continue_") : (__builtin_constant_p (cd.orbit_exten) &&
((size_t)(const void *)((cd.orbit_exten) + 1) - (size_t)(const
void *)(cd.orbit_exten) == 1) && (__s1_len = __builtin_strlen
(cd.orbit_exten), __s1_len < 4) ? (__builtin_constant_p (
"_continue_") && ((size_t)(const void *)(("_continue_"
) + 1) - (size_t)(const void *)("_continue_") == 1) ? __builtin_strcmp
(cd.orbit_exten, "_continue_") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ("_continue_"
); int __result = (((const unsigned char *) (const char *) (cd
.orbit_exten))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
cd.orbit_exten))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (cd.orbit_exten))[2] - __s2[2]); if (__s1_len > 2
&& __result == 0) __result = (((const unsigned char *
) (const char *) (cd.orbit_exten))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p ("_continue_") && ((size_t
)(const void *)(("_continue_") + 1) - (size_t)(const void *)(
"_continue_") == 1) && (__s2_len = __builtin_strlen (
"_continue_"), __s2_len < 4) ? (__builtin_constant_p (cd.orbit_exten
) && ((size_t)(const void *)((cd.orbit_exten) + 1) - (
size_t)(const void *)(cd.orbit_exten) == 1) ? __builtin_strcmp
(cd.orbit_exten, "_continue_") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (cd.orbit_exten
); int __result = (((const unsigned char *) (const char *) ("_continue_"
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("_continue_"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("_continue_"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("_continue_"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (cd.
orbit_exten, "_continue_")))); })
) {
2872 switch_ivr_session_transfer(session, cd.orbit_exten, cd.orbit_dialplan, cd.orbit_context);
2873 }
2874 }
2875
2876 cancel_caller_outbound_call(switch_core_session_get_uuid(session), SWITCH_CAUSE_ORIGINATOR_CANCEL);
2877
2878 goto done;
2879 } else { /* consumer */
2880 switch_event_t *pop = NULL((void*)0);
2881 switch_frame_t *read_frame;
2882 switch_status_t status;
2883 switch_core_session_t *other_session;
2884 switch_input_args_t args = { 0 };
2885 const char *pop_order = NULL((void*)0);
2886 int custom_pop = 0;
2887 int pop_array[MAX_PRI10] = { 0 };
2888 char *pop_list[MAX_PRI10] = { 0 };
2889 const char *fifo_consumer_wrapup_sound = NULL((void*)0);
2890 const char *fifo_consumer_wrapup_key = NULL((void*)0);
2891 const char *sfifo_consumer_wrapup_time = NULL((void*)0);
2892 uint32_t fifo_consumer_wrapup_time = 0;
2893 switch_time_t wrapup_time_elapsed = 0, wrapup_time_started = 0, wrapup_time_remaining = 0;
2894 const char *my_id;
2895 char buf[5] = "";
2896 const char *strat_str = switch_channel_get_variable(channel, "fifo_strategy")switch_channel_get_variable_dup(channel, "fifo_strategy", SWITCH_TRUE
, -1)
;
2897 fifo_strategy_t strat = STRAT_WAITING_LONGER;
2898 const char *url = NULL((void*)0);
2899 const char *caller_uuid = NULL((void*)0);
2900 const char *outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid")switch_channel_get_variable_dup(channel, "fifo_outbound_uuid"
, SWITCH_TRUE, -1)
;
2901 switch_event_t *event;
2902 const char *cid_name = NULL((void*)0), *cid_number = NULL((void*)0);
2903
2904 //const char *track_use_count = switch_channel_get_variable(channel, "fifo_track_use_count");
2905 //int do_track = switch_true(track_use_count);
2906
2907 if (switch_core_event_hook_remove_receive_message(session, messagehook) == SWITCH_STATUS_SUCCESS) {
2908 dec_use_count(session, NULL((void*)0));
2909 switch_core_event_hook_remove_state_change(session, hanguphook);
2910 switch_channel_clear_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_TRACKING);
2911 }
2912
2913 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2914 cid_name = switch_channel_get_variable(channel, "callee_id_name")switch_channel_get_variable_dup(channel, "callee_id_name", SWITCH_TRUE
, -1)
;
2915 cid_number = switch_channel_get_variable(channel, "callee_id_number")switch_channel_get_variable_dup(channel, "callee_id_number", SWITCH_TRUE
, -1)
;
2916
2917 if (!cid_name) {
2918 cid_name = switch_channel_get_variable(channel, "destination_number")switch_channel_get_variable_dup(channel, "destination_number"
, SWITCH_TRUE, -1)
;
2919 }
2920 if (!cid_number) {
2921 cid_number = cid_name;
2922 }
2923 } else {
2924 cid_name = switch_channel_get_variable(channel, "caller_id_name")switch_channel_get_variable_dup(channel, "caller_id_name", SWITCH_TRUE
, -1)
;
2925 cid_number = switch_channel_get_variable(channel, "caller_id_number")switch_channel_get_variable_dup(channel, "caller_id_number", SWITCH_TRUE
, -1)
;
2926 }
2927
2928 if (!zstr(strat_str)_zstr(strat_str)) {
2929 if (!strcasecmp(strat_str, "more_ppl")) {
2930 strat = STRAT_MORE_PPL;
2931 } else if (!strcasecmp(strat_str, "waiting_longer")) {
2932 strat = STRAT_WAITING_LONGER;
2933 } else {
2934 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 2934, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid strategy\n");
2935 goto done;
2936 }
2937 }
2938
2939 if (argc > 2) {
2940 if (!strcasecmp(argv[2], "nowait")) {
2941 do_wait = 0;
2942 } else if (strcasecmp(argv[2], "wait")) {
2943 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 2943, (const char*)(session)
, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE"<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]");
2944 goto done;
2945 }
2946 }
2947
2948 if (!(my_id = switch_channel_get_variable(channel, "fifo_consumer_id")switch_channel_get_variable_dup(channel, "fifo_consumer_id", SWITCH_TRUE
, -1)
)) {
2949 my_id = switch_core_session_get_uuid(session);
2950 }
2951
2952 if (do_wait) {
2953 for (i = 0; i < node_count; i++) {
2954 if (!(node = node_list[i])) {
2955 continue;
2956 }
2957 switch_mutex_lock(node->mutex);
2958 node->consumer_count++;
2959 switch_core_hash_insert(node->consumer_hash, switch_core_session_get_uuid(session), session)switch_core_hash_insert_destructor(node->consumer_hash, switch_core_session_get_uuid
(session), session, ((void*)0))
;
2960 switch_mutex_unlock(node->mutex);
2961 }
2962 switch_channel_answer(channel)switch_channel_perform_answer(channel, "mod_fifo.c", (const char
*)__func__, 2962)
;
2963 }
2964
2965 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 2965, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
2966 switch_channel_event_set_data(channel, event);
2967 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
2968 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_start");
2969 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 2969, &event, ((void*)0))
;
2970 }
2971
2972 ts = switch_micro_time_now();
2973 switch_time_exp_lt(&tm, ts);
2974 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
2975 switch_channel_set_variable(channel, "fifo_status", "WAITING")switch_channel_set_variable_var_check(channel, "fifo_status",
"WAITING", SWITCH_TRUE)
;
2976 switch_channel_set_variable(channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
2977
2978 if ((pop_order = switch_channel_get_variable(channel, "fifo_pop_order")switch_channel_get_variable_dup(channel, "fifo_pop_order", SWITCH_TRUE
, -1)
)) {
2979 char *tmp = switch_core_session_strdup(session, pop_order)switch_core_perform_session_strdup(session, pop_order, "mod_fifo.c"
, (const char *)__func__, 2979)
;
2980 int x;
2981 custom_pop = switch_separate_string(tmp, ',', pop_list, (sizeof(pop_list) / sizeof(pop_list[0])));
2982 if (custom_pop >= MAX_PRI10) {
2983 custom_pop = MAX_PRI10 - 1;
2984 }
2985
2986 for (x = 0; x < custom_pop; x++) {
2987 int temp;
2988 switch_assert(pop_list[x])((pop_list[x]) ? (void) (0) : __assert_fail ("pop_list[x]", "mod_fifo.c"
, 2988, __PRETTY_FUNCTION__))
;
2989 temp = atoi(pop_list[x]);
2990 if (temp > -1 && temp < MAX_PRI10) {
2991 pop_array[x] = temp;
2992 }
2993 }
2994 } else {
2995 int x = 0;
2996 for (x = 0; x < MAX_PRI10; x++) {
2997 pop_array[x] = x;
2998 }
2999 }
3000
3001 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
3002 int x = 0, winner = -1;
3003 switch_time_t longest = (0xFFFFFFFFFFFFFFFFULL / 2);
3004 uint32_t importance = 0, waiting = 0, most_waiting = 0;
3005
3006 pop = NULL((void*)0);
3007
3008 if (moh && do_wait) {
3009 switch_status_t moh_status;
3010 memset(&args, 0, sizeof(args));
3011 args.read_frame_callback = consumer_read_frame_callback;
3012 args.user_data = node_list;
3013 moh_status = switch_ivr_play_file(session, NULL((void*)0), moh, &args);
3014
3015 if (!SWITCH_READ_ACCEPTABLE(moh_status)(moh_status == SWITCH_STATUS_SUCCESS || moh_status == SWITCH_STATUS_BREAK
|| moh_status == SWITCH_STATUS_INUSE)
) {
3016 break;
3017 }
3018 }
3019
3020 /* Before we can pick a caller we have to decide on a fifo
3021 node to service if the consumer can service more than
3022 one.
3023
3024 If all fifos have an importance of zero, we'll find the
3025 first node that wins based on the chosen strategy.
3026
3027 The `waiting_longer` strategy will choose the node that
3028 hasn't been empty for the longest time.
3029
3030 The `more_ppl` strategy will choose the node that has
3031 the most people waiting.
3032
3033 If a node has an importance value set, it will cause us
3034 to ignore later nodes with equivalent or lower
3035 importance values. This means that a node with the
3036 same importance that would otherwise win based on the
3037 strategy will not be considered at all if it comes
3038 later in the list. Note also that the high importance
3039 node may still lose if a considered fifo earlier in the
3040 list beats it per the strategy.
3041
3042 Note that when the consumer has been delivered by an
3043 outbound strategy there will only be one fifo node
3044 passed to us, so neither the importance nor the
3045 strategy here will have any effect.
3046 */
3047 for (i = 0; i < node_count; i++) {
3048 if (!(node = node_list[i])) {
3049 continue;
3050 }
3051
3052 if ((waiting = node_caller_count(node))) {
3053 if (!importance || node->importance > importance) {
3054 if (strat == STRAT_WAITING_LONGER) {
3055 if (node->start_waiting < longest) {
3056 longest = node->start_waiting;
3057 winner = i;
3058 }
3059 } else {
3060 if (waiting > most_waiting) {
3061 most_waiting = waiting;
3062 winner = i;
3063 }
3064 }
3065 }
3066
3067 if (node->importance > importance) {
3068 importance = node->importance;
3069 }
3070 }
3071 }
3072
3073 if (winner > -1) {
3074 node = node_list[winner];
3075 } else {
3076 node = NULL((void*)0);
3077 }
3078
3079 if (node) {
3080 const char *varval, *check = NULL((void*)0);
3081
3082 check = switch_channel_get_variable(channel, "fifo_bridge_uuid_required")switch_channel_get_variable_dup(channel, "fifo_bridge_uuid_required"
, SWITCH_TRUE, -1)
;
3083
3084 /* Handle predestined calls, including calls from the ringall strategy */
3085 if ((varval = switch_channel_get_variable(channel, "fifo_bridge_uuid")switch_channel_get_variable_dup(channel, "fifo_bridge_uuid", SWITCH_TRUE
, -1)
)) {
3086 if (check_bridge_call(varval) && switch_true(check)) {
3087 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 3087, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Call has already been answered\n",
3088 switch_channel_get_name(channel));
3089 goto done;
3090 }
3091
3092 cancel_consumer_outbound_call(outbound_id, SWITCH_CAUSE_ORIGINATOR_CANCEL);
3093
3094 for (x = 0; x < MAX_PRI10; x++) {
3095 if (fifo_queue_pop_nameval(node->fifo_list[pop_array[x]], "+unique-id", varval, &pop, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && pop) {
3096 cancel_caller_outbound_call(varval, SWITCH_CAUSE_PICKED_OFF);
3097 break;
3098 }
3099 }
3100 if (!pop && switch_true(check)) {
3101 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 3101, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Call has already been answered\n",
3102 switch_channel_get_name(channel));
3103
3104 goto done;
3105 }
3106 }
3107
3108 if (!pop && (varval = switch_channel_get_variable(channel, "fifo_target_skill")switch_channel_get_variable_dup(channel, "fifo_target_skill",
SWITCH_TRUE, -1)
)) {
3109 for (x = 0; x < MAX_PRI10; x++) {
3110 if (fifo_queue_pop_nameval(node->fifo_list[pop_array[x]], "variable_fifo_skill",
3111 varval, &pop, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && pop) {
3112 break;
3113 }
3114 }
3115 }
3116
3117 if (!pop) {
3118 for (x = 0; x < MAX_PRI10; x++) {
3119 if (fifo_queue_pop_nameval(node->fifo_list[pop_array[x]], "variable_fifo_vip", "true",
3120 &pop, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && pop) {
3121 break;
3122 }
3123 }
3124 }
3125
3126 if (!pop) {
3127 if (custom_pop) {
3128 for (x = 0; x < MAX_PRI10; x++) {
3129 if (fifo_queue_pop(node->fifo_list[pop_array[x]], &pop, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && pop) {
3130 break;
3131 }
3132 }
3133 } else {
3134 for (x = 0; x < MAX_PRI10; x++) {
3135 if (fifo_queue_pop(node->fifo_list[x], &pop, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && pop) {
3136 break;
3137 }
3138 }
3139 }
3140 }
3141
3142 if (pop && !node_caller_count(node)) {
3143 switch_mutex_lock(node->update_mutex);
3144 node->start_waiting = 0;
3145 switch_mutex_unlock(node->update_mutex);
3146 }
3147 }
3148
3149 if (!pop) {
3150 if (!do_wait) {
3151 break;
3152 }
3153
3154 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
3155
3156 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
) {
3157 break;
3158 }
3159
3160 continue;
3161 }
3162
3163 url = switch_event_get_header(pop, "dial-url")switch_event_get_header_idx(pop, "dial-url", -1);
3164 caller_uuid = switch_core_session_strdup(session, switch_event_get_header(pop, "unique-id"))switch_core_perform_session_strdup(session, switch_event_get_header_idx
(pop, "unique-id", -1), "mod_fifo.c", (const char *)__func__,
3164)
;
3165 switch_event_destroy(&pop);
3166
3167 if (url) {
3168 switch_call_cause_t cause = SWITCH_CAUSE_NONE;
3169 const char *o_announce = NULL((void*)0);
3170
3171 if ((o_announce = switch_channel_get_variable(channel, "fifo_outbound_announce")switch_channel_get_variable_dup(channel, "fifo_outbound_announce"
, SWITCH_TRUE, -1)
)) {
3172 status = switch_ivr_play_file(session, NULL((void*)0), o_announce, NULL((void*)0));
3173 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
) {
3174 break;
3175 }
3176 }
3177
3178 if (switch_ivr_originate(session, &other_session, &cause, url, 120, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), SOF_NONE, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
3179 other_session = NULL((void*)0);
3180 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 3180
, ((void*)0)
, SWITCH_LOG_WARNING, "Originate to [%s] failed, cause: %s\n", url,
3181 switch_channel_cause2str(cause));
3182
3183 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3183, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3184 switch_channel_event_set_data(channel, event);
3185 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3186 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "caller_outbound");
3187 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Result", "failure:%s", switch_channel_cause2str(cause));
3188 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Outbound-URL", url);
3189 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3189, &event, ((void*)0))
;
3190 }
3191 } else {
3192 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3192, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3193 switch_channel_event_set_data(channel, event);
3194 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3195 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "caller_outbound");
3196 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Result", "success");
3197 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Outbound-URL", url);
3198 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3198, &event, ((void*)0))
;
3199 }
3200 url = NULL((void*)0);
3201 caller_uuid = switch_core_session_strdup(session, switch_core_session_get_uuid(other_session))switch_core_perform_session_strdup(session, switch_core_session_get_uuid
(other_session), "mod_fifo.c", (const char *)__func__, 3201)
;
3202 }
3203 } else {
3204 if ((other_session = switch_core_session_locate(caller_uuid)switch_core_session_perform_locate(caller_uuid, "mod_fifo.c",
(const char *)__func__, 3204)
)) {
3205 switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
3206 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3206, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3207 switch_channel_event_set_data(other_channel, event);
3208 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3209 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "caller_pop");
3210 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3210, &event, ((void*)0))
;
3211 }
3212 }
3213 }
3214
3215 if (node && other_session) {
3216 switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
3217 switch_caller_profile_t *originator_cp, *originatee_cp;
3218 const char *o_announce = NULL((void*)0);
3219 const char *record_template = switch_channel_get_variable(channel, "fifo_record_template")switch_channel_get_variable_dup(channel, "fifo_record_template"
, SWITCH_TRUE, -1)
;
3220 char *expanded = NULL((void*)0);
3221 char *sql = NULL((void*)0);
3222 long epoch_start, epoch_end;
3223
3224 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3224, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3225 switch_channel_event_set_data(channel, event);
3226 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3227 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_pop");
3228 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-UUID", switch_core_session_get_uuid(other_session));
3229 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3229, &event, ((void*)0))
;
3230 }
3231
3232 if ((o_announce = switch_channel_get_variable(other_channel, "fifo_override_announce")switch_channel_get_variable_dup(other_channel, "fifo_override_announce"
, SWITCH_TRUE, -1)
)) {
3233 announce = o_announce;
3234 }
3235
3236 if (announce) {
3237 status = switch_ivr_play_file(session, NULL((void*)0), announce, NULL((void*)0));
3238 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
) {
3239 break;
3240 }
3241 }
3242
3243 switch_channel_set_variable(other_channel, "fifo_serviced_by", my_id)switch_channel_set_variable_var_check(other_channel, "fifo_serviced_by"
, my_id, SWITCH_TRUE)
;
3244 switch_channel_set_variable(other_channel, "fifo_serviced_uuid", switch_core_session_get_uuid(session))switch_channel_set_variable_var_check(other_channel, "fifo_serviced_uuid"
, switch_core_session_get_uuid(session), SWITCH_TRUE)
;
3245 switch_channel_set_flag(other_channel, CF_BREAK)switch_channel_set_flag_value(other_channel, CF_BREAK, 1);
3246
3247 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_ready(other_channel)switch_channel_test_ready(other_channel, SWITCH_TRUE, SWITCH_FALSE
)
&&
3248 switch_channel_test_app_flag_key(FIFO_APP_KEY"mod_fifo", other_channel, FIFO_APP_BRIDGE_TAG)) {
3249 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
3250 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
) {
3251 break;
3252 }
3253 }
3254
3255 if (!(switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE))) {
3256 const char *app = switch_channel_get_variable(other_channel, "current_application")switch_channel_get_variable_dup(other_channel, "current_application"
, SWITCH_TRUE, -1)
;
3257 const char *arg = switch_channel_get_variable(other_channel, "current_application_data")switch_channel_get_variable_dup(other_channel, "current_application_data"
, SWITCH_TRUE, -1)
;
3258 switch_caller_extension_t *extension = NULL((void*)0);
3259
3260 switch_channel_set_variable_printf(channel, "last_sent_callee_id_name", "%s (AGENT FAIL)",
3261 switch_channel_get_variable(other_channel, "caller_id_name")switch_channel_get_variable_dup(other_channel, "caller_id_name"
, SWITCH_TRUE, -1)
);
3262 switch_channel_set_variable(channel, "last_sent_callee_id_number", switch_channel_get_variable(other_channel, "caller_id_number"))switch_channel_set_variable_var_check(channel, "last_sent_callee_id_number"
, switch_channel_get_variable_dup(other_channel, "caller_id_number"
, SWITCH_TRUE, -1), SWITCH_TRUE)
;
3263
3264 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 3264, (const char*)(session)
, SWITCH_LOG_WARNING,
3265 "Customer %s %s [%s] appears to be abandoned by agent %s [%s] "
3266 "but is still on the line, redirecting them back to the queue with VIP status.\n",
3267 switch_channel_get_name(other_channel),
3268 switch_channel_get_variable(other_channel, "caller_id_name")switch_channel_get_variable_dup(other_channel, "caller_id_name"
, SWITCH_TRUE, -1)
,
3269 switch_channel_get_variable(other_channel, "caller_id_number")switch_channel_get_variable_dup(other_channel, "caller_id_number"
, SWITCH_TRUE, -1)
,
3270 switch_channel_get_variable(channel, "caller_id_name")switch_channel_get_variable_dup(channel, "caller_id_name", SWITCH_TRUE
, -1)
,
3271 switch_channel_get_variable(channel, "caller_id_number")switch_channel_get_variable_dup(channel, "caller_id_number", SWITCH_TRUE
, -1)
);
3272
3273 switch_channel_wait_for_state_timeout(other_channel, CS_HIBERNATE, 5000);
3274
3275 send_presence(node);
3276 check_cancel(node);
3277
3278 if (app) {
3279 extension = switch_caller_extension_new(other_session, app, arg);
3280 switch_caller_extension_add_application(other_session, extension, app, arg);
3281 switch_channel_set_caller_extension(other_channel, extension);
3282 switch_channel_set_state(other_channel, CS_EXECUTE)switch_channel_perform_set_state(other_channel, "mod_fifo.c",
(const char *)__func__, 3282, CS_EXECUTE)
;
3283 } else {
3284 switch_channel_hangup(other_channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(other_channel, "mod_fifo.c", (const
char *)__func__, 3284, SWITCH_CAUSE_NORMAL_CLEARING)
;
3285 }
3286 switch_channel_set_variable(other_channel, "fifo_vip", "true")switch_channel_set_variable_var_check(other_channel, "fifo_vip"
, "true", SWITCH_TRUE)
;
3287
3288 switch_core_session_rwunlock(other_session);
3289 break;
3290 }
3291
3292 switch_channel_answer(channel)switch_channel_perform_answer(channel, "mod_fifo.c", (const char
*)__func__, 3292)
;
3293
3294 if (switch_channel_inbound_display(other_channel)((switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_INBOUND
&& !switch_channel_test_flag(other_channel, CF_BLEG)
) || (switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_OUTBOUND
&& switch_channel_test_flag(other_channel, CF_DIALPLAN
)))
) {
3295 if (switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
3296 switch_channel_set_flag(other_channel, CF_BLEG)switch_channel_set_flag_value(other_channel, CF_BLEG, 1);
3297 }
3298 }
3299
3300 switch_channel_step_caller_profile(channel);
3301 switch_channel_step_caller_profile(other_channel);
3302
3303 originator_cp = switch_channel_get_caller_profile(channel);
3304 originatee_cp = switch_channel_get_caller_profile(other_channel);
3305
3306 switch_channel_set_originator_caller_profile(other_channel, switch_caller_profile_clone(other_session, originator_cp));
3307 switch_channel_set_originatee_caller_profile(channel, switch_caller_profile_clone(session, originatee_cp));
3308
3309 originator_cp->callee_id_name = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_name)switch_core_perform_strdup(originator_cp->pool, originatee_cp
->callee_id_name, "mod_fifo.c", (const char *)__func__, 3309
)
;
3310 originator_cp->callee_id_number = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_number)switch_core_perform_strdup(originator_cp->pool, originatee_cp
->callee_id_number, "mod_fifo.c", (const char *)__func__, 3310
)
;
3311
3312 originatee_cp->callee_id_name = switch_core_strdup(originatee_cp->pool, originatee_cp->caller_id_name)switch_core_perform_strdup(originatee_cp->pool, originatee_cp
->caller_id_name, "mod_fifo.c", (const char *)__func__, 3312
)
;
3313 originatee_cp->callee_id_number = switch_core_strdup(originatee_cp->pool, originatee_cp->caller_id_number)switch_core_perform_strdup(originatee_cp->pool, originatee_cp
->caller_id_number, "mod_fifo.c", (const char *)__func__, 3313
)
;
3314
3315 originatee_cp->caller_id_name = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_name)switch_core_perform_strdup(originatee_cp->pool, originator_cp
->caller_id_name, "mod_fifo.c", (const char *)__func__, 3315
)
;
3316 originatee_cp->caller_id_number = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_number)switch_core_perform_strdup(originatee_cp->pool, originator_cp
->caller_id_number, "mod_fifo.c", (const char *)__func__, 3316
)
;
3317
3318 ts = switch_micro_time_now();
3319 switch_time_exp_lt(&tm, ts);
3320 epoch_start = (long)switch_epoch_time_now(NULL((void*)0));
3321 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
3322 switch_channel_set_variable(channel, "fifo_status", "TALKING")switch_channel_set_variable_var_check(channel, "fifo_status",
"TALKING", SWITCH_TRUE)
;
3323 switch_channel_set_variable(channel, "fifo_target", caller_uuid)switch_channel_set_variable_var_check(channel, "fifo_target",
caller_uuid, SWITCH_TRUE)
;
3324 switch_channel_set_variable(channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
3325 switch_channel_set_variable_printf(channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
3326 switch_channel_set_variable(channel, "fifo_role", "consumer")switch_channel_set_variable_var_check(channel, "fifo_role", "consumer"
, SWITCH_TRUE)
;
3327
3328 switch_channel_set_variable(other_channel, "fifo_status", "TALKING")switch_channel_set_variable_var_check(other_channel, "fifo_status"
, "TALKING", SWITCH_TRUE)
;
3329 switch_channel_set_variable(other_channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(other_channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
3330 switch_channel_set_variable_printf(other_channel, "fifo_epoch_start_bridge", "%ld", epoch_start);
3331 switch_channel_set_variable(other_channel, "fifo_target", switch_core_session_get_uuid(session))switch_channel_set_variable_var_check(other_channel, "fifo_target"
, switch_core_session_get_uuid(session), SWITCH_TRUE)
;
3332 switch_channel_set_variable(other_channel, "fifo_role", "caller")switch_channel_set_variable_var_check(other_channel, "fifo_role"
, "caller", SWITCH_TRUE)
;
3333
3334 send_presence(node);
3335
3336 if (record_template) {
3337 expanded = switch_channel_expand_variables(other_channel, record_template)switch_channel_expand_variables_check(other_channel, record_template
, ((void*)0), ((void*)0), 0)
;
3338 switch_ivr_record_session(session, expanded, 0, NULL((void*)0));
3339 }
3340
3341 switch_core_media_bug_resume(session);
3342 switch_core_media_bug_resume(other_session);
3343
3344 switch_process_import(session, other_channel, "fifo_caller_consumer_import", switch_channel_get_variable(channel, "fifo_import_prefix")switch_channel_get_variable_dup(channel, "fifo_import_prefix"
, SWITCH_TRUE, -1)
);
3345 switch_process_import(other_session, channel, "fifo_consumer_caller_import", switch_channel_get_variable(other_channel, "fifo_import_prefix")switch_channel_get_variable_dup(other_channel, "fifo_import_prefix"
, SWITCH_TRUE, -1)
);
3346
3347 if (outbound_id) {
3348 cancel_consumer_outbound_call(outbound_id, SWITCH_CAUSE_ORIGINATOR_CANCEL);
3349 add_bridge_call(outbound_id);
3350
3351 sql = switch_mprintf("update fifo_outbound set stop_time=0,start_time=%ld,use_count=use_count+1,outbound_fail_count=0 where uuid='%s'",
3352 switch_epoch_time_now(NULL((void*)0)), outbound_id);
3353
3354 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
3355 fifo_inc_use_count(outbound_id);
3356 }
3357
3358 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3358, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3359 switch_channel_event_set_data(channel, event);
3360 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3361 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-start");
3362 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "onhook");
3363 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", cid_name);
3364 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number);
3365 if (outbound_id) {
3366 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
3367 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
3368 }
3369 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3369, &event, ((void*)0))
;
3370 }
3371
3372 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3372, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3373 switch_channel_event_set_data(channel, event);
3374 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3375 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-start");
3376 if (outbound_id) {
3377 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
3378 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
3379 }
3380
3381 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3381, &event, ((void*)0))
;
3382 }
3383 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3383, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3384 switch_channel_event_set_data(other_channel, event);
3385 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3386 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-start");
3387 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3387, &event, ((void*)0))
;
3388 }
3389
3390 add_bridge_call(switch_core_session_get_uuid(other_session));
3391 add_bridge_call(switch_core_session_get_uuid(session));
3392
3393 sql = switch_mprintf("insert into fifo_bridge "
3394 "(fifo_name,caller_uuid,caller_caller_id_name,caller_caller_id_number,consumer_uuid,consumer_outgoing_uuid,bridge_start) "
3395 "values ('%q','%q','%q','%q','%q','%q',%ld)",
3396 node->name,
3397 switch_core_session_get_uuid(other_session),
3398 switch_str_nil(switch_channel_get_variable(other_channel, "caller_id_name"))(switch_channel_get_variable_dup(other_channel, "caller_id_name"
, SWITCH_TRUE, -1) ? switch_channel_get_variable_dup(other_channel
, "caller_id_name", SWITCH_TRUE, -1) : "")
,
3399 switch_str_nil(switch_channel_get_variable(other_channel, "caller_id_number"))(switch_channel_get_variable_dup(other_channel, "caller_id_number"
, SWITCH_TRUE, -1) ? switch_channel_get_variable_dup(other_channel
, "caller_id_number", SWITCH_TRUE, -1) : "")
,
3400 switch_core_session_get_uuid(session),
3401 switch_str_nil(outbound_id)(outbound_id ? outbound_id : ""),
3402 (long) switch_epoch_time_now(NULL((void*)0))
3403 );
3404
3405 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE);
3406
3407 switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(other_session))switch_channel_set_variable_var_check(channel, "signal_bond",
switch_core_session_get_uuid(other_session), SWITCH_TRUE)
;
3408 switch_channel_set_variable(other_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session))switch_channel_set_variable_var_check(other_channel, "signal_bond"
, switch_core_session_get_uuid(session), SWITCH_TRUE)
;
3409
3410 switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_initiated_bridge", "true")switch_channel_set_variable_var_check(switch_core_session_get_channel
(other_session), "fifo_initiated_bridge", "true", SWITCH_TRUE
)
;
3411 switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_bridge_role", "caller")switch_channel_set_variable_var_check(switch_core_session_get_channel
(other_session), "fifo_bridge_role", "caller", SWITCH_TRUE)
;
3412 switch_channel_set_variable(switch_core_session_get_channel(session), "fifo_initiated_bridge", "true")switch_channel_set_variable_var_check(switch_core_session_get_channel
(session), "fifo_initiated_bridge", "true", SWITCH_TRUE)
;
3413 switch_channel_set_variable(switch_core_session_get_channel(session), "fifo_bridge_role", "consumer")switch_channel_set_variable_var_check(switch_core_session_get_channel
(session), "fifo_bridge_role", "consumer", SWITCH_TRUE)
;
3414
3415 switch_ivr_multi_threaded_bridge(session, other_session, on_dtmf, other_session, session);
3416
3417 if (switch_channel_test_flag(other_channel, CF_TRANSFER) && switch_channel_up(other_channel)(switch_channel_check_signal(other_channel, SWITCH_TRUE) || switch_channel_get_state
(other_channel) < CS_HANGUP)
) {
3418 switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_initiated_bridge", NULL)switch_channel_set_variable_var_check(switch_core_session_get_channel
(other_session), "fifo_initiated_bridge", ((void*)0), SWITCH_TRUE
)
;
3419 switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_bridge_role", NULL)switch_channel_set_variable_var_check(switch_core_session_get_channel
(other_session), "fifo_bridge_role", ((void*)0), SWITCH_TRUE)
;
3420 }
3421
3422 if (switch_channel_test_flag(channel, CF_TRANSFER) && switch_channel_up(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state
(channel) < CS_HANGUP)
) {
3423 switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_initiated_bridge", NULL)switch_channel_set_variable_var_check(switch_core_session_get_channel
(other_session), "fifo_initiated_bridge", ((void*)0), SWITCH_TRUE
)
;
3424 switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_bridge_role", NULL)switch_channel_set_variable_var_check(switch_core_session_get_channel
(other_session), "fifo_bridge_role", ((void*)0), SWITCH_TRUE)
;
3425 }
3426
3427 if (outbound_id) {
3428 long now = (long) switch_epoch_time_now(NULL((void*)0));
3429
3430 sql = switch_mprintf("update fifo_outbound set stop_time=%ld, use_count=use_count-1, "
3431 "outbound_call_total_count=outbound_call_total_count+1, "
3432 "outbound_call_count=outbound_call_count+1, next_avail=%ld + lag + 1 where uuid='%s' and use_count > 0",
3433 now, now, outbound_id);
3434
3435 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
3436
3437 del_bridge_call(outbound_id);
3438 fifo_dec_use_count(outbound_id);
3439 }
3440
3441 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3441, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3442 uint64_t hold_usec = 0, tt_usec = 0;
3443 switch_channel_event_set_data(channel, event);
3444 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", arg_fifo_name);
3445 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-stop");
3446 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "onhook");
3447 if (outbound_id) {
3448 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
3449 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
3450 }
3451 hold_usec = originator_cp->times->hold_accum;
3452 tt_usec = (switch_micro_time_now() - originator_cp->times->bridged) - hold_usec;
3453 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Bridge-Time-us", "%"SWITCH_TIME_T_FMT"ld", originator_cp->times->bridged);
3454 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Bridge-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(originator_cp->times->bridged / 1000));
3455 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Bridge-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(originator_cp->times->bridged / 1000000));
3456 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Talk-Time-us", "%"SWITCH_TIME_T_FMT"ld", tt_usec);
3457 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Talk-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(tt_usec / 1000));
3458 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Talk-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(tt_usec / 1000000));
3459 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-us", "%"SWITCH_TIME_T_FMT"ld", hold_usec);
3460 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(hold_usec / 1000));
3461 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(hold_usec / 1000000));
3462
3463 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3463, &event, ((void*)0))
;
3464 }
3465
3466 del_bridge_call(switch_core_session_get_uuid(session));
3467 del_bridge_call(switch_core_session_get_uuid(other_session));
3468
3469 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3469, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3470 switch_channel_event_set_data(channel, event);
3471 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3472 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-stop");
3473 if (outbound_id) {
3474 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
3475 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
3476 }
3477 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3477, &event, ((void*)0))
;
3478 }
3479 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3479, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3480 uint64_t hold_usec = 0, tt_usec = 0;
3481 switch_channel_event_set_data(other_channel, event);
3482 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3483 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-caller-stop");
3484 hold_usec = originatee_cp->times->hold_accum;
3485 tt_usec = (switch_micro_time_now() - originatee_cp->times->bridged) - hold_usec;
3486 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-Talk-Time-us", "%"SWITCH_TIME_T_FMT"ld", tt_usec);
3487 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-Talk-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(tt_usec / 1000));
3488 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-Talk-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(tt_usec / 1000000));
3489 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-Hold-Time-us", "%"SWITCH_TIME_T_FMT"ld", hold_usec);
3490 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-Hold-Time-ms", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(hold_usec / 1000));
3491 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-Hold-Time-s", "%"SWITCH_TIME_T_FMT"ld", (uint64_t)(hold_usec / 1000000));
3492 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3492, &event, ((void*)0))
;
3493 }
3494
3495 epoch_end = (long)switch_epoch_time_now(NULL((void*)0));
3496
3497 switch_channel_set_variable_printf(channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
3498 switch_channel_set_variable_printf(channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
3499
3500 switch_channel_set_variable_printf(other_channel, "fifo_epoch_stop_bridge", "%ld", epoch_end);
3501 switch_channel_set_variable_printf(other_channel, "fifo_bridge_seconds", "%d", epoch_end - epoch_start);
3502
3503 sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(session));
3504 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE);
3505
3506 if (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
3507 switch_core_media_bug_pause(session);
3508 }
3509
3510 if (record_template) {
3511 switch_ivr_stop_record_session(session, expanded);
3512 if (expanded != record_template) {
3513 switch_safe_free(expanded)if (expanded) {free(expanded);expanded=((void*)0);};
3514 }
3515 }
3516
3517 ts = switch_micro_time_now();
3518 switch_time_exp_lt(&tm, ts);
3519 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
3520 switch_channel_set_variable(channel, "fifo_status", "WAITING")switch_channel_set_variable_var_check(channel, "fifo_status",
"WAITING", SWITCH_TRUE)
;
3521 switch_channel_set_variable(channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
3522
3523 switch_channel_set_variable(other_channel, "fifo_status", "DONE")switch_channel_set_variable_var_check(other_channel, "fifo_status"
, "DONE", SWITCH_TRUE)
;
3524 switch_channel_set_variable(other_channel, "fifo_timestamp", date)switch_channel_set_variable_var_check(other_channel, "fifo_timestamp"
, date, SWITCH_TRUE)
;
3525
3526 send_presence(node);
3527 check_cancel(node);
3528
3529 switch_core_session_rwunlock(other_session);
3530
3531 if (!do_wait || !switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
3532 break;
3533 }
3534
3535 fifo_consumer_wrapup_sound = switch_channel_get_variable(channel, "fifo_consumer_wrapup_sound")switch_channel_get_variable_dup(channel, "fifo_consumer_wrapup_sound"
, SWITCH_TRUE, -1)
;
3536 fifo_consumer_wrapup_key = switch_channel_get_variable(channel, "fifo_consumer_wrapup_key")switch_channel_get_variable_dup(channel, "fifo_consumer_wrapup_key"
, SWITCH_TRUE, -1)
;
3537 sfifo_consumer_wrapup_time = switch_channel_get_variable(channel, "fifo_consumer_wrapup_time")switch_channel_get_variable_dup(channel, "fifo_consumer_wrapup_time"
, SWITCH_TRUE, -1)
;
3538 if (!zstr(sfifo_consumer_wrapup_time)_zstr(sfifo_consumer_wrapup_time)) {
3539 fifo_consumer_wrapup_time = atoi(sfifo_consumer_wrapup_time);
3540 } else {
3541 fifo_consumer_wrapup_time = 5000;
3542 }
3543
3544 memset(buf, 0, sizeof(buf));
3545
3546 if (fifo_consumer_wrapup_time || !zstr(fifo_consumer_wrapup_key)_zstr(fifo_consumer_wrapup_key)) {
3547 switch_channel_set_variable(channel, "fifo_status", "WRAPUP")switch_channel_set_variable_var_check(channel, "fifo_status",
"WRAPUP", SWITCH_TRUE)
;
3548 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3548, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3549 switch_channel_event_set_data(channel, event);
3550 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3551 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_wrapup");
3552 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3552, &event, ((void*)0))
;
3553 }
3554 }
3555
3556 if (!zstr(fifo_consumer_wrapup_sound)_zstr(fifo_consumer_wrapup_sound)) {
3557 memset(&args, 0, sizeof(args));
3558 args.buf = buf;
3559 args.buflen = sizeof(buf);
3560 status = switch_ivr_play_file(session, NULL((void*)0), fifo_consumer_wrapup_sound, &args);
3561 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
) {
3562 break;
3563 }
3564 }
3565
3566 if (fifo_consumer_wrapup_time) {
3567 wrapup_time_started = switch_micro_time_now();
3568 }
3569
3570 if (!zstr(fifo_consumer_wrapup_key)_zstr(fifo_consumer_wrapup_key) && strcmp(buf, fifo_consumer_wrapup_key)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(buf) && __builtin_constant_p (fifo_consumer_wrapup_key
) && (__s1_len = __builtin_strlen (buf), __s2_len = __builtin_strlen
(fifo_consumer_wrapup_key), (!((size_t)(const void *)((buf) +
1) - (size_t)(const void *)(buf) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((fifo_consumer_wrapup_key) + 1) - (
size_t)(const void *)(fifo_consumer_wrapup_key) == 1) || __s2_len
>= 4)) ? __builtin_strcmp (buf, fifo_consumer_wrapup_key)
: (__builtin_constant_p (buf) && ((size_t)(const void
*)((buf) + 1) - (size_t)(const void *)(buf) == 1) &&
(__s1_len = __builtin_strlen (buf), __s1_len < 4) ? (__builtin_constant_p
(fifo_consumer_wrapup_key) && ((size_t)(const void *
)((fifo_consumer_wrapup_key) + 1) - (size_t)(const void *)(fifo_consumer_wrapup_key
) == 1) ? __builtin_strcmp (buf, fifo_consumer_wrapup_key) : (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (fifo_consumer_wrapup_key); int __result =
(((const unsigned char *) (const char *) (buf))[0] - __s2[0]
); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (buf))[1] - __s2[1]
); if (__s1_len > 1 && __result == 0) { __result =
(((const unsigned char *) (const char *) (buf))[2] - __s2[2]
); if (__s1_len > 2 && __result == 0) __result = (
((const unsigned char *) (const char *) (buf))[3] - __s2[3]);
} } __result; }))) : (__builtin_constant_p (fifo_consumer_wrapup_key
) && ((size_t)(const void *)((fifo_consumer_wrapup_key
) + 1) - (size_t)(const void *)(fifo_consumer_wrapup_key) == 1
) && (__s2_len = __builtin_strlen (fifo_consumer_wrapup_key
), __s2_len < 4) ? (__builtin_constant_p (buf) && (
(size_t)(const void *)((buf) + 1) - (size_t)(const void *)(buf
) == 1) ? __builtin_strcmp (buf, fifo_consumer_wrapup_key) : (
- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (buf); int __result = (((const unsigned
char *) (const char *) (fifo_consumer_wrapup_key))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (fifo_consumer_wrapup_key
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (fifo_consumer_wrapup_key
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (fifo_consumer_wrapup_key
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (buf
, fifo_consumer_wrapup_key)))); })
) {
3571 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
3572 char terminator = 0;
3573
3574 if (fifo_consumer_wrapup_time) {
3575 wrapup_time_elapsed = (switch_micro_time_now() - wrapup_time_started) / 1000;
3576 if (wrapup_time_elapsed > fifo_consumer_wrapup_time) {
3577 break;
3578 } else {
3579 wrapup_time_remaining = fifo_consumer_wrapup_time - wrapup_time_elapsed + 100;
3580 }
3581 }
3582
3583 switch_ivr_collect_digits_count(session, buf, sizeof(buf) - 1, 1, fifo_consumer_wrapup_key, &terminator, 0, 0,
3584 (uint32_t) wrapup_time_remaining);
3585 if ((terminator == *fifo_consumer_wrapup_key) || !(switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE))) {
3586 break;
3587 }
3588 }
3589 } else if (fifo_consumer_wrapup_time && (zstr(fifo_consumer_wrapup_key)_zstr(fifo_consumer_wrapup_key) || !strcmp(buf, fifo_consumer_wrapup_key)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(buf) && __builtin_constant_p (fifo_consumer_wrapup_key
) && (__s1_len = __builtin_strlen (buf), __s2_len = __builtin_strlen
(fifo_consumer_wrapup_key), (!((size_t)(const void *)((buf) +
1) - (size_t)(const void *)(buf) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((fifo_consumer_wrapup_key) + 1) - (
size_t)(const void *)(fifo_consumer_wrapup_key) == 1) || __s2_len
>= 4)) ? __builtin_strcmp (buf, fifo_consumer_wrapup_key)
: (__builtin_constant_p (buf) && ((size_t)(const void
*)((buf) + 1) - (size_t)(const void *)(buf) == 1) &&
(__s1_len = __builtin_strlen (buf), __s1_len < 4) ? (__builtin_constant_p
(fifo_consumer_wrapup_key) && ((size_t)(const void *
)((fifo_consumer_wrapup_key) + 1) - (size_t)(const void *)(fifo_consumer_wrapup_key
) == 1) ? __builtin_strcmp (buf, fifo_consumer_wrapup_key) : (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (fifo_consumer_wrapup_key); int __result =
(((const unsigned char *) (const char *) (buf))[0] - __s2[0]
); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (buf))[1] - __s2[1]
); if (__s1_len > 1 && __result == 0) { __result =
(((const unsigned char *) (const char *) (buf))[2] - __s2[2]
); if (__s1_len > 2 && __result == 0) __result = (
((const unsigned char *) (const char *) (buf))[3] - __s2[3]);
} } __result; }))) : (__builtin_constant_p (fifo_consumer_wrapup_key
) && ((size_t)(const void *)((fifo_consumer_wrapup_key
) + 1) - (size_t)(const void *)(fifo_consumer_wrapup_key) == 1
) && (__s2_len = __builtin_strlen (fifo_consumer_wrapup_key
), __s2_len < 4) ? (__builtin_constant_p (buf) && (
(size_t)(const void *)((buf) + 1) - (size_t)(const void *)(buf
) == 1) ? __builtin_strcmp (buf, fifo_consumer_wrapup_key) : (
- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (buf); int __result = (((const unsigned
char *) (const char *) (fifo_consumer_wrapup_key))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (fifo_consumer_wrapup_key
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (fifo_consumer_wrapup_key
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (fifo_consumer_wrapup_key
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (buf
, fifo_consumer_wrapup_key)))); })
)) {
3590 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
3591 wrapup_time_elapsed = (switch_micro_time_now() - wrapup_time_started) / 1000;
3592 if (wrapup_time_elapsed > fifo_consumer_wrapup_time) {
3593 break;
3594 }
3595 switch_yield(500)switch_sleep(500);;
3596 }
3597 }
3598 switch_channel_set_variable(channel, "fifo_status", "WAITING")switch_channel_set_variable_var_check(channel, "fifo_status",
"WAITING", SWITCH_TRUE)
;
3599 }
3600
3601 if (do_wait && switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
3602 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3602, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3603 switch_channel_event_set_data(channel, event);
3604 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3605 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_reentrance");
3606 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3606, &event, ((void*)0))
;
3607 }
3608 }
3609 }
3610
3611 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 3611, &event, SWITCH_EVENT_CUSTOM
, "fifo::info")
== SWITCH_STATUS_SUCCESS) {
3612 switch_channel_event_set_data(channel, event);
3613 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
3614 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_stop");
3615 switch_event_fire(&event)switch_event_fire_detailed("mod_fifo.c", (const char * )(const
char *)__func__, 3615, &event, ((void*)0))
;
3616 }
3617
3618 if (do_wait) {
3619 for (i = 0; i < node_count; i++) {
3620 if (!(node = node_list[i])) {
3621 continue;
3622 }
3623 switch_mutex_lock(node->mutex);
3624 switch_core_hash_delete(node->consumer_hash, switch_core_session_get_uuid(session));
3625 node->consumer_count--;
3626 switch_mutex_unlock(node->mutex);
3627 }
3628 }
3629
3630 if (outbound_id && switch_channel_up(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state
(channel) < CS_HANGUP)
) {
3631 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_fifo.c", (const char *)__func__
, 3631, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s is still alive, tracking call.\n", switch_channel_get_name(channel));
3632 fifo_track_call_function(session, outbound_id);
3633 }
3634 }
3635
3636 done:
3637
3638 if (!consumer && in_table) {
3639 fifo_caller_del(switch_core_session_get_uuid(session));
3640 }
3641
3642 if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use")switch_channel_get_variable_dup(channel, "fifo_destroy_after_use"
, SWITCH_TRUE, -1)
)) {
3643 do_destroy = 1;
3644 }
3645
3646 switch_mutex_lock(globals.mutex);
3647 for (i = 0; i < node_count; i++) {
3648 if (!(node = node_list[i])) {
3649 continue;
3650 }
3651 switch_thread_rwlock_unlock(node->rwlock);
3652
3653 if (node->ready == 1 && do_destroy && node_caller_count(node) == 0 && node->consumer_count == 0) {
3654 switch_core_hash_delete(globals.fifo_hash, node->name);
3655 node->ready = 0;
3656 }
3657 }
3658 switch_mutex_unlock(globals.mutex);
3659
3660 switch_channel_clear_app_flag_key(FIFO_APP_KEY"mod_fifo", channel, FIFO_APP_BRIDGE_TAG);
3661
3662 switch_core_media_bug_resume(session);
3663}
3664
3665struct xml_helper {
3666 switch_xml_t xml;
3667 fifo_node_t *node;
3668 char *container;
3669 char *tag;
3670 int cc_off;
3671 int row_off;
3672 int verbose;
3673};
3674
3675static int xml_callback(void *pArg, int argc, char **argv, char **columnNames)
3676{
3677 struct xml_helper *h = (struct xml_helper *) pArg;
3678 switch_xml_t x_out;
3679 int c_off = 0;
3680 char exp_buf[128] = "";
3681 switch_time_exp_t tm;
3682 switch_time_t etime = 0;
3683 char atime[128] = "";
3684 char *expires = exp_buf, *tb = atime;
3685 int arg = 0;
3686
3687 for(arg = 0; arg < argc; arg++) {
3688 if (!argv[arg]) {
3689 argv[arg] = "";
3690 }
3691 }
3692
3693 arg = 0;
3694
3695 if (argv[7]) {
3696 if ((etime = atol(argv[7]))) {
3697 switch_size_t retsize;
3698
3699 switch_time_exp_lt(&tm, switch_time_from_sec(etime)((switch_time_t)(etime) * 1000000));
3700 switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
3701 } else {
3702 switch_set_string(exp_buf, "now")switch_copy_string(exp_buf, "now", sizeof(exp_buf));
3703 }
3704 }
3705
3706 if (atoi(argv[13])) {
3707 arg = 17;
3708 } else {
3709 arg = 18;
3710 }
3711
3712 if ((etime = atol(argv[arg]))) {
3713 switch_size_t retsize;
3714 switch_time_exp_lt(&tm, switch_time_from_sec(etime)((switch_time_t)(etime) * 1000000));
3715 switch_strftime_nocheck(atime, &retsize, sizeof(atime), "%Y-%m-%d %T", &tm);
3716 } else {
3717 switch_set_string(atime, "now")switch_copy_string(atime, "now", sizeof(atime));
3718 }
3719
3720 x_out = switch_xml_add_child_d(h->xml, h->tag, c_off++)switch_xml_set_flag(switch_xml_add_child(h->xml, (__extension__
(__builtin_constant_p (h->tag) && ((size_t)(const
void *)((h->tag) + 1) - (size_t)(const void *)(h->tag)
== 1) ? (((const char *) (h->tag))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (h->tag
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, h->tag
, __len); __retval; })) : __strdup (h->tag))), c_off++), SWITCH_XML_NAMEM
)
;
3721 switch_xml_set_attr_d(x_out, "simo", argv[3])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("simo") && (
(size_t)(const void *)(("simo") + 1) - (size_t)(const void *)
("simo") == 1) ? (((const char *) ("simo"))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
("simo") + 1; char *__retval = (char *) malloc (__len); if (
__retval != ((void*)0)) __retval = (char *) memcpy (__retval,
"simo", __len); __retval; })) : __strdup ("simo"))), (__extension__
(__builtin_constant_p ((argv[3] ? argv[3] : "")) && (
(size_t)(const void *)(((argv[3] ? argv[3] : "")) + 1) - (size_t
)(const void *)((argv[3] ? argv[3] : "")) == 1) ? (((const char
*) ((argv[3] ? argv[3] : "")))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((argv[3] ?
argv[3] : "")) + 1; char *__retval = (char *) malloc (__len)
; if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (argv[3] ? argv[3] : ""), __len); __retval; })) : __strdup (
(argv[3] ? argv[3] : "")))))
;
3722 switch_xml_set_attr_d(x_out, "use_count", argv[4])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("use_count") &&
((size_t)(const void *)(("use_count") + 1) - (size_t)(const void
*)("use_count") == 1) ? (((const char *) ("use_count"))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("use_count") + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "use_count", __len); __retval; })) : __strdup ("use_count"
))), (__extension__ (__builtin_constant_p ((argv[4] ? argv[4]
: "")) && ((size_t)(const void *)(((argv[4] ? argv[4
] : "")) + 1) - (size_t)(const void *)((argv[4] ? argv[4] : ""
)) == 1) ? (((const char *) ((argv[4] ? argv[4] : "")))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((argv[4] ? argv[4] : "")) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (argv[4] ? argv[4] : ""), __len); __retval
; })) : __strdup ((argv[4] ? argv[4] : "")))))
;
3723 switch_xml_set_attr_d(x_out, "timeout", argv[5])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("timeout") &&
((size_t)(const void *)(("timeout") + 1) - (size_t)(const void
*)("timeout") == 1) ? (((const char *) ("timeout"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("timeout") + 1; char *__retval = (char *) malloc (
__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "timeout", __len); __retval; })) : __strdup ("timeout"
))), (__extension__ (__builtin_constant_p ((argv[5] ? argv[5]
: "")) && ((size_t)(const void *)(((argv[5] ? argv[5
] : "")) + 1) - (size_t)(const void *)((argv[5] ? argv[5] : ""
)) == 1) ? (((const char *) ((argv[5] ? argv[5] : "")))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((argv[5] ? argv[5] : "")) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (argv[5] ? argv[5] : ""), __len); __retval
; })) : __strdup ((argv[5] ? argv[5] : "")))))
;
3724 switch_xml_set_attr_d(x_out, "lag", argv[6])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("lag") && ((
size_t)(const void *)(("lag") + 1) - (size_t)(const void *)("lag"
) == 1) ? (((const char *) ("lag"))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("lag") +
1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, "lag", __len
); __retval; })) : __strdup ("lag"))), (__extension__ (__builtin_constant_p
((argv[6] ? argv[6] : "")) && ((size_t)(const void *
)(((argv[6] ? argv[6] : "")) + 1) - (size_t)(const void *)((argv
[6] ? argv[6] : "")) == 1) ? (((const char *) ((argv[6] ? argv
[6] : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t
) 1) : ({ size_t __len = strlen ((argv[6] ? argv[6] : "")) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, (argv[6] ? argv
[6] : ""), __len); __retval; })) : __strdup ((argv[6] ? argv[
6] : "")))))
;
3725 switch_xml_set_attr_d(x_out, "outbound-call-count", argv[10])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound-call-count"
) && ((size_t)(const void *)(("outbound-call-count") +
1) - (size_t)(const void *)("outbound-call-count") == 1) ? (
((const char *) ("outbound-call-count"))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
"outbound-call-count") + 1; char *__retval = (char *) malloc (
__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "outbound-call-count", __len); __retval; })) : __strdup
("outbound-call-count"))), (__extension__ (__builtin_constant_p
((argv[10] ? argv[10] : "")) && ((size_t)(const void
*)(((argv[10] ? argv[10] : "")) + 1) - (size_t)(const void *
)((argv[10] ? argv[10] : "")) == 1) ? (((const char *) ((argv
[10] ? argv[10] : "")))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ((argv[10] ? argv
[10] : "")) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (argv[10] ? argv[10] : ""), __len); __retval; })) : __strdup
((argv[10] ? argv[10] : "")))))
;
3726 switch_xml_set_attr_d(x_out, "outbound-fail-count", argv[11])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound-fail-count"
) && ((size_t)(const void *)(("outbound-fail-count") +
1) - (size_t)(const void *)("outbound-fail-count") == 1) ? (
((const char *) ("outbound-fail-count"))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
"outbound-fail-count") + 1; char *__retval = (char *) malloc (
__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "outbound-fail-count", __len); __retval; })) : __strdup
("outbound-fail-count"))), (__extension__ (__builtin_constant_p
((argv[11] ? argv[11] : "")) && ((size_t)(const void
*)(((argv[11] ? argv[11] : "")) + 1) - (size_t)(const void *
)((argv[11] ? argv[11] : "")) == 1) ? (((const char *) ((argv
[11] ? argv[11] : "")))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ((argv[11] ? argv
[11] : "")) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (argv[11] ? argv[11] : ""), __len); __retval; })) : __strdup
((argv[11] ? argv[11] : "")))))
;
3727 switch_xml_set_attr_d(x_out, "taking-calls", argv[13])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("taking-calls") &&
((size_t)(const void *)(("taking-calls") + 1) - (size_t)(const
void *)("taking-calls") == 1) ? (((const char *) ("taking-calls"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("taking-calls") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "taking-calls", __len); __retval
; })) : __strdup ("taking-calls"))), (__extension__ (__builtin_constant_p
((argv[13] ? argv[13] : "")) && ((size_t)(const void
*)(((argv[13] ? argv[13] : "")) + 1) - (size_t)(const void *
)((argv[13] ? argv[13] : "")) == 1) ? (((const char *) ((argv
[13] ? argv[13] : "")))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ((argv[13] ? argv
[13] : "")) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (argv[13] ? argv[13] : ""), __len); __retval; })) : __strdup
((argv[13] ? argv[13] : "")))))
;
3728 switch_xml_set_attr_d(x_out, "status", argv[14])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("status") &&
((size_t)(const void *)(("status") + 1) - (size_t)(const void
*)("status") == 1) ? (((const char *) ("status"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("status") + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, "status", __len); __retval; })) : __strdup ("status"))), (__extension__
(__builtin_constant_p ((argv[14] ? argv[14] : "")) &&
((size_t)(const void *)(((argv[14] ? argv[14] : "")) + 1) - (
size_t)(const void *)((argv[14] ? argv[14] : "")) == 1) ? (((
const char *) ((argv[14] ? argv[14] : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((argv[14] ? argv[14] : "")) + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, (argv[14] ? argv[14] : ""), __len); __retval; }))
: __strdup ((argv[14] ? argv[14] : "")))))
;
3729
3730 switch_xml_set_attr_d(x_out, "outbound-call-total-count", argv[15])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound-call-total-count"
) && ((size_t)(const void *)(("outbound-call-total-count"
) + 1) - (size_t)(const void *)("outbound-call-total-count") ==
1) ? (((const char *) ("outbound-call-total-count"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("outbound-call-total-count") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "outbound-call-total-count", __len
); __retval; })) : __strdup ("outbound-call-total-count"))), (
__extension__ (__builtin_constant_p ((argv[15] ? argv[15] : ""
)) && ((size_t)(const void *)(((argv[15] ? argv[15] :
"")) + 1) - (size_t)(const void *)((argv[15] ? argv[15] : ""
)) == 1) ? (((const char *) ((argv[15] ? argv[15] : "")))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((argv[15] ? argv[15] : "")) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, (argv[15] ? argv[15] : ""), __len
); __retval; })) : __strdup ((argv[15] ? argv[15] : "")))))
;
3731 switch_xml_set_attr_d(x_out, "outbound-fail-total-count", argv[16])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound-fail-total-count"
) && ((size_t)(const void *)(("outbound-fail-total-count"
) + 1) - (size_t)(const void *)("outbound-fail-total-count") ==
1) ? (((const char *) ("outbound-fail-total-count"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("outbound-fail-total-count") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "outbound-fail-total-count", __len
); __retval; })) : __strdup ("outbound-fail-total-count"))), (
__extension__ (__builtin_constant_p ((argv[16] ? argv[16] : ""
)) && ((size_t)(const void *)(((argv[16] ? argv[16] :
"")) + 1) - (size_t)(const void *)((argv[16] ? argv[16] : ""
)) == 1) ? (((const char *) ((argv[16] ? argv[16] : "")))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((argv[16] ? argv[16] : "")) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, (argv[16] ? argv[16] : ""), __len
); __retval; })) : __strdup ((argv[16] ? argv[16] : "")))))
;
3732
3733 if (arg == 17) {
3734 switch_xml_set_attr_d(x_out, "logged-on-since", tb)switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("logged-on-since") &&
((size_t)(const void *)(("logged-on-since") + 1) - (size_t)(
const void *)("logged-on-since") == 1) ? (((const char *) ("logged-on-since"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("logged-on-since") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "logged-on-since", __len); __retval
; })) : __strdup ("logged-on-since"))), (__extension__ (__builtin_constant_p
((tb ? tb : "")) && ((size_t)(const void *)(((tb ? tb
: "")) + 1) - (size_t)(const void *)((tb ? tb : "")) == 1) ?
(((const char *) ((tb ? tb : "")))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((tb ? tb
: "")) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, (tb ? tb
: ""), __len); __retval; })) : __strdup ((tb ? tb : "")))))
;
3735 } else {
3736 switch_xml_set_attr_d(x_out, "logged-off-since", tb)switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("logged-off-since") &&
((size_t)(const void *)(("logged-off-since") + 1) - (size_t)
(const void *)("logged-off-since") == 1) ? (((const char *) (
"logged-off-since"))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen ("logged-off-since")
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, "logged-off-since"
, __len); __retval; })) : __strdup ("logged-off-since"))), (__extension__
(__builtin_constant_p ((tb ? tb : "")) && ((size_t)(
const void *)(((tb ? tb : "")) + 1) - (size_t)(const void *)(
(tb ? tb : "")) == 1) ? (((const char *) ((tb ? tb : "")))[0]
== '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t
__len = strlen ((tb ? tb : "")) + 1; char *__retval = (char *
) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (tb ? tb : ""), __len); __retval; })) :
__strdup ((tb ? tb : "")))))
;
3737 }
3738
3739 switch_xml_set_attr_d(x_out, "manual-calls-out-count", argv[19])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("manual-calls-out-count"
) && ((size_t)(const void *)(("manual-calls-out-count"
) + 1) - (size_t)(const void *)("manual-calls-out-count") == 1
) ? (((const char *) ("manual-calls-out-count"))[0] == '\0' ?
(char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len =
strlen ("manual-calls-out-count") + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, "manual-calls-out-count", __len); __retval
; })) : __strdup ("manual-calls-out-count"))), (__extension__
(__builtin_constant_p ((argv[19] ? argv[19] : "")) &&
((size_t)(const void *)(((argv[19] ? argv[19] : "")) + 1) - (
size_t)(const void *)((argv[19] ? argv[19] : "")) == 1) ? (((
const char *) ((argv[19] ? argv[19] : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((argv[19] ? argv[19] : "")) + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, (argv[19] ? argv[19] : ""), __len); __retval; }))
: __strdup ((argv[19] ? argv[19] : "")))))
;
3740 switch_xml_set_attr_d(x_out, "manual-calls-in-count", argv[20])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("manual-calls-in-count"
) && ((size_t)(const void *)(("manual-calls-in-count"
) + 1) - (size_t)(const void *)("manual-calls-in-count") == 1
) ? (((const char *) ("manual-calls-in-count"))[0] == '\0' ? (
char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
("manual-calls-in-count") + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "manual-calls-in-count", __len); __retval; })) : __strdup
("manual-calls-in-count"))), (__extension__ (__builtin_constant_p
((argv[20] ? argv[20] : "")) && ((size_t)(const void
*)(((argv[20] ? argv[20] : "")) + 1) - (size_t)(const void *
)((argv[20] ? argv[20] : "")) == 1) ? (((const char *) ((argv
[20] ? argv[20] : "")))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ((argv[20] ? argv
[20] : "")) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (argv[20] ? argv[20] : ""), __len); __retval; })) : __strdup
((argv[20] ? argv[20] : "")))))
;
3741 switch_xml_set_attr_d(x_out, "manual-calls-out-total-count", argv[21])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("manual-calls-out-total-count"
) && ((size_t)(const void *)(("manual-calls-out-total-count"
) + 1) - (size_t)(const void *)("manual-calls-out-total-count"
) == 1) ? (((const char *) ("manual-calls-out-total-count"))[
0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t
__len = strlen ("manual-calls-out-total-count") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "manual-calls-out-total-count",
__len); __retval; })) : __strdup ("manual-calls-out-total-count"
))), (__extension__ (__builtin_constant_p ((argv[21] ? argv[21
] : "")) && ((size_t)(const void *)(((argv[21] ? argv
[21] : "")) + 1) - (size_t)(const void *)((argv[21] ? argv[21
] : "")) == 1) ? (((const char *) ((argv[21] ? argv[21] : "")
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ((argv[21] ? argv[21] : "")) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, (argv[21] ? argv[21
] : ""), __len); __retval; })) : __strdup ((argv[21] ? argv[21
] : "")))))
;
3742 switch_xml_set_attr_d(x_out, "manual-calls-in-total-count", argv[22])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("manual-calls-in-total-count"
) && ((size_t)(const void *)(("manual-calls-in-total-count"
) + 1) - (size_t)(const void *)("manual-calls-in-total-count"
) == 1) ? (((const char *) ("manual-calls-in-total-count"))[0
] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t
__len = strlen ("manual-calls-in-total-count") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "manual-calls-in-total-count", __len
); __retval; })) : __strdup ("manual-calls-in-total-count")))
, (__extension__ (__builtin_constant_p ((argv[22] ? argv[22] :
"")) && ((size_t)(const void *)(((argv[22] ? argv[22
] : "")) + 1) - (size_t)(const void *)((argv[22] ? argv[22] :
"")) == 1) ? (((const char *) ((argv[22] ? argv[22] : "")))[
0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t
__len = strlen ((argv[22] ? argv[22] : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (argv[22] ? argv[22] : ""), __len
); __retval; })) : __strdup ((argv[22] ? argv[22] : "")))))
;
3743
3744 if (argc > 23) {
3745 switch_xml_set_attr_d(x_out, "ring-count", argv[23])switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("ring-count") &&
((size_t)(const void *)(("ring-count") + 1) - (size_t)(const
void *)("ring-count") == 1) ? (((const char *) ("ring-count"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("ring-count") + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, "ring-count", __len); __retval; }
)) : __strdup ("ring-count"))), (__extension__ (__builtin_constant_p
((argv[23] ? argv[23] : "")) && ((size_t)(const void
*)(((argv[23] ? argv[23] : "")) + 1) - (size_t)(const void *
)((argv[23] ? argv[23] : "")) == 1) ? (((const char *) ((argv
[23] ? argv[23] : "")))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ((argv[23] ? argv
[23] : "")) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (argv[23] ? argv[23] : ""), __len); __retval; })) : __strdup
((argv[23] ? argv[23] : "")))))
;
3746
3747 if ((etime = atol(argv[24]))) {
3748 switch_size_t retsize;
3749 switch_time_exp_lt(&tm, switch_time_from_sec(etime)((switch_time_t)(etime) * 1000000));
3750 switch_strftime_nocheck(atime, &retsize, sizeof(atime), "%Y-%m-%d %T", &tm);
3751 } else {
3752 switch_set_string(atime, "never")switch_copy_string(atime, "never", sizeof(atime));
3753 }
3754
3755 switch_xml_set_attr_d(x_out, "start-time", tb)switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("start-time") &&
((size_t)(const void *)(("start-time") + 1) - (size_t)(const
void *)("start-time") == 1) ? (((const char *) ("start-time"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("start-time") + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, "start-time", __len); __retval; }
)) : __strdup ("start-time"))), (__extension__ (__builtin_constant_p
((tb ? tb : "")) && ((size_t)(const void *)(((tb ? tb
: "")) + 1) - (size_t)(const void *)((tb ? tb : "")) == 1) ?
(((const char *) ((tb ? tb : "")))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((tb ? tb
: "")) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, (tb ? tb
: ""), __len); __retval; })) : __strdup ((tb ? tb : "")))))
;
3756
3757 if ((etime = atol(argv[25]))) {
3758 switch_size_t retsize;
3759 switch_time_exp_lt(&tm, switch_time_from_sec(etime)((switch_time_t)(etime) * 1000000));
3760 switch_strftime_nocheck(atime, &retsize, sizeof(atime), "%Y-%m-%d %T", &tm);
3761 } else {
3762 switch_set_string(atime, "never")switch_copy_string(atime, "never", sizeof(atime));
3763 }
3764
3765 switch_xml_set_attr_d(x_out, "stop-time", tb)switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("stop-time") &&
((size_t)(const void *)(("stop-time") + 1) - (size_t)(const void
*)("stop-time") == 1) ? (((const char *) ("stop-time"))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("stop-time") + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "stop-time", __len); __retval; })) : __strdup ("stop-time"
))), (__extension__ (__builtin_constant_p ((tb ? tb : "")) &&
((size_t)(const void *)(((tb ? tb : "")) + 1) - (size_t)(const
void *)((tb ? tb : "")) == 1) ? (((const char *) ((tb ? tb :
"")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) :
({ size_t __len = strlen ((tb ? tb : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (tb ? tb : ""), __len); __retval
; })) : __strdup ((tb ? tb : "")))))
;
3766 }
3767
3768 switch_xml_set_attr_d(x_out, "next-available", expires)switch_xml_set_attr(switch_xml_set_flag(x_out, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("next-available") &&
((size_t)(const void *)(("next-available") + 1) - (size_t)(const
void *)("next-available") == 1) ? (((const char *) ("next-available"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("next-available") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "next-available", __len); __retval
; })) : __strdup ("next-available"))), (__extension__ (__builtin_constant_p
((expires ? expires : "")) && ((size_t)(const void *
)(((expires ? expires : "")) + 1) - (size_t)(const void *)((expires
? expires : "")) == 1) ? (((const char *) ((expires ? expires
: "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1
) : ({ size_t __len = strlen ((expires ? expires : "")) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, (expires ? expires
: ""), __len); __retval; })) : __strdup ((expires ? expires :
"")))))
;
3769
3770 switch_xml_set_txt_d(x_out, argv[2])switch_xml_set_flag(switch_xml_set_txt(x_out, (__extension__ (
__builtin_constant_p (argv[2]) && ((size_t)(const void
*)((argv[2]) + 1) - (size_t)(const void *)(argv[2]) == 1) ? (
((const char *) (argv[2]))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (argv[2]) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, argv[2], __len); __retval
; })) : __strdup (argv[2])))), SWITCH_XML_TXTM)
;
3771
3772 return 0;
3773}
3774
3775static int xml_outbound(switch_xml_t xml, fifo_node_t *node, char *container, char *tag, int cc_off, int verbose)
3776{
3777 struct xml_helper h = { 0 };
3778 char *sql;
3779
3780 if (!strcmp(node->name, MANUAL_QUEUE_NAME)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(node->name) && __builtin_constant_p ("manual_calls"
) && (__s1_len = __builtin_strlen (node->name), __s2_len
= __builtin_strlen ("manual_calls"), (!((size_t)(const void *
)((node->name) + 1) - (size_t)(const void *)(node->name
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)(("manual_calls") + 1) - (size_t)(const void *)("manual_calls"
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (node->name
, "manual_calls") : (__builtin_constant_p (node->name) &&
((size_t)(const void *)((node->name) + 1) - (size_t)(const
void *)(node->name) == 1) && (__s1_len = __builtin_strlen
(node->name), __s1_len < 4) ? (__builtin_constant_p ("manual_calls"
) && ((size_t)(const void *)(("manual_calls") + 1) - (
size_t)(const void *)("manual_calls") == 1) ? __builtin_strcmp
(node->name, "manual_calls") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ("manual_calls"
); int __result = (((const unsigned char *) (const char *) (node
->name))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
node->name))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (node->name))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (node->name))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("manual_calls") && ((size_t)(const void *)(("manual_calls"
) + 1) - (size_t)(const void *)("manual_calls") == 1) &&
(__s2_len = __builtin_strlen ("manual_calls"), __s2_len <
4) ? (__builtin_constant_p (node->name) && ((size_t
)(const void *)((node->name) + 1) - (size_t)(const void *)
(node->name) == 1) ? __builtin_strcmp (node->name, "manual_calls"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (node->name); int __result = (((const
unsigned char *) (const char *) ("manual_calls"))[0] - __s2[
0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("manual_calls"))
[1] - __s2[1]); if (__s2_len > 1 && __result == 0)
{ __result = (((const unsigned char *) (const char *) ("manual_calls"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("manual_calls"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (node
->name, "manual_calls")))); })
) {
3781 sql = switch_mprintf("select uuid, '%s', originate_string, simo_count, use_count, timeout,"
3782 "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count,"
3783 "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time,"
3784 "manual_calls_out_count, manual_calls_in_count, manual_calls_out_total_count, manual_calls_in_total_count from fifo_outbound "
3785 "group by "
3786 "uuid, originate_string, simo_count, use_count, timeout,"
3787 "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count,"
3788 "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time,"
3789 "manual_calls_out_count, manual_calls_in_count, manual_calls_out_total_count, manual_calls_in_total_count",
3790 MANUAL_QUEUE_NAME"manual_calls");
3791 } else {
3792 sql = switch_mprintf("select uuid, fifo_name, originate_string, simo_count, use_count, timeout, "
3793 "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count, "
3794 "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time, "
3795 "manual_calls_out_count, manual_calls_in_count, manual_calls_out_total_count, manual_calls_in_total_count,"
3796 "ring_count,start_time,stop_time "
3797 "from fifo_outbound where fifo_name = '%q'", node->name);
3798 }
3799
3800 h.xml = xml;
3801 h.node = node;
3802 h.container = container;
3803 h.tag = tag;
3804 h.cc_off = cc_off;
3805 h.row_off = 0;
3806 h.verbose = verbose;
3807
3808 h.xml = switch_xml_add_child_d(h.xml, h.container, h.cc_off++)switch_xml_set_flag(switch_xml_add_child(h.xml, (__extension__
(__builtin_constant_p (h.container) && ((size_t)(const
void *)((h.container) + 1) - (size_t)(const void *)(h.container
) == 1) ? (((const char *) (h.container))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
h.container) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, h.container, __len); __retval; })) : __strdup (h.container)
)), h.cc_off++), SWITCH_XML_NAMEM)
;
3809
3810 fifo_execute_sql_callback(globals.sql_mutex, sql, xml_callback, &h);
3811
3812 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3813
3814 return h.cc_off;
3815}
3816
3817static int xml_bridge_callback(void *pArg, int argc, char **argv, char **columnNames)
3818{
3819 struct xml_helper *h = (struct xml_helper *) pArg;
3820 switch_xml_t x_bridge, x_var, x_caller, x_consumer, x_cdr;
3821 char exp_buf[128] = "";
3822 switch_time_exp_t tm;
3823 switch_time_t etime = 0;
3824 int off = 0, tag_off = 0;
3825 switch_core_session_t *session;
3826 char url_buf[512] = "";
3827 char *encoded;
3828
3829 if ((etime = atol(argv[6]))) {
1
Assuming 'etime' is zero
2
Taking false branch
3830 switch_size_t retsize;
3831
3832 switch_time_exp_lt(&tm, switch_time_from_sec(etime)((switch_time_t)(etime) * 1000000));
3833 switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
3834 } else {
3835 switch_set_string(exp_buf, "now")switch_copy_string(exp_buf, "now", sizeof(exp_buf));
3836 }
3837
3838 x_bridge = switch_xml_add_child_d(h->xml, h->tag, h->row_off++)switch_xml_set_flag(switch_xml_add_child(h->xml, (__extension__
(__builtin_constant_p (h->tag) && ((size_t)(const
void *)((h->tag) + 1) - (size_t)(const void *)(h->tag)
== 1) ? (((const char *) (h->tag))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (h->tag
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, h->tag
, __len); __retval; })) : __strdup (h->tag))), h->row_off
++), SWITCH_XML_NAMEM)
;
3839
3840 switch_xml_set_attr_d(x_bridge, "fifo_name", argv[0])switch_xml_set_attr(switch_xml_set_flag(x_bridge, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("fifo_name") &&
((size_t)(const void *)(("fifo_name") + 1) - (size_t)(const void
*)("fifo_name") == 1) ? (((const char *) ("fifo_name"))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("fifo_name") + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "fifo_name", __len); __retval; })) : __strdup ("fifo_name"
))), (__extension__ (__builtin_constant_p ((argv[0] ? argv[0]
: "")) && ((size_t)(const void *)(((argv[0] ? argv[0
] : "")) + 1) - (size_t)(const void *)((argv[0] ? argv[0] : ""
)) == 1) ? (((const char *) ((argv[0] ? argv[0] : "")))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((argv[0] ? argv[0] : "")) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (argv[0] ? argv[0] : ""), __len); __retval
; })) : __strdup ((argv[0] ? argv[0] : "")))))
;
3841 switch_xml_set_attr_d_buf(x_bridge, "bridge_start", exp_buf)switch_xml_set_attr(switch_xml_set_flag(x_bridge, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("bridge_start") &&
((size_t)(const void *)(("bridge_start") + 1) - (size_t)(const
void *)("bridge_start") == 1) ? (((const char *) ("bridge_start"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("bridge_start") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "bridge_start", __len); __retval
; })) : __strdup ("bridge_start"))), (__extension__ (__builtin_constant_p
(exp_buf) && ((size_t)(const void *)((exp_buf) + 1) -
(size_t)(const void *)(exp_buf) == 1) ? (((const char *) (exp_buf
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (exp_buf) + 1; char *__retval = (char *
) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, exp_buf, __len); __retval; })) : __strdup
(exp_buf))))
;
3842 switch_xml_set_attr_d(x_bridge, "bridge_start_epoch", argv[6])switch_xml_set_attr(switch_xml_set_flag(x_bridge, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("bridge_start_epoch"
) && ((size_t)(const void *)(("bridge_start_epoch") +
1) - (size_t)(const void *)("bridge_start_epoch") == 1) ? ((
(const char *) ("bridge_start_epoch"))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("bridge_start_epoch"
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, "bridge_start_epoch"
, __len); __retval; })) : __strdup ("bridge_start_epoch"))), (
__extension__ (__builtin_constant_p ((argv[6] ? argv[6] : "")
) && ((size_t)(const void *)(((argv[6] ? argv[6] : ""
)) + 1) - (size_t)(const void *)((argv[6] ? argv[6] : "")) ==
1) ? (((const char *) ((argv[6] ? argv[6] : "")))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((argv[6] ? argv[6] : "")) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (argv[6] ? argv[6] : ""), __len); __retval
; })) : __strdup ((argv[6] ? argv[6] : "")))))
;
3843
3844 x_caller = switch_xml_add_child_d(x_bridge, "caller", tag_off++)switch_xml_set_flag(switch_xml_add_child(x_bridge, (__extension__
(__builtin_constant_p ("caller") && ((size_t)(const void
*)(("caller") + 1) - (size_t)(const void *)("caller") == 1) ?
(((const char *) ("caller"))[0] == '\0' ? (char *) calloc ((
size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("caller") +
1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, "caller", __len
); __retval; })) : __strdup ("caller"))), tag_off++), SWITCH_XML_NAMEM
)
;
3845
3846 switch_xml_set_attr_d(x_caller, "uuid", argv[1])switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("uuid") && (
(size_t)(const void *)(("uuid") + 1) - (size_t)(const void *)
("uuid") == 1) ? (((const char *) ("uuid"))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
("uuid") + 1; char *__retval = (char *) malloc (__len); if (
__retval != ((void*)0)) __retval = (char *) memcpy (__retval,
"uuid", __len); __retval; })) : __strdup ("uuid"))), (__extension__
(__builtin_constant_p ((argv[1] ? argv[1] : "")) && (
(size_t)(const void *)(((argv[1] ? argv[1] : "")) + 1) - (size_t
)(const void *)((argv[1] ? argv[1] : "")) == 1) ? (((const char
*) ((argv[1] ? argv[1] : "")))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((argv[1] ?
argv[1] : "")) + 1; char *__retval = (char *) malloc (__len)
; if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (argv[1] ? argv[1] : ""), __len); __retval; })) : __strdup (
(argv[1] ? argv[1] : "")))))
;
3847
3848 encoded = switch_url_encode(argv[2], url_buf, sizeof(url_buf));
3849 switch_xml_set_attr_d(x_caller, "caller_id_name", encoded)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("caller_id_name") &&
((size_t)(const void *)(("caller_id_name") + 1) - (size_t)(const
void *)("caller_id_name") == 1) ? (((const char *) ("caller_id_name"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("caller_id_name") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "caller_id_name", __len); __retval
; })) : __strdup ("caller_id_name"))), (__extension__ (__builtin_constant_p
((encoded ? encoded : "")) && ((size_t)(const void *
)(((encoded ? encoded : "")) + 1) - (size_t)(const void *)((encoded
? encoded : "")) == 1) ? (((const char *) ((encoded ? encoded
: "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1
) : ({ size_t __len = strlen ((encoded ? encoded : "")) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, (encoded ? encoded
: ""), __len); __retval; })) : __strdup ((encoded ? encoded :
"")))))
;
3850
3851 encoded = switch_url_encode(argv[3], url_buf, sizeof(url_buf));
3852 switch_xml_set_attr_d(x_caller, "caller_id_number", encoded)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("caller_id_number") &&
((size_t)(const void *)(("caller_id_number") + 1) - (size_t)
(const void *)("caller_id_number") == 1) ? (((const char *) (
"caller_id_number"))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen ("caller_id_number")
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, "caller_id_number"
, __len); __retval; })) : __strdup ("caller_id_number"))), (__extension__
(__builtin_constant_p ((encoded ? encoded : "")) && (
(size_t)(const void *)(((encoded ? encoded : "")) + 1) - (size_t
)(const void *)((encoded ? encoded : "")) == 1) ? (((const char
*) ((encoded ? encoded : "")))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((encoded ?
encoded : "")) + 1; char *__retval = (char *) malloc (__len)
; if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (encoded ? encoded : ""), __len); __retval; })) : __strdup (
(encoded ? encoded : "")))))
;
3853
3854 if (h->verbose) {
3
Taking false branch
3855 if ((session = switch_core_session_locate(argv[1])switch_core_session_perform_locate(argv[1], "mod_fifo.c", (const
char *)__func__, 3855)
)) {
3856 x_cdr = switch_xml_add_child_d(x_caller, "cdr", 0)switch_xml_set_flag(switch_xml_add_child(x_caller, (__extension__
(__builtin_constant_p ("cdr") && ((size_t)(const void
*)(("cdr") + 1) - (size_t)(const void *)("cdr") == 1) ? (((const
char *) ("cdr"))[0] == '\0' ? (char *) calloc ((size_t) 1, (
size_t) 1) : ({ size_t __len = strlen ("cdr") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "cdr", __len); __retval; })) : __strdup
("cdr"))), 0), SWITCH_XML_NAMEM)
;
3857 switch_ivr_generate_xml_cdr(session, &x_cdr);
3858 switch_core_session_rwunlock(session);
3859 }
3860 }
3861
3862 off = 0;
3863
3864 x_consumer = switch_xml_add_child_d(x_bridge, "consumer", tag_off++)switch_xml_set_flag(switch_xml_add_child(x_bridge, (__extension__
(__builtin_constant_p ("consumer") && ((size_t)(const
void *)(("consumer") + 1) - (size_t)(const void *)("consumer"
) == 1) ? (((const char *) ("consumer"))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
"consumer") + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, "consumer", __len); __retval; })) : __strdup ("consumer")))
, tag_off++), SWITCH_XML_NAMEM)
;
3865
3866 x_var = switch_xml_add_child_d(x_consumer, "uuid", off++)switch_xml_set_flag(switch_xml_add_child(x_consumer, (__extension__
(__builtin_constant_p ("uuid") && ((size_t)(const void
*)(("uuid") + 1) - (size_t)(const void *)("uuid") == 1) ? ((
(const char *) ("uuid"))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ("uuid") + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, "uuid", __len); __retval
; })) : __strdup ("uuid"))), off++), SWITCH_XML_NAMEM)
;
4
Within the expansion of the macro 'switch_xml_add_child_d':
a
Memory is allocated
b
Assuming '__retval' is not equal to null
c
Potential leak of memory pointed to by '__retval'
3867 switch_xml_set_txt_d(x_var, argv[4])switch_xml_set_flag(switch_xml_set_txt(x_var, (__extension__ (
__builtin_constant_p (argv[4]) && ((size_t)(const void
*)((argv[4]) + 1) - (size_t)(const void *)(argv[4]) == 1) ? (
((const char *) (argv[4]))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (argv[4]) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, argv[4], __len); __retval
; })) : __strdup (argv[4])))), SWITCH_XML_TXTM)
;
3868 x_var = switch_xml_add_child_d(x_consumer, "outgoing_uuid", off++)switch_xml_set_flag(switch_xml_add_child(x_consumer, (__extension__
(__builtin_constant_p ("outgoing_uuid") && ((size_t)
(const void *)(("outgoing_uuid") + 1) - (size_t)(const void *
)("outgoing_uuid") == 1) ? (((const char *) ("outgoing_uuid")
)[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t
__len = strlen ("outgoing_uuid") + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, "outgoing_uuid", __len); __retval; })) :
__strdup ("outgoing_uuid"))), off++), SWITCH_XML_NAMEM)
;
3869 switch_xml_set_txt_d(x_var, argv[5])switch_xml_set_flag(switch_xml_set_txt(x_var, (__extension__ (
__builtin_constant_p (argv[5]) && ((size_t)(const void
*)((argv[5]) + 1) - (size_t)(const void *)(argv[5]) == 1) ? (
((const char *) (argv[5]))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (argv[5]) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, argv[5], __len); __retval
; })) : __strdup (argv[5])))), SWITCH_XML_TXTM)
;
3870
3871 if (h->verbose) {
3872 if ((session = switch_core_session_locate(argv[1])switch_core_session_perform_locate(argv[1], "mod_fifo.c", (const
char *)__func__, 3872)
)) {
3873 x_cdr = switch_xml_add_child_d(x_consumer, "cdr", 0)switch_xml_set_flag(switch_xml_add_child(x_consumer, (__extension__
(__builtin_constant_p ("cdr") && ((size_t)(const void
*)(("cdr") + 1) - (size_t)(const void *)("cdr") == 1) ? (((const
char *) ("cdr"))[0] == '\0' ? (char *) calloc ((size_t) 1, (
size_t) 1) : ({ size_t __len = strlen ("cdr") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "cdr", __len); __retval; })) : __strdup
("cdr"))), 0), SWITCH_XML_NAMEM)
;
3874 switch_ivr_generate_xml_cdr(session, &x_cdr);
3875 switch_core_session_rwunlock(session);
3876 }
3877 }
3878
3879 return 0;
3880}
3881
3882static int xml_bridges(switch_xml_t xml, fifo_node_t *node, char *container, char *tag, int cc_off, int verbose)
3883{
3884 struct xml_helper h = { 0 };
3885 char *sql = switch_mprintf("select "
3886 "fifo_name,caller_uuid,caller_caller_id_name,caller_caller_id_number,consumer_uuid,consumer_outgoing_uuid,bridge_start "
3887 "from fifo_bridge where fifo_name = '%q'", node->name);
3888
3889 h.xml = xml;
3890 h.node = node;
3891 h.container = container;
3892 h.tag = tag;
3893 h.cc_off = cc_off;
3894 h.row_off = 0;
3895 h.verbose = verbose;
3896
3897 h.xml = switch_xml_add_child_d(h.xml, h.container, h.cc_off++)switch_xml_set_flag(switch_xml_add_child(h.xml, (__extension__
(__builtin_constant_p (h.container) && ((size_t)(const
void *)((h.container) + 1) - (size_t)(const void *)(h.container
) == 1) ? (((const char *) (h.container))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
h.container) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, h.container, __len); __retval; })) : __strdup (h.container)
)), h.cc_off++), SWITCH_XML_NAMEM)
;
3898
3899 fifo_execute_sql_callback(globals.sql_mutex, sql, xml_bridge_callback, &h);
3900
3901 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3902
3903 return h.cc_off;
3904}
3905
3906static int xml_hash(switch_xml_t xml, switch_hash_t *hash, char *container, char *tag, int cc_off, int verbose)
3907{
3908 switch_xml_t x_tmp, x_caller, x_cp;
3909 switch_hash_index_t *hi;
3910 switch_core_session_t *session;
3911 switch_channel_t *channel;
3912 void *val;
3913 const void *var;
3914
3915 x_tmp = switch_xml_add_child_d(xml, container, cc_off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ (
__builtin_constant_p (container) && ((size_t)(const void
*)((container) + 1) - (size_t)(const void *)(container) == 1
) ? (((const char *) (container))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (container
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, container
, __len); __retval; })) : __strdup (container))), cc_off++), SWITCH_XML_NAMEM
)
;
3916 switch_assert(x_tmp)((x_tmp) ? (void) (0) : __assert_fail ("x_tmp", "mod_fifo.c",
3916, __PRETTY_FUNCTION__))
;
3917
3918 for (hi = switch_core_hash_first(hash)switch_core_hash_first_iter(hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
3919 int c_off = 0, d_off = 0;
3920 const char *status;
3921 const char *ts;
3922 char url_buf[512] = "";
3923 char *encoded;
3924
3925 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
3926 session = (switch_core_session_t *) val;
3927 channel = switch_core_session_get_channel(session);
3928 x_caller = switch_xml_add_child_d(x_tmp, tag, c_off++)switch_xml_set_flag(switch_xml_add_child(x_tmp, (__extension__
(__builtin_constant_p (tag) && ((size_t)(const void *
)((tag) + 1) - (size_t)(const void *)(tag) == 1) ? (((const char
*) (tag))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t)
1) : ({ size_t __len = strlen (tag) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, tag, __len); __retval; })) : __strdup (
tag))), c_off++), SWITCH_XML_NAMEM)
;
3929 switch_assert(x_caller)((x_caller) ? (void) (0) : __assert_fail ("x_caller", "mod_fifo.c"
, 3929, __PRETTY_FUNCTION__))
;
3930
3931 switch_xml_set_attr_d(x_caller, "uuid", switch_core_session_get_uuid(session))switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("uuid") && (
(size_t)(const void *)(("uuid") + 1) - (size_t)(const void *)
("uuid") == 1) ? (((const char *) ("uuid"))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
("uuid") + 1; char *__retval = (char *) malloc (__len); if (
__retval != ((void*)0)) __retval = (char *) memcpy (__retval,
"uuid", __len); __retval; })) : __strdup ("uuid"))), (__extension__
(__builtin_constant_p ((switch_core_session_get_uuid(session
) ? switch_core_session_get_uuid(session) : "")) && (
(size_t)(const void *)(((switch_core_session_get_uuid(session
) ? switch_core_session_get_uuid(session) : "")) + 1) - (size_t
)(const void *)((switch_core_session_get_uuid(session) ? switch_core_session_get_uuid
(session) : "")) == 1) ? (((const char *) ((switch_core_session_get_uuid
(session) ? switch_core_session_get_uuid(session) : "")))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((switch_core_session_get_uuid(session) ? switch_core_session_get_uuid
(session) : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (switch_core_session_get_uuid(session) ? switch_core_session_get_uuid
(session) : ""), __len); __retval; })) : __strdup ((switch_core_session_get_uuid
(session) ? switch_core_session_get_uuid(session) : "")))))
;
3932
3933 if ((status = switch_channel_get_variable(channel, "fifo_status")switch_channel_get_variable_dup(channel, "fifo_status", SWITCH_TRUE
, -1)
)) {
3934 switch_xml_set_attr_d(x_caller, "status", status)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("status") &&
((size_t)(const void *)(("status") + 1) - (size_t)(const void
*)("status") == 1) ? (((const char *) ("status"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("status") + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, "status", __len); __retval; })) : __strdup ("status"))), (__extension__
(__builtin_constant_p ((status ? status : "")) && ((
size_t)(const void *)(((status ? status : "")) + 1) - (size_t
)(const void *)((status ? status : "")) == 1) ? (((const char
*) ((status ? status : "")))[0] == '\0' ? (char *) calloc ((
size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((status ? status
: "")) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, (status
? status : ""), __len); __retval; })) : __strdup ((status ? status
: "")))))
;
3935 }
3936
3937 if ((status = switch_channel_get_variable(channel, "caller_id_name")switch_channel_get_variable_dup(channel, "caller_id_name", SWITCH_TRUE
, -1)
)) {
3938 encoded = switch_url_encode(status, url_buf, sizeof(url_buf));
3939 switch_xml_set_attr_d(x_caller, "caller_id_name", encoded)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("caller_id_name") &&
((size_t)(const void *)(("caller_id_name") + 1) - (size_t)(const
void *)("caller_id_name") == 1) ? (((const char *) ("caller_id_name"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("caller_id_name") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "caller_id_name", __len); __retval
; })) : __strdup ("caller_id_name"))), (__extension__ (__builtin_constant_p
((encoded ? encoded : "")) && ((size_t)(const void *
)(((encoded ? encoded : "")) + 1) - (size_t)(const void *)((encoded
? encoded : "")) == 1) ? (((const char *) ((encoded ? encoded
: "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1
) : ({ size_t __len = strlen ((encoded ? encoded : "")) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, (encoded ? encoded
: ""), __len); __retval; })) : __strdup ((encoded ? encoded :
"")))))
;
3940 }
3941
3942 if ((status = switch_channel_get_variable(channel, "caller_id_number")switch_channel_get_variable_dup(channel, "caller_id_number", SWITCH_TRUE
, -1)
)) {
3943 encoded = switch_url_encode(status, url_buf, sizeof(url_buf));
3944 switch_xml_set_attr_d(x_caller, "caller_id_number", encoded)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("caller_id_number") &&
((size_t)(const void *)(("caller_id_number") + 1) - (size_t)
(const void *)("caller_id_number") == 1) ? (((const char *) (
"caller_id_number"))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen ("caller_id_number")
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, "caller_id_number"
, __len); __retval; })) : __strdup ("caller_id_number"))), (__extension__
(__builtin_constant_p ((encoded ? encoded : "")) && (
(size_t)(const void *)(((encoded ? encoded : "")) + 1) - (size_t
)(const void *)((encoded ? encoded : "")) == 1) ? (((const char
*) ((encoded ? encoded : "")))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((encoded ?
encoded : "")) + 1; char *__retval = (char *) malloc (__len)
; if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (encoded ? encoded : ""), __len); __retval; })) : __strdup (
(encoded ? encoded : "")))))
;
3945 }
3946
3947 if ((ts = switch_channel_get_variable(channel, "fifo_timestamp")switch_channel_get_variable_dup(channel, "fifo_timestamp", SWITCH_TRUE
, -1)
)) {
3948 switch_xml_set_attr_d(x_caller, "timestamp", ts)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("timestamp") &&
((size_t)(const void *)(("timestamp") + 1) - (size_t)(const void
*)("timestamp") == 1) ? (((const char *) ("timestamp"))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("timestamp") + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "timestamp", __len); __retval; })) : __strdup ("timestamp"
))), (__extension__ (__builtin_constant_p ((ts ? ts : "")) &&
((size_t)(const void *)(((ts ? ts : "")) + 1) - (size_t)(const
void *)((ts ? ts : "")) == 1) ? (((const char *) ((ts ? ts :
"")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) :
({ size_t __len = strlen ((ts ? ts : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (ts ? ts : ""), __len); __retval
; })) : __strdup ((ts ? ts : "")))))
;
3949 }
3950
3951 if ((ts = switch_channel_get_variable(channel, "fifo_target")switch_channel_get_variable_dup(channel, "fifo_target", SWITCH_TRUE
, -1)
)) {
3952 switch_xml_set_attr_d(x_caller, "target", ts)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("target") &&
((size_t)(const void *)(("target") + 1) - (size_t)(const void
*)("target") == 1) ? (((const char *) ("target"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("target") + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, "target", __len); __retval; })) : __strdup ("target"))), (__extension__
(__builtin_constant_p ((ts ? ts : "")) && ((size_t)(
const void *)(((ts ? ts : "")) + 1) - (size_t)(const void *)(
(ts ? ts : "")) == 1) ? (((const char *) ((ts ? ts : "")))[0]
== '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t
__len = strlen ((ts ? ts : "")) + 1; char *__retval = (char *
) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (ts ? ts : ""), __len); __retval; })) :
__strdup ((ts ? ts : "")))))
;
3953 }
3954
3955 if (verbose) {
3956 if (!(x_cp = switch_xml_add_child_d(x_caller, "cdr", d_off++)switch_xml_set_flag(switch_xml_add_child(x_caller, (__extension__
(__builtin_constant_p ("cdr") && ((size_t)(const void
*)(("cdr") + 1) - (size_t)(const void *)("cdr") == 1) ? (((const
char *) ("cdr"))[0] == '\0' ? (char *) calloc ((size_t) 1, (
size_t) 1) : ({ size_t __len = strlen ("cdr") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "cdr", __len); __retval; })) : __strdup
("cdr"))), d_off++), SWITCH_XML_NAMEM)
)) {
3957 abort();
3958 }
3959
3960 switch_ivr_generate_xml_cdr(session, &x_cp);
3961 }
3962 }
3963
3964 return cc_off;
3965}
3966
3967static int xml_caller(switch_xml_t xml, fifo_node_t *node, char *container, char *tag, int cc_off, int verbose)
3968{
3969 switch_xml_t x_tmp, x_caller, x_cp;
3970 int i, x;
3971 switch_core_session_t *session;
3972 switch_channel_t *channel;
3973
3974 x_tmp = switch_xml_add_child_d(xml, container, cc_off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ (
__builtin_constant_p (container) && ((size_t)(const void
*)((container) + 1) - (size_t)(const void *)(container) == 1
) ? (((const char *) (container))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (container
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, container
, __len); __retval; })) : __strdup (container))), cc_off++), SWITCH_XML_NAMEM
)
;
3975 switch_assert(x_tmp)((x_tmp) ? (void) (0) : __assert_fail ("x_tmp", "mod_fifo.c",
3975, __PRETTY_FUNCTION__))
;
3976
3977 for (x = 0; x < MAX_PRI10; x++) {
3978 fifo_queue_t *q = node->fifo_list[x];
3979
3980 switch_mutex_lock(q->mutex);
3981
3982 for (i = 0; i < q->idx; i++) {
3983 int c_off = 0, d_off = 0;
3984 const char *status;
3985 const char *ts;
3986 const char *uuid = switch_event_get_header(q->data[i], "unique-id")switch_event_get_header_idx(q->data[i], "unique-id", -1);
3987 char sl[30] = "";
3988 char url_buf[512] = "";
3989 char *encoded;
3990
3991 if (!uuid) {
3992 continue;
3993 }
3994
3995 if (!(session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_fifo.c", (const
char *)__func__, 3995)
)) {
3996 continue;
3997 }
3998
3999 channel = switch_core_session_get_channel(session);
4000 x_caller = switch_xml_add_child_d(x_tmp, tag, c_off++)switch_xml_set_flag(switch_xml_add_child(x_tmp, (__extension__
(__builtin_constant_p (tag) && ((size_t)(const void *
)((tag) + 1) - (size_t)(const void *)(tag) == 1) ? (((const char
*) (tag))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t)
1) : ({ size_t __len = strlen (tag) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, tag, __len); __retval; })) : __strdup (
tag))), c_off++), SWITCH_XML_NAMEM)
;
4001 switch_assert(x_caller)((x_caller) ? (void) (0) : __assert_fail ("x_caller", "mod_fifo.c"
, 4001, __PRETTY_FUNCTION__))
;
4002
4003 switch_xml_set_attr_d(x_caller, "uuid", switch_core_session_get_uuid(session))switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("uuid") && (
(size_t)(const void *)(("uuid") + 1) - (size_t)(const void *)
("uuid") == 1) ? (((const char *) ("uuid"))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
("uuid") + 1; char *__retval = (char *) malloc (__len); if (
__retval != ((void*)0)) __retval = (char *) memcpy (__retval,
"uuid", __len); __retval; })) : __strdup ("uuid"))), (__extension__
(__builtin_constant_p ((switch_core_session_get_uuid(session
) ? switch_core_session_get_uuid(session) : "")) && (
(size_t)(const void *)(((switch_core_session_get_uuid(session
) ? switch_core_session_get_uuid(session) : "")) + 1) - (size_t
)(const void *)((switch_core_session_get_uuid(session) ? switch_core_session_get_uuid
(session) : "")) == 1) ? (((const char *) ((switch_core_session_get_uuid
(session) ? switch_core_session_get_uuid(session) : "")))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((switch_core_session_get_uuid(session) ? switch_core_session_get_uuid
(session) : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (switch_core_session_get_uuid(session) ? switch_core_session_get_uuid
(session) : ""), __len); __retval; })) : __strdup ((switch_core_session_get_uuid
(session) ? switch_core_session_get_uuid(session) : "")))))
;
4004
4005 if ((status = switch_channel_get_variable(channel, "fifo_status")switch_channel_get_variable_dup(channel, "fifo_status", SWITCH_TRUE
, -1)
)) {
4006 switch_xml_set_attr_d(x_caller, "status", status)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("status") &&
((size_t)(const void *)(("status") + 1) - (size_t)(const void
*)("status") == 1) ? (((const char *) ("status"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("status") + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, "status", __len); __retval; })) : __strdup ("status"))), (__extension__
(__builtin_constant_p ((status ? status : "")) && ((
size_t)(const void *)(((status ? status : "")) + 1) - (size_t
)(const void *)((status ? status : "")) == 1) ? (((const char
*) ((status ? status : "")))[0] == '\0' ? (char *) calloc ((
size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((status ? status
: "")) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, (status
? status : ""), __len); __retval; })) : __strdup ((status ? status
: "")))))
;
4007 }
4008
4009 if ((status = switch_channel_get_variable(channel, "caller_id_name")switch_channel_get_variable_dup(channel, "caller_id_name", SWITCH_TRUE
, -1)
)) {
4010 encoded = switch_url_encode(status, url_buf, sizeof(url_buf));
4011 switch_xml_set_attr_d(x_caller, "caller_id_name", encoded)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("caller_id_name") &&
((size_t)(const void *)(("caller_id_name") + 1) - (size_t)(const
void *)("caller_id_name") == 1) ? (((const char *) ("caller_id_name"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("caller_id_name") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "caller_id_name", __len); __retval
; })) : __strdup ("caller_id_name"))), (__extension__ (__builtin_constant_p
((encoded ? encoded : "")) && ((size_t)(const void *
)(((encoded ? encoded : "")) + 1) - (size_t)(const void *)((encoded
? encoded : "")) == 1) ? (((const char *) ((encoded ? encoded
: "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1
) : ({ size_t __len = strlen ((encoded ? encoded : "")) + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, (encoded ? encoded
: ""), __len); __retval; })) : __strdup ((encoded ? encoded :
"")))))
;
4012 }
4013
4014 if ((status = switch_channel_get_variable(channel, "caller_id_number")switch_channel_get_variable_dup(channel, "caller_id_number", SWITCH_TRUE
, -1)
)) {
4015 encoded = switch_url_encode(status, url_buf, sizeof(url_buf));
4016 switch_xml_set_attr_d(x_caller, "caller_id_number", encoded)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("caller_id_number") &&
((size_t)(const void *)(("caller_id_number") + 1) - (size_t)
(const void *)("caller_id_number") == 1) ? (((const char *) (
"caller_id_number"))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen ("caller_id_number")
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, "caller_id_number"
, __len); __retval; })) : __strdup ("caller_id_number"))), (__extension__
(__builtin_constant_p ((encoded ? encoded : "")) && (
(size_t)(const void *)(((encoded ? encoded : "")) + 1) - (size_t
)(const void *)((encoded ? encoded : "")) == 1) ? (((const char
*) ((encoded ? encoded : "")))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((encoded ?
encoded : "")) + 1; char *__retval = (char *) malloc (__len)
; if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (encoded ? encoded : ""), __len); __retval; })) : __strdup (
(encoded ? encoded : "")))))
;
4017 }
4018
4019 if ((ts = switch_channel_get_variable(channel, "fifo_timestamp")switch_channel_get_variable_dup(channel, "fifo_timestamp", SWITCH_TRUE
, -1)
)) {
4020 switch_xml_set_attr_d(x_caller, "timestamp", ts)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("timestamp") &&
((size_t)(const void *)(("timestamp") + 1) - (size_t)(const void
*)("timestamp") == 1) ? (((const char *) ("timestamp"))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("timestamp") + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "timestamp", __len); __retval; })) : __strdup ("timestamp"
))), (__extension__ (__builtin_constant_p ((ts ? ts : "")) &&
((size_t)(const void *)(((ts ? ts : "")) + 1) - (size_t)(const
void *)((ts ? ts : "")) == 1) ? (((const char *) ((ts ? ts :
"")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) :
({ size_t __len = strlen ((ts ? ts : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (ts ? ts : ""), __len); __retval
; })) : __strdup ((ts ? ts : "")))))
;
4021 }
4022
4023 if ((ts = switch_channel_get_variable(channel, "fifo_target")switch_channel_get_variable_dup(channel, "fifo_target", SWITCH_TRUE
, -1)
)) {
4024 switch_xml_set_attr_d(x_caller, "target", ts)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("target") &&
((size_t)(const void *)(("target") + 1) - (size_t)(const void
*)("target") == 1) ? (((const char *) ("target"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("target") + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, "target", __len); __retval; })) : __strdup ("target"))), (__extension__
(__builtin_constant_p ((ts ? ts : "")) && ((size_t)(
const void *)(((ts ? ts : "")) + 1) - (size_t)(const void *)(
(ts ? ts : "")) == 1) ? (((const char *) ((ts ? ts : "")))[0]
== '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t
__len = strlen ((ts ? ts : "")) + 1; char *__retval = (char *
) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (ts ? ts : ""), __len); __retval; })) :
__strdup ((ts ? ts : "")))))
;
4025 }
4026
4027 if ((ts = switch_channel_get_variable(channel, "fifo_position")switch_channel_get_variable_dup(channel, "fifo_position", SWITCH_TRUE
, -1)
)) {
4028 switch_xml_set_attr_d(x_caller, "position", ts)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("position") &&
((size_t)(const void *)(("position") + 1) - (size_t)(const void
*)("position") == 1) ? (((const char *) ("position"))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ("position") + 1; char *__retval = (char *) malloc (
__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, "position", __len); __retval; })) : __strdup ("position"
))), (__extension__ (__builtin_constant_p ((ts ? ts : "")) &&
((size_t)(const void *)(((ts ? ts : "")) + 1) - (size_t)(const
void *)((ts ? ts : "")) == 1) ? (((const char *) ((ts ? ts :
"")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) :
({ size_t __len = strlen ((ts ? ts : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (ts ? ts : ""), __len); __retval
; })) : __strdup ((ts ? ts : "")))))
;
4029 }
4030
4031 switch_snprintf(sl, sizeof(sl), "%d", x);
4032 switch_xml_set_attr_d_buf(x_caller, "slot", sl)switch_xml_set_attr(switch_xml_set_flag(x_caller, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("slot") && (
(size_t)(const void *)(("slot") + 1) - (size_t)(const void *)
("slot") == 1) ? (((const char *) ("slot"))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
("slot") + 1; char *__retval = (char *) malloc (__len); if (
__retval != ((void*)0)) __retval = (char *) memcpy (__retval,
"slot", __len); __retval; })) : __strdup ("slot"))), (__extension__
(__builtin_constant_p (sl) && ((size_t)(const void *
)((sl) + 1) - (size_t)(const void *)(sl) == 1) ? (((const char
*) (sl))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1
) : ({ size_t __len = strlen (sl) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, sl, __len); __retval; })) : __strdup (sl
))))
;
4033
4034 if (verbose) {
4035 if (!(x_cp = switch_xml_add_child_d(x_caller, "cdr", d_off++)switch_xml_set_flag(switch_xml_add_child(x_caller, (__extension__
(__builtin_constant_p ("cdr") && ((size_t)(const void
*)(("cdr") + 1) - (size_t)(const void *)("cdr") == 1) ? (((const
char *) ("cdr"))[0] == '\0' ? (char *) calloc ((size_t) 1, (
size_t) 1) : ({ size_t __len = strlen ("cdr") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "cdr", __len); __retval; })) : __strdup
("cdr"))), d_off++), SWITCH_XML_NAMEM)
)) {
4036 abort();
4037 }
4038
4039 switch_ivr_generate_xml_cdr(session, &x_cp);
4040 }
4041
4042 switch_core_session_rwunlock(session);
4043 session = NULL((void*)0);
4044 }
4045
4046 switch_mutex_unlock(q->mutex);
4047 }
4048
4049 return cc_off;
4050}
4051
4052static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int verbose)
4053{
4054 switch_xml_t x_fifo;
4055 int cc_off = 0;
4056 char buffer[35];
4057 char *tmp = buffer;
4058
4059 x_fifo = switch_xml_add_child_d(x_report, "fifo", (*off)++)switch_xml_set_flag(switch_xml_add_child(x_report, (__extension__
(__builtin_constant_p ("fifo") && ((size_t)(const void
*)(("fifo") + 1) - (size_t)(const void *)("fifo") == 1) ? ((
(const char *) ("fifo"))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ("fifo") + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, "fifo", __len); __retval
; })) : __strdup ("fifo"))), (*off)++), SWITCH_XML_NAMEM)
;;
4060 switch_assert(x_fifo)((x_fifo) ? (void) (0) : __assert_fail ("x_fifo", "mod_fifo.c"
, 4060, __PRETTY_FUNCTION__))
;
4061
4062 switch_xml_set_attr_d(x_fifo, "name", node->name)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("name") && (
(size_t)(const void *)(("name") + 1) - (size_t)(const void *)
("name") == 1) ? (((const char *) ("name"))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
("name") + 1; char *__retval = (char *) malloc (__len); if (
__retval != ((void*)0)) __retval = (char *) memcpy (__retval,
"name", __len); __retval; })) : __strdup ("name"))), (__extension__
(__builtin_constant_p ((node->name ? node->name : ""))
&& ((size_t)(const void *)(((node->name ? node->
name : "")) + 1) - (size_t)(const void *)((node->name ? node
->name : "")) == 1) ? (((const char *) ((node->name ? node
->name : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (
size_t) 1) : ({ size_t __len = strlen ((node->name ? node->
name : "")) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (node->name ? node->name : ""), __len); __retval; }))
: __strdup ((node->name ? node->name : "")))))
;
4063 switch_snprintf(tmp, sizeof(buffer), "%d", node->consumer_count);
4064 switch_xml_set_attr_d(x_fifo, "consumer_count", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("consumer_count") &&
((size_t)(const void *)(("consumer_count") + 1) - (size_t)(const
void *)("consumer_count") == 1) ? (((const char *) ("consumer_count"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("consumer_count") + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "consumer_count", __len); __retval
; })) : __strdup ("consumer_count"))), (__extension__ (__builtin_constant_p
((tmp ? tmp : "")) && ((size_t)(const void *)(((tmp ?
tmp : "")) + 1) - (size_t)(const void *)((tmp ? tmp : "")) ==
1) ? (((const char *) ((tmp ? tmp : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((tmp ? tmp : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (tmp ? tmp : ""), __len); __retval; })) : __strdup ((tmp ? tmp
: "")))))
;
4065 switch_snprintf(tmp, sizeof(buffer), "%d", node_caller_count(node));
4066 switch_xml_set_attr_d(x_fifo, "caller_count", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("caller_count") &&
((size_t)(const void *)(("caller_count") + 1) - (size_t)(const
void *)("caller_count") == 1) ? (((const char *) ("caller_count"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("caller_count") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "caller_count", __len); __retval
; })) : __strdup ("caller_count"))), (__extension__ (__builtin_constant_p
((tmp ? tmp : "")) && ((size_t)(const void *)(((tmp ?
tmp : "")) + 1) - (size_t)(const void *)((tmp ? tmp : "")) ==
1) ? (((const char *) ((tmp ? tmp : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((tmp ? tmp : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (tmp ? tmp : ""), __len); __retval; })) : __strdup ((tmp ? tmp
: "")))))
;
4067 switch_snprintf(tmp, sizeof(buffer), "%d", node_caller_count(node));
4068 switch_xml_set_attr_d(x_fifo, "waiting_count", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("waiting_count") &&
((size_t)(const void *)(("waiting_count") + 1) - (size_t)(const
void *)("waiting_count") == 1) ? (((const char *) ("waiting_count"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("waiting_count") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "waiting_count", __len); __retval
; })) : __strdup ("waiting_count"))), (__extension__ (__builtin_constant_p
((tmp ? tmp : "")) && ((size_t)(const void *)(((tmp ?
tmp : "")) + 1) - (size_t)(const void *)((tmp ? tmp : "")) ==
1) ? (((const char *) ((tmp ? tmp : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((tmp ? tmp : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (tmp ? tmp : ""), __len); __retval; })) : __strdup ((tmp ? tmp
: "")))))
;
4069 switch_snprintf(tmp, sizeof(buffer), "%u", node->importance);
4070 switch_xml_set_attr_d(x_fifo, "importance", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("importance") &&
((size_t)(const void *)(("importance") + 1) - (size_t)(const
void *)("importance") == 1) ? (((const char *) ("importance"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("importance") + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, "importance", __len); __retval; }
)) : __strdup ("importance"))), (__extension__ (__builtin_constant_p
((tmp ? tmp : "")) && ((size_t)(const void *)(((tmp ?
tmp : "")) + 1) - (size_t)(const void *)((tmp ? tmp : "")) ==
1) ? (((const char *) ((tmp ? tmp : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((tmp ? tmp : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (tmp ? tmp : ""), __len); __retval; })) : __strdup ((tmp ? tmp
: "")))))
;
4071
4072 switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_per_cycle);
4073 switch_xml_set_attr_d(x_fifo, "outbound_per_cycle", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound_per_cycle"
) && ((size_t)(const void *)(("outbound_per_cycle") +
1) - (size_t)(const void *)("outbound_per_cycle") == 1) ? ((
(const char *) ("outbound_per_cycle"))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("outbound_per_cycle"
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, "outbound_per_cycle"
, __len); __retval; })) : __strdup ("outbound_per_cycle"))), (
__extension__ (__builtin_constant_p ((tmp ? tmp : "")) &&
((size_t)(const void *)(((tmp ? tmp : "")) + 1) - (size_t)(const
void *)((tmp ? tmp : "")) == 1) ? (((const char *) ((tmp ? tmp
: "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1
) : ({ size_t __len = strlen ((tmp ? tmp : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (tmp ? tmp : ""), __len); __retval
; })) : __strdup ((tmp ? tmp : "")))))
;
4074
4075 switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_per_cycle_min);
4076 switch_xml_set_attr_d(x_fifo, "outbound_per_cycle_min", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound_per_cycle_min"
) && ((size_t)(const void *)(("outbound_per_cycle_min"
) + 1) - (size_t)(const void *)("outbound_per_cycle_min") == 1
) ? (((const char *) ("outbound_per_cycle_min"))[0] == '\0' ?
(char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len =
strlen ("outbound_per_cycle_min") + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, "outbound_per_cycle_min", __len); __retval
; })) : __strdup ("outbound_per_cycle_min"))), (__extension__
(__builtin_constant_p ((tmp ? tmp : "")) && ((size_t
)(const void *)(((tmp ? tmp : "")) + 1) - (size_t)(const void
*)((tmp ? tmp : "")) == 1) ? (((const char *) ((tmp ? tmp : ""
)))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : (
{ size_t __len = strlen ((tmp ? tmp : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (tmp ? tmp : ""), __len); __retval
; })) : __strdup ((tmp ? tmp : "")))))
;
4077
4078 switch_snprintf(tmp, sizeof(buffer), "%u", node->ring_timeout);
4079 switch_xml_set_attr_d(x_fifo, "ring_timeout", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("ring_timeout") &&
((size_t)(const void *)(("ring_timeout") + 1) - (size_t)(const
void *)("ring_timeout") == 1) ? (((const char *) ("ring_timeout"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("ring_timeout") + 1; char *__retval =
(char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, "ring_timeout", __len); __retval
; })) : __strdup ("ring_timeout"))), (__extension__ (__builtin_constant_p
((tmp ? tmp : "")) && ((size_t)(const void *)(((tmp ?
tmp : "")) + 1) - (size_t)(const void *)((tmp ? tmp : "")) ==
1) ? (((const char *) ((tmp ? tmp : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((tmp ? tmp : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (tmp ? tmp : ""), __len); __retval; })) : __strdup ((tmp ? tmp
: "")))))
;
4080
4081 switch_snprintf(tmp, sizeof(buffer), "%u", node->default_lag);
4082 switch_xml_set_attr_d(x_fifo, "default_lag", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("default_lag") &&
((size_t)(const void *)(("default_lag") + 1) - (size_t)(const
void *)("default_lag") == 1) ? (((const char *) ("default_lag"
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen ("default_lag") + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, "default_lag", __len); __retval; }
)) : __strdup ("default_lag"))), (__extension__ (__builtin_constant_p
((tmp ? tmp : "")) && ((size_t)(const void *)(((tmp ?
tmp : "")) + 1) - (size_t)(const void *)((tmp ? tmp : "")) ==
1) ? (((const char *) ((tmp ? tmp : "")))[0] == '\0' ? (char
*) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen
((tmp ? tmp : "")) + 1; char *__retval = (char *) malloc (__len
); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, (tmp ? tmp : ""), __len); __retval; })) : __strdup ((tmp ? tmp
: "")))))
;
4083
4084 switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_priority);
4085 switch_xml_set_attr_d(x_fifo, "outbound_priority", tmp)switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound_priority")
&& ((size_t)(const void *)(("outbound_priority") + 1
) - (size_t)(const void *)("outbound_priority") == 1) ? (((const
char *) ("outbound_priority"))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("outbound_priority"
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, "outbound_priority"
, __len); __retval; })) : __strdup ("outbound_priority"))), (
__extension__ (__builtin_constant_p ((tmp ? tmp : "")) &&
((size_t)(const void *)(((tmp ? tmp : "")) + 1) - (size_t)(const
void *)((tmp ? tmp : "")) == 1) ? (((const char *) ((tmp ? tmp
: "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1
) : ({ size_t __len = strlen ((tmp ? tmp : "")) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, (tmp ? tmp : ""), __len); __retval
; })) : __strdup ((tmp ? tmp : "")))))
;
4086
4087 switch_xml_set_attr_d(x_fifo, "outbound_strategy", print_strategy(node->outbound_strategy))switch_xml_set_attr(switch_xml_set_flag(x_fifo, SWITCH_XML_DUP
), (__extension__ (__builtin_constant_p ("outbound_strategy")
&& ((size_t)(const void *)(("outbound_strategy") + 1
) - (size_t)(const void *)("outbound_strategy") == 1) ? (((const
char *) ("outbound_strategy"))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("outbound_strategy"
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, "outbound_strategy"
, __len); __retval; })) : __strdup ("outbound_strategy"))), (
__extension__ (__builtin_constant_p ((print_strategy(node->
outbound_strategy) ? print_strategy(node->outbound_strategy
) : "")) && ((size_t)(const void *)(((print_strategy(
node->outbound_strategy) ? print_strategy(node->outbound_strategy
) : "")) + 1) - (size_t)(const void *)((print_strategy(node->
outbound_strategy) ? print_strategy(node->outbound_strategy
) : "")) == 1) ? (((const char *) ((print_strategy(node->outbound_strategy
) ? print_strategy(node->outbound_strategy) : "")))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen ((print_strategy(node->outbound_strategy) ? print_strategy
(node->outbound_strategy) : "")) + 1; char *__retval = (char
*) malloc (__len); if (__retval != ((void*)0)) __retval = (char
*) memcpy (__retval, (print_strategy(node->outbound_strategy
) ? print_strategy(node->outbound_strategy) : ""), __len);
__retval; })) : __strdup ((print_strategy(node->outbound_strategy
) ? print_strategy(node->outbound_strategy) : "")))))
;
4088
4089 cc_off = xml_outbound(x_fifo, node, "outbound", "member", cc_off, verbose);
4090 cc_off = xml_caller(x_fifo, node, "callers", "caller", cc_off, verbose);
4091 cc_off = xml_hash(x_fifo, node->consumer_hash, "consumers", "consumer", cc_off, verbose);
4092 cc_off = xml_bridges(x_fifo, node, "bridges", "bridge", cc_off, verbose);
4093}
4094
4095void dump_hash(switch_hash_t *hash, switch_stream_handle_t *stream)
4096{
4097 switch_hash_index_t *hi;
4098 void *val;
4099 const void *var;
4100
4101 switch_mutex_lock(globals.mutex);
4102 for (hi = switch_core_hash_first(hash)switch_core_hash_first_iter(hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
4103 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
4104 stream->write_function(stream, " %s\n", (char *)var);
4105 }
4106 switch_mutex_unlock(globals.mutex);
4107}
4108
4109void node_dump(switch_stream_handle_t *stream)
4110{
4111 switch_hash_index_t *hi;
4112 fifo_node_t *node;
4113 void *val;
4114 switch_mutex_lock(globals.mutex);
4115 for (hi = switch_core_hash_first(globals.fifo_hash)switch_core_hash_first_iter(globals.fifo_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
4116 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
4117 if ((node = (fifo_node_t *) val)) {
4118 stream->write_function(stream, "node: %s\n"
4119 " outbound_name: %s\n"
4120 " outbound_per_cycle: %d"
4121 " outbound_per_cycle_min: %d"
4122 " outbound_priority: %d"
4123 " outbound_strategy: %s\n"
4124 " has_outbound: %d\n"
4125 " outbound_priority: %d\n"
4126 " busy: %d\n"
4127 " ready: %d\n"
4128 " waiting: %d\n"
4129 ,
4130 node->name, node->outbound_name, node->outbound_per_cycle, node->outbound_per_cycle_min,
4131 node->outbound_priority, print_strategy(node->outbound_strategy),
4132 node->has_outbound,
4133 node->outbound_priority,
4134 node->busy,
4135 node->ready,
4136 node_caller_count(node)
4137
4138 );
4139 }
4140 }
4141
4142 stream->write_function(stream, " caller_orig:\n");
4143 dump_hash(globals.caller_orig_hash, stream);
4144 stream->write_function(stream, " consumer_orig:\n");
4145 dump_hash(globals.consumer_orig_hash, stream);
4146 stream->write_function(stream, " bridge:\n");
4147 dump_hash(globals.bridge_hash, stream);
4148
4149 switch_mutex_unlock(globals.mutex);
4150}
4151
4152#define FIFO_API_SYNTAX"list|list_verbose|count|debug|status|has_outbound|importance [<fifo name>]|reparse [del_all]" "list|list_verbose|count|debug|status|has_outbound|importance [<fifo name>]|reparse [del_all]"
4153SWITCH_STANDARD_API(fifo_api_function)static switch_status_t fifo_api_function ( const char *cmd, switch_core_session_t
*session, switch_stream_handle_t *stream)
4154{
4155 fifo_node_t *node;
4156 char *data = NULL((void*)0);
4157 int argc = 0;
4158 char *argv[5] = { 0 };
4159 switch_hash_index_t *hi;
4160 void *val;
4161 const void *var;
4162 int x = 0, verbose = 0;
4163
4164 if (!globals.running) {
4165 return SWITCH_STATUS_FALSE;
4166 }
4167
4168 if (!zstr(cmd)_zstr(cmd)) {
4169 data = strdup(cmd)(__extension__ (__builtin_constant_p (cmd) && ((size_t
)(const void *)((cmd) + 1) - (size_t)(const void *)(cmd) == 1
) ? (((const char *) (cmd))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (cmd) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, cmd, __len); __retval
; })) : __strdup (cmd)))
;
4170 switch_assert(data)((data) ? (void) (0) : __assert_fail ("data", "mod_fifo.c", 4170
, __PRETTY_FUNCTION__))
;
4171 }
4172
4173 switch_mutex_lock(globals.mutex);
4174
4175 if (zstr(cmd)_zstr(cmd) || (argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 1 || !argv[0]) {
4176 stream->write_function(stream, "%s\n", FIFO_API_SYNTAX"list|list_verbose|count|debug|status|has_outbound|importance [<fifo name>]|reparse [del_all]");
4177 goto done;
4178 }
4179
4180 if (!strcasecmp(argv[0], "status")) {
4181 node_dump(stream);
4182 goto done;
4183 }
4184
4185 if (!strcasecmp(argv[0], "debug")) {
4186 if (argv[1]) {
4187 if ((globals.debug = atoi(argv[1])) < 0) {
4188 globals.debug = 0;
4189 }
4190 }
4191 stream->write_function(stream, "debug %d\n", globals.debug);
4192 goto done;
4193 }
4194
4195 verbose = !strcasecmp(argv[0], "list_verbose");
4196
4197 if (!strcasecmp(argv[0], "reparse")) {
4198 load_config(1, argv[1] && !strcasecmp(argv[1], "del_all"));
4199 stream->write_function(stream, "+OK\n");
4200 goto done;
4201 }
4202
4203 if (!strcasecmp(argv[0], "list") || verbose) {
4204 char *xml_text = NULL((void*)0);
4205 switch_xml_t x_report = switch_xml_new("fifo_report");
4206 switch_assert(x_report)((x_report) ? (void) (0) : __assert_fail ("x_report", "mod_fifo.c"
, 4206, __PRETTY_FUNCTION__))
;
4207
4208 if (argc < 2) {
4209 for (hi = switch_core_hash_first(globals.fifo_hash)switch_core_hash_first_iter(globals.fifo_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
4210 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
4211 node = (fifo_node_t *) val;
4212
4213 switch_mutex_lock(node->mutex);
4214 list_node(node, x_report, &x, verbose);
4215 switch_mutex_unlock(node->mutex);
4216 }
4217 } else {
4218 if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
4219 switch_mutex_lock(node->mutex);
4220 list_node(node, x_report, &x, verbose);
4221 switch_mutex_unlock(node->mutex);
4222 }
4223 }
4224 xml_text = switch_xml_toxml(x_report, SWITCH_FALSE);
4225 switch_assert(xml_text)((xml_text) ? (void) (0) : __assert_fail ("xml_text", "mod_fifo.c"
, 4225, __PRETTY_FUNCTION__))
;
4226 stream->write_function(stream, "%s\n", xml_text);
4227 switch_xml_free(x_report);
4228 switch_safe_free(xml_text)if (xml_text) {free(xml_text);xml_text=((void*)0);};
4229 } else if (!strcasecmp(argv[0], "importance")) {
4230 if (argv[1] && (node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
4231 int importance = 0;
4232 if (argc > 2) {
4233 importance = atoi(argv[2]);
4234 if (importance < 0) {
4235 importance = 0;
4236 }
4237 node->importance = importance;
4238 }
4239 stream->write_function(stream, "importance: %u\n", node->importance);
4240 } else {
4241 stream->write_function(stream, "no fifo by that name\n");
4242 }
4243 } else if (!strcasecmp(argv[0], "count")) {
4244 if (argc < 2) {
4245 for (hi = switch_core_hash_first(globals.fifo_hash)switch_core_hash_first_iter(globals.fifo_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
4246 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
4247 node = (fifo_node_t *) val;
4248 switch_mutex_lock(node->update_mutex);
4249 stream->write_function(stream, "%s:%d:%d:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), node->member_count, node->ring_consumer_count, node_idle_consumers(node));
4250 switch_mutex_unlock(node->update_mutex);
4251 x++;
4252 }
4253
4254 if (!x) {
4255 stream->write_function(stream, "none\n");
4256 }
4257 } else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
4258 switch_mutex_lock(node->update_mutex);
4259 stream->write_function(stream, "%s:%d:%d:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), node->member_count, node->ring_consumer_count, node_idle_consumers(node));
4260 switch_mutex_unlock(node->update_mutex);
4261 } else {
4262 stream->write_function(stream, "none\n");
4263 }
4264 } else if (!strcasecmp(argv[0], "has_outbound")) {
4265 if (argc < 2) {
4266 for (hi = switch_core_hash_first(globals.fifo_hash)switch_core_hash_first_iter(globals.fifo_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
4267 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
4268 node = (fifo_node_t *) val;
4269 switch_mutex_lock(node->update_mutex);
4270 stream->write_function(stream, "%s:%d\n", (char *) var, node->has_outbound);
4271 switch_mutex_unlock(node->update_mutex);
4272 x++;
4273 }
4274
4275 if (!x) {
4276 stream->write_function(stream, "none\n");
4277 }
4278 } else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
4279 switch_mutex_lock(node->update_mutex);
4280 stream->write_function(stream, "%s:%d\n", argv[1], node->has_outbound);
4281 switch_mutex_unlock(node->update_mutex);
4282 } else {
4283 stream->write_function(stream, "none\n");
4284 }
4285 } else {
4286 stream->write_function(stream, "-ERR Usage: %s\n", FIFO_API_SYNTAX"list|list_verbose|count|debug|status|has_outbound|importance [<fifo name>]|reparse [del_all]");
4287 }
4288
4289 done:
4290
4291 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
4292
4293 switch_mutex_unlock(globals.mutex);
4294 return SWITCH_STATUS_SUCCESS;
4295}
4296
4297const char outbound_sql[] =
4298 "create table fifo_outbound (\n"
4299 " uuid varchar(255),\n"
4300 " fifo_name varchar(255),\n"
4301 " originate_string varchar(255),\n"
4302 " simo_count integer,\n"
4303 " use_count integer,\n"
4304 " timeout integer,\n"
4305 " lag integer,\n"
4306 " next_avail integer not null default 0,\n"
4307 " expires integer not null default 0,\n"
4308 " static integer not null default 0,\n"
4309 " outbound_call_count integer not null default 0,\n"
4310 " outbound_fail_count integer not null default 0,\n"
4311 " hostname varchar(255),\n"
4312 " taking_calls integer not null default 1,\n"
4313 " status varchar(255),\n"
4314 " outbound_call_total_count integer not null default 0,\n"
4315 " outbound_fail_total_count integer not null default 0,\n"
4316 " active_time integer not null default 0,\n"
4317 " inactive_time integer not null default 0,\n"
4318 " manual_calls_out_count integer not null default 0,\n"
4319 " manual_calls_in_count integer not null default 0,\n"
4320 " manual_calls_out_total_count integer not null default 0,\n"
4321 " manual_calls_in_total_count integer not null default 0,\n"
4322 " ring_count integer not null default 0,\n"
4323 " start_time integer not null default 0,\n"
4324 " stop_time integer not null default 0\n"
4325 ");\n";
4326
4327const char bridge_sql[] =
4328 "create table fifo_bridge (\n"
4329 " fifo_name varchar(1024) not null,\n"
4330 " caller_uuid varchar(255) not null,\n"
4331 " caller_caller_id_name varchar(255),\n"
4332 " caller_caller_id_number varchar(255),\n"
4333
4334 " consumer_uuid varchar(255) not null,\n"
4335 " consumer_outgoing_uuid varchar(255),\n"
4336 " bridge_start integer\n"
4337 ");\n"
4338;
4339
4340const char callers_sql[] =
4341 "create table fifo_callers (\n"
4342 " fifo_name varchar(255) not null,\n"
4343 " uuid varchar(255) not null,\n"
4344 " caller_caller_id_name varchar(255),\n"
4345 " caller_caller_id_number varchar(255),\n"
4346 " timestamp integer\n"
4347 ");\n"
4348;
4349
4350static void extract_fifo_outbound_uuid(char *string, char *uuid, switch_size_t len)
4351{
4352 switch_event_t *ovars;
4353 char *parsed = NULL((void*)0);
4354 const char *fifo_outbound_uuid;
4355
4356 switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_fifo.c", (const char
* )(const char *)__func__, 4356, &ovars, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
4357 switch_event_create_brackets(string, '{', '}', ',', &ovars, &parsed, SWITCH_TRUE);
4358
4359 if ((fifo_outbound_uuid = switch_event_get_header(ovars, "fifo_outbound_uuid")switch_event_get_header_idx(ovars, "fifo_outbound_uuid", -1))) {
4360 switch_snprintf(uuid, len, "%s", fifo_outbound_uuid);
4361 }
4362
4363 switch_safe_free(parsed)if (parsed) {free(parsed);parsed=((void*)0);};
4364 switch_event_destroy(&ovars);
4365}
4366
4367static switch_status_t read_config_file(switch_xml_t *xml, switch_xml_t *cfg) {
4368 const char *cf = "fifo.conf";
4369 switch_xml_t settings;
4370
4371 if (!(*xml = switch_xml_open_cfg(cf, cfg, NULL((void*)0)))) {
4372 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4372
, ((void*)0)
, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
4373 return SWITCH_STATUS_TERM;
4374 }
4375 if ((settings = switch_xml_child(*cfg, "settings"))) {
4376 switch_xml_t param;
4377 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
4378 char *var = (char*)switch_xml_attr_soft(param, "name");
4379 char *val = (char*)switch_xml_attr_soft(param, "value");
4380
4381 if (!strcasecmp(var, "outbound-strategy") && !zstr(val)_zstr(val)) {
4382 globals.default_strategy = parse_strategy(val);
4383 } else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)_zstr(val)) {
4384 if (switch_odbc_available() || switch_pgsql_available()) {
4385 switch_set_string(globals.odbc_dsn, val)switch_copy_string(globals.odbc_dsn, val, sizeof(globals.odbc_dsn
))
;
4386 } else {
4387 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4387
, ((void*)0)
, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
4388 }
4389 } else if (!strcasecmp(var, "dbname") && !zstr(val)_zstr(val)) {
4390 globals.dbname = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_fifo.c", (
const char *)__func__, 4390)
;
4391 } else if (!strcasecmp(var, "allow-transcoding") && !zstr(val)_zstr(val)) {
4392 globals.allow_transcoding = switch_true(val);
4393 } else if (!strcasecmp(var, "db-pre-trans-execute") && !zstr(val)_zstr(val)) {
4394 globals.pre_trans_execute = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_fifo.c", (
const char *)__func__, 4394)
;
4395 } else if (!strcasecmp(var, "db-post-trans-execute") && !zstr(val)_zstr(val)) {
4396 globals.post_trans_execute = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_fifo.c", (
const char *)__func__, 4396)
;
4397 } else if (!strcasecmp(var, "db-inner-pre-trans-execute") && !zstr(val)_zstr(val)) {
4398 globals.inner_pre_trans_execute = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_fifo.c", (
const char *)__func__, 4398)
;
4399 } else if (!strcasecmp(var, "db-inner-post-trans-execute") && !zstr(val)_zstr(val)) {
4400 globals.inner_post_trans_execute = switch_core_strdup(globals.pool, val)switch_core_perform_strdup(globals.pool, val, "mod_fifo.c", (
const char *)__func__, 4400)
;
4401 } else if (!strcasecmp(var, "delete-all-outbound-member-on-startup")) {
4402 globals.delete_all_members_on_startup = switch_true(val);
4403 }
4404 }
4405 }
4406 return SWITCH_STATUS_SUCCESS;
4407}
4408
4409/*!\brief Load or reload the configuration
4410 *
4411 * On the initial load, non-static members are preserved unless the
4412 * parameter `delete-all-outbound-members-on-startup` is set. The
4413 * parameter `del_all` is ignored in this case.
4414 *
4415 * On reload, non-static members are preserved unless `del_all` is
4416 * set.
4417 *
4418 * \param reload true if we're reloading the config
4419 * \param del_all delete all outbound members when reloading;
4420 * not used unless reload is true
4421 */
4422static switch_status_t load_config(int reload, int del_all)
4423{
4424 switch_xml_t xml, cfg, fifo, fifos, member;
4425 switch_status_t status = SWITCH_STATUS_SUCCESS;
4426 char *sql;
4427 switch_cache_db_handle_t *dbh = NULL((void*)0);
4428 fifo_node_t *node;
4429
4430 strncpy(globals.hostname, switch_core_get_switchname(), sizeof(globals.hostname) - 1)__builtin_strncpy (globals.hostname, switch_core_get_switchname
(), sizeof(globals.hostname) - 1)
;
4431 globals.dbname = "fifo";
4432 globals.default_strategy = NODE_STRATEGY_RINGALL;
4433 globals.delete_all_members_on_startup = SWITCH_FALSE;
4434
4435 if ((status = read_config_file(&xml, &cfg)) != SWITCH_STATUS_SUCCESS) return status;
4436
4437 if (!(dbh = fifo_get_db_handle())) {
4438 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4438
, ((void*)0)
, SWITCH_LOG_CRIT, "Cannot open DB!\n");
4439 goto done;
4440 }
4441
4442 if (!reload) {
4443 switch_sql_queue_manager_init_name("fifo",
4444 &globals.qm,
4445 2,
4446 !zstr(globals.odbc_dsn)_zstr(globals.odbc_dsn) ? globals.odbc_dsn : globals.dbname,
4447 SWITCH_MAX_TRANS2000,
4448 globals.pre_trans_execute,
4449 globals.post_trans_execute,
4450 globals.inner_pre_trans_execute,
4451 globals.inner_post_trans_execute);
4452 switch_sql_queue_manager_start(globals.qm);
4453
4454 switch_cache_db_test_reactive(dbh, "delete from fifo_outbound where static = 1 or taking_calls < 0 or stop_time < 0",
4455 "drop table fifo_outbound", outbound_sql);
4456 switch_cache_db_test_reactive(dbh, "delete from fifo_bridge", "drop table fifo_bridge", bridge_sql);
4457 switch_cache_db_test_reactive(dbh, "delete from fifo_callers", "drop table fifo_callers", callers_sql);
4458 }
4459
4460 switch_cache_db_release_db_handle(&dbh);
4461
4462 if (!reload) {
4463 char *sql= "update fifo_outbound set start_time=0,stop_time=0,ring_count=0,use_count=0,outbound_call_count=0,outbound_fail_count=0 where static=0";
4464 fifo_execute_sql_queued(&sql, SWITCH_FALSE, SWITCH_TRUE);
4465 fifo_init_use_count();
4466 }
4467
4468 if (reload) {
4469 switch_hash_index_t *hi;
4470 fifo_node_t *node;
4471 void *val;
4472 switch_mutex_lock(globals.mutex);
4473 for (hi = switch_core_hash_first(globals.fifo_hash)switch_core_hash_first_iter(globals.fifo_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
4474 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
4475 if ((node = (fifo_node_t *) val) && node->is_static && node->ready == 1) {
4476 node->ready = -1;
4477 }
4478 }
4479 switch_mutex_unlock(globals.mutex);
4480 }
4481
4482 if ((reload && del_all) || (!reload && globals.delete_all_members_on_startup)) {
4483 sql = switch_mprintf("delete from fifo_outbound where hostname='%q'", globals.hostname);
4484 } else {
4485 sql = switch_mprintf("delete from fifo_outbound where static=1 and hostname='%q'", globals.hostname);
4486 }
4487
4488 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
4489
4490 if (!switch_core_hash_find(globals.fifo_hash, MANUAL_QUEUE_NAME"manual_calls")) {
4491 node = create_node(MANUAL_QUEUE_NAME"manual_calls", 0, globals.sql_mutex);
4492 node->ready = 2;
4493 node->is_static = 0;
4494 }
4495
4496 if ((fifos = switch_xml_child(cfg, "fifos"))) {
4497 for (fifo = switch_xml_child(fifos, "fifo"); fifo; fifo = fifo->next) {
4498 const char *name, *sp;
4499 const char *val;
4500 int i, importance = 0;
4501
4502 if (!(name = switch_xml_attr(fifo, "name"))) {
4503 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4503
, ((void*)0)
, SWITCH_LOG_ERROR, "fifo has no name!\n");
4504 continue;
4505 }
4506
4507 if (!strcasecmp(name, MANUAL_QUEUE_NAME"manual_calls")) {
4508 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4508
, ((void*)0)
, SWITCH_LOG_ERROR, "%s is a reserved name, use another name please.\n", MANUAL_QUEUE_NAME"manual_calls");
4509 continue;
4510 }
4511
4512 if ((val = switch_xml_attr(fifo, "importance")) && !((i = atoi(val)) < 0)) {
4513 importance = i;
4514 }
4515
4516 switch_mutex_lock(globals.mutex);
4517 if (!(node = switch_core_hash_find(globals.fifo_hash, name))) {
4518 node = create_node(name, importance, globals.sql_mutex);
4519 }
4520
4521 if ((val = switch_xml_attr(fifo, "outbound_name"))) {
4522 node->outbound_name = switch_core_strdup(node->pool, val)switch_core_perform_strdup(node->pool, val, "mod_fifo.c", (
const char *)__func__, 4522)
;
4523 }
4524
4525 switch_mutex_unlock(globals.mutex);
4526 switch_assert(node)((node) ? (void) (0) : __assert_fail ("node", "mod_fifo.c", 4526
, __PRETTY_FUNCTION__))
;
4527 switch_mutex_lock(node->mutex);
4528
4529 if ((sp = switch_xml_attr(fifo, "outbound_strategy"))) {
4530 node->outbound_strategy = parse_strategy(sp);
4531 node->has_outbound = 1;
4532 }
4533
4534 node->outbound_per_cycle = 1;
4535 if ((val = switch_xml_attr(fifo, "outbound_per_cycle"))) {
4536 if (!((i = atoi(val)) < 0)) {
4537 node->outbound_per_cycle = i;
4538 }
4539 node->has_outbound = 1;
4540 }
4541
4542 node->outbound_per_cycle_min = 1;
4543 if ((val = switch_xml_attr(fifo, "outbound_per_cycle_min"))) {
4544 if (!((i = atoi(val)) < 0)) {
4545 node->outbound_per_cycle_min = i;
4546 }
4547 }
4548
4549 if ((val = switch_xml_attr(fifo, "retry_delay"))) {
4550 if ((i = atoi(val)) < 0) i = 0;
4551 node->retry_delay = i;
4552 }
4553
4554 node->outbound_priority = 5;
4555 if ((val = switch_xml_attr(fifo, "outbound_priority"))) {
4556 i = atoi(val);
4557 if (!(i < 1 || i > 10)) {
4558 node->outbound_priority = i;
4559 }
4560 node->has_outbound = 1;
4561 }
4562
4563 node->ring_timeout = 60;
4564 if ((val = switch_xml_attr(fifo, "outbound_ring_timeout"))) {
4565 if ((i = atoi(val)) > 10) {
4566 node->ring_timeout = i;
4567 } else {
4568 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4568
, ((void*)0)
, SWITCH_LOG_CRIT, "Invalid ring_timeout: must be > 10 for queue %s\n", node->name);
4569 }
4570 }
4571
4572 node->default_lag = 30;
4573 if ((val = switch_xml_attr(fifo, "outbound_default_lag"))) {
4574 if ((i = atoi(val)) > 10) {
4575 node->default_lag = i;
4576 } else {
4577 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4577
, ((void*)0)
, SWITCH_LOG_CRIT, "Invalid default_lag: must be > 10 for queue %s\n", node->name);
4578 }
4579 }
4580
4581 for (member = switch_xml_child(fifo, "member"); member; member = member->next) {
4582 const char *simo, *taking_calls, *timeout, *lag;
4583 int simo_i = 1, taking_calls_i = 1, timeout_i = 60, lag_i = 10;
4584 char digest[SWITCH_MD5_DIGEST_STRING_SIZE33] = { 0 };
4585
4586 if (switch_stristr("fifo_outbound_uuid=", member->txt)) {
4587 extract_fifo_outbound_uuid(member->txt, digest, sizeof(digest));
4588 } else {
4589 switch_md5_string(digest, (void *) member->txt, strlen(member->txt));
4590 }
4591
4592 if ((simo = switch_xml_attr_soft(member, "simo"))) {
4593 simo_i = atoi(simo);
4594 }
4595
4596 if ((taking_calls = switch_xml_attr_soft(member, "taking_calls"))
4597 && (taking_calls_i = atoi(taking_calls)) < 1) {
4598 taking_calls_i = 1;
4599 }
4600
4601 if ((timeout = switch_xml_attr_soft(member, "timeout"))
4602 && (timeout_i = atoi(timeout)) < 10) {
4603 timeout_i = node->ring_timeout;
4604 }
4605
4606 if ((lag = switch_xml_attr_soft(member, "lag"))
4607 && (lag_i = atoi(lag)) < 0) {
4608 lag_i = node->default_lag;
4609 }
4610
4611 sql = switch_mprintf("insert into fifo_outbound "
4612 "(uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, "
4613 "next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls, "
4614 "active_time, inactive_time) "
4615 "values ('%q','%q','%q',%d,%d,%d,%d,0,0,1,0,0,'%q',%d,%ld,0)",
4616 digest, node->name, member->txt, simo_i, 0, timeout_i, lag_i, globals.hostname, taking_calls_i,
4617 (long) switch_epoch_time_now(NULL((void*)0)));
4618 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_fifo.c", 4618
, __PRETTY_FUNCTION__))
;
4619 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE);
4620 node->has_outbound = 1;
4621 node->member_count++;
4622 }
4623 node->ready = 1;
4624 node->is_static = 1;
4625 switch_mutex_unlock(node->mutex);
4626 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4626
, ((void*)0)
, SWITCH_LOG_INFO, "%s configured\n", node->name);
4627 }
4628 }
4629
4630 done:
4631
4632 switch_xml_free(xml);
4633 if (reload) {
4634 fifo_node_t *node;
4635 switch_mutex_lock(globals.mutex);
4636 for (node = globals.nodes; node; node = node->next) {
4637 if (node->ready == -1) {
4638 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4638
, ((void*)0)
, SWITCH_LOG_INFO, "%s queued for removal\n", node->name);
4639 switch_core_hash_delete(globals.fifo_hash, node->name);
4640 node->ready = 0;
4641 }
4642 }
4643 switch_mutex_unlock(globals.mutex);
4644 }
4645
4646 return status;
4647}
4648
4649static void fifo_member_add(char *fifo_name, char *originate_string, int simo_count, int timeout, int lag, time_t expires, int taking_calls)
4650{
4651 char digest[SWITCH_MD5_DIGEST_STRING_SIZE33] = { 0 };
4652 char *sql, *name_dup, *p;
4653 char outbound_count[80] = "";
4654 callback_t cbt = { 0 };
4655 fifo_node_t *node = NULL((void*)0);
4656
4657 if (!fifo_name) return;
4658
4659 if (switch_stristr("fifo_outbound_uuid=", originate_string)) {
4660 extract_fifo_outbound_uuid(originate_string, digest, sizeof(digest));
4661 } else {
4662 switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
4663 }
4664
4665 sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q'", fifo_name, digest);
4666 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_fifo.c", 4666
, __PRETTY_FUNCTION__))
;
4667 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
4668
4669 switch_mutex_lock(globals.mutex);
4670 if (!(node = switch_core_hash_find(globals.fifo_hash, fifo_name))) {
4671 node = create_node(fifo_name, 0, globals.sql_mutex);
4672 node->ready = 1;
4673 }
4674 switch_mutex_unlock(globals.mutex);
4675
4676 name_dup = strdup(fifo_name)(__extension__ (__builtin_constant_p (fifo_name) && (
(size_t)(const void *)((fifo_name) + 1) - (size_t)(const void
*)(fifo_name) == 1) ? (((const char *) (fifo_name))[0] == '\0'
? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen (fifo_name) + 1; char *__retval = (char *) malloc (
__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, fifo_name, __len); __retval; })) : __strdup (fifo_name
)))
;
4677 if ((p = strchr(name_dup, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(name_dup) && ('@') == '\0' ? (char *) __rawmemchr (
name_dup, '@') : __builtin_strchr (name_dup, '@')))
)) {
4678 *p = '\0';
4679 }
4680
4681 sql = switch_mprintf("insert into fifo_outbound "
4682 "(uuid, fifo_name, originate_string, simo_count, use_count, timeout, "
4683 "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls, active_time, inactive_time) "
4684 "values ('%q','%q','%q',%d,%d,%d,%d,%d,%ld,0,0,0,'%q',%d,%ld,0)",
4685 digest, fifo_name, originate_string, simo_count, 0, timeout, lag, 0, (long) expires, globals.hostname, taking_calls,
4686 (long)switch_epoch_time_now(NULL((void*)0)));
4687 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_fifo.c", 4687
, __PRETTY_FUNCTION__))
;
4688 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
4689 free(name_dup);
4690
4691 cbt.buf = outbound_count;
4692 cbt.len = sizeof(outbound_count);
4693 sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", fifo_name);
4694 fifo_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt);
4695 node->member_count = atoi(outbound_count);
4696 if (node->member_count > 0) {
4697 node->has_outbound = 1;
4698 } else {
4699 node->has_outbound = 0;
4700 }
4701 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4702}
4703
4704static void fifo_member_del(char *fifo_name, char *originate_string)
4705{
4706 char digest[SWITCH_MD5_DIGEST_STRING_SIZE33] = { 0 };
4707 char *sql;
4708 char outbound_count[80] = "";
4709 callback_t cbt = { 0 };
4710 fifo_node_t *node = NULL((void*)0);
4711
4712 if (!fifo_name) return;
4713
4714 if (switch_stristr("fifo_outbound_uuid=", originate_string)) {
4715 extract_fifo_outbound_uuid(originate_string, digest, sizeof(digest));
4716 } else {
4717 switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
4718 }
4719
4720 sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q' and hostname='%q'", fifo_name, digest, globals.hostname);
4721 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_fifo.c", 4721
, __PRETTY_FUNCTION__))
;
4722 fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE);
4723
4724 switch_mutex_lock(globals.mutex);
4725 if (!(node = switch_core_hash_find(globals.fifo_hash, fifo_name))) {
4726 node = create_node(fifo_name, 0, globals.sql_mutex);
4727 node->ready = 1;
4728 }
4729 switch_mutex_unlock(globals.mutex);
4730
4731 cbt.buf = outbound_count;
4732 cbt.len = sizeof(outbound_count);
4733 sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", node->name);
4734 fifo_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt);
4735 node->member_count = atoi(outbound_count);
4736 if (node->member_count > 0) {
4737 node->has_outbound = 1;
4738 } else {
4739 node->has_outbound = 0;
4740 }
4741 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4742}
4743
4744#define FIFO_MEMBER_API_SYNTAX"[add <fifo_name> <originate_string> [<simo_count>] [<timeout>] [<lag>] [<expires>] [<taking_calls>] | del <fifo_name> <originate_string>]" "[add <fifo_name> <originate_string> [<simo_count>] [<timeout>] [<lag>] [<expires>] [<taking_calls>] | del <fifo_name> <originate_string>]"
4745SWITCH_STANDARD_API(fifo_member_api_function)static switch_status_t fifo_member_api_function ( const char *
cmd, switch_core_session_t *session, switch_stream_handle_t *
stream)
4746{
4747 char *fifo_name;
4748 char *originate_string;
4749 int simo_count = 1;
4750 int timeout = 60;
4751 int lag = 5;
4752 int taking_calls = 1;
4753 char *action;
4754 char *mydata = NULL((void*)0), *argv[8] = { 0 };
4755 int argc;
4756 time_t expires = 0;
4757
4758 if (!globals.running) {
4759 return SWITCH_STATUS_FALSE;
4760 }
4761
4762 if (zstr(cmd)_zstr(cmd)) {
4763 stream->write_function(stream, "-USAGE: %s\n", FIFO_MEMBER_API_SYNTAX"[add <fifo_name> <originate_string> [<simo_count>] [<timeout>] [<lag>] [<expires>] [<taking_calls>] | del <fifo_name> <originate_string>]");
4764 return SWITCH_STATUS_SUCCESS;
4765 }
4766
4767 mydata = strdup(cmd)(__extension__ (__builtin_constant_p (cmd) && ((size_t
)(const void *)((cmd) + 1) - (size_t)(const void *)(cmd) == 1
) ? (((const char *) (cmd))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (cmd) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, cmd, __len); __retval
; })) : __strdup (cmd)))
;
4768 switch_assert(mydata)((mydata) ? (void) (0) : __assert_fail ("mydata", "mod_fifo.c"
, 4768, __PRETTY_FUNCTION__))
;
4769
4770 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
4771
4772 if (argc < 3) {
4773 stream->write_function(stream, "%s", "-ERR Invalid!\n");
4774 goto done;
4775 }
4776
4777 action = argv[0];
4778 fifo_name = argv[1];
4779 originate_string = argv[2];
4780
4781 if (action && !strcasecmp(action, "add")) {
4782 if (argc > 3) {
4783 simo_count = atoi(argv[3]);
4784 }
4785 if (argc > 4) {
4786 timeout = atoi(argv[4]);
4787 }
4788 if (argc > 5) {
4789 lag = atoi(argv[5]);
4790 }
4791 if (argc > 6) {
4792 expires = switch_epoch_time_now(NULL((void*)0)) + atoi(argv[6]);
4793 }
4794 if (argc > 7) {
4795 taking_calls = atoi(argv[7]);
4796 }
4797 if (simo_count < 0) {
4798 simo_count = 1;
4799 }
4800 if (timeout < 0) {
4801 timeout = 60;
4802 }
4803 if (lag < 0) {
4804 lag = 5;
4805 }
4806 if (taking_calls < 1) {
4807 taking_calls = 1;
4808 }
4809
4810 fifo_member_add(fifo_name, originate_string, simo_count, timeout, lag, expires, taking_calls);
4811 stream->write_function(stream, "%s", "+OK\n");
4812 } else if (action && !strcasecmp(action, "del")) {
4813 fifo_member_del(fifo_name, originate_string);
4814 stream->write_function(stream, "%s", "+OK\n");
4815 } else {
4816 stream->write_function(stream, "%s", "-ERR Invalid!\n");
4817 goto done;
4818 }
4819
4820 done:
4821
4822 free(mydata);
4823
4824 return SWITCH_STATUS_SUCCESS;
4825}
4826
4827SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)switch_status_t mod_fifo_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
4828{
4829 switch_application_interface_t *app_interface;
4830 switch_api_interface_t *commands_api_interface;
4831 switch_status_t status;
4832
4833 /* create/register custom event message type */
4834 if (switch_event_reserve_subclass(FIFO_EVENT)switch_event_reserve_subclass_detailed("mod_fifo.c", "fifo::info"
)
!= SWITCH_STATUS_SUCCESS) {
4835 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4835
, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!", FIFO_EVENT"fifo::info");
4836 return SWITCH_STATUS_TERM;
4837 }
4838
4839 /* Subscribe to presence request events */
4840 if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY((void*)0),
4841 pres_event_handler, NULL((void*)0), &globals.node) != SWITCH_STATUS_SUCCESS) {
4842 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_fifo.c", (const char *)__func__, 4842
, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't subscribe to presence request events!\n");
4843 return SWITCH_STATUS_GENERR;
4844 }
4845
4846 globals.pool = pool;
4847 switch_core_hash_init(&globals.fifo_hash)switch_core_hash_init_case(&globals.fifo_hash, SWITCH_TRUE
)
;
4848
4849 switch_core_hash_init(&globals.caller_orig_hash)switch_core_hash_init_case(&globals.caller_orig_hash, SWITCH_TRUE
)
;
4850 switch_core_hash_init(&globals.consumer_orig_hash)switch_core_hash_init_case(&globals.consumer_orig_hash, SWITCH_TRUE
)
;
4851 switch_core_hash_init(&globals.bridge_hash)switch_core_hash_init_case(&globals.bridge_hash, SWITCH_TRUE
)
;
4852 switch_core_hash_init(&globals.use_hash)switch_core_hash_init_case(&globals.use_hash, SWITCH_TRUE
)
;
4853 switch_mutex_init(&globals.caller_orig_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
4854 switch_mutex_init(&globals.consumer_orig_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
4855 switch_mutex_init(&globals.bridge_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
4856
4857 switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
4858 switch_mutex_init(&globals.use_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
4859 switch_mutex_init(&globals.sql_mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
4860
4861 globals.running = 1;
4862
4863 if ((status = load_config(0, 1)) != SWITCH_STATUS_SUCCESS) {
4864 switch_event_unbind(&globals.node);
4865 switch_event_free_subclass(FIFO_EVENT)switch_event_free_subclass_detailed("mod_fifo.c", "fifo::info"
)
;
4866 switch_core_hash_destroy(&globals.fifo_hash);
4867 return status;
4868 }
4869
4870 /* connect my internal structure to the blank pointer passed to me */
4871 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
4872 SWITCH_ADD_APP(app_interface, "fifo", "Park with FIFO", FIFO_DESC, fifo_function, FIFO_USAGE, SAF_NONE)for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "fifo"; app_interface->
application_function = fifo_function; app_interface->short_desc
= "Park with FIFO"; app_interface->long_desc = "Fifo for stacking parked calls."
; app_interface->syntax = "<fifo name>[!<importance_number>] [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]"
; app_interface->flags = SAF_NONE; break; }
;
4873 SWITCH_ADD_APP(app_interface, "fifo_track_call", "Count a call as a fifo call in the manual_calls queue",for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "fifo_track_call"; app_interface
->application_function = fifo_track_call_function; app_interface
->short_desc = "Count a call as a fifo call in the manual_calls queue"
; app_interface->long_desc = ""; app_interface->syntax =
"<fifo_outbound_uuid>"; app_interface->flags = SAF_SUPPORT_NOMEDIA
; break; }
4874 "", fifo_track_call_function, "<fifo_outbound_uuid>", SAF_SUPPORT_NOMEDIA)for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "fifo_track_call"; app_interface
->application_function = fifo_track_call_function; app_interface
->short_desc = "Count a call as a fifo call in the manual_calls queue"
; app_interface->long_desc = ""; app_interface->syntax =
"<fifo_outbound_uuid>"; app_interface->flags = SAF_SUPPORT_NOMEDIA
; break; }
;
4875 SWITCH_ADD_API(commands_api_interface, "fifo", "Return data about a fifo", fifo_api_function, FIFO_API_SYNTAX)for (;;) { commands_api_interface = (switch_api_interface_t *
)switch_loadable_module_create_interface(*module_interface, SWITCH_API_INTERFACE
); commands_api_interface->interface_name = "fifo"; commands_api_interface
->desc = "Return data about a fifo"; commands_api_interface
->function = fifo_api_function; commands_api_interface->
syntax = "list|list_verbose|count|debug|status|has_outbound|importance [<fifo name>]|reparse [del_all]"
; break; }
;
4876 SWITCH_ADD_API(commands_api_interface, "fifo_member", "Add members to a fifo", fifo_member_api_function, FIFO_MEMBER_API_SYNTAX)for (;;) { commands_api_interface = (switch_api_interface_t *
)switch_loadable_module_create_interface(*module_interface, SWITCH_API_INTERFACE
); commands_api_interface->interface_name = "fifo_member";
commands_api_interface->desc = "Add members to a fifo"; commands_api_interface
->function = fifo_member_api_function; commands_api_interface
->syntax = "[add <fifo_name> <originate_string> [<simo_count>] [<timeout>] [<lag>] [<expires>] [<taking_calls>] | del <fifo_name> <originate_string>]"
; break; }
;
4877 SWITCH_ADD_API(commands_api_interface, "fifo_add_outbound", "Add outbound members to a fifo", fifo_add_outbound_function, "<node> <url> [<priority>]")for (;;) { commands_api_interface = (switch_api_interface_t *
)switch_loadable_module_create_interface(*module_interface, SWITCH_API_INTERFACE
); commands_api_interface->interface_name = "fifo_add_outbound"
; commands_api_interface->desc = "Add outbound members to a fifo"
; commands_api_interface->function = fifo_add_outbound_function
; commands_api_interface->syntax = "<node> <url> [<priority>]"
; break; }
;
4878 SWITCH_ADD_API(commands_api_interface, "fifo_check_bridge", "check if uuid is in a bridge", fifo_check_bridge_function, "<uuid>|<outbound_id>")for (;;) { commands_api_interface = (switch_api_interface_t *
)switch_loadable_module_create_interface(*module_interface, SWITCH_API_INTERFACE
); commands_api_interface->interface_name = "fifo_check_bridge"
; commands_api_interface->desc = "check if uuid is in a bridge"
; commands_api_interface->function = fifo_check_bridge_function
; commands_api_interface->syntax = "<uuid>|<outbound_id>"
; break; }
;
4879 switch_console_set_complete("add fifo list");
4880 switch_console_set_complete("add fifo list_verbose");
4881 switch_console_set_complete("add fifo count");
4882 switch_console_set_complete("add fifo debug");
4883 switch_console_set_complete("add fifo status");
4884 switch_console_set_complete("add fifo has_outbound");
4885 switch_console_set_complete("add fifo importance");
4886 switch_console_set_complete("add fifo reparse");
4887 switch_console_set_complete("add fifo_check_bridge ::console::list_uuid");
4888
4889 start_node_thread(globals.pool);
4890
4891 return SWITCH_STATUS_SUCCESS;
4892}
4893
4894/*
4895 Called when the system shuts down
4896*/
4897SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)switch_status_t mod_fifo_shutdown (void)
4898{
4899 switch_event_t *pop = NULL((void*)0);
4900 fifo_node_t *node, *this_node;
4901 switch_mutex_t *mutex = globals.mutex;
4902
4903 switch_sql_queue_manager_destroy(&globals.qm);
4904
4905 switch_event_unbind(&globals.node);
4906 switch_event_free_subclass(FIFO_EVENT)switch_event_free_subclass_detailed("mod_fifo.c", "fifo::info"
)
;
4907
4908 switch_mutex_lock(mutex);
4909
4910 globals.running = 0;
4911 /* Cleanup */
4912
4913 stop_node_thread();
4914
4915 while(globals.threads) {
4916 switch_cond_next();
4917 }
4918
4919 node = globals.nodes;
4920
4921 while(node) {
4922 int x = 0;
4923
4924 this_node = node;
4925 node = node->next;
4926
4927 switch_mutex_lock(this_node->update_mutex);
4928 switch_mutex_lock(this_node->mutex);
4929 for (x = 0; x < MAX_PRI10; x++) {
4930 while (fifo_queue_pop(this_node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
4931 switch_event_destroy(&pop);
4932 }
4933 }
4934 switch_mutex_unlock(this_node->mutex);
4935 switch_core_hash_delete(globals.fifo_hash, this_node->name);
4936 switch_core_hash_destroy(&this_node->consumer_hash);
4937 switch_mutex_unlock(this_node->update_mutex);
4938 switch_core_destroy_memory_pool(&this_node->pool)switch_core_perform_destroy_memory_pool(&this_node->pool
, "mod_fifo.c", (const char *)__func__, 4938)
;
4939 }
4940
4941 switch_core_hash_destroy(&globals.fifo_hash);
4942 switch_core_hash_destroy(&globals.caller_orig_hash);
4943 switch_core_hash_destroy(&globals.consumer_orig_hash);
4944 switch_core_hash_destroy(&globals.bridge_hash);
4945 switch_core_hash_destroy(&globals.use_hash);
4946 memset(&globals, 0, sizeof(globals));
4947 switch_mutex_unlock(mutex);
4948
4949 return SWITCH_STATUS_SUCCESS;
4950}
4951
4952/* For Emacs:
4953 * Local Variables:
4954 * mode:c
4955 * indent-tabs-mode:t
4956 * tab-width:4
4957 * c-basic-offset:4
4958 * End:
4959 * For VIM:
4960 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
4961 */