⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcr_mod.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * $Id: lcr_mod.c,v 1.28 2006/05/26 12:16:23 juhe Exp $ * * Least Cost Routing module (also implements sequential forking) * * Copyright (C) 2005 Juha Heinanen * * 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: * ------- *  2005-02-14: Introduced lcr module (jh) *  2005-02-20: Added sequential forking functions (jh) *  2005-02-25: Added support for int AVP names, combined addr and port *              AVPs (jh) *  2005-07-28: Added support for gw URI scheme and transport,  *              backport from ser (kd) *  2005-08-20: Added support for gw prefixes (jh) *  2005-09-03: Request-URI user part can be modified between load_gws() *              and first next_gw() calls. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <arpa/inet.h>#include <regex.h>#include "../../sr_module.h"#include "../../dprint.h"#include "../../ut.h"#include "../../error.h"#include "../../mem/mem.h"#include "../../mem/shm_mem.h"#include "../../db/db.h"#include "../../usr_avp.h"#include "../../parser/parse_uri.h"#include "../../parser/parse_from.h"#include "../../parser/msg_parser.h"#include "../mysql/dbase.h"#include "../../action.h"#include "../../qvalue.h"#include "../../dset.h"#include "../../ip_addr.h"#include "fifo.h"MODULE_VERSION/* * Version of gw and lcr tables required by the module, * increment this value if you change the table in * an backwards incompatible way */#define GW_TABLE_VERSION 3#define LCR_TABLE_VERSION 2/* usr_avp flag for sequential forking */#define Q_FLAG      (1<<2)static void destroy(void);       /* Module destroy function */static int child_init(int rank); /* Per-child initialization function */static int mod_init(void);       /* Module initialization function */static int fixstring2int(void **param, int param_count); /* string to int fixup */int reload_gws ( void );#define GW_TABLE "gw"#define GW_NAME_COL "gw_name"#define IP_ADDR_COL "ip_addr"#define PORT_COL "port"#define URI_SCHEME_COL "uri_scheme"#define TRANSPORT_COL "transport"#define GRP_ID_COL "grp_id"#define LCR_TABLE "lcr"#define STRIP_COL "strip"#define PREFIX_COL "prefix"#define FROM_URI_COL "from_uri"#define PRIORITY_COL "priority"#define MAX_QUERY_SIZE 512#define MAX_NO_OF_GWS 32#define MAX_NO_OF_LCRS 256#define MAX_PREFIX_LEN 16#define MAX_FROM_URI_LEN 128/* Default avp names */#define DEF_GW_URI_AVP "1400"#define DEF_CONTACT_AVP "1401"#define DEF_RURI_USER_AVP "1402"#define DEF_FR_INV_TIMER_AVP "fr_inv_timer_avp"#define DEF_FR_INV_TIMER 90#define DEF_FR_INV_TIMER_NEXT 30#define DEF_RPID_AVP "rpid"#define DEF_DB_MODE 1/* * Type definitions */typedef enum sip_protos uri_transport;struct gw_info {    unsigned int ip_addr;    unsigned int port;    unsigned int grp_id;    uri_type scheme;    uri_transport transport;    unsigned int strip;    char prefix[MAX_PREFIX_LEN];    unsigned short prefix_len;};struct lcr_info {    char prefix[MAX_PREFIX_LEN];    unsigned short prefix_len;    char from_uri[MAX_FROM_URI_LEN + 1];    unsigned short from_uri_len;    unsigned int grp_id;    unsigned short priority;    unsigned short end_record;};struct from_uri_regex {    regex_t re;    short int valid;};struct mi {    unsigned int gw_index;    unsigned int route_index;    int randomizer;};/* * Database variables */static db_con_t* db_handle = 0;   /* Database connection handle */static db_func_t lcr_dbf;/* * Module parameter variables */static str db_url    = str_init(DEFAULT_RODB_URL);str gw_table         = str_init(GW_TABLE);str gw_name_col      = str_init(GW_NAME_COL);str ip_addr_col      = str_init(IP_ADDR_COL);str port_col         = str_init(PORT_COL);str uri_scheme_col   = str_init(URI_SCHEME_COL);str transport_col    = str_init(TRANSPORT_COL);str grp_id_col       = str_init(GRP_ID_COL);str lcr_table        = str_init(LCR_TABLE);str strip_col        = str_init(STRIP_COL);str prefix_col       = str_init(PREFIX_COL);str from_uri_col     = str_init(FROM_URI_COL);str priority_col     = str_init(PRIORITY_COL);str gw_uri_avp       = str_init(DEF_GW_URI_AVP);str ruri_user_avp    = str_init(DEF_RURI_USER_AVP);str contact_avp      = str_init(DEF_CONTACT_AVP);str inv_timer_avp    = str_init(DEF_FR_INV_TIMER_AVP);int inv_timer        = DEF_FR_INV_TIMER;int inv_timer_next   = DEF_FR_INV_TIMER_NEXT;str rpid_avp         = str_init(DEF_RPID_AVP);int db_mode          = DEF_DB_MODE;/* * Other module types and variables */struct contact {    str uri;    qvalue_t q;    unsigned short q_flag;    struct contact *next;};int_str gw_uri_name, ruri_user_name, contact_name, rpid_name, inv_timer_name;unsigned short gw_uri_avp_name_str;unsigned short ruri_user_avp_name_str;unsigned short contact_avp_name_str;unsigned short rpid_avp_name_str;struct gw_info **gws;	/* Pointer to current gw table pointer */struct gw_info *gws_1;	/* Pointer to gw table 1 */struct gw_info *gws_2;	/* Pointer to gw table 2 */struct lcr_info **lcrs;  /* Pointer to current lcr table pointer */struct lcr_info *lcrs_1; /* Pointer to lcr table 1 */struct lcr_info *lcrs_2; /* Pointer to lcr table 2 */unsigned int *lcrs_ws_reload_counter;unsigned int reload_counter;struct from_uri_regex from_uri_reg[MAX_NO_OF_LCRS];/* * Module functions that are defined later */int load_gws(struct sip_msg* _m, char* _s1, char* _s2);int load_gws_grp(struct sip_msg* _m, char* _s1, char* _s2);int next_gw(struct sip_msg* _m, char* _s1, char* _s2);int from_gw(struct sip_msg* _m, char* _s1, char* _s2);int from_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);int to_gw(struct sip_msg* _m, char* _s1, char* _s2);int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);int load_contacts (struct sip_msg*, char*, char*);int next_contacts (struct sip_msg*, char*, char*);/* * Exported functions */static cmd_export_t cmds[] = {	{"load_gws",      load_gws,      0, 0, REQUEST_ROUTE | FAILURE_ROUTE},	{"load_gws",      load_gws_grp,  1, fixstring2int, REQUEST_ROUTE | FAILURE_ROUTE},	{"next_gw",       next_gw,       0, 0, REQUEST_ROUTE | FAILURE_ROUTE},	{"from_gw",       from_gw,       0, 0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},	{"from_gw",       from_gw_grp,   1, fixstring2int, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},	{"to_gw",         to_gw,         0, 0, REQUEST_ROUTE | FAILURE_ROUTE},	{"to_gw",         to_gw_grp,     1, fixstring2int, REQUEST_ROUTE | FAILURE_ROUTE},	{"load_contacts", load_contacts, 0, 0, REQUEST_ROUTE},	{"next_contacts", next_contacts, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},	{0, 0, 0, 0, 0}};/* * Exported parameters */static param_export_t params[] = {	{"db_url",                   STR_PARAM, &db_url.s       },	{"gw_table",                 STR_PARAM, &gw_table.s     },	{"gw_name_column",           STR_PARAM, &gw_name_col.s  },	{"ip_addr_column",           STR_PARAM, &ip_addr_col.s  },	{"port_column",              STR_PARAM, &port_col.s     },	{"uri_scheme_column",        STR_PARAM, &uri_scheme_col.s },	{"transport_column",         STR_PARAM, &transport_col.s },	{"grp_id_column",            STR_PARAM, &grp_id_col.s   },	{"lcr_table",                STR_PARAM, &lcr_table.s    },	{"strip_column",             STR_PARAM, &strip_col.s    },	{"prefix_column",            STR_PARAM, &prefix_col.s   },	{"from_uri_column",          STR_PARAM, &from_uri_col.s },	{"priority_column",          STR_PARAM, &priority_col.s },	{"gw_uri_avp",               STR_PARAM, &gw_uri_avp.s   },	{"ruri_user_avp",            STR_PARAM, &ruri_user_avp.s },	{"contact_avp",              STR_PARAM, &contact_avp.s  },	{"fr_inv_timer_avp",         STR_PARAM, &inv_timer_avp.s },	{"fr_inv_timer",             INT_PARAM, &inv_timer      },	{"fr_inv_timer_next",        INT_PARAM, &inv_timer_next },	{"rpid_avp",                 STR_PARAM, &rpid_avp.s     },	{"db_mode",                  INT_PARAM, &db_mode        },	{0, 0, 0}};/* * Module interface */struct module_exports exports = {	"lcr", 	cmds,      /* Exported functions */	params,    /* Exported parameters */	0,          /* exported statistics */	mod_init,  /* module initialization function */	0,         /* response function */	destroy,   /* destroy function */	child_init /* child initialization function */};int lcr_db_init(char* db_url){	if (lcr_dbf.init==0){		LOG(L_CRIT, "BUG: lcr_db_bind: null dbf\n");		goto error;	}	db_handle=lcr_dbf.init(db_url);	if (db_handle==0){		LOG(L_ERR, "ERROR: lcr_db_bind: unable to connect to the database\n");		goto error;	}	return 0;error:	return -1;}int lcr_db_bind(char* db_url){	if (bind_dbmod(db_url, &lcr_dbf)<0){		LOG(L_ERR, "ERROR: lcr_db_bind: unable to bind to the database"				" module\n");		return -1;	}	if (!DB_CAPABILITY(lcr_dbf, DB_CAP_QUERY)) {		LOG(L_ERR, "ERROR: lcr_db_bind: Database module does not "		    "implement 'query' function\n");		return -1;	}	if (!DB_CAPABILITY(lcr_dbf, DB_CAP_RAW_QUERY)) {	    LOG(L_ERR, "ERROR: lcr_db_bind: Database module does not "		"implement raw 'query' function\n");	    return -1;	}	return 0;}void lcr_db_close(){	if (db_handle && lcr_dbf.close){		lcr_dbf.close(db_handle);		db_handle=0;	}}int lcr_db_ver(char* db_url, str* name){	db_con_t* dbh;	int ver;	if (lcr_dbf.init==0){		LOG(L_CRIT, "BUG: lcr_db_ver: unbound database\n");		return -1;	}	dbh=lcr_dbf.init(db_url);	if (dbh==0){		LOG(L_ERR, "ERROR: lcr_db_ver: unable to open database connection\n");		return -1;	}	ver=table_version(&lcr_dbf, dbh, name);	lcr_dbf.close(dbh);	return ver;}/* * Module initialization function callee in each child separately */static int child_init(int rank){	if (lcr_db_init(db_url.s) < 0) {		LOG(L_ERR, "ERROR: lcr:child_init():"		    " Unable to connect to the database\n");		return -1;	}      	return 0;}/* * Module initialization function that is called before the main process forks */static int mod_init(void){	int ver, i;	unsigned int par;	DBG("lcr - initializing\n");	/* Bind database */	if (lcr_db_bind(db_url.s)) {		LOG(L_ERR, "ERROR: lcr:mod_init(): No database module found\n");		return -1;	}	/* Update length of module variables */	db_url.len = strlen(db_url.s);	gw_table.len = strlen(gw_table.s);	gw_name_col.len = strlen(gw_name_col.s);	ip_addr_col.len = strlen(ip_addr_col.s);	port_col.len = strlen(port_col.s);	uri_scheme_col.len = strlen(uri_scheme_col.s);	transport_col.len = strlen(transport_col.s);	grp_id_col.len = strlen(grp_id_col.s);	lcr_table.len = strlen(lcr_table.s);	strip_col.len = strlen(strip_col.s);	prefix_col.len = strlen(prefix_col.s);	from_uri_col.len = strlen(from_uri_col.s);	priority_col.len = strlen(priority_col.s);	gw_uri_avp.len = strlen(gw_uri_avp.s);	ruri_user_avp.len = strlen(ruri_user_avp.s);	contact_avp.len = strlen(contact_avp.s);	inv_timer_avp.len = strlen(inv_timer_avp.s);	rpid_avp.len = strlen(rpid_avp.s);	/* Check table version */	ver = lcr_db_ver(db_url.s, &gw_table);	if (ver < 0) {		LOG(L_ERR, "ERROR: lcr:mod_init():"				" Error while querying table version\n");		goto err;	} else if (ver < GW_TABLE_VERSION) {		LOG(L_ERR, "ERROR: lcr:mod_init(): Invalid table version"				" of gw table\n");		goto err;	}			/* Check table version */	ver = lcr_db_ver(db_url.s, &lcr_table);	if (ver < 0) {		LOG(L_ERR, "ERROR: lcr:mod_init():"				" Error while querying table version\n");		goto err;	} else if (ver < LCR_TABLE_VERSION) {		LOG(L_ERR, "ERROR: lcr:mod_init(): Invalid table version of"				" lcr table (use openser_mysql.sh reinstall)\n");		goto err;	}				/* Initialize fifo interface */	(void)init_lcr_fifo();	/* Initializing gw tables and gw table pointer variable */	gws_1 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) * (MAX_NO_OF_GWS + 1));	if (gws_1 == 0) {	    LOG(L_ERR, "ERROR: lcr: mod_init(): "		"No memory for gw table\n");	    goto err;	}	gws_2 = (struct gw_info *)shm_malloc(sizeof(struct gw_info) * (MAX_NO_OF_GWS + 1));	if (gws_2 == 0) {	    LOG(L_ERR, "ERROR: lcr: mod_init(): "		"No memory for gw table\n");	    goto err;	}	for (i = 0; i < MAX_NO_OF_GWS + 1; i++) {		gws_1[i].ip_addr = gws_2[i].ip_addr = 0;	}	gws = (struct gw_info **)shm_malloc(sizeof(struct gw_info *));	if (gws == 0) {	    LOG(L_ERR, "ERROR: lcr: mod_init(): "		"No memory for gw table pointer\n");	}	*gws = gws_1;	/* Initializing lcr tables and lcr table pointer variable */	lcrs_1 = (struct lcr_info *)shm_malloc(sizeof(struct lcr_info) *			(MAX_NO_OF_LCRS + 1));	if (lcrs_1 == 0) {		LOG(L_ERR, "ERROR: lcr: mod_init(): "			"No memory for lcr table\n");		goto err;	}	lcrs_2 = (struct lcr_info *)shm_malloc(sizeof(struct lcr_info) *			(MAX_NO_OF_LCRS + 1));	if (lcrs_2 == 0) {		LOG(L_ERR, "ERROR: lcr: mod_init(): "			"No memory for lcr table\n");		goto err;	}	for (i = 0; i < MAX_NO_OF_LCRS + 1; i++) {		lcrs_1[i].end_record = lcrs_2[i].end_record = 0;	}	lcrs = (struct lcr_info **)shm_malloc(sizeof(struct lcr_info *));	if (lcrs == 0) {		LOG(L_ERR, "ERROR: lcr: mod_init(): "			"No memory for lcr table pointer\n");		goto err;	}	*lcrs = lcrs_1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -