From 30e4066e7166b0116aece8d57fd9ddce47311161 Mon Sep 17 00:00:00 2001 From: markster Date: Mon, 2 Feb 2004 23:21:36 +0000 Subject: Centralize all sip registration around a single lock git-svn-id: http://svn.digium.com/svn/asterisk/trunk@2114 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 64 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index c126fd12e..0a167ec5a 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -371,7 +371,6 @@ ast_mutex_t sip_reload_lock = AST_MUTEX_INITIALIZER; #define REG_STATE_NOAUTH 6 struct sip_registry { - ast_mutex_t lock; /* Channel private lock */ struct sockaddr_in addr; /* Who we connect to for registration purposes */ char username[80]; /* Who we are registering as */ char authuser[80]; /* Who we *authenticate* as */ @@ -383,6 +382,7 @@ struct sip_registry { int expire; /* Sched ID of expiration */ int timeout; /* sched id of sip_reg_timeout */ int refresh; /* How often to refresh */ + int delme; /* Need to be deleted? */ struct sip_pvt *call; /* create a sip_pvt structure for each outbound "registration call" in progress */ int regstate; int callid_valid; /* 0 means we haven't chosen callid for this registry yet. */ @@ -405,13 +405,14 @@ static struct ast_peer_list { static struct ast_register_list { struct sip_registry *registrations; ast_mutex_t lock; + int recheck; } regl = { NULL, AST_MUTEX_INITIALIZER }; #define REINVITE_INVITE 1 #define REINVITE_UPDATE 2 -static int sip_do_register(struct sip_registry *r); +static int __sip_do_register(struct sip_registry *r); static int sipsock = -1; static int globalnat = 0; @@ -441,6 +442,7 @@ static void free_old_route(struct sip_route *route); static int build_reply_digest(struct sip_pvt *p, char *orig_header, char *digest, int digest_len); static int find_user(struct sip_pvt *fup, int event); static void prune_peers(void); +static void prune_regs(void); static int __sip_xmit(struct sip_pvt *p, char *data, int len) { @@ -3113,18 +3115,18 @@ static int sip_reregister(void *data) { /* if we are here, we know that we need to reregister. */ struct sip_registry *r=(struct sip_registry *)data; + ast_mutex_lock(®l.lock); r->expire = -1; - sip_do_register(r); + __sip_do_register(r); + ast_mutex_unlock(®l.lock); return 0; } -static int sip_do_register(struct sip_registry *r) +static int __sip_do_register(struct sip_registry *r) { int res; - ast_mutex_lock(&r->lock); res=transmit_register(r, "REGISTER", NULL, NULL); - ast_mutex_unlock(&r->lock); return res; } @@ -3134,7 +3136,7 @@ static int sip_reg_timeout(void *data) struct sip_registry *r=data; struct sip_pvt *p; int res; - ast_mutex_lock(&r->lock); + ast_mutex_lock(®l.lock); ast_log(LOG_NOTICE, "Registration for '%s@%s' timed out, trying again\n", r->username, inet_ntoa(r->addr.sin_addr)); if (r->call) { /* Unlink us, destroy old call. Locking is not relevent here because all this happens @@ -3147,7 +3149,7 @@ static int sip_reg_timeout(void *data) r->regstate=REG_STATE_UNREGISTERED; r->timeout = -1; res=transmit_register(r, "REGISTER", NULL, NULL); - ast_mutex_unlock(&r->lock); + ast_mutex_unlock(®l.lock); return 0; } @@ -5710,6 +5712,7 @@ static void *do_monitor(void *data) (and thus do not have a separate thread) indefinitely */ /* From here on out, we die whenever asked */ for(;;) { + prune_regs(); /* Check for interfaces needing to be killed */ ast_mutex_lock(&iflock); restartsearch: @@ -6627,11 +6630,41 @@ static struct ast_rtp_protocol sip_rtp = { get_codec: sip_get_codec, }; +static void prune_regs(void) +{ + struct sip_registry *reg, *next, *prev = NULL; + ast_mutex_lock(®l.lock); + if (!regl.recheck) { + ast_mutex_unlock(®l.lock); + return; + } + for (reg = regl.registrations;reg;) { + next = reg->next; + if (reg->delme) { + /* Really delete */ + if (reg->call) { + /* Clear registry before destroying to ensure + we don't get reentered trying to grab the registry lock */ + reg->call->registry = NULL; + sip_destroy(reg->call); + } + if (reg->expire > -1) + ast_sched_del(sched, reg->expire); + if (reg->timeout > -1) + ast_sched_del(sched, reg->timeout); + free(reg); + } else + prev = reg; + reg = next; + } + ast_mutex_unlock(®l.lock); +} + static void delete_users(void) { struct sip_user *user, *userlast; struct sip_peer *peer; - struct sip_registry *reg, *reglast; + struct sip_registry *reg; /* Delete all users */ ast_mutex_lock(&userl.lock); @@ -6646,17 +6679,8 @@ static void delete_users(void) ast_mutex_lock(®l.lock); for (reg = regl.registrations;reg;) { - reglast = reg; + reg->delme = 1; reg = reg->next; - if (reglast->call) { - /* Clear registry before destroying to ensure - we don't get reentered trying to grab the registry lock */ - reglast->call->registry = NULL; - sip_destroy(reglast->call); - } - if (reglast->expire > -1) - ast_sched_del(sched, reglast->expire); - free(reglast); } regl.registrations = NULL; ast_mutex_unlock(®l.lock); @@ -6715,7 +6739,7 @@ static int sip_reload(int fd, int argc, char *argv[]) restart_monitor(); ast_mutex_lock(®l.lock); for (reg = regl.registrations; reg; reg = reg->next) - sip_do_register(reg); + __sip_do_register(reg); ast_mutex_unlock(®l.lock); ast_mutex_lock(&peerl.lock); for (peer = peerl.peers; peer; peer = peer->next) -- cgit v1.2.3