Browse code

modules/ims: dialog, usrloc, qos and charging modules for IMS - dialog_ng - some fixes related to ref counting and state machine - usrlocs - fixes/improvements to internal storage for both P-CSCF and S-CSCF usrloc storage - registrars - fixes/improvements to the registrars for S-CSCF, P-CSCF - ims_charging - align to updated api for dialog_ng - ims_qos - align to updated api for dialog_ng

jaybeepee authored on 14/09/2015 07:04:03
Showing 70 changed files
... ...
@@ -12,4 +12,5 @@ SERLIBPATH=../../lib
12 12
 SER_LIBS+=$(SERLIBPATH)/kmi/kmi
13 13
 SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
14 14
 SER_LIBS+=$(SERLIBPATH)/kcore/kcore
15
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
15 16
 include ../../Makefile.modules
... ...
@@ -55,8 +55,6 @@ static char* profiles_wv_s = NULL;
55 55
 static char* profiles_nv_s = NULL;
56 56
 int detect_spirals = 1;
57 57
 str dlg_extra_hdrs = {NULL, 0};
58
-int initial_cbs_inscript = 1;
59
-
60 58
 str dlg_bridge_controller = str_init("sip:controller@kamailio.org");
61 59
 
62 60
 str ruri_pvar_param = str_init("$ru");
... ...
@@ -792,7 +790,7 @@ static int w_dlg_terminate(struct sip_msg *msg, char *side, char *r) {
792 790
         }
793 791
     }
794 792
 
795
-    dlg = get_current_dialog(msg);
793
+    dlg = dlg_get_msg_dialog(msg);
796 794
     //dlg_get_ctx_dialog();
