[svn-commits] branch oej/metermaids-trunk r22195 - /team/oej/metermaids-trunk/channels/

svn-commits at lists.digium.com svn-commits at lists.digium.com
Sun Apr 23 05:55:45 MST 2006


Author: oej
Date: Sun Apr 23 07:55:44 2006
New Revision: 22195

URL: http://svn.digium.com/view/asterisk?rev=22195&view=rev
Log:
Reset automerge

Modified:
    team/oej/metermaids-trunk/channels/chan_sip.c

Modified: team/oej/metermaids-trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/metermaids-trunk/channels/chan_sip.c?rev=22195&r1=22194&r2=22195&view=diff
==============================================================================
--- team/oej/metermaids-trunk/channels/chan_sip.c (original)
+++ team/oej/metermaids-trunk/channels/chan_sip.c Sun Apr 23 07:55:44 2006
@@ -32,6 +32,8 @@
  * \todo SIP over TCP
  * \todo SIP over TLS
  * \todo Better support of forking
+ * \todo VIA branch tag transaction checking
+ * \todo Transaction support
  *
  * \ingroup channel_drivers
  *
@@ -59,6 +61,8 @@
  * if it's a response to an outbound request, it's sent to handle_response().
  * If it is a request, handle_request sends it to one of a list of functions
  * depending on the request type - INVITE, OPTIONS, REFER, BYE, CANCEL etc
+ * sipsock_read locks the ast_channel if it exists (an active call) and
+ * unlocks it after we have processed the SIP message.
  *
  * A new INVITE is sent to handle_request_invite(), that will end up
  * starting a new channel in the PBX, the new channel after that executing
@@ -187,6 +191,9 @@
 
 #define DEFAULT_RETRANS		1000		/*!< How frequently to retransmit Default: 2 * 500 ms in RFC 3261 */
 #define MAX_RETRANS		6		/*!< Try only 6 times for retransmissions, a total of 7 transmissions */
+#define SIP_TRANS_TIMEOUT	32000		/*!< SIP request timeout (rfc 3261) 64*T1 
+						\todo Use known T1 for timeout (peerpoke)
+						*/
 #define MAX_AUTHTRIES		3		/*!< Try authentication three times, then fail */
 
 #define SIP_MAX_HEADERS		64			/*!< Max amount of SIP headers to read */
@@ -250,7 +257,7 @@
 	{ CPIM_PIDF_XML,   "presence", "application/cpim-pidf+xml",   "cpim-pidf+xml" },  /* RFC 3863 */
 	{ PIDF_XML,        "presence", "application/pidf+xml",        "pidf+xml" },       /* RFC 3863 */
 	{ XPIDF_XML,       "presence", "application/xpidf+xml",       "xpidf+xml" },       /* Pre-RFC 3863 with MS additions */
-	{ MWI_NOTIFICATION,	"message-summary", "application/simple-message-summary", "mwi" } /* Mailbox notification */
+	{ MWI_NOTIFICATION,	"message-summary", "application/simple-message-summary", "mwi" } /* RFC 3842: Mailbox notification */
 };
 
 enum sipmethod {
@@ -708,6 +715,24 @@
 	{ REFER_NOAUTH,		"Failed - auth failure" }
 } ;
 
