- describe how sip packets are stored internally;
authorLuigi Rizzo <rizzo@icir.org>
Mon, 10 Apr 2006 10:40:13 +0000 (10:40 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Mon, 10 Apr 2006 10:40:13 +0000 (10:40 +0000)
- remove useless braces or local variables;
- simplify some code sequences;
- mark with XXX a possible locking issue.

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

channels/chan_sip.c

index 8f4f700..417efe3 100644 (file)
@@ -489,6 +489,25 @@ struct sip_request {
        char data[SIP_MAX_PACKET];
 };
 
+/*
+ * A sip packet is stored into the data[] buffer, with the header followed
+ * by an empty line and the body of the message.
+ * On outgoing packets, data is accumulated in data[] with len reflecting
+ * the next available byte, headers and lines count the number of lines
+ * in both parts. There are no '\0' in data[0..len-1].
+ *
+ * On received packet, the input read from the socket is copied into data[],
+ * len is set and the string is NUL-terminated. Then a parser fills up
+ * the other fields -header[] and line[] to point to the lines of the
+ * message, rlPart1 and rlPart2 parse the first lnie as below:
+ *
+ * Requests have in the first line     METHOD URI SIP/2.0
+ *     rlPart1 = method; rlPart2 = uri;
+ * Responses have in the first line    SIP/2.0 code description
+ *     rlPart1 = SIP/2.0; rlPart2 = code + description;
+ *
+ */
+
 /*! \brief structure used in transfers */
 struct sip_dual {
        struct ast_channel *chan1;
@@ -1345,7 +1364,6 @@ static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *dat
        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;
 
@@ -1492,16 +1510,14 @@ static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod)
 {
        struct sip_pkt *cur;
        int res = -1;
-       char *msg = sip_methods[sipmethod].text;
 
-       for (cur = p->packets; cur ; cur = cur->next) {
-               if ((cur->seqno == seqno) && ((ast_test_flag(cur, FLAG_RESPONSE)) == resp) &&
-                       ((ast_test_flag(cur, FLAG_RESPONSE)) || 
-                        (!strncasecmp(msg, cur->data, strlen(msg)) && (cur->data[strlen(msg)] < 33)))) {
+       for (cur = p->packets; cur; cur = cur->next) {
+               if (cur->seqno == seqno && ast_test_flag(cur, FLAG_RESPONSE) == resp &&
+                       (ast_test_flag(cur, FLAG_RESPONSE) || method_match(sipmethod, cur->data))) {
                        /* this is our baby */
                        if (cur->retransid > -1) {
                                if (option_debug > 3 && sipdebug)
-                                       ast_log(LOG_DEBUG, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, msg);
+                                       ast_log(LOG_DEBUG, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text);
                                ast_sched_del(sched, cur->retransid);
                        }
                        cur->retransid = -1;
@@ -1642,6 +1658,7 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin,
        char ipaddr[20];
        char regseconds[20];
        time_t nowtime;
+       const char *fc = fullcontact ? "fullcontact" : NULL;
        
        time(&nowtime);
        nowtime += expirey;
@@ -1649,10 +1666,9 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin,
        ast_inet_ntoa(ipaddr, sizeof(ipaddr), sin->sin_addr);
        snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
        
-       if (fullcontact)
-               ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, "username", username, "fullcontact", fullcontact, NULL);
-       else
-               ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, "username", username, NULL);
+       ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr,
+               "port", port, "regseconds", regseconds,
+               "username", username, fc, fullcontact, NULL); /* note fc _can_ be NULL */
 }
 
 /*! \brief Automatically add peer extension to dial plan */
@@ -1895,6 +1911,8 @@ static struct sip_user *find_user(const char *name, int realtime)
 /*! \brief Create address structure from peer reference */
 static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
 {
+       int natflags;
+
        if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
            (!peer->maxms || ((peer->lastms >= 0)  && (peer->lastms <= peer->maxms)))) {
                r->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr;
@@ -1911,15 +1929,16 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
                r->vrtp = NULL;
        }
        r->prefs = peer->prefs;
+       natflags = ast_test_flag(&r->flags[0], SIP_NAT) & SIP_NAT_ROUTE;
        if (r->rtp) {
                if (option_debug)
-                       ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (ast_test_flag(&r->flags[0], SIP_NAT) & SIP_NAT_ROUTE));
-               ast_rtp_setnat(r->rtp, (ast_test_flag(&r->flags[0], SIP_NAT) & SIP_NAT_ROUTE));
+                       ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", natflags);
+               ast_rtp_setnat(r->rtp, natflags);
        }
        if (r->vrtp) {
                if (option_debug)
-                       ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(&r->flags[0], SIP_NAT) & SIP_NAT_ROUTE));
-               ast_rtp_setnat(r->vrtp, (ast_test_flag(&r->flags[0], SIP_NAT) & SIP_NAT_ROUTE));
+                       ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", natflags);
+               ast_rtp_setnat(r->vrtp, natflags);
        }
        ast_string_field_set(r, peername, peer->username);
        ast_string_field_set(r, authname, peer->username);
@@ -2048,6 +2067,7 @@ static int auto_congest(void *nothing)
        ast_mutex_lock(&p->lock);
        p->initid = -1;
        if (p->owner) {
+               /* XXX fails on possible deadlock */
                if (!ast_mutex_trylock(&p->owner->lock)) {
                        ast_log(LOG_NOTICE, "Auto-congesting %s\n", p->owner->name);
                        ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
@@ -2214,9 +2234,8 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
        /* remove all current packets in this dialog */
        while((cp = p->packets)) {
                p->packets = p->packets->next;
-               if (cp->retransid > -1) {
+               if (cp->retransid > -1)
                        ast_sched_del(sched, cp->retransid);
-               }
                free(cp);
        }
        if (p->chanvars) {
@@ -2685,16 +2704,18 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
         Basically update any ->owner links */
 static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
 {
+       int ret = -1;
        struct sip_pvt *p = newchan->tech_pvt;
+
        ast_mutex_lock(&p->lock);
-       if (p->owner != oldchan) {
+       if (p->owner != oldchan)
                ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
-               ast_mutex_unlock(&p->lock);
-               return -1;
+       else {
+               p->owner = newchan;
+               ret = 0;
        }
-       p->owner = newchan;
        ast_mutex_unlock(&p->lock);
-       return 0;
+       return ret;
 }
 
 /*! \brief Send DTMF character on SIP channel