aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2010-11-11 21:12:27 +0000
committerjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2010-11-11 21:12:27 +0000
commitfed18e5fa383988cd9d99413812d0fb781106543 (patch)
tree842a323e23d138f61ac684745f2ad7957698498f
parent70be34aa120cbe1e110718dbd47022549ac99035 (diff)
Fix problem with qualify option packets for realtime peers never stopping.
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: http://svn.digium.com/svn/asterisk/branches/1.4@294688 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_sip.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 37206448a..e5a97ae3d 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -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)