+/*! \brief Structure to handle SIP transfers. Dynamically allocated when needed  */
+/* OEJ: Should be moved to string fields */
+struct sip_refer {
+	char refer_to[AST_MAX_EXTENSION];		/*!< Place to store REFER-TO extension */
+	char refer_to_domain[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO domain */
+	char refer_to_urioption[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO uri options */
+	char refer_to_context[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO context */
+	char referred_by[AST_MAX_EXTENSION];		/*!< Place to store REFERRED-BY extension */
+	char referred_by_name[AST_MAX_EXTENSION];	/*!< Place to store REFERRED-BY extension */
+	char refer_contact[AST_MAX_EXTENSION];		/*!< Place to store Contact info from a REFER extension */
+	char replaces_callid[BUFSIZ];			/*!< Replace info */
+	char replaces_callid_totag[BUFSIZ/2];		/*!< Replace info */
+	char replaces_callid_fromtag[BUFSIZ/2];		/*!< Replace info */
+	struct sip_pvt *refer_call;			/*!< Call we are referring */
+	int attendedtransfer;				/*!< Attended or blind transfer? */
+	int localtransfer;				/*!< Transfer to local domain? */
+	enum referstatus status;			/*!< REFER status */
+};
 
 /*! \brief sip_pvt: PVT structures are used for each SIP dialog, ie. a call, a registration, a subscribe  */
 static struct sip_pvt {
@@ -730,6 +755,7 @@
 		AST_STRING_FIELD(exten);	/*!< Extension where to start */
 		AST_STRING_FIELD(context);	/*!< Context for this call */
 		AST_STRING_FIELD(subscribecontext); /*!< Subscribecontext */
+		AST_STRING_FIELD(subscribeuri); /*!< Subscribecontext */
 		AST_STRING_FIELD(fromdomain);	/*!< Domain to show in the from field */
 		AST_STRING_FIELD(fromuser);	/*!< User to show in the user field */
 		AST_STRING_FIELD(fromname);	/*!< Name to show in the user field */
@@ -801,11 +827,12 @@
 	int rtpholdtimeout;			/*!< RTP timeout when on hold */
 	int rtpkeepalive;			/*!< Send RTP packets for keepalive */
 	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
-	enum subscriptiontype subscribed;	/*!< Is this dialog a subscription?  */
-	int stateid;
-	int laststate;				/*!< Last known extension state */
-	int dialogver;
+	enum subscriptiontype subscribed;	/*!< SUBSCRIBE: Is this dialog a subscription?  */
+	int stateid;				/*!< SUBSCRIBE: ID for devicestate subscriptions */
+	int laststate;				/*!< SUBSCRIBE: Last known extension state */
+	int dialogver;				/*!< SUBSCRIBE: Version for subscription dialog-info */
 	
+	struct sip_refer *refer;		/*!< REFER: SIP transfer data structure */
 	struct ast_dsp *vad;			/*!< Voice Activation Detection dsp */
 	
 	struct sip_peer *relatedpeer;		/*!< If this dialog is related to a peer, which one 
@@ -815,7 +842,7 @@
 	struct ast_rtp *vrtp;			/*!< Video RTP session */
 	struct sip_pkt *packets;		/*!< Packets scheduled for re-transmission */
 	struct sip_history_head *history;	/*!< History of this SIP dialog */
-	struct ast_variable *chanvars;		/*!< Channel variables to set for call */
+	struct ast_variable *chanvars;		/*!< Channel variables to set for inbound call */
 	struct sip_pvt *next;			/*!< Next dialog in chain */
 	struct sip_invite_param *options;	/*!< Options for INVITE */
 } *iflist = NULL;
@@ -823,9 +850,9 @@
 #define FLAG_RESPONSE (1 << 0)
 #define FLAG_FATAL (1 << 1)
 
-/*! \brief sip packet - read in sipsock_read(), transmitted in send_request() */
+/*! \brief sip packet - raw format for outbound packets that are sent or scheduled for transmission */
 struct sip_pkt {
-	struct sip_pkt *next;			/*!< Next packet */
+	struct sip_pkt *next;			/*!< Next packet in linked list */
 	int retrans;				/*!< Retransmission number */
 	int method;				/*!< SIP method for this packet */
 	int seqno;				/*!< Sequence number */
@@ -1079,6 +1106,11 @@
 static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
 static int handle_request_options(struct sip_pvt *p, struct sip_request *req);
 
+/*------Response handling functions */
+static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+static int handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req);
+
 /*----- RTP interface functions */
 static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active);
 static struct ast_rtp *sip_get_rtp_peer(struct ast_channel *chan);
@@ -1129,6 +1161,22 @@
 	return "";
 }
 
+/*! \brief Initialize the initital request packet in the pvt structure.
+ 	This packet is used for creating replies and future requests in
+	a dialog */
+void initialize_initreq(struct sip_pvt *p, struct sip_request *req)
+{
+	if (p->initreq.headers) {
+		ast_log(LOG_WARNING, "Initializing already initialized SIP dialog??? %s\n", p->callid);
+		return;
+	}
+	/* Use this as the basis */
+	copy_request(&p->initreq, req);
+	parse_request(&p->initreq);
+	if (ast_test_flag(req, SIP_PKT_DEBUG))
+		ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
+}
+
 
 /*! \brief returns true if 'name' (with optional trailing whitespace)
  * matches the sip method 'id'.
@@ -1339,11 +1387,11 @@
 /*! \brief Retransmit SIP message if no answer */
 static int retrans_pkt(void *data)
 {
-	struct sip_pkt *pkt=data, *prev, *cur = NULL;
+	struct sip_pkt *pkt = data, *prev, *cur = NULL;
 	char iabuf[INET_ADDRSTRLEN];
 	int reschedule = DEFAULT_RETRANS;
 
-	/* Lock channel */
+	/* Lock channel PVT */
 	ast_mutex_lock(&pkt->owner->lock);
 
 	if (pkt->retrans < MAX_RETRANS) {
@@ -1406,7 +1454,7 @@
 			ast_set_flag(&pkt->owner->flags[0], SIP_ALREADYGONE);
 			ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet.\n", pkt->owner->callid);
 			ast_queue_hangup(pkt->owner->owner);
-			ast_mutex_unlock(&pkt->owner->owner->lock);
+			ast_channel_unlock(pkt->owner->owner);
 		} else {
 			/* If no channel owner, destroy now */
 			ast_set_flag(&pkt->owner->flags[0], SIP_NEEDDESTROY);	
@@ -2153,17 +2201,15 @@
 	p->initid = -1;
 	if (p->owner) {
 		/* XXX fails on possible deadlock */
-		if (!ast_mutex_trylock(&p->owner->lock)) {
+		if (!ast_channel_trylock(p->owner)) {
 			ast_log(LOG_NOTICE, "Auto-congesting %s\n", p->owner->name);
 			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
-			ast_mutex_unlock(&p->owner->lock);
+			ast_channel_unlock(p->owner);
 		}
 	}
 	ast_mutex_unlock(&p->lock);
 	return 0;
 }
-
-
 
 
 /*! \brief Initiate SIP call from PBX 
@@ -2174,7 +2220,8 @@
 	struct sip_pvt *p;
 	struct varshead *headp;
 	struct ast_var_t *current;
-	
+	const char *referer = NULL;   /* SIP refererer */	
+
 	p = ast->tech_pvt;
 	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
 		ast_log(LOG_WARNING, "sip_call called on %s, neither down nor reserved\n", ast->name);
@@ -2195,13 +2242,36 @@
 		} else if (!p->options->addsipheaders && !strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) {
 			/* Check whether there is a variable with a name starting with SIPADDHEADER */
 			p->options->addsipheaders = 1;
+		} else if (!strcasecmp(ast_var_name(current),"SIPTRANSFER")) {
+			/* This is a transfered call */
+			p->options->transfer = 1;
+		} else if (!strcasecmp(ast_var_name(current),"SIPTRANSFER_REFERER")) {
+			/* This is the referer */
+			referer = ast_var_value(current);
+		} else if (!strcasecmp(ast_var_name(current),"SIPTRANSFER_REPLACES")) {
+			/* We're replacing a call. */
+			p->options->replaces = ast_var_value(current);
 		}
 	}
 	
 	res = 0;
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);
+
+	if (p->options->transfer) {
+		char buf[BUFSIZ/2];
+
+		if (referer) {
+			if (sipdebug && option_debug > 2)
+				ast_log(LOG_DEBUG, "Call for %s transfered by %s\n", p->username, referer);
+			snprintf(buf, sizeof(buf)-1, "-> %s (via %s)", p->cid_name, referer);
+		} else {
+			snprintf(buf, sizeof(buf)-1, "-> %s", p->cid_name);
+		}
+		ast_string_field_set(p, cid_name, buf);
+	} 
 	if (option_debug)
 		ast_log(LOG_DEBUG, "Outgoing Call for %s\n", p->username);
