[asterisk-commits] branch oej/siptransfer r12547 - in /team/oej/siptransfer: ./ apps/ cdr/ chann...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sun Mar 12 09:57:01 MST 2006


Author: oej
Date: Sun Mar 12 10:56:47 2006
New Revision: 12547

URL: http://svn.digium.com/view/asterisk?rev=12547&view=rev
Log:
Resolve conflict

Modified:
    team/oej/siptransfer/   (props changed)
    team/oej/siptransfer/README
    team/oej/siptransfer/README.siptransfer
    team/oej/siptransfer/UPGRADE.txt
    team/oej/siptransfer/apps/app_queue.c
    team/oej/siptransfer/ast_expr2.fl
    team/oej/siptransfer/ast_expr2f.c
    team/oej/siptransfer/cdr/cdr_tds.c
    team/oej/siptransfer/channels/chan_iax2.c
    team/oej/siptransfer/channels/chan_misdn.c
    team/oej/siptransfer/channels/chan_sip.c
    team/oej/siptransfer/channels/misdn/chan_misdn_config.h
    team/oej/siptransfer/channels/misdn/isdn_lib.c
    team/oej/siptransfer/channels/misdn/isdn_lib.h
    team/oej/siptransfer/channels/misdn/isdn_msg_parser.c
    team/oej/siptransfer/channels/misdn_config.c
    team/oej/siptransfer/configs/cdr_tds.conf.sample
    team/oej/siptransfer/configs/misdn.conf.sample
    team/oej/siptransfer/doc/asterisk-mib.txt
    team/oej/siptransfer/doc/misdn.txt
    team/oej/siptransfer/include/asterisk/doxyref.h
    team/oej/siptransfer/include/asterisk/sched.h
    team/oej/siptransfer/sched.c

Propchange: team/oej/siptransfer/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Propchange: team/oej/siptransfer/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Sun Mar 12 10:56:47 2006
@@ -1,1 +1,1 @@
-/trunk:1-12449
+/trunk:1-12544

Modified: team/oej/siptransfer/README
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/README?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/README (original)
+++ team/oej/siptransfer/README Sun Mar 12 10:56:47 2006
@@ -51,13 +51,15 @@
 	* All Wildcard (tm) products from Digium (www.digium.com)
 	* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
 	* any full duplex sound card supported by ALSA or OSS
+	* any ISDN card supported by mISDN on Linux (BRI)
+	* The Xorcom AstriBank channel bank
         * VoiceTronix OpenLine products
 
 The are several drivers for ISDN BRI cards available from third party sources.
-Check the voip-info.org wiki for more information on chan_capi, chan_misdn and 
+Check the voip-info.org wiki for more information on chan_capi and 
 zaphfc.
 
-* UPGRADING FROM VERSION 1.0
+* UPGRADING FROM AN EARLIER VERSION
 
   If you are updating from a previous version of Asterisk, make sure you
 read the UPGRADE.txt file in the source directory. There are some files

Modified: team/oej/siptransfer/README.siptransfer
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/README.siptransfer?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/README.siptransfer (original)
+++ team/oej/siptransfer/README.siptransfer Sun Mar 12 10:56:47 2006
@@ -1,5 +1,8 @@
 This is the SIP transfer re-write that now support attended transfers on multiple servers.
 It significantly changes the way we handle incoming REFER transactions.
+
+Todo:
+- Resolve all the conflicts in the code properly
 
 Additional features
 - Improved transfer support (we can deny transfers now)

Modified: team/oej/siptransfer/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/UPGRADE.txt?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/UPGRADE.txt (original)
+++ team/oej/siptransfer/UPGRADE.txt Sun Mar 12 10:56:47 2006
@@ -59,7 +59,7 @@
 
 Installation:
 
-* On BSD systems, the installation directories have changed to more "FreeBSDish" directories. On startup, Asterisk will look for the main configuration in /usr7local/etc/asterisk/asterisk.conf
+* On BSD systems, the installation directories have changed to more "FreeBSDish" directories. On startup, Asterisk will look for the main configuration in /usr/local/etc/asterisk/asterisk.conf
 If you have an old installation, you might want to remove the binaries and move the configuration files to the new locations. The following directories are now default:
 	ASTLIBDIR	/usr/local/lib/asterisk
 	ASTVARLIBDIR	/usr/local/share/asterisk

Modified: team/oej/siptransfer/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/apps/app_queue.c?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/apps/app_queue.c (original)
+++ team/oej/siptransfer/apps/app_queue.c Sun Mar 12 10:56:47 2006
@@ -1624,6 +1624,14 @@
 static void record_abandoned(struct queue_ent *qe)
 {
 	ast_mutex_lock(&qe->parent->lock);
+	manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
+	              "Queue: %s\r\n"
+	              "Uniqueid: %s\r\n"
+	              "Position: %d\r\n"
+	              "OriginalPosition: %d\r\n"
+	              "HoldTime: %d\r\n",
+	              qe->parent->name, qe->chan->uniqueid, qe->pos, qe->opos, (int)(time(NULL) - qe->start));
+
 	qe->parent->callsabandoned++;
 	ast_mutex_unlock(&qe->parent->lock);
 }

