diff --git a/Makefile.am b/Makefile.am index a26346277a..ad04fde392 100644 --- a/Makefile.am +++ b/Makefile.am @@ -267,7 +267,7 @@ src/include/switch_swigable_cpp.h: $(switch_srcdir)/src/include/switch_cpp.h ## ## Applications ## -bin_PROGRAMS = freeswitch fs_cli fs_ivrd +bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav ## ## fs_cli () @@ -281,6 +281,14 @@ fs_cli_CFLAGS += -DHAVE_EDITLINE -I$(switch_srcdir)/libs/libedit/src fs_cli_LDADD = libs/libedit/src/.libs/libedit.a endif +## +## tone2wav () +## +tone2wav_SOURCES = src/tone2wav.c +tone2wav_CFLAGS = $(AM_CFLAGS) +tone2wav_LDFLAGS = $(AM_LDFLAGS) $(CORE_LIBS) +tone2wav_LDADD = libfreeswitch.la + ## ## fs_ivrd () ## diff --git a/conf/autoload_configs/sangoma_codec.conf.xml b/conf/autoload_configs/sangoma_codec.conf.xml index da4b8ed643..14fae63a6b 100644 --- a/conf/autoload_configs/sangoma_codec.conf.xml +++ b/conf/autoload_configs/sangoma_codec.conf.xml @@ -8,25 +8,22 @@ --> - + + - - - - - - - - - - - - - diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index 8abb8d8348..b143280fba 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -250,6 +250,7 @@ + @@ -262,7 +263,7 @@ - + diff --git a/conf/dialplan/features.xml b/conf/dialplan/features.xml index 901b3091b7..b85cadc5f7 100644 --- a/conf/dialplan/features.xml +++ b/conf/dialplan/features.xml @@ -11,6 +11,14 @@ + + + + + + + + diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index e4af5cc772..1c2ef1216c 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -116,7 +116,7 @@ - + diff --git a/libs/.gitignore b/libs/.gitignore index 24e32c1954..cc42ba4fa4 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -355,6 +355,7 @@ /libsndfile/Cfg/missing /libsndfile/M4/Makefile /libsndfile/M4/Makefile.in +/libsndfile/M4/lt~obsolete.m4 /libsndfile/Makefile /libsndfile/Makefile.in /libsndfile/Octave/Makefile diff --git a/libs/freetdm/src/libteletone_generate.c b/libs/freetdm/src/libteletone_generate.c index 089268bc7b..7f37b7a258 100644 --- a/libs/freetdm/src/libteletone_generate.c +++ b/libs/freetdm/src/libteletone_generate.c @@ -267,7 +267,7 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone ts->samples * 2); } } - return ts->samples; + return ts->samples / ts->channels; } TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd) diff --git a/libs/libteletone/src/libteletone_generate.c b/libs/libteletone/src/libteletone_generate.c index 911e3c2797..8098e3605c 100644 --- a/libs/libteletone/src/libteletone_generate.c +++ b/libs/libteletone/src/libteletone_generate.c @@ -302,7 +302,7 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone ts->samples * 2); } } - return ts->samples; + return ts->samples / ts->channels; } /* don't ask */ diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index e56753e07d..b8a2e8be1c 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.h @@ -60,10 +60,8 @@ struct t30_state_s int supported_t30_features; /*! \brief TRUE is ECM mode handling is enabled. */ int ecm_allowed; -#if 0 /*! \brief TRUE if we are capable of retransmitting pages */ int retransmit_capable; -#endif /*! \brief The received DCS, formatted as an ASCII string, for inclusion in the TIFF file. */ @@ -71,12 +69,12 @@ struct t30_state_s /*! \brief The text which will be used in FAX page header. No text results in no header line. */ char header_info[T30_MAX_PAGE_HEADER_INFO + 1]; -#if 0 /*! \brief TRUE for FAX page headers to overlay (i.e. replace) the beginning of the page image. FALSE for FAX page headers to add to the overall length of the page. */ int header_overlays_image; -#endif + /*! \brief TRUE if remote T.30 procedural interrupts are allowed. */ + int remote_interrupts_allowed; /*! \brief The information fields received. */ t30_exchanged_info_t rx_info; @@ -207,13 +205,6 @@ struct t30_state_s /*! \brief This is only used in full duplex (e.g. ISDN) modes. */ int timer_t8; - /* These fields are guessed based on compiler error forensics, I added them to fix the build -anthm */ - int remote_interrupts_allowed; - int rtp_events; - int rtn_events; - int retransmit_capable; - /* end guessed fields */ - /*! \brief TRUE once the far end FAX entity has been detected. */ int far_end_detected; @@ -283,12 +274,10 @@ struct t30_state_s /*! \brief The current completion status. */ int current_status; -#if 0 /*! \brief The number of RTP events */ int rtp_events; /*! \brief The number of RTN events */ int rtn_events; -#endif /*! \brief the FCF2 field of the last PPS message we received. */ uint8_t last_pps_fcf2; diff --git a/libs/spandsp/src/spandsp/t30.h b/libs/spandsp/src/spandsp/t30.h index 9df7321abd..a2fff2d28c 100644 --- a/libs/spandsp/src/spandsp/t30.h +++ b/libs/spandsp/src/spandsp/t30.h @@ -682,6 +682,10 @@ SPAN_DECLARE(void) t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t); \param state TRUE to enable interrupt request, else FALSE. */ SPAN_DECLARE(void) t30_local_interrupt_request(t30_state_t *s, int state); +/*! Allow remote interrupts of FAX exchange. + \brief Allow remote interrupts of FAX exchange. + \param s The T.30 context. + \param state TRUE to allow interruptd, else FALSE. */ SPAN_DECLARE(void) t30_remote_interrupts_allowed(t30_state_t *s, int state); #if defined(__cplusplus) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 50dde95dc7..e77d5f74ef 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -233,6 +233,8 @@ struct switch_runtime { switch_profile_timer_t *profile_timer; double profile_time; double min_idle_time; + int sql_buffer_len; + int max_sql_buffer_len; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_config.h b/src/include/switch_config.h index 2281a9bbc1..4115564f56 100644 --- a/src/include/switch_config.h +++ b/src/include/switch_config.h @@ -38,7 +38,7 @@ /** * @defgroup config Config File Parser * @ingroup core1 - * This module implements a basic interface and file format parser it may be depricated in favor of database entries + * This module implements a basic interface and file format parser it may be deprecated in favor of database entries * or expanded to tie to external handlers in the future as necessary. *
  *
diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h
index 68719062b7..37c752bd3e 100644
--- a/src/include/switch_loadable_module.h
+++ b/src/include/switch_loadable_module.h
@@ -92,7 +92,7 @@ SWITCH_BEGIN_EXTERN_C
   \brief Initilize the module backend and load all the modules
   \return SWITCH_STATUS_SUCCESS when complete
  */
-SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(void);
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autoload);
 
 /*!
   \brief Shutdown the module backend and call the shutdown routine in all loaded modules
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index 5a88cd5751..b0395bafdc 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -255,7 +255,8 @@ typedef enum {
 	SCF_USE_CLOCK_RT = (1 << 10),
 	SCF_VERBOSE_EVENTS = (1 << 11),
 	SCF_USE_WIN32_MONOTONIC = (1 << 12),
-	SCF_AUTO_SCHEMAS = (1 << 13)
+	SCF_AUTO_SCHEMAS = (1 << 13),
+	SCF_MINIMAL = (1 << 14)
 } switch_core_flag_enum_t;
 typedef uint32_t switch_core_flag_t;
 
@@ -479,9 +480,16 @@ typedef struct {
 	switch_size_t flush_packet_count;
 } switch_rtp_numbers_t;
 
+
+typedef struct {
+	uint32_t packet_count;
+	uint32_t octet_count;
+} switch_rtcp_numbers_t;
+
 typedef struct {
 	switch_rtp_numbers_t inbound;
 	switch_rtp_numbers_t outbound;
+	switch_rtcp_numbers_t rtcp;
 } switch_rtp_stats_t;
 
 typedef enum {
diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h
index f24cee5e9f..4dc7ed7f1b 100644
--- a/src/include/switch_utils.h
+++ b/src/include/switch_utils.h
@@ -680,7 +680,15 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_netwo
 
 SWITCH_DECLARE(int) switch_inet_pton(int af, const char *src, void *dst);
 
+SWITCH_DECLARE(const char *) switch_dow_int2str(int val);
+SWITCH_DECLARE(int) switch_dow_str2int(const char *exp);
+SWITCH_DECLARE(int) switch_dow_cmp(const char *exp, int val);
 SWITCH_DECLARE(int) switch_number_cmp(const char *exp, int val);
+SWITCH_DECLARE(int) switch_tod_cmp(const char *exp, int val);
+
+SWITCH_DECLARE(int) switch_fulldate_cmp(const char *exp, switch_time_t *ts);
+SWITCH_DECLARE(void) switch_split_date(const char *exp, int *year, int *month, int *day);
+SWITCH_DECLARE(void) switch_split_time(const char *exp, int *hour, int *min, int *sec);
 
 /*!
   \brief Split a user@domain string as user and domain
diff --git a/src/include/switch_xml.h b/src/include/switch_xml.h
index 220e65df02..9b0fbb44f3 100644
--- a/src/include/switch_xml.h
+++ b/src/include/switch_xml.h
@@ -331,6 +331,7 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(_In_ uint8_t reload, _Out_ con
 ///\return SWITCH_STATUS_SUCCESS if successful
 SWITCH_DECLARE(switch_status_t) switch_xml_init(_In_ switch_memory_pool_t *pool, _Out_ const char **err);
 
+SWITCH_DECLARE(switch_status_t) switch_xml_reload(const char **err);
 
 SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void);
 
diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c
index e08757ba38..874c6156fd 100644
--- a/src/mod/applications/mod_callcenter/mod_callcenter.c
+++ b/src/mod/applications/mod_callcenter/mod_callcenter.c
@@ -1259,7 +1259,7 @@ static switch_status_t load_config(void)
 			if (!strcasecmp(var, "debug")) {
 				globals.debug = atoi(val);
 			} else if (!strcasecmp(var, "odbc-dsn")) {
-				globals.odbc_dsn = strdup(switch_xml_attr(param, "odbc-dsn"));
+				globals.odbc_dsn = strdup(val);
 
 				if (!zstr(globals.odbc_dsn)) {
 					if ((globals.odbc_user = strchr(globals.odbc_dsn, ':'))) {
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index e1eb2a6b6a..febb7f6608 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -605,11 +605,12 @@ SWITCH_STANDARD_API(in_group_function)
 
 SWITCH_STANDARD_API(user_data_function)
 {
-	switch_xml_t x_domain, xml = NULL, x_user = NULL, x_param, x_params;
+	switch_xml_t x_domain, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
 	int argc;
 	char *mydata = NULL, *argv[3], *key = NULL, *type = NULL, *user, *domain;
 	char delim = ' ';
 	const char *container = "params", *elem = "param";
+	const char *result = NULL;
 	switch_event_t *params = NULL;
 
 	if (zstr(cmd) || !(mydata = strdup(cmd))) {
@@ -637,10 +638,10 @@ SWITCH_STANDARD_API(user_data_function)
 	switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain);
 	switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "type", type);
 
-	if (key && type && switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, NULL, params) == SWITCH_STATUS_SUCCESS) {
+	if (key && type && switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, params) == SWITCH_STATUS_SUCCESS) {
 		if (!strcmp(type, "attr")) {
 			const char *attr = switch_xml_attr_soft(x_user, key);
-			stream->write_function(stream, "%s", attr);
+			result = attr;
 			goto end;
 		}
 
@@ -649,33 +650,45 @@ SWITCH_STANDARD_API(user_data_function)
 			elem = "variable";
 		}
 
-		if ((x_params = switch_xml_child(x_user, container))) {
-			for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
-				const char *var = switch_xml_attr(x_param, "name");
-				const char *val = switch_xml_attr(x_param, "value");
-
-				if (var && val && !strcasecmp(var, key)) {
-					stream->write_function(stream, "%s", val);
-					goto end;
-				}
-
-			}
-		}
-
 		if ((x_params = switch_xml_child(x_domain, container))) {
 			for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
 				const char *var = switch_xml_attr(x_param, "name");
 				const char *val = switch_xml_attr(x_param, "value");
 
 				if (var && val && !strcasecmp(var, key)) {
-					stream->write_function(stream, "%s", val);
-					goto end;
+					result = val;
+				}
+
+			}
+		}
+
+		if (x_group && (x_params = switch_xml_child(x_group, container))) {
+			for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
+				const char *var = switch_xml_attr(x_param, "name");
+				const char *val = switch_xml_attr(x_param, "value");
+
+				if (var && val && !strcasecmp(var, key)) {
+					result = val;
+				}
+			}
+		}
+
+		if ((x_params = switch_xml_child(x_user, container))) {
+			for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) {
+				const char *var = switch_xml_attr(x_param, "name");
+				const char *val = switch_xml_attr(x_param, "value");
+
+				if (var && val && !strcasecmp(var, key)) {
+					result = val;
 				}
 			}
 		}
 	}
 
   end:
+	if (result) {
+		stream->write_function(stream, "%s", result);
+	}
 	switch_xml_free(xml);
 	switch_safe_free(mydata);
 	switch_event_destroy(¶ms);
@@ -1166,17 +1179,18 @@ SWITCH_STANDARD_API(xml_locate_function)
 SWITCH_STANDARD_API(reload_acl_function)
 {
 	const char *err;
-	switch_xml_t xml_root;
 
-	if (cmd && !strcmp(cmd, "reloadxml")) {
-		if ((xml_root = switch_xml_open_root(1, &err))) {
-			switch_xml_free(xml_root);
-		}
+	if (cmd && !strcasecmp(cmd, "reloadxml")) {
+		stream->write_function(stream, "This option is deprecated, we now always reloadxml.\n");
+	}
+	
+	if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) {
+		switch_load_network_lists(SWITCH_TRUE);
+		stream->write_function(stream, "+OK acl reloaded\n");
+	} else {
+		stream->write_function(stream, "-Error [%s]\n", err);
 	}
 
-	switch_load_network_lists(SWITCH_TRUE);
-
-	stream->write_function(stream, "+OK acl reloaded\n");
 	return SWITCH_STATUS_SUCCESS;
 }
 
@@ -1374,7 +1388,7 @@ SWITCH_STANDARD_API(cond_function)
 
 	argc = switch_separate_string(mydata, ':', argv, (sizeof(argv) / sizeof(argv[0])));
 
-	if (argc != 3) {
+	if (! (argc >= 2 && argc <= 3)) {
 		goto error;
 	}
 
@@ -1451,7 +1465,12 @@ SWITCH_STANDARD_API(cond_function)
 		}
 		switch_safe_free(s_a);
 		switch_safe_free(s_b);
-		stream->write_function(stream, "%s", is_true ? argv[1] : argv[2]);
+
+		if ((argc == 2 && !is_true)) {
+			stream->write_function(stream, "");
+		} else {
+			stream->write_function(stream, "%s", is_true ? argv[1] : argv[2]);
+		}
 		goto ok;
 	}
 
@@ -1720,6 +1739,10 @@ SWITCH_STANDARD_API(load_function)
 		return SWITCH_STATUS_SUCCESS;
 	}
 
+	if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) {
+		stream->write_function(stream, "+OK Reloading XML\n");
+	}
+
 	if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS) {
 		stream->write_function(stream, "+OK\n");
 	} else {
@@ -1814,6 +1837,10 @@ SWITCH_STANDARD_API(reload_function)
 		stream->write_function(stream, "-ERR unloading module [%s]\n", err);
 	}
 
+	if (switch_xml_reload(&err) == SWITCH_STATUS_SUCCESS) {
+		stream->write_function(stream, "+OK Reloading XML\n");
+	}
+
 	if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS) {
 		stream->write_function(stream, "+OK module loaded\n");
 	} else {
@@ -1825,13 +1852,9 @@ SWITCH_STANDARD_API(reload_function)
 
 SWITCH_STANDARD_API(reload_xml_function)
 {
-	const char *err;
-	switch_xml_t xml_root;
-
-	if ((xml_root = switch_xml_open_root(1, &err))) {
-		switch_xml_free(xml_root);
-	}
+	const char *err = "";
 
+	switch_xml_reload(&err);
 	stream->write_function(stream, "+OK [%s]\n", err);
 
 	return SWITCH_STATUS_SUCCESS;
@@ -4551,7 +4574,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
 	SWITCH_ADD_API(commands_api_interface, "originate", "Originate a Call", originate_function, ORIGINATE_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "pause", "Pause", pause_function, PAUSE_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "regex", "Eval a regex", regex_function, "|[|]");
-	SWITCH_ADD_API(commands_api_interface, "reloadacl", "Reload ACL", reload_acl_function, "[reloadxml]");
+	SWITCH_ADD_API(commands_api_interface, "reloadacl", "Reload ACL", reload_acl_function, "");
 	SWITCH_ADD_API(commands_api_interface, "reload", "Reload Module", reload_function, UNLOAD_SYNTAX);
 	SWITCH_ADD_API(commands_api_interface, "reloadxml", "Reload XML", reload_xml_function, "");
 	SWITCH_ADD_API(commands_api_interface, "replace", "replace a string", replace_function, "||");
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 5128e3baed..dc1995fbef 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -99,7 +99,7 @@ typedef enum {
 	CALLER_CONTROL_DEAF_MUTE,
 	CALLER_CONTROL_ENERGY_UP,
 	CALLER_CONTROL_ENERGY_EQU_CONF,
-	CALLER_CONTROL_ENERGEY_DN,
+	CALLER_CONTROL_ENERGY_DN,
 	CALLER_CONTROL_VOL_TALK_UP,
 	CALLER_CONTROL_VOL_TALK_ZERO,
 	CALLER_CONTROL_VOL_TALK_DN,
@@ -121,7 +121,7 @@ typedef struct conference_member conference_member_t;
 
 struct call_list {
 	char *string;
-	int itteration;
+	int iteration;
 	struct call_list *next;
 };
 typedef struct call_list call_list_t;
@@ -717,7 +717,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
 
 		if (call_list) {
 			char saymsg[1024];
-			switch_snprintf(saymsg, sizeof(saymsg), "Auto Calling %d parties", call_list->itteration);
+			switch_snprintf(saymsg, sizeof(saymsg), "Auto Calling %d parties", call_list->iteration);
 			conference_member_say(member, saymsg, 0);
 		} else {
 			if (zstr(conference->special_announce)) {
@@ -2298,7 +2298,7 @@ static caller_control_fn_table_t ccfntbl[] = {
 	{"deaf mute", "*", CALLER_CONTROL_DEAF_MUTE, conference_loop_fn_deafmute_toggle},
 	{"energy up", "9", CALLER_CONTROL_ENERGY_UP, conference_loop_fn_energy_up},
 	{"energy equ", "8", CALLER_CONTROL_ENERGY_EQU_CONF, conference_loop_fn_energy_equ_conf},
-	{"energy dn", "7", CALLER_CONTROL_ENERGEY_DN, conference_loop_fn_energy_dn},
+	{"energy dn", "7", CALLER_CONTROL_ENERGY_DN, conference_loop_fn_energy_dn},
 	{"vol talk up", "3", CALLER_CONTROL_VOL_TALK_UP, conference_loop_fn_volume_talk_up},
 	{"vol talk zero", "2", CALLER_CONTROL_VOL_TALK_ZERO, conference_loop_fn_volume_talk_zero},
 	{"vol talk dn", "1", CALLER_CONTROL_VOL_TALK_DN, conference_loop_fn_volume_talk_dn},
@@ -5199,9 +5199,9 @@ SWITCH_STANDARD_APP(conference_auto_function)
 		np->string = switch_core_session_strdup(session, data);
 		if (call_list) {
 			np->next = call_list;
-			np->itteration = call_list->itteration + 1;
+			np->iteration = call_list->iteration + 1;
 		} else {
-			np->itteration = 1;
+			np->iteration = 1;
 		}
 		call_list = np;
 	}
diff --git a/src/mod/applications/mod_directory/mod_directory.c b/src/mod/applications/mod_directory/mod_directory.c
index d3389ab3b1..bfad1a68f6 100644
--- a/src/mod/applications/mod_directory/mod_directory.c
+++ b/src/mod/applications/mod_directory/mod_directory.c
@@ -884,6 +884,18 @@ SWITCH_STANDARD_APP(directory_function)
 	if (strcasecmp(profile->search_order, "last_name")) {
 		s_param.search_by_last_name = 0;
 	}
+ 	 
+	{
+		const char *var_search_order = switch_channel_get_variable(channel, "directory_search_order");
+		if (var_search_order) {
+			if (!strcasecmp(var_search_order, "first_name")) {
+				s_param.search_by_last_name = 0;
+			} else {
+				s_param.search_by_last_name = 1;
+			}
+		}
+	}
+
 	attempts = profile->max_menu_attempt;
 	s_param.try_again = 1;
 	while (switch_channel_ready(channel) && (s_param.try_again && attempts-- > 0)) {
diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c
index bbf7bb568d..105576ce14 100644
--- a/src/mod/applications/mod_lcr/mod_lcr.c
+++ b/src/mod/applications/mod_lcr/mod_lcr.c
@@ -1571,7 +1571,6 @@ SWITCH_STANDARD_APP(lcr_app_function)
 				switch_channel_set_variable(channel, vbuf, cur_route->carrier_name);
 				switch_snprintf(vbuf, sizeof(vbuf), "lcr_codec_%d", cnt);
 				switch_channel_set_variable(channel, vbuf, cur_route->codec);
-				cnt++;
 				if (cur_route->next) {
 					if (routes.profile->enable_sip_redir) {
 						dig_stream.write_function(&dig_stream, "%s,", cur_route->dialstring);
diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
index 7ff106aceb..1c825ec8dd 100644
--- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
+++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
@@ -74,6 +74,8 @@ static struct {
 	char header[50];
 	char *prepend_string;
 	char *spool;
+	switch_thread_cond_t *cond;
+	switch_mutex_t *cond_mutex;    
 } globals;
 
 struct pvt_s {
@@ -121,24 +123,16 @@ static struct {
 static int add_pvt(pvt_t *pvt)
 {
     int r = 0;
-    uint32_t sanity = 50;
-
-    switch_mutex_lock(t38_state_list.mutex);
-    if (!t38_state_list.thread_running) {
-
-        launch_timer_thread();
-
-        while(--sanity && !t38_state_list.thread_running) {
-            switch_yield(10000);
-        }
-    }
-    switch_mutex_unlock(t38_state_list.mutex);
     
     if (t38_state_list.thread_running) {
         switch_mutex_lock(t38_state_list.mutex);
         pvt->next = t38_state_list.head;
         t38_state_list.head = pvt;
         switch_mutex_unlock(t38_state_list.mutex);
+        r = 1;
+        switch_thread_cond_broadcast(globals.cond);
+    } else {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error launching thread\n");
     }
 
     return r;
@@ -151,9 +145,9 @@ static int del_pvt(pvt_t *del_pvt)
     pvt_t *p, *l = NULL;
     int r = 0;
 
-    if (!t38_state_list.thread_running) goto end;
-    
+
     switch_mutex_lock(t38_state_list.mutex);
+
     for (p = t38_state_list.head; p; p = p->next) {
         if (p == del_pvt) {
             if (l) {
@@ -163,42 +157,48 @@ static int del_pvt(pvt_t *del_pvt)
             }
             p->next = NULL;
             r = 1;
-            goto end;
+            break;
         }
 
         l = p;
     }
 
- end:
-
     switch_mutex_unlock(t38_state_list.mutex);
 
-    return r;
+    switch_thread_cond_broadcast(globals.cond);
 
+    return r;
 }
 
 static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *obj)
 {
     switch_timer_t timer = { 0 };
     pvt_t *pvt;
-    int samples = 240;
-    int ms = 30;
+    int samples = 160;
+    int ms = 20;
 
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread started.\n");
+    switch_mutex_lock(t38_state_list.mutex);
+    t38_state_list.thread_running = 1;
+    switch_mutex_unlock(t38_state_list.mutex);
+
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FAX timer thread started.\n");
 
 	if (switch_core_timer_init(&timer, "soft", ms, samples, NULL) != SWITCH_STATUS_SUCCESS) {
-        return NULL;
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "timer init failed.\n");
+        goto end;
     }
 
-    t38_state_list.thread_running = 1;
-
     while(t38_state_list.thread_running) {
 
+		switch_mutex_lock(globals.cond_mutex);
+
         switch_mutex_lock(t38_state_list.mutex);
 
         if (!t38_state_list.head) {
             switch_mutex_unlock(t38_state_list.mutex);
-            goto end;
+			switch_thread_cond_wait(globals.cond, globals.cond_mutex);
+            switch_core_timer_sync(&timer);
+            continue;
         }
 
         for (pvt = t38_state_list.head; pvt; pvt = pvt->next) {
@@ -214,10 +214,15 @@ static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *
     
  end:
 
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread ended.\n");
-
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FAX timer thread ended.\n");
+    
+    switch_mutex_lock(t38_state_list.mutex);
     t38_state_list.thread_running = 0;
-    switch_core_timer_destroy(&timer);
+    switch_mutex_unlock(t38_state_list.mutex);
+
+    if (timer.timer_interface) {
+        switch_core_timer_destroy(&timer);
+    }
     
     return NULL;
 }
@@ -468,49 +473,61 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
 		}
 		break;
 	case T38_MODE:
-		if (pvt->t38_state == NULL) {
-			pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t));
-		}
-		if (pvt->t38_state == NULL) {
-			return SWITCH_STATUS_FALSE;
-		}
-		if (pvt->udptl_state == NULL) {
-            pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t));
-        }
-		if (pvt->udptl_state == NULL) {
-    		t38_terminal_free(pvt->t38_state);
-            pvt->t38_state = NULL;
-			return SWITCH_STATUS_FALSE;
-		}
+        {
+            switch_core_session_message_t msg = { 0 };
 
-        /* add to timer thread processing */
-        add_pvt(pvt);
+            if (pvt->t38_state == NULL) {
+                pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t));
+            }
+            if (pvt->t38_state == NULL) {
+                return SWITCH_STATUS_FALSE;
+            }
+            if (pvt->udptl_state == NULL) {
+                pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t));
+            }
+            if (pvt->udptl_state == NULL) {
+                t38_terminal_free(pvt->t38_state);
+                pvt->t38_state = NULL;
+                return SWITCH_STATUS_FALSE;
+            }
+
+            t38 = pvt->t38_state;
+            t30 = t38_terminal_get_t30_state(t38);
+
+            memset(t38, 0, sizeof(t38_terminal_state_t));
+
+            if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL) {
+                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
+                return SWITCH_STATUS_FALSE;
+            }
+
+            pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
+
+            if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, 
+                           (udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
+                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
+                return SWITCH_STATUS_FALSE;
+            }
+
+            msg.from = __FILE__;
+            msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
+            switch_core_session_receive_message(pvt->session, &msg);
         
-		t38 = pvt->t38_state;
-		t30 = t38_terminal_get_t30_state(t38);
+            /* add to timer thread processing */
+            if (!add_pvt(pvt)) {
+                if (channel) {
+                    switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+                }
+            }
+        
+            span_log_set_message_handler(&t38->logging, spanfax_log_message);
+            span_log_set_message_handler(&t30->logging, spanfax_log_message);
 
-		memset(t38, 0, sizeof(t38_terminal_state_t));
-
-		if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL) {
-			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
-			return SWITCH_STATUS_FALSE;
-		}
-
-        pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
-
-        if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, 
-                       (udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) {
-			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
-			return SWITCH_STATUS_FALSE;
-		}
-
-		span_log_set_message_handler(&t38->logging, spanfax_log_message);
-		span_log_set_message_handler(&t30->logging, spanfax_log_message);
-
-		if (pvt->verbose) {
-			span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
-			span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
-		}
+            if (pvt->verbose) {
+                span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
+                span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
+            }
+        }
 		break;
  case T38_GATEWAY_MODE:
 	 if (pvt->t38_gateway_state == NULL) {
@@ -1145,8 +1162,6 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
                     //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "READ %d udptl bytes\n", read_frame->packetlen);
                     
                     udptl_rx_packet(pvt->udptl_state, read_frame->packet, read_frame->packetlen);
-
-
                 }
             }
             continue;
