|
@@ -74,7 +74,6 @@ extern int unreg_validity;
|
|
extern int maxcontact_behaviour;
|
|
extern int maxcontact_behaviour;
|
|
extern int maxcontact;
|
|
extern int maxcontact;
|
|
extern int db_mode;
|
|
extern int db_mode;
|
|
-extern struct ul_scscf_counters_h ul_scscf_cnts_h;
|
|
|
|
|
|
|
|
extern int sub_dialog_hash_size;
|
|
extern int sub_dialog_hash_size;
|
|
extern int subs_hash_size;
|
|
extern int subs_hash_size;
|
|
@@ -84,6 +83,9 @@ extern struct ims_subscription_list* ims_subscription_list;
|
|
|
|
|
|
extern struct dlg_binds dlgb;
|
|
extern struct dlg_binds dlgb;
|
|
|
|
|
|
|
|
+static ucontact_t* contacts_to_expire [MAX_CONTACTS_PER_IMPU]; //this is done to prevent fragmentation of memory...
|
|
|
|
+static int num_contacts_to_expire;
|
|
|
|
+
|
|
/*!
|
|
/*!
|
|
* \brief Create and initialize new record structure
|
|
* \brief Create and initialize new record structure
|
|
* \param _dom domain name
|
|
* \param _dom domain name
|
|
@@ -91,7 +93,7 @@ extern struct dlg_binds dlgb;
|
|
* \param _r pointer to the new record
|
|
* \param _r pointer to the new record
|
|
* \return 0 on success, negative on failure
|
|
* \return 0 on success, negative on failure
|
|
*/
|
|
*/
|
|
-int new_impurecord(str* _dom, str* public_identity, int reg_state, int barring, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, impurecord_t** _r) {
|
|
|
|
|
|
+int new_impurecord(str* _dom, str* public_identity, str* private_identity, int reg_state, int barring, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, impurecord_t** _r) {
|
|
*_r = (impurecord_t*) shm_malloc(sizeof (impurecord_t));
|
|
*_r = (impurecord_t*) shm_malloc(sizeof (impurecord_t));
|
|
if (*_r == 0) {
|
|
if (*_r == 0) {
|
|
LM_ERR("no more shared memory\n");
|
|
LM_ERR("no more shared memory\n");
|
|
@@ -105,8 +107,7 @@ int new_impurecord(str* _dom, str* public_identity, int reg_state, int barring,
|
|
if ((*_r)->cbs == 0) {
|
|
if ((*_r)->cbs == 0) {
|
|
LM_CRIT("no more shared mem\n");
|
|
LM_CRIT("no more shared mem\n");
|
|
shm_free(*_r);
|
|
shm_free(*_r);
|
|
- *_r = 0;
|
|
|
|
- return -2;
|
|
|
|
|
|
+ goto error;
|
|
}
|
|
}
|
|
(*_r)->cbs->first = 0;
|
|
(*_r)->cbs->first = 0;
|
|
(*_r)->cbs->reg_types = 0;
|
|
(*_r)->cbs->reg_types = 0;
|
|
@@ -115,11 +116,20 @@ int new_impurecord(str* _dom, str* public_identity, int reg_state, int barring,
|
|
if ((*_r)->public_identity.s == 0) {
|
|
if ((*_r)->public_identity.s == 0) {
|
|
LM_ERR("no more shared memory\n");
|
|
LM_ERR("no more shared memory\n");
|
|
shm_free(*_r);
|
|
shm_free(*_r);
|
|
- *_r = 0;
|
|
|
|
- return -2;
|
|
|
|
|
|
+ goto error;
|
|
}
|
|
}
|
|
memcpy((*_r)->public_identity.s, public_identity->s, public_identity->len);
|
|
memcpy((*_r)->public_identity.s, public_identity->s, public_identity->len);
|
|
(*_r)->public_identity.len = public_identity->len;
|
|
(*_r)->public_identity.len = public_identity->len;
|
|
|
|
+
|
|
|
|
+ (*_r)->private_identity.s = (char*) shm_malloc(private_identity->len);
|
|
|
|
+ if ((*_r)->private_identity.s == 0) {
|
|
|
|
+ LM_ERR("no more shared memory\n");
|
|
|
|
+ shm_free(*_r);
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ memcpy((*_r)->private_identity.s, private_identity->s, private_identity->len);
|
|
|
|
+ (*_r)->private_identity.len = private_identity->len;
|
|
|
|
+
|
|
(*_r)->domain = _dom;
|
|
(*_r)->domain = _dom;
|
|
(*_r)->aorhash = core_hash(public_identity, 0, 0);
|
|
(*_r)->aorhash = core_hash(public_identity, 0, 0);
|
|
(*_r)->reg_state = reg_state;
|
|
(*_r)->reg_state = reg_state;
|
|
@@ -133,15 +143,20 @@ int new_impurecord(str* _dom, str* public_identity, int reg_state, int barring,
|
|
if (ecf2 && ecf2->len > 0) STR_SHM_DUP((*_r)->ecf2, *ecf2, "ECF2");
|
|
if (ecf2 && ecf2->len > 0) STR_SHM_DUP((*_r)->ecf2, *ecf2, "ECF2");
|
|
/*assign ims subscription profile*/
|
|
/*assign ims subscription profile*/
|
|
if (s && *s) {
|
|
if (s && *s) {
|
|
- ref_subscription_unsafe(*s);
|
|
|
|
- (*_r)->s = *s;
|
|
|
|
|
|
+ ref_subscription_unsafe(*s);
|
|
|
|
+ (*_r)->s = *s;
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
out_of_memory:
|
|
out_of_memory:
|
|
LM_ERR("no more shared memory\n");
|
|
LM_ERR("no more shared memory\n");
|
|
|
|
+ *_r = 0;
|
|
return -3;
|
|
return -3;
|
|
|
|
+error:
|
|
|
|
+ LM_ERR("Failed to create new impurecord...\n");
|
|
|
|
+ *_r = 0;
|
|
|
|
+ return -2;
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
/*!
|
|
@@ -167,7 +182,7 @@ void free_impurecord(impurecord_t* _r) {
|
|
if (_r->ecf2.s)
|
|
if (_r->ecf2.s)
|
|
shm_free(_r->ecf2.s);
|
|
shm_free(_r->ecf2.s);
|
|
if (_r->s) {
|
|
if (_r->s) {
|
|
- unref_subscription_unsafe(_r->s);
|
|
|
|
|
|
+ unref_subscription(_r->s);
|
|
}
|
|
}
|
|
|
|
|
|
/*remove REG subscriptions to this IMPU*/
|
|
/*remove REG subscriptions to this IMPU*/
|
|
@@ -177,10 +192,14 @@ void free_impurecord(impurecord_t* _r) {
|
|
free_subscriber(subscriber);
|
|
free_subscriber(subscriber);
|
|
subscriber = s_tmp;
|
|
subscriber = s_tmp;
|
|
}
|
|
}
|
|
|
|
+ _r->shead = 0;
|
|
|
|
|
|
if (_r->public_identity.s)
|
|
if (_r->public_identity.s)
|
|
shm_free(_r->public_identity.s);
|
|
shm_free(_r->public_identity.s);
|
|
|
|
|
|
|
|
+ if (_r->private_identity.s)
|
|
|
|
+ shm_free(_r->private_identity.s);
|
|
|
|
+
|
|
//free callback list
|
|
//free callback list
|
|
for (cbp = _r->cbs->first; cbp;) {
|
|
for (cbp = _r->cbs->first; cbp;) {
|
|
cbp_tmp = cbp;
|
|
cbp_tmp = cbp;
|
|
@@ -190,8 +209,6 @@ void free_impurecord(impurecord_t* _r) {
|
|
shm_free(cbp_tmp);
|
|
shm_free(cbp_tmp);
|
|
}
|
|
}
|
|
shm_free(_r->cbs);
|
|
shm_free(_r->cbs);
|
|
-
|
|
|
|
-
|
|
|
|
shm_free(_r);
|
|
shm_free(_r);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -203,7 +220,7 @@ void free_impurecord(impurecord_t* _r) {
|
|
void print_impurecord(FILE* _f, impurecord_t* _r) {
|
|
void print_impurecord(FILE* _f, impurecord_t* _r) {
|
|
ucontact_t* ptr;
|
|
ucontact_t* ptr;
|
|
int i;
|
|
int i;
|
|
-
|
|
|
|
|
|
+
|
|
fprintf(_f, "...Record(%p)...\n", _r);
|
|
fprintf(_f, "...Record(%p)...\n", _r);
|
|
fprintf(_f, "domain : '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));
|
|
fprintf(_f, "domain : '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));
|
|
fprintf(_f, "public_identity : '%.*s'\n", _r->public_identity.len, ZSW(_r->public_identity.s));
|
|
fprintf(_f, "public_identity : '%.*s'\n", _r->public_identity.len, ZSW(_r->public_identity.s));
|
|
@@ -233,7 +250,7 @@ void print_impurecord(FILE* _f, impurecord_t* _r) {
|
|
}
|
|
}
|
|
|
|
|
|
if (_r->newcontacts[0]) {
|
|
if (_r->newcontacts[0]) {
|
|
- while ((ptr=_r->newcontacts[i++])) {
|
|
|
|
|
|
+ while ((ptr = _r->newcontacts[i++])) {
|
|
print_ucontact(_f, ptr);
|
|
print_ucontact(_f, ptr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -254,16 +271,16 @@ void print_impurecord(FILE* _f, impurecord_t* _r) {
|
|
ucontact_t* mem_insert_ucontact(impurecord_t* _r, str* _c, ucontact_info_t* _ci) {
|
|
ucontact_t* mem_insert_ucontact(impurecord_t* _r, str* _c, ucontact_info_t* _ci) {
|
|
ucontact_t* c;
|
|
ucontact_t* c;
|
|
int sl;
|
|
int sl;
|
|
-
|
|
|
|
|
|
+
|
|
if ((c = new_ucontact(_r->domain, &_r->public_identity, _c, _ci)) == 0) {
|
|
if ((c = new_ucontact(_r->domain, &_r->public_identity, _c, _ci)) == 0) {
|
|
LM_ERR("failed to create new contact\n");
|
|
LM_ERR("failed to create new contact\n");
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
counter_inc(ul_scscf_cnts_h.active_contacts);
|
|
counter_inc(ul_scscf_cnts_h.active_contacts);
|
|
|
|
|
|
- LM_DBG("Created new contact in memory with AOR: [%.*s] and hash [%d]\n", _c->len, _c->s, c->contact_hash);
|
|
|
|
-
|
|
|
|
- sl = (c->contact_hash);// & (contact_list->size - 1);
|
|
|
|
|
|
+ LM_DBG("Created new contact in memory with AOR: [%.*s] and hash [%d]\n", _c->len, _c->s, c->sl);
|
|
|
|
+
|
|
|
|
+ sl = (c->sl);
|
|
lock_contact_slot_i(sl);
|
|
lock_contact_slot_i(sl);
|
|
contact_slot_add(&contact_list->slot[sl], c);
|
|
contact_slot_add(&contact_list->slot[sl], c);
|
|
unlock_contact_slot_i(sl);
|
|
unlock_contact_slot_i(sl);
|
|
@@ -277,8 +294,9 @@ ucontact_t* mem_insert_ucontact(impurecord_t* _r, str* _c, ucontact_info_t* _ci)
|
|
* \param _c removed contact
|
|
* \param _c removed contact
|
|
*/
|
|
*/
|
|
void mem_remove_ucontact(ucontact_t* _c) {
|
|
void mem_remove_ucontact(ucontact_t* _c) {
|
|
- LM_DBG("removing contact [%.*s] from slot %d\n", _c->c.len, _c->c.s, _c->contact_hash);
|
|
|
|
- contact_slot_rem(&contact_list->slot[_c->contact_hash], _c);
|
|
|
|
|
|
+ LM_DBG("removing contact [%.*s] from slot %d\n", _c->c.len, _c->c.s, _c->sl);
|
|
|
|
+ contact_slot_rem(&contact_list->slot[_c->sl], _c);
|
|
|
|
+ counter_add(ul_scscf_cnts_h.active_contacts, -1);
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
/*!
|
|
@@ -287,17 +305,15 @@ void mem_remove_ucontact(ucontact_t* _c) {
|
|
* \param _c deleted contact
|
|
* \param _c deleted contact
|
|
*/
|
|
*/
|
|
void mem_delete_ucontact(ucontact_t* _c) {
|
|
void mem_delete_ucontact(ucontact_t* _c) {
|
|
-
|
|
|
|
|
|
+
|
|
struct contact_dialog_data *dialog_data;
|
|
struct contact_dialog_data *dialog_data;
|
|
//tear down dialogs in dialog data list
|
|
//tear down dialogs in dialog data list
|
|
for (dialog_data = _c->first_dialog_data; dialog_data;) {
|
|
for (dialog_data = _c->first_dialog_data; dialog_data;) {
|
|
- dlgb.lookup_terminate_dlg(dialog_data->h_entry, dialog_data->h_id, NULL );
|
|
|
|
|
|
+ dlgb.lookup_terminate_dlg(dialog_data->h_entry, dialog_data->h_id, NULL);
|
|
dialog_data = dialog_data->next;
|
|
dialog_data = dialog_data->next;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
mem_remove_ucontact(_c);
|
|
mem_remove_ucontact(_c);
|
|
- //TODO: fix stats
|
|
|
|
-// if_update_stat(_r->slot, _r->slot->d->contacts, -1);
|
|
|
|
free_ucontact(_c);
|
|
free_ucontact(_c);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -308,18 +324,17 @@ void mem_delete_ucontact(ucontact_t* _c) {
|
|
* the record, delete the expired ones from memory.
|
|
* the record, delete the expired ones from memory.
|
|
* \param _r processed record
|
|
* \param _r processed record
|
|
*/
|
|
*/
|
|
-static inline void nodb_timer(impurecord_t* _r) {
|
|
|
|
|
|
+static inline void process_impurecord(impurecord_t* _r) {
|
|
|
|
+ int flag, mustdeleteimpu = 1, n, k;
|
|
|
|
+ unsigned int sl;
|
|
ucontact_t* ptr;
|
|
ucontact_t* ptr;
|
|
- int i, flag, mustdeleteimpu=1, hascontacts=0;
|
|
|
|
- udomain_t* udomain;
|
|
|
|
- unsigned int hash_code = 0;
|
|
|
|
- impurecord_t* tmp_impu;
|
|
|
|
-
|
|
|
|
|
|
+ int hascontacts;
|
|
|
|
+ udomain_t* _d;
|
|
reg_subscriber *s;
|
|
reg_subscriber *s;
|
|
subs_t* sub_dialog;
|
|
subs_t* sub_dialog;
|
|
|
|
|
|
get_act_time();
|
|
get_act_time();
|
|
-
|
|
|
|
|
|
+
|
|
s = _r->shead;
|
|
s = _r->shead;
|
|
LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
|
|
LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
|
|
while (s) {
|
|
while (s) {
|
|
@@ -328,88 +343,93 @@ static inline void nodb_timer(impurecord_t* _r) {
|
|
s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
|
|
s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
|
|
delete_subscriber(_r, s);
|
|
delete_subscriber(_r, s);
|
|
} else {
|
|
} else {
|
|
- mustdeleteimpu = 0;
|
|
|
|
LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n",
|
|
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,
|
|
s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s,
|
|
(unsigned int) (s->expires - time(NULL)));
|
|
(unsigned int) (s->expires - time(NULL)));
|
|
- hash_code = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size);
|
|
|
|
- LM_DBG("Hash size: <%i>", sub_dialog_hash_size);
|
|
|
|
- LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>", s->call_id.len, s->call_id.s, s->to_tag.len, s->to_tag.s, s->from_tag.len, s->from_tag.s, hash_code);
|
|
|
|
- /* search the record in hash table */
|
|
|
|
- lock_get(&sub_dialog_table[hash_code].lock);
|
|
|
|
- sub_dialog= pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, hash_code);
|
|
|
|
- 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[hash_code].lock);
|
|
|
|
|
|
+ sl = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size);
|
|
|
|
+ LM_DBG("Hash size: <%i>", sub_dialog_hash_size);
|
|
|
|
+ LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>", 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);
|
|
}
|
|
}
|
|
s = s->next;
|
|
s = s->next;
|
|
}
|
|
}
|
|
|
|
|
|
- LM_DBG("Checking validity of IMPU: <%.*s> contacts (#%d contacts)\n", _r->public_identity.len, _r->public_identity.s, _r->num_contacts);
|
|
|
|
|
|
+ LM_DBG("\tPublic Identity %.*s, Barred: [%d], State: [%s]\n",
|
|
|
|
+ _r->public_identity.len, _r->public_identity.s,
|
|
|
|
+ _r->barring,
|
|
|
|
+ get_impu_regstate_as_string(_r->reg_state));
|
|
flag = 0;
|
|
flag = 0;
|
|
-
|
|
|
|
- for (i=0; i<MAX_CONTACTS_PER_IMPU; i++) {
|
|
|
|
- if ((ptr = _r->newcontacts[i])) {
|
|
|
|
- flag=1;
|
|
|
|
- if (!VALID_CONTACT(ptr, act_time)) {
|
|
|
|
- LM_DBG("IMPU:<%.*s> - contact:<%.*s> has expired\n", _r->public_identity.len, _r->public_identity.s, ptr->c.len, ptr->c.s);
|
|
|
|
- lock_contact_slot_i(ptr->contact_hash); //TODO, this maybe should be a lock on the strcuture itself and not the slot
|
|
|
|
- unlink_contact_from_impu(_r, ptr, 1);
|
|
|
|
- unlock_contact_slot_i(ptr->contact_hash);
|
|
|
|
- } else {
|
|
|
|
- LM_DBG("IMPU:<%.*s> - contact:<%.*s> is valid and expires in %d seconds\n", _r->public_identity.len, _r->public_identity.s,
|
|
|
|
- ptr->c.len, ptr->c.s,
|
|
|
|
- (unsigned int) (ptr->expires - time(NULL)));
|
|
|
|
- mustdeleteimpu = 0;
|
|
|
|
- hascontacts = 1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+ mustdeleteimpu = 1;
|
|
|
|
+ hascontacts = 0;
|
|
|
|
+ num_contacts_to_expire = 0;
|
|
|
|
+ for (k = 0; (k < _r->num_contacts) && (k < MAX_CONTACTS_PER_IMPU); k++) {
|
|
|
|
+ if ((ptr = _r->newcontacts[k])) {
|
|
|
|
+ flag = 1;
|
|
|
|
+ if (!VALID_CONTACT(ptr, act_time)) {
|
|
|
|
+ LM_DBG("IMPU:<%.*s> - contact:<%.*s> has expired... unlinking contact from IMPU\n", _r->public_identity.len, _r->public_identity.s, ptr->c.len, ptr->c.s);
|
|
|
|
+ contacts_to_expire[num_contacts_to_expire] = ptr;
|
|
|
|
+ num_contacts_to_expire++;
|
|
|
|
+ } else {
|
|
|
|
+ LM_DBG("\t\tContact #%i - %.*s, Ref [%d] (expires in %ld seconds)\n", k, ptr->c.len, ptr->c.s, ptr->ref_count, ptr->expires - act_time);
|
|
|
|
+ mustdeleteimpu = 0;
|
|
|
|
+ hascontacts = 1;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ LM_WARN("num_contacts and actual data not consistent... .aborting\n");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if (num_contacts_to_expire > 0) {
|
|
|
|
+ LM_DBG("\tThere are %d contacts to expire\n", num_contacts_to_expire);
|
|
|
|
+ for (n = 0; n < num_contacts_to_expire; n++) {
|
|
|
|
+ ptr = contacts_to_expire[n];
|
|
|
|
+ LM_DBG("\t\texpiring contact %i: [%.*s] in slot [%d]\n", n, contacts_to_expire[n]->c.len, contacts_to_expire[n]->c.s, contacts_to_expire[n]->sl);
|
|
|
|
+ sl = ptr->sl;
|
|
|
|
+ lock_contact_slot_i(sl);
|
|
|
|
+ unlink_contact_from_impu(_r, ptr, 1);
|
|
|
|
+ unlock_contact_slot_i(sl);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if (!flag)
|
|
if (!flag)
|
|
LM_DBG("no contacts\n");
|
|
LM_DBG("no contacts\n");
|
|
|
|
|
|
- register_udomain("location", &udomain);
|
|
|
|
if (mustdeleteimpu) {
|
|
if (mustdeleteimpu) {
|
|
- delete_impurecord(udomain, &_r->public_identity, _r);
|
|
|
|
|
|
+ register_udomain("location", &_d);
|
|
|
|
+ delete_impurecord(_d, &_r->public_identity, _r);
|
|
} else {
|
|
} else {
|
|
- if (!hascontacts) {
|
|
|
|
- LM_DBG("This impu is not to be deleted but has no contacts - should change state to IMPU_UNREGISTERED\n");
|
|
|
|
- if (update_impurecord(udomain, &_r->public_identity, IMPU_UNREGISTERED,
|
|
|
|
- -1/*do not change*/, -1 /*do not change */, -1/*do not change*/, NULL, NULL, NULL, NULL, NULL, &tmp_impu) != 0) {
|
|
|
|
- LM_ERR("Unable to update impurecord for <%.*s>\n", _r->public_identity.len, _r->public_identity.s);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (!hascontacts) {
|
|
|
|
+ LM_DBG("This impu is not to be deleted but has no contacts - changing state to IMPU_UNREGISTERED\n");
|
|
|
|
+ _r->reg_state = IMPU_UNREGISTERED;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
/*!
|
|
- * \brief Run timer functions depending on the db_mode setting.
|
|
|
|
- *
|
|
|
|
- * Helper function that run the appropriate timer function, depending
|
|
|
|
- * on the db_mode setting.
|
|
|
|
- * \param _r processed record
|
|
|
|
|
|
+ * \brief Process impurecords (check contacts for expiry, etc (assume domain slot is locked)
|
|
|
|
+ * @param _r impurecord to process
|
|
*/
|
|
*/
|
|
void timer_impurecord(impurecord_t* _r) {
|
|
void timer_impurecord(impurecord_t* _r) {
|
|
- nodb_timer(_r);
|
|
|
|
|
|
+ process_impurecord(_r);
|
|
}
|
|
}
|
|
|
|
|
|
int get_contacts_count(impurecord_t* _r) {
|
|
int get_contacts_count(impurecord_t* _r) {
|
|
ucontact_t* ptr;
|
|
ucontact_t* ptr;
|
|
int i = 0;
|
|
int i = 0;
|
|
-
|
|
|
|
- while (i<MAX_CONTACTS_PER_IMPU && (ptr=_r->newcontacts[i])) {
|
|
|
|
- i++;
|
|
|
|
|
|
+
|
|
|
|
+ while (i < MAX_CONTACTS_PER_IMPU && (ptr = _r->newcontacts[i])) {
|
|
|
|
+ i++;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
return i;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -449,15 +469,13 @@ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucont
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // /*DB?*/
|
|
|
|
+ if (db_mode == WRITE_THROUGH && db_insert_ucontact(_r, *_c) != 0) {
|
|
|
|
+ LM_ERR("error inserting contact into db");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
|
-// /*DB?*/
|
|
|
|
- if (db_mode == WRITE_THROUGH && db_insert_ucontact(_r, *_c) != 0) {
|
|
|
|
- LM_ERR("error inserting contact into db");
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-//make sure IMPU is linked to this contact
|
|
|
|
|
|
+ //make sure IMPU is linked to this contact
|
|
link_contact_to_impu(_r, *_c, 1);
|
|
link_contact_to_impu(_r, *_c, 1);
|
|
|
|
|
|
release_ucontact(*_c);
|
|
release_ucontact(*_c);
|
|
@@ -471,7 +489,6 @@ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucont
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
-
|
|
|
|
/*!
|
|
/*!
|
|
* \brief Delete ucontact from impurecord
|
|
* \brief Delete ucontact from impurecord
|
|
* \param _r record where the contact belongs to
|
|
* \param _r record where the contact belongs to
|
|
@@ -480,56 +497,43 @@ int insert_ucontact(impurecord_t* _r, str* _contact, ucontact_info_t* _ci, ucont
|
|
*/
|
|
*/
|
|
int delete_ucontact(struct ucontact* _c) {
|
|
int delete_ucontact(struct ucontact* _c) {
|
|
int ret = 0;
|
|
int ret = 0;
|
|
-
|
|
|
|
- LM_DBG("Deleting contact: [%.*s]\n", _c->c.len, _c->c.s);
|
|
|
|
- //TODO: restore callbacks
|
|
|
|
-// if (exists_ulcb_type(_c->cbs, UL_CONTACT_DELETE)) {
|
|
|
|
-// run_ul_callbacks(_c->cbs, UL_CONTACT_DELETE, _r, _c);
|
|
|
|
-// }
|
|
|
|
-
|
|
|
|
- //TODO: following callbacks need to move to unlink contact from impu functions
|
|
|
|
-// if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) {
|
|
|
|
-// run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, _c);
|
|
|
|
-// }
|
|
|
|
-
|
|
|
|
- /*DB?*/
|
|
|
|
- if (db_mode == WRITE_THROUGH && db_delete_ucontact(_c) != 0) {
|
|
|
|
- LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", _c->c.len, _c->c.s);
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
+ LM_DBG("Deleting contact: [%.*s]\n", _c->c.len, _c->c.s);
|
|
|
|
+ /*DB?*/
|
|
|
|
+ if (db_mode == WRITE_THROUGH && db_delete_ucontact(_c) != 0) {
|
|
|
|
+ LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", _c->c.len, _c->c.s);
|
|
|
|
+ }
|
|
mem_delete_ucontact(_c);
|
|
mem_delete_ucontact(_c);
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/* function to convert contact aor to only have data after @ - ie strip user part */
|
|
/* function to convert contact aor to only have data after @ - ie strip user part */
|
|
inline int aor_to_contact(str* aor, str* contact) {
|
|
inline int aor_to_contact(str* aor, str* contact) {
|
|
- char* p;
|
|
|
|
- int ret = 0; //success
|
|
|
|
-
|
|
|
|
- contact->s = aor->s;
|
|
|
|
- contact->len = aor->len;
|
|
|
|
- if (memcmp(aor->s, "sip:", 4) == 0) {
|
|
|
|
- contact->s = aor->s + 4;
|
|
|
|
- contact->len-=4;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ((p=memchr(contact->s, '@', contact->len))) {
|
|
|
|
- contact->len -= (p - contact->s + 1);
|
|
|
|
- contact->s = p+1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ((p=memchr(contact->s, ';', contact->len))) {
|
|
|
|
- contact->len = p - contact->s;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ((p=memchr(contact->s, '>', contact->len))) {
|
|
|
|
- contact->len = p - contact->s;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
|
|
+ char* p;
|
|
|
|
+ int ret = 0; //success
|
|
|
|
+
|
|
|
|
+ contact->s = aor->s;
|
|
|
|
+ contact->len = aor->len;
|
|
|
|
+ if (memcmp(aor->s, "sip:", 4) == 0) {
|
|
|
|
+ contact->s = aor->s + 4;
|
|
|
|
+ contact->len -= 4;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((p = memchr(contact->s, '@', contact->len))) {
|
|
|
|
+ contact->len -= (p - contact->s + 1);
|
|
|
|
+ contact->s = p + 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((p = memchr(contact->s, ';', contact->len))) {
|
|
|
|
+ contact->len = p - contact->s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((p = memchr(contact->s, '>', contact->len))) {
|
|
|
|
+ contact->len = p - contact->s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
/*!
|
|
@@ -540,9 +544,9 @@ inline int aor_to_contact(str* aor, str* contact) {
|
|
*/
|
|
*/
|
|
static inline struct ucontact* contact_match(unsigned int slot, str* _c) {
|
|
static inline struct ucontact* contact_match(unsigned int slot, str* _c) {
|
|
ucontact_t* ptr = contact_list->slot[slot].first;
|
|
ucontact_t* ptr = contact_list->slot[slot].first;
|
|
-
|
|
|
|
|
|
+
|
|
while (ptr) {
|
|
while (ptr) {
|
|
- if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len) && VALID_CONTACT(ptr, act_time)) {//check validity
|
|
|
|
|
|
+ if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len)) {//check validity
|
|
return ptr;
|
|
return ptr;
|
|
}
|
|
}
|
|
ptr = ptr->next;
|
|
ptr = ptr->next;
|
|
@@ -559,11 +563,11 @@ static inline struct ucontact* contact_match(unsigned int slot, str* _c) {
|
|
static inline struct ucontact* contact_port_ip_match(unsigned int slot, str* _c) {
|
|
static inline struct ucontact* contact_port_ip_match(unsigned int slot, str* _c) {
|
|
ucontact_t* ptr = contact_list->slot[slot].first;
|
|
ucontact_t* ptr = contact_list->slot[slot].first;
|
|
str string_ip_port, contact_ip_port;
|
|
str string_ip_port, contact_ip_port;
|
|
- aor_to_contact(_c, &string_ip_port);//strip userpart from test contact
|
|
|
|
|
|
+ aor_to_contact(_c, &string_ip_port); //strip userpart from test contact
|
|
|
|
|
|
while (ptr) {
|
|
while (ptr) {
|
|
- aor_to_contact(&ptr->c, &contact_ip_port);//strip userpart from contact
|
|
|
|
- if ((string_ip_port.len == contact_ip_port.len) && !memcmp(string_ip_port.s, contact_ip_port.s, string_ip_port.len) && VALID_CONTACT(ptr, act_time)) {
|
|
|
|
|
|
+ aor_to_contact(&ptr->c, &contact_ip_port); //strip userpart from contact
|
|
|
|
+ if ((string_ip_port.len == contact_ip_port.len) && !memcmp(string_ip_port.s, contact_ip_port.s, string_ip_port.len)) {
|
|
return ptr;
|
|
return ptr;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -586,8 +590,7 @@ static inline struct ucontact* contact_callid_match(unsigned int slot,
|
|
while (ptr) {
|
|
while (ptr) {
|
|
if ((_c->len == ptr->c.len) && (_callid->len == ptr->callid.len)
|
|
if ((_c->len == ptr->c.len) && (_callid->len == ptr->callid.len)
|
|
&& !memcmp(_c->s, ptr->c.s, _c->len)
|
|
&& !memcmp(_c->s, ptr->c.s, _c->len)
|
|
- && !memcmp(_callid->s, ptr->callid.s, _callid->len)
|
|
|
|
- && VALID_CONTACT(ptr, act_time)) {
|
|
|
|
|
|
+ && !memcmp(_callid->s, ptr->callid.s, _callid->len)) {
|
|
return ptr;
|
|
return ptr;
|
|
}
|
|
}
|
|
ptr = ptr->next;
|
|
ptr = ptr->next;
|
|
@@ -613,7 +616,7 @@ static inline struct ucontact* contact_path_match(unsigned int slot, str* _c, st
|
|
&& !memcmp(_c->s, ptr->c.s, _c->len)
|
|
&& !memcmp(_c->s, ptr->c.s, _c->len)
|
|
&& !memcmp(_path->s, ptr->path.s, _path->len)
|
|
&& !memcmp(_path->s, ptr->path.s, _path->len)
|
|
&& VALID_CONTACT(ptr, act_time)
|
|
&& VALID_CONTACT(ptr, act_time)
|
|
- ) {
|
|
|
|
|
|
+ ) {
|
|
return ptr;
|
|
return ptr;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -642,10 +645,10 @@ int get_ucontact(impurecord_t* _r, str* _c, str* _callid, str* _path, int _cseq,
|
|
|
|
|
|
sl = core_hash(_c, 0, contact_list->size);
|
|
sl = core_hash(_c, 0, contact_list->size);
|
|
LM_DBG("looking for contact [%.*s] in slot %d\n", _c->len, _c->s, sl);
|
|
LM_DBG("looking for contact [%.*s] in slot %d\n", _c->len, _c->s, sl);
|
|
- lock_contact_slot_i(sl);
|
|
|
|
-
|
|
|
|
get_act_time();
|
|
get_act_time();
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ lock_contact_slot_i(sl);
|
|
|
|
+
|
|
switch (matching_mode) {
|
|
switch (matching_mode) {
|
|
case CONTACT_ONLY:
|
|
case CONTACT_ONLY:
|
|
ptr = contact_match(sl, _c);
|
|
ptr = contact_match(sl, _c);
|
|
@@ -656,41 +659,33 @@ int get_ucontact(impurecord_t* _r, str* _c, str* _callid, str* _path, int _cseq,
|
|
break;
|
|
break;
|
|
case CONTACT_PATH:
|
|
case CONTACT_PATH:
|
|
ptr = contact_path_match(sl, _c, _path);
|
|
ptr = contact_path_match(sl, _c, _path);
|
|
- break;
|
|
|
|
- case CONTACT_PORT_IP_ONLY:
|
|
|
|
- ptr = contact_port_ip_match(sl, _c);
|
|
|
|
- break;
|
|
|
|
|
|
+ break;
|
|
|
|
+ case CONTACT_PORT_IP_ONLY:
|
|
|
|
+ ptr = contact_port_ip_match(sl, _c);
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
LM_CRIT("unknown matching_mode %d\n", matching_mode);
|
|
LM_CRIT("unknown matching_mode %d\n", matching_mode);
|
|
unlock_contact_slot_i(sl);
|
|
unlock_contact_slot_i(sl);
|
|
- return -1;
|
|
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
-
|
|
|
|
- unlock_contact_slot_i(sl); /*TODO: we probably need to ref count here..... */
|
|
|
|
|
|
|
|
if (ptr) {
|
|
if (ptr) {
|
|
- LM_DBG("have partially found a contact\n");
|
|
|
|
|
|
+ LM_DBG("have partially found a contact\n");
|
|
/* found -> check callid and cseq */
|
|
/* found -> check callid and cseq */
|
|
if (!with_callid || (_callid && ptr->callid.len == _callid->len
|
|
if (!with_callid || (_callid && ptr->callid.len == _callid->len
|
|
&& memcmp(_callid->s, ptr->callid.s, _callid->len) == 0)) {
|
|
&& memcmp(_callid->s, ptr->callid.s, _callid->len) == 0)) {
|
|
if (_cseq < ptr->cseq) {
|
|
if (_cseq < ptr->cseq) {
|
|
- LM_DBG("cseq less than expected\n");
|
|
|
|
-// return -1;
|
|
|
|
- }
|
|
|
|
-// if (_cseq == ptr->cseq) {
|
|
|
|
-// get_act_time();
|
|
|
|
-// return (ptr->last_modified + cseq_delay > act_time) ? -2 : -1;
|
|
|
|
-// }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ LM_DBG("cseq less than expected\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
- LM_DBG("contact found p=[%p], aor:[%.*s] and contact:[%.*s]\n", ptr, ptr->aor.len, ptr->aor.s, ptr->c.len, ptr->c.s);
|
|
|
|
-
|
|
|
|
- ptr->ref_count++;
|
|
|
|
|
|
+ LM_DBG("contact found p=[%p], aor:[%.*s] and contact:[%.*s]\n", ptr, ptr->aor.len, ptr->aor.s, ptr->c.len, ptr->c.s);
|
|
|
|
+ ref_contact_unsafe(ptr);
|
|
*_co = ptr;
|
|
*_co = ptr;
|
|
-
|
|
|
|
|
|
+ unlock_contact_slot_i(sl); /*TODO: we probably need to ref count here..... */
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+ unlock_contact_slot_i(sl);
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -777,85 +772,120 @@ void free_ims_subscription_data(ims_subscription *s) {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-/* update an existing impurecord. if one doesnt exist it will be created.
|
|
|
|
- * make sure yuo lock the domain before calling this and unlock it afterwards
|
|
|
|
- * return: 0 on success, -1 on failure
|
|
|
|
|
|
+/* Still needs to be implemented */
|
|
|
|
+int compare_subscription(ims_subscription* new, ims_subscription* orig) {
|
|
|
|
+ int i, j;
|
|
|
|
+ LM_DBG("Comparing subscription for IMPI [%.*s]\n", orig->private_identity.len, orig->private_identity.s);
|
|
|
|
+ for (i = 0; i < orig->service_profiles_cnt; i++) {
|
|
|
|
+
|
|
|
|
+ for (j = 0; j < orig->service_profiles[i].public_identities_cnt; j++) {
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief update an existing impurecord. if one doesn't exist it will be created. assumes the domain is locked
|
|
|
|
+ * @param _d
|
|
|
|
+ * @param public_identity only used if impu_rec is null
|
|
|
|
+ * @param impu_rec if passed in we use this as the record and we assume caller has already done locking on the domain...
|
|
|
|
+ * @param reg_state
|
|
|
|
+ * @param send_sar_on_delete
|
|
|
|
+ * @param barring
|
|
|
|
+ * @param is_primary
|
|
|
|
+ * @param s
|
|
|
|
+ * @param ccf1
|
|
|
|
+ * @param ccf2
|
|
|
|
+ * @param ecf1
|
|
|
|
+ * @param ecf2
|
|
|
|
+ * @param _r
|
|
|
|
+ * @return 0 on success (domain will remain locked)
|
|
*/
|
|
*/
|
|
-int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r) {
|
|
|
|
|
|
+int update_impurecord(struct udomain* _d, str* public_identity, impurecord_t* impu_rec, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r) {
|
|
int res;
|
|
int res;
|
|
- int subscription_hash, sl;
|
|
|
|
- struct ims_subscription_s* subscription, *subs_ptr;
|
|
|
|
|
|
+ struct ims_subscription_s* subscription, *subs_ptr = 0;
|
|
|
|
+ int leave_slot_locked = 1;
|
|
|
|
+ int subscription_locked = 0;
|
|
|
|
+ str private_identity = {0, 0};
|
|
|
|
+ str* impu_str = public_identity;
|
|
|
|
+
|
|
|
|
+ //make usre we have IMPU or enough data to find it...
|
|
|
|
+ if (!impu_rec && (!public_identity || !public_identity->len || !public_identity->s)) {
|
|
|
|
+ LM_WARN("can't call update_impurecord with no details of IMPU..n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
|
|
/* before we get started let's check if we already have subscription data for this impi */
|
|
/* before we get started let's check if we already have subscription data for this impi */
|
|
if (s && *s) {
|
|
if (s && *s) {
|
|
subs_ptr = (*s);
|
|
subs_ptr = (*s);
|
|
- subscription_hash = core_hash(&(*s)->private_identity, 0, 0);
|
|
|
|
- sl = subscription_hash & (subs_hash_size - 1);
|
|
|
|
- lock_get(ims_subscription_list->slot[sl].lock);
|
|
|
|
- subscription = ims_subscription_list->slot[sl].first;
|
|
|
|
- if (!subscription) {
|
|
|
|
|
|
+ res = get_subscription(&(*s)->private_identity, &subscription, leave_slot_locked); //leave slot locked in case we need to add.... don't want racing adds
|
|
|
|
+ if (res != 0) {
|
|
LM_DBG("No subscription yet for [%.*s]... adding\n", (*s)->private_identity.len, (*s)->private_identity.s);
|
|
LM_DBG("No subscription yet for [%.*s]... adding\n", (*s)->private_identity.len, (*s)->private_identity.s);
|
|
- //(*s)->ref_count++; //bump subscription - we're currently referencing it
|
|
|
|
- subs_slot_add(&ims_subscription_list->slot[sl], subs_ptr);
|
|
|
|
|
|
+ ref_subscription_unsafe(subs_ptr); //we reference coz we are using it - will be unreferenced later.
|
|
|
|
+ add_subscription_unsafe(subs_ptr);
|
|
|
|
+ unlock_subscription_slot(subs_ptr->sl);
|
|
} else {
|
|
} else {
|
|
- /* check through entries if any match */
|
|
|
|
- while (subscription) {
|
|
|
|
- if ((subs_ptr->private_identity.len == subscription->private_identity.len) && (memcmp(subs_ptr->private_identity.s, subscription->private_identity.s, subscription->private_identity.len) == 0)) {
|
|
|
|
- LM_DBG("found an existing subscription for IMPI [%.*s]\n", subs_ptr->private_identity.len, subs_ptr->private_identity.s);
|
|
|
|
- //reuse the existing one... TODO - maybe update it with the latest profile... (if it has changed)
|
|
|
|
- subs_ptr = subscription;
|
|
|
|
- //subscription->ref_count++; //we don't bump ref now becuase this impu could already be referencing this subscription
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- subscription = subscription->next;
|
|
|
|
- }
|
|
|
|
- if (subscription == NULL) {
|
|
|
|
- LM_DBG("could not find existing subscription for IMPI [%.*s]... adding\n", (*s)->private_identity.len, (*s)->private_identity.s);
|
|
|
|
- //subs_ptr->ref_count++; //bump ref coz we're currently reffing it
|
|
|
|
- subs_slot_add(&ims_subscription_list->slot[sl], subs_ptr);
|
|
|
|
- }
|
|
|
|
|
|
+ //TODO: we may want to do a deep comparison of the subscription and update....
|
|
|
|
+ subs_ptr = subscription;
|
|
}
|
|
}
|
|
- lock_release(ims_subscription_list->slot[sl].lock);
|
|
|
|
|
|
+ lock_subscription(subs_ptr);
|
|
|
|
+ subscription_locked = 1;
|
|
|
|
+ private_identity = (*s)->private_identity;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- // r = _d->table[sl].first;
|
|
|
|
- res = get_impurecord(_d, public_identity, _r);
|
|
|
|
- if (res != 0) {
|
|
|
|
- if (reg_state != IMPU_NOT_REGISTERED && s) {
|
|
|
|
- LM_DBG("No existing impu record for <%.*s>.... creating new one\n", public_identity->len, public_identity->s);
|
|
|
|
- res = insert_impurecord(_d, public_identity, reg_state, barring, &subs_ptr, ccf1, ccf2, ecf1, ecf2, _r);
|
|
|
|
- if (res != 0) {
|
|
|
|
- LM_ERR("Unable to insert new IMPU for <%.*s>\n", public_identity->len, public_identity->s);
|
|
|
|
- return -1;
|
|
|
|
|
|
+ if (impu_rec) {
|
|
|
|
+ LM_DBG("We already have impurecord....\n");
|
|
|
|
+ (*_r) = impu_rec;
|
|
|
|
+ impu_str = &(*_r)->public_identity;
|
|
|
|
+ } else {
|
|
|
|
+ res = get_impurecord(_d, impu_str, _r); //return with lock on the domain
|
|
|
|
+ if (res != 0) {
|
|
|
|
+ if (reg_state != IMPU_NOT_REGISTERED && s) {
|
|
|
|
+ LM_DBG("No existing impu record for <%.*s>.... creating new one\n", impu_str->len, impu_str->s);
|
|
|
|
+ res = insert_impurecord(_d, impu_str, &private_identity, reg_state, barring, &subs_ptr, ccf1, ccf2, ecf1, ecf2, _r);
|
|
|
|
+ if (res != 0) {
|
|
|
|
+ LM_ERR("Unable to insert new IMPU for <%.*s>\n", impu_str->len, impu_str->s);
|
|
|
|
+ // unlock_udomain(_d, impu_str);
|
|
|
|
+ goto error;
|
|
|
|
+ } else {
|
|
|
|
+ //for the first time we create an IMPU we must set the primary record (we don't worry about it on updates - ignored)
|
|
|
|
+ (*_r)->is_primary = is_primary; //TODO = this should prob move to insert_impurecord fn
|
|
|
|
+ if (reg_state == IMPU_UNREGISTERED) {
|
|
|
|
+ //update unreg expiry so the unreg record is not stored 'forever'
|
|
|
|
+ (*_r)->expires = time(NULL) + unreg_validity;
|
|
|
|
+ }
|
|
|
|
+ run_ul_callbacks(NULL, UL_IMPU_INSERT, *_r, NULL);
|
|
|
|
+ if (subscription_locked) {
|
|
|
|
+ unref_subscription_unsafe(subs_ptr);
|
|
|
|
+ unlock_subscription(subs_ptr);
|
|
|
|
+ }
|
|
|
|
+ // unlock_udomain(_d, impu_str);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
- //for the first time we create an IMPU we must set the primary record (we don't worry about it on updates - ignored)
|
|
|
|
- (*_r)->is_primary = is_primary; //TODO = this should prob move to insert_impurecord fn
|
|
|
|
- if (reg_state == IMPU_UNREGISTERED) {
|
|
|
|
- //update unreg expiry so the unreg record is not stored 'forever'
|
|
|
|
- (*_r)->expires = time(NULL) + unreg_validity;
|
|
|
|
|
|
+ LM_DBG("no IMPU found to update and data not valid to create new one - not a problem record was probably removed as it has no contacts\n");
|
|
|
|
+ if (subscription_locked) {
|
|
|
|
+ unref_subscription_unsafe(subs_ptr);
|
|
|
|
+ unlock_subscription(subs_ptr);
|
|
}
|
|
}
|
|
- run_ul_callbacks(NULL, UL_IMPU_INSERT, *_r, NULL);
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- LM_DBG("no IMPU found to update and data not valid to create new one - not a problem record was probably removed as it has no contacts\n");
|
|
|
|
- return 0;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//if we get here, we have a record to update
|
|
//if we get here, we have a record to update
|
|
- LM_DBG("updating IMPU record with public identity for <%.*s>\n", public_identity->len, public_identity->s);
|
|
|
|
|
|
+ LM_DBG("updating IMPU record with public identity for <%.*s>\n", impu_str->len, impu_str->s);
|
|
(*_r)->reg_state = reg_state;
|
|
(*_r)->reg_state = reg_state;
|
|
if (reg_state == IMPU_UNREGISTERED) {
|
|
if (reg_state == IMPU_UNREGISTERED) {
|
|
//update unreg expiry so the unreg record is not stored 'forever'
|
|
//update unreg expiry so the unreg record is not stored 'forever'
|
|
(*_r)->expires = time(NULL) + unreg_validity;
|
|
(*_r)->expires = time(NULL) + unreg_validity;
|
|
}
|
|
}
|
|
if (barring >= 0) (*_r)->barring = barring;
|
|
if (barring >= 0) (*_r)->barring = barring;
|
|
-
|
|
|
|
|
|
+
|
|
if (send_sar_on_delete >= 0) (*_r)->send_sar_on_delete = send_sar_on_delete;
|
|
if (send_sar_on_delete >= 0) (*_r)->send_sar_on_delete = send_sar_on_delete;
|
|
-
|
|
|
|
|
|
+
|
|
if (ccf1) {
|
|
if (ccf1) {
|
|
if ((*_r)->ccf1.s)
|
|
if ((*_r)->ccf1.s)
|
|
shm_free((*_r)->ccf1.s);
|
|
shm_free((*_r)->ccf1.s);
|
|
@@ -877,155 +907,174 @@ int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, i
|
|
STR_SHM_DUP((*_r)->ecf2, *ecf2, "SHM ECF2");
|
|
STR_SHM_DUP((*_r)->ecf2, *ecf2, "SHM ECF2");
|
|
}
|
|
}
|
|
|
|
|
|
- if (s) {
|
|
|
|
|
|
+ if (subs_ptr) {
|
|
LM_DBG("IMS subscription passed into update_impurecord\n");
|
|
LM_DBG("IMS subscription passed into update_impurecord\n");
|
|
if ((*_r)->s != subs_ptr) {
|
|
if ((*_r)->s != subs_ptr) {
|
|
LM_DBG("new subscription for IMPU... swapping - TODO need to unref the old one...and then ref the new one\n");
|
|
LM_DBG("new subscription for IMPU... swapping - TODO need to unref the old one...and then ref the new one\n");
|
|
- unref_subscription_unsafe((*_r)->s);
|
|
|
|
|
|
+ unref_subscription((*_r)->s); //different subscription which we don't have lock on yet.
|
|
ref_subscription_unsafe(subs_ptr);
|
|
ref_subscription_unsafe(subs_ptr);
|
|
(*_r)->s = subs_ptr;
|
|
(*_r)->s = subs_ptr;
|
|
} else {
|
|
} else {
|
|
- if (s && *s) {
|
|
|
|
- LM_DBG("new subscription is the same as the old one....not doing anything");
|
|
|
|
|
|
+ LM_DBG("new subscription is the same as the old one....not doing anything");
|
|
|
|
+ //check that the service profile and associated impus are in the subscription, if not, add...
|
|
|
|
+ if (compare_subscription(subs_ptr, *s) != 0) {
|
|
|
|
+ LM_WARN("TODO: There is a new service profile we need to add to the subscription\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
run_ul_callbacks((*_r)->cbs, UL_IMPU_UPDATE, *_r, NULL);
|
|
run_ul_callbacks((*_r)->cbs, UL_IMPU_UPDATE, *_r, NULL);
|
|
-
|
|
|
|
|
|
+
|
|
if (db_mode == WRITE_THROUGH && db_insert_impurecord(_d, &(*_r)->public_identity, (*_r)->reg_state, (*_r)->barring, &(*_r)->s, &(*_r)->ccf1, &(*_r)->ccf2, &(*_r)->ecf1, &(*_r)->ecf2, _r) != 0) {
|
|
if (db_mode == WRITE_THROUGH && db_insert_impurecord(_d, &(*_r)->public_identity, (*_r)->reg_state, (*_r)->barring, &(*_r)->s, &(*_r)->ccf1, &(*_r)->ccf2, &(*_r)->ecf1, &(*_r)->ecf2, _r) != 0) {
|
|
- LM_ERR("error inserting IMPU [%.*s] into db... continuing", (*_r)->public_identity.len, (*_r)->public_identity.s);
|
|
|
|
|
|
+ LM_ERR("error inserting IMPU [%.*s] into db... continuing", (*_r)->public_identity.len, (*_r)->public_identity.s);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if (subscription_locked) {
|
|
|
|
+ unref_subscription_unsafe(subs_ptr);
|
|
|
|
+ unlock_subscription(subs_ptr);
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
out_of_memory:
|
|
out_of_memory:
|
|
- unlock_udomain(_d, public_identity);
|
|
|
|
|
|
+
|
|
|
|
+ error :
|
|
|
|
+ if (subscription_locked) {
|
|
|
|
+ unref_subscription_unsafe(subs_ptr);
|
|
|
|
+ unlock_subscription(subs_ptr);
|
|
|
|
+ }
|
|
|
|
+
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/* link contact to impu
|
|
/* link contact to impu
|
|
must be called with lock on domain (IMPU) as well as lock on contact_slot
|
|
must be called with lock on domain (IMPU) as well as lock on contact_slot
|
|
*/
|
|
*/
|
|
-int link_contact_to_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db)
|
|
|
|
-{
|
|
|
|
|
|
+int link_contact_to_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db) {
|
|
ucontact_t* ptr;
|
|
ucontact_t* ptr;
|
|
int i;
|
|
int i;
|
|
- i=0;
|
|
|
|
- int overwrite=0;
|
|
|
|
- ptr=impu->newcontacts[i];
|
|
|
|
|
|
+ i = 0;
|
|
|
|
+ int overwrite = 0;
|
|
|
|
+ ptr = impu->newcontacts[i];
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- while (i<MAX_CONTACTS_PER_IMPU && ptr) {
|
|
|
|
- if (ptr == contact) {
|
|
|
|
- LM_DBG("contact [%.*s] already linked to impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- i++;
|
|
|
|
- ptr = impu->newcontacts[i];
|
|
|
|
|
|
+ while (i < MAX_CONTACTS_PER_IMPU && ptr) {
|
|
|
|
+ if (ptr == contact) {
|
|
|
|
+ LM_DBG("contact [%.*s] already linked to impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ i++;
|
|
|
|
+ ptr = impu->newcontacts[i];
|
|
}
|
|
}
|
|
-
|
|
|
|
- if ((maxcontact_behaviour>0) && (maxcontact>0) && (maxcontact < (i+1))) {
|
|
|
|
- LM_DBG("Need to overwrite oldest contact at position %d\n", i);
|
|
|
|
- i = maxcontact-1;
|
|
|
|
- overwrite = 1;
|
|
|
|
|
|
+
|
|
|
|
+ if ((maxcontact_behaviour > 0) && (maxcontact > 0) && (maxcontact < (i + 1))) {
|
|
|
|
+ LM_DBG("Need to overwrite oldest contact at position %d\n", i);
|
|
|
|
+ i = maxcontact - 1;
|
|
|
|
+ overwrite = 1;
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (i<MAX_CONTACTS_PER_IMPU) {
|
|
|
|
- LM_DBG("contact [%.*s] needs to be linked to impu [%.*s] at position %d\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s, i);
|
|
|
|
- if (overwrite)
|
|
|
|
- unlink_contact_from_impu(impu, impu->newcontacts[i], write_to_db); //unlink the contact we are overwriting
|
|
|
|
-
|
|
|
|
- impu->num_contacts = i+1; //we always bump this - as unlink (in overwrite would have decremented)
|
|
|
|
-
|
|
|
|
- impu->newcontacts[i] = contact;
|
|
|
|
-
|
|
|
|
- contact->ref_count++;
|
|
|
|
- LM_DBG("number of contacts for IMPU [%.*s] is %d\n", impu->public_identity.len, impu->public_identity.s, impu->num_contacts);
|
|
|
|
- if (write_to_db && db_mode == WRITE_THROUGH && db_link_contact_to_impu(impu, contact) !=0) {
|
|
|
|
- LM_ERR("Failed to update DB linking contact [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
- };
|
|
|
|
|
|
+
|
|
|
|
+ if (i < MAX_CONTACTS_PER_IMPU) {
|
|
|
|
+ LM_DBG("contact [%.*s] needs to be linked to impu [%.*s] at position %d\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s, i);
|
|
|
|
+ if (overwrite)
|
|
|
|
+ unlink_contact_from_impu(impu, impu->newcontacts[i], write_to_db); //unlink the contact we are overwriting
|
|
|
|
+
|
|
|
|
+ impu->num_contacts = i + 1; //we always bump this - as unlink (in overwrite would have decremented)
|
|
|
|
+ impu->newcontacts[i] = contact;
|
|
|
|
+ ref_contact_unsafe(contact);
|
|
|
|
+ LM_DBG("number of contacts for IMPU [%.*s] is %d\n", impu->public_identity.len, impu->public_identity.s, impu->num_contacts);
|
|
|
|
+ if (write_to_db && db_mode == WRITE_THROUGH && db_link_contact_to_impu(impu, contact) != 0) {
|
|
|
|
+ LM_ERR("Failed to update DB linking contact [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
+ };
|
|
} else {
|
|
} else {
|
|
- LM_DBG("unable to link contact to impu as too many links already > %d\n", MAX_CONTACTS_PER_IMPU);
|
|
|
|
- return -1;
|
|
|
|
|
|
+ LM_DBG("unable to link contact to impu as too many links already > %d\n", MAX_CONTACTS_PER_IMPU);
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/* link contact to impu
|
|
|
|
- must be called with lock on domain (IMPU) as well as lock on contact_slot
|
|
|
|
- */
|
|
|
|
-int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db)
|
|
|
|
-{
|
|
|
|
|
|
+int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_to_db) {
|
|
ucontact_t* ptr;
|
|
ucontact_t* ptr;
|
|
int i;
|
|
int i;
|
|
- i=0;
|
|
|
|
- int found=0;
|
|
|
|
- ptr=impu->newcontacts[i];
|
|
|
|
|
|
+ i = 0;
|
|
|
|
+ int found = 0;
|
|
|
|
+ ptr = impu->newcontacts[i];
|
|
|
|
|
|
- LM_DBG("asked to unlink contact [%.*s] from impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
-
|
|
|
|
- while (i<MAX_CONTACTS_PER_IMPU && ptr) {
|
|
|
|
- if (found) {
|
|
|
|
- //shift all later pointers forward by 1
|
|
|
|
- impu->newcontacts[i-1] = impu->newcontacts[i];
|
|
|
|
- } else {
|
|
|
|
- if (ptr == contact) {
|
|
|
|
- LM_DBG("unlinking contact [%.*s] from impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
-
|
|
|
|
- if (exists_ulcb_type(impu->cbs, UL_IMPU_DELETE_CONTACT)) {
|
|
|
|
- LM_DBG("Running callback UL_IMPU_DELETE_CONTACT for contact [%.*s] and impu [%.*s]\n", impu->public_identity.len, impu->public_identity.s, ptr->c.len, ptr->c.s);
|
|
|
|
- run_ul_callbacks(impu->cbs, UL_IMPU_DELETE_CONTACT, impu, ptr);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- found = 1;
|
|
|
|
- impu->newcontacts[i]=0;
|
|
|
|
- impu->num_contacts--;
|
|
|
|
- LM_DBG("decrementing ref count on contact [%.*s] to %d\n", contact->c.len, contact->c.s, contact->ref_count);
|
|
|
|
- contact->ref_count--; //TODO - should we lock the actual ucontact struct?
|
|
|
|
- if (write_to_db && db_mode == WRITE_THROUGH && db_unlink_contact_from_impu(impu, contact) != 0) {
|
|
|
|
- LM_ERR("Failed to un-link DB contact [%.*s] from IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- i++;
|
|
|
|
- ptr = impu->newcontacts[i];
|
|
|
|
|
|
+ LM_DBG("asked to unlink contact [%.*s] from impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
+
|
|
|
|
+ while (i < MAX_CONTACTS_PER_IMPU && ptr) {
|
|
|
|
+ if (found) {
|
|
|
|
+ //shift all later pointers forward by 1
|
|
|
|
+ impu->newcontacts[i - 1] = impu->newcontacts[i];
|
|
|
|
+ } else {
|
|
|
|
+ if (ptr == contact) {
|
|
|
|
+ LM_DBG("unlinking contact [%.*s] from impu [%.*s]\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
+
|
|
|
|
+ if (exists_ulcb_type(impu->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, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
+ run_ul_callbacks(impu->cbs, UL_IMPU_DELETE_CONTACT, impu, ptr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ found = 1;
|
|
|
|
+ impu->newcontacts[i] = 0;
|
|
|
|
+ impu->num_contacts--;
|
|
|
|
+ unref_contact_unsafe(contact); //should we lock the actual contact? safe version maybe?
|
|
|
|
+
|
|
|
|
+ if (write_to_db && db_mode == WRITE_THROUGH && db_unlink_contact_from_impu(impu, contact) != 0) {
|
|
|
|
+ LM_ERR("Failed to un-link DB contact [%.*s] from IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ i++;
|
|
|
|
+ ptr = impu->newcontacts[i];
|
|
}
|
|
}
|
|
|
|
|
|
if (found && i < MAX_CONTACTS_PER_IMPU) {
|
|
if (found && i < MAX_CONTACTS_PER_IMPU) {
|
|
- LM_DBG("zero'ing last pointer to contact in the list\n");
|
|
|
|
- impu->newcontacts[i-1]=0;
|
|
|
|
|
|
+ LM_DBG("zero'ing last pointer to contact in the list\n");
|
|
|
|
+ impu->newcontacts[i - 1] = 0;
|
|
} else {
|
|
} else {
|
|
- LM_DBG("contact [%.*s] did not exist in IMPU list [%.*s] while trying to unlink\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
|
|
|
|
+ LM_DBG("contact [%.*s] did not exist in IMPU list [%.*s] while trying to unlink\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void ref_subscription_unsafe(ims_subscription* s) {
|
|
void ref_subscription_unsafe(ims_subscription* s) {
|
|
LM_DBG("Reffing subscription [%.*s] - was [%d]\n", s->private_identity.len, s->private_identity.s, s->ref_count);
|
|
LM_DBG("Reffing subscription [%.*s] - was [%d]\n", s->private_identity.len, s->private_identity.s, s->ref_count);
|
|
- lock_subscription(s);
|
|
|
|
s->ref_count++;
|
|
s->ref_count++;
|
|
- unlock_subscription(s);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * @brief unref a subscription - assume slot and subsription locked!
|
|
|
|
+ * @param s
|
|
|
|
+ */
|
|
void unref_subscription_unsafe(ims_subscription* s) {
|
|
void unref_subscription_unsafe(ims_subscription* s) {
|
|
int sl;
|
|
int sl;
|
|
- unsigned int subscription_hash;
|
|
|
|
- LM_DBG("un-Reffing subscription [%.*s] - was [%d]\n", s->private_identity.len, s->private_identity.s, s->ref_count);
|
|
|
|
|
|
|
|
- subscription_hash = core_hash(&s->private_identity, 0, 0);
|
|
|
|
- sl = subscription_hash & (subs_hash_size - 1);
|
|
|
|
- lock_get(ims_subscription_list->slot[sl].lock);
|
|
|
|
- lock_subscription(s);
|
|
|
|
|
|
+ LM_DBG("un-reffing subscription [%.*s] - was [%d]\n", s->private_identity.len, s->private_identity.s, s->ref_count);
|
|
s->ref_count--;
|
|
s->ref_count--;
|
|
- if (s->ref_count == 0) {
|
|
|
|
|
|
+ if (s->ref_count == 0 && (s->sl >= 0)) { //-1 as sl means the subscription was never added to the list
|
|
|
|
+ sl = s->sl;
|
|
subs_slot_rem(&ims_subscription_list->slot[sl], s);
|
|
subs_slot_rem(&ims_subscription_list->slot[sl], s);
|
|
- free_ims_subscription_data(s);
|
|
|
|
- } else {
|
|
|
|
- unlock_subscription(s);
|
|
|
|
|
|
+ delete_subscription(s);
|
|
|
|
+ s = 0;
|
|
}
|
|
}
|
|
- lock_release(ims_subscription_list->slot[sl].lock);
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ref_subscription(ims_subscription* s) {
|
|
|
|
+ lock_subscription(s);
|
|
|
|
+ ref_subscription_unsafe(s);
|
|
|
|
+ unlock_subscription(s);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief unref subscription safely - assume no lock on subscription or subscription slot
|
|
|
|
+ * @param s
|
|
|
|
+ */
|
|
|
|
+void unref_subscription(ims_subscription* s) {
|
|
|
|
+ int ref;
|
|
|
|
+ lock_subscription(s);
|
|
|
|
+ ref = s->ref_count;
|
|
|
|
+ unref_subscription_unsafe(s);
|
|
|
|
+ if (ref > 1)
|
|
|
|
+ unlock_subscription(s);
|
|
}
|
|
}
|