797 795
     if (!dlg) {
798 796
         LM_DBG("Unable to find dialog for terminate\n");
... ...
@@ -234,6 +234,7 @@ void run_load_callbacks( void )
234 234
 void run_create_callbacks(struct dlg_cell *dlg, struct sip_msg *msg)
235 235
 {
236 236
 	struct dlg_callback *cb;
237
+        LM_DBG("Running DLG_CREATED callbacks\n");
237 238
 
238 239
 	if (create_cbs==NULL || create_cbs==POINTER_CLOSED_MARKER || create_cbs->first==NULL)
239 240
 		return;
... ...
@@ -70,8 +70,6 @@ typedef int (*set_dlg_variable_f)( str* callid, str* ftag, str* ttag,
70 70
 typedef str* (*get_dlg_variable_f)( str *callid, str *ftag, str *ttag,
71 71
                                     str* key);
72 72
 
73
-typedef struct dlg_cell* (*get_current_dlg_f)( struct sip_msg* msg);
74
-
75 73
 #define DLGCB_LOADED          (1<<0)
76 74
 #define DLGCB_CREATED         (1<<1)
77 75
 #define DLGCB_FAILED          (1<<2)
... ...
@@ -426,7 +426,7 @@ static int load_dialog_out_from_db(struct dlg_cell *dlg, str *did, int fetch_num
426 426
 			GET_STR_VALUE(to_uri,	values, DLGO_TO_URI_IDX, 	1, 0);
427 427
 			GET_STR_VALUE(to_tag,	values, DLGO_TO_TAG_IDX, 	1, 0);
428 428
 
429
-			dlg_out	= build_new_dlg_out(dlg, &to_uri, &to_tag);
429
+			dlg_out	= build_new_dlg_out(dlg, &to_uri, &to_tag, 0);
430 430
 
431 431
 			if (!dlg_out) {
432 432
 				LM_ERR("Error creating dlg_out cell\n");
... ...
@@ -534,7 +534,7 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
534 534
 			}
535 535
 
536 536
 			/*link the dialog*/
537
-			link_dlg(dlg, 0);
537
+			link_dlg(dlg, 0, 0);
538 538
 
539 539
 			GET_STR_VALUE(did, 		values, DLGI_DID_COL_IDX,		1, 0);
540 540
 			update_dlg_did(dlg, &did);
... ...
@@ -721,7 +721,7 @@ static int load_dialog_vars_from_db(int fetch_num_rows)
721 721
 					if (dlg->h_id == VAL_INT(values+1)) {
722 722
 						str key = { VAL_STR(values+2).s, strlen(VAL_STRING(values+2)) };
723 723
 						str value = { VAL_STR(values+3).s, strlen(VAL_STRING(values+3)) };
724
-						set_dlg_variable_unsafe(dlg, &key, &value, 1);
724
+						set_dlg_variable_unsafe(dlg, &key, &value);
725 725
 						break;
726 726
 					}
727 727
 					dlg = dlg->next;
... ...
@@ -886,8 +886,14 @@ error:
886 886
 
887 887
 int update_dialog_out_dbinfo_unsafe(struct dlg_cell * cell)
888 888
 {
889
+    	str x = {0,0};
890
+
889 891
 	struct dlg_cell_out *dlg_out	= cell->dlg_entry_out.first;
890
-	str x = {0,0};
892
+        if (!dlg_out) {
893
+            LM_DBG("no out dialogs to update\n");
894
+            return 0;
895
+        }
896
+            
891 897
 	if(use_dialog_out_table()!=0)
892 898
 		return -1;
893 899
 
... ...
@@ -1044,8 +1050,9 @@ int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
1044 1050
 		VAL_INT(GET_FIELD_IDX(values, DLGI_HASH_ENTRY_COL_IDX))	= cell->h_entry;
1045 1051
 		VAL_INT(GET_FIELD_IDX(values, DLGI_HASH_ID_COL_IDX))	= cell->h_id;
1046 1052
 		VAL_INT(GET_FIELD_IDX(values, DLGI_START_TIME_COL_IDX))	= cell->start_ts;
1047
-		VAL_INT(GET_FIELD_IDX(values, DLGI_STATE_COL_IDX))		= cell->state;
1053
+		VAL_INT(GET_FIELD_IDX(values, DLGI_STATE_COL_IDX))	= cell->state;
1048 1054
 		VAL_INT(GET_FIELD_IDX(values, DLGI_TIMEOUT_COL_IDX))	= (unsigned int)( (unsigned int)time(0) + cell->tl.timeout - get_ticks() );
1055
+                VAL_INT(GET_FIELD_IDX(values, DLGI_TOROUTE_INDEX_COL_IDX)) = cell->toroute;
1049 1056
 
1050 1057
 		SET_STR_VALUE(GET_FIELD_IDX(values, DLGI_CALLID_COL_IDX), cell->callid);
1051 1058
 		SET_STR_VALUE(GET_FIELD_IDX(values, DLGI_DID_COL_IDX), cell->did);
... ...
@@ -39,7 +39,6 @@ static int default_timeout; /*!< default dialog timeout */
39 39
 static int seq_match_mode; /*!< dlg_match mode */
40 40
 static int shutdown_done = 0; /*!< 1 when destroy_dlg_handlers was called */
41 41
 extern int detect_spirals;
42
-extern int initial_cbs_inscript;
43 42
 int spiral_detected = -1;
44 43
 
45 44
 extern struct rr_binds d_rrb; /*!< binding to record-routing module */
... ...
@@ -91,7 +90,7 @@ void destroy_dlg_handlers(void) {
91 90
  * \param id dialog hash id
92 91
  * \return 0 on success, -1 on failure
93 92
  */
94
-static inline int add_dlg_rr_param(struct dlg_cell *dlg, struct sip_msg *req, unsigned int entry, unsigned int id) {
93
+static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry, unsigned int id) {
95 94
     static char buf[RR_DLG_PARAM_SIZE];
96 95
     str s;
97 96
     int n;
... ...
@@ -104,8 +103,6 @@ static inline int add_dlg_rr_param(struct dlg_cell *dlg, struct sip_msg *req, un
104 103
     p += rr_param.len;
105 104
     *(p++) = '=';
106 105
 
107
-    char *did = p;
108
-
109 106
     n = RR_DLG_PARAM_SIZE - (p - buf);
110 107
     if (int2reverse_hex(&p, &n, entry) == -1)
111 108
         return -1;
... ...
@@ -123,33 +120,29 @@ static inline int add_dlg_rr_param(struct dlg_cell *dlg, struct sip_msg *req, un
123 120
         return -1;
124 121
     }
125 122
 
123
+    return 0;
124
+}
126 125
 
126
+/*!
127
+ * \brief Unreference a dialog from tm callback (another wrapper)
128
+ * \param t transaction, unused
129
+ * \param type type of the entered callback
130
+ * \param param saved dialog structure in the callback
131
+ */
132
+static void unref_dlg_from_cb(struct cell* t, int type, struct tmcb_params *param) {
133
+    dlg_cell_t *dlg = NULL;
134
+    dlg_iuid_t *iuid = NULL;
127 135
 
128
-    //add the did into the dlg structure
129
-    int did_len = p - did;
130
-
131
-    if (dlg->did.s) {
132
-        if (dlg->did.len < did_len) {
133
-            shm_free(dlg->did.s);
134
-            dlg->did.s = (char*) shm_malloc(did_len);
135
-            if (dlg->did.s == NULL) {
136
-                LM_ERR("failed to add did to dlg_cell struct\n");
137
-                return -1;
138
-            }
139
-        }
140
-    } else {
141
-        dlg->did.s = (char*) shm_malloc(did_len);
142
-        if (dlg->did.s == NULL) {
143
-            LM_ERR("failed to add did to dlg_cell struct\n");
144
-            return -1;
145
-        }
146
-    }
147
-    memcpy(dlg->did.s, did, did_len);
148
-    dlg->did.len = did_len;
149
-
150
-
136
+    LM_DBG("Unref dlg from callback called\n");
137
+    iuid = (dlg_iuid_t*) (*param->param);
138
+    if (iuid == NULL)
139
+        return;
151 140
 
152
-    return 0;
141
+    dlg = dlg_get_by_iuid(iuid);
142
+    if (dlg == NULL)
143
+        return;
144
+    /* unref by 2: 1 set when adding in tm cb, 1 sent by dlg_get_by_iuid() */
145
+    unref_dlg(dlg, 2);
153 146
 }
154 147
 
155 148
 /*!
... ...
@@ -236,11 +229,11 @@ int populate_leg_info(struct dlg_cell *dlg, struct sip_msg *msg,
236 229
     if (leg == DLG_CALLER_LEG)
237 230
         dlg->from_rr_nb = skip_recs;
238 231
 
239
-    LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
232
+    LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s [%p]\n",
240 233
             rr_set.len, rr_set.s, contact.len, contact.s,
241 234
             cseq.len, cseq.s,
242 235
             msg->rcv.bind_address->sock_str.len,
243
-            msg->rcv.bind_address->sock_str.s);
236
+            msg->rcv.bind_address->sock_str.s, msg->rcv.bind_address);
244 237
 
245 238
     if (dlg_set_leg_info(dlg, tag, &rr_set, &contact, &cseq, callee_bind_address, leg) != 0) {
246 239
         LM_ERR("dlg_set_leg_info failed\n");
... ...
@@ -255,6 +248,40 @@ error0:
255 248
     return -1;
256 249
 }
257 250
 
251
+/*!
252
+ * \brief Clone dialog internal unique id to shared memory
253
+ */
254
+dlg_iuid_t *dlg_get_iuid_shm_clone(dlg_cell_t *dlg) {
255
+    dlg_iuid_t *iuid = NULL;
256
+
257
+    if (dlg == NULL)
258
+        return NULL;
259
+
260
+    iuid = (dlg_iuid_t*) shm_malloc(sizeof (dlg_iuid_t));
261
+    if (iuid == NULL) {
262
+        LM_ERR("failed to clone dialog iuid\n");
263
+        return NULL;
264
+    }
265
+
266
+    memset(iuid, 0, sizeof (dlg_iuid_t));
267
+    iuid->h_entry = dlg->h_entry;
268
+    iuid->h_id = dlg->h_id;
269
+
270
+    return iuid;
271
+}
272
+
273
+/*!
274
+ * \brief Free dialog internal unique id stored in shared memory
275
+ */
276
+void dlg_iuid_sfree(void *iuid) {
277
+    if (iuid) {
278
+        LM_DBG("freeing dlg iuid [%u:%u] (%p)\n",
279
+                ((dlg_iuid_t*) iuid)->h_entry,
280
+                ((dlg_iuid_t*) iuid)->h_id, iuid);
281
+        shm_free(iuid);
282
+    }
283
+}
284
+
258 285
 /*!
259 286
  * \brief Function that executes BYE reply callbacks
260 287
  * \param t transaction, unused
... ...
@@ -284,6 +311,29 @@ static void dlg_terminated_confirmed(struct cell* t,
284 311
             0);
285 312
 }
286 313
 
314
+static void dlg_cancel_confirmed(struct cell* t,
315
+        int type,
316
+        struct tmcb_params* params) {
317
+    if (!params || !params->req || !params->param) {
318
+        LM_ERR("invalid parameters!\n");
319
+        return;
320
+    }
321
+
322
+    struct dlg_cell* dlg = (struct dlg_cell*) *params->param;
323
+
324
+    if (!dlg) {
325
+        LM_ERR("failed to get dialog from params!\n");
326
+        return;
327
+    }
328
+    /* dialog termination confirmed (BYE reply) */
329
+    run_dlg_callbacks(DLGCB_TERMINATED_CONFIRMED,
330
+            dlg,
331
+            params->req,
332
+            params->rpl,
333
+            DLG_DIR_UPSTREAM,
334
+            0);
335
+}
336
+
287 337
 /*!
288 338
  * \brief Execute callback for the BYE request and register callback for the BYE reply
289 339
  * \param req request message
... ...
@@ -319,952 +369,1323 @@ static void dlg_terminated(struct sip_msg* req,
319 369
     }
320 370
 }
321 371
 
322
-static void unlink_dlgouts_from_cb(struct cell* t, int type, struct tmcb_params *param) {
323
-    struct dlg_cell *dlg = (struct dlg_cell *) (*param->param);
372
+/*!
373
+ * \brief Execute callback for the BYE request and register callback for the BYE reply
374
+ * \param req request message
375
+ * \param dlg corresponding dialog
376
+ * \param dir message direction
377
+ */
378
+static void dlg_cancelled(struct sip_msg* req,
379
+        struct dlg_cell* dlg,
380
+        unsigned int dir) {
381
+    if (!req) {
382
+        LM_ERR("request is empty!");
383
+        return;
384
+    }
324 385
 
325
-    if (!dlg)
386
+    if (!dlg) {
387
+        LM_ERR("dialog is empty!");
326 388
         return;
389
+    }
327 390
 
328
-    if (t && t->fwded_totags && t->fwded_totags->tag.len > 0) {
329
-        LM_DBG("unlink_dlgouts_from_cb: transaction [%.*s] can now be removed IFF it has been marked for deletion\n", t->fwded_totags->tag.len, t->fwded_totags->tag.s);
330
-        dlg_remove_dlg_out_tag(dlg, &t->fwded_totags->tag);
391
+    /* dialog terminated (BYE) */
392
+    run_dlg_callbacks(DLGCB_TERMINATED, dlg, req, NULL, dir, 0);
393
+
394
+    /* register callback for the coresponding reply */
395
+    LM_DBG("Registering tmcb for CANCEL confirmed\n");
396
+    if (d_tmb.register_tmcb(req,
397
+            0,
398
+            TMCB_RESPONSE_OUT,
399
+            dlg_cancel_confirmed,
400
+            (void*) dlg,
401
+            0) <= 0) {
402
+        LM_ERR("cannot register response callback for CANCEL request\n");
403
+        return;
331 404
     }
332 405
 }
333 406
 
334
-/*!
335
- * \brief Function that is registered as TM callback and called on replies
336
- *
337
- * Function that is registered as TM callback and called on replies. It
338
- * parses the reply and set the appropriate event. This is then used to
339
- * update the dialog state, run eventual dialog callbacks and save or
340
- * update the necessary informations about the dialog.
341
- * \see next_state_dlg
342
- * \param t transaction, unused
343
- * \param type type of the entered callback
344
- * \param param saved dialog structure in the callback
345
- */
346
-static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) {
347
-    struct dlg_cell *dlg;
348
-    struct dlg_cell_out *dlg_out = 0;
407
+//static void unlink_dlgouts_from_cb(struct cell* t, int type, struct tmcb_params *param) {
408
+//    struct dlg_cell *dlg = (struct dlg_cell *) (*param->param);
409
+//
410
+//    if (!dlg)
411
+//        return;
349 412
 
350
-    int new_state, old_state, unref, event;
351
-    str to_tag, to_uri;
352
-    struct sip_msg *req = param->req;
353
-    struct sip_msg *rpl = param->rpl;
354
-    struct dlg_entry_out* dlg_entry_out = 0;
413
+//    if (t && t->fwded_totags && t->fwded_totags->tag.len > 0) {
414
+//        LM_DBG("unlink_dlgouts_from_cb: transaction [%.*s] can now be removed IFF it has been marked for deletion\n", t->fwded_totags->tag.len, t->fwded_totags->tag.s);
415
+//        dlg_remove_dlg_out_tag(dlg, &t->fwded_totags->tag);
416
+//    }
417
+//}
355 418
 
356
-    if (t && t->fwded_totags)
357
-        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] and TO is [%.*s]\n", type, t->fwded_totags->tag.len, t->fwded_totags->tag.s);
358
-    else
359
-        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i]\n", type);
419
+/*static void dlg_oncancel(struct cell* t, int type, struct tmcb_params *param) {
420
+    struct dlg_cell* dlg;
421
+    int unref = 0, old_state, new_state;
360 422
 
423
+    LM_DBG("RECEIVED CANCEL ON DIALOG......\n");
361 424
     dlg = (struct dlg_cell *) (*param->param);
362 425
     if (shutdown_done || dlg == 0)
363 426
         return;
364 427
 
365
-    if (t) {
366
-        dlg->transaction = t;
367
-    }
428
+    struct sip_msg *req = param->req;
429
+    old_state = dlg->state;
430
+    LM_DBG("DLG dialog id is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id);
431
+    next_state_dlg(dlg, DLG_EVENT_REQCANCEL, &old_state, &new_state, &unref, 0);
368 432
 
369
-    LM_DBG("DLG dialogid is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id);
433
+    if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED)
434
+        dlg_cancelled(req, dlg, DLG_DIR_NONE);
370 435
 
371
-    if (type == TMCB_RESPONSE_FWDED) {
372
-        // The state does not change, but the msg is mutable in this callback
373
-        LM_DBG("TMCB_RESPONSE_FWDED from TM received");
374
-        run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
375
-        return;
376
-    }
436
+    unref_dlg(dlg, unref);
437
+}*/
438
+
439
+/*!
440
+ * \brief Helper function that run dialog callbacks on forwarded requests
441
+ * \see dlg_seq_up_onreply
442
+ * \see dlg_seq_down_onreply
443
+ * \param t transaction, unused
444
+ * \param type type of the callback, should be TMCB_RESPONSE_FWDED
445
+ * \param param saved dialog structure inside the callback
446
+ * \param direction direction of the request
447
+ */
448
+static void dlg_seq_onreply_helper(struct cell* t, int type,
449
+        struct tmcb_params *param, const int direction) {
450
+    dlg_cell_t *dlg = NULL;
451
+    dlg_iuid_t *iuid = NULL;
377 452
 
378
-    if (type == TMCB_RESPONSE_OUT) {
379
-        LM_DBG("TMCB_RESPONSE_OUT\n");
453
+    if (shutdown_done)
454
+        return;
455
+    iuid = (dlg_iuid_t*) (*param->param);
456
+    dlg = dlg_get_by_iuid(iuid);
457
+    if (dlg == 0)
380 458
         return;
459
+
460
+    if (type == TMCB_RESPONSE_FWDED) {
461
+        run_dlg_callbacks(DLGCB_RESPONSE_WITHIN,
462
+                dlg,
463
+                param->req,
464
+                param->rpl,
465
+                direction,
466
+                0);
381 467
     }
468
+    dlg_release(dlg);
382 469
 
383
-    if (type == TMCB_RESPONSE_READY) {
384
-        if (rpl == FAKED_REPLY) {
385
-            LM_DBG("Faked reply\n");
386
-            return;
387
-        }
470
+    return;
471
+}
388 472
 
389
-        // get to tag
390
-        LM_DBG("Extracting to-tag from reply");
391
-        if (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)) {
392
-            LM_ERR("bad reply or missing TO hdr :-/\n");
393
-            to_tag.s = 0;
394
-            to_tag.len = 0;
395
-        } else {
396
-            //populate to uri for this branch.
397
-            to_uri = get_to(rpl)->uri;
473
+/*!
474
+ * \brief Run dialog callbacks on forwarded requests in upstream direction
475
+ * \see dlg_seq_onreply_helper
476
+ * \param t transaction, unused
477
+ * \param type type of the callback, should be TMCB_RESPONSE_FWDED
478
+ * \param param saved dialog structure inside the callback
479
+ */
480
+static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *param) {
481
+    return dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
482
+}
398 483
 
399
-            to_tag = get_to(rpl)->tag_value;
400
-            if (to_tag.s == 0 || to_tag.len == 0) {
401
-                LM_ERR("missing TAG param in TO hdr :-/\n");
402
-                to_tag.s = 0;
403
-                to_tag.len = 0;
404
-                //Here we assume that the transaction module timer will remove any early dialogs
405
-                return;
406
-            }
484
+/*!
485
+ * \brief Run dialog callbacks on forwarded requests in downstream direction
486
+ * \see dlg_seq_onreply_helper
487
+ * \param t transaction, unused
488
+ * \param type type of the callback, should be TMCB_RESPONSE_FWDED
489
+ * \param param saved dialog structure inside the callback
490
+ */
491
+static void dlg_seq_down_onreply(struct cell* t, int type, struct tmcb_params *param) {
492
+    return dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
493
+}
494
+
495
+/*!
496
+ * \brief Return the timeout for a dialog
497
+ * \param req SIP message
498
+ * \return value from timeout AVP if present or default timeout
499
+ */
500
+inline static int get_dlg_timeout(struct sip_msg *req) {
501
+    pv_value_t pv_val;
502
+
503
+    if (timeout_avp) {
504
+        if (pv_get_spec_value(req, timeout_avp, &pv_val) == 0 &&
505
+                pv_val.flags & PV_VAL_INT && pv_val.ri > 0) {
506
+            return pv_val.ri;
407 507
         }
508
+        LM_DBG("invalid AVP value, using default timeout\n");
509
+    }
510
+    return default_timeout;
511
+}
408 512
 
409
-        LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s);
513
+/*!
514
+ * \brief Helper function to get the necessary content from SIP message
515
+ * \param req SIP request
516
+ * \param callid found callid
517
+ * \param ftag found from tag
518
+ * \param ttag found to tag
519
+ * \param with_ttag flag set if to tag must be found for success
520
+ * \return 0 on success, -1 on failure
521
+ */
522
+static inline int pre_match_parse(struct sip_msg *req, str *callid,
523
+        str *ftag, str *ttag, int with_ttag) {
524
+    if (parse_headers(req, HDR_CALLID_F | HDR_TO_F, 0) < 0 || !req->callid ||
525
+            !req->to) {
526
+        LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
527
+        return -1;
410 528
     }
411 529
 
412
-    if (type == TMCB_DESTROY)
413
-        event = DLG_EVENT_TDEL;
414
-    else if (param->code < 200)
415
-        event = DLG_EVENT_RPL1xx;
416
-    else if (param->code < 300)
417
-        event = DLG_EVENT_RPL2xx;
418
-    else
419
-        event = DLG_EVENT_RPL3xx;
530
+    if (get_to(req)->tag_value.len == 0) {
531
+        if (with_ttag == 1) {
532
+            /* out of dialog request with preloaded Route headers; ignore. */
533
+            return -1;
534
+        } else {
535
+            ttag->s = NULL;
536
+            ttag->len = 0;
537
+        }
538
+    } else {
539
+        *ttag = get_to(req)->tag_value;
540
+    }
420 541
 
421
-    LM_DBG("Calling next_state_dlg and event is %i\n", event);
422
-    next_state_dlg(dlg, event, &old_state, &new_state, &unref, &to_tag);
542
+    if (parse_from_header(req) < 0 || get_from(req)->tag_value.len == 0) {
543
+        LM_ERR("failed to get From header\n");
544
+        return -1;
545
+    }
423 546
 
424
-    if (type == TMCB_RESPONSE_READY) {
425
-        LM_DBG("Checking if there is an existing dialog_out entry with same to-tag");
547
+    /* callid */
548
+    *callid = req->callid->body;
549
+    trim(callid);
550
+    /* from tag */
551
+    *ftag = get_from(req)->tag_value;
552
+    return 0;
553
+}
426 554
 
427
-        dlg_entry_out = &dlg->dlg_entry_out;
555
+static inline char* tm_type_to_string(int type) {
556
+    switch (type) {
557
+        case TMCB_REQUEST_IN:
558
+            return "TMCB_REQUEST_IN";
559
+        case TMCB_RESPONSE_IN:
560
+            return "TMCB_RESPONSE_IN";
561
+        case TMCB_E2EACK_IN:
562
+            return "TMCB_E2EACK_IN";
563
+        case TMCB_REQUEST_PENDING:
564
+            return "TMCB_REQUEST_PENDING";
565
+        case TMCB_REQUEST_FWDED:
566
+            return "TMCB_REQUEST_FWDED";
567
+        case TMCB_RESPONSE_FWDED:
568
+            return "TMCB_RESPONSE_FWDED";
569
+        case TMCB_ON_FAILURE_RO:
570
+            return "TMCB_ON_FAILURE_RO";
571
+        case TMCB_ON_FAILURE:
572
+            return "TMCB_ON_FAILURE";
573
+        case TMCB_REQUEST_OUT:
574
+            return "TMCB_REQUEST_OUT";
575
+        case TMCB_RESPONSE_OUT:
576
+            return "TMCB_RESPONSE_OUT";
577
+        case TMCB_LOCAL_COMPLETED:
578
+            return "TMCB_LOCAL_COMPLETED";
579
+        case TMCB_LOCAL_RESPONSE_OUT:
580
+            return "TMCB_LOCAL_RESPONSE_OUT";
581
+        case TMCB_ACK_NEG_IN:
582
+            return "TMCB_ACK_NEG_IN";
583
+        case TMCB_REQ_RETR_IN:
584
+            return "TMCB_REQ_RETR_IN";
585
+        case TMCB_LOCAL_RESPONSE_IN:
586
+            return "TMCB_LOCAL_RESPONSE_IN";
587
+        case TMCB_LOCAL_REQUEST_IN:
588
+            return "TMCB_LOCAL_REQUEST_IN";
589
+        case TMCB_DLG:
590
+            return "TMCB_DLG";
591
+        case TMCB_DESTROY:
592
+            return "TMCB_DESTROY";
593
+        case TMCB_E2ECANCEL_IN:
594
+            return "TMCB_E2ECANCEL_IN";
595
+        case TMCB_E2EACK_RETR_IN:
596
+            return "TMCB_E2EACK_RETR_IN";
597
+        case TMCB_RESPONSE_READY:
598
+            return "TMCB_RESPONSE_READY";
599
+        case TMCB_DONT_ACK:
600
+            return "TMCB_DONT_ACK";
601
+        case TMCB_REQUEST_SENT:
602
+            return "TMCB_REQUEST_SENT";
603
+        case TMCB_RESPONSE_SENT:
604
+            return "TMCB_RESPONSE_SENT";
605
+        case TMCB_ON_BRANCH_FAILURE:
606
+            return "TMCB_ON_BRANCH_FAILURE";
607
+        case TMCB_ON_BRANCH_FAILURE_RO:
608
+            return "TMCB_ON_BRANCH_FAILURE_RO";
609
+        case TMCB_MAX:
610
+            return "TMCB_MAX";
611
+    }
428 612
 
429
-        lock_get(dlg->dlg_out_entries_lock);
430
-        dlg_out = dlg_entry_out->first;
613
+    return "UNKNOWN";
614
+}
431 615
 
432
-        LM_DBG("Scanning dlg_entry_out list for dlg_out");
433
-        while (dlg_out) {
434
-            //Check if there is an already dialog_out entry with same To-tag
435
-            if (dlg_out->to_tag.len == to_tag.len &&
436
-                    memcmp(dlg_out->to_tag.s, to_tag.s, dlg_out->to_tag.len) == 0) {
437
-                //Found a dialog_out entry with same to_tag!
438
-                LM_DBG("Found dlg_out for to-tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s);
439
-                break;
440
-            }
441
-            dlg_out = dlg_out->next;
442
-        }
443
-        lock_release(dlg->dlg_out_entries_lock);
444
-
445
-        if (!dlg_out) {
446
-            LM_DBG("No dlg_out entry found - creating a new dialog_out entry on dialog [%p]\n", dlg);
447
-            dlg_out = build_new_dlg_out(dlg, &to_uri, &to_tag);
448
-
449
-            link_dlg_out(dlg, dlg_out, 0);
616
+/*!
617
+ * \brief Unreference a dialog (small wrapper to take care of shutdown)
618
+ * \see unref_dlg
619
+ * \param dialog unreferenced dialog
620
+ */
621
+/*static void unreference_dialog(void *dialog) {
622
+    // if the dialog table is gone, it means the system is shutting down.
623
+    if (!dialog || !d_table)
624
+        return;
625
+    unref_dlg((struct dlg_cell*) dialog, 1);
626
+}*/
450 627
 
451
-            /* save callee's cseq, caller cseq, callee contact and callee record route*/
452
-            if (populate_leg_info(dlg, rpl, t, DLG_CALLEE_LEG, &to_tag) != 0) {
453
-                LM_ERR("could not add further info to the dlg out\n");
454
-            }
628
+/*!
629
+ * \brief Parse the record-route parameter, to get dialog information back
630
+ * \param p start of parameter string
631
+ * \param end end of parameter string
632
+ * \param h_entry found dialog hash entry
633
+ * \param h_id found dialog hash id
634
+ * \return 0 on success, -1 on failure
635
+ */
636
+static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id) {
637
+    char *s;
455 638
 
456
-            if (!dlg_out) {
457
-                LM_ERR("failed to create new dialog out structure\n");
458
-                //TODO do something on this error!
639
+    for (s = p; p < end && *p != DLG_SEPARATOR; p++);
640
+    if (*p != DLG_SEPARATOR) {
641
+        LM_ERR("malformed rr param '%.*s'\n", (int) (long) (end - s), s);
642
+        return -1;
643
+    }
459 644
 
460
-            }
461
-        } else {
462
-            //This dlg_out already exists, update cseq and contact if present
645
+    if (reverse_hex2int(s, p - s, (unsigned int*) h_entry) < 0) {
646
+        LM_ERR("invalid hash entry '%.*s'\n", (int) (long) (p - s), s);
647
+        return -1;
648
+    }
463 649
 
464
-            LM_DBG("dlg_out entry found - updating cseq's for dialog out [%p] for to-tag [%.*s] \n", dlg_out, dlg_out->to_tag.len, dlg_out->to_tag.s);
650
+    if (reverse_hex2int(p + 1, end - (p + 1), (unsigned int*) h_id) < 0) {
651
+        LM_ERR("invalid hash id '%.*s'\n", (int) (long) (end - (p + 1)), p + 1);
652
+        return -1;
653
+    }
465 654
 
466
-            if ((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) < 0) || !rpl->cseq ||
467
-                    !rpl->cseq->parsed) {
468
-                LM_ERR("bad sip message or missing CSeq hdr :-/\n");
469
-            }
470
-            dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(rpl))->number), &(dlg_out->to_tag));
655
+    return 0;
656
+}
471 657
 
658
+/*!
659
+ * \brief Register a transaction on a dialog
660
+ * \param t transaction
661
+ * \param type type of the entered callback
662
+ * \param param saved dialog structure in the callback
663
+ */
664
+/*static int store_dlg_in_tm(struct sip_msg* msg,
665
+        struct cell* t,
666
+        struct dlg_cell *dlg) {
667
+    if (!msg || msg == FAKED_REPLY || !t || !dlg) {
668
+        LM_ERR("invalid parameter msg(%p), t(%p), dlg(%p)\n", msg, t, dlg);
669
+        return -1;
670
+    }
472 671
 
473
-            /* extract the contact address to update if present*/
474
-            if (!rpl->contact && (parse_headers(rpl, HDR_CONTACT_F, 0) < 0 || !rpl->contact)) {
475
-                LM_ERR("Can not update callee contact: bad sip message or missing Contact hdr\n");
476
-            }
477
-            else if (parse_contact(rpl->contact) < 0 ||
478
-                    ((contact_body_t *) rpl->contact->parsed)->contacts == NULL ||
479
-                    ((contact_body_t *) rpl->contact->parsed)->contacts->next != NULL) {
480
-                LM_ERR("Can not update callee contact: bad Contact HDR\n");
481
-            }
482
-            else
483
-            {
484
-                str contact;
485
-                contact = ((contact_body_t *) rpl->contact->parsed)->contacts->uri;
486
-                dlg_update_contact(dlg, DLG_CALLEE_LEG, &contact, &(dlg_out->to_tag));
487
-            }
672
+    if (get_dialog_from_tm(t)) {
673
+        LM_NOTICE("dialog %p is already set for this transaction!\n", dlg);
674
+        return 1;
675
+    }
488 676
 
489
-        }
677
+    // facilitate referencing of dialog through TMCB_MAX
678
+    if (d_tmb.register_tmcb(msg,
679
+            t,
680
+            TMCB_MAX,
681
+            dlg_tmcb_dummy,
682
+            (void*) dlg, unreference_dialog) < 0) {
683
+        LM_ERR("failed cache in T the shortcut to dlg %p\n", dlg);
684
+        return -3;
490 685
     }
491 686
 
492
-    if (new_state == DLG_STATE_EARLY) {
493
-	if ((dlg->dflags & DLG_FLAG_INSERTED) == 0) {
494
-	    dlg->dflags |= DLG_FLAG_NEW;
495
-	} else {
496
-	    dlg->dflags |= DLG_FLAG_CHANGED;
497
-	}
498
-	if (dlg_db_mode == DB_MODE_REALTIME)
499
-	    update_dialog_dbinfo(dlg);
687
+    // registering succeeded, we must increase the reference counter
688
+    ref_dlg(dlg, 1);
500 689
 
501
-	if (old_state != DLG_STATE_EARLY) {
502
-	    counter_inc(dialog_ng_cnts_h.early);
503
-	}
690
+    return 0;
691
+}*/
504 692
 
505
-	run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
506
-	return;
693
+/*!
694
+ * \brief Callback to register a transaction on a dialog
695
+ * \param t transaction, unused
696
+ * \param type type of the entered callback
697
+ * \param param saved dialog structure in the callback
698
+ */
699
+/*static void store_dlg_in_tm_cb(struct cell* t,
700
+        int type,
701
+        struct tmcb_params *param) {
702
+    struct dlg_cell *dlg = (struct dlg_cell *) (*param->param);
703
+
704
+    struct sip_msg* msg = param->rpl;
705
+    if (msg == NULL || msg == FAKED_REPLY) {
706
+        msg = param->req;
507 707
     }
508 708
 
509
-    LM_DBG("new state is %i and old state is %i\n", new_state, old_state);
709
+    store_dlg_in_tm(msg, t, dlg);
710
+}*/
510 711
 
511
-    if ((new_state == DLG_STATE_CONFIRMED) && (event == DLG_EVENT_RPL2xx)) {
512
-        LM_DBG("dialog %p confirmed \n", dlg);
513
-        //Remove all the other entries in dialog_out for the same dialog after TM expires the transaction
514
-        //(not before in order to absorb late in-early-dialog requests).
712
+/*!
713
+ * \brief Update the saved CSEQ information in dialog from SIP message
714
+ * \param dlg updated dialog
715
+ * \param req SIP request
716
+ * \param dir direction of request, must DLG_DIR_UPSTREAM or DLG_DIR_DOWNSTREAM
717
+ * \return 0 on success, -1 on failure
718
+ */
719
+static inline int update_cseqs(struct dlg_cell *dlg, struct sip_msg *req,
720
+        unsigned int dir, str *to_tag) {
721
+    if ((!req->cseq && parse_headers(req, HDR_CSEQ_F, 0) < 0) || !req->cseq ||
722
+            !req->cseq->parsed) {
723
+        LM_ERR("bad sip message or missing CSeq hdr :-/\n");
724
+        return -1;
725
+    }
515 726
 
516
-        //remove all other dlg_out objects
517
-        if (dlg_out) {
518
-            if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, unlink_dlgouts_from_cb, (void*) dlg, NULL) < 0) {
519
-                LM_ERR("failed to register deletion delay function\n");
520
-                LM_DBG("Removing all other DLGs");
521
-                dlg_remove_dlg_out(dlg_out, dlg, 0);
522
-            } else {
523
-                //mark the outs for deletion
524
-                dlg_remove_dlg_out(dlg_out, dlg, 1);
727
+    if (dir == DLG_DIR_UPSTREAM) {
728
+        return dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(req))->number), to_tag);
729
+    } else if (dir == DLG_DIR_DOWNSTREAM) {
730
+        return dlg_update_cseq(dlg, DLG_CALLER_LEG, &((get_cseq(req))->number), to_tag);
731
+    } else {
732
+        LM_CRIT("dir is not set!\n");
733
+        return -1;
734
+    }
735
+}
525 736
 