@@ -1282,6 +1297,8 @@ void mod_spandsp_fax_event_handler(switch_event_t *event)
 
 void mod_spandsp_fax_load(switch_memory_pool_t *pool)
 {
+    uint32_t sanity = 200;
+
 	memset(&globals, 0, sizeof(globals));
     memset(&t38_state_list, 0, sizeof(t38_state_list));
 
@@ -1289,6 +1306,9 @@ void mod_spandsp_fax_load(switch_memory_pool_t *pool)
 
 	switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
 	switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, globals.pool);
+
+	switch_mutex_init(&globals.cond_mutex, SWITCH_MUTEX_NESTED, globals.pool);
+	switch_thread_cond_create(&globals.cond, globals.pool);
     
     globals.enable_t38 = 1;
 	globals.total_sessions = 0;
@@ -1301,10 +1321,22 @@ void mod_spandsp_fax_load(switch_memory_pool_t *pool)
 	strncpy(globals.header, "SpanDSP Fax Header", sizeof(globals.header) - 1);
 
 	load_configuration(0);
+
+
+    launch_timer_thread();
+
+    while(--sanity && !t38_state_list.thread_running) {
+        switch_yield(20000);
+    }
 }
 
 void mod_spandsp_fax_shutdown(void)
 {
+    switch_status_t tstatus = SWITCH_STATUS_SUCCESS;
+
+    t38_state_list.thread_running = 0;
+    switch_thread_cond_broadcast(globals.cond);
+    switch_thread_join(&tstatus, t38_state_list.thread);
 	memset(&globals, 0, sizeof(globals));
 }
 
@@ -1659,8 +1691,8 @@ static switch_status_t t38_gateway_on_reset(switch_core_session_t *session)
     
     switch_channel_clear_flag(channel, CF_REDIRECT);
 
-    if (switch_channel_test_app_flag(channel, CF_APP_TAGGED)) {
-        switch_channel_clear_app_flag(channel, CF_APP_TAGGED);
+    if (switch_channel_test_app_flag_key("T38", channel, CF_APP_TAGGED)) {
+        switch_channel_clear_app_flag_key("T38", channel, CF_APP_TAGGED);
         switch_channel_set_state(channel, CS_CONSUME_MEDIA);
     } else {
         switch_channel_set_state(channel, CS_SOFT_EXECUTE);
@@ -1697,6 +1729,9 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
         switch_channel_set_variable(channel, "t38_peer", switch_core_session_get_uuid(other_session));
         switch_channel_set_variable(other_channel, "t38_peer", switch_core_session_get_uuid(session));
 
+        switch_channel_set_variable(peer ? other_channel : channel, "t38_gateway_format", "audio");
+        switch_channel_set_variable(peer ? channel : other_channel, "t38_gateway_format", "udptl");
+
 
         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s starting gateway mode to %s\n", 
                           switch_channel_get_name(peer ? channel : other_channel),
@@ -1709,8 +1744,8 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
         switch_channel_add_state_handler(channel, &t38_gateway_state_handlers);
         switch_channel_add_state_handler(other_channel, &t38_gateway_state_handlers);
 
-        switch_channel_set_app_flag(peer ? channel : other_channel, CF_APP_TAGGED);
-        switch_channel_clear_app_flag(peer ? other_channel : channel, CF_APP_TAGGED);   
+        switch_channel_set_app_flag_key("T38", peer ? channel : other_channel, CF_APP_TAGGED);
+        switch_channel_clear_app_flag_key("T38", peer ? other_channel : channel, CF_APP_TAGGED);   
         
         switch_channel_set_flag(channel, CF_REDIRECT);
         switch_channel_set_state(channel, CS_RESET);
diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index c683712922..069cfd8d9f 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -824,7 +824,8 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
 			if (!cc->noexit
 				&& (dtmf->digit == *cc->profile->delete_file_key || dtmf->digit == *cc->profile->save_file_key
 					|| dtmf->digit == *cc->profile->prev_msg_key || dtmf->digit == *cc->profile->next_msg_key
-					|| dtmf->digit == *cc->profile->terminator_key || dtmf->digit == *cc->profile->skip_info_key)) {
+					|| dtmf->digit == *cc->profile->terminator_key || dtmf->digit == *cc->profile->skip_info_key
+					|| dtmf->digit == *cc->profile->email_key || dtmf->digit == *cc->profile->forward_key)) {
 				*cc->buf = dtmf->digit;
 				return SWITCH_STATUS_BREAK;
 			}
@@ -2686,23 +2687,29 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t
 
 	if ((domain = strchr(user, '@'))) {
 		*domain++ = '\0';
-	} else {
-		domain = user;
-	}
 
-	if ((profile_name = strchr(domain, '@'))) {
-		*profile_name++ = '\0';
-	} else {
-		profile_name = domain;
+		if ((profile_name = strchr(domain, '@'))) {
+			*profile_name++ = '\0';
+		} else {
+			profile_name = domain;
+		}
 	}
 
 	if (switch_stristr("group=", user)) {
 		user += 6;
 		isgroup++;
-	} else if (user == domain) {
+	} else if (switch_stristr("domain=", user)) {
+		user += 7;
+		domain = user;
+		profile_name = domain;
 		isall++;
 	}
 
+	if (zstr(domain)) {
+		domain = switch_core_get_variable("domain");
+		profile_name = domain;
+	}
+
 	if (!(user && domain)) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid syntax [%s][%s]\n", switch_str_nil(user), switch_str_nil(domain));
 		status = SWITCH_STATUS_FALSE;
@@ -2746,6 +2753,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain);
 			status = SWITCH_STATUS_FALSE;
 			switch_event_destroy(&my_params);
+			profile_rwunlock(profile);
 			goto end;
 		}
 
