RFC3261 compliant sip unreliable retransmit timing + 'registerattempts' option tweak
authorDavid Vossel <dvossel@digium.com>
Fri, 4 Jun 2010 21:55:14 +0000 (21:55 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 4 Jun 2010 21:55:14 +0000 (21:55 +0000)
Changes.
1. RFC 3261 states in section 17.1.2.2 and 17.1.1.2 that retransmission
timers should initially be set to timer T1.   T1 by default is 500ms.
Asterisk was starting the retransmission timers at T1*2 which shouldn't
cause any problems, but is not RFC compliant.

2. RFC 3261 states in section 17.1.2.2 that for a non-INVITE client transaction,
if the retransmit timer fires while in the proceeding state that
the request must be retransmitted.  Asterisk currently ack's
requests for both INVITE and non-INVITE transactions when a
1XX response is received, this patch changes this for non-INVITE requests.

3. The 'registerattempts' option in sip.conf is supposed to set
how many registry attempts will be made before giving up.  When
this option is set to 1, I would expect only one registry attempt
to be made before stopping because of a failure, but instead two are
made.  In my opinion this is not expected behavior.  This option does
not indicate that these are re-attempts.  The logic behind this option
has been changed to only attempt registers the exact number of times
this option is set to.  If this option is 0, it still continues to
re-attempt the registration forever.

Review: https://reviewboard.asterisk.org/r/687/

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@268205 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index 0d45bb2..815cb0c 100644 (file)
@@ -3469,7 +3469,7 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
        pkt->timer_t1 = p->timer_t1;    /* Set SIP timer T1 */
        pkt->retransid = -1;
        if (pkt->timer_t1)
-               siptimer_a = pkt->timer_t1 * 2;
+               siptimer_a = pkt->timer_t1;
 
        /* Schedule retransmission */
        AST_SCHED_REPLACE_VARIABLE(pkt->retransid, sched, siptimer_a, retrans_pkt, pkt, 1);
@@ -11528,7 +11528,6 @@ static int sip_reg_timeout(const void *data)
                ast_dnsmgr_refresh(r->dnsmgr);
        }
 
-       ast_log(LOG_NOTICE, "   -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts);
        /* If the initial tranmission failed, we may not have an existing dialog,
         * so it is possible that r->call == NULL.
         * Otherwise destroy it, as we have a timeout so we don't want it.
@@ -11551,15 +11550,16 @@ static int sip_reg_timeout(const void *data)
        }
        /* If we have a limit, stop registration and give up */
        r->timeout = -1;
-       if (global_regattempts_max && r->regattempts > global_regattempts_max) {
+       if (global_regattempts_max && r->regattempts >= global_regattempts_max) {
                /* Ok, enough is enough. Don't try any more */
                /* We could add an external notification here...
                        steal it from app_voicemail :-) */
-               ast_log(LOG_NOTICE, "   -- Giving up forever trying to register '%s@%s'\n", r->username, r->hostname);
+               ast_log(LOG_NOTICE, "   -- Last Registration Attempt #%d failed, Giving up forever trying to register '%s@%s'\n", r->regattempts, r->username, r->hostname);
                r->regstate = REG_STATE_FAILED;
        } else {
                r->regstate = REG_STATE_UNREGISTERED;
-               res=transmit_register(r, SIP_REGISTER, NULL, NULL);
+               res = transmit_register(r, SIP_REGISTER, NULL, NULL);
+               ast_log(LOG_NOTICE, "   -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts);
        }
        manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate));
        registry_unref(r, "unreffing registry_unref r");
@@ -18768,7 +18768,10 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
 
                /* Acknowledge whatever it is destined for */
                if ((resp >= 100) && (resp <= 199)) {
-                       ack_res = __sip_semi_ack(p, seqno, 0, sipmethod);
+                       /* NON-INVITE messages do not ack a 1XX response. RFC 3261 section 17.1.2.2 */
+                       if (sipmethod == SIP_INVITE) {
+                               ack_res = __sip_semi_ack(p, seqno, 0, sipmethod);
+                       }
                } else {
                        ack_res = __sip_ack(p, seqno, 0, sipmethod);
                }