526
-            }
527
-        } else {
528
-            LM_ERR("There is no dlg_out structure - this is bad\n");
529
-            //TODO: add error handling here
530
-        }
737
+/*!
738
+ * \brief Function that is registered as TM callback and called on requests
739
+ * \see dlg_new_dialog
740
+ * \param t transaction, used to created the dialog
741
+ * \param type type of the entered callback
742
+ * \param param saved dialog structure in the callback
743
+ */
744
+void dlg_onreq(struct cell* t, int type, struct tmcb_params *param) {
745
+    sip_msg_t *req = param->req;
746
+    dlg_cell_t *dlg = NULL;
531 747
 
532
-        /* set start time */
533
-        dlg->start_ts = (unsigned int) (time(0));
748
+    if (req->first_line.u.request.method_value == METHOD_BYE) {
749
+        _dlg_ctx.t = 1;
750
+        return;
751
+    }
534 752
 
535
-        /* save the settings to the database,
536
-         * if realtime saving mode configured- save dialog now
537
-         * else: the next time the timer will fire the update*/
538
-        if ((dlg->dflags & DLG_FLAG_INSERTED) == 0) {
539
-	    dlg->dflags |= DLG_FLAG_NEW;
540
-	} else {
541
-	    dlg->dflags |= DLG_FLAG_CHANGED;
542
-	}
543
-	if (dlg_db_mode == DB_MODE_REALTIME)
544
-		update_dialog_dbinfo(dlg);
545
-	
753
+    if (req->first_line.u.request.method_value != METHOD_INVITE/* && req->first_line.u.request.method_value != METHOD_CANCEL*/) {
754
+        LM_DBG("Ignoring SIP Request: [%.*s] in dlg_onreq\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);
755
+        return;
756
+    }
546 757
 
547
-        if (0 != insert_dlg_timer(&dlg->tl, dlg->lifetime)) {
548
-            LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
549
-                    "with clid '%.*s' and tags '%.*s' \n",
550
-                    dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
551
-                    dlg->callid.len, dlg->callid.s,
552
-                    dlg->from_tag.len, dlg->from_tag.s);
758
+    dlg = dlg_get_ctx_dialog();
553 759
 
760
+    if (dlg != NULL) {
761
+        if (spiral_detected == 1) {
762
+            LM_DBG("Running DLGB_SPIRALED callback\n");
763
+            run_dlg_callbacks(DLGCB_SPIRALED, dlg,
764
+                    req, NULL, DLG_DIR_DOWNSTREAM, 0);
765
+            LM_DBG("This is a spiraled REQUEST\n");
766
+        } else if (spiral_detected == 0)
767
+            run_create_callbacks(dlg, req);
768
+    }
769
+    if (dlg == NULL) {
770
+        if ((req->flags & dlg_flag) != dlg_flag)
771
+            return;
772
+        LM_DBG("dialog creation on config flag\n");
773
+        dlg_new_dialog(req, t, 1);
774
+        dlg = dlg_get_ctx_dialog();
775
+    }
776
+    if (dlg != NULL) {
777
+        if (dlg_set_tm_callbacks(t, req, dlg, spiral_detected) !=0) {
778
+            LM_ERR("Failed to register TM Callbacks for dialog... this is bad!\n");
779
+            //the DLG_TM flag will not be set so at least we can clear the dialog later...
554 780
         } else {
555
-            ref_dlg(dlg, 1);
781
+            LM_DBG("dialog [%p] added to tm callbacks\n", dlg);
556 782
         }
557
-	
558
-	if (old_state == DLG_STATE_EARLY) 
559
-	    counter_add(dialog_ng_cnts_h.early, -1);
560
-	
561
-	counter_inc(dialog_ng_cnts_h.active);
562
-        run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
783
+        _dlg_ctx.t = 1;
784
+        dlg_release(dlg);
785
+    } else {
786
+        LM_ERR("Failed to create dialog.... this is bad\n");
787
+    }
788
+}
563 789
 
564
-        if (unref) unref_dlg(dlg, unref);
790
+/*!
791
+ * \brief Function that is registered as RR callback for dialog tracking
792
+ *
793
+ * Function that is registered as RR callback for dialog tracking. It
794
+ * sets the appropriate events after the SIP method and run the state
795
+ * machine to update the dialog state. It updates then the saved
796
+ * dialogs and also the statistics.
797
+ * \param req SIP request
798
+ * \param route_params record-route parameter
799
+ * \param param unused
800
+ */
801
+void dlg_onroute(struct sip_msg* req, str *route_params, void *param) {
802
+    dlg_cell_t *dlg;
803
+    dlg_iuid_t *iuid;
804
+    str val, callid, ftag, ttag;
805
+    int h_entry, h_id, new_state, old_state, unref, event, timeout;
806
+    unsigned int dir;
807
+    int ret = 0;
808
+
809
+    dlg = dlg_get_ctx_dialog();
810
+    if (dlg != NULL) {
811
+        dlg_release(dlg);
565 812
         return;
566 813
     }
567 814
 
568
-    if (new_state == DLG_STATE_CONCURRENTLY_CONFIRMED && (old_state == DLG_STATE_CONFIRMED || old_state == DLG_STATE_CONCURRENTLY_CONFIRMED)) {
569
-        //This is a concurrently confirmed call
570
-        LM_DBG("This is a concurrently confirmed call.");
571
-        //Create a new Dialog ID token “X”
572
-        //Not sure how to do this so just going to use existing Did and add an X character to it
573
-        str new_did;
574
-        create_concurrent_did(dlg, &new_did);
815
+    /* skip initial requests - they may end up here because of the
816
+     * preloaded route */
817
+    if ((!req->to && parse_headers(req, HDR_TO_F, 0) < 0) || !req->to) {
818
+        LM_ERR("bad request or missing TO hdr :-/\n");
819
+        return;
820
+    }
821
+    if (get_to(req)->tag_value.len == 0) {
822
+        LM_DBG("No to tag header found --- ignoring... MESSAGE [%.*s\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);
823
+        return;
824
+    }
575 825
 
576
-        //assign new did to the created or updated dialog_out entry.
577
-        update_dlg_out_did(dlg_out, &new_did);
826
+    dlg = 0;
827
+    dir = DLG_DIR_NONE;
578 828
 
579
-        //Then, duplicate the dialog_in entry and set its Dialog ID value to new_did
580
-        //for now rather just create new dlg structure with the correct params - this should be fixed if future use requires
829
+    if (seq_match_mode != SEQ_MATCH_NO_ID) {
830
+        if (d_rrb.get_route_param(req, &rr_param, &val) != 0) {
831
+            LM_DBG("Route param '%.*s' not found\n", rr_param.len, rr_param.s);
832
+            if (seq_match_mode == SEQ_MATCH_STRICT_ID)
833
+                return;
834
+        } else {
835
+            LM_DBG("route param is '%.*s' (len=%d)\n", val.len, val.s, val.len);
581 836
 
582
-        struct dlg_cell *new_dlg = 0;
583
-        new_dlg = build_new_dlg(&(dlg->callid) /*callid*/,
584
-                &(dlg->from_uri) /*from uri*/,
585
-                &(dlg->from_tag)/*from_tag*/,
586
-                &(dlg->req_uri) /*r-uri*/);
837
+            if (parse_dlg_rr_param(val.s, val.s + val.len, &h_entry, &h_id) < 0)
838
+                return;
587 839
 
588
-        //assign new did to dlg_in
589
-        update_dlg_did(new_dlg, &new_did);
840
+            dlg = lookup_dlg(h_entry, h_id);
841
+            if (dlg == 0) {
842
+                LM_WARN("unable to find dialog for %.*s "
843
+                        "with route param '%.*s' [%u:%u]\n",
844
+                        req->first_line.u.request.method.len,
845
+                        req->first_line.u.request.method.s,
846
+                        val.len, val.s, h_entry, h_id);
847
+                if (seq_match_mode == SEQ_MATCH_STRICT_ID)
848
+                    return;
849
+            } else {
850
+                if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0) {
851
+                    // lookup_dlg has incremented the ref count by 1
852
+                    unref_dlg(dlg, 1);
853
+                    return;
854
+                }
855
+                if (match_dialog(dlg, &callid, &ftag, &ttag, &dir) == 0) {
856
+                    LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
857
+                            "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
858
+                            req->first_line.u.request.method.len,
859
+                            req->first_line.u.request.method.s,
860
+                            callid.len, callid.s, callid.len,
861
+                            ftag.len, ftag.s, ftag.len,
862
+                            ttag.len, ttag.s, ttag.len, dir);
863
+                    LM_WARN("dialog identification elements are callid='%.*s'/%d, "
864
+                            "caller tag='%.*s'/%d\n",
865
+                            dlg->callid.len, dlg->callid.s, dlg->callid.len,
866
+                            dlg->from_tag.len, dlg->from_tag.s,
867
+                            dlg->from_tag.len);
868
+                    // lookup_dlg has incremented the ref count by 1
869
+                    dlg_release(dlg);
590 870
 
591
-        if (new_dlg == 0) {
592
-            LM_ERR("failed to create new dialog\n");
871
+                    // Reset variables in order to do a lookup based on SIP-Elements.
872
+                    dlg = 0;
873
+                    dir = DLG_DIR_NONE;
874
+
875
+                    if (seq_match_mode == SEQ_MATCH_STRICT_ID)
876
+                        return;
877
+                }
878
+            }
879
+        }
880
+    }
881
+
882
+    if (dlg == 0) {
883
+        if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0)
884
+            return;
885
+        /* TODO - try to use the RR dir detection to speed up here the
886
+         * search -bogdan */
887
+        dlg = get_dlg(&callid, &ftag, &ttag, &dir);
888
+        if (!dlg) {
889
+            LM_DBG("Callid '%.*s' not found\n",
890
+                    req->callid->body.len, req->callid->body.s);
593 891
             return;
594 892
         }
893
+    }
595 894
 
596
-        //link the new_dlg with dlg_out object
597
-        link_dlg_out(new_dlg, dlg_out, 0);
895
+    /* set current dialog - re-use ref increment from dlg_get() above */
896
+    set_current_dialog(req, dlg);
897
+    _dlg_ctx.iuid.h_entry = dlg->h_entry;
898
+    _dlg_ctx.iuid.h_id = dlg->h_id;
899
+
900
+    if (req->first_line.u.request.method_value != METHOD_ACK) {
901
+        iuid = dlg_get_iuid_shm_clone(dlg);
902
+        if (iuid != NULL) {
903
+            /* register callback for the replies of this request */
904
+            if (d_tmb.register_tmcb(req, 0, TMCB_RESPONSE_IN | TMCB_ON_FAILURE,
905
+                    dlg_onreply, (void*) iuid, dlg_iuid_sfree) < 0) {
906
+                LM_ERR("failed to register TMCB (3)\n");
907
+                shm_free(iuid);
908
+            }
909
+            iuid = NULL;
910
+        }
911
+    }
912
+    //    if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED,
913
+    //            store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) {
914
+    //        LM_ERR("failed to store dialog in transaction during dialog creation for later reference\n");
915
+    //    }
598 916
 
917
+    /* run state machine */
918
+    switch (req->first_line.u.request.method_value) {
919
+        case METHOD_PRACK:
920
+            event = DLG_EVENT_REQPRACK;
921
+            break;
922
+        case METHOD_ACK:
923
+            event = DLG_EVENT_REQACK;
924
+            break;
925
+        case METHOD_BYE:
926
+            event = DLG_EVENT_REQBYE;
927
+            break;
928
+//        case METHOD_CANCEL:
929
+//            event = DLG_EVENT_REQCANCEL;
930
+//            break;
931
+        default:
932
+            event = DLG_EVENT_REQ;
599 933
     }
600 934
 
601
-    if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED) {
602
-        LM_DBG("dialog %p failed (negative reply)\n", dlg);
603
-        /* dialog setup not completed (3456XX) */
604
-        run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
605
-        /* do unref */
606
-        if (unref)
607
-            unref_dlg(dlg, unref);
935
+    next_state_dlg(dlg, event, &old_state, &new_state, &unref, 0);
936
+    LM_DBG("unref after next state is %i\n", unref);
937
+    CURR_DLG_ID = req->id;
938
+    CURR_DLG_LIFETIME = (unsigned int) (time(0)) - dlg->start_ts;
939
+    CURR_DLG_STATUS = new_state;
940
+
941
+    //    dlg_run_event_route(dlg, req, old_state, new_state);
608 942
 
609
-		if (old_state == DLG_STATE_EARLY)
610
-		    counter_add(dialog_ng_cnts_h.early, -1);
611
-		return;
943
+    /* delay deletion of dialog until transaction has died off in order
944
+     * to absorb in-air messages */
945
+    if ((new_state == DLG_STATE_DELETED) && (old_state != DLG_STATE_DELETED)) {
946
+        iuid = dlg_get_iuid_shm_clone(dlg);
947
+        if (iuid != NULL) {
948
+            if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
949
+                    unref_dlg_from_cb, (void*) iuid, dlg_iuid_sfree) < 0) {
950
+                LM_ERR("failed to register deletion delay function\n");
951
+                shm_free(iuid);
952
+            } else {
953
+                ref_dlg(dlg, 1);
954
+            }
955
+        }
956
+//        unref_dlg(dlg, unref);
612 957
     }