@@ -3164,7 +3172,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
 		switch_event_destroy(&vars);
 		if (status == SWITCH_STATUS_SUCCESS) {
 			if ((vm_cc = switch_channel_get_variable(channel, "vm_cc"))) {
-				char *cmd = switch_core_session_sprintf(session, "%s %s %s %s %s@%s %s",
+				char *cmd = switch_core_session_sprintf(session, "%s %s %s '%s' %s@%s %s",
 														vm_cc, file_path, caller_id_number, caller_id_name, id, domain_name, read_flags);
 
 				if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
@@ -3961,7 +3969,7 @@ static void do_web(vm_profile_t *profile, const char *user_in, const char *domai
 	}
 }
 
-#define VM_INJECT_USAGE "[group=]  [] []"
+#define VM_INJECT_USAGE "[group=[@domain]|domain=|[@]]  [] []"
 SWITCH_STANDARD_API(voicemail_inject_api_function)
 {
 	if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
diff --git a/src/mod/endpoints/mod_h323/changes.txt b/src/mod/endpoints/mod_h323/changes.txt
index ff47780118..19aca46dc8 100644
--- a/src/mod/endpoints/mod_h323/changes.txt
+++ b/src/mod/endpoints/mod_h323/changes.txt
@@ -1,3 +1,4 @@
+fix crashes on FSH323Connection calls in on_hangup routine in different threads.
 move PTrace level set to FSH323EndPoint::Initialise
 partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directive.
 apply changes from mod_h323-patch.diff by Peter Olsson.
diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp
index aeee422ca5..142506dd92 100644
--- a/src/mod/endpoints/mod_h323/mod_h323.cpp
+++ b/src/mod/endpoints/mod_h323/mod_h323.cpp
@@ -24,7 +24,7 @@
  *
  * mod_h323.cpp -- H323 endpoint
  *
- *	Version 0.0.55
+ *	Version 0.0.56
 */
 
 //#define DEBUG_RTP_PACKETS
@@ -747,6 +747,17 @@ FSH323Connection::~FSH323Connection()
 //	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->h323_mutex_unlock\n");
 }	
 
+void FSH323Connection::AttachSignalChannel(const PString & token,
+                                         H323Transport * channel,
+                                         PBoolean answeringCall)
+{
+	h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
+	tech_pvt->token = strdup((const char *)token);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"---------->token = %s [%p]\n",(const char *)token,this);
+	H323Connection::AttachSignalChannel(token,channel,answeringCall);
+}
+
+
 void FSH323Connection::OnSetLocalCapabilities()
 {
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"======>FSH323Connection::OnSetLocalCapabilities() [%p]\n",this);
@@ -2321,8 +2332,9 @@ static switch_status_t on_hangup(switch_core_session_t *session)
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(session);
 	FSH323Connection *me = tech_pvt->me;
+	FSH323EndPoint & ep = h323_process->GetH323EndPoint();
 	tech_pvt->me = NULL;
-
+    
 	if (me) {
 		if (me->m_rtp_resetting == 1) {
 			switch_core_session_unlock_codec_read(session);
@@ -2340,12 +2352,12 @@ static switch_status_t on_hangup(switch_core_session_t *session)
 			me->CloseAllLogicalChannels(false);
 			me->Unlock();
 		}
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"----->%s\n",(const char *)(me->GetCallToken()));
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"----->%s\n",(const char *)(tech_pvt->token));
 		Q931::CauseValues cause = (Q931::CauseValues)switch_channel_get_cause_q850(channel);
 		int trylock = me->TryLock();
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"-----> () = %d\n",trylock);
 		if (trylock == 1) {
-			const PString currentToken(me->GetCallToken());
+			const PString currentToken(tech_pvt->token);
 			FSH323Connection *connection = (FSH323Connection *)me->GetEndPoint()->FindConnectionWithLock(currentToken); 
 			if (connection) {
 				connection->Unlock();
@@ -2356,8 +2368,10 @@ static switch_status_t on_hangup(switch_core_session_t *session)
 		} else if (trylock == -1) {
 			/* Failed to lock - just go on */
 		}
+		const PString currentToken(tech_pvt->token);
 		me->SetQ931Cause(cause);
-		me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));
+//		me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));
+		ep.ClearCall(currentToken, H323TranslateToCallEndReason(cause, UINT_MAX));
 //		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"------------->h323_mutex_lock\n");
 //		switch_mutex_lock(tech_pvt->h323_mutex);
 	}
diff --git a/src/mod/endpoints/mod_h323/mod_h323.h b/src/mod/endpoints/mod_h323/mod_h323.h
index 087540c509..8127206126 100644
--- a/src/mod/endpoints/mod_h323/mod_h323.h
+++ b/src/mod/endpoints/mod_h323/mod_h323.h
@@ -184,6 +184,7 @@ typedef struct {
 	switch_mutex_t *h323_io_mutex;
 
 	FSH323Connection *me;
+	char			*token;
 } h323_private_t;
 
 #define DECLARE_CALLBACK0(name)                           \
@@ -306,7 +307,11 @@ class FSH323Connection:public H323Connection {
 					 unsigned callReference, switch_caller_profile_t *outbound_profile,
 					 switch_core_session_t *fsSession, switch_channel_t *fsChannel);
 	~FSH323Connection();
-
+	virtual void AttachSignalChannel(
+      const PString & token,
+      H323Transport * channel,
+      PBoolean answeringCall
+    );
 	virtual H323Channel *CreateRealTimeLogicalChannel(const H323Capability & capability,
 							H323Channel::Directions dir,
 							unsigned sessionID, const H245_H2250LogicalChannelParameters * param, RTP_QOS * rtpqos = NULL);
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 19a44f43e1..68c99f1ac2 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -85,6 +85,10 @@ static switch_status_t sofia_on_init(switch_core_session_t *session)
 		sofia_glue_tech_absorb_sdp(tech_pvt);
 	}
 
