msilo.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. /*
  2. * $Id$
  3. *
  4. * MSILO module
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * [email protected]
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. /*
  30. * History
  31. * -------
  32. *
  33. * 2003-01-23: switched from t_uac to t_uac_dlg (dcm)
  34. * 2003-02-28: protocolization of t_uac_dlg completed (jiri)
  35. * 2003-03-11: updated to the new module interface (andrei)
  36. * removed non-constant initializers to some strs (andrei)
  37. * 2003-03-16: flags parameter added (janakj)
  38. * 2003-04-05: default_uri #define used (jiri)
  39. * 2003-04-06: db_init removed from mod_init, will be called from child_init
  40. * now (janakj)
  41. * 2003-04-07: m_dump takes a parameter which sets the way the outgoing URI
  42. * is computed (dcm)
  43. * 2003-08-05 adapted to the new parse_content_type_hdr function (bogdan)
  44. * 2004-06-07 updated to the new DB api (andrei)
  45. */
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <stdlib.h>
  49. #include <sys/types.h>
  50. #include <sys/ipc.h>
  51. #include <unistd.h>
  52. #include <fcntl.h>
  53. #include <time.h>
  54. #include "../../sr_module.h"
  55. #include "../../dprint.h"
  56. #include "../../ut.h"
  57. #include "../../timer.h"
  58. #include "../../mem/shm_mem.h"
  59. #include "../../lib/srdb2/db.h"
  60. #include "../../parser/parse_from.h"
  61. #include "../../parser/parse_content.h"
  62. #include "../../parser/contact/parse_contact.h"
  63. #include "../../resolve.h"
  64. #include "../../id.h"
  65. #include "../../modules/tm/tm_load.h"
  66. #define CONTACT_PREFIX "Content-Type: text/plain"CRLF"Contact: <"
  67. #define CONTACT_SUFFIX ">;msilo=yes"CRLF
  68. #define CONTACT_PREFIX_LEN (sizeof(CONTACT_PREFIX)-1)
  69. #define CONTACT_SUFFIX_LEN (sizeof(CONTACT_SUFFIX)-1)
  70. #define OFFLINE_MESSAGE "] is offline. The message will be delivered when user goes online."
  71. #define OFFLINE_MESSAGE_LEN (sizeof(OFFLINE_MESSAGE)-1)
  72. #include "ms_msg_list.h"
  73. #include "msfuncs.h"
  74. char *sc_mid = "mid"; /* 0 */
  75. char *sc_from = "from_hdr"; /* 1 */
  76. char *sc_to = "to_hdr"; /* 2 */
  77. char *sc_ruri = "ruri"; /* 3 */
  78. char *sc_uid = "uid"; /* 4 */
  79. char *sc_body = "body"; /* 5 */
  80. char *sc_ctype = "ctype"; /* 6 */
  81. char *sc_exp_time = "exp_time"; /* 7 */
  82. char *sc_inc_time = "inc_time"; /* 8 */
  83. MODULE_VERSION
  84. /** database layer variables */
  85. static db_ctx_t* ctx = NULL;
  86. static db_cmd_t* store = NULL;
  87. static db_cmd_t* load = NULL;
  88. static db_cmd_t* del_mid = NULL;
  89. static db_cmd_t* del_expired = NULL;
  90. /** precessed msg list - used for dumping the messages */
  91. msg_list ml = NULL;
  92. /** TM bind */
  93. struct tm_binds tmb;
  94. /** parameters */
  95. char *ms_db_url=DEFAULT_DB_URL;
  96. char *ms_db_table="silo";
  97. char *ms_registrar=NULL; //"sip:[email protected]";
  98. int ms_expire_time=259200;
  99. int ms_check_time=30;
  100. int ms_clean_period=5;
  101. int ms_use_contact=1;
  102. str msg_type = STR_STATIC_INIT("MESSAGE");
  103. str reg_addr;
  104. /** module functions */
  105. static int mod_init(void);
  106. static int child_init(int);
  107. static int m_store(struct sip_msg*, char*, char*);
  108. static int m_dump(struct sip_msg*, char*, char*);
  109. static void destroy(void);
  110. void m_clean_silo(unsigned int ticks, void *);
  111. /** TM callback function */
  112. static void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps);
  113. static cmd_export_t cmds[]={
  114. {"m_store", m_store, 2, 0, REQUEST_ROUTE | FAILURE_ROUTE},
  115. {"m_store", m_store, 1, 0, REQUEST_ROUTE | FAILURE_ROUTE},
  116. {"m_dump", m_dump, 1, 0, REQUEST_ROUTE},
  117. {"m_dump", m_dump, 0, 0, REQUEST_ROUTE},
  118. {0,0,0,0,0}
  119. };
  120. static param_export_t params[]={
  121. {"db_url", PARAM_STRING, &ms_db_url},
  122. {"db_table", PARAM_STRING, &ms_db_table},
  123. {"registrar", PARAM_STRING, &ms_registrar},
  124. {"expire_time", PARAM_INT, &ms_expire_time},
  125. {"check_time", PARAM_INT, &ms_check_time},
  126. {"clean_period", PARAM_INT, &ms_clean_period},
  127. {"use_contact", PARAM_INT, &ms_use_contact},
  128. {"sc_mid", PARAM_STRING, &sc_mid},
  129. {"sc_from", PARAM_STRING, &sc_from},
  130. {"sc_to", PARAM_STRING, &sc_to},
  131. {"sc_ruri", PARAM_STRING, &sc_ruri},
  132. {"sc_uid", PARAM_STRING, &sc_uid},
  133. {"sc_body", PARAM_STRING, &sc_body},
  134. {"sc_ctype", PARAM_STRING, &sc_ctype},
  135. {"sc_exp_time", PARAM_STRING, &sc_exp_time},
  136. {"sc_inc_time", PARAM_STRING, &sc_inc_time},
  137. {0,0,0}
  138. };
  139. /** module exports */
  140. struct module_exports exports= {
  141. "msilo", /* module id */
  142. cmds, /* module's exported functions */
  143. 0, /* RPC methods */
  144. params, /* module's exported parameters */
  145. mod_init, /* module initialization function */
  146. (response_function) 0, /* response handler */
  147. (destroy_function) destroy, /* module destroy function */
  148. 0,
  149. child_init /* per-child init function */
  150. };
  151. /**
  152. * init module function
  153. */
  154. static int mod_init(void)
  155. {
  156. load_tm_f load_tm;
  157. DBG("MSILO: initializing ...\n");
  158. /* import the TM auto-loading function */
  159. if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
  160. LOG(L_ERR, "ERROR: msilo: mod_init: can't import load_tm\n");
  161. return -1;
  162. }
  163. /* let the auto-loading function load all TM stuff */
  164. if (load_tm( &tmb )==-1)
  165. return -1;
  166. ml = msg_list_init();
  167. if(!ml)
  168. {
  169. DBG("ERROR: msilo: mod_init: can't initialize msg list\n");
  170. return -1;
  171. }
  172. register_timer( m_clean_silo, 0, ms_check_time);
  173. reg_addr.s = ms_registrar;
  174. reg_addr.len = (ms_registrar)?strlen(ms_registrar):0;
  175. return 0;
  176. }
  177. void msilo_db_close(void)
  178. {
  179. if (store) db_cmd_free(store);
  180. store = NULL;
  181. if (load) db_cmd_free(load);
  182. load = NULL;
  183. if (del_mid) db_cmd_free(del_mid);
  184. del_mid = NULL;
  185. if (del_expired) db_cmd_free(del_expired);
  186. del_expired = NULL;
  187. if (ctx) {
  188. db_disconnect(ctx);
  189. db_ctx_free(ctx);
  190. ctx = NULL;
  191. }
  192. }
  193. int msilo_db_init(char* db_url)
  194. {
  195. db_fld_t del_mid_param[] = {
  196. {.name = sc_mid, .type = DB_INT},
  197. {.name = 0}
  198. };
  199. db_fld_t del_expired_param[] = {
  200. {.name = sc_exp_time, .type = DB_DATETIME, .op = DB_LEQ},
  201. {.name = 0}
  202. };
  203. db_fld_t store_param[] = {
  204. {.name = sc_to, .type = DB_STR },
  205. {.name = sc_from, .type = DB_STR },
  206. {.name = sc_ruri, .type = DB_STR },
  207. {.name = sc_uid, .type = DB_STR },
  208. {.name = sc_body, .type = DB_BLOB },
  209. {.name = sc_ctype, .type = DB_STR },
  210. {.name = sc_exp_time, .type = DB_DATETIME},
  211. {.name = sc_inc_time, .type = DB_DATETIME},
  212. {.name = 0}
  213. };
  214. db_fld_t load_match[] = {
  215. {.name = sc_uid, .type = DB_STR},
  216. {.name = 0}
  217. };
  218. db_fld_t load_cols[] = {
  219. {.name = sc_mid, .type = DB_INT},
  220. {.name = sc_from, .type = DB_STR},
  221. {.name = sc_to, .type = DB_STR},
  222. {.name = sc_body, .type = DB_BLOB},
  223. {.name = sc_ctype, .type = DB_STR},
  224. {.name = sc_inc_time, .type = DB_DATETIME},
  225. {.name = sc_ruri, .type = DB_STR},
  226. {.name = 0}
  227. };
  228. ctx = db_ctx("msilo");
  229. if (!ctx) goto error;
  230. if (db_add_db(ctx, db_url) < 0) goto error;
  231. if (db_connect(ctx) < 0) goto error;
  232. store = db_cmd(DB_PUT, ctx, ms_db_table, NULL, NULL, store_param);
  233. if (!store) goto error;
  234. load = db_cmd(DB_GET, ctx, ms_db_table, load_cols, load_match, NULL);
  235. if (!store) goto error;
  236. del_mid = db_cmd(DB_DEL, ctx, ms_db_table, NULL, del_mid_param, NULL);
  237. if (!del_mid) goto error;
  238. del_expired = db_cmd(DB_DEL, ctx, ms_db_table, NULL, del_expired_param, NULL);
  239. if (!store) goto error;
  240. return 0;
  241. error:
  242. msilo_db_close();
  243. ERR("msilo: Error while initializing database layer\n");
  244. return -1;
  245. }
  246. /**
  247. * Initialize children
  248. */
  249. static int child_init(int rank)
  250. {
  251. if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
  252. return 0; /* do nothing for the main or tcp_main processes */
  253. DBG("MSILO: init_child #%d / pid <%d>\n", rank, getpid());
  254. if (msilo_db_init(ms_db_url) < 0) return -1;
  255. return 0;
  256. }
  257. /**
  258. * destroy function
  259. */
  260. static void destroy(void)
  261. {
  262. DBG("MSILO: destroy module ...\n");
  263. msg_list_free(ml);
  264. msilo_db_close();
  265. }
  266. /**
  267. * store message
  268. * mode = "0" -- look for outgoing URI starting with new_uri
  269. * = "1" -- look for outgoing URI starting with r-uri
  270. * = "2" -- look for outgoing URI only at to header
  271. * next_hop = parameter specifying next hop for outgoing messages (like outbound proxy)
  272. */
  273. static int m_store(struct sip_msg* msg, char* str1, char* str2)
  274. {
  275. str body, str_hdr, ctaddr, uri, uid;
  276. struct to_body* to, *from;
  277. int val, lexpire;
  278. t_content_type ctype;
  279. static char buf[512];
  280. static char buf1[1024];
  281. int mime, mode;
  282. str next_hop = STR_NULL;
  283. uac_req_t uac_r;
  284. DBG("MSILO: m_store: ------------ start ------------\n");
  285. if (!str1) {
  286. LOG(L_ERR, "MSILO:m_store: Invalid parameter value\n");
  287. goto error;
  288. }
  289. mode = str1[0] - '0';
  290. if (str2) {
  291. next_hop.s = str2;
  292. next_hop.len = strlen(str2);
  293. }
  294. if (get_to_uid(&uid, msg) < 0) {
  295. LOG(L_ERR, "MSILO:m_store: Unable to find out identity of user\n");
  296. goto error;
  297. }
  298. /* get message body - after that whole SIP MESSAGE is parsed */
  299. body.s = get_body( msg );
  300. if (body.s==0) {
  301. LOG(L_ERR,"MSILO:m_store: ERROR cannot extract body from msg\n");
  302. goto error;
  303. }
  304. /* content-length (if present) must be already parsed */
  305. if (!msg->content_length) {
  306. LOG(L_ERR,"MSILO:m_store: ERROR no Content-Length header found!\n");
  307. goto error;
  308. }
  309. body.len = get_content_length(msg);
  310. /* check if the body of message contains something */
  311. if(body.len <= 0) {
  312. DBG("MSILO:m_store: body of the message is empty!\n");
  313. goto error;
  314. }
  315. to = get_to(msg);
  316. if (!to) {
  317. LOG(L_ERR, "MSILO:m_store: Cannot get To header\n");
  318. goto error;
  319. }
  320. if (parse_from_header(msg) < 0) {
  321. LOG(L_ERR, "MSILO:m_store: Error while Parsing From header\n");
  322. goto error;
  323. }
  324. from = get_from(msg);
  325. if (!from) {
  326. LOG(L_ERR, "MSILO:m_store: Cannot find From header\n");
  327. goto error;
  328. }
  329. store->vals[0].v.lstr = to->uri;
  330. store->vals[1].v.lstr = from->uri;
  331. switch(mode) {
  332. case 0:
  333. uri = *GET_RURI(msg);
  334. /* new_ruri, orig_ruri*/
  335. break;
  336. case 1:
  337. /* orig_ruri */
  338. uri = msg->first_line.u.request.uri;
  339. break;
  340. case 2:
  341. uri = to->uri;
  342. break;
  343. default:
  344. LOG(L_ERR, "MSILO:m_store: Unrecognized parameter value: %s\n", str1);
  345. goto error;
  346. }
  347. store->vals[2].v.lstr = uri;
  348. store->vals[3].v.lstr = uid;
  349. /* add the message's body in SQL query */
  350. store->vals[4].v.blob = body;
  351. lexpire = ms_expire_time;
  352. /* add 'content-type' -- parse the content-type header */
  353. if ((mime=parse_content_type_hdr(msg))<1 )
  354. {
  355. LOG(L_ERR,"MSILO:m_store: ERROR cannot parse Content-Type header\n");
  356. goto error;
  357. }
  358. store->vals[5].v.lstr.s = "text/plain";
  359. store->vals[5].v.lstr.len = 10;
  360. /** check the content-type value */
  361. if( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
  362. && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM )
  363. {
  364. if(m_extract_content_type(msg->content_type->body.s,
  365. msg->content_type->body.len, &ctype, CT_TYPE) != -1)
  366. {
  367. DBG("MSILO:m_store: 'content-type' found\n");
  368. store->vals[5].v.lstr = ctype.type;
  369. }
  370. }
  371. /* check 'expires' -- no more parsing - already done by get_body() */
  372. if(msg->expires && msg->expires->body.len > 0)
  373. {
  374. DBG("MSILO:m_store: 'expires' found\n");
  375. val = atoi(msg->expires->body.s);
  376. if(val > 0)
  377. lexpire = (ms_expire_time<=val)?ms_expire_time:val;
  378. }
  379. /* current time */
  380. val = (int)time(NULL);
  381. /* add expiration time */
  382. store->vals[6].v.time = val + lexpire;
  383. store->vals[7].v.time = val;
  384. if (db_exec(NULL, store) < 0) {
  385. LOG(L_ERR, "MSILO:m_store: error storing message\n");
  386. goto error;
  387. }
  388. DBG("MSILO:m_store: message stored. uid:<%.*s> F:<%.*s>\n",
  389. uid.len, uid.s, from->uri.len, ZSW(from->uri.s));
  390. if(reg_addr.len > 0
  391. && reg_addr.len+CONTACT_PREFIX_LEN+CONTACT_SUFFIX_LEN+1<1024)
  392. {
  393. DBG("MSILO:m_store: sending info message.\n");
  394. strcpy(buf1, CONTACT_PREFIX);
  395. strncat(buf1,reg_addr.s,reg_addr.len);
  396. strncat(buf1, CONTACT_SUFFIX, CONTACT_SUFFIX_LEN);
  397. str_hdr.len = CONTACT_PREFIX_LEN+reg_addr.len+CONTACT_SUFFIX_LEN;
  398. str_hdr.s = buf1;
  399. strncpy(buf, "User [", 6);
  400. body.len = 6;
  401. if(uri.len+OFFLINE_MESSAGE_LEN+7/*6+1*/ < 512)
  402. {
  403. strncpy(buf+body.len, uri.s, uri.len);
  404. body.len += uri.len;
  405. }
  406. strncpy(buf+body.len, OFFLINE_MESSAGE, OFFLINE_MESSAGE_LEN);
  407. body.len += OFFLINE_MESSAGE_LEN;
  408. body.s = buf;
  409. /* look for Contact header -- must be parsed by now*/
  410. ctaddr.s = NULL;
  411. if(ms_use_contact && msg->contact!=NULL && msg->contact->body.s!=NULL
  412. && msg->contact->body.len > 0)
  413. {
  414. DBG("MSILO:m_store: contact header found\n");
  415. if((msg->contact->parsed!=NULL
  416. && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL)
  417. || (parse_contact(msg->contact)==0
  418. && msg->contact->parsed!=NULL
  419. && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL))
  420. {
  421. DBG("MSILO:m_store: using contact header for info msg\n");
  422. ctaddr.s =
  423. ((contact_body_t*)(msg->contact->parsed))->contacts->uri.s;
  424. ctaddr.len =
  425. ((contact_body_t*)(msg->contact->parsed))->contacts->uri.len;
  426. if(!ctaddr.s || ctaddr.len < 6 || strncmp(ctaddr.s, "sip:", 4)
  427. || ctaddr.s[4]==' ')
  428. ctaddr.s = NULL;
  429. else
  430. DBG("MSILO:m_store: feedback contact [%.*s]\n",
  431. ctaddr.len,ctaddr.s);
  432. }
  433. }
  434. set_uac_req(&uac_r,
  435. &msg_type, /* Type of the message */
  436. &str_hdr, /* Optional headers including CRLF */
  437. &body, /* Message body */
  438. 0, /* dialog */
  439. 0, /* callback flags */
  440. 0, /* callback function */
  441. 0 /* callback parameter */
  442. );
  443. tmb.t_request(&uac_r,
  444. (ctaddr.s)?&ctaddr:&from->uri, /* Request-URI */
  445. &from->uri, /* To */
  446. &reg_addr, /* From */
  447. next_hop.len ? &next_hop: NULL /* next hop */
  448. );
  449. }
  450. return 1;
  451. error:
  452. return -1;
  453. }
  454. /**
  455. * dump message
  456. */
  457. static int m_dump(struct sip_msg* msg, char* str1, char* str2)
  458. {
  459. db_res_t* res = NULL;
  460. db_rec_t* rec;
  461. int i, mid, n;
  462. char hdr_buf[1024], body_buf[1024];
  463. str str_vals[5], hdr_str , body_str, uid;
  464. time_t rtime;
  465. str next_hop = STR_NULL;
  466. uac_req_t uac_r;
  467. i=0; /* fix warning in DBG() */
  468. if (str1) {
  469. next_hop.s = str1;
  470. next_hop.len = strlen(str1);
  471. }
  472. DBG("MSILO:m_dump: ------------ start ------------\n");
  473. if (get_to_uid(&uid, msg) < 0) {
  474. LOG(L_ERR, "MSILO:m_dump: Unable to retrieve identity of user\n");
  475. goto error;
  476. }
  477. hdr_str.s = hdr_buf;
  478. hdr_str.len = 1024;
  479. body_str.s = body_buf;
  480. body_str.len = 1024;
  481. /**
  482. * check if has expires=0 (REGISTER)
  483. */
  484. if(parse_headers(msg, HDR_EXPIRES_F, 0) >= 0)
  485. {
  486. /* check 'expires' > 0 */
  487. if(msg->expires && msg->expires->body.len > 0)
  488. {
  489. i = atoi(msg->expires->body.s);
  490. if(i <= 0)
  491. { /* user goes offline */
  492. DBG("MSILO:m_dump: user <%.*s> goes offline - expires=%d\n",
  493. uid.len, uid.s, i);
  494. goto error;
  495. }
  496. else
  497. DBG("MSILO:m_dump: user <%.*s> online - expires=%d\n",
  498. uid.len, uid.s, i);
  499. }
  500. }
  501. else
  502. {
  503. DBG("MSILO:m_dump: 'expires' threw error at parsing\n");
  504. goto error;
  505. }
  506. load->match[0].v.lstr = uid;
  507. if (db_exec(&res, load) < 0) {
  508. ERR("msilo: Error while loading messages from database\n");
  509. goto error;
  510. }
  511. if (!res || !(rec = db_first(res))) {
  512. DBG("MSILO:m_dump: no stored message for <%.*s>!\n", STR_FMT(&uid));
  513. goto done;
  514. }
  515. for(; rec; rec = db_next(res)) {
  516. if (rec->fld[0].flags & DB_NULL) {
  517. ERR("msilo: Database returned message with NULL msgid, skipping\n");
  518. continue;
  519. }
  520. mid = rec->fld[0].v.int4;
  521. if(msg_list_check_msg(ml, mid))
  522. {
  523. DBG("MSILO:m_dump: message[%d] mid=%d already sent.\n",
  524. i, mid);
  525. continue;
  526. }
  527. memset(str_vals, 0, 4*sizeof(str));
  528. if (!(rec->fld[1].flags & DB_NULL)) str_vals[0] = rec->fld[1].v.lstr;
  529. if (!(rec->fld[2].flags & DB_NULL)) str_vals[1] = rec->fld[2].v.lstr;
  530. if (!(rec->fld[3].flags & DB_NULL)) str_vals[2] = rec->fld[3].v.lstr;
  531. if (!(rec->fld[4].flags & DB_NULL)) str_vals[3] = rec->fld[4].v.lstr;
  532. if (!(rec->fld[6].flags & DB_NULL)) str_vals[4] = rec->fld[6].v.lstr;
  533. hdr_str.len = 1024;
  534. if(m_build_headers(&hdr_str, str_vals[3] /*ctype*/,
  535. str_vals[0]/*from*/) < 0)
  536. {
  537. DBG("MSILO:m_dump: headers building failed!!!\n");
  538. msg_list_set_flag(ml, mid, MS_MSG_ERRO);
  539. goto error;
  540. }
  541. DBG("MSILO:m_dump: msg [%d-%d] for: %.*s\n", i+1, mid,
  542. uid.len, ZSW(uid.s));
  543. /** sending using TM function: t_uac */
  544. body_str.len = 1024;
  545. if (rec->fld[5].flags & DB_NULL) {
  546. rtime = 0;
  547. } else {
  548. rtime = rec->fld[5].v.time;
  549. }
  550. n = m_build_body(&body_str, rtime, str_vals[2/*body*/]);
  551. if(n<0)
  552. DBG("MSILO:m_dump: sending simple body\n");
  553. else
  554. DBG("MSILO:m_dump: sending composed body\n");
  555. set_uac_req(&uac_r,
  556. &msg_type, /* Type of the message */
  557. &hdr_str, /* Optional headers including CRLF */
  558. (n<0)?&str_vals[2]:&body_str, /* Message body */
  559. 0, /* dialog */
  560. TMCB_LOCAL_COMPLETED, /* callback flags */
  561. m_tm_callback, /* Callback function */
  562. (void*)(long)mid /* Callback parameter */
  563. );
  564. tmb.t_request(&uac_r,
  565. &str_vals[4], /* Request-URI */
  566. &str_vals[1], /* To */
  567. &str_vals[0], /* From */
  568. next_hop.len ? &next_hop: NULL /* next hop */
  569. );
  570. }
  571. done:
  572. /**
  573. * Free the result because we don't need it
  574. * anymore
  575. */
  576. if (res) db_res_free(res);
  577. return 1;
  578. error:
  579. if (res) db_res_free(res);
  580. return -1;
  581. }
  582. /**
  583. * - cleaning up the messages that got reply
  584. * - delete expired messages from database
  585. */
  586. void m_clean_silo(unsigned int ticks, void *param)
  587. {
  588. msg_list_el mle = NULL, p;
  589. DBG("MSILO:clean_silo: cleaning stored messages - %d\n", ticks);
  590. msg_list_check(ml);
  591. mle = p = msg_list_reset(ml);
  592. while(p) {
  593. if(p->flag & MS_MSG_DONE) {
  594. del_mid->match[0].v.int4 = p->msgid;
  595. DBG("MSILO:clean_silo: cleaning sent message [%d]\n", p->msgid);
  596. if (db_exec(NULL, del_mid) < 0) {
  597. DBG("MSILO:clean_silo: error while cleaning message %d.\n", p->msgid);
  598. }
  599. }
  600. p = p->next;
  601. }
  602. msg_list_el_free_all(mle);
  603. /* cleaning expired messages */
  604. if(ticks % (ms_check_time * ms_clean_period) < ms_check_time) {
  605. DBG("MSILO:clean_silo: cleaning expired messages\n");
  606. del_expired->match[0].v.time = (int)time(NULL);
  607. if (db_exec(NULL, del_expired) < 0) {
  608. DBG("MSILO:clean_silo: ERROR cleaning expired messages\n");
  609. }
  610. }
  611. }
  612. /**
  613. * TM callback function - delete message from database if was sent OK
  614. */
  615. void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
  616. {
  617. int mid = -1;
  618. DBG("MSILO:m_tm_callback: completed with status %d\n", ps->code);
  619. if(!ps->param)
  620. {
  621. DBG("MSILO m_tm_callback: message id not received\n");
  622. goto done;
  623. }
  624. mid = (int)(long)(*ps->param);
  625. if(ps->code < 200 || ps->code >= 300)
  626. {
  627. DBG("MSILO:m_tm_callback: message <%d> was not sent successfully\n",
  628. mid);
  629. msg_list_set_flag(ml, mid, MS_MSG_ERRO);
  630. goto done;
  631. }
  632. msg_list_set_flag(ml, mid, MS_MSG_DONE);
  633. done:
  634. return;
  635. }