+
 	res = update_call_counter(p, INC_CALL_LIMIT);
 	if ( res != -1 ) {
 		p->callingpres = ast->cid.cid_pres;
@@ -2210,6 +2280,8 @@
 		if (p->maxtime) {
 			/* Initialize auto-congest time */
 			p->initid = ast_sched_add(sched, p->maxtime * 4, auto_congest, p);
+		} else {
+			p->initid = ast_sched_add(sched, SIP_TRANS_TIMEOUT, auto_congest, p);
 		}
 	}
 	return res;
@@ -2271,6 +2343,8 @@
 		ast_rtp_destroy(p->rtp);
 	if (p->vrtp)
 		ast_rtp_destroy(p->vrtp);
+	if (p->refer)
+		free(p->refer);
 	if (p->route) {
 		free_old_route(p->route);
 		p->route = NULL;
@@ -2284,12 +2358,12 @@
 	/* Unlink us from the owner if we have one */
 	if (p->owner) {
 		if (lockowner)
-			ast_mutex_lock(&p->owner->lock);
+			ast_channel_lock(p->owner);
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name);
 		p->owner->tech_pvt = NULL;
 		if (lockowner)
-			ast_mutex_unlock(&p->owner->lock);
+			ast_channel_unlock(p->owner);
 	}
 	/* Clear history */
 	if (p->history) {
@@ -2654,7 +2728,7 @@
 				   INVITE, but do set an autodestruct just in case we never get it. */
 				ast_clear_flag(&locflags, SIP_NEEDDESTROY);
 
-				sip_scheddestroy(p, 32000);
+				sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 				if ( p->initid != -1 ) {
 					/* channel still up - reverse dec of inUse counter
 					   only if the channel is not auto-congested */
@@ -2721,7 +2795,7 @@
 		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, XMIT_RELIABLE);
+		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
 	}
 	ast_mutex_unlock(&p->lock);
 	return res;
@@ -2798,11 +2872,12 @@
 	p = newchan->tech_pvt;
 
 	ast_mutex_lock(&p->lock);
+	append_history(p, "Masq", "Old channel: %s\n", oldchan->name);
+	append_history(p, "Masq (cont)", "...new owner: %s\n", p->owner->name);
 	if (p->owner != oldchan)
 		ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
 	else {
 		p->owner = newchan;
-		append_history(p, "Masq", "Old channel: %s\n", oldchan->name);
 		ret = 0;
 	}
 	ast_mutex_unlock(&p->lock);
@@ -3048,7 +3123,8 @@
 	for (v = i->chanvars ; v ; v = v->next)
 		pbx_builtin_setvar_helper(tmp,v->name,v->value);
 
-	append_history(i, "NewChan", "Channel %s - from %s", tmp->name, i->callid);
+	if (recordhistory)
+		append_history(i, "NewChan", "Channel %s - from %s", tmp->name, i->callid);
 				
 	return tmp;
 }
@@ -3380,6 +3456,12 @@
 	char totag[128];
 	char fromtag[128];
 	const char *callid = get_header(req, "Call-ID");
+	const char *from = get_header(req, "From");
+	const char *to = get_header(req, "To");
+	const char *cseq = get_header(req, "Cseq");
+
+	if (!callid || !to || !from || !cseq)		/* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */
+		return NULL;	/* Invalid packet */
 
 	if (pedanticsipchecking) {
 		/* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
@@ -3562,7 +3644,9 @@
 	return t; 
 }
 
-/*! \brief Parse a SIP message */
+/*! \brief Parse a SIP message 
+	\note this function is used both on incoming and outgoing packets
+*/
 static void parse_request(struct sip_request *req)
 {
 	/* Divide fields by NULL's */
@@ -4244,6 +4328,7 @@
 	copy_header(resp, req, "CSeq");
 	add_header(resp, "User-Agent", global_useragent);
 	add_header(resp, "Allow", ALLOWED_METHODS);
+	add_header(resp, "Supported", SUPPORTED_EXTENSIONS);
 	if (msg[0] == '2' && (p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER)) {
 		/* For registration responses, we also need expiry and
 		   contact info */
@@ -4378,8 +4463,12 @@
 	add_header_contentLength(&resp, 0);
 	/* If we are cancelling an incoming invite for some reason, add information
 		about the reason why we are doing this in clear text */
-	if (msg[0] != '1' && p->owner && p->owner->hangupcause) {
+	if (p->method == SIP_INVITE && msg[0] != '1' && p->owner && p->owner->hangupcause) {
+		char buf[10];
+
 		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause));
+		snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause);
+		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
 	}
 	add_blank_header(&resp);
 	return send_response(p, &resp, reliable, seqno);
@@ -4846,10 +4935,8 @@
 static int transmit_reinvite_with_sdp(struct sip_pvt *p)
 {
 	struct sip_request req;
-	if (ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE))
-		reqprep(&req, p, SIP_UPDATE, 0, 1);
-	else 
-		reqprep(&req, p, SIP_INVITE, 0, 1);
+
+	reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ?  SIP_UPDATE : SIP_INVITE, 0, 1);
 	
 	add_header(&req, "Allow", ALLOWED_METHODS);
 	add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
