[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