00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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");
00076 static str sc_from = str_init("src_addr");
00077 static str sc_to = str_init("dst_addr");
00078 static str sc_uri_user = str_init("username");
00079 static str sc_uri_host = str_init("domain");
00080 static str sc_body = str_init("body");
00081 static str sc_ctype = str_init("ctype");
00082 static str sc_exp_time = str_init("exp_time");
00083 static str sc_inc_time = str_init("inc_time");
00084 static str sc_snd_time = str_init("snd_time");
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
00114 static db_con_t *db_con = NULL;
00115 static db_func_t msilo_dbf;
00116
00117
00118 msg_list ml = NULL;
00119
00120
00121 struct tm_binds tmb;
00122
00123
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;
00131 char* ms_contact = NULL;
00132 char* ms_content_type = NULL;
00133 char* ms_offline_message = NULL;
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
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
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
00233 struct module_exports exports= {
00234 "msilo",
00235 DEFAULT_DLFLAGS,
00236 cmds,
00237 params,
00238 #ifdef STATISTICS
00239 msilo_stats,
00240 #else
00241 0,
00242 #endif
00243 0,
00244 0,
00245 0,
00246 mod_init,
00247 0,
00248 (destroy_function) destroy,
00249 child_init
00250 };
00251
00252
00253
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
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
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
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
00445
00446
00447
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
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
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
00493 if(body.len <= 0)
00494 {
00495 LM_ERR("body of the message is empty!\n");
00496 goto error;
00497 }
00498
00499
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)
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
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 {
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
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
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
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
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
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
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
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
00698 val = (int)time(NULL);
00699
00700
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
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
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, ¬ify_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, ¬ify_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, ¬ify_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 ¬ify_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
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,
00810 (ctaddr.s)?&ctaddr:&pfrom->uri,
00811 &pfrom->uri,
00812 ¬ify_from,
00813 &str_hdr,
00814 ¬ify_body,
00815 (ms_outbound_proxy.s)?&ms_outbound_proxy:0,
00816 NULL,
00817 NULL
00818 );
00819
00820 done:
00821 return 1;
00822 error:
00823 return -1;
00824 }
00825
00826
00827
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
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
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
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)
00892 {
00893 LM_ERR("'To' header NOT parsed\n");
00894 goto error;
00895 }
00896 pto = &to;
00897 }
00898
00899
00900
00901
00902 if(parse_headers(msg, HDR_EXPIRES_F, 0) >= 0)
00903 {
00904
00905 if(msg->expires && msg->expires->body.len > 0)
00906 {
00907 i = atoi(msg->expires->body.s);
00908 if(i <= 0)
00909 {
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
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 {
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);
01001 SET_STR_VAL(str_vals[1], db_res, i, 2);
01002 SET_STR_VAL(str_vals[2], db_res, i, 3);
01003 SET_STR_VAL(str_vals[3], db_res, i, 4);
01004 rtime =
01005 (time_t)RES_ROWS(db_res)[i].values[5].val.int_val;
01006
01007 hdr_str.len = 1024;
01008 if(m_build_headers(&hdr_str, str_vals[3] ,
01009 str_vals[0], rtime ) < 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
01021 body_str.len = 1024;
01022 n = m_build_body(&body_str, rtime, str_vals[2], 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,
01029 &str_vals[1],
01030 &str_vals[1],
01031 &str_vals[0],
01032 &hdr_str,
01033 (n<0)?&str_vals[2]:&body_str,
01034 (ms_outbound_proxy.s)?&ms_outbound_proxy:0,
01035
01036 m_tm_callback,
01037 (void*)(long)mid
01038 );
01039 }
01040
01041 done:
01042
01043
01044
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
01056
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 {
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
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
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
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
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);
01254 SET_STR_VAL(str_vals[1], db_res, i, 2);
01255 SET_STR_VAL(str_vals[2], db_res, i, 3);
01256 SET_STR_VAL(str_vals[3], db_res, i, 4);
01257
01258 hdr_str.len = 1024;
01259 if(m_build_headers(&hdr_str, str_vals[3] ,
01260 ms_reminder,0) < 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
01279 body_str.len = 1024;
01280 stime =
01281 (time_t)RES_ROWS(db_res)[i].values[5].val.int_val;
01282 n = m_build_body(&body_str, 0, str_vals[2], 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,
01291 &puri,
01292 &puri,
01293 &ms_reminder,
01294 &hdr_str,
01295 (n<0)?&str_vals[2]:&body_str,
01296 (ms_outbound_proxy.s)?&ms_outbound_proxy:0,
01297
01298 m_tm_callback,
01299 (void*)(long)mid
01300 );
01301 }
01302
01303 done:
01304
01305
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
01352
01353
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
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
01398
01399
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
01430 if(allow_hdr==0)
01431 return 0;
01432 return -1;
01433 }
01434