@@ -4859,10 +4946,7 @@
 		append_history(p, "ReInv", "Re-invite sent");
 	add_sdp(&req, p);
 	/* Use this as the basis */
-	copy_request(&p->initreq, &req);
-	parse_request(&p->initreq);
-	if (sip_debug_test_pvt(p))
-		ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
+	initialize_initreq(p, &req);
 	p->lastinvite = p->ocseq;
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);
 	return send_request(p, &req, 1, p->ocseq);
@@ -5139,13 +5223,24 @@
 		add_header(&req, p->options->authheader, p->options->auth);
 	append_date(&req);
 	if (sipmethod == SIP_REFER) {	/* Call transfer */
-		if (!ast_strlen_zero(p->refer_to))
-			add_header(&req, "Refer-To", p->refer_to);
-		if (!ast_strlen_zero(p->referred_by))
-			add_header(&req, "Referred-By", p->referred_by);
-	}
-	if (p->options && !ast_strlen_zero(p->options->distinctive_ring))
-	{
+		if (p->refer) {
+			char buf[BUFSIZ];
+			if (!ast_strlen_zero(p->refer->refer_to))
+				add_header(&req, "Refer-To", p->refer->refer_to);
+			if (!ast_strlen_zero(p->refer->referred_by)) {
+				sprintf(buf, "%s <%s>", p->refer->referred_by_name, p->refer->referred_by);
+				add_header(&req, "Referred-By", buf);
+			}
+		}
+	}
+	/* This new INVITE is part of an attended transfer. Make sure that the
+	other end knows and replace the current call with this new call */
+	if (p->options && p->options->replaces && !ast_strlen_zero(p->options->replaces)) {
+		add_header(&req, "Replaces", p->options->replaces);
+		add_header(&req, "Required", "replaces");
+	}
+
+	if (p->options && !ast_strlen_zero(p->options->distinctive_ring)) {
 		add_header(&req, "Alert-Info", p->options->distinctive_ring);
 	}
 	add_header(&req, "Allow", ALLOWED_METHODS);
@@ -5196,13 +5291,8 @@
 		add_blank_header(&req);
 	}
 
-	if (!p->initreq.headers) {
-		/* Use this as the basis */
-		copy_request(&p->initreq, &req);
-		parse_request(&p->initreq);
-		if (sip_debug_test_pvt(p))
-			ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
-	}
+	if (!p->initreq.headers)
+		initialize_initreq(p, &req);
 	p->lastinvite = p->ocseq;
 	return send_request(p, &req, init ? 2 : 1, p->ocseq);
 }
@@ -5405,42 +5495,30 @@
 	add_header_contentLength(&req, strlen(tmp));
 	add_line(&req, tmp);
 
-	if (!p->initreq.headers) { /* Use this as the basis */
-		copy_request(&p->initreq, &req);
-		parse_request(&p->initreq);
-		if (sip_debug_test_pvt(p))
-			ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
-		determine_firstline_parts(&p->initreq);
-	}
-
+	if (!p->initreq.headers) 
+		initialize_initreq(p, &req);
 	return send_request(p, &req, 1, p->ocseq);
 }
 
 /*! \brief Transmit SIP request */
 static int transmit_sip_request(struct sip_pvt *p,struct sip_request *req)
 {
-	if (!p->initreq.headers) {
-		/* Use this as the basis */
-		copy_request(&p->initreq, req);
-		parse_request(&p->initreq);
-		if (sip_debug_test_pvt(p))
-			ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
-		determine_firstline_parts(&p->initreq);
-	}
-
+	if (!p->initreq.headers) 
+		initialize_initreq(p, req);
 	return send_request(p, req, 0, p->ocseq);
 }
 
-/*! \brief Notify a transferring party of the status of transfer
- */
-static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message)
+/*! \brief Notify a transferring party of the status of transfer */
+static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate)
 {
 	struct sip_request req;
-	char tmp[50];
+	char tmp[BUFSIZ/2];
+
 	reqprep(&req, p, SIP_NOTIFY, 0, 1);
 	snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq);
 	add_header(&req, "Event", tmp);
-	add_header(&req, "Subscription-state", "terminated;reason=noresource");
+	if (terminate)
+		add_header(&req, "Subscription-state", "terminated;reason=noresource");
 	add_header(&req, "Content-Type", "message/sipfrag;version=2.0");
 	add_header(&req, "Allow", ALLOWED_METHODS);
 	add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
@@ -5449,14 +5527,14 @@
 	add_header_contentLength(&req, strlen(tmp));
 	add_line(&req, tmp);
 
