dlg_var.c 22 KB

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