Modified: team/oej/siptransfer/ast_expr2.fl
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/ast_expr2.fl?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/ast_expr2.fl (original)
+++ team/oej/siptransfer/ast_expr2.fl Sun Mar 12 10:56:47 2006
@@ -201,7 +201,7 @@
 			s, parseio->string,spacebuf2);
 #endif
 #ifndef STANDALONE
-	ast_log(LOG_WARNING,"If you have questions, please refer to doc/README.variables in the asterisk source.\n");
+	ast_log(LOG_WARNING,"If you have questions, please refer to doc/channelvariables.txt in the asterisk source.\n");
 #endif
 	return(0);
 }

Modified: team/oej/siptransfer/ast_expr2f.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/ast_expr2f.c?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/ast_expr2f.c (original)
+++ team/oej/siptransfer/ast_expr2f.c Sun Mar 12 10:56:47 2006
@@ -2981,7 +2981,7 @@
 			s, parseio->string,spacebuf2);
 #endif
 #ifndef STANDALONE
-	ast_log(LOG_WARNING,"If you have questions, please refer to doc/README.variables in the asterisk source.\n");
+	ast_log(LOG_WARNING,"If you have questions, please refer to doc/channelvariables.txt in the asterisk source.\n");
 #endif
 	return(0);
 }

Modified: team/oej/siptransfer/cdr/cdr_tds.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/cdr/cdr_tds.c?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/cdr/cdr_tds.c (original)
+++ team/oej/siptransfer/cdr/cdr_tds.c Sun Mar 12 10:56:47 2006
@@ -89,6 +89,7 @@
 static char *config = "cdr_tds.conf";
 
 static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL;
+static char *table = NULL;
 
 static int connected = 0;
 
@@ -135,7 +136,7 @@
 
 	sprintf(
 		sqlcmd,
-		"INSERT INTO cdr "
+		"INSERT INTO %s "
 		"("
 			"accountcode, "
 			"src, "
@@ -175,6 +176,7 @@
 			"'%s', "	/* amaflags */
 			"'%s'"		/* uniqueid */
 		")",
+		table,
 		accountcode,
 		src,
 		dst,
@@ -415,6 +417,7 @@
 	if (password) free(password);
 	if (charset) free(charset);
 	if (language) free(language);
+	if (table) free(table);
 
 	return 0;
 }
@@ -475,6 +478,13 @@
 	else
 		language = strdup("us_english");
 
+	ptr = ast_variable_retrieve(cfg,"global","table");
+	if (ptr == NULL) {
+		ast_log(LOG_DEBUG,"cdr_tds: table not specified.  Assuming cdr\n");
+		ptr = "cdr";
+	}
+	table = strdup(ptr);
+
 	ast_config_destroy(cfg);
 
 	mssql_connect();

Modified: team/oej/siptransfer/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/channels/chan_iax2.c?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/channels/chan_iax2.c (original)
+++ team/oej/siptransfer/channels/chan_iax2.c Sun Mar 12 10:56:47 2006
@@ -5759,8 +5759,6 @@
 	ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", p->name);
 	/* Reset the address */
 	memset(&p->addr, 0, sizeof(p->addr));
-	/* Reset expire notice */
-	p->expire = -1;
 	/* Reset expiry value */
 	p->expiry = min_reg_expire;
 	if (!ast_test_flag(p, IAX_TEMPONLY))
