📄 avp_db.c
字号:
/* * $Id: avp_db.c,v 1.2.2.1 2005/04/20 19:56:26 bogdan Exp $ * * Copyright (C) 2004 FhG Fokus * * This file is part of ser, a free SIP server. * * ser 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 * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * ser 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 */#include <string.h>#include "../../sr_module.h"#include "../../mem/mem.h"#include "../../parser/msg_parser.h"#include "../../parser/hf.h"#include "../../parser/parse_from.h"#include "../../parser/parse_to.h"#include "../../parser/parse_uri.h"#include "../../str.h"#include "../../db/db.h"#include "../../config.h"#include "../../usr_avp.h"MODULE_VERSION#define CALLER_PREFIX "caller_"#define CALLER_PREFIX_LEN (sizeof(CALLER_PREFIX) - 1)#define CALLEE_PREFIX "callee_"#define CALLEE_PREFIX_LEN (sizeof(CALLEE_PREFIX) - 1)typedef enum load_avp_param { LOAD_CALLER_UUID, /* Use the caller's UUID as the key */ LOAD_CALLEE_UUID, /* Use the callee's UUID as the key */ LOAD_CALLER, /* Use the caller's username and domain as the key */ LOAD_CALLEE /* Use the callee's username and domain as the key */} load_avp_param_t;static char* db_url = DEFAULT_RODB_URL; /* Database URL */static char* db_table = "usr_preferences";static char* uuid_column = "uuid";static char* username_column = "username";static char* domain_column = "domain";static char* attr_column = "attribute";static char* val_column = "value";static str caller_prefix = {CALLER_PREFIX, CALLER_PREFIX_LEN};static str callee_prefix = {CALLEE_PREFIX, CALLEE_PREFIX_LEN};static int caller_uuid_avp = 1;static int callee_uuid_avp = 2;static int use_domain = 0;static db_con_t* db_handle;static db_func_t dbf;static int load_avp(struct sip_msg*, char*, char*);static int mod_init(void);static int child_init(int);static int load_avp_fixup(void**, int);/* * Exported functions */static cmd_export_t cmds[] = { {"avp_load", load_avp, 1, load_avp_fixup, REQUEST_ROUTE | FAILURE_ROUTE}, {0, 0, 0, 0, 0}};/* * Exported parameters */static param_export_t params[] = { {"caller_uuid_avp", INT_PARAM, &caller_uuid_avp}, {"callee_uuid_avp", INT_PARAM, &callee_uuid_avp}, {"db_url", STR_PARAM, &db_url }, {"pref_table", STR_PARAM, &db_table }, {"uuid_column", STR_PARAM, &uuid_column }, {"username_column", STR_PARAM, &username_column}, {"domain_column", STR_PARAM, &domain_column }, {"attr_column", STR_PARAM, &attr_column }, {"val_column", INT_PARAM, &val_column }, {"use_domain", INT_PARAM, &use_domain }, {0, 0, 0}};struct module_exports exports = { "avp_db", cmds, /* Exported commands */ params, /* Exported parameters */ mod_init, /* module initialization function */ 0, /* response function*/ 0, /* destroy function */ 0, /* oncancel function */ child_init /* per-child init function */};static int mod_init(void){ DBG("avp_db - initializing\n"); if (bind_dbmod(db_url, &dbf) < 0) { LOG(L_ERR, "avpdb_mod_init: Unable to bind a database driver\n"); return -1; } if (!DB_CAPABILITY(dbf, DB_CAP_QUERY)) { LOG(L_ERR, "avpdb_mod_init: Selected database driver does not suppor the query capability\n"); return -1; } caller_prefix.len = strlen(caller_prefix.s); callee_prefix.len = strlen(callee_prefix.s); return 0;}static int child_init(int rank){ DBG("avp_db - Initializing child %i\n", rank); db_handle = dbf.init(db_url); if (!db_handle) { LOG(L_ERR, "avpdb_init_child: could not initialize connection to %s\n", db_url); return -1; } return 0;}static int query_db(str* prefix, str* uuid, str* username, str* domain){ int name_len, err = -1; db_key_t cols[2], keys[2]; db_val_t vals[2]; db_res_t* res; db_row_t* cur_row; int_str name, val; str name_str, val_str; cols[0] = attr_column; cols[1] = val_column; if (uuid) { keys[0] = uuid_column; VAL_TYPE(vals) = DB_STR; VAL_NULL(vals) = 0; VAL_STR(vals) = *uuid; } else { keys[0] = username_column; VAL_TYPE(vals) = DB_STR; VAL_NULL(vals) = 0; VAL_STR(vals) = *username; } if (use_domain) { keys[1] = domain_column; VAL_TYPE(vals + 1) = DB_STR; VAL_NULL(vals + 1) = 0; VAL_STR(vals + 1) = *domain; } if (dbf.use_table(db_handle, db_table) < 0) { LOG(L_ERR, "query_db: Unable to change the table\n"); } err = dbf.query(db_handle, keys, 0, vals, cols, (use_domain ? 2 : 1), 2, 0, &res); if (err) { LOG(L_ERR,"query_db: db_query failed."); return -1; } name.s = &name_str; val.s = &val_str; for (cur_row = res->rows; cur_row < res->rows + res->n; cur_row++) { if (VAL_NULL(ROW_VALUES(cur_row)) || VAL_NULL(ROW_VALUES(cur_row) + 1)) { continue; } name_len = strlen((char*)VAL_STRING(ROW_VALUES(cur_row))); name_str.len = prefix->len + name_len; name_str.s = pkg_malloc(name_str.len); if (name_str.s == 0) { LOG(L_ERR, "query_db: Out of memory"); dbf.free_result(db_handle, res); return -1; } memcpy(name_str.s, prefix->s, prefix->len); memcpy(name_str.s + prefix->len, (char*)VAL_STRING(ROW_VALUES(cur_row)), name_len); val_str.len = strlen((char*)VAL_STRING(ROW_VALUES(cur_row) + 1)); val_str.s = (char*)VAL_STRING(ROW_VALUES(cur_row) + 1); err = add_avp(AVP_NAME_STR | AVP_VAL_STR, name, val); if (err != 0) { LOG(L_ERR, "query_db: add_avp failed\n"); pkg_free(name_str.s); dbf.free_result(db_handle, res); } DBG("query_db: AVP '%.*s'='%.*s' has been added\n", name_str.len, name_str.s, val_str.len, val_str.s); } dbf.free_result(db_handle, res); return 1;}static int load_avp_uuid(struct sip_msg* msg, str* prefix, int avp_id){ struct usr_avp *uuid; int_str attr_istr, val_istr; attr_istr.n = avp_id; uuid = search_first_avp(AVP_NAME_STR, attr_istr, &val_istr); if (!uuid) { LOG(L_ERR, "load_avp_uuid: no AVP with id %d was found\n", avp_id); return -1; } if (!(uuid->flags & AVP_VAL_STR)) { LOG(L_ERR, "load_avp_uuid: value for <%d> should " "be of type string\n", avp_id); return -1; } return query_db(prefix, val_istr.s, 0, 0);}static int load_avp_user(struct sip_msg* msg, str* prefix, load_avp_param_t param){ str* uri; struct sip_uri puri; if (param == LOAD_CALLER) { if (parse_from_header(msg) < 0) { LOG(L_ERR, "load_avp_user: Error while parsing From header field\n"); return -1; } uri = &get_from(msg)->uri; if (parse_uri(uri->s, uri->len, &puri) == -1) { LOG(L_ERR, "load_avp_user: Error while parsing From URI\n"); return -1; } return query_db(prefix, 0, &puri.user, &puri.host); } else if (param == LOAD_CALLEE) { if (parse_sip_msg_uri(msg) < 0) { LOG(L_ERR, "load_avp_user: Request-URI parsing failed\n"); return -1; } if (msg->parsed_uri_ok != 1) { LOG(L_ERR, "load_avp_user: Unable to parse Request-URI\n"); return -1; } return query_db(prefix, 0, &msg->parsed_uri.user, &msg->parsed_uri.host); } else { LOG(L_ERR, "load_avp_user: Unknown header field type\n"); return -1; }}static int load_avp(struct sip_msg* msg, char* attr, char* _dummy){ switch((load_avp_param_t)attr) { case LOAD_CALLER_UUID: return load_avp_uuid(msg, &caller_prefix, caller_uuid_avp); break; case LOAD_CALLEE_UUID: return load_avp_uuid(msg, &callee_prefix, callee_uuid_avp); break; case LOAD_CALLER: return load_avp_user(msg, &caller_prefix, LOAD_CALLER); break; case LOAD_CALLEE: return load_avp_user(msg, &callee_prefix, LOAD_CALLEE); break; default: LOG(L_ERR, "load_avp: Unknown parameter value\n"); return -1; }}static int load_avp_fixup(void** param, int param_no){ long id = 0; if (param_no == 1) { if (!strcasecmp(*param, "caller_uuid")) { id = LOAD_CALLER_UUID; } else if (!strcasecmp(*param, "callee_uuid")) { id = LOAD_CALLEE_UUID; } else if (!strcasecmp(*param, "caller")) { id = LOAD_CALLER; } else if (!strcasecmp(*param, "callee")) { id = LOAD_CALLEE; } else { LOG(L_ERR, "load_avp_fixup: Unknown parameter\n"); return -1; } } pkg_free(*param); *param=(void*)id; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -