[asterisk-commits] oej: branch oej/darjeeling-prack-1.8 r369695 - in /team/oej/darjeeling-prack-...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jul 6 07:04:57 CDT 2012


Author: oej
Date: Fri Jul  6 07:02:35 2012
New Revision: 369695

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=369695
Log:
Add a - maybe unrelated - feature:
- Lock on the SDP of the first 183 and skip the rest for early media

Fix a bug
- Update the pvt with the latest to-tag received until we get a 200.

Add an ugly fix
- If we get provisional responses that require prack from multiple 
  devices, just track the rseq from the first one. Respond to the
  second one and have fun

Modified:
    team/oej/darjeeling-prack-1.8/channels/chan_sip.c
    team/oej/darjeeling-prack-1.8/channels/sip/include/sip.h
    team/oej/darjeeling-prack-1.8/configs/sip.conf.sample

Modified: team/oej/darjeeling-prack-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/darjeeling-prack-1.8/channels/chan_sip.c?view=diff&rev=369695&r1=369694&r2=369695
==============================================================================
--- team/oej/darjeeling-prack-1.8/channels/chan_sip.c (original)
+++ team/oej/darjeeling-prack-1.8/channels/chan_sip.c Fri Jul  6 07:02:35 2012
@@ -12311,26 +12311,61 @@
  */
 static int transmit_prack(struct sip_pvt *p, uint32_t their_rseq)
 {
-	if (their_rseq == p->irseq) {
-		ast_debug(3, "!?!?!?!?!? This is a retransmit of the previous response. %u \n", their_rseq);
-		/* RFC 3262: In particular, a UAC SHOULD NOT retransmit the PRACK request
-   		   	when it receives a retransmission of the provisional response being
-   		   	acknowledged, although doing so does not create a protocol error.*/
-		return -2;	/* Not used by transmit_invite et al */
-	}
-	if (p->irseq > 0 && their_rseq != p->irseq + 1) {
-		ast_debug(3, "!?!?!?!?!? This is a response out of sequence! ignored. %u \n", their_rseq);
-		/* RFC 3262: if the UAC receives another reliable provisional
-   			response to the same request, and its RSeq value is not one higher
-   			than the value of the sequence number, that response MUST NOT be
-   			acknowledged with a PRACK, and MUST NOT be processed further by the
-   			UAC.  An implementation MAY discard the response, or MAY cache the
-   			response in the hopes of receiving the missing responses.
+	int res;
+	int comparerseq = TRUE;
+	uint32_t focus_rseq = p->irseq;
+
+	/* During the early media phase, we could have a situation where we get provisional
+	   responses from multiple devices, in separate early dialogs. In this case, this 
+	   code focuses on the FIRST early media response as the one in focus where we 
+	   check the rseq sequence numbers for retransmits and act upon them.
+	*/
+
+	if (!ast_strlen_zero(p->theirtag_prack) && !strcmp(p->theirtag, p->theirtag_prack)) {
+		/* We have already sent a PRACK in this dialog, but to a different device.
+		   In this code, we focus on the first response that requires PRACK and do not check
+		   the validity of rseq in responses in other early dialogs by controlling
+		   the PRACK sequence numbers ordering.
+
+		   To be 100% RFC correct, we should have a sip_pvt structure for each early dialog
+		   and terminate them if we get a 199 response in that early dialog. these should
+		   be organized in a tree-like structure based on the original
+		   INVITE callid, cseq and from-tag.
 		*/
-		return -3;
+		comparerseq = FALSE;
+	}
+	
+	if (comparerseq) {
+		if (their_rseq == p->irseq) {
+			ast_debug(3, "!?!?!?!?!? This is a retransmit of the previous response. %u \n", their_rseq);
+			/* RFC 3262: In particular, a UAC SHOULD NOT retransmit the PRACK request
+   		   		when it receives a retransmission of the provisional response being
+   		   		acknowledged, although doing so does not create a protocol error.*/
+			return -2;	/* Not used by transmit_invite et al */
+		}
+		if (p->irseq > 0 && their_rseq != p->irseq + 1) {
+			ast_debug(3, "!?!?!?!?!? This is a response out of sequence! ignored. %u \n", their_rseq);
+			/* RFC 3262: if the UAC receives another reliable provisional
+   				response to the same request, and its RSeq value is not one higher
+   				than the value of the sequence number, that response MUST NOT be
+   				acknowledged with a PRACK, and MUST NOT be processed further by the
+   				UAC.  An implementation MAY discard the response, or MAY cache the
+   				response in the hopes of receiving the missing responses.
+			*/
+			return -3;
+		}
 	}
 	p->irseq = their_rseq;
-	return transmit_invite(p, SIP_PRACK, 0, 1, NULL);
+	res = transmit_invite(p, SIP_PRACK, 0, 1, NULL);
+
+	if (ast_strlen_zero(p->theirtag_prack)) {
+		p->irseq = their_rseq;
+		ast_string_field_set(p, theirtag_prack, p->tag);		/* Save this tag as a PRACK focus for this dialog */
+	} else {
+		p->irseq = focus_rseq;
+	}
+
+	return res;
 }
 
 /*! 
@@ -18440,6 +18475,7 @@
 	ast_cli(a->fd, "  Timer T1 minimum:       %d\n", global_t1min);
  	ast_cli(a->fd, "  Timer B:                %d\n", global_timer_b);
 	ast_cli(a->fd, "  No premature media:     %s\n", AST_CLI_YESNO(global_prematuremediafilter));
+	ast_cli(a->fd, "  Early media focus:      %s\n", AST_CLI_YESNO(sip_cfg.early_media_focus));
 	ast_cli(a->fd, "  Max forwards:           %d\n", sip_cfg.default_max_forwards);
 	ast_cli(a->fd, "  PRACK support:          %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[2], SIP_PAGE3_PRACK)));
 
@@ -20366,7 +20402,7 @@
 				ast_setstate(p->owner, AST_STATE_RINGING);
 			}
 		}
-		if (find_sdp(req)) {
+		if (!req->ignoresdp && find_sdp(req)) {
 			if (p->invitestate != INV_CANCELLED)
 				p->invitestate = INV_EARLY_MEDIA;
 			res = process_sdp(p, req, SDP_T38_NONE);
@@ -20375,6 +20411,9 @@
 				ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
 			}
 			ast_rtp_instance_activate(p->rtp);
+			if (sip_cfg.early_media_focus && ast_strlen_zero(p->theirtag_early)) {
+				ast_string_field_set(p, theirtag_early, p->tag);
+			}
 		}
 		check_pendings(p);
 		break;
@@ -20438,7 +20477,7 @@
 			}
 			sip_handle_cc(p, req, AST_CC_CCNR);
 		}
-		if (find_sdp(req)) {
+		if (!req->ignoresdp && find_sdp(req)) {
 			if (p->invitestate != INV_CANCELLED)
 				p->invitestate = INV_EARLY_MEDIA;
 			res = process_sdp(p, req, SDP_T38_NONE);
@@ -21256,6 +21295,7 @@
 	int sipmethod;
 	const char *c = get_header(req, "Cseq");
 	const char *required = get_header(req, "Require");
+	char tag[128];
 
 	/* GCC 4.2 complains if I try to cast c as a char * when passing it to ast_skip_nonblanks, so make a copy of it */
 	char *c_copy = ast_strdupa(c);
@@ -21317,13 +21357,13 @@
 		p->pendinginvite = 0;
 	}
 
