dlg_db_handler.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. /*
  2. * Copyright (C) 2007 Voice System SRL
  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. /*!
  23. * \file
  24. * \brief Database interface
  25. * \ingroup dialog
  26. * Module: \ref dialog
  27. */
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <sys/time.h>
  31. #include "../../dprint.h"
  32. #include "../../ut.h"
  33. #include "../../timer.h"
  34. #include "../../lib/srdb1/db.h"
  35. #include "../../str.h"
  36. #include "../../socket_info.h"
  37. #include "dlg_hash.h"
  38. #include "dlg_var.h"
  39. #include "dlg_profile.h"
  40. #include "dlg_db_handler.h"
  41. str call_id_column = str_init(CALL_ID_COL);
  42. str from_uri_column = str_init(FROM_URI_COL);
  43. str from_tag_column = str_init(FROM_TAG_COL);
  44. str to_uri_column = str_init(TO_URI_COL);
  45. str to_tag_column = str_init(TO_TAG_COL);
  46. str h_id_column = str_init(HASH_ID_COL);
  47. str h_entry_column = str_init(HASH_ENTRY_COL);
  48. str state_column = str_init(STATE_COL);
  49. str start_time_column = str_init(START_TIME_COL);
  50. str timeout_column = str_init(TIMEOUT_COL);
  51. str to_cseq_column = str_init(TO_CSEQ_COL);
  52. str from_cseq_column = str_init(FROM_CSEQ_COL);
  53. str to_route_column = str_init(TO_ROUTE_COL);
  54. str from_route_column = str_init(FROM_ROUTE_COL);
  55. str to_contact_column = str_init(TO_CONTACT_COL);
  56. str from_contact_column = str_init(FROM_CONTACT_COL);
  57. str to_sock_column = str_init(TO_SOCK_COL);
  58. str from_sock_column = str_init(FROM_SOCK_COL);
  59. str sflags_column = str_init(SFLAGS_COL);
  60. str iflags_column = str_init(IFLAGS_COL);
  61. str toroute_name_column = str_init(TOROUTE_NAME_COL);
  62. str req_uri_column = str_init(REQ_URI_COL);
  63. str xdata_column = str_init(XDATA_COL);
  64. str dialog_table_name = str_init(DIALOG_TABLE_NAME);
  65. int dlg_db_mode = DB_MODE_NONE;
  66. str vars_h_id_column = str_init(VARS_HASH_ID_COL);
  67. str vars_h_entry_column = str_init(VARS_HASH_ENTRY_COL);
  68. str vars_key_column = str_init(VARS_KEY_COL);
  69. str vars_value_column = str_init(VARS_VALUE_COL);
  70. str dialog_vars_table_name = str_init(DIALOG_VARS_TABLE_NAME);
  71. static db1_con_t* dialog_db_handle = 0; /* database connection handle */
  72. static db_func_t dialog_dbf;
  73. extern int dlg_enable_stats;
  74. extern int active_dlgs_cnt;
  75. extern int early_dlgs_cnt;
  76. #define SET_STR_VALUE(_val, _str)\
  77. do{\
  78. VAL_STR((_val)).s = (_str).s;\
  79. VAL_STR((_val)).len = (_str).len;\
  80. }while(0);
  81. #define SET_NULL_FLAG(_vals, _i, _max, _flag)\
  82. do{\
  83. for((_i) = 0;(_i)<(_max); (_i)++)\
  84. VAL_NULL((_vals)+(_i)) = (_flag);\
  85. }while(0);
  86. #define SET_PROPER_NULL_FLAG(_str, _vals, _index)\
  87. do{\
  88. if( (_str).len == 0)\
  89. VAL_NULL( (_vals)+(_index) ) = 1;\
  90. else\
  91. VAL_NULL( (_vals)+(_index) ) = 0;\
  92. }while(0);
  93. #define GET_STR_VALUE(_res, _values, _index, _not_null, _unref)\
  94. do{\
  95. if (VAL_NULL((_values)+ (_index))) { \
  96. if (_not_null) {\
  97. if (_unref) dlg_unref(dlg,1);\
  98. goto next_dialog; \
  99. } else { \
  100. (_res).s = 0; \
  101. (_res).len = 0; \
  102. }\
  103. } else { \
  104. (_res).s = VAL_STR((_values)+ (_index)).s;\
  105. (_res).len = strlen(VAL_STR((_values)+ (_index)).s);\
  106. } \
  107. }while(0);
  108. static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows);
  109. static int load_dialog_vars_from_db(int fetch_num_rows);
  110. int dlg_connect_db(const str *db_url)
  111. {
  112. if (dialog_db_handle) {
  113. LM_CRIT("BUG - db connection found already open\n");
  114. return -1;
  115. }
  116. if ((dialog_db_handle = dialog_dbf.init(db_url)) == 0)
  117. return -1;
  118. return 0;
  119. }
  120. int init_dlg_db(const str *db_url, int dlg_hash_size , int db_update_period, int fetch_num_rows)
  121. {
  122. /* Find a database module */
  123. if (db_bind_mod(db_url, &dialog_dbf) < 0){
  124. LM_ERR("Unable to bind to a database driver\n");
  125. return -1;
  126. }
  127. if (dlg_connect_db(db_url)!=0){
  128. LM_ERR("unable to connect to the database\n");
  129. return -1;
  130. }
  131. if(db_check_table_version(&dialog_dbf, dialog_db_handle, &dialog_table_name, DLG_TABLE_VERSION) < 0) {
  132. LM_ERR("error during dialog-table version check.\n");
  133. return -1;
  134. }
  135. if(db_check_table_version(&dialog_dbf, dialog_db_handle, &dialog_vars_table_name, DLG_VARS_TABLE_VERSION) < 0) {
  136. LM_ERR("error during dialog-vars version check.\n");
  137. return -1;
  138. }
  139. if( (dlg_db_mode==DB_MODE_DELAYED) &&
  140. (register_timer( dialog_update_db, 0, db_update_period)<0 )) {
  141. LM_ERR("failed to register update db\n");
  142. return -1;
  143. }
  144. if( (load_dialog_info_from_db(dlg_hash_size, fetch_num_rows) ) !=0 ){
  145. LM_ERR("unable to load the dialog data\n");
  146. return -1;
  147. }
  148. if( (load_dialog_vars_from_db(fetch_num_rows) ) !=0 ){
  149. LM_ERR("unable to load the dialog data\n");
  150. return -1;
  151. }
  152. dialog_dbf.close(dialog_db_handle);
  153. dialog_db_handle = 0;
  154. return 0;
  155. }
  156. void destroy_dlg_db(void)
  157. {
  158. /* close the DB connection */
  159. if (dialog_db_handle) {
  160. dialog_dbf.close(dialog_db_handle);
  161. dialog_db_handle = 0;
  162. }
  163. }
  164. static int use_dialog_table(void)
  165. {
  166. if(!dialog_db_handle){
  167. LM_ERR("invalid database handle\n");
  168. return -1;
  169. }
  170. if (dialog_dbf.use_table(dialog_db_handle, &dialog_table_name) < 0) {
  171. LM_ERR("Error in use_table\n");
  172. return -1;
  173. }
  174. return 0;
  175. }
  176. static int use_dialog_vars_table(void)
  177. {
  178. if(!dialog_db_handle){
  179. LM_ERR("invalid database handle\n");
  180. return -1;
  181. }
  182. if (dialog_dbf.use_table(dialog_db_handle, &dialog_vars_table_name) < 0) {
  183. LM_ERR("Error in use_table\n");
  184. return -1;
  185. }
  186. return 0;
  187. }
  188. static int select_entire_dialog_table(db1_res_t ** res, int fetch_num_rows)
  189. {
  190. db_key_t query_cols[DIALOG_TABLE_COL_NO] = { &h_entry_column,
  191. &h_id_column, &call_id_column, &from_uri_column,
  192. &from_tag_column, &to_uri_column, &to_tag_column,
  193. &start_time_column, &state_column, &timeout_column,
  194. &from_cseq_column, &to_cseq_column, &from_route_column,
  195. &to_route_column, &from_contact_column, &to_contact_column,
  196. &from_sock_column, &to_sock_column, &sflags_column,
  197. &toroute_name_column, &req_uri_column, &xdata_column,
  198. &iflags_column};
  199. if(use_dialog_table() != 0){
  200. return -1;
  201. }
  202. /* select the whole tabel and all the columns */
  203. if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
  204. if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
  205. DIALOG_TABLE_COL_NO, 0, 0) < 0) {
  206. LM_ERR("Error while querying (fetch) database\n");
  207. return -1;
  208. }
  209. if(dialog_dbf.fetch_result(dialog_db_handle, res, fetch_num_rows) < 0) {
  210. LM_ERR("fetching rows failed\n");
  211. return -1;
  212. }
  213. } else {
  214. if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
  215. DIALOG_TABLE_COL_NO, 0, res) < 0) {
  216. LM_ERR("Error while querying database\n");
  217. return -1;
  218. }
  219. }
  220. return 0;
  221. }
  222. struct socket_info * create_socket_info(db_val_t * vals, int n){
  223. struct socket_info * sock;
  224. char* p;
  225. str host;
  226. int port, proto;
  227. /* socket name */
  228. p = (VAL_STR(vals+n)).s;
  229. if (VAL_NULL(vals+n) || p==0 || p[0]==0){
  230. sock = 0;
  231. } else {
  232. if (parse_phostport( p, &host.s, &host.len,
  233. &port, &proto)!=0) {
  234. LM_ERR("bad socket <%s>\n", p);
  235. return 0;
  236. }
  237. sock = grep_sock_info( &host, (unsigned short)port, proto);
  238. if (sock==0) {
  239. LM_WARN("non-local socket <%s>...ignoring\n", p);
  240. }
  241. }
  242. return sock;
  243. }
  244. static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
  245. {
  246. db1_res_t * res;
  247. db_val_t * values;
  248. db_row_t * rows;
  249. int i, nr_rows;
  250. struct dlg_cell *dlg;
  251. str callid, from_uri, to_uri, from_tag, to_tag, req_uri;
  252. str cseq1, cseq2, contact1, contact2, rroute1, rroute2;
  253. str toroute_name;
  254. str xdata;
  255. unsigned int next_id;
  256. srjson_doc_t jdoc;
  257. res = 0;
  258. if((nr_rows = select_entire_dialog_table(&res, fetch_num_rows)) < 0)
  259. goto end;
  260. nr_rows = RES_ROW_N(res);
  261. LM_DBG("the database has information about %i dialogs\n", nr_rows);
  262. rows = RES_ROWS(res);
  263. do {
  264. /* for every row---dialog */
  265. for(i=0; i<nr_rows; i++){
  266. values = ROW_VALUES(rows + i);
  267. if (VAL_NULL(values) || VAL_NULL(values+1)) {
  268. LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n",
  269. h_entry_column.len, h_entry_column.s,
  270. h_id_column.len, h_id_column.s);
  271. continue;
  272. }
  273. if (VAL_NULL(values+7) || VAL_NULL(values+8)) {
  274. LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n",
  275. start_time_column.len, start_time_column.s,
  276. state_column.len, state_column.s);
  277. continue;
  278. }
  279. /*restore the dialog info*/
  280. GET_STR_VALUE(callid, values, 2, 1, 0);
  281. GET_STR_VALUE(from_uri, values, 3, 1, 0);
  282. GET_STR_VALUE(from_tag, values, 4, 1, 0);
  283. GET_STR_VALUE(to_uri, values, 5, 1, 0);
  284. GET_STR_VALUE(req_uri, values, 20, 1, 0);
  285. if((dlg=build_new_dlg(&callid, &from_uri, &to_uri, &from_tag,
  286. &req_uri))==0){
  287. LM_ERR("failed to build new dialog\n");
  288. goto error;
  289. }
  290. if(dlg->h_entry != VAL_INT(values)){
  291. LM_ERR("inconsistent hash data in the dialog database: "
  292. "you may have restarted Kamailio using a different "
  293. "hash_size: please erase %.*s database and restart\n",
  294. dialog_table_name.len, dialog_table_name.s);
  295. shm_free(dlg);
  296. goto error;
  297. }
  298. /*link the dialog*/
  299. link_dlg(dlg, 0, 0);
  300. dlg->h_id = VAL_INT(values+1);
  301. next_id = d_table->entries[dlg->h_entry].next_id;
  302. d_table->entries[dlg->h_entry].next_id =
  303. (next_id <= dlg->h_id) ? (dlg->h_id+1) : next_id;
  304. GET_STR_VALUE(to_tag, values, 6, 1, 1);
  305. dlg->start_ts = VAL_INT(values+7);
  306. dlg->state = VAL_INT(values+8);
  307. if (dlg->state==DLG_STATE_CONFIRMED_NA ||
  308. dlg->state==DLG_STATE_CONFIRMED) {
  309. active_dlgs_cnt++;
  310. } else if (dlg->state==DLG_STATE_EARLY) {
  311. early_dlgs_cnt++;
  312. }
  313. dlg->tl.timeout = (unsigned int)(VAL_INT(values+9));
  314. LM_DBG("db dialog timeout is %u (%u/%u)\n", dlg->tl.timeout,
  315. get_ticks(), (unsigned int)time(0));
  316. if (dlg->tl.timeout<=(unsigned int)time(0)) {
  317. dlg->tl.timeout = 0;
  318. dlg->lifetime = 0;
  319. } else {
  320. dlg->lifetime = dlg->tl.timeout - dlg->start_ts;
  321. dlg->tl.timeout -= (unsigned int)time(0);
  322. }
  323. GET_STR_VALUE(cseq1, values, 10 , 1, 1);
  324. GET_STR_VALUE(cseq2, values, 11 , 1, 1);
  325. GET_STR_VALUE(rroute1, values, 12, 0, 0);
  326. GET_STR_VALUE(rroute2, values, 13, 0, 0);
  327. GET_STR_VALUE(contact1, values, 14, 1, 1);
  328. GET_STR_VALUE(contact2, values, 15, 1, 1);
  329. if ( (dlg_set_leg_info( dlg, &from_tag, &rroute1, &contact1,
  330. &cseq1, DLG_CALLER_LEG)!=0) ||
  331. (dlg_set_leg_info( dlg, &to_tag, &rroute2, &contact2,
  332. &cseq2, DLG_CALLEE_LEG)!=0) ) {
  333. LM_ERR("dlg_set_leg_info failed\n");
  334. dlg_unref(dlg,1);
  335. continue;
  336. }
  337. dlg->bind_addr[DLG_CALLER_LEG] = create_socket_info(values, 16);
  338. dlg->bind_addr[DLG_CALLEE_LEG] = create_socket_info(values, 17);
  339. dlg->sflags = (unsigned int)VAL_INT(values+18);
  340. GET_STR_VALUE(toroute_name, values, 19, 0, 0);
  341. dlg_set_toroute(dlg, &toroute_name);
  342. GET_STR_VALUE(xdata, values, 21, 0, 0);
  343. if(xdata.s!=NULL && dlg->state!=DLG_STATE_DELETED)
  344. {
  345. srjson_InitDoc(&jdoc, NULL);
  346. jdoc.buf = xdata;
  347. dlg_json_to_profiles(dlg, &jdoc);
  348. srjson_DestroyDoc(&jdoc);
  349. }
  350. dlg->iflags = (unsigned int)VAL_INT(values+22);
  351. /*restore the timer values */
  352. if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) {
  353. LM_CRIT("Unable to insert dlg %p [%u:%u] "
  354. "with clid '%.*s' and tags '%.*s' '%.*s'\n",
  355. dlg, dlg->h_entry, dlg->h_id,
  356. dlg->callid.len, dlg->callid.s,
  357. dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
  358. dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
  359. dlg_unref(dlg,1);
  360. continue;
  361. }
  362. dlg_ref(dlg,1);
  363. LM_DBG("current dialog timeout is %u (%u)\n", dlg->tl.timeout,
  364. get_ticks());
  365. dlg->dflags = 0;
  366. next_dialog:
  367. ;
  368. }
  369. /* any more data to be fetched ?*/
  370. if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
  371. if(dialog_dbf.fetch_result(dialog_db_handle, &res, fetch_num_rows) < 0) {
  372. LM_ERR("re-fetching rows failed\n");
  373. goto error;
  374. }
  375. nr_rows = RES_ROW_N(res);
  376. rows = RES_ROWS(res);
  377. } else {
  378. nr_rows = 0;
  379. }
  380. }while (nr_rows>0);
  381. if (dlg_db_mode==DB_MODE_SHUTDOWN) {
  382. if (dialog_dbf.delete(dialog_db_handle, 0, 0, 0, 0) < 0) {
  383. LM_ERR("failed to clear dialog table\n");
  384. goto error;
  385. }
  386. }
  387. end:
  388. dialog_dbf.free_result(dialog_db_handle, res);
  389. return 0;
  390. error:
  391. dialog_dbf.free_result(dialog_db_handle, res);
  392. return -1;
  393. }
  394. static int select_entire_dialog_vars_table(db1_res_t ** res, int fetch_num_rows)
  395. {
  396. db_key_t query_cols[DIALOG_VARS_TABLE_COL_NO] = { &vars_h_entry_column,
  397. &vars_h_id_column, &vars_key_column, &vars_value_column };
  398. if(use_dialog_vars_table() != 0){
  399. return -1;
  400. }
  401. /* select the whole tabel and all the columns */
  402. if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
  403. if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
  404. DIALOG_VARS_TABLE_COL_NO, 0, 0) < 0) {
  405. LM_ERR("Error while querying (fetch) database\n");
  406. return -1;
  407. }
  408. if(dialog_dbf.fetch_result(dialog_db_handle, res, fetch_num_rows) < 0) {
  409. LM_ERR("fetching rows failed\n");
  410. return -1;
  411. }
  412. } else {
  413. if(dialog_dbf.query(dialog_db_handle,0,0,0,query_cols, 0,
  414. DIALOG_VARS_TABLE_COL_NO, 0, res) < 0) {
  415. LM_ERR("Error while querying database\n");
  416. return -1;
  417. }
  418. }
  419. return 0;
  420. }
  421. static int load_dialog_vars_from_db(int fetch_num_rows)
  422. {
  423. db1_res_t * res;
  424. db_val_t * values;
  425. db_row_t * rows;
  426. struct dlg_cell * dlg;
  427. int i, nr_rows;
  428. res = 0;
  429. if((nr_rows = select_entire_dialog_vars_table(&res, fetch_num_rows)) < 0)
  430. goto end;
  431. nr_rows = RES_ROW_N(res);
  432. LM_DBG("the database has information about %i dialog variables\n", nr_rows);
  433. rows = RES_ROWS(res);
  434. do {
  435. /* for every row---dialog */
  436. for(i=0; i<nr_rows; i++){
  437. values = ROW_VALUES(rows + i);
  438. if (VAL_NULL(values) || VAL_NULL(values+1)) {
  439. LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n",
  440. vars_h_entry_column.len, vars_h_entry_column.s,
  441. vars_h_id_column.len, vars_h_id_column.s);
  442. continue;
  443. }
  444. if (VAL_NULL(values+2) || VAL_NULL(values+3)) {
  445. LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n",
  446. vars_key_column.len, vars_key_column.s,
  447. vars_value_column.len, vars_value_column.s);
  448. continue;
  449. }
  450. if (VAL_INT(values) < d_table->size) {
  451. dlg = (d_table->entries)[VAL_INT(values)].first;
  452. while (dlg) {
  453. if (dlg->h_id == VAL_INT(values+1)) {
  454. str key = { VAL_STR(values+2).s, strlen(VAL_STRING(values+2)) };
  455. str value = { VAL_STR(values+3).s, strlen(VAL_STRING(values+3)) };
  456. set_dlg_variable_unsafe(dlg, &key, &value);
  457. break;
  458. }
  459. dlg = dlg->next;
  460. if (!dlg) {
  461. LM_WARN("insonsistent data: the dialog h_entry/h_id does not exist!\n");
  462. }
  463. }
  464. } else {
  465. LM_WARN("insonsistent data: the h_entry in the DB does not exist!\n");
  466. }
  467. }
  468. /* any more data to be fetched ?*/
  469. if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH) && (fetch_num_rows > 0)) {
  470. if(dialog_dbf.fetch_result(dialog_db_handle, &res, fetch_num_rows) < 0) {
  471. LM_ERR("re-fetching rows failed\n");
  472. goto error;
  473. }
  474. nr_rows = RES_ROW_N(res);
  475. rows = RES_ROWS(res);
  476. } else {
  477. nr_rows = 0;
  478. }
  479. }while (nr_rows>0);
  480. if (dlg_db_mode==DB_MODE_SHUTDOWN) {
  481. if (dialog_dbf.delete(dialog_db_handle, 0, 0, 0, 0) < 0) {
  482. LM_ERR("failed to clear dialog variable table\n");
  483. goto error;
  484. }
  485. }
  486. end:
  487. dialog_dbf.free_result(dialog_db_handle, res);
  488. return 0;
  489. error:
  490. dialog_dbf.free_result(dialog_db_handle, res);
  491. return -1;
  492. }
  493. /*this is only called from destroy_dlg, where the cell's entry lock is acquired*/
  494. int remove_dialog_from_db(struct dlg_cell * cell)
  495. {
  496. db_val_t values[2];
  497. db_key_t match_keys[2] = { &h_entry_column, &h_id_column};
  498. db_key_t vars_match_keys[2] = { &vars_h_entry_column, &vars_h_id_column};
  499. /*if the dialog hasn 't been yet inserted in the database*/
  500. LM_DBG("trying to remove dialog [%.*s], update_flag is %i\n",
  501. cell->callid.len, cell->callid.s,
  502. cell->dflags);
  503. if (cell->dflags & DLG_FLAG_NEW)
  504. return 0;
  505. if (use_dialog_table()!=0)
  506. return -1;
  507. VAL_TYPE(values) = VAL_TYPE(values+1) = DB1_INT;
  508. VAL_NULL(values) = VAL_NULL(values+1) = 0;
  509. VAL_INT(values) = cell->h_entry;
  510. VAL_INT(values+1) = cell->h_id;
  511. if(dialog_dbf.delete(dialog_db_handle, match_keys, 0, values, 2) < 0) {
  512. LM_ERR("failed to delete database information\n");
  513. return -1;
  514. }
  515. if (use_dialog_vars_table()!=0)
  516. return -1;
  517. if(dialog_dbf.delete(dialog_db_handle, vars_match_keys, 0, values, 2) < 0) {
  518. LM_ERR("failed to delete database information\n");
  519. return -1;
  520. }
  521. LM_DBG("callid was %.*s\n", cell->callid.len, cell->callid.s );
  522. return 0;
  523. }
  524. int update_dialog_vars_dbinfo(struct dlg_cell * cell, struct dlg_var * var)
  525. {
  526. db_val_t values[DIALOG_VARS_TABLE_COL_NO];
  527. db_key_t insert_keys[DIALOG_VARS_TABLE_COL_NO] = { &vars_h_entry_column,
  528. &vars_h_id_column, &vars_key_column, &vars_value_column };
  529. if(use_dialog_vars_table()!=0)
  530. return -1;
  531. VAL_TYPE(values) = VAL_TYPE(values+1) = DB1_INT;
  532. VAL_TYPE(values+2) = VAL_TYPE(values+3) = DB1_STR;
  533. VAL_NULL(values) = VAL_NULL(values+1) = VAL_NULL(values+2) = VAL_NULL(values+3) = 0;
  534. SET_STR_VALUE(values+2, var->key);
  535. VAL_INT(values) = cell->h_entry;
  536. VAL_INT(values+1) = cell->h_id;
  537. if((var->vflags & DLG_FLAG_DEL) != 0) {
  538. /* delete the current variable */
  539. db_key_t vars_match_keys[3] = { &vars_h_entry_column, &vars_h_id_column, &vars_key_column};
  540. if (use_dialog_vars_table()!=0)
  541. return -1;
  542. if(dialog_dbf.delete(dialog_db_handle, vars_match_keys, 0, values, 3) < 0) {
  543. LM_ERR("failed to delete database information\n");
  544. return -1;
  545. }
  546. } else if((var->vflags & DLG_FLAG_NEW) != 0) {
  547. /* save all the current dialogs information*/
  548. SET_STR_VALUE(values+3, var->value);
  549. if((dialog_dbf.insert(dialog_db_handle, insert_keys, values,
  550. DIALOG_VARS_TABLE_COL_NO)) !=0){
  551. LM_ERR("could not add another dialog-var to db\n");
  552. goto error;
  553. }
  554. var->vflags &= ~(DLG_FLAG_NEW|DLG_FLAG_CHANGED);
  555. } else if((var->vflags & DLG_FLAG_CHANGED) != 0) {
  556. /* save only dialog's state and timeout */
  557. SET_STR_VALUE(values+3, var->value);
  558. if((dialog_dbf.update(dialog_db_handle, insert_keys, 0,
  559. values, (insert_keys+3), (values+3), 3, 1)) !=0){
  560. LM_ERR("could not update database info\n");
  561. goto error;
  562. }
  563. var->vflags &= ~DLG_FLAG_CHANGED;
  564. } else {
  565. return 0;
  566. }
  567. return 0;
  568. error:
  569. return -1;
  570. }
  571. int update_dialog_dbinfo_unsafe(struct dlg_cell * cell)
  572. {
  573. int i;
  574. struct dlg_var *var;
  575. srjson_doc_t jdoc;
  576. db_val_t values[DIALOG_TABLE_COL_NO];
  577. db_key_t insert_keys[DIALOG_TABLE_COL_NO] = { &h_entry_column,
  578. &h_id_column, &call_id_column, &from_uri_column,
  579. &from_tag_column, &to_uri_column, &to_tag_column,
  580. &from_sock_column, &to_sock_column,
  581. &start_time_column, &state_column, &timeout_column,
  582. &from_cseq_column, &to_cseq_column, &from_route_column,
  583. &to_route_column, &from_contact_column,&to_contact_column,
  584. &sflags_column, &toroute_name_column, &req_uri_column,
  585. &xdata_column, &iflags_column };
  586. if(cell->state<DLG_STATE_EARLY) {
  587. LM_DBG("not storing dlg in db during initial state\n");
  588. return 0;
  589. }
  590. i = 0;
  591. if( (cell->dflags & DLG_FLAG_NEW) != 0
  592. || (cell->dflags & DLG_FLAG_CHANGED_VARS) != 0) {
  593. /* iterate the list */
  594. for(var=cell->vars ; var ; var=var->next) {
  595. if (update_dialog_vars_dbinfo(cell, var) != 0)
  596. return -1;
  597. i++;
  598. }
  599. /* Remove the flag */
  600. cell->dflags &= ~DLG_FLAG_CHANGED_VARS;
  601. LM_DBG("updated %d vars for dlg [%d:%d]\n", i, cell->h_entry, cell->h_id);
  602. }
  603. if(use_dialog_table()!=0)
  604. return -1;
  605. srjson_InitDoc(&jdoc, NULL);
  606. if((cell->dflags & DLG_FLAG_NEW) != 0){
  607. /* save all the current dialogs information*/
  608. VAL_TYPE(values) = VAL_TYPE(values+1) = VAL_TYPE(values+9) =
  609. VAL_TYPE(values+10) = VAL_TYPE(values+11) = DB1_INT;
  610. VAL_TYPE(values+2) = VAL_TYPE(values+3) = VAL_TYPE(values+4) =
  611. VAL_TYPE(values+5) = VAL_TYPE(values+6) = VAL_TYPE(values+7) =
  612. VAL_TYPE(values+8) = VAL_TYPE(values+12) = VAL_TYPE(values+13) =
  613. VAL_TYPE(values+14) = VAL_TYPE(values+15) = VAL_TYPE(values+16)=
  614. VAL_TYPE(values+17) = VAL_TYPE(values+20) = DB1_STR;
  615. SET_NULL_FLAG(values, i, DIALOG_TABLE_COL_NO-6, 0);
  616. VAL_TYPE(values+18) = DB1_INT;
  617. VAL_TYPE(values+19) = DB1_STR;
  618. VAL_TYPE(values+21) = DB1_STR;
  619. VAL_TYPE(values+22) = DB1_INT;
  620. VAL_INT(values) = cell->h_entry;
  621. VAL_INT(values+1) = cell->h_id;
  622. VAL_INT(values+9) = cell->start_ts;
  623. VAL_INT(values+10) = cell->state;
  624. VAL_INT(values+11) = (unsigned int)( (unsigned int)time(0) +
  625. cell->tl.timeout - get_ticks() );
  626. SET_STR_VALUE(values+2, cell->callid);
  627. SET_STR_VALUE(values+3, cell->from_uri);
  628. SET_STR_VALUE(values+4, cell->tag[DLG_CALLER_LEG]);
  629. SET_STR_VALUE(values+5, cell->to_uri);
  630. SET_STR_VALUE(values+6, cell->tag[DLG_CALLEE_LEG]);
  631. SET_PROPER_NULL_FLAG(cell->tag[DLG_CALLEE_LEG], values, 6);
  632. LM_DBG("sock_info is %.*s\n",
  633. cell->bind_addr[DLG_CALLER_LEG]->sock_str.len,
  634. cell->bind_addr[DLG_CALLEE_LEG]->sock_str.s);
  635. SET_STR_VALUE(values+7, cell->bind_addr[DLG_CALLER_LEG]->sock_str);
  636. SET_STR_VALUE(values+8, cell->bind_addr[DLG_CALLEE_LEG]->sock_str);
  637. SET_STR_VALUE(values+12, cell->cseq[DLG_CALLER_LEG]);
  638. SET_STR_VALUE(values+13, cell->cseq[DLG_CALLEE_LEG]);
  639. SET_STR_VALUE(values+14, cell->route_set[DLG_CALLER_LEG]);
  640. SET_STR_VALUE(values+15, cell->route_set[DLG_CALLEE_LEG]);
  641. SET_STR_VALUE(values+16, cell->contact[DLG_CALLER_LEG]);
  642. SET_STR_VALUE(values+17, cell->contact[DLG_CALLEE_LEG]);
  643. SET_PROPER_NULL_FLAG(cell->route_set[DLG_CALLER_LEG], values, 14);
  644. SET_PROPER_NULL_FLAG(cell->route_set[DLG_CALLEE_LEG], values, 15);
  645. SET_PROPER_NULL_FLAG(cell->contact[DLG_CALLER_LEG], values, 16);
  646. SET_PROPER_NULL_FLAG(cell->contact[DLG_CALLEE_LEG], values, 17);
  647. VAL_NULL(values+18) = 0;
  648. VAL_INT(values+18) = cell->sflags;
  649. SET_STR_VALUE(values+19, cell->toroute_name);
  650. SET_PROPER_NULL_FLAG(cell->toroute_name, values, 19);
  651. SET_STR_VALUE(values+20, cell->req_uri);
  652. SET_PROPER_NULL_FLAG(cell->req_uri, values, 20);
  653. dlg_profiles_to_json(cell, &jdoc);
  654. if(jdoc.buf.s!=NULL)
  655. {
  656. SET_STR_VALUE(values+21, jdoc.buf);
  657. SET_PROPER_NULL_FLAG(jdoc.buf, values, 21);
  658. } else {
  659. VAL_NULL(values+21) = 1;
  660. }
  661. VAL_NULL(values+22) = 0;
  662. VAL_INT(values+22) = cell->iflags;
  663. if((dialog_dbf.insert(dialog_db_handle, insert_keys, values,
  664. DIALOG_TABLE_COL_NO)) !=0){
  665. LM_ERR("could not add another dialog to db\n");
  666. goto error;
  667. }
  668. cell->dflags &= ~(DLG_FLAG_NEW|DLG_FLAG_CHANGED);
  669. } else if((cell->dflags & DLG_FLAG_CHANGED) != 0) {
  670. /* save only dialog's state and timeout */
  671. VAL_TYPE(values) = VAL_TYPE(values+1) =
  672. VAL_TYPE(values+10) = VAL_TYPE(values+11) = DB1_INT;
  673. VAL_TYPE(values+12) = VAL_TYPE(values+13) =DB1_STR;
  674. VAL_INT(values) = cell->h_entry;
  675. VAL_INT(values+1) = cell->h_id;
  676. VAL_INT(values+10) = cell->state;
  677. VAL_INT(values+11) = (unsigned int)( (unsigned int)time(0) +
  678. cell->tl.timeout - get_ticks() );
  679. SET_STR_VALUE(values+12, cell->cseq[DLG_CALLER_LEG]);
  680. SET_STR_VALUE(values+13, cell->cseq[DLG_CALLEE_LEG]);
  681. VAL_NULL(values) = VAL_NULL(values+1) =
  682. VAL_NULL(values+10) = VAL_NULL(values+11) =
  683. VAL_NULL(values+12) = VAL_NULL(values+13) = 0;
  684. if((dialog_dbf.update(dialog_db_handle, (insert_keys), 0,
  685. (values), (insert_keys+10), (values+10), 2, 4)) !=0){
  686. LM_ERR("could not update database info\n");
  687. goto error;
  688. }
  689. cell->dflags &= ~(DLG_FLAG_CHANGED);
  690. } else {
  691. return 0;
  692. }
  693. if(jdoc.buf.s!=NULL) {
  694. jdoc.free_fn(jdoc.buf.s);
  695. jdoc.buf.s = NULL;
  696. }
  697. srjson_DestroyDoc(&jdoc);
  698. return 0;
  699. error:
  700. if(jdoc.buf.s!=NULL) {
  701. jdoc.free_fn(jdoc.buf.s);
  702. jdoc.buf.s = NULL;
  703. }
  704. srjson_DestroyDoc(&jdoc);
  705. return -1;
  706. }
  707. int update_dialog_dbinfo(struct dlg_cell * cell)
  708. {
  709. struct dlg_entry entry;
  710. /* lock the entry */
  711. entry = (d_table->entries)[cell->h_entry];
  712. dlg_lock( d_table, &entry);
  713. if (update_dialog_dbinfo_unsafe(cell) != 0) {
  714. dlg_unlock( d_table, &entry);
  715. return -1;
  716. }
  717. dlg_unlock( d_table, &entry);
  718. return 0;
  719. }
  720. void dialog_update_db(unsigned int ticks, void * param)
  721. {
  722. int index;
  723. struct dlg_entry entry;
  724. struct dlg_cell * cell;
  725. LM_DBG("saving current_info \n");
  726. for(index = 0; index< d_table->size; index++){
  727. /* lock the whole entry */
  728. entry = (d_table->entries)[index];
  729. dlg_lock( d_table, &entry);
  730. for(cell = entry.first; cell != NULL; cell = cell->next){
  731. if (update_dialog_dbinfo_unsafe(cell) != 0) {
  732. dlg_unlock( d_table, &entry);
  733. goto error;
  734. }
  735. }
  736. dlg_unlock( d_table, &entry);
  737. }
  738. return;
  739. error:
  740. dlg_unlock( d_table, &entry);
  741. }