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

This commit is contained in:
David Yat Sin 2010-04-27 14:32:55 -04:00
commit 75190b4dff
36 changed files with 751 additions and 214 deletions

View File

@ -350,7 +350,7 @@ src/include/switch_version.h: src/include/switch_version.h.in .version $(libfree
touch .version ; \
else \
if [ -d .git ] ; then \
version=`git log --format="%h %ci" -1 HEAD | head -1 || echo hacked` ; \
version=`git log --format="%h %ci" -1 HEAD | head -1 | sed -e 's|:|-|g' || echo hacked` ; \
if [ "x$$version" == "xhacked" ] ; then \
version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \
else \

View File

@ -353,7 +353,6 @@ AC_SUBST(PA_LIBS)
AM_CONDITIONAL([ENABLE_ZRTP],[test "x$enable_zrtp" != "xno"])
AM_CONDITIONAL([WANT_DEBUG],[test "${enable_debug}" = "yes"])
AC_ARG_ENABLE(core-odbc-support,
@ -363,6 +362,11 @@ if test "$ac_cv_found_odbc" = "yes" ; then
enable_core_odbc_support="yes"
fi
AC_CHECK_LIB(z, inflateReset, have_libz=yes, have_libz=no)
if test "x$have_libz" = "xyes" ; then
APR_ADDTO(SWITCH_AM_LDFLAGS, -lz)
fi
ESL_LDFLAGS=
PLATFORM_CORE_DEPLIBS=
# tweak platform specific flags

View File

@ -786,7 +786,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
return ESL_FAIL;
}
if (esl_mutex_trylock(handle->mutex) != ESL_SUCCESS) {
if (activity == 0 || !FD_ISSET(handle->sock, &rfds) || (esl_mutex_trylock(handle->mutex) != ESL_SUCCESS)) {
return ESL_BREAK;
}

View File

@ -2179,7 +2179,11 @@ ldl_status ldl_session_get_payloads(ldl_session_t *session, ldl_payload_t **payl
ldl_status ldl_global_terminate(void)
{
ldl_clear_flag_locked((&globals), LDL_FLAG_READY);
if (globals.flag_mutex) {
ldl_clear_flag_locked((&globals), LDL_FLAG_READY);
} else {
ldl_clear_flag((&globals), LDL_FLAG_READY);
}
return LDL_STATUS_SUCCESS;
}

View File

@ -39,8 +39,8 @@ difficult to achieve the precise transcoding procedure laid down in the G.711
specification by other means.
*/
#if !defined(_G711_H_)
#define _G711_H_
#if !defined(FREESWITCH_G711_H)
#define FREESWITCH_G711_H
#ifdef __cplusplus
extern "C" {

View File

@ -18,8 +18,8 @@
*/
#ifndef _SWITCH_DSO_H
#define _SWITCH_DSO_H
#ifndef FREESWITCH_DSO_H
#define FREESWITCH_DSO_H
typedef int (*switch_dso_func_t) (void);
#ifdef WIN32

View File

@ -35,8 +35,8 @@
\ingroup core1
\{
*/
#ifndef _SWITCH_NAT_H
#define _SWITCH_NAT_H
#ifndef FREESWITCH_NAT_H
#define FREESWITCH_NAT_H
SWITCH_BEGIN_EXTERN_C typedef enum {
SWITCH_NAT_TYPE_NONE,

View File

@ -34,8 +34,8 @@
\ingroup core1
\{
*/
#ifndef _SWITCH_STUN_PARSER_H
#define _SWITCH_STUN_PARSER_H
#ifndef FREESWITCH_STUN_PARSER_H
#define FREESWITCH_STUN_PARSER_H
SWITCH_BEGIN_EXTERN_C
#define SWITCH_STUN_DEFAULT_PORT 3478

View File

@ -141,6 +141,7 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_API_HANGUP_HOOK_VARIABLE "api_hangup_hook"
#define SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE "session_in_hangup_hook"
#define SWITCH_PROCESS_CDR_VARIABLE "process_cdr"
#define SWITCH_FORCE_PROCESS_CDR_VARIABLE "force_process_cdr"
#define SWITCH_BRIDGE_CHANNEL_VARIABLE "bridge_channel"
#define SWITCH_CHANNEL_NAME_VARIABLE "channel_name"
#define SWITCH_BRIDGE_UUID_VARIABLE "bridge_uuid"

View File

@ -53,8 +53,8 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _SWITCH_XML_H
#define _SWITCH_XML_H
#ifndef FREESWITCH_XML_H
#define FREESWITCH_XML_H
#include <switch.h>
@ -413,6 +413,8 @@ SWITCH_DECLARE(switch_status_t) switch_xml_unbind_search_function_ptr(_In_ switc
///\return the section mask
SWITCH_DECLARE(switch_xml_section_t) switch_xml_parse_section_string(_In_opt_z_ const char *str);
SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond);
SWITCH_END_EXTERN_C
///\}
#endif // _SWITCH_XML_H

View File

@ -262,6 +262,7 @@ typedef struct conference_obj {
char *sound_prefix;
char *special_announce;
char *auto_record;
uint32_t terminate_on_silence;
uint32_t max_members;
char *maxmember_sound;
uint32_t announce_count;
@ -336,6 +337,8 @@ struct conference_member {
int32_t energy_level;
int32_t volume_in_level;
int32_t volume_out_level;
switch_time_t join_time;
switch_time_t last_talking;
uint32_t native_rate;
switch_audio_resampler_t *read_resampler;
int16_t *resample_out;
@ -638,6 +641,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
switch_mutex_lock(conference->member_mutex);
switch_clear_flag(conference, CFLAG_DESTRUCT);
member->join_time = switch_epoch_time_now(NULL);
member->conference = conference;
member->next = conference->members;
member->energy_level = conference->energy_level;
@ -1045,6 +1049,23 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
switch_mutex_unlock(imember->audio_in_mutex);
}
/* Find if no one talked for more than x number of second */
if (conference->terminate_on_silence && conference->count > 1) {
int is_talking = 0;
for (imember = conference->members; imember; imember = imember->next) {
if (switch_epoch_time_now(NULL) - imember->join_time <= conference->terminate_on_silence) {
is_talking++;
} else if (imember->last_talking != 0 && switch_epoch_time_now(NULL) - imember->last_talking <= conference->terminate_on_silence) {
is_talking++;
}
}
if (is_talking == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Conference has been idle for over %d seconds, terminating\n", conference->terminate_on_silence);
switch_set_flag(conference, CFLAG_DESTRUCT);
}
}
/* Start recording if there's more than one participant. */
if (conference->auto_record && !conference->is_recording && conference->count > 1) {
conference->is_recording = 1;
@ -1912,6 +1933,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
if (diff >= diff_level || ++hangunder_hits >= hangunder) {
hangover_hits = hangunder_hits = 0;
member->last_talking = switch_epoch_time_now(NULL);
if (!switch_test_flag(member, MFLAG_TALKING)) {
switch_event_t *event;
@ -3616,6 +3638,12 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer
add_x_tag(x_member, "caller_id_number", profile->caller_id_number, toff++);
switch_snprintf(i, sizeof(i), "%d", switch_epoch_time_now(NULL) - member->join_time);
add_x_tag(x_member, "join_time", i, toff++);
switch_snprintf(i, sizeof(i), "%d", switch_epoch_time_now(NULL) - member->last_talking);
add_x_tag(x_member, "last_talking", member->last_talking ? i : "N/A", toff++);
x_flags = switch_xml_add_child_d(x_member, "flags", count++);
switch_assert(x_flags);
@ -5793,6 +5821,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
char *suppress_events = NULL;
char *verbose_events = NULL;
char *auto_record = NULL;
char *terminate_on_silence = NULL;
/* Validate the conference name */
if (zstr(name)) {
@ -5922,6 +5951,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
verbose_events = val;
} else if (!strcasecmp(var, "auto-record") && !zstr(val)) {
auto_record = val;
} else if (!strcasecmp(var, "terminate-on-silence") && !zstr(val)) {
terminate_on_silence = val;
}
}
@ -6093,6 +6124,9 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
if (!zstr(auto_record)) {
conference->auto_record = switch_core_strdup(conference->pool, auto_record);
}
if (!zstr(terminate_on_silence)) {
conference->terminate_on_silence = atoi(terminate_on_silence);
}
if (!zstr(verbose_events) && switch_true(verbose_events)) {
conference->verbose_events = 1;

View File

@ -8,8 +8,8 @@
* Offered for use in the public domain without any warranty.
*/
#ifndef _CONIO_H_
#define _CONIO_H_
#ifndef CONIO_H
#define CONIO_H
#include <stdio.h>

View File

@ -75,6 +75,15 @@ static int sql2str_callback(void *pArg, int argc, char **argv, char **columnName
return 0;
}
static switch_bool_t match_key(const char *caller_exit_key, char key)
{
while (caller_exit_key && *caller_exit_key) {
if (*caller_exit_key++ == key) {
return SWITCH_TRUE;
}
}
return SWITCH_FALSE;
}
static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
{
@ -131,7 +140,7 @@ static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input,
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *caller_exit_key = switch_channel_get_variable(channel, "fifo_caller_exit_key");
if (caller_exit_key && dtmf->digit == *caller_exit_key) {
if (match_key(caller_exit_key, dtmf->digit)) {
char *bp = buf;
*bp = dtmf->digit;
return SWITCH_STATUS_BREAK;
@ -230,9 +239,10 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session
return SWITCH_STATUS_FALSE;
}
if (caller_exit_key && *buf == *caller_exit_key) {
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++;
@ -1051,7 +1061,8 @@ SWITCH_STANDARD_APP(fifo_function)
switch_ivr_collect_digits_callback(session, &args, 0, 0);
}
if (caller_exit_key && *buf == *caller_exit_key) {
if (match_key(caller_exit_key, *buf)) {
switch_channel_set_variable(channel, "fifo_caller_exit_key", (char *)buf);
aborted = 1;
goto abort;
}

View File

@ -128,16 +128,17 @@ SWITCH_STANDARD_API(dump_hash)
return SWITCH_STATUS_SUCCESS;
}
static void event_handler(switch_event_t *event)
static switch_status_t process_event(switch_event_t *event)
{
switch_core_session_t *session = NULL;
switch_channel_t *channel;
char *username[2] = { 0 };
char *domain[2] = { 0 };
char *username[3] = { 0 };
char *domain[3] = { 0 };
char key[512];
char *uuid = NULL, *my_uuid = NULL;
int i;
switch_thread_rwlock_rdlock(globals.spy_hash_lock);
if (!globals.spy_count) {
@ -146,10 +147,15 @@ static void event_handler(switch_event_t *event)
username[0] = switch_event_get_header(event, "Caller-Username");
domain[0] = switch_event_get_header(event, "variable_domain_name");
domain[1] = switch_event_get_header(event, "variable_dialed_domain");
username[1] = switch_event_get_header(event, "variable_dialed_user");
for (i = 0; i < 2; i++) {
username[2] = switch_event_get_header(event, "variable_user_name");
domain[2] = switch_event_get_header(event, "variable_domain_name");
for (i = 0; i < 3; i++) {
if (username[i] && domain[i]) {
switch_snprintf(key, sizeof(key), "%s@%s", username[i], domain[i]);
@ -159,11 +165,11 @@ static void event_handler(switch_event_t *event)
}
}
done:
done:
switch_thread_rwlock_unlock(globals.spy_hash_lock);
if (!uuid) {
return;
return SWITCH_STATUS_FALSE;
}
session = switch_core_session_locate(uuid);
@ -178,9 +184,46 @@ static void event_handler(switch_event_t *event)
switch_channel_set_flag(channel, CF_BREAK);
switch_core_session_rwunlock(session);
return SWITCH_STATUS_SUCCESS;
}
static void event_handler(switch_event_t *event)
{
if (process_event(event) != SWITCH_STATUS_SUCCESS) {
const char *peer_uuid = switch_event_get_header(event, "variable_signal_bond");
switch_core_session_t *peer_session = NULL;
switch_channel_t *peer_channel = NULL;
switch_event_t *peer_event = NULL;
if (!peer_uuid) {
return;
}
if (!(peer_session = switch_core_session_locate(peer_uuid))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cant locate peer session for uuid %s\n", peer_uuid);
return;
}
peer_channel = switch_core_session_get_channel(peer_session);
if (switch_event_create(&peer_event, SWITCH_EVENT_CHANNEL_BRIDGE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cant create bridge event for peer channel %s\n", peer_uuid);
goto end;
}
switch_channel_event_set_data(peer_channel, peer_event);
end:
switch_core_session_rwunlock(peer_session);
if (peer_event) {
process_event(peer_event);
switch_event_destroy(&peer_event);
}
}
}
#define USERSPY_SYNTAX "<user@domain> [uuid]"
SWITCH_STANDARD_APP(userspy_function)
{

View File

@ -22,8 +22,8 @@
*
*/
#if !defined(_UDPTL_H_)
#define _UDPTL_H_
#if !defined(FREESWITCH_UDPTL_H)
#define FREESWITCH_UDPTL_H
#define LOCAL_FAX_MAX_DATAGRAM 400
#define LOCAL_FAX_MAX_FEC_PACKETS 5

View File

@ -1524,7 +1524,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
TRY_CODE(switch_ivr_phrase_macro(session, VM_INVALID_EXTENSION_MACRO, vm_cc, NULL, NULL));
goto get_exten;
}
} else if (!strcmp(input, profile->delete_file_key) || !strcmp(input, profile->email_key)) {
} else if (!strcmp(input, profile->delete_file_key) || (!strcmp(input, profile->email_key) && !zstr(cbt->email))) {
char *sql = switch_mprintf("update voicemail_msgs set flags='delete' where uuid='%s'", cbt->uuid);
vm_execute_sql(profile, sql, profile->mutex);
switch_safe_free(sql);
@ -1681,7 +1681,7 @@ static void update_mwi(vm_profile_t *profile, const char *id, const char *domain
}
#define FREE_DOMAIN_ROOT() if (x_domain_root) switch_xml_free(x_domain_root); x_user = x_domain = x_domain_root = NULL
#define FREE_DOMAIN_ROOT() if (x_user) switch_xml_free(x_user); x_user = NULL
static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *profile, const char *domain_name, const char *id, int auth)
@ -1689,7 +1689,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
vm_check_state_t vm_check_state = VM_CHECK_START;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_caller_profile_t *caller_profile = switch_channel_get_caller_profile(channel);
switch_xml_t x_domain = NULL, x_domain_root = NULL, x_user = NULL, x_params, x_param;
switch_xml_t x_user = NULL, x_params, x_param;
switch_status_t status;
char pass_buf[80] = "", *mypass = NULL, id_buf[80] = "", *myfolder = NULL;
const char *thepass = NULL, *myid = id, *thehash = NULL, *vmhash = NULL;
@ -2083,18 +2083,37 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
switch_event_t *params;
int ok = 1;
switch_event_create(&params, SWITCH_EVENT_GENERAL);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "destination_number", caller_profile->destination_number);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "caller_id_number", caller_id_number);
if (switch_xml_locate_user("id", myid, domain_name, switch_channel_get_variable(channel, "network_addr"),
&x_domain_root, &x_domain, &x_user, NULL, params) != SWITCH_STATUS_SUCCESS) {
if (switch_xml_locate_user_merged("id", myid, domain_name, switch_channel_get_variable(channel, "network_addr"),
&x_user, params) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", myid, domain_name);
ok = 0;
} else {
switch_bool_t vm_enabled = SWITCH_TRUE;
x_params = switch_xml_child(x_user, "params");
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr_soft(x_param, "value");
if (zstr(var) || zstr(val)) {
continue; /* Ignore empty entires */
}
if (!strcasecmp(var, "vm-enabled")) {
vm_enabled = !switch_false(val);
}
}
if (!vm_enabled) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "User [%s@%s] have voicemail disabled\n", myid, domain_name);
ok = 0;
}
myid = switch_core_session_strdup(session, switch_xml_attr(x_user, "id"));
}
@ -2261,9 +2280,9 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
status = switch_ivr_phrase_macro(session, VM_GOODBYE_MACRO, NULL, NULL, NULL);
}
if (x_domain_root) {
switch_xml_free(x_domain_root);
x_domain_root = NULL;
if (x_user) {
switch_xml_free(x_user);
x_user = NULL;
}
}
@ -2836,6 +2855,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
int disk_quota = 0;
switch_bool_t skip_greeting = switch_true(switch_channel_get_variable(channel, "skip_greeting"));
switch_bool_t skip_instructions = switch_true(switch_channel_get_variable(channel, "skip_instructions"));
switch_bool_t vm_enabled = SWITCH_TRUE;
switch_channel_set_variable(channel, "skip_greeting", NULL);
switch_channel_set_variable(channel, "skip_instructions", NULL);
@ -2888,12 +2908,19 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
disk_quota = atoi(val);
} else if (!strcasecmp(var, "vm-alternate-greet-id")) {
read_id = switch_core_session_strdup(session, val);
} else if (!strcasecmp(var, "vm-enabled")) {
vm_enabled = !switch_false(val);
} else if (!strcasecmp(var, "vm-message-ext")) {
vm_ext = switch_core_session_strdup(session, val);
}
}
}
if (!vm_enabled) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "User [%s@%s] have voicemail disabled\n", id, domain_name);
ok = 0;
}
if (send_main && zstr(vm_email) && !zstr(email_addr)) {
vm_email = switch_core_session_strdup(session, email_addr);
if (zstr(vm_email)) {

View File

@ -101,19 +101,7 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
switch_bool_t anti_action = SWITCH_TRUE;
break_t do_break_i = BREAK_ON_FALSE;
const char *xyear = switch_xml_attr(xcond, "year");
const char *xyday = switch_xml_attr(xcond, "yday");
const char *xmon = switch_xml_attr(xcond, "mon");
const char *xmday = switch_xml_attr(xcond, "mday");
const char *xweek = switch_xml_attr(xcond, "week");
const char *xmweek = switch_xml_attr(xcond, "mweek");
const char *xwday = switch_xml_attr(xcond, "wday");
const char *xhour = switch_xml_attr(xcond, "hour");
const char *xminute = switch_xml_attr(xcond, "minute");
const char *xminday = switch_xml_attr(xcond, "minute-of-day");
switch_time_t ts = switch_micro_time_now();
int time_match = -1;
switch_time_exp_t tm;
int time_match = switch_xml_std_datetime_check(xcond);
switch_safe_free(field_expanded);
switch_safe_free(expression_expanded);
@ -124,81 +112,6 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
goto done;
}
switch_time_exp_lt(&tm, ts);
if (time_match && xyear) {
int test = tm.tm_year + 1900;
time_match = switch_number_cmp(xyear, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: year[%d] =~ %s (%s)\n", test, xyear, time_match ? "PASS" : "FAIL");
}
if (time_match && xyday) {
int test = tm.tm_yday + 1;
time_match = switch_number_cmp(xyday, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: day of year[%d] =~ %s (%s)\n", test, xyday, time_match ? "PASS" : "FAIL");
}
if (time_match && xmon) {
int test = tm.tm_mon + 1;
time_match = switch_number_cmp(xmon, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: month[%d] =~ %s (%s)\n", test, xmon, time_match ? "PASS" : "FAIL");
}
if (time_match && xmday) {
int test = tm.tm_mday;
time_match = switch_number_cmp(xmday, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: day of month[%d] =~ %s (%s)\n", test, xmday, time_match ? "PASS" : "FAIL");
}
if (time_match && xweek) {
int test = (int) (tm.tm_yday / 7 + 1);
time_match = switch_number_cmp(xweek, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: week of year[%d] =~ %s (%s)\n", test, xweek, time_match ? "PASS" : "FAIL");
}
if (time_match && xmweek) {
/* calculate the day of the week of the first of the month (0-6) */
int firstdow = (int) (7 - (tm.tm_mday - (tm.tm_wday + 1)) % 7) % 7;
/* calculate the week of the month (1-6) */
int test = (int) ceil((tm.tm_mday + firstdow) / 7.0);
time_match = switch_number_cmp(xmweek, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: week of month[%d] =~ %s (%s)\n", test, xmweek, time_match ? "PASS" : "FAIL");
}
if (time_match && xwday) {
int test = tm.tm_wday + 1;
time_match = switch_number_cmp(xwday, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: day of week[%d] =~ %s (%s)\n", test, xwday, time_match ? "PASS" : "FAIL");
}
if (time_match && xhour) {
int test = tm.tm_hour;
time_match = switch_number_cmp(xhour, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: hour[%d] =~ %s (%s)\n", test, xhour, time_match ? "PASS" : "FAIL");
}
if (time_match && xminute) {
int test = tm.tm_min;
time_match = switch_number_cmp(xminute, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: minute[%d] =~ %s (%s)\n", test, xminute, time_match ? "PASS" : "FAIL");
}
if (time_match && xminday) {
int test = (tm.tm_hour * 60) + (tm.tm_min + 1);
time_match = switch_number_cmp(xminday, test);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
"Dialplan: minute of day[%d] =~ %s (%s)\n", test, xminday, time_match ? "PASS" : "FAIL");
}
field = (char *) switch_xml_attr(xcond, "field");
if ((xexpression = switch_xml_child(xcond, "expression"))) {

View File

@ -1,5 +1,5 @@
#ifndef _PABLIO_H
#define _PABLIO_H
#ifndef PORTAUDIO_PABLIO_H
#define PORTAUDIO_PABLIO_H
#ifdef __cplusplus
extern "C" {

View File

@ -392,7 +392,13 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
switch_call_cause_t cause = switch_channel_get_cause(channel);
int sip_cause = hangup_cause_to_sip(cause);
const char *ps_cause = NULL, *use_my_cause;
const char *gateway_name = NULL;
sofia_gateway_t *gateway_ptr = NULL;
if ((gateway_name = switch_channel_get_variable(channel, "sip_gateway_name"))) {
gateway_ptr = sofia_reg_find_gateway(gateway_name);
}
switch_mutex_lock(tech_pvt->sofia_mutex);
sofia_clear_flag(tech_pvt, TFLAG_RECOVERING);
@ -405,6 +411,18 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
} else {
tech_pvt->profile->ib_failed_calls++;
}
if (gateway_ptr) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
gateway_ptr->ob_failed_calls++;
} else {
gateway_ptr->ib_failed_calls++;
}
}
}
if (gateway_ptr) {
sofia_reg_release_gateway(gateway_ptr);
}
if (!((use_my_cause = switch_channel_get_variable(channel, "sip_ignore_remote_cause")) && switch_true(use_my_cause))) {
@ -2086,7 +2104,14 @@ const char *sofia_state_string(int state)
return sofia_state_names[state];
}
struct cb_helper_sql2str {
char *buf;
size_t len;
int matches;
};
struct cb_helper {
uint32_t row_process;
sofia_profile_t *profile;
switch_stream_handle_t *stream;
};
@ -2097,12 +2122,17 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
{
struct cb_helper *cb = (struct cb_helper *) pArg;
char exp_buf[128] = "";
int exp_secs = 0;
switch_time_exp_t tm;
cb->row_process++;
if (argv[6]) {
time_t now = switch_epoch_time_now(NULL);
switch_time_t etime = atoi(argv[6]);
switch_size_t retsize;
exp_secs = 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);
}
@ -2112,7 +2142,7 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
"User: \t%s@%s\n"
"Contact: \t%s\n"
"Agent: \t%s\n"
"Status: \t%s(%s) EXP(%s)\n"
"Status: \t%s(%s) EXP(%s) EXPSECS(%d)\n"
"Host: \t%s\n"
"IP: \t%s\n"
"Port: \t%s\n"
@ -2120,7 +2150,7 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam
"Auth-Realm: \t%s\n"
"MWI-Account:\t%s@%s\n\n",
switch_str_nil(argv[0]), switch_str_nil(argv[1]), switch_str_nil(argv[2]), switch_str_nil(argv[3]),
switch_str_nil(argv[7]), switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf, switch_str_nil(argv[11]),
switch_str_nil(argv[7]), switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf, exp_secs, switch_str_nil(argv[11]),
switch_str_nil(argv[12]), switch_str_nil(argv[13]), switch_str_nil(argv[14]), switch_str_nil(argv[15]),
switch_str_nil(argv[16]), switch_str_nil(argv[17]));
return 0;
@ -2133,11 +2163,16 @@ static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **colum
switch_time_exp_t tm;
const int buflen = 2048;
char xmlbuf[2048];
int exp_secs = 0;
cb->row_process++;
if (argv[6]) {
time_t now = switch_epoch_time_now(NULL);
switch_time_t etime = atoi(argv[6]);
switch_size_t retsize;
exp_secs = 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);
}
@ -2147,7 +2182,7 @@ static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **colum
cb->stream->write_function(cb->stream," <user>%s@%s</user>\n", switch_str_nil(argv[1]), switch_str_nil(argv[2]));
cb->stream->write_function(cb->stream," <contact>%s</contact>\n", switch_amp_encode(switch_str_nil(argv[3]), xmlbuf, buflen));
cb->stream->write_function(cb->stream," <agent>%s</agent>\n", switch_str_nil(argv[7]));
cb->stream->write_function(cb->stream," <status>%s(%s) exp(%s)</status>\n", switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf);
cb->stream->write_function(cb->stream," <status>%s(%s) exp(%s) expsecs(%d)</status>\n", switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf, exp_secs);
cb->stream->write_function(cb->stream," <host>%s</host>\n", switch_str_nil(argv[11]));
cb->stream->write_function(cb->stream," <network-ip>%s</network-ip>\n", switch_str_nil(argv[12]));
cb->stream->write_function(cb->stream," <network-port>%s</network-port>\n", switch_str_nil(argv[13]));
@ -2175,7 +2210,56 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
if (argc > 0) {
if (argc == 1) {
stream->write_function(stream, "Invalid Syntax!\n");
/* show summary of all gateways*/
uint32_t ib_failed = 0;
uint32_t ib = 0;
uint32_t ob_failed = 0;
uint32_t ob = 0;
stream->write_function(stream, "%25s\t%32s\t%s\t%s\t%s\n", "Profile::Gateway-Name", " Data ", "State", "IB Calls(F/T)", "OB Calls(F/T)");
stream->write_function(stream, "%s\n", line);
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
if (!strcmp(vvar, profile->name)) { /* not an alias */
for (gp = profile->gateways; gp; gp = gp->next) {
char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
switch_assert(gp->state < REG_STATE_LAST);
c++;
ib_failed += gp->ib_failed_calls;
ib += gp->ib_calls;
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",
pkey, gp->register_to, sofia_state_names[gp->state],
gp->ib_failed_calls, gp->ib_calls, gp->ob_failed_calls, gp->ob_calls);
if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
time_t now = switch_epoch_time_now(NULL);
if (gp->retry > now) {
stream->write_function(stream, " (retry: %ds)", gp->retry - now);
} else {
stream->write_function(stream, " (retry: NEVER)");
}
}
stream->write_function(stream, "\n");
}
}
}
}
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);
return SWITCH_STATUS_SUCCESS;
}
@ -2205,6 +2289,8 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
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, "%s\n", line);
sofia_reg_release_gateway(gp);
} else {
@ -2213,7 +2299,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;
cb.row_process = 0;
if ((argv[1]) && (profile = sofia_glue_find_profile(argv[1]))) {
if (!argv[2] || (strcasecmp(argv[2], "reg") && strcasecmp(argv[2], "user"))) {
stream->write_function(stream, "%s\n", line);
@ -2334,6 +2420,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb);
switch_safe_free(sql);
stream->write_function(stream, "Total items returned: %d\n", cb.row_process);
stream->write_function(stream, "%s\n", line);
sofia_glue_release_profile(profile);
@ -2412,7 +2499,46 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
if (argc > 0) {
if (argc == 1) {
stream->write_function(stream, "Invalid Syntax!\n");
/* show summary of all gateways */
stream->write_function(stream, "%s\n", header);
stream->write_function(stream, "<gateways>\n", header);
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
if (!strcmp(vvar, profile->name)) { /* not an alias */
for (gp = profile->gateways; gp; gp = gp->next) {
switch_assert(gp->state < REG_STATE_LAST);
stream->write_function(stream, "\t<gateway>\n");
stream->write_function(stream, "\t\t<profile>%s</profile>\n", profile->name);
stream->write_function(stream, "\t\t<to>%s</to>\n", gp->register_to);
stream->write_function(stream, "\t\t<state>%s</state>\n", sofia_state_names[gp->state]);
stream->write_function(stream, "\t\t<calls-in>%ld</calls-in>\n", gp->ib_calls);
stream->write_function(stream, "\t\t<calls-out>%ld</calls-out>\n", gp->ob_calls);
stream->write_function(stream, "\t\t<failed-calls-in>%ld</failed-calls-in>\n", gp->ib_failed_calls);
stream->write_function(stream, "\t\t<failed-calls-out>%ld</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);
if (gp->retry > now) {
stream->write_function(stream, "\t\t<retry>%ds</retry>\n", gp->retry - now);
} else {
stream->write_function(stream, "\t\t<retry>NEVER</retry>\n");
}
}
stream->write_function(stream, "\t</gateway>\n");
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
stream->write_function(stream, "</gateways>\n");
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[0], "gateway")) {
@ -2440,7 +2566,8 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
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</calls-in>\n", gp->ib_failed_calls);
stream->write_function(stream, " <failed-calls-out>%d</calls-out>\n", gp->ob_failed_calls);
stream->write_function(stream, " </gateway>\n");
sofia_reg_release_gateway(gp);
} else {
@ -2449,6 +2576,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;
cb.row_process = 0;
if ((argv[1]) && (profile = sofia_glue_find_profile(argv[1]))) {
stream->write_function(stream, "%s\n", header);
@ -2867,6 +2995,8 @@ static int contact_callback(void *pArg, int argc, char **argv, char **columnName
struct cb_helper *cb = (struct cb_helper *) pArg;
char *contact;
cb->row_process++;
if (!zstr(argv[0]) && (contact = sofia_glue_get_url_from_contact(argv[0], 1))) {
cb->stream->write_function(cb->stream, "%ssofia/%s/sip:%s,", argv[2], argv[1], sofia_glue_strip_proto(contact));
free(contact);
@ -2874,7 +3004,115 @@ static int contact_callback(void *pArg, int argc, char **argv, char **columnName
return 0;
}
static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct cb_helper_sql2str *cbt = (struct cb_helper_sql2str *) pArg;
switch_copy_string(cbt->buf, argv[0], cbt->len);
cbt->matches++;
return 0;
}
SWITCH_STANDARD_API(sofia_count_reg_function) {
char *data;
char *user = NULL;
char *domain = NULL;
char *concat = NULL;
char *profile_name = NULL;
char *p;
char *reply = "-1";
sofia_profile_t *profile = NULL;
if (!cmd) {
stream->write_function(stream, "%s", "");
return SWITCH_STATUS_SUCCESS;
}
data = strdup(cmd);
switch_assert(data);
if ((p = strchr(data, '/'))) {
profile_name = data;
*p++ = '\0';
user = p;
} else {
user = data;
}
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
if ( (concat = strchr( domain, '/')) ) {
*concat++ = '\0';
}
}
else {
if ( (concat = strchr( user, '/')) ) {
*concat++ = '\0';
}
}
if (!profile_name && domain) {
profile_name = domain;
}
if (user && profile_name) {
char *sql;
if (!(profile = sofia_glue_find_profile(profile_name))) {
profile_name = domain;
domain = NULL;
}
if (!profile && profile_name) {
profile = sofia_glue_find_profile(profile_name);
}
if (profile) {
struct cb_helper_sql2str cb;
char reg_count[80] = "";
cb.buf = reg_count;
cb.len = sizeof(reg_count);
if (!domain || !strchr(domain, '.')) {
domain = profile->name;
}
if (zstr(user)) {
sql = switch_mprintf("select count(*) "
"from sip_registrations where (sip_host='%q' or presence_hosts like '%%%q%%')",
( concat != NULL ) ? concat : "", domain, domain);
} else {
sql = switch_mprintf("select count(*) "
"from sip_registrations where (sip_user='%q' or dir_user='%q') and (sip_host='%q' or presence_hosts like '%%%q%%')",
( concat != NULL ) ? concat : "", user, user, domain, domain);
}
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sql2str_callback, &cb);
switch_safe_free(sql);
if (!zstr(reg_count)) {
stream->write_function(stream, "%s", reg_count);
} else {
stream->write_function(stream, "0");
}
reply = NULL;
}
}
if (reply) {
stream->write_function(stream, "%s", reply);
}
switch_safe_free(data);
if (profile) {
sofia_glue_release_profile(profile);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(sofia_contact_function)
{
char *data;
@ -2940,6 +3178,8 @@ SWITCH_STANDARD_API(sofia_contact_function)
struct cb_helper cb;
switch_stream_handle_t mystream = { 0 };
cb.row_process = 0;
if (!domain || (!strchr(domain, '.') && strcmp(profile_name, domain))) {
domain = profile->name;
}
@ -3255,6 +3495,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (gateway_ptr->status != SOFIA_GATEWAY_UP) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway is down!\n");
cause = SWITCH_CAUSE_NETWORK_OUT_OF_ORDER;
gateway_ptr->ob_failed_calls++;
sofia_reg_release_gateway(gateway_ptr);
gateway_ptr = NULL;
goto error;
@ -3280,6 +3521,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
tech_pvt->transport = sofia_glue_str2transport(tp_param);
if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN) {
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
gateway_ptr->ob_failed_calls++;
goto error;
}
}
@ -4161,6 +4403,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_count_reg", "Count Sofia registration", sofia_count_reg_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_dig", "SIP DIG", sip_dig_function, "<url>");
SWITCH_ADD_CHAT(chat_interface, SOFIA_CHAT_PROTO, sofia_presence_chat_send);

View File

@ -402,6 +402,8 @@ struct sofia_gateway {
switch_event_t *ob_vars;
uint32_t ib_calls;
uint32_t ob_calls;
uint32_t ib_failed_calls;
uint32_t ob_failed_calls;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
int failures;
struct sofia_gateway *next;

View File

@ -1758,6 +1758,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
gateway->ping_max = 0;
gateway->ping_min = 0;
gateway->ping_count = 0;
gateway->ib_calls = 0;
gateway->ob_calls = 0;
gateway->ib_failed_calls = 0;
gateway->ob_failed_calls = 0;
if ((x_params = switch_xml_child(gateway_tag, "variables"))) {
param = switch_xml_child(x_params, "variable");

View File

@ -2189,6 +2189,7 @@ void sofia_glue_deactivate_rtp(private_object_t *tech_pvt)
if (tech_pvt->local_sdp_video_port > 0 && !zstr(tech_pvt->remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->remote_ip)) {
switch_nat_del_mapping((switch_port_t) tech_pvt->local_sdp_video_port, SWITCH_NAT_UDP);
switch_nat_del_mapping((switch_port_t) tech_pvt->local_sdp_video_port + 1, SWITCH_NAT_UDP);
}
@ -2200,6 +2201,7 @@ void sofia_glue_deactivate_rtp(private_object_t *tech_pvt)
if (tech_pvt->local_sdp_audio_port > 0 && !zstr(tech_pvt->remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->remote_ip)) {
switch_nat_del_mapping((switch_port_t) tech_pvt->local_sdp_audio_port, SWITCH_NAT_UDP);
switch_nat_del_mapping((switch_port_t) tech_pvt->local_sdp_audio_port + 1, SWITCH_NAT_UDP);
}
}

View File

@ -1901,7 +1901,7 @@ void sofia_presence_handle_sip_i_subscribe(int status,
full_from = sip_header_as_string(profile->home, (void *) sip->sip_from);
full_via = sip_header_as_string(profile->home, (void *) sip->sip_via);
if (sip->sip_expires->ex_delta > 31536000) {
if (sip && sip->sip_expires && sip->sip_expires->ex_delta > 31536000) {
sip->sip_expires->ex_delta = 31536000;
}

View File

@ -1688,6 +1688,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
const char *passwd = NULL;
const char *a1_hash = NULL;
const char *mwi_account = NULL;
switch_bool_t allow_empty_password = SWITCH_TRUE;
const char *call_id = NULL;
char *sql;
char *number_alias = NULL;
@ -1924,7 +1925,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
if (!strcasecmp(var, "mwi-account")) {
mwi_account = val;
}
if (!strcasecmp(var, "allow-empty-password")) {
allow_empty_password = switch_true(val);
}
if (!strcasecmp(var, "user-agent-filter")) {
user_agent_filter = val;
}
@ -1958,7 +1961,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
if (!strcasecmp(var, "mwi-account")) {
mwi_account = val;
}
if (!strcasecmp(var, "allow-empty-password")) {
allow_empty_password = switch_true(val);
}
if (!strcasecmp(var, "user-agent-filter")) {
user_agent_filter = val;
}
@ -1992,6 +1997,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
if (!strcasecmp(var, "mwi-account")) {
mwi_account = val;
}
if (!strcasecmp(var, "allow-empty-password")) {
allow_empty_password = switch_true(val);
}
if (!strcasecmp(var, "user-agent-filter")) {
user_agent_filter = val;
}
@ -2058,6 +2066,12 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
}
}
if (!allow_empty_password && zstr(passwd) && zstr(a1_hash)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Empty password denied for user %s@%s\n", username, domain_name);
ret = AUTH_FORBIDDEN;
goto end;
}
if (zstr(passwd) && zstr(a1_hash)) {
ret = AUTH_OK;
goto skip_auth;

View File

@ -620,7 +620,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
is_b = channel && switch_channel_get_originator_caller_profile(channel);
if (!globals.log_b && is_b) {
return SWITCH_STATUS_SUCCESS;
const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE);
if (!switch_true(force_cdr)) {
return SWITCH_STATUS_SUCCESS;
}
}
if (!is_b && globals.prefix_a)
a_prefix = "a_";

View File

@ -200,7 +200,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
is_b = channel && switch_channel_get_originator_caller_profile(channel);
if (!globals.log_b && is_b) {
return SWITCH_STATUS_SUCCESS;
const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE);
if (!switch_true(force_cdr)) {
return SWITCH_STATUS_SUCCESS;
}
}
if (!is_b && globals.prefix_a)
a_prefix = "a_";
@ -334,7 +337,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
switch_yield(globals.delay * 1000000);
}
destUrl = switch_mprintf("%s?uuid=%s", globals.urls[globals.url_index], switch_core_session_get_uuid(session));
destUrl = switch_mprintf("%s?uuid=%s&leg=%c", globals.urls[globals.url_index], switch_core_session_get_uuid(session),
is_b ? 'b' : 'a');
curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl);
if (!strncasecmp(destUrl, "https", 5)) {

View File

@ -13,8 +13,8 @@
* <http://www.OpenLDAP.org/license.html>.
*/
#ifndef _LUTIL_LDAP_H
#define _LUTIL_LDAP_H 1
#ifndef LUTIL_LDAP_H
#define LUTIL_LDAP_H
#include <ldap_cdefs.h>
#include <lber_types.h>

View File

@ -241,6 +241,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel,
(*channel)->hangup_cause = SWITCH_CAUSE_NONE;
(*channel)->name = "";
(*channel)->direction = direction;
switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
return SWITCH_STATUS_SUCCESS;
}

View File

@ -958,6 +958,7 @@ static void core_event_handler(switch_event_t *event)
case SWITCH_EVENT_CHANNEL_DESTROY:
sql = switch_mprintf("delete from channels where uuid='%q' and hostname='%q'",
switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
printf("%s\n", sql);
break;
case SWITCH_EVENT_CHANNEL_UUID:
{
@ -1143,7 +1144,7 @@ static void core_event_handler(switch_event_t *event)
}
if (sql) {
if (switch_stristr("update channels", sql)) {
if (switch_stristr("update channels", sql) || switch_stristr("delete from channels", sql)) {
switch_queue_push(sql_manager.sql_queue[1], sql);
} else {
switch_queue_push(sql_manager.sql_queue[0], sql);

View File

@ -526,8 +526,9 @@ SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *ses
switch_api_execute(cmd, expanded, use_session, &stream);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s(%s):\n%s\n", cmd, switch_str_nil(expanded),
switch_str_nil((char *) stream.data));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s %s(%s):\n%s\n",
use_session ? "with Session" : "with no Session", cmd, switch_str_nil(expanded),
switch_str_nil((char *) stream.data) );
if (expanded != arg) {
switch_safe_free(expanded);

View File

@ -131,7 +131,7 @@ void *switch_dso_data_sym(switch_dso_lib_t lib, const char *sym, char **err)
dlerror();
if (!(addr = dlsym(lib, sym))) {
err_str = dlerror();
err_str = (char *)dlerror();
}
if (err_str) {

View File

@ -353,10 +353,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_displace_session(switch_core_session_
switch_media_bug_t *bug;
switch_status_t status;
time_t to = 0;
char *ext;
const char *prefix;
displace_helper_t *dh;
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
if (zstr(file)) {
return SWITCH_STATUS_FALSE;
}
if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
@ -376,6 +381,34 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_displace_session(switch_core_session_
return SWITCH_STATUS_MEMERR;
}
if (!(prefix = switch_channel_get_variable(channel, "sound_prefix"))) {
prefix = SWITCH_GLOBAL_dirs.base_dir;
}
if (!strstr(file, SWITCH_URL_SEPARATOR)) {
if (!switch_is_file_path(file)) {
char *tfile = NULL;
char *e;
if (*file == '[') {
tfile = switch_core_session_strdup(session, file);
if ((e = switch_find_end_paren(tfile, '[', ']'))) {
*e = '\0';
file = e + 1;
} else {
tfile = NULL;
}
}
file = switch_core_session_sprintf(session, "%s%s%s%s%s", switch_str_nil(tfile), tfile ? "]" : "", prefix, SWITCH_PATH_SEPARATOR, file);
}
if ((ext = strrchr(file, '.'))) {
ext++;
} else {
ext = read_impl.iananame;
file = switch_core_session_sprintf(session, "%s.%s", file, ext);
}
}
dh->fh.channels = read_impl.number_of_channels;
dh->fh.samplerate = read_impl.actual_samples_per_second;

View File

@ -372,6 +372,38 @@ static switch_bool_t monitor_callback(switch_core_session_t *session, const char
return SWITCH_FALSE;
}
static void inherit_codec(switch_channel_t *caller_channel, switch_core_session_t *session)
{
const char *var = switch_channel_get_variable(caller_channel, "inherit_codec");
switch_channel_t *channel = switch_core_session_get_channel(session);
if (switch_true(var)) {
switch_codec_implementation_t impl = { 0 };
switch_codec_implementation_t video_impl = { 0 };
char tmp[128] = "";
if (switch_core_session_get_read_impl(session, &impl) == SWITCH_STATUS_SUCCESS) {
if (switch_core_session_get_video_read_impl(session, &impl) == SWITCH_STATUS_SUCCESS) {
switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui,%s",
impl.iananame, impl.samples_per_second, impl.microseconds_per_packet / 1000,
video_impl.iananame);
} else {
switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui",
impl.iananame, impl.samples_per_second, impl.microseconds_per_packet / 1000);
}
switch_channel_set_variable(caller_channel, "absolute_codec_string", tmp);
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "Setting codec string on %s to %s\n",
switch_channel_get_name(caller_channel), tmp);
} else {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_WARNING,
"Error inheriting codec. Channel %s has no read codec yet.\n",
switch_channel_get_name(channel));
}
}
}
static uint8_t check_channel_status(originate_global_t *oglobals, originate_status_t *originate_status, uint32_t len)
{
@ -671,32 +703,7 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat
end:
if (pindex > -1 && caller_channel && switch_channel_ready(caller_channel) && !switch_channel_media_ready(caller_channel)) {
const char *var = switch_channel_get_variable(caller_channel, "inherit_codec");
if (switch_true(var)) {
switch_codec_implementation_t impl = { 0 };
switch_codec_implementation_t video_impl = { 0 };
char tmp[128] = "";
if (switch_core_session_get_read_impl(originate_status[pindex].peer_session, &impl) == SWITCH_STATUS_SUCCESS) {
if (switch_core_session_get_video_read_impl(originate_status[pindex].peer_session, &impl) == SWITCH_STATUS_SUCCESS) {
switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui,%s",
impl.iananame, impl.samples_per_second, impl.microseconds_per_packet / 1000,
video_impl.iananame);
} else {
switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui",
impl.iananame, impl.samples_per_second, impl.microseconds_per_packet / 1000);
}
switch_channel_set_variable(caller_channel, "absolute_codec_string", tmp);
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "Setting codec string on %s to %s\n",
switch_channel_get_name(caller_channel), tmp);
} else {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(originate_status[pindex].peer_channel), SWITCH_LOG_WARNING,
"Error inheriting codec. Channel %s has no read codec yet.\n",
switch_channel_get_name(originate_status[pindex].peer_channel));
}
}
inherit_codec(caller_channel, originate_status[pindex].peer_session);
}
if (send_ringback) {
@ -1051,7 +1058,7 @@ SWITCH_DECLARE(void) switch_process_import(switch_core_session_t *session, switc
}
static switch_status_t setup_ringback(originate_global_t *oglobals,
static switch_status_t setup_ringback(originate_global_t *oglobals, originate_status_t *originate_status, int len,
const char *ringback_data, ringback_t *ringback, switch_frame_t *write_frame, switch_codec_t *write_codec)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
@ -1061,6 +1068,10 @@ static switch_status_t setup_ringback(originate_global_t *oglobals,
if (!switch_channel_test_flag(caller_channel, CF_ANSWERED)
&& !switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) {
if (oglobals->bridge_early_media > -1 && len == 1 && originate_status[0].peer_session &&
switch_channel_media_ready(originate_status[0].peer_channel)) {
inherit_codec(caller_channel, originate_status[0].peer_session);
}
if ((status = switch_channel_pre_answer(caller_channel)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "%s Media Establishment Failed.\n",
switch_channel_get_name(caller_channel));
@ -1073,6 +1084,25 @@ static switch_status_t setup_ringback(originate_global_t *oglobals,
if (!(strrchr(ringback_data, '.') || strstr(ringback_data, SWITCH_URL_SEPARATOR))) {
ringback->asis++;
}
} else if (oglobals->bridge_early_media > -1 && zstr(ringback_data) && len == 1 && originate_status[0].peer_session) {
switch_codec_implementation_t read_impl = { 0 }, write_impl = { 0 };
if (switch_channel_ready(originate_status[0].peer_channel)
&& switch_core_session_get_read_impl(originate_status[0].peer_session, &read_impl) == SWITCH_STATUS_SUCCESS
&& switch_core_session_get_write_impl(oglobals->session, &write_impl) == SWITCH_STATUS_SUCCESS) {
if (read_impl.impl_id == write_impl.impl_id &&
read_impl.microseconds_per_packet == write_impl.microseconds_per_packet &&
read_impl.actual_samples_per_second == write_impl.actual_samples_per_second) {
ringback->asis++;
write_frame->codec = switch_core_session_get_write_codec(originate_status[0].peer_session);
write_frame->datalen = write_frame->codec->implementation->decoded_bytes_per_packet;
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "bridge_early_media: passthrough enabled\n");
} else {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "bridge_early_media: codecs don't match (%s@%uh@%di / %s@%uh@%di)\n",
read_impl.iananame, read_impl.actual_samples_per_second, read_impl.microseconds_per_packet / 1000,
write_impl.iananame, write_impl.actual_samples_per_second, write_impl.microseconds_per_packet / 1000);
}
}
}
if (!ringback->asis) {
@ -1553,6 +1583,7 @@ struct early_state {
switch_mutex_t *mutex;
switch_buffer_t *buffer;
int ready;
ringback_t *ringback;
};
typedef struct early_state early_state_t;
@ -1591,37 +1622,51 @@ static void *SWITCH_THREAD_FUNC early_thread_run(switch_thread_t *thread, void *
answered++;
}
if (!switch_core_codec_ready((&read_codecs[i]))) {
read_codec = switch_core_session_get_read_codec(session);
if (!state->ringback->asis) {
if (!switch_core_codec_ready((&read_codecs[i]))) {
read_codec = switch_core_session_get_read_codec(session);
if (switch_core_codec_init(&read_codecs[i],
"L16",
NULL,
read_codec->implementation->actual_samples_per_second,
read_codec->implementation->microseconds_per_packet / 1000,
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error!\n");
} else {
switch_core_session_set_read_codec(session, &read_codecs[i]);
if (switch_core_codec_init(&read_codecs[i],
"L16",
NULL,
read_codec->implementation->actual_samples_per_second,
read_codec->implementation->microseconds_per_packet / 1000,
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error!\n");
} else {
switch_core_session_set_read_codec(session, &read_codecs[i]);
}
}
}
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (SWITCH_READ_ACCEPTABLE(status)) {
data = (int16_t *) read_frame->data;
if (datalen < read_frame->datalen) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (SWITCH_READ_ACCEPTABLE(status)) {
data = (int16_t *) read_frame->data;
if (datalen < read_frame->datalen) {
datalen = read_frame->datalen;
}
for (x = 0; x < (int) read_frame->datalen / 2; x++) {
sample = data[x] + mux_data[x];
switch_normalize_to_16bit(sample);
mux_data[x] = (int16_t) sample;
}
}
} else {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (SWITCH_READ_ACCEPTABLE(status)) {
datalen = read_frame->datalen;
}
for (x = 0; x < (int) read_frame->datalen / 2; x++) {
sample = data[x] + mux_data[x];
switch_normalize_to_16bit(sample);
mux_data[x] = (int16_t) sample;
}
break;
}
}
}
if (datalen) {
if (state->ringback->asis && datalen) {
uint16_t flen = (uint16_t)datalen;
switch_mutex_lock(state->mutex);
switch_buffer_write(state->buffer, &flen, sizeof(uint16_t));
switch_buffer_write(state->buffer, read_frame->data, datalen);
switch_mutex_unlock(state->mutex);
} else if (datalen) {
switch_mutex_lock(state->mutex);
switch_buffer_write(state->buffer, mux_data, datalen);
switch_mutex_unlock(state->mutex);
@ -2758,9 +2803,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
if (oglobals.ringback_ok && (oglobals.ring_ready || oglobals.instant_ringback ||
oglobals.sending_ringback > 1 || oglobals.bridge_early_media > -1)) {
if (oglobals.ringback_ok == 1) {
switch_status_t rst = setup_ringback(&oglobals, ringback_data, &ringback, &write_frame, &write_codec);
switch_status_t rst;
rst = setup_ringback(&oglobals, originate_status, and_argc, ringback_data, &ringback, &write_frame, &write_codec);
if (oglobals.bridge_early_media > -1) {
switch_threadattr_t *thd_attr = NULL;
switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
@ -2768,6 +2814,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
early_state.oglobals = &oglobals;
early_state.originate_status = originate_status;
early_state.ready = 1;
early_state.ringback = &ringback;
switch_mutex_init(&early_state.mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_buffer_create_dynamic(&early_state.buffer, 1024, 1024, 0);
switch_thread_create(&oglobals.ethread, thd_attr, early_thread_run, &early_state, switch_core_session_get_pool(session));
@ -2794,12 +2841,24 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
continue;
}
if (oglobals.bridge_early_media > -1) {
if (oglobals.bridge_early_media > -1) {
write_frame.datalen = 0;
switch_mutex_lock(early_state.mutex);
if (switch_buffer_inuse(early_state.buffer) >= write_frame.codec->implementation->decoded_bytes_per_packet) {
write_frame.datalen = switch_buffer_read(early_state.buffer, write_frame.data,
write_frame.codec->implementation->decoded_bytes_per_packet);
if (ringback.asis) {
uint16_t mlen;
switch_size_t buflen = switch_buffer_inuse(early_state.buffer);
if (buflen > sizeof(uint16_t)) {
switch_buffer_peek(early_state.buffer, &mlen, sizeof(uint16_t));
if (buflen >= (mlen + sizeof(uint16_t))) {
switch_buffer_toss(early_state.buffer, sizeof(uint16_t));
write_frame.datalen = switch_buffer_read(early_state.buffer, write_frame.data, mlen);
}
}
} else {
if (switch_buffer_inuse(early_state.buffer) >= write_frame.codec->implementation->decoded_bytes_per_packet) {
write_frame.datalen = switch_buffer_read(early_state.buffer, write_frame.data,
write_frame.codec->implementation->decoded_bytes_per_packet);
}
}
switch_mutex_unlock(early_state.mutex);
} else if (ringback.fh) {

View File

@ -1176,13 +1176,20 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) {
switch_bool_t global = SWITCH_FALSE;
const char *val = switch_xml_attr_soft(ld, "module");
const char *critical = switch_xml_attr_soft(ld, "critical");
const char *sglobal = switch_xml_attr_soft(ld, "global");
if (zstr(val) || (strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
continue;
}
global = switch_true(sglobal);
switch_loadable_module_load_module_ex((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE, global, &err);
if (switch_loadable_module_load_module_ex((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val, SWITCH_FALSE, global, &err) == SWITCH_STATUS_FALSE) {
if (critical && switch_true(critical)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load critical module '%s', abort()\n", val);
abort();
}
}
count++;
}
}

View File

@ -2130,7 +2130,7 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
"Sender Packet Count = %u, " \
"Sender Octet Count = %u\n",
rtp_session->rtcp_recv_msg.header.count,
ntohs(rtp_session->rtcp_recv_msg.header.length),
ntohs((uint16_t)rtp_session->rtcp_recv_msg.header.length),
ntohl(sr->ssrc),
ntohl(sr->ntp_msw),
ntohl(sr->ntp_lsw),
@ -2907,7 +2907,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtcp_zerocopy_read_frame(switch_rtp_t *rt
rtp_session->rtcp_fresh_frame = 0;
frame->ssrc = ntohl(sr->ssrc);
frame->packet_type = rtp_session->rtcp_recv_msg.header.type;
frame->packet_type = (uint16_t)rtp_session->rtcp_recv_msg.header.type;
frame->ntp_msw = ntohl(sr->ntp_msw);
frame->ntp_lsw = ntohl(sr->ntp_lsw);
frame->timestamp = ntohl(sr->ts);
@ -3337,8 +3337,8 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
struct switch_rtcp_senderinfo* sr = (struct switch_rtcp_senderinfo*)rtp_session->rtcp_send_msg.body;
sr->ssrc = send_msg->header.ssrc;
sr->ntp_msw = htonl(rtp_session->send_time / 1000000 + 2208988800UL);
sr->ntp_lsw = htonl(rtp_session->send_time % 1000000 * ((UINT_MAX * 1.0)/ 1000000.0));
sr->ntp_msw = htonl((u_long)rtp_session->send_time / 1000000 + 2208988800UL);
sr->ntp_lsw = htonl((u_long)(rtp_session->send_time % 1000000 * ((UINT_MAX * 1.0)/ 1000000.0)));
sr->ts = send_msg->header.ts;
sr->pc = htonl(rtp_session->stats.outbound.packet_count);
sr->oc = htonl((rtp_session->stats.outbound.raw_bytes - rtp_session->stats.outbound.packet_count * sizeof(srtp_hdr_t)));

View File

@ -403,6 +403,10 @@ SWITCH_DECLARE(const char *) switch_xml_attr(switch_xml_t xml, const char *attr)
return NULL;
}
if (!root->attr) {
return NULL;
}
for (i = 0; root->attr[i] && xml->name && strcmp(xml->name, root->attr[i][0]); i++);
if (!root->attr[i])
return NULL; /* no matching default attributes */
@ -451,6 +455,9 @@ SWITCH_DECLARE(const char **) switch_xml_pi(switch_xml_t xml, const char *target
return (const char **) SWITCH_XML_NIL;
while (root->xml.parent)
root = (switch_xml_root_t) root->xml.parent; /* root tag */
if (!root || !root->pi) {
return (const char **) SWITCH_XML_NIL;
}
while (root->pi[i] && strcmp(target, root->pi[i][0]))
i++; /* find target */
return (const char **) ((root->pi[i]) ? root->pi[i] + 1 : SWITCH_XML_NIL);
@ -463,6 +470,10 @@ static switch_xml_t switch_xml_err(switch_xml_root_t root, char *s, const char *
int line = 1;
char *t, fmt[SWITCH_XML_ERRL];
if (!root || !root->s) {
return NULL;
}
for (t = root->s; t && t < s; t++)
if (*t == '\n')
line++;
@ -578,7 +589,13 @@ static char *switch_xml_decode(char *s, char **ent, char t)
/* called when parser finds start of new tag */
static void switch_xml_open_tag(switch_xml_root_t root, char *name, char **attr)
{
switch_xml_t xml = root->cur;
switch_xml_t xml;
if (!root || !root->cur) {
return;
}
xml = root->cur;
if (xml->name)
xml = switch_xml_add_child(xml, name, strlen(xml->txt));
@ -592,10 +609,16 @@ static void switch_xml_open_tag(switch_xml_root_t root, char *name, char **attr)
/* called when parser finds character content between open and closing tag */
static void switch_xml_char_content(switch_xml_root_t root, char *s, switch_size_t len, char t)
{
switch_xml_t xml = root->cur;
switch_xml_t xml;
char *m = s;
switch_size_t l;
if (!root || !root->cur) {
return;
}
xml = root->cur;
if (!xml || !xml->name || !len)
return; /* sanity check */
@ -632,7 +655,7 @@ static void switch_xml_char_content(switch_xml_root_t root, char *s, switch_size
/* called when parser finds closing tag */
static switch_xml_t switch_xml_close_tag(switch_xml_root_t root, char *name, char *s)
{
if (!root->cur || !root->cur->name || strcmp(name, root->cur->name))
if (!root || !root->cur || !root->cur->name || strcmp(name, root->cur->name))
return switch_xml_err(root, s, "unexpected closing tag </%s>", name);
root->cur = root->cur->parent;
@ -681,7 +704,7 @@ static void switch_xml_proc_inst(switch_xml_root_t root, char *s, switch_size_t
return;
}
if (!root->pi[0]) {
if (!root->pi || !root->pi[0]) {
root->pi = (char ***) malloc(sizeof(char **));
if (!root->pi)
return;
@ -2601,6 +2624,107 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_cut(switch_xml_t xml)
return xml;
}
SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond) {
const char *xyear = switch_xml_attr(xcond, "year");
const char *xyday = switch_xml_attr(xcond, "yday");
const char *xmon = switch_xml_attr(xcond, "mon");
const char *xmday = switch_xml_attr(xcond, "mday");
const char *xweek = switch_xml_attr(xcond, "week");
const char *xmweek = switch_xml_attr(xcond, "mweek");
const char *xwday = switch_xml_attr(xcond, "wday");
const char *xhour = switch_xml_attr(xcond, "hour");
const char *xminute = switch_xml_attr(xcond, "minute");
const char *xminday = switch_xml_attr(xcond, "minute-of-day");
switch_time_t ts = switch_micro_time_now();
int time_match = -1;
switch_time_exp_t tm;
switch_time_exp_lt(&tm, ts);
if (time_match && xyear) {
int test = tm.tm_year + 1900;
time_match = switch_number_cmp(xyear, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: year[%d] =~ %s (%s)\n", test, xyear, time_match ? "PASS" : "FAIL");
}
if (time_match && xyday) {
int test = tm.tm_yday + 1;
time_match = switch_number_cmp(xyday, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: day of year[%d] =~ %s (%s)\n", test, xyday, time_match ? "PASS" : "FAIL");
}
if (time_match && xmon) {
int test = tm.tm_mon + 1;
time_match = switch_number_cmp(xmon, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: month[%d] =~ %s (%s)\n", test, xmon, time_match ? "PASS" : "FAIL");
}
if (time_match && xmday) {
int test = tm.tm_mday;
time_match = switch_number_cmp(xmday, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: day of month[%d] =~ %s (%s)\n", test, xmday, time_match ? "PASS" : "FAIL");
}
if (time_match && xweek) {
int test = (int) (tm.tm_yday / 7 + 1);
time_match = switch_number_cmp(xweek, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: week of year[%d] =~ %s (%s)\n", test, xweek, time_match ? "PASS" : "FAIL");
}
if (time_match && xweek) {
int test = (int) (tm.tm_yday / 7 + 1);
time_match = switch_number_cmp(xweek, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: week of year[%d] =~ %s (%s)\n", test, xweek, time_match ? "PASS" : "FAIL");
}
if (time_match && xmweek) {
/* calculate the day of the week of the first of the month (0-6) */
int firstdow = (int) (7 - (tm.tm_mday - (tm.tm_wday + 1)) % 7) % 7;
/* calculate the week of the month (1-6)*/
int test = (int) ceil((tm.tm_mday + firstdow) / 7.0);
time_match = switch_number_cmp(xmweek, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime: week of month[%d] =~ %s (%s)\n", test, xmweek, time_match ? "PASS" : "FAIL");
}
if (time_match && xwday) {
int test = tm.tm_wday + 1;
time_match = switch_number_cmp(xwday, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: day of week[%d] =~ %s (%s)\n", test, xwday, time_match ? "PASS" : "FAIL");
}
if (time_match && xhour) {
int test = tm.tm_hour;
time_match = switch_number_cmp(xhour, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: hour[%d] =~ %s (%s)\n", test, xhour, time_match ? "PASS" : "FAIL");
}
if (time_match && xminute) {
int test = tm.tm_min;
time_match = switch_number_cmp(xminute, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: minute[%d] =~ %s (%s)\n", test, xminute, time_match ? "PASS" : "FAIL");
}
if (time_match && xminday) {
int test = (tm.tm_hour * 60) + (tm.tm_min + 1);
time_match = switch_number_cmp(xminday, test);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9,
"XML DateTime Check: minute of day[%d] =~ %s (%s)\n", test, xminday, time_match ? "PASS" : "FAIL");
}
return time_match;
}
#ifdef WIN32
/*
* globbing functions for windows, part of libc on unix, this code was cut and paste from