613 958
 
614
-    if (unref) unref_dlg(dlg, unref);
959
+    //    if (new_state == DLG_STATE_CONFIRMED && old_state != DLG_STATE_CONFIRMED)
960
+    //        dlg_ka_add(dlg);
615 961
 
616
-    return;
617
-}
962
+    if (event == DLG_EVENT_REQCANCEL && new_state == DLG_STATE_DELETED &&
963
+            old_state != DLG_STATE_DELETED) {
964
+        LM_DBG("CANCEL successfully processed and old state was [%d]\n", old_state);
965
+        
966
+        ret = remove_dialog_timer(&dlg->tl);
967
+        if (ret < 0) {
968
+            LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
969
+                    "with clid '%.*s' and tags '%.*s'\n",
970
+                    dlg, dlg->h_entry, dlg->h_id,
971
+                    dlg->callid.len, dlg->callid.s,
972
+                    dlg->from_tag.len, dlg->from_tag.s);
618 973
 
619
-/*!
620
- * \brief Helper function that run dialog callbacks on forwarded requests
621
- * \see dlg_seq_up_onreply
622
- * \see dlg_seq_down_onreply
623
- * \param t transaction, unused
624
- * \param type type of the callback, should be TMCB_RESPONSE_FWDED
625
- * \param param saved dialog structure inside the callback
626
- * \param direction direction of the request
627
- */
628
-static void dlg_seq_onreply_helper(struct cell* t, int type,
629
-        struct tmcb_params *param, const int direction) {
630
-    struct dlg_cell *dlg;
974
+        } else if (ret > 0) {
975
+            LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
976
+                    "with clid '%.*s' and tags '%.*s' \n",
977
+                    dlg, dlg->h_entry, dlg->h_id,
978
+                    dlg->callid.len, dlg->callid.s,
979
+                    dlg->from_tag.len, dlg->from_tag.s);
631 980
 
632
-    dlg = (struct dlg_cell *) (*param->param);
633
-    if (shutdown_done || dlg == 0)
634
-        return;
981
+        } else {
982
+            unref++;
983
+        }
984
+        
985
+        dlg_terminated(req, dlg, dir);
986
+        unref_dlg(dlg, unref);
987
+        _dlg_ctx.cpid = my_pid();
988
+        _dlg_ctx.expect_t = 1;
989
+        dlg_set_ctx_iuid(dlg);
990
+        
991
+        if (old_state == DLG_STATE_EARLY) {
992
+            counter_add(dialog_ng_cnts_h.early, -1);
993
+        } else if (old_state == DLG_STATE_CONFIRMED ||old_state == DLG_STATE_CONFIRMED_NA) {
994
+            counter_add(dialog_ng_cnts_h.active, -1);
995
+        }
996
+        
997
+        goto done;
998
+    }
999
+    
1000
+    /* run actions for the transition */
1001
+    if (event == DLG_EVENT_REQBYE && new_state == DLG_STATE_DELETED &&
1002
+            old_state != DLG_STATE_DELETED) {
1003
+        LM_DBG("BYE successfully processed\n");
1004
+        /* remove from timer */
1005
+        ret = remove_dialog_timer(&dlg->tl);
1006
+        if (ret < 0) {
1007
+            LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
1008
+                    "with clid '%.*s' and tags '%.*s'\n",
1009
+                    dlg, dlg->h_entry, dlg->h_id,
1010
+                    dlg->callid.len, dlg->callid.s,
1011
+                    dlg->from_tag.len, dlg->from_tag.s);
635 1012
 
636
-    if (type == TMCB_RESPONSE_FWDED) {
637
-        run_dlg_callbacks(DLGCB_RESPONSE_WITHIN,
638
-                dlg,
639
-                param->req,
640
-                param->rpl,
641
-                direction,
642
-                0);
643
-        return;
1013
+        } else if (ret > 0) {
1014
+            LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
1015
+                    "with clid '%.*s' and tags '%.*s' \n",
1016
+                    dlg, dlg->h_entry, dlg->h_id,
1017
+                    dlg->callid.len, dlg->callid.s,
1018
+                    dlg->from_tag.len, dlg->from_tag.s);
1019
+
1020
+        } else {
1021
+            unref++;
1022
+        }
1023
+        /* dialog terminated (BYE) */
1024
+        dlg_terminated(req, dlg, dir);
1025
+        unref_dlg(dlg, unref);
1026
+        _dlg_ctx.cpid = my_pid();
1027
+        _dlg_ctx.expect_t = 1;
1028
+        dlg_set_ctx_iuid(dlg);
1029
+
1030
+        if (old_state == DLG_STATE_CONFIRMED ||old_state == DLG_STATE_CONFIRMED_NA) {
1031
+            counter_add(dialog_ng_cnts_h.active, -1);
1032
+        }
1033
+        
1034
+        goto done;
644 1035
     }
