handle expires 0 and wait for last NOTIFY

This commit is contained in:
Richard Aas 2011-12-20 11:59:26 +00:00
parent a36ecce4e0
commit 3ebaf443d3
3 changed files with 67 additions and 17 deletions

View file

@ -210,12 +210,14 @@ static void notify_handler(struct sipevent_sock *sock,
case SIPEVENT_PENDING:
sub->subscribed = true;
if (!sub->terminated && pl_isset(&state.expires))
if (!sub->terminated && !sub->termwait &&
pl_isset(&state.expires))
sipsub_reschedule(sub, pl_u32(&state.expires) * 900);
break;
case SIPEVENT_TERMINATED:
sub->subscribed = false;
sub->termconf = true;
break;
}
@ -228,8 +230,18 @@ static void notify_handler(struct sipevent_sock *sock,
if (nrefs == 1)
return;
if (!sub->terminated && state.state == SIPEVENT_TERMINATED)
sipsub_terminate(sub, 0, msg, &state);
if (state.state == SIPEVENT_TERMINATED) {
if (!sub->terminated) {
sub->termwait = false;
sipsub_terminate(sub, 0, msg, &state);
}
else if (sub->termwait) {
sub->termwait = false;
tmr_cancel(&sub->tmr);
mem_deref(sub);
}
}
}

View file

@ -79,6 +79,8 @@ struct sipsub {
uint32_t failc;
bool subscribed;
bool terminated;
bool termconf;
bool termwait;
bool refer;
};

View file

@ -23,6 +23,7 @@ enum {
DEFAULT_EXPIRES = 3600,
RESUB_FAIL_WAIT = 60000,
RESUB_FAILC_MAX = 7,
NOTIFY_TIMEOUT = 10000,
};
@ -56,12 +57,19 @@ static bool terminate(struct sipsub *sub)
sub->notifyh = internal_notify_handler;
sub->closeh = internal_close_handler;
if (sub->termwait) {
mem_ref(sub);
return true;
}
tmr_cancel(&sub->tmr);
if (sub->req) {
mem_ref(sub);
return true;
}
if (sub->subscribed && !request(sub, true)) {
if (sub->expires && sub->subscribed && !request(sub, true)) {
mem_ref(sub);
return true;
}
@ -74,14 +82,13 @@ static void destructor(void *arg)
{
struct sipsub *sub = arg;
tmr_cancel(&sub->tmr);
if (!sub->terminated) {
if (terminate(sub))
return;
}
tmr_cancel(&sub->tmr);
hash_unlink(&sub->he);
mem_deref(sub->req);
mem_deref(sub->dlg);
@ -96,6 +103,21 @@ static void destructor(void *arg)
}
static void notify_timeout_handler(void *arg)
{
struct sipsub *sub = arg;
re_printf("timeout waiting for NOTIFY\n");
sub->termwait = false;
if (sub->terminated)
mem_deref(sub);
else
sipsub_terminate(sub, ETIMEDOUT, NULL, NULL);
}
static void tmr_handler(void *arg)
{
struct sipsub *sub = arg;
@ -133,7 +155,6 @@ void sipsub_terminate(struct sipsub *sub, int err, const struct sip_msg *msg,
closeh = sub->closeh;
arg = sub->arg;
tmr_cancel(&sub->tmr);
(void)terminate(sub);
closeh(err, msg, substate, arg);
@ -198,9 +219,20 @@ static void response_handler(int err, const struct sip_msg *msg, void *arg)
(void)sip_dialog_update(sub->dlg, msg);
}
sub->subscribed = true;
if (!sub->termconf)
sub->subscribed = true;
sub->failc = 0;
if (!sub->expires && !sub->termconf) {
re_printf("waiting for last NOTIFY\n");
tmr_start(&sub->tmr, NOTIFY_TIMEOUT,
notify_timeout_handler, sub);
sub->termwait = true;
return;
}
if (sub->terminated)
goto out;
@ -263,11 +295,9 @@ static void response_handler(int err, const struct sip_msg *msg, void *arg)
out:
sub->refer = false;
if (!sub->expires) {
mem_deref(sub);
}
else if (sub->terminated) {
if (!sub->subscribed || request(sub, true))
if (sub->terminated) {
if (!sub->expires || !sub->subscribed || request(sub, true))
mem_deref(sub);
}
else {
@ -301,9 +331,6 @@ static int print_event(struct re_printf *pf, const struct sipsub *sub)
static int request(struct sipsub *sub, bool reset_ls)
{
if (sub->terminated)
sub->expires = 0;
if (reset_ls)
sip_loopstate_reset(&sub->ls);
@ -320,6 +347,9 @@ static int request(struct sipsub *sub, bool reset_ls)
sub->refer_hdrs);
}
else {
if (sub->terminated)
sub->expires = 0;
return sip_drequestf(&sub->req, sub->sip, true, "SUBSCRIBE",
sub->dlg, 0, sub->auth,
send_handler, response_handler, sub,
@ -349,7 +379,7 @@ static int sipsub_alloc(struct sipsub **subp, struct sipevent_sock *sock,
struct sipsub *sub;
int err;
if (!subp || !sock || !event || !expires || !cuser)
if (!subp || !sock || !event || !cuser)
return EINVAL;
if (!dlg && (!uri || !from_uri))
@ -635,6 +665,12 @@ int sipevent_fork(struct sipsub **subp, struct sipsub *osub,
sub->closeh = closeh ? closeh : internal_close_handler;
sub->arg = arg;
if (!sub->expires) {
tmr_start(&sub->tmr, NOTIFY_TIMEOUT,
notify_timeout_handler, sub);
sub->termwait = true;
}
out:
if (err)
mem_deref(sub);