Browse code

ims_usrloc_scscf: added a new contact state, udomain/impu improvements

- Added a new contact state: CONTACT_NOTIFY_READY - protect the
deletion of contact during the preparation of NOTIFY msg.
- Improved mem_timer_udomain() - protect the deletion of contact
during the preparation of NOTIFY msg.
- Improved process_impurecord() - first doing the contacts'
validity, then the subscribers' validity. This prevents contact
from remaining in the database after deleting a subscriber.

Aleksandar Yosifov authored on 17/07/2020 07:42:15 • Henning Westerholt committed on 21/07/2020 20:07:30
Showing 3 changed files
... ...
@@ -368,39 +368,6 @@ static inline void process_impurecord(impurecord_t* _r) {
368 368
 
369 369
     get_act_time();
370 370
 
371
-    s = _r->shead;
372
-    LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
373
-    while (s) {
374
-		next = s->next;
375
-        if (!valid_subscriber(s, act_time)) {
376
-            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n",
377
-                    s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
378
-            if (!dbwork) {
379
-                start_dbtransaction();
380
-                dbwork = 1;
381
-            }
382
-            delete_subscriber(_r, s);
383
-        } else {
384
-            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n",
385
-                    s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s,
386
-                    (unsigned int) (s->expires - time(NULL)));
387
-            sl = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size);
388
-            LM_DBG("Hash size: <%i>\n", sub_dialog_hash_size);
389
-            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);
390
-            /* search the record in hash table */
391
-            lock_get(&sub_dialog_table[sl].lock);
392
-            sub_dialog = pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, sl);
393
-            if (sub_dialog == NULL) {
394
-                LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n");
395
-            } else {
396
-                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);
397
-            }
398
-            lock_release(&sub_dialog_table[sl].lock);
399
-            mustdeleteimpu = 0;
400
-        }
401
-        s = next;
402
-    }
403
-
404 371
     LM_DBG("\tPublic Identity %.*s, Barred: [%d], State: [%s], contacts [%d], 3gppcontacts [%d]\n",
405 372
             _r->public_identity.len, _r->public_identity.s,
406 373
             _r->barring,
... ...
@@ -422,9 +389,9 @@ static inline void process_impurecord(impurecord_t* _r) {
422 389
 				num_contacts_to_expire++;
423 390
 			} else if (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
424 391
 				LM_DBG("Contact: <%.*s> is in state CONTACT_EXPIRE_PENDING_NOTIFY....running callback\n", ptr->c.len, ptr->c.s);
425
-				if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) {
426
-					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);
427
-					run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, ptr);
392
+				if (exists_ulcb_type(_r->cbs, UL_IMPU_EXPIRE_CONTACT)) {
393
+					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);
394
+					run_ul_callbacks(_r->cbs, UL_IMPU_EXPIRE_CONTACT, _r, ptr);
428 395
 				}
429 396
 				hascontacts = 1;    // we do this because the impu must only be deleted if in state deleted....
430 397
 				mustdeleteimpu = 0;
... ...
@@ -463,6 +430,39 @@ static inline void process_impurecord(impurecord_t* _r) {
463 430
         }
464 431
     }
465 432
 
433
+	s = _r->shead;
434
+    LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
435
+    while (s) {
436
+		next = s->next;
437
+        if (!valid_subscriber(s, act_time)) {
438
+            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n",
439
+                    s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
440
+            if (!dbwork) {
441
+                start_dbtransaction();
442
+                dbwork = 1;
443
+            }
444
+            delete_subscriber(_r, s);
445
+        } else {
446
+            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n",
447
+                    s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s,
448
+                    (unsigned int) (s->expires - time(NULL)));
449
+            sl = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size);
450
+            LM_DBG("Hash size: <%i>\n", sub_dialog_hash_size);
451
+            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);
452
+            /* search the record in hash table */
453
+            lock_get(&sub_dialog_table[sl].lock);
454
+            sub_dialog = pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, sl);
455
+            if (sub_dialog == NULL) {
456
+                LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n");
457
+            } else {
458
+                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);
459
+            }
460
+            lock_release(&sub_dialog_table[sl].lock);
461
+            mustdeleteimpu = 0;
462
+        }
463
+        s = next;
464
+    }
465
+
466 466
     if (!flag)
467 467
         LM_DBG("no contacts\n");
468 468
 
... ...
@@ -331,8 +331,19 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) {
331 331
 								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);
332 332
 							}
333 333
                         }
