[svn-commits] irroot: branch irroot/t38gateway-1.8 r347949 - in /team/irroot/t38gateway-1.8...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Dec 12 10:29:43 CST 2011


Author: irroot
Date: Mon Dec 12 10:29:28 2011
New Revision: 347949

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=347949
Log:
Merge 346715:347946 enable automerge

Modified:
    team/irroot/t38gateway-1.8/   (props changed)
    team/irroot/t38gateway-1.8/addons/chan_ooh323.c
    team/irroot/t38gateway-1.8/apps/app_meetme.c
    team/irroot/t38gateway-1.8/apps/app_voicemail.c
    team/irroot/t38gateway-1.8/channels/chan_dahdi.c
    team/irroot/t38gateway-1.8/channels/chan_h323.c
    team/irroot/t38gateway-1.8/channels/chan_sip.c
    team/irroot/t38gateway-1.8/channels/sig_analog.c
    team/irroot/t38gateway-1.8/channels/sig_analog.h
    team/irroot/t38gateway-1.8/channels/sip/include/sip.h
    team/irroot/t38gateway-1.8/main/features.c
    team/irroot/t38gateway-1.8/main/manager.c
    team/irroot/t38gateway-1.8/main/pbx.c
    team/irroot/t38gateway-1.8/res/res_jabber.exports.in

Propchange: team/irroot/t38gateway-1.8/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/irroot/t38gateway-1.8/
------------------------------------------------------------------------------
Binary property 'branch-1.6.2-merged' - no diff available.

Modified: team/irroot/t38gateway-1.8/addons/chan_ooh323.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/addons/chan_ooh323.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/addons/chan_ooh323.c (original)
+++ team/irroot/t38gateway-1.8/addons/chan_ooh323.c Mon Dec 12 10:29:28 2011
@@ -4519,7 +4519,7 @@
 		f = &null_frame;
 	}
 
-	if (p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) {
+	if (f && p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) {
 		/* We already hold the channel lock */
 		if (f->subclass.codec != p->owner->nativeformats) {
 			ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(f->subclass.codec));

Modified: team/irroot/t38gateway-1.8/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/apps/app_meetme.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/apps/app_meetme.c (original)
+++ team/irroot/t38gateway-1.8/apps/app_meetme.c Mon Dec 12 10:29:28 2011
@@ -3927,8 +3927,12 @@
 			cnf->useropts = ast_strdup(useropts);
 			cnf->adminopts = ast_strdup(adminopts);
 			cnf->bookid = ast_strdup(bookid);
-			cnf->recordingfilename = ast_strdup(recordingfilename);
-			cnf->recordingformat = ast_strdup(recordingformat);
+			if (!ast_strlen_zero(recordingfilename)) {
+				cnf->recordingfilename = ast_strdup(recordingfilename);
+			}
+			if (!ast_strlen_zero(recordingformat)) {
+				cnf->recordingformat = ast_strdup(recordingformat);
+			}
 
 			/* Parse the other options into confflags -- need to do this in two
 			 * steps, because the parse_options routine zeroes the buffer. */

Modified: team/irroot/t38gateway-1.8/apps/app_voicemail.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/apps/app_voicemail.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/apps/app_voicemail.c (original)
+++ team/irroot/t38gateway-1.8/apps/app_voicemail.c Mon Dec 12 10:29:28 2011
@@ -540,6 +540,10 @@
 });
 
 static int load_config(int reload);