-	if (!p->initreq.headers) {
-		/* Use this as the basis */
-		copy_request(&p->initreq, &req);
-		parse_request(&p->initreq);
-		if (sip_debug_test_pvt(p))
-			ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
-		determine_firstline_parts(&p->initreq);
-	}
+
+	snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message);
+	add_header_contentLength(&req, strlen(tmp));
+	add_line(&req, tmp);
+
+	
+	if (!p->initreq.headers)
+		initialize_initreq(p, &req);
 
 	return send_request(p, &req, 1, p->ocseq);
 }
@@ -5732,12 +5810,10 @@
 	add_header(&req, "Event", "registration");
 	add_header_contentLength(&req, 0);
 	add_blank_header(&req);
-	copy_request(&p->initreq, &req);
-	parse_request(&p->initreq);
-	if (sip_debug_test_pvt(p)) {
+
+	initialize_initreq(p, &req);
+	if (sip_debug_test_pvt(p))
 		ast_verbose("REGISTER %d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
-	}
-	determine_firstline_parts(&p->initreq);
 	r->regstate = auth ? REG_STATE_AUTHSENT : REG_STATE_REGSENT;
 	r->regattempts++;	/* Another attempt */
 	if (option_debug > 3)
@@ -5755,6 +5831,12 @@
 	return send_request(p, &req, 1, p->ocseq);
 }
 
+/*! \brief Allocate SIP refer structure */
+int sip_refer_allocate(struct sip_pvt *p) {
+	p->refer = ast_calloc(1, sizeof(struct sip_refer)); 
+	return p->refer ? 1 : 0;
+}
+
 /*! \brief Transmit SIP REFER message */
 static int transmit_refer(struct sip_pvt *p, const char *dest)
 {
@@ -5763,12 +5845,23 @@
 	const char *of;
 	char *c;
 	char referto[256];
-
-	/* Are we transfering an inbound or outbound call? */
-	if (ast_test_flag(&p->flags[0], SIP_OUTGOING))
+	char *ttag, *ftag;
+	char *theirtag = ast_strdupa(p->theirtag);
+
+	if (option_debug || sipdebug)
+		ast_log(LOG_DEBUG, "SIP transfer of %s to %s\n", p->callid, dest);
+
+	/* Are we transfering an inbound or outbound call ? */
+	if (ast_test_flag(&p->flags[0], SIP_OUTGOING))  {
 		of = get_header(&p->initreq, "To");
-	else
+		ttag = theirtag;
+		ftag = p->tag;
+	} else {
 		of = get_header(&p->initreq, "From");
+		ftag = theirtag;
+		ttag = p->tag;
+	}
+
 	ast_copy_string(from, of, sizeof(from));
 	of = get_in_brackets(from);
 	ast_string_field_set(p, from, of);
@@ -5781,17 +5874,18 @@
 		c = NULL;
 	else if ((c = strchr(of, '@')))
 		*c++ = '\0';
-	if (c) {
+	if (c) 
 		snprintf(referto, sizeof(referto), "<sip:%s@%s>", dest, c);
-	} else {
+	else
 		snprintf(referto, sizeof(referto), "<sip:%s>", dest);
-	}
 
 	add_header(&req, "Max-Forwards", DEFAULT_MAX_FORWARDS);
 
 	/* save in case we get 407 challenge */
-	ast_string_field_set(p, refer_to, referto);
-	ast_string_field_set(p, referred_by, p->our_contact);
+	sip_refer_allocate(p);
+	ast_copy_string(p->refer->refer_to, referto, sizeof(p->refer->refer_to));
+	ast_copy_string(p->refer->referred_by, p->our_contact, sizeof(p->refer->referred_by));
+	p->refer->status = REFER_SENT;   /* Set refer status */
 
 	reqprep(&req, p, SIP_REFER, 0, 1);
 	add_header(&req, "Refer-To", referto);
@@ -5800,7 +5894,10 @@
 	if (!ast_strlen_zero(p->our_contact))
 		add_header(&req, "Referred-By", p->our_contact);
 	add_blank_header(&req);
+
 	return send_request(p, &req, 1, p->ocseq);
+	/* We should propably wait for a NOTIFY here until we ack the transfer */
+	/* Maybe fork a new thread and wait for a STATUS of REFER_200OK on the refer status before returning to app_transfer */
 
 	/*! \todo In theory, we should hang around and wait for a reply, before
 	returning to the dial plan here. Don't know really how that would
@@ -5808,6 +5905,7 @@
 	useful we should have a STATUS code on transfer().
 	*/
 }
+
 
 /*! \brief Send SIP INFO dtmf message, see Cisco documentation on cisco.com */
 static int transmit_info_with_digit(struct sip_pvt *p, char digit)
@@ -5859,10 +5957,12 @@
 	}
 	/* If we are hanging up and know a cause for that, send it in clear text to make
 		debugging easier. */
-	if (sipmethod == SIP_BYE) {
-		if (p->owner && p->owner->hangupcause)	{
-			add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause));
-		}
+	if (sipmethod == SIP_BYE && p->owner && p->owner->hangupcause)	{
+		char buf[10];
+
+		add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause));
+		snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause);
+		add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
 	}
 
 	add_header_contentLength(&resp, 0);
@@ -6375,7 +6475,7 @@
 			   retransmission should get it */
 			transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
 			/* Schedule auto destroy in 32 seconds (according to RFC 3261) */