@@ -5778,6 +5776,9 @@
 
 static int expire_registry(void *data)
 {
+	struct iax2_peer *p = data;
+	/* Reset expire notice */
+	p->expire = -1;
 #ifdef SCHED_MULTITHREADED
 	if (schedule_action(__expire_registry, data))
 #endif		

Modified: team/oej/siptransfer/channels/chan_misdn.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/channels/chan_misdn.c?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/channels/chan_misdn.c (original)
+++ team/oej/siptransfer/channels/chan_misdn.c Sun Mar 12 10:56:47 2006
@@ -648,13 +648,14 @@
 {
 	struct ast_channel *ast=help->ast;
 	ast_cli(fd,
-		"* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
+		"* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
 
 		bc->pid, bc->port, bc->channel,
 		bc->nt?"NT":"TE",
 		help->orginator == ORG_AST?"*":"I",
 		ast?ast->exten:NULL,
 		ast?AST_CID_P(ast):NULL,
+		bc->rad,
 		ast?ast->context:NULL,
 		misdn_get_ch_state(help)
 		);
@@ -1340,26 +1341,47 @@
 			misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
 			switch (bc->onumplan) {
 			case NUMPLAN_INTERNATIONAL:
-				chan_misdn_log(2, port, " --> TON: International\n");
+				chan_misdn_log(2, port, " --> LTON: International\n");
 				break;
 			case NUMPLAN_NATIONAL:
-				chan_misdn_log(2, port, " --> TON: National\n");
+				chan_misdn_log(2, port, " --> LTON: National\n");
 				break;
 			case NUMPLAN_SUBSCRIBER:
-				chan_misdn_log(2, port, " --> TON: Subscriber\n");
+				chan_misdn_log(2, port, " --> LTON: Subscriber\n");
 				break;
 			case NUMPLAN_UNKNOWN:
-				chan_misdn_log(2, port, " --> TON: Unknown\n");
+				chan_misdn_log(2, port, " --> LTON: Unknown\n");
 				break;
 				/* Maybe we should cut off the prefix if present ? */
 			default:
 					chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
 					break;
 			}
-		}
-
-		
-				
+
+			misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
+
+			switch (bc->cpnnumplan) {
+			case NUMPLAN_INTERNATIONAL:
+				chan_misdn_log(2, port, " --> CTON: International\n");
+				break;
+			case NUMPLAN_NATIONAL:
+				chan_misdn_log(2, port, " --> CTON: National\n");
+				break;
+			case NUMPLAN_SUBSCRIBER:
+				chan_misdn_log(2, port, " --> CTON: Subscriber\n");
+				break;
+			case NUMPLAN_UNKNOWN:
+				chan_misdn_log(2, port, " --> CTON: Unknown\n");
+				break;
+				/* Maybe we should cut off the prefix if present ? */
+			default:
+					chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
+					break;
+			}
+
+		}
+
+		
 		
 	} else { /** ORIGINATOR MISDN **/
 		

Modified: team/oej/siptransfer/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/siptransfer/channels/chan_sip.c?rev=12547&r1=12546&r2=12547&view=diff
==============================================================================
--- team/oej/siptransfer/channels/chan_sip.c (original)
+++ team/oej/siptransfer/channels/chan_sip.c Sun Mar 12 10:56:47 2006
@@ -103,6 +103,7 @@
 #ifndef TRUE
 #define TRUE 1
 #endif
+
  
 #define VIDEO_CODEC_MASK	0x1fc0000 /*!< Video codecs from H.261 thru AST_FORMAT_MAX_VIDEO */
 #ifndef IPTOS_MINCOST
@@ -177,6 +178,13 @@
    submitting a patch. If these two lists do not match properly
    bad things will happen.
 */
+
+enum xmittype {
+	XMIT_CRITICAL = 2,		/*!< Transmit critical SIP message reliably, with re-transmits.
+							If it fails, it's critical and will cause a teardown of the session */
+	XMIT_RELIABLE = 1,		/*!< Transmit SIP message reliably, with re-transmits */
+	XMIT_UNRELIABLE = 0,		/*!< Transmit SIP message without bothering with re-transmits */
+};
 
 enum subscriptiontype { 
 	NONE = 0,
@@ -977,11 +985,11 @@
 
 /*---------------------------- Forward declarations of functions in chan_sip.c */
 static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
-static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
+static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, enum xmittype reliable);
 static int transmit_response_with_unsupported(struct sip_pvt *p, char *msg, struct sip_request *req, char *unsupported);
-static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, struct sip_request *req, const char *rand, int reliable, const char *header, int stale);
-static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
-static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
+static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
+static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
+static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sendsdp, int init);
 static int transmit_reinvite_with_sdp(struct sip_pvt *p);
 static int transmit_info_with_digit(struct sip_pvt *p, char digit);
@@ -1015,7 +1023,7 @@
 static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, const char *realm);	/* Find authentication for a specific realm */
 static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *username,
 		const char *secret, const char *md5secret, int sipmethod,
-		char *uri, int reliable, int ignore);
+		char *uri, enum xmittype reliable, int ignore);
 static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */
 static void append_date(struct sip_request *req);	/* Append date to SIP packet */
 static int determine_firstline_parts(struct sip_request *req);
@@ -1029,7 +1037,7 @@
 static void parse_request(struct sip_request *req);
 static char *get_header(struct sip_request *req, const char *name);
 static void copy_request(struct sip_request *dst,struct sip_request *src);
-static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req, int fatal);
+static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req);
 static int transmit_register(struct sip_registry *r, int sipmethod, char *auth, char *authheader);
 static int sip_poke_peer(struct sip_peer *peer);
 static int __sip_do_register(struct sip_registry *r);