645 1036
 
646
-    return;
647
-}
1037
+    if (event == DLG_EVENT_REQCANCEL && new_state == DLG_STATE_DELETED &&
1038
+            old_state != DLG_STATE_DELETED) {
1039
+        LM_DBG("CANCEL successfully processed\n");
1040
+        /* remove from timer */
1041
+        ret = remove_dialog_timer(&dlg->tl);
1042
+        if (ret < 0) {
1043
+            LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
1044
+                    "with clid '%.*s' and tags '%.*s'\n",
1045
+                    dlg, dlg->h_entry, dlg->h_id,
1046
+                    dlg->callid.len, dlg->callid.s,
1047
+                    dlg->from_tag.len, dlg->from_tag.s);
1048
+
1049
+        } else if (ret > 0) {
1050
+            LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
1051
+                    "with clid '%.*s' and tags '%.*s' \n",
1052
+                    dlg, dlg->h_entry, dlg->h_id,
1053
+                    dlg->callid.len, dlg->callid.s,
1054
+                    dlg->from_tag.len, dlg->from_tag.s);
648 1055
 
649
-/*!
650
- * \brief Run dialog callbacks on forwarded requests in upstream direction
651
- * \see dlg_seq_onreply_helper
652
- * \param t transaction, unused
653
- * \param type type of the callback, should be TMCB_RESPONSE_FWDED
654
- * \param param saved dialog structure inside the callback
655
- */
656
-static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *param) {
657
-    return dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
658
-}
1056
+        } else {
1057
+            unref++;
1058
+        }
1059
+        /* dialog terminated (CANCEL) */
1060
+        dlg_cancelled(req, dlg, dir);
1061
+//        unref_dlg(dlg, unref);
1062
+        _dlg_ctx.cpid = my_pid();
1063
+        _dlg_ctx.expect_t = 1;
1064
+        dlg_set_ctx_iuid(dlg);
1065
+        counter_add(dialog_ng_cnts_h.early, -1);
1066
+        goto done;
1067
+    }
659 1068
 