334
-                    } else if (contact_ptr->state != CONTACT_DELETED) {
335
-                        LM_DBG("expiring contact [%.*s](%.*s).... setting to CONTACT_EXPIRE_PENDING_NOTIFY\n",
334
+                    } else if (contact_ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
335
+						LM_DBG("expired pending notify contact [%.*s](%.*s).... setting to CONTACT_NOTIFY_READY\n",
336
+								contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s);
337
+						contact_ptr->state = CONTACT_NOTIFY_READY;
338
+						expired_contacts[num_expired_contacts] = contact_ptr;
339
+						num_expired_contacts++;
340
+					} else if (contact_ptr->state == CONTACT_NOTIFY_READY) {
341
+						LM_DBG("expired notify ready contact [%.*s](%.*s).... marking for deletion\n",
342
+								contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s);
343
+						expired_contacts[num_expired_contacts] = contact_ptr;
344
+						num_expired_contacts++;
345
+					} else if (contact_ptr->state != CONTACT_DELETED) {
346
+						LM_DBG("expiring contact [%.*s](%.*s).... setting to CONTACT_EXPIRE_PENDING_NOTIFY\n",
336 347
 								contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s);
337 348
                         contact_ptr->state = CONTACT_EXPIRE_PENDING_NOTIFY;
338 349
                         ref_contact_unsafe(contact_ptr);
... ...
@@ -399,16 +410,22 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep) {
399 410
         for (i=0; i<num_expired_contacts; i++) {
400 411
             slot = expired_contacts[i]->sl;
401 412
             lock_contact_slot_i(slot);
402
-            if (expired_contacts[i]->state != CONTACT_DELAYED_DELETE) {
403
-                LM_DBG("Setting contact state to CONTACT_DELETED for contact [%.*s](%.*s)\n",
413
+			if(expired_contacts[i]->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
414
+				LM_DBG("Contact state CONTACT_EXPIRE_PENDING_NOTIFY for contact [%.*s](%.*s)\n",
404 415
 						expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s);
405
-                expired_contacts[i]->state = CONTACT_DELETED;
406
-                unref_contact_unsafe(expired_contacts[i]);
407
-            } else {
408
-                LM_DBG("deleting contact [%.*s](%.*s)\n",
409
-						expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s);
410
-                delete_scontact(expired_contacts[i]);
411
-            }
416
+			} else {
417
+				if (expired_contacts[i]->state != CONTACT_DELAYED_DELETE) {
418
+					LM_DBG("Setting contact state from '%s' to CONTACT_DELETED for contact [%.*s](%.*s)\n",
419
+							get_contact_state_as_string(expired_contacts[i]->state),
420
+							expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s);
421
+					expired_contacts[i]->state = CONTACT_DELETED;
422
+					unref_contact_unsafe(expired_contacts[i]);
423
+				} else {
424
+					LM_DBG("deleting contact [%.*s](%.*s)\n",
425
+							expired_contacts[i]->aor.len, expired_contacts[i]->aor.s, expired_contacts[i]->c.len, expired_contacts[i]->c.s);
426
+					delete_scontact(expired_contacts[i]);
427
+				}
428
+			}
412 429
             unlock_contact_slot_i(slot);
413 430
         }
414 431
     }
... ...
@@ -146,11 +146,12 @@ typedef enum contact_state {
146 146
     CONTACT_DELETE_PENDING,
147 147
     CONTACT_EXPIRE_PENDING_NOTIFY,
148 148
     CONTACT_DELETED,
149
-    CONTACT_DELAYED_DELETE
149
+    CONTACT_DELAYED_DELETE,
150
+	CONTACT_NOTIFY_READY /**< Prevents deletion of a contact before construction of notify body */
150 151
 } contact_state_t;
151 152
 
152 153
 /*! \brief Valid contact is a contact that either didn't expire yet or is permanent */
153
-#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)
154
+#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)
154 155
 
155 156
 #define VALID_UE_TYPE(c, t)   ((t==0) || (t==1 && c->is_3gpp) || (t==2 && !c->is_3gpp))
156 157
 
... ...
@@ -405,6 +406,8 @@ static inline char* get_contact_state_as_string(enum contact_state c_state) {
405 406
             return "Contact deleted";
406 407
         case CONTACT_DELAYED_DELETE:
407 408
             return "Contact with delayed delete";
409
+		case CONTACT_NOTIFY_READY:
410
+			return "Contact expired with prepared NOTIFY";
408 411
         default:
409 412
             return "unknown";
410 413
     }