]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Back out changes from revision 97077, since it wasn't perfect
authorTilghman Lesher <tilghman@meg.abyt.es>
Fri, 11 Jan 2008 15:52:31 +0000 (15:52 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Fri, 11 Jan 2008 15:52:31 +0000 (15:52 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@98164 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index dce4f799d66401f20f0317d40c07169922ad9536..92c1389101671642d9e2a5f79743d93b1f0813f8 100644 (file)
@@ -150,7 +150,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/threadstorage.h"
 #include "asterisk/translate.h"
 #include "asterisk/dnsmgr.h"
-#include "asterisk/astobj2.h"
 
 #ifndef FALSE
 #define FALSE    0
@@ -1008,7 +1007,7 @@ static struct sip_pvt {
        struct sip_registry *registry;          /*!< If this is a REGISTER dialog, to which registry */
        struct ast_rtp *rtp;                    /*!< RTP Session */
        struct ast_rtp *vrtp;                   /*!< Video RTP session */
-       struct ao2_container *packets;          /*!< Packets scheduled for re-transmission */
+       struct sip_pkt *packets;                /*!< Packets scheduled for re-transmission */
        struct sip_history_head *history;       /*!< History of this SIP dialog */
        size_t history_entries;                 /*!< Number of entires in the history */
        struct ast_variable *chanvars;          /*!< Channel variables to set for inbound call */
@@ -1025,6 +1024,7 @@ static struct sip_pvt {
 
 /*! \brief sip packet - raw format for outbound packets that are sent or scheduled for transmission */
 struct sip_pkt {
+       struct sip_pkt *next;                   /*!< Next packet in linked list */
        int retrans;                            /*!< Retransmission number */
        int method;                             /*!< SIP method for this packet */
        int seqno;                              /*!< Sequence number */
@@ -1852,7 +1852,7 @@ static void append_history_va(struct sip_pvt *p, const char *fmt, va_list ap)
        if (!(hist = ast_calloc(1, sizeof(*hist) + l)))
                return;
        if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) {
-               ast_free(hist);
+               free(hist);
                return;
        }
        memcpy(hist->event, buf, l);
@@ -1889,15 +1889,12 @@ static void append_history_full(struct sip_pvt *p, const char *fmt, ...)
 /*! \brief Retransmit SIP message if no answer (Called from scheduler) */
 static int retrans_pkt(const void *data)
 {
-       struct sip_pkt *pkt = (struct sip_pkt *)data, *prev;
+       struct sip_pkt *pkt = (struct sip_pkt *)data, *prev, *cur = NULL;
        int reschedule = DEFAULT_RETRANS;
        int xmitres = 0;
 
-       ao2_ref(pkt, 1); /* Make sure this cannot go away while we're using it */
-
        /* Lock channel PVT */
-       if (pkt->owner)
-               ast_mutex_lock(&pkt->owner->lock);
+       ast_mutex_lock(&pkt->owner->lock);
 
        if (pkt->retrans < MAX_RETRANS) {
                pkt->retrans++;
@@ -1925,7 +1922,7 @@ static int retrans_pkt(const void *data)
                                ast_log(LOG_DEBUG, "** SIP timers: Rescheduling retransmission %d to %d ms (t1 %d ms (Retrans id #%d)) \n", pkt->retrans +1, siptimer_a, pkt->timer_t1, pkt->retransid);
                } 
 
-               if (pkt->owner && sip_debug_test_pvt(pkt->owner)) {
+               if (sip_debug_test_pvt(pkt->owner)) {
                        const struct sockaddr_in *dst = sip_real_dst(pkt->owner);
                        ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
                                pkt->retrans, sip_nat_mode(pkt->owner),
@@ -1935,43 +1932,38 @@ static int retrans_pkt(const void *data)
 
                append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data);
                xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
-               if (pkt->owner)
-                       ast_mutex_unlock(&pkt->owner->lock);
+               ast_mutex_unlock(&pkt->owner->lock);
                if (xmitres == XMIT_ERROR)
-                       ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner ? pkt->owner->callid : "<unknown>");
-               else {
-                       ao2_ref(pkt, -1);
+                       ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner->callid);
+               else
                        return  reschedule;
-               }
        } 
        /* Too many retries */
        if (pkt->owner && pkt->method != SIP_OPTIONS && xmitres == 0) {
                if (ast_test_flag(pkt, FLAG_FATAL) || sipdebug) /* Tell us if it's critical or if we're debugging */
                        ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s)\n", pkt->owner->callid, pkt->seqno, (ast_test_flag(pkt, FLAG_FATAL)) ? "Critical" : "Non-critical", (ast_test_flag(pkt, FLAG_RESPONSE)) ? "Response" : "Request");
-       } else if (pkt->owner && (pkt->method == SIP_OPTIONS) && sipdebug) {
-               ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) \n", pkt->owner->callid);
+       } else if ((pkt->method == SIP_OPTIONS) && sipdebug) {
+                       ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) \n", pkt->owner->callid);
        }
-       if (pkt->owner) {
-               if (xmitres == XMIT_ERROR) {
-                       ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission of transaction in call id %s \n", pkt->owner->callid);
-                       append_history(pkt->owner, "XmitErr", "%s", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)");
-               } else
-                       append_history(pkt->owner, "MaxRetries", "%s", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)");
-       }
+       if (xmitres == XMIT_ERROR) {
+               ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission of transaction in call id %s \n", pkt->owner->callid);
+               append_history(pkt->owner, "XmitErr", "%s", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)");
+       } else
+               append_history(pkt->owner, "MaxRetries", "%s", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)");
+               
        pkt->retransid = -1;
 
        if (ast_test_flag(pkt, FLAG_FATAL)) {
-               while (pkt->owner && pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) {
+               while(pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) {
                        ast_mutex_unlock(&pkt->owner->lock);    /* SIP_PVT, not channel */
                        usleep(1);
-                       if (pkt->owner)
-                               ast_mutex_lock(&pkt->owner->lock);
+                       ast_mutex_lock(&pkt->owner->lock);
                }
 
-               if (pkt->owner && pkt->owner->owner && !pkt->owner->owner->hangupcause) 
+               if (pkt->owner->owner && !pkt->owner->owner->hangupcause) 
                        pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE;
                
-               if (pkt->owner && pkt->owner->owner) {
+               if (pkt->owner->owner) {
                        sip_alreadygone(pkt->owner);
                        ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet.\n", pkt->owner->callid);
                        ast_queue_hangup(pkt->owner->owner);
@@ -1980,7 +1972,7 @@ static int retrans_pkt(const void *data)
                        /* If no channel owner, destroy now */
 
                        /* Let the peerpoke system expire packets when the timer expires for poke_noanswer */
-                       if (pkt->owner && pkt->method != SIP_OPTIONS) {
+                       if (pkt->method != SIP_OPTIONS) {
                                ast_set_flag(&pkt->owner->flags[0], SIP_NEEDDESTROY);   
                                sip_alreadygone(pkt->owner);
                                if (option_debug)
@@ -1989,7 +1981,7 @@ static int retrans_pkt(const void *data)
                }
        }
 
-       if (pkt->owner && pkt->method == SIP_BYE) {
+       if (pkt->method == SIP_BYE) {
                /* We're not getting answers on SIP BYE's.  Tear down the call anyway. */
                if (pkt->owner->owner) 
                        ast_channel_unlock(pkt->owner->owner);
@@ -1998,23 +1990,23 @@ static int retrans_pkt(const void *data)
        }
 
        /* In any case, go ahead and remove the packet */
-       if (pkt->owner && (prev = ao2_find(pkt->owner->packets, pkt, OBJ_UNLINK | OBJ_POINTER))) {
-               /* Destroy the container's reference (inherited) */
-               ao2_ref(prev, -1);
+       for (prev = NULL, cur = pkt->owner->packets; cur; prev = cur, cur = cur->next) {
+               if (cur == pkt)
+                       break;
+       }
+       if (cur) {
+               if (prev)
+                       prev->next = cur->next;
+               else
+                       pkt->owner->packets = cur->next;
                ast_mutex_unlock(&pkt->owner->lock);
-               /* Now destroy our initial reference */
-               ao2_ref(pkt, -1);
-               /* And destroy the sched ref */
-               ao2_ref(pkt, -1);
-               return 0;
-       } else {
+               free(cur);
+               pkt = NULL;
+       } else
                ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
-               if (pkt->owner)
-                       ast_mutex_unlock(&pkt->owner->lock);
-               ao2_ref(pkt, -1); /* Initial ref */
-               ao2_ref(pkt, -1); /* Sched ref */
-               return 0;
-       }
+       if (pkt)
+               ast_mutex_unlock(&pkt->owner->lock);
+       return 0;
 }
 
 /*! \brief Transmit packet with retransmits 
@@ -2026,11 +2018,12 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
        int siptimer_a = DEFAULT_RETRANS;
        int xmitres = 0;
 
-       if (!(pkt = ao2_alloc(sizeof(*pkt) + len + 1, ast_free)))
+       if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1)))
                return AST_FAILURE;
        memcpy(pkt->data, data, len);
        pkt->method = sipmethod;
        pkt->packetlen = len;
+       pkt->next = p->packets;
        pkt->owner = p;
        pkt->seqno = seqno;
        if (resp)
@@ -2042,9 +2035,12 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
        if (pkt->timer_t1)
                siptimer_a = pkt->timer_t1 * 2;
 
+       /* Schedule retransmission */
+       pkt->retransid = ast_sched_add_variable(sched, siptimer_a, retrans_pkt, pkt, 1);
        if (option_debug > 3 && sipdebug)
                ast_log(LOG_DEBUG, "*** SIP TIMER: Initializing retransmit timer on packet: Id  #%d\n", pkt->retransid);
-
+       pkt->next = p->packets;
+       p->packets = pkt;
        if (sipmethod == SIP_INVITE) {
                /* Note this is a pending invite */
                p->pendinginvite = seqno;
@@ -2054,25 +2050,11 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
 
        if (xmitres == XMIT_ERROR) {    /* Serious network trouble, no need to try again */
                append_history(pkt->owner, "XmitErr", "%s", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)");
+               ast_sched_del(sched, pkt->retransid);   /* No more retransmission */
                pkt->retransid = -1;
-               ao2_ref(pkt, -1);       /* and deallocate */
                return AST_FAILURE;
-       } else {
-               /* Add refcount for scheduler pointer */
-               ao2_ref(pkt, 1);
-               /* Schedule retransmission */
-               pkt->retransid = ast_sched_add_variable(sched, siptimer_a, retrans_pkt, pkt, 1);
-               /* Link into the list of packets */
-               ao2_link(p->packets, pkt);
+       } else
                return AST_SUCCESS;
-       }
-}
-
-static int __deref_ao2_owner_cb(void *obj, void *unused, int flags)
-{
-       struct sip_pkt *pkt = obj;
-       pkt->owner = NULL;
-       return 0;
 }
 
 /*! \brief Kill a SIP dialog (called by scheduler) */
@@ -2086,15 +2068,16 @@ static int __sip_autodestruct(const void *data)
                p->subscribed = NONE;
                append_history(p, "Subscribestatus", "timeout");
                if (option_debug > 2)
-                       ast_log(LOG_DEBUG, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>");
+                       ast_log(LOG_DEBUG, "Re-scheduled destruction of SIP subsription %s\n", p->callid ? p->callid : "<unknown>");
                return 10000;   /* Reschedule this destruction so that we know that it's gone */
        }
 
-       /* If there are packets still waiting for delivery, make sure they can't callback to us anymore. */
-       if (ao2_container_count(p->packets)) {
-               ast_mutex_lock(&p->lock);
-               ao2_callback(p->packets, 0, __deref_ao2_owner_cb, NULL);
-               ast_mutex_unlock(&p->lock);
+       /* If there are packets still waiting for delivery, delay the destruction */
+       if (p->packets) {
+               if (option_debug > 2)
+                       ast_log(LOG_DEBUG, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
+               append_history(p, "ReliableXmit", "timeout");
+               return 10000;
        }
 
        /* If we're destroying a subscription, dereference peer object too */
@@ -2151,8 +2134,7 @@ static void sip_cancel_destroy(struct sip_pvt *p)
 /*! \brief Acknowledges receipt of a packet and stops retransmission */
 static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod)
 {
-       struct sip_pkt *cur;
-       struct ao2_iterator ao2i;
+       struct sip_pkt *cur, *prev = NULL;
 
        /* Just in case... */
        char *msg;
@@ -2161,8 +2143,7 @@ static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod)
        msg = sip_methods[sipmethod].text;
 
        ast_mutex_lock(&p->lock);
-       ao2i = ao2_iterator_init(p->packets, 0);
-       while ((cur = ao2_iterator_next(&ao2i))) {
+       for (cur = p->packets; cur; prev = 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)))) {
@@ -2173,68 +2154,59 @@ static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod)
                        }
                        /* this is our baby */
                        res = TRUE;
+                       UNLINK(cur, p->packets, prev);
                        if (cur->retransid > -1) {
                                if (sipdebug && option_debug > 3)
                                        ast_log(LOG_DEBUG, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid);
-                               if (!ast_sched_del(sched, cur->retransid))
-                                       ao2_ref(cur, -1); /* scheduler deref */
+                               ast_sched_del(sched, cur->retransid);
                                cur->retransid = -1;
                        }
-
-                       /* Remove it from the list */
-                       ao2_unlink(p->packets, cur);
-                       ao2_ref(cur, -1); /* iterator deref */
+                       free(cur);
                        break;
                }