+#ifdef TEST_FRAMEWORK
+static int load_config_from_memory(int reload, struct ast_config *cfg, struct ast_config *ucfg);
+#endif
+static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg);
 
 /*! \page vmlang Voicemail Language Syntaxes Supported
 
@@ -11777,16 +11781,9 @@
 
 static int load_config(int reload)
 {
-	struct ast_vm_user *current;
 	struct ast_config *cfg, *ucfg;
-	char *cat;
-	struct ast_variable *var;
-	const char *val;
-	char *q, *stringp, *tmp;
-	int x;
-	int tmpadsi[4];
 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
-	char secretfn[PATH_MAX] = "";
+	int res;
 
 	ast_unload_realtime("voicemail");
 	ast_unload_realtime("voicemail_data");
@@ -11814,6 +11811,35 @@
 			ucfg = NULL;
 		}
 	}
+
+	res = actual_load_config(reload, cfg, ucfg);
+
+	ast_config_destroy(cfg);
+	ast_config_destroy(ucfg);
+
+	return res;
+}
+
+#ifdef TEST_FRAMEWORK
+static int load_config_from_memory(int reload, struct ast_config *cfg, struct ast_config *ucfg)
+{
+	ast_unload_realtime("voicemail");
+	ast_unload_realtime("voicemail_data");
+	return actual_load_config(reload, cfg, ucfg);
+}
+#endif
+
+static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
+{
+	struct ast_vm_user *current;
+	char *cat;
+	struct ast_variable *var;
+	const char *val;
+	char *q, *stringp, *tmp;
+	int x;
+	int tmpadsi[4];
+	char secretfn[PATH_MAX] = "";
+
 #ifdef IMAP_STORAGE
 	ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
 #endif
@@ -12325,6 +12351,70 @@
 		if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
 			poll_mailboxes = ast_true(val);
 
+		memset(fromstring, 0, sizeof(fromstring));
+		memset(pagerfromstring, 0, sizeof(pagerfromstring));
+		strcpy(charset, "ISO-8859-1");
+		if (emailbody) {
+			ast_free(emailbody);
+			emailbody = NULL;
+		}
+		if (emailsubject) {
+			ast_free(emailsubject);
+			emailsubject = NULL;
+		}
+		if (pagerbody) {
+			ast_free(pagerbody);
+			pagerbody = NULL;
+		}
+		if (pagersubject) {
+			ast_free(pagersubject);
+			pagersubject = NULL;
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
+			ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
+		if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
+			ast_copy_string(fromstring, val, sizeof(fromstring));
+		if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
+			ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
+		if ((val = ast_variable_retrieve(cfg, "general", "charset")))
+			ast_copy_string(charset, val, sizeof(charset));
+		if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
+			sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
+			for (x = 0; x < 4; x++) {
+				memcpy(&adsifdn[x], &tmpadsi[x], 1);
+			}
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
+			sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
+			for (x = 0; x < 4; x++) {
+				memcpy(&adsisec[x], &tmpadsi[x], 1);
+			}
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
+			if (atoi(val)) {
+				adsiver = atoi(val);
+			}
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
+			ast_copy_string(zonetag, val, sizeof(zonetag));
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
+			ast_copy_string(locale, val, sizeof(locale));
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
+			emailsubject = ast_strdup(substitute_escapes(val));
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
+			emailbody = ast_strdup(substitute_escapes(val));
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
+			pagersubject = ast_strdup(substitute_escapes(val));
+		}
+		if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
+			pagerbody = ast_strdup(substitute_escapes(val));
+		}
+
+		/* load mailboxes from users.conf */
 		if (ucfg) {	
 			for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
 				if (!strcasecmp(cat, "general")) {
@@ -12347,8 +12437,9 @@
 					}
 				}
 			}
-			ast_config_destroy(ucfg);
-		}
+		}
+
+		/* load mailboxes from voicemail.conf */
 		cat = ast_category_browse(cfg, NULL);
 		while (cat) {
 			if (strcasecmp(cat, "general")) {
@@ -12380,7 +12471,6 @@
 							}
 						} else {
 							AST_LIST_UNLOCK(&users);
-							ast_config_destroy(cfg);
 							return -1;
 						}
 						var = var->next;
@@ -12389,70 +12479,8 @@
 			}
 			cat = ast_category_browse(cfg, cat);
 		}
-		memset(fromstring, 0, sizeof(fromstring));
-		memset(pagerfromstring, 0, sizeof(pagerfromstring));
-		strcpy(charset, "ISO-8859-1");
-		if (emailbody) {
-			ast_free(emailbody);
-			emailbody = NULL;
-		}
-		if (emailsubject) {
-			ast_free(emailsubject);
-			emailsubject = NULL;
-		}
-		if (pagerbody) {
-			ast_free(pagerbody);
-			pagerbody = NULL;
-		}
-		if (pagersubject) {
-			ast_free(pagersubject);
-			pagersubject = NULL;
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
-			ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
-		if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
-			ast_copy_string(fromstring, val, sizeof(fromstring));
-		if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
-			ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
-		if ((val = ast_variable_retrieve(cfg, "general", "charset")))
-			ast_copy_string(charset, val, sizeof(charset));
-		if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
-			sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
-			for (x = 0; x < 4; x++) {
-				memcpy(&adsifdn[x], &tmpadsi[x], 1);
-			}
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
-			sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
-			for (x = 0; x < 4; x++) {
-				memcpy(&adsisec[x], &tmpadsi[x], 1);
-			}
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
-			if (atoi(val)) {
-				adsiver = atoi(val);
-			}
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
-			ast_copy_string(zonetag, val, sizeof(zonetag));
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
-			ast_copy_string(locale, val, sizeof(locale));
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
-			emailsubject = ast_strdup(substitute_escapes(val));
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
-			emailbody = ast_strdup(substitute_escapes(val));
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
-			pagersubject = ast_strdup(substitute_escapes(val));
-		}
-		if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
-			pagerbody = ast_strdup(substitute_escapes(val));
-		}
+
 		AST_LIST_UNLOCK(&users);
-		ast_config_destroy(cfg);
 
 		if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
 			start_poll_thread();
@@ -12463,8 +12491,6 @@
 	} else {
 		AST_LIST_UNLOCK(&users);
 		ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
-		if (ucfg)
-			ast_config_destroy(ucfg);
 		return 0;
 	}
 }
@@ -12924,6 +12950,84 @@
 	fclose(file);
 	return res;
 }
