📄 msilo.c
字号:
/* * $Id: msilo.c,v 1.12 2006/05/07 20:48:52 miconda Exp $ * * MSILO module * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * History * ------- * * 2003-01-23: switched from t_uac to t_uac_dlg (dcm) * 2003-02-28: protocolization of t_uac_dlg completed (jiri) * 2003-03-11: updated to the new module interface (andrei) * removed non-constant initializers to some strs (andrei) * 2003-03-16: flags parameter added (janakj) * 2003-04-05: default_uri #define used (jiri) * 2003-04-06: db_init removed from mod_init, will be called from child_init * now (janakj) * 2003-04-07: m_dump takes a parameter which sets the way the outgoing URI * is computed (dcm) * 2003-08-05 adapted to the new parse_content_type_hdr function (bogdan) * 2004-06-07 updated to the new DB api (andrei) */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/ipc.h>#include <unistd.h>#include <fcntl.h>#include <time.h>#include "../../sr_module.h"#include "../../dprint.h"#include "../../ut.h"#include "../../timer.h"#include "../../mem/shm_mem.h"#include "../../db/db.h"#include "../../parser/parse_from.h"#include "../../parser/parse_content.h"#include "../../parser/contact/parse_contact.h"#include "../../resolve.h"#include "../../usr_avp.h"#include "../tm/tm_load.h"#define CONTACT_PREFIX "Content-Type: text/plain"CRLF"Contact: <"#define CONTACT_SUFFIX ">;msilo=yes"CRLF#define CONTACT_PREFIX_LEN (sizeof(CONTACT_PREFIX)-1)#define CONTACT_SUFFIX_LEN (sizeof(CONTACT_SUFFIX)-1)#define OFFLINE_MESSAGE "] is offline. The message will be delivered when user goes online."#define OFFLINE_MESSAGE_LEN (sizeof(OFFLINE_MESSAGE)-1)#include "ms_msg_list.h"#include "msfuncs.h"#define MAX_DEL_KEYS 1 #define NR_KEYS 10char *sc_mid = "mid"; /* 0 */char *sc_from = "src_addr"; /* 1 */char *sc_to = "dst_addr"; /* 2 */char *sc_uri_user = "username"; /* 3 */char *sc_uri_host = "domain"; /* 4 */char *sc_body = "body"; /* 5 */char *sc_ctype = "ctype"; /* 6 */char *sc_exp_time = "exp_time"; /* 7 */char *sc_inc_time = "inc_time"; /* 8 */char *sc_snd_time = "snd_time"; /* 9 */#define SET_STR_VAL(_str, _res, _r, _c) \ if (RES_ROWS(_res)[_r].values[_c].nul == 0) \ { \ switch(RES_ROWS(_res)[_r].values[_c].type) \ { \ case DB_STRING: \ (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.string_val; \ (_str).len=strlen((_str).s); \ break; \ case DB_STR: \ (_str).len=RES_ROWS(_res)[_r].values[_c].val.str_val.len; \ (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.str_val.s; \ break; \ case DB_BLOB: \ (_str).len=RES_ROWS(_res)[_r].values[_c].val.blob_val.len; \ (_str).s=(char*)RES_ROWS(_res)[_r].values[_c].val.blob_val.s; \ break; \ default: \ (_str).len=0; \ (_str).s=NULL; \ } \ }MODULE_VERSION#define S_TABLE_VERSION 4/** database connection */static db_con_t *db_con = NULL;static db_func_t msilo_dbf;/** precessed msg list - used for dumping the messages */msg_list ml = NULL;/** TM bind */struct tm_binds tmb;/** parameters */char *ms_db_url=DEFAULT_DB_URL;char *ms_db_table="silo";str ms_registrar={NULL, 0}; /*"sip:registrar@example.org";*/str ms_reminder={NULL, 0};int ms_expire_time=259200;int ms_check_time=60;int ms_send_time=0;int ms_clean_period=10;int ms_use_contact=1;int ms_userid_avp=0;int ms_snd_time_avp = 0;str msg_type = { "MESSAGE", 7 };str reg_addr;/** module functions */static int mod_init(void);static int child_init(int);static int m_store(struct sip_msg*, char*, char*);static int m_store_1(struct sip_msg*, char*, char*);static int m_store_2(struct sip_msg*, char*, char*);static int m_dump(struct sip_msg*, char*, char*);void destroy(void);void m_clean_silo(unsigned int ticks, void *);void m_send_ontimer(unsigned int ticks, void *);int ms_reset_stime(int mid);/** TM callback function */static void m_tm_callback( struct cell *t, int type, struct tmcb_params *ps);static cmd_export_t cmds[]={ {"m_store", m_store_1, 1, 0, REQUEST_ROUTE | FAILURE_ROUTE}, {"m_store", m_store_2, 2, 0, REQUEST_ROUTE | FAILURE_ROUTE}, {"m_dump", m_dump, 0, 0, REQUEST_ROUTE}, {0,0,0,0,0}};static param_export_t params[]={ { "db_url", STR_PARAM, &ms_db_url }, { "db_table", STR_PARAM, &ms_db_table }, { "registrar", STR_PARAM, &ms_registrar.s }, { "reminder", STR_PARAM, &ms_reminder.s }, { "expire_time", INT_PARAM, &ms_expire_time }, { "check_time", INT_PARAM, &ms_check_time }, { "send_time", INT_PARAM, &ms_send_time }, { "clean_period", INT_PARAM, &ms_clean_period }, { "use_contact", INT_PARAM, &ms_use_contact }, { "sc_mid", STR_PARAM, &sc_mid }, { "sc_from", STR_PARAM, &sc_from }, { "sc_to", STR_PARAM, &sc_to }, { "sc_uri_user", STR_PARAM, &sc_uri_user }, { "sc_uri_host", STR_PARAM, &sc_uri_host }, { "sc_body", STR_PARAM, &sc_body }, { "sc_ctype", STR_PARAM, &sc_ctype }, { "sc_exp_time", STR_PARAM, &sc_exp_time }, { "sc_inc_time", STR_PARAM, &sc_inc_time }, { "sc_snd_time", STR_PARAM, &sc_snd_time }, { "userid_avp", INT_PARAM, &ms_userid_avp }, { "snd_time_avp", INT_PARAM, &ms_snd_time_avp }, { 0,0,0 }};#ifdef STATISTICS#include "../../statistics.h"stat_var* ms_stored_msgs;stat_var* ms_dumped_msgs;stat_var* ms_failed_msgs;stat_var* ms_dumped_rmds;stat_var* ms_failed_rmds;stat_export_t msilo_stats[] = { {"stored_messages" , 0, &ms_stored_msgs }, {"dumped_messages" , 0, &ms_dumped_msgs }, {"failed_messages" , 0, &ms_failed_msgs }, {"dumped_reminders" , 0, &ms_dumped_rmds }, {"failed_reminders" , 0, &ms_failed_rmds }, {0,0,0}};#endif/** module exports */struct module_exports exports= { "msilo", /* module id */ cmds, /* module's exported functions */ params, /* module's exported parameters */#ifdef STATISTICS msilo_stats,#else 0, /* exported statistics */#endif mod_init, /* module initialization function */ (response_function) 0, /* response handler */ (destroy_function) destroy, /* module destroy function */ child_init /* per-child init function */};/** * init module function */static int mod_init(void){ str _s; int ver = 0; DBG("MSILO: initializing ...\n"); /* binding to mysql module */ if (bind_dbmod(ms_db_url, &msilo_dbf)) { DBG("MSILO: ERROR: Database module not found\n"); return -1; } if (!DB_CAPABILITY(msilo_dbf, DB_CAP_ALL)) { LOG(L_ERR, "MSILO: ERROR: Database module does not implement " "all functions needed by the module\n"); return -1; } db_con = msilo_dbf.init(ms_db_url); if (!db_con) { LOG(L_ERR,"MSILO:mod_init: Error while connecting database\n"); return -1; } _s.s = ms_db_table; _s.len = strlen(ms_db_table); ver = table_version(&msilo_dbf, db_con, &_s); if(ver!=S_TABLE_VERSION) { LOG(L_ERR,"MSILO:mod_init: Wrong version v%d for table <%s>," " need v%d\n", ver, ms_db_table, S_TABLE_VERSION); return -1; } if(db_con) msilo_dbf.close(db_con); db_con = NULL; /* load the TM API */ if (load_tm_api(&tmb)!=0) { LOG(L_ERR, "ERROR:msilo:mod_init: can't load TM API\n"); return -1; } ml = msg_list_init(); if(ml==NULL) { DBG("ERROR: msilo: mod_init: can't initialize msg list\n"); return -1; } if(ms_check_time<0) { DBG("ERROR: msilo: mod_init: bad check time value\n"); return -1; } register_timer(m_clean_silo, 0, ms_check_time); if(ms_send_time>0 && ms_reminder.s!=NULL) register_timer(m_send_ontimer, 0, ms_send_time); if(ms_registrar.s!=NULL) ms_registrar.len = strlen(ms_registrar.s); if(ms_reminder.s!=NULL) ms_reminder.len = strlen(ms_reminder.s); return 0;}/** * Initialize children */static int child_init(int rank){ DBG("MSILO: init_child #%d / pid <%d>\n", rank, getpid()); if (msilo_dbf.init==0) { LOG(L_CRIT, "BUG: msilo: child_init: database not bound\n"); return -1; } db_con = msilo_dbf.init(ms_db_url); if (!db_con) { LOG(L_ERR,"MSILO: child %d: Error while connecting database\n", rank); return -1; } else { if (msilo_dbf.use_table(db_con, ms_db_table) < 0) { LOG(L_ERR, "MSILO: child %d: Error in use_table\n", rank); return -1; } DBG("MSILO: child %d: Database connection opened successfully\n", rank); } return 0;}/** * store message * mode = "0" -- look for outgoing URI starting with new_uri * = "1" -- look for outgoing URI starting with r-uri * = "2" -- look for outgoing URI only at to header */static int m_store_1(struct sip_msg* msg, char* mode, char* str2){ return m_store(msg, mode, NULL);}static int m_store_2(struct sip_msg* msg, char* mode, char* flags){ return m_store(msg, mode, flags);}static int m_store(struct sip_msg* msg, char* mode, char* flags){ str body, str_hdr, ctaddr; struct to_body to, *pto, *pfrom; struct sip_uri puri; db_key_t db_keys[NR_KEYS-1]; db_val_t db_vals[NR_KEYS-1]; int nr_keys = 0, val, lexpire; content_type_t ctype; static char buf[512]; static char buf1[1024]; int mime; int_str avp_name; int_str avp_value; struct usr_avp *avp; DBG("MSILO: m_store: ------------ start ------------\n"); /* get message body - after that whole SIP MESSAGE is parsed */ body.s = get_body( msg ); if (body.s==0) { LOG(L_ERR,"MSILO:m_store: ERROR cannot extract body from msg\n"); goto error; } /* content-length (if present) must be already parsed */ if (!msg->content_length) { LOG(L_ERR,"MSILO:m_store: ERROR no Content-Length header found!\n"); goto error; } body.len = get_content_length( msg ); /* check if the body of message contains something */ if(body.len <= 0) { DBG("MSILO:m_store: body of the message is empty!\n"); goto error; } /* get TO URI */ if(!msg->to || !msg->to->body.s) { DBG("MSILO:m_store: cannot find 'to' header!\n"); goto error; } if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; DBG("MSILO:m_store: 'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len, pto->uri.s ); } else { DBG("MSILO:m_store: 'To' header NOT PARSED ->parsing ...\n"); memset( &to , 0, sizeof(to) ); parse_to(msg->to->body.s, msg->to->body.s+msg->to->body.len+1, &to); if(to.uri.len > 0) /* && to.error == PARSE_OK) */ { DBG("MSILO:m_store: 'To' parsed OK <%.*s>.\n", to.uri.len, to.uri.s); pto = &to; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -