Revision
17416
Author
dyatsin
Date
2010-04-27 13:32:55 -0500 (Tue, 27 Apr 2010)

Log Message

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

Modified Paths

Diff

Modified: freeswitch/trunk/Makefile.am (17415 => 17416)


--- freeswitch/trunk/Makefile.am	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/Makefile.am	2010-04-27 18:32:55 UTC (rev 17416)
@@ -350,7 +350,7 @@
 	  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 \

Modified: freeswitch/trunk/configure.in (17415 => 17416)


--- freeswitch/trunk/configure.in	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/configure.in	2010-04-27 18:32:55 UTC (rev 17416)
@@ -353,7 +353,6 @@
 
 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 @@
   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

Modified: freeswitch/trunk/libs/esl/src/esl.c (17415 => 17416)


--- freeswitch/trunk/libs/esl/src/esl.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/libs/esl/src/esl.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -786,7 +786,7 @@
 		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;
 	}
 

Modified: freeswitch/trunk/libs/libdingaling/src/libdingaling.c (17415 => 17416)


--- freeswitch/trunk/libs/libdingaling/src/libdingaling.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/libs/libdingaling/src/libdingaling.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -2179,7 +2179,11 @@
 
 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;
 }
 

Modified: freeswitch/trunk/src/include/g711.h (17415 => 17416)


--- freeswitch/trunk/src/include/g711.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/include/g711.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -39,8 +39,8 @@
 specification by other means.
 */
 
-#if !defined(_G711_H_)
-#define _G711_H_
+#if !defined(FREESWITCH_G711_H)
+#define FREESWITCH_G711_H
 
 #ifdef __cplusplus
 extern "C" {

Modified: freeswitch/trunk/src/include/switch_dso.h (17415 => 17416)


--- freeswitch/trunk/src/include/switch_dso.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/include/switch_dso.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -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

Modified: freeswitch/trunk/src/include/switch_nat.h (17415 => 17416)


--- freeswitch/trunk/src/include/switch_nat.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/include/switch_nat.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -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,

Modified: freeswitch/trunk/src/include/switch_stun.h (17415 => 17416)


--- freeswitch/trunk/src/include/switch_stun.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/include/switch_stun.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -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

Modified: freeswitch/trunk/src/include/switch_types.h (17415 => 17416)


--- freeswitch/trunk/src/include/switch_types.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/include/switch_types.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -141,6 +141,7 @@
 #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"

Modified: freeswitch/trunk/src/include/switch_xml.h (17415 => 17416)


--- freeswitch/trunk/src/include/switch_xml.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/include/switch_xml.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -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 @@
 ///\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

Modified: freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c (17415 => 17416)


--- freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -262,6 +262,7 @@
 	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 @@
 	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 @@
 	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 @@
 			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 @@
 
 				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 @@
 		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 @@
 	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 @@
 				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 @@
 	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;

Modified: freeswitch/trunk/src/mod/applications/mod_expr/conio.h (17415 => 17416)


--- freeswitch/trunk/src/mod/applications/mod_expr/conio.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/applications/mod_expr/conio.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -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>

Modified: freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c (17415 => 17416)


--- freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/applications/mod_fifo/mod_fifo.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -75,6 +75,15 @@
 	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 @@
 			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 @@
 				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_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;
 			}

Modified: freeswitch/trunk/src/mod/applications/mod_spy/mod_spy.c (17415 => 17416)


--- freeswitch/trunk/src/mod/applications/mod_spy/mod_spy.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/applications/mod_spy/mod_spy.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -128,16 +128,17 @@
 	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 @@
 
 	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 @@
 		}
 	}
 
-  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 @@
 	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)
 {

Modified: freeswitch/trunk/src/mod/applications/mod_t38gateway/udptl.h (17415 => 17416)


--- freeswitch/trunk/src/mod/applications/mod_t38gateway/udptl.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/applications/mod_t38gateway/udptl.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -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

Modified: freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c (17415 => 17416)


--- freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -1524,7 +1524,7 @@
 					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 @@
 }
 
 
-#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 @@
 	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 @@
 					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 @@
 		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 @@
 	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 @@
 						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)) {

Modified: freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c (17415 => 17416)


--- freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -101,19 +101,7 @@
 		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 @@
 			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"))) {

Modified: freeswitch/trunk/src/mod/endpoints/mod_portaudio/pablio.h (17415 => 17416)


--- freeswitch/trunk/src/mod/endpoints/mod_portaudio/pablio.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/endpoints/mod_portaudio/pablio.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -1,5 +1,5 @@
-#ifndef _PABLIO_H
-#define _PABLIO_H
+#ifndef PORTAUDIO_PABLIO_H
+#define PORTAUDIO_PABLIO_H
 
 #ifdef __cplusplus
 extern "C" {

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (17415 => 17416)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -392,7 +392,13 @@
 	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,7 +411,19 @@
 		} 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))) {
 		ps_cause = switch_channel_get_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE);