-			sip_scheddestroy(p, 32000);
+			sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 		}
 		return 1;	/* Auth sent */
 	} else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) {
@@ -6383,7 +6483,7 @@
 		ast_string_field_build(p, randdata, "%08lx", ast_random());	/* Create nonce for challenge */
 		transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
 		/* Schedule auto destroy in 32 seconds */
-		sip_scheddestroy(p, 32000);
+		sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 		return 1;	/* Auth sent */
 	} else {	/* We have auth, so check it */
 		/* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting
@@ -6484,7 +6584,7 @@
 			}
 
 			/* Schedule auto destroy in 32 seconds */
-			sip_scheddestroy(p, 32000);
+			sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 			return 1;	/* XXX should it be -1 ? */
 		} 
 		if (good_response) /* Auth is OK */
@@ -6494,7 +6594,7 @@
 		/* Ok, we have a bad username/secret pair */
 		/* Challenge again, and again, and again */
 		transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
-		sip_scheddestroy(p, 32000);
+		sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 		return 1;		/* Challenge sent */
 
 	}
@@ -6512,7 +6612,7 @@
 	case AST_EXTENSION_REMOVED:	/* Extension is gone */
 		if (p->autokillid > -1)
 			sip_cancel_destroy(p);	/* Remove subscription expiry for renewals */
-		sip_scheddestroy(p, 15000);	/* Delete subscription in 15 secs */
+		sip_scheddestroy(p, SIP_TRANS_TIMEOUT);	/* Delete subscription in 32 secs */
 		ast_verbose(VERBOSE_PREFIX_2 "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username);
 		p->stateid = -1;
 		p->subscribed = NONE;
@@ -6807,19 +6907,46 @@
 	return -1;
 }
 