+
+AST_TEST_DEFINE(test_voicemail_load_config)
+{
+	int res = AST_TEST_PASS;
+	struct ast_vm_user *vmu;
+	struct ast_config *cfg;
+	char config_filename[32] = "/tmp/voicemail.conf.XXXXXX";
+	int fd;
+	FILE *file;
+	struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "test_voicemail_load_config";
+		info->category = "/apps/app_voicemail/";
+		info->summary = "Test loading Voicemail config";
+		info->description =
+			"Verify that configuration is loaded consistently. "
+			"This is to test regressions of ASTERISK-18838 where it was noticed that "
+			"some options were loaded after the mailboxes were instantiated, causing "
+			"those options not to be set correctly.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	/* build a config file by hand... */
+	if ((fd = mkstemp(config_filename)) < 0) {
+		return AST_TEST_FAIL;
+	}
+	if (!(file = fdopen(fd, "w"))) {
+		close(fd);
+		unlink(config_filename);
+		return AST_TEST_FAIL;
+	}
+	fputs("[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]", file);
+	fputs("00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n", file);
+	fputs("00000002 => 9999,Mrs. Test\n", file);
+	fclose(file);
+
+	if (!(cfg = ast_config_load(config_filename, config_flags))) {
+		res = AST_TEST_FAIL;
+		goto cleanup;
+	}
+
+	load_config_from_memory(1, cfg, NULL);
+	ast_config_destroy(cfg);
+
+#define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \
+	ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
+	u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
+
+	AST_LIST_LOCK(&users);
+	AST_LIST_TRAVERSE(&users, vmu, list) {
+		if (!strcmp(vmu->mailbox, "00000001")) {
+			if (0); /* trick to get CHECK to work */
+			CHECK(vmu, callback, "othercontext")
+			CHECK(vmu, locale, "nl_NL.UTF-8")
+			CHECK(vmu, zonetag, "central")
+		} else if (!strcmp(vmu->mailbox, "00000002")) {
+			if (0); /* trick to get CHECK to work */
+			CHECK(vmu, callback, "somecontext")
+			CHECK(vmu, locale, "de_DE.UTF-8")
+			CHECK(vmu, zonetag, "european")
+		}
+	}
+	AST_LIST_UNLOCK(&users);
+
+#undef CHECK
+
+	/* restore config */
+	load_config(1); /* this might say "Failed to load configuration file." */
+
+cleanup:
+	unlink(config_filename);
+	return res;
+}
+
 #endif /* defined(TEST_FRAMEWORK) */
 
 static int reload(void)
@@ -12948,6 +13052,7 @@
 	res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
 	res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
 	res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
+	res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
 #endif
 	ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
 	ast_uninstall_vm_functions();
@@ -12997,6 +13102,7 @@
 	res |= AST_TEST_REGISTER(test_voicemail_msgcount);
 	res |= AST_TEST_REGISTER(test_voicemail_vmuser);
 	res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
+	res |= AST_TEST_REGISTER(test_voicemail_load_config);
 #endif
 
 	if (res)

Modified: team/irroot/t38gateway-1.8/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/channels/chan_dahdi.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/channels/chan_dahdi.c (original)
+++ team/irroot/t38gateway-1.8/channels/chan_dahdi.c Mon Dec 12 10:29:28 2011
@@ -3576,7 +3576,18 @@
 	}
 }
 
-
+static int my_have_progressdetect(void *pvt)
+{
+	struct dahdi_pvt *p = pvt;
+
+	if ((p->callprogress & CALLPROGRESS_PROGRESS)
+		&& CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
+		return 1;
+	} else {
+		/* Don't have progress detection. */
+		return 0;
+	}
+}
 
 static struct analog_callback dahdi_analog_callbacks =
 {
@@ -3644,6 +3655,7 @@
 	.start_polarityswitch = my_start_polarityswitch,
 	.answer_polarityswitch = my_answer_polarityswitch,
 	.hangup_polarityswitch = my_hangup_polarityswitch,
+	.have_progressdetect = my_have_progressdetect,
 };
 
 /*! Round robin search locations. */

Modified: team/irroot/t38gateway-1.8/channels/chan_h323.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/channels/chan_h323.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/channels/chan_h323.c (original)
+++ team/irroot/t38gateway-1.8/channels/chan_h323.c Mon Dec 12 10:29:28 2011
@@ -764,7 +764,7 @@
 	if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) {
 		return &ast_null_frame;
 	}