-
-               ao2_ref(cur, -1); /* iterator deref */
        }
        ast_mutex_unlock(&p->lock);
        if (option_debug)
                ast_log(LOG_DEBUG, "Stopping retransmission on '%s' of %s %d: Match %s\n", p->callid, resp ? "Response" : "Request", seqno, res ? "Not Found" : "Found");
 }
 
-static int __sip_pretend_ack_cb(void *obj, void *vp, int flags)
-{
-       struct sip_pvt *p = vp;
-       struct sip_pkt *pkt = obj;
-       __sip_ack(p, pkt->seqno, ast_test_flag(pkt, FLAG_RESPONSE), pkt->method ? pkt->method : find_sip_method(pkt->data));
-       return 0;
-}
-
-/*! \brief Pretend to ack all packets */
+/*! \brief Pretend to ack all packets
+ * maybe the lock on p is not strictly necessary but there might be a race */
 static void __sip_pretend_ack(struct sip_pvt *p)
 {
-       ao2_callback(p->packets, 0, __sip_pretend_ack_cb, p);
+       struct sip_pkt *cur = NULL;
+
+       while (p->packets) {
+               int method;
+               if (cur == p->packets) {
+                       ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text);
+                       return;
+               }
+               cur = p->packets;
+               method = (cur->method) ? cur->method : find_sip_method(cur->data);
+               __sip_ack(p, cur->seqno, ast_test_flag(cur, FLAG_RESPONSE), method);
+       }
 }
 
 /*! \brief Acks receipt of packet, keep it around (used for provisional responses) */
 static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod)
 {
-       struct sip_pkt *cur, *found;
+       struct sip_pkt *cur;
        int res = -1;
-       struct ao2_iterator ao2i;
 
-       ao2i = ao2_iterator_init(p->packets, 0);
-       while ((cur = ao2_iterator_next(&ao2i))) {
+       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, sip_methods[sipmethod].text);
-                               if (!ast_sched_del(sched, cur->retransid))
-                                       ao2_ref(cur, -1); /* scheduler deref */
+                               ast_sched_del(sched, cur->retransid);
                                cur->retransid = -1;
                        }
                        res = 0;