+	if (sofia_test_flag(tech_pvt, TFLAG_RECOVERING) || sofia_test_flag(tech_pvt, TFLAG_RECOVERING_BRIDGE)) {
+		sofia_set_flag(tech_pvt, TFLAG_RECOVERED);
+	}
+
 	if (sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) || sofia_test_flag(tech_pvt, TFLAG_RECOVERING)) {
 		const char *var;
 
@@ -717,6 +721,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 						TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
 						TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
 						NUTAG_SESSION_TIMER(session_timeout),
+						TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
 						SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
 						SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
 						SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
@@ -732,6 +737,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 						TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
 						TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
 						NUTAG_SESSION_TIMER(session_timeout),
+						TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
 						SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
 						SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
 						SIPTAG_CONTENT_TYPE_STR("application/sdp"),
@@ -2951,7 +2957,6 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
 	sofia_profile_t *profile = NULL;
 	char *profile_name = argv[0];
 	const char *err;
-	switch_xml_t xml_root;
 
 	if (argc < 2) {
 		stream->write_function(stream, "Invalid Args!\n");
@@ -2959,12 +2964,10 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
 	}
 
 	if (!strcasecmp(argv[1], "start")) {
-		if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) {
-			if ((xml_root = switch_xml_open_root(1, &err))) {
-				switch_xml_free(xml_root);
-			}
-			stream->write_function(stream, "Reload XML [%s]\n", err);
-		}
+
+		switch_xml_reload(&err);
+		stream->write_function(stream, "Reload XML [%s]\n", err);
+
 		if (config_sofia(1, argv[0]) == SWITCH_STATUS_SUCCESS) {
 			stream->write_function(stream, "%s started successfully\n", argv[0]);
 		} else {
@@ -3039,12 +3042,8 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
 
 	if (!strcasecmp(argv[1], "rescan")) {
 
-		if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) {
-			if ((xml_root = switch_xml_open_root(1, &err))) {
-				switch_xml_free(xml_root);
-			}
-			stream->write_function(stream, "Reload XML [%s]\n", err);
-		}
+		switch_xml_reload(&err);
+		stream->write_function(stream, "Reload XML [%s]\n", err);
 
 		if (reconfig_sofia(profile) == SWITCH_STATUS_SUCCESS) {
 			stream->write_function(stream, "+OK scan complete\n");
@@ -3141,12 +3140,8 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
 								   profile->name, rsec, remain, remain == 1 ? "" : "s");
 		} else {
 
-			if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) {
-				if ((xml_root = switch_xml_open_root(1, &err))) {
-					switch_xml_free(xml_root);
-				}
-				stream->write_function(stream, "Reload XML [%s]\n", err);
-			}
+			switch_xml_reload(&err);
+			stream->write_function(stream, "Reload XML [%s]\n", err);
 
 			if (!strcasecmp(argv[1], "stop")) {
 				sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
@@ -3487,7 +3482,7 @@ SWITCH_STANDARD_API(sofia_function)
 	const char *usage_string = "USAGE:\n"
 		"--------------------------------------------------------------------------------\n"
 		"sofia help\n"
-		"sofia profile  [[start|stop|restart|rescan] [reloadxml]|"
+		"sofia profile  [[start|stop|restart|rescan]|"
 		"flush_inbound_reg [] [reboot]|"
 		"[register|unregister] [|all]|"
 		"killgw |"
@@ -4628,10 +4623,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
 	switch_console_set_complete("add sofia profile");
 	switch_console_set_complete("add sofia profile restart all");
 
-	switch_console_set_complete("add sofia profile ::sofia::list_profiles start reloadxml");
-	switch_console_set_complete("add sofia profile ::sofia::list_profiles stop reloadxml");
-	switch_console_set_complete("add sofia profile ::sofia::list_profiles rescan reloadxml");
-	switch_console_set_complete("add sofia profile ::sofia::list_profiles restart reloadxml");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles start");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles stop");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles rescan");
+	switch_console_set_complete("add sofia profile ::sofia::list_profiles restart");
 
 	switch_console_set_complete("add sofia profile ::sofia::list_profiles flush_inbound_reg");
 	switch_console_set_complete("add sofia profile ::sofia::list_profiles register ::sofia::list_profile_gateway");
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h
index aa2149503a..96acbcd9ed 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.h
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.h
@@ -106,6 +106,7 @@ typedef struct private_object private_object_t;
 #define SOFIA_CRYPTO_MANDATORY_VARIABLE "sip_crypto_mandatory"
 #define FREESWITCH_SUPPORT "update_display"
 
+#include 
 #include 
 #include 
 #include 
@@ -199,6 +200,7 @@ typedef enum {
 	PFLAG_DISABLE_NAPTR,
 	PFLAG_AUTOFLUSH,
 	PFLAG_NAT_OPTIONS_PING,
+	PFLAG_ALL_REG_OPTIONS_PING,
 	PFLAG_AUTOFIX_TIMING,
 	PFLAG_MESSAGE_QUERY_ON_REGISTER,
 	PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER,
@@ -275,6 +277,7 @@ typedef enum {
 	TFLAG_RECOVERING,
 	TFLAG_RECOVERING_BRIDGE,
 	TFLAG_T38_PASSTHRU,
+	TFLAG_RECOVERED,
 	/* No new flags below this line */
 	TFLAG_MAX
 } TFLAGS;
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 14d05fd977..e76a56a4aa 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -1225,7 +1225,7 @@ static void sofia_perform_profile_start_failure(sofia_profile_t *profile, char *
 #define sofia_profile_start_failure(p, xp) sofia_perform_profile_start_failure(p, xp, __FILE__, __LINE__)
 
 
-#define SQLLEN 1024 * 64
+#define SQLLEN 1024 * 1024
 void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread, void *obj)
 {
 	sofia_profile_t *profile = (sofia_profile_t *) obj;
@@ -1233,11 +1233,12 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
 	uint32_t gateway_loops = 0;
 	int loops = 0;
 	uint32_t qsize;
-	void *pop;
+	void *pop = NULL;
 	int loop_count = 0;
-	switch_size_t sql_len = SQLLEN;
+	switch_size_t sql_len = 1024 * 32;
 	char *tmp, *sqlbuf = NULL;
-
+	char *sql = NULL;
+	
 	if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) {
 		sqlbuf = (char *) malloc(sql_len);
 	}
@@ -1253,37 +1254,43 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
 
 	while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) || qsize) {
 		if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) {
-			if (qsize > 0 && (qsize >= 1024 || ++loop_count >= profile->trans_timeout)) {
+			if (qsize > 0 && (qsize >= 1024 || ++loop_count >= (int)profile->trans_timeout)) {
 				switch_size_t newlen;
-				uint32_t itterations = 0;
+				uint32_t iterations = 0;
 				switch_size_t len = 0;
 
 				switch_mutex_lock(profile->ireg_mutex);
 				
-				//sofia_glue_actually_execute_sql(profile, "begin;\n", NULL);
-
-				while (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
-					char *sql = (char *) pop;
+				while (sql || (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop)) {
+					if (!sql) sql = (char *) pop;
 
 					newlen = strlen(sql) + 2;
+					iterations++;
 
-					if (newlen + 10 < SQLLEN) {
-						itterations++;
-						if (len + newlen + 10 > sql_len) {
-							sql_len = len + 10 + SQLLEN;
+					if (len + newlen + 10 > sql_len) {
+						int new_mlen = len + newlen + 10 + 10240;
+						
+						if (new_mlen < SQLLEN) {
+							sql_len = new_mlen;
+							
 							if (!(tmp = realloc(sqlbuf, sql_len))) {
 								abort();
 								break;
 							}
 							sqlbuf = tmp;
+						} else {
+							goto skip;
 						}
-						sprintf(sqlbuf + len, "%s;\n", sql);
-						len += newlen;
 					}
 
-					free(pop);
+					sprintf(sqlbuf + len, "%s;\n", sql);
+					len += newlen;
+					free(sql);
+					sql = NULL;
 				}
 
+			skip:
+
 				//printf("TRANS:\n%s\n", sqlbuf);
 				sofia_glue_actually_execute_sql_trans(profile, sqlbuf, NULL);
 				//sofia_glue_actually_execute_sql(profile, "commit;\n", NULL);
@@ -2549,6 +2556,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
 						} else {
 							sofia_clear_pflag(profile, PFLAG_NAT_OPTIONS_PING);
 						}
+					} else if (!strcasecmp(var, "all-reg-options-ping")) {
+						if (switch_true(val)) {
+							sofia_set_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
+						} else {
+							sofia_clear_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
+						}
 					} else if (!strcasecmp(var, "inbound-codec-negotiation")) {
 						if (!strcasecmp(val, "greedy")) {
 							sofia_set_pflag(profile, PFLAG_GREEDY);
@@ -2860,7 +2873,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
 					goto done;
 				}
 
-				profile->trans_timeout = 500;
+				profile->trans_timeout = 100;
 
 				profile->auto_rtp_bugs = RTP_BUG_CISCO_SKIP_MARK_BIT_2833;// | RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
 
@@ -3303,6 +3316,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
 						} else {
 							sofia_clear_pflag(profile, PFLAG_NAT_OPTIONS_PING);
 						}
+					} else if (!strcasecmp(var, "all-options-ping")) {
+						if (switch_true(val)) {
+							sofia_set_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
+						} else {
+							sofia_clear_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
+						}
 					} else if (!strcasecmp(var, "inbound-codec-negotiation")) {
 						if (!strcasecmp(val, "greedy")) {
 							sofia_set_pflag(profile, PFLAG_GREEDY);
@@ -4521,7 +4540,20 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
 		}
 		break;
 	case nua_callstate_completing:
-		nua_ack(nh, TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
+		{
+			if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
+				const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
+				const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");			
+
+				nua_ack(nh, 
+						TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)),
+						TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)),
+						TAG_END());
+						
+			} else {
+				nua_ack(nh, TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
+			}
+		}
 		goto done;
 	case nua_callstate_received:
 		if (!sofia_test_flag(tech_pvt, TFLAG_SDP)) {
@@ -5901,6 +5933,26 @@ void sofia_handle_sip_i_reinvite(switch_core_session_t *session,
 {
 	char *call_info = NULL;
 
+	if (session && profile && sip && sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
+		switch_channel_t *channel = switch_core_session_get_channel(session);
+		private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
+		char network_ip[80];
+		int network_port = 0;
+		char via_space[2048];
+		char branch[16] = "";
+
+		sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port);
+		switch_stun_random_string(branch, sizeof(branch) - 1, "0123456789abcdef");
+
+		switch_snprintf(via_space, sizeof(via_space), "SIP/2.0/UDP %s;rport=%d;branch=%s", network_ip, network_port, branch);
+		switch_channel_set_variable(channel, "sip_full_via", via_space);
+		switch_channel_set_variable_printf(channel, "sip_network_port", "%d", network_port);
+		switch_channel_set_variable_printf(channel, "sip_recieved_port", "%d", network_port);
+		switch_channel_set_variable_printf(channel, "sip_via_rport", "%d", network_port);
+		
+		sofia_glue_tech_track(tech_pvt->profile, session);
+	}
+
 	if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
 		switch_channel_t *channel = switch_core_session_get_channel(session);
 		if (channel && sip->sip_call_info) {
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 82b933c981..d17981c9d0 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -1658,7 +1658,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 		sofia_private_t *sofia_private;
 		char *invite_contact = NULL, *to_str, *use_from_str, *from_str;
 		const char *t_var;
-		char *rpid_domain = "cluecon.com", *p;
+		char *rpid_domain = NULL, *p;
 		const char *priv = "off";
 		const char *screen = "no";
 		const char *invite_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_params");
@@ -1670,6 +1670,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 		const char *from_var = switch_channel_get_variable(tech_pvt->channel, "sip_from_uri");
 		const char *from_display = switch_channel_get_variable(tech_pvt->channel, "sip_from_display");
 		const char *invite_req_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_req_uri");
+		const char *invite_domain = switch_channel_get_variable(tech_pvt->channel, "sip_invite_domain");
 		const char *use_name, *use_number;
 
 		if (zstr(tech_pvt->dest)) {
@@ -1688,7 +1689,6 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 		if (!tech_pvt->from_str) {
 			const char *sipip;
 			const char *format;
-			const char *alt = NULL;
 
 			sipip = tech_pvt->profile->sipip;
 
@@ -1698,8 +1698,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 
 			format = strchr(sipip, ':') ? "\"%s\" " : "\"%s\" ";
 
-			if ((alt = switch_channel_get_variable(channel, "sip_invite_domain"))) {
-				sipip = alt;
+			if (!zstr(invite_domain)) {
+				sipip = invite_domain;
 			}
 
 			tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, format, cid_name, cid_num, !zstr(cid_num) ? "@" : "", sipip);
@@ -1739,6 +1739,10 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 			}
 		}
 
+		if (!zstr(invite_domain)) {
+			rpid_domain = (char *)invite_domain;
+		}
+
 		if (zstr(rpid_domain)) {
 			rpid_domain = "cluecon.com";
 		}
@@ -2055,10 +2059,16 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 		sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
 	}
 
+	if (sofia_test_flag(tech_pvt, TFLAG_RECOVERED)) {
+		session_timeout = 0;
+	}
+
 	if (sofia_use_soa(tech_pvt)) {
 		nua_invite(tech_pvt->nh,
 				   NUTAG_AUTOANSWER(0),
 				   NUTAG_SESSION_TIMER(session_timeout),
+				   TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
+				   TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
 				   TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
 				   TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
 				   TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
@@ -2087,6 +2097,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 		nua_invite(tech_pvt->nh,
 				   NUTAG_AUTOANSWER(0),
 				   NUTAG_SESSION_TIMER(session_timeout),
+				   TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
+				   TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
 				   TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
 				   TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
 				   TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
@@ -2230,6 +2242,9 @@ static void set_stats(switch_rtp_t *rtp_session, private_object_t *tech_pvt, con
 		add_stat(stats->outbound.dtmf_packet_count, "out_dtmf_packet_count");
 		add_stat(stats->outbound.cng_packet_count, "out_cng_packet_count");
 
+		add_stat(stats->rtcp.packet_count, "rtcp_packet_count");
+		add_stat(stats->rtcp.octet_count, "rtcp_octet_count");
+
 	}
 }
 
@@ -3579,11 +3594,12 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
 	if (sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_HOLD) ||
 		((val = switch_channel_get_variable(tech_pvt->channel, "sip_disable_hold")) && switch_true(val))) {
 		sendonly = 0;
-	}
+	} else {
 
-	if (!tech_pvt->hold_laps) {
-		tech_pvt->hold_laps++;
-		sofia_glue_toggle_hold(tech_pvt, sendonly);
+		if (!tech_pvt->hold_laps) {
+			tech_pvt->hold_laps++;
+			sofia_glue_toggle_hold(tech_pvt, sendonly);
+		}
 	}
 
 	for (m = sdp->sdp_media; m; m = m->m_next) {
@@ -4644,7 +4660,7 @@ void sofia_glue_tech_untrack(sofia_profile_t *profile, switch_core_session_t *se
 			}
 		}
 		
-		sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+		sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
 		sofia_clear_flag(tech_pvt, TFLAG_TRACKED);
 		
 		switch_safe_free(sql);
diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index 73d930314b..5eb71b37e9 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -1442,7 +1442,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
 					op = switch_event_get_header(helper->event, "Caller-Callee-ID-Number");
 				}
 
-				if (!op) {
+				if (zstr(op)) {
 					op = switch_event_get_header(helper->event, "Caller-Destination-Number");
 				}
 
@@ -1452,7 +1452,7 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
 
 				if (!strcmp(astate, "early")) {
 					if (zstr(op)) {
-						switch_snprintf(status_line, sizeof(status_line), "%s %s", what, status);
+						switch_snprintf(status_line, sizeof(status_line), "%sing", what);
 					} else {
 						switch_snprintf(status_line, sizeof(status_line), "%s %s", what, op);
 					}
@@ -2043,7 +2043,11 @@ void sofia_presence_handle_sip_i_subscribe(int status,
 			from_host = "n/a";
 		}
 
-		exp_delta = profile->force_subscription_expires ? profile->force_subscription_expires : (sip->sip_expires ? sip->sip_expires->ex_delta : 3600);
+		if ((exp_delta = sip->sip_expires ? sip->sip_expires->ex_delta : 3600)) {
+			if (profile->force_subscription_expires) {
+				exp_delta = profile->force_subscription_expires;
+			}
+		}
 
 		if (exp_delta) {
 			exp_abs = (long) switch_epoch_time_now(NULL) + exp_delta;
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index c78ed90fe3..3ffbc26c33 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -438,11 +438,14 @@ int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames
 	switch_snprintf(to, sizeof(to), "sip:%s@%s", argv[1], argv[2]);
 	dst = sofia_glue_get_destination(argv[3]);
 	switch_assert(dst);
-
+	
 	nh = nua_handle(profile->nua, NULL, SIPTAG_FROM_STR(profile->url), SIPTAG_TO_STR(to), NUTAG_URL(dst->contact), SIPTAG_CONTACT_STR(profile->url),
 					TAG_END());
 	nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
-	nua_options(nh, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_END());
+	nua_options(nh, 
+				NTATAG_SIP_T2(5000),
+				NTATAG_SIP_T4(10000),
+				TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_END());
 
 	sofia_glue_free_destination(dst);
 
@@ -514,7 +517,7 @@ int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames
 			switch_event_fire(&s_event);
 		}
 
-		if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
+		if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "away");
 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->url);
@@ -637,15 +640,14 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
 	}
 
 	sofia_glue_actually_execute_sql(profile, sql, NULL);
-
-
-
+	
 	if (now) {
 		switch_snprintf(sql, sizeof(sql),
 						"select call_id from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'", (long) now,
 						mod_sofia_globals.hostname);
 	} else {
-		switch_snprintf(sql, sizeof(sql), "select call_id from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
+		switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'", 
+						mod_sofia_globals.hostname);
 	}
 
 	sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile);
@@ -670,13 +672,21 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
 	sofia_glue_actually_execute_sql(profile, sql, NULL);
 
 
-	if (now && sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
-		switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
-						"expires,user_agent,server_user,server_host,profile_name"
-						" from sip_registrations where (status like '%%NAT%%' "
-						"or contact like '%%fs_nat=true%%') and hostname='%s'", mod_sofia_globals.hostname);
-
-		sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
+	if (now) {
+		if (sofia_test_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING)) {
+			switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
+							"expires,user_agent,server_user,server_host,profile_name"
+							" from sip_registrations where hostname='%s'", mod_sofia_globals.hostname);
+			
+			sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
+		} else if (sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
+			switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
+							"expires,user_agent,server_user,server_host,profile_name"
+							" from sip_registrations where (status like '%%NAT%%' "
+							"or contact like '%%fs_nat=yes%%') and hostname='%s'", mod_sofia_globals.hostname);
+			
+			sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
+		}
 	}
 
 	switch_mutex_unlock(profile->ireg_mutex);