-	if (pvt->owner) {
+	if (f && pvt->owner) {
 		/* We already hold the channel lock */
 		if (f->frametype == AST_FRAME_VOICE) {
 			if (f->subclass.codec != pvt->owner->nativeformats) {

Modified: team/irroot/t38gateway-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/channels/chan_sip.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/channels/chan_sip.c (original)
+++ team/irroot/t38gateway-1.8/channels/chan_sip.c Mon Dec 12 10:29:28 2011
@@ -10687,14 +10687,20 @@
 	int event;
 	if (mode) {
 		/* Application/dtmf short version used by some implementations */
-		if (digit == '*')
+		if ('0' <= digit && digit <= '9') {
+			event = digit - '0';
+		} else if (digit == '*') {
 			event = 10;
-		else if (digit == '#')
+		} else if (digit == '#') {
 			event = 11;
-		else if ((digit >= 'A') && (digit <= 'D'))
+		} else if ('A' <= digit && digit <= 'D') {
 			event = 12 + digit - 'A';
-		else
-			event = atoi(&digit);
+		} else if ('a' <= digit && digit <= 'd') {
+			event = 12 + digit - 'a';
+		} else {
+			/* Unknown digit */
+			event = 0;
+		}
 		snprintf(tmp, sizeof(tmp), "%d\r\n", event);
 		add_header(req, "Content-Type", "application/dtmf");
 		add_content(req, tmp);
@@ -13636,7 +13642,12 @@
 	return TRUE;		
 }
 
-/*! \brief parse uri in a way that allows semicolon stripping if legacy mode is enabled */
+/*! \brief parse uri in a way that allows semicolon stripping if legacy mode is enabled
+ *
+ * \note This calls parse_uri which has the unexpected property that passing more
+ *       arguments results in more splitting. Most common is to leave out the pass
+ *       argument, causing user to contain user:pass if available.
+ */
 static int parse_uri_legacy_check(char *uri, const char *scheme, char **user, char **pass, char **hostport, char **transport)
 {
 	int ret = parse_uri(uri, scheme, user, pass, hostport, transport);
@@ -14496,7 +14507,7 @@
 	enum check_auth_result res = AUTH_NOT_FOUND;
 	struct sip_peer *peer;
 	char tmp[256];
-	char *name = NULL, *c, *domain = NULL, *dummy = NULL;
+	char *c, *name, *unused_password, *domain;
 	char *uri2 = ast_strdupa(uri);
 
 	terminate_uri(uri2);
@@ -14506,7 +14517,7 @@
 	c = get_in_brackets(tmp);
 	c = remove_uri_parameters(c);
 
-	if (parse_uri_legacy_check(c, "sip:,sips:", &name, &dummy, &domain, NULL)) {
+	if (parse_uri_legacy_check(c, "sip:,sips:", &name, &unused_password, &domain, NULL)) {
 		ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_sockaddr_stringify_addr(addr));
 		return -1;
 	}
@@ -14516,12 +14527,34 @@
 
 	extract_host_from_hostport(&domain);
 
-	/*! \todo XXX here too we interpret a missing @domain as a name-only
-	 * URI, whereas the RFC says this is a domain-only uri.
-	 */
-	if (!ast_strlen_zero(domain) && !AST_LIST_EMPTY(&domain_list)) {
+	if (ast_strlen_zero(domain)) {
+		/* <sip:name@[EMPTY]>, never good */
+		transmit_response(p, "404 Not found", &p->initreq);
+		return AUTH_UNKNOWN_DOMAIN;
+	}
+
+	if (ast_strlen_zero(name)) {
+		/* <sip:[EMPTY][@]hostport>, unsure whether valid for
+		 * registration. RFC 3261, 10.2 states:
+		 * "The To header field and the Request-URI field typically
+		 * differ, as the former contains a user name."
+		 * But, Asterisk has always treated the domain-only uri as a
+		 * username: we allow admins to create accounts described by
+		 * domain name. */
+		name = domain;
+	}
+
+	/* This here differs from 1.4 and 1.6: the domain matching ACLs were
+	 * skipped if it was a domain-only URI (used as username). Here we treat
+	 * <sip:hostport> as <sip:host at hostport> and won't forget to test the
+	 * domain ACLs against host. */
+	if (!AST_LIST_EMPTY(&domain_list)) {
 		if (!check_sip_domain(domain, NULL, 0)) {
-			transmit_response(p, "404 Not found (unknown domain)", &p->initreq);
+			if (sip_cfg.alwaysauthreject) {
+				transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE);
+			} else {
+				transmit_response(p, "404 Not found (unknown domain)", &p->initreq);
+			}
 			return AUTH_UNKNOWN_DOMAIN;
 		}
 	}
@@ -15063,7 +15096,7 @@
  */
 static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id)
 {
-	char tmp[256] = "", *uri, *domain, *dummy = NULL;
+	char tmp[256] = "", *uri, *unused_password, *domain;
 	char tmpf[256] = "", *from = NULL;
 	struct sip_request *req;
 	char *decoded_uri;
@@ -15079,7 +15112,7 @@
 	
 	uri = ast_strdupa(get_in_brackets(tmp));
 
-	if (parse_uri_legacy_check(uri, "sip:,sips:", &uri, &dummy, &domain, NULL)) {
+	if (parse_uri_legacy_check(uri, "sip:,sips:", &uri, &unused_password, &domain, NULL)) {
 		ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri);
 		return SIP_GET_DEST_INVALID_URI;
 	}
@@ -15854,10 +15887,7 @@
 					      int sipmethod, const char *uri, enum xmittype reliable,
 					      struct ast_sockaddr *addr, struct sip_peer **authpeer)
 {
-	char from[256] = { 0, };
-	char *dummy = NULL;	/* dummy return value for parse_uri */
-	char *domain = NULL;	/* dummy return value for parse_uri */
-	char *of;
+	char from[256] = "", *of, *name, *unused_password, *domain;
 	enum check_auth_result res = AUTH_DONT_KNOW;
 	char calleridname[50];
 	char *uri2 = ast_strdupa(uri);
@@ -15874,8 +15904,9 @@
 		return res;
 	}
 
-	if (calleridname[0])
+	if (calleridname[0]) {
 		ast_string_field_set(p, cid_name, calleridname);
+	}
 
 	if (ast_strlen_zero(p->exten)) {
 		char *t = uri2;
@@ -15897,32 +15928,36 @@
 	/* save the URI part of the From header */
 	ast_string_field_set(p, from, of);
 
-	/* ignore all fields but name */
-	if (parse_uri_legacy_check(of, "sip:,sips:", &of, &dummy, &domain, NULL)) {
+	if (parse_uri_legacy_check(of, "sip:,sips:", &name, &unused_password, &domain, NULL)) {
 		ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
 	}
 
-	SIP_PEDANTIC_DECODE(of);
+	SIP_PEDANTIC_DECODE(name);
 	SIP_PEDANTIC_DECODE(domain);
 
-	if (ast_strlen_zero(of)) {
-		/* XXX note: the original code considered a missing @host
-		 * as a username-only URI. The SIP RFC (19.1.1) says that
-		 * this is wrong, and it should be considered as a domain-only URI.
-		 * For backward compatibility, we keep this block, but it is
-		 * really a mistake and should go away.
-		 */
-
-		extract_host_from_hostport(&domain);
-		of = domain;
+	extract_host_from_hostport(&domain);
+
+	if (ast_strlen_zero(domain)) {
+		/* <sip:name@[EMPTY]>, never good */
+		ast_log(LOG_ERROR, "Empty domain name in FROM header\n");
+		return res;
+	}
+
+	if (ast_strlen_zero(name)) {
+		/* <sip:[EMPTY][@]hostport>. Asterisk 1.4 and 1.6 have always
+		 * treated that as a username, so we continue the tradition:
+		 * uri is now <sip:host at hostport>. */
+		name = domain;
 	} else {
-		char *tmp = ast_strdupa(of);
-		/* We need to be able to handle auth-headers looking like
+		/* Non-empty name, try to get caller id from it */
+		char *tmp = ast_strdupa(name);
+		/* We need to be able to handle from-headers looking like
 			<sip:8164444422;phone-context=+1 at 1.2.3.4:5060;user=phone;tag=SDadkoa01-gK0c3bdb43>
 		*/
 		tmp = strsep(&tmp, ";");
-		if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp))
+		if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) {
 			ast_shrink_phone_number(tmp);
+		}
 		ast_string_field_set(p, cid_num, tmp);
 	}
 
@@ -15936,20 +15971,22 @@
 		 * pick one or another depending on the request ? XXX
 		 */
 		const char *hdr = get_header(req, "Authorization");
-		if (ast_strlen_zero(hdr))
+		if (ast_strlen_zero(hdr)) {
 			hdr = get_header(req, "Proxy-Authorization");
-
-		if ( !ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\"")) ) {
+		}
+
+		if (!ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\""))) {
 			ast_copy_string(from, hdr + strlen("username=\""), sizeof(from));
-			of = from;
-			of = strsep(&of, "\"");
-		}
-	}
-
-	res = check_peer_ok(p, of, req, sipmethod, addr,
+			name = from;
+			name = strsep(&name, "\"");
+		}
+	}
+
+	res = check_peer_ok(p, name, req, sipmethod, addr,
 			authpeer, reliable, calleridname, uri2);
