2007-10-01 20:39:16 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* Version: MPL 1.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* mod_fifo.c -- FIFO
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <switch.h>
|
|
|
|
|
|
|
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown);
|
|
|
|
SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load);
|
|
|
|
SWITCH_MODULE_DEFINITION(mod_fifo, mod_fifo_load, mod_fifo_shutdown, NULL);
|
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
#define FIFO_EVENT "fifo::info"
|
|
|
|
|
2008-03-19 16:03:51 +00:00
|
|
|
#define MAX_PRI 10
|
|
|
|
|
|
|
|
struct fifo_node {
|
|
|
|
char *name;
|
|
|
|
switch_mutex_t *mutex;
|
|
|
|
switch_queue_t *fifo_list[MAX_PRI];
|
|
|
|
switch_hash_t *caller_hash;
|
|
|
|
switch_hash_t *consumer_hash;
|
|
|
|
int caller_count;
|
|
|
|
int waiting_count;
|
|
|
|
int consumer_count;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct fifo_node fifo_node_t;
|
2007-10-02 00:03:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
|
|
|
{
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_core_session_t *bleg = (switch_core_session_t *) buf;
|
2007-10-02 00:03:53 +00:00
|
|
|
|
|
|
|
switch (itype) {
|
|
|
|
case SWITCH_INPUT_TYPE_DTMF:
|
|
|
|
{
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
|
|
|
|
|
|
|
|
if (dtmf->digit == '*') {
|
2008-01-28 07:26:10 +00:00
|
|
|
if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_ORIGINATOR)) {
|
|
|
|
switch_channel_hangup(switch_core_session_get_channel(bleg), SWITCH_CAUSE_NORMAL_CLEARING);
|
2007-10-02 00:03:53 +00:00
|
|
|
return SWITCH_STATUS_BREAK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define check_string(s) if (!switch_strlen_zero(s) && !strcasecmp(s, "undef")) { s = NULL; }
|
|
|
|
|
|
|
|
static switch_status_t read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
|
|
|
|
{
|
2008-03-19 16:03:51 +00:00
|
|
|
fifo_node_t *node = (fifo_node_t *) user_data;
|
|
|
|
int x = 0, total = 0;
|
|
|
|
|
|
|
|
for (x = 0; x < MAX_PRI; x++) {
|
|
|
|
total += switch_queue_size(node->fifo_list[x]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (total) {
|
2007-10-02 00:03:53 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2008-03-19 16:03:51 +00:00
|
|
|
|
2007-10-02 00:03:53 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
static struct {
|
|
|
|
switch_hash_t *fifo_hash;
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_mutex_t *mutex;
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_memory_pool_t *pool;
|
2008-01-03 21:34:44 +00:00
|
|
|
int running;
|
2007-10-01 20:39:16 +00:00
|
|
|
} globals;
|
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
|
2007-12-18 23:07:48 +00:00
|
|
|
static fifo_node_t *create_node(const char *name)
|
|
|
|
{
|
|
|
|
fifo_node_t *node;
|
2008-03-19 16:03:51 +00:00
|
|
|
int x = 0;
|
|
|
|
|
2008-01-03 21:34:44 +00:00
|
|
|
if (!globals.running) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-12-18 23:07:48 +00:00
|
|
|
node = switch_core_alloc(globals.pool, sizeof(*node));
|
|
|
|
node->name = switch_core_strdup(globals.pool, name);
|
2008-03-19 16:03:51 +00:00
|
|
|
for (x = 0; x < MAX_PRI; x++) {
|
|
|
|
switch_queue_create(&node->fifo_list[x], SWITCH_CORE_QUEUE_LEN, globals.pool);
|
|
|
|
switch_assert(node->fifo_list[x]);
|
|
|
|
}
|
2007-12-18 23:07:48 +00:00
|
|
|
switch_core_hash_init(&node->caller_hash, globals.pool);
|
|
|
|
switch_core_hash_init(&node->consumer_hash, globals.pool);
|
2008-03-19 16:03:51 +00:00
|
|
|
|
2007-12-18 23:07:48 +00:00
|
|
|
switch_mutex_init(&node->mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
|
|
|
switch_core_hash_insert(globals.fifo_hash, name, node);
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void send_presence(fifo_node_t *node)
|
|
|
|
{
|
|
|
|
switch_event_t *event;
|
|
|
|
|
2008-01-03 21:34:44 +00:00
|
|
|
if (!globals.running) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-12-18 23:07:48 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "%s", "park");
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", node->name);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", node->name);
|
|
|
|
if (node->waiting_count > 0) {
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d waiting)", node->waiting_count);
|
|
|
|
} else {
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Idle");
|
|
|
|
}
|
2008-01-01 22:27:51 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", "unknown");
|
2007-12-18 23:07:48 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", 0);
|
|
|
|
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-state", "%s", node->waiting_count > 0 ? "CS_RING" : "CS_HANGUP");
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "unique-id", "%s", node->name);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "answer-state", "%s", node->waiting_count > 0 ? "early" : "terminated");
|
2007-12-29 19:41:41 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-direction", "%s", "inbound");
|
2007-12-18 23:07:48 +00:00
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void pres_event_handler(switch_event_t *event)
|
|
|
|
{
|
|
|
|
char *to = switch_event_get_header(event, "to");
|
|
|
|
char *dup_to = NULL, *node_name;
|
|
|
|
fifo_node_t *node;
|
2008-01-03 21:34:44 +00:00
|
|
|
|
|
|
|
if (!globals.running) {
|
|
|
|
return;
|
|
|
|
}
|
2007-12-18 23:07:48 +00:00
|
|
|
|
|
|
|
if (!to || strncasecmp(to, "park+", 5)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dup_to = strdup(to);
|
|
|
|
switch_assert(dup_to);
|
|
|
|
|
|
|
|
node_name = dup_to + 5;
|
|
|
|
|
|
|
|
switch_mutex_lock(globals.mutex);
|
|
|
|
if (!(node = switch_core_hash_find(globals.fifo_hash, node_name))) {
|
|
|
|
node = create_node(node_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
send_presence(node);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
|
|
|
|
|
|
|
switch_mutex_unlock(globals.mutex);
|
|
|
|
|
|
|
|
switch_safe_free(dup_to);
|
|
|
|
}
|
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
#define FIFO_DESC "Fifo for stacking parked calls."
|
2007-10-02 00:03:53 +00:00
|
|
|
#define FIFO_USAGE "<fifo name> [in [<announce file>|undef] [<music file>|undef] | out [wait|nowait] [<announce file>|undef] [<music file>|undef]]"
|
2007-10-01 20:39:16 +00:00
|
|
|
SWITCH_STANDARD_APP(fifo_function)
|
|
|
|
{
|
|
|
|
int argc;
|
2007-10-02 00:03:53 +00:00
|
|
|
char *mydata = NULL, *argv[5] = { 0 };
|
2007-10-02 19:58:06 +00:00
|
|
|
fifo_node_t *node;
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
2007-10-01 20:39:16 +00:00
|
|
|
int nowait = 0;
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *moh = NULL;
|
|
|
|
const char *announce = NULL;
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_event_t *event = NULL;
|
|
|
|
char date[80] = "";
|
|
|
|
switch_time_exp_t tm;
|
2007-10-03 16:44:11 +00:00
|
|
|
switch_time_t ts = switch_timestamp_now();
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_size_t retsize;
|
|
|
|
|
2008-01-03 21:34:44 +00:00
|
|
|
if (!globals.running) {
|
|
|
|
return;
|
|
|
|
}
|
2007-10-02 00:03:53 +00:00
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
if (switch_strlen_zero(data)) {
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Args\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mydata = switch_core_session_strdup(session, data);
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(mydata);
|
2008-01-28 09:27:01 +00:00
|
|
|
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 2 || !argv[0]) {
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_mutex_lock(globals.mutex);
|
2007-10-02 19:58:06 +00:00
|
|
|
if (!(node = switch_core_hash_find(globals.fifo_hash, argv[0]))) {
|
2007-12-18 23:07:48 +00:00
|
|
|
node = create_node(argv[0]);
|
2007-10-01 20:39:16 +00:00
|
|
|
}
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_mutex_unlock(globals.mutex);
|
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
moh = switch_channel_get_variable(channel, "fifo_music");
|
2007-10-02 00:03:53 +00:00
|
|
|
announce = switch_channel_get_variable(channel, "fifo_announce");
|
2007-10-01 20:39:16 +00:00
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
nowait = !strcasecmp(argv[2], "nowait");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcasecmp(argv[1], "in")) {
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *uuid = strdup(switch_core_session_get_uuid(session));
|
2008-03-19 16:03:51 +00:00
|
|
|
const char *pri;
|
|
|
|
int p = 0;
|
2007-10-01 20:39:16 +00:00
|
|
|
|
|
|
|
switch_channel_answer(channel);
|
|
|
|
|
|
|
|
if (argc > 2) {
|
2007-10-02 00:03:53 +00:00
|
|
|
announce = argv[2];
|
|
|
|
}
|
2007-10-02 19:58:06 +00:00
|
|
|
|
2007-10-02 00:03:53 +00:00
|
|
|
if (argc > 3) {
|
|
|
|
moh = argv[3];
|
2007-10-01 20:39:16 +00:00
|
|
|
}
|
|
|
|
|
2007-10-02 00:03:53 +00:00
|
|
|
check_string(announce);
|
|
|
|
check_string(moh);
|
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
if (moh) {
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_ivr_broadcast(uuid, moh, SMF_LOOP | SMF_ECHO_ALEG);
|
|
|
|
}
|
2007-10-02 00:03:53 +00:00
|
|
|
|
|
|
|
switch_channel_set_flag(channel, CF_TAGGED);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
node->caller_count++;
|
2007-12-18 23:07:48 +00:00
|
|
|
node->waiting_count++;
|
|
|
|
send_presence(node);
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_core_hash_insert(node->caller_hash, uuid, session);
|
2008-03-19 16:03:51 +00:00
|
|
|
|
|
|
|
if ((pri = switch_channel_get_variable(channel, "fifo_priority"))) {
|
|
|
|
p = atoi(pri);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p >= MAX_PRI) {
|
|
|
|
p = MAX_PRI - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_queue_push(node->fifo_list[p], (void *)uuid);
|
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_mutex_unlock(node->mutex);
|
|
|
|
|
2007-10-03 16:44:11 +00:00
|
|
|
ts = switch_timestamp_now();
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_time_exp_lt(&tm, ts);
|
|
|
|
switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
|
|
|
|
switch_channel_set_variable(channel, "fifo_status", "WAITING");
|
|
|
|
switch_channel_set_variable(channel, "fifo_timestamp", date);
|
2007-10-02 00:03:53 +00:00
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "push");
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2008-02-15 16:01:12 +00:00
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_ivr_park(session, NULL);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
if (switch_channel_ready(channel)) {
|
2007-10-02 00:03:53 +00:00
|
|
|
if (announce) {
|
|
|
|
switch_ivr_play_file(session, NULL, announce, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_clear_flag(channel, CF_TAGGED);
|
|
|
|
|
|
|
|
if (switch_channel_ready(channel)) {
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_channel_set_state(channel, CS_HIBERNATE);
|
|
|
|
} else {
|
2007-10-03 16:44:11 +00:00
|
|
|
ts = switch_timestamp_now();
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_time_exp_lt(&tm, ts);
|
|
|
|
switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
|
|
|
|
switch_channel_set_variable(channel, "fifo_status", "ABORTED");
|
|
|
|
switch_channel_set_variable(channel, "fifo_timestamp", date);
|
|
|
|
|
|
|
|
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "abort");
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
node->caller_count--;
|
2007-12-18 23:07:48 +00:00
|
|
|
node->waiting_count--;
|
|
|
|
send_presence(node);
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_core_hash_delete(node->caller_hash, uuid);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
2007-10-02 00:03:53 +00:00
|
|
|
}
|
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
return;
|
|
|
|
} else if (!strcasecmp(argv[1], "out")) {
|
2008-03-20 00:27:04 +00:00
|
|
|
void *pop = NULL;
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_frame_t *read_frame;
|
|
|
|
switch_status_t status;
|
|
|
|
char *uuid;
|
|
|
|
int done = 0;
|
|
|
|
switch_core_session_t *other_session;
|
2007-10-02 00:03:53 +00:00
|
|
|
switch_input_args_t args = { 0 };
|
2008-03-19 16:03:51 +00:00
|
|
|
const char *pop_order = NULL;
|
|
|
|
int custom_pop = 0;
|
|
|
|
int pop_array[MAX_PRI] = { 0 };
|
|
|
|
char *pop_list[MAX_PRI] = { 0 };
|
|
|
|
|
2007-10-02 00:03:53 +00:00
|
|
|
if (argc > 3) {
|
|
|
|
announce = argv[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > 4) {
|
|
|
|
moh = argv[4];
|
|
|
|
}
|
|
|
|
|
|
|
|
check_string(announce);
|
|
|
|
check_string(moh);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
if (!nowait) {
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
node->consumer_count++;
|
|
|
|
switch_core_hash_insert(node->consumer_hash, switch_core_session_get_uuid(session), session);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_channel_answer(channel);
|
|
|
|
}
|
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_start");
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2007-10-03 16:44:11 +00:00
|
|
|
ts = switch_timestamp_now();
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_time_exp_lt(&tm, ts);
|
|
|
|
switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
|
|
|
|
switch_channel_set_variable(channel, "fifo_status", "WAITING");
|
|
|
|
switch_channel_set_variable(channel, "fifo_timestamp", date);
|
|
|
|
|
2008-03-19 16:03:51 +00:00
|
|
|
if ((pop_order = switch_channel_get_variable(channel, "fifo_pop_order"))) {
|
|
|
|
char *tmp = switch_core_session_strdup(session, pop_order);
|
|
|
|
int x;
|
|
|
|
custom_pop = switch_separate_string(tmp, ',', pop_list, (sizeof(pop_list) / sizeof(pop_list[0])));
|
|
|
|
if (custom_pop >= MAX_PRI) {
|
|
|
|
custom_pop = MAX_PRI -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (x = 0; x < custom_pop; x++) {
|
|
|
|
int tmp = atoi(pop_list[x]);
|
|
|
|
if (tmp > -1 && tmp < MAX_PRI) {
|
|
|
|
pop_array[x] = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
while(switch_channel_ready(channel)) {
|
2008-03-19 16:03:51 +00:00
|
|
|
int x = 0 ;
|
2008-03-24 16:22:33 +00:00
|
|
|
pop = NULL;
|
|
|
|
|
2007-10-02 00:03:53 +00:00
|
|
|
if (moh) {
|
|
|
|
args.read_frame_callback = read_frame_callback;
|
2008-03-19 16:03:51 +00:00
|
|
|
args.user_data = node;
|
2007-10-02 00:03:53 +00:00
|
|
|
switch_ivr_play_file(session, NULL, moh, &args);
|
|
|
|
}
|
2008-03-19 16:03:51 +00:00
|
|
|
|
|
|
|
if (custom_pop) {
|
|
|
|
for(x = 0; x < MAX_PRI; x++) {
|
|
|
|
if (switch_queue_trypop(node->fifo_list[pop_array[x]], &pop) == SWITCH_STATUS_SUCCESS && pop) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for(x = 0; x < MAX_PRI; x++) {
|
|
|
|
if (switch_queue_trypop(node->fifo_list[x], &pop) == SWITCH_STATUS_SUCCESS && pop) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pop) {
|
2007-10-01 20:39:16 +00:00
|
|
|
if (nowait) {
|
2007-10-02 19:58:06 +00:00
|
|
|
break;
|
2007-10-01 20:39:16 +00:00
|
|
|
}
|
2008-03-19 16:03:51 +00:00
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
status = switch_core_session_read_frame(session, &read_frame, -1, 0);
|
2008-03-19 16:03:51 +00:00
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
2007-10-02 19:58:06 +00:00
|
|
|
break;
|
2007-10-01 20:39:16 +00:00
|
|
|
}
|
2008-03-19 16:03:51 +00:00
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
continue;
|
|
|
|
}
|
2008-03-19 16:03:51 +00:00
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
uuid = (char *) pop;
|
2008-03-24 16:22:33 +00:00
|
|
|
pop = NULL;
|
2007-10-01 20:39:16 +00:00
|
|
|
|
|
|
|
if ((other_session = switch_core_session_locate(uuid))) {
|
|
|
|
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
|
2007-10-02 00:03:53 +00:00
|
|
|
switch_caller_profile_t *cloned_profile;
|
2007-10-02 19:58:06 +00:00
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_channel_event_set_data(other_channel, event);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "caller_pop");
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_pop");
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
if (announce) {
|
2007-10-02 00:03:53 +00:00
|
|
|
switch_ivr_play_file(session, NULL, announce, NULL);
|
|
|
|
} else {
|
|
|
|
switch_ivr_sleep(session, 500);
|
|
|
|
}
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
if (switch_channel_test_flag(other_channel, CF_TAGGED)) {
|
|
|
|
switch_channel_clear_flag(other_channel, CF_CONTROLLED);
|
2008-02-15 16:01:12 +00:00
|
|
|
switch_core_session_flush_private_events(other_session);
|
2008-01-05 20:44:54 +00:00
|
|
|
switch_channel_stop_broadcast(other_channel);
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
|
|
|
|
while (switch_channel_test_flag(other_channel, CF_TAGGED)) {
|
|
|
|
status = switch_core_session_read_frame(session, &read_frame, -1, 0);
|
|
|
|
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
|
|
|
break;
|
|
|
|
}
|
2007-10-02 00:03:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_answer(channel);
|
2007-10-02 16:38:15 +00:00
|
|
|
cloned_profile = switch_caller_profile_clone(other_session, switch_channel_get_caller_profile(channel));
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(cloned_profile);
|
2007-10-02 00:03:53 +00:00
|
|
|
switch_channel_set_originator_caller_profile(other_channel, cloned_profile);
|
|
|
|
|
2007-10-02 16:38:15 +00:00
|
|
|
cloned_profile = switch_caller_profile_clone(session, switch_channel_get_caller_profile(other_channel));
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(cloned_profile);
|
|
|
|
switch_assert(cloned_profile->next == NULL);
|
2007-10-02 00:03:53 +00:00
|
|
|
switch_channel_set_originatee_caller_profile(channel, cloned_profile);
|
|
|
|
|
2007-10-03 16:44:11 +00:00
|
|
|
ts = switch_timestamp_now();
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_time_exp_lt(&tm, ts);
|
|
|
|
switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
|
|
|
|
switch_channel_set_variable(channel, "fifo_status", "TALKING");
|
|
|
|
switch_channel_set_variable(channel, "fifo_target", uuid);
|
|
|
|
switch_channel_set_variable(channel, "fifo_timestamp", date);
|
|
|
|
|
|
|
|
switch_channel_set_variable(other_channel, "fifo_status", "TALKING");
|
|
|
|
switch_channel_set_variable(other_channel, "fifo_timestamp", date);
|
|
|
|
switch_channel_set_variable(other_channel, "fifo_target", switch_core_session_get_uuid(session));
|
2007-12-18 23:07:48 +00:00
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
node->waiting_count--;
|
|
|
|
send_presence(node);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
2007-10-02 00:03:53 +00:00
|
|
|
switch_ivr_multi_threaded_bridge(session, other_session, on_dtmf, other_session, session);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
2007-10-03 16:44:11 +00:00
|
|
|
ts = switch_timestamp_now();
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_time_exp_lt(&tm, ts);
|
|
|
|
switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
|
|
|
|
switch_channel_set_variable(channel, "fifo_status", "WAITING");
|
|
|
|
switch_channel_set_variable(channel, "fifo_timestamp", date);
|
|
|
|
|
|
|
|
switch_channel_set_variable(other_channel, "fifo_status", "DONE");
|
|
|
|
switch_channel_set_variable(other_channel, "fifo_timestamp", date);
|
|
|
|
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
node->caller_count--;
|
2007-12-18 23:07:48 +00:00
|
|
|
send_presence(node);
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_core_hash_delete(node->caller_hash, uuid);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_core_session_rwunlock(other_session);
|
2007-10-02 00:03:53 +00:00
|
|
|
if (nowait) {
|
|
|
|
done = 1;
|
|
|
|
}
|
2007-10-01 20:39:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch_safe_free(uuid);
|
|
|
|
|
|
|
|
if (done) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-10-02 19:58:06 +00:00
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Name", "%s", argv[0]);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "consumer_stop");
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nowait) {
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
switch_core_hash_delete(node->consumer_hash, switch_core_session_get_uuid(session));
|
|
|
|
node->consumer_count--;
|
|
|
|
switch_mutex_unlock(node->mutex);
|
|
|
|
}
|
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
} else {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "USAGE %s\n", FIFO_USAGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
static int xml_hash(switch_xml_t xml, switch_hash_t *hash, char *container, char *tag, int cc_off, int verbose)
|
|
|
|
{
|
|
|
|
switch_xml_t x_tmp, x_caller, x_cp, variables;
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
switch_core_session_t *session;
|
|
|
|
switch_channel_t *channel;
|
|
|
|
void *val;
|
|
|
|
const void *var;
|
|
|
|
|
|
|
|
x_tmp = switch_xml_add_child_d(xml, container, cc_off++);
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(x_tmp);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
for (hi = switch_hash_first(NULL, hash); hi; hi = switch_hash_next(hi)) {
|
|
|
|
int c_off = 0, d_off = 0;
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *status;
|
|
|
|
const char *ts;
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
switch_hash_this(hi, &var, NULL, &val);
|
|
|
|
session = (switch_core_session_t *) val;
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
x_caller = switch_xml_add_child_d(x_tmp, tag, c_off++);
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(x_caller);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
switch_xml_set_attr_d(x_caller, "uuid", switch_core_session_get_uuid(session));
|
|
|
|
|
|
|
|
if ((status = switch_channel_get_variable(channel, "fifo_status"))) {
|
|
|
|
switch_xml_set_attr_d(x_caller, "status", status);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ts = switch_channel_get_variable(channel, "fifo_timestamp"))) {
|
|
|
|
switch_xml_set_attr_d(x_caller, "timestamp", ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ts = switch_channel_get_variable(channel, "fifo_target"))) {
|
|
|
|
switch_xml_set_attr_d(x_caller, "target", ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(x_cp = switch_xml_add_child_d(x_caller, "caller_profile", d_off++))) {
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
if (verbose) {
|
|
|
|
d_off += switch_ivr_set_xml_profile_data(x_cp, switch_channel_get_caller_profile(channel), d_off);
|
|
|
|
|
|
|
|
if (!(variables = switch_xml_add_child_d(x_caller, "variables", c_off++))) {
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_ivr_set_xml_chan_vars(variables, channel, c_off);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return cc_off;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int verbose)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch_xml_t x_fifo;
|
|
|
|
int cc_off = 0;
|
2007-11-04 11:05:52 +00:00
|
|
|
char buffer[35];
|
|
|
|
char *tmp = buffer;
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
x_fifo = switch_xml_add_child_d(x_report, "fifo", (*off)++);;
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(x_fifo);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
switch_xml_set_attr_d(x_fifo, "name", node->name);
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(tmp, sizeof(buffer), "%d", node->consumer_count);
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_xml_set_attr_d(x_fifo, "consumer_count", tmp);
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(tmp, sizeof(buffer), "%d", node->caller_count);
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_xml_set_attr_d(x_fifo, "caller_count", tmp);
|
2007-12-18 23:07:48 +00:00
|
|
|
switch_snprintf(tmp, sizeof(buffer), "%d", node->waiting_count);
|
|
|
|
switch_xml_set_attr_d(x_fifo, "waiting_count", tmp);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
cc_off = xml_hash(x_fifo, node->caller_hash, "callers", "caller", cc_off, verbose);
|
|
|
|
cc_off = xml_hash(x_fifo, node->consumer_hash, "consumers", "consumer", cc_off, verbose);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-10-02 21:53:26 +00:00
|
|
|
#define FIFO_API_SYNTAX "list|count [<fifo name>]"
|
2007-10-02 19:58:06 +00:00
|
|
|
SWITCH_STANDARD_API(fifo_api_function)
|
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
fifo_node_t *node;
|
2007-10-29 20:49:22 +00:00
|
|
|
char *data = NULL;
|
2007-10-02 19:58:06 +00:00
|
|
|
int argc = 0;
|
|
|
|
char *argv[5] = { 0 };
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
void *val;
|
|
|
|
const void *var;
|
|
|
|
int x = 0, verbose = 0;
|
|
|
|
|
2008-01-03 21:34:44 +00:00
|
|
|
|
|
|
|
if (!globals.running) {
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
if (!switch_strlen_zero(cmd)) {
|
|
|
|
data = strdup(cmd);
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(data);
|
2007-10-02 19:58:06 +00:00
|
|
|
}
|
|
|
|
|
2007-12-12 03:21:14 +00:00
|
|
|
if (switch_strlen_zero(cmd) || (argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 1 || !argv[0]) {
|
2007-10-02 19:58:06 +00:00
|
|
|
stream->write_function(stream, "%s\n", FIFO_API_SYNTAX);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_mutex_lock(globals.mutex);
|
|
|
|
verbose = !strcasecmp(argv[0], "list_verbose");
|
|
|
|
|
|
|
|
if (!strcasecmp(argv[0], "list") || verbose) {
|
|
|
|
char *xml_text = NULL;
|
|
|
|
switch_xml_t x_report = switch_xml_new("fifo_report");
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(x_report);
|
2007-10-02 19:58:06 +00:00
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
|
|
|
|
switch_hash_this(hi, &var, NULL, &val);
|
|
|
|
node = (fifo_node_t *) val;
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
list_node(node, x_report, &x, verbose);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
list_node(node, x_report, &x, verbose);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
|
|
|
}
|
|
|
|
}
|
2007-11-30 23:45:27 +00:00
|
|
|
xml_text = switch_xml_toxml(x_report, SWITCH_FALSE);
|
2007-12-12 03:21:14 +00:00
|
|
|
switch_assert(xml_text);
|
2007-10-02 19:58:06 +00:00
|
|
|
stream->write_function(stream, "%s\n", xml_text);
|
|
|
|
switch_xml_free(x_report);
|
|
|
|
switch_safe_free(xml_text);
|
|
|
|
|
|
|
|
} else if (!strcasecmp(argv[0], "count")) {
|
|
|
|
if (argc < 2) {
|
|
|
|
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
|
2008-03-19 16:03:51 +00:00
|
|
|
int x = 0;
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_hash_this(hi, &var, NULL, &val);
|
|
|
|
node = (fifo_node_t *) val;
|
2008-03-19 16:03:51 +00:00
|
|
|
len = 0;
|
|
|
|
for (x = 0 ;x < MAX_PRI; x++) {
|
|
|
|
len += switch_queue_size(node->fifo_list[x]);
|
|
|
|
}
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
stream->write_function(stream, "%s:%d:%d:%d\n", (char *)var, node->consumer_count, node->caller_count, len);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!x) {
|
|
|
|
stream->write_function(stream, "none\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
|
2008-03-19 16:03:51 +00:00
|
|
|
int x = 0;
|
|
|
|
len = 0;
|
|
|
|
for (x = 0 ;x < MAX_PRI; x++) {
|
|
|
|
len += switch_queue_size(node->fifo_list[x]);
|
|
|
|
}
|
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
}
|
|
|
|
switch_mutex_lock(node->mutex);
|
|
|
|
stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node->caller_count, len);
|
|
|
|
switch_mutex_unlock(node->mutex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_mutex_unlock(globals.mutex);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
|
|
|
|
{
|
|
|
|
switch_application_interface_t *app_interface;
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_api_interface_t *commands_api_interface;
|
|
|
|
|
|
|
|
|
|
|
|
/* create/register custom event message type */
|
|
|
|
if (switch_event_reserve_subclass(FIFO_EVENT) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!", FIFO_EVENT);
|
|
|
|
return SWITCH_STATUS_TERM;
|
|
|
|
}
|
2007-10-01 20:39:16 +00:00
|
|
|
|
2007-12-18 23:07:48 +00:00
|
|
|
/* Subscribe to presence request events */
|
|
|
|
if (switch_event_bind((char *) modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, pres_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to presence request events!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_core_new_memory_pool(&globals.pool);
|
|
|
|
switch_core_hash_init(&globals.fifo_hash, globals.pool);
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
|
2007-10-01 20:39:16 +00:00
|
|
|
|
|
|
|
/* connect my internal structure to the blank pointer passed to me */
|
|
|
|
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
|
|
|
SWITCH_ADD_APP(app_interface, "fifo", "Park with FIFO", FIFO_DESC, fifo_function, FIFO_USAGE, SAF_NONE);
|
2007-10-02 19:58:06 +00:00
|
|
|
SWITCH_ADD_API(commands_api_interface, "fifo", "Return data about a fifo", fifo_api_function, FIFO_API_SYNTAX);
|
2008-01-03 21:34:44 +00:00
|
|
|
globals.running = 1;
|
2007-10-01 20:39:16 +00:00
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Called when the system shuts down
|
|
|
|
*/
|
|
|
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
|
|
|
|
{
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
void *val, *pop;
|
2007-10-02 19:58:06 +00:00
|
|
|
fifo_node_t *node;
|
2008-01-03 21:34:44 +00:00
|
|
|
switch_memory_pool_t *pool = globals.pool;
|
2008-01-03 22:04:19 +00:00
|
|
|
switch_mutex_t *mutex = globals.mutex;
|
2008-01-03 21:34:44 +00:00
|
|
|
|
2008-01-03 22:04:19 +00:00
|
|
|
switch_mutex_lock(mutex);
|
|
|
|
|
2008-01-03 21:34:44 +00:00
|
|
|
globals.running = 0;
|
2007-10-01 20:39:16 +00:00
|
|
|
/* Cleanup*/
|
|
|
|
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
|
2008-03-19 16:03:51 +00:00
|
|
|
int x = 0 ;
|
2007-10-01 20:39:16 +00:00
|
|
|
switch_hash_this(hi, NULL, NULL, &val);
|
2007-10-02 19:58:06 +00:00
|
|
|
node = (fifo_node_t *) val;
|
2008-03-19 16:03:51 +00:00
|
|
|
for (x = 0; x < MAX_PRI; x++) {
|
|
|
|
while (switch_queue_trypop(node->fifo_list[x], &pop) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
free(pop);
|
|
|
|
}
|
|
|
|
}
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_core_hash_destroy(&node->caller_hash);
|
|
|
|
switch_core_hash_destroy(&node->consumer_hash);
|
2007-10-01 20:39:16 +00:00
|
|
|
}
|
|
|
|
switch_core_hash_destroy(&globals.fifo_hash);
|
2008-01-03 22:04:19 +00:00
|
|
|
memset(&globals, 0, sizeof(globals));
|
|
|
|
switch_mutex_unlock(mutex);
|
2008-01-03 21:34:44 +00:00
|
|
|
switch_core_destroy_memory_pool(&pool);
|
2007-10-01 20:39:16 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2008-02-03 22:14:57 +00:00
|
|
|
* indent-tabs-mode:t
|
2007-10-01 20:39:16 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
|
|
*/
|