]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix problem with qualify option packets for realtime peers never stopping.
authorJeff Peeler <jpeeler@digium.com>
Thu, 11 Nov 2010 21:12:27 +0000 (21:12 +0000)
committerJeff Peeler <jpeeler@digium.com>
Thu, 11 Nov 2010 21:12:27 +0000 (21:12 +0000)
The option packets not only never stopped, but if a realtime peer was not in
the peer list multiple options dialogs could accumulate over time. This
scenario has the potential to progress to the point of saturating a link just
from options packets. The fix was to ensure that the poke scheduler checks to
see if a peer is in the peer list before continuing to poke. The reason a peer
must be in the peer list to be able to properly manage an options dialog is
because otherwise the call pointer is lost when the peer is regenerated from
the database, which is how existing qualify dialogs are detected.

(closes issue #16382)
Reported by: lftsy
Patches:
      bug16382-3.patch uploaded by jpeeler (license 325)
Tested by: zerohalo

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

channels/chan_sip.c

index 37206448a5f95c63ff54af577d79a8614cc70a2e..e5a97ae3d1cdf7b0c6f933293c0468117f4d0dd5 100644 (file)
@@ -8617,11 +8617,22 @@ static int expire_register(const void *data)
 static int sip_poke_peer_s(const void *data)
 {
        struct sip_peer *peer = (struct sip_peer *) data;
+       struct sip_peer *foundpeer;
 
        peer->pokeexpire = -1;
 
-       sip_poke_peer(peer);
+       foundpeer = ASTOBJ_CONTAINER_FIND(&peerl, peer->name);
+       if (!foundpeer) {
+               ASTOBJ_UNREF(peer, sip_destroy_peer);
+               return 0;
+       } else if (foundpeer->name != peer->name) {
+               ASTOBJ_UNREF(foundpeer, sip_destroy_peer);
+               ASTOBJ_UNREF(peer, sip_destroy_peer);
+               return 0;
+       }
 
+       ASTOBJ_UNREF(foundpeer, sip_destroy_peer);
+       sip_poke_peer(peer);
        ASTOBJ_UNREF(peer, sip_destroy_peer);
 
        return 0;
@@ -19764,6 +19775,18 @@ static int sip_do_reload(enum channelreloadreason reason)
 {
        reload_config(reason);
 
+       /* before peers are removed from the peer container, cancel any scheduled pokes */
+       ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
+               ASTOBJ_RDLOCK(iterator);
+               if (ast_test_flag(&iterator->flags[0], SIP_REALTIME)) {
+                       if (!AST_SCHED_DEL(sched, iterator->pokeexpire)) {
+                               struct sip_peer *peer_ptr = iterator;
+                               ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+                       }
+               }
+               ASTOBJ_UNLOCK(iterator);
+       } while (0) );
+
        /* Prune peers who still are supposed to be deleted */
        ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, sip_destroy_peer);
        if (option_debug > 3)