-	if (res != AUTH_DONT_KNOW)
+	if (res != AUTH_DONT_KNOW) {
 		return res;
+	}
 
 	/* Finally, apply the guest policy */
 	if (sip_cfg.allowguest) {
@@ -15962,11 +15999,11 @@
 		} else {
 			res = AUTH_RTP_FAILED;
 		}
-	} else if (sip_cfg.alwaysauthreject)
+	} else if (sip_cfg.alwaysauthreject) {
 		res = AUTH_FAKE_AUTH; /* reject with fake authorization request */
-	else
+	} else {
 		res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */
-
+	}
 
 	if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT)) {
 		ast_set_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT);
@@ -18510,16 +18547,22 @@
 			return;
 		}
 
-		if (buf[0] == '*')
+		if ('0' <= buf[0] && buf[0] <= '9') {
+			event = buf[0] - '0';
+		} else if (buf[0] == '*') {
 			event = 10;
-		else if (buf[0] == '#')
+		} else if (buf[0] == '#') {
 			event = 11;
-		else if ((buf[0] >= 'A') && (buf[0] <= 'D'))
+		} else if ('A' <= buf[0] && buf[0] <= 'D') {
 			event = 12 + buf[0] - 'A';
-		else if (buf[0] == '!')
+		} else if ('a' <= buf[0] && buf[0] <= 'd') {
+			event = 12 + buf[0] - 'a';
+		} else if (buf[0] == '!') {
 			event = 16;
-		else
-			event = atoi(buf);
+		} else {
+			/* Unknown digit */
+			event = 0;
+		}
 		if (event == 16) {
 			/* send a FLASH event */
 			struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH, } };