@@ -1466,7 +1474,9 @@
 	} 
 	/* Too many retries */
 	if (pkt->owner && pkt->method != SIP_OPTIONS) {
-		if (ast_test_flag(pkt, FLAG_FATAL) || sipdebug)	/* Tell us if it's critical or if we're debugging */ ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s)\n", pkt->owner->callid, pkt->seqno, (ast_test_flag(pkt, FLAG_FATAL)) ? "Critical" : "Non-critical", (ast_test_flag(pkt, FLAG_RESPONSE)) ? "Response" : "Request"); } else {
+		if (ast_test_flag(pkt, FLAG_FATAL) || sipdebug)	/* Tell us if it's critical or if we're debugging */
+			ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s)\n", pkt->owner->callid, pkt->seqno, (ast_test_flag(pkt, FLAG_FATAL)) ? "Critical" : "Non-critical", (ast_test_flag(pkt, FLAG_RESPONSE)) ? "Response" : "Request");
+	} else {
 		if ((pkt->method == SIP_OPTIONS) && sipdebug)
 			ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) \n", pkt->owner->callid);
 	}
@@ -1536,6 +1546,7 @@
 	pkt->timer_t1 = p->timer_t1;	/* Set SIP timer T1 */
 	if (fatal)
 		ast_set_flag(pkt, FLAG_FATAL);
+
 	if (pkt->timer_t1)
 		siptimer_a = pkt->timer_t1 * 2;
 
@@ -1721,7 +1732,7 @@
 }
 
 /*! \brief Transmit response on SIP request*/
-static int send_response(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno)
+static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno)
 {
 	int res;
 
@@ -1738,7 +1749,7 @@
 		append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s", tmp.data, get_header(&tmp, "CSeq"));
 	}
 	res = (reliable) ?
-		__sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable > 1), req->method) :
+		__sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) :
 		__sip_xmit(p, req->data, req->len);
 	if (res > 0)
 		return 0;
@@ -1746,7 +1757,7 @@
 }
 
 /*! \brief Send SIP Request to the other part of the dialogue */
-static int send_request(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno)
+static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno)
 {
 	int res;
 
@@ -2816,13 +2827,16 @@
 	if (!ast_test_flag(p, SIP_ALREADYGONE) && !ast_strlen_zero(p->initreq.data)) {
 		if (needcancel) {	/* Outgoing call, not up */
 			if (ast_test_flag(p, SIP_OUTGOING)) {
-				transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0);
+				/* stop retransmitting an INVITE that has not received a response */
+				__sip_pretend_ack(p);
+
+				/* Send a new request: CANCEL */
+				transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, XMIT_RELIABLE, 0);
 				/* Actually don't destroy us yet, wait for the 487 on our original 
 				   INVITE, but do set an autodestruct just in case we never get it. */
 				ast_clear_flag(&locflags, SIP_NEEDDESTROY);
-				sip_scheddestroy(p, 15000);
-				/* stop retransmitting an INVITE that has not received a response */
-				__sip_pretend_ack(p);
+
+				sip_scheddestroy(p, 32000);
 				if ( p->initid != -1 ) {
 					/* channel still up - reverse dec of inUse counter
 					   only if the channel is not auto-congested */
@@ -2831,14 +2845,14 @@
 			} else {	/* Incoming call, not up */
 				char *res;
 				if (ast->hangupcause && ((res = hangup_cause2sip(ast->hangupcause)))) {
-					transmit_response_reliable(p, res, &p->initreq, 1);
+					transmit_response_reliable(p, res, &p->initreq);
 				} else 
-					transmit_response_reliable(p, "603 Declined", &p->initreq, 1);
+					transmit_response_reliable(p, "603 Declined", &p->initreq);
 			}
 		} else {	/* Call is in UP state, send BYE */
 			if (!p->pendinginvite) {
 				/* Send a hangup */
-				transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
+				transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
 			} else {
 				/* Note we will need a BYE when this all settles out
 				   but we can't send one while we have "INVITE" outstanding. */
@@ -2853,12 +2867,34 @@
 	return 0;
 }
 
+/*! \brief Try setting codec suggested by the SIP_CODEC channel variable */
+static void try_suggested_sip_codec(struct sip_pvt *p)
+{
+	int fmt;
+	const char *codec;
+
+	codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC");
+	if (!codec) 
+		return;
+
+	fmt = ast_getformatbyname(codec);
+	if (fmt) {
+		ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC) variable\n", codec);
+		if (p->jointcapability & fmt) {
+			p->jointcapability &= fmt;
+			p->capability &= fmt;
+		} else
+			ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because it is not shared by both ends.\n");
+	} else
+		ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because of unrecognized/not configured codec (check allow/disallow in sip.conf): %s\n", codec);
+	return;	
+}
+
 /*! \brief  sip_answer: Answer SIP call , send 200 OK on Invite 
  * Part of PBX interface */
 static int sip_answer(struct ast_channel *ast)
 {
-	int res = 0,fmt;
-	const char *codec;
+	int res = 0;
 	struct sip_pvt *p = ast->tech_pvt;
 
 	ast_mutex_lock(&p->lock);
@@ -2866,24 +2902,12 @@
 #ifdef OSP_SUPPORT	
 		time(&p->ospstart);
 #endif
-	
-		codec=pbx_builtin_getvar_helper(p->owner,"SIP_CODEC");
-		if (codec) {
-			fmt=ast_getformatbyname(codec);
-			if (fmt) {
-				ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC) variable\n",codec);
-				if (p->jointcapability & fmt) {
-					p->jointcapability &= fmt;
-					p->capability &= fmt;
-				} else
-					ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because it is not shared by both ends.\n");
-			} else ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because of unrecognized/not configured codec (check allow/disallow in sip.conf): %s\n",codec);
-		}
+		try_suggested_sip_codec(p);	
 
 		ast_setstate(ast, AST_STATE_UP);
 		if (option_debug)
 			ast_log(LOG_DEBUG, "SIP answering channel: %s\n", ast->name);
-		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, 1);
+		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_RELIABLE);
 	}
 	ast_mutex_unlock(&p->lock);
 	return res;
