1 /*
2 * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
3 * Copyright (C) 2011 Carsten Bock, carsten@ng-voice.com
4 *
5 * This file is part of kamailio, a free SIP server.
6 *
7 * Kamailio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version
11 *
12 * Kamailio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /*!
23 * \file
24 * \brief Dialog variables
25 * \ingroup dialog
26 * Module: \ref dialog
27 */
28
29 #include "../../core/route.h"
30 #include "../../core/script_cb.h"
31 #include "../../core/pvapi.h"
32 #include "../../core/counters.h"
33
34 #include "dlg_var.h"
35 #include "dlg_hash.h"
36 #include "dlg_profile.h"
37 #include "dlg_handlers.h"
38 #include "dlg_db_handler.h"
39
40 dlg_ctx_t _dlg_ctx;
41 extern int spiral_detected;
42
43 /*! global variable table, in case the dialog does not exist yet */
44 static struct dlg_var *_dlg_var_table = 0;
45 /*! ID of the current message */
46 int msg_id;
47
dlg_cfg_cb(sip_msg_t * msg,unsigned int flags,void * cbp)48 int dlg_cfg_cb(sip_msg_t *msg, unsigned int flags, void *cbp)
49 {
50 dlg_cell_t *dlg;
51 if(get_route_type()==LOCAL_ROUTE) {
52 return 1;
53 }
54 if(flags&POST_SCRIPT_CB) {
55 dlg = dlg_get_ctx_dialog();
56 if(dlg!=NULL) {
57 if(_dlg_ctx.t==0 && (dlg->state==DLG_STATE_UNCONFIRMED
58 || _dlg_ctx.expect_t==1)) {
59 if(_dlg_ctx.cpid!=0 && _dlg_ctx.cpid==my_pid()) {
60 /* release to destroy dialog if created by this process
61 * and request was not forwarded */
62 if(dlg->state==DLG_STATE_UNCONFIRMED) {
63 LM_DBG("new dialog with no transaction after config"
64 " execution\n");
65 } else {
66 LM_DBG("dialog with no expected transaction after"
67 " config execution\n");
68 }
69 dlg_release(dlg);
70 }
71 }
72 /* get ctx dlg increased ref count - release now */
73 dlg_release(dlg);
74 }
75 }
76 memset(&_dlg_ctx, 0, sizeof(dlg_ctx_t));
77
78 return 1;
79 }
80
cb_dlg_cfg_reset(sip_msg_t * msg,unsigned int flags,void * cbp)81 int cb_dlg_cfg_reset(sip_msg_t *msg, unsigned int flags, void *cbp)
82 {
83 if(get_route_type()==LOCAL_ROUTE) {
84 return 1;
85 }
86
87 memset(&_dlg_ctx, 0, sizeof(dlg_ctx_t));
88
89 return 1;
90 }
91
cb_dlg_locals_reset(sip_msg_t * msg,unsigned int flags,void * cbp)92 int cb_dlg_locals_reset(sip_msg_t *msg, unsigned int flags, void *cbp)
93 {
94 if(get_route_type()==LOCAL_ROUTE) {
95 return 1;
96 }
97 LM_DBG("resetting the local dialog shortcuts on script callback: %u\n", flags);
98 cb_dlg_cfg_reset(msg, flags, cbp);
99 cb_profile_reset(msg, flags, cbp);
100
101 return 1;
102 }
103
new_dlg_var(str * key,str * val)104 static inline struct dlg_var *new_dlg_var(str *key, str *val)
105 {
106 struct dlg_var *var;
107
108 var =(struct dlg_var*)shm_malloc(sizeof(struct dlg_var));
109 if (var==NULL) {
110 LM_ERR("no more shm mem\n");
111 return NULL;
112 }
113 memset(var, 0, sizeof(struct dlg_var));
114 var->vflags = DLG_FLAG_NEW;
115 /* set key */
116 var->key.len = key->len;
117 var->key.s = (char*)shm_malloc(var->key.len+1);
118 if (var->key.s==NULL) {
119 shm_free(var);
120 LM_ERR("no more shm mem\n");
121 return NULL;
122 }
123 memcpy(var->key.s, key->s, key->len);
124 var->key.s[var->key.len] = '\0';
125 /* set value */
126 var->value.len = val->len;
127 var->value.s = (char*)shm_malloc(var->value.len+1);
128 if (var->value.s==NULL) {
129 shm_free(var->key.s);
130 shm_free(var);
131 LM_ERR("no more shm mem\n");
132 return NULL;
133 }
134 memcpy(var->value.s, val->s, val->len);
135 var->value.s[var->value.len] = '\0';
136 return var;
137 }
138
139 /*! Delete the current var-list */
free_local_varlist()140 void free_local_varlist() {
141 struct dlg_var *var;
142 while (_dlg_var_table) {
143 var = _dlg_var_table;
144 _dlg_var_table = _dlg_var_table->next;
145 shm_free(var->key.s);
146 shm_free(var->value.s);
147 shm_free(var);
148 }
149 _dlg_var_table = NULL;
150 }
151
152 /*! Retrieve the local var-list pointer */
get_local_varlist_pointer(struct sip_msg * msg,int clear_pointer)153 struct dlg_var * get_local_varlist_pointer(struct sip_msg *msg, int clear_pointer) {
154 struct dlg_var *var;
155 /* New list, delete the old one */
156 if (msg->id != msg_id) {
157 free_local_varlist();
158 msg_id = msg->id;
159 }
160 var = _dlg_var_table;
161 if (clear_pointer)
162 _dlg_var_table = NULL;
163 return var;
164 }
165
166 /* Adds, updates and deletes dialog variables */
set_dlg_variable_unsafe(struct dlg_cell * dlg,str * key,str * val)167 int set_dlg_variable_unsafe(struct dlg_cell *dlg, str *key, str *val)
168 {
169 struct dlg_var * var = NULL;
170 struct dlg_var * it;
171 struct dlg_var * it_prev;
172 struct dlg_var ** var_list;
173
174 if (dlg)
175 var_list = &dlg->vars;
176 else
177 var_list = &_dlg_var_table;
178
179 if ( val && (var=new_dlg_var(key, val))==NULL) {
180 LM_ERR("failed to create new dialog variable\n");
181 return -1;
182 }
183
184 /* iterate the list */
185 for( it_prev=NULL, it=*var_list ; it ; it_prev=it,it=it->next) {
186 if (key->len==it->key.len && memcmp(key->s,it->key.s,key->len)==0
187 && (it->vflags & DLG_FLAG_DEL) == 0) {
188 /* found -> replace or delete it */
189 if (val==NULL) {
190 /* delete it */
191 if (it_prev) it_prev->next = it->next;
192 else *var_list = it->next;
193 /* Set the delete-flag for the current var: */
194 it->vflags &= DLG_FLAG_DEL;
195 } else {
196 /* replace the current it with var and free the it */
197 var->next = it->next;
198 /* Take the previous vflags: */
199 var->vflags = it->vflags | DLG_FLAG_CHANGED;
200 if (it_prev) it_prev->next = var;
201 else *var_list = var;
202 }
203
204 /* Free this var: */
205 shm_free(it->key.s);
206 shm_free(it->value.s);
207 shm_free(it);
208 return 0;
209 }
210 }
211
212 /* not found: */
213 if (!var) {
214 LM_DBG("dialog variable <%.*s> does not exist in variable list\n", key->len, key->s);
215 return 1;
216 }
217
218 /* insert a new one at the beginning of the list */
219 var->next = *var_list;
220 *var_list = var;
221
222 return 0;
223 }
224
get_dlg_variable_unsafe(struct dlg_cell * dlg,str * key)225 str * get_dlg_variable_unsafe(struct dlg_cell *dlg, str *key)
226 {
227 struct dlg_var *var, *var_list;
228
229 if (dlg)
230 var_list = dlg->vars;
231 else
232 var_list = _dlg_var_table;
233
234 /* iterate the list */
235 for(var=var_list ; var ; var=var->next) {
236 if (key->len==var->key.len && memcmp(key->s,var->key.s,key->len)==0
237 && (var->vflags & DLG_FLAG_DEL) == 0) {
238 return &var->value;
239 }
240 }
241
242 return NULL;
243 }
244
pv_parse_dialog_var_name(pv_spec_p sp,str * in)245 int pv_parse_dialog_var_name(pv_spec_p sp, str *in)
246 {
247 if(in==NULL || in->s==NULL || sp==NULL)
248 return -1;
249
250 sp->pvp.pvn.type = PV_NAME_INTSTR;
251 sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
252 sp->pvp.pvn.u.isname.name.s = *in;
253
254 return 0;
255 }
256
257 /*! Internal debugging function: Prints the list of dialogs */
print_lists(struct dlg_cell * dlg)258 void print_lists(struct dlg_cell *dlg) {
259 struct dlg_var *varlist;
260 varlist = _dlg_var_table;
261 LM_DBG("Internal var-list (%p):\n", varlist);
262 while (varlist) {
263 LM_DBG("%.*s=%.*s (flags %i)\n",
264 varlist->key.len, varlist->key.s,
265 varlist->value.len, varlist->value.s,
266 varlist->vflags);
267 varlist = varlist->next;
268 }
269 if (dlg) {
270 varlist = dlg->vars;
271 LM_DBG("Dialog var-list (%p):\n", varlist);
272 while (varlist) {
273 LM_DBG("%.*s=%.*s (flags %i)\n",
274 varlist->key.len, varlist->key.s,
275 varlist->value.len, varlist->value.s,
276 varlist->vflags);
277 varlist = varlist->next;
278 }
279 }
280 }
281
get_dlg_variable(struct dlg_cell * dlg,str * key)282 str * get_dlg_variable(struct dlg_cell *dlg, str *key)
283 {
284 str* var = NULL;
285
286 if( !dlg || !key || key->len > strlen(key->s))
287 {
288 LM_ERR("BUG - bad parameters\n");
289
290 return NULL;
291 }
292
293 dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
294 var = get_dlg_variable_unsafe( dlg, key);
295 dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
296
297 return var;
298 }
299
set_dlg_variable(struct dlg_cell * dlg,str * key,str * val)300 int set_dlg_variable(struct dlg_cell *dlg, str *key, str *val)
301 {
302 int ret = -1;
303 if( !dlg || !key || key->len > strlen(key->s) || (val && val->len > strlen(val->s)))
304 {
305 LM_ERR("BUG - bad parameters\n");
306 return -1;
307 }
308
309 dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
310
311 ret = set_dlg_variable_unsafe(dlg, key, val);
312 if(ret!= 0)
313 goto done;
314
315 dlg->dflags |= DLG_FLAG_CHANGED_VARS;
316 dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
317 if ( dlg_db_mode==DB_MODE_REALTIME )
318 update_dialog_dbinfo(dlg);
319
320 print_lists(dlg);
321
322 return 0;
323
324 done:
325 dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
326 return ret;
327 }
328
pv_get_dlg_variable(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)329 int pv_get_dlg_variable(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
330 {
331 dlg_cell_t *dlg;
332 str * value;
333 str spv;
334
335 if (param==NULL || param->pvn.type!=PV_NAME_INTSTR
336 || param->pvn.u.isname.type!=AVP_NAME_STR
337 || param->pvn.u.isname.name.s.s==NULL) {
338 LM_CRIT("BUG - bad parameters\n");
339 return -1;
340 }
341
342 /* Retrieve the dialog for current message */
343 dlg=dlg_get_msg_dialog( msg);
344
345 if (dlg) {
346 /* Lock the dialog */
347 dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
348 } else {
349 /* Verify the local list */
350 get_local_varlist_pointer(msg, 0);
351 }
352
353 /* dcm: todo - the value should be cloned for safe usage */
354 value = get_dlg_variable_unsafe(dlg, ¶m->pvn.u.isname.name.s);
355
356 spv.s = NULL;
357 if(value) {
358 spv.len = pv_get_buffer_size();
359 if(spv.len<value->len+1) {
360 LM_ERR("pv buffer too small (%d) - needed %d\n", spv.len, value->len);
361 } else {
362 spv.s = pv_get_buffer();
363 strncpy(spv.s, value->s, value->len);
364 spv.len = value->len;
365 spv.s[spv.len] = '\0';
366 }
367 }
368
369 print_lists(dlg);
370
371 /* unlock dialog */
372 if (dlg) {
373 dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
374 dlg_release(dlg);
375 }
376
377 if (spv.s)
378 return pv_get_strval(msg, param, res, &spv);
379
380
381 return pv_get_null(msg, param, res);
382 }
383
pv_set_dlg_variable(struct sip_msg * msg,pv_param_t * param,int op,pv_value_t * val)384 int pv_set_dlg_variable(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val)
385 {
386 dlg_cell_t *dlg = NULL;
387 int ret = -1;
388
389 if (param==NULL || param->pvn.type!=PV_NAME_INTSTR
390 || param->pvn.u.isname.type!=AVP_NAME_STR
391 || param->pvn.u.isname.name.s.s==NULL ) {
392 LM_CRIT("BUG - bad parameters\n");
393 goto error;
394 }
395
396 /* Retrieve the dialog for current message */
397 dlg=dlg_get_msg_dialog( msg);
398
399 if (dlg) {
400 /* Lock the dialog */
401 dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
402 } else {
403 /* Verify the local list */
404 get_local_varlist_pointer(msg, 0);
405 }
406
407 if (val==NULL || val->flags&(PV_VAL_NONE|PV_VAL_NULL|PV_VAL_EMPTY)) {
408 /* if NULL, remove the value */
409 ret = set_dlg_variable_unsafe(dlg, ¶m->pvn.u.isname.name.s, NULL);
410 if(ret!= 0) {
411 /* unlock dialog */
412 if (dlg) {
413 dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
414 dlg_release(dlg);
415 }
416 return ret;
417 }
418 } else {
419 /* if value, must be string */
420 if ( !(val->flags&PV_VAL_STR)) {
421 LM_ERR("non-string values are not supported\n");
422 /* unlock dialog */
423 if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
424 goto error;
425 }
426
427 ret = set_dlg_variable_unsafe(dlg, ¶m->pvn.u.isname.name.s, &val->rs);
428 if(ret!= 0) {
429 /* unlock dialog */
430 if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
431 goto error;
432 }
433 }
434 /* unlock dialog */
435 if (dlg) {
436 dlg->dflags |= DLG_FLAG_CHANGED_VARS;
437 if ( dlg_db_mode==DB_MODE_REALTIME ) {
438 /* dlg_lock() / dlg_unlock() are reentrant */
439 update_dialog_dbinfo(dlg);
440 }
441 dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
442 }
443 print_lists(dlg);
444
445 dlg_release(dlg);
446 return 0;
447 error:
448 dlg_release(dlg);
449 return -1;
450 }
451
pv_get_dlg_ctx(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)452 int pv_get_dlg_ctx(struct sip_msg *msg, pv_param_t *param,
453 pv_value_t *res)
454 {
455 if(param==NULL)
456 return -1;
457 switch(param->pvn.u.isname.name.n)
458 {
459 case 1:
460 return pv_get_uintval(msg, param, res,
461 (unsigned int)_dlg_ctx.flags);
462 case 2:
463 return pv_get_uintval(msg, param, res,
464 (unsigned int)_dlg_ctx.timeout);
465 case 3:
466 return pv_get_uintval(msg, param, res,
467 (unsigned int)_dlg_ctx.to_bye);
468 case 4:
469 if(_dlg_ctx.to_route>0) {
470 return pv_get_strzval(msg, param, res,
471 _dlg_ctx.to_route_name);
472 }
473 return pv_get_null(msg, param, res);
474 case 5:
475 _dlg_ctx.set = (_dlg_ctx.iuid.h_id==0)?0:1;
476 return pv_get_uintval(msg, param, res,
477 (unsigned int)_dlg_ctx.set);
478 case 6:
479 return pv_get_uintval(msg, param, res,
480 (unsigned int)_dlg_ctx.dir);
481 case 7:
482 return pv_get_sintval(msg, param, res,
483 _dlg_ctx.to_route);
484 default:
485 return pv_get_uintval(msg, param, res,
486 (unsigned int)_dlg_ctx.on);
487 }
488 return 0;
489 }
490
pv_set_dlg_ctx(struct sip_msg * msg,pv_param_t * param,int op,pv_value_t * val)491 int pv_set_dlg_ctx(struct sip_msg* msg, pv_param_t *param,
492 int op, pv_value_t *val)
493 {
494 int n;
495 int rlen;
496 char *rtp;
497
498 if(param==NULL)
499 return -1;
500
501 n = 0;
502 if(val!=NULL && val->flags&PV_VAL_INT)
503 n = val->ri;
504
505 switch(param->pvn.u.isname.name.n)
506 {
507 case 1:
508 _dlg_ctx.flags = n;
509 break;
510 case 2:
511 _dlg_ctx.timeout = n;
512 break;
513 case 3:
514 _dlg_ctx.to_bye = n;
515 break;
516 case 4:
517 if(val && val->flags&PV_VAL_STR) {
518 if(val->rs.s[val->rs.len]=='\0'
519 && val->rs.len<DLG_TOROUTE_SIZE) {
520 _dlg_ctx.to_route = route_lookup(&main_rt, val->rs.s);
521 strcpy(_dlg_ctx.to_route_name, val->rs.s);
522 } else { _dlg_ctx.to_route = 0; }
523 } else {
524 if(n!=0) {
525 rtp = int2str(n, &rlen);
526 if(rlen<DLG_TOROUTE_SIZE) {
527 _dlg_ctx.to_route = route_lookup(&main_rt, rtp);
528 strcpy(_dlg_ctx.to_route_name, rtp);
529 } else { _dlg_ctx.to_route = 0; }
530 } else { _dlg_ctx.to_route = 0; }
531 }
532 if(_dlg_ctx.to_route <0) _dlg_ctx.to_route = 0;
533 break;
534 default:
535 _dlg_ctx.on = n;
536 break;
537 }
538 return 0;
539 }
540
pv_parse_dlg_ctx_name(pv_spec_p sp,str * in)541 int pv_parse_dlg_ctx_name(pv_spec_p sp, str *in)
542 {
543 if(sp==NULL || in==NULL || in->len<=0)
544 return -1;
545
546 switch(in->len)
547 {
548 case 2:
549 if(strncmp(in->s, "on", 2)==0)
550 sp->pvp.pvn.u.isname.name.n = 0;
551 else goto error;
552 break;
553 case 3:
554 if(strncmp(in->s, "set", 3)==0)
555 sp->pvp.pvn.u.isname.name.n = 5;
556 else if(strncmp(in->s, "dir", 3)==0)
557 sp->pvp.pvn.u.isname.name.n = 6;
558 else goto error;
559 break;
560 case 5:
561 if(strncmp(in->s, "flags", 6)==0)
562 sp->pvp.pvn.u.isname.name.n = 1;
563 else goto error;
564 break;
565 case 7:
566 if(strncmp(in->s, "timeout", 7)==0)
567 sp->pvp.pvn.u.isname.name.n = 2;
568 else goto error;
569 break;
570 case 11:
571 if(strncmp(in->s, "timeout_bye", 11)==0)
572 sp->pvp.pvn.u.isname.name.n = 3;
573 else goto error;
574 break;
575 case 13:
576 if(strncmp(in->s, "timeout_route", 13)==0)
577 sp->pvp.pvn.u.isname.name.n = 4;
578 else goto error;
579 break;
580 case 16:
581 if(strncmp(in->s, "timeout_route_id", 16)==0)
582 sp->pvp.pvn.u.isname.name.n = 7;
583 else goto error;
584 break;
585 default:
586 goto error;
587 }
588 sp->pvp.pvn.type = PV_NAME_INTSTR;
589 sp->pvp.pvn.u.isname.type = 0;
590
591 return 0;
592
593 error:
594 LM_ERR("unknown PV name %.*s\n", in->len, in->s);
595 return -1;
596 }
597
pv_get_dlg(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)598 int pv_get_dlg(struct sip_msg *msg, pv_param_t *param,
599 pv_value_t *res)
600 {
601 dlg_cell_t *dlg = NULL;
602 int res_type = 0;
603 str sv = { 0 };
604 unsigned int ui = 0;
605 int si = 0;
606
607 if(param==NULL)
608 return -1;
609
610 if(_dlg_ctx.iuid.h_id==0)
611 {
612 /* Retrieve the dialog for current message */
613 dlg=dlg_get_msg_dialog(msg);
614 } else {
615 /* Retrieve the dialog for current context */
616 dlg=dlg_get_by_iuid(&_dlg_ctx.iuid);
617 }
618 if(dlg == NULL)
619 return pv_get_null(msg, param, res);
620
621 switch(param->pvn.u.isname.name.n)
622 {
623 case 1:
624 res_type = 1;
625 ui = (unsigned int)dlg->h_id;
626 break;
627 case 2:
628 res_type = 1;
629 ui = (unsigned int)dlg->state;
630 break;
631 case 3:
632 if(dlg->route_set[DLG_CALLEE_LEG].s==NULL
633 || dlg->route_set[DLG_CALLEE_LEG].len<=0)
634 goto done;
635 sv.s = pv_get_buffer();
636 sv.len = dlg->route_set[DLG_CALLEE_LEG].len;
637 if(pv_get_buffer_size()<sv.len)
638 goto done;
639 res_type = 2;
640 strncpy(sv.s, dlg->route_set[DLG_CALLEE_LEG].s, sv.len);
641 sv.s[sv.len] = '\0';
642 break;
643 case 4:
644 res_type = 1;
645 ui = (unsigned int)dlg->dflags;
646 break;
647 case 5:
648 res_type = 1;
649 ui = (unsigned int)dlg->sflags;
650 break;
651 case 6:
652 if(dlg->callid.s==NULL
653 || dlg->callid.len<=0)
654 goto done;
655 sv.s = pv_get_buffer();
656 sv.len = dlg->callid.len;
657 if(pv_get_buffer_size()<sv.len)
658 goto done;
659 res_type = 2;
660 strncpy(sv.s, dlg->callid.s, sv.len);
661 sv.s[sv.len] = '\0';
662 break;
663 case 7:
664 if(dlg->to_uri.s==NULL
665 || dlg->to_uri.len<=0)
666 goto done;
667 sv.s = pv_get_buffer();
668 sv.len = dlg->to_uri.len;
669 if(pv_get_buffer_size()<sv.len)
670 goto done;
671 res_type = 2;
672 strncpy(sv.s, dlg->to_uri.s, sv.len);
673 sv.s[sv.len] = '\0';
674 break;
675 case 8:
676 if(dlg->tag[DLG_CALLEE_LEG].s==NULL
677 || dlg->tag[DLG_CALLEE_LEG].len<=0)
678 goto done;
679 sv.s = pv_get_buffer();
680 sv.len = dlg->tag[DLG_CALLEE_LEG].len;
681 if(pv_get_buffer_size()<sv.len)
682 goto done;
683 res_type = 2;
684 strncpy(sv.s, dlg->tag[DLG_CALLEE_LEG].s, sv.len);
685 sv.s[sv.len] = '\0';
686 break;
687 case 9:
688 res_type = 3;
689 si = dlg->toroute;
690 break;
691 case 10:
692 if(dlg->cseq[DLG_CALLEE_LEG].s==NULL
693 || dlg->cseq[DLG_CALLEE_LEG].len<=0)
694 goto done;
695 sv.s = pv_get_buffer();
696 sv.len = dlg->cseq[DLG_CALLEE_LEG].len;
697 if(pv_get_buffer_size()<sv.len)
698 goto done;
699 res_type = 2;
700 strncpy(sv.s, dlg->cseq[DLG_CALLEE_LEG].s, sv.len);
701 sv.s[sv.len] = '\0';
702 break;
703 case 11:
704 if(dlg->route_set[DLG_CALLER_LEG].s==NULL
705 || dlg->route_set[DLG_CALLER_LEG].len<=0)
706 goto done;
707 sv.s = pv_get_buffer();
708 sv.len = dlg->route_set[DLG_CALLER_LEG].len;
709 if(pv_get_buffer_size()<sv.len)
710 goto done;
711 res_type = 2;
712 strncpy(sv.s, dlg->route_set[DLG_CALLER_LEG].s, sv.len);
713 sv.s[sv.len] = '\0';
714 break;
715 case 12:
716 if(dlg->from_uri.s==NULL
717 || dlg->from_uri.len<=0)
718 goto done;
719 sv.s = pv_get_buffer();
720 sv.len = dlg->from_uri.len;
721 if(pv_get_buffer_size()<sv.len)
722 goto done;
723 res_type = 2;
724 strncpy(sv.s, dlg->from_uri.s, sv.len);
725 sv.s[sv.len] = '\0';
726 break;
727 case 13:
728 if(dlg->tag[DLG_CALLER_LEG].s==NULL
729 || dlg->tag[DLG_CALLER_LEG].len<=0)
730 goto done;
731 sv.s = pv_get_buffer();
732 sv.len = dlg->tag[DLG_CALLER_LEG].len;
733 if(pv_get_buffer_size()<sv.len)
734 goto done;
735 res_type = 2;
736 strncpy(sv.s, dlg->tag[DLG_CALLER_LEG].s, sv.len);
737 sv.s[sv.len] = '\0';
738 break;
739 case 14:
740 res_type = 1;
741 ui = (unsigned int)dlg->lifetime;
742 break;
743 case 15:
744 res_type = 1;
745 ui = (unsigned int)dlg->start_ts;
746 break;
747 case 16:
748 if(dlg->cseq[DLG_CALLER_LEG].s==NULL
749 || dlg->cseq[DLG_CALLER_LEG].len<=0)
750 goto done;
751 sv.s = pv_get_buffer();
752 sv.len = dlg->cseq[DLG_CALLER_LEG].len;
753 if(pv_get_buffer_size()<sv.len)
754 goto done;
755 res_type = 2;
756 strncpy(sv.s, dlg->cseq[DLG_CALLER_LEG].s, sv.len);
757 sv.s[sv.len] = '\0';
758 break;
759 case 17:
760 if(dlg->contact[DLG_CALLEE_LEG].s==NULL
761 || dlg->contact[DLG_CALLEE_LEG].len<=0)
762 goto done;
763 sv.s = pv_get_buffer();
764 sv.len = dlg->contact[DLG_CALLEE_LEG].len;
765 if(pv_get_buffer_size()<sv.len)
766 goto done;
767 res_type = 2;
768 strncpy(sv.s, dlg->contact[DLG_CALLEE_LEG].s, sv.len);
769 sv.s[sv.len] = '\0';
770 break;
771 case 18:
772 if(dlg->bind_addr[DLG_CALLEE_LEG]==NULL)
773 goto done;
774 sv.s = pv_get_buffer();
775 sv.len = dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len;
776 if(pv_get_buffer_size()<sv.len)
777 goto done;
778 res_type = 2;
779 strncpy(sv.s, dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s, sv.len);
780 sv.s[sv.len] = '\0';
781 break;
782 case 19:
783 if(dlg->contact[DLG_CALLER_LEG].s==NULL
784 || dlg->contact[DLG_CALLER_LEG].len<=0)
785 goto done;
786 sv.s = pv_get_buffer();
787 sv.len = dlg->contact[DLG_CALLER_LEG].len;
788 if(pv_get_buffer_size()<sv.len)
789 goto done;
790 res_type = 2;
791 strncpy(sv.s, dlg->contact[DLG_CALLER_LEG].s, sv.len);
792 sv.s[sv.len] = '\0';
793 break;
794 case 20:
795 if(dlg->bind_addr[DLG_CALLER_LEG]==NULL)
796 goto done;
797 sv.s = pv_get_buffer();
798 sv.len = dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len;
799 if(pv_get_buffer_size()<sv.len)
800 goto done;
801 res_type = 2;
802 strncpy(sv.s, dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s, sv.len);
803 sv.s[sv.len] = '\0';
804 break;
805 case 21:
806 res_type = 1;
807 ui = (unsigned int)dlg->h_entry;
808 break;
809 default:
810 res_type = 1;
811 ui = (unsigned int)dlg->ref;
812 }
813
814 done:
815 dlg_release(dlg);
816
817 switch(res_type) {
818 case 1:
819 return pv_get_uintval(msg, param, res, ui);
820 case 2:
821 return pv_get_strval(msg, param, res, &sv);
822 case 3:
823 return pv_get_sintval(msg, param, res, si);
824 default:
825 return pv_get_null(msg, param, res);
826 }
827 }
828
pv_parse_dlg_name(pv_spec_p sp,str * in)829 int pv_parse_dlg_name(pv_spec_p sp, str *in)
830 {
831 if(sp==NULL || in==NULL || in->len<=0)
832 return -1;
833
834 switch(in->len)
835 {
836 case 3:
837 if(strncmp(in->s, "ref", 3)==0)
838 sp->pvp.pvn.u.isname.name.n = 0;
839 else goto error;
840 break;
841 case 4:
842 if(strncmp(in->s, "h_id", 4)==0)
843 sp->pvp.pvn.u.isname.name.n = 1;
844 else goto error;
845 break;
846 case 5:
847 if(strncmp(in->s, "state", 5)==0)
848 sp->pvp.pvn.u.isname.name.n = 2;
849 else if(strncmp(in->s, "to_rs", 5)==0)
850 sp->pvp.pvn.u.isname.name.n = 3;
851 else goto error;
852 break;
853 case 6:
854 if(strncmp(in->s, "dflags", 6)==0)
855 sp->pvp.pvn.u.isname.name.n = 4;
856 else if(strncmp(in->s, "sflags", 6)==0)
857 sp->pvp.pvn.u.isname.name.n = 5;
858 else if(strncmp(in->s, "callid", 6)==0)
859 sp->pvp.pvn.u.isname.name.n = 6;
860 else if(strncmp(in->s, "to_uri", 6)==0)
861 sp->pvp.pvn.u.isname.name.n = 7;
862 else if(strncmp(in->s, "to_tag", 6)==0)
863 sp->pvp.pvn.u.isname.name.n = 8;
864 else goto error;
865 break;
866 case 7:
867 if(strncmp(in->s, "toroute", 7)==0)
868 sp->pvp.pvn.u.isname.name.n = 9;
869 else if(strncmp(in->s, "to_cseq", 7)==0)
870 sp->pvp.pvn.u.isname.name.n = 10;
871 else if(strncmp(in->s, "from_rs", 7)==0)
872 sp->pvp.pvn.u.isname.name.n = 11;
873 else if(strncmp(in->s, "h_entry", 7)==0)
874 sp->pvp.pvn.u.isname.name.n = 21;
875 else goto error;
876 break;
877 case 8:
878 if(strncmp(in->s, "from_uri", 8)==0)
879 sp->pvp.pvn.u.isname.name.n = 12;
880 else if(strncmp(in->s, "from_tag", 8)==0)
881 sp->pvp.pvn.u.isname.name.n = 13;
882 else if(strncmp(in->s, "lifetime", 8)==0)
883 sp->pvp.pvn.u.isname.name.n = 14;
884 else if(strncmp(in->s, "start_ts", 8)==0)
885 sp->pvp.pvn.u.isname.name.n = 15;
886 else goto error;
887 break;
888 case 9:
889 if(strncmp(in->s, "from_cseq", 9)==0)
890 sp->pvp.pvn.u.isname.name.n = 16;
891 else goto error;
892 break;
893 case 10:
894 if(strncmp(in->s, "to_contact", 10)==0)
895 sp->pvp.pvn.u.isname.name.n = 17;
896 else goto error;
897 break;
898 case 11:
899 if(strncmp(in->s, "to_bindaddr", 11)==0)
900 sp->pvp.pvn.u.isname.name.n = 18;
901 else goto error;
902 break;
903 case 12:
904 if(strncmp(in->s, "from_contact", 12)==0)
905 sp->pvp.pvn.u.isname.name.n = 19;
906 else goto error;
907 break;
908 case 13:
909 if(strncmp(in->s, "from_bindaddr", 13)==0)
910 sp->pvp.pvn.u.isname.name.n = 20;
911 else goto error;
912 break;
913 default:
914 goto error;
915 }
916 sp->pvp.pvn.type = PV_NAME_INTSTR;
917 sp->pvp.pvn.u.isname.type = 0;
918
919 return 0;
920
921 error:
922 LM_ERR("unknown PV name %.*s\n", in->len, in->s);
923 return -1;
924 }
925
dlg_set_ctx_iuid(dlg_cell_t * dlg)926 void dlg_set_ctx_iuid(dlg_cell_t *dlg)
927 {
928 _dlg_ctx.iuid.h_entry = dlg->h_entry;
929 _dlg_ctx.iuid.h_id = dlg->h_id;
930 }
931
dlg_reset_ctx_iuid(void)932 void dlg_reset_ctx_iuid(void)
933 {
934 _dlg_ctx.iuid.h_entry = 0;
935 _dlg_ctx.iuid.h_id = 0;
936 }
937
dlg_get_ctx_dialog(void)938 dlg_cell_t* dlg_get_ctx_dialog(void)
939 {
940 return dlg_get_by_iuid(&_dlg_ctx.iuid);
941 }
942
dlg_get_dlg_ctx(void)943 dlg_ctx_t* dlg_get_dlg_ctx(void)
944 {
945 return &_dlg_ctx;
946 }
947
spiral_detect_reset(struct sip_msg * foo,unsigned int flags,void * bar)948 int spiral_detect_reset(struct sip_msg *foo, unsigned int flags, void *bar)
949 {
950 if(get_route_type()==LOCAL_ROUTE) {
951 return 1;
952 }
953 spiral_detected = -1;
954
955 return 0;
956 }
957