@@ -18580,6 +18623,9 @@
 				f.subclass.integer = '#';
 			} else if (event < 16) {
 				f.subclass.integer = 'A' + (event - 12);
+			} else {
+				/* Unknown digit. */
+				f.subclass.integer = '0';
 			}
 			f.len = duration;
 			ast_queue_frame(p->owner, &f);
@@ -18614,11 +18660,18 @@
 			per device. I don't want incoming callers to record calls in my
 			pbx.
 		*/
-		/* first, get the feature string, if it exists */
+		
 		struct ast_call_feature *feat;
 		int j;
 		struct ast_frame f = { AST_FRAME_DTMF, };
 
+		if (!p->owner) {        /* not a PBX call */
+			transmit_response(p, "481 Call leg/transaction does not exist", req);
+			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+			return;
+		}
+
+		/* first, get the feature string, if it exists */
 		ast_rdlock_call_features();
 		feat = ast_find_call_feature("automon");
 		if (!feat || ast_strlen_zero(feat->exten)) {
@@ -24206,11 +24259,21 @@
 	return handler_result;
 }
 
+/*! \internal \brief Subscribe to MWI events for the specified peer
+ * \note The peer cannot be locked during this method.  sip_send_mwi_peer will
+ * attempt to lock the peer after the event subscription lock is held; if the peer is locked during
+ * this method then we will attempt to lock the event subscription lock but after the peer, creating
+ * a locking inversion.
+ */
 static void add_peer_mwi_subs(struct sip_peer *peer)
 {
 	struct sip_mailbox *mailbox;
 
 	AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) {
+		if (mailbox->event_sub) {
+			ast_event_unsubscribe(mailbox->event_sub);
+		}
+
 		mailbox->event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "SIP mbox event", peer,
 			AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox,
 			AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"),
@@ -24364,7 +24427,7 @@
 		/* if an authentication response was sent, we are done here */
 		if (res == AUTH_CHALLENGE_SENT)	/* authpeer = NULL here */
 			return 0;
-		if (res < 0) {
+		if (res != AUTH_SUCCESSFUL) {
 			if (res == AUTH_FAKE_AUTH) {
 				ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From"));
 				transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE);
@@ -24378,17 +24441,17 @@
 		}
 	}
 
-	/* At this point, authpeer cannot be NULL. Remember we hold a reference,
-	 * so we must release it when done.
-	 * XXX must remove all the checks for authpeer == NULL.
+	/* At this point, we hold a reference to authpeer (if not NULL).  It
+	 * must be released when done.
 	 */
 
 	/* Check if this device  is allowed to subscribe at all */
 	if (!ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) {
 		transmit_response(p, "403 Forbidden (policy)", req);
 		pvt_set_needdestroy(p, "subscription not allowed");
-		if (authpeer)
+		if (authpeer) {
 			unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 1)");
+		}
 		return 0;
 	}
 
@@ -24408,8 +24471,9 @@
 			transmit_response(p, "404 Not Found", req);
 		}
 		pvt_set_needdestroy(p, "subscription target not found");
-		if (authpeer)
+		if (authpeer) {
 			unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)");
+		}
 		return 0;
 	}
 
@@ -24423,9 +24487,6 @@
 		int start = 0;
 		enum subscriptiontype subscribed = NONE;
 		const char *unknown_acceptheader = NULL;
-
-		if (authpeer)	/* We do not need the authpeer any more */
-			authpeer = unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)");
 
 		/* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */
 		accept = __get_header(req, "Accept", &start);
@@ -24464,6 +24525,9 @@
 					p->subscribecontext,
 					p->subscribeuri);
 				pvt_set_needdestroy(p, "no Accept header");
+				if (authpeer) {
+					unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)");
+				}
 				return 0;
 			}
 			/* if p->subscribed is non-zero, then accept is not obligatory; according to rfc 3265 section 3.1.3, at least.
@@ -24488,6 +24552,9 @@
 				p->subscribecontext,
 				p->subscribeuri);
 			pvt_set_needdestroy(p, "unrecognized format");
+			if (authpeer) {
+				unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)");
+			}
 			return 0;
 		} else {
 			p->subscribed = subscribed;
@@ -24510,8 +24577,9 @@
 			transmit_response(p, "406 Not Acceptable", req);
 			ast_debug(2, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader);
 			pvt_set_needdestroy(p, "unknown format");
-			if (authpeer)
+			if (authpeer) {
 				unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 3)");
+			}
 			return 0;
 		}
 		/* Looks like they actually want a mailbox status
@@ -24520,11 +24588,16 @@
 		  In most devices, this is configurable to the voicemailmain extension you use
 		*/
 		if (!authpeer || AST_LIST_EMPTY(&authpeer->mailboxes)) {
-			transmit_response(p, "404 Not found (no mailbox)", req);
+			if (!authpeer) {
+				transmit_response(p, "404 Not found", req);
+			} else {
+				transmit_response(p, "404 Not found (no mailbox)", req);
+				ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", S_OR(authpeer->name, ""));
+			}
 			pvt_set_needdestroy(p, "received 404 response");
-			ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", S_OR(authpeer->name, ""));
-			if (authpeer)
-				unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 4)");
+			if (authpeer) {
+				unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 3)");
+			}
 			return 0;
 		}
 