@@ -2907,7 +2931,7 @@
 			if (p->rtp) {
 				/* If channel is not up, activate early media session */
 				if ((ast->_state != AST_STATE_UP) && !ast_test_flag(p, SIP_PROGRESS_SENT) && !ast_test_flag(p, SIP_OUTGOING)) {
-					transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
+					transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE);
 					ast_set_flag(p, SIP_PROGRESS_SENT);	
 				}
 				time(&p->lastrtptx);
@@ -2922,7 +2946,7 @@
 			if (p->vrtp) {
 				/* Activate video early media */
 				if ((ast->_state != AST_STATE_UP) && !ast_test_flag(p, SIP_PROGRESS_SENT) && !ast_test_flag(p, SIP_OUTGOING)) {
-					transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
+					transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE);
 					ast_set_flag(p, SIP_PROGRESS_SENT);	
 				}
 				time(&p->lastrtptx);
@@ -3065,7 +3089,7 @@
 		break;
 	case AST_CONTROL_PROGRESS:
 		if ((ast->_state != AST_STATE_UP) && !ast_test_flag(p, SIP_PROGRESS_SENT) && !ast_test_flag(p, SIP_OUTGOING)) {
-			transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
+			transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE);
 			ast_set_flag(p, SIP_PROGRESS_SENT);	
 			break;
 		}
@@ -4553,7 +4577,7 @@
 }
 
 /*! \brief Base transmit response function */
-static int __transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req, int reliable)
+static int __transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req, enum xmittype reliable)
 {
 	struct sip_request resp;
 	int seqno = 0;
@@ -4579,7 +4603,7 @@
 /*! \brief Transmit response, no retransmits */
 static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req) 
 {
-	return __transmit_response(p, msg, req, 0);
+	return __transmit_response(p, msg, req, XMIT_UNRELIABLE);
 }
 
 /*! \brief Transmit response, no retransmits */
@@ -4589,13 +4613,15 @@
 	respprep(&resp, p, msg, req);
 	append_date(&resp);
 	add_header(&resp, "Unsupported", unsupported);
-	return send_response(p, &resp, 0, 0);
-}
-
-/*! \brief Transmit response, Make sure you get a reply */
-static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req, int fatal)
-{
-	return __transmit_response(p, msg, req, fatal ? 2 : 1);
+	return send_response(p, &resp, XMIT_UNRELIABLE, 0);
+}
+
+/*! \brief Transmit response, Make sure you get an ACK
+	This is only used for responses to INVITEs, where we need to make sure we get an ACK
+*/
+static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req)
+{
+	return __transmit_response(p, msg, req, XMIT_CRITICAL);
 }
 
 /*! \brief Append date to SIP message */
@@ -4619,11 +4645,11 @@
 	append_date(&resp);
 	add_header_contentLength(&resp, 0);
 	add_blank_header(&resp);
-	return send_response(p, &resp, 0, 0);
+	return send_response(p, &resp, XMIT_UNRELIABLE, 0);
 }
 
 /*! \brief Append Accept header, content length before transmitting response */
-static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip_request *req, int reliable)
+static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip_request *req, enum xmittype reliable)
 {
 	struct sip_request resp;
 	respprep(&resp, p, msg, req);
@@ -4634,7 +4660,7 @@
 }
 
 /*! \brief Respond with authorization request */
-static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, struct sip_request *req, const char *randdata, int reliable, const char *header, int stale)
+static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, struct sip_request *req, const char *randdata, enum xmittype reliable, const char *header, int stale)
 {
 	struct sip_request resp;
 	char tmp[256];
@@ -4945,7 +4971,7 @@
 }
 
 /*! \brief Used for 200 OK and 183 early media */
-static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans)
+static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, enum xmittype reliable)
 {
 	struct sip_request resp;
 	int seqno;
@@ -4955,11 +4981,12 @@
 	}
 	respprep(&resp, p, msg, req);
 	if (p->rtp) {
+		try_suggested_sip_codec(p);	
 		add_sdp(&resp, p);
 	} else {
 		ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid);
 	}
