diff options
Diffstat (limited to 'modules/presence/subscriber.c')
-rw-r--r-- | modules/presence/subscriber.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/modules/presence/subscriber.c b/modules/presence/subscriber.c index 66c15a2..9cc84b1 100644 --- a/modules/presence/subscriber.c +++ b/modules/presence/subscriber.c @@ -24,6 +24,8 @@ struct presence { enum presence_status status; unsigned failc; struct contact *contact; + struct ua *ua; + bool shutdown; }; static struct list presencel; @@ -81,6 +83,9 @@ static void notify_handler(struct sip *sip, const struct sip_msg *msg, const struct sip_hdr *type_hdr, *length_hdr; struct pl pl; + if (pres->shutdown) + goto done; + pres->failc = 0; type_hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_TYPE); @@ -138,6 +143,9 @@ done: (void)sip_treply(NULL, sip, msg, 200, "OK"); contact_set_presence(pres->contact, status); + + if (pres->shutdown) + pres = mem_deref(pres); } @@ -177,10 +185,20 @@ static void destructor(void *arg) { struct presence *pres = arg; + debug("presence: subscriber destroyed\n"); + list_unlink(&pres->le); tmr_cancel(&pres->tmr); mem_deref(pres->contact); mem_deref(pres->sub); + mem_deref(pres->ua); +} + + +static void deref_handler(void *arg) +{ + struct mwi *mwi = arg; + mem_deref(mwi); } @@ -205,6 +223,9 @@ static int subscribe(struct presence *pres) return ENOENT; } + mem_deref(pres->ua); + pres->ua = mem_ref(ua); + pl_strcpy(&contact_addr(pres->contact)->auri, uri, sizeof(uri)); routev[0] = ua_outbound(ua); @@ -282,3 +303,29 @@ void subscriber_close(void) { list_flush(&presencel); } + + +void subscriber_close_all(void) +{ + struct le *le; + + info("presence: subscriber: closing %u subs\n", + list_count(&presencel)); + + le = presencel.head; + while (le) { + + struct presence *pres = le->data; + le = le->next; + + debug("presence: shutdown: sub=%p\n", pres->sub); + + pres->shutdown = true; + if (pres->sub) { + pres->sub = mem_deref(pres->sub); + tmr_start(&pres->tmr, 500, deref_handler, pres); + } + else + mem_deref(pres); + } +} |