You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/ims_icscf/db.c

382 lines
10 KiB

/*
* $Id$
*
* Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
* Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
*
* The initial version of this code was written by Dragos Vingarzan
* (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
* Fruanhofer Institute. It was and still is maintained in a separate
* branch of the original SER. We are therefore migrating it to
* Kamailio/SR and look forward to maintaining it from here on out.
* 2011/2012 Smile Communications, Pty. Ltd.
* ported/maintained/improved by
* Jason Penton (jason(dot)penton(at)smilecoms.com and
* Richard Good (richard(dot)good(at)smilecoms.com) as part of an
* effort to add full IMS support to Kamailio/SR using a new and
* improved architecture
*
* NB: Alot of this code was originally part of OpenIMSCore,
* FhG Fokus.
* Copyright (C) 2004-2006 FhG Fokus
* Thanks for great work! This is an effort to
* break apart the various CSCF functions into logically separate
* components. We hope this will drive wider use. We also feel
* that in this way the architecture is more complete and thereby easier
* to manage in the Kamailio/SR environment
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio 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
*
* Kamailio 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
*
*/
/**
* \file
*
* Interrogating-CSCF - Database operations
*
*
* \author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de
*
*/
#include "db.h"
#include "../../lib/srdb1/db.h"
#include "../../mem/shm_mem.h"
#include "mod.h"
static db_func_t dbf; /**< db function bindings*/
extern char * ims_icscf_db_url; /**< DB URL */
extern char * ims_icscf_db_nds_table; /**< NDS table in DB */
extern char * ims_icscf_db_scscf_table; /**< S-CSCF table in db */
extern char * ims_icscf_db_capabilities_table; /**< S-CSCF capabilities table in db */
static db1_con_t *hdl_db=0; /**< handle for the database queries */
/**
* Bind to the database module.
* @param db_url - URL of the database
* @returns 0 on success, -1 on error
*/
int ims_icscf_db_bind(char* db_url)
{
str db_url_str={db_url,strlen(db_url)};
if (db_bind_mod(&db_url_str, &dbf) < 0) {
LM_ERR("ims_icscf_db_bind: cannot bind to database module! "
"Did you forget to load a database module ?\n");
return -1;
}
return 0;
}
/**
* Init the database connection
* @param db_url - URL of the database
* @param db_table_nds - name of the NDS table
* @param db_table_scscf - name of the S-CSCF table
* @param db_table_capabilities - name of the S-CSCF capabilities table
* @returns 0 on success, -1 on error
*/
int ims_icscf_db_init(char* db_url,
char* db_table_nds,
char* db_table_scscf,
char* db_table_capabilities)
{
str db_url_str={db_url,strlen(db_url)};
if (dbf.init==0){
LM_ERR("BUG:cscf_db_init: unbound database module\n");
return -1;
}
hdl_db=dbf.init(&db_url_str);
if (hdl_db==0){
LM_ERR("ERR:ims_icscf_db_init: cannot initialize database connection\n");
goto error;
}
return 0;
error:
if (hdl_db){
dbf.close(hdl_db);
hdl_db=0;
}
return -1;
}
/**
* Close the database connection.
*/
void ims_icscf_db_close()
{
if (!dbf.close) return;
if (hdl_db){
dbf.close(hdl_db);
hdl_db=0;
}
}
/**
* Simply check if the database connection was initialized and connect if not.
* @param db_hdl - database handle to test
* @returns 1 if connected, 0 if not
*/
static inline int ims_icscf_db_check_init(db1_con_t *db_hdl)
{
if (db_hdl) return 1;
return (ims_icscf_db_init( ims_icscf_db_url,
ims_icscf_db_nds_table,
ims_icscf_db_scscf_table,
ims_icscf_db_capabilities_table)==0);
}
static str s_trusted_domain={"trusted_domain",14};
/**
* Get the NDS list from the database.
* @param d - array of string to fill with the db contents
* @returns 1 on success, 0 on error
*/
int ims_icscf_db_get_nds(str *d[])
{
db_key_t keys_ret[] = {&s_trusted_domain};
db1_res_t * res = 0 ;
str db_table_nds_str={ims_icscf_db_nds_table,strlen(ims_icscf_db_nds_table)};
str s;
int i;
if (!ims_icscf_db_check_init(hdl_db))
goto error;
LM_DBG("DBG:ims_icscf_db_get_nds: fetching list of NDS for I-CSCF \n");
if (dbf.use_table(hdl_db, &db_table_nds_str)<0) {
LM_ERR("ERR:ims_icscf_db_init: cannot select table \"%s\"\n",db_table_nds_str.s);
goto error;
}
if (dbf.query(hdl_db, 0, 0, 0, keys_ret, 0, 1, NULL, & res) < 0) {
LM_ERR("ERR:ims_icscf_db_get_nds: db_query failed\n");
goto error;
}
if (res->n == 0) {
LM_DBG("DBG:ims_icscf_db_get_nds: I-CSCF has no NDS trusted domains in db\n");
*d=shm_malloc(sizeof(str));
if (*d==NULL){
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for 0 domains\n");
goto error;
}
(*d)[0].s=0;
(*d)[0].len=0;
}
else {
*d=shm_malloc(sizeof(str)*(res->n+1));
if (*d==NULL){
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for %d domains\n",
res->n);
goto error;
}
for(i=0;i<res->n;i++){
s.s = (char*) res->rows[i].values[0].val.string_val;
s.len = strlen(s.s);
(*d)[i].s = shm_malloc(s.len);
if ((*d)[i].s==NULL) {
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for %d bytes\n",
s.len);
(*d)[i].len = 0;
}else{
(*d)[i].len = s.len;
memcpy((*d)[i].s,s.s,s.len);
}
}
(*d)[res->n].s=0;
(*d)[res->n].len=0;
}
LM_DBG("INF:ims_icscf_db_get_nds: Loaded %d trusted domains\n",
res->n);
dbf.free_result( hdl_db, res);
return 1;
error:
if (res)
dbf.free_result( hdl_db, res);
*d=shm_malloc(sizeof(str));
if (*d==NULL)
LM_ERR("ERR:ims_icscf_db_get_nds: failed shm_malloc for 0 domains\n");
else {
(*d)[0].s=0;
(*d)[0].len=0;
}
return 0;
}
static str s_id={"id",2};
static str s_s_cscf_uri={"s_cscf_uri",10};
/**
* Get the S-CSCF names from the database and create the S-CSCF set.
* @param cap - array of scscf_capabilities to fill with the db contents for the S-CSCF names
* @returns 1 on success, 0 on error
*/
int ims_icscf_db_get_scscf(scscf_capabilities *cap[])
{
db_key_t keys_ret[] = {&s_id,&s_s_cscf_uri};
db_key_t key_ord = &s_id;
db1_res_t * res = 0 ;
str db_table_scscf_str={ims_icscf_db_scscf_table,strlen(ims_icscf_db_scscf_table)};
int i;
*cap = 0;
if (!ims_icscf_db_check_init(hdl_db))
goto error;
LM_DBG("DBG:ims_icscf_db_get_scscf: fetching S-CSCFs \n");
if (dbf.use_table(hdl_db, &db_table_scscf_str)<0) {
LM_ERR("ERR:ims_icscf_db_init: cannot select table \"%s\"\n",db_table_scscf_str.s);
goto error;
}
if (dbf.query(hdl_db, 0, 0, 0, keys_ret, 0, 2, key_ord, & res) < 0) {
LM_ERR("ERR:ims_icscf_db_get_scscf: db_query failed\n");
goto error;
}
if (res->n == 0) {
LM_ERR("ERR:ims_icscf_db_get_scscf: no S-CSCFs found\n");
goto error;
}
else {
*cap = shm_malloc(sizeof(scscf_capabilities)*res->n);
if (!(*cap)) {
LM_ERR("ERR:ims_icscf_db_get_scscf: Error allocating %lx bytes\n",
sizeof(scscf_capabilities)*res->n);
goto error;
}
memset((*cap),0,sizeof(scscf_capabilities)*res->n);
for(i=0;i<res->n;i++){
(*cap)[i].id_s_cscf = res->rows[i].values[0].val.int_val;
(*cap)[i].scscf_name.len = strlen(res->rows[i].values[1].val.string_val);
(*cap)[i].scscf_name.s = shm_malloc((*cap)[i].scscf_name.len);
if (!(*cap)[i].scscf_name.s){
LM_ERR("ERR:ims_icscf_db_get_scscf: Error allocating %d bytes\n",
(*cap)[i].scscf_name.len);
(*cap)[i].scscf_name.len=0;
goto error;
}
memcpy((*cap)[i].scscf_name.s,res->rows[i].values[1].val.string_val,
(*cap)[i].scscf_name.len);
}
}
dbf.free_result( hdl_db, res);
// return the size of scscf set
return i;
error:
if (res)
dbf.free_result( hdl_db, res);
return 0;
}
static str s_id_s_cscf={"id_s_cscf",9};
static str s_capability={"capability",10};
/**
* Get the S-CSCF capabilities from the database and fill the S-CSCF set.
* @param cap - array of scscf_capabilities to fill with capabilities
* @returns 1 on success, 0 on error
*/
int ims_icscf_db_get_capabilities(scscf_capabilities *cap[],int cap_cnt)
{
db_key_t keys_ret[] = {&s_id_s_cscf,&s_capability};
db_key_t key_ord = &s_id_s_cscf;
db1_res_t * res = 0 ;
str db_table_capabilities_str={ims_icscf_db_capabilities_table,strlen(ims_icscf_db_capabilities_table)};
int i,j;
int ccnt=0;
int cnt;
if (!ims_icscf_db_check_init(hdl_db))
goto error;
LM_DBG("DBG:ims_icscf_db_get_capabilities: fetching list of Capabilities for I-CSCF\n");
if (dbf.use_table(hdl_db, &db_table_capabilities_str)<0) {
LM_ERR("ERR:ims_icscf_db_init: cannot select table \"%s\"\n",db_table_capabilities_str.s);
goto error;
}
if (dbf.query(hdl_db, 0, 0, 0, keys_ret, 0, 2, key_ord, & res) < 0) {
LM_ERR("ERR:ims_icscf_db_get_capabilities: db_query failed\n");
goto error;
}
if (res->n == 0) {
LM_DBG("DBG:ims_icscf_db_get_capabilities: No Capabilites found... not critical...\n");
return 1;
}
else {
for(i=0;i<cap_cnt;i++){
cnt = 0;
for(j=0;j<res->n;j++)
if (res->rows[j].values[0].val.int_val == (*cap)[i].id_s_cscf)
cnt++;
(*cap)[i].capabilities = shm_malloc(sizeof(int)*cnt);
if (!(*cap)[i].capabilities) {
LM_ERR("ERR:ims_icscf_db_get_capabilities: Error allocating %lx bytes\n",
sizeof(int)*cnt);
(*cap)[i].cnt=0;
goto error;
}
cnt=0;
for(j=0;j<res->n;j++)
if (res->rows[j].values[0].val.int_val == (*cap)[i].id_s_cscf) {
(*cap)[i].capabilities[cnt++]=res->rows[j].values[1].val.int_val;
ccnt++;
}
(*cap)[i].cnt=cnt;
}
}
LM_DBG("INF:ims_icscf_db_get_capabilities: Loaded %d capabilities for %d S-CSCFs (%d invalid entries in db)\n",
ccnt,cap_cnt,res->n-ccnt);
dbf.free_result( hdl_db, res);
return 1;
error:
if (res)
dbf.free_result( hdl_db, res);
return 0;
}