660
-/*!
661
- * \brief Run dialog callbacks on forwarded requests in downstream direction
662
- * \see dlg_seq_onreply_helper
663
- * \param t transaction, unused
664
- * \param type type of the callback, should be TMCB_RESPONSE_FWDED
665
- * \param param saved dialog structure inside the callback
666
- */
667
-static void dlg_seq_down_onreply(struct cell* t, int type, struct tmcb_params *param) {
668
-    return dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
669
-}
1069
+    if ((event == DLG_EVENT_REQ || event == DLG_EVENT_REQACK)
1070
+            && (new_state == DLG_STATE_CONFIRMED || new_state == DLG_STATE_EARLY)) {
670 1071
 
671
-/*!
672
- * \brief Return the timeout for a dialog
673
- * \param req SIP message
674
- * \return value from timeout AVP if present or default timeout
675
- */
676
-inline static int get_dlg_timeout(struct sip_msg *req) {
677
-    pv_value_t pv_val;
1072
+        timeout = get_dlg_timeout(req);
1073
+        if (timeout != default_timeout) {
1074
+            dlg->lifetime = timeout;
1075
+        }
1076
+        //        reset = !((dlg->iflags & DLG_IFLAG_TIMER_NORESET) || dlg_timeout_noreset);
678 1077
 
679
-    if (timeout_avp) {
680
-        if (pv_get_spec_value(req, timeout_avp, &pv_val) == 0 &&
681
-                pv_val.flags & PV_VAL_INT && pv_val.ri > 0) {
682
-            return pv_val.ri;
1078
+        if ((new_state != DLG_STATE_EARLY) && (old_state != DLG_STATE_CONFIRMED/* || reset*/)) {
1079
+            if (update_dlg_timer(&dlg->tl, dlg->lifetime) == -1) {
1080
+                LM_ERR("failed to update dialog lifetime\n");
1081
+            } else {
1082
+                dlg->dflags |= DLG_FLAG_CHANGED;
1083
+            }
1084
+        }
1085
+        if (event != DLG_EVENT_REQACK) {
1086
+            if (update_cseqs(dlg, req, dir, &ttag) != 0) {
1087
+                LM_ERR("cseqs update failed\n");
1088
+            } else {
1089
+                dlg->dflags |= DLG_FLAG_CHANGED;
1090
+            }
1091
+        }
1092
+        if (dlg_db_mode == DB_MODE_REALTIME && (dlg->dflags & DLG_FLAG_CHANGED)) {
1093
+            update_dialog_dbinfo(dlg);
683 1094
         }
684
-        LM_DBG("invalid AVP value, using default timeout\n");
685
-    }
686
-    return default_timeout;
687
-}
688 1095
 
689
-/*!
690
- * \brief Helper function to get the necessary content from SIP message
691
- * \param req SIP request
692
- * \param callid found callid
693
- * \param ftag found from tag
694
- * \param ttag found to tag
695
- * \param with_ttag flag set if to tag must be found for success
696
- * \return 0 on success, -1 on failure
697
- */
698
-static inline int pre_match_parse(struct sip_msg *req, str *callid,
699
-        str *ftag, str *ttag, int with_ttag) {
700
-    if (parse_headers(req, HDR_CALLID_F | HDR_TO_F, 0) < 0 || !req->callid ||
701
-            !req->to) {
702
-        LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
703
-        return -1;
704
-    }
1096
+        if (old_state == DLG_STATE_CONFIRMED_NA) {
1097
+            LM_DBG("confirming ACK successfully processed\n");
705 1098
 
706
-    if (get_to(req)->tag_value.len == 0) {
707
-        if (with_ttag == 1) {
708
-            /* out of dialog request with preloaded Route headers; ignore. */
709
-            return -1;
1099
+            /* confirming ACK request */
1100
+            run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
710 1101
         } else {
711
-            ttag->s = NULL;
712
-            ttag->len = 0;
1102
+            LM_DBG("sequential request successfully processed\n");
1103
+
1104
+            /* within dialog request */
1105
+            run_dlg_callbacks(DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);
1106
+
1107
+            if ((event != DLG_EVENT_REQACK) &&
1108
+                    (dlg->cbs.types) & DLGCB_RESPONSE_WITHIN) {
1109
+                iuid = dlg_get_iuid_shm_clone(dlg);
1110
+                if (iuid != NULL) {
1111
+                    /* register callback for the replies of this request */
1112
+                    if (d_tmb.register_tmcb(req, 0, TMCB_RESPONSE_FWDED,
1113
+                            (dir == DLG_DIR_UPSTREAM) ? dlg_seq_down_onreply :
1114
+                            dlg_seq_up_onreply,
1115
+                            (void*) iuid, dlg_iuid_sfree) < 0) {
1116
+                        LM_ERR("failed to register TMCB (2)\n");
1117
+                        shm_free(iuid);
1118
+                    }
1119
+                }
1120
+            }
713 1121
         }
714
-    } else {
715
-        *ttag = get_to(req)->tag_value;
716 1122
     }
717 1123
 
718
-    if (parse_from_header(req) < 0 || get_from(req)->tag_value.len == 0) {
719
-        LM_ERR("failed to get From header\n");
720
-        return -1;
1124
+    if (new_state == DLG_STATE_CONFIRMED && old_state == DLG_STATE_CONFIRMED_NA) {
1125
+        dlg->dflags |= DLG_FLAG_CHANGED;
1126
+        if (dlg_db_mode == DB_MODE_REALTIME)
1127
+            update_dialog_dbinfo(dlg);
721 1128
     }
722 1129
 
723
-    /* callid */
724
-    *callid = req->callid->body;
725
-    trim(callid);
726
-    /* from tag */
727
-    *ftag = get_from(req)->tag_value;
728
-    return 0;
1130
+done:
1131
+    dlg_release(dlg);
1132
+    return;
729 1133
 }
730 1134
 
731 1135
 /*!
732
- * \brief Function that is registered as TM callback and called on requests
733
- * \see dlg_new_dialog
734
- * \param t transaction, used to created the dialog
1136
+ * \brief Function that is registered as TM callback and called on replies
1137
+ *
1138
+ * Function that is registered as TM callback and called on replies. It
1139
+ * parses the reply and set the appropriate event. This is then used to
1140
+ * update the dialog state, run eventual dialog callbacks and save or
1141
+ * update the necessary informations about the dialog.
1142
+ * \see next_state_dlg
1143
+ * \param t transaction, unused
735 1144
  * \param type type of the entered callback
736 1145
  * \param param saved dialog structure in the callback
737 1146
  */
738
-void dlg_onreq(struct cell* t, int type, struct tmcb_params *param) {
1147
+void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) {
1148
+    dlg_cell_t *dlg = NULL;
1149
+    dlg_iuid_t *iuid = NULL;
1150
+    struct dlg_cell_out *dlg_out = 0;
1151
+    char *event_s;
1152
+
1153
+    int new_state, old_state, unref, event;
1154
+    str to_tag={0,0}, to_uri, branch={0,0};
739 1155
     struct sip_msg *req = param->req;
1156
+    struct sip_msg *rpl = param->rpl;
1157
+    struct dlg_entry_out* dlg_entry_out = 0;
1158
+
1159
+    char* cb_type_s = tm_type_to_string(type);
1160
+
1161
+    if (t && t->fwded_totags)
1162
+        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] = [%s] and TO is [%.*s]\n", type, cb_type_s, t->fwded_totags->tag.len, t->fwded_totags->tag.s);
1163
+    else
1164
+        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] = [%s]\n", type, cb_type_s);
740 1165
 
741
-    if ((req->flags & dlg_flag) != dlg_flag)
1166
+    if (shutdown_done)
742