@@ -810,6 +820,9 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 	switch_event_t *auth_params = NULL;
 	int r = 0;
 	long reg_count = 0;
+	int delete_subs = 1;
+	const char *agent = "unknown";
+		
 
 	/* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */
 	switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL);
@@ -826,6 +839,14 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 	to = sip->sip_to;
 	from = sip->sip_from;
 
+	if (sip->sip_user_agent) {
+		agent = sip->sip_user_agent->g_string;
+
+		if (switch_stristr("snom", agent)) {
+			delete_subs = 0;
+		}
+	}
+
 	if (from) {
 		from_user = from->a_url->url_user;
 		from_host = from->a_url->url_host;
@@ -1135,7 +1156,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 	}
 
 	if (exptime) {
-		const char *agent = "dunno";
 		char guess_ip4[256];
 		const char *username = "unknown";
 		const char *realm = reg_host;
@@ -1145,19 +1165,15 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 			realm = switch_event_get_header(auth_params, "sip_auth_realm");
 		}
 
-		if (sip->sip_user_agent) {
-			agent = sip->sip_user_agent->g_string;
-		}
-
 		if (multi_reg) {
 
-#ifdef DEL_SUBS
-			if (reg_count == 1) {
-				sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", 
-									 to_user, sub_host, contact_str);
-				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+			if (delete_subs) {
+				if (reg_count == 1) {
+					sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", 
+										 to_user, sub_host, contact_str);
+					sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+				}
 			}
-#endif
 				
 
 			if (multi_reg_contact) {
@@ -1167,10 +1183,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 				sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
 			}
 		} else {
-#ifdef DEL_SUBS
-			sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
-			sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
-#endif
+			if (delete_subs) {
+				sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
+				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+			}
 			sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
 		}
 		switch_mutex_lock(profile->ireg_mutex);
@@ -1185,7 +1201,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 							 "mwi_user,mwi_host, orig_server_host, orig_hostname) "
 							 "values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q')", 
 							 call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : reg_host, 
-							 contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime * 2, 
+							 contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime + 60, 
 							 agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm, 
 							 mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname);
 							 
@@ -1290,16 +1306,16 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 			if ((p = strchr(icontact + 4, ':'))) {
 				*p = '\0';
 			}