-                       /* Now remove it from the packet list. */
-                       if ((found = ao2_find(p->packets, cur, OBJ_UNLINK | OBJ_POINTER)))
-                               ao2_ref(found, -1); /* container item deref */
-                       ao2_ref(cur, -1); /* iterator deref */
                        break;
                }
-               ao2_ref(cur, -1); /* iterator deref */
        }
        if (option_debug)
                ast_log(LOG_DEBUG, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %d: %s\n", p->callid, resp ? "Response" : "Request", seqno, res ? "Not Found" : "Found");
@@ -3080,21 +3052,11 @@ static void sip_registry_destroy(struct sip_registry *reg)
        
 }
 
-static int __sip_destroy_packet_cb(void *obj, void *unused, int flags)
-{
-       struct sip_pkt *pkt = obj;
-       if (pkt->retransid > -1) {
-               if (!ast_sched_del(sched, pkt->retransid))
-                       ao2_ref(pkt, -1); /* scheduler deref */
-       }
-       pkt->owner = NULL;
-       return 0;
-}
-
 /*! \brief Execute destruction of SIP dialog structure, release memory */
 static void __sip_destroy(struct sip_pvt *p, int lockowner)
 {
        struct sip_pvt *cur, *prev = NULL;
+       struct sip_pkt *cp;
 
        if (sip_debug_test_pvt(p) || option_debug > 2)
                ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
@@ -3113,7 +3075,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
                sip_dump_history(p);
 
        if (p->options)
-               ast_free(p->options);
+               free(p->options);
 
        if (p->stateid > -1)
                ast_extension_state_del(p->stateid, NULL);
@@ -3131,7 +3093,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
        if (p->udptl)
                ast_udptl_destroy(p->udptl);
        if (p->refer)
-               ast_free(p->refer);
+               free(p->refer);
        if (p->route) {
                free_old_route(p->route);
                p->route = NULL;
@@ -3156,7 +3118,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
        if (p->history) {
                struct sip_history *hist;
                while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) {
-                       ast_free(hist);
+                       free(hist);
                        p->history_entries--;
                }
                free(p->history);
@@ -3175,8 +3137,12 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
        } 
 
        /* remove all current packets in this dialog */
-       ao2_callback(p->packets, 0, __sip_destroy_packet_cb, NULL);
-
+       while((cp = p->packets)) {
+               p->packets = p->packets->next;
+               if (cp->retransid > -1)
+                       ast_sched_del(sched, cp->retransid);
+               free(cp);
+       }
        if (p->chanvars) {
                ast_variables_destroy(p->chanvars);
                p->chanvars = NULL;
@@ -3185,7 +3151,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
 
        ast_string_field_free_memory(p);
 
-       ast_free(p);
+       free(p);
 }
 
 /*! \brief  update_call_counter: Handle call_limit for SIP users 
@@ -4425,40 +4391,17 @@ static void make_our_tag(char *tagbuf, size_t len)
        snprintf(tagbuf, len, "as%08lx", ast_random());
 }
 
-static int packet_hash_fn(const void *obj, const int flags)
-{
-       const struct sip_pkt *pkt = obj;
-       return pkt->seqno;
-}
-
-static int packet_cmp_fn(void *obj1, void *obj2, int flags)
-{
-       struct sip_pkt *p1 = obj1, *p2 = obj2;
-
-       if (flags & OBJ_POINTER)
-               return p1 == p2 ? CMP_MATCH : 0;
-       else
-               return p1->seqno == p2->seqno ? CMP_MATCH : 0;
-}
-
 /*! \brief Allocate SIP_PVT structure and set defaults */
 static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
                                 int useglobal_nat, const int intended_method)
 {
        struct sip_pvt *p;
-       struct ao2_container *aoc;
 
-       if (!(aoc = ao2_container_alloc(37, packet_hash_fn, packet_cmp_fn)))
+       if (!(p = ast_calloc(1, sizeof(*p))))
                return NULL;
 
-       if (!(p = ast_calloc(1, sizeof(*p)))) {
-               ao2_ref(aoc, -1);
-               return NULL;
-       }
-
        if (ast_string_field_init(p, 512)) {
-               ao2_ref(aoc, -1);
-               ast_free(p);
+               free(p);
                return NULL;
        }
 
@@ -4471,7 +4414,6 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
        p->subscribed = NONE;
        p->stateid = -1;
        p->prefs = default_prefs;               /* Set default codecs for this call */
-       p->packets = aoc;
 
        if (intended_method != SIP_OPTIONS)     /* Peerpoke has it's own system */
                p->timer_t1 = 500;      /* Default SIP retransmission timer T1 (RFC 3261) */
@@ -15626,7 +15568,7 @@ restartsearch:
                                }
                        }
                        /* If we have sessions that needs to be destroyed, do it now */
-                       if (ast_test_flag(&sip->flags[0], SIP_NEEDDESTROY) && !ao2_container_count(sip->packets) &&
+                       if (ast_test_flag(&sip->flags[0], SIP_NEEDDESTROY) && !sip->packets &&
                            !sip->owner) {
                                ast_mutex_unlock(&sip->lock);
                                __sip_destroy(sip, 1);