Merge branch 'master' of git.freeswitch.org:freeswitch

This commit is contained in:
Moises Silva committed 2010-10-01 07:07:12 -04:00
commit 588eea410f
325 files changed
+24933 -4354

No files matched your search

@@ -1259,7 +1259,7 @@ static switch_status_t load_config(void)
if (!strcasecmp(var, "debug")) {
globals.debug = atoi(val);
} else if (!strcasecmp(var, "odbc-dsn")) {
globals.odbc_dsn = strdup(switch_xml_attr(param, "odbc-dsn"));
globals.odbc_dsn = strdup(val);
if (!zstr(globals.odbc_dsn)) {
if ((globals.odbc_user = strchr(globals.odbc_dsn, ':'))) {
@@ -1498,7 +1498,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* Update Agents Items */
/* Do not remove uuid of the agent if we are a standby agent */
sql = switch_mprintf("UPDATE agents SET %q last_bridge_end = %ld, talk_time = talk_time + (%ld-last_bridge_start) WHERE name = '%q' AND system = '%q';"
sql = switch_mprintf("UPDATE agents SET %s last_bridge_end = %ld, talk_time = talk_time + (%ld-last_bridge_start) WHERE name = '%q' AND system = '%q';"
, (strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)?"uuid = '',":""), (long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL), h->agent_name, h->agent_system);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@@ -2675,9 +2675,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
{
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_status_t status;
memset(&globals, 0, sizeof(globals));
globals.pool = pool;
@@ -2685,11 +2683,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
switch_core_hash_init(&globals.queue_hash, globals.pool);
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
if ((status = load_config()) != SWITCH_STATUS_SUCCESS) {
return status;
}
switch_mutex_lock(globals.mutex);
globals.running = 1;
switch_mutex_unlock(globals.mutex);
load_config();
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
if (!AGENT_DISPATCH_THREAD_STARTED) {
cc_agent_dispatch_thread_start();
@@ -135,7 +135,7 @@ SWITCH_STANDARD_API(nat_map_function)
switch_bool_t sticky = SWITCH_FALSE;
if (!cmd) {
goto error;
goto usage;
}
if (!switch_nat_is_initialized()) {
@@ -147,9 +147,8 @@ SWITCH_STANDARD_API(nat_map_function)
switch_assert(mydata);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 1) {
goto error;
goto usage;
}
if (argv[0] && switch_stristr("status", argv[0])) {
tmp = switch_nat_status();
@@ -197,6 +196,10 @@ SWITCH_STANDARD_API(nat_map_function)
error:
stream->write_function(stream, "false");
goto ok;
usage:
stream->write_function(stream, "USAGE: nat_map [status|reinit|republish] | [add|del] <port> [tcp|udp] [sticky]");
ok:
@@ -605,11 +608,12 @@ SWITCH_STANDARD_API(in_group_function)
SWITCH_STANDARD_API(user_data_function)
{
switch_xml_t x_domain, xml = NULL, x_user = NULL, x_param, x_params;
switch_xml_t x_domain, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
int argc;
char *mydata = NULL, *argv[3], *key = NULL, *type = NULL, *user, *domain;
char delim = ' ';
const char *container = "params", *elem = "param";
const char *result = NULL;
switch_event_t *params = NULL;
if (zstr(cmd) || !(mydata = strdup(cmd))) {
@@ -637,10 +641,10 @@ SWITCH_STANDARD_API(user_data_function)
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "type", type);
if (key && type && switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, NULL, params) == SWITCH_STATUS_SUCCESS) {
if (key && type && switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, params) == SWITCH_STATUS_SUCCESS) {
if (!strcmp(type, "attr")) {
const char *attr = switch_xml_attr_soft(x_user, key);
stream->write_function(stream, "%s", attr);
result = attr;
goto end;
}
@@ -649,33 +653,45 @@ SWITCH_STANDARD_API(user_data_function)
elem = "variable";
}
if ((x_params = switch_xml_child(x_user, container))) {
for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val && !strcasecmp(var, key)) {
stream->write_function(stream, "%s", val);
goto end;
}
}
}
if ((x_params = switch_xml_child(x_domain, container))) {
for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val && !strcasecmp(var, key)) {
stream->write_function(stream, "%s", val);
goto end;
result = val;
}
}
}
if (x_group && (x_params = switch_xml_child(x_group, container))) {
for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val && !strcasecmp(var, key)) {
result = val;
}
}
}
if ((x_params = switch_xml_child(x_user, container))) {
for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val && !strcasecmp(var, key)) {
result = val;
}
}
}
}
end:
if (result) {
stream->write_function(stream, "%s", result);
}
switch_xml_free(xml);
switch_safe_free(mydata);
switch_event_destroy(&params);
@@ -1049,7 +1065,7 @@ SWITCH_STANDARD_API(url_encode_function)
int len = 0;
if (!zstr(cmd)) {
len = (strlen(cmd) * 3) + 1;
len = (int)(strlen(cmd) * 3) + 1;
switch_zmalloc(data, len);
switch_url_encode(cmd, data, len);
reply = data;
@@ -1166,17 +1182,18 @@ SWITCH_STANDARD_API(xml_locate_function)
SWITCH_STANDARD_API(reload_acl_function)
{
const char *err;
switch_xml_t xml_root;
if (cmd && !strcmp(cmd, "reloadxml")) {
if ((xml_root = switch_xml_open_root(1, &err))) {
switch_xml_free(xml_root);
}
if (cmd && !strcasecmp(cmd, "reloadxml")) {
stream->write_function(stream, "This option is deprecated, we now always reloadxml.\n");
}
if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) {
switch_load_network_lists(SWITCH_TRUE);
stream->write_function(stream, "+OK acl reloaded\n");
} else {
stream->write_function(stream, "-Error [%s]\n", err);
}
switch_load_network_lists(SWITCH_TRUE);
stream->write_function(stream, "+OK acl reloaded\n");
return SWITCH_STATUS_SUCCESS;
}
@@ -1374,7 +1391,7 @@ SWITCH_STANDARD_API(cond_function)
argc = switch_separate_string(mydata, ':', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc != 3) {
if (! (argc >= 2 && argc <= 3)) {
goto error;
}
@@ -1451,7 +1468,12 @@ SWITCH_STANDARD_API(cond_function)
}
switch_safe_free(s_a);
switch_safe_free(s_b);
stream->write_function(stream, "%s", is_true ? argv[1] : argv[2]);
if ((argc == 2 && !is_true)) {
stream->write_function(stream, "");
} else {
stream->write_function(stream, "%s", is_true ? argv[1] : argv[2]);
}
goto ok;
}
@@ -1720,6 +1742,10 @@ SWITCH_STANDARD_API(load_function)
return SWITCH_STATUS_SUCCESS;
}
if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Reloading XML\n");
}
if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK\n");
} else {
@@ -1814,6 +1840,10 @@ SWITCH_STANDARD_API(reload_function)
stream->write_function(stream, "-ERR unloading module [%s]\n", err);
}
if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Reloading XML\n");
}
if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK module loaded\n");
} else {
@@ -1825,13 +1855,9 @@ SWITCH_STANDARD_API(reload_function)
SWITCH_STANDARD_API(reload_xml_function)
{
const char *err;
switch_xml_t xml_root;
if ((xml_root = switch_xml_open_root(1, &err))) {
switch_xml_free(xml_root);
}
const char *err = "";
switch_xml_reload(&err);
stream->write_function(stream, "+OK [%s]\n", err);
return SWITCH_STATUS_SUCCESS;
@@ -3022,7 +3048,7 @@ SWITCH_STANDARD_API(xml_wrap_api_function)
if (mystream.data) {
if (encoded) {
elen = (int) strlen(mystream.data) * 3;
elen = (int) strlen(mystream.data) * 3 + 1;
edata = malloc(elen);
switch_assert(edata != NULL);
memset(edata, 0, elen);
@@ -4040,7 +4066,7 @@ SWITCH_STANDARD_API(uuid_dump_function)
return SWITCH_STATUS_SUCCESS;
}
#define GLOBAL_SETVAR_SYNTAX "<var> <value> [<value2>]"
#define GLOBAL_SETVAR_SYNTAX "<var>=<value> [=<value2>]"
SWITCH_STANDARD_API(global_setvar_function)
{
char *mycmd = NULL, *argv[3] = { 0 };
@@ -4192,7 +4218,7 @@ SWITCH_STANDARD_API(escape_function)
return SWITCH_STATUS_SUCCESS;
}
len = strlen(cmd) * 2;
len = (int)strlen(cmd) * 2;
mycmd = malloc(len);
stream->write_function(stream, "%s", switch_escape_string(cmd, mycmd, len));
@@ -4551,7 +4577,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "originate", "Originate a Call", originate_function, ORIGINATE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "pause", "Pause", pause_function, PAUSE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "regex", "Eval a regex", regex_function, "<data>|<pattern>[|<subst string>]");
SWITCH_ADD_API(commands_api_interface, "reloadacl", "Reload ACL", reload_acl_function, "[reloadxml]");
SWITCH_ADD_API(commands_api_interface, "reloadacl", "Reload ACL", reload_acl_function, "");
SWITCH_ADD_API(commands_api_interface, "reload", "Reload Module", reload_function, UNLOAD_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "reloadxml", "Reload XML", reload_xml_function, "");
SWITCH_ADD_API(commands_api_interface, "replace", "replace a string", replace_function, "<data>|<string1>|<string2>");
@@ -99,7 +99,7 @@ typedef enum {
CALLER_CONTROL_DEAF_MUTE,
CALLER_CONTROL_ENERGY_UP,
CALLER_CONTROL_ENERGY_EQU_CONF,
CALLER_CONTROL_ENERGEY_DN,
CALLER_CONTROL_ENERGY_DN,
CALLER_CONTROL_VOL_TALK_UP,
CALLER_CONTROL_VOL_TALK_ZERO,
CALLER_CONTROL_VOL_TALK_DN,
@@ -121,7 +121,7 @@ typedef struct conference_member conference_member_t;
struct call_list {
char *string;
int itteration;
int iteration;
struct call_list *next;
};
typedef struct call_list call_list_t;
@@ -717,7 +717,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
if (call_list) {
char saymsg[1024];
switch_snprintf(saymsg, sizeof(saymsg), "Auto Calling %d parties", call_list->itteration);
switch_snprintf(saymsg, sizeof(saymsg), "Auto Calling %d parties", call_list->iteration);
conference_member_say(member, saymsg, 0);
} else {
if (zstr(conference->special_announce)) {
@@ -1012,7 +1012,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
uint8_t *file_frame;
uint8_t *async_file_frame;
int16_t *bptr;
int x = 0;
uint32_t x = 0;
int32_t z = 0;
int member_score_sum = 0;
int divisor = 0;
@@ -2298,7 +2298,7 @@ static caller_control_fn_table_t ccfntbl[] = {
{"deaf mute", "*", CALLER_CONTROL_DEAF_MUTE, conference_loop_fn_deafmute_toggle},
{"energy up", "9", CALLER_CONTROL_ENERGY_UP, conference_loop_fn_energy_up},
{"energy equ", "8", CALLER_CONTROL_ENERGY_EQU_CONF, conference_loop_fn_energy_equ_conf},
{"energy dn", "7", CALLER_CONTROL_ENERGEY_DN, conference_loop_fn_energy_dn},
{"energy dn", "7", CALLER_CONTROL_ENERGY_DN, conference_loop_fn_energy_dn},
{"vol talk up", "3", CALLER_CONTROL_VOL_TALK_UP, conference_loop_fn_volume_talk_up},
{"vol talk zero", "2", CALLER_CONTROL_VOL_TALK_ZERO, conference_loop_fn_volume_talk_zero},
{"vol talk dn", "1", CALLER_CONTROL_VOL_TALK_DN, conference_loop_fn_volume_talk_dn},
@@ -3733,7 +3733,7 @@ static switch_status_t conf_api_sub_list(conference_obj_t *conference, switch_st
static switch_xml_t add_x_tag(switch_xml_t x_member, const char *name, const char *value, int off)
{
switch_size_t dlen = strlen(value) * 3;
switch_size_t dlen = strlen(value) * 3 + 1;
char *data;
switch_xml_t x_tag;
@@ -5199,9 +5199,9 @@ SWITCH_STANDARD_APP(conference_auto_function)
np->string = switch_core_session_strdup(session, data);
if (call_list) {
np->next = call_list;
np->itteration = call_list->itteration + 1;
np->iteration = call_list->iteration + 1;
} else {
np->itteration = 1;
np->iteration = 1;
}
call_list = np;
}
@@ -393,7 +393,7 @@ static dir_profile_t *load_profile(const char *profile_name)
profile_set_config(profile);
/* Add the params to the event structure */
count = switch_event_import_xml(switch_xml_child(x_profile, "param"), "name", "value", &event);
count = (int)switch_event_import_xml(switch_xml_child(x_profile, "param"), "name", "value", &event);
if (switch_xml_config_parse_event(event, count, SWITCH_FALSE, profile->config) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to process configuration\n");
@@ -611,7 +611,7 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
}
if (strlen(cbr->digits) < sizeof(cbr->digits) - 2) {
int at = strlen(cbr->digits);
int at = (int)strlen(cbr->digits);
cbr->digits[at++] = dtmf->digit;
cbr->digits[at] = '\0';
} else {
@@ -649,25 +649,25 @@ static switch_status_t listen_entry(switch_core_session_t *session, dir_profile_
if (zstr_buf(buf)) {
switch_snprintf(macro, sizeof(macro), "phrase:%s:%d", DIR_RESULT_ITEM, cbt->want + 1);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0);
}
if (!zstr_buf(recorded_name) && zstr_buf(buf)) {
switch_ivr_read(session, 0, 1, recorded_name, NULL, buf, sizeof(buf), 1, profile->terminator_key);
switch_ivr_read(session, 0, 1, recorded_name, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0);
}
if (zstr_buf(recorded_name) && zstr_buf(buf)) {
switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", DIR_RESULT_SAY_NAME, cbt->fullname);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0);
}
if (cbt->exten_visible && zstr_buf(buf)) {
switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", DIR_RESULT_AT, cbt->extension);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0);
}
if (zstr_buf(buf)) {
switch_snprintf(macro, sizeof(macro), "phrase:%s:%c,%c,%c,%c", DIR_RESULT_MENU, *profile->select_name_key, *profile->next_key, *profile->prev_key,
*profile->new_search_key);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), profile->digit_timeout, profile->terminator_key);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), profile->digit_timeout, profile->terminator_key, 0);
}
if (!zstr_buf(buf)) {
@@ -884,6 +884,18 @@ SWITCH_STANDARD_APP(directory_function)
if (strcasecmp(profile->search_order, "last_name")) {
s_param.search_by_last_name = 0;
}
{
const char *var_search_order = switch_channel_get_variable(channel, "directory_search_order");
if (var_search_order) {
if (!strcasecmp(var_search_order, "first_name")) {
s_param.search_by_last_name = 0;
} else {
s_param.search_by_last_name = 1;
}
}
}
attempts = profile->max_menu_attempt;
s_param.try_again = 1;
while (switch_channel_ready(channel) && (s_param.try_again && attempts-- > 0)) {
+26 -6
View File
@@ -1712,10 +1712,11 @@ SWITCH_STANDARD_APP(att_xfer_function)
SWITCH_STANDARD_APP(read_function)
{
char *mydata;
char *argv[6] = { 0 };
char *argv[7] = { 0 };
int argc;
int32_t min_digits = 0;
int32_t max_digits = 0;
uint32_t digit_timeout = 0;
int timeout = 1000;
char digit_buffer[128] = "";
const char *prompt_audio_file = NULL;
@@ -1751,6 +1752,13 @@ SWITCH_STANDARD_APP(read_function)
valid_terminators = argv[5];
}
if (argc > 6) {
digit_timeout = atoi(argv[6]);
if (digit_timeout < 0) {
digit_timeout = 0;
}
}
if (min_digits <= 1) {
min_digits = 1;
}
@@ -1767,17 +1775,19 @@ SWITCH_STANDARD_APP(read_function)
valid_terminators = "#";
}
switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name, digit_buffer, sizeof(digit_buffer), timeout, valid_terminators);
switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name, digit_buffer, sizeof(digit_buffer), timeout, valid_terminators,
digit_timeout);
}
SWITCH_STANDARD_APP(play_and_get_digits_function)
{
char *mydata;
char *argv[9] = { 0 };
char *argv[10] = { 0 };
int argc;
int32_t min_digits = 0;
int32_t max_digits = 0;
int32_t max_tries = 0;
uint32_t digit_timeout = 0;
int timeout = 1000;
char digit_buffer[128] = "";
const char *prompt_audio_file = NULL;
@@ -1827,6 +1837,14 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
digits_regex = argv[8];
}
if (argc > 9) {
digit_timeout = atoi(argv[9]);
if (digit_timeout < 0) {
digit_timeout = 0;
}
}
if (min_digits <= 1) {
min_digits = 1;
}
@@ -1844,7 +1862,7 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
}
switch_play_and_get_digits(session, min_digits, max_digits, max_tries, timeout, valid_terminators,
prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer), digits_regex);
prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer), digits_regex, digit_timeout);
}
#define SAY_SYNTAX "<module_name> <say_type> <say_method> [<say_gender>] <text>"
@@ -3367,9 +3385,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "endless_playback", "Playback File Endlessly", "Endlessly Playback a file to the channel",
endless_playback_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "att_xfer", "Attended Transfer", "Attended Transfer", att_xfer_function, "<channel_url>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function, "<min> <max> <file> <var_name> <timeout> <terminators>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function,
"<min> <max> <file> <var_name> <timeout> <terminators> <digit_timeout>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "play_and_get_digits", "Play and get Digits", "Play and get Digits",
play_and_get_digits_function, "<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp>", SAF_NONE);
play_and_get_digits_function,
"<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp> [<digit_timeout>]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, "<path> [+<timeout>]", SAF_MEDIA_TAP);
SWITCH_ADD_APP(app_interface, "record", "Record File", "Record a file from the channels input", record_function,
+35 -38
View File
@@ -439,7 +439,7 @@ static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input,
#define check_string(s) if (!zstr(s) && !strcasecmp(s, "undef")) { s = NULL; }
static int node_consumer_wait_count(fifo_node_t *node)
static int node_caller_count(fifo_node_t *node)
{
int i, len = 0;
@@ -458,7 +458,7 @@ static void node_remove_uuid(fifo_node_t *node, const char *uuid)
fifo_queue_popfly(node->fifo_list[i], uuid);
}
if (!node_consumer_wait_count(node)) {
if (!node_caller_count(node)) {
node->start_waiting = 0;
}
@@ -513,7 +513,6 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session
if (match_key(caller_exit_key, *buf)) {
cd->abort = 1;
return SWITCH_STATUS_FALSE;
switch_channel_set_variable(channel, "fifo_caller_exit_key", (char *)buf);
}
cd->next = switch_epoch_time_now(NULL) + cd->freq;
cd->index++;
@@ -875,7 +874,7 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses
char *sql;
switch_event_t *event;
switch_channel_clear_app_flag(consumer_channel, FIFO_APP_BRIDGE_TAG);
switch_channel_clear_app_flag_key(__FILE__, consumer_channel, FIFO_APP_BRIDGE_TAG);
switch_channel_set_variable(consumer_channel, "fifo_bridged", NULL);
ts = switch_micro_time_now();
@@ -989,7 +988,7 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_
goto end;
}
switch_channel_set_app_flag(consumer_channel, FIFO_APP_BRIDGE_TAG);
switch_channel_set_app_flag_key(__FILE__, consumer_channel, FIFO_APP_BRIDGE_TAG);
switch_channel_set_variable(consumer_channel, "fifo_bridged", "true");
switch_channel_set_variable(consumer_channel, "fifo_manual_bridge", "true");
@@ -1683,7 +1682,7 @@ static void find_consumers(fifo_node_t *node)
switch(node->outbound_strategy) {
case NODE_STRATEGY_ENTERPRISE:
{
int need = node_consumer_wait_count(node);
int need = node_caller_count(node);
if (node->outbound_per_cycle && node->outbound_per_cycle < need) {
need = node->outbound_per_cycle;
@@ -1753,7 +1752,7 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
if ((node = (fifo_node_t *) val)) {
if (node->outbound_priority == 0) node->outbound_priority = 5;
if (node->has_outbound && node->ready && !node->busy && node->outbound_priority == cur_priority) {
ppl_waiting = node_consumer_wait_count(node);
ppl_waiting = node_caller_count(node);
consumer_total = node->consumer_count;
idle_consumers = node_idle_consumers(node);
@@ -1831,7 +1830,7 @@ static void check_cancel(fifo_node_t *node)
return;
}
ppl_waiting = node_consumer_wait_count(node);
ppl_waiting = node_caller_count(node);
if (node->ring_consumer_count > 0 && ppl_waiting < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Outbound call count (%d) exceeds required value for queue %s (%d), "
@@ -1855,7 +1854,7 @@ static void send_presence(fifo_node_t *node)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "park");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", node->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", node->name);
if ((wait_count = node_consumer_wait_count(node)) > 0) {
if ((wait_count = node_caller_count(node)) > 0) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Active (%d waiting)", wait_count);
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Idle");
@@ -1990,6 +1989,11 @@ static void dec_use_count(switch_core_session_t *session, switch_bool_t send_eve
if ((outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid"))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s untracking call on uuid %s!\n", switch_channel_get_name(channel), outbound_id);
sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(session));
fifo_execute_sql(sql, globals.sql_mutex);
switch_safe_free(sql);
del_bridge_call(outbound_id);
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'",
now, now, outbound_id);
@@ -2043,7 +2047,7 @@ SWITCH_STANDARD_APP(fifo_track_call_function)
add_bridge_call(data);
switch_channel_set_app_flag(channel, FIFO_APP_TRACKING);
switch_channel_set_app_flag_key(__FILE__, channel, FIFO_APP_TRACKING);
switch_channel_set_variable(channel, "fifo_outbound_uuid", data);
switch_channel_set_variable(channel, "fifo_track_call", "true");
@@ -2296,7 +2300,6 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_answer(channel);
switch_thread_rwlock_wrlock(node->rwlock);
node->caller_count++;
if ((pri = switch_channel_get_variable(channel, "fifo_priority"))) {
p = atoi(pri);
@@ -2306,7 +2309,7 @@ SWITCH_STANDARD_APP(fifo_function)
p = MAX_PRI - 1;
}
if (!node_consumer_wait_count(node)) {
if (!node_caller_count(node)) {
node->start_waiting = switch_micro_time_now();
}
@@ -2343,7 +2346,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_set_variable(channel, "fifo_timestamp", date);
switch_channel_set_variable(channel, "fifo_serviced_uuid", NULL);
switch_channel_set_app_flag(channel, FIFO_APP_BRIDGE_TAG);
switch_channel_set_app_flag_key(__FILE__, channel, FIFO_APP_BRIDGE_TAG);
if (chime_list) {
char *list_dup = switch_core_session_strdup(session, chime_list);
@@ -2416,10 +2419,10 @@ SWITCH_STANDARD_APP(fifo_function)
}
}
switch_channel_clear_app_flag(channel, FIFO_APP_BRIDGE_TAG);
abort:
switch_channel_clear_app_flag_key(__FILE__, channel, FIFO_APP_BRIDGE_TAG);
abort:
fifo_caller_del(switch_core_session_get_uuid(session));
if (!aborted && switch_channel_ready(channel)) {
@@ -2442,7 +2445,6 @@ SWITCH_STANDARD_APP(fifo_function)
switch_mutex_lock(globals.mutex);
switch_thread_rwlock_wrlock(node->rwlock);
node_remove_uuid(node, uuid);
node->caller_count--;
switch_thread_rwlock_unlock(node->rwlock);
send_presence(node);
check_cancel(node);
@@ -2583,7 +2585,7 @@ SWITCH_STANDARD_APP(fifo_function)
continue;
}
if ((waiting = node_consumer_wait_count(node))) {
if ((waiting = node_caller_count(node))) {
if (!importance || node->importance > importance) {
if (strat == STRAT_WAITING_LONGER) {
@@ -2671,7 +2673,7 @@ SWITCH_STANDARD_APP(fifo_function)
}
}
if (pop && !node_consumer_wait_count(node)) {
if (pop && !node_caller_count(node)) {
switch_thread_rwlock_wrlock(node->rwlock);
node->start_waiting = 0;
switch_thread_rwlock_unlock(node->rwlock);
@@ -2775,7 +2777,8 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_set_flag(other_channel, CF_BREAK);
while (switch_channel_ready(channel) && switch_channel_ready(other_channel) && switch_channel_test_app_flag(other_channel, FIFO_APP_BRIDGE_TAG)) {
while (switch_channel_ready(channel) && switch_channel_ready(other_channel) &&
switch_channel_test_app_flag(other_channel, FIFO_APP_BRIDGE_TAG)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
@@ -2787,9 +2790,6 @@ SWITCH_STANDARD_APP(fifo_function)
const char *arg = switch_channel_get_variable(other_channel, "current_application_data");
switch_caller_extension_t *extension = NULL;
switch_thread_rwlock_wrlock(node->rwlock);
node->caller_count--;
switch_thread_rwlock_unlock(node->rwlock);
send_presence(node);
check_cancel(node);
@@ -2955,9 +2955,6 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_set_variable(other_channel, "fifo_status", "DONE");
switch_channel_set_variable(other_channel, "fifo_timestamp", date);
switch_thread_rwlock_wrlock(node->rwlock);
node->caller_count--;
switch_thread_rwlock_unlock(node->rwlock);
send_presence(node);
check_cancel(node);
switch_core_session_rwunlock(other_session);
@@ -3070,7 +3067,7 @@ SWITCH_STANDARD_APP(fifo_function)
done:
switch_mutex_lock(globals.mutex);
if (node && node->ready == FIFO_DELAY_DESTROY && node->consumer_count == 0 && node->caller_count == 0) {
if (node && node->ready == FIFO_DELAY_DESTROY && node->consumer_count == 0 && node_caller_count(node) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_thread_rwlock_wrlock(node->rwlock);
@@ -3085,7 +3082,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_mutex_unlock(globals.mutex);
switch_channel_clear_app_flag(channel, FIFO_APP_BRIDGE_TAG);
switch_channel_clear_app_flag_key(__FILE__, channel, FIFO_APP_BRIDGE_TAG);
switch_core_media_bug_resume(session);
@@ -3505,9 +3502,9 @@ static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int ve
switch_xml_set_attr_d(x_fifo, "name", node->name);
switch_snprintf(tmp, sizeof(buffer), "%d", node->consumer_count);
switch_xml_set_attr_d(x_fifo, "consumer_count", tmp);
switch_snprintf(tmp, sizeof(buffer), "%d", node->caller_count);
switch_snprintf(tmp, sizeof(buffer), "%d", node_caller_count(node));
switch_xml_set_attr_d(x_fifo, "caller_count", tmp);
switch_snprintf(tmp, sizeof(buffer), "%d", node_consumer_wait_count(node));
switch_snprintf(tmp, sizeof(buffer), "%d", node_caller_count(node));
switch_xml_set_attr_d(x_fifo, "waiting_count", tmp);
switch_snprintf(tmp, sizeof(buffer), "%u", node->importance);
switch_xml_set_attr_d(x_fifo, "importance", tmp);
@@ -3569,7 +3566,7 @@ void node_dump(switch_stream_handle_t *stream)
node->outbound_priority,
node->busy,
node->ready,
node_consumer_wait_count(node)
node_caller_count(node)
);
}
@@ -3687,9 +3684,9 @@ SWITCH_STANDARD_API(fifo_api_function)
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;
len = node_consumer_wait_count(node);
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
stream->write_function(stream, "%s:%d:%d:%d\n", (char *) var, node->consumer_count, node->caller_count, len);
stream->write_function(stream, "%s:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), len);
switch_thread_rwlock_unlock(node->rwlock);
x++;
}
@@ -3698,9 +3695,9 @@ SWITCH_STANDARD_API(fifo_api_function)
stream->write_function(stream, "none\n");
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_consumer_wait_count(node);
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node->caller_count, len);
stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), len);
switch_thread_rwlock_unlock(node->rwlock);
} else {
stream->write_function(stream, "none\n");
@@ -3710,7 +3707,7 @@ SWITCH_STANDARD_API(fifo_api_function)
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;
len = node_consumer_wait_count(node);
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
stream->write_function(stream, "%s:%d\n", (char *) var, node->has_outbound);
switch_thread_rwlock_unlock(node->rwlock);
@@ -3721,7 +3718,7 @@ SWITCH_STANDARD_API(fifo_api_function)
stream->write_function(stream, "none\n");
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_consumer_wait_count(node);
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
stream->write_function(stream, "%s:%d\n", argv[1], node->has_outbound);
switch_thread_rwlock_unlock(node->rwlock);
@@ -4072,7 +4069,7 @@ static switch_status_t load_config(int reload, int del_all)
continue;
}
if (node_consumer_wait_count(node) || node->consumer_count || node_idle_consumers(node)) {
if (node_caller_count(node) || node->consumer_count || node_idle_consumers(node)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s removal delayed, still in use.\n", node->name);
node->ready = FIFO_DELAY_DESTROY;
} else {
+4 -3
View File
@@ -852,7 +852,8 @@ static void do_config(switch_bool_t reload)
const char *username = switch_xml_attr(x_list, "username");
const char *password = switch_xml_attr(x_list, "password");
const char *szinterval = switch_xml_attr(x_list, "interval");
int port = 0, interval = 0;
uint16_t port = 0;
int interval = 0;
limit_remote_t *remote;
switch_threadattr_t *thd_attr = NULL;
@@ -866,7 +867,7 @@ static void do_config(switch_bool_t reload)
}
if (!zstr(szport)) {
port = atoi(szport);
port = (uint16_t)atoi(szport);
}
if (!zstr(szinterval)) {
@@ -949,7 +950,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_hash_shutdown)
/* Kill remote connections, destroy needs a wrlock so we unlock after finding a pointer */
while(remote_clean) {
void *val;
const void *key;
const void *key = NULL;
switch_ssize_t keylen;
limit_remote_t *item = NULL;
+2 -3
View File
@@ -167,7 +167,7 @@ static const char *do_cid(switch_memory_pool_t *pool, const char *cid, const cha
switch_channel_t *channel = NULL;
if (!zstr(cid)) {
len = strlen(cid);
len = (uint32_t)strlen(cid);
} else {
goto done;
}
@@ -506,7 +506,7 @@ static char *expand_digits(switch_memory_pool_t *pool, char *digits, switch_bool
int digit_len;
SWITCH_STANDARD_STREAM(dig_stream);
digit_len = strlen(digits);
digit_len = (int)strlen(digits);
digits_copy = switch_core_strdup(pool, digits);
for (n = digit_len; n > 0; n--) {
@@ -1571,7 +1571,6 @@ SWITCH_STANDARD_APP(lcr_app_function)
switch_channel_set_variable(channel, vbuf, cur_route->carrier_name);
switch_snprintf(vbuf, sizeof(vbuf), "lcr_codec_%d", cnt);
switch_channel_set_variable(channel, vbuf, cur_route->codec);
cnt++;
if (cur_route->next) {
if (routes.profile->enable_sip_redir) {
dig_stream.write_function(&dig_stream, "%s,", cur_route->dialstring);
@@ -419,10 +419,10 @@ static switch_status_t do_billing(switch_core_session_t *session)
billaccount = switch_channel_get_variable(channel, "nibble_account");
if (!zstr(switch_channel_get_variable(channel, "nobal_amt"))) {
nobal_amt = atof(switch_channel_get_variable(channel, "nobal_amt"));
nobal_amt = (float)atof(switch_channel_get_variable(channel, "nobal_amt"));
}
if (!zstr(switch_channel_get_variable(channel, "lowbal_amt"))) {
lowbal_amt = atof(switch_channel_get_variable(channel, "lowbal_amt"));
lowbal_amt = (float)atof(switch_channel_get_variable(channel, "lowbal_amt"));
}
/* Return if there's no billing information on this session */
@@ -549,8 +549,8 @@ static switch_status_t do_config(void)
if (id == -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to add tone_descriptor: %s, tone: %s. (too many tones)\n", name, tone_name);
return SWITCH_STATUS_FALSE;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s, tone: %s(%d)\n", name, tone_name, id);}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s, tone: %s(%d)\n", name, tone_name, id);
/* add elements to tone */
for (element = switch_xml_child(tone, "element"); element; element = switch_xml_next(element)) {
const char *freq1_attr = switch_xml_attr(element, "freq1");
@@ -74,6 +74,8 @@ static struct {
char header[50];
char *prepend_string;
char *spool;
switch_thread_cond_t *cond;
switch_mutex_t *cond_mutex;
} globals;
struct pvt_s {
@@ -118,27 +120,34 @@ static struct {
int thread_running;
} t38_state_list;
static void wake_thread(int force)
{
if (force) {
switch_thread_cond_signal(globals.cond);
return;
}
if (switch_mutex_trylock(globals.cond_mutex) == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(globals.cond);
switch_mutex_unlock(globals.cond_mutex);
}
}
static int add_pvt(pvt_t *pvt)
{
int r = 0;
uint32_t sanity = 50;
switch_mutex_lock(t38_state_list.mutex);
if (!t38_state_list.thread_running) {
launch_timer_thread();
while(--sanity && !t38_state_list.thread_running) {
switch_yield(10000);
}
}
switch_mutex_unlock(t38_state_list.mutex);
if (t38_state_list.thread_running) {
switch_mutex_lock(t38_state_list.mutex);
pvt->next = t38_state_list.head;
t38_state_list.head = pvt;
switch_mutex_unlock(t38_state_list.mutex);
r = 1;
wake_thread(0);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error launching thread\n");
}
return r;
@@ -151,9 +160,9 @@ static int del_pvt(pvt_t *del_pvt)
pvt_t *p, *l = NULL;
int r = 0;
if (!t38_state_list.thread_running) goto end;
switch_mutex_lock(t38_state_list.mutex);
for (p = t38_state_list.head; p; p = p->next) {
if (p == del_pvt) {
if (l) {
@@ -163,34 +172,38 @@ static int del_pvt(pvt_t *del_pvt)
}
p->next = NULL;
r = 1;
goto end;
break;
}
l = p;
}
end:
switch_mutex_unlock(t38_state_list.mutex);
return r;
wake_thread(0);
return r;
}
static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *obj)
{
switch_timer_t timer = { 0 };
pvt_t *pvt;
int samples = 240;
int ms = 30;
int samples = 160;
int ms = 20;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread started.\n");
switch_mutex_lock(t38_state_list.mutex);
t38_state_list.thread_running = 1;
switch_mutex_unlock(t38_state_list.mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FAX timer thread started.\n");
if (switch_core_timer_init(&timer, "soft", ms, samples, NULL) != SWITCH_STATUS_SUCCESS) {
return NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "timer init failed.\n");
goto end;
}
t38_state_list.thread_running = 1;
switch_mutex_lock(globals.cond_mutex);
while(t38_state_list.thread_running) {
@@ -198,7 +211,9 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
if (!t38_state_list.head) {
switch_mutex_unlock(t38_state_list.mutex);
goto end;
switch_thread_cond_wait(globals.cond, globals.cond_mutex);
switch_core_timer_sync(&timer);
continue;
}
for (pvt = t38_state_list.head; pvt; pvt = pvt->next) {
@@ -211,13 +226,20 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
switch_core_timer_next(&timer);
}
switch_mutex_unlock(globals.cond_mutex);
end:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread ended.\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FAX timer thread ended.\n");
switch_mutex_lock(t38_state_list.mutex);
t38_state_list.thread_running = 0;
switch_core_timer_destroy(&timer);
switch_mutex_unlock(t38_state_list.mutex);
if (timer.timer_interface) {
switch_core_timer_destroy(&timer);
}
return NULL;
}
@@ -468,49 +490,61 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
}
break;
case T38_MODE:
if (pvt->t38_state == NULL) {
pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t));
}
if (pvt->t38_state == NULL) {
return SWITCH_STATUS_FALSE;
}
if (pvt->udptl_state == NULL) {
pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t));
}
if (pvt->udptl_state == NULL) {
t38_terminal_free(pvt->t38_state);
pvt->t38_state = NULL;
return SWITCH_STATUS_FALSE;
}
{
switch_core_session_message_t msg = { 0 };
/* add to timer thread processing */
add_pvt(pvt);
if (pvt->t38_state == NULL) {
pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t));
}
if (pvt->t38_state == NULL) {
return SWITCH_STATUS_FALSE;
}
if (pvt->udptl_state == NULL) {
pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t));
}
if (pvt->udptl_state == NULL) {
t38_terminal_free(pvt->t38_state);
pvt->t38_state = NULL;
return SWITCH_STATUS_FALSE;
}
t38 = pvt->t38_state;
t30 = t38_terminal_get_t30_state(t38);
memset(t38, 0, sizeof(t38_terminal_state_t));
if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
return SWITCH_STATUS_FALSE;
}
pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3,
(udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
return SWITCH_STATUS_FALSE;
}
msg.from = __FILE__;
msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
switch_core_session_receive_message(pvt->session, &msg);
t38 = pvt->t38_state;
t30 = t38_terminal_get_t30_state(t38);
/* add to timer thread processing */
if (!add_pvt(pvt)) {
if (channel) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
}
span_log_set_message_handler(&t38->logging, spanfax_log_message);
span_log_set_message_handler(&t30->logging, spanfax_log_message);
memset(t38, 0, sizeof(t38_terminal_state_t));
if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
return SWITCH_STATUS_FALSE;
}
pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3,
(udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
return SWITCH_STATUS_FALSE;
}
span_log_set_message_handler(&t38->logging, spanfax_log_message);
span_log_set_message_handler(&t30->logging, spanfax_log_message);
if (pvt->verbose) {
span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
}
if (pvt->verbose) {
span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
}
}
break;
case T38_GATEWAY_MODE:
if (pvt->t38_gateway_state == NULL) {
@@ -757,9 +791,9 @@ static t38_mode_t negotiate_t38(pvt_t *pvt)
t38_options->T38FaxRateManagement = "transferredTCF";
t38_options->T38FaxMaxBuffer = 2000;
t38_options->T38FaxMaxDatagram = LOCAL_FAX_MAX_DATAGRAM;
if (strcasecmp(t38_options->T38FaxUdpEC, "t38UDPRedundancy") == 0
||
strcasecmp(t38_options->T38FaxUdpEC, "t38UDPFEC") == 0) {
if (!zstr(t38_options->T38FaxUdpEC) &&
(strcasecmp(t38_options->T38FaxUdpEC, "t38UDPRedundancy") == 0 ||
strcasecmp(t38_options->T38FaxUdpEC, "t38UDPFEC") == 0)) {
t38_options->T38FaxUdpEC = "t38UDPRedundancy";
} else {
t38_options->T38FaxUdpEC = NULL;
@@ -818,6 +852,12 @@ static t38_mode_t request_t38(pvt_t *pvt)
insist = globals.enable_t38_insist;
}
if ((t38_options = switch_channel_get_private(channel, "t38_options"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"%s already has T.38 data\n", switch_channel_get_name(channel));
enabled = 0;
}
if (enabled) {
t38_options = switch_core_session_alloc(session, sizeof(*t38_options));
@@ -960,6 +1000,7 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
switch_frame_t write_frame = { 0 };
switch_codec_implementation_t read_impl = { 0 };
int16_t *buf = NULL;
uint32_t req_counter = 0;
switch_core_session_get_read_impl(session, &read_impl);
@@ -1075,10 +1116,11 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
switch_ivr_sleep(session, 250, SWITCH_TRUE, NULL);
/* If you have the means, I highly recommend picking one up. ...*/
request_t38(pvt);
if (pvt->app_mode == FUNCTION_TX) {
req_counter = 100;
} else {
req_counter = 50;
}
while (switch_channel_ready(channel)) {
int tx = 0;
@@ -1122,6 +1164,13 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
break;
case T38_MODE_UNKNOWN:
{
if (req_counter) {
if (!--req_counter) {
/* If you have the means, I highly recommend picking one up. ...*/
request_t38(pvt);
}
}
if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
if (negotiate_t38(pvt) == T38_MODE_NEGOTIATED) {
/* is is safe to call this again, it was already called above in AUDIO_MODE */
@@ -1145,8 +1194,6 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "READ %d udptl bytes\n", read_frame->packetlen);
udptl_rx_packet(pvt->udptl_state, read_frame->packet, read_frame->packetlen);
}
}
continue;
@@ -1282,6 +1329,8 @@ void mod_spandsp_fax_event_handler(switch_event_t *event)
void mod_spandsp_fax_load(switch_memory_pool_t *pool)
{
uint32_t sanity = 200;
memset(&globals, 0, sizeof(globals));
memset(&t38_state_list, 0, sizeof(t38_state_list));
@@ -1289,6 +1338,9 @@ void mod_spandsp_fax_load(switch_memory_pool_t *pool)
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_mutex_init(&globals.cond_mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_thread_cond_create(&globals.cond, globals.pool);
globals.enable_t38 = 1;
globals.total_sessions = 0;
@@ -1301,10 +1353,22 @@ void mod_spandsp_fax_load(switch_memory_pool_t *pool)
strncpy(globals.header, "SpanDSP Fax Header", sizeof(globals.header) - 1);
load_configuration(0);
launch_timer_thread();
while(--sanity && !t38_state_list.thread_running) {
switch_yield(20000);
}
}
void mod_spandsp_fax_shutdown(void)
{
switch_status_t tstatus = SWITCH_STATUS_SUCCESS;
t38_state_list.thread_running = 0;
wake_thread(1);
switch_thread_join(&tstatus, t38_state_list.thread);
memset(&globals, 0, sizeof(globals));
}
@@ -1659,8 +1723,8 @@ static switch_status_t t38_gateway_on_reset(switch_core_session_t *session)
switch_channel_clear_flag(channel, CF_REDIRECT);
if (switch_channel_test_app_flag(channel, CF_APP_TAGGED)) {
switch_channel_clear_app_flag(channel, CF_APP_TAGGED);
if (switch_channel_test_app_flag_key("T38", channel, CF_APP_TAGGED)) {
switch_channel_clear_app_flag_key("T38", channel, CF_APP_TAGGED);
switch_channel_set_state(channel, CS_CONSUME_MEDIA);
} else {
switch_channel_set_state(channel, CS_SOFT_EXECUTE);
@@ -1697,6 +1761,9 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
switch_channel_set_variable(channel, "t38_peer", switch_core_session_get_uuid(other_session));
switch_channel_set_variable(other_channel, "t38_peer", switch_core_session_get_uuid(session));
switch_channel_set_variable(peer ? other_channel : channel, "t38_gateway_format", "audio");
switch_channel_set_variable(peer ? channel : other_channel, "t38_gateway_format", "udptl");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s starting gateway mode to %s\n",
switch_channel_get_name(peer ? channel : other_channel),
@@ -1709,8 +1776,8 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
switch_channel_add_state_handler(channel, &t38_gateway_state_handlers);
switch_channel_add_state_handler(other_channel, &t38_gateway_state_handlers);
switch_channel_set_app_flag(peer ? channel : other_channel, CF_APP_TAGGED);
switch_channel_clear_app_flag(peer ? other_channel : channel, CF_APP_TAGGED);
switch_channel_set_app_flag_key("T38", peer ? channel : other_channel, CF_APP_TAGGED);
switch_channel_clear_app_flag_key("T38", peer ? other_channel : channel, CF_APP_TAGGED);
switch_channel_set_flag(channel, CF_REDIRECT);
switch_channel_set_state(channel, CS_RESET);
+4 -4
View File
@@ -93,7 +93,7 @@ static int encode_length(uint8_t *buf, int *len, int value)
if (value < 0x80) {
/* 1 octet */
buf[(*len)++] = value;
buf[(*len)++] = (uint8_t)value;
return value;
}
if (value < 0x4000) {
@@ -106,7 +106,7 @@ static int encode_length(uint8_t *buf, int *len, int value)
/* Fragmentation */
multiplier = (value < 0x10000) ? (value >> 14) : 4;
/* Set the first 2 bits of the octet */
buf[(*len)++] = 0xC0 | multiplier;
buf[(*len)++] = (uint8_t) (0xC0 | multiplier);
return multiplier << 14;
}
@@ -419,10 +419,10 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int
/* Span is defined as an inconstrained integer, which it dumb. It will only
ever be a small value. Treat it as such. */
buf[len++] = 1;
buf[len++] = span;
buf[len++] = (uint8_t)span;
/* The number of entries is defined as a length, but will only ever be a small
value. Treat it as such. */
buf[len++] = entries;
buf[len++] = (uint8_t)entries;
for (m = 0; m < entries; m++) {
/* Make an XOR'ed entry the maximum length */
limit = (entry + m) & UDPTL_BUF_MASK;
@@ -203,7 +203,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
}
do {
status = switch_ivr_read(session, min, max, prompt, NULL, dtmf_buf, sizeof(dtmf_buf), to, "#");
status = switch_ivr_read(session, min, max, prompt, NULL, dtmf_buf, sizeof(dtmf_buf), to, "#", 0);
} while (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_FALSE);
if (status == SWITCH_STATUS_SUCCESS) {
@@ -824,7 +824,8 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
if (!cc->noexit
&& (dtmf->digit == *cc->profile->delete_file_key || dtmf->digit == *cc->profile->save_file_key
|| dtmf->digit == *cc->profile->prev_msg_key || dtmf->digit == *cc->profile->next_msg_key
|| dtmf->digit == *cc->profile->terminator_key || dtmf->digit == *cc->profile->skip_info_key)) {
|| dtmf->digit == *cc->profile->terminator_key || dtmf->digit == *cc->profile->skip_info_key
|| dtmf->digit == *cc->profile->email_key || dtmf->digit == *cc->profile->forward_key)) {
*cc->buf = dtmf->digit;
return SWITCH_STATUS_BREAK;
}
@@ -1421,6 +1422,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
char cid_buf[1024] = "";
if (switch_channel_ready(channel)) {
const char *vm_announce_cid = NULL;
switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", cbt->cid_number, cbt->cid_name);
@@ -1428,7 +1430,13 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
msg.string_arg = cid_buf;
msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
switch_core_session_receive_message(session, &msg);
if (!zstr(cbt->cid_number) && (vm_announce_cid = switch_channel_get_variable(channel, "vm_announce_cid"))) {
switch_ivr_play_file(session, NULL, vm_announce_cid, NULL);
switch_ivr_sleep(session, 500, SWITCH_TRUE, NULL);
switch_ivr_say(session, cbt->cid_number, NULL, "name_spelled", "pronounced", NULL, NULL);
}
args.input_callback = cancel_on_dtmf;
switch_snprintf(key_buf, sizeof(key_buf), "%s:%s:%s:%s:%s:%s%s%s", profile->listen_file_key, profile->save_file_key,
@@ -1523,7 +1531,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
vm_cc[0] = '\0';
TRY_CODE(switch_ivr_read
(session, 0, sizeof(vm_cc), macro_buf, NULL, vm_cc, sizeof(vm_cc), profile->digit_timeout, profile->terminator_key));
(session, 0, sizeof(vm_cc), macro_buf, NULL, vm_cc, sizeof(vm_cc), profile->digit_timeout, profile->terminator_key, 0));
cmd = switch_core_session_sprintf(session, "%s@%s %s %s '%s'", vm_cc, cbt->domain, new_file_path, cbt->cid_number, cbt->cid_name);
@@ -1987,7 +1995,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
switch_xml_t xx_user, xx_domain, xx_domain_root;
switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", VM_ENTER_PASS_MACRO, profile->terminator_key);
TRY_CODE(switch_ivr_read(session, 0, 255, macro, NULL, buf, sizeof(buf), 10000, profile->terminator_key));
TRY_CODE(switch_ivr_read(session, 0, 255, macro, NULL, buf, sizeof(buf), 10000, profile->terminator_key, 0));
sql = switch_mprintf("update voicemail_prefs set password='%s' where username='%s' and domain='%s'", buf, myid, domain_name);
vm_execute_sql(profile, sql, profile->mutex);
switch_safe_free(file_path);
@@ -2686,23 +2694,29 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
} else {
domain = user;
}
if ((profile_name = strchr(domain, '@'))) {
*profile_name++ = '\0';
} else {
profile_name = domain;
if ((profile_name = strchr(domain, '@'))) {
*profile_name++ = '\0';
} else {
profile_name = domain;
}
}
if (switch_stristr("group=", user)) {
user += 6;
isgroup++;
} else if (user == domain) {
} else if (switch_stristr("domain=", user)) {
user += 7;
domain = user;
profile_name = domain;
isall++;
}
if (zstr(domain)) {
domain = switch_core_get_variable("domain");
profile_name = domain;
}
if (!(user && domain)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid syntax [%s][%s]\n", switch_str_nil(user), switch_str_nil(domain));
status = SWITCH_STATUS_FALSE;
@@ -2746,6 +2760,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain);
status = SWITCH_STATUS_FALSE;
switch_event_destroy(&my_params);
profile_rwunlock(profile);
goto end;
}
@@ -3164,7 +3179,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
switch_event_destroy(&vars);
if (status == SWITCH_STATUS_SUCCESS) {
if ((vm_cc = switch_channel_get_variable(channel, "vm_cc"))) {
char *cmd = switch_core_session_sprintf(session, "%s %s %s %s %s@%s %s",
char *cmd = switch_core_session_sprintf(session, "%s %s %s '%s' %s@%s %s",
vm_cc, file_path, caller_id_number, caller_id_name, id, domain_name, read_flags);
if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
@@ -3670,7 +3685,7 @@ static int web_callback(void *pArg, int argc, char **argv, char **columnNames)
const char *fmt = "%a, %e %b %Y %T %z";
char heard[80];
char title_b4[128] = "";
char title_aft[128 * 3] = "";
char title_aft[128 * 3 + 1] = "";
if (argc > 0) {
l_created = switch_time_make(atol(argv[0]), 0);
@@ -3961,7 +3976,7 @@ static void do_web(vm_profile_t *profile, const char *user_in, const char *domai
}
}
#define VM_INJECT_USAGE "[group=]<box> <sound_file> [<cid_num>] [<cid_name>]"
#define VM_INJECT_USAGE "[group=<group>[@domain]|domain=<domain>|<box>[@<domain>]] <sound_file> [<cid_num>] [<cid_name>]"
SWITCH_STANDARD_API(voicemail_inject_api_function)
{
if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
+1 -1
View File
@@ -2724,7 +2724,7 @@ static switch_status_t recog_asr_open(switch_asr_handle_t *ah, const char *codec
name++;
name = switch_core_sprintf(ah->memory_pool, "%s ASR-%d", name, speech_channel_number);
} else {
name = switch_core_sprintf(ah->memory_pool, "ASR-%d", name, speech_channel_number);
name = switch_core_sprintf(ah->memory_pool, "ASR-%d", speech_channel_number);
}
/* Allocate the channel */
+111 -57
View File
@@ -98,11 +98,8 @@ typedef enum {
AMR_DTX_ENABLED
} amr_dtx_t;
struct amr_context {
void *encoder_state;
void *decoder_state;
switch_byte_t enc_modes;
switch_byte_t enc_mode;
/*! \brief Various codec settings */
struct amr_codec_settings {
int dtx_mode;
uint32_t change_period;
switch_byte_t max_ptime;
@@ -110,6 +107,24 @@ struct amr_context {
switch_byte_t channels;
switch_byte_t flags;
};
typedef struct amr_codec_settings amr_codec_settings_t;
static amr_codec_settings_t default_codec_settings = {
/*.dtx_mode */ AMR_DTX_ENABLED,
/*.change_period */ 0,
/*.max_ptime */ 0,
/*.ptime */ 0,
/*.channels */ 0,
/*.flags */ 0,
};
struct amr_context {
void *encoder_state;
void *decoder_state;
switch_byte_t enc_modes;
switch_byte_t enc_mode;
};
#define AMR_DEFAULT_BITRATE AMR_BITRATE_1220
@@ -117,6 +132,88 @@ static struct {
switch_byte_t default_bitrate;
} globals;
static switch_status_t switch_amr_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
{
if (codec_fmtp) {
amr_codec_settings_t *codec_settings = NULL;
if (codec_fmtp->private_info) {
codec_settings = codec_fmtp->private_info;
memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
}
if (fmtp) {
int x, argc;
char *argv[10];
char *fmtp_dup = strdup(fmtp);
switch_assert(fmtp_dup);
argc = switch_separate_string((char *) fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
switch_assert(data);
while (*data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
/*
if (!strcasecmp(data, "bitrate")) {
bit_rate = atoi(arg);
}
*/
if (codec_settings) {
if (!strcasecmp(data, "octet-align")) {
if (atoi(arg)) {
switch_set_flag(codec_settings, AMR_OPT_OCTET_ALIGN);
}
} else if (!strcasecmp(data, "mode-change-neighbor")) {
if (atoi(arg)) {
switch_set_flag(codec_settings, AMR_OPT_MODE_CHANGE_NEIGHBOR);
}
} else if (!strcasecmp(data, "crc")) {
if (atoi(arg)) {
switch_set_flag(codec_settings, AMR_OPT_CRC);
}
} else if (!strcasecmp(data, "robust-sorting")) {
if (atoi(arg)) {
switch_set_flag(codec_settings, AMR_OPT_ROBUST_SORTING);
}
} else if (!strcasecmp(data, "interveaving")) {
if (atoi(arg)) {
switch_set_flag(codec_settings, AMR_OPT_INTERLEAVING);
}
} else if (!strcasecmp(data, "mode-change-period")) {
codec_settings->change_period = atoi(arg);
} else if (!strcasecmp(data, "ptime")) {
codec_settings->ptime = (switch_byte_t) atoi(arg);
} else if (!strcasecmp(data, "channels")) {
codec_settings->channels = (switch_byte_t) atoi(arg);
} else if (!strcasecmp(data, "maxptime")) {
codec_settings->max_ptime = (switch_byte_t) atoi(arg);
} else if (!strcasecmp(data, "mode-set")) {
int y, m_argc;
char *m_argv[7];
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
for (y = 0; y < m_argc; y++) {
codec_settings->enc_modes |= (1 << atoi(m_argv[y]));
}
} else if (!strcasecmp(data, "dtx")) {
codec_settings->dtx_mode = (atoi(arg)) ? AMR_DTX_ENABLED : AMR_DTX_DISABLED;
}
}
}
}
free(fmtp_dup);
}
//codec_fmtp->bits_per_second = bit_rate;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
#endif
static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
@@ -128,7 +225,10 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
}
return SWITCH_STATUS_SUCCESS;
#else
struct amr_context *context = NULL;
switch_codec_fmtp_t codec_fmtp;
amr_codec_settings_t amr_codec_settings;
int encoding, decoding;
int x, i, argc;
char *argv[10];
@@ -141,58 +241,9 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
return SWITCH_STATUS_FALSE;
} else {
context->dtx_mode = AMR_DTX_ENABLED;
if (codec->fmtp_in) {
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
while (*data && *data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (!strcasecmp(data, "octet-align")) {
if (atoi(arg)) {
switch_set_flag(context, AMR_OPT_OCTET_ALIGN);
}
} else if (!strcasecmp(data, "mode-change-neighbor")) {
if (atoi(arg)) {
switch_set_flag(context, AMR_OPT_MODE_CHANGE_NEIGHBOR);
}
} else if (!strcasecmp(data, "crc")) {
if (atoi(arg)) {
switch_set_flag(context, AMR_OPT_CRC);
}
} else if (!strcasecmp(data, "robust-sorting")) {
if (atoi(arg)) {
switch_set_flag(context, AMR_OPT_ROBUST_SORTING);
}
} else if (!strcasecmp(data, "interveaving")) {
if (atoi(arg)) {
switch_set_flag(context, AMR_OPT_INTERLEAVING);
}
} else if (!strcasecmp(data, "mode-change-period")) {
context->change_period = atoi(arg);
} else if (!strcasecmp(data, "ptime")) {
context->ptime = (switch_byte_t) atoi(arg);
} else if (!strcasecmp(data, "channels")) {
context->channels = (switch_byte_t) atoi(arg);
} else if (!strcasecmp(data, "maxptime")) {
context->max_ptime = (switch_byte_t) atoi(arg);
} else if (!strcasecmp(data, "mode-set")) {
int y, m_argc;
char *m_argv[7];
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
for (y = 0; y < m_argc; y++) {
context->enc_modes |= (1 << atoi(m_argv[y]));
}
} else if (!strcasecmp(data, "dtx")) {
context->dtx_mode = (atoi(arg)) ? AMR_DTX_ENABLED : AMR_DTX_DISABLED;
}
}
}
}
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
codec_fmtp.private_info = &amr_codec_settings;
switch_amr_fmtp_parse(codec->fmtp_in, &codec_fmtp);
if (context->enc_modes) {
for (i = 7; i > -1; i++) {
@@ -321,6 +372,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_amr_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "AMR");
#ifndef AMR_PASSTHROUGH
codec_interface->parse_fmtp = switch_amr_fmtp_parse;
#endif
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
96, /* the IANA code number */
"AMR", /* the IANA code name */
+14
View File
@@ -0,0 +1,14 @@
BASE=../../../..
CODEC2_DIR=$(switch_srcdir)/libs/libcodec2
CODEC2_BUILDDIR=$(switch_builddir)/libs/libcodec2
CODEC2LA=$(CODEC2_BUILDDIR)/src/libcodec2.la
LOCAL_CFLAGS=-I$(CODEC2_DIR)/include -I$(CODEC2_BUILDDIR)/src
LOCAL_LIBADD=$(CODEC2LA)
include $(BASE)/build/modmake.rules
$(CODEC2LA): $(CODEC2_DIR) $(CODEC2_DIR)/.update
cd $(CODEC2_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)
+264
View File
@@ -0,0 +1,264 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* 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
*
* The Initial Developer of the Original Code is
* Brian West <brian@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mathieu Rene <mrene@avgs.ca>
*
* mod_codec2 -- FreeSWITCH CODEC2 Module
*
*/
#include <switch.h>
#include <codec2.h>
/* Uncomment to log input/output data for debugging
#define LOG_DATA
#define CODEC2_DEBUG
*/
#ifdef CODEC2_DEBUG
#define codec2_assert(_x) switch_assert(_x)
#else
#define codec2_assert(_x)
#endif
SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load);
SWITCH_MODULE_DEFINITION(mod_codec2, mod_codec2_load, NULL, NULL);
struct codec2_context {
void *encoder;
void *decoder;
#ifdef LOG_DATA
FILE *encoder_in;
FILE *encoder_out;
FILE *encoder_out_unpacked;
FILE *decoder_in;
FILE *decoder_in_unpacked;
FILE *decoder_out;
#endif
};
#ifdef LOG_DATA
static int c2_count = 0;
#endif
static switch_status_t switch_codec2_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
uint32_t encoding, decoding;
struct codec2_context *context = NULL;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
if (!(encoding || decoding)) {
return SWITCH_STATUS_FALSE;
}
if (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context)))) {
return SWITCH_STATUS_FALSE;
}
if (encoding) {
context->encoder = codec2_create();
}
if (decoding) {
context->decoder = codec2_create();
}
codec->private_info = context;
#ifdef LOG_DATA
{
int c = c2_count++;
char buf[1024];
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Logging as /tmp/c2-%d-*\n", c);
if (encoding) {
snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-in", c);
context->encoder_in = fopen(buf, "w");
snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-out", c);
context->encoder_out = fopen(buf, "w");
snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-out-unpacked", c);
context->encoder_out_unpacked = fopen(buf, "w");
}
if (decoding) {
snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-in", c);
context->decoder_in = fopen(buf, "w");
snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-out", c);
context->decoder_out = fopen(buf, "w");
snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-out-unpacked", c);
context->decoder_in_unpacked = fopen(buf, "w");
}
}
#endif
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_codec2_encode(switch_codec_t *codec, switch_codec_t *other_codec,
void *decoded_data,
uint32_t decoded_data_len,
uint32_t decoded_rate,
void *encoded_data,
uint32_t *encoded_data_len,
uint32_t *encoded_rate,
unsigned int *flag)
{
struct codec2_context *context = codec->private_info;
codec2_assert(decoded_data_len == CODEC2_SAMPLES_PER_FRAME * 2);
#ifdef LOG_DATA
fwrite(decoded_data, decoded_data_len, 1, context->encoder_in);
fflush(context->encoder_in);
#endif
codec2_encode(context->encoder, encoded_data, decoded_data);
#ifdef LOG_DATA
fwrite(encode_buf, sizeof(encode_buf), 1, context->encoder_out_unpacked);
fflush(context->encoder_out_unpacked);
fwrite(encoded_data, 8, 1, context->encoder_out);
fflush(context->encoder_out);
#endif
*encoded_data_len = 8;
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_codec2_decode(switch_codec_t *codec,
switch_codec_t *other_codec,
void *encoded_data,
uint32_t encoded_data_len,
uint32_t encoded_rate,
void *decoded_data,
uint32_t *decoded_data_len,
uint32_t *decoded_rate,
unsigned int *flag)
{
struct codec2_context *context = codec->private_info;
codec2_assert(encoded_data_len == 8 /* aligned to 8 */);
#ifdef LOG_DATA
fwrite(encoded_data, encoded_data_len, 1, context->decoder_in);
fflush(context->decoder_in);
fwrite(bits, sizeof(bits), 1, context->decoder_in_unpacked);
fflush(context->decoder_in_unpacked);
#endif
codec2_decode(context->decoder, decoded_data, encoded_data);
#ifdef LOG_DATA
fwrite(decoded_data, CODEC2_SAMPLES_PER_FRAME, 2, context->decoder_out);
fflush(context->decoder_out);
#endif
*decoded_data_len = CODEC2_SAMPLES_PER_FRAME * 2; /* 160 samples */
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t switch_codec2_destroy(switch_codec_t *codec)
{
struct codec2_context *context = codec->private_info;
codec2_destroy(context->encoder);
codec2_destroy(context->decoder);
context->encoder = NULL;
context->decoder = NULL;
#ifdef LOG_DATA
if (context->encoder_in) {
fclose(context->encoder_in);
}
if (context->encoder_out) {
fclose(context->encoder_out);
}
if (context->encoder_out_unpacked) {
fclose(context->encoder_out_unpacked);
}
if (context->decoder_in) {
fclose(context->decoder_in);
}
if (context->decoder_in_unpacked) {
fclose(context->decoder_in_unpacked);
}
if (context->decoder_out) {
fclose(context->decoder_out);
}
#endif
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load)
{
switch_codec_interface_t *codec_interface;
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "CODEC2 2550bps");
switch_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_AUDIO,
111,
"CODEC2",
NULL,
8000, /* samples/sec */
8000, /* samples/sec */
2550, /* bps */
20000, /* ptime */
CODEC2_SAMPLES_PER_FRAME, /* samples decoded */
CODEC2_SAMPLES_PER_FRAME*2, /* bytes decoded */
0, /* bytes encoded */
1, /* channels */
1, /* frames/packet */
switch_codec2_init,
switch_codec2_encode,
switch_codec2_decode,
switch_codec2_destroy);
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
+22 -20
View File
@@ -40,6 +40,27 @@ struct ilbc_context {
ilbc_decode_state_t decoder_object;
};
static switch_status_t switch_ilbc_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
{
if (codec_fmtp) {
char *mode = NULL;
int codec_ms = 0;
memset(codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
if (fmtp && (mode = strstr(fmtp, "mode=")) && (mode + 5)) {
codec_ms = atoi(mode + 5);
}
if (!codec_ms) {
/* default to 30 when no mode is defined for ilbc ONLY */
codec_ms = 30;
}
codec_fmtp->microseconds_per_packet = (codec_ms * 1000);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_ilbc_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
struct ilbc_context *context;
@@ -51,26 +72,6 @@ static switch_status_t switch_ilbc_init(switch_codec_t *codec, switch_codec_flag
return SWITCH_STATUS_FALSE;
}
if (codec->fmtp_in) {
int x, argc;
char *argv[10];
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
switch_assert(data);
while (*data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (!strcasecmp(data, "mode")) {
mode = atoi(arg);
}
}
}
}
codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "mode=%d", mode);
if (encoding) {
@@ -136,6 +137,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ilbc_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "iLBC");
codec_interface->parse_fmtp = switch_ilbc_fmtp_parse;
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
98, /* the IANA code number */
+123 -76
View File
@@ -41,6 +41,22 @@ SWITCH_MODULE_DEFINITION(mod_silk, mod_silk_load, NULL, NULL);
#define MAX_LBRR_DELAY 2
#define MAX_FRAME_LENGTH 480
/*! \brief Various codec settings */
struct silk_codec_settings {
SKP_int useinbandfec;
SKP_int usedtx;
SKP_int maxaveragebitrate;
SKP_int plpct;
};
typedef struct silk_codec_settings silk_codec_settings_t;
static silk_codec_settings_t default_codec_settings = {
/*.useinbandfec */ 0,
/*.usedtx */ 0,
/*.maxaveragebitrate */ 0,
/*.plpct */ 10, // 10% for now
};
struct silk_context {
SKP_SILK_SDK_EncControlStruct encoder_object;
SKP_SILK_SDK_DecControlStruct decoder_object;
@@ -48,12 +64,105 @@ struct silk_context {
void *dec_state;
};
static switch_status_t switch_silk_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
{
if (codec_fmtp) {
silk_codec_settings_t *codec_settings = NULL;
if (codec_fmtp->private_info) {
codec_settings = codec_fmtp->private_info;
memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
}
if (fmtp) {
int x, argc;
char *argv[10];
char *fmtp_dup = strdup(fmtp);
switch_assert(fmtp_dup);
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
switch_assert(data);
while (*data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (codec_settings) {
if (!strcasecmp(data, "useinbandfec")) {
if (switch_true(arg)) {
codec_settings->useinbandfec = 1;
}
}
if (!strcasecmp(data, "usedtx")) {
if (switch_true(arg)) {
codec_settings->usedtx = 1;
}
}
if (!strcasecmp(data, "maxaveragebitrate")) {
codec_settings->maxaveragebitrate = atoi(arg);
switch(codec_fmtp->actual_samples_per_second) {
case 8000:
{
if(codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 20000) {
codec_settings->maxaveragebitrate = 20000;
}
break;
}
case 12000:
{
if(codec_settings->maxaveragebitrate < 7000 || codec_settings->maxaveragebitrate > 25000) {
codec_settings->maxaveragebitrate = 25000;
}
break;
}
case 16000:
{
if(codec_settings->maxaveragebitrate < 8000 || codec_settings->maxaveragebitrate > 30000) {
codec_settings->maxaveragebitrate = 30000;
}
break;
}
case 24000:
{
if(codec_settings->maxaveragebitrate < 12000 || codec_settings->maxaveragebitrate > 40000) {
codec_settings->maxaveragebitrate = 40000;
}
break;
}
default:
/* this should never happen but 20000 is common among all rates */
codec_settings->maxaveragebitrate = 20000;
break;
}
}
}
}
}
free(fmtp_dup);
}
//codec_fmtp->bits_per_second = bit_rate;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_silk_init(switch_codec_t *codec,
switch_codec_flag_t freeswitch_flags,
const switch_codec_settings_t *codec_settings)
{
struct silk_context *context = NULL;
SKP_int useinbandfec = 0, usedtx = 0, maxaveragebitrate = 0, plpct =0;
switch_codec_fmtp_t codec_fmtp;
silk_codec_settings_t silk_codec_settings;
SKP_int32 encSizeBytes;
SKP_int32 decSizeBytes;
int encoding = (freeswitch_flags & SWITCH_CODEC_FLAG_ENCODE);
@@ -62,78 +171,15 @@ static switch_status_t switch_silk_init(switch_codec_t *codec,
if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
return SWITCH_STATUS_FALSE;
}
if (codec->fmtp_in) {
int x, argc;
char *argv[10];
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
switch_assert(data);
while (*data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (!strcasecmp(data, "useinbandfec")) {
if (switch_true(arg)) {
useinbandfec = 1;
plpct = 10;// 10% for now
}
}
if (!strcasecmp(data, "usedtx")) {
if (switch_true(arg)) {
usedtx = 1;
}
}
if (!strcasecmp(data, "maxaveragebitrate")) {
maxaveragebitrate = atoi(arg);
switch(codec->implementation->actual_samples_per_second) {
case 8000:
{
if(maxaveragebitrate < 6000 || maxaveragebitrate > 20000) {
maxaveragebitrate = 20000;
}
break;
}
case 12000:
{
if(maxaveragebitrate < 7000 || maxaveragebitrate > 25000) {
maxaveragebitrate = 25000;
}
break;
}
case 16000:
{
if(maxaveragebitrate < 8000 || maxaveragebitrate > 30000) {
maxaveragebitrate = 30000;
}
break;
}
case 24000:
{
if(maxaveragebitrate < 12000 || maxaveragebitrate > 40000) {
maxaveragebitrate = 40000;
}
break;
}
default:
/* this should never happen but 20000 is common among all rates */
maxaveragebitrate = 20000;
break;
}
}
}
}
}
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
codec_fmtp.private_info = &silk_codec_settings;
switch_silk_fmtp_parse(codec->fmtp_in, &codec_fmtp);
codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "useinbandfec=%s; usedtx=%s; maxaveragebitrate=%d",
useinbandfec ? "1" : "0",
usedtx ? "1" : "0",
maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second);
silk_codec_settings.useinbandfec ? "1" : "0",
silk_codec_settings.usedtx ? "1" : "0",
silk_codec_settings.maxaveragebitrate ? silk_codec_settings.maxaveragebitrate : codec->implementation->bits_per_second);
if (encoding) {
if (SKP_Silk_SDK_Get_Encoder_Size(&encSizeBytes)) {
@@ -148,11 +194,11 @@ static switch_status_t switch_silk_init(switch_codec_t *codec,
context->encoder_object.sampleRate = codec->implementation->actual_samples_per_second;
context->encoder_object.packetSize = codec->implementation->samples_per_packet;
context->encoder_object.useInBandFEC = useinbandfec;
context->encoder_object.useInBandFEC = silk_codec_settings.useinbandfec;
context->encoder_object.complexity = 0;
context->encoder_object.bitRate = maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second;
context->encoder_object.useDTX = usedtx;
context->encoder_object.packetLossPercentage = plpct;;
context->encoder_object.bitRate = silk_codec_settings.maxaveragebitrate ? silk_codec_settings.maxaveragebitrate : codec->implementation->bits_per_second;
context->encoder_object.useDTX = silk_codec_settings.usedtx;
context->encoder_object.packetLossPercentage = silk_codec_settings.plpct;
}
if (decoding) {
@@ -174,7 +220,7 @@ static switch_status_t switch_silk_init(switch_codec_t *codec,
static switch_status_t switch_silk_destroy(switch_codec_t *codec)
{
codec->private_info = NULL;
codec->private_info = NULL;
return SWITCH_STATUS_SUCCESS;
}
@@ -299,6 +345,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_silk_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "SILK");
codec_interface->parse_fmtp = switch_silk_fmtp_parse;
switch_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
117, /* the IANA code number */
+56 -20
View File
@@ -47,6 +47,40 @@ struct siren_context {
g722_1_encode_state_t encoder_object;
};
static switch_status_t switch_siren_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
{
if (codec_fmtp) {
int bit_rate = 0;
memset(codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
if (fmtp) {
int x, argc;
char *argv[10];
char *fmtp_dup = strdup(fmtp);
switch_assert(fmtp_dup);
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
switch_assert(data);
while (*data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (!strcasecmp(data, "bitrate")) {
bit_rate = atoi(arg);
}
}
}
free(fmtp_dup);
}
codec_fmtp->bits_per_second = bit_rate;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_siren_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
struct siren_context *context = NULL;
@@ -58,26 +92,6 @@ static switch_status_t switch_siren_init(switch_codec_t *codec, switch_codec_fla
return SWITCH_STATUS_FALSE;
}
if (codec->fmtp_in) {
int x, argc;
char *argv[10];
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
switch_assert(data);
while (*data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (!strcasecmp(data, "bitrate")) {
bit_rate = atoi(arg);
}
}
}
}
codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "bitrate=%d", bit_rate);
if (encoding) {
@@ -145,6 +159,28 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_siren_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "Polycom(R) G722.1/G722.1C");
codec_interface->parse_fmtp = switch_siren_fmtp_parse;
spf = 320, bpf = 640;
for (count = 3; count > 0; count--) {
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
107, /* the IANA code number */
"G7221", /* the IANA code name */
"bitrate=24000", /* default fmtp to send (can be overridden by the init function) */
16000, /* samples transferred per second */
16000, /* actual samples transferred per second */
24000, /* bits transferred per second */
mpf * count, /* number of microseconds per frame */
spf * count, /* number of samples per frame */
bpf * count, /* number of bytes per frame decompressed */
0, /* number of bytes per frame compressed */
1, /* number of channels represented */
1, /* number of frames per network packet */
switch_siren_init, /* function to initialize a codec handle using this implementation */
switch_siren_encode, /* function to encode raw data into encoded data */
switch_siren_decode, /* function to decode encoded data into raw data */
switch_siren_destroy); /* deinitalize a codec handle using this implementation */
}
spf = 320, bpf = 640;
for (count = 3; count > 0; count--) {
+123 -30
View File
@@ -37,7 +37,46 @@
SWITCH_MODULE_LOAD_FUNCTION(mod_speex_load);
SWITCH_MODULE_DEFINITION(mod_speex, mod_speex_load, NULL, NULL);
static switch_codec_settings_t default_codec_settings = {
/* nobody has more setting than speex so we will let them set the standard */
/*! \brief Various codec settings (currently only relevant to speex) */
struct speex_codec_settings {
/*! desired quality */
int quality;
/*! desired complexity */
int complexity;
/*! desired enhancement */
int enhancement;
/*! desired vad level */
int vad;
/*! desired vbr level */
int vbr;
/*! desired vbr quality */
float vbr_quality;
/*! desired abr level */
int abr;
/*! desired dtx setting */
int dtx;
/*! desired preprocessor settings */
int preproc;
/*! preprocessor vad settings */
int pp_vad;
/*! preprocessor gain control settings */
int pp_agc;
/*! preprocessor gain level */
float pp_agc_level;
/*! preprocessor denoise level */
int pp_denoise;
/*! preprocessor dereverb settings */
int pp_dereverb;
/*! preprocessor dereverb decay level */
float pp_dereverb_decay;
/*! preprocessor dereverb level */
float pp_dereverb_level;
};
typedef struct speex_codec_settings speex_codec_settings_t;
static speex_codec_settings_t default_codec_settings = {
/*.quality */ 5,
/*.complexity */ 5,
/*.enhancement */ 1,
@@ -58,6 +97,7 @@ static switch_codec_settings_t default_codec_settings = {
struct speex_context {
switch_codec_t *codec;
speex_codec_settings_t codec_settings;
unsigned int flags;
/* Encoder */
@@ -74,6 +114,56 @@ struct speex_context {
int decoder_mode;
};
static switch_status_t switch_speex_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
{
if (codec_fmtp) {
speex_codec_settings_t *codec_settings = NULL;
if (codec_fmtp->private_info) {
codec_settings = codec_fmtp->private_info;
memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
}
if (fmtp) {
int x, argc;
char *argv[10];
char *fmtp_dup = strdup(fmtp);
switch_assert(fmtp_dup);
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
switch_assert(data);
while (*data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
/*
if (!strcasecmp(data, "bitrate")) {
bit_rate = atoi(arg);
}
*/
/*
if (codec_settings) {
if (!strcasecmp(data, "vad")) {
bit_rate = atoi(arg);
}
}
*/
}
}
free(fmtp_dup);
}
/*codec_fmtp->bits_per_second = bit_rate;*/
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
struct speex_context *context = NULL;
@@ -82,16 +172,18 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
if (!codec_settings) {
codec_settings = &default_codec_settings;
}
memcpy(&codec->codec_settings, codec_settings, sizeof(codec->codec_settings));
if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) {
return SWITCH_STATUS_FALSE;
} else {
const SpeexMode *mode = NULL;
switch_codec_fmtp_t codec_fmtp;
speex_codec_settings_t codec_settings;
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
codec_fmtp.private_info = &codec_settings;
switch_speex_fmtp_parse(codec->fmtp_in, &codec_fmtp);
memcpy(&context->codec_settings, &codec_settings, sizeof(context->codec_settings));
context->codec = codec;
if (codec->implementation->actual_samples_per_second == 8000) {
@@ -110,41 +202,41 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
speex_bits_init(&context->encoder_bits);
context->encoder_state = speex_encoder_init(mode);
speex_encoder_ctl(context->encoder_state, SPEEX_GET_FRAME_SIZE, &context->encoder_frame_size);
speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &codec->codec_settings.complexity);
if (codec->codec_settings.preproc) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &context->codec_settings.complexity);
if (context->codec_settings.preproc) {
context->pp = speex_preprocess_state_init(context->encoder_frame_size, codec->implementation->actual_samples_per_second);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &codec->codec_settings.pp_vad);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &codec->codec_settings.pp_agc);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &codec->codec_settings.pp_agc_level);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &codec->codec_settings.pp_denoise);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &codec->codec_settings.pp_dereverb);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &codec->codec_settings.pp_dereverb_decay);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &codec->codec_settings.pp_dereverb_level);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &context->codec_settings.pp_vad);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &context->codec_settings.pp_agc);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &context->codec_settings.pp_agc_level);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &context->codec_settings.pp_denoise);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &context->codec_settings.pp_dereverb);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &context->codec_settings.pp_dereverb_decay);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &context->codec_settings.pp_dereverb_level);
}
if (!codec->codec_settings.abr && !codec->codec_settings.vbr) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_QUALITY, &codec->codec_settings.quality);
if (codec->codec_settings.vad) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &codec->codec_settings.vad);
if (!context->codec_settings.abr && !context->codec_settings.vbr) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_QUALITY, &context->codec_settings.quality);
if (context->codec_settings.vad) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &context->codec_settings.vad);
}
}
if (codec->codec_settings.vbr) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR, &codec->codec_settings.vbr);
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR_QUALITY, &codec->codec_settings.vbr_quality);
if (context->codec_settings.vbr) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR, &context->codec_settings.vbr);
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR_QUALITY, &context->codec_settings.vbr_quality);
}
if (codec->codec_settings.abr) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &codec->codec_settings.abr);
if (context->codec_settings.abr) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &context->codec_settings.abr);
}
if (codec->codec_settings.dtx) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &codec->codec_settings.dtx);
if (context->codec_settings.dtx) {
speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &context->codec_settings.dtx);
}
}
if (decoding) {
speex_bits_init(&context->decoder_bits);
context->decoder_state = speex_decoder_init(mode);
if (codec->codec_settings.enhancement) {
speex_decoder_ctl(context->decoder_state, SPEEX_SET_ENH, &codec->codec_settings.enhancement);
if (context->codec_settings.enhancement) {
speex_decoder_ctl(context->decoder_state, SPEEX_SET_ENH, &context->codec_settings.enhancement);
}
}
@@ -178,7 +270,7 @@ static switch_status_t switch_speex_encode(switch_codec_t *codec,
if (is_speech) {
is_speech = speex_encode_int(context->encoder_state, buf, &context->encoder_bits)
|| !context->codec->codec_settings.dtx;
|| !context->codec_settings.dtx;
} else {
speex_bits_pack(&context->encoder_bits, 0, 5);
}
@@ -270,6 +362,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_speex_load)
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "Speex");
codec_interface->parse_fmtp = switch_speex_fmtp_parse;
for (counta = 1; counta <= 3; counta++) {
for (countb = 1; countb > 0; countb--) {
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
+1
View File
@@ -1,3 +1,4 @@
fix crashes on FSH323Connection calls in on_hangup routine in different threads.
move PTrace level set to FSH323EndPoint::Initialise
partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directive.
apply changes from mod_h323-patch.diff by Peter Olsson.
+19 -5
View File
@@ -24,7 +24,7 @@
*
* mod_h323.cpp -- H323 endpoint
*
* Version 0.0.55
* Version 0.0.56
*/
//#define DEBUG_RTP_PACKETS
@@ -747,6 +747,17 @@ FSH323Connection::~FSH323Connection()
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->h323_mutex_unlock\n");
}
void FSH323Connection::AttachSignalChannel(const PString & token,
H323Transport * channel,
PBoolean answeringCall)
{
h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
tech_pvt->token = strdup((const char *)token);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"---------->token = %s [%p]\n",(const char *)token,this);
H323Connection::AttachSignalChannel(token,channel,answeringCall);
}
void FSH323Connection::OnSetLocalCapabilities()
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"======>FSH323Connection::OnSetLocalCapabilities() [%p]\n",this);
@@ -2321,8 +2332,9 @@ static switch_status_t on_hangup(switch_core_session_t *session)
switch_channel_t *channel = switch_core_session_get_channel(session);
h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(session);
FSH323Connection *me = tech_pvt->me;
FSH323EndPoint & ep = h323_process->GetH323EndPoint();
tech_pvt->me = NULL;
if (me) {
if (me->m_rtp_resetting == 1) {
switch_core_session_unlock_codec_read(session);
@@ -2340,12 +2352,12 @@ static switch_status_t on_hangup(switch_core_session_t *session)
me->CloseAllLogicalChannels(false);
me->Unlock();
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"----->%s\n",(const char *)(me->GetCallToken()));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"----->%s\n",(const char *)(tech_pvt->token));
Q931::CauseValues cause = (Q931::CauseValues)switch_channel_get_cause_q850(channel);
int trylock = me->TryLock();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"-----> () = %d\n",trylock);
if (trylock == 1) {
const PString currentToken(me->GetCallToken());
const PString currentToken(tech_pvt->token);
FSH323Connection *connection = (FSH323Connection *)me->GetEndPoint()->FindConnectionWithLock(currentToken);
if (connection) {
connection->Unlock();
@@ -2356,8 +2368,10 @@ static switch_status_t on_hangup(switch_core_session_t *session)
} else if (trylock == -1) {
/* Failed to lock - just go on */
}
const PString currentToken(tech_pvt->token);
me->SetQ931Cause(cause);
me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));
// me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));
ep.ClearCall(currentToken, H323TranslateToCallEndReason(cause, UINT_MAX));
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->h323_mutex_lock\n");
// switch_mutex_lock(tech_pvt->h323_mutex);
}
+6 -1
View File
@@ -184,6 +184,7 @@ typedef struct {
switch_mutex_t *h323_io_mutex;
FSH323Connection *me;
char *token;
} h323_private_t;
#define DECLARE_CALLBACK0(name) \
@@ -306,7 +307,11 @@ class FSH323Connection:public H323Connection {
unsigned callReference, switch_caller_profile_t *outbound_profile,
switch_core_session_t *fsSession, switch_channel_t *fsChannel);
~FSH323Connection();
virtual void AttachSignalChannel(
const PString & token,
H323Transport * channel,
PBoolean answeringCall
);
virtual H323Channel *CreateRealTimeLogicalChannel(const H323Capability & capability,
H323Channel::Directions dir,
unsigned sessionID, const H245_H2250LogicalChannelParameters * param, RTP_QOS * rtpqos = NULL);
@@ -52,7 +52,8 @@ typedef enum {
TFLAG_BRIDGE = (1 << 4),
TFLAG_BOWOUT = (1 << 5),
TFLAG_BLEG = (1 << 6),
TFLAG_APP = (1 << 7)
TFLAG_APP = (1 << 7),
TFLAG_BOWOUT_USED = (1 << 8)
} TFLAGS;
struct private_object {
@@ -635,7 +636,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
if (switch_test_flag(frame, SFF_CNG) || switch_test_flag(tech_pvt, TFLAG_CNG) || switch_test_flag(tech_pvt, TFLAG_BOWOUT)) {
if (switch_test_flag(frame, SFF_CNG) || switch_test_flag(tech_pvt, TFLAG_CNG) || (switch_test_flag(tech_pvt, TFLAG_BOWOUT) && switch_test_flag(tech_pvt, TFLAG_BOWOUT_USED))) {
return SWITCH_STATUS_SUCCESS;
}
@@ -662,6 +663,9 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
switch_clear_flag_locked(tech_pvt, TFLAG_WRITE);
switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE);
switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT_USED);
switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT_USED);
if (a_uuid && b_uuid) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s detected bridge on both ends, attempting direct connection.\n", switch_channel_get_name(channel));
+72 -20
View File
@@ -1343,19 +1343,6 @@ static switch_status_t kill_listener(listener_t *listener, void *pvt)
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t kill_expired_listener(listener_t *listener, void *pvt)
{
switch_event_t *event = NULL;
if(listener->expire_time < switch_epoch_time_now(NULL)) {
/* skinny::expire event */
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_EXPIRE);
switch_event_fire(&event);
return kill_listener(listener, pvt);
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t keepalive_listener(listener_t *listener, void *pvt)
{
skinny_profile_t *profile;
@@ -1414,6 +1401,13 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
case SWITCH_STATUS_TIMEOUT:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Communication Time Out with %s:%d.\n",
listener->remote_ip, listener->remote_port);
if(listener->expire_time < switch_epoch_time_now(NULL)) {
switch_event_t *event = NULL;
/* skinny::expire event */
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_EXPIRE);
switch_event_fire(&event);
}
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Communication Error with %s:%d.\n",
@@ -1917,9 +1911,57 @@ static switch_status_t load_skinny_config(void)
return SWITCH_STATUS_SUCCESS;
}
static void skinny_heartbeat_event_handler(switch_event_t *event)
static void skinny_user_to_device_event_handler(switch_event_t *event)
{
walk_listeners(kill_expired_listener, NULL);
char *profile_name = switch_event_get_header_nil(event, "Skinny-Profile-Name");
skinny_profile_t *profile;
if ((profile = skinny_find_profile(profile_name))) {
char *device_name = switch_event_get_header_nil(event, "Skinny-Device-Name");
uint32_t device_instance = atoi(switch_event_get_header_nil(event, "Skinny-Station-Instance"));
listener_t *listener = NULL;
skinny_profile_find_listener_by_device_name_and_instance(profile, device_name, device_instance, &listener);
if(listener) {
uint32_t message_type = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Message-Id"));
uint32_t application_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Application-Id"));
uint32_t line_instance = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Line-Instance"));
uint32_t call_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Call-Id"));
uint32_t transaction_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Transaction-Id"));
uint32_t data_length = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Data-Length"));
uint32_t sequence_flag = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Sequence-Flag"));
uint32_t display_priority = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Display-Priority"));
uint32_t conference_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Conference-Id"));
uint32_t app_instance_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-App-Instance-Id"));
uint32_t routing_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Routing-Id"));
char *data = switch_event_get_body(event);
if (message_type == 0) {
message_type = skinny_str2message_type(switch_event_get_header_nil(event, "Skinny-UserToDevice-Message-Id-String"));
}
switch(message_type) {
case USER_TO_DEVICE_DATA_MESSAGE:
data_length = strlen(data); /* we ignore data_length sent */
send_data(listener, message_type,
application_id, line_instance, call_id, transaction_id, data_length,
data);
case USER_TO_DEVICE_DATA_VERSION1_MESSAGE:
data_length = strlen(data); /* we ignore data_length sent */
send_extended_data(listener, message_type,
application_id, line_instance, call_id, transaction_id, data_length,
sequence_flag, display_priority, conference_id, app_instance_id, routing_id,
data);
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Incorrect message type %s (%d).\n", skinny_message_type2str(message_type), message_type);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Profile '%s' not found.\n", profile_name);
}
}
static void skinny_call_state_event_handler(switch_event_t *event)
@@ -2129,10 +2171,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
return SWITCH_STATUS_TERM;
}
/* bind to events */
if ((switch_event_bind_removable(modname, SWITCH_EVENT_HEARTBEAT, NULL, skinny_heartbeat_event_handler, NULL, &globals.heartbeat_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our heartbeat handler!\n");
/* Not such severe to prevent loading */
}
if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE, skinny_call_state_event_handler, NULL, &globals.call_state_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our call_state handler!\n");
return SWITCH_STATUS_TERM;
@@ -2145,6 +2183,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our trap handler!\n");
/* Not such severe to prevent loading */
}
if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_USER_TO_DEVICE, skinny_user_to_device_event_handler, NULL, &globals.user_to_device_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our user_to_device handler!\n");
/* Not such severe to prevent loading */
}
/* reserve events */
if (switch_event_reserve_subclass(SKINNY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) {
@@ -2167,6 +2209,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_CALL_STATE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(SKINNY_EVENT_USER_TO_DEVICE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_USER_TO_DEVICE);
return SWITCH_STATUS_TERM;
}
if (switch_event_reserve_subclass(SKINNY_EVENT_DEVICE_TO_USER) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_DEVICE_TO_USER);
return SWITCH_STATUS_TERM;
}
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(globals.pool, modname);
@@ -2205,7 +2255,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown)
skinny_api_unregister();
/* release events */
switch_event_unbind(&globals.heartbeat_node);
switch_event_unbind(&globals.user_to_device_node);
switch_event_unbind(&globals.call_state_node);
switch_event_unbind(&globals.message_waiting_node);
switch_event_unbind(&globals.trap_node);
@@ -2214,6 +2264,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown)
switch_event_free_subclass(SKINNY_EVENT_EXPIRE);
switch_event_free_subclass(SKINNY_EVENT_ALARM);
switch_event_free_subclass(SKINNY_EVENT_CALL_STATE);
switch_event_free_subclass(SKINNY_EVENT_USER_TO_DEVICE);
switch_event_free_subclass(SKINNY_EVENT_DEVICE_TO_USER);
switch_mutex_lock(mutex);
+3 -1
View File
@@ -43,13 +43,15 @@
#define SKINNY_EVENT_EXPIRE "skinny::expire"
#define SKINNY_EVENT_ALARM "skinny::alarm"
#define SKINNY_EVENT_CALL_STATE "skinny::call_state"
#define SKINNY_EVENT_USER_TO_DEVICE "skinny::user_to_device"
#define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user"
struct skinny_globals {
int running;
switch_memory_pool_t *pool;
switch_mutex_t *mutex;
switch_hash_t *profile_hash;
switch_event_node_t *heartbeat_node;
switch_event_node_t *user_to_device_node;
switch_event_node_t *call_state_node;
switch_event_node_t *message_waiting_node;
switch_event_node_t *trap_node;
+69
View File
@@ -366,6 +366,62 @@ static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const ch
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_data(const char *profile_name, const char *device_name, const char *message_type, char *params, const char *body, switch_stream_handle_t *stream)
{
skinny_profile_t *profile;
if ((profile = skinny_find_profile(profile_name))) {
listener_t *listener = NULL;
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
switch_event_t *event = NULL;
char *argv[64] = { 0 };
int argc = 0;
int x = 0;
/* skinny::user_to_device event */
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_USER_TO_DEVICE);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Message-Id-String", "%s", message_type);
argc = switch_separate_string(params, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *var_name, *var_value = NULL;
var_name = argv[x];
if (var_name && (var_value = strchr(var_name, '='))) {
*var_value++ = '\0';
}
if (zstr(var_name)) {
stream->write_function(stream, "-ERR No variable specified\n");
} else {
char *tmp = switch_mprintf("Skinny-UserToDevice-%s", var_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, tmp, "%s", var_value);
switch_safe_free(tmp);
/*
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Application-Id", "%d", request->data.extended_data.application_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Line-Instance", "%d", request->data.extended_data.line_instance);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Call-Id", "%d", request->data.extended_data.call_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Transaction-Id", "%d", request->data.extended_data.transaction_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Data-Length", "%d", request->data.extended_data.data_length);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Sequence-Flag", "%d", request->data.extended_data.sequence_flag);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Display-Priority", "%d", request->data.extended_data.display_priority);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Conference-Id", "%d", request->data.extended_data.conference_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-App-Instance-Id", "%d", request->data.extended_data.app_instance_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Routing-Id", "%d", request->data.extended_data.routing_id);
*/
}
}
switch_event_add_body(event, "%s", body);
switch_event_fire(&event);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
} else {
stream->write_function(stream, "Profile not found!\n");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, const char *name, const char *value, switch_stream_handle_t *stream)
{
skinny_profile_t *profile;
@@ -403,6 +459,7 @@ SWITCH_STANDARD_API(skinny_function)
"skinny profile <profile_name> device <device_name> send SetLampMessage <stimulus> <instance> <lamp_mode>\n"
"skinny profile <profile_name> device <device_name> send SetSpeakerModeMessage <speaker_mode>\n"
"skinny profile <profile_name> device <device_name> send CallStateMessage <call_state> <line_instance> <call_id>\n"
"skinny profile <profile_name> device <device_name> send <UserToDeviceDataMessage|UserToDeviceDataVersion1Message> [ <param>=<value>;... ] <data>\n"
"skinny profile <profile_name> set <name> <value>\n"
"--------------------------------------------------------------------------------\n";
if (session) {
@@ -465,6 +522,16 @@ SWITCH_STANDARD_API(skinny_function)
status = skinny_api_cmd_profile_device_send_reset_message(argv[1], argv[3], argv[6], stream);
}
break;
case USER_TO_DEVICE_DATA_MESSAGE:
case USER_TO_DEVICE_DATA_VERSION1_MESSAGE:
if(argc == 8) {
/* <UserToDeviceDataMessage|UserToDeviceDataVersion1Message> [ <param>=<value>;... ] <data> */
status = skinny_api_cmd_profile_device_send_data(argv[1], argv[3], argv[5], argv[6], argv[7], stream);
} else if(argc == 7) {
/* <UserToDeviceDataMessage|UserToDeviceDataVersion1Message> <data> */
status = skinny_api_cmd_profile_device_send_data(argv[1], argv[3], argv[5], "", argv[6], stream);
}
break;
default:
stream->write_function(stream, "Unhandled message %s\n", argv[5]);
}
@@ -495,6 +562,8 @@ switch_status_t skinny_api_register(switch_loadable_module_interface_t **module_
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetLampMessage ::skinny::list_stimuli ::skinny::list_stimulus_instances ::skinny::list_stimulus_modes");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetSpeakerModeMessage ::skinny::list_speaker_modes");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send CallStateMessage ::skinny::list_call_states ::skinny::list_line_instances ::skinny::list_call_ids");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataMessage");
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataVersion1Message");
switch_console_set_complete("add skinny profile ::skinny::list_profiles set ::skinny::list_settings");
switch_console_add_complete_func("::skinny::list_profiles", skinny_api_list_profiles);
@@ -135,6 +135,10 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
status = switch_socket_recv(listener->sock, ptr, &mlen);
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
return SWITCH_STATUS_TIMEOUT;
}
if (!listener_is_ready(listener)) {
break;
}
@@ -898,6 +902,68 @@ switch_status_t send_reset(listener_t *listener, uint32_t reset_type)
return skinny_send_reply(listener, message);
}
switch_status_t send_data(listener_t *listener, uint32_t message_type,
uint32_t application_id,
uint32_t line_instance,
uint32_t call_id,
uint32_t transaction_id,
uint32_t data_length,
const char *data)
{
skinny_message_t *message;
switch_assert(data_length == strlen(data));
/* data_length should be a multiple of 4 */
if ((data_length % 4) != 0) {
data_length = (data_length / 4 + 1) * 4;
}
message = switch_core_alloc(listener->pool, 12+sizeof(message->data.data)+data_length-1);
message->type = message_type;
message->length = 4 + sizeof(message->data.data)+data_length-1;
message->data.data.application_id = application_id;
message->data.data.line_instance = line_instance;
message->data.data.call_id = call_id;
message->data.data.transaction_id = transaction_id;
message->data.data.data_length = data_length;
strncpy(message->data.data.data, data, data_length);
return skinny_send_reply(listener, message);
}
switch_status_t send_extended_data(listener_t *listener, uint32_t message_type,
uint32_t application_id,
uint32_t line_instance,
uint32_t call_id,
uint32_t transaction_id,
uint32_t data_length,
uint32_t sequence_flag,
uint32_t display_priority,
uint32_t conference_id,
uint32_t app_instance_id,
uint32_t routing_id,
const char *data)
{
skinny_message_t *message;
switch_assert(data_length == strlen(data));
/* data_length should be a multiple of 4 */
if ((data_length % 4) != 0) {
data_length = (data_length / 4 + 1) * 4;
}
message = switch_core_alloc(listener->pool, 12+sizeof(message->data.extended_data)+data_length-1);
message->type = message_type;
message->length = 4 + sizeof(message->data.extended_data)+data_length-1;
message->data.extended_data.application_id = application_id;
message->data.extended_data.line_instance = line_instance;
message->data.extended_data.call_id = call_id;
message->data.extended_data.transaction_id = transaction_id;
message->data.extended_data.data_length = data_length;
message->data.extended_data.sequence_flag = sequence_flag;
message->data.extended_data.display_priority = display_priority;
message->data.extended_data.conference_id = conference_id;
message->data.extended_data.app_instance_id = app_instance_id;
message->data.extended_data.routing_id = routing_id;
strncpy(message->data.extended_data.data, data, data_length);
return skinny_send_reply(listener, message);
}
switch_status_t skinny_perform_send_reply(listener_t *listener, const char *file, const char *func, int line, skinny_message_t *reply)
{
char *ptr;
+85 -2
View File
@@ -174,6 +174,21 @@ struct PACKED register_available_lines_message {
uint32_t count;
};
/* DeviceToUserDataMessage */
#define DEVICE_TO_USER_DATA_MESSAGE 0x002E
struct PACKED data_message {
uint32_t application_id;
uint32_t line_instance;
uint32_t call_id;
uint32_t transaction_id;
uint32_t data_length;
char data[1];
};
/* DeviceToUserDataResponseMessage */
#define DEVICE_TO_USER_DATA_RESPONSE_MESSAGE 0x002F
/* See struct PACKED data_message */
/* ServiceUrlStatReqMessage */
#define SERVICE_URL_STAT_REQ_MESSAGE 0x0033
struct PACKED service_url_stat_req_message {
@@ -186,6 +201,26 @@ struct PACKED feature_stat_req_message {
uint32_t feature_index;
};
/* DeviceToUserDataVersion1Message */
#define DEVICE_TO_USER_DATA_VERSION1_MESSAGE 0x0041
struct PACKED extended_data_message {
uint32_t application_id;
uint32_t line_instance;
uint32_t call_id;
uint32_t transaction_id;
uint32_t data_length;
uint32_t sequence_flag;
uint32_t display_priority;
uint32_t conference_id;
uint32_t app_instance_id;
uint32_t routing_id;
char data[1];
};
/* DeviceToUserDataResponseVersion1Message */
#define DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE 0x0042
/* See struct PACKED extended_data_message */
/* RegisterAckMessage */
#define REGISTER_ACK_MESSAGE 0x0081
struct PACKED register_ack_message {
@@ -479,6 +514,10 @@ struct PACKED dialed_number_message {
uint32_t call_id;
};
/* UserToDeviceDataMessage */
#define USER_TO_DEVICE_DATA_MESSAGE 0x011E
/* See struct PACKED data_message */
/* FeatureStatMessage */
#define FEATURE_STAT_RES_MESSAGE 0x011F
struct PACKED feature_stat_res_message {
@@ -504,6 +543,10 @@ struct PACKED service_url_stat_res_message {
char display_name[40];
};
/* UserToDeviceDataVersion1Message */
#define USER_TO_DEVICE_DATA_VERSION1_MESSAGE 0x013F
/* See struct PACKED extended_data_message */
/*****************************************************************************/
/* SKINNY MESSAGE */
/*****************************************************************************/
@@ -512,6 +555,7 @@ struct PACKED service_url_stat_res_message {
#define SKINNY_MESSAGE_MAXSIZE 1000
union skinny_data {
/* no data for KEEP_ALIVE_MESSAGE */
struct register_message reg;
struct port_message port;
struct keypad_button_message keypad_button;
@@ -520,14 +564,25 @@ union skinny_data {
struct on_hook_message on_hook;
struct speed_dial_stat_req_message speed_dial_req;
struct line_stat_req_message line_req;
/* no data for CONFIG_STAT_REQ_MESSAGE */
/* no data for TIME_DATE_REQ_MESSAGE */
/* no data for BUTTON_TEMPLATE_REQ_MESSAGE */
/* no data for VERSION_REQ_MESSAGE */
struct capabilities_res_message cap_res;
struct alarm_message alarm;
struct open_receive_channel_ack_message open_receive_channel_ack;
/* no data for SOFT_KEY_SET_REQ_MESSAGE */
struct soft_key_event_message soft_key_event;
struct service_url_stat_req_message service_url_req;
struct feature_stat_req_message feature_req;
/* no data for UNREGISTER_MESSAGE */
/* no data for SOFT_KEY_TEMPLATE_REQ_MESSAGE */
struct headset_status_message headset_status;
struct register_available_lines_message reg_lines;
/* see field "data" for DEVICE_TO_USER_DATA_MESSAGE */
/* see field "data" for DEVICE_TO_USER_DATA_RESPONSE_MESSAGE */
struct service_url_stat_req_message service_url_req;
struct feature_stat_req_message feature_req;
/* see field "extended_data" for DEVICE_TO_USER_DATA_VERSION1_MESSAGE */
/* see field "extended_data" for DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE */
struct register_ack_message reg_ack;
struct start_tone_message start_tone;
struct stop_tone_message stop_tone;
@@ -543,8 +598,10 @@ union skinny_data {
struct define_time_date_message define_time_date;
struct button_template_message button_template;
struct version_message version;
/* no data for CAPABILITIES_REQ_MESSAGE */
struct register_reject_message reg_rej;
struct reset_message reset;
/* no data for KEEP_ALIVE_ACK_MESSAGE */
struct open_receive_channel_message open_receive_channel;
struct close_receive_channel_message close_receive_channel;
struct soft_key_template_res_message soft_key_template;
@@ -557,9 +614,14 @@ union skinny_data {
struct unregister_ack_message unregister_ack;
struct back_space_req_message back_space_req;
struct dialed_number_message dialed_number;
/* see field "data" for USER_TO_DEVICE_DATA_MESSAGE */
struct feature_stat_res_message feature_res;
struct display_pri_notify_message display_pri_notify;
struct service_url_stat_res_message service_url_res;
/* see field "extended_data" for USER_TO_DEVICE_DATA_VERSION1_MESSAGE */
struct data_message data;
struct extended_data_message extended_data;
uint16_t as_uint16;
char as_char;
@@ -777,6 +839,27 @@ switch_status_t send_display_pri_notify(listener_t *listener,
switch_status_t send_reset(listener_t *listener,
uint32_t reset_type);
switch_status_t send_data(listener_t *listener, uint32_t message_type,
uint32_t application_id,
uint32_t line_instance,
uint32_t call_id,
uint32_t transaction_id,
uint32_t data_length,
const char *data);
switch_status_t send_extended_data(listener_t *listener, uint32_t message_type,
uint32_t application_id,
uint32_t line_instance,
uint32_t call_id,
uint32_t transaction_id,
uint32_t data_length,
uint32_t sequence_flag,
uint32_t display_priority,
uint32_t conference_id,
uint32_t app_instance_id,
uint32_t routing_id,
const char *data);
#endif /* _SKINNY_PROTOCOL_H */
/* For Emacs:
@@ -1864,6 +1864,33 @@ switch_status_t skinny_handle_register_available_lines_message(listener_t *liste
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_data_message(listener_t *listener, skinny_message_t *request)
{
switch_event_t *event = NULL;
char *tmp = NULL;
skinny_check_data_length(request, sizeof(request->data.data));
skinny_check_data_length(request, sizeof(request->data.data) + request->data.data.data_length - 1);
/* skinny::device_to_user event */
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_DEVICE_TO_USER);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id", "%d", request->type);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id-String", "%s", skinny_message_type2str(request->type));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Application-Id", "%d", request->data.data.application_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Line-Instance", "%d", request->data.data.line_instance);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Call-Id", "%d", request->data.data.call_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Transaction-Id", "%d", request->data.data.transaction_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Data-Length", "%d", request->data.data.data_length);
/* Ensure that the body is null-terminated */
tmp = malloc(request->data.data.data_length + 1);
memcpy(tmp, request->data.data.data, request->data.data.data_length);
tmp[request->data.data.data_length] = '\0';
switch_event_add_body(event, "%s", tmp);
switch_safe_free(tmp);
switch_event_fire(&event);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_service_url_stat_request(listener_t *listener, skinny_message_t *request)
{
skinny_message_t *message;
@@ -1904,6 +1931,38 @@ switch_status_t skinny_handle_feature_stat_request(listener_t *listener, skinny_
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_extended_data_message(listener_t *listener, skinny_message_t *request)
{
switch_event_t *event = NULL;
char *tmp = NULL;
skinny_check_data_length(request, sizeof(request->data.extended_data));
skinny_check_data_length(request, sizeof(request->data.extended_data)+request->data.extended_data.data_length-1);
/* skinny::device_to_user event */
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_DEVICE_TO_USER);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id", "%d", request->type);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id-String", "%s", skinny_message_type2str(request->type));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Application-Id", "%d", request->data.extended_data.application_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Line-Instance", "%d", request->data.extended_data.line_instance);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Call-Id", "%d", request->data.extended_data.call_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Transaction-Id", "%d", request->data.extended_data.transaction_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Data-Length", "%d", request->data.extended_data.data_length);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Sequence-Flag", "%d", request->data.extended_data.sequence_flag);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Display-Priority", "%d", request->data.extended_data.display_priority);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Conference-Id", "%d", request->data.extended_data.conference_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-App-Instance-Id", "%d", request->data.extended_data.app_instance_id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Routing-Id", "%d", request->data.extended_data.routing_id);
/* Ensure that the body is null-terminated */
tmp = malloc(request->data.data.data_length + 1);
memcpy(tmp, request->data.data.data, request->data.data.data_length);
tmp[request->data.data.data_length] = '\0';
switch_event_add_body(event, "%s", tmp);
switch_safe_free(tmp);
switch_event_fire(&event);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *request)
{
if (listener->profile->debug >= 10 || request->type != KEEP_ALIVE_MESSAGE) {
@@ -1961,10 +2020,18 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
return skinny_headset_status_message(listener, request);
case REGISTER_AVAILABLE_LINES_MESSAGE:
return skinny_handle_register_available_lines_message(listener, request);
case DEVICE_TO_USER_DATA_MESSAGE:
return skinny_handle_data_message(listener, request);
case DEVICE_TO_USER_DATA_RESPONSE_MESSAGE:
return skinny_handle_data_message(listener, request);
case SERVICE_URL_STAT_REQ_MESSAGE:
return skinny_handle_service_url_stat_request(listener, request);
case FEATURE_STAT_REQ_MESSAGE:
return skinny_handle_feature_stat_request(listener, request);
case DEVICE_TO_USER_DATA_VERSION1_MESSAGE:
return skinny_handle_extended_data_message(listener, request);
case DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE:
return skinny_handle_extended_data_message(listener, request);
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unhandled request %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
+8 -2
View File
@@ -55,10 +55,14 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
{"SoftKeyEventMessage", SOFT_KEY_EVENT_MESSAGE},
{"UnregisterMessage", UNREGISTER_MESSAGE},
{"SoftKeyTemplateReqMessage", SOFT_KEY_TEMPLATE_REQ_MESSAGE},
{"ServiceUrlStatReqMessage", SERVICE_URL_STAT_REQ_MESSAGE},
{"FeatureStatReqMessage", FEATURE_STAT_REQ_MESSAGE},
{"HeadsetStatusMessage", HEADSET_STATUS_MESSAGE},
{"RegisterAvailableLinesMessage", REGISTER_AVAILABLE_LINES_MESSAGE},
{"DeviceToUserDataMessage", DEVICE_TO_USER_DATA_MESSAGE},
{"DeviceToUserDataResponseMessage", DEVICE_TO_USER_DATA_RESPONSE_MESSAGE},
{"ServiceUrlStatReqMessage", SERVICE_URL_STAT_REQ_MESSAGE},
{"FeatureStatReqMessage", FEATURE_STAT_REQ_MESSAGE},
{"DeviceToUserDataVersion1Message", DEVICE_TO_USER_DATA_VERSION1_MESSAGE},
{"DeviceToUserDataResponseVersion1Message", DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE},
{"RegisterAckMessage", REGISTER_ACK_MESSAGE},
{"StartToneMessage", START_TONE_MESSAGE},
{"StopToneMessage", STOP_TONE_MESSAGE},
@@ -90,9 +94,11 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
{"UnregisterAckMessage", UNREGISTER_ACK_MESSAGE},
{"BackSpaceReqMessage", BACK_SPACE_REQ_MESSAGE},
{"DialedNumberMessage", DIALED_NUMBER_MESSAGE},
{"UserToDeviceDataMessage", USER_TO_DEVICE_DATA_MESSAGE},
{"FeatureResMessage", FEATURE_STAT_RES_MESSAGE},
{"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE},
{"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE},
{"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE},
{NULL, 0}
};
SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage")
+1 -1
View File
@@ -87,7 +87,7 @@ uint32_t func(const char *str)\
}
extern struct skinny_table SKINNY_MESSAGE_TYPES[59];
extern struct skinny_table SKINNY_MESSAGE_TYPES[65];
const char *skinny_message_type2str(uint32_t id);
uint32_t skinny_str2message_type(const char *str);
#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES)
+107 -58
View File
@@ -85,6 +85,10 @@ static switch_status_t sofia_on_init(switch_core_session_t *session)
sofia_glue_tech_absorb_sdp(tech_pvt);
}
if (sofia_test_flag(tech_pvt, TFLAG_RECOVERING) || sofia_test_flag(tech_pvt, TFLAG_RECOVERING_BRIDGE)) {
sofia_set_flag(tech_pvt, TFLAG_RECOVERED);
}
if (sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) || sofia_test_flag(tech_pvt, TFLAG_RECOVERING)) {
const char *var;
@@ -717,6 +721,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
@@ -732,6 +737,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
@@ -1232,7 +1238,12 @@ static void start_udptl(private_object_t *tech_pvt, switch_t38_options_t *t38_op
switch_rtp_udptl_mode(tech_pvt->rtp_session);
if (remote_host && remote_port && !strcmp(remote_host, t38_options->remote_ip) && remote_port == t38_options->remote_port) {
if (!t38_options || !t38_options->remote_ip) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "No remote address\n");
return;
}
if (remote_host && remote_port && remote_port == t38_options->remote_port && !strcmp(remote_host, t38_options->remote_ip)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
t38_options->remote_ip, t38_options->remote_port);
return;
@@ -1471,12 +1482,11 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ:
{
const char *pl =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"
" <media_control>\r\n"
" <vc_primitive>\r\n"
" <to_encoder>\r\n"
" <picture_fast_update>\r\n" " </picture_fast_update>\r\n" " </to_encoder>\r\n" " </vc_primitive>\r\n" " </media_control>\r\n";
const char *pl = "<media_control><vc_primitive><to_encoder><picture_fast_update/></to_encoder></vc_primitive></media_control>";
if (!zstr(msg->string_arg)) {
pl = msg->string_arg;
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/media_control+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
@@ -1765,7 +1775,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
nua_update(tech_pvt->nh,
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
} else if ((ua && (switch_stristr("cisco", ua)))) {
} else if (0 && (ua && (switch_stristr("cisco", ua)))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
@@ -2005,6 +2015,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
if (t38_options) {
sofia_glue_set_image_sdp(tech_pvt, t38_options, 0);
if (switch_rtp_ready(tech_pvt->rtp_session)) {
switch_rtp_udptl_mode(tech_pvt->rtp_session);
}
}
} else {
sofia_glue_tech_set_local_sdp(tech_pvt, sdp, SWITCH_TRUE);
@@ -2090,6 +2103,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
status = sofia_answer_channel(session);
if (switch_channel_test_flag(tech_pvt->channel, CF_VIDEO)) {
sofia_glue_build_vid_refresh_message(session, NULL);
}
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
@@ -2315,7 +2331,7 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
switch_time_t etime = atoi(argv[6]);
switch_size_t retsize;
exp_secs = etime - now;
exp_secs = (int)(etime - now);
switch_time_exp_lt(&tm, switch_time_from_sec(etime));
switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
}
@@ -2355,7 +2371,7 @@ static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **colum
switch_time_t etime = atoi(argv[6]);
switch_size_t retsize;
exp_secs = etime - now;
exp_secs = (int)(etime - now);
switch_time_exp_lt(&tm, switch_time_from_sec(etime));
switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
}
@@ -2422,7 +2438,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
ob_failed += gp->ob_failed_calls;
ob += gp->ob_calls;
stream->write_function(stream, "%25s\t%32s\t%s\t%ld/%ld\t%ld/%ld",
stream->write_function(stream, "%25s\t%32s\t%s\t%u/%u\t%u/%u",
pkey, gp->register_to, sofia_state_names[gp->state],
gp->ib_failed_calls, gp->ib_calls, gp->ob_failed_calls, gp->ob_calls);
@@ -2441,8 +2457,8 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
stream->write_function(stream, "%s\n", line);
stream->write_function(stream, "%d gateway%s: Inound(Failed/Total): %ld/%ld,"
"Outbound(Failed/Total):%ld/%ld\n", c, c == 1 ? "" : "s", ib_failed, ib, ob_failed, ob);
stream->write_function(stream, "%d gateway%s: Inbound(Failed/Total): %u/%u,"
"Outbound(Failed/Total):%u/%u\n", c, c == 1 ? "" : "s", ib_failed, ib, ob_failed, ob);
return SWITCH_STATUS_SUCCESS;
}
@@ -2471,10 +2487,10 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
stream->write_function(stream, "PingState\t%d/%d/%d\n", gp->ping_min, gp->ping_count, gp->ping_max);
stream->write_function(stream, "State \t%s\n", sofia_state_names[gp->state]);
stream->write_function(stream, "Status \t%s%s\n", status_names[gp->status], gp->pinging ? " (ping)" : "");
stream->write_function(stream, "CallsIN \t%d\n", gp->ib_calls);
stream->write_function(stream, "CallsOUT\t%d\n", gp->ob_calls);
stream->write_function(stream, "FailedCallsIN\t%d\n", gp->ib_failed_calls);
stream->write_function(stream, "FailedCallsOUT\t%d\n", gp->ob_failed_calls);
stream->write_function(stream, "CallsIN \t%u\n", gp->ib_calls);
stream->write_function(stream, "CallsOUT\t%u\n", gp->ob_calls);
stream->write_function(stream, "FailedCallsIN\t%u\n", gp->ib_failed_calls);
stream->write_function(stream, "FailedCallsOUT\t%u\n", gp->ob_failed_calls);
stream->write_function(stream, "%s\n", line);
sofia_reg_release_gateway(gp);
} else {
@@ -2483,7 +2499,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
} else if (!strcasecmp(argv[0], "profile")) {
struct cb_helper cb;
char *sql = NULL;
int x = 0;
uint32_t x = 0;
cb.row_process = 0;
@@ -2548,10 +2564,10 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
if (profile->max_registrations_perext > 0) {
stream->write_function(stream, "MAX-REG-PEREXT \t%d\n", profile->max_registrations_perext);
}
stream->write_function(stream, "CALLS-IN \t%d\n", profile->ib_calls);
stream->write_function(stream, "FAILED-CALLS-IN \t%d\n", profile->ib_failed_calls);
stream->write_function(stream, "CALLS-OUT \t%d\n", profile->ob_calls);
stream->write_function(stream, "FAILED-CALLS-OUT \t%d\n", profile->ob_failed_calls);
stream->write_function(stream, "CALLS-IN \t%u\n", profile->ib_calls);
stream->write_function(stream, "FAILED-CALLS-IN \t%u\n", profile->ib_failed_calls);
stream->write_function(stream, "CALLS-OUT \t%u\n", profile->ob_calls);
stream->write_function(stream, "FAILED-CALLS-OUT \t%u\n", profile->ob_failed_calls);
}
stream->write_function(stream, "\nRegistrations:\n%s\n", line);
@@ -2697,10 +2713,10 @@ static void xml_gateway_status(sofia_gateway_t *gp, switch_stream_handle_t *stre
stream->write_function(stream, " <pingfreq>%d</pingfreq>\n", gp->ping_freq);
stream->write_function(stream, " <state>%s</state>\n", sofia_state_names[gp->state]);
stream->write_function(stream, " <status>%s%s</status>\n", status_names[gp->status], gp->pinging ? " (ping)" : "");
stream->write_function(stream, " <calls-in>%d</calls-in>\n", gp->ib_calls);
stream->write_function(stream, " <calls-out>%d</calls-out>\n", gp->ob_calls);
stream->write_function(stream, " <failed-calls-in>%d</failed-calls-in>\n", gp->ib_failed_calls);
stream->write_function(stream, " <failed-calls-out>%d</failed-calls-out>\n", gp->ob_failed_calls);
stream->write_function(stream, " <calls-in>%u</calls-in>\n", gp->ib_calls);
stream->write_function(stream, " <calls-out>%u</calls-out>\n", gp->ob_calls);
stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", gp->ib_failed_calls);
stream->write_function(stream, " <failed-calls-out>%u</failed-calls-out>\n", gp->ob_failed_calls);
if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
time_t now = switch_epoch_time_now(NULL);
@@ -2763,7 +2779,7 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
} else if (!strcasecmp(argv[0], "profile")) {
struct cb_helper cb;
char *sql = NULL;
int x = 0;
uint32_t x = 0;
cb.row_process = 0;
@@ -2819,10 +2835,10 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
stream->write_function(stream, " <user-agent-filter>%s</user-agent-filter>\n", switch_str_nil(profile->user_agent_filter));
stream->write_function(stream, " <max-registrations-per-extension>%d</max-registrations-per-extension>\n",
profile->max_registrations_perext);
stream->write_function(stream, " <calls-in>%d</calls-in>\n", profile->ib_calls);
stream->write_function(stream, " <calls-out>%d</calls-out>\n", profile->ob_calls);
stream->write_function(stream, " <failed-calls-in>%d</failed-calls-in>\n", profile->ib_failed_calls);
stream->write_function(stream, " <failed-calls-out>%d</failed-calls-out>\n", profile->ob_failed_calls);
stream->write_function(stream, " <calls-in>%u</calls-in>\n", profile->ib_calls);
stream->write_function(stream, " <calls-out>%u</calls-out>\n", profile->ob_calls);
stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", profile->ib_failed_calls);
stream->write_function(stream, " <failed-calls-out>%u</failed-calls-out>\n", profile->ob_failed_calls);
stream->write_function(stream, " </profile-info>\n");
}
stream->write_function(stream, " <registrations>\n");
@@ -2951,7 +2967,6 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
sofia_profile_t *profile = NULL;
char *profile_name = argv[0];
const char *err;
switch_xml_t xml_root;
if (argc < 2) {
stream->write_function(stream, "Invalid Args!\n");
@@ -2959,12 +2974,10 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
}
if (!strcasecmp(argv[1], "start")) {
if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) {
if ((xml_root = switch_xml_open_root(1, &err))) {
switch_xml_free(xml_root);
}
stream->write_function(stream, "Reload XML [%s]\n", err);
}
switch_xml_reload(&err);
stream->write_function(stream, "Reload XML [%s]\n", err);
if (config_sofia(1, argv[0]) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "%s started successfully\n", argv[0]);
} else {
@@ -3039,12 +3052,8 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
if (!strcasecmp(argv[1], "rescan")) {
if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) {
if ((xml_root = switch_xml_open_root(1, &err))) {
switch_xml_free(xml_root);
}
stream->write_function(stream, "Reload XML [%s]\n", err);
}
switch_xml_reload(&err);
stream->write_function(stream, "Reload XML [%s]\n", err);
if (reconfig_sofia(profile) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK scan complete\n");
@@ -3141,12 +3150,8 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
profile->name, rsec, remain, remain == 1 ? "" : "s");
} else {
if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) {
if ((xml_root = switch_xml_open_root(1, &err))) {
switch_xml_free(xml_root);
}
stream->write_function(stream, "Reload XML [%s]\n", err);
}
switch_xml_reload(&err);
stream->write_function(stream, "Reload XML [%s]\n", err);
if (!strcasecmp(argv[1], "stop")) {
sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
@@ -3171,6 +3176,21 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
goto done;
}
if (!strcasecmp(argv[1], "gwlist")) {
int up = 1;
if (argc > 2) {
if (!strcasecmp(argv[2], "down")) {
up = 0;
}
}
sofia_glue_gateway_list(profile, stream, up);
goto done;
}
stream->write_function(stream, "-ERR Unknown command!\n");
done:
@@ -3487,7 +3507,7 @@ SWITCH_STANDARD_API(sofia_function)
const char *usage_string = "USAGE:\n"
"--------------------------------------------------------------------------------\n"
"sofia help\n"
"sofia profile <profile_name> [[start|stop|restart|rescan] [reloadxml]|"
"sofia profile <profile_name> [[start|stop|restart|rescan]|"
"flush_inbound_reg [<call_id>] [reboot]|"
"[register|unregister] [<gateway name>|all]|"
"killgw <gateway name>|"
@@ -3497,6 +3517,7 @@ SWITCH_STANDARD_API(sofia_function)
"sofia status|xmlstatus gateway <name>\n"
"sofia loglevel <all|default|tport|iptsec|nea|nta|nth_client|nth_server|nua|soa|sresolv|stun> [0-9]\n"
"sofia tracelevel <console|alert|crit|err|warning|notice|info|debug>\n"
"sofa global siptrace [on|off]\n"
"--------------------------------------------------------------------------------\n";
if (session) {
@@ -3552,6 +3573,26 @@ SWITCH_STANDARD_API(sofia_function)
} else if (!strcasecmp(argv[0], "help")) {
stream->write_function(stream, "%s", usage_string);
goto done;
} else if (!strcasecmp(argv[0], "global")) {
int on = -1;
if (argc > 1) {
if (!strcasecmp(argv[1], "siptrace")) {
if (argc > 2) {
on = switch_true(argv[2]);
}
}
}
if (on != -1) {
sofia_glue_global_siptrace(on);
stream->write_function(stream, "+OK Global siptrace %s", on ? "on" : "off");
} else {
stream->write_function(stream, "-ERR Usage: siptrace on|off");
}
goto done;
} else if (!strcasecmp(argv[0], "recover")) {
if (argv[1] && !strcasecmp(argv[1], "flush")) {
sofia_glue_recover(SWITCH_TRUE);
@@ -4353,7 +4394,8 @@ static void general_event_handler(switch_event_t *event)
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
int rb = 0, x = 0;
int rb = 0;
uint32_t x = 0;
switch_hash_this(hi, &var, NULL, &val);
if ((profile = (sofia_profile_t *) val) && profile->auto_restart) {
if (!strcmp(profile->sipip, old_ip4)) {
@@ -4623,15 +4665,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_console_set_complete("add sofia help");
switch_console_set_complete("add sofia status");
switch_console_set_complete("add sofia xmlstatus");
switch_console_set_complete("add sofia loglevel");
switch_console_set_complete("add sofia tracelevel");
switch_console_set_complete("add sofia loglevel ::[all:default:tport:iptsec:nea:nta:nth_client:nth_server:nua:soa:sresolv:stun ::[0:1:2:3:4:5:6:7:8:9");
switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug");
switch_console_set_complete("add sofia global siptrace ::[on:off");
switch_console_set_complete("add sofia profile");
switch_console_set_complete("add sofia profile restart all");
switch_console_set_complete("add sofia profile ::sofia::list_profiles start reloadxml");
switch_console_set_complete("add sofia profile ::sofia::list_profiles stop reloadxml");
switch_console_set_complete("add sofia profile ::sofia::list_profiles rescan reloadxml");
switch_console_set_complete("add sofia profile ::sofia::list_profiles restart reloadxml");
switch_console_set_complete("add sofia profile ::sofia::list_profiles start");
switch_console_set_complete("add sofia profile ::sofia::list_profiles stop");
switch_console_set_complete("add sofia profile ::sofia::list_profiles rescan");
switch_console_set_complete("add sofia profile ::sofia::list_profiles restart");
switch_console_set_complete("add sofia profile ::sofia::list_profiles flush_inbound_reg");
switch_console_set_complete("add sofia profile ::sofia::list_profiles register ::sofia::list_profile_gateway");
@@ -4640,6 +4686,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_console_set_complete("add sofia profile ::sofia::list_profiles siptrace on");
switch_console_set_complete("add sofia profile ::sofia::list_profiles siptrace off");
switch_console_set_complete("add sofia profile ::sofia::list_profiles gwlist up");
switch_console_set_complete("add sofia profile ::sofia::list_profiles gwlist down");
switch_console_set_complete("add sofia status profile ::sofia::list_profiles");
switch_console_set_complete("add sofia status profile ::sofia::list_profiles reg");
switch_console_set_complete("add sofia status gateway ::sofia::list_gateways");
+10
View File
@@ -106,6 +106,7 @@ typedef struct private_object private_object_t;
#define SOFIA_CRYPTO_MANDATORY_VARIABLE "sip_crypto_mandatory"
#define FREESWITCH_SUPPORT "update_display"
#include <switch_stun.h>
#include <sofia-sip/nua.h>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/sdp.h>
@@ -199,6 +200,7 @@ typedef enum {
PFLAG_DISABLE_NAPTR,
PFLAG_AUTOFLUSH,
PFLAG_NAT_OPTIONS_PING,
PFLAG_ALL_REG_OPTIONS_PING,
PFLAG_AUTOFIX_TIMING,
PFLAG_MESSAGE_QUERY_ON_REGISTER,
PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER,
@@ -218,6 +220,7 @@ typedef enum {
PFLAG_T38_PASSTHRU,
PFLAG_CID_IN_1XX,
PFLAG_IN_DIALOG_CHAT,
PFLAG_DEL_SUBS_ON_REG,
/* No new flags below this line */
PFLAG_MAX
} PFLAGS;
@@ -275,6 +278,7 @@ typedef enum {
TFLAG_RECOVERING,
TFLAG_RECOVERING_BRIDGE,
TFLAG_T38_PASSTHRU,
TFLAG_RECOVERED,
/* No new flags below this line */
TFLAG_MAX
} TFLAGS;
@@ -574,6 +578,7 @@ struct private_object {
switch_codec_t read_codec;
switch_codec_t write_codec;
uint32_t codec_ms;
uint32_t bitrate;
switch_caller_profile_t *caller_profile;
uint32_t timestamp_send;
switch_rtp_t *rtp_session;
@@ -939,6 +944,7 @@ switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int
const char *sofia_glue_strip_proto(const char *uri);
switch_status_t reconfig_sofia(sofia_profile_t *profile);
void sofia_glue_del_gateway(sofia_gateway_t *gp);
void sofia_glue_gateway_list(sofia_profile_t *profile, switch_stream_handle_t *stream, int up);
void sofia_glue_del_every_gateway(sofia_profile_t *profile);
void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent,
const char *network_ip);
@@ -1008,3 +1014,7 @@ char *sofia_glue_get_multipart(switch_core_session_t *session, const char *prefi
void sofia_glue_tech_simplify(private_object_t *tech_pvt);
switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *profile, const char *user, const char *host);
switch_bool_t sofia_glue_profile_exists(const char *key);
void sofia_glue_global_siptrace(switch_bool_t on);
void sofia_glue_proxy_codec(switch_core_session_t *session, const char *r_sdp);
switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, switch_event_t **pt);
void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl);
+1 -1
View File
@@ -785,7 +785,7 @@ int dig_addr(struct dig *dig,
char const *tport2 = NULL;
sres_record_t **answers1 = NULL, **answers2 = NULL;
unsigned count1 = 0, count2 = 0, tcount = 0;
int type1 = 0, type2 = 0, family1 = 0, family2 = 0;
uint16_t type1 = 0, type2 = 0, family1 = 0, family2 = 0;
if (dig->ip6 > dig->ip4) {
type1 = sres_type_aaaa, family1 = AF_INET6;
+157 -34
View File
@@ -1225,7 +1225,7 @@ static void sofia_perform_profile_start_failure(sofia_profile_t *profile, char *
#define sofia_profile_start_failure(p, xp) sofia_perform_profile_start_failure(p, xp, __FILE__, __LINE__)
#define SQLLEN 1024 * 64
#define SQLLEN 1024 * 1024
void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread, void *obj)
{
sofia_profile_t *profile = (sofia_profile_t *) obj;
@@ -1233,11 +1233,12 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
uint32_t gateway_loops = 0;
int loops = 0;
uint32_t qsize;
void *pop;
void *pop = NULL;
int loop_count = 0;
switch_size_t sql_len = SQLLEN;
switch_size_t sql_len = 1024 * 32;
char *tmp, *sqlbuf = NULL;
char *sql = NULL;
if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) {
sqlbuf = (char *) malloc(sql_len);
}
@@ -1253,37 +1254,43 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) || qsize) {
if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) {
if (qsize > 0 && (qsize >= 1024 || ++loop_count >= profile->trans_timeout)) {
if (qsize > 0 && (qsize >= 1024 || ++loop_count >= (int)profile->trans_timeout)) {
switch_size_t newlen;
uint32_t itterations = 0;
uint32_t iterations = 0;
switch_size_t len = 0;
switch_mutex_lock(profile->ireg_mutex);
//sofia_glue_actually_execute_sql(profile, "begin;\n", NULL);
while (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
char *sql = (char *) pop;
while (sql || (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop)) {
if (!sql) sql = (char *) pop;
newlen = strlen(sql) + 2;
iterations++;
if (newlen + 10 < SQLLEN) {
itterations++;
if (len + newlen + 10 > sql_len) {
sql_len = len + 10 + SQLLEN;
if (len + newlen + 10 > sql_len) {
switch_size_t new_mlen = len + newlen + 10 + 10240;
if (new_mlen < SQLLEN) {
sql_len = new_mlen;
if (!(tmp = realloc(sqlbuf, sql_len))) {
abort();
break;
}
sqlbuf = tmp;
} else {
goto skip;
}
sprintf(sqlbuf + len, "%s;\n", sql);
len += newlen;
}
free(pop);
sprintf(sqlbuf + len, "%s;\n", sql);
len += newlen;
free(sql);
sql = NULL;
}
skip:
//printf("TRANS:\n%s\n", sqlbuf);
sofia_glue_actually_execute_sql_trans(profile, sqlbuf, NULL);
//sofia_glue_actually_execute_sql(profile, "commit;\n", NULL);
@@ -2258,6 +2265,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
sofia_clear_pflag(profile, PFLAG_PASS_CALLEE_ID);
}
} else if (!strcasecmp(var, "delete-subs-on-register")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_DEL_SUBS_ON_REG);
} else {
sofia_clear_pflag(profile, PFLAG_DEL_SUBS_ON_REG);
}
} else if (!strcasecmp(var, "in-dialog-chat")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_IN_DIALOG_CHAT);
@@ -2305,12 +2318,6 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
sofia_clear_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY);
}
} else if (!strcasecmp(var, "forward-unsolicited-mwi-notify")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY);
} else {
sofia_clear_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY);
}
} else if (!strcasecmp(var, "t38-passthru")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_T38_PASSTHRU);
@@ -2549,6 +2556,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
sofia_clear_pflag(profile, PFLAG_NAT_OPTIONS_PING);
}
} else if (!strcasecmp(var, "all-reg-options-ping")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
} else {
sofia_clear_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
}
} else if (!strcasecmp(var, "inbound-codec-negotiation")) {
if (!strcasecmp(val, "greedy")) {
sofia_set_pflag(profile, PFLAG_GREEDY);
@@ -2860,7 +2873,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
goto done;
}
profile->trans_timeout = 500;
profile->trans_timeout = 100;
profile->auto_rtp_bugs = RTP_BUG_CISCO_SKIP_MARK_BIT_2833;// | RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
@@ -2920,6 +2933,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
}
} else if (!strcasecmp(var, "forward-unsolicited-mwi-notify")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY);
} else {
sofia_clear_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY);
}
} else if (!strcasecmp(var, "user-agent-string")) {
profile->user_agent = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "auto-restart")) {
@@ -2936,6 +2955,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_IN_DIALOG_CHAT);
}
} else if (!strcasecmp(var, "delete-subs-on-register")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_DEL_SUBS_ON_REG);
} else {
sofia_clear_pflag(profile, PFLAG_DEL_SUBS_ON_REG);
}
} else if (!strcasecmp(var, "t38-passthru")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_T38_PASSTHRU);
@@ -3303,6 +3328,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_NAT_OPTIONS_PING);
}
} else if (!strcasecmp(var, "all-options-ping")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
} else {
sofia_clear_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
}
} else if (!strcasecmp(var, "inbound-codec-negotiation")) {
if (!strcasecmp(val, "greedy")) {
sofia_set_pflag(profile, PFLAG_GREEDY);
@@ -3914,6 +3945,23 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
}
#if 0
if (status == 200 && switch_channel_test_flag(channel, CF_PROXY_MEDIA) &&
sip->sip_payload && sip->sip_payload->pl_data && !strcasecmp(tech_pvt->iananame, "PROXY")) {
switch_core_session_t *other_session;
sofia_glue_proxy_codec(session, sip->sip_payload->pl_data);
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
if (switch_core_session_compare(session, other_session)) {
sofia_glue_proxy_codec(other_session, sip->sip_payload->pl_data);
}
switch_core_session_rwunlock(other_session);
}
}
#endif
if ((status == 180 || status == 183 || status == 200)) {
const char *x_freeswitch_support;
@@ -3940,7 +3988,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
if (channel && sip && (status == 300 || status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
sip_contact_t *p_contact = sip->sip_contact;
int i = 0;
char var_name[80];
@@ -4090,7 +4138,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
}
if (tech_pvt && tech_pvt->remote_sdp_str && switch_stristr("m=image", tech_pvt->remote_sdp_str)) {
if (sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) {
has_t38 = 1;
}
@@ -4118,6 +4167,36 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38) {
if (sip->sip_payload && sip->sip_payload->pl_data) {
switch_t38_options_t *t38_options = sofia_glue_extract_t38_options(session, sip->sip_payload->pl_data);
char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
char tmp[32] = "";
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, t38_options->remote_ip);
tech_pvt->remote_sdp_audio_port = t38_options->remote_port;
if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) &&
remote_port == tech_pvt->remote_sdp_audio_port) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
"Audio params are unchanged for %s.\n",
switch_channel_get_name(tech_pvt->channel));
} else {
const char *err = NULL;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
"Audio params changed for %s from %s:%d to %s:%d\n",
switch_channel_get_name(tech_pvt->channel),
remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip,
tech_pvt->remote_sdp_audio_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
}
}
if (t38_options) {
sofia_glue_copy_t38_options(t38_options, other_session);
@@ -4145,16 +4224,13 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38) {
switch_core_session_receive_message(other_session, msg);
if (switch_rtp_ready(tech_pvt->rtp_session) && switch_rtp_ready(other_tech_pvt->rtp_session)) {
switch_rtp_udptl_mode(tech_pvt->rtp_session);
switch_rtp_udptl_mode(other_tech_pvt->rtp_session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating T38 Passthru\n");
}
} else {
switch_core_session_queue_message(other_session, msg);
}
switch_core_session_queue_message(other_session, msg);
switch_core_session_rwunlock(other_session);
}
@@ -4374,7 +4450,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (ss_state == nua_callstate_terminated) {
if ((status == 300 || status == 302 || status == 305) && session) {
if ((status == 300 || status == 301 || status == 302 || status == 305) && session) {
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
@@ -4447,6 +4523,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
}
state_process:
switch ((enum nua_callstate) ss_state) {
@@ -4521,7 +4599,20 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
break;
case nua_callstate_completing:
nua_ack(nh, TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
{
if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
nua_ack(nh,
TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)),
TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)),
TAG_END());
} else {
nua_ack(nh, TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
}
}
goto done;
case nua_callstate_received:
if (!sofia_test_flag(tech_pvt, TFLAG_SDP)) {
@@ -4912,6 +5003,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
sofia_set_flag(tech_pvt, TFLAG_SDP);
switch_channel_mark_answered(channel);
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
&& (other_session = switch_core_session_locate(uuid))) {
@@ -4932,6 +5024,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
sofia_set_flag_locked(tech_pvt, TFLAG_SDP);
switch_channel_mark_answered(channel);
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
goto done;
@@ -5037,6 +5130,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
done:
if ((enum nua_callstate) ss_state == nua_callstate_ready && channel && session && tech_pvt) {
sofia_glue_tech_simplify(tech_pvt);
@@ -5188,7 +5282,6 @@ nua_handle_t *sofia_global_nua_handle_by_replaces(sip_replaces_t *replaces)
}
void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[])
{
/* Incoming refer */
@@ -5761,7 +5854,17 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
if (sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype &&
sip->sip_payload && sip->sip_payload->pl_data) {
if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "dtmf-relay")) {
if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "media_control+xml")) {
switch_core_session_t *other_session;
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
sofia_glue_build_vid_refresh_message(other_session, sip->sip_payload->pl_data);
switch_core_session_rwunlock(other_session);
} else {
sofia_glue_build_vid_refresh_message(session, sip->sip_payload->pl_data);
}
} else if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "dtmf-relay")) {
/* Try and find signal information in the payload */
if ((signal_ptr = switch_stristr("Signal=", sip->sip_payload->pl_data))) {
int tmp;
@@ -5901,6 +6004,26 @@ void sofia_handle_sip_i_reinvite(switch_core_session_t *session,
{
char *call_info = NULL;
if (session && profile && sip && sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
switch_channel_t *channel = switch_core_session_get_channel(session);
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
char network_ip[80];
int network_port = 0;
char via_space[2048];
char branch[16] = "";
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port);
switch_stun_random_string(branch, sizeof(branch) - 1, "0123456789abcdef");
switch_snprintf(via_space, sizeof(via_space), "SIP/2.0/UDP %s;rport=%d;branch=%s", network_ip, network_port, branch);
switch_channel_set_variable(channel, "sip_full_via", via_space);
switch_channel_set_variable_printf(channel, "sip_network_port", "%d", network_port);
switch_channel_set_variable_printf(channel, "sip_recieved_port", "%d", network_port);
switch_channel_set_variable_printf(channel, "sip_via_rport", "%d", network_port);
sofia_glue_tech_track(tech_pvt->profile, session);
}
if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
switch_channel_t *channel = switch_core_session_get_channel(session);
if (channel && sip->sip_call_info) {
File diff suppressed because it is too large. Load diff
+15 -3
View File
@@ -1442,7 +1442,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
op = switch_event_get_header(helper->event, "Caller-Callee-ID-Number");
}
if (!op) {
if (zstr(op)) {
op = switch_event_get_header(helper->event, "Caller-Destination-Number");
}
@@ -1452,7 +1452,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
if (!strcmp(astate, "early")) {
if (zstr(op)) {
switch_snprintf(status_line, sizeof(status_line), "%s %s", what, status);
switch_snprintf(status_line, sizeof(status_line), "%sing", what);
} else {
switch_snprintf(status_line, sizeof(status_line), "%s %s", what, op);
}
@@ -1983,12 +1983,20 @@ void sofia_presence_handle_sip_i_subscribe(int status,
is_nat = NULL;
}
if (zstr(contact_host)) {
is_nat = "No contact host";
}
if (is_nat) {
contact_host = network_ip;
switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
port = NULL;
}
if (zstr(contact_host)) {
nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END());
return;
}
if (port) {
switch_snprintf(new_port, sizeof(new_port), ":%s", port);
@@ -2043,7 +2051,11 @@ void sofia_presence_handle_sip_i_subscribe(int status,
from_host = "n/a";
}
exp_delta = profile->force_subscription_expires ? profile->force_subscription_expires : (sip->sip_expires ? sip->sip_expires->ex_delta : 3600);
if ((exp_delta = sip->sip_expires ? sip->sip_expires->ex_delta : 3600)) {
if (profile->force_subscription_expires) {
exp_delta = profile->force_subscription_expires;
}
}
if (exp_delta) {
exp_abs = (long) switch_epoch_time_now(NULL) + exp_delta;
+134 -124
View File
@@ -438,11 +438,14 @@ int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames
switch_snprintf(to, sizeof(to), "sip:%s@%s", argv[1], argv[2]);
dst = sofia_glue_get_destination(argv[3]);
switch_assert(dst);
nh = nua_handle(profile->nua, NULL, SIPTAG_FROM_STR(profile->url), SIPTAG_TO_STR(to), NUTAG_URL(dst->contact), SIPTAG_CONTACT_STR(profile->url),
TAG_END());
nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
nua_options(nh, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_END());
nua_options(nh,
NTATAG_SIP_T2(5000),
NTATAG_SIP_T4(10000),
TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_END());
sofia_glue_free_destination(dst);
@@ -514,7 +517,7 @@ int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames
switch_event_fire(&s_event);
}
if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "away");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->url);
@@ -637,15 +640,14 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
if (now) {
switch_snprintf(sql, sizeof(sql),
"select call_id from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'", (long) now,
mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "select call_id from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'",
mod_sofia_globals.hostname);
}
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile);
@@ -670,13 +672,21 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
sofia_glue_actually_execute_sql(profile, sql, NULL);
if (now && sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
"expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where (status like '%%AUTO-NAT%%' "
"or status like '%%UDP-NAT%%') and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
if (now) {
if (sofia_test_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING)) {
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
"expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
} else if (sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
"expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where (status like '%%NAT%%' "
"or contact like '%%fs_nat=yes%%') and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
}
}
switch_mutex_unlock(profile->ireg_mutex);
@@ -810,6 +820,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_t *auth_params = NULL;
int r = 0;
long reg_count = 0;
int delete_subs;
const char *agent = "unknown";
delete_subs = sofia_test_pflag(profile, PFLAG_DEL_SUBS_ON_REG);
/* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */
switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL);
@@ -826,6 +840,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
to = sip->sip_to;
from = sip->sip_from;
if (sip->sip_user_agent) {
agent = sip->sip_user_agent->g_string;
}
if (from) {
from_user = from->a_url->url_user;
from_host = from->a_url->url_host;
@@ -913,7 +931,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (sip->sip_path) {
path_val = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_path);
path_encoded_len = (strlen(path_val) * 3) + 1;
path_encoded_len = (int)(strlen(path_val) * 3) + 1;
switch_zmalloc(path_encoded, path_encoded_len);
switch_copy_string(path_encoded, ";fs_path=", 10);
switch_url_encode(path_val, path_encoded + 9, path_encoded_len - 9);
@@ -926,7 +944,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_snprintf(my_contact_str, sizeof(my_contact_str), "sip:%s@%s:%d", contact->m_url->url_user, url_ip, network_port);
}
path_encoded_len = (strlen(my_contact_str) * 3) + 1;
path_encoded_len = (int)(strlen(my_contact_str) * 3) + 1;
switch_zmalloc(path_encoded, path_encoded_len);
switch_copy_string(path_encoded, ";fs_path=", 10);
@@ -1135,7 +1153,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
if (exptime) {
const char *agent = "dunno";
char guess_ip4[256];
const char *username = "unknown";
const char *realm = reg_host;
@@ -1145,19 +1162,15 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
realm = switch_event_get_header(auth_params, "sip_auth_realm");
}
if (sip->sip_user_agent) {
agent = sip->sip_user_agent->g_string;
}
if (multi_reg) {
#ifdef DEL_SUBS
if (reg_count == 1) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'",
to_user, sub_host, contact_str);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
if (delete_subs) {
if (reg_count == 1) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'",
to_user, sub_host, contact_str);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
}
#endif
if (multi_reg_contact) {
@@ -1167,10 +1180,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
}
} else {
#ifdef DEL_SUBS
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
#endif
if (delete_subs) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
}
switch_mutex_lock(profile->ireg_mutex);
@@ -1185,7 +1198,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
"mwi_user,mwi_host, orig_server_host, orig_hostname) "
"values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q')",
call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : reg_host,
contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime * 2,
contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime + 60,
agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm,
mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname);
@@ -1290,16 +1303,16 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if ((p = strchr(icontact + 4, ':'))) {
*p = '\0';
}
#ifdef DEL_SUBS
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
}
if (delete_subs) {
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
}
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
#endif
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
if (multi_reg_contact) {
sql =
@@ -1312,11 +1325,11 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(icontact);
} else {
#ifdef DEL_SUBS
if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
if (delete_subs) {
if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
}
#endif
if ((sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
@@ -2110,7 +2123,8 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
if (auth_acl) {
if (!switch_check_network_list_ip(ip, auth_acl)) {
int network_ip_is_proxy = 0, x = 0;
int network_ip_is_proxy = 0;
uint32_t x = 0;
char *last_acl = NULL;
if (profile->proxy_acl_count == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by user acl [%s] and no proxy acl present\n", ip, auth_acl);
@@ -2207,7 +2221,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
if (max_registrations_perext > 0 && (sip && sip->sip_contact && (sip->sip_contact->m_expires == NULL || atol(sip->sip_contact->m_expires) > 0))) {
/* if expires is null still process */
/* expires == 0 means the phone is going to unregiser, so don't count against max */
int count = 0;
uint32_t count = 0;
call_id = sip->sip_call_id->i_id;
switch_assert(call_id);
@@ -2292,9 +2306,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "mwi-account", mwi_account);
}
if ((uparams = switch_xml_child(user, "params"))) {
if ((dparams = switch_xml_child(domain, "params"))) {
xparams_type[i] = 0;
xparams[i++] = uparams;
xparams[i++] = dparams;
}
if (group && (gparams = switch_xml_child(group, "params"))) {
@@ -2302,102 +2316,98 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
xparams[i++] = gparams;
}
if ((dparams = switch_xml_child(domain, "params"))) {
if ((uparams = switch_xml_child(user, "params"))) {
xparams_type[i] = 0;
xparams[i++] = dparams;
}
if ((uparams = switch_xml_child(user, "variables"))) {
xparams_type[i] = 1;
xparams[i++] = uparams;
}
if (group && (gparams = switch_xml_child(group, "variables"))) {
xparams_type[i] = 1;
xparams[i++] = gparams;
}
if ((dparams = switch_xml_child(domain, "variables"))) {
xparams_type[i] = 1;
xparams[i++] = dparams;
}
if (group && (gparams = switch_xml_child(group, "variables"))) {
xparams_type[i] = 1;
xparams[i++] = gparams;
}
if ((uparams = switch_xml_child(user, "variables"))) {
xparams_type[i] = 1;
xparams[i++] = uparams;
}
if (i <= 6) {
int j = 0;
const char *gw_val = NULL;
for (j = 0; j < i; j++) {
for (param = switch_xml_child(xparams[j], (xparams_type[j] ? "variable" : "param")); param; param = param->next) {
const char *var = switch_xml_attr_soft(param, "name");
const char *val = switch_xml_attr_soft(param, "value");
sofia_gateway_t *gateway_ptr = NULL;
if (!zstr(var) && !zstr(val) && (xparams_type[j] == 1 || !strncasecmp(var, "sip-", 4) || !strcasecmp(var, "register-gateway"))) {
if (!switch_event_get_header(*v_event, var)) {
if (profile->debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event_add_header -> '%s' = '%s'\n", var, val);
}
switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, var, val);
} else {
continue;
if (profile->debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event_add_header -> '%s' = '%s'\n", var, val);
}
if (!strcasecmp(var, "register-gateway")) {
if (!strcasecmp(val, "all")) {
switch_xml_t gateways_tag, gateway_tag;
if ((gateways_tag = switch_xml_child(user, "gateways"))) {
for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
if (zstr(name)) {
name = "anonymous";
}
if ((gateway_ptr = sofia_reg_find_gateway(name))) {
reg_state_t ostate = gateway_ptr->state;
gateway_ptr->retry = 0;
if (exptime) {
gateway_ptr->state = REG_STATE_UNREGED;
} else {
gateway_ptr->state = REG_STATE_UNREGISTER;
}
if (ostate != gateway_ptr->state) {
sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
}
sofia_reg_release_gateway(gateway_ptr);
}
}
}
} else {
int x, argc;
char *mydata, *argv[50];
mydata = strdup(val);
switch_assert(mydata != NULL);
argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
if ((gateway_ptr = sofia_reg_find_gateway((char *) argv[x]))) {
reg_state_t ostate = gateway_ptr->state;
gateway_ptr->retry = 0;
if (exptime) {
gateway_ptr->state = REG_STATE_UNREGED;
} else {
gateway_ptr->state = REG_STATE_UNREGISTER;
}
if (ostate != gateway_ptr->state) {
sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
}
sofia_reg_release_gateway(gateway_ptr);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Gateway '%s' not found.\n", argv[x]);
}
}
free(mydata);
switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, var, val);
}
}
}
if ((gw_val = switch_event_get_header(*v_event, "register-gateway"))) {
sofia_gateway_t *gateway_ptr = NULL;
if (!strcasecmp(gw_val, "all")) {
switch_xml_t gateways_tag, gateway_tag;
if ((gateways_tag = switch_xml_child(user, "gateways"))) {
for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
if (zstr(name)) {
name = "anonymous";
}
if ((gateway_ptr = sofia_reg_find_gateway(name))) {
reg_state_t ostate = gateway_ptr->state;
gateway_ptr->retry = 0;
if (exptime) {
gateway_ptr->state = REG_STATE_UNREGED;
} else {
gateway_ptr->state = REG_STATE_UNREGISTER;
}
if (ostate != gateway_ptr->state) {
sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
}
sofia_reg_release_gateway(gateway_ptr);
}
}
}
} else {
int x, argc;
char *mydata, *argv[50];
mydata = strdup(gw_val);
switch_assert(mydata != NULL);
argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
if ((gateway_ptr = sofia_reg_find_gateway((char *) argv[x]))) {
reg_state_t ostate = gateway_ptr->state;
gateway_ptr->retry = 0;
if (exptime) {
gateway_ptr->state = REG_STATE_UNREGED;
} else {
gateway_ptr->state = REG_STATE_UNREGISTER;
}
if (ostate != gateway_ptr->state) {
sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
}
sofia_reg_release_gateway(gateway_ptr);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Gateway '%s' not found.\n", argv[x]);
}
}
free(mydata);
}
}
}
@@ -2486,7 +2496,7 @@ sofia_gateway_t *sofia_reg_find_gateway_by_realm__(const char *file, const char
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (hi = switch_hash_first(NULL, mod_sofia_globals.gateway_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((gateway = (sofia_gateway_t *) val) && gateway->register_realm && !strcasecmp(gateway->register_realm, key)) {
if (key && (gateway = (sofia_gateway_t *) val) && gateway->register_realm && !strcasecmp(gateway->register_realm, key)) {
break;
} else {
gateway = NULL;
+1 -1
View File
@@ -1100,7 +1100,7 @@ static int web_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct holder *holder = (struct holder *) pArg;
char title_b4[128] = "";
char title_aft[128 * 3] = "";
char title_aft[128 * 3 + 1] = "";
char *mp3, *m3u;
/*
@@ -213,12 +213,12 @@ public class CoreSession {
return freeswitchJNI.CoreSession_transfer(swigCPtr, this, extension, dialplan, context);
}
public String read(int min_digits, int max_digits, String prompt_audio_file, int timeout, String valid_terminators) {
return freeswitchJNI.CoreSession_read(swigCPtr, this, min_digits, max_digits, prompt_audio_file, timeout, valid_terminators);
public String read(int min_digits, int max_digits, String prompt_audio_file, int timeout, String valid_terminators, int digit_timeout) {
return freeswitchJNI.CoreSession_read(swigCPtr, this, min_digits, max_digits, prompt_audio_file, timeout, valid_terminators, digit_timeout);
}
public String playAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, String terminators, String audio_files, String bad_input_audio_files, String digits_regex, String var_name) {
return freeswitchJNI.CoreSession_playAndGetDigits(swigCPtr, this, min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, digits_regex, var_name);
public String playAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, String terminators, String audio_files, String bad_input_audio_files, String digits_regex, String var_name, int digit_timeout) {
return freeswitchJNI.CoreSession_playAndGetDigits(swigCPtr, this, min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, digits_regex, var_name, digit_timeout);
}
public int streamFile(String file, int starting_sample_count) {
@@ -125,8 +125,8 @@ class freeswitchJNI {
public final static native String CoreSession_getDigits__SWIG_0(long jarg1, CoreSession jarg1_, int jarg2, String jarg3, int jarg4);
public final static native String CoreSession_getDigits__SWIG_1(long jarg1, CoreSession jarg1_, int jarg2, String jarg3, int jarg4, int jarg5);
public final static native int CoreSession_transfer(long jarg1, CoreSession jarg1_, String jarg2, String jarg3, String jarg4);
public final static native String CoreSession_read(long jarg1, CoreSession jarg1_, int jarg2, int jarg3, String jarg4, int jarg5, String jarg6);
public final static native String CoreSession_playAndGetDigits(long jarg1, CoreSession jarg1_, int jarg2, int jarg3, int jarg4, int jarg5, String jarg6, String jarg7, String jarg8, String jarg9, String jarg10);
public final static native String CoreSession_read(long jarg1, CoreSession jarg1_, int jarg2, int jarg3, String jarg4, int jarg5, String jarg6, int jarg7);
public final static native String CoreSession_playAndGetDigits(long jarg1, CoreSession jarg1_, int jarg2, int jarg3, int jarg4, int jarg5, String jarg6, String jarg7, String jarg8, String jarg9, String jarg10, int jarg11);
public final static native int CoreSession_streamFile(long jarg1, CoreSession jarg1_, String jarg2, int jarg3);
public final static native int CoreSession_sleep(long jarg1, CoreSession jarg1_, int jarg2, int jarg3);
public final static native int CoreSession_flushEvents(long jarg1, CoreSession jarg1_);
@@ -2405,7 +2405,7 @@ SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1tran
}
SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1read(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3, jstring jarg4, jint jarg5, jstring jarg6) {
SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1read(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3, jstring jarg4, jint jarg5, jstring jarg6, jint jarg7) {
jstring jresult = 0 ;
CoreSession *arg1 = (CoreSession *) 0 ;
int arg2 ;
@@ -2413,6 +2413,7 @@ SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1r
char *arg4 = (char *) 0 ;
int arg5 ;
char *arg6 = (char *) 0 ;
int arg7 = (int) 0 ;
char *result = 0 ;
(void)jenv;
@@ -2432,7 +2433,8 @@ SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1r
arg6 = (char *)jenv->GetStringUTFChars(jarg6, 0);
if (!arg6) return 0;
}
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6);
arg7 = (int)jarg7;
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6,arg7);
if(result) jresult = jenv->NewStringUTF((const char *)result);
if (arg4) jenv->ReleaseStringUTFChars(jarg4, (const char *)arg4);
if (arg6) jenv->ReleaseStringUTFChars(jarg6, (const char *)arg6);
@@ -2440,7 +2442,7 @@ SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1r
}
SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1playAndGetDigits(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3, jint jarg4, jint jarg5, jstring jarg6, jstring jarg7, jstring jarg8, jstring jarg9, jstring jarg10) {
SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1playAndGetDigits(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3, jint jarg4, jint jarg5, jstring jarg6, jstring jarg7, jstring jarg8, jstring jarg9, jstring jarg10, jint jarg11) {
jstring jresult = 0 ;
CoreSession *arg1 = (CoreSession *) 0 ;
int arg2 ;
@@ -2452,6 +2454,7 @@ SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1p
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
char *arg10 = (char *) NULL ;
int arg11 = (int) 0 ;
char *result = 0 ;
(void)jenv;
@@ -2487,7 +2490,8 @@ SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1p
arg10 = (char *)jenv->GetStringUTFChars(jarg10, 0);
if (!arg10) return 0;
}
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10);
arg11 = (int)jarg11;
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10,arg11);
if(result) jresult = jenv->NewStringUTF((const char *)result);
if (arg6) jenv->ReleaseStringUTFChars(jarg6, (const char *)arg6);
if (arg7) jenv->ReleaseStringUTFChars(jarg7, (const char *)arg7);
+9 -2
View File
@@ -19,8 +19,15 @@
/* Lua function typemap */
%typemap(in,checkfn="lua_isfunction") SWIGLUA_FN
%{ $1.L=L; $1.idx=$input; %}
%typemap(in, checkfn = "lua_isfunction") SWIGLUA_FN {
$1.L = L;
$1.idx = $input;
}
%typemap(default) SWIGLUA_FN {
SWIGLUA_FN default_swiglua_fn = { 0 };
$1 = default_swiglua_fn;
}
%ignore SwitchToMempool;
+8 -3
View File
@@ -367,10 +367,15 @@ int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
{
if (connected) {
if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
return true;
if (lua_fun.L) {
if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
return true;
}
} else { /* if no lua_fun arg is passed from Lua, an empty initialized struct will be sent - see freeswitch.i */
if (switch_cache_db_execute_sql(dbh, sql, NULL) == SWITCH_STATUS_SUCCESS) {
return true;
}
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no workie workie :(\n");
return false;
}
+1 -1
View File
@@ -588,7 +588,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load)
SWITCH_ADD_API(api_interface, "luarun", "run a script", luarun_api_function, "<script>");
SWITCH_ADD_API(api_interface, "lua", "run a script as an api function", lua_api_function, "<script>");
SWITCH_ADD_APP(app_interface, "lua", "Launch LUA ivr", "Run a lua ivr on a channel", lua_function, "<script>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "lua", "Launch LUA ivr", "Run a lua ivr on a channel", lua_function, "<script>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_DIALPLAN(dp_interface, "LUA", lua_dialplan_hunt);
+28 -7
View File
@@ -5175,15 +5175,17 @@ static int _wrap_CoreSession_read(lua_State* L) {
char *arg4 = (char *) 0 ;
int arg5 ;
char *arg6 = (char *) 0 ;
int arg7 = (int) 0 ;
char *result = 0 ;
SWIG_check_num_args("read",6,6)
SWIG_check_num_args("read",6,7)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("read",1,"CoreSession *");
if(!lua_isnumber(L,2)) SWIG_fail_arg("read",2,"int");
if(!lua_isnumber(L,3)) SWIG_fail_arg("read",3,"int");
if(!lua_isstring(L,4)) SWIG_fail_arg("read",4,"char const *");
if(!lua_isnumber(L,5)) SWIG_fail_arg("read",5,"int");
if(!lua_isstring(L,6)) SWIG_fail_arg("read",6,"char const *");
if(lua_gettop(L)>=7 && !lua_isnumber(L,7)) SWIG_fail_arg("read",7,"int");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_CoreSession,0))){
SWIG_fail_ptr("CoreSession_read",1,SWIGTYPE_p_CoreSession);
@@ -5194,7 +5196,10 @@ static int _wrap_CoreSession_read(lua_State* L) {
arg4 = (char *)lua_tostring(L, 4);
arg5 = (int)lua_tonumber(L, 5);
arg6 = (char *)lua_tostring(L, 6);
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6);
if(lua_gettop(L)>=7){
arg7 = (int)lua_tonumber(L, 7);
}
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6,arg7);
SWIG_arg=0;
lua_pushstring(L,(const char*)result); SWIG_arg++;
return SWIG_arg;
@@ -5219,9 +5224,10 @@ static int _wrap_CoreSession_playAndGetDigits(lua_State* L) {
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
char *arg10 = (char *) NULL ;
int arg11 = (int) 0 ;
char *result = 0 ;
SWIG_check_num_args("playAndGetDigits",9,10)
SWIG_check_num_args("playAndGetDigits",9,11)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("playAndGetDigits",1,"CoreSession *");
if(!lua_isnumber(L,2)) SWIG_fail_arg("playAndGetDigits",2,"int");
if(!lua_isnumber(L,3)) SWIG_fail_arg("playAndGetDigits",3,"int");
@@ -5232,6 +5238,7 @@ static int _wrap_CoreSession_playAndGetDigits(lua_State* L) {
if(!lua_isstring(L,8)) SWIG_fail_arg("playAndGetDigits",8,"char *");
if(!lua_isstring(L,9)) SWIG_fail_arg("playAndGetDigits",9,"char *");
if(lua_gettop(L)>=10 && !lua_isstring(L,10)) SWIG_fail_arg("playAndGetDigits",10,"char const *");
if(lua_gettop(L)>=11 && !lua_isnumber(L,11)) SWIG_fail_arg("playAndGetDigits",11,"int");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_CoreSession,0))){
SWIG_fail_ptr("CoreSession_playAndGetDigits",1,SWIGTYPE_p_CoreSession);
@@ -5248,7 +5255,10 @@ static int _wrap_CoreSession_playAndGetDigits(lua_State* L) {
if(lua_gettop(L)>=10){
arg10 = (char *)lua_tostring(L, 10);
}
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10);
if(lua_gettop(L)>=11){
arg11 = (int)lua_tonumber(L, 11);
}
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10,arg11);
SWIG_arg=0;
lua_pushstring(L,(const char*)result); SWIG_arg++;
return SWIG_arg;
@@ -7191,17 +7201,28 @@ static int _wrap_Dbh_query(lua_State* L) {
SWIGLUA_FN arg3 ;
bool result;
SWIG_check_num_args("query",3,3)
{
SWIGLUA_FN default_swiglua_fn = {
0
};
arg3 = default_swiglua_fn;
}
SWIG_check_num_args("query",2,3)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("query",1,"LUA::Dbh *");
if(!lua_isstring(L,2)) SWIG_fail_arg("query",2,"char *");
if(!lua_isfunction(L,3)) SWIG_fail_arg("query",3,"SWIGLUA_FN");
if(lua_gettop(L)>=3 && !lua_isfunction(L,3)) SWIG_fail_arg("query",3,"SWIGLUA_FN");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_query",1,SWIGTYPE_p_LUA__Dbh);
}
arg2 = (char *)lua_tostring(L, 2);
(&arg3)->L=L; (&arg3)->idx=3;
if(lua_gettop(L)>=3){
{
(&arg3)->L = L;
(&arg3)->idx = 3;
}
}
result = (bool)(arg1)->query(arg2,arg3);
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
+4 -1
View File
@@ -193,7 +193,10 @@ char * SWIG_csharp_string_callback(const char * str) {
%include switch_core_db.h
%include switch_regex.h
%include switch_core.h
//%include switch_loadable_module.h // todo: Sort out some linking issues
%ignore switch_module_runtime;
%ignore switch_module_load;
%ignore switch_module_shutdown;
%include switch_loadable_module.h // note: Above three ignore lines sort out some linking issues
%include switch_console.h // Has unsupported varargs functions
%include switch_utils.h
%include switch_caller.h
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+30 -6
View File
@@ -6637,6 +6637,7 @@ XS(_wrap_CoreSession_read) {
char *arg4 = (char *) 0 ;
int arg5 ;
char *arg6 = (char *) 0 ;
int arg7 = (int) 0 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
@@ -6652,11 +6653,13 @@ XS(_wrap_CoreSession_read) {
int res6 ;
char *buf6 = 0 ;
int alloc6 = 0 ;
int val7 ;
int ecode7 = 0 ;
int argvi = 0;
dXSARGS;
if ((items < 6) || (items > 6)) {
SWIG_croak("Usage: CoreSession_read(self,min_digits,max_digits,prompt_audio_file,timeout,valid_terminators);");
if ((items < 6) || (items > 7)) {
SWIG_croak("Usage: CoreSession_read(self,min_digits,max_digits,prompt_audio_file,timeout,valid_terminators,digit_timeout);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
@@ -6688,7 +6691,14 @@ XS(_wrap_CoreSession_read) {
SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "CoreSession_read" "', argument " "6"" of type '" "char const *""'");
}
arg6 = reinterpret_cast< char * >(buf6);
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6);
if (items > 6) {
ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
if (!SWIG_IsOK(ecode7)) {
SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "CoreSession_read" "', argument " "7"" of type '" "int""'");
}
arg7 = static_cast< int >(val7);
}
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6,arg7);
ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ;
@@ -6696,6 +6706,7 @@ XS(_wrap_CoreSession_read) {
if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
XSRETURN(argvi);
fail:
@@ -6704,6 +6715,7 @@ XS(_wrap_CoreSession_read) {
if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
SWIG_croak_null();
}
}
@@ -6721,6 +6733,7 @@ XS(_wrap_CoreSession_playAndGetDigits) {
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
char *arg10 = (char *) NULL ;
int arg11 = (int) 0 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
@@ -6747,11 +6760,13 @@ XS(_wrap_CoreSession_playAndGetDigits) {
int res10 ;
char *buf10 = 0 ;
int alloc10 = 0 ;
int val11 ;
int ecode11 = 0 ;
int argvi = 0;
dXSARGS;
if ((items < 9) || (items > 10)) {
SWIG_croak("Usage: CoreSession_playAndGetDigits(self,min_digits,max_digits,max_tries,timeout,terminators,audio_files,bad_input_audio_files,digits_regex,var_name);");
if ((items < 9) || (items > 11)) {
SWIG_croak("Usage: CoreSession_playAndGetDigits(self,min_digits,max_digits,max_tries,timeout,terminators,audio_files,bad_input_audio_files,digits_regex,var_name,digit_timeout);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
@@ -6805,7 +6820,14 @@ XS(_wrap_CoreSession_playAndGetDigits) {
}
arg10 = reinterpret_cast< char * >(buf10);
}
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10);
if (items > 10) {
ecode11 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(10), &val11);
if (!SWIG_IsOK(ecode11)) {
SWIG_exception_fail(SWIG_ArgError(ecode11), "in method '" "CoreSession_playAndGetDigits" "', argument " "11"" of type '" "int""'");
}
arg11 = static_cast< int >(val11);
}
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10,arg11);
ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ;
@@ -6817,6 +6839,7 @@ XS(_wrap_CoreSession_playAndGetDigits) {
if (alloc8 == SWIG_NEWOBJ) delete[] buf8;
if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
if (alloc10 == SWIG_NEWOBJ) delete[] buf10;
XSRETURN(argvi);
fail:
@@ -6829,6 +6852,7 @@ XS(_wrap_CoreSession_playAndGetDigits) {
if (alloc8 == SWIG_NEWOBJ) delete[] buf8;
if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
if (alloc10 == SWIG_NEWOBJ) delete[] buf10;
SWIG_croak_null();
}
}
@@ -7025,6 +7025,7 @@ SWIGINTERN PyObject *_wrap_CoreSession_read(PyObject *SWIGUNUSEDPARM(self), PyOb
char *arg4 = (char *) 0 ;
int arg5 ;
char *arg6 = (char *) 0 ;
int arg7 = (int) 0 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
@@ -7040,14 +7041,17 @@ SWIGINTERN PyObject *_wrap_CoreSession_read(PyObject *SWIGUNUSEDPARM(self), PyOb
int res6 ;
char *buf6 = 0 ;
int alloc6 = 0 ;
int val7 ;
int ecode7 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
PyObject * obj3 = 0 ;
PyObject * obj4 = 0 ;
PyObject * obj5 = 0 ;
PyObject * obj6 = 0 ;
if (!PyArg_ParseTuple(args,(char *)"OOOOOO:CoreSession_read",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
if (!PyArg_ParseTuple(args,(char *)"OOOOOO|O:CoreSession_read",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_read" "', argument " "1"" of type '" "CoreSession *""'");
@@ -7078,7 +7082,14 @@ SWIGINTERN PyObject *_wrap_CoreSession_read(PyObject *SWIGUNUSEDPARM(self), PyOb
SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "CoreSession_read" "', argument " "6"" of type '" "char const *""'");
}
arg6 = reinterpret_cast< char * >(buf6);
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6);
if (obj6) {
ecode7 = SWIG_AsVal_int(obj6, &val7);
if (!SWIG_IsOK(ecode7)) {
SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "CoreSession_read" "', argument " "7"" of type '" "int""'");
}
arg7 = static_cast< int >(val7);
}
result = (char *)(arg1)->read(arg2,arg3,(char const *)arg4,arg5,(char const *)arg6,arg7);
resultobj = SWIG_FromCharPtr((const char *)result);
if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
@@ -7102,6 +7113,7 @@ SWIGINTERN PyObject *_wrap_CoreSession_playAndGetDigits(PyObject *SWIGUNUSEDPARM
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
char *arg10 = (char *) NULL ;
int arg11 = (int) 0 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
@@ -7128,6 +7140,8 @@ SWIGINTERN PyObject *_wrap_CoreSession_playAndGetDigits(PyObject *SWIGUNUSEDPARM
int res10 ;
char *buf10 = 0 ;
int alloc10 = 0 ;
int val11 ;
int ecode11 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
@@ -7138,8 +7152,9 @@ SWIGINTERN PyObject *_wrap_CoreSession_playAndGetDigits(PyObject *SWIGUNUSEDPARM
PyObject * obj7 = 0 ;
PyObject * obj8 = 0 ;
PyObject * obj9 = 0 ;
PyObject * obj10 = 0 ;
if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO|O:CoreSession_playAndGetDigits",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9)) SWIG_fail;
if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO|OO:CoreSession_playAndGetDigits",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_playAndGetDigits" "', argument " "1"" of type '" "CoreSession *""'");
@@ -7192,7 +7207,14 @@ SWIGINTERN PyObject *_wrap_CoreSession_playAndGetDigits(PyObject *SWIGUNUSEDPARM
}
arg10 = reinterpret_cast< char * >(buf10);
}
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10);
if (obj10) {
ecode11 = SWIG_AsVal_int(obj10, &val11);
if (!SWIG_IsOK(ecode11)) {
SWIG_exception_fail(SWIG_ArgError(ecode11), "in method '" "CoreSession_playAndGetDigits" "', argument " "11"" of type '" "int""'");
}
arg11 = static_cast< int >(val11);
}
result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,(char const *)arg10,arg11);
resultobj = SWIG_FromCharPtr((const char *)result);
if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
+1 -1
View File
@@ -264,7 +264,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
if (globals.encode == ENCODING_TEXTXML) {
headers = curl_slist_append(headers, "Content-Type: text/xml");
} else if (globals.encode) {
switch_size_t need_bytes = strlen(xml_text) * 3;
switch_size_t need_bytes = strlen(xml_text) * 3 + 1;
xml_text_escaped = malloc(need_bytes);
switch_assert(xml_text_escaped);
@@ -275,7 +275,6 @@ static abyss_bool is_authorized(const TSession * r, const char *command)
err = 686;
status = "EXECUTION OF SPECIFIED API COMMAND NOT PERMITTED IN USER ACCOUNT";
if (!user_attributes(user, domain_name, NULL, NULL, NULL, &allowed_commands)) {
goto end;
@@ -305,11 +304,6 @@ static abyss_bool is_authorized(const TSession * r, const char *command)
if (!ok) {
ResponseStatus(r, err);
if (status) {
ResponseError2(r, status);
} else {
ResponseError(r);
}
}