-/*! \brief Lock interface lock and find matching pvt lock  */
-static struct sip_pvt *get_sip_pvt_byid_locked(char *callid) 
+/*! \brief Lock interface lock and find matching pvt lock  
+	- Their tag is fromtag, our tag is to-tag
+	- This means that in some transactions, totag needs to be their tag :-)
+	  depending upon the direction
+*/
+static struct sip_pvt *get_sip_pvt_byid_locked(char *callid, char *totag, char *fromtag) 
 {
 	struct sip_pvt *sip_pvt_ptr = NULL;
 	
 	/* Search interfaces and find the match */
 	ast_mutex_lock(&iflock);
-	for (sip_pvt_ptr = iflist; sip_pvt_ptr ; sip_pvt_ptr = sip_pvt_ptr->next) {
+
+	if (option_debug > 3 && totag)
+		ast_log(LOG_DEBUG, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>");
+
+	for (sip_pvt_ptr = iflist; sip_pvt_ptr; sip_pvt_ptr = sip_pvt_ptr->next) {
 		if (!strcmp(sip_pvt_ptr->callid, callid)) {
+			int match = 1;
+			char *ourtag = sip_pvt_ptr->tag;
+
 			/* Go ahead and lock it (and its owner) before returning */
 			ast_mutex_lock(&sip_pvt_ptr->lock);
+
+			/* Check if tags match. If not, this is not the call we want
+			   (With a forking SIP proxy, several call legs share the
+			   call id, but have different tags)
+			*/
+			if (pedanticsipchecking && (strcmp(fromtag, sip_pvt_ptr->theirtag) || strcmp(totag, ourtag)))
+				match = 0;
+
+			if (!match) {
+				ast_mutex_unlock(&sip_pvt_ptr->lock);
+				break;
+			}
+
+			if (option_debug > 3 && totag)				 
+				ast_log(LOG_DEBUG, "Matched %s call - their tag is %s Our tag is %s\n", ast_test_flag(&sip_pvt_ptr->flags[0], SIP_OUTGOING) ? "OUTGOING": "INCOMING", sip_pvt_ptr->theirtag, sip_pvt_ptr->tag);
+
 			if (sip_pvt_ptr->owner) {
-				while(ast_mutex_trylock(&sip_pvt_ptr->owner->lock)) {
+				while(ast_channel_trylock(sip_pvt_ptr->owner)) {
 					ast_mutex_unlock(&sip_pvt_ptr->lock);
 					usleep(1);
 					ast_mutex_lock(&sip_pvt_ptr->lock);
@@ -6831,6 +6958,8 @@
 		}
 	}
 	ast_mutex_unlock(&iflock);
+	if (option_debug > 3 && !sip_pvt_ptr)
+		ast_log(LOG_DEBUG, "Found no match for callid %s to-tag %s from-tag %s\n", callid, totag, fromtag);
 	return sip_pvt_ptr;
 }
 
@@ -6921,13 +7050,13 @@
 	}
 	if (!ast_strlen_zero(replace_callid)) {	
 		/* This is a supervised transfer */
-		ast_log(LOG_DEBUG,"Assigning Replace-Call-ID Info %s to REPLACE_CALL_ID\n",replace_callid);
+		ast_log(LOG_DEBUG,"Assigning Replace-Call-ID Info %s to REPLACE_CALL_ID\n", replace_callid);
 		
 		ast_string_field_free(sip_pvt, refer_to);
 		ast_string_field_free(sip_pvt, referred_by);
 		ast_string_field_free(sip_pvt, refer_contact);
 		sip_pvt->refer_call = NULL;
-		if ((sip_pvt_ptr = get_sip_pvt_byid_locked(replace_callid))) {
+		if ((sip_pvt_ptr = get_sip_pvt_byid_locked(replace_callid, NULL, NULL))) {
 			sip_pvt->refer_call = sip_pvt_ptr;
 			if (sip_pvt->refer_call == sip_pvt) {
 				ast_log(LOG_NOTICE, "Supervised transfer attempted to transfer into same call id (%s == %s)!\n", replace_callid, sip_pvt->callid);
@@ -8563,10 +8692,12 @@
 {
 #define FORMAT3 "%-15.15s  %-10.10s  %-11.11s  %-15.15s  %-13.13s  %-15.15s %-10.10s\n"
 #define FORMAT2 "%-15.15s  %-10.10s  %-11.11s  %-11.11s  %-4.4s  %-7.7s  %-15.15s\n"
-#define FORMAT  "%-15.15s  %-10.10s  %-11.11s  %5.5d/%5.5d  %-4.4s  %-3.3s %-3.3s  %-15.15s\n"
+#define FORMAT  "%-15.15s  %-10.10s  %-11.11s  %5.5d/%5.5d  %-4.4s  %-3.3s %-3.3s  %-15.15s %-10.10s\n"
 	struct sip_pvt *cur;
 	char iabuf[INET_ADDRSTRLEN];
 	int numchans = 0;
+	char *referstatus = NULL;
+
 	if (argc != 3)
 		return RESULT_SHOWUSAGE;
 	ast_mutex_lock(&iflock);
@@ -8576,6 +8707,10 @@
 	else 
 		ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
 	for (; cur; cur = cur->next) {
+		referstatus = "";
+		if (cur->refer) { /* SIP transfer in progress */
+			referstatus = referstatus2str(cur->refer->status);
+		}
 		if (cur->subscribed == NONE && !subscriptions) {
 			ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), cur->sa.sin_addr), 
 				S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
@@ -8584,7 +8719,9 @@
 				ast_getformatname(cur->owner ? cur->owner->nativeformats : 0), 
 				ast_test_flag(&cur->flags[0], SIP_CALL_ONHOLD) ? "Yes" : "No",
 				ast_test_flag(&cur->flags[0], SIP_NEEDDESTROY) ? "(d)" : "",
-				cur->lastmsg );
+				cur->lastmsg ,
+				referstatus
+			);
 			numchans++;
 		}
 		if (cur->subscribed != NONE && subscriptions) {
@@ -8592,7 +8729,7 @@
 				S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 
 			   	cur->callid,
 				/* the 'complete' exten/context is hidden in the refer_to field for subscriptions */
-				cur->subscribed == MWI_NOTIFICATION ? "--" : cur->refer_to,
+				cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri,
 				cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 
 				subscription_type2str(cur->subscribed),
 				cur->subscribed == MWI_NOTIFICATION ? (cur->relatedpeer ? cur->relatedpeer->mailbox : "<none>") : "<none>"
@@ -9088,7 +9225,7 @@
 		build_callid_pvt(p);
 		ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
 		transmit_sip_request(p, &req);
-		sip_scheddestroy(p, 15000);
+		sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 	}
 
 	return RESULT_SUCCESS;
@@ -9423,10 +9560,10 @@
 		return -1;
 	}
 
-	ast_mutex_lock(&chan->lock);
+	ast_channel_lock(chan);
 	if (chan->tech != &sip_tech) {
 		ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n");
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return -1;
 	}
 
@@ -9434,19 +9571,19 @@
 
 	/* If there is no private structure, this channel is no longer alive */
 	if (!p) {
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return -1;
 	}
 
 	content = get_header(&p->initreq, data);
 
 	if (ast_strlen_zero(content)) {
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return -1;
 	}
 
 	ast_copy_string(buf, content, len);
-	ast_mutex_unlock(&chan->lock);
+	ast_channel_unlock(chan);
 
 	return 0;
 }
@@ -9589,10 +9726,10 @@
 		return -1;
 	}
 
-	ast_mutex_lock(&chan->lock);
+	ast_channel_lock(chan);
 	if (chan->tech != &sip_tech) {
 		ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n");
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return -1;
 	}
 
@@ -9600,7 +9737,7 @@
 
 	/* If there is no private structure, this channel is no longer alive */
 	if (!p) {
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return -1;
 	}
 
@@ -9617,10 +9754,10 @@
 	} else  if (!strcasecmp(data, "peername")) {
 		ast_copy_string(buf, p->peername, len);
 	} else {
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return -1;
 	}
-	ast_mutex_unlock(&chan->lock);
+	ast_channel_unlock(chan);
 
 	return 0;
 }
@@ -9703,7 +9840,7 @@
 }
 
 /*! \brief Handle SIP response in dialogue */
-static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno)
+static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
 {
 	int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING);
 	
@@ -9720,41 +9857,48 @@
 		return;
 	}
 
+	/* Acknowledge sequence number - This only happens on INVITE from SIP-call */
+	if (p->initid > -1) {
+		/* Don't auto congest anymore since we've gotten something useful back */
+		ast_sched_del(sched, p->initid);
+		p->initid = -1;
+	}
+
 	switch (resp) {
 	case 100:	/* Trying */
-		if (!ignore)
+		if (!ast_test_flag(req, SIP_PKT_IGNORE))
 			sip_cancel_destroy(p);
 		break;
 	case 180:	/* 180 Ringing */
-		if (!ignore)
+		if (!ast_test_flag(req, SIP_PKT_IGNORE))
 			sip_cancel_destroy(p);
-		if (!ignore && p->owner) {
+		if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
 			ast_queue_control(p->owner, AST_CONTROL_RINGING);
 			if (p->owner->_state != AST_STATE_UP)
 				ast_setstate(p->owner, AST_STATE_RINGING);
 		}
 		if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
 			process_sdp(p, req);
-			if (!ignore && p->owner) {
+			if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
 				/* Queue a progress frame only if we have SDP in 180 */
 				ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
 			}
 		}
 		break;
 	case 183:	/* Session progress */
