modules_k/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 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  * 2011-10-19 added storage of extra SIP headers (hpw)
00042  * 2011-12-07 added storage of extra SIP headers from AVP (jh)
00043  */
00044 
00045 #include <stdio.h>
00046 #include <string.h>
00047 #include <stdlib.h>
00048 #include <sys/types.h>
00049 #include <sys/ipc.h>
00050 #include <unistd.h>
00051 #include <fcntl.h>
00052 #include <time.h>
00053 
00054 #include "../../sr_module.h"
00055 #include "../../dprint.h"
00056 #include "../../ut.h"
00057 #include "../../timer.h"
00058 #include "../../mem/shm_mem.h"
00059 #include "../../lib/srdb1/db.h"
00060 #include "../../parser/parse_from.h"
00061 #include "../../parser/parse_content.h"
00062 #include "../../parser/contact/parse_contact.h"
00063 #include "../../parser/parse_allow.h"
00064 #include "../../parser/parse_methods.h"
00065 #include "../../resolve.h"
00066 #include "../../usr_avp.h"
00067 #include "../../mod_fix.h"
00068 
00069 #include "../../modules/tm/tm_load.h"
00070 
00071 #include "ms_msg_list.h"
00072 #include "msfuncs.h"
00073 #include "api.h"
00074 
00075 #define MAX_DEL_KEYS    1       
00076 #define NR_KEYS                 11
00077 
00078 static str sc_mid         = str_init("id");         /*  0 */
00079 static str sc_from        = str_init("src_addr");   /*  1 */
00080 static str sc_to          = str_init("dst_addr");   /*  2 */
00081 static str sc_uri_user    = str_init("username");   /*  3 */
00082 static str sc_uri_host    = str_init("domain");     /*  4 */
00083 static str sc_body        = str_init("body");       /*  5 */
00084 static str sc_ctype       = str_init("ctype");      /*  6 */
00085 static str sc_exp_time    = str_init("exp_time");   /*  7 */
00086 static str sc_inc_time    = str_init("inc_time");   /*  8 */
00087 static str sc_snd_time    = str_init("snd_time");   /*  9 */
00088 static str sc_stored_hdrs = str_init("extra_hdrs"); /* 10 */
00089 
00090 #define SET_STR_VAL(_str, _res, _r, _c) \
00091         if (RES_ROWS(_res)[_r].values[_c].nul == 0) \
00092         { \
00093                 switch(RES_ROWS(_res)[_r].values[_c].type) \
00094                 { \
00095                 case DB1_STRING: \
00096                         (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.string_val; \
00097                         (_str).len=strlen((_str).s); \
00098                         break; \
00099                 case DB1_STR: \
00100                         (_str).len=RES_ROWS(_res)[_r].values[_c].val.str_val.len; \
00101                         (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.str_val.s; \
00102                         break; \
00103                 case DB1_BLOB: \
00104                         (_str).len=RES_ROWS(_res)[_r].values[_c].val.blob_val.len; \
00105                         (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.blob_val.s; \
00106                         break; \
00107                 default: \
00108                         (_str).len=0; \
00109                         (_str).s=NULL; \
00110                 } \
00111         }
00112 
00113 MODULE_VERSION
00114 
00115 #define S_TABLE_VERSION 7
00116 
00118 static db1_con_t *db_con = NULL;
00119 static db_func_t msilo_dbf;
00120 
00122 msg_list ml = NULL;
00123 
00125 struct tm_binds tmb;
00126 
00129 static str ms_db_url = str_init(DEFAULT_DB_URL);
00130 static str ms_db_table = str_init("silo");
00131 str  ms_reminder = {NULL, 0};
00132 str  ms_outbound_proxy = {NULL, 0};
00133 
00134 char*  ms_from = NULL; /*"sip:registrar@example.org";*/
00135 char*  ms_contact = NULL; /*"Contact: <sip:registrar@example.org>\r\n";*/
00136 char*  ms_extra_hdrs = NULL; /*"X-foo: bar\r\nX-bar: foo\r\n";*/
00137 char*  ms_content_type = NULL; /*"Content-Type: text/plain\r\n";*/
00138 char*  ms_offline_message = NULL; /*"<em>I'm offline.</em>"*/
00139 void**  ms_from_sp = NULL;
00140 void**  ms_contact_sp = NULL;
00141 void**  ms_extra_hdrs_sp = NULL;
00142 void**  ms_content_type_sp = NULL;
00143 void**  ms_offline_message_sp = NULL;
00144 
00145 int  ms_expire_time = 259200;
00146 int  ms_check_time = 60;
00147 int  ms_send_time = 0;
00148 int  ms_clean_period = 10;
00149 int  ms_use_contact = 1;
00150 int  ms_add_date = 1;
00151 int  ms_add_contact = 0;
00152 int  ms_max_messages = 0;
00153 
00154 static str ms_snd_time_avp_param = {NULL, 0};
00155 int_str ms_snd_time_avp_name;
00156 unsigned short ms_snd_time_avp_type;
00157 
00158 static str ms_extra_hdrs_avp_param = {NULL, 0};
00159 int_str ms_extra_hdrs_avp_name;
00160 unsigned short ms_extra_hdrs_avp_type;
00161 
00162 str msg_type = str_init("MESSAGE");
00163 
00165 static int mod_init(void);
00166 static int child_init(int);
00167 
00168 static int m_store(struct sip_msg*, str*);
00169 static int m_dump(struct sip_msg*, str*);
00170 
00171 static int m_store_2(struct sip_msg*, char*, char*);
00172 static int m_dump_2(struct sip_msg*, char*, char*);
00173 
00174 static void destroy(void);
00175 
00176 static int bind_msilo(msilo_api_t* api);
00177 
00178 void m_clean_silo(unsigned int ticks, void *);
00179 void m_send_ontimer(unsigned int ticks, void *);
00180 
00181 int ms_reset_stime(int mid);
00182 
00183 int check_message_support(struct sip_msg* msg);
00184 
00185 
00187 static void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps);
00188 
00189 static cmd_export_t cmds[]={
00190         {"m_store",  (cmd_function)m_store_2, 0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00191         {"m_store",  (cmd_function)m_store_2, 1, fixup_spve_null, 0,
00192                 REQUEST_ROUTE | FAILURE_ROUTE},
00193         {"m_dump",   (cmd_function)m_dump_2,  0, 0, 0, REQUEST_ROUTE},
00194         {"m_dump",   (cmd_function)m_dump_2,  1, fixup_spve_null, 0,
00195                 REQUEST_ROUTE},
00196         {"bind_msilo",(cmd_function)bind_msilo, 1, 0, 0, ANY_ROUTE},
00197         {0,0,0,0,0,0}
00198 };
00199 
00200 
00201 static param_export_t params[]={
00202         { "db_url",           STR_PARAM, &ms_db_url.s             },
00203         { "db_table",         STR_PARAM, &ms_db_table.s           },
00204         { "from_address",     STR_PARAM, &ms_from                 },
00205         { "contact_hdr",      STR_PARAM, &ms_contact              },
00206         { "extra_hdrs",       STR_PARAM, &ms_extra_hdrs           },
00207         { "content_type_hdr", STR_PARAM, &ms_content_type         },
00208         { "offline_message",  STR_PARAM, &ms_offline_message      },
00209         { "reminder",         STR_PARAM, &ms_reminder.s           },
00210         { "outbound_proxy",   STR_PARAM, &ms_outbound_proxy.s     },
00211         { "expire_time",      INT_PARAM, &ms_expire_time          },
00212         { "check_time",       INT_PARAM, &ms_check_time           },
00213         { "send_time",        INT_PARAM, &ms_send_time            },
00214         { "clean_period",     INT_PARAM, &ms_clean_period         },
00215         { "use_contact",      INT_PARAM, &ms_use_contact          },
00216         { "sc_mid",           STR_PARAM, &sc_mid.s                },
00217         { "sc_from",          STR_PARAM, &sc_from.s               },
00218         { "sc_to",            STR_PARAM, &sc_to.s                 },
00219         { "sc_uri_user",      STR_PARAM, &sc_uri_user.s           },
00220         { "sc_uri_host",      STR_PARAM, &sc_uri_host.s           },
00221         { "sc_body",          STR_PARAM, &sc_body.s               },
00222         { "sc_ctype",         STR_PARAM, &sc_ctype.s              },
00223         { "sc_exp_time",      STR_PARAM, &sc_exp_time.s           },
00224         { "sc_inc_time",      STR_PARAM, &sc_inc_time.s           },
00225         { "sc_snd_time",      STR_PARAM, &sc_snd_time.s           },
00226         { "sc_stored_hdrs",   STR_PARAM, &sc_stored_hdrs.s        },
00227         { "snd_time_avp",     STR_PARAM, &ms_snd_time_avp_param.s },
00228         { "extra_hdrs_avp",   STR_PARAM, &ms_extra_hdrs_avp_param.s },
00229         { "add_date",         INT_PARAM, &ms_add_date             },
00230         { "max_messages",     INT_PARAM, &ms_max_messages         },
00231         { "add_contact",      INT_PARAM, &ms_add_contact          },
00232         { 0,0,0 }
00233 };
00234 
00235 #ifdef STATISTICS
00236 #include "../../lib/kcore/statistics.h"
00237 
00238 stat_var* ms_stored_msgs;
00239 stat_var* ms_dumped_msgs;
00240 stat_var* ms_failed_msgs;
00241 stat_var* ms_dumped_rmds;
00242 stat_var* ms_failed_rmds;
00243 
00244 stat_export_t msilo_stats[] = {
00245         {"stored_messages" ,  0,  &ms_stored_msgs  },
00246         {"dumped_messages" ,  0,  &ms_dumped_msgs  },
00247         {"failed_messages" ,  0,  &ms_failed_msgs  },
00248         {"dumped_reminders" , 0,  &ms_dumped_rmds  },
00249         {"failed_reminders" , 0,  &ms_failed_rmds  },
00250         {0,0,0}
00251 };
00252 
00253 #endif
00254 
00255 struct module_exports exports= {
00256         "msilo",    /* module id */
00257         DEFAULT_DLFLAGS, /* dlopen flags */
00258         cmds,       /* module's exported functions */
00259         params,     /* module's exported parameters */
00260 #ifdef STATISTICS
00261         msilo_stats,
00262 #else
00263         0,          /* exported statistics */
00264 #endif
00265         0,          /* exported MI functions */
00266         0,          /* exported pseudo-variables */
00267         0,          /* extra processes */
00268         mod_init,   /* module initialization function */
00269         0,          /* response handler */
00270         (destroy_function) destroy,  /* module destroy function */
00271         child_init  /* per-child init function */
00272 };
00273 
00274 static int bind_msilo(msilo_api_t* api)
00275 {
00276         if (!api) {
00277                 return -1;
00278         }
00279         api->m_store = m_store;
00280         api->m_dump = m_dump;
00281         return 0;
00282 }
00283 
00287 static int mod_init(void)
00288 {
00289         pv_spec_t avp_spec;
00290 
00291 #ifdef STATISTICS
00292         /* register statistics */
00293         if (register_module_stats( exports.name, msilo_stats)!=0 ) {
00294                 LM_ERR("failed to register core statistics\n");
00295                 return -1;
00296         }
00297 #endif
00298         ms_db_url.len = strlen (ms_db_url.s);
00299         ms_db_table.len = strlen (ms_db_table.s);
00300         sc_mid.len = strlen(sc_mid.s);
00301         sc_from.len = strlen(sc_from.s);
00302         sc_to.len = strlen(sc_to.s);
00303         sc_uri_user.len = strlen(sc_uri_user.s);
00304         sc_uri_host.len = strlen(sc_uri_host.s);
00305         sc_body.len = strlen(sc_body.s);
00306         sc_ctype.len = strlen(sc_ctype.s);
00307         sc_exp_time.len = strlen(sc_exp_time.s);
00308         sc_inc_time.len = strlen(sc_inc_time.s);
00309         sc_snd_time.len = strlen(sc_snd_time.s);
00310         if (ms_snd_time_avp_param.s)
00311                 ms_snd_time_avp_param.len = strlen(ms_snd_time_avp_param.s);
00312         if (ms_extra_hdrs_avp_param.s)
00313                 ms_extra_hdrs_avp_param.len = strlen(ms_extra_hdrs_avp_param.s);
00314 
00315         /* binding to mysql module  */
00316         if (db_bind_mod(&ms_db_url, &msilo_dbf))
00317         {
00318                 LM_DBG("database module not found\n");
00319                 return -1;
00320         }
00321 
00322         if (!DB_CAPABILITY(msilo_dbf, DB_CAP_ALL)) {
00323                 LM_ERR("database module does not implement "
00324                     "all functions needed by the module\n");
00325                 return -1;
00326         }
00327 
00328         if (ms_snd_time_avp_param.s && ms_snd_time_avp_param.len > 0) {
00329                 if (pv_parse_spec(&ms_snd_time_avp_param, &avp_spec)==0
00330                                 || avp_spec.type!=PVT_AVP) {
00331                         LM_ERR("malformed or non AVP %.*s AVP definition\n",
00332                                         ms_snd_time_avp_param.len, ms_snd_time_avp_param.s);
00333                         return -1;
00334                 }
00335 
00336                 if(pv_get_avp_name(0, &(avp_spec.pvp), &ms_snd_time_avp_name,
00337                                         &ms_snd_time_avp_type)!=0)
00338                 {
00339                         LM_ERR("[%.*s]- invalid AVP definition\n",
00340                                         ms_snd_time_avp_param.len, ms_snd_time_avp_param.s);
00341                         return -1;
00342                 }
00343         }
00344 
00345         if (ms_extra_hdrs_avp_param.s && ms_extra_hdrs_avp_param.len > 0) {
00346             if (pv_parse_spec(&ms_extra_hdrs_avp_param, &avp_spec)==0
00347                 || avp_spec.type!=PVT_AVP) {
00348                 LM_ERR("malformed or non AVP %.*s AVP definition\n",
00349                        ms_extra_hdrs_avp_param.len, ms_extra_hdrs_avp_param.s);
00350                 return -1;
00351             }
00352 
00353             if (pv_get_avp_name(0, &(avp_spec.pvp), &ms_extra_hdrs_avp_name,
00354                                &ms_extra_hdrs_avp_type) != 0) {
00355                 LM_ERR("[%.*s]- invalid AVP definition\n",
00356                        ms_extra_hdrs_avp_param.len, ms_extra_hdrs_avp_param.s);
00357                 return -1;
00358             }
00359         }
00360 
00361         db_con = msilo_dbf.init(&ms_db_url);
00362         if (!db_con)
00363         {
00364                 LM_ERR("failed to connect to the database\n");
00365                 return -1;
00366         }
00367 
00368         if(db_check_table_version(&msilo_dbf, db_con, &ms_db_table, S_TABLE_VERSION) < 0) {
00369                 LM_ERR("error during table version check.\n");
00370                 return -1;
00371         }
00372         if(db_con)
00373                 msilo_dbf.close(db_con);
00374         db_con = NULL;
00375 
00376         /* load the TM API */
00377         if (load_tm_api(&tmb)!=0) {
00378                 LM_ERR("can't load TM API\n");
00379                 return -1;
00380         }
00381 
00382         if(ms_from!=NULL)
00383         {
00384                 ms_from_sp = (void**)pkg_malloc(sizeof(void*));
00385                 if(ms_from_sp==NULL)
00386                 {
00387                         LM_ERR("no more pkg\n");
00388                         return -1;
00389                 }
00390                 *ms_from_sp = (void*)ms_from;
00391                 if(fixup_spve_null(ms_from_sp, 1)!=0)
00392                 {
00393                         LM_ERR("bad contact parameter\n");
00394                         return -1;
00395                 }
00396         }
00397         if(ms_contact!=NULL)
00398         {
00399                 ms_contact_sp = (void**)pkg_malloc(sizeof(void*));
00400                 if(ms_contact_sp==NULL)
00401                 {
00402                         LM_ERR("no more pkg\n");
00403                         return -1;
00404                 }
00405                 *ms_contact_sp = (void*)ms_contact;
00406                 if(fixup_spve_null(ms_contact_sp, 1)!=0)
00407                 {
00408                         LM_ERR("bad contact parameter\n");
00409                         return -1;
00410                 }
00411         }
00412         if(ms_extra_hdrs!=NULL)
00413         {
00414                 ms_extra_hdrs_sp = (void**)pkg_malloc(sizeof(void*));
00415                 if(ms_extra_hdrs_sp==NULL)
00416                 {
00417                         LM_ERR("no more pkg\n");
00418                         return -1;
00419                 }
00420                 *ms_extra_hdrs_sp = (void*)ms_extra_hdrs;
00421                 if(fixup_spve_null(ms_extra_hdrs_sp, 1)!=0)
00422                 {
00423                         LM_ERR("bad extra_hdrs parameter\n");
00424                         return -1;
00425                 }
00426         }
00427         if(ms_content_type!=NULL)
00428         {
00429                 ms_content_type_sp = (void**)pkg_malloc(sizeof(void*));
00430                 if(ms_content_type_sp==NULL)
00431                 {
00432                         LM_ERR("no more pkg\n");
00433                         return -1;
00434                 }
00435                 *ms_content_type_sp = (void*)ms_content_type;
00436                 if(fixup_spve_null(ms_content_type_sp, 1)!=0)
00437                 {
00438                         LM_ERR("bad content_type parameter\n");
00439                         return -1;
00440                 }
00441         }
00442         if(ms_offline_message!=NULL)
00443         {
00444                 ms_offline_message_sp = (void**)pkg_malloc(sizeof(void*));
00445                 if(ms_offline_message_sp==NULL)
00446                 {
00447                         LM_ERR("no more pkg\n");
00448                         return -1;
00449                 }
00450                 *ms_offline_message_sp = (void*)ms_offline_message;
00451                 if(fixup_spve_null(ms_offline_message_sp, 1)!=0)
00452                 {
00453                         LM_ERR("bad offline_message parameter\n");
00454                         return -1;
00455                 }
00456         }
00457         if(ms_offline_message!=NULL && ms_content_type==NULL)
00458         {
00459                 LM_ERR("content_type parameter must be set\n");
00460                 return -1;
00461         }
00462 
00463         ml = msg_list_init();
00464         if(ml==NULL)
00465         {
00466                 LM_ERR("can't initialize msg list\n");
00467                 return -1;
00468         }
00469         if(ms_check_time<0)
00470         {
00471                 LM_ERR("bad check time value\n");
00472                 return -1;
00473         }
00474         register_timer(m_clean_silo, 0, ms_check_time);
00475         if(ms_send_time>0 && ms_reminder.s!=NULL)
00476                 register_timer(m_send_ontimer, 0, ms_send_time);
00477 
00478         if(ms_reminder.s!=NULL)
00479                 ms_reminder.len = strlen(ms_reminder.s);
00480         if(ms_outbound_proxy.s!=NULL)
00481                 ms_outbound_proxy.len = strlen(ms_outbound_proxy.s);
00482 
00483         return 0;
00484 }
00485 
00489 static int child_init(int rank)
00490 {
00491         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00492                 return 0; /* do nothing for the main process */
00493 
00494         LM_DBG("rank #%d / pid <%d>\n", rank, getpid());
00495         if (msilo_dbf.init==0)
00496         {
00497                 LM_CRIT("database not bound\n");
00498                 return -1;
00499         }
00500         db_con = msilo_dbf.init(&ms_db_url);
00501         if (!db_con)
00502         {
00503                 LM_ERR("child %d: failed to connect database\n", rank);
00504                 return -1;
00505         }
00506         else
00507         {
00508                 if (msilo_dbf.use_table(db_con, &ms_db_table) < 0) {
00509                         LM_ERR("child %d: failed in use_table\n", rank);
00510                         return -1;
00511                 }
00512                 
00513                 LM_DBG("#%d database connection opened successfully\n", rank);
00514         }
00515         return 0;
00516 }
00517 
00525 static int get_non_mandatory_headers(struct sip_msg *msg, char *buf, int buf_len)
00526 {
00527         struct hdr_field *hdrs;
00528         int len = 0;
00529         int_str avp_value;
00530         struct usr_avp *avp;
00531 
00532         if (ms_extra_hdrs_avp_name.n != 0) {
00533             avp = NULL;
00534             avp = search_first_avp(ms_extra_hdrs_avp_type,
00535                                    ms_extra_hdrs_avp_name, &avp_value, 0);
00536             if ((avp != NULL) && is_avp_str_val(avp)) {
00537                 if (buf_len <= avp_value.s.len) {
00538                     LM_ERR("insufficient space to store headers in silo\n");
00539                     return -1;
00540                 }
00541                 memcpy(buf, avp_value.s.s, avp_value.s.len);
00542                 return avp_value.s.len;
00543             }
00544         }
00545 
00546         for (hdrs = msg->headers; hdrs != NULL; hdrs = hdrs->next)
00547         {
00548                 switch (hdrs->type) {
00549                         case HDR_OTHER_T:
00550                         case HDR_PPI_T:
00551                         case HDR_PAI_T:
00552                         case HDR_PRIVACY_T:
00553                                 if (buf_len <= hdrs->len)
00554                                 {
00555                                         LM_ERR("Insufficient space to store headers in silo\n");
00556                                         return -1;
00557                                 }
00558                                 memcpy(buf, hdrs->name.s, hdrs->len);
00559                                 len += hdrs->len;
00560                                 buf += hdrs->len;
00561                                 buf_len -= hdrs->len;
00562                                 break;
00563                         default:
00564                                 break;
00565                 }
00566         }
00567         return len;
00568 }
00569 
00577 static int m_store(struct sip_msg* msg, str *owner_s)
00578 {
00579         str body, str_hdr, ctaddr;
00580         struct to_body *pto, *pfrom;
00581         struct sip_uri puri;
00582         str duri;
00583 #define EXTRA_HDRS_BUF_LEN      1024
00584         static char extra_hdrs_buf[EXTRA_HDRS_BUF_LEN];
00585         str extra_hdrs;
00586         db_key_t db_keys[NR_KEYS-1];
00587         db_val_t db_vals[NR_KEYS-1];
00588         db_key_t db_cols[1]; 
00589         db1_res_t* res = NULL;
00590         uac_req_t uac_r;
00591         
00592         int nr_keys = 0, val, lexpire;
00593         content_type_t ctype;
00594 #define MS_BUF1_SIZE    1024
00595         static char ms_buf1[MS_BUF1_SIZE];
00596         int mime;
00597         str notify_from;
00598         str notify_body;
00599         str notify_ctype;
00600         str notify_contact;
00601 
00602         int_str        avp_value;
00603         struct usr_avp *avp;
00604 
00605         LM_DBG("------------ start ------------\n");
00606 
00607         /* get message body - after that whole SIP MESSAGE is parsed */
00608         body.s = get_body( msg );
00609         if (body.s==0) 
00610         {
00611                 LM_ERR("cannot extract body from msg\n");
00612                 goto error;
00613         }
00614         
00615         /* content-length (if present) must be already parsed */
00616         if (!msg->content_length) 
00617         {
00618                 LM_ERR("no Content-Length header found!\n");
00619                 goto error;
00620         }
00621         body.len = get_content_length( msg );
00622 
00623         /* check if the body of message contains something */
00624         if(body.len <= 0)
00625         {
00626                 LM_ERR("body of the message is empty!\n");
00627                 goto error;
00628         }
00629         
00630         /* get TO URI */
00631         if(parse_to_header(msg)<0)
00632         {
00633             LM_ERR("failed getting 'to' header!\n");
00634             goto error;
00635         }
00636         
00637         pto = get_to(msg);
00638         
00639         /* get the owner */
00640         memset(&puri, 0, sizeof(struct sip_uri));
00641         if(owner_s != NULL)
00642         {
00643                 if(parse_uri(owner_s->s, owner_s->len, &puri)!=0)
00644                 {
00645                         LM_ERR("bad owner SIP address!\n");
00646                         goto error;
00647                 } else {
00648                         LM_DBG("using user id [%.*s]\n", owner_s->len, owner_s->s);
00649                 }
00650         } else { /* get it from R-URI */
00651                 if(msg->new_uri.len <= 0)
00652                 {
00653                         if(msg->first_line.u.request.uri.len <= 0)
00654                         {
00655                                 LM_ERR("bad dst URI!\n");
00656                                 goto error;
00657                         }
00658                         duri = msg->first_line.u.request.uri;
00659                 } else {
00660                         duri = msg->new_uri;
00661                 }
00662                 LM_DBG("NEW R-URI found - check if is AoR!\n");
00663                 if(parse_uri(duri.s, duri.len, &puri)!=0)
00664                 {
00665                         LM_ERR("bad dst R-URI!!\n");
00666                         goto error;
00667                 }
00668         }
00669         if(puri.user.len<=0)
00670         {
00671                 LM_ERR("no username for owner\n");
00672                 goto error;
00673         }
00674         
00675         db_keys[nr_keys] = &sc_uri_user;
00676         
00677         db_vals[nr_keys].type = DB1_STR;
00678         db_vals[nr_keys].nul = 0;
00679         db_vals[nr_keys].val.str_val.s = puri.user.s;
00680         db_vals[nr_keys].val.str_val.len = puri.user.len;
00681 
00682         nr_keys++;
00683 
00684         db_keys[nr_keys] = &sc_uri_host;
00685         
00686         db_vals[nr_keys].type = DB1_STR;
00687         db_vals[nr_keys].nul = 0;
00688         db_vals[nr_keys].val.str_val.s = puri.host.s;
00689         db_vals[nr_keys].val.str_val.len = puri.host.len;
00690 
00691         nr_keys++;
00692 
00693         if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
00694         {
00695                 LM_ERR("failed to use_table\n");
00696                 goto error;
00697         }
00698 
00699         if (ms_max_messages > 0) {
00700             db_cols[0] = &sc_inc_time;
00701             if (msilo_dbf.query(db_con, db_keys, 0, db_vals, db_cols,
00702                                 2, 1, 0, &res) < 0 ) {
00703                         LM_ERR("failed to query the database\n");
00704                         return -1;
00705             }
00706             if (RES_ROW_N(res) >= ms_max_messages) {
00707                         LM_ERR("too many messages for AoR '%.*s@%.*s'\n",
00708                             puri.user.len, puri.user.s, puri.host.len, puri.host.s);
00709                 msilo_dbf.free_result(db_con, res);
00710                 return -1;
00711             }
00712             msilo_dbf.free_result(db_con, res);
00713         }
00714 
00715         /* Set To key */
00716         db_keys[nr_keys] = &sc_to;
00717         
00718         db_vals[nr_keys].type = DB1_STR;
00719         db_vals[nr_keys].nul = 0;
00720         db_vals[nr_keys].val.str_val.s = pto->uri.s;
00721         db_vals[nr_keys].val.str_val.len = pto->uri.len;
00722 
00723         nr_keys++;
00724 
00725         /* check FROM URI */
00726         if ( parse_from_header( msg )<0 ) 
00727         {
00728                 LM_ERR("cannot parse From header\n");
00729                 goto error;
00730         }
00731         pfrom = get_from(msg);
00732         LM_DBG("'From' header: <%.*s>\n", pfrom->uri.len, pfrom->uri.s);        
00733         
00734         db_keys[nr_keys] = &sc_from;
00735         
00736         db_vals[nr_keys].type = DB1_STR;
00737         db_vals[nr_keys].nul = 0;
00738         db_vals[nr_keys].val.str_val.s = pfrom->uri.s;
00739         db_vals[nr_keys].val.str_val.len = pfrom->uri.len;
00740 
00741         nr_keys++;
00742 
00743         /* add the message's body in SQL query */
00744 
00745         db_keys[nr_keys] = &sc_body;
00746 
00747         db_vals[nr_keys].type = DB1_BLOB;
00748         db_vals[nr_keys].nul = 0;
00749         db_vals[nr_keys].val.blob_val.s = body.s;
00750         db_vals[nr_keys].val.blob_val.len = body.len;
00751 
00752         nr_keys++;
00753 
00754         lexpire = ms_expire_time;
00755         /* add 'content-type' -- parse the content-type header */
00756         if ((mime=parse_content_type_hdr(msg))<1 ) 
00757         {
00758                 LM_ERR("cannot parse Content-Type header\n");
00759                 goto error;
00760         }
00761 
00762         db_keys[nr_keys]      = &sc_ctype;
00763         db_vals[nr_keys].type = DB1_STR;
00764         db_vals[nr_keys].nul  = 0;
00765         db_vals[nr_keys].val.str_val.s   = "text/plain";
00766         db_vals[nr_keys].val.str_val.len = 10;
00767         
00769         if( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
00770                 && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM )
00771         {
00772                 if(m_extract_content_type(msg->content_type->body.s, 
00773                                 msg->content_type->body.len, &ctype, CT_TYPE) != -1)
00774                 {
00775                         LM_DBG("'content-type' found\n");
00776                         db_vals[nr_keys].val.str_val.s   = ctype.type.s;
00777                         db_vals[nr_keys].val.str_val.len = ctype.type.len;
00778                 }
00779         }
00780         nr_keys++;
00781 
00782         /* check 'expires' -- no more parsing - already done by get_body() */
00783         if(msg->expires && msg->expires->body.len > 0)
00784         {
00785                 LM_DBG("'expires' found\n");
00786                 val = atoi(msg->expires->body.s);
00787                 if(val > 0)
00788                         lexpire = (ms_expire_time<=val)?ms_expire_time:val;
00789         }
00790 
00791         /* current time */
00792         val = (int)time(NULL);
00793 
00794         /* add expiration time */
00795         db_keys[nr_keys] = &sc_exp_time;
00796         db_vals[nr_keys].type = DB1_INT;
00797         db_vals[nr_keys].nul = 0;
00798         db_vals[nr_keys].val.int_val = val+lexpire;
00799         nr_keys++;
00800 
00801         /* add incoming time */
00802         db_keys[nr_keys] = &sc_inc_time;
00803         db_vals[nr_keys].type = DB1_INT;
00804         db_vals[nr_keys].nul = 0;
00805         db_vals[nr_keys].val.int_val = val;
00806         nr_keys++;
00807 
00808         /* add sending time */
00809         db_keys[nr_keys] = &sc_snd_time;
00810         db_vals[nr_keys].type = DB1_INT;
00811         db_vals[nr_keys].nul = 0;
00812         db_vals[nr_keys].val.int_val = 0;
00813         if(ms_snd_time_avp_name.n!=0)
00814         {
00815                 avp = NULL;
00816                 avp=search_first_avp(ms_snd_time_avp_type, ms_snd_time_avp_name,
00817                                 &avp_value, 0);
00818                 if(avp!=NULL && is_avp_str_val(avp))
00819                 {
00820                         if(ms_extract_time(&avp_value.s, &db_vals[nr_keys].val.int_val)!=0)
00821                                 db_vals[nr_keys].val.int_val = 0;
00822                 }
00823         }
00824         nr_keys++;
00825 
00826         /* add the extra headers in SQL query */
00827         extra_hdrs.s = extra_hdrs_buf;
00828         extra_hdrs.len = get_non_mandatory_headers(msg, extra_hdrs_buf, EXTRA_HDRS_BUF_LEN);
00829         if (extra_hdrs.len < 0)
00830         {
00831           goto error;
00832         }
00833 
00834         db_keys[nr_keys] = &sc_stored_hdrs;
00835 
00836         db_vals[nr_keys].type = DB1_BLOB;
00837         db_vals[nr_keys].nul = 0;
00838         db_vals[nr_keys].val.blob_val.s = extra_hdrs.s;
00839         db_vals[nr_keys].val.blob_val.len = extra_hdrs.len;
00840 
00841         nr_keys++;
00842         
00843         if(msilo_dbf.insert(db_con, db_keys, db_vals, nr_keys) < 0)
00844         {
00845                 LM_ERR("failed to store message\n");
00846                 goto error;
00847         }
00848         LM_DBG("message stored. T:<%.*s> F:<%.*s>\n",
00849                 pto->uri.len, pto->uri.s, pfrom->uri.len, pfrom->uri.s);
00850         
00851 #ifdef STATISTICS
00852         update_stat(ms_stored_msgs, 1);
00853 #endif
00854 
00855         if(ms_from==NULL || ms_offline_message == NULL)
00856                 goto done;
00857 
00858         LM_DBG("sending info message.\n");
00859         if(fixup_get_svalue(msg, (gparam_p)*ms_from_sp, &notify_from)!=0
00860                         || notify_from.len<=0)
00861         {
00862                 LM_WARN("cannot get notification From address\n");
00863                 goto done;
00864         }
00865         if(fixup_get_svalue(msg, (gparam_p)*ms_offline_message_sp, &notify_body)!=0
00866                         || notify_body.len<=0)
00867         {
00868                 LM_WARN("cannot get notification body\n");
00869                 goto done;
00870         }
00871         if(fixup_get_svalue(msg, (gparam_p)*ms_content_type_sp, &notify_ctype)!=0
00872                         || notify_ctype.len<=0)
00873         {
00874                 LM_WARN("cannot get notification content type\n");
00875                 goto done;
00876         }
00877 
00878         if(ms_contact!=NULL && fixup_get_svalue(msg, (gparam_p)*ms_contact_sp,
00879                                 &notify_contact)==0 && notify_contact.len>0)
00880         {
00881                 if(notify_contact.len+notify_ctype.len>=MS_BUF1_SIZE)
00882                 {
00883                         LM_WARN("insufficient buffer to build notification headers\n");
00884                         goto done;
00885                 }
00886                 memcpy(ms_buf1, notify_contact.s, notify_contact.len);
00887                 memcpy(ms_buf1+notify_contact.len, notify_ctype.s, notify_ctype.len);
00888                 str_hdr.s = ms_buf1;
00889                 str_hdr.len = notify_contact.len + notify_ctype.len;
00890         } else {
00891                 str_hdr = notify_ctype;
00892         }
00893 
00894         /* look for Contact header -- must be parsed by now*/
00895         ctaddr.s = NULL;
00896         if(ms_use_contact && msg->contact!=NULL && msg->contact->body.s!=NULL
00897                         && msg->contact->body.len > 0)
00898         {
00899                 LM_DBG("contact header found\n");
00900                 if((msg->contact->parsed!=NULL 
00901                         && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL)
00902                         || (parse_contact(msg->contact)==0
00903                         && msg->contact->parsed!=NULL
00904                         && ((contact_body_t*)(msg->contact->parsed))->contacts!=NULL))
00905                 {
00906                         LM_DBG("using contact header for info msg\n");
00907                         ctaddr.s = 
00908                         ((contact_body_t*)(msg->contact->parsed))->contacts->uri.s;
00909                         ctaddr.len =
00910                         ((contact_body_t*)(msg->contact->parsed))->contacts->uri.len;
00911                 
00912                         if(!ctaddr.s || ctaddr.len < 6 || strncmp(ctaddr.s, "sip:", 4)
00913                                 || ctaddr.s[4]==' ')
00914                                 ctaddr.s = NULL;
00915                         else
00916                                 LM_DBG("feedback contact [%.*s]\n",     ctaddr.len,ctaddr.s);
00917                 }
00918         }
00919                 
00920         memset(&uac_r,'\0', sizeof(uac_r));
00921         uac_r.method = &msg_type;
00922         uac_r.headers = &str_hdr;
00923         uac_r.body = &notify_body;
00924         tmb.t_request(&uac_r,  /* UAC Req */
00925                                   (ctaddr.s)?&ctaddr:&pfrom->uri,    /* Request-URI */
00926                                   &pfrom->uri,      /* To */
00927                                   &notify_from,     /* From */
00928                                   (ms_outbound_proxy.s)?&ms_outbound_proxy:0 /* outbound uri */
00929                 );
00930 
00931 done:
00932         return 1;
00933 error:
00934         return -1;
00935 }
00936 
00940 static int m_store_2(struct sip_msg* msg, char* owner, char* s2)
00941 {
00942         str owner_s;
00943         if (owner != NULL)
00944         {
00945                 if(fixup_get_svalue(msg, (gparam_p)owner, &owner_s)!=0)
00946                 {
00947                         LM_ERR("invalid owner uri parameter");
00948                         return -1;
00949                 }
00950                 return m_store(msg, &owner_s);
00951         }
00952         return m_store(msg, NULL);
00953 }
00954 
00958 static int m_dump(struct sip_msg* msg, str* owner_s)
00959 {
00960         struct to_body *pto = NULL;
00961         db_key_t db_keys[3];
00962         db_key_t ob_key;
00963         db_op_t  db_ops[3];
00964         db_val_t db_vals[3];
00965         db_key_t db_cols[7];
00966         db1_res_t* db_res = NULL;
00967         int i, db_no_cols = 7, db_no_keys = 3, mid, n;
00968         static char hdr_buf[1024];
00969         static char body_buf[1024];
00970         struct sip_uri puri;
00971         uac_req_t uac_r;
00972         str str_vals[5], hdr_str, body_str, extra_hdrs_str, tmp_extra_hdrs;
00973         time_t rtime;
00974         
00975         /* init */
00976         ob_key = &sc_mid;
00977 
00978         db_keys[0]=&sc_uri_user;
00979         db_keys[1]=&sc_uri_host;
00980         db_keys[2]=&sc_snd_time;
00981         db_ops[0]=OP_EQ;
00982         db_ops[1]=OP_EQ;
00983         db_ops[2]=OP_EQ;
00984 
00985         db_cols[0]=&sc_mid;
00986         db_cols[1]=&sc_from;
00987         db_cols[2]=&sc_to;
00988         db_cols[3]=&sc_body;
00989         db_cols[4]=&sc_ctype;
00990         db_cols[5]=&sc_inc_time;
00991         db_cols[6]=&sc_stored_hdrs;
00992 
00993         
00994         LM_DBG("------------ start ------------\n");
00995         hdr_str.s=hdr_buf;
00996         hdr_str.len=1024;
00997         body_str.s=body_buf;
00998         body_str.len=1024;
00999         
01000         /* check for TO header */
01001         if(parse_to_header(msg)<0)
01002         {
01003                 LM_ERR("failed parsing  To header\n");
01004                 goto error;
01005         }
01006 
01007         pto = get_to(msg);
01008 
01012         if(msg->first_line.u.request.method_value==METHOD_REGISTER)
01013         {
01014                 if (check_message_support(msg)!=0) {
01015                     LM_DBG("MESSAGE method not supported\n");
01016                         return -1;
01017                 }
01018         }
01019          
01020         /* get the owner */
01021         memset(&puri, 0, sizeof(struct sip_uri));
01022         if(owner_s)
01023         {
01024                 if(parse_uri(owner_s->s, owner_s->len, &puri)!=0)
01025                 {
01026                         LM_ERR("bad owner SIP address!\n");
01027                         goto error;
01028                 } else {
01029                         LM_DBG("using user id [%.*s]\n", owner_s->len, owner_s->s);
01030                 }
01031         } else { /* get it from  To URI */
01032                 if(parse_uri(pto->uri.s, pto->uri.len, &puri)!=0)
01033                 {
01034                         LM_ERR("bad owner To URI!\n");
01035                         goto error;
01036                 }
01037         }
01038         if(puri.user.len<=0 || puri.user.s==NULL
01039                         || puri.host.len<=0 || puri.host.s==NULL)
01040         {
01041                 LM_ERR("bad owner URI!\n");
01042                 goto error;
01043         }
01044 
01045         db_vals[0].type = DB1_STR;
01046         db_vals[0].nul = 0;
01047         db_vals[0].val.str_val.s = puri.user.s;
01048         db_vals[0].val.str_val.len = puri.user.len;
01049 
01050         db_vals[1].type = DB1_STR;
01051         db_vals[1].nul = 0;
01052         db_vals[1].val.str_val.s = puri.host.s;
01053         db_vals[1].val.str_val.len = puri.host.len;
01054 
01055         db_vals[2].type = DB1_INT;
01056         db_vals[2].nul = 0;
01057         db_vals[2].val.int_val = 0;
01058 
01059         if (db_con == NULL) {
01060             LM_ERR("database connection has not been established\n");
01061             goto error;
01062         }
01063 
01064         if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
01065         {
01066                 LM_ERR("failed to use_table\n");
01067                 return -1;
01068         }
01069 
01070         if (msilo_dbf.query(db_con,db_keys,db_ops,db_vals,db_cols,db_no_keys,
01071                             db_no_cols, ob_key, &db_res) < 0) {
01072             LM_ERR("failed to query database\n");
01073             goto error;
01074         }
01075 
01076         if (RES_ROW_N(db_res) <= 0) {
01077             LM_DBG("no stored message for <%.*s>!\n", pto->uri.len, pto->uri.s);
01078             goto done;
01079         }
01080                 
01081         LM_DBG("dumping [%d] messages for <%.*s>!!!\n", 
01082                RES_ROW_N(db_res), pto->uri.len, pto->uri.s);
01083 
01084         for(i = 0; i < RES_ROW_N(db_res); i++) 
01085         {
01086                 mid =  RES_ROWS(db_res)[i].values[0].val.int_val;
01087                 if(msg_list_check_msg(ml, mid))
01088                 {
01089                         LM_DBG("message[%d] mid=%d already sent.\n", i, mid);
01090                         continue;
01091                 }
01092                 
01093                 memset(str_vals, 0, 5*sizeof(str));
01094                 SET_STR_VAL(str_vals[0], db_res, i, 1); /* from */
01095                 SET_STR_VAL(str_vals[1], db_res, i, 2); /* to */
01096                 SET_STR_VAL(str_vals[2], db_res, i, 3); /* body */
01097                 SET_STR_VAL(str_vals[3], db_res, i, 4); /* ctype */
01098                 SET_STR_VAL(str_vals[4], db_res, i, 6); /* stored hdrs */
01099                 rtime = 
01100                         (time_t)RES_ROWS(db_res)[i].values[5/*inc time*/].val.int_val;
01101                 
01102                 if (ms_extra_hdrs != NULL) {
01103                     if (fixup_get_svalue(msg, (gparam_p)*ms_extra_hdrs_sp,
01104                                          &extra_hdrs_str) != 0) {
01105                         if (msilo_dbf.free_result(db_con, db_res) < 0)
01106                                 LM_ERR("failed to free the query result\n");
01107                         LM_ERR("unable to get extra_hdrs value\n");
01108                         goto error;
01109                     }
01110                 } else {
01111                     extra_hdrs_str.len = 0;
01112                 }
01113 
01114                 tmp_extra_hdrs.len = extra_hdrs_str.len+str_vals[4].len;
01115                 if(tmp_extra_hdrs.len>0)
01116                 {
01117                         if ((tmp_extra_hdrs.s = pkg_malloc(tmp_extra_hdrs.len)) == NULL)
01118                         {
01119                                 LM_ERR("Out of pkg memory");
01120                                 if (msilo_dbf.free_result(db_con, db_res) < 0)
01121                                         LM_ERR("failed to free the query result\n");
01122                                 msg_list_set_flag(ml, mid, MS_MSG_ERRO);
01123                                 goto error;
01124                         }
01125                         memcpy(tmp_extra_hdrs.s, extra_hdrs_str.s, extra_hdrs_str.len);
01126                         memcpy(tmp_extra_hdrs.s+extra_hdrs_str.len, str_vals[4].s, str_vals[4].len);
01127                 } else {
01128                         tmp_extra_hdrs.len = 0;
01129                         tmp_extra_hdrs.s = "";
01130                 }
01131                 hdr_str.len = 1024;
01132                 if(m_build_headers(&hdr_str, str_vals[3] /*ctype*/,
01133                                    str_vals[0]/*from*/, rtime /*Date*/,
01134                                    tmp_extra_hdrs /*extra_hdrs*/) < 0)
01135                 {
01136                         LM_ERR("headers building failed [%d]\n", mid);
01137                         pkg_free(tmp_extra_hdrs.s);
01138                         if (msilo_dbf.free_result(db_con, db_res) < 0)
01139                                 LM_ERR("failed to free the query result\n");
01140                         msg_list_set_flag(ml, mid, MS_MSG_ERRO);
01141                         goto error;
01142                 }
01143                 pkg_free(tmp_extra_hdrs.s);
01144                         
01145                 LM_DBG("msg [%d-%d] for: %.*s\n", i+1, mid,     pto->uri.len, pto->uri.s);
01146                         
01148                 body_str.len = 1024;
01149                 /* send composed body only if content type is text/plain */
01150                 if ((str_vals[3].len == 10) &&
01151                     (strncmp(str_vals[3].s, "text/plain", 10) == 0)) {
01152                     n = m_build_body(&body_str, rtime, str_vals[2/*body*/], 0);
01153                 } else {
01154                     n = -1;
01155                 }
01156                 if(n<0)
01157                         LM_DBG("sending simple body\n");
01158                 else
01159                         LM_DBG("sending composed body\n");
01160                 
01161                 memset(&uac_r,'\0', sizeof(uac_r));
01162                 uac_r.method = &msg_type;
01163                 uac_r.headers = &hdr_str;
01164                 uac_r.body = (n<0)?&str_vals[2]:&body_str;
01165                 uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
01166                 uac_r.cb  = m_tm_callback;
01167                 uac_r.cbp = (void*)(long)mid;
01168 
01169                 tmb.t_request(&uac_r,  /* UAC Req */
01170                                           &str_vals[1],  /* Request-URI */
01171                                           &str_vals[1],  /* To */
01172                                           &str_vals[0],  /* From */
01173                                           (ms_outbound_proxy.s)?&ms_outbound_proxy:0 /* ob uri */
01174                         );
01175         }
01176 
01177 done:
01182         if ((db_res !=NULL) && msilo_dbf.free_result(db_con, db_res) < 0)
01183                 LM_ERR("failed to free result of query\n");
01184 
01185         return 1;
01186 error:
01187         return -1;
01188 }
01189 
01193 static int m_dump_2(struct sip_msg* msg, char* owner, char* s2)
01194 {
01195         str owner_s;
01196         if (owner != NULL)
01197         {
01198                 if(fixup_get_svalue(msg, (gparam_p)owner, &owner_s)!=0)
01199                 {
01200                         LM_ERR("invalid owner uri parameter");
01201                         return -1;
01202                 }
01203                 return m_dump(msg, &owner_s);
01204         }
01205         return m_dump(msg, NULL);
01206 }
01207 
01212 void m_clean_silo(unsigned int ticks, void *param)
01213 {
01214         msg_list_el mle = NULL, p;
01215         db_key_t db_keys[MAX_DEL_KEYS];
01216         db_val_t db_vals[MAX_DEL_KEYS];
01217         db_op_t  db_ops[1] = { OP_LEQ };
01218         int n;
01219         
01220         LM_DBG("cleaning stored messages - %d\n", ticks);
01221         
01222         msg_list_check(ml);
01223         mle = p = msg_list_reset(ml);
01224         n = 0;
01225         if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
01226         {
01227                 LM_ERR("failed to use_table\n");
01228                 return;
01229         }
01230         while(p)
01231         {
01232                 if(p->flag & MS_MSG_DONE)
01233                 {
01234 #ifdef STATISTICS
01235                         if(p->flag & MS_MSG_TSND)
01236                                 update_stat(ms_dumped_msgs, 1);
01237                         else
01238                                 update_stat(ms_dumped_rmds, 1);
01239 #endif
01240 
01241                         db_keys[n] = &sc_mid;
01242                         db_vals[n].type = DB1_INT;
01243                         db_vals[n].nul = 0;
01244                         db_vals[n].val.int_val = p->msgid;
01245                         LM_DBG("cleaning sent message [%d]\n", p->msgid);
01246                         n++;
01247                         if(n==MAX_DEL_KEYS)
01248                         {
01249                                 if (msilo_dbf.delete(db_con, db_keys, NULL, db_vals, n) < 0) 
01250                                         LM_ERR("failed to clean %d messages.\n",n);
01251                                 n = 0;
01252                         }
01253                 }
01254                 if((p->flag & MS_MSG_ERRO) && (p->flag & MS_MSG_TSND))
01255                 { /* set snd time to 0 */
01256                         ms_reset_stime(p->msgid);
01257 #ifdef STATISTICS
01258                         update_stat(ms_failed_rmds, 1);
01259 #endif
01260 
01261                 }
01262 #ifdef STATISTICS
01263                 if((p->flag & MS_MSG_ERRO) && !(p->flag & MS_MSG_TSND))
01264                         update_stat(ms_failed_msgs, 1);
01265 #endif
01266                 p = p->next;
01267         }
01268         if(n>0)
01269         {
01270                 if (msilo_dbf.delete(db_con, db_keys, NULL, db_vals, n) < 0) 
01271                         LM_ERR("failed to clean %d messages\n", n);
01272                 n = 0;
01273         }
01274 
01275         msg_list_el_free_all(mle);
01276         
01277         /* cleaning expired messages */
01278         if(ticks%(ms_check_time*ms_clean_period)<ms_check_time)
01279         {
01280                 LM_DBG("cleaning expired messages\n");
01281                 db_keys[0] = &sc_exp_time;
01282                 db_vals[0].type = DB1_INT;
01283                 db_vals[0].nul = 0;
01284                 db_vals[0].val.int_val = (int)time(NULL);
01285                 if (msilo_dbf.delete(db_con, db_keys, db_ops, db_vals, 1) < 0) 
01286                         LM_DBG("ERROR cleaning expired messages\n");
01287         }
01288 }
01289 
01290 
01294 static void destroy(void)
01295 {
01296         msg_list_free(ml);
01297 
01298         if(db_con && msilo_dbf.close)
01299                 msilo_dbf.close(db_con);
01300 }
01301 
01305 void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
01306 {
01307         if(ps->param==NULL || *ps->param==0)
01308         {
01309                 LM_DBG("message id not received\n");
01310                 goto done;
01311         }
01312         
01313         LM_DBG("completed with status %d [mid: %ld/%d]\n",
01314                 ps->code, (long)ps->param, *((int*)ps->param));
01315         if(!db_con)
01316         {
01317                 LM_ERR("db_con is NULL\n");
01318                 goto done;
01319         }
01320         if(ps->code >= 300)
01321         {
01322                 LM_DBG("message <%d> was not sent successfully\n", *((int*)ps->param));
01323                 msg_list_set_flag(ml, *((int*)ps->param), MS_MSG_ERRO);
01324                 goto done;
01325         }
01326 
01327         LM_DBG("message <%d> was sent successfully\n", *((int*)ps->param));
01328         msg_list_set_flag(ml, *((int*)ps->param), MS_MSG_DONE);
01329 
01330 done:
01331         return;
01332 }
01333 
01334 void m_send_ontimer(unsigned int ticks, void *param)
01335 {
01336         db_key_t db_keys[2];
01337         db_op_t  db_ops[2];
01338         db_val_t db_vals[2];
01339         db_key_t db_cols[6];
01340         db1_res_t* db_res = NULL;
01341         int i, db_no_cols = 6, db_no_keys = 2, mid, n;
01342         static char hdr_buf[1024];
01343         static char uri_buf[1024];
01344         static char body_buf[1024];
01345         str puri;
01346         time_t ttime;
01347         uac_req_t uac_r;
01348         str str_vals[4], hdr_str, body_str, extra_hdrs_str;
01349         time_t stime;
01350 
01351         if(ms_reminder.s==NULL)
01352         {
01353                 LM_WARN("reminder address null\n");
01354                 return;
01355         }
01356         
01357         /* init */
01358         db_keys[0]=&sc_snd_time;
01359         db_keys[1]=&sc_snd_time;
01360         db_ops[0]=OP_NEQ;
01361         db_ops[1]=OP_LEQ;
01362 
01363         db_cols[0]=&sc_mid;
01364         db_cols[1]=&sc_uri_user;
01365         db_cols[2]=&sc_uri_host;
01366         db_cols[3]=&sc_body;
01367         db_cols[4]=&sc_ctype;
01368         db_cols[5]=&sc_snd_time;
01369 
01370         
01371         LM_DBG("------------ start ------------\n");
01372         hdr_str.s=hdr_buf;
01373         hdr_str.len=1024;
01374         body_str.s=body_buf;
01375         body_str.len=1024;
01376         
01377         db_vals[0].type = DB1_INT;
01378         db_vals[0].nul = 0;
01379         db_vals[0].val.int_val = 0;
01380         
01381         db_vals[1].type = DB1_INT;
01382         db_vals[1].nul = 0;
01383         ttime = time(NULL);
01384         db_vals[1].val.int_val = (int)ttime;
01385         
01386         if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
01387         {
01388                 LM_ERR("failed to use_table\n");
01389                 return;
01390         }
01391 
01392         if (msilo_dbf.query(db_con,db_keys,db_ops,db_vals,db_cols,db_no_keys,
01393                             db_no_cols, NULL,&db_res) < 0) {
01394             LM_ERR("failed to query database\n");
01395             goto done;
01396         }
01397 
01398         if (RES_ROW_N(db_res) <= 0)
01399         {
01400                 LM_DBG("no message for <%.*s>!\n", 24, ctime((const time_t*)&ttime));
01401                 goto done;
01402         }
01403                 
01404         LM_DBG("dumping [%d] messages for <%.*s>!!!\n", RES_ROW_N(db_res), 24,
01405                         ctime((const time_t*)&ttime));
01406 
01407         for(i = 0; i < RES_ROW_N(db_res); i++) 
01408         {
01409                 mid =  RES_ROWS(db_res)[i].values[0].val.int_val;
01410                 if(msg_list_check_msg(ml, mid))
01411                 {
01412                         LM_DBG("message[%d] mid=%d already sent.\n", i, mid);
01413                         continue;
01414                 }
01415                 
01416                 memset(str_vals, 0, 4*sizeof(str));
01417                 SET_STR_VAL(str_vals[0], db_res, i, 1); /* user */
01418                 SET_STR_VAL(str_vals[1], db_res, i, 2); /* host */
01419                 SET_STR_VAL(str_vals[2], db_res, i, 3); /* body */
01420                 SET_STR_VAL(str_vals[3], db_res, i, 4); /* ctype */
01421 
01422                 extra_hdrs_str.len = 0;
01423                 hdr_str.len = 1024;
01424                 if(m_build_headers(&hdr_str, str_vals[3] /*ctype*/,
01425                                    ms_reminder/*from*/,0/*Date*/,
01426                                    extra_hdrs_str/*extra*/)
01427                    < 0)
01428                 {
01429                         LM_ERR("headers building failed [%d]\n", mid);
01430                         if (msilo_dbf.free_result(db_con, db_res) < 0)
01431                                 LM_DBG("failed to free result of query\n");
01432                         msg_list_set_flag(ml, mid, MS_MSG_ERRO);
01433                         return;
01434                 }
01435 
01436                 puri.s = uri_buf;
01437                 puri.len = 4 + str_vals[0].len + 1 + str_vals[1].len;
01438                 memcpy(puri.s, "sip:", 4);
01439                 memcpy(puri.s+4, str_vals[0].s, str_vals[0].len);
01440                 puri.s[4+str_vals[0].len] = '@';
01441                 memcpy(puri.s+4+str_vals[0].len+1, str_vals[1].s, str_vals[1].len);
01442                 
01443                 LM_DBG("msg [%d-%d] for: %.*s\n", i+1, mid,     puri.len, puri.s);
01444                         
01446                 body_str.len = 1024;
01447                 stime = 
01448                         (time_t)RES_ROWS(db_res)[i].values[5/*snd time*/].val.int_val;
01449                 n = m_build_body(&body_str, 0, str_vals[2/*body*/], stime);
01450                 if(n<0)
01451                         LM_DBG("sending simple body\n");
01452                 else
01453                         LM_DBG("sending composed body\n");
01454                 
01455                 msg_list_set_flag(ml, mid, MS_MSG_TSND);
01456 
01457 
01458                 memset(&uac_r, '\0', sizeof(uac_r));
01459                 uac_r.method  = &msg_type;
01460                 uac_r.headers = &hdr_str;
01461                 uac_r.body = (n<0)?&str_vals[2]:&body_str;
01462                 uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
01463                 uac_r.cb  = m_tm_callback;
01464                 uac_r.cbp = (void*)(long)mid;
01465                 tmb.t_request(&uac_r,  /* UAC Req */
01466                                           &puri,         /* Request-URI */
01467                                           &puri,         /* To */
01468                                           &ms_reminder,  /* From */
01469                                           (ms_outbound_proxy.s)?&ms_outbound_proxy:0 /* ob uri */
01470                         );
01471         }
01472 
01473 done:
01477         if ((db_res != NULL) && msilo_dbf.free_result(db_con, db_res) < 0)
01478                 LM_DBG("failed to free result of query\n");
01479 
01480         return;
01481 }
01482 
01483 int ms_reset_stime(int mid)
01484 {
01485         db_key_t db_keys[1];
01486         db_op_t  db_ops[1];
01487         db_val_t db_vals[1];
01488         db_key_t db_cols[1];
01489         db_val_t db_cvals[1];
01490         
01491         db_keys[0]=&sc_mid;
01492         db_ops[0]=OP_EQ;
01493 
01494         db_vals[0].type = DB1_INT;
01495         db_vals[0].nul = 0;
01496         db_vals[0].val.int_val = mid;
01497         
01498 
01499         db_cols[0]=&sc_snd_time;
01500         db_cvals[0].type = DB1_INT;
01501         db_cvals[0].nul = 0;
01502         db_cvals[0].val.int_val = 0;
01503         
01504         LM_DBG("updating send time for [%d]!\n", mid);
01505         
01506         if (msilo_dbf.use_table(db_con, &ms_db_table) < 0)
01507         {
01508                 LM_ERR("failed to use_table\n");
01509                 return -1;
01510         }
01511 
01512         if(msilo_dbf.update(db_con,db_keys,db_ops,db_vals,db_cols,db_cvals,1,1)!=0)
01513         {
01514                 LM_ERR("failed to make update for [%d]!\n",     mid);
01515                 return -1;
01516         }
01517         return 0;
01518 }
01519 
01520 /*
01521  * Check if REGISTER request has contacts that support MESSAGE method or
01522  * if MESSAGE method is listed in Allow header and contact does not have 
01523  * methods parameter.
01524  */
01525 int check_message_support(struct sip_msg* msg)
01526 {
01527         contact_t* c;
01528         unsigned int allow_message = 0;
01529         unsigned int allow_hdr = 0;
01530         str *methods_body;
01531         unsigned int methods;
01532         int expires;
01533 
01534         /* Parse all headers in order to see all Allow headers */
01535         if (parse_headers(msg, HDR_EOH_F, 0) == -1)
01536         {
01537                 LM_ERR("failed to parse headers\n");
01538                 return -1;
01539         }
01540 
01541         if (parse_allow(msg) == 0)
01542         {
01543                 allow_hdr = 1;
01544                 allow_message = get_allow_methods(msg) & METHOD_MESSAGE;
01545         }
01546         LM_DBG("Allow message: %u\n", allow_message);
01547 
01548         if (!msg->contact)
01549         {
01550                 LM_DBG("no Contact found\n");
01551                 return -1;
01552         }
01553         if (parse_contact(msg->contact) < 0)
01554         {
01555                 LM_ERR("failed to parse Contact HF\n");
01556                 return -1;
01557         }
01558         if (((contact_body_t*)msg->contact->parsed)->star)
01559         {
01560                 LM_DBG("* Contact found\n");
01561                 return -1;
01562         }
01563 
01564         if (contact_iterator(&c, msg, 0) < 0)
01565                 return -1;
01566 
01567         /* 
01568          * Check contacts for MESSAGE method in methods parameter list
01569          * If contact does not have methods parameter, use Allow header methods,
01570          * if any.  Stop if MESSAGE method is found.
01571          */
01572         while(c)
01573         {
01574                 /* calculate expires */
01575                 expires=1; /* 0 is explicitely set in hdr or param */
01576                 if(c->expires==NULL || c->expires->body.len<=0)
01577                 {
01578                         if(msg->expires!=NULL && msg->expires->body.len>0)
01579                                 expires = atoi(msg->expires->body.s);
01580                 } else {
01581                         str2int(&c->expires->body, (unsigned int*)(&expires));
01582                 }
01583                 /* skip contacts with zero expires */
01584                 if (expires > 0)
01585                 {
01586                         if (c->methods)
01587                         {
01588                                 methods_body = &(c->methods->body);
01589                                 if (parse_methods(methods_body, &methods) < 0)
01590                                 {
01591                                         LM_ERR("failed to parse contact methods\n");
01592                                         return -1;
01593                                 }
01594                                 if (methods & METHOD_MESSAGE)
01595                                 {
01596                                         LM_DBG("MESSAGE contact found\n");
01597                                         return 0;
01598                                 }
01599                         } else {
01600                                 if (allow_message)
01601                                 {
01602                                         LM_DBG("MESSAGE found in Allow Header\n");
01603                                         return 0;
01604                                 }
01605                         }
01606                 }
01607                 if (contact_iterator(&c, msg, c) < 0)
01608                 {
01609                         LM_DBG("MESSAGE contact not found\n");
01610                         return -1;
01611                 }
01612         }
01613         /* no Allow header and no methods in Contact => dump MESSAGEs */
01614         if(allow_hdr==0)
01615                 return 0;
01616         return -1;
01617 }
01618