@@ -24534,18 +24607,20 @@
 			add_peer_mwi_subs(authpeer);
 			ao2_lock(p);
 		}
-		if (authpeer->mwipvt && authpeer->mwipvt != p) {	/* Destroy old PVT if this is a new one */
+		if (authpeer->mwipvt != p) {	/* Destroy old PVT if this is a new one */
 			/* We only allow one subscription per peer */
-			dialog_unlink_all(authpeer->mwipvt);
-			authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt");
-			/* sip_destroy(authpeer->mwipvt); */
-		}
-		if (authpeer->mwipvt)
-			dialog_unref(authpeer->mwipvt, "Unref previously stored mwipvt dialog pointer");
-		authpeer->mwipvt = dialog_ref(p, "setting peers' mwipvt to p");		/* Link from peer to pvt UH- should this be dialog_ref()? */
-		if (p->relatedpeer)
-			unref_peer(p->relatedpeer, "Unref previously stored relatedpeer ptr");
-		p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer");	/* already refcounted...Link from pvt to peer UH- should this be dialog_ref()? */
+			if (authpeer->mwipvt) {
+				dialog_unlink_all(authpeer->mwipvt);
+				authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt");
+			}
+			authpeer->mwipvt = dialog_ref(p, "setting peers' mwipvt to p");
+		}
+		if (p->relatedpeer != authpeer) {
+			if (p->relatedpeer) {
+				unref_peer(p->relatedpeer, "Unref previously stored relatedpeer ptr");
+			}
+			p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer");
+		}
 		/* Do not release authpeer here */
 	} else if (!strcmp(event, "call-completion")) {
 		handle_cc_subscribe(p, req);
@@ -24553,14 +24628,10 @@
 		transmit_response(p, "489 Bad Event", req);
 		ast_debug(2, "Received SIP subscribe for unknown event package: %s\n", event);
 		pvt_set_needdestroy(p, "unknown event package");
-		if (authpeer)
+		if (authpeer) {
 			unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 5)");
+		}
 		return 0;
-	}
-
-	/* At this point, if we have an authpeer we should unref it. */
-	if (authpeer) {
-		authpeer = unref_peer(authpeer, "unref pointer into (*authpeer)");
 	}
 
 	/* Add subscription for extension state from the PBX core */
@@ -24587,6 +24658,9 @@
 				"with Expire header less that 'minexpire' limit. Received \"Expire: %d\" min is %d\n",
 				p->exten, p->context, p->expiry, min_expiry);
 			pvt_set_needdestroy(p, "Expires is less that the min expires allowed.");
+			if (authpeer) {
+				unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 6)");
+			}
 			return 0;
 		}
 
@@ -24621,6 +24695,9 @@
 				ast_log(LOG_NOTICE, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension.\n", p->exten, p->context, ast_sockaddr_stringify(&p->sa));
 				transmit_response(p, "404 Not found", req);
 				pvt_set_needdestroy(p, "no extension for SUBSCRIBE");
+				if (authpeer) {
+					unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 6)");
+				}
 				return 0;
 			}
 			ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
@@ -24635,6 +24712,10 @@
 		if (!p->expiry) {
 			pvt_set_needdestroy(p, "forcing expiration");
 		}
+	}
+
+	if (authpeer) {
+		unref_peer(authpeer, "unref pointer into (*authpeer)");
 	}
 	return 1;
 }
@@ -25329,7 +25410,7 @@
 */
 static int sip_send_mwi_to_peer(struct sip_peer *peer, int cache_only)
 {
-	/* Called with peerl lock, but releases it */
+	/* Called with peer lock, but releases it */
 	struct sip_pvt *p;
 	int newmsgs = 0, oldmsgs = 0;
 	const char *vmexten = NULL;
@@ -27033,12 +27114,14 @@
 
 					if (!strncasecmp(trans, "udp", 3)) {
 						peer->transports |= SIP_TRANSPORT_UDP;
-					} else if (!strncasecmp(trans, "tcp", 3)) {
+					} else if (sip_cfg.tcp_enabled && !strncasecmp(trans, "tcp", 3)) {
 						peer->transports |= SIP_TRANSPORT_TCP;
-					} else if (!strncasecmp(trans, "tls", 3)) {
+					} else if (default_tls_cfg.enabled && !strncasecmp(trans, "tls", 3)) {
 						peer->transports |= SIP_TRANSPORT_TLS;
+					} else if (!strncasecmp(trans, "tcp", 3) || !strncasecmp(trans, "tls", 3)) {
+						ast_log(LOG_WARNING, "'%.3s' is not a valid transport type when %.3senabled=no. If no other is specified, the defaults from general will be used.\n", trans, trans);
 					} else {
-						ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans);
+						ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, the defaults from general will be used.\n", trans);
 					}
 
 					if (!peer->default_outbound_transport) { /*!< The first transport listed should be default outbound */
@@ -28394,9 +28477,23 @@
 		ast_log(LOG_WARNING, "To disallow external domains, you need to configure local SIP domains.\n");
 		sip_cfg.allow_external_domains = 1;
 	}
