modules_s/msilo/msilo.c

00001 /*
00002  * $Id$
00003  *
00004  * MSILO module
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  */
00029 
00030 /*
00031  * History
00032  * -------
00033  *
00034  * 2003-01-23: switched from t_uac to t_uac_dlg (dcm)
00035  * 2003-02-28: protocolization of t_uac_dlg completed (jiri)
00036  * 2003-03-11: updated to the new module interface (andrei)
00037  *             removed non-constant initializers to some strs (andrei)
00038  * 2003-03-16: flags parameter added (janakj)
00039  * 2003-04-05: default_uri #define used (jiri)
00040  * 2003-04-06: db_init removed from mod_init, will be called from child_init
00041  *             now (janakj)
00042  * 2003-04-07: m_dump takes a parameter which sets the way the outgoing URI
00043  *             is computed (dcm)
00044  * 2003-08-05 adapted to the new parse_content_type_hdr function (bogdan)
00045  * 2004-06-07 updated to the new DB api (andrei)
00046  */
00047 
00048 #include <stdio.h>
00049 #include <string.h>
00050 #include <stdlib.h>
00051 #include <sys/types.h>
00052 #include <sys/ipc.h>
00053 #include <unistd.h>
00054 #include <fcntl.h>
00055 #include <time.h>
00056 
00057 #include "../../sr_module.h"
00058 #include "../../dprint.h"
00059 #include "../../ut.h"
00060 #include "../../timer.h"
00061 #include "../../mem/shm_mem.h"
00062 #include "../../lib/srdb2/db.h"
00063 #include "../../parser/parse_from.h"
00064 #include "../../parser/parse_content.h"
00065 #include "../../parser/contact/parse_contact.h"
00066 #include "../../resolve.h"
00067 #include "../../id.h"
00068 
00069 #include "../../modules/tm/tm_load.h"
00070 
00071 #define CONTACT_PREFIX "Content-Type: text/plain"CRLF"Contact: <"
00072 #define CONTACT_SUFFIX  ">;msilo=yes"CRLF
00073 #define CONTACT_PREFIX_LEN (sizeof(CONTACT_PREFIX)-1)
00074 #define CONTACT_SUFFIX_LEN  (sizeof(CONTACT_SUFFIX)-1)
00075 #define OFFLINE_MESSAGE "] is offline. The message will be delivered when user goes online."
00076 #define OFFLINE_MESSAGE_LEN     (sizeof(OFFLINE_MESSAGE)-1)
00077 
00078 #include "ms_msg_list.h"
00079 #include "msfuncs.h"
00080 
00081 char *sc_mid      = "mid";       /* 0 */
00082 char *sc_from     = "from_hdr";  /* 1 */
00083 char *sc_to       = "to_hdr";    /* 2 */
00084 char *sc_ruri     = "ruri";      /* 3 */
00085 char *sc_uid      = "uid";       /* 4 */
00086 char *sc_body     = "body";      /* 5 */
00087 char *sc_ctype    = "ctype";     /* 6 */
00088 char *sc_exp_time = "exp_time";  /* 7 */
00089 char *sc_inc_time = "inc_time";  /* 8 */
00090 
00091 MODULE_VERSION
00092 
00093 
00095 static db_ctx_t* ctx = NULL;
00096 static db_cmd_t* store = NULL;
00097 static db_cmd_t* load = NULL;
00098 static db_cmd_t* del_mid = NULL;
00099 static db_cmd_t* del_expired = NULL;
00100 
00102 msg_list ml = NULL;
00103 
00105 struct tm_binds tmb;
00106 
00109 char *ms_db_url=DEFAULT_DB_URL;
00110 char *ms_db_table="silo";
00111 char *ms_registrar=NULL; //"sip:registrar@iptel.org";
00112 int  ms_expire_time=259200;
00113 int  ms_check_time=30;
00114 int  ms_clean_period=5;
00115 int  ms_use_contact=1;
00116 
00117 str msg_type = STR_STATIC_INIT("MESSAGE");
00118 
00119 str reg_addr;
00120 
00122 static int mod_init(void);
00123 static int child_init(int);
00124 
00125 static int m_store(struct sip_msg*, char*, char*);
00126 static int m_dump(struct sip_msg*, char*, char*);
00127 
00128 static void destroy(void);
00129 
00130 void m_clean_silo(unsigned int ticks, void *);
00131 
00133 static void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps);
00134 
00135 static cmd_export_t cmds[]={
00136         {"m_store",  m_store, 2, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00137         {"m_store",  m_store, 1, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00138         {"m_dump",   m_dump,  1, 0, REQUEST_ROUTE},
00139         {"m_dump",   m_dump,  0, 0, REQUEST_ROUTE},
00140         {0,0,0,0,0}
00141 };
00142 
00143 
00144 static param_export_t params[]={
00145         {"db_url",       PARAM_STRING, &ms_db_url},
00146         {"db_table",     PARAM_STRING, &ms_db_table},
00147         {"registrar",    PARAM_STRING, &ms_registrar},
00148         {"expire_time",  PARAM_INT,    &ms_expire_time},
00149         {"check_time",   PARAM_INT,    &ms_check_time},
00150         {"clean_period", PARAM_INT,    &ms_clean_period},
00151         {"use_contact",  PARAM_INT,    &ms_use_contact},
00152         {"sc_mid",       PARAM_STRING, &sc_mid},
00153         {"sc_from",      PARAM_STRING, &sc_from},
00154         {"sc_to",        PARAM_STRING, &sc_to},
00155         {"sc_ruri",      PARAM_STRING, &sc_ruri},
00156         {"sc_uid",       PARAM_STRING, &sc_uid},
00157         {"sc_body",      PARAM_STRING, &sc_body},
00158         {"sc_ctype",     PARAM_STRING, &sc_ctype},
00159         {"sc_exp_time",  PARAM_STRING, &sc_exp_time},
00160         {"sc_inc_time",  PARAM_STRING, &sc_inc_time},
00161         {0,0,0}
00162 };
00163 
00164 
00166 struct module_exports exports= {
00167         "msilo",    /* module id */
00168         cmds,       /* module's exported functions */
00169         0,          /* RPC methods */
00170         params,     /* module's exported parameters */
00171 
00172         mod_init,   /* module initialization function */
00173         (response_function) 0,       /* response handler */
00174         (destroy_function) destroy,  /* module destroy function */
00175         0,
00176         child_init  /* per-child init function */
00177 };
00178 
00182 static int mod_init(void)
00183 {
00184         load_tm_f  load_tm;
00185 
00186         DBG("MSILO: initializing ...\n");
00187 
00188         /* import the TM auto-loading function */
00189         if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
00190                 LOG(L_ERR, "ERROR: msilo: mod_init: can't import load_tm\n");
00191                 return -1;
00192         }
00193         /* let the auto-loading function load all TM stuff */
00194         if (load_tm( &tmb )==-1)
00195                 return -1;
00196 
00197         ml = msg_list_init();
00198         if(!ml)
00199         {
00200                 DBG("ERROR: msilo: mod_init: can't initialize msg list\n");
00201                 return -1;
00202         }
00203         register_timer( m_clean_silo, 0, ms_check_time);
00204 
00205         reg_addr.s = ms_registrar;
00206         reg_addr.len = (ms_registrar)?strlen(ms_registrar):0;
00207 
00208         return 0;
00209 }
00210 
00211 
00212 void msilo_db_close(void)
00213 {
00214         if (store) db_cmd_free(store);
00215         store = NULL;
00216 
00217         if (load) db_cmd_free(load);
00218         load = NULL;
00219 
00220         if (del_mid) db_cmd_free(del_mid);
00221         del_mid = NULL;
00222 
00223         if (del_expired) db_cmd_free(del_expired);
00224         del_expired = NULL;
00225 
00226         if (ctx) {
00227                 db_disconnect(ctx);
00228                 db_ctx_free(ctx);
00229                 ctx = NULL;
00230         }
00231 }
00232 
00233 
00234 int msilo_db_init(char* db_url)
00235 {
00236         db_fld_t del_mid_param[] = {
00237                 {.name = sc_mid, .type = DB_INT},
00238                 {.name = 0}
00239         };
00240 
00241         db_fld_t del_expired_param[] = {
00242                 {.name = sc_exp_time, .type = DB_DATETIME, .op = DB_LEQ},
00243                 {.name = 0}
00244         };
00245 
00246         db_fld_t store_param[] = {
00247                 {.name = sc_to,       .type = DB_STR     },
00248                 {.name = sc_from,     .type = DB_STR     },
00249                 {.name = sc_ruri,     .type = DB_STR     },
00250                 {.name = sc_uid,      .type = DB_STR     },
00251                 {.name = sc_body,     .type = DB_BLOB    },
00252                 {.name = sc_ctype,    .type = DB_STR     },
00253                 {.name = sc_exp_time, .type = DB_DATETIME},
00254                 {.name = sc_inc_time, .type = DB_DATETIME},
00255                 {.name = 0}
00256         };
00257 
00258         db_fld_t load_match[] = {
00259                 {.name = sc_uid, .type = DB_STR},
00260                 {.name = 0}
00261         };
00262 
00263         db_fld_t load_cols[] = {
00264                 {.name = sc_mid,      .type = DB_INT},
00265                 {.name = sc_from,     .type = DB_STR},
00266                 {.name = sc_to,       .type = DB_STR},
00267                 {.name = sc_body,     .type = DB_BLOB},
00268                 {.name = sc_ctype,    .type = DB_STR},
00269                 {.name = sc_inc_time, .type = DB_DATETIME},
00270                 {.name = sc_ruri,     .type = DB_STR},
00271                 {.name = 0}
00272         };
00273 
00274         ctx = db_ctx("msilo");
00275         if (!ctx) goto error;
00276         if (db_add_db(ctx, db_url) < 0) goto error;
00277         if (db_connect(ctx) < 0) goto error;
00278 
00279         store = db_cmd(DB_PUT, ctx, ms_db_table, NULL, NULL, store_param);
00280         if (!store) goto error;
00281 
00282         load = db_cmd(DB_GET, ctx, ms_db_table, load_cols, load_match, NULL);
00283         if (!store) goto error;
00284 
00285         del_mid = db_cmd(DB_DEL, ctx, ms_db_table, NULL, del_mid_param, NULL);
00286         if (!del_mid) goto error;
00287 
00288         del_expired = db_cmd(DB_DEL, ctx, ms_db_table, NULL, del_expired_param, NULL);
00289         if (!store) goto error;
00290 
00291     return 0;
00292 
00293 error:
00294         msilo_db_close();
00295         ERR("msilo: Error while initializing database layer\n");
00296         return -1;
00297 }
00298 
00299 
00300 
00301 
00302 
00303 
00307 static int child_init(int rank)
00308 {
00309 
00310         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00311                 return 0; /* do nothing for the main or tcp_main processes */
00312 
00313         DBG("MSILO: init_child #%d / pid <%d>\n", rank, getpid());
00314         if (msilo_db_init(ms_db_url) < 0) return -1;
00315         return 0;
00316 }
00317 
00318 
00322 static void destroy(void)
00323 {
00324         DBG("MSILO: destroy module ...\n");
00325         msg_list_free(ml);
00326 
00327         msilo_db_close();
00328 }
00329 
00330 
00331 
00332 
00340 static int m_store(struct sip_msg* msg, char* str1, char* str2)
00341 {
00342         str body, str_hdr, ctaddr, uri, uid;
00343         struct to_body* to, *from;
00344 
00345         int val, lexpire;
00346         t_content_type ctype;
00347         static char buf[512];
00348         static char buf1[1024];
00349         int mime, mode;
00350         str next_hop = STR_NULL;
00351         uac_req_t       uac_r;
00352 
00353         DBG("MSILO: m_store: ------------ start ------------\n");
00354 
00355         if (!str1) {
00356                 LOG(L_ERR, "MSILO:m_store: Invalid parameter value\n");
00357                 goto error;
00358         }
00359         mode = str1[0] - '0';
00360         if (str2) {
00361                 next_hop.s = str2;
00362                 next_hop.len = strlen(str2);
00363         }
00364 
00365         if (get_to_uid(&uid, msg) < 0) {
00366                 LOG(L_ERR, "MSILO:m_store: Unable to find out identity of user\n");
00367                 goto error;
00368         }
00369 
00370         /* get message body - after that whole SIP MESSAGE is parsed */
00371         body.s = get_body( msg );
00372         if (body.s==0) {
00373                 LOG(L_ERR,"MSILO:m_store: ERROR cannot extract body from msg\n");
00374                 goto error;
00375         }
00376 
00377         /* content-length (if present) must be already parsed */
00378         if (!msg->content_length) {
00379                 LOG(L_ERR,"MSILO:m_store: ERROR no Content-Length header found!\n");
00380                 goto error;
00381         }
00382         body.len = get_content_length(msg);
00383 
00384         /* check if the body of message contains something */
00385         if(body.len <= 0) {
00386                 DBG("MSILO:m_store: body of the message is empty!\n");
00387                 goto error;
00388         }
00389 
00390         to = get_to(msg);
00391         if (!to) {
00392                 LOG(L_ERR, "MSILO:m_store: Cannot get To header\n");
00393                 goto error;
00394         }
00395 
00396         if (parse_from_header(msg) < 0) {
00397                 LOG(L_ERR, "MSILO:m_store: Error while Parsing From header\n");
00398                 goto error;
00399         }
00400         from = get_from(msg);
00401         if (!from) {
00402                 LOG(L_ERR, "MSILO:m_store: Cannot find From header\n");
00403                 goto error;
00404         }
00405 
00406         store->vals[0].v.lstr = to->uri;
00407         store->vals[1].v.lstr = from->uri;
00408 
00409         switch(mode) {
00410         case 0:
00411                 uri = *GET_RURI(msg);
00412                      /* new_ruri, orig_ruri*/
00413                 break;
00414         case 1:
00415                      /* orig_ruri */
00416                 uri = msg->first_line.u.request.uri;
00417                 break;
00418         case 2:
00419                 uri = to->uri;
00420                 break;
00421         default:
00422                 LOG(L_ERR, "MSILO:m_store: Unrecognized parameter value: %s\n", str1);
00423                 goto error;
00424         }
00425 
00426         store->vals[2].v.lstr = uri;
00427         store->vals[3].v.lstr = uid;
00428         /* add the message's body in SQL query */
00429         store->vals[4].v.blob = body;
00430 
00431         lexpire = ms_expire_time;
00432         /* add 'content-type' -- parse the content-type header */
00433         if ((mime=parse_content_type_hdr(msg))<1 )
00434         {
00435                 LOG(L_ERR,"MSILO:m_store: ERROR cannot parse Content-Type header\n");
00436                 goto error;
00437         }
00438 
00439         store->vals[5].v.lstr.s = "text/plain";
00440         store->vals[5].v.lstr.len = 10;
00441 
00443         if( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
00444                 && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM )
00445         {
00446                 if(m_extract_content_type(msg->content_type->body.s,
00447                                 msg->content_type->body.len, &ctype, CT_TYPE) != -1)
00448                 {
00449                         DBG("MSILO:m_store: 'content-type' found\n");
00450                         store->vals[5].v.lstr = ctype.type;
00451                 }
00452         }
00453 
00454         /* check 'expires' -- no more parsing - already done by get_body() */
00455         if(msg->expires && msg->expires->body.len > 0)
00456         {
00457                 DBG("MSILO:m_store: 'expires' found\n");
00458                 val = atoi(msg->expires->body.s);
00459                 if(val > 0)
00460                         lexpire = (ms_expire_time<=val)?ms_expire_time:val;
00461         }
00462 
00463         /* current time */
00464         val = (int)time(NULL);
00465 
00466         /* add expiration time */
00467         store->vals[6].v.time = val + lexpire;
00468         store->vals[7].v.time = val;
00469 
00470         if (db_exec(NULL, store) < 0) {
00471                 LOG(L_ERR, "MSILO:m_store: error storing message\n");
00472                 goto error;
00473         }
00474         DBG("MSILO:m_store: message stored. uid:<%.*s> F:<%.*s>\n",
00475                 uid.len, uid.s, from->uri.len, ZSW(from->uri.s));
00476         
00477         if(reg_addr.len > 0
00478                 && reg_addr.len+CONTACT_PREFIX_LEN+CONTACT_SUFFIX_LEN+1<1024)
00479         {
00480                 DBG("MSILO:m_store: sending info message.\n");
00481                 strcpy(buf1, CONTACT_PREFIX);
00482                 strncat(buf1,reg_addr.s,reg_addr.len);
00483                 strncat(buf1, CONTACT_SUFFIX, CONTACT_SUFFIX_LEN);
00484                 str_hdr.len = CONTACT_PREFIX_LEN+reg_addr.len+CONTACT_SUFFIX_LEN;
00485                 str_hdr.s = buf1;
00486 
00487                 strncpy(buf, "User [", 6);
00488                 body.len = 6;
00489                 if(uri.len+OFFLINE_MESSAGE_LEN+7/*6+1*/ < 512)
00490                 {
00491                         strncpy(buf+body.len, uri.s, uri.len);
00492                         body.len += uri.len;
00493                 }
00494                 strncpy(buf+body.len, OFFLINE_MESSAGE, OFFLINE_MESSAGE_LEN);
00495                 body.len += OFFLINE_MESSAGE_LEN;
00496 
00497                 body.s = buf;
00498 
00499                 /* look for Contact header -- must be parsed by now*/
00500                 ctaddr.s = NULL;
00501                 if(ms_use_contact && msg->contact!=NULL && msg->contact->body.s!=NULL
00502                                 && msg->contact->body.len > 0)
00503                 {
00504                         DBG("MSILO:m_store: contact header found\n");
00505                         if((msg->contact->parsed!=NULL
00506                                 && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL)
00507                                 || (parse_contact(msg->contact)==0
00508                                 && msg->contact->parsed!=NULL
00509                                 && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL))
00510                         {
00511                                 DBG("MSILO:m_store: using contact header for info msg\n");
00512                                 ctaddr.s =
00513                                 ((contact_body_t*)(msg->contact->parsed))->contacts->uri.s;
00514                                 ctaddr.len =
00515                                 ((contact_body_t*)(msg->contact->parsed))->contacts->uri.len;
00516 
00517                                 if(!ctaddr.s || ctaddr.len < 6 || strncmp(ctaddr.s, "sip:", 4)
00518                                         || ctaddr.s[4]==' ')
00519                                         ctaddr.s = NULL;
00520                                 else
00521                                         DBG("MSILO:m_store: feedback contact [%.*s]\n",
00522                                                         ctaddr.len,ctaddr.s);
00523                         }
00524                 }
00525 
00526                 set_uac_req(&uac_r,
00527                                 &msg_type,        /* Type of the message */
00528                                 &str_hdr,         /* Optional headers including CRLF */
00529                                 &body,            /* Message body */
00530                                 0,                /* dialog */
00531                                 0,                /* callback flags */
00532                                 0,                /* callback function */
00533                                 0                 /* callback parameter */
00534                                         );
00535                                 
00536                 tmb.t_request(&uac_r,
00537                                 (ctaddr.s)?&ctaddr:&from->uri,    /* Request-URI */
00538                                 &from->uri,       /* To */
00539                                 &reg_addr,        /* From */
00540                                 next_hop.len ? &next_hop: NULL        /* next hop */
00541                         );
00542         }
00543 
00544         return 1;
00545 error:
00546         return -1;
00547 }
00548 
00552 static int m_dump(struct sip_msg* msg, char* str1, char* str2)
00553 {
00554         db_res_t* res = NULL;
00555         db_rec_t* rec;
00556         int i, mid, n;
00557         char hdr_buf[1024], body_buf[1024];
00558 
00559         str str_vals[5], hdr_str , body_str, uid;
00560         time_t rtime;
00561         str next_hop = STR_NULL;
00562         uac_req_t       uac_r;
00563         
00564         i=0; /* fix warning in DBG() */
00565         if (str1) {
00566                 next_hop.s = str1;
00567                 next_hop.len = strlen(str1);
00568         }
00569 
00570         DBG("MSILO:m_dump: ------------ start ------------\n");
00571 
00572         if (get_to_uid(&uid, msg) < 0) {
00573                 LOG(L_ERR, "MSILO:m_dump: Unable to retrieve identity of user\n");
00574                 goto error;
00575         }
00576 
00577         hdr_str.s = hdr_buf;
00578         hdr_str.len = 1024;
00579         body_str.s = body_buf;
00580         body_str.len = 1024;
00581 
00585         if(parse_headers(msg, HDR_EXPIRES_F, 0) >= 0)
00586         {
00587                 /* check 'expires' > 0 */
00588                 if(msg->expires && msg->expires->body.len > 0)
00589                 {
00590                         i = atoi(msg->expires->body.s);
00591                         if(i <= 0)
00592                         { /* user goes offline */
00593                                 DBG("MSILO:m_dump: user <%.*s> goes offline - expires=%d\n",
00594                                                 uid.len, uid.s, i);
00595                                 goto error;
00596                         }
00597                         else
00598                                 DBG("MSILO:m_dump: user <%.*s> online - expires=%d\n",
00599                                                 uid.len, uid.s, i);
00600                 }
00601         }
00602         else
00603         {
00604                 DBG("MSILO:m_dump: 'expires' threw error at parsing\n");
00605                 goto error;
00606         }
00607 
00608         load->match[0].v.lstr = uid;
00609 
00610         if (db_exec(&res, load) < 0) {
00611                 ERR("msilo: Error while loading messages from database\n");
00612                 goto error;
00613         }
00614         if (!res || !(rec = db_first(res))) {
00615                 DBG("MSILO:m_dump: no stored message for <%.*s>!\n", STR_FMT(&uid));
00616                 goto done;
00617         }
00618 
00619         for(; rec; rec = db_next(res)) {
00620                 if (rec->fld[0].flags & DB_NULL) {
00621                         ERR("msilo: Database returned message with NULL msgid, skipping\n");
00622                         continue;
00623                 }
00624                 mid = rec->fld[0].v.int4;
00625                 if(msg_list_check_msg(ml, mid))
00626                 {
00627                         DBG("MSILO:m_dump: message[%d] mid=%d already sent.\n",
00628                                 i, mid);
00629                         continue;
00630                 }
00631 
00632                 memset(str_vals, 0, 4*sizeof(str));
00633                 if (!(rec->fld[1].flags & DB_NULL)) str_vals[0] = rec->fld[1].v.lstr;
00634                 if (!(rec->fld[2].flags & DB_NULL)) str_vals[1] = rec->fld[2].v.lstr;
00635                 if (!(rec->fld[3].flags & DB_NULL)) str_vals[2] = rec->fld[3].v.lstr;
00636                 if (!(rec->fld[4].flags & DB_NULL)) str_vals[3] = rec->fld[4].v.lstr;
00637                 if (!(rec->fld[6].flags & DB_NULL)) str_vals[4] = rec->fld[6].v.lstr;
00638 
00639                 hdr_str.len = 1024;
00640                 if(m_build_headers(&hdr_str, str_vals[3] /*ctype*/,
00641                                 str_vals[0]/*from*/) < 0)
00642                 {
00643                         DBG("MSILO:m_dump: headers building failed!!!\n");
00644                         msg_list_set_flag(ml, mid, MS_MSG_ERRO);
00645                         goto error;
00646                 }
00647 
00648                 DBG("MSILO:m_dump: msg [%d-%d] for: %.*s\n", i+1, mid,
00649                                 uid.len, ZSW(uid.s));
00650 
00652                 body_str.len = 1024;
00653                 if (rec->fld[5].flags & DB_NULL) {
00654                         rtime = 0;
00655                 } else {
00656                         rtime = rec->fld[5].v.time;
00657                 }
00658                 n = m_build_body(&body_str, rtime, str_vals[2/*body*/]);
00659                 if(n<0)
00660                         DBG("MSILO:m_dump: sending simple body\n");
00661                 else
00662                         DBG("MSILO:m_dump: sending composed body\n");
00663                 
00664                 set_uac_req(&uac_r,
00665                                         &msg_type,  /* Type of the message */
00666                                         &hdr_str,         /* Optional headers including CRLF */
00667                                         (n<0)?&str_vals[2]:&body_str, /* Message body */
00668                                         0,                      /* dialog */
00669                                         TMCB_LOCAL_COMPLETED,   /* callback flags */
00670                                         m_tm_callback,          /* Callback function */
00671                                         (void*)(long)mid        /* Callback parameter */
00672                                         );
00673                 tmb.t_request(&uac_r,
00674                                           &str_vals[4],     /* Request-URI */
00675                                           &str_vals[1],     /* To */
00676                                           &str_vals[0],     /* From */
00677                                           next_hop.len ? &next_hop: NULL /* next hop */
00678                                           );
00679         }
00680         
00681  done:
00686         if (res) db_res_free(res);
00687         return 1;
00688  error:
00689         if (res) db_res_free(res);
00690         return -1;
00691 }
00692 
00697 void m_clean_silo(unsigned int ticks, void *param)
00698 {
00699         msg_list_el mle = NULL, p;
00700 
00701         DBG("MSILO:clean_silo: cleaning stored messages - %d\n", ticks);
00702 
00703         msg_list_check(ml);
00704         mle = p = msg_list_reset(ml);
00705         while(p) {
00706                 if(p->flag & MS_MSG_DONE) {
00707                         del_mid->match[0].v.int4 = p->msgid;
00708                         DBG("MSILO:clean_silo: cleaning sent message [%d]\n", p->msgid);
00709                         if (db_exec(NULL, del_mid) < 0) {
00710                                 DBG("MSILO:clean_silo: error while cleaning message %d.\n", p->msgid);
00711                         }
00712                 }
00713                 p = p->next;
00714         }
00715 
00716         msg_list_el_free_all(mle);
00717 
00718         /* cleaning expired messages */
00719         if(ticks % (ms_check_time * ms_clean_period) < ms_check_time) {
00720                 DBG("MSILO:clean_silo: cleaning expired messages\n");
00721                 del_expired->match[0].v.time = (int)time(NULL);
00722                 if (db_exec(NULL, del_expired) < 0) {
00723                         DBG("MSILO:clean_silo: ERROR cleaning expired messages\n");
00724                 }
00725         }
00726 }
00727 
00728 
00732 void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
00733 {
00734         int mid = -1;
00735         
00736         DBG("MSILO:m_tm_callback: completed with status %d\n", ps->code);
00737         if(!ps->param)
00738         {
00739                 DBG("MSILO m_tm_callback: message id not received\n");
00740                 goto done;
00741         }
00742         mid = (int)(long)(*ps->param);
00743         if(ps->code < 200 || ps->code >= 300)
00744         {
00745                 
00746                 DBG("MSILO:m_tm_callback: message <%d> was not sent successfully\n",
00747                                 mid);
00748                 msg_list_set_flag(ml, mid, MS_MSG_ERRO);
00749                 goto done;
00750         }
00751 
00752         msg_list_set_flag(ml, mid, MS_MSG_DONE);
00753 
00754 done:
00755         return;
00756 }