-#ifdef DEL_SUBS
-			if (multi_reg_contact) {
-				sql =
-					switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
-			} else {
-				sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
-			}
+			if (delete_subs) {
+				if (multi_reg_contact) {
+					sql =
+						switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
+				} else {
+					sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
+				}
 
-			sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
-#endif
+				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+			}
 
 			if (multi_reg_contact) {
 				sql =
@@ -1312,11 +1328,11 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
 
 			switch_safe_free(icontact);
 		} else {
-#ifdef DEL_SUBS
-			if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
-				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+			if (delete_subs) {
+				if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
+					sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+				}
 			}
-#endif
 			if ((sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
 				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
 			}
@@ -2292,9 +2308,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
 				switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "mwi-account", mwi_account);
 			}
 
-			if ((uparams = switch_xml_child(user, "params"))) {
+			if ((dparams = switch_xml_child(domain, "params"))) {
 				xparams_type[i] = 0;
-				xparams[i++] = uparams;
+				xparams[i++] = dparams;
 			}
 
 			if (group && (gparams = switch_xml_child(group, "params"))) {
@@ -2302,102 +2318,98 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
 				xparams[i++] = gparams;
 			}
 
-			if ((dparams = switch_xml_child(domain, "params"))) {
+			if ((uparams = switch_xml_child(user, "params"))) {
 				xparams_type[i] = 0;
-				xparams[i++] = dparams;
-			}
-
-			if ((uparams = switch_xml_child(user, "variables"))) {
-				xparams_type[i] = 1;
 				xparams[i++] = uparams;
 			}
 
-			if (group && (gparams = switch_xml_child(group, "variables"))) {
-				xparams_type[i] = 1;
-				xparams[i++] = gparams;
-			}
-
 			if ((dparams = switch_xml_child(domain, "variables"))) {
 				xparams_type[i] = 1;
 				xparams[i++] = dparams;
 			}
 
+			if (group && (gparams = switch_xml_child(group, "variables"))) {
+				xparams_type[i] = 1;
+				xparams[i++] = gparams;
+			}
+
+			if ((uparams = switch_xml_child(user, "variables"))) {
+				xparams_type[i] = 1;
+				xparams[i++] = uparams;
+			}
+
 			if (i <= 6) {
 				int j = 0;
+				const char *gw_val = NULL;
 
 				for (j = 0; j < i; j++) {
 					for (param = switch_xml_child(xparams[j], (xparams_type[j] ? "variable" : "param")); param; param = param->next) {
 						const char *var = switch_xml_attr_soft(param, "name");
 						const char *val = switch_xml_attr_soft(param, "value");
-						sofia_gateway_t *gateway_ptr = NULL;
 
 						if (!zstr(var) && !zstr(val) && (xparams_type[j] == 1 || !strncasecmp(var, "sip-", 4) || !strcasecmp(var, "register-gateway"))) {
-							if (!switch_event_get_header(*v_event, var)) {
-								if (profile->debug) {
-									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event_add_header -> '%s' = '%s'\n", var, val);
-								}
-								switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, var, val);
-							} else {
-								continue;
+							if (profile->debug) {
+								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event_add_header -> '%s' = '%s'\n", var, val);
 							}
-
-							if (!strcasecmp(var, "register-gateway")) {
-								if (!strcasecmp(val, "all")) {
-									switch_xml_t gateways_tag, gateway_tag;
-									if ((gateways_tag = switch_xml_child(user, "gateways"))) {
-										for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
-											char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
-											if (zstr(name)) {
-												name = "anonymous";
-											}
-
-											if ((gateway_ptr = sofia_reg_find_gateway(name))) {
-												reg_state_t ostate = gateway_ptr->state;
-												gateway_ptr->retry = 0;
-												if (exptime) {
-													gateway_ptr->state = REG_STATE_UNREGED;
-												} else {
-													gateway_ptr->state = REG_STATE_UNREGISTER;
-												}
-												if (ostate != gateway_ptr->state) {
-													sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
-												}
-												sofia_reg_release_gateway(gateway_ptr);
-											}
-
-										}
-									}
-								} else {
-									int x, argc;
-									char *mydata, *argv[50];
-
-									mydata = strdup(val);
-									switch_assert(mydata != NULL);
-
-									argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
-
-									for (x = 0; x < argc; x++) {
-										if ((gateway_ptr = sofia_reg_find_gateway((char *) argv[x]))) {
-											reg_state_t ostate = gateway_ptr->state;
-											gateway_ptr->retry = 0;
-											if (exptime) {
-												gateway_ptr->state = REG_STATE_UNREGED;
-											} else {
-												gateway_ptr->state = REG_STATE_UNREGISTER;
-											}
-											if (ostate != gateway_ptr->state) {
-												sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
-											}
-											sofia_reg_release_gateway(gateway_ptr);
-										} else {
-											switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Gateway '%s' not found.\n", argv[x]);
-										}
-									}
-
-									free(mydata);
+							switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, var, val);
+						}
+					}
+				}
+				if ((gw_val = switch_event_get_header(*v_event, "register-gateway"))) {
+					sofia_gateway_t *gateway_ptr = NULL;
+					if (!strcasecmp(gw_val, "all")) {
+						switch_xml_t gateways_tag, gateway_tag;
+						if ((gateways_tag = switch_xml_child(user, "gateways"))) {
+							for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
+								char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
+								if (zstr(name)) {
+									name = "anonymous";
 								}
+
+								if ((gateway_ptr = sofia_reg_find_gateway(name))) {
+									reg_state_t ostate = gateway_ptr->state;
+									gateway_ptr->retry = 0;
+									if (exptime) {
+										gateway_ptr->state = REG_STATE_UNREGED;
+									} else {
+										gateway_ptr->state = REG_STATE_UNREGISTER;
+									}
+									if (ostate != gateway_ptr->state) {
+										sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
+									}
+									sofia_reg_release_gateway(gateway_ptr);
+								}
+
 							}
 						}
+					} else {
+						int x, argc;
+						char *mydata, *argv[50];
+
+						mydata = strdup(gw_val);
+						switch_assert(mydata != NULL);
+
+						argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
+
+						for (x = 0; x < argc; x++) {
+							if ((gateway_ptr = sofia_reg_find_gateway((char *) argv[x]))) {
+								reg_state_t ostate = gateway_ptr->state;
+								gateway_ptr->retry = 0;
+								if (exptime) {
+									gateway_ptr->state = REG_STATE_UNREGED;
+								} else {
+									gateway_ptr->state = REG_STATE_UNREGISTER;
+								}
+								if (ostate != gateway_ptr->state) {
+									sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
+								}
+								sofia_reg_release_gateway(gateway_ptr);
+							} else {
+								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Gateway '%s' not found.\n", argv[x]);
+							}
+						}
+
+						free(mydata);
 					}
 				}
 			}
diff --git a/src/mod/languages/mod_lua/freeswitch.i b/src/mod/languages/mod_lua/freeswitch.i
index 383580103f..54bdb7bdc9 100644
--- a/src/mod/languages/mod_lua/freeswitch.i
+++ b/src/mod/languages/mod_lua/freeswitch.i
@@ -19,8 +19,15 @@
 
 
 /* Lua function typemap */
-%typemap(in,checkfn="lua_isfunction") SWIGLUA_FN
-%{  $1.L=L; $1.idx=$input; %}
+%typemap(in, checkfn = "lua_isfunction") SWIGLUA_FN {
+  $1.L = L;
+  $1.idx = $input;
+}
+
+%typemap(default) SWIGLUA_FN {
+  SWIGLUA_FN default_swiglua_fn = { 0 };
+  $1 = default_swiglua_fn;
+}
 
 
 %ignore SwitchToMempool;   
diff --git a/src/mod/languages/mod_lua/freeswitch_lua.cpp b/src/mod/languages/mod_lua/freeswitch_lua.cpp
index 17d12bc1cb..d60ae737a8 100644
--- a/src/mod/languages/mod_lua/freeswitch_lua.cpp
+++ b/src/mod/languages/mod_lua/freeswitch_lua.cpp
@@ -367,10 +367,15 @@ int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
 bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
 {
   if (connected) {
-    if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
-      return true;
+    if (lua_fun.L) {
+      if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
+        return true;
+      }
+    } else { /* if no lua_fun arg is passed from Lua, an empty initialized struct will be sent - see freeswitch.i */
+      if (switch_cache_db_execute_sql(dbh, sql, NULL) == SWITCH_STATUS_SUCCESS) {
+        return true;
+      }
     }
   }
-  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no workie workie :(\n");
   return false;
 }
diff --git a/src/mod/languages/mod_lua/mod_lua.cpp b/src/mod/languages/mod_lua/mod_lua.cpp
index 3ccbef5aaa..cf9b373ce0 100644
--- a/src/mod/languages/mod_lua/mod_lua.cpp
+++ b/src/mod/languages/mod_lua/mod_lua.cpp
@@ -588,7 +588,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load)
 
 	SWITCH_ADD_API(api_interface, "luarun", "run a script", luarun_api_function, "