-	return send_response(p, &resp, retrans, seqno);
+	return send_response(p, &resp, reliable, seqno);
 }
 
 /*! \brief Parse first line of incoming SIP request */
@@ -6042,7 +6069,7 @@
 }
 
 /*! \brief Transmit generic SIP request */
-static int transmit_request(struct sip_pvt *p, int sipmethod, int seqno, int reliable, int newbranch)
+static int transmit_request(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
 {
 	struct sip_request resp;
 	reqprep(&resp, p, sipmethod, seqno, newbranch);
@@ -6052,7 +6079,7 @@
 }
 
 /*! \brief Transmit SIP request, auth added */
-static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, int reliable, int newbranch)
+static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
 {
 	struct sip_request resp;
 
@@ -6571,7 +6598,7 @@
 */
 static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *username,
 		      const char *secret, const char *md5secret, int sipmethod,
-		      char *uri, int reliable, int ignore)
+		      char *uri, enum xmittype reliable, int ignore)
 {
 	const char *response = "407 Proxy Authentication Required";
 	const char *reqheader = "Proxy-Authorization";
@@ -6855,7 +6882,7 @@
 		} else {
 			ast_copy_flags(p, peer, SIP_NAT);
 			transmit_response(p, "100 Trying", req);
-			if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
+			if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, XMIT_UNRELIABLE, ignore))) {
 				sip_cancel_destroy(p);
 				switch (parse_register_contact(p, peer, req)) {
 				case PARSE_REGISTER_FAILED:
@@ -7480,7 +7507,7 @@
 	\return 0 on success, -1 on failure, and 1 on challenge sent
 	-2 on authentication error from chedck_auth()
 */
-static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore, char *mailbox, int mailboxlen)
+static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, int ignore, char *mailbox, int mailboxlen)
 {
 	struct sip_user *user = NULL;
 	struct sip_peer *peer;
@@ -7773,7 +7800,7 @@
 /*! \brief  Find user 
 	If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced
 */
-static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore)
+static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, int ignore)
 {
 	return check_user_full(p, req, sipmethod, uri, reliable, sin, ignore, NULL, 0);
 }
@@ -9956,6 +9983,8 @@
 {
 	char tmp[256];
 	char *s, *e;
+	char *domain;
+
 	ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
 	s = get_in_brackets(tmp);
 	e = strchr(s, ';');
@@ -9972,16 +10001,25 @@
 			ast_string_field_build(p->owner, call_forward, "SIP/%s", s);
 	} else {
 		e = strchr(tmp, '@');
-		if (e)
+		if (e) {
 			*e = '\0';
+			e++;
+			domain = e;
+		} else {
+			/* No username part */
+			domain = tmp;
+		}
 		e = strchr(tmp, '/');
 		if (e)
 			*e = '\0';
 		if (!strncasecmp(s, "sip:", 4))
 			s += 4;
-		ast_log(LOG_DEBUG, "Found 302 Redirect to extension '%s'\n", s);
-		if (p->owner)
+		if (option_debug > 1)
+			ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
+		if (p->owner) {
+			pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
 			ast_string_field_set(p->owner, call_forward, s);
+		}
 	}
 }
 
@@ -9990,7 +10028,7 @@
 {
 	/* Go ahead and send bye at this point */
 	if (ast_test_flag(p, SIP_PENDINGBYE)) {
-		transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
+		transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
 		ast_set_flag(p, SIP_NEEDDESTROY);	
 		ast_clear_flag(p, SIP_NEEDREINVITE);	
 	} else if (ast_test_flag(p, SIP_NEEDREINVITE)) {
@@ -10040,12 +10078,13 @@
 		break;
 	case 183:	/* Session progress */
 		sip_cancel_destroy(p);
+		/* Ignore 183 Session progress without SDP */
 		if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
 			process_sdp(p, req);
-		}
-		if (!ignore && p->owner) {
-			/* Queue a progress frame */
-			ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
+			if (!ignore && p->owner) {
+				/* Queue a progress frame */
+				ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
+			}
 		}
 		break;
 	case 200:	/* 200 OK on invite - someone's answering our call */
@@ -10082,13 +10121,13 @@
 				ast_set_flag(p, SIP_PENDINGBYE);	
 		}
 		/* If I understand this right, the branch is different for a non-200 ACK only */
-		transmit_request(p, SIP_ACK, seqno, 0, 1);
+		transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 1);
 		check_pendings(p);
 		break;
 	case 407: /* Proxy authentication */
 	case 401: /* Www auth */
 		/* First we ACK */
-		transmit_request(p, SIP_ACK, seqno, 0, 0);
+		transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		if (p->options)
 			p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH);
 