-		if (!ignore)
+		if (!ast_test_flag(req, SIP_PKT_IGNORE))
 			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) {
+			if (!ast_test_flag(req, SIP_PKT_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 */
-		if (!ignore)
+		if (!ast_test_flag(req, SIP_PKT_IGNORE))
 			sip_cancel_destroy(p);
 		p->authtries = 0;
 		if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) 
@@ -9773,7 +9917,7 @@
 					should we care about resolving the contact
 					or should we just send it?
 				*/
-				if (!ignore)
+				if (!ast_test_flag(req, SIP_PKT_IGNORE))
 					ast_set_flag(&p->flags[0], SIP_PENDINGBYE);	
 			} 
 
@@ -9781,7 +9925,7 @@
 			build_route(p, req, 1);
 		}
 		
-		if (!ignore && p->owner) {
+		if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
 			if (p->owner->_state != AST_STATE_UP) {
 				ast_queue_control(p->owner, AST_CONTROL_ANSWER);
 			} else {	/* RE-invite */
@@ -9791,7 +9935,7 @@
 			 /* It's possible we're getting an 200 OK after we've tried to disconnect
 				  by sending CANCEL */
 			/* First send ACK, then send bye */
-			if (!ignore)
+			if (!ast_test_flag(req, SIP_PKT_IGNORE))
 				ast_set_flag(&p->flags[0], SIP_PENDINGBYE);	
 		}
 		/* If I understand this right, the branch is different for a non-200 ACK only */
@@ -9807,7 +9951,7 @@
 
 		/* Then we AUTH */
 		ast_string_field_free(p, theirtag);	/* forget their old tag, so we don't match tags when getting response */
-		if (!ignore) {
+		if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
 			char *authenticate = (resp == 401 ? "WWW-Authenticate" : "Proxy-Authenticate");
 			char *authorization = (resp == 401 ? "Authorization" : "Proxy-Authorization");
 			if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, authenticate, authorization, SIP_INVITE, 1)) {
@@ -9823,14 +9967,14 @@
 		/* First we ACK */
 		transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", get_header(&p->initreq, "From"));
-		if (!ignore && p->owner)
+		if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner)
 			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
 		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
 		ast_set_flag(&p->flags[0], SIP_ALREADYGONE);	
 		break;
 	case 404: /* Not found */
 		transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
-		if (p->owner && !ignore)
+		if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE))
 			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
 		ast_set_flag(&p->flags[0], SIP_ALREADYGONE);	
 		break;
@@ -9854,7 +9998,7 @@
 /* \brief Handle SIP response in REFER transaction
 	We've sent a REFER, now handle responses to it 
   */
-static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno)
+static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
 {
 	char *auth = "Proxy-Authenticate";
 	char *auth2 = "Proxy-Authorization";
@@ -9966,7 +10110,7 @@
 		r->call = NULL;
 		p->registry = NULL;
 		/* Let this one hang around until we have all the responses */
-		sip_scheddestroy(p, 32000);
+		sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
 		/* ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	*/
 
 		/* set us up for re-registering */
@@ -10021,7 +10165,7 @@
 }
 
 /*! \brief Handle qualification responses (OPTIONS) */
-static int handle_response_peerpoke(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno, int sipmethod)
+static int handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req)
 {
 	struct sip_peer *peer;
 	int pingtime;
@@ -10063,8 +10207,6 @@
 
 		if (peer->pokeexpire > -1)
 			ast_sched_del(sched, peer->pokeexpire);
-		if (sipmethod == SIP_INVITE)	/* Does this really happen? */
-			transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
 
 		/* Try again eventually */
@@ -10115,32 +10257,28 @@
 		   Well, as long as it's not a 100 response...  since we might
 		   need to hang around for something more "definitive" */
 
-		res = handle_response_peerpoke(p, resp, rest, req, ignore, seqno, sipmethod);
+		res = handle_response_peerpoke(p, resp, req);
 	} else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
-		/* Acknowledge sequence number */
-		if (p->initid > -1) {
-			/* Don't auto congest anymore since we've gotten something useful back */
-			ast_sched_del(sched, p->initid);
-			p->initid = -1;
-		}
 		switch(resp) {
 		case 100:	/* 100 Trying */
 			if (sipmethod == SIP_INVITE) 
-				handle_response_invite(p, resp, rest, req, ignore, seqno);
+				handle_response_invite(p, resp, rest, req, seqno);
 			break;
 		case 183:	/* 183 Session Progress */
 			if (sipmethod == SIP_INVITE) 
-				handle_response_invite(p, resp, rest, req, ignore, seqno);
+				handle_response_invite(p, resp, rest, req, seqno);
 			break;
 		case 180:	/* 180 Ringing */
 			if (sipmethod == SIP_INVITE) 
-				handle_response_invite(p, resp, rest, req, ignore, seqno);
+				handle_response_invite(p, resp, rest, req, seqno);
 			break;
 		case 200:	/* 200 OK */
 			p->authtries = 0;	/* Reset authentication counter */
 			if (sipmethod == SIP_MESSAGE) {
 				/* We successfully transmitted a message */
 				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
+			} else if (sipmethod == SIP_INVITE) {

[... 662 lines stripped ...]


More information about the svn-commits mailing list