-	/* If not configured, set default transports */
-	if (default_transports == 0) {
+	/* If not or badly configured, set default transports */
+	if (!sip_cfg.tcp_enabled && (default_transports & SIP_TRANSPORT_TCP)) {
+		ast_log(LOG_WARNING, "Cannot use 'tcp' transport with tcpenable=no. Removing from available transports.\n");
+		default_primary_transport &= ~SIP_TRANSPORT_TCP;
+		default_transports &= ~SIP_TRANSPORT_TCP;
+	}
+	if (!default_tls_cfg.enabled && (default_transports & SIP_TRANSPORT_TLS)) {
+		ast_log(LOG_WARNING, "Cannot use 'tls' transport with tlsenable=no. Removing from available transports.\n");
+		default_primary_transport &= ~SIP_TRANSPORT_TLS;
+		default_transports &= ~SIP_TRANSPORT_TLS;
+	}
+	if (!default_transports) {
+		ast_log(LOG_WARNING, "No valid transports available, falling back to 'udp'.\n");
 		default_transports = default_primary_transport = SIP_TRANSPORT_UDP;
+	} else if (!default_primary_transport) {
+		ast_log(LOG_WARNING, "No valid default transport. Selecting 'udp' as default.\n");
+		default_primary_transport = SIP_TRANSPORT_UDP;
 	}
 
 	/* Build list of authentication to various SIP realms, i.e. service providers */

Modified: team/irroot/t38gateway-1.8/channels/sig_analog.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/channels/sig_analog.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/channels/sig_analog.c (original)
+++ team/irroot/t38gateway-1.8/channels/sig_analog.c Mon Dec 12 10:29:28 2011
@@ -198,6 +198,15 @@
 		return p->calls->wait_event(p->chan_pvt);
 	}
 	return -1;
+}
+
+static int analog_have_progressdetect(struct analog_pvt *p)
+{
+	if (p->calls->have_progressdetect) {
+		return p->calls->have_progressdetect(p->chan_pvt);
+	}
+	/* Don't have progress detection. */
+	return 0;
 }
 
 enum analog_cid_start analog_str_to_cidstart(const char *value)
@@ -2741,7 +2750,9 @@
 					}
 				}
 				if (ast->_state == AST_STATE_DIALING) {
-					if (analog_check_confirmanswer(p) || (!p->dialednone
+					if (analog_have_progressdetect(p)) {
+						ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
+					} else if (analog_check_confirmanswer(p) || (!p->dialednone
 						&& ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1)
 							|| (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD)
 							|| (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF)

Modified: team/irroot/t38gateway-1.8/channels/sig_analog.h
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/channels/sig_analog.h?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/channels/sig_analog.h (original)
+++ team/irroot/t38gateway-1.8/channels/sig_analog.h Mon Dec 12 10:29:28 2011
@@ -235,6 +235,7 @@
 	void (* const set_new_owner)(void *pvt, struct ast_channel *new_owner);
 
 	const char *(* const get_orig_dialstring)(void *pvt);
+	int (* const have_progressdetect)(void *pvt);
 };
 
 

Modified: team/irroot/t38gateway-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/channels/sip/include/sip.h?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/channels/sip/include/sip.h (original)
+++ team/irroot/t38gateway-1.8/channels/sip/include/sip.h Mon Dec 12 10:29:28 2011
@@ -474,7 +474,7 @@
 	AUTH_PEER_NOT_DYNAMIC = -6,
 	AUTH_ACL_FAILED = -7,
 	AUTH_BAD_TRANSPORT = -8,
-	AUTH_RTP_FAILED = 9,
+	AUTH_RTP_FAILED = -9,
 };
 
 /*! \brief States for outbound registrations (with register= lines in sip.conf */

Modified: team/irroot/t38gateway-1.8/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/main/features.c?view=diff&rev=347949&r1=347948&r2=347949
==============================================================================
--- team/irroot/t38gateway-1.8/main/features.c (original)
+++ team/irroot/t38gateway-1.8/main/features.c Mon Dec 12 10:29:28 2011
@@ -4278,7 +4278,13 @@
 		int  save_prio;
 		int  found = 0;	/* set if we find at least one match */
 		int  spawn_error = 0;
-		
+
+		/*
+		 * Make sure that the channel is marked as hungup since we are
+		 * going to run the "h" exten on it.
+		 */

[... 524 lines stripped ...]



More information about the svn-commits mailing list