@@ -10108,7 +10147,7 @@
 		break;
 	case 403: /* Forbidden */
 		/* First we ACK */
-		transmit_request(p, SIP_ACK, seqno, 0, 0);
+		transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for INVITE to '%s'\n", get_header(&p->initreq, "From"));
 		if (!ignore && p->owner)
 			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
@@ -10116,7 +10155,7 @@
 		ast_set_flag(p, SIP_ALREADYGONE);	
 		break;
 	case 404: /* Not found */
-		transmit_request(p, SIP_ACK, seqno, 0, 0);
+		transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		if (p->owner && !ignore)
 			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
 		ast_set_flag(p, SIP_ALREADYGONE);	
@@ -10124,7 +10163,7 @@
 	case 481: /* Call leg does not exist */
 		/* Could be REFER or INVITE */
 		ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid);
-		transmit_request(p, SIP_ACK, seqno, 0, 0);
+		transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		break;
 	case 491: /* Pending */
 		/* we have to wait a while, then retransmit */
@@ -10355,7 +10394,7 @@
 		if (peer->pokeexpire > -1)
 			ast_sched_del(sched, peer->pokeexpire);
 		if (sipmethod == SIP_INVITE)	/* Does this really happen? */
-			transmit_request(p, SIP_ACK, seqno, 0, 0);
+			transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		ast_set_flag(p, SIP_NEEDDESTROY);	
 
 		/* Try again eventually */