-	/* Get their tag if we haven't already */
-	if (ast_strlen_zero(p->theirtag) || (resp >= 200)) {
-		char tag[128];
-
-		gettag(req, "To", tag, sizeof(tag));
-		ast_string_field_set(p, theirtag, tag);
-	}
+	
+	/* Always get the tag. Find_call will filter out after we have an established dialog,
+	   so that we don't update the tag after a 200 or other final response. 
+	   Provided that SIP pedantic checking is turned on of course.
+	*/
+	gettag(req, "To", tag, sizeof(tag));
+	ast_string_field_set(p, theirtag, tag);
 
 	/* This needs to be configurable on a channel/peer level,
 	   not mandatory for all communication. Sadly enough, NAT implementations
@@ -21379,6 +21419,14 @@
 		}
 		if (activeextensions & SIP_OPT_TIMER) {
 			ast_debug(3, "!=!=!=!=!=! The other side activated Session timers! \n");
+		}
+	}
+
+	if (sip_cfg.early_media_focus && !ast_strlen_zero(p->theirtag_early) && !strcmp(p->theirtag_early, p->theirtag)) {
+		/* If we already are in early media phase, and have a response from a new device in this call we should
+	   	ignore the SDP. */
+		if(p->invitestate == INV_EARLY_MEDIA) {
+			req->ignoresdp = TRUE;
 		}
 	}
 
@@ -27977,6 +28025,8 @@
 					ast_log(LOG_WARNING, "'%s' is not a valid maxforwards value at line %d.  Using default.\n", v->value, v->lineno);
 					peer->maxforwards = sip_cfg.default_max_forwards;
 				}
+			} else if (!strcasecmp(v->name, "earlymediafocus")) {
+				sip_cfg.early_media_focus = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "accountcode")) {
 				ast_string_field_set(peer, accountcode, v->value);
 			} else if (!strcasecmp(v->name, "mohinterpret")) {
@@ -28522,6 +28572,7 @@
 	externtcpport = STANDARD_SIP_PORT;
 	externtlsport = STANDARD_TLS_PORT;
 	sip_cfg.srvlookup = DEFAULT_SRVLOOKUP;
+	sip_cfg.early_media_focus = DEFAULT_EARLY_MEDIA_FOCUS;
 	global_tos_sip = DEFAULT_TOS_SIP;
 	global_tos_audio = DEFAULT_TOS_AUDIO;
 	global_tos_video = DEFAULT_TOS_VIDEO;

Modified: team/oej/darjeeling-prack-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/darjeeling-prack-1.8/channels/sip/include/sip.h?view=diff&rev=369695&r1=369694&r2=369695
==============================================================================
--- team/oej/darjeeling-prack-1.8/channels/sip/include/sip.h (original)
+++ team/oej/darjeeling-prack-1.8/channels/sip/include/sip.h Fri Jul  6 07:02:35 2012
@@ -187,6 +187,7 @@
 #define DEFAULT_MWI_FROM       ""
 #define DEFAULT_NOTIFYMIME     "application/simple-message-summary"
 #define DEFAULT_ALLOWGUEST     TRUE
+#define DEFAULT_EARLY_MEDIA_FOCUS	FALSE;	/*!< Focus on a single early media stream */
 #define DEFAULT_RTPKEEPALIVE   0      /*!< Default RTPkeepalive setting */
 #define DEFAULT_CALLCOUNTER    FALSE   /*!< Do not enable call counters by default */
 #define DEFAULT_SRVLOOKUP      TRUE    /*!< Recommended setting is ON */
@@ -681,6 +682,7 @@
 	      be applied to devices (trunks, services, phones)
 */
 struct sip_settings {
+	int early_media_focus;		/*!< G: Focus on the first early media stream received, ignore the rest */
 	int peer_rtupdate;          /*!< G: Update database with registration data for peer? */
 	int rtsave_sysname;         /*!< G: Save system name at registration? */
 	int ignore_regexpire;       /*!< G: Ignore expiration of peer  */
@@ -763,6 +765,7 @@
 	char has_to_tag;        /*!< non-zero if packet has To: tag */
 	char ignore;            /*!< if non-zero This is a re-transmit, ignore it */
 	char authenticated;     /*!< non-zero if this request was authenticated */
+	char ignoresdp;		/*!< In some cases, we have to ignore the SDP in responses */
 	ptrdiff_t header[SIP_MAX_HEADERS]; /*!< Array of offsets into the request string of each SIP header*/
 	ptrdiff_t line[SIP_MAX_LINES];     /*!< Array of offsets into the request string of each SDP line*/
 	struct ast_str *data;	
@@ -967,6 +970,8 @@
 		AST_STRING_FIELD(rdnis);        /*!< Referring DNIS */
 		AST_STRING_FIELD(redircause);   /*!< Referring cause */
 		AST_STRING_FIELD(theirtag);     /*!< Their tag */
+		AST_STRING_FIELD(theirtag_prack);  /*!< Current tag focus for PRACK handling */
+		AST_STRING_FIELD(theirtag_early);  /*!< Current tag focus for early media handling */
 		AST_STRING_FIELD(tag);          /*!< Our tag for this session */
 		AST_STRING_FIELD(username);     /*!< [user] name */
 		AST_STRING_FIELD(peername);     /*!< [peer] name, not set if [user] */

Modified: team/oej/darjeeling-prack-1.8/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/darjeeling-prack-1.8/configs/sip.conf.sample?view=diff&rev=369695&r1=369694&r2=369695
==============================================================================
--- team/oej/darjeeling-prack-1.8/configs/sip.conf.sample (original)
+++ team/oej/darjeeling-prack-1.8/configs/sip.conf.sample Fri Jul  6 07:02:35 2012
@@ -241,7 +241,7 @@
                                 ; and multiline formatted headers for strict
                                 ; SIP compatibility (defaults to "yes")
 
-;prack=yes			; Enable PRACK support. (defaults to "no")
+;prack=yes			; Enable PRACK (SIP option 100rel)  support. (defaults to "no")
 				; Can also be set on a per device basis.
 
 ; See https://wiki.asterisk.org/wiki/display/AST/IP+Quality+of+Service for a description of these parameters.
@@ -349,6 +349,14 @@
                                 ;
                                 ; In order for "noanswer" applications to work, you need to run
                                 ; the progress() application in the priority before the app.
+;earlymediafocus=yes		; If you have a forking SIP proxy in the call, Asterisk may get multiple
+				; 183/180 responses with SDP from *different* devices. The default is that 
+				; Asterisk jumps on to each one. There's no *correct* solution to this
+				; problem. Turning this on means that Asterisk focuses on the *first*
+				; early media response and ignores the rest. This might mean that the
+				; user gets a ring tone and stays with that even if the service provider
+				; from a different media server plays a very important message.
+				; Default is "no" - jump to the latest one.
 
 ;progressinband=never           ; If we should generate in-band ringing always
                                 ; use 'never' to never use in-band signalling, even in cases




More information about the asterisk-commits mailing list