Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva committed 2011-01-31 15:56:30 -05:00
commit 0fa9f47c25
76 files changed
+5846 -2191

No files matched your search

+1 -1
View File
@@ -192,7 +192,7 @@ static inline char switch_itodtmf(char i)
r = i + 55;
}
return r;
return r + 48;
}
static inline int switch_dtmftoi(char *s)
@@ -2372,7 +2372,7 @@ SWITCH_STANDARD_API(uuid_media_function)
return SWITCH_STATUS_SUCCESS;
}
#define BROADCAST_SYNTAX "<uuid> <path> [aleg|bleg|both]"
#define BROADCAST_SYNTAX "<uuid> <path> [aleg|bleg|holdb|both]"
SWITCH_STANDARD_API(uuid_broadcast_function)
{
char *mycmd = NULL, *argv[4] = { 0 };
@@ -2389,15 +2389,26 @@ SWITCH_STANDARD_API(uuid_broadcast_function)
switch_media_flag_t flags = SMF_NONE;
if (argv[2]) {
if (!strcasecmp(argv[2], "both")) {
if (switch_stristr("both", (argv[2]))) {
flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG);
} else if (!strcasecmp(argv[2], "aleg")) {
}
if (switch_stristr("aleg", argv[2])) {
flags |= SMF_ECHO_ALEG;
} else if (!strcasecmp(argv[2], "bleg")) {
}
if (switch_stristr("bleg", argv[2])) {
flags &= ~SMF_HOLD_BLEG;
flags |= SMF_ECHO_BLEG;
}
if (switch_stristr("holdb", argv[2])) {
flags &= ~SMF_ECHO_BLEG;
flags |= SMF_HOLD_BLEG;
}
} else {
flags |= SMF_ECHO_ALEG;
flags = SMF_ECHO_ALEG | SMF_HOLD_BLEG;
}
status = switch_ivr_broadcast(argv[0], argv[1], flags);
@@ -152,7 +152,8 @@ typedef enum {
CFLAG_BRIDGE_TO = (1 << 6),
CFLAG_WAIT_MOD = (1 << 7),
CFLAG_VID_FLOOR = (1 << 8),
CFLAG_WASTE_BANDWIDTH = (1 << 9)
CFLAG_WASTE_BANDWIDTH = (1 << 9),
CFLAG_OUTCALL = (1 << 10)
} conf_flag_t;
typedef enum {
@@ -288,6 +289,8 @@ typedef struct conference_obj {
uint32_t avg_tally;
switch_time_t run_time;
char *uuid_str;
uint32_t originating;
switch_call_cause_t cancel_cause;
} conference_obj_t;
/* Relationship with another member */
@@ -395,11 +398,16 @@ SWITCH_STANDARD_API(conf_api_main);
static switch_status_t conference_outcall(conference_obj_t *conference,
char *conference_name,
switch_core_session_t *session,
char *bridgeto, uint32_t timeout, char *flags, char *cid_name, char *cid_num, switch_call_cause_t *cause);
char *bridgeto, uint32_t timeout,
char *flags,
char *cid_name,
char *cid_num,
switch_call_cause_t *cause,
switch_call_cause_t *cancel_cause);
static switch_status_t conference_outcall_bg(conference_obj_t *conference,
char *conference_name,
switch_core_session_t *session, char *bridgeto, uint32_t timeout, const char *flags, const char *cid_name,
const char *cid_num, const char *call_uuid);
const char *cid_num, const char *call_uuid, switch_call_cause_t *cancel_cause);
SWITCH_STANDARD_APP(conference_function);
static void launch_conference_thread(conference_obj_t *conference);
static void launch_conference_video_thread(conference_obj_t *conference);
@@ -477,6 +485,7 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Mute-Detect", "%s", switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", switch_test_flag(member, MFLAG_MOD) ? "moderator" : "member");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Energy-Level", "%d", member->energy_level);
return status;
}
@@ -1380,6 +1389,14 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
/* Rinse ... Repeat */
end:
if (switch_test_flag(conference, CFLAG_OUTCALL)) {
conference->cancel_cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Ending pending outcall channels for Conference: '%s'\n", conference->name);
while(conference->originating) {
switch_yield(200000);
}
}
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference->name);
@@ -2403,6 +2420,8 @@ static void conference_loop_output(conference_member_t *member)
switch_channel_set_private(channel, "_conference_autocall_list_", NULL);
switch_set_flag(member->conference, CFLAG_OUTCALL);
if (toval) {
to = atoi(toval);
if (to < 10 || to > 500) {
@@ -2421,7 +2440,8 @@ static void conference_loop_output(conference_member_t *member)
for (x = 0; x < argc; x++) {
char *dial_str = switch_mprintf("%s%s", switch_str_nil(prefix), argv[x]);
switch_assert(dial_str);
conference_outcall_bg(member->conference, NULL, NULL, dial_str, to, switch_str_nil(flags), cid_name, cid_num, NULL);
conference_outcall_bg(member->conference, NULL, NULL, dial_str, to, switch_str_nil(flags), cid_name, cid_num, NULL,
&member->conference->cancel_cause);
switch_safe_free(dial_str);
}
switch_safe_free(cpstr);
@@ -4243,9 +4263,9 @@ static switch_status_t conf_api_sub_dial(conference_obj_t *conference, switch_st
}
if (conference) {
conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], &cause);
conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], &cause, NULL);
} else {
conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], &cause);
conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], &cause, NULL);
}
stream->write_function(stream, "Call Requested: result: [%s]\n", switch_channel_cause2str(cause));
@@ -4268,9 +4288,9 @@ static switch_status_t conf_api_sub_bgdial(conference_obj_t *conference, switch_
switch_uuid_format(uuid_str, &uuid);
if (conference) {
conference_outcall_bg(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str);
conference_outcall_bg(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL);
} else {
conference_outcall_bg(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str);
conference_outcall_bg(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL);
}
stream->write_function(stream, "OK Job-UUID: %s\n", uuid_str);
@@ -4784,7 +4804,11 @@ SWITCH_STANDARD_API(conf_api_main)
static switch_status_t conference_outcall(conference_obj_t *conference,
char *conference_name,
switch_core_session_t *session,
char *bridgeto, uint32_t timeout, char *flags, char *cid_name, char *cid_num, switch_call_cause_t *cause)
char *bridgeto, uint32_t timeout,
char *flags, char *cid_name,
char *cid_num,
switch_call_cause_t *cause,
switch_call_cause_t *cancel_cause)
{
switch_core_session_t *peer_session = NULL;
switch_channel_t *peer_channel;
@@ -4830,8 +4854,15 @@ static switch_status_t conference_outcall(conference_obj_t *conference,
/* establish an outbound call leg */
if (switch_ivr_originate(session, &peer_session, cause, bridgeto, timeout, NULL, cid_name, cid_num, NULL, NULL, SOF_NO_LIMITS, NULL) !=
SWITCH_STATUS_SUCCESS) {
switch_mutex_lock(conference->mutex);
conference->originating++;
switch_mutex_unlock(conference->mutex);
status = switch_ivr_originate(session, &peer_session, cause, bridgeto, timeout, NULL, cid_name, cid_num, NULL, NULL, SOF_NO_LIMITS, cancel_cause);
switch_mutex_lock(conference->mutex);
conference->originating--;
switch_mutex_unlock(conference->mutex);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot create outgoing channel, cause: %s\n",
switch_channel_cause2str(*cause));
if (caller_channel) {
@@ -4908,6 +4939,7 @@ struct bg_call {
char *cid_num;
char *conference_name;
char *uuid;
switch_call_cause_t *cancel_cause;
switch_memory_pool_t *pool;
};
@@ -4920,7 +4952,7 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread,
switch_event_t *event;
conference_outcall(call->conference, call->conference_name,
call->session, call->bridgeto, call->timeout, call->flags, call->cid_name, call->cid_num, &cause);
call->session, call->bridgeto, call->timeout, call->flags, call->cid_name, call->cid_num, &cause, call->cancel_cause);
if (call->conference && test_eflag(call->conference, EFLAG_BGDIAL_RESULT) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
@@ -4948,7 +4980,7 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread,
static switch_status_t conference_outcall_bg(conference_obj_t *conference,
char *conference_name,
switch_core_session_t *session, char *bridgeto, uint32_t timeout, const char *flags, const char *cid_name,
const char *cid_num, const char *call_uuid)
const char *cid_num, const char *call_uuid, switch_call_cause_t *cancel_cause)
{
struct bg_call *call = NULL;
switch_thread_t *thread;
@@ -4962,6 +4994,7 @@ static switch_status_t conference_outcall_bg(conference_obj_t *conference,
call->conference = conference;
call->session = session;
call->timeout = timeout;
call->cancel_cause = cancel_cause;
if (conference) {
pool = conference->pool;
@@ -5664,8 +5697,9 @@ SWITCH_STANDARD_APP(conference_function)
/* more friendliness */
if (conference->bad_pin_sound) {
conference_local_play_file(conference, session, conference->bad_pin_sound, 20, pin_buf, sizeof(pin_buf));
conference_local_play_file(conference, session, conference->bad_pin_sound, 20, NULL, 0);
}
switch_channel_flush_dtmf(channel);
}
pin_retries--;
}
@@ -5715,7 +5749,7 @@ SWITCH_STANDARD_APP(conference_function)
/* if we're using "bridge:" make an outbound call and bridge it in */
if (!zstr(bridgeto) && strcasecmp(bridgeto, "none")) {
switch_call_cause_t cause;
if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, &cause) != SWITCH_STATUS_SUCCESS) {
if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, &cause, NULL) != SWITCH_STATUS_SUCCESS) {
goto done;
}
} else {
@@ -2982,6 +2982,8 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
}
}
}
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", user);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
if (!dest) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
@@ -65,6 +65,7 @@ static struct {
switch_mutex_t *mutex;
char *custom_query;
switch_odbc_handle_t *master_odbc;
int odbc_num_retries;
} globals;
SWITCH_MODULE_LOAD_FUNCTION(mod_easyroute_load);
@@ -120,6 +121,8 @@ static switch_status_t load_config(void)
set_global_default_gateway(val);
} else if (!strcasecmp(var, "custom-query")) {
set_global_custom_query(val);
} else if (!strcasecmp(var, "odbc-retries")) {
globals.odbc_num_retries = atoi(val);
}
}
}
@@ -143,6 +146,9 @@ static switch_status_t load_config(void)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database!\n");
}
if (globals.odbc_num_retries) {
switch_odbc_set_num_retries(globals.master_odbc, globals.odbc_num_retries);
}
if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
status = SWITCH_STATUS_FALSE;
@@ -205,7 +211,7 @@ static switch_status_t route_lookup(char *dn, easyroute_results_t *results, int
switch_mutex_lock(globals.mutex);
}
/* Do the Query */
if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, route_callback, &pdata, NULL) == SWITCH_ODBC_SUCCESS) {
if (globals.master_odbc && switch_odbc_handle_callback_exec(globals.master_odbc, sql, route_callback, &pdata, NULL) == SWITCH_ODBC_SUCCESS) {
char tmp_profile[129];
char tmp_gateway[129];
@@ -418,7 +424,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_easyroute_load)
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_easyroute_shutdown)
{
switch_odbc_handle_disconnect(globals.master_odbc);
if (globals.master_odbc) {
switch_odbc_handle_disconnect(globals.master_odbc);
switch_odbc_handle_destroy(&globals.master_odbc);
}
switch_safe_free(globals.db_username);
switch_safe_free(globals.db_password);
switch_safe_free(globals.db_dsn);
@@ -40,6 +40,9 @@
#define MAX_FEC_ENTRIES 4
#define MAX_FEC_SPAN 4
#define SPANDSP_EVENT_TXFAXRESULT "spandsp::txfaxresult"
#define SPANDSP_EVENT_RXFAXRESULT "spandsp::rxfaxresult"
/*****************************************************************************
OUR DEFINES AND STRUCTS
*****************************************************************************/
@@ -305,7 +308,14 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result)
switch_core_session_t *session;
switch_channel_t *channel;
pvt_t *pvt;
char *tmp;
char *fax_document_transferred_pages = NULL;
char *fax_document_total_pages = NULL;
char *fax_image_resolution = NULL;
char *fax_image_size = NULL;
char *fax_bad_rows = NULL;
char *fax_transfer_rate = NULL;
char *fax_result_code = NULL;
switch_event_t *event;
pvt = (pvt_t *) user_data;
switch_assert(pvt);
@@ -353,13 +363,12 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==============================================================================\n");
/*
Set our channel variables
Set our channel variables, variables are also used in event
*/
tmp = switch_mprintf("%i", result);
if (tmp) {
switch_channel_set_variable(channel, "fax_result_code", tmp);
switch_safe_free(tmp);
fax_result_code = switch_core_session_sprintf(session, "%i", result);
if (fax_result_code) {
switch_channel_set_variable(channel, "fax_result_code", fax_result_code);
}
switch_channel_set_variable(channel, "fax_result_text", t30_completion_code_to_str(result));
@@ -368,49 +377,56 @@ static void phase_e_handler(t30_state_t *s, void *user_data, int result)
switch_channel_set_variable(channel, "fax_local_station_id", local_ident);
switch_channel_set_variable(channel, "fax_remote_station_id", far_ident);
tmp = switch_mprintf("%i", pvt->app_mode == FUNCTION_TX ? t.pages_tx : t.pages_rx);
if (tmp) {
switch_channel_set_variable(channel, "fax_document_transferred_pages", tmp);
switch_safe_free(tmp);
fax_document_transferred_pages = switch_core_session_sprintf(session, "%i", pvt->app_mode == FUNCTION_TX ? t.pages_tx : t.pages_rx);
if (fax_document_transferred_pages) {
switch_channel_set_variable(channel, "fax_document_transferred_pages", fax_document_transferred_pages);
}
tmp = switch_mprintf("%i", t.pages_in_file);
if (tmp) {
switch_channel_set_variable(channel, "fax_document_total_pages", tmp);
switch_safe_free(tmp);
fax_document_total_pages = switch_core_session_sprintf(session, "%i", t.pages_in_file);
if (fax_document_total_pages) {
switch_channel_set_variable(channel, "fax_document_total_pages", fax_document_total_pages);
}
tmp = switch_mprintf("%ix%i", t.x_resolution, t.y_resolution);
if (tmp) {
switch_channel_set_variable(channel, "fax_image_resolution", tmp);
switch_safe_free(tmp);
fax_image_resolution = switch_core_session_sprintf(session, "%ix%i", t.x_resolution, t.y_resolution);
if (fax_image_resolution) {
switch_channel_set_variable(channel, "fax_image_resolution", fax_image_resolution);
}
tmp = switch_mprintf("%d", t.image_size);
if (tmp) {
switch_channel_set_variable(channel, "fax_image_size", tmp);
switch_safe_free(tmp);
fax_image_size = switch_core_session_sprintf(session, "%d", t.image_size);
if (fax_image_size) {
switch_channel_set_variable(channel, "fax_image_size", fax_image_size);
}
tmp = switch_mprintf("%d", t.bad_rows);
if (tmp) {
switch_channel_set_variable(channel, "fax_bad_rows", tmp);
switch_safe_free(tmp);
fax_bad_rows = switch_core_session_sprintf(session, "%d", t.bad_rows);
if (fax_bad_rows) {
switch_channel_set_variable(channel, "fax_bad_rows", fax_bad_rows);
}
tmp = switch_mprintf("%i", t.bit_rate);
if (tmp) {
switch_channel_set_variable(channel, "fax_transfer_rate", tmp);
switch_safe_free(tmp);
fax_transfer_rate = switch_core_session_sprintf(session, "%i", t.bit_rate);
if (fax_transfer_rate) {
switch_channel_set_variable(channel, "fax_transfer_rate", fax_transfer_rate);
}
/* switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); */
pvt->done = 1;
/*
TODO Fire events
*/
/* Fire event */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXRESULT : SPANDSP_EVENT_RXFAXRESULT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-total-pages", fax_document_total_pages);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_image_resolution);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-bad-rows", fax_bad_rows);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-result-code", fax_result_code);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-result-text", t30_completion_code_to_str(result));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t.error_correcting_mode) ? "on" : "off");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-station-id", far_ident);
switch_core_session_queue_private_event(session, &event, SWITCH_FALSE);
}
}
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
@@ -1026,7 +1042,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, "Fax TX filename not set.\n");
goto done;
} else if (pvt->app_mode == FUNCTION_RX) {
char *fname;
const char *prefix;
switch_time_t time;
@@ -1036,11 +1051,7 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
prefix = globals.prepend_string;
}
fname = switch_mprintf("%s/%s-%ld-%ld.tif", globals.spool, prefix, globals.total_sessions, time);
if (fname) {
pvt->filename = switch_core_session_strdup(session, fname);
switch_safe_free(fname);
} else {
if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%ld.tif", globals.spool, prefix, globals.total_sessions, time))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot automatically set fax RX destination file\n");
goto done;
}
+12 -22
View File
@@ -53,8 +53,8 @@ static switch_status_t switch_celt_init(switch_codec_t *codec, switch_codec_flag
return SWITCH_STATUS_FALSE;
}
context->mode_object = celt_mode_create(codec->implementation->actual_samples_per_second, codec->implementation->samples_per_packet, NULL);
context->frame_size = codec->implementation->samples_per_packet;
context->mode_object = celt_mode_create(codec->implementation->actual_samples_per_second, context->frame_size, NULL);
context->bytes_per_packet = (codec->implementation->bits_per_second * context->frame_size / codec->implementation->actual_samples_per_second + 4) / 8;
/*
@@ -106,15 +106,22 @@ static switch_status_t switch_celt_encode(switch_codec_t *codec,
unsigned int *flag)
{
struct celt_context *context = codec->private_info;
int bytes = 0;
if (!context) {
return SWITCH_STATUS_FALSE;
}
*encoded_data_len = (uint32_t) celt_encode(context->encoder_object, (void *) decoded_data, codec->implementation->samples_per_packet,
(unsigned char *) encoded_data, context->bytes_per_packet);
bytes = (uint32_t) celt_encode(context->encoder_object, (void *) decoded_data, codec->implementation->samples_per_packet,
(unsigned char *) encoded_data, context->bytes_per_packet);
return SWITCH_STATUS_SUCCESS;
if (bytes > 0) {
*encoded_data_len = (uint32_t) bytes;
return SWITCH_STATUS_SUCCESS;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Error!\n");
return SWITCH_STATUS_GENERR;
}
static switch_status_t switch_celt_decode(switch_codec_t *codec,
@@ -152,23 +159,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_celt_load)
SWITCH_ADD_CODEC(codec_interface, "CELT ultra-low delay");
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
114, /* the IANA code number */
"CELT", /* the IANA code name */
NULL, /* default fmtp to send (can be overridden by the init function) */
32000, /* samples transferred per second */
32000, /* actual samples transferred per second */
32000, /* bits transferred per second */
10000, /* number of microseconds per frame */
320, /* number of samples per frame */
640, /* 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_celt_init, /* function to initialize a codec handle using this implementation */
switch_celt_encode, /* function to encode raw data into encoded data */
switch_celt_decode, /* function to decode encoded data into raw data */
switch_celt_destroy); /* deinitalize a codec handle using this implementation */
ms_per_frame = 2000;
samples_per_frame = 96;
bytes_per_frame = 192;
+2
View File
@@ -1,2 +1,4 @@
!/gsmlib/gsmlib-*/aclocal.m4
!/gsmlib/gsmlib-*/configure
!/gsmlib/gsmlib-1.10.tar.gz
!/gsmlib/gsmlib_1.10-12ubuntu1.diff.gz
+6 -18
View File
@@ -77,11 +77,11 @@ struct private_object {
switch_frame_t cng_frame;
unsigned char cng_databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
switch_timer_t timer;
switch_caller_profile_t *caller_profile;
int32_t bowout_frame_count;
char *other_uuid;
switch_queue_t *frame_queue;
switch_codec_implementation_t read_impl;
};
typedef struct private_object private_t;
@@ -111,7 +111,6 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses
int interval = 20;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_channel_t *channel = switch_core_session_get_channel(session);
const switch_codec_implementation_t *read_impl;
if (codec) {
iananame = codec->implementation->iananame;
@@ -166,15 +165,7 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses
switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
if (tech_pvt->flag_mutex) {
switch_core_timer_destroy(&tech_pvt->timer);
}
read_impl = tech_pvt->read_codec.implementation;
switch_core_timer_init(&tech_pvt->timer, "soft",
read_impl->microseconds_per_packet / 1000, read_impl->samples_per_packet * 4, switch_core_session_get_pool(session));
tech_pvt->read_impl = *tech_pvt->read_codec.implementation;
if (!tech_pvt->flag_mutex) {
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
@@ -376,7 +367,6 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
tech_pvt = switch_core_session_get_private(session);
if (tech_pvt) {
switch_core_timer_destroy(&tech_pvt->timer);
if (switch_core_codec_ready(&tech_pvt->read_codec)) {
switch_core_codec_destroy(&tech_pvt->read_codec);
@@ -568,12 +558,10 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
goto end;
}
switch_core_timer_next(&tech_pvt->timer);
mutex = tech_pvt->mutex;
switch_mutex_lock(mutex);
if (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
if (switch_queue_pop_timeout(tech_pvt->frame_queue, &pop, tech_pvt->read_impl.microseconds_per_packet) == SWITCH_STATUS_SUCCESS && pop) {
if (tech_pvt->write_frame) {
switch_frame_free(&tech_pvt->write_frame);
}
@@ -585,6 +573,8 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
switch_set_flag(tech_pvt, TFLAG_CNG);
}
switch_mutex_lock(mutex);
if (switch_test_flag(tech_pvt, TFLAG_CNG)) {
unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE];
uint32_t flag = 0;
@@ -775,8 +765,6 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
switch_frame_free(&frame);
}
switch_core_timer_sync(&tech_pvt->timer);
}
break;
default:
+1 -1
View File
@@ -4945,7 +4945,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
sofia_endpoint_interface->state_handler = &sofia_event_handlers;
management_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_MANAGEMENT_INTERFACE);
management_interface->relative_oid = "1";
management_interface->relative_oid = "1001";
management_interface->management_function = sofia_manage;
SWITCH_ADD_API(api_interface, "sofia", "Sofia Controls", sofia_function, "<cmd> <args>");
+12
View File
@@ -808,6 +808,18 @@ void sofia_event_callback(nua_event_t event,
}
}
if ((event == nua_i_invite) && (!session)) {
uint32_t sess_count = switch_core_session_count();
uint32_t sess_max = switch_core_session_limit(0);
if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready()) {
nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No more sessions allowed at this time.\n");
goto done;
}
}
if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) {
sip_authorization_t const *authorization = NULL;
@@ -630,6 +630,11 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
char *probe_user = NULL, *probe_euser, *probe_host, *p;
struct dialog_helper dh = { { 0 } };
if (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0) {
goto done;
}
if (!to || !(probe_user = strdup(to))) {
goto done;
}
@@ -2405,6 +2410,20 @@ void sofia_presence_handle_sip_i_subscribe(int status,
switch_event_fire(&sevent);
}
} else if (to_user && (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0)) {
if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", proto);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "long", profile->name);
switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s%s%s@%s", proto, "+", to_user, to_host);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
switch_event_fire(&sevent);
}
} else {
if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
@@ -111,6 +111,7 @@ void ei_encode_switch_event_headers(ei_x_buff * ebuf, switch_event_t *event)
for (hp = event->headers; hp; hp = hp->next) {
ei_x_encode_tuple_header(ebuf, 2);
_ei_x_encode_string(ebuf, hp->name);
switch_url_decode(hp->value);
_ei_x_encode_string(ebuf, hp->value);
}
@@ -778,7 +778,7 @@ static switch_status_t handle_msg_bind(listener_t *listener, erlang_msg * msg, e
binding->process.pid = msg->from;
binding->listener = listener;
switch_thread_rwlock_wrlock(globals.listener_rwlock);
switch_thread_rwlock_wrlock(globals.bindings_rwlock);
for (ptr = bindings.head; ptr && ptr->next; ptr = ptr->next);
@@ -789,7 +789,7 @@ static switch_status_t handle_msg_bind(listener_t *listener, erlang_msg * msg, e
}
switch_xml_set_binding_sections(bindings.search_binding, switch_xml_get_binding_sections(bindings.search_binding) | section);
switch_thread_rwlock_unlock(globals.listener_rwlock);
switch_thread_rwlock_unlock(globals.bindings_rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sections %d\n", switch_xml_get_binding_sections(bindings.search_binding));
@@ -90,7 +90,7 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
{
struct erlang_binding *ptr, *lst = NULL;
switch_thread_rwlock_wrlock(globals.listener_rwlock);
switch_thread_rwlock_wrlock(globals.bindings_rwlock);
switch_xml_set_binding_sections(bindings.search_binding, SWITCH_XML_SECTION_MAX);
@@ -100,7 +100,7 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
if (ptr->next) {
bindings.head = ptr->next;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed all (only?) listeners\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed all (only?) binding\n");
bindings.head = NULL;
break;
}
@@ -111,13 +111,13 @@ static void remove_binding(listener_t *listener, erlang_pid * pid)
lst->next = NULL;
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed listener\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed binding\n");
} else {
switch_xml_set_binding_sections(bindings.search_binding, switch_xml_get_binding_sections(bindings.search_binding) | ptr->section);
}
}
switch_thread_rwlock_unlock(globals.listener_rwlock);
switch_thread_rwlock_unlock(globals.bindings_rwlock);
}
@@ -381,6 +381,8 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c
section = switch_xml_parse_section_string((char *) sectionstr);
switch_thread_rwlock_rdlock(globals.bindings_rwlock);
for (ptr = bindings.head; ptr; ptr = ptr->next) {
if (ptr->section != section)
continue;
@@ -417,6 +419,8 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c
switch_mutex_unlock(ptr->listener->sock_mutex);
}
switch_thread_rwlock_unlock(globals.bindings_rwlock);
ei_x_free(&buf);
if (!p) {
@@ -532,6 +536,7 @@ static switch_status_t notify_new_session(listener_t *listener, session_elem_t *
session_element->uuid_str);
}
switch_event_destroy(&call_event);
ei_x_free(&lbuf);
return SWITCH_STATUS_SUCCESS;
}
@@ -1637,6 +1642,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_erlang_event_load)
memset(&prefs, 0, sizeof(prefs));
switch_thread_rwlock_create(&globals.listener_rwlock, pool);
switch_thread_rwlock_create(&globals.bindings_rwlock, pool);
switch_mutex_init(&globals.fetch_reply_mutex, SWITCH_MUTEX_DEFAULT, pool);
switch_mutex_init(&globals.listener_count_mutex, SWITCH_MUTEX_UNNESTED, pool);
switch_core_hash_init(&globals.fetch_reply_hash, pool);
@@ -161,6 +161,7 @@ struct api_command_struct {
struct globals_struct {
switch_thread_rwlock_t *listener_rwlock;
switch_thread_rwlock_t *bindings_rwlock;
switch_event_node_t *node;
switch_mutex_t *ref_mutex;
switch_mutex_t *fetch_reply_mutex;
@@ -32,7 +32,7 @@
#include <switch.h>
#define CMD_BUFLEN 1024 * 1000
#define MAX_QUEUE_LEN 25000
#define MAX_MISSED 2000
#define MAX_MISSED 500
SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_event_socket_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime);
@@ -143,7 +143,7 @@ static const char *format2str(event_format_t format)
}
static void remove_listener(listener_t *listener);
static void kill_listener(listener_t *l);
static void kill_listener(listener_t *l, const char *message);
static void kill_all_listeners(void);
static uint32_t next_id(void)
@@ -170,7 +170,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l
if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) {
switch_log_node_t *dnode = switch_log_node_dup(node);
if (switch_queue_push(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_trypush(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) {
if (l->lost_logs) {
int ll = l->lost_logs;
switch_event_t *event;
@@ -184,7 +184,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l
} else {
switch_log_node_free(&dnode);
if (++l->lost_logs > MAX_MISSED) {
kill_listener(l);
kill_listener(l, "Disconnected due to log queue failure.\n");
}
}
}
@@ -366,7 +366,7 @@ static void event_handler(switch_event_t *event)
if (send) {
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_push(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_trypush(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) {
if (l->lost_events) {
int le = l->lost_events;
l->lost_events = 0;
@@ -379,7 +379,7 @@ static void event_handler(switch_event_t *event)
}
} else {
if (++l->lost_events > MAX_MISSED) {
kill_listener(l);
kill_listener(l, "Disconnected due to event queue failure.\n");
}
switch_event_destroy(&clone);
}
@@ -579,8 +579,41 @@ static void remove_listener(listener_t *listener)
switch_mutex_unlock(globals.listener_mutex);
}
static void kill_listener(listener_t *l)
static void send_disconnect(listener_t *listener, const char *message)
{
char disco_buf[512] = "";
switch_size_t len, mlen;
if (zstr(message)) {
message = "Disconnected.\n";
}
mlen = strlen(message);
if (listener->session) {
switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\n"
"Controlled-Session-UUID: %s\n"
"Content-Disposition: disconnect\n" "Content-Length: %d\n\n", switch_core_session_get_uuid(listener->session), mlen);
} else {
switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\nContent-Length: %d\n\n", mlen);
}
len = strlen(disco_buf);
switch_socket_send(listener->sock, disco_buf, &len);
if (len > 0) {
len = mlen;
switch_socket_send(listener->sock, message, &len);
}
}
static void kill_listener(listener_t *l, const char *message)
{
if (message) {
send_disconnect(l, message);
}
switch_clear_flag(l, LFLAG_RUNNING);
if (l->sock) {
switch_socket_shutdown(l->sock, SWITCH_SHUTDOWN_READWRITE);
@@ -595,7 +628,7 @@ static void kill_all_listeners(void)
switch_mutex_lock(globals.listener_mutex);
for (l = listen_list.listeners; l; l = l->next) {
kill_listener(l);
kill_listener(l, "The system is being shut down.\n");
}
switch_mutex_unlock(globals.listener_mutex);
}
@@ -1233,7 +1266,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
if (switch_channel_get_state(chan) < CS_HANGUP && switch_channel_test_flag(chan, CF_DIVERT_EVENTS)) {
switch_event_t *e = NULL;
while (switch_core_session_dequeue_event(listener->session, &e, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_push(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) {
if (switch_queue_trypush(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) {
switch_core_session_queue_event(listener->session, &e);
break;
}
@@ -2540,22 +2573,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
}
if (listener->sock) {
char disco_buf[512] = "";
const char message[] = "Disconnected, goodbye.\nSee you at ClueCon! http://www.cluecon.com/\n";
int mlen = strlen(message);
if (listener->session) {
switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\n"
"Controlled-Session-UUID: %s\n"
"Content-Disposition: disconnect\n" "Content-Length: %d\n\n", switch_core_session_get_uuid(listener->session), mlen);
} else {
switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\nContent-Length: %d\n\n", mlen);
}
len = strlen(disco_buf);
switch_socket_send(listener->sock, disco_buf, &len);
len = mlen;
switch_socket_send(listener->sock, message, &len);
send_disconnect(listener, "Disconnected, goodbye.\nSee you at ClueCon! http://www.cluecon.com/\n");
close_socket(&listener->sock);
}
@@ -0,0 +1,110 @@
FREESWITCH-MIB DEFINITIONS ::= BEGIN
IMPORTS
OBJECT-TYPE, MODULE-IDENTITY,
Integer32, Gauge32, Counter32, Counter64, TimeTicks,
enterprises,
FROM SNMPv2-SMI
DisplayString
FROM SNMPv2-TC
;
freeswitch MODULE-IDENTITY
LAST-UPDATED "201101170000Z"
ORGANIZATION "www.freeswitch.org"
CONTACT-INFO
"Primary contact: Anthony Minessale II
Email: anthm@freeswitch.org"
DESCRIPTION
"This file defines the private FreeSWITCH SNMP MIB extensions."
REVISION "201101170000Z"
DESCRIPTION
"First draft by daniel.swarbrick@seventhsignal.de"
::= { enterprises 27880 }
core OBJECT IDENTIFIER ::= { freeswitch 1 }
mod-sofia OBJECT IDENTIFIER ::= { freeswitch 1001 }
mod-skinny OBJECT IDENTIFIER ::= { freeswitch 1002 }
identity OBJECT IDENTIFIER ::= { core 1 }
versionString OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"FreeSWITCH version as a string"
::= { identity 1 }
uuid OBJECT-TYPE
SYNTAX DisplayString
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"FreeSWITCH core UUID"
::= { identity 2 }
systemStats OBJECT IDENTIFIER ::= { core 2 }
uptime OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"FreeSWITCH process uptime in hundredths of seconds"
::= { systemStats 1 }
sessionsSinceStartup OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of sessions since FreeSWITCH process was started"
::= { systemStats 2 }
currentSessions OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Currently active sessions"
::= { systemStats 3 }
maxSessions OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum permissible active sessions"
::= { systemStats 4 }
currentCalls OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Currently active calls"
::= { systemStats 5 }
sessionsPerSecond OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current sessions per second"
::= { systemStats 6 }
maxSessionsPerSecond OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum permissible sessions per second"
::= { systemStats 7 }
END
+7
View File
@@ -0,0 +1,7 @@
include ../../../../build/modmake.rules
LOCAL_CFLAGS=-I `net-snmp-config --cflags`
LOCAL_LDFLAGS=`net-snmp-config --agent-libs`
LOCAL_OBJS=subagent.o
local_depend: $(LOCAL_OBJS)
+158
View File
@@ -0,0 +1,158 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, 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 / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Swarbrick <daniel.swarbrick@seventhsignal.de>
* Stefan Knoblich <s.knoblich@axsentis.de>
*
* mod_snmp.c -- SNMP AgentX Subagent Module
*
*/
#include <switch.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "subagent.h"
static struct {
switch_memory_pool_t *pool;
switch_mutex_t *mutex;
int shutdown;
} globals;
SWITCH_MODULE_LOAD_FUNCTION(mod_snmp_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_snmp_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_snmp_runtime);
SWITCH_MODULE_DEFINITION(mod_snmp, mod_snmp_load, mod_snmp_shutdown, mod_snmp_runtime);
static switch_status_t snmp_manage(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen)
{
if (action == SMA_GET) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Mutex lock request from relative OID %s.\n", relative_oid);
switch_mutex_lock(globals.mutex);
} else if (action == SMA_SET) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Mutex unlock request from relative OID %s.\n", relative_oid);
switch_mutex_unlock(globals.mutex);
}
return SWITCH_STATUS_SUCCESS;
}
static int snmp_callback_log(int major, int minor, void *serverarg, void *clientarg)
{
struct snmp_log_message *slm = (struct snmp_log_message *) serverarg;
switch_log_printf(SWITCH_CHANNEL_LOG, slm->priority, "%s", slm->msg);
return SNMP_ERR_NOERROR;
}
static switch_status_t load_config(switch_memory_pool_t *pool)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
memset(&globals, 0, sizeof(globals));
globals.pool = pool;
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_snmp_load)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_management_interface_t *management_interface;
load_config(pool);
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
management_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_MANAGEMENT_INTERFACE);
management_interface->relative_oid = "1000";
management_interface->management_function = snmp_manage;
/* Register callback function so we get Net-SNMP logging handled by FreeSWITCH */
snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, snmp_callback_log, NULL);
snmp_enable_calllog();
netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
init_agent("mod_snmp");
/*
* Override master/subagent ping interval to 2s, to ensure that
* agent_check_and_process() never blocks for longer than that.
*/
netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL, 2);
init_subagent();
init_snmp("mod_snmp");
return status;
}
SWITCH_MODULE_RUNTIME_FUNCTION(mod_snmp_runtime)
{
if (!globals.shutdown) {
switch_mutex_lock(globals.mutex);
/* Block on select() */
agent_check_and_process(1);
switch_mutex_unlock(globals.mutex);
}
switch_yield(5000);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_snmp_shutdown)
{
globals.shutdown = 1;
switch_mutex_lock(globals.mutex);
snmp_shutdown("mod_snmp");
switch_mutex_unlock(globals.mutex);
switch_mutex_destroy(globals.mutex);
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:
*/
+158
View File
@@ -0,0 +1,158 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, 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 / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Swarbrick <daniel.swarbrick@seventhsignal.de>
* Stefan Knoblich <s.knoblich@axsentis.de>
*
* mod_snmp.c -- SNMP AgentX Subagent Module
*
*/
#include <switch.h>
#include <switch_version.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "subagent.h"
void init_subagent(void)
{
static oid identity_oid[] = { 1,3,6,1,4,1,27880,1,1 };
static oid systemStats_oid[] = { 1,3,6,1,4,1,27880,1,2 };
DEBUGMSGTL(("init_subagent", "Initializing\n"));
netsnmp_register_scalar_group(netsnmp_create_handler_registration("identity", handle_identity, identity_oid, OID_LENGTH(identity_oid), HANDLER_CAN_RONLY), 1, 2);
netsnmp_register_scalar_group(netsnmp_create_handler_registration("systemStats", handle_systemStats, systemStats_oid, OID_LENGTH(systemStats_oid), HANDLER_CAN_RONLY), 1, 7);
}
int handle_identity(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests)
{
netsnmp_request_info *request = NULL;
oid subid;
static char const version[] = SWITCH_VERSION_FULL;
char uuid[40] = "";
switch(reqinfo->mode) {
case MODE_GET:
subid = requests->requestvb->name[reginfo->rootoid_len - 2];
switch (subid) {
case ID_VERSION_STR:
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &version, strlen(version));
break;
case ID_UUID:
strncpy(uuid, switch_core_get_uuid(), sizeof(uuid));
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &uuid, strlen(uuid));
break;
default:
snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
}
break;
default:
/* we should never get here, so this is a really bad error */
snmp_log(LOG_ERR, "Unknown mode (%d) in handle_identity\n", reqinfo->mode );
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
int handle_systemStats(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests)
{
netsnmp_request_info *request = NULL;
oid subid;
switch_time_t uptime;
uint32_t int_val;
switch(reqinfo->mode) {
case MODE_GET:
subid = requests->requestvb->name[reginfo->rootoid_len - 2];
switch (subid) {
case SS_UPTIME:
uptime = switch_core_uptime() / 10000;
snmp_set_var_typed_value(requests->requestvb, ASN_TIMETICKS, (u_char *) &uptime, sizeof(uptime));
break;
case SS_SESSIONS_SINCE_STARTUP:
int_val = switch_core_session_id() - 1;
snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER, (u_char *) &int_val, sizeof(int_val));
break;
case SS_CURRENT_SESSIONS:
int_val = switch_core_session_count();
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case SS_MAX_SESSIONS:
switch_core_session_ctl(SCSC_MAX_SESSIONS, &int_val);;
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case SS_CURRENT_CALLS:
/*
* This is zero for now, since there is no convenient way to get total call
* count (not to be confused with session count), without touching the
* database.
*/
int_val = 0;
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case SS_SESSIONS_PER_SECOND:
switch_core_session_ctl(SCSC_LAST_SPS, &int_val);
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
case SS_MAX_SESSIONS_PER_SECOND:
switch_core_session_ctl(SCSC_SPS, &int_val);
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
break;
default:
snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
}
break;
default:
/* we should never get here, so this is a really bad error */
snmp_log(LOG_ERR, "Unknown mode (%d) in handle_systemStats\n", reqinfo->mode);
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
/* 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:
*/
@@ -0,0 +1,22 @@
#ifndef subagent_H
#define subagent_H
/* .1.3.6.1.4.1.27880.1.1 */
#define ID_VERSION_STR 1
#define ID_UUID 2
/* .1.3.6.1.4.1.27880.1.2 */
#define SS_UPTIME 1
#define SS_SESSIONS_SINCE_STARTUP 2
#define SS_CURRENT_SESSIONS 3
#define SS_MAX_SESSIONS 4
#define SS_CURRENT_CALLS 5
#define SS_SESSIONS_PER_SECOND 6
#define SS_MAX_SESSIONS_PER_SECOND 7
void init_subagent(void);
Netsnmp_Node_Handler handle_identity;
Netsnmp_Node_Handler handle_systemStats;
#endif /* subagent_H */
+5 -1
View File
@@ -584,7 +584,11 @@ static void launch_write_stream_thread(shout_context_t *context)
}
#define TC_BUFFER_SIZE 1024 * 32
#define MPGERROR() {err = "MPG123 Error at __FILE__:__LINE__."; mpg123err = mpg123_strerror(context->mh); goto error; }
#define CONCAT_LOCATION(_x,_y) _x ":" #_y
#define MAKE_LOCATION(_x,_y) CONCAT_LOCATION(_x,_y)
#define HERE MAKE_LOCATION(__FILE__, __LINE__)
#define MPGERROR() {err = "MPG123 Error at " HERE "."; mpg123err = mpg123_strerror(context->mh); goto error; }
static switch_status_t shout_file_open(switch_file_handle_t *handle, const char *path)
{
shout_context_t *context;
+1
View File
@@ -89,6 +89,7 @@ class Dbh {
~Dbh();
bool release();
bool connected();
bool test_reactive(char *test_sql, char *drop_sql = NULL, char *reactive_sql = NULL);
bool query(char *sql, SWIGLUA_FN lua_fun);
int affected_rows();
};
+23 -7
View File
@@ -312,15 +312,21 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
Dbh::Dbh(char *dsn, char *user, char *pass)
{
switch_cache_db_connection_options_t options = { {0} };
const char *prefix = "core:";
m_connected = false;
options.odbc_options.dsn = dsn;
options.odbc_options.user = user;
options.odbc_options.pass = pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) {
m_connected = true;
if (strstr(dsn, prefix) == dsn) {
options.core_db_options.db_path = &dsn[strlen(prefix)];
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) == SWITCH_STATUS_SUCCESS) {
m_connected = true;
}
} else {
m_connected = false;
options.odbc_options.dsn = dsn;
options.odbc_options.user = user;
options.odbc_options.pass = pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) {
m_connected = true;
}
}
}
@@ -344,6 +350,16 @@ bool Dbh::connected()
return m_connected;
}
bool Dbh::test_reactive(char *test_sql, char *drop_sql, char *reactive_sql)
{
if (m_connected) {
if (switch_cache_db_test_reactive(dbh, test_sql, drop_sql, reactive_sql) == SWITCH_TRUE) {
return true;
}
}
return false;
}
int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
{
SWIGLUA_FN *lua_fun = (SWIGLUA_FN *)pArg;
@@ -62,6 +62,7 @@ namespace LUA {
~Dbh();
bool release();
bool connected();
bool test_reactive(char *test_sql, char *drop_sql = NULL, char *reactive_sql = NULL);
bool query(char *sql, SWIGLUA_FN lua_fun);
int affected_rows();
};
+179
View File
@@ -7254,6 +7254,184 @@ fail:
}
static int _wrap_Dbh_test_reactive__SWIG_0(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
char *arg4 = (char *) 0 ;
bool result;
SWIG_check_num_args("test_reactive",4,4)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("test_reactive",1,"LUA::Dbh *");
if(!lua_isstring(L,2)) SWIG_fail_arg("test_reactive",2,"char *");
if(!lua_isstring(L,3)) SWIG_fail_arg("test_reactive",3,"char *");
if(!lua_isstring(L,4)) SWIG_fail_arg("test_reactive",4,"char *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_test_reactive",1,SWIGTYPE_p_LUA__Dbh);
}
arg2 = (char *)lua_tostring(L, 2);
arg3 = (char *)lua_tostring(L, 3);
arg4 = (char *)lua_tostring(L, 4);
result = (bool)(arg1)->test_reactive(arg2,arg3,arg4);
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_test_reactive__SWIG_1(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
bool result;
SWIG_check_num_args("test_reactive",3,3)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("test_reactive",1,"LUA::Dbh *");
if(!lua_isstring(L,2)) SWIG_fail_arg("test_reactive",2,"char *");
if(!lua_isstring(L,3)) SWIG_fail_arg("test_reactive",3,"char *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_test_reactive",1,SWIGTYPE_p_LUA__Dbh);
}
arg2 = (char *)lua_tostring(L, 2);
arg3 = (char *)lua_tostring(L, 3);
result = (bool)(arg1)->test_reactive(arg2,arg3);
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_test_reactive__SWIG_2(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
char *arg2 = (char *) 0 ;
bool result;
SWIG_check_num_args("test_reactive",2,2)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("test_reactive",1,"LUA::Dbh *");
if(!lua_isstring(L,2)) SWIG_fail_arg("test_reactive",2,"char *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_test_reactive",1,SWIGTYPE_p_LUA__Dbh);
}
arg2 = (char *)lua_tostring(L, 2);
result = (bool)(arg1)->test_reactive(arg2);
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_test_reactive(lua_State* L) {
int argc;
int argv[5]={
1,2,3,4,5
};
argc = lua_gettop(L);
if (argc == 2) {
int _v;
{
void *ptr;
if (SWIG_isptrtype(L,argv[0])==0 || SWIG_ConvertPtr(L,argv[0], (void **) &ptr, SWIGTYPE_p_LUA__Dbh, 0)) {
_v = 0;
} else {
_v = 1;
}
}
if (_v) {
{
_v = lua_isstring(L,argv[1]);
}
if (_v) {
return _wrap_Dbh_test_reactive__SWIG_2(L);
}
}
}
if (argc == 3) {
int _v;
{
void *ptr;
if (SWIG_isptrtype(L,argv[0])==0 || SWIG_ConvertPtr(L,argv[0], (void **) &ptr, SWIGTYPE_p_LUA__Dbh, 0)) {
_v = 0;
} else {
_v = 1;
}
}
if (_v) {
{
_v = lua_isstring(L,argv[1]);
}
if (_v) {
{
_v = lua_isstring(L,argv[2]);
}
if (_v) {
return _wrap_Dbh_test_reactive__SWIG_1(L);
}
}
}
}
if (argc == 4) {
int _v;
{
void *ptr;
if (SWIG_isptrtype(L,argv[0])==0 || SWIG_ConvertPtr(L,argv[0], (void **) &ptr, SWIGTYPE_p_LUA__Dbh, 0)) {
_v = 0;
} else {
_v = 1;
}
}
if (_v) {
{
_v = lua_isstring(L,argv[1]);
}
if (_v) {
{
_v = lua_isstring(L,argv[2]);
}
if (_v) {
{
_v = lua_isstring(L,argv[3]);
}
if (_v) {
return _wrap_Dbh_test_reactive__SWIG_0(L);
}
}
}
}
}
lua_pushstring(L,"No matching function for overloaded 'Dbh_test_reactive'");
lua_error(L);return 0;
}
static int _wrap_Dbh_query(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
@@ -7328,6 +7506,7 @@ delete arg1;
static swig_lua_method swig_LUA_Dbh_methods[] = {
{"release", _wrap_Dbh_release},
{"connected", _wrap_Dbh_connected},
{"test_reactive", _wrap_Dbh_test_reactive},
{"query", _wrap_Dbh_query},
{"affected_rows", _wrap_Dbh_affected_rows},
{0,0}
@@ -7413,6 +7413,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jar
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_set_codec_slin(void * jarg1, void * jarg2) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
switch_slin_data_t *arg2 = (switch_slin_data_t *) 0 ;
switch_status_t result;
arg1 = (switch_core_session_t *)jarg1;
arg2 = (switch_slin_data_t *)jarg2;
result = (switch_status_t)switch_core_session_set_codec_slin(arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_uuid() {
char * jresult ;
char *result = 0 ;
@@ -22794,6 +22808,119 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_api_interface(void * jarg1) {
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_session_set(void * jarg1, void * jarg2) {
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
switch_core_session_t *arg2 = (switch_core_session_t *) 0 ;
arg1 = (switch_slin_data *)jarg1;
arg2 = (switch_core_session_t *)jarg2;
if (arg1) (arg1)->session = arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_session_get(void * jarg1) {
void * jresult ;
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
switch_core_session_t *result = 0 ;
arg1 = (switch_slin_data *)jarg1;
result = (switch_core_session_t *) ((arg1)->session);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_write_frame_set(void * jarg1, void * jarg2) {
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
switch_frame_t *arg2 = (switch_frame_t *) 0 ;
arg1 = (switch_slin_data *)jarg1;
arg2 = (switch_frame_t *)jarg2;
if (arg1) (arg1)->write_frame = *arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_write_frame_get(void * jarg1) {
void * jresult ;
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
switch_frame_t *result = 0 ;
arg1 = (switch_slin_data *)jarg1;
result = (switch_frame_t *)& ((arg1)->write_frame);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_codec_set(void * jarg1, void * jarg2) {
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
switch_codec_t *arg2 = (switch_codec_t *) 0 ;
arg1 = (switch_slin_data *)jarg1;
arg2 = (switch_codec_t *)jarg2;
if (arg1) (arg1)->codec = *arg2;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_codec_get(void * jarg1) {
void * jresult ;
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
switch_codec_t *result = 0 ;
arg1 = (switch_slin_data *)jarg1;
result = (switch_codec_t *)& ((arg1)->codec);
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_frame_data_set(void * jarg1, char * jarg2) {
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
char *arg2 ;
arg1 = (switch_slin_data *)jarg1;
arg2 = (char *)jarg2;
{
if (arg2) strncpy((char *)arg1->frame_data, (const char *)arg2, 4096);
else arg1->frame_data[0] = 0;
}
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_slin_data_frame_data_get(void * jarg1) {
char * jresult ;
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
char *result = 0 ;
arg1 = (switch_slin_data *)jarg1;
result = (char *)(char *) ((arg1)->frame_data);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_slin_data() {
void * jresult ;
switch_slin_data *result = 0 ;
result = (switch_slin_data *)new switch_slin_data();
jresult = (void *)result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_slin_data(void * jarg1) {
switch_slin_data *arg1 = (switch_slin_data *) 0 ;
arg1 = (switch_slin_data *)jarg1;
delete arg1;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_timetable_profile_created_set(void * jarg1, void * jarg2) {
switch_channel_timetable *arg1 = (switch_channel_timetable *) 0 ;
switch_time_t arg2 ;
+132 -2
View File
@@ -1357,6 +1357,11 @@ public class freeswitch {
return ret;
}
public static switch_status_t switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session session, switch_slin_data data) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_slin_data.getCPtr(data));
return ret;
}
public static string switch_core_get_uuid() {
string ret = freeswitchPINVOKE.switch_core_get_uuid();
return ret;
@@ -7504,6 +7509,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_dmachine")]
public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_codec_slin")]
public static extern int switch_core_session_set_codec_slin(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_uuid")]
public static extern string switch_core_get_uuid();
@@ -11188,6 +11196,36 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_delete_switch_api_interface")]
public static extern void delete_switch_api_interface(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_set")]
public static extern void switch_slin_data_session_set(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_get")]
public static extern IntPtr switch_slin_data_session_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_set")]
public static extern void switch_slin_data_write_frame_set(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_get")]
public static extern IntPtr switch_slin_data_write_frame_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_set")]
public static extern void switch_slin_data_codec_set(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_get")]
public static extern IntPtr switch_slin_data_codec_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_set")]
public static extern void switch_slin_data_frame_data_set(HandleRef jarg1, string jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_get")]
public static extern string switch_slin_data_frame_data_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_new_switch_slin_data")]
public static extern IntPtr new_switch_slin_data();
[DllImport("mod_managed", EntryPoint="CSharp_delete_switch_slin_data")]
public static extern void delete_switch_slin_data(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_timetable_profile_created_set")]
public static extern void switch_channel_timetable_profile_created_set(HandleRef jarg1, HandleRef jarg2);
@@ -28401,7 +28439,8 @@ public enum switch_rtp_bug_flag_t {
RTP_BUG_IGNORE_MARK_BIT = (1 << 2),
RTP_BUG_SEND_LINEAR_TIMESTAMPS = (1 << 3),
RTP_BUG_START_SEQ_AT_ZERO = (1 << 4),
RTP_BUG_NEVER_SEND_MARKER = (1 << 5)
RTP_BUG_NEVER_SEND_MARKER = (1 << 5),
RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6)
}
}
@@ -29437,6 +29476,96 @@ public enum switch_signal_t {
namespace FreeSWITCH.Native {
using System;
using System.Runtime.InteropServices;
public class switch_slin_data : IDisposable {
private HandleRef swigCPtr;
protected bool swigCMemOwn;
internal switch_slin_data(IntPtr cPtr, bool cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = new HandleRef(this, cPtr);
}
internal static HandleRef getCPtr(switch_slin_data obj) {
return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
}
~switch_slin_data() {
Dispose();
}
public virtual void Dispose() {
lock(this) {
if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
swigCMemOwn = false;
freeswitchPINVOKE.delete_switch_slin_data(swigCPtr);
}
swigCPtr = new HandleRef(null, IntPtr.Zero);
GC.SuppressFinalize(this);
}
}
public SWIGTYPE_p_switch_core_session session {
set {
freeswitchPINVOKE.switch_slin_data_session_set(swigCPtr, SWIGTYPE_p_switch_core_session.getCPtr(value));
}
get {
IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_session_get(swigCPtr);
SWIGTYPE_p_switch_core_session ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_core_session(cPtr, false);
return ret;
}
}
public switch_frame write_frame {
set {
freeswitchPINVOKE.switch_slin_data_write_frame_set(swigCPtr, switch_frame.getCPtr(value));
}
get {
IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_write_frame_get(swigCPtr);
switch_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_frame(cPtr, false);
return ret;
}
}
public switch_codec codec {
set {
freeswitchPINVOKE.switch_slin_data_codec_set(swigCPtr, switch_codec.getCPtr(value));
}
get {
IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_codec_get(swigCPtr);
switch_codec ret = (cPtr == IntPtr.Zero) ? null : new switch_codec(cPtr, false);
return ret;
}
}
public string frame_data {
set {
freeswitchPINVOKE.switch_slin_data_frame_data_set(swigCPtr, value);
}
get {
string ret = freeswitchPINVOKE.switch_slin_data_frame_data_get(swigCPtr);
return ret;
}
}
public switch_slin_data() : this(freeswitchPINVOKE.new_switch_slin_data(), true) {
}
}
}
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 1.3.35
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
namespace FreeSWITCH.Native {
[System.Flags] public enum switch_speech_flag_enum_t {
SWITCH_SPEECH_FLAG_NONE = 0,
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0),
@@ -30146,7 +30275,7 @@ public enum switch_status_t {
SWITCH_STATUS_FALSE,
SWITCH_STATUS_TIMEOUT,
SWITCH_STATUS_RESTART,
SWITCH_STATUS_TERM,
SWITCH_STATUS_INTR,
SWITCH_STATUS_NOTIMPL,
SWITCH_STATUS_MEMERR,
SWITCH_STATUS_NOOP,
@@ -30163,6 +30292,7 @@ public enum switch_status_t {
SWITCH_STATUS_TOO_SMALL,
SWITCH_STATUS_FOUND,
SWITCH_STATUS_CONTINUE,
SWITCH_STATUS_TERM,
SWITCH_STATUS_NOT_INITALIZED
}
+1 -1
View File
@@ -846,7 +846,7 @@ SWITCH_DECLARE(switch_status_t) switch_socket_recvfrom(switch_sockaddr_t *from,
*/
}
if (r == 35) {
if (r == 35 || r == 730035) {
r = SWITCH_STATUS_BREAK;
}
+2 -2
View File
@@ -2564,8 +2564,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
char *app;
switch_event_t *event;
if (!switch_channel_test_flag(channel, CF_RING_READY) && !switch_channel_test_flag(channel, CF_EARLY_MEDIA &&
!switch_channel_test_flag(channel, CF_ANSWERED))) {
if (!switch_channel_test_flag(channel, CF_RING_READY) &&
!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring-Ready %s!\n", channel->name);
switch_channel_set_flag_value(channel, CF_RING_READY, rv);
if (channel->caller_profile && channel->caller_profile->times) {
+11 -1
View File
@@ -151,13 +151,21 @@ static void check_ip(void)
SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback)
{
send_heartbeat();
check_ip();
/* reschedule this task */
task->runtime = switch_epoch_time_now(NULL) + 20;
}
SWITCH_STANDARD_SCHED_FUNC(check_ip_callback)
{
check_ip();
/* reschedule this task */
task->runtime = switch_epoch_time_now(NULL) + 60;
}
SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console)
{
if ((runtime.console = fopen(console, "a")) == 0) {
@@ -1363,6 +1371,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL);
switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD);
switch_uuid_get(&uuid);
switch_uuid_format(runtime.uuid_str, &uuid);
+1 -1
View File
@@ -391,10 +391,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh,
if ((status = fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen)) != SWITCH_STATUS_SUCCESS) {
*len = 0;
}
fh->samples_out += blen;
}
}
fh->samples_out += orig_len;
return status;
} else {
switch_status_t status;
+1 -1
View File
@@ -224,7 +224,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
switch_ivr_parse_all_events(session);
if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) {
if (args) {
switch_dtmf_t dtmf;
/*
+1
View File
@@ -3129,6 +3129,7 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
switch_event_t *dup;
if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, dup);
switch_event_fire(&dup);
}
+21 -1
View File
@@ -2755,6 +2755,26 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
}
}
}
if (session) {
switch_channel_set_variable(originate_status[i].peer_channel, "originating_leg_uuid", switch_core_session_get_uuid(session));
}
if ((vvar = switch_channel_get_variable_dup(originate_status[i].peer_channel, "execute_on_originate", SWITCH_FALSE))) {
char *app = switch_core_session_strdup(originate_status[i].peer_session, vvar);
char *arg = NULL;
if (strstr(app, "::")) {
switch_core_session_execute_application_async(originate_status[i].peer_session, app, arg);
} else {
if ((arg = strchr(app, ' '))) {
*arg++ = '\0';
}
switch_core_session_execute_application(originate_status[i].peer_session, app, arg);
}
}
}
if (table) {
@@ -2773,7 +2793,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
*cause = SWITCH_CAUSE_SUCCESS;
goto outer_for;
}
if (!switch_core_session_running(originate_status[i].peer_session)) {
if (originate_status[i].per_channel_delay_start) {
switch_channel_set_flag(originate_status[i].peer_channel, CF_BLOCK_STATE);
+13 -5
View File
@@ -372,6 +372,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
switch_event_t *event;
int divisor = 0;
int file_flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT;
int restart_limit_on_dtmf = 0;
const char *prefix;
prefix = switch_channel_get_variable(channel, "sound_prefix");
@@ -528,6 +529,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
asis = 1;
}
restart_limit_on_dtmf = switch_true(switch_channel_get_variable(channel, "record_restart_limit_on_dtmf"));
if ((p = switch_channel_get_variable(channel, "RECORD_TITLE"))) {
vval = switch_core_session_strdup(session, p);
@@ -631,12 +634,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
break;
}
if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) {
if (args) {
/*
dtmf handler function you can hook up to be executed when a digit is dialed during playback
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/
if (switch_channel_has_dtmf(channel)) {
if (limit && restart_limit_on_dtmf) {
start = switch_epoch_time_now(NULL);
}
if (!args->input_callback && !args->buf && !args->dmachine) {
status = SWITCH_STATUS_BREAK;
break;
@@ -854,7 +862,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi
switch_ivr_parse_all_events(session);
if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) {
if (args) {
/*
dtmf handler function you can hook up to be executed when a digit is dialed during gentones
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
@@ -1306,7 +1314,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
switch_ivr_parse_all_events(session);
if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) {
if (args) {
/*
dtmf handler function you can hook up to be executed when a digit is dialed during playback
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
@@ -1867,7 +1875,7 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
switch_status_t status;
memset(digit_buffer, 0, digit_buffer_length);
switch_channel_flush_dtmf(channel);
status = switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name,
digit_buffer, digit_buffer_length, timeout, valid_terminators, digit_timeout);
if (status == SWITCH_STATUS_TIMEOUT && strlen(digit_buffer) >= min_digits) {
@@ -2029,7 +2037,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
switch_event_destroy(&event);
}
if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) {
if (args) {
/* dtmf handler function you can hook up to be executed when a digit is dialed during playback
* if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/
+10 -6
View File
@@ -1047,20 +1047,24 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir,
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Module is not unloadable.\n");
*err = "Module is not unloadable";
status = SWITCH_STATUS_NOUNLOAD;
goto end;
goto unlock;
} else {
if ((status = do_shutdown(module, SWITCH_TRUE, SWITCH_TRUE, !force, err) != SWITCH_STATUS_SUCCESS)) {
goto end;
/* Prevent anything from using the module while it's shutting down */
switch_core_hash_delete(loadable_modules.module_hash, fname);
switch_mutex_unlock(loadable_modules.mutex);
if ((status = do_shutdown(module, SWITCH_TRUE, SWITCH_TRUE, !force, err)) != SWITCH_STATUS_SUCCESS) {
/* Something went wrong in the module's shutdown function, add it again */
switch_core_hash_insert_locked(loadable_modules.module_hash, fname, module, loadable_modules.mutex);
}
goto end;
}
switch_core_hash_delete(loadable_modules.module_hash, fname);
} else {
*err = "No such module!";
status = SWITCH_STATUS_FALSE;
}
end:
unlock:
switch_mutex_unlock(loadable_modules.mutex);
end:
if (force) {
switch_yield(1000000);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "PHEW!\n");
+253 -172
View File
@@ -32,6 +32,7 @@
*/
//#define DEBUG_2833
//#define RTP_DEBUG_WRITE_DELTA
//#define DEBUG_MISSED_SEQ
#include <switch.h>
#include <switch_stun.h>
#undef PACKAGE_NAME
@@ -245,6 +246,9 @@ struct switch_rtp {
switch_time_t send_time;
switch_byte_t auto_adj_used;
uint8_t pause_jb;
uint16_t last_seq;
switch_time_t last_read_time;
switch_size_t last_flush_packet_count;
};
struct switch_rtcp_senderinfo {
@@ -256,6 +260,180 @@ struct switch_rtcp_senderinfo {
unsigned oc:32;
};
typedef enum {
RESULT_CONTINUE,
RESULT_GOTO_END,
RESULT_GOTO_RECVFROM,
RESULT_GOTO_TIMERCHECK
} handle_rfc2833_result_t;
static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_size_t bytes, int *do_cng)
{
#ifdef DEBUG_2833
if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
}
#endif
if (rtp_session->dtmf_data.in_digit_sanity && !--rtp_session->dtmf_data.in_digit_sanity) {
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF sanity check.\n");
}
/* RFC2833 ... like all RFC RE: VoIP, guaranteed to drive you to insanity!
We know the real rules here, but if we enforce them, it's an interop nightmare so,
we put up with as much as we can so we don't have to deal with being punished for
doing it right. Nice guys finish last!
*/
if (bytes > rtp_header_len && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
switch_size_t len = bytes - rtp_header_len;
unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body;
int end;
uint16_t duration;
char key;
uint16_t in_digit_seq;
uint32_t ts;
if (!(packet[0] || packet[1] || packet[2] || packet[3]) && len >= 8) {
packet += 4;
len -= 4;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF payload offset by 4 bytes.\n");
}
if (!(packet[0] || packet[1] || packet[2] || packet[3])) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF payload check.\n");
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
}
end = packet[1] & 0x80 ? 1 : 0;
duration = (packet[2] << 8) + packet[3];
key = switch_rfc2833_to_char(packet[0]);
in_digit_seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
ts = htonl(rtp_session->recv_msg.header.ts);
if (in_digit_seq < rtp_session->dtmf_data.in_digit_seq) {
if (rtp_session->dtmf_data.in_digit_seq - in_digit_seq > 100) {
rtp_session->dtmf_data.in_digit_seq = 0;
}
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
packet[1], (unsigned) packet[2], (unsigned) packet[3]);
#endif
if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq,
ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif
if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) &&
rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) };
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
rtp_session->dtmf_data.in_digit_queued = 1;
}
/* only set sanity if we do NOT ignore the packet */
if (rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
if (rtp_session->dtmf_data.last_duration > duration &&
rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.flip++;
}
if (end) {
if (rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, duration };
if (ts > rtp_session->dtmf_data.in_digit_ts) {
dtmf.duration += (ts - rtp_session->dtmf_data.in_digit_ts);
}
if (rtp_session->dtmf_data.flip) {
dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
rtp_session->dtmf_data.flip = 0;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n");
#endif
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
#endif
if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
}
rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
*do_cng = 1;
} else {
if (!switch_rtp_ready(rtp_session)) {
return RESULT_GOTO_END;
}
switch_cond_next();
return RESULT_GOTO_RECVFROM;
}
} else if (!rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_ts = ts;
rtp_session->dtmf_data.first_digit = key;
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
rtp_session->dtmf_data.last_duration = duration;
} else {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end);
#endif
switch_cond_next();
return RESULT_GOTO_RECVFROM;
}
}
if (bytes && rtp_session->dtmf_data.in_digit_ts) {
if (!switch_rtp_ready(rtp_session)) {
return RESULT_GOTO_END;
}
if (!rtp_session->dtmf_data.in_interleaved && rtp_session->recv_msg.header.pt != rtp_session->recv_te) {
/* Drat, they are sending audio still as well as DTMF ok fine..... *sigh* */
rtp_session->dtmf_data.in_interleaved = 1;
}
if (rtp_session->dtmf_data.in_interleaved || (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) {
if (rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
return RESULT_GOTO_RECVFROM;
}
} else {
*do_cng = 1;
return RESULT_GOTO_TIMERCHECK;
}
}
return RESULT_CONTINUE;
}
static int global_init = 0;
static int rtp_common_write(switch_rtp_t *rtp_session,
rtp_msg_t *send_msg, void *data, uint32_t datalen, switch_payload_t payload, uint32_t timestamp, switch_frame_flag_t *flags);
@@ -2157,6 +2335,15 @@ static void do_flush(switch_rtp_t *rtp_session)
bytes = sizeof(rtp_msg_t);
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes);
if (bytes) {
int do_cng = 0;
/* Make sure to handle RFC2833 packets, even if we're flushing the packets */
if (bytes > rtp_header_len && rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
handle_rfc2833(rtp_session, bytes, &do_cng);
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "*** RTP packet handled in flush loop ***\n");
#endif
}
flushed++;
@@ -2195,7 +2382,52 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
*bytes = sizeof(rtp_msg_t);
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
ts = ntohl(rtp_session->recv_msg.header.ts);
if (*bytes ) {
uint16_t seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
if (rtp_session->last_seq && rtp_session->last_seq+1 != seq) {
#ifdef DEBUG_MISSED_SEQ
switch_size_t flushed_packets_diff = rtp_session->stats.inbound.flush_packet_count - rtp_session->last_flush_packet_count;
switch_size_t num_missed = (switch_size_t)seq - (rtp_session->last_seq+1);
if (num_missed == 1) { /* We missed one packet */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missed one RTP frame with sequence [%d]%s. Time since last read [%d]\n",
rtp_session->last_seq+1, (flushed_packets_diff == 1) ? " (flushed by FS)" : " (missed)",
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else { /* We missed multiple packets */
if (flushed_packets_diff == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (missed). Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else if (flushed_packets_diff == num_missed) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (flushed by FS). Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else if (num_missed > flushed_packets_diff) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (%d packets flushed by FS, %d packets missed)."
" Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
flushed_packets_diff, num_missed-flushed_packets_diff,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %d RTP frames from sequence [%d] to [%d] (%d packets flushed by FS). Time since last read [%d]\n",
num_missed, rtp_session->last_seq+1, seq-1,
flushed_packets_diff, rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
}
}
#endif
}
rtp_session->last_seq = seq;
}
rtp_session->last_flush_packet_count = rtp_session->stats.inbound.flush_packet_count;
rtp_session->last_read_time = switch_micro_time_now();
if (*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
ts && !rtp_session->jb && !rtp_session->pause_jb && ts == rtp_session->last_cng_ts) {
/* we already sent this frame..... */
@@ -2494,13 +2726,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
if (rtp_session->recv_msg.header.pt != 13 &&
rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
rtp_session->recv_msg.header.pt != rtp_session->payload) {
/* drop frames of incorrect payload number and return CNG frame instead */
return_cng_frame();
}
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP) && rtp_session->rtcp_read_pollfd) {
rtcp_poll_status = switch_poll(rtp_session->rtcp_read_pollfd, 1, &rtcp_fdr, 0);
@@ -2579,6 +2804,15 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
goto end;
}
if (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL) &&
rtp_session->recv_msg.header.pt != 13 &&
rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
rtp_session->recv_msg.header.pt != rtp_session->payload) {
/* drop frames of incorrect payload number and return CNG frame instead */
return_cng_frame();
}
if (!bytes && (io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
rtp_session->missed_count = 0;
ret = 0;
@@ -2835,173 +3069,20 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
bytes = sbytes;
}
#ifdef DEBUG_2833
if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity);
}
#endif
if (rtp_session->dtmf_data.in_digit_sanity && !--rtp_session->dtmf_data.in_digit_sanity) {
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF sanity check.\n");
}
/* RFC2833 ... like all RFC RE: VoIP, guaranteed to drive you to insanity!
We know the real rules here, but if we enforce them, it's an interop nightmare so,
we put up with as much as we can so we don't have to deal with being punished for
doing it right. Nice guys finish last!
*/
if (bytes > rtp_header_len && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
switch_size_t len = bytes - rtp_header_len;
unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body;
int end;
uint16_t duration;
char key;
uint16_t in_digit_seq;
uint32_t ts;
if (!(packet[0] || packet[1] || packet[2] || packet[3]) && len >= 8) {
packet += 4;
len -= 4;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF payload offset by 4 bytes.\n");
}
if (!(packet[0] || packet[1] || packet[2] || packet[3])) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed DTMF payload check.\n");
rtp_session->dtmf_data.last_digit = 0;
rtp_session->dtmf_data.in_digit_ts = 0;
}
end = packet[1] & 0x80 ? 1 : 0;
duration = (packet[2] << 8) + packet[3];
key = switch_rfc2833_to_char(packet[0]);
in_digit_seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
ts = htonl(rtp_session->recv_msg.header.ts);
if (in_digit_seq < rtp_session->dtmf_data.in_digit_seq) {
if (rtp_session->dtmf_data.in_digit_seq - in_digit_seq > 100) {
rtp_session->dtmf_data.in_digit_seq = 0;
}
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned)
packet[1], (unsigned) packet[2], (unsigned) packet[3]);
#endif
if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
rtp_session->dtmf_data.in_digit_seq = in_digit_seq;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq,
ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif
if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) &&
rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) };
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
rtp_session->dtmf_data.in_digit_queued = 1;
}
/* only set sanity if we do NOT ignore the packet */
if (rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
if (rtp_session->dtmf_data.last_duration > duration &&
rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.flip++;
}
if (end) {
if (rtp_session->dtmf_data.in_digit_ts) {
switch_dtmf_t dtmf = { key, duration };
if (ts > rtp_session->dtmf_data.in_digit_ts) {
dtmf.duration += (ts - rtp_session->dtmf_data.in_digit_ts);
}
if (rtp_session->dtmf_data.flip) {
dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF;
rtp_session->dtmf_data.flip = 0;
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n");
#endif
}
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n",
dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration);
#endif
if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8);
#endif
switch_rtp_queue_rfc2833_in(rtp_session, &dtmf);
}
rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit;
rtp_session->dtmf_data.in_digit_ts = 0;
rtp_session->dtmf_data.in_digit_sanity = 0;
rtp_session->dtmf_data.in_digit_queued = 0;
do_cng = 1;
} else {
if (!switch_rtp_ready(rtp_session)) {
goto end;
}
switch_cond_next();
goto recvfrom;
}
} else if (!rtp_session->dtmf_data.in_digit_ts) {
rtp_session->dtmf_data.in_digit_ts = ts;
rtp_session->dtmf_data.first_digit = key;
rtp_session->dtmf_data.in_digit_sanity = 2000;
}
rtp_session->dtmf_data.last_duration = duration;
} else {
#ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end);
#endif
switch_cond_next();
goto recvfrom;
}
}
if (rtp_session->dtmf_data.in_digit_ts) {
}
if (bytes && rtp_session->dtmf_data.in_digit_ts) {
if (!switch_rtp_ready(rtp_session)) {
goto end;
}
if (!rtp_session->dtmf_data.in_interleaved && rtp_session->recv_msg.header.pt != rtp_session->recv_te) {
/* Drat, they are sending audio still as well as DTMF ok fine..... *sigh* */
rtp_session->dtmf_data.in_interleaved = 1;
}
if (rtp_session->dtmf_data.in_interleaved || (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) {
if (rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
goto recvfrom;
}
} else {
return_cng_frame();
}
/* Handle incoming RFC2833 packets */
switch (handle_rfc2833(rtp_session, bytes, &do_cng)) {
case RESULT_GOTO_END:
goto end;
case RESULT_GOTO_RECVFROM:
goto recvfrom;
case RESULT_GOTO_TIMERCHECK:
goto timer_check;
case RESULT_CONTINUE:
goto result_continue;
}
result_continue:
timer_check:
if (do_cng) {