@@ -10546,6 +10585,7 @@
 			break;
 		default:
 			if ((resp >= 300) && (resp < 700)) {
+				/* Fatal response */
 				if ((option_verbose > 2) && (resp != 487))
 					ast_verbose(VERBOSE_PREFIX_3 "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr));
 				ast_set_flag(p, SIP_ALREADYGONE);	
@@ -10571,7 +10611,7 @@
 					if (p->owner)
 						ast_queue_control(p->owner, AST_CONTROL_BUSY);
 					break;
-				case 487:
+				case 487:	/* Response on INVITE that has been CANCELled */
 					/* channel now destroyed - dec the inUse counter */
 					update_call_counter(p, DEC_CALL_LIMIT);
 					break;
@@ -10602,7 +10642,7 @@
 				}
 				/* ACK on invite */
 				if (sipmethod == SIP_INVITE) 
-					transmit_request(p, SIP_ACK, seqno, 0, 0);
+					transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 				ast_set_flag(p, SIP_ALREADYGONE);	
 				if (!p->owner)
 					ast_set_flag(p, SIP_NEEDDESTROY);	
@@ -11173,12 +11213,12 @@
 	if (!p->lastinvite && !ignore && !p->owner) {	/* This is a new INVITE */
 
 		/* Handle authentication if this is our first invite */
-		res = check_user(p, req, SIP_INVITE, e, 1, sin, ignore);
+		res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin, ignore);
 		if (res > 0)	/* We have challenged the user for auth */
 			return 0; 
 		if (res < 0) { /* Something failed in authentication */
 			ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
-			transmit_response_reliable(p, "403 Forbidden", req, 1);
+			transmit_response_reliable(p, "403 Forbidden", req);
 			ast_set_flag(p, SIP_NEEDDESTROY);
 			ast_string_field_free(p, theirtag);
 			return 0;
@@ -11187,7 +11227,7 @@
 		if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp") ) {
 			if (process_sdp(p, req)) {
 				/* Unacceptable codecs */
-				transmit_response_reliable(p, "488 Not acceptable here", req, 1);
+				transmit_response_reliable(p, "488 Not acceptable here", req);
 
 				ast_set_flag(p, SIP_NEEDDESTROY);	
 				if (option_debug > 1)
@@ -11218,7 +11258,7 @@
 		if (res) {
 			if (res < 0) {
 				ast_log(LOG_NOTICE, "Failed to place call for user %s, too many calls\n", p->username);
-				transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req, 1);
+				transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req);
 				ast_set_flag(p, SIP_NEEDDESTROY);	
 			}
 			return 0;
@@ -11230,10 +11270,10 @@
 
 		if (!replace_id && gotdest) {	/* No matching extension found */
 			if (gotdest < 0) {
-				transmit_response_reliable(p, "404 Not Found", req, 1);
+				transmit_response_reliable(p, "404 Not Found", req);
 				update_call_counter(p, DEC_CALL_LIMIT);
 			} else {
-				transmit_response_reliable(p, "484 Address Incomplete", req, 1);
+				transmit_response_reliable(p, "484 Address Incomplete", req);
 				update_call_counter(p, DEC_CALL_LIMIT);
 			}
 			ast_set_flag(p, SIP_NEEDDESTROY);		
@@ -11289,18 +11329,39 @@
 			transmit_response(p, "100 Trying", req);
 			ast_setstate(c, AST_STATE_RING);
 			if (strcmp(p->exten, ast_pickup_ext())) {	/* Call to extension -start pbx on this call */
-				if (ast_pbx_start(c)) {
+				enum ast_pbx_result res;
+
+				res = ast_pbx_start(c);
+
+				switch(res) {
+				case AST_PBX_FAILED:
 					ast_log(LOG_WARNING, "Failed to start PBX :(\n");
 					/* Unlock locks so ast_hangup can do its magic */
-					ast_channel_unlock(c);
-					ast_mutex_unlock(&p->lock);
-					c->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
-					ast_hangup(c);
-					ast_mutex_lock(&p->lock);
 					if (ignore)
 						transmit_response(p, "503 Unavailable", req);
 					else
-						transmit_response_reliable(p, "503 Unavailable", req, 1);
+						transmit_response_reliable(p, "503 Unavailable", req);
+					break;
+				case AST_PBX_CALL_LIMIT:
+					ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
+					if (ignore)
+						transmit_response(p, "480 Temporarily Unavailable", req);
+					else
+						transmit_response_reliable(p, "480 Temporarily Unavailable", req);
+					break;
+				case AST_PBX_SUCCESS:
+					/* nothing to do */
+					break;
+				}
+
+				if (res) {
+					ast_log(LOG_WARNING, "Failed to start PBX :(\n");
+
+					/* Unlock locks so ast_hangup can do its magic */
+					ast_mutex_unlock(&c->lock);
+					ast_mutex_unlock(&p->lock);
+					ast_hangup(c);
+					ast_mutex_lock(&p->lock);
 					c = NULL;
 				}
 			} else {	/* Pickup call in call group */
@@ -11310,7 +11371,7 @@
 					if (ignore)
 						transmit_response(p, "503 Unavailable", req);	/* OEJ - Right answer? */
 					else
-						transmit_response_reliable(p, "503 Unavailable", req, 1);
+						transmit_response_reliable(p, "503 Unavailable", req);
 					ast_set_flag(p, SIP_ALREADYGONE);	
 					/* Unlock locks so ast_hangup can do its magic */
 					ast_mutex_unlock(&p->lock);
@@ -11351,14 +11412,14 @@
 				if (ignore)
 					transmit_response(p, "488 Not Acceptable Here (codec error)", req);
 				else
-					transmit_response_reliable(p, "488 Not Acceptable Here (codec error)", req, 1);
+					transmit_response_reliable(p, "488 Not Acceptable Here (codec error)", req);
 				ast_set_flag(p, SIP_NEEDDESTROY);	
 			} else {
 				ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n");
 				if (ignore)
 					transmit_response(p, "503 Unavailable", req);
 				else
-					transmit_response_reliable(p, "503 Unavailable", req, 1);
+					transmit_response_reliable(p, "503 Unavailable", req);
 				ast_set_flag(p, SIP_NEEDDESTROY);	
 			}
 		}
@@ -12001,7 +12062,7 @@
 		ast_set_flag(p, SIP_NEEDDESTROY);	
 	if (p->initreq.len > 0) {
 		if (!ignore)
-			transmit_response_reliable(p, "487 Request Terminated", &p->initreq, 1);
+			transmit_response_reliable(p, "487 Request Terminated", &p->initreq);
 		transmit_response(p, "200 OK", req);
 		return 1;
 	} else {
@@ -12019,7 +12080,7 @@
 	char iabuf[INET_ADDRSTRLEN];
 	
 	if (p->pendinginvite && !ast_test_flag(p, SIP_OUTGOING) && !ignore)
-		transmit_response_reliable(p, "487 Request Terminated", &p->initreq, 1);
+		transmit_response_reliable(p, "487 Request Terminated", &p->initreq);
 
 	copy_request(&p->initreq, req);
 	check_via(p, req);
@@ -12120,7 +12181,7 @@
 			mailboxsize = sizeof(mailboxbuf);
 		}
 		/* Handle authentication if this is our first subscribe */
-		res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, mailbox, mailboxsize);
+		res = check_user_full(p, req, SIP_SUBSCRIBE, e, XMIT_UNRELIABLE, sin, ignore, mailbox, mailboxsize);
 		if (res) {
 			if (res < 0) {
 				ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
@@ -12411,7 +12472,7 @@
 		if (!p->initreq.headers && ast_test_flag(req, SIP_PKT_WITH_TOTAG)) {
 			/* If this is a first request and it got a to-tag, it is not for us */
 			if (!ignore && req->method == SIP_INVITE) {
-				transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req, 1);
+				transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req);
 				/* Will cease to exist after ACK */
 			} else {
 				transmit_response(p, "481 Call/Transaction Does Not Exist", req);
@@ -14308,7 +14369,7 @@
 	}
 
 	ast_string_field_build(p, our_contact, "Transfer <sip:%s@%s%s%s>", extension, host, port ? ":" : "", port ? port : "");

[... 554 lines stripped ...]


More information about the asterisk-commits mailing list