diff --git a/src/modules/ims_usrloc_scscf/impurecord.c b/src/modules/ims_usrloc_scscf/impurecord.c index d7c7dde7c6f..e0ad1f7ef90 100644 --- a/src/modules/ims_usrloc_scscf/impurecord.c +++ b/src/modules/ims_usrloc_scscf/impurecord.c @@ -368,39 +368,6 @@ static inline void process_impurecord(impurecord_t* _r) { get_act_time(); - s = _r->shead; - LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s); - while (s) { - next = s->next; - if (!valid_subscriber(s, act_time)) { - LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n", - s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s); - if (!dbwork) { - start_dbtransaction(); - dbwork = 1; - } - delete_subscriber(_r, s); - } else { - LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n", - s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s, - (unsigned int) (s->expires - time(NULL))); - sl = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size); - LM_DBG("Hash size: <%i>\n", sub_dialog_hash_size); - LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>\n", s->call_id.len, s->call_id.s, s->to_tag.len, s->to_tag.s, s->from_tag.len, s->from_tag.s, sl); - /* search the record in hash table */ - lock_get(&sub_dialog_table[sl].lock); - sub_dialog = pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, sl); - if (sub_dialog == NULL) { - LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n"); - } else { - LM_DBG("DBG:registrar_timer: Subscription has dialog record in hash table with presentity uri <%.*s>\n", sub_dialog->pres_uri.len, sub_dialog->pres_uri.s); - } - lock_release(&sub_dialog_table[sl].lock); - mustdeleteimpu = 0; - } - s = next; - } - LM_DBG("\tPublic Identity %.*s, Barred: [%d], State: [%s], contacts [%d], 3gppcontacts [%d]\n", _r->public_identity.len, _r->public_identity.s, _r->barring, @@ -422,9 +389,9 @@ static inline void process_impurecord(impurecord_t* _r) { num_contacts_to_expire++; } else if (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) { LM_DBG("Contact: <%.*s> is in state CONTACT_EXPIRE_PENDING_NOTIFY....running callback\n", ptr->c.len, ptr->c.s); - if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) { - LM_DBG("Running callback UL_IMPU_DELETE_CONTACT for contact [%.*s] and impu [%.*s]\n", ptr->c.len, ptr->c.s, _r->public_identity.len, _r->public_identity.s); - run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, ptr); + if (exists_ulcb_type(_r->cbs, UL_IMPU_EXPIRE_CONTACT)) { + LM_DBG("Running callback UL_IMPU_EXPIRE_CONTACT for contact [%.*s] and impu [%.*s]\n", ptr->c.len, ptr->c.s, _r->public_identity.len, _r->public_identity.s); + run_ul_callbacks(_r->cbs, UL_IMPU_EXPIRE_CONTACT, _r, ptr); } hascontacts = 1; // we do this because the impu must only be deleted if in state deleted.... mustdeleteimpu = 0; @@ -463,6 +430,39 @@ static inline void process_impurecord(impurecord_t* _r) { } } + s = _r->shead; + LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s); + while (s) { + next = s->next; + if (!valid_subscriber(s, act_time)) { + LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n", + s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s); + if (!dbwork) { + start_dbtransaction(); + dbwork = 1; + } + delete_subscriber(_r, s); + } else { + LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n", + s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s, + (unsigned int) (s->expires - time(NULL))); + sl = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size); + LM_DBG("Hash size: <%i>\n", sub_dialog_hash_size); + LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>\n", s->call_id.len, s->call_id.s, s->to_tag.len, s->to_tag.s, s->from_tag.len, s->from_tag.s, sl); + /* search the record in hash table */ + lock_get(&sub_dialog_table[sl].lock); + sub_dialog = pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, sl); + if (sub_dialog == NULL) { + LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n"); + } else { + LM_DBG("DBG:registrar_timer: Subscription has dialog record in hash table with presentity uri <%.*s>\n", sub_dialog->pres_uri.len, sub_dialog->pres_uri.s); + } + lock_release(&sub_dialog_table[sl].lock); + mustdeleteimpu = 0; + } + s = next; + } + if (!flag) LM_DBG("no contacts\n"); diff --git a/src/modules/ims_usrloc_scscf/udomain.c b/src/modules/ims_usrloc_scscf/udomain.c index 0379d27cbe2..3d54fe6d3c3 100644 --- a/src/modules/ims_usrloc_scscf/udomain.c +++ b/src/modules/ims_usrloc_scscf/udomain.c @@ -331,8 +331,19 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) { LM_DBG("contact in state CONTACT_DELAYED_DELETE still has a ref count of [%d] in memory. Not doing anything for now \n", contact_ptr->ref_count); } } - } else if (contact_ptr->state != CONTACT_DELETED) { - LM_DBG("expiring contact [%.*s](%.*s).... setting to CONTACT_EXPIRE_PENDING_NOTIFY\n", + } else if (contact_ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) { + LM_DBG("expired pending notify contact [%.*s](%.*s).... setting to CONTACT_NOTIFY_READY\n", + contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s); + contact_ptr->state = CONTACT_NOTIFY_READY; + expired_contacts[num_expired_contacts] = contact_ptr; + num_expired_contacts++; + } else if (contact_ptr->state == CONTACT_NOTIFY_READY) { + LM_DBG("expired notify ready contact [%.*s](%.*s).... marking for deletion\n", + contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s); + expired_contacts[num_expired_contacts] = contact_ptr; + num_expired_contacts++; + } else if (contact_ptr->state != CONTACT_DELETED) { + LM_DBG("expiring contact [%.*s](%.*s).... setting to CONTACT_EXPIRE_PENDING_NOTIFY\n", contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s); contact_ptr->state = CONTACT_EXPIRE_PENDING_NOTIFY; ref_contact_unsafe(contact_ptr); @@ -399,16 +410,22 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) { for (i=0; isl; lock_contact_slot_i(slot); - if (expired_contacts[i]->state != CONTACT_DELAYED_DELETE) { - LM_DBG("Setting contact state to CONTACT_DELETED for contact [%.*s](%.*s)\n", + if(expired_contacts[i]->state == CONTACT_EXPIRE_PENDING_NOTIFY) { + LM_DBG("Contact state CONTACT_EXPIRE_PENDING_NOTIFY for contact [%.*s](%.*s)\n", expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s); - expired_contacts[i]->state = CONTACT_DELETED; - unref_contact_unsafe(expired_contacts[i]); - } else { - LM_DBG("deleting contact [%.*s](%.*s)\n", - expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s); - delete_scontact(expired_contacts[i]); - } + } else { + if (expired_contacts[i]->state != CONTACT_DELAYED_DELETE) { + LM_DBG("Setting contact state from '%s' to CONTACT_DELETED for contact [%.*s](%.*s)\n", + get_contact_state_as_string(expired_contacts[i]->state), + expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s); + expired_contacts[i]->state = CONTACT_DELETED; + unref_contact_unsafe(expired_contacts[i]); + } else { + LM_DBG("deleting contact [%.*s](%.*s)\n", + expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s); + delete_scontact(expired_contacts[i]); + } + } unlock_contact_slot_i(slot); } } diff --git a/src/modules/ims_usrloc_scscf/usrloc.h b/src/modules/ims_usrloc_scscf/usrloc.h index 0db0f020637..8f6bcb3b1ef 100644 --- a/src/modules/ims_usrloc_scscf/usrloc.h +++ b/src/modules/ims_usrloc_scscf/usrloc.h @@ -146,11 +146,12 @@ typedef enum contact_state { CONTACT_DELETE_PENDING, CONTACT_EXPIRE_PENDING_NOTIFY, CONTACT_DELETED, - CONTACT_DELAYED_DELETE + CONTACT_DELAYED_DELETE, + CONTACT_NOTIFY_READY /**< Prevents deletion of a contact before construction of notify body */ } contact_state_t; /*! \brief Valid contact is a contact that either didn't expire yet or is permanent */ -#define VALID_CONTACT(c, t) (((c->expires>t) || (c->expires==0)) && c->state!=CONTACT_DELETED && c->state!=CONTACT_DELETE_PENDING && c->state!=CONTACT_EXPIRE_PENDING_NOTIFY && c->state!=CONTACT_DELAYED_DELETE) +#define VALID_CONTACT(c, t) (((c->expires>t) || (c->expires==0)) && c->state!=CONTACT_DELETED && c->state!=CONTACT_DELETE_PENDING && c->state!=CONTACT_EXPIRE_PENDING_NOTIFY && c->state!=CONTACT_DELAYED_DELETE && c->state!=CONTACT_NOTIFY_READY) #define VALID_UE_TYPE(c, t) ((t==0) || (t==1 && c->is_3gpp) || (t==2 && !c->is_3gpp)) @@ -405,6 +406,8 @@ static inline char* get_contact_state_as_string(enum contact_state c_state) { return "Contact deleted"; case CONTACT_DELAYED_DELETE: return "Contact with delayed delete"; + case CONTACT_NOTIFY_READY: + return "Contact expired with prepared NOTIFY"; default: return "unknown"; }