Mailbox list would previously grow at each reload, containing duplicates.
authorTilghman Lesher <tilghman@meg.abyt.es>
Mon, 7 Jun 2010 22:47:13 +0000 (22:47 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Mon, 7 Jun 2010 22:47:13 +0000 (22:47 +0000)
Also, optimize the allocation of mailboxes to avoid additional memory structures.

(closes issue #16320)
 Reported by: Marquis
 Patches:
       20100525__issue16320.diff.txt uploaded by tilghman (license 14)

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

channels/chan_sip.c
channels/sip/include/sip.h

index d7b6c18..d65471d 100644 (file)
@@ -4145,10 +4145,6 @@ static void register_peer_exten(struct sip_peer *peer, int onoff)
 /*! Destroy mailbox subscriptions */
 static void destroy_mailbox(struct sip_mailbox *mailbox)
 {
-       if (mailbox->mailbox)
-               ast_free(mailbox->mailbox);
-       if (mailbox->context)
-               ast_free(mailbox->context);
        if (mailbox->event_sub)
                ast_event_unsubscribe(mailbox->event_sub);
        ast_free(mailbox);
@@ -24933,17 +24929,35 @@ static void add_peer_mailboxes(struct sip_peer *peer, const char *value)
 
        while ((mbox = context = strsep(&next, ","))) {
                struct sip_mailbox *mailbox;
-
-               if (!(mailbox = ast_calloc(1, sizeof(*mailbox))))
-                       continue;
+               int duplicate = 0;
 
                strsep(&context, "@");
+
                if (ast_strlen_zero(mbox)) {
-                       ast_free(mailbox);
                        continue;
                }
-               mailbox->mailbox = ast_strdup(mbox);
-               mailbox->context = ast_strdup(context);
+
+               /* Check whether the mailbox is already in the list */
+               AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) {
+                       if (!strcmp(mailbox->mailbox, mbox) && !strcmp(S_OR(mailbox->context, ""), S_OR(context, ""))) {
+                               duplicate = 1;
+                               mailbox->delme = 0;
+                               break;
+                       }
+               }
+               if (duplicate) {
+                       continue;
+               }
+
+               if (!(mailbox = ast_calloc(1, sizeof(*mailbox) + strlen(mbox) + strlen(S_OR(context, ""))))) {
+                       continue;
+               }
+
+               if (!ast_strlen_zero(context)) {
+                       mailbox->context = mailbox->mailbox + strlen(mbox) + 1;
+                       strcpy(mailbox->context, context); /* SAFE */
+               }
+               strcpy(mailbox->mailbox, mbox); /* SAFE */
 
                AST_LIST_INSERT_TAIL(&peer->mailboxes, mailbox, entry);
        }
@@ -25035,6 +25049,13 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
        peer->default_outbound_transport = 0;
        peer->transports = 0;
 
+       if (!devstate_only) {
+               struct sip_mailbox *mailbox;
+               AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) {
+                       mailbox->delme = 1;
+               }
+       }
+
        for (; v || ((v = alt) && !(alt=NULL)); v = v->next) {
                if (!devstate_only) {
                        if (handle_common_options(&peerflags[0], &mask[0], v)) {
@@ -25413,6 +25434,17 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                }
        }
 
+       if (!devstate_only) {
+               struct sip_mailbox *mailbox;
+               AST_LIST_TRAVERSE_SAFE_BEGIN(&peer->mailboxes, mailbox, entry) {
+                       if (mailbox->delme) {
+                               AST_LIST_REMOVE_CURRENT(entry);
+                               ast_free(mailbox);
+                       }
+               }
+               AST_LIST_TRAVERSE_SAFE_END;
+       }
+
        if (!can_parse_xml && (ast_get_cc_agent_policy(peer->cc_params) == AST_CC_AGENT_NATIVE)) {
                ast_log(LOG_WARNING, "Peer %s has a cc_agent_policy of 'native' but required libxml2 dependency is not installed. Changing policy to 'never'\n", peer->name);
                ast_set_cc_agent_policy(peer->cc_params, AST_CC_AGENT_NEVER);
index 0ee377c..9017d7e 100644 (file)
@@ -1112,11 +1112,12 @@ struct sip_pkt {
  * too much effort ...
  */
 struct sip_mailbox {
-       char *mailbox;
-       char *context;
        /*! Associated MWI subscription */
        struct ast_event_sub *event_sub;
        AST_LIST_ENTRY(sip_mailbox) entry;
+       unsigned int delme:1;
+       char *context;
+       char mailbox[2];
 };
 
 /*! \brief Structure for SIP peer data, we place calls to peers if registered  or fixed IP address (host)