00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00052 #include <string.h>
00053 #include <time.h>
00054
00055 #include "../../trim.h"
00056 #include "../../pvar.h"
00057 #include "../../timer.h"
00058 #include "../../lib/kcore/statistics.h"
00059 #include "../../action.h"
00060 #include "../../script_cb.h"
00061 #include "../../lib/kcore/faked_msg.h"
00062 #include "../../parser/parse_from.h"
00063 #include "../../parser/parse_cseq.h"
00064 #include "../../parser/contact/parse_contact.h"
00065 #include "../../parser/parse_from.h"
00066 #include "../../parser/parse_rr.h"
00067 #include "../../modules/tm/tm_load.h"
00068 #include "../rr/api.h"
00069 #include "dlg_hash.h"
00070 #include "dlg_timer.h"
00071 #include "dlg_cb.h"
00072 #include "dlg_handlers.h"
00073 #include "dlg_req_within.h"
00074 #include "dlg_db_handler.h"
00075 #include "dlg_profile.h"
00076 #include "dlg_var.h"
00077
00078 static str rr_param;
00079 static int dlg_flag;
00080 static pv_spec_t *timeout_avp;
00081 static int default_timeout;
00082 static int seq_match_mode;
00083 static int shutdown_done = 0;
00084 extern int detect_spirals;
00085 extern int initial_cbs_inscript;
00086 extern int dlg_send_bye;
00087 extern int dlg_event_rt[DLG_EVENTRT_MAX];
00088 extern int dlg_wait_ack;
00089 int spiral_detected = -1;
00090
00091 extern struct rr_binds d_rrb;
00093
00094 extern stat_var *early_dlgs;
00095 extern stat_var *processed_dlgs;
00096 extern stat_var *expired_dlgs;
00097 extern stat_var *failed_dlgs;
00099 extern pv_elem_t *ruri_param_model;
00101 static unsigned int CURR_DLG_LIFETIME = 0;
00102 static unsigned int CURR_DLG_STATUS = 0;
00103 static unsigned int CURR_DLG_ID = 0xffffffff;
00107 #define RR_DLG_PARAM_SIZE (2*2*sizeof(int)+3+MAX_DLG_RR_PARAM_NAME)
00108
00109 #define DLG_SEPARATOR '.'
00110
00111 int dlg_set_tm_callbacks(tm_cell_t *t, sip_msg_t *req, dlg_cell_t *dlg,
00112 int mode);
00113 int dlg_set_tm_waitack(tm_cell_t *t, dlg_cell_t *dlg);
00114
00123 void init_dlg_handlers(char *rr_param_p, int dlg_flag_p,
00124 pv_spec_t *timeout_avp_p ,int default_timeout_p,
00125 int seq_match_mode_p)
00126 {
00127 rr_param.s = rr_param_p;
00128 rr_param.len = strlen(rr_param.s);
00129
00130 dlg_flag = 1<<dlg_flag_p;
00131
00132 timeout_avp = timeout_avp_p;
00133 default_timeout = default_timeout_p;
00134 seq_match_mode = seq_match_mode_p;
00135 }
00136
00137
00141 void destroy_dlg_handlers(void)
00142 {
00143 shutdown_done = 1;
00144 }
00145
00146
00154 static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry,
00155 unsigned int id)
00156 {
00157 static char buf[RR_DLG_PARAM_SIZE];
00158 str s;
00159 int n;
00160 char *p;
00161
00162 s.s = p = buf;
00163
00164 *(p++) = ';';
00165 memcpy(p, rr_param.s, rr_param.len);
00166 p += rr_param.len;
00167 *(p++) = '=';
00168
00169 n = RR_DLG_PARAM_SIZE - (p-buf);
00170 if (int2reverse_hex( &p, &n, entry)==-1)
00171 return -1;
00172
00173 *(p++) = DLG_SEPARATOR;
00174
00175 n = RR_DLG_PARAM_SIZE - (p-buf);
00176 if (int2reverse_hex( &p, &n, id)==-1)
00177 return -1;
00178
00179 s.len = p-buf;
00180
00181 if (d_rrb.add_rr_param( req, &s)<0) {
00182 LM_ERR("failed to add rr param\n");
00183 return -1;
00184 }
00185
00186 return 0;
00187 }
00188
00189
00203 int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg,
00204 struct cell* t, unsigned int leg, str *tag)
00205 {
00206 unsigned int skip_recs;
00207 str cseq;
00208 str contact;
00209 str rr_set;
00210
00211 dlg->bind_addr[leg] = msg->rcv.bind_address;
00212
00213
00214 if (leg==DLG_CALLER_LEG) {
00215 if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
00216 || !msg->cseq->parsed){
00217 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
00218 goto error0;
00219 }
00220 cseq = (get_cseq(msg))->number;
00221 } else {
00222
00223 cseq = dlg->cseq[DLG_CALLER_LEG];
00224 }
00225
00226
00227 if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){
00228 LM_ERR("bad sip message or missing Contact hdr\n");
00229 goto error0;
00230 }
00231 if ( parse_contact(msg->contact)<0 ||
00232 ((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
00233 ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) {
00234 LM_ERR("bad Contact HDR\n");
00235 goto error0;
00236 }
00237 contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri;
00238
00239
00240 if(!msg->record_route && (parse_headers(msg,HDR_EOH_F,0)<0) ){
00241 LM_ERR("failed to parse record route header\n");
00242 goto error0;
00243 }
00244
00245 if (leg==DLG_CALLER_LEG) {
00246 skip_recs = 0;
00247 } else {
00248
00249 skip_recs = dlg->from_rr_nb +
00250 ((t->relayed_reply_branch>=0)?
00251 ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_R2)?2:
00252 ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_RR)?1:0))
00253 :0);
00254 }
00255
00256 if(msg->record_route){
00257 if( print_rr_body(msg->record_route, &rr_set, leg,
00258 &skip_recs) != 0 ){
00259 LM_ERR("failed to print route records \n");
00260 goto error0;
00261 }
00262 } else {
00263 rr_set.s = 0;
00264 rr_set.len = 0;
00265 }
00266
00267 if(leg==DLG_CALLER_LEG)
00268 dlg->from_rr_nb = skip_recs;
00269
00270 LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
00271 rr_set.len, rr_set.s, contact.len, contact.s,
00272 cseq.len, cseq.s,
00273 msg->rcv.bind_address->sock_str.len,
00274 msg->rcv.bind_address->sock_str.s);
00275
00276 if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) {
00277 LM_ERR("dlg_set_leg_info failed\n");
00278 if (rr_set.s) pkg_free(rr_set.s);
00279 goto error0;
00280 }
00281
00282 if (rr_set.s) pkg_free(rr_set.s);
00283
00284 return 0;
00285 error0:
00286 return -1;
00287 }
00288
00292 dlg_iuid_t *dlg_get_iuid_shm_clone(dlg_cell_t *dlg)
00293 {
00294 dlg_iuid_t *iuid = NULL;
00295
00296 if(dlg==NULL)
00297 return NULL;
00298
00299 iuid = (dlg_iuid_t*)shm_malloc(sizeof(dlg_iuid_t));
00300 if(iuid==NULL)
00301 {
00302 LM_ERR("failed to clone dialog iuid\n");
00303 return NULL;
00304 }
00305
00306 memset(iuid, 0, sizeof(dlg_iuid_t));
00307 iuid->h_entry = dlg->h_entry;
00308 iuid->h_id = dlg->h_id;
00309
00310 return iuid;
00311 }
00312
00313
00317 void dlg_iuid_sfree(void *iuid)
00318 {
00319 if(iuid) {
00320 LM_DBG("freeing dlg iuid [%u:%u] (%p)\n",
00321 ((dlg_iuid_t*)iuid)->h_entry,
00322 ((dlg_iuid_t*)iuid)->h_id, iuid);
00323 shm_free(iuid);
00324 }
00325 }
00326
00327
00334 static void dlg_terminated_confirmed(tm_cell_t *t, int type,
00335 struct tmcb_params* params)
00336 {
00337 dlg_cell_t *dlg = NULL;
00338 dlg_iuid_t *iuid = NULL;
00339
00340 if(!params || !params->req || !params->param)
00341 {
00342 LM_ERR("invalid parameters!\n");
00343 return;
00344 }
00345
00346 iuid = (dlg_iuid_t*)*params->param;
00347 if(iuid==NULL)
00348 return;
00349
00350 dlg = dlg_get_by_iuid(iuid);
00351
00352 if(dlg==NULL)
00353 {
00354 LM_ERR("failed to get dialog from params!\n");
00355 return;
00356 }
00357
00358 run_dlg_callbacks(DLGCB_TERMINATED_CONFIRMED,
00359 dlg,
00360 params->req,
00361 params->rpl,
00362 DLG_DIR_UPSTREAM,
00363 0);
00364 dlg_release(dlg);
00365 }
00366
00373 static void dlg_terminated(sip_msg_t *req, dlg_cell_t *dlg, unsigned int dir)
00374 {
00375 dlg_iuid_t *iuid = NULL;
00376
00377 if(!req) {
00378 LM_ERR("request is empty!");
00379 return;
00380 }
00381
00382 if(!dlg) {
00383 LM_ERR("dialog is empty!");
00384 return;
00385 }
00386
00387
00388 run_dlg_callbacks(DLGCB_TERMINATED, dlg, req, NULL, dir, 0);
00389
00390 iuid = dlg_get_iuid_shm_clone(dlg);
00391 if(iuid==NULL)
00392 return;
00393
00394
00395 if (d_tmb.register_tmcb(req,
00396 0,
00397 TMCB_RESPONSE_OUT,
00398 dlg_terminated_confirmed,
00399 (void*)iuid,
00400 dlg_iuid_sfree) <= 0 ) {
00401 LM_ERR("cannot register response callback for BYE request\n");
00402 return;
00403 }
00404 }
00405
00412 static void dlg_ontdestroy(struct cell* t, int type, struct tmcb_params *param)
00413 {
00414 dlg_cell_t *dlg = NULL;
00415 dlg_iuid_t *iuid = NULL;
00416
00417 iuid = (dlg_iuid_t*)(*param->param);
00418 dlg = dlg_get_by_iuid(iuid);
00419 if(dlg==0)
00420 return;
00421
00422 dlg_unref(dlg, 2);
00423 }
00424
00437 static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
00438 {
00439 dlg_cell_t *dlg = NULL;
00440 dlg_iuid_t *iuid = NULL;
00441 int new_state, old_state, unref, event;
00442 str tag;
00443 sip_msg_t *req = param->req;
00444 sip_msg_t *rpl = param->rpl;
00445
00446 if (shutdown_done)
00447 return;
00448 iuid = (dlg_iuid_t*)(*param->param);
00449 dlg = dlg_get_by_iuid(iuid);
00450 if(dlg==0)
00451 return;
00452
00453 unref = 0;
00454 if (type==TMCB_RESPONSE_FWDED) {
00455
00456 run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
00457 goto done;
00458 }
00459
00460 if (type==TMCB_DESTROY)
00461 event = DLG_EVENT_TDEL;
00462 else if (param->code<200)
00463 event = DLG_EVENT_RPL1xx;
00464 else if (param->code<300)
00465 event = DLG_EVENT_RPL2xx;
00466 else
00467 event = DLG_EVENT_RPL3xx;
00468
00469 next_state_dlg( dlg, event, &old_state, &new_state, &unref);
00470 dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, new_state);
00471
00472 if (new_state==DLG_STATE_EARLY) {
00473 run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
00474 if (old_state!=DLG_STATE_EARLY)
00475 if_update_stat(dlg_enable_stats, early_dlgs, 1);
00476 goto done;
00477 }
00478
00479 if (new_state==DLG_STATE_CONFIRMED_NA &&
00480 old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
00481 LM_DBG("dialog %p confirmed (ACK pending)\n",dlg);
00482
00483 if (rpl != FAKED_REPLY) {
00484
00485 if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0)
00486 || !rpl->to) ) {
00487 LM_ERR("bad reply or missing TO hdr :-/\n");
00488 tag.s = 0;
00489 tag.len = 0;
00490 } else {
00491 tag = get_to(rpl)->tag_value;
00492 if (tag.s==0 || tag.len==0) {
00493 LM_ERR("missing TAG param in TO hdr :-/\n");
00494 tag.s = 0;
00495 tag.len = 0;
00496 }
00497 }
00498
00499
00500 if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
00501 LM_ERR("could not add further info to the dialog\n");
00502 }
00503 } else {
00504 LM_ERR("Faked reply!\n");
00505 }
00506
00507
00508 dlg->start_ts = (unsigned int)(time(0));
00509
00510
00511
00512
00513 dlg->dflags |= DLG_FLAG_NEW;
00514 if ( dlg_db_mode==DB_MODE_REALTIME )
00515 update_dialog_dbinfo(dlg);
00516
00517 if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
00518 LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
00519 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00520 dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
00521 dlg->callid.len, dlg->callid.s,
00522 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00523 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00524 } else {
00525
00526 dlg_ref(dlg, 1);
00527 }
00528
00529
00530 run_dlg_callbacks( DLGCB_CONFIRMED_NA, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
00531
00532 if (old_state==DLG_STATE_EARLY)
00533 if_update_stat(dlg_enable_stats, early_dlgs, -1);
00534
00535 if (unref) dlg_unref(dlg, unref);
00536 if_update_stat(dlg_enable_stats, active_dlgs, 1);
00537 goto done;
00538 }
00539
00540 if ( new_state==DLG_STATE_DELETED
00541 && (old_state==DLG_STATE_UNCONFIRMED
00542 || old_state==DLG_STATE_EARLY) ) {
00543 LM_DBG("dialog %p failed (negative reply)\n", dlg);
00544
00545 run_dlg_callbacks( DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
00546
00547 if (unref)
00548 dlg_unref(dlg, unref);
00549 if (old_state==DLG_STATE_EARLY)
00550 if_update_stat(dlg_enable_stats, early_dlgs, -1);
00551
00552 if_update_stat(dlg_enable_stats, failed_dlgs, 1);
00553
00554 if(dlg_wait_ack==1)
00555 dlg_set_tm_waitack(t, dlg);
00556 goto done;
00557 }
00558
00559 if (unref) dlg_unref(dlg, unref);
00560
00561 done:
00562
00563 dlg_release(dlg);
00564 return;
00565 }
00566
00567
00577 static void dlg_seq_onreply_helper(struct cell* t, int type,
00578 struct tmcb_params *param, const int direction)
00579 {
00580 dlg_cell_t *dlg = NULL;
00581 dlg_iuid_t *iuid = NULL;
00582
00583 if (shutdown_done)
00584 return;
00585 iuid = (dlg_iuid_t*)(*param->param);
00586 dlg = dlg_get_by_iuid(iuid);
00587 if (dlg==0)
00588 return;
00589
00590 if (type==TMCB_RESPONSE_FWDED)
00591 {
00592 run_dlg_callbacks( DLGCB_RESPONSE_WITHIN,
00593 dlg,
00594 param->req,
00595 param->rpl,
00596 direction,
00597 0);
00598 }
00599 dlg_release(dlg);
00600
00601 return;
00602 }
00603
00604
00612 static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *param)
00613 {
00614 return dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
00615 }
00616
00617
00625 static void dlg_seq_down_onreply(struct cell* t, int type, struct tmcb_params *param)
00626 {
00627 return dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
00628 }
00629
00630
00636 inline static int get_dlg_timeout(struct sip_msg *req)
00637 {
00638 pv_value_t pv_val;
00639
00640 if( timeout_avp ) {
00641 if ( pv_get_spec_value( req, timeout_avp, &pv_val)==0 &&
00642 pv_val.flags&PV_VAL_INT && pv_val.ri>0 ) {
00643 return pv_val.ri;
00644 }
00645 LM_DBG("invalid AVP value, using default timeout\n");
00646 }
00647 return default_timeout;
00648 }
00649
00650
00660 static inline int pre_match_parse( struct sip_msg *req, str *callid,
00661 str *ftag, str *ttag, int with_ttag)
00662 {
00663 if (parse_headers(req,HDR_CALLID_F|HDR_TO_F,0)<0 || !req->callid ||
00664 !req->to ) {
00665 LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
00666 return -1;
00667 }
00668
00669 if (get_to(req)->tag_value.len==0) {
00670 if (with_ttag == 1) {
00671
00672 return -1;
00673 } else {
00674 ttag->s = NULL;
00675 ttag->len = 0;
00676 }
00677 } else {
00678 *ttag = get_to(req)->tag_value;
00679 }
00680
00681 if (parse_from_header(req)<0 || get_from(req)->tag_value.len==0) {
00682 LM_ERR("failed to get From header\n");
00683 return -1;
00684 }
00685
00686
00687 *callid = req->callid->body;
00688 trim(callid);
00689
00690 *ftag = get_from(req)->tag_value;
00691 return 0;
00692 }
00693
00694
00702 void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
00703 {
00704 sip_msg_t *req = param->req;
00705 dlg_cell_t *dlg = NULL;
00706
00707 if(req->first_line.u.request.method_value != METHOD_INVITE)
00708 return;
00709
00710 dlg = dlg_get_ctx_dialog();
00711
00712 if (dlg!=NULL) {
00713 if (!initial_cbs_inscript) {
00714 if (spiral_detected == 1)
00715 run_dlg_callbacks( DLGCB_SPIRALED, dlg,
00716 req, NULL, DLG_DIR_DOWNSTREAM, 0);
00717 else if (spiral_detected == 0)
00718 run_create_callbacks(dlg, req);
00719 }
00720 }
00721 if (dlg==NULL) {
00722 if((req->flags&dlg_flag)!=dlg_flag)
00723 return;
00724 dlg_new_dialog(req, t, 1);
00725 dlg = dlg_get_ctx_dialog();
00726 }
00727 if (dlg!=NULL) {
00728 dlg_set_tm_callbacks(t, req, dlg, spiral_detected);
00729 dlg_release(dlg);
00730 }
00731 }
00732
00733
00739 #if 0
00740 static void unref_new_dialog(void *iuid)
00741 {
00742 struct tmcb_params p;
00743
00744 memset(&p, 0, sizeof(struct tmcb_params));
00745 p.param = (void*)&iuid;
00746 dlg_onreply(0, TMCB_DESTROY, &p);
00747 }
00748 #endif
00749
00750
00765 int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs)
00766 {
00767 dlg_cell_t *dlg;
00768 str s;
00769 str callid;
00770 str ftag;
00771 str ttag;
00772 str req_uri;
00773 unsigned int dir;
00774
00775 dlg = dlg_get_ctx_dialog();
00776 if(dlg != NULL) {
00777 dlg_release(dlg);
00778 return -1;
00779 }
00780
00781 if(req->first_line.u.request.method_value != METHOD_INVITE)
00782 return -1;
00783
00784 if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
00785 LM_WARN("pre-matching failed\n");
00786 return -1;
00787 }
00788
00789 if(ttag.s!=0 && ttag.len!=0)
00790 return -1;
00791
00792 if(pv_printf_s(req, ruri_param_model, &req_uri)<0) {
00793 LM_ERR("error - cannot print the r-uri format\n");
00794 return -1;
00795 }
00796 trim(&req_uri);
00797
00798 if (detect_spirals)
00799 {
00800 if (spiral_detected == 1)
00801 return 0;
00802
00803 dir = DLG_DIR_NONE;
00804
00805 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
00806 if (dlg)
00807 {
00808 LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
00809 callid.len, callid.s);
00810 spiral_detected = 1;
00811
00812 if (run_initial_cbs)
00813 run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL,
00814 DLG_DIR_DOWNSTREAM, 0);
00815
00816
00817 goto finish;
00818 }
00819 }
00820 spiral_detected = 0;
00821
00822 dlg = build_new_dlg (&callid ,
00823 &(get_from(req)->uri) ,
00824 &(get_to(req)->uri) ,
00825 &ftag,
00826 &req_uri );
00827
00828 if (dlg==0)
00829 {
00830 LM_ERR("failed to create new dialog\n");
00831 return -1;
00832 }
00833
00834
00835 if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
00836 &(get_from(req)->tag_value)) !=0)
00837 {
00838 LM_ERR("could not add further info to the dialog\n");
00839 shm_free(dlg);
00840 return -1;
00841 }
00842
00843
00844 dlg->vars = get_local_varlist_pointer(req, 1);
00845
00846 link_dlg(dlg, 0);
00847
00848 dlg->lifetime = get_dlg_timeout(req);
00849 s.s = _dlg_ctx.to_route_name;
00850 s.len = strlen(s.s);
00851 dlg_set_toroute(dlg, &s);
00852 dlg->sflags |= _dlg_ctx.flags;
00853 dlg->iflags |= _dlg_ctx.iflags;
00854
00855 if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0)
00856 dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;
00857
00858 if (run_initial_cbs) run_create_callbacks( dlg, req);
00859
00860
00861 if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
00862 add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
00863 LM_ERR("failed to add RR param\n");
00864 goto error;
00865 }
00866
00867
00868 dlg_ref(dlg, 1);
00869
00870 if_update_stat( dlg_enable_stats, processed_dlgs, 1);
00871
00872 finish:
00873 _dlg_ctx.iuid.h_entry = dlg->h_entry;
00874 _dlg_ctx.iuid.h_id = dlg->h_id;
00875 set_current_dialog(req, dlg);
00876 dlg_release(dlg);
00877
00878 return 0;
00879
00880 error:
00881 if (!spiral_detected)
00882 dlg_unref(dlg, 1);
00883 return -1;
00884 }
00885
00886
00895 int dlg_set_tm_callbacks(tm_cell_t *t, sip_msg_t *req, dlg_cell_t *dlg,
00896 int smode)
00897 {
00898 dlg_iuid_t *iuid = NULL;
00899 if(t==NULL)
00900 return -1;
00901
00902 if(smode==0) {
00903 iuid = dlg_get_iuid_shm_clone(dlg);
00904 if(iuid==NULL)
00905 {
00906 LM_ERR("failed to create dialog unique id clone\n");
00907 goto error;
00908 }
00909 if ( d_tmb.register_tmcb( req, t,
00910 TMCB_RESPONSE_READY|TMCB_RESPONSE_FWDED,
00911 dlg_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) {
00912 LM_ERR("failed to register TMCB\n");
00913 goto error;
00914 }
00915 }
00916
00917 dlg->dflags |= DLG_FLAG_TM;
00918
00919 return 0;
00920 error:
00921 dlg_iuid_sfree(iuid);
00922 return -1;
00923 }
00924
00931 int dlg_set_tm_waitack(tm_cell_t *t, dlg_cell_t *dlg)
00932 {
00933 dlg_iuid_t *iuid = NULL;
00934 if(t==NULL)
00935 return -1;
00936
00937 LM_DBG("registering TMCB to wait for negative ACK\n");
00938 iuid = dlg_get_iuid_shm_clone(dlg);
00939 if(iuid==NULL)
00940 {
00941 LM_ERR("failed to create dialog unique id clone\n");
00942 goto error;
00943 }
00944 dlg_ref(dlg, 1);
00945 if ( d_tmb.register_tmcb( NULL, t,
00946 TMCB_DESTROY,
00947 dlg_ontdestroy, (void*)iuid, dlg_iuid_sfree)<0 ) {
00948 LM_ERR("failed to register TMCB to wait for negative ACK\n");
00949 dlg_unref(dlg, 1);
00950 goto error;
00951 }
00952
00953 return 0;
00954 error:
00955 dlg_iuid_sfree(iuid);
00956 return -1;
00957 }
00958
00967 static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id)
00968 {
00969 char *s;
00970
00971 for ( s=p ; p<end && *p!=DLG_SEPARATOR ; p++ );
00972 if (*p!=DLG_SEPARATOR) {
00973 LM_ERR("malformed rr param '%.*s'\n", (int)(long)(end-s), s);
00974 return -1;
00975 }
00976
00977 if ( reverse_hex2int( s, p-s, (unsigned int*)h_entry)<0 ) {
00978 LM_ERR("invalid hash entry '%.*s'\n", (int)(long)(p-s), s);
00979 return -1;
00980 }
00981
00982 if ( reverse_hex2int( p+1, end-(p+1), (unsigned int*)h_id)<0 ) {
00983 LM_ERR("invalid hash id '%.*s'\n", (int)(long)(end-(p+1)), p+1 );
00984 return -1;
00985 }
00986
00987 return 0;
00988 }
00989
00990
00998 static inline int update_cseqs(struct dlg_cell *dlg, struct sip_msg *req,
00999 unsigned int dir)
01000 {
01001 if ( (!req->cseq && parse_headers(req,HDR_CSEQ_F,0)<0) || !req->cseq ||
01002 !req->cseq->parsed) {
01003 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
01004 return -1;
01005 }
01006
01007 if ( dir==DLG_DIR_UPSTREAM) {
01008 return dlg_update_cseq(dlg, DLG_CALLEE_LEG,&((get_cseq(req))->number));
01009 } else if ( dir==DLG_DIR_DOWNSTREAM) {
01010 return dlg_update_cseq(dlg, DLG_CALLER_LEG,&((get_cseq(req))->number));
01011 } else {
01012 LM_CRIT("dir is not set!\n");
01013 return -1;
01014 }
01015 }
01016
01023 static void unref_dlg_from_cb(struct cell* t, int type, struct tmcb_params *param)
01024 {
01025 dlg_cell_t *dlg = NULL;
01026 dlg_iuid_t *iuid = NULL;
01027
01028 iuid = (dlg_iuid_t*)(*param->param);
01029 if (iuid==NULL)
01030 return;
01031
01032 dlg = dlg_get_by_iuid(iuid);
01033 if(dlg==NULL)
01034 return;
01035
01036 dlg_unref(dlg, 2);
01037 }
01038
01039
01040 dlg_cell_t *dlg_get_msg_dialog(sip_msg_t *msg)
01041 {
01042 dlg_cell_t *dlg = NULL;
01043 str callid;
01044 str ftag;
01045 str ttag;
01046 unsigned int dir;
01047
01048
01049 dlg = dlg_get_ctx_dialog();
01050 if(dlg!=NULL)
01051 return dlg;
01052
01053 if (pre_match_parse(msg, &callid, &ftag, &ttag, 0)<0)
01054 return NULL;
01055 dir = DLG_DIR_NONE;
01056 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
01057 if (dlg==NULL){
01058 LM_DBG("dlg with callid '%.*s' not found\n",
01059 msg->callid->body.len, msg->callid->body.s);
01060 return NULL;
01061 }
01062 return dlg;
01063 }
01064
01076 void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
01077 {
01078 dlg_cell_t *dlg;
01079 dlg_iuid_t *iuid;
01080 str val, callid, ftag, ttag;
01081 int h_entry, h_id, new_state, old_state, unref, event, timeout;
01082 unsigned int dir;
01083 int ret = 0;
01084
01085 dlg = dlg_get_ctx_dialog();
01086 if (dlg!=NULL) {
01087 dlg_release(dlg);
01088 return;
01089 }
01090
01091
01092
01093 if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
01094 LM_ERR("bad request or missing TO hdr :-/\n");
01095 return;
01096 }
01097 if ( get_to(req)->tag_value.len==0 )
01098 return;
01099
01100 dlg = 0;
01101 dir = DLG_DIR_NONE;
01102
01103 if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
01104 if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
01105 LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
01106 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
01107 return;
01108 } else {
01109 LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);
01110
01111 if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
01112 return;
01113
01114 dlg = dlg_lookup(h_entry, h_id);
01115 if (dlg==0) {
01116 LM_WARN("unable to find dialog for %.*s "
01117 "with route param '%.*s' [%u:%u]\n",
01118 req->first_line.u.request.method.len,
01119 req->first_line.u.request.method.s,
01120 val.len,val.s, h_entry, h_id);
01121 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
01122 return;
01123 } else {
01124 if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) {
01125
01126 dlg_release(dlg);
01127 return;
01128 }
01129 if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
01130 LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
01131 "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
01132 req->first_line.u.request.method.len,
01133 req->first_line.u.request.method.s,
01134 callid.len, callid.s, callid.len,
01135 ftag.len, ftag.s, ftag.len,
01136 ttag.len, ttag.s, ttag.len, dir);
01137 LM_WARN("dialog identification elements are callid='%.*s'/%d, "
01138 "caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
01139 dlg->callid.len, dlg->callid.s, dlg->callid.len,
01140 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
01141 dlg->tag[DLG_CALLER_LEG].len,
01142 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
01143 dlg->tag[DLG_CALLEE_LEG].len);
01144
01145 dlg_release(dlg);
01146
01147
01148 dlg = 0;
01149 dir = DLG_DIR_NONE;
01150
01151 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
01152 return;
01153 }
01154 }
01155 }
01156 }
01157
01158 if (dlg==0) {
01159 if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
01160 return;
01161
01162
01163 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
01164 if (dlg==0){
01165 LM_DBG("Callid '%.*s' not found\n",
01166 req->callid->body.len, req->callid->body.s);
01167 return;
01168 }
01169 }
01170
01171
01172 set_current_dialog( req, dlg);
01173 _dlg_ctx.iuid.h_entry = dlg->h_entry;
01174 _dlg_ctx.iuid.h_id = dlg->h_id;
01175
01176
01177 switch ( req->first_line.u.request.method_value ) {
01178 case METHOD_PRACK:
01179 event = DLG_EVENT_REQPRACK; break;
01180 case METHOD_ACK:
01181 event = DLG_EVENT_REQACK; break;
01182 case METHOD_BYE:
01183 event = DLG_EVENT_REQBYE; break;
01184 default:
01185 event = DLG_EVENT_REQ;
01186 }
01187
01188 next_state_dlg( dlg, event, &old_state, &new_state, &unref);
01189 dlg_run_event_route(dlg, req, old_state, new_state);
01190
01191 CURR_DLG_ID = req->id;
01192 CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
01193 CURR_DLG_STATUS = new_state;
01194
01195
01196
01197 if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
01198 iuid = dlg_get_iuid_shm_clone(dlg);
01199 if(iuid!=NULL) {
01200 if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
01201 unref_dlg_from_cb, (void*)iuid, dlg_iuid_sfree)<0 ) {
01202 LM_ERR("failed to register deletion delay function\n");
01203 shm_free(iuid);
01204 } else {
01205 dlg_ref(dlg, 1);
01206 }
01207 }
01208 }
01209
01210 if (new_state==DLG_STATE_CONFIRMED && old_state!=DLG_STATE_CONFIRMED)
01211 dlg_ka_add(dlg);
01212
01213
01214 if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
01215 old_state!=DLG_STATE_DELETED) {
01216 LM_DBG("BYE successfully processed\n");
01217
01218 ret = remove_dialog_timer(&dlg->tl);
01219 if (ret < 0) {
01220 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
01221 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
01222 dlg, dlg->h_entry, dlg->h_id,
01223 dlg->callid.len, dlg->callid.s,
01224 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
01225 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
01226 } else if (ret > 0) {
01227 LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
01228 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
01229 dlg, dlg->h_entry, dlg->h_id,
01230 dlg->callid.len, dlg->callid.s,
01231 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
01232 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
01233 } else {
01234
01235 unref++;
01236 }
01237
01238 dlg_terminated( req, dlg, dir);
01239
01240 dlg_unref(dlg, unref);
01241
01242 if_update_stat( dlg_enable_stats, active_dlgs, -1);
01243 goto done;
01244 }
01245
01246 if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
01247 && new_state==DLG_STATE_CONFIRMED) {
01248
01249 timeout = get_dlg_timeout(req);
01250 if (timeout!=default_timeout) {
01251 dlg->lifetime = timeout;
01252 }
01253 if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) {
01254 LM_ERR("failed to update dialog lifetime\n");
01255 }
01256 if (update_cseqs(dlg, req, dir)!=0) {
01257 LM_ERR("cseqs update failed\n");
01258 } else {
01259 dlg->dflags |= DLG_FLAG_CHANGED;
01260 if ( dlg_db_mode==DB_MODE_REALTIME )
01261 update_dialog_dbinfo(dlg);
01262 }
01263
01264 if (old_state==DLG_STATE_CONFIRMED_NA) {
01265 LM_DBG("confirming ACK successfully processed\n");
01266
01267
01268 run_dlg_callbacks( DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
01269 } else {
01270 LM_DBG("sequential request successfully processed\n");
01271
01272
01273 run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);
01274
01275 if ( (event!=DLG_EVENT_REQACK) &&
01276 (dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
01277 iuid = dlg_get_iuid_shm_clone(dlg);
01278 if(iuid!=NULL)
01279 {
01280
01281 if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
01282 (dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:
01283 dlg_seq_up_onreply,
01284 (void*)iuid, dlg_iuid_sfree)<0 ) {
01285 LM_ERR("failed to register TMCB (2)\n");
01286 shm_free(iuid);
01287 }
01288 }
01289 }
01290 }
01291 }
01292
01293 if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
01294 dlg->dflags |= DLG_FLAG_CHANGED;
01295 if(dlg_db_mode == DB_MODE_REALTIME)
01296 update_dialog_dbinfo(dlg);
01297 }
01298
01299 done:
01300 dlg_release(dlg);
01301 return;
01302 }
01303
01304
01309 void dlg_ontimeout(struct dlg_tl *tl)
01310 {
01311 dlg_cell_t *dlg;
01312 int new_state, old_state, unref;
01313 sip_msg_t *fmsg;
01314
01315
01316 dlg = ((struct dlg_cell*)((char *)(tl) -
01317 (unsigned long)(&((struct dlg_cell*)0)->tl)));
01318
01319 if(dlg->state==DLG_STATE_CONFIRMED_NA
01320 || dlg->state==DLG_STATE_CONFIRMED)
01321 {
01322 if(dlg->toroute>0 && dlg->toroute<main_rt.entries
01323 && main_rt.rlist[dlg->toroute]!=NULL)
01324 {
01325 fmsg = faked_msg_next();
01326 if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0)
01327 {
01328 dlg_ref(dlg, 1);
01329 dlg_set_ctx_iuid(dlg);
01330 LM_DBG("executing route %d on timeout\n", dlg->toroute);
01331 set_route_type(REQUEST_ROUTE);
01332 run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0);
01333 dlg_reset_ctx_iuid();
01334 exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
01335 dlg_unref(dlg, 1);
01336 }
01337 }
01338
01339 if(dlg->iflags&DLG_IFLAG_TIMEOUTBYE)
01340 {
01341 dlg_bye_all(dlg, NULL);
01342
01343 dlg_run_event_route(dlg, NULL, dlg->state, DLG_STATE_DELETED);
01344 dlg_unref(dlg, 1);
01345 if_update_stat(dlg_enable_stats, expired_dlgs, 1);
01346 return;
01347 }
01348 }
01349
01350 next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref);
01351 dlg_run_event_route(dlg, NULL, old_state, new_state);
01352
01353 if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
01354 LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n",
01355 dlg->callid.len, dlg->callid.s,
01356 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
01357 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
01358
01359
01360 run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0);
01361
01362 dlg_unref(dlg, unref+1);
01363
01364 if_update_stat( dlg_enable_stats, expired_dlgs, 1);
01365 if_update_stat( dlg_enable_stats, active_dlgs, -1);
01366 } else {
01367 dlg_unref(dlg, 1);
01368 }
01369
01370 return;
01371 }
01372
01373
01381 int pv_get_dlg_lifetime(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
01382 {
01383 int l = 0;
01384 char *ch = NULL;
01385
01386 if(msg==NULL || res==NULL)
01387 return -1;
01388
01389 if (CURR_DLG_ID!=msg->id)
01390 return pv_get_null( msg, param, res);
01391
01392 res->ri = CURR_DLG_LIFETIME;
01393 ch = int2str( (unsigned long)res->ri, &l);
01394
01395 res->rs.s = ch;
01396 res->rs.len = l;
01397
01398 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
01399
01400 return 0;
01401 }
01402
01403
01411 int pv_get_dlg_status(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
01412 {
01413 int l = 0;
01414 char *ch = NULL;
01415
01416 if(msg==NULL || res==NULL)
01417 return -1;
01418
01419 if (CURR_DLG_ID!=msg->id)
01420 return pv_get_null( msg, param, res);
01421
01422 res->ri = CURR_DLG_STATUS;
01423 ch = int2str( (unsigned long)res->ri, &l);
01424
01425 res->rs.s = ch;
01426 res->rs.len = l;
01427
01428 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
01429
01430 return 0;
01431 }
01432
01437 void dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate)
01438 {
01439 sip_msg_t *fmsg;
01440 int rt;
01441
01442 if(dlg==NULL)
01443 return;
01444 if(ostate==nstate)
01445 return;
01446
01447 rt = -1;
01448 if(nstate==DLG_STATE_CONFIRMED_NA) {
01449 rt = dlg_event_rt[DLG_EVENTRT_START];
01450 } else if(nstate==DLG_STATE_DELETED) {
01451 if(ostate==DLG_STATE_CONFIRMED || ostate==DLG_STATE_CONFIRMED_NA)
01452 rt = dlg_event_rt[DLG_EVENTRT_END];
01453 else if(ostate==DLG_STATE_UNCONFIRMED || ostate==DLG_STATE_EARLY)
01454 rt = dlg_event_rt[DLG_EVENTRT_FAILED];
01455 }
01456
01457 if(rt==-1 || event_rt.rlist[rt]==NULL)
01458 return;
01459
01460 if(msg==NULL)
01461 fmsg = faked_msg_next();
01462 else
01463 fmsg = msg;
01464
01465 if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0)
01466 {
01467 dlg_ref(dlg, 1);
01468 dlg_set_ctx_iuid(dlg);
01469 LM_DBG("executing event_route %d on state %d\n", rt, nstate);
01470 set_route_type(REQUEST_ROUTE);
01471 run_top_route(event_rt.rlist[rt], fmsg, 0);
01472 dlg_reset_ctx_iuid();
01473 exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
01474 dlg_unref(dlg, 1);
01475 }
01476 }
01477
01478 int dlg_manage(sip_msg_t *msg)
01479 {
01480 str tag;
01481 int backup_mode;
01482 dlg_cell_t *dlg = NULL;
01483 tm_cell_t *t = NULL;
01484
01485 if( (msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL )
01486 {
01487 LM_ERR("bad TO header\n");
01488 return -1;
01489 }
01490 tag = get_to(msg)->tag_value;
01491 if(tag.s!=0 && tag.len!=0)
01492 {
01493 backup_mode = seq_match_mode;
01494 seq_match_mode = SEQ_MATCH_NO_ID;
01495 dlg_onroute(msg, NULL, NULL);
01496 seq_match_mode = backup_mode;
01497 } else {
01498 t = d_tmb.t_gett();
01499 if(t==T_UNDEFINED)
01500 t = NULL;
01501 if(dlg_new_dialog(msg, t, initial_cbs_inscript)!=0)
01502 return -1;
01503 dlg = dlg_get_ctx_dialog();
01504 if(dlg==NULL)
01505 return -1;
01506 if(t!=NULL)
01507 dlg_set_tm_callbacks(t, msg, dlg, spiral_detected);
01508 dlg_release(dlg);
01509 }
01510 return 1;
01511 }