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
00037 #include <string.h>
00038 #include "../../mem/shm_mem.h"
00039 #include "../../dprint.h"
00040 #include "../../parser/contact/parse_contact.h"
00041 #include "../../parser/parse_to.h"
00042 #include "../../parser/parse_from.h"
00043 #include "../../parser/parse_uri.h"
00044 #include "../../trim.h"
00045 #include "../../ut.h"
00046 #include "../../config.h"
00047 #include "dlg.h"
00048 #include "t_reply.h"
00049 #include "../../parser/parser_f.h"
00050
00051
00052 #include "callid.h"
00053 #include "uac.h"
00054
00055 #define NORMAL_ORDER 0
00056 #define REVERSE_ORDER 1
00057
00058
00059 #ifdef DIALOG_CALLBACKS
00060
00061 struct new_dlg_cb{
00062 int types;
00063 struct new_dlg_cb* next;
00064 dialog_cb* callback;
00065 void* param;
00066 };
00067
00068 static struct new_dlg_cb* new_dlg_cb_list=0;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 int register_new_dlg_cb(int type, dialog_cb f, void* param)
00079 {
00080 struct new_dlg_cb* dlg_cb;
00081
00082 dlg_cb=shm_malloc(sizeof(struct new_dlg_cb));
00083 if (dlg_cb==0)
00084 return E_OUT_OF_MEM;
00085 dlg_cb->types=type;
00086 dlg_cb->callback=f;
00087 dlg_cb->param=param;
00088 dlg_cb->next=new_dlg_cb_list;
00089 new_dlg_cb_list=dlg_cb;
00090 return 0;
00091 }
00092
00093
00094 void destroy_new_dlg_cbs()
00095 {
00096 struct new_dlg_cb* c;
00097 struct new_dlg_cb* n;
00098
00099 c=new_dlg_cb_list;
00100 while(c){
00101 n=c->next;
00102 shm_free(c);
00103 c=n;
00104 }
00105 new_dlg_cb_list=0;
00106 }
00107
00108
00109 static void run_new_dlg_callbacks(int type, dlg_t* dlg, struct sip_msg* msg)
00110 {
00111 struct new_dlg_cb* c;
00112 for (c=new_dlg_cb_list; c; c=c->next){
00113 if (c->types & type)
00114 c->callback(type, dlg, msg);
00115 }
00116 }
00117
00118
00119 int register_dlg_tmcb(int types, dlg_t* dlg, transaction_cb f, void* param)
00120 {
00121
00122 if ((types&(TMCB_DLG|TMCB_DESTROY))!=types){
00123 LOG(L_CRIT, "BUG: tm: register_dlg_tmcb: bad types %d\n", types);
00124 return E_BUG;
00125 }
00126 if (f==0){
00127 LOG(L_CRIT, "BUG: tm: register_dlg_tmcb: null callback function");
00128 return E_BUG;
00129 }
00130 return insert_tmcb(&dlg->dlg_callbacks, types, f, param, NULL);
00131 }
00132
00133
00134
00135
00136 void run_trans_dlg_callbacks(dlg_t* dlg, struct cell* trans,
00137 struct retr_buf* rbuf)
00138 {
00139 struct tmcb_params params;
00140
00141 if (dlg->dlg_callbacks.first==0)
00142 return;
00143 memset(¶ms, 0, sizeof(params));
00144 if (rbuf){
00145 params.t_rbuf=rbuf;
00146 params.dst=&rbuf->dst;
00147 params.send_buf.s=rbuf->buffer;
00148 params.send_buf.len=rbuf->buffer_len;
00149 }
00150
00151 run_trans_callbacks_internal(&dlg->dlg_callbacks, TMCB_DLG, trans,
00152 ¶ms);
00153 }
00154
00155
00156 static void destroy_trans_dlg_callbacks(dlg_t* dlg)
00157 {
00158 struct tmcb_params params;
00159 struct tm_callback* cbp;
00160
00161 if ((dlg->dlg_callbacks.first==0) ||
00162 ((dlg->dlg_callbacks.reg_types&TMCB_DESTROY)==0) )
00163 return;
00164 memset(¶ms, 0, sizeof(params));
00165 for (cbp=(struct tm_callback*)dlg->dlg_callbacks.first;cbp;cbp=cbp->next){
00166 if (cbp->types & TMCB_DESTROY){
00167 params.param=&(cbp->param);
00168 cbp->callback(0, 0, ¶ms);
00169 }
00170 }
00171 }
00172 #endif
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 void get_raw_uri(str* _s)
00187 {
00188 char* aq;
00189
00190 if (_s->s[_s->len - 1] == '>') {
00191 aq = find_not_quoted(_s, '<');
00192 _s->len -= aq - _s->s + 2;
00193 _s->s = aq + 1;
00194 }
00195 }
00196
00197
00198
00199
00200
00201 static inline int str_duplicate(str* _d, str* _s)
00202 {
00203 _d->s = shm_malloc(_s->len);
00204 if (!_d->s) {
00205 LOG(L_ERR, "str_duplicate(): No memory left\n");
00206 return -1;
00207 }
00208
00209 memcpy(_d->s, _s->s, _s->len);
00210 _d->len = _s->len;
00211 return 0;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 static inline int calculate_hooks(dlg_t* _d)
00224 {
00225 str* uri;
00226 struct sip_uri puri;
00227 int nhop;
00228
00229
00230
00231 memset(&_d->hooks, 0, sizeof(_d->hooks));
00232 if (_d->route_set) {
00233 uri = &_d->route_set->nameaddr.uri;
00234 if (parse_uri(uri->s, uri->len, &puri) < 0) {
00235 LOG(L_ERR, "calculate_hooks(): Error while parsing URI\n");
00236 return -1;
00237 }
00238
00239 if (puri.lr.s) {
00240 if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
00241 else _d->hooks.request_uri = &_d->rem_uri;
00242 _d->hooks.next_hop = &_d->route_set->nameaddr.uri;
00243 _d->hooks.first_route = _d->route_set;
00244 nhop = F_RB_NH_LOOSE;
00245 } else {
00246 _d->hooks.request_uri = &_d->route_set->nameaddr.uri;
00247 _d->hooks.next_hop = _d->hooks.request_uri;
00248 _d->hooks.first_route = _d->route_set->next;
00249 if (_d->rem_target.len > 0)
00250 _d->hooks.last_route = &_d->rem_target;
00251 else
00252 _d->hooks.last_route = NULL;
00253 nhop = F_RB_NH_STRICT;
00254 }
00255 } else {
00256 if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
00257 else _d->hooks.request_uri = &_d->rem_uri;
00258
00259 if (_d->dst_uri.s) _d->hooks.next_hop = &_d->dst_uri;
00260 else _d->hooks.next_hop = _d->hooks.request_uri;
00261
00262 nhop = 0;
00263
00264
00265
00266
00267
00268 _d->hooks.first_route = 0;
00269 _d->hooks.last_route = 0;
00270 }
00271
00272 if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) {
00273 _d->hooks.ru.s = _d->hooks.request_uri->s;
00274 _d->hooks.ru.len = _d->hooks.request_uri->len;
00275 _d->hooks.request_uri = &_d->hooks.ru;
00276 get_raw_uri(_d->hooks.request_uri);
00277 }
00278 if ((_d->hooks.next_hop) && (_d->hooks.next_hop->s) && (_d->hooks.next_hop->len)) {
00279 _d->hooks.nh.s = _d->hooks.next_hop->s;
00280 _d->hooks.nh.len = _d->hooks.next_hop->len;
00281 _d->hooks.next_hop = &_d->hooks.nh;
00282 get_raw_uri(_d->hooks.next_hop);
00283 }
00284
00285 return nhop;
00286 }
00287
00288
00289
00290
00291
00292 int w_calculate_hooks(dlg_t* _d)
00293 {
00294 return calculate_hooks(_d);
00295 }
00296
00297
00298
00299
00300 int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d)
00301 {
00302 dlg_t* res;
00303 str generated_cid;
00304 str generated_ltag;
00305
00306 if (!_cid) {
00307 generate_callid(&generated_cid);
00308 _cid = &generated_cid;
00309 }
00310 if (_cid && (!_ltag)) {
00311 generate_fromtag(&generated_ltag, _cid);
00312 _ltag = &generated_ltag;
00313 }
00314 if (_lseq == 0) _lseq = DEFAULT_CSEQ;
00315
00316 if (!_cid || !_ltag || !_luri || !_ruri || !_d) {
00317 LOG(L_ERR, "new_dlg_uac(): Invalid parameter value\n");
00318 return -1;
00319 }
00320
00321 res = (dlg_t*)shm_malloc(sizeof(dlg_t));
00322 if (res == 0) {
00323 LOG(L_ERR, "new_dlg_uac(): No memory left\n");
00324 return -2;
00325 }
00326
00327
00328 memset(res, 0, sizeof(dlg_t));
00329
00330
00331 if (str_duplicate(&res->id.call_id, _cid) < 0) return -3;
00332
00333 if (str_duplicate(&res->id.loc_tag, _ltag) < 0) return -4;
00334
00335 if (str_duplicate(&res->loc_uri, _luri) < 0) return -5;
00336
00337 if (str_duplicate(&res->rem_uri, _ruri) < 0) return -6;
00338
00339 res->loc_seq.value = _lseq;
00340
00341 res->loc_seq.is_set = 1;
00342
00343 *_d = res;
00344
00345 if (calculate_hooks(*_d) < 0) {
00346 LOG(L_ERR, "new_dlg_uac(): Error while calculating hooks\n");
00347
00348 shm_free(res);
00349 return -2;
00350 }
00351 #ifdef DIALOG_CALLBACKS
00352 run_new_dlg_callbacks(DLG_CB_UAC, res, 0);
00353 #endif
00354
00355 return 0;
00356 }
00357
00366 int dlg_add_extra(dlg_t* _d, str* _ldname, str* _rdname)
00367 {
00368 if(!_d || !_ldname || !_rdname)
00369 {
00370 LM_ERR("Invalid parameters\n");
00371 return -1;
00372 }
00373
00374
00375 if(shm_str_dup(&_d->loc_dname, _ldname) < 0) return -2;
00376
00377 if(shm_str_dup(&_d->rem_dname, _rdname) < 0) return -3;
00378
00379 return 0;
00380 }
00381
00382
00383
00384
00385
00386 static inline int get_contact_uri(struct sip_msg* _m, str* _uri)
00387 {
00388 contact_t* c;
00389
00390 _uri->len = 0;
00391 _uri->s = 0;
00392
00393 if (!_m->contact) return 1;
00394
00395 if (parse_contact(_m->contact) < 0) {
00396 LOG(L_ERR, "get_contact_uri(): Error while parsing Contact body\n");
00397 return -2;
00398 }
00399
00400 c = ((contact_body_t*)_m->contact->parsed)->contacts;
00401
00402 if (!c) {
00403 LOG(L_ERR, "get_contact_uri(): Empty body or * contact\n");
00404 return -3;
00405 }
00406
00407 _uri->s = c->uri.s;
00408 _uri->len = c->uri.len;
00409 return 0;
00410 }
00411
00412
00413
00414
00415
00416
00417 static inline int get_to_tag(struct sip_msg* _m, str* _tag)
00418 {
00419 if (!_m->to) {
00420 LOG(L_ERR, "get_to_tag(): To header field missing\n");
00421 return -1;
00422 }
00423
00424 if (get_to(_m)->tag_value.len) {
00425 _tag->s = get_to(_m)->tag_value.s;
00426 _tag->len = get_to(_m)->tag_value.len;
00427 } else {
00428 _tag->len = 0;
00429 }
00430
00431 return 0;
00432 }
00433
00434
00435
00436
00437
00438 static inline int get_from_tag(struct sip_msg* _m, str* _tag)
00439 {
00440 if (parse_from_header(_m) == -1) {
00441 LOG(L_ERR, "get_from_tag(): Error while parsing From header\n");
00442 return -1;
00443 }
00444
00445 if (get_from(_m)->tag_value.len) {
00446 _tag->s = get_from(_m)->tag_value.s;
00447 _tag->len = get_from(_m)->tag_value.len;
00448 } else {
00449 _tag->len = 0;
00450 }
00451
00452 return 0;
00453 }
00454
00455
00456
00457
00458
00459
00460 static inline int get_callid(struct sip_msg* _m, str* _cid)
00461 {
00462 if (_m->callid == 0) {
00463 LOG(L_ERR, "get_callid(): Call-ID not found\n");
00464 return -1;
00465 }
00466
00467 _cid->s = _m->callid->body.s;
00468 _cid->len = _m->callid->body.len;
00469 trim(_cid);
00470 return 0;
00471 }
00472
00473 static rr_t *revert_route(rr_t *r)
00474 {
00475 rr_t *a, *b;
00476
00477 a = NULL;
00478
00479 while (r) {
00480 b = r->next;
00481 r->next = a;
00482 a = r;
00483 r = b;
00484 }
00485
00486 return a;
00487 }
00488
00489
00490
00491
00492 static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order)
00493 {
00494 struct hdr_field* ptr;
00495 rr_t* last, *p, *t;
00496
00497 last = 0;
00498
00499 ptr = _m->record_route;
00500 while(ptr) {
00501 if (ptr->type == HDR_RECORDROUTE_T) {
00502 if (parse_rr(ptr) < 0) {
00503 LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n");
00504 goto error;
00505 }
00506
00507 p = (rr_t*)ptr->parsed;
00508 if (shm_duplicate_rr(&t, p) < 0) {
00509 LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n");
00510 goto error;
00511 }
00512 if (!*_rs) *_rs = t;
00513 if (last) last->next = t;
00514 last = t;
00515 while (last->next) last = last->next;
00516
00517 }
00518 ptr = ptr->next;
00519 }
00520 if ((*_rs) && (_order != NORMAL_ORDER)) {
00521
00522 *_rs = revert_route(*_rs);
00523 }
00524
00525 return 0;
00526
00527 error:
00528 shm_free_rr(_rs);
00529 return -1;
00530 }
00531
00532
00533
00534
00535 static inline int get_cseq_method(struct sip_msg* _m, str* _method)
00536 {
00537 if (!_m->cseq && ((parse_headers(_m, HDR_CSEQ_F, 0) == -1) || !_m->cseq)) {
00538 LOG(L_ERR, "get_cseq_method(): Error while parsing CSeq\n");
00539 return -1;
00540 }
00541
00542 _method->s = get_cseq(_m)->method.s;
00543 _method->len = get_cseq(_m)->method.len;
00544 return 0;
00545 }
00546
00547
00548 static inline int refresh_dialog_resp(struct sip_msg* _m,
00549 target_refresh_t is_target_refresh)
00550 {
00551 str method;
00552
00553 switch (is_target_refresh) {
00554 case IS_NOT_TARGET_REFRESH:
00555 return 0;
00556 case IS_TARGET_REFRESH:
00557 return 1;
00558 case TARGET_REFRESH_UNKNOWN:
00559 if (get_cseq_method(_m, &method) < 0) return 0;
00560 if ((method.len == 6) && !memcmp("INVITE", method.s, 6))
00561 return 1;
00562 else return 0;
00563 }
00564 return 0;
00565 }
00566
00567 static inline int refresh_dialog_req(struct sip_msg* _m, target_refresh_t is_target_refresh)
00568 {
00569 switch (is_target_refresh) {
00570 case IS_NOT_TARGET_REFRESH:
00571 return 0;
00572 case IS_TARGET_REFRESH:
00573 return 1;
00574 case TARGET_REFRESH_UNKNOWN:
00575 return (_m->first_line.u.request.method_value == METHOD_INVITE);
00576 break;
00577 }
00578 return 0;
00579 }
00580
00581
00582
00583
00584
00585 static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
00586 {
00587 str contact, rtag;
00588
00589
00590 if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00591 LOG(L_ERR, "response2dlg(): Error while parsing headers\n");
00592 return -1;
00593 }
00594
00595 if (get_contact_uri(_m, &contact) < 0) return -2;
00596 if (_d->rem_target.s) {
00597 shm_free(_d->rem_target.s);
00598 _d->rem_target.s = 0;
00599 _d->rem_target.len = 0;
00600 }
00601 if (_d->dst_uri.s) {
00602 shm_free(_d->dst_uri.s);
00603 _d->dst_uri.s = 0;
00604 _d->dst_uri.len = 0;
00605 }
00606 if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
00607
00608 if (get_to_tag(_m, &rtag) < 0) goto err1;
00609 if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
00610
00611 if (get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0) goto err2;
00612
00613 return 0;
00614 err2:
00615 if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
00616 _d->id.rem_tag.s = 0;
00617 _d->id.rem_tag.len = 0;
00618
00619 err1:
00620 if (_d->rem_target.s) shm_free(_d->rem_target.s);
00621 _d->rem_target.s = 0;
00622 _d->rem_target.len = 0;
00623 return -4;
00624 }
00625
00626
00627
00628
00629
00630
00631 static inline int dlg_new_resp_uac(dlg_t* _d, struct sip_msg* _m)
00632 {
00633 int code;
00634
00635
00636
00637
00638
00639
00640
00641
00642 code = _m->first_line.u.reply.statuscode;
00643
00644 if (code < 200) {
00645
00646
00647
00648
00649
00650
00651
00652
00653 } else if ((code >= 200) && (code < 299)) {
00654
00655
00656
00657 if (response2dlg(_m, _d) < 0) return -1;
00658 _d->state = DLG_CONFIRMED;
00659
00660 if (calculate_hooks(_d) < 0) {
00661 LOG(L_ERR, "dlg_new_resp_uac(): Error while calculating hooks\n");
00662 return -2;
00663 }
00664 } else {
00665
00666
00667
00668
00669
00670
00671 _d->state = DLG_DESTROYED;
00672
00673 return 1;
00674 }
00675
00676 return 0;
00677 }
00678
00679
00680
00681
00682
00683
00684 static inline int dlg_early_resp_uac(dlg_t* _d, struct sip_msg* _m)
00685 {
00686 int code;
00687 code = _m->first_line.u.reply.statuscode;
00688
00689 if (code < 200) {
00690
00691
00692 } else if ((code >= 200) && (code <= 299)) {
00693
00694
00695
00696
00697
00698
00699
00700
00701 if (response2dlg(_m, _d) < 0) return -1;
00702 _d->state = DLG_CONFIRMED;
00703
00704 if (calculate_hooks(_d) < 0) {
00705 LOG(L_ERR, "dlg_early_resp_uac(): Error while calculating hooks\n");
00706 return -2;
00707 }
00708 } else {
00709
00710 _d->state = DLG_DESTROYED;
00711
00712 return 1;
00713 }
00714
00715 return 0;
00716 }
00717
00718
00719
00720
00721
00722
00723 static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m,
00724 target_refresh_t is_target_refresh)
00725 {
00726 int code;
00727 str contact;
00728
00729 code = _m->first_line.u.reply.statuscode;
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 if (code == 481) {
00743 _d->state = DLG_DESTROYED;
00744 return 1;
00745 }
00746
00747
00748 if ((code < 200) || (code >= 300)) return 0;
00749
00750 if (refresh_dialog_resp(_m, is_target_refresh)) {
00751
00752 if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
00753 LOG(L_ERR, "dlg_confirmed_resp_uac(): Error while parsing headers\n");
00754 return -2;
00755 }
00756
00757
00758 if (get_contact_uri(_m, &contact) < 0) return -3;
00759
00760 if (contact.len) {
00761
00762 if (_d->rem_target.s) shm_free(_d->rem_target.s);
00763 if (_d->dst_uri.s) {
00764 shm_free(_d->dst_uri.s);
00765 _d->dst_uri.s = 0;
00766 _d->dst_uri.len = 0;
00767 }
00768
00769
00770 if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
00771 }
00772
00773 if (calculate_hooks(_d) < 0)
00774 return -1;
00775 }
00776
00777 return 0;
00778 }
00779
00780
00781
00782
00783
00784 int dlg_response_uac(dlg_t* _d, struct sip_msg* _m,
00785 target_refresh_t is_target_refresh)
00786 {
00787 if (!_d || !_m) {
00788 LOG(L_ERR, "dlg_response_uac(): Invalid parameter value\n");
00789 return -1;
00790 }
00791
00792
00793 switch(_d->state) {
00794 case DLG_NEW:
00795 return dlg_new_resp_uac(_d, _m);
00796
00797 case DLG_EARLY:
00798 return dlg_early_resp_uac(_d, _m);
00799
00800 case DLG_CONFIRMED:
00801 return dlg_confirmed_resp_uac(_d, _m, is_target_refresh);
00802
00803 case DLG_DESTROYED:
00804 LOG(L_DBG, "dlg_response_uac(): Cannot handle destroyed dialog\n");
00805 return -2;
00806 }
00807
00808 LOG(L_ERR, "dlg_response_uac(): Error in switch statement\n");
00809 return -3;
00810 }
00811
00812
00813
00814
00815
00816
00817 static inline int get_cseq_value(struct sip_msg* _m, unsigned int* _cs)
00818 {
00819 str num;
00820
00821 if (_m->cseq == 0) {
00822 LOG(L_ERR, "get_cseq_value(): CSeq header not found\n");
00823 return -1;
00824 }
00825
00826 num.s = get_cseq(_m)->number.s;
00827 num.len = get_cseq(_m)->number.len;
00828
00829 trim_leading(&num);
00830 if (str2int(&num, _cs) < 0) {
00831 LOG(L_ERR, "get_cseq_value(): Error while converting cseq number\n");
00832 return -2;
00833 }
00834 return 0;
00835 }
00836
00837
00838
00839
00840
00841 static inline int get_dlg_uri(struct hdr_field* _h, str* _s)
00842 {
00843 struct to_param* ptr, *prev;
00844 struct to_body* body;
00845 char* tag = 0;
00846 int tag_len = 0, len;
00847
00848 if (!_h) {
00849 LOG(L_ERR, "get_dlg_uri(): Header field not found\n");
00850 return -1;
00851 }
00852
00853
00854
00855
00856
00857 body = (struct to_body*)_h->parsed;
00858
00859 ptr = body->param_lst;
00860 prev = 0;
00861 while(ptr) {
00862 if (ptr->type == TAG_PARAM) break;
00863 prev = ptr;
00864 ptr = ptr->next;
00865 }
00866
00867 if (ptr) {
00868
00869 if (prev) {
00870 tag = prev->value.s + prev->value.len;
00871 } else {
00872 tag = body->body.s + body->body.len;
00873 }
00874
00875 if (ptr->next) {
00876 tag_len = ptr->value.s + ptr->value.len - tag;
00877 } else {
00878 tag_len = _h->body.s + _h->body.len - tag;
00879 }
00880 }
00881
00882 _s->s = shm_malloc(_h->body.len - tag_len);
00883 if (!_s->s) {
00884 LOG(L_ERR, "get_dlg_uri(): No memory left\n");
00885 return -1;
00886 }
00887
00888 if (tag_len) {
00889 len = tag - _h->body.s;
00890 memcpy(_s->s, _h->body.s, len);
00891 memcpy(_s->s + len, tag + tag_len, _h->body.len - len - tag_len);
00892 _s->len = _h->body.len - tag_len;
00893 } else {
00894 memcpy(_s->s, _h->body.s, _h->body.len);
00895 _s->len = _h->body.len;
00896 }
00897
00898 return 0;
00899 }
00900
00901
00902
00903
00904
00905
00906 static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
00907 {
00908 str contact, rtag, callid;
00909
00910 if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00911 LOG(L_ERR, "request2dlg(): Error while parsing headers");
00912 return -1;
00913 }
00914
00915 if (get_contact_uri(_m, &contact) < 0) return -2;
00916 if (contact.len) {
00917 if (_d->rem_target.s) shm_free(_d->rem_target.s);
00918 if (_d->dst_uri.s) {
00919 shm_free(_d->dst_uri.s);
00920 _d->dst_uri.s = 0;
00921 _d->dst_uri.len = 0;
00922 }
00923 if (str_duplicate(&_d->rem_target, &contact) < 0) return -3;
00924 }
00925
00926 if (get_from_tag(_m, &rtag) < 0) goto err1;
00927 if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
00928
00929 if (get_callid(_m, &callid) < 0) goto err2;
00930 if (callid.len && str_duplicate(&_d->id.call_id, &callid) < 0) goto err2;
00931
00932 if (get_cseq_value(_m, &_d->rem_seq.value) < 0) goto err3;
00933 _d->rem_seq.is_set = 1;
00934
00935 if (get_dlg_uri(_m->from, &_d->rem_uri) < 0) goto err3;
00936 if (get_dlg_uri(_m->to, &_d->loc_uri) < 0) goto err4;
00937
00938 if (get_route_set(_m, &_d->route_set, NORMAL_ORDER) < 0) goto err5;
00939
00940 return 0;
00941 err5:
00942 if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
00943 _d->loc_uri.s = 0;
00944 _d->loc_uri.len = 0;
00945 err4:
00946 if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
00947 _d->rem_uri.s = 0;
00948 _d->rem_uri.len = 0;
00949 err3:
00950 if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
00951 _d->id.call_id.s = 0;
00952 _d->id.call_id.len = 0;
00953 err2:
00954 if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
00955 _d->id.rem_tag.s = 0;
00956 _d->id.rem_tag.len = 0;
00957 err1:
00958 if (_d->rem_target.s) shm_free(_d->rem_target.s);
00959 _d->rem_target.s = 0;
00960 _d->rem_target.len = 0;
00961 return -4;
00962 }
00963
00964
00965
00966
00967
00968 int new_dlg_uas(struct sip_msg* _req, int _code, dlg_t** _d)
00969 {
00970 dlg_t* res;
00971 str tag;
00972
00973 if (!_req || !_d) {
00974 LOG(L_ERR, "new_dlg_uas(): Invalid parameter value\n");
00975 return -1;
00976 }
00977
00978 if (_code > 299) {
00979 DBG("new_dlg_uas(): Status code >= 300, no dialog created\n");
00980 }
00981
00982 res = (dlg_t*)shm_malloc(sizeof(dlg_t));
00983 if (res == 0) {
00984 LOG(L_ERR, "new_dlg_uac(): No memory left\n");
00985 return -3;
00986 }
00987
00988 memset(res, 0, sizeof(dlg_t));
00989
00990 if (request2dlg(_req, res) < 0) {
00991 LOG(L_ERR, "new_dlg_uas(): Error while converting request to dialog\n");
00992 free_dlg(res);
00993 return -4;
00994 }
00995
00996 if (_code > 100) {
00997 tag.s = tm_tags;
00998 tag.len = TOTAG_VALUE_LEN;
00999 calc_crc_suffix(_req, tm_tag_suffix);
01000 if (str_duplicate(&res->id.loc_tag, &tag) < 0) {
01001 free_dlg(res);
01002 return -5;
01003 }
01004 }
01005
01006 *_d = res;
01007
01008 if (_code < 100)
01009 (*_d)->state = DLG_NEW;
01010 else if (_code < 200)
01011 (*_d)->state = DLG_EARLY;
01012 else
01013 (*_d)->state = DLG_CONFIRMED;
01014
01015 if (calculate_hooks(*_d) < 0) {
01016 LOG(L_ERR, "new_dlg_uas(): Error while calculating hooks\n");
01017 free_dlg(res);
01018 return -6;
01019 }
01020 #ifdef DIALOG_CALLBACKS
01021 run_new_dlg_callbacks(DLG_CB_UAS, res, _req);
01022 #endif
01023
01024 return 0;
01025 }
01026
01027
01028
01029
01030 int update_dlg_uas(dlg_t *_d, int _code, str* _tag)
01031 {
01032 if (_d->state == DLG_CONFIRMED) {
01033 LOG(L_ERR, "update_dlg_uas(): Dialog is already confirmed\n");
01034 return -1;
01035 } else if (_d->state == DLG_DESTROYED) {
01036 LOG(L_ERR, "update_dlg_uas(): Dialog is already destroyed\n");
01037 return -2;
01038 }
01039
01040 if (_tag && _tag->s) {
01041 if (_d->id.loc_tag.s) {
01042 if ((_tag->len == _d->id.loc_tag.len)
01043 && (!memcmp(_tag->s, _d->id.loc_tag.s, _tag->len))) {
01044 LOG(L_DBG, "update_dlg_uas(): Local tag is already set\n");
01045 } else {
01046 LOG(L_ERR, "update_dlg_uas(): ERROR: trying to rewrite local tag\n");
01047 return -3;
01048 }
01049 } else {
01050 if (str_duplicate(&_d->id.loc_tag, _tag) < 0) {
01051 LOG(L_ERR, "update_dlg_uas(): Not enough memory\n");
01052 return -4;
01053 }
01054 }
01055 }
01056
01057 if ((100 < _code) && (_code < 200))
01058 _d->state = DLG_EARLY;
01059 else if (_code < 300)
01060 _d->state = DLG_CONFIRMED;
01061 else
01062 _d->state = DLG_DESTROYED;
01063
01064 return 0;
01065 }
01066
01067
01068
01069
01070 int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_refresh)
01071 {
01072 str contact;
01073 int cseq;
01074
01075 if (!_d || !_m) {
01076 LOG(L_ERR, "dlg_request_uas(): Invalid parameter value\n");
01077 return -1;
01078 }
01079
01080
01081
01082
01083 if (parse_headers(_m, HDR_CSEQ_F, 0) == -1) {
01084 LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
01085 return -2;
01086 }
01087 if (get_cseq_value(_m, (unsigned int*)&cseq) < 0) return -3;
01088 if (_d->rem_seq.is_set && (cseq <= _d->rem_seq.value)) return 0;
01089
01090
01091 _d->rem_seq.value = cseq;
01092 _d->rem_seq.is_set = 1;
01093
01094
01095
01096
01097 if (refresh_dialog_req(_m, is_target_refresh)) {
01098 if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
01099 LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
01100 return -4;
01101 }
01102
01103 if (get_contact_uri(_m, &contact) < 0) return -5;
01104 if (contact.len) {
01105 if (_d->rem_target.s) shm_free(_d->rem_target.s);
01106 if (_d->dst_uri.s) {
01107 shm_free(_d->dst_uri.s);
01108 _d->dst_uri.s = 0;
01109 _d->dst_uri.len = 0;
01110 }
01111 if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
01112 }
01113
01114 if (calculate_hooks(_d) < 0)
01115 return -1;
01116
01117 }
01118
01119 return 0;
01120 }
01121
01122
01123
01124
01125
01126 int calculate_routeset_length(dlg_t* _d)
01127 {
01128 int len;
01129 rr_t *ptr;
01130
01131 if (! _d->route_set)
01132 return 0;
01133
01134 len = ROUTE_PREFIX_LEN;
01135
01136 for (ptr = _d->hooks.first_route; ptr; ptr = ptr->next) {
01137 len += ptr->len;
01138 len += ROUTE_SEPARATOR_LEN;
01139 }
01140 if (_d->hooks.last_route) {
01141 if (_d->hooks.first_route)
01142 len += ROUTE_SEPARATOR_LEN;
01143 len += _d->hooks.last_route->len + 2;
01144 } else {
01145 len -= ROUTE_SEPARATOR_LEN;
01146 }
01147
01148 len += CRLF_LEN;
01149
01150 return len;
01151 }
01152
01153
01154
01155
01156
01157 char* print_routeset(char* buf, dlg_t* _d)
01158 {
01159 rr_t* ptr;
01160
01161 ptr = _d->hooks.first_route;
01162
01163 if (ptr || _d->hooks.last_route) {
01164 memcpy(buf, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
01165 buf += ROUTE_PREFIX_LEN;
01166 }
01167
01168 while(ptr) {
01169 memcpy(buf, ptr->nameaddr.name.s, ptr->len);
01170 buf += ptr->len;
01171
01172 ptr = ptr->next;
01173 if (ptr) {
01174 memcpy(buf, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
01175 buf += ROUTE_SEPARATOR_LEN;
01176 }
01177 }
01178
01179 if (_d->hooks.last_route) {
01180 if (_d->hooks.first_route) {
01181 memcpy(buf, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
01182 buf += ROUTE_SEPARATOR_LEN;
01183 }
01184 memcpy(buf, "<", 1);
01185 buf++;
01186 memcpy(buf, _d->hooks.last_route->s, _d->hooks.last_route->len);
01187 buf += _d->hooks.last_route->len;
01188 *buf = '>';
01189 buf++;
01190 }
01191
01192 if (_d->hooks.first_route || _d->hooks.last_route) {
01193 memcpy(buf, CRLF, CRLF_LEN);
01194 buf += CRLF_LEN;
01195 }
01196
01197 return buf;
01198 }
01199
01200
01201
01202
01203
01204 void free_dlg(dlg_t* _d)
01205 {
01206 if (!_d) return;
01207 #ifdef DIALOG_CALLBACKS
01208 destroy_trans_dlg_callbacks(_d);
01209 #endif
01210 if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
01211 if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
01212 if (_d->id.loc_tag.s) shm_free(_d->id.loc_tag.s);
01213
01214 if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
01215 if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
01216 if (_d->rem_target.s) shm_free(_d->rem_target.s);
01217 if (_d->dst_uri.s) shm_free(_d->dst_uri.s);
01218
01219
01220 shm_free_rr(&_d->route_set);
01221 shm_free(_d);
01222 }
01223
01224
01225
01226
01227
01228 void print_dlg(FILE* out, dlg_t* _d)
01229 {
01230 fprintf(out, "====dlg_t===\n");
01231 fprintf(out, "id.call_id : '%.*s'\n", _d->id.call_id.len, _d->id.call_id.s);
01232 fprintf(out, "id.rem_tag : '%.*s'\n", _d->id.rem_tag.len, _d->id.rem_tag.s);
01233 fprintf(out, "id.loc_tag : '%.*s'\n", _d->id.loc_tag.len, _d->id.loc_tag.s);
01234 fprintf(out, "loc_seq.value : %d\n", _d->loc_seq.value);
01235 fprintf(out, "loc_seq.is_set: %s\n", _d->loc_seq.is_set ? "YES" : "NO");
01236 fprintf(out, "rem_seq.value : %d\n", _d->rem_seq.value);
01237 fprintf(out, "rem_seq.is_set: %s\n", _d->rem_seq.is_set ? "YES" : "NO");
01238 fprintf(out, "loc_uri : '%.*s'\n", _d->loc_uri.len, _d->loc_uri.s);
01239 fprintf(out, "rem_uri : '%.*s'\n", _d->rem_uri.len, _d->rem_uri.s);
01240 fprintf(out, "rem_target : '%.*s'\n", _d->rem_target.len, _d->rem_target.s);
01241 fprintf(out, "dst_uri : '%.*s'\n", _d->dst_uri.len, _d->dst_uri.s);
01242 fprintf(out, "secure: : %d\n", _d->secure);
01243 fprintf(out, "state : ");
01244 switch(_d->state) {
01245 case DLG_NEW: fprintf(out, "DLG_NEW\n"); break;
01246 case DLG_EARLY: fprintf(out, "DLG_EARLY\n"); break;
01247 case DLG_CONFIRMED: fprintf(out, "DLG_CONFIRMED\n"); break;
01248 case DLG_DESTROYED: fprintf(out, "DLG_DESTROYED\n"); break;
01249 }
01250 print_rr(out, _d->route_set);
01251 if (_d->hooks.request_uri)
01252 fprintf(out, "hooks.request_uri: '%.*s'\n", _d->hooks.request_uri->len, _d->hooks.request_uri->s);
01253 if (_d->hooks.next_hop)
01254 fprintf(out, "hooks.next_hop : '%.*s'\n", _d->hooks.next_hop->len, _d->hooks.next_hop->s);
01255 if (_d->hooks.first_route)
01256 fprintf(out, "hooks.first_route: '%.*s'\n", _d->hooks.first_route->len, _d->hooks.first_route->nameaddr.name.s);
01257 if (_d->hooks.last_route)
01258 fprintf(out, "hooks.last_route : '%.*s'\n", _d->hooks.last_route->len, _d->hooks.last_route->s);
01259
01260 fprintf(out, "====dlg_t====\n");
01261 }
01262
01263
01264
01265
01266 int set_dlg_target(dlg_t* _d, str* _ruri, str* _duri) {
01267
01268 if (!_d || !_ruri) {
01269 LOG(L_ERR, "set_dlg_target(): Invalid parameter value\n");
01270 return -1;
01271 }
01272
01273 if (_d->rem_target.s) shm_free(_d->rem_target.s);
01274 if (_d->dst_uri.s) {
01275 shm_free(_d->dst_uri.s);
01276 _d->dst_uri.s = 0;
01277 _d->dst_uri.len = 0;
01278 }
01279
01280 if (str_duplicate(&_d->rem_target, _ruri)) return -1;
01281 if (_duri && _duri->len) {
01282 if (str_duplicate(&_d->dst_uri, _duri)) return -1;
01283 }
01284
01285 if (calculate_hooks(_d) < 0) {
01286 LOG(L_ERR, "set_dlg_target(): Error while calculating hooks\n");
01287 return -1;
01288 }
01289
01290 return 0;
01291 }