msilo.c

Go to the documentation of this file.
00001 /*
00002  * $Id: msilo.c 4949 2008-09-18 12:02:39Z henningw $
00003  *
00004  * MSILO module
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio 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  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History
00025  * -------
00026  *
00027  * 2003-01-23: switched from t_uac to t_uac_dlg (dcm)
00028  * 2003-02-28: protocolization of t_uac_dlg completed (jiri)
00029  * 2003-03-11: updated to the new module interface (andrei)
00030  *             removed non-constant initializers to some strs (andrei)
00031  * 2003-03-16: flags parameter added (janakj)
00032  * 2003-04-05: default_uri #define used (jiri)
00033  * 2003-04-06: db_init removed from mod_init, will be called from child_init
00034  *             now (janakj)
00035  * 2003-04-07: m_dump takes a parameter which sets the way the outgoing URI
00036  *             is computed (dcm)
00037  * 2003-08-05 adapted to the new parse_content_type_hdr function (bogdan)
00038  * 2004-06-07 updated to the new DB api (andrei)
00039  * 2006-09-10 m_dump now checks if registering UA supports MESSAGE method (jh)
00040  * 2006-10-05 added max_messages module variable (jh)
00041  */
00042 
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <stdlib.h>
00046 #include <sys/types.h>
00047 #include <sys/ipc.h>
00048 #include <unistd.h>
00049 #include <fcntl.h>
00050 #include <time.h>
00051 
00052 #include "../../sr_module.h"
00053 #include "../../dprint.h"
00054 #include "../../ut.h"
00055 #include "../../timer.h"
00056 #include "../../mem/shm_mem.h"
00057 #include "../../db/db.h"
00058 #include "../../parser/parse_from.h"
00059 #include "../../parser/parse_content.h"
00060 #include "../../parser/contact/parse_contact.h"
00061 #include "../../parser/parse_allow.h"
00062 #include "../../parser/parse_methods.h"
00063 #include "../../resolve.h"
00064 #include "../../usr_avp.h"
00065 #include "../../mod_fix.h"
00066 
00067 #include "../tm/tm_load.h"
00068 
00069 #include "ms_msg_list.h"
00070 #include "msfuncs.h"
00071 
00072 #define MAX_DEL_KEYS 1  
00073 #define NR_KEYS         10
00074 
00075 static str sc_mid      = str_init("id");        /* 0 */
00076 static str sc_from     = str_init("src_addr");  /* 1 */
00077 static str sc_to       = str_init("dst_addr");  /* 2 */
00078 static str sc_uri_user = str_init("username");  /* 3 */
00079 static str sc_uri_host = str_init("domain");    /* 4 */
00080 static str sc_body     = str_init("body");      /* 5 */
00081 static str sc_ctype    = str_init("ctype");     /* 6 */
00082 static str sc_exp_time = str_init("exp_time");  /* 7 */
00083 static str sc_inc_time = str_init("inc_time");  /* 8 */
00084 static str sc_snd_time = str_init("snd_time");  /* 9 */
00085 
00086 #define SET_STR_VAL(_str, _res, _r, _c)   \
00087    if (RES_ROWS(_res)[_r].values[_c].nul == 0) \
00088    { \
00089       switch(RES_ROWS(_res)[_r].values[_c].type) \
00090       { \
00091       case DB_STRING: \
00092          (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.string_val; \
00093          (_str).len=strlen((_str).s); \
00094          break; \
00095       case DB_STR: \
00096          (_str).len=RES_ROWS(_res)[_r].values[_c].val.str_val.len; \
00097          (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.str_val.s; \
00098          break; \
00099       case DB_BLOB: \
00100          (_str).len=RES_ROWS(_res)[_r].values[_c].val.blob_val.len; \
00101          (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.blob_val.s; \
00102          break; \
00103       default: \
00104          (_str).len=0; \
00105          (_str).s=NULL; \
00106       } \
00107    }
00108 
00109 MODULE_VERSION
00110 
00111 #define S_TABLE_VERSION 5
00112 
00113 /** database connection */
00114 static db_con_t *db_con = NULL;
00115 static db_func_t msilo_dbf;
00116 
00117 /** precessed msg list - used for dumping the messages */
00118 msg_list ml = NULL;
00119 
00120 /** TM bind */
00121 struct tm_binds tmb;
00122 
00123 /** parameters */
00124 
00125 static str ms_db_url = str_init(DEFAULT_DB_URL);
00126 static str ms_db_table = str_init("silo");
00127 str  ms_reminder = {NULL, 0};
00128 str  ms_outbound_proxy = {NULL, 0};
00129 
00130 char*  ms_from = NULL; /*"sip:registrar@example.org";*/
00131 char*  ms_contact = NULL; /*"Contact: <sip:registrar@example.org>\r\n";*/
00132 char*  ms_content_type = NULL; /*"Content-Type: text/plain\r\n";*/
00133 char*  ms_offline_message = NULL; /*"<em>I'm offline.</em>"*/
00134 void**  ms_from_sp = NULL;
00135 void**  ms_contact_sp = NULL;
00136 void**  ms_content_type_sp = NULL;
00137 void**  ms_offline_message_sp = NULL;
00138 
00139 int  ms_expire_time = 259200;
00140 int  ms_check_time = 60;
00141 int  ms_send_time = 0;
00142 int  ms_clean_period = 10;
00143 int  ms_use_contact = 1;
00144 int  ms_add_date = 1;
00145 int  ms_max_messages = 0;
00146 
00147 static str ms_snd_time_avp_param = {NULL, 0};
00148 int_str ms_snd_time_avp_name;
00149 unsigned short ms_snd_time_avp_type;
00150 
00151 str msg_type = str_init("MESSAGE");
00152 
00153 /** module functions */
00154 static int mod_init(void);
00155 static int child_init(int);
00156 
00157 static int m_store(struct sip_msg*, char*, char*);
00158 static int m_dump(struct sip_msg*, char*, char*);
00159 
00160 void destroy(void);
00161 
00162 void m_clean_silo(unsigned int ticks, void *);
00163 void m_send_ontimer(unsigned int ticks, void *);
00164 
00165 int ms_reset_stime(int mid);
00166 
00167 int check_message_support(struct sip_msg* msg);
00168 
00169 /** TM callback function */
00170 static void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps);
00171 
00172 static cmd_export_t cmds[]={
00173    {"m_store",  (cmd_function)m_store, 0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00174    {"m_store",  (cmd_function)m_store, 1, fixup_spve_null, 0,
00175       REQUEST_ROUTE | FAILURE_ROUTE},
00176    {"m_dump",   (cmd_function)m_dump,  0, 0, 0, REQUEST_ROUTE},
00177    {"m_dump",   (cmd_function)m_dump,  1, fixup_spve_null, 0,
00178       REQUEST_ROUTE},
00179    {0,0,0,0,0,0}
00180 };
00181 
00182 
00183 static param_export_t params[]={
00184    { "db_url",           STR_PARAM, &ms_db_url.s             },
00185    { "db_table",         STR_PARAM, &ms_db_table.s           },
00186    { "from_address",     STR_PARAM, &ms_from                 },
00187    { "contact_hdr",      STR_PARAM, &ms_contact              },
00188    { "content_type_hdr", STR_PARAM, &ms_content_type         },
00189    { "offline_message",  STR_PARAM, &ms_offline_message      },
00190    { "reminder",         STR_PARAM, &ms_reminder.s           },
00191    { "outbound_proxy",   STR_PARAM, &ms_outbound_proxy.s     },
00192    { "expire_time",      INT_PARAM, &ms_expire_time          },
00193    { "check_time",       INT_PARAM, &ms_check_time           },
00194    { "send_time",        INT_PARAM, &ms_send_time            },
00195    { "clean_period",     INT_PARAM, &ms_clean_period         },
00196    { "use_contact",      INT_PARAM, &ms_use_contact          },
00197    { "sc_mid",           STR_PARAM, &sc_mid.s                },
00198    { "sc_from",          STR_PARAM, &sc_from.s               },
00199    { "sc_to",            STR_PARAM, &sc_to.s                 },
00200    { "sc_uri_user",      STR_PARAM, &sc_uri_user.s           },
00201    { "sc_uri_host",      STR_PARAM, &sc_uri_host.s           },
00202    { "sc_body",          STR_PARAM, &sc_body.s               },
00203    { "sc_ctype",         STR_PARAM, &sc_ctype.s              },
00204    { "sc_exp_time",      STR_PARAM, &sc_exp_time.s           },
00205    { "sc_inc_time",      STR_PARAM, &sc_inc_time.s           },
00206    { "sc_snd_time",      STR_PARAM, &sc_snd_time.s           },
00207    { "snd_time_avp",     STR_PARAM, &ms_snd_time_avp_param.s },
00208    { "add_date",         INT_PARAM, &ms_add_date             },
00209    { "max_messages",     INT_PARAM, &ms_max_messages         },
00210    { 0,0,0 }
00211 };
00212 
00213 #ifdef STATISTICS
00214 #include "../../statistics.h"
00215 
00216 stat_var* ms_stored_msgs;
00217 stat_var* ms_dumped_msgs;
00218 stat_var* ms_failed_msgs;
00219 stat_var* ms_dumped_rmds;
00220 stat_var* ms_failed_rmds;
00221 
00222 stat_export_t msilo_stats[] = {
00223    {"stored_messages" ,  0,  &ms_stored_msgs  },
00224    {"dumped_messages" ,  0,  &ms_dumped_msgs  },
00225    {"failed_messages" ,  0,  &ms_failed_msgs  },
00226    {"dumped_reminders" , 0,  &ms_dumped_rmds  },
00227    {"failed_reminders" , 0,  &ms_failed_rmds  },
00228    {0,0,0}
00229 };
00230 
00231 #endif
00232 /** module exports */
00233 struct module_exports exports= {
00234    "msilo",    /* module id */
00235    DEFAULT_DLFLAGS, /* dlopen flags */
00236    cmds,       /* module's exported functions */
00237    params,     /* module's exported parameters */
00238 #ifdef STATISTICS
00239    msilo_stats,
00240 #else
00241    0,          /* exported statistics */
00242 #endif
00243    0,          /* exported MI functions */
00244    0,          /* exported pseudo-variables */
00245    0,          /* extra processes */
00246    mod_init,   /* module initialization function */
00247    0,        /* response handler */
00248    (destroy_function) destroy,  /* module destroy function */
00249    child_init  /* per-child init function */
00250 };
00251 
00252 /**
00253  * init module function
00254  */
00255 static int mod_init(void)
00256 {
00257    pv_spec_t avp_spec;
00258 
00259    ms_db_url.len = strlen (ms_db_url.s);
00260    ms_db_table.len = strlen (ms_db_table.s);
00261    sc_mid.len = strlen(sc_mid.s);
00262    sc_from.len = strlen(sc_from.s);
00263    sc_to.len = strlen(sc_to.s);
00264    sc_uri_user.len = strlen(sc_uri_user.s);
00265    sc_uri_host.len = strlen(sc_uri_host.s);
00266    sc_body.len = strlen(sc_body.s);
00267    sc_ctype.len = strlen(sc_ctype.s);
00268    sc_exp_time.len = strlen(sc_exp_time.s);
00269    sc_inc_time.len = strlen(sc_inc_time.s);
00270    sc_snd_time.len = strlen(sc_snd_time.s);
00271    if (ms_snd_time_avp_param.s)
00272       ms_snd_time_avp_param.len = strlen(ms_snd_time_avp_param.s);
00273 
00274    /* binding to mysql module  */
00275    if (db_bind_mod(&ms_db_url, &msilo_dbf))
00276    {
00277       LM_DBG("database module not found\n");
00278       return -1;
00279    }
00280 
00281    if (!DB_CAPABILITY(msilo_dbf, DB_CAP_ALL)) {
00282       LM_ERR("database module does not implement "
00283           "all functions needed by the module\n");
00284       return -1;
00285    }
00286 
00287    if (ms_snd_time_avp_param.s && ms_snd_time_avp_param.len > 0) {
00288       if (pv_parse_spec(&ms_snd_time_avp_param, &avp_spec)==0
00289             || avp_spec.type!=PVT_AVP) {
00290          LM_ERR("malformed or non AVP %.*s AVP definition\n",
00291                ms_snd_time_avp_param.len, ms_snd_time_avp_param.s);
00292          return -1;
00293       }
00294 
00295       if(pv_get_avp_name(0, &(avp_spec.pvp), &ms_snd_time_avp_name,
00296                &ms_snd_time_avp_type)!=0)
00297       {
00298          LM_ERR("[%.*s]- invalid AVP definition\n",
00299                ms_snd_time_avp_param.len, ms_snd_time_avp_param.s);
00300          return -1;
00301       }
00302    }
00303 
00304    db_con = msilo_dbf.init(&ms_db_url);
00305    if (!db_con)
00306    {
00307       LM_ERR("failed to connect to the database\n");
00308       return -1;
00309    }
00310 
00311    if(db_check_table_version(&msilo_dbf, db_con, &ms_db_table, S_TABLE_VERSION) < 0) {
00312       LM_ERR("error during table version check.\n");
00313       return -1;
00314    }
00315    if(db_con)
00316       msilo_dbf.close(db_con);
00317    db_con = NULL;
00318 
00319    /* load the TM API */
00320    if (load_tm_api(&tmb)!=0) {
00321       LM_ERR("can't load TM API\n");
00322       return -1;
00323    }
00324 
00325    if(ms_from!=NULL)
00326    {
00327       ms_from_sp = (void**)pkg_malloc(sizeof(void*));
00328       if(ms_from_sp==NULL)
00329       {
00330          LM_ERR("no more pkg\n");
00331          return -1;
00332       }
00333       *ms_from_sp = (void*)ms_from;
00334       if(fixup_spve_null(ms_from_sp, 1)!=0)
00335       {
00336          LM_ERR("bad contact parameter\n");
00337          return -1;
00338       }
00339    }
00340    if(ms_contact!=NULL)
00341    {
00342       ms_contact_sp = (void**)pkg_malloc(sizeof(void*));
00343       if(ms_contact_sp==NULL)
00344       {
00345          LM_ERR("no more pkg\n");
00346          return -1;
00347       }
00348       *ms_contact_sp = (void*)ms_contact;
00349       if(fixup_spve_null(ms_contact_sp, 1)!=0)
00350       {
00351          LM_ERR("bad contact parameter\n");
00352          return -1;
00353       }
00354    }
00355    if(ms_content_type!=NULL)
00356    {
00357       ms_content_type_sp = (void**)pkg_malloc(sizeof(void*));
00358       if(ms_content_type_sp==NULL)
00359       {
00360          LM_ERR("no more pkg\n");
00361          return -1;
00362       }
00363       *ms_content_type_sp = (void*)ms_content_type;
00364       if(fixup_spve_null(ms_content_type_sp, 1)!=0)
00365       {
00366          LM_ERR("bad content_type parameter\n");
00367          return -1;
00368       }
00369    }
00370    if(ms_offline_message!=NULL)
00371    {
00372       ms_offline_message_sp = (void**)pkg_malloc(sizeof(void*));
00373       if(ms_offline_message_sp==NULL)
00374       {
00375          LM_ERR("no more pkg\n");
00376          return -1;
00377       }
00378       *ms_offline_message_sp = (void*)ms_offline_message;
00379       if(fixup_spve_null(ms_offline_message_sp, 1)!=0)
00380       {
00381          LM_ERR("bad offline_message parameter\n");
00382          return -1;
00383       }
00384    }
00385    if(ms_offline_message!=NULL && ms_content_type==NULL)
00386    {
00387       LM_ERR("content_type parameter must be set\n");
00388       return -1;
00389    }
00390 
00391    ml = msg_list_init();
00392    if(ml==NULL)
00393    {
00394       LM_ERR("can't initialize msg list\n");
00395       return -1;
00396    }
00397    if(ms_check_time<0)
00398    {
00399       LM_ERR("bad check time value\n");
00400       return -1;
00401    }
00402    register_timer(m_clean_silo, 0, ms_check_time);
00403    if(ms_send_time>0 && ms_reminder.s!=NULL)
00404       register_timer(m_send_ontimer, 0, ms_send_time);
00405 
00406    if(ms_reminder.s!=NULL)
00407       ms_reminder.len = strlen(ms_reminder.s);
00408    if(ms_outbound_proxy.s!=NULL)
00409       ms_outbound_proxy.len = strlen(ms_outbound_proxy.s);
00410 
00411    return 0;
00412 }
00413 
00414 /**
00415  * Initialize children
00416  */
00417 static int child_init(int rank)
00418 {
00419    LM_DBG("rank #%d / pid <%d>\n", rank, getpid());
00420    if (msilo_dbf.init==0)
00421    {
00422       LM_CRIT("database not bound\n");
00423       return -1;
00424    }
00425    db_con = msilo_dbf.init(&ms_db_url);
00426    if (!db_con)
00427    {
00428       LM_ERR("child %d: failed to connect database\n", rank);
00429       return -1;
00430    }
00431    else
00432    {
00433       if (msilo_dbf.use_table(db_con, &ms_db_table) < 0) {
00434          LM_ERR("child %d: failed in use_table\n", rank);
00435          return -1;
00436       }
00437       
00438       LM_DBG("#%d database connection opened successfully\n", rank);
00439    }
00440    return 0;
00441 }
00442 
00443 /**
00444  * store message
00445  * mode = "0" -- look for outgoing URI starting with new_uri
00446  *       = "1" -- look for outgoing URI starting with r-uri
00447  *       = "2" -- look for outgoing URI only at to header
00448  */
00449 
00450 static int m_store(struct sip_msg* msg, char* owner, char* s2)
00451 {
00452    str body, str_hdr, ctaddr;
00453    struct to_body to, *pto, *pfrom;
00454    struct sip_uri puri;
00455    str duri, owner_s;
00456    db_key_t db_keys[NR_KEYS-1];
00457    db_val_t db_vals[NR_KEYS-1];
00458    db_key_t db_cols[1]; 
00459    db_res_t* res = NULL;
00460    
00461    int nr_keys = 0, val, lexpire;
00462    content_type_t ctype;
00463 #define MS_BUF1_SIZE 1024
00464    static char ms_buf1[MS_BUF1_SIZE];
00465    int mime;
00466    str notify_from;
00467    str notify_body;
00468    str notify_ctype;
00469    str notify_contact;
00470 
00471    int_str        avp_value;
00472    struct usr_avp *avp;
00473 
00474    LM_DBG("------------ start ------------\n");
00475 
00476    /* get message body - after that whole SIP MESSAGE is parsed */
00477    body.s = get_body( msg );
00478    if (body.s==0) 
00479    {
00480       LM_ERR("cannot extract body from msg\n");
00481       goto error;
00482    }
00483    
00484    /* content-length (if present) must be already parsed */
00485    if (!msg->content_length) 
00486    {
00487       LM_ERR("no Content-Length header found!\n");
00488       goto error;
00489    }
00490    body.len = get_content_length( msg );
00491 
00492    /* check if the body of message contains something */
00493    if(body.len <= 0)
00494    {
00495       LM_ERR("body of the message is empty!\n");
00496       goto error;
00497    }
00498    
00499    /* get TO URI */
00500    if(!msg->to || !msg->to->body.s)
00501    {
00502        LM_ERR("cannot find 'to' header!\n");
00503        goto error;
00504    }
00505    
00506    if(msg->to->parsed != NULL)
00507    {
00508       pto = (struct to_body*)msg->to->parsed;
00509       LM_DBG("the 'To' header ALREADY PARSED: <%.*s>\n",
00510          pto->uri.len, pto->uri.s );   
00511    }
00512    else
00513    {
00514       LM_DBG("the 'To' header NOT PARSED ->parsing ...\n");
00515       memset( &to , 0, sizeof(to) );
00516       parse_to(msg->to->body.s, msg->to->body.s+msg->to->body.len+1, &to);
00517       if(to.uri.len > 0) /* && to.error == PARSE_OK) */
00518       {
00519          LM_DBG("'To' parsed OK <%.*s>.\n", to.uri.len, to.uri.s);
00520          pto = &to;
00521       }
00522       else
00523       {
00524          LM_ERR("'To' cannot be parsed\n");
00525          goto error;
00526       }
00527    }
00528    
00529    /* get the owner */
00530    memset(&puri, 0, sizeof(struct sip_uri));
00531    if(owner)
00532    {
00533       if(fixup_get_svalue(msg, (gparam_p)owner, &owner_s)!=0)
00534       {
00535          LM_ERR("invalid owner uri parameter");
00536          return -1;
00537       }
00538       if(parse_uri(owner_s.s, owner_s.len, &puri)!=0)
00539       {
00540          LM_ERR("bad owner SIP address!\n");
00541          goto error;
00542       } else {
00543          LM_DBG("using user id [%.*s]\n", owner_s.len, owner_s.s);
00544       }
00545    } else { /* get it from R-URI */
00546       if(msg->new_uri.len <= 0)
00547       {
00548          if(msg->first_line.u.request.uri.len <= 0)
00549          {
00550             LM_ERR("bad dst URI!\n");
00551             goto error;
00552          }
00553          duri = msg->first_line.u.request.uri;
00554       } else {
00555          duri = msg->new_uri;
00556       }
00557       LM_DBG("NEW R-URI found - check if is AoR!\n");
00558       if(parse_uri(duri.s, duri.len, &puri)!=0)
00559       {
00560          LM_ERR("bad dst R-URI!!\n");
00561          goto error;
00562       }
00563    }
00564    if(puri.user.len<=0)
00565    {
00566       LM_ERR("no username for owner\n");
00567       goto error;
00568    }
00569    
00570    db_keys[nr_keys] = &sc_uri_user;
00571    
00572    db_vals[nr_keys].type = DB_STR;
00573    db_vals[nr_keys].nul = 0;
00574    db_vals[nr_keys].val.str_val.s = puri.user.s;
00575    db_vals[nr_keys].val.str_val.len = puri.user.len;
00576 
00577    nr_keys++;
00578 
00579    db_keys[nr_keys] = &sc_uri_host;
00580    
00581    db_vals[nr_keys].type = DB_STR;
00582    db_vals[nr_keys].nul = 0;
00583    db_vals[nr_keys].val.str_val.s = puri.host.s;
00584    db_vals[nr_keys].val.str_val.len = puri.host.len;
00585 
00586    nr_keys++;
00587 
00588    if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
00589    {
00590       LM_ERR("failed to use_table\n");
00591       goto error;
00592    }
00593 
00594    if (ms_max_messages > 0) {
00595        db_cols[0] = &sc_inc_time;
00596        if (msilo_dbf.query(db_con, db_keys, 0, db_vals, db_cols,
00597             2, 1, 0, &res) < 0 ) {
00598          LM_ERR("failed to query the database\n");
00599          return -1;
00600        }
00601        if (RES_ROW_N(res) >= ms_max_messages) {
00602          LM_ERR("too many messages for AoR '%.*s@%.*s'\n",
00603              puri.user.len, puri.user.s, puri.host.len, puri.host.s);
00604            msilo_dbf.free_result(db_con, res);
00605       return -1;
00606        }
00607        msilo_dbf.free_result(db_con, res);
00608    }
00609 
00610    /* Set To key */
00611    db_keys[nr_keys] = &sc_to;
00612    
00613    db_vals[nr_keys].type = DB_STR;
00614    db_vals[nr_keys].nul = 0;
00615    db_vals[nr_keys].val.str_val.s = pto->uri.s;
00616    db_vals[nr_keys].val.str_val.len = pto->uri.len;
00617 
00618    nr_keys++;
00619 
00620    /* check FROM URI */
00621    if(!msg->from || !msg->from->body.s)
00622    {
00623       LM_ERR("cannot find 'from' header!\n");
00624       goto error;
00625    }
00626 
00627    if(msg->from->parsed == NULL)
00628    {
00629       LM_DBG("'From' header not parsed\n");
00630       /* parsing from header */
00631       if ( parse_from_header( msg )<0 ) 
00632       {
00633          LM_ERR("cannot parse From header\n");
00634          goto error;
00635       }
00636    }
00637    pfrom = (struct to_body*)msg->from->parsed;
00638    LM_DBG("'From' header: <%.*s>\n", pfrom->uri.len, pfrom->uri.s);  
00639    
00640    db_keys[nr_keys] = &sc_from;
00641    
00642    db_vals[nr_keys].type = DB_STR;
00643    db_vals[nr_keys].nul = 0;
00644    db_vals[nr_keys].val.str_val.s = pfrom->uri.s;
00645    db_vals[nr_keys].val.str_val.len = pfrom->uri.len;
00646 
00647    nr_keys++;
00648 
00649    /* add the message's body in SQL query */
00650    
00651    db_keys[nr_keys] = &sc_body;
00652    
00653    db_vals[nr_keys].type = DB_BLOB;
00654    db_vals[nr_keys].nul = 0;
00655    db_vals[nr_keys].val.blob_val.s = body.s;
00656    db_vals[nr_keys].val.blob_val.len = body.len;
00657 
00658    nr_keys++;
00659    
00660    lexpire = ms_expire_time;
00661    /* add 'content-type' -- parse the content-type header */
00662    if ((mime=parse_content_type_hdr(msg))<1 ) 
00663    {
00664       LM_ERR("cannot parse Content-Type header\n");
00665       goto error;
00666    }
00667 
00668    db_keys[nr_keys]      = &sc_ctype;
00669    db_vals[nr_keys].type = DB_STR;
00670    db_vals[nr_keys].nul  = 0;
00671    db_vals[nr_keys].val.str_val.s   = "text/plain";
00672    db_vals[nr_keys].val.str_val.len = 10;
00673    
00674    /** check the content-type value */
00675    if( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
00676       && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM )
00677    {
00678       if(m_extract_content_type(msg->content_type->body.s, 
00679             msg->content_type->body.len, &ctype, CT_TYPE) != -1)
00680       {
00681          LM_DBG("'content-type' found\n");
00682          db_vals[nr_keys].val.str_val.s   = ctype.type.s;
00683          db_vals[nr_keys].val.str_val.len = ctype.type.len;
00684       }
00685    }
00686    nr_keys++;
00687 
00688    /* check 'expires' -- no more parsing - already done by get_body() */
00689    if(msg->expires && msg->expires->body.len > 0)
00690    {
00691       LM_DBG("'expires' found\n");
00692       val = atoi(msg->expires->body.s);
00693       if(val > 0)
00694          lexpire = (ms_expire_time<=val)?ms_expire_time:val;
00695    }
00696 
00697    /* current time */
00698    val = (int)time(NULL);
00699    
00700    /* add expiration time */
00701    db_keys[nr_keys] = &sc_exp_time;
00702    db_vals[nr_keys].type = DB_INT;
00703    db_vals[nr_keys].nul = 0;
00704    db_vals[nr_keys].val.int_val = val+lexpire;
00705    nr_keys++;
00706 
00707    /* add incoming time */
00708    db_keys[nr_keys] = &sc_inc_time;
00709    db_vals[nr_keys].type = DB_INT;
00710    db_vals[nr_keys].nul = 0;
00711    db_vals[nr_keys].val.int_val = val;
00712    nr_keys++;
00713 
00714    /* add sending time */
00715    db_keys[nr_keys] = &sc_snd_time;
00716    db_vals[nr_keys].type = DB_INT;
00717    db_vals[nr_keys].nul = 0;
00718    db_vals[nr_keys].val.int_val = 0;
00719    if(ms_snd_time_avp_name.n!=0)
00720    {
00721       avp = NULL;
00722       avp=search_first_avp(ms_snd_time_avp_type, ms_snd_time_avp_name,
00723             &avp_value, 0);
00724       if(avp!=NULL && is_avp_str_val(avp))
00725       {
00726          if(ms_extract_time(&avp_value.s, &db_vals[nr_keys].val.int_val)!=0)
00727             db_vals[nr_keys].val.int_val = 0;
00728       }
00729    }
00730    nr_keys++;
00731 
00732    if(msilo_dbf.insert(db_con, db_keys, db_vals, nr_keys) < 0)
00733    {
00734       LM_ERR("failed to store message\n");
00735       goto error;
00736    }
00737    LM_DBG("message stored. T:<%.*s> F:<%.*s>\n",
00738       pto->uri.len, pto->uri.s, pfrom->uri.len, pfrom->uri.s);
00739    
00740 #ifdef STATISTICS
00741    update_stat(ms_stored_msgs, 1);
00742 #endif
00743 
00744    if(ms_from==NULL || ms_offline_message == NULL)
00745       goto done;
00746 
00747    LM_DBG("sending info message.\n");
00748    if(fixup_get_svalue(msg, (gparam_p)*ms_from_sp, &notify_from)!=0
00749          || notify_from.len<=0)
00750    {
00751       LM_WARN("cannot get notification From address\n");
00752       goto done;
00753    }
00754    if(fixup_get_svalue(msg, (gparam_p)*ms_offline_message_sp, &notify_body)!=0
00755          || notify_body.len<=0)
00756    {
00757       LM_WARN("cannot get notification body\n");
00758       goto done;
00759    }
00760    if(fixup_get_svalue(msg, (gparam_p)*ms_content_type_sp, &notify_ctype)!=0
00761          || notify_ctype.len<=0)
00762    {
00763       LM_WARN("cannot get notification content type\n");
00764       goto done;
00765    }
00766 
00767    if(ms_contact!=NULL && fixup_get_svalue(msg, (gparam_p)*ms_contact_sp,
00768             &notify_contact)==0 && notify_contact.len>0)
00769    {
00770       if(notify_contact.len+notify_ctype.len>=MS_BUF1_SIZE)
00771       {
00772          LM_WARN("insufficient buffer to build notification headers\n");
00773          goto done;
00774       }
00775       memcpy(ms_buf1, notify_contact.s, notify_contact.len);
00776       memcpy(ms_buf1+notify_contact.len, notify_ctype.s, notify_ctype.len);
00777       str_hdr.s = ms_buf1;
00778       str_hdr.len = notify_contact.len + notify_ctype.len;
00779    } else {
00780       str_hdr = notify_ctype;
00781    }
00782 
00783    /* look for Contact header -- must be parsed by now*/
00784    ctaddr.s = NULL;
00785    if(ms_use_contact && msg->contact!=NULL && msg->contact->body.s!=NULL
00786          && msg->contact->body.len > 0)
00787    {
00788       LM_DBG("contact header found\n");
00789       if((msg->contact->parsed!=NULL 
00790          && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL)
00791          || (parse_contact(msg->contact)==0
00792          && msg->contact->parsed!=NULL
00793          && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL))
00794       {
00795          LM_DBG("using contact header for info msg\n");
00796          ctaddr.s = 
00797          ((contact_body_t*)(msg->contact->parsed))->contacts->uri.s;
00798          ctaddr.len =
00799          ((contact_body_t*)(msg->contact->parsed))->contacts->uri.len;
00800       
00801          if(!ctaddr.s || ctaddr.len < 6 || strncmp(ctaddr.s, "sip:", 4)
00802             || ctaddr.s[4]==' ')
00803             ctaddr.s = NULL;
00804          else
00805             LM_DBG("feedback contact [%.*s]\n", ctaddr.len,ctaddr.s);
00806       }
00807    }
00808       
00809    tmb.t_request(&msg_type,  /* Type of the message */
00810          (ctaddr.s)?&ctaddr:&pfrom->uri,    /* Request-URI */
00811          &pfrom->uri,      /* To */
00812          &notify_from,     /* From */
00813          &str_hdr,         /* Optional headers including CRLF */
00814          &notify_body,     /* Message body */
00815          (ms_outbound_proxy.s)?&ms_outbound_proxy:0, /* outbound uri */
00816          NULL,             /* Callback function */
00817          NULL              /* Callback parameter */
00818       );
00819 
00820 done:
00821    return 1;
00822 error:
00823    return -1;
00824 }
00825 
00826 /**
00827  * dump message
00828  */
00829 static int m_dump(struct sip_msg* msg, char* owner, char* str2)
00830 {
00831    struct to_body to, *pto = NULL;
00832    db_key_t db_keys[3];
00833    db_key_t ob_key;
00834    db_op_t  db_ops[3];
00835    db_val_t db_vals[3];
00836    db_key_t db_cols[6];
00837    db_res_t* db_res = NULL;
00838    int i, db_no_cols = 6, db_no_keys = 3, mid, n;
00839    static char hdr_buf[1024];
00840    static char body_buf[1024];
00841    struct sip_uri puri;
00842    str owner_s;
00843 
00844    str str_vals[4], hdr_str , body_str;
00845    time_t rtime;
00846    
00847    /* init */
00848    ob_key = &sc_mid;
00849 
00850    db_keys[0]=&sc_uri_user;
00851    db_keys[1]=&sc_uri_host;
00852    db_keys[2]=&sc_snd_time;
00853    db_ops[0]=OP_EQ;
00854    db_ops[1]=OP_EQ;
00855    db_ops[2]=OP_EQ;
00856 
00857    db_cols[0]=&sc_mid;
00858    db_cols[1]=&sc_from;
00859    db_cols[2]=&sc_to;
00860    db_cols[3]=&sc_body;
00861    db_cols[4]=&sc_ctype;
00862    db_cols[5]=&sc_inc_time;
00863 
00864    
00865    LM_DBG("------------ start ------------\n");
00866    hdr_str.s=hdr_buf;
00867    hdr_str.len=1024;
00868    body_str.s=body_buf;
00869    body_str.len=1024;
00870    
00871    /* check for TO header */
00872    if(msg->to==NULL && (parse_headers(msg, HDR_TO_F, 0)==-1
00873             || msg->to==NULL || msg->to->body.s==NULL))
00874    {
00875       LM_ERR("cannot find TO HEADER!\n");
00876       goto error;
00877    }
00878 
00879    /* get TO header URI */
00880    if(msg->to->parsed != NULL)
00881    {
00882       pto = (struct to_body*)msg->to->parsed;
00883       LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",
00884          pto->uri.len, pto->uri.s );   
00885    }
00886    else
00887    {
00888       memset( &to , 0, sizeof(to) );
00889       parse_to(msg->to->body.s,
00890          msg->to->body.s + msg->to->body.len + 1, &to);
00891       if(to.uri.len <= 0) /* || to.error != PARSE_OK) */
00892       {
00893          LM_ERR("'To' header NOT parsed\n");
00894          goto error;
00895       }
00896       pto = &to;
00897    }
00898 
00899    /**
00900     * check if has expires=0 (REGISTER)
00901     */
00902    if(parse_headers(msg, HDR_EXPIRES_F, 0) >= 0)
00903    {
00904       /* check 'expires' > 0 */
00905       if(msg->expires && msg->expires->body.len > 0)
00906       {
00907          i = atoi(msg->expires->body.s);
00908          if(i <= 0)
00909          { /* user goes offline */
00910             LM_DBG("user <%.*s> goes offline - expires=%d\n",
00911                   pto->uri.len, pto->uri.s, i);
00912             goto error;
00913          }
00914          else
00915             LM_DBG("user <%.*s> online - expires=%d\n",
00916                   pto->uri.len, pto->uri.s, i);
00917       }
00918    }
00919    else
00920    {
00921       LM_ERR("failed to parse 'expires'\n");
00922       goto error;
00923    }
00924 
00925    if (check_message_support(msg)!=0) {
00926        LM_DBG("MESSAGE method not supported\n");
00927        return -1;
00928    }
00929     
00930    /* get the owner */
00931    memset(&puri, 0, sizeof(struct sip_uri));
00932    if(owner)
00933    {
00934       if(fixup_get_svalue(msg, (gparam_p)owner, &owner_s)!=0)
00935       {
00936          LM_ERR("invalid owner uri parameter");
00937          return -1;
00938       }
00939       if(parse_uri(owner_s.s, owner_s.len, &puri)!=0)
00940       {
00941          LM_ERR("bad owner SIP address!\n");
00942          goto error;
00943       } else {
00944          LM_DBG("using user id [%.*s]\n", owner_s.len, owner_s.s);
00945       }
00946    } else { /* get it from  To URI */
00947       if(parse_uri(pto->uri.s, pto->uri.len, &puri)!=0)
00948       {
00949          LM_ERR("bad owner To URI!\n");
00950          goto error;
00951       }
00952    }
00953    if(puri.user.len<=0 || puri.user.s==NULL
00954          || puri.host.len<=0 || puri.host.s==NULL)
00955    {
00956       LM_ERR("bad owner URI!\n");
00957       goto error;
00958    }
00959 
00960    db_vals[0].type = DB_STR;
00961    db_vals[0].nul = 0;
00962    db_vals[0].val.str_val.s = puri.user.s;
00963    db_vals[0].val.str_val.len = puri.user.len;
00964 
00965    db_vals[1].type = DB_STR;
00966    db_vals[1].nul = 0;
00967    db_vals[1].val.str_val.s = puri.host.s;
00968    db_vals[1].val.str_val.len = puri.host.len;
00969 
00970    db_vals[2].type = DB_INT;
00971    db_vals[2].nul = 0;
00972    db_vals[2].val.int_val = 0;
00973    
00974    if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
00975    {
00976       LM_ERR("failed to use_table\n");
00977       goto error;
00978    }
00979 
00980    if((msilo_dbf.query(db_con,db_keys,db_ops,db_vals,db_cols,db_no_keys,
00981             db_no_cols, ob_key, &db_res)!=0) || (RES_ROW_N(db_res) <= 0))
00982    {
00983       LM_DBG("no stored message for <%.*s>!\n", pto->uri.len,  pto->uri.s);
00984       goto done;
00985    }
00986       
00987    LM_DBG("dumping [%d] messages for <%.*s>!!!\n", 
00988          RES_ROW_N(db_res), pto->uri.len, pto->uri.s);
00989 
00990    for(i = 0; i < RES_ROW_N(db_res); i++) 
00991    {
00992       mid =  RES_ROWS(db_res)[i].values[0].val.int_val;
00993       if(msg_list_check_msg(ml, mid))
00994       {
00995          LM_DBG("message[%d] mid=%d already sent.\n", i, mid);
00996          continue;
00997       }
00998       
00999       memset(str_vals, 0, 4*sizeof(str));
01000       SET_STR_VAL(str_vals[0], db_res, i, 1); /* from */
01001       SET_STR_VAL(str_vals[1], db_res, i, 2); /* to */
01002       SET_STR_VAL(str_vals[2], db_res, i, 3); /* body */
01003       SET_STR_VAL(str_vals[3], db_res, i, 4); /* ctype */
01004       rtime = 
01005          (time_t)RES_ROWS(db_res)[i].values[5/*inc time*/].val.int_val;
01006 
01007       hdr_str.len = 1024;
01008       if(m_build_headers(&hdr_str, str_vals[3] /*ctype*/,
01009             str_vals[0]/*from*/, rtime /*Date*/) < 0)
01010       {
01011          LM_ERR("headers building failed [%d]\n", mid);
01012          if (msilo_dbf.free_result(db_con, db_res) < 0)
01013             LM_ERR("failed to free the query result\n");
01014          msg_list_set_flag(ml, mid, MS_MSG_ERRO);
01015          goto error;
01016       }
01017          
01018       LM_DBG("msg [%d-%d] for: %.*s\n", i+1, mid,  pto->uri.len, pto->uri.s);
01019          
01020       /** sending using TM function: t_uac */
01021       body_str.len = 1024;
01022       n = m_build_body(&body_str, rtime, str_vals[2/*body*/], 0);
01023       if(n<0)
01024          LM_DBG("sending simple body\n");
01025       else
01026          LM_DBG("sending composed body\n");
01027       
01028          tmb.t_request(&msg_type,  /* Type of the message */
01029                &str_vals[1],     /* Request-URI (To) */
01030                &str_vals[1],     /* To */
01031                &str_vals[0],     /* From */
01032                &hdr_str,         /* Optional headers including CRLF */
01033                (n<0)?&str_vals[2]:&body_str, /* Message body */
01034                (ms_outbound_proxy.s)?&ms_outbound_proxy:0,
01035                            /* outbound uri */
01036                m_tm_callback,    /* Callback function */
01037                (void*)(long)mid  /* Callback parameter */
01038             );
01039    }
01040 
01041 done:
01042    /**
01043     * Free the result because we don't need it
01044     * anymore
01045     */
01046    if (db_res!=NULL && msilo_dbf.free_result(db_con, db_res) < 0)
01047       LM_ERR("failed to free result of query\n");
01048 
01049    return 1;
01050 error:
01051    return -1;
01052 }
01053 
01054 /**
01055  * - cleaning up the messages that got reply
01056  * - delete expired messages from database
01057  */
01058 void m_clean_silo(unsigned int ticks, void *param)
01059 {
01060    msg_list_el mle = NULL, p;
01061    db_key_t db_keys[MAX_DEL_KEYS];
01062    db_val_t db_vals[MAX_DEL_KEYS];
01063    db_op_t  db_ops[1] = { OP_LEQ };
01064    int n;
01065    
01066    LM_DBG("cleaning stored messages - %d\n", ticks);
01067    
01068    msg_list_check(ml);
01069    mle = p = msg_list_reset(ml);
01070    n = 0;
01071    while(p)
01072    {
01073       if(p->flag & MS_MSG_DONE)
01074       {
01075 #ifdef STATISTICS
01076          if(p->flag & MS_MSG_TSND)
01077             update_stat(ms_dumped_msgs, 1);
01078          else
01079             update_stat(ms_dumped_rmds, 1);
01080 #endif
01081 
01082          db_keys[n] = &sc_mid;
01083          db_vals[n].type = DB_INT;
01084          db_vals[n].nul = 0;
01085          db_vals[n].val.int_val = p->msgid;
01086          LM_DBG("cleaning sent message [%d]\n", p->msgid);
01087          n++;
01088          if(n==MAX_DEL_KEYS)
01089          {
01090             if (msilo_dbf.delete(db_con, db_keys, NULL, db_vals, n) < 0) 
01091                LM_ERR("failed to clean %d messages.\n",n);
01092             n = 0;
01093          }
01094       }
01095       if((p->flag & MS_MSG_ERRO) && (p->flag & MS_MSG_TSND))
01096       { /* set snd time to 0 */
01097          ms_reset_stime(p->msgid);
01098 #ifdef STATISTICS
01099          update_stat(ms_failed_rmds, 1);
01100 #endif
01101 
01102       }
01103 #ifdef STATISTICS
01104       if((p->flag & MS_MSG_ERRO) && !(p->flag & MS_MSG_TSND))
01105          update_stat(ms_failed_msgs, 1);
01106 #endif
01107       p = p->next;
01108    }
01109    if(n>0)
01110    {
01111       if (msilo_dbf.delete(db_con, db_keys, NULL, db_vals, n) < 0) 
01112          LM_ERR("failed to clean %d messages\n", n);
01113       n = 0;
01114    }
01115 
01116    msg_list_el_free_all(mle);
01117    
01118    /* cleaning expired messages */
01119    if(ticks%(ms_check_time*ms_clean_period)<ms_check_time)
01120    {
01121       LM_DBG("cleaning expired messages\n");
01122       db_keys[0] = &sc_exp_time;
01123       db_vals[0].type = DB_INT;
01124       db_vals[0].nul = 0;
01125       db_vals[0].val.int_val = (int)time(NULL);
01126       if (msilo_dbf.delete(db_con, db_keys, db_ops, db_vals, 1) < 0) 
01127          LM_DBG("ERROR cleaning expired messages\n");
01128    }
01129 }
01130 
01131 
01132 /**
01133  * destroy function
01134  */
01135 void destroy(void)
01136 {
01137    msg_list_free(ml);
01138 
01139    if(db_con && msilo_dbf.close)
01140       msilo_dbf.close(db_con);
01141 }
01142 
01143 /** 
01144  * TM callback function - delete message from database if was sent OK
01145  */
01146 void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
01147 {
01148    if(ps->param==NULL || *ps->param==0)
01149    {
01150       LM_DBG("message id not received\n");
01151       goto done;
01152    }
01153    
01154    LM_DBG("completed with status %d [mid: %ld/%d]\n",
01155       ps->code, (long)ps->param, *((int*)ps->param));
01156    if(!db_con)
01157    {
01158       LM_ERR("db_con is NULL\n");
01159       goto done;
01160    }
01161    if(ps->code >= 300)
01162    {
01163       LM_DBG("message <%d> was not sent successfully\n", *((int*)ps->param));
01164       msg_list_set_flag(ml, *((int*)ps->param), MS_MSG_ERRO);
01165       goto done;
01166    }
01167 
01168    LM_DBG("message <%d> was sent successfully\n", *((int*)ps->param));
01169    msg_list_set_flag(ml, *((int*)ps->param), MS_MSG_DONE);
01170 
01171 done:
01172    return;
01173 }
01174 
01175 void m_send_ontimer(unsigned int ticks, void *param)
01176 {
01177    db_key_t db_keys[2];
01178    db_op_t  db_ops[2];
01179    db_val_t db_vals[2];
01180    db_key_t db_cols[6];
01181    db_res_t* db_res = NULL;
01182    int i, db_no_cols = 6, db_no_keys = 2, mid, n;
01183    static char hdr_buf[1024];
01184    static char uri_buf[1024];
01185    static char body_buf[1024];
01186    str puri;
01187    time_t ttime;
01188    
01189    str str_vals[4], hdr_str , body_str;
01190    time_t stime;
01191 
01192    if(ms_reminder.s==NULL)
01193    {
01194       LM_WARN("reminder address null\n");
01195       return;
01196    }
01197    
01198    /* init */
01199    db_keys[0]=&sc_snd_time;
01200    db_keys[1]=&sc_snd_time;
01201    db_ops[0]=OP_NEQ;
01202    db_ops[1]=OP_LEQ;
01203 
01204    db_cols[0]=&sc_mid;
01205    db_cols[1]=&sc_uri_user;
01206    db_cols[2]=&sc_uri_host;
01207    db_cols[3]=&sc_body;
01208    db_cols[4]=&sc_ctype;
01209    db_cols[5]=&sc_snd_time;
01210 
01211    
01212    LM_DBG("------------ start ------------\n");
01213    hdr_str.s=hdr_buf;
01214    hdr_str.len=1024;
01215    body_str.s=body_buf;
01216    body_str.len=1024;
01217    
01218    db_vals[0].type = DB_INT;
01219    db_vals[0].nul = 0;
01220    db_vals[0].val.int_val = 0;
01221    
01222    db_vals[1].type = DB_INT;
01223    db_vals[1].nul = 0;
01224    ttime = time(NULL);
01225    db_vals[1].val.int_val = (int)ttime;
01226    
01227    if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
01228    {
01229       LM_ERR("failed to use_table\n");
01230       return;
01231    }
01232 
01233    if((msilo_dbf.query(db_con,db_keys,db_ops,db_vals,db_cols,db_no_keys,
01234             db_no_cols, NULL,&db_res)!=0) || (RES_ROW_N(db_res) <= 0))
01235    {
01236       LM_DBG("no message for <%.*s>!\n", 24, ctime((const time_t*)&ttime));
01237       goto done;
01238    }
01239       
01240    LM_DBG("dumping [%d] messages for <%.*s>!!!\n", RES_ROW_N(db_res), 24,
01241          ctime((const time_t*)&ttime));
01242 
01243    for(i = 0; i < RES_ROW_N(db_res); i++) 
01244    {
01245       mid =  RES_ROWS(db_res)[i].values[0].val.int_val;
01246       if(msg_list_check_msg(ml, mid))
01247       {
01248          LM_DBG("message[%d] mid=%d already sent.\n", i, mid);
01249          continue;
01250       }
01251       
01252       memset(str_vals, 0, 4*sizeof(str));
01253       SET_STR_VAL(str_vals[0], db_res, i, 1); /* user */
01254       SET_STR_VAL(str_vals[1], db_res, i, 2); /* host */
01255       SET_STR_VAL(str_vals[2], db_res, i, 3); /* body */
01256       SET_STR_VAL(str_vals[3], db_res, i, 4); /* ctype */
01257 
01258       hdr_str.len = 1024;
01259       if(m_build_headers(&hdr_str, str_vals[3] /*ctype*/,
01260             ms_reminder/*from*/,0/*Date*/) < 0)
01261       {
01262          LM_ERR("headers building failed [%d]\n", mid);
01263          if (msilo_dbf.free_result(db_con, db_res) < 0)
01264             LM_DBG("failed to free result of query\n");
01265          msg_list_set_flag(ml, mid, MS_MSG_ERRO);
01266          return;
01267       }
01268 
01269       puri.s = uri_buf;
01270       puri.len = 4 + str_vals[0].len + 1 + str_vals[1].len;
01271       memcpy(puri.s, "sip:", 4);
01272       memcpy(puri.s+4, str_vals[0].s, str_vals[0].len);
01273       puri.s[4+str_vals[0].len] = '@';
01274       memcpy(puri.s+4+str_vals[0].len+1, str_vals[1].s, str_vals[1].len);
01275       
01276       LM_DBG("msg [%d-%d] for: %.*s\n", i+1, mid,  puri.len, puri.s);
01277          
01278       /** sending using TM function: t_uac */
01279       body_str.len = 1024;
01280       stime = 
01281          (time_t)RES_ROWS(db_res)[i].values[5/*snd time*/].val.int_val;
01282       n = m_build_body(&body_str, 0, str_vals[2/*body*/], stime);
01283       if(n<0)
01284          LM_DBG("sending simple body\n");
01285       else
01286          LM_DBG("sending composed body\n");
01287       
01288       msg_list_set_flag(ml, mid, MS_MSG_TSND);
01289       
01290       tmb.t_request(&msg_type,  /* Type of the message */
01291                &puri,            /* Request-URI */
01292                &puri,            /* To */
01293                &ms_reminder,     /* From */
01294                &hdr_str,         /* Optional headers including CRLF */
01295                (n<0)?&str_vals[2]:&body_str, /* Message body */
01296                (ms_outbound_proxy.s)?&ms_outbound_proxy:0,
01297                      /* outbound uri */
01298                m_tm_callback,    /* Callback function */
01299                (void*)(long)mid  /* Callback parameter */
01300             );
01301    }
01302 
01303 done:
01304    /**
01305     * Free the result because we don't need it anymore
01306     */
01307    if (db_res!=NULL && msilo_dbf.free_result(db_con, db_res) < 0)
01308       LM_DBG("failed to free result of query\n");
01309 
01310    return;
01311 }
01312 
01313 int ms_reset_stime(int mid)
01314 {
01315    db_key_t db_keys[1];
01316    db_op_t  db_ops[1];
01317    db_val_t db_vals[1];
01318    db_key_t db_cols[1];
01319    db_val_t db_cvals[1];
01320    
01321    db_keys[0]=&sc_mid;
01322    db_ops[0]=OP_EQ;
01323 
01324    db_vals[0].type = DB_INT;
01325    db_vals[0].nul = 0;
01326    db_vals[0].val.int_val = mid;
01327    
01328 
01329    db_cols[0]=&sc_snd_time;
01330    db_cvals[0].type = DB_INT;
01331    db_cvals[0].nul = 0;
01332    db_cvals[0].val.int_val = 0;
01333    
01334    LM_DBG("updating send time for [%d]!\n", mid);
01335    
01336    if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
01337    {
01338       LM_ERR("failed to use_table\n");
01339       return -1;
01340    }
01341 
01342    if(msilo_dbf.update(db_con,db_keys,db_ops,db_vals,db_cols,db_cvals,1,1)!=0)
01343    {
01344       LM_ERR("failed to make update for [%d]!\n",  mid);
01345       return -1;
01346    }
01347    return 0;
01348 }
01349 
01350 /*
01351  * Check if REGISTER request has contacts that support MESSAGE method or
01352  * if MESSAGE method is listed in Allow header and contact does not have 
01353  * methods parameter.
01354  */
01355 int check_message_support(struct sip_msg* msg)
01356 {
01357    contact_t* c;
01358    unsigned int allow_message = 0;
01359    unsigned int allow_hdr = 0;
01360    str *methods_body;
01361    unsigned int methods;
01362 
01363    /* Parse all headers in order to see all Allow headers */
01364    if (parse_headers(msg, HDR_EOH_F, 0) == -1)
01365    {
01366       LM_ERR("failed to parse headers\n");
01367       return -1;
01368    }
01369 
01370    if (parse_allow(msg) == 0)
01371    {
01372       allow_hdr = 1;
01373       allow_message = get_allow_methods(msg) & METHOD_MESSAGE;
01374    }
01375    LM_DBG("Allow message: %u\n", allow_message);
01376 
01377    if (!msg->contact)
01378    {
01379       LM_ERR("no Contact found\n");
01380       return -1;
01381    }
01382    if (parse_contact(msg->contact) < 0)
01383    {
01384       LM_ERR("failed to parse Contact HF\n");
01385       return -1;
01386    }
01387    if (((contact_body_t*)msg->contact->parsed)->star)
01388    {
01389       LM_DBG("* Contact found\n");
01390       return -1;
01391    }
01392 
01393    if (contact_iterator(&c, msg, 0) < 0)
01394       return -1;
01395 
01396    /* 
01397     * Check contacts for MESSAGE method in methods parameter list
01398     * If contact does not have methods parameter, use Allow header methods,
01399     * if any.  Stop if MESSAGE method is found.
01400     */
01401    while(c)
01402    {
01403       if (c->methods)
01404       {
01405          methods_body = &(c->methods->body);
01406          if (parse_methods(methods_body, &methods) < 0)
01407          {
01408             LM_ERR("failed to parse contact methods\n");
01409             return -1;
01410          }
01411          if (methods & METHOD_MESSAGE)
01412          {
01413             LM_DBG("MESSAGE contact found\n");
01414             return 0;
01415          }
01416       } else {
01417          if (allow_message)
01418          {
01419             LM_DBG("MESSAGE found in Allow Header\n");
01420             return 0;
01421          }
01422       }
01423       if (contact_iterator(&c, msg, c) < 0)
01424       {
01425          LM_DBG("MESSAGE contact not found\n");
01426          return -1;
01427       }
01428    }
01429    /* no Allow header and no methods in Contact => dump MESSAGEs */
01430    if(allow_hdr==0)
01431       return 0;
01432    return -1;
01433 }
01434 

Generated on Wed May 23 20:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6