@@ -2086,7 +2104,14 @@
 	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 @@
 {
 	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 @@
 							   "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 @@
 							   "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 @@
 	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 @@
 	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 @@
 
 	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 @@
 				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 @@
 		} 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 @@
 				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 @@
 
 	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 @@
 				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 @@
 		} 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 @@
 	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 @@
 
 	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 @@
 			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 @@
 		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 @@
 				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_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);
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (17415 => 17416)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -402,6 +402,8 @@
 	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;

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (17415 => 17416)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -1758,6 +1758,10 @@
 			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");

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (17415 => 17416)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -2189,6 +2189,7 @@
 
 	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 @@
 
 	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);
 	}
 
 }

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c (17415 => 17416)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -1901,7 +1901,7 @@
 		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;
 		}
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c (17415 => 17416)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -1688,6 +1688,7 @@
 	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 @@
 			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 @@
 			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 @@
 			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 @@
 		}
 	}
 
+	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;

Modified: freeswitch/trunk/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c (17415 => 17416)


--- freeswitch/trunk/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -620,7 +620,10 @@
 
 	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_";

Modified: freeswitch/trunk/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c (17415 => 17416)


--- freeswitch/trunk/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -200,7 +200,10 @@
 
 	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 @@
 				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)) {

Modified: freeswitch/trunk/src/mod/xml_int/mod_xml_ldap/lutil_ldap.h (17415 => 17416)


--- freeswitch/trunk/src/mod/xml_int/mod_xml_ldap/lutil_ldap.h	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/mod/xml_int/mod_xml_ldap/lutil_ldap.h	2010-04-27 18:32:55 UTC (rev 17416)
@@ -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>

Modified: freeswitch/trunk/src/switch_channel.c (17415 => 17416)


--- freeswitch/trunk/src/switch_channel.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_channel.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -241,6 +241,7 @@
 	(*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;
 }

Modified: freeswitch/trunk/src/switch_core_sqldb.c (17415 => 17416)


--- freeswitch/trunk/src/switch_core_sqldb.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_core_sqldb.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -958,6 +958,7 @@
 	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 @@
 	}
 
 	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);

Modified: freeswitch/trunk/src/switch_core_state_machine.c (17415 => 17416)


--- freeswitch/trunk/src/switch_core_state_machine.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_core_state_machine.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -526,8 +526,9 @@
 
 		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);

Modified: freeswitch/trunk/src/switch_dso.c (17415 => 17416)


--- freeswitch/trunk/src/switch_dso.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_dso.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -131,7 +131,7 @@
 		dlerror();
 
 		if (!(addr = dlsym(lib, sym))) {
-			err_str = dlerror();
+			err_str = (char *)dlerror();
 		}
 
 		if (err_str) {

Modified: freeswitch/trunk/src/switch_ivr_async.c (17415 => 17416)


--- freeswitch/trunk/src/switch_ivr_async.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_ivr_async.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -353,10 +353,15 @@
 	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,7 +381,35 @@
 		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;
 	dh->file = switch_core_session_strdup(session, file);

Modified: freeswitch/trunk/src/switch_ivr_originate.c (17415 => 17416)


--- freeswitch/trunk/src/switch_ivr_originate.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_ivr_originate.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -372,6 +372,38 @@
 	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 @@
   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 @@
 }
 
 
-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 @@
 
 	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 @@
 			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 @@
 	switch_mutex_t *mutex;
 	switch_buffer_t *buffer;
 	int ready;
+	ringback_t *ringback;
 };
 typedef struct early_state early_state_t;
 
@@ -1591,38 +1622,52 @@
 					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 @@
 					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 @@
 								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 @@
 							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) {

Modified: freeswitch/trunk/src/switch_loadable_module.c (17415 => 17416)


--- freeswitch/trunk/src/switch_loadable_module.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_loadable_module.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -1176,13 +1176,20 @@
 			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++;
 			}
 		}

Modified: freeswitch/trunk/src/switch_rtp.c (17415 => 17416)


--- freeswitch/trunk/src/switch_rtp.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_rtp.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -2130,7 +2130,7 @@
 								  "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 @@
 		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 @@
 			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)));

Modified: freeswitch/trunk/src/switch_xml.c (17415 => 17416)


--- freeswitch/trunk/src/switch_xml.c	2010-04-27 18:32:36 UTC (rev 17415)
+++ freeswitch/trunk/src/switch_xml.c	2010-04-27 18:32:55 UTC (rev 17416)
@@ -403,6 +403,10 @@
 		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 @@
 		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 @@
 	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,8 +589,14 @@
 /* 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));
 	else
@@ -592,10 +609,16 @@
 /* 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 @@
 /* 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 @@
 		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 @@
 	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