コード例 #1
0
ファイル: ul_db_handle.c プロジェクト: kiryu/kamailio
int load_handles(db_func_t * dbf, db1_con_t * dbh) {
	static char query[UL_DB_QUERY_LEN];
	db1_res_t * res;
	db_row_t * row;
	ul_db_handle_list_t * element;
	int i, id, query_len;
	str tmp;

	if(!dbf || !dbh){
		LM_ERR("NULL parameter passed \n");
		return -1;
	}

	query_len = 25 + id_col.len + reg_table.len;

	if(query_len > UL_DB_QUERY_LEN) {
		LM_ERR("weird: query larger than %i bytes.\n", UL_DB_QUERY_LEN);
		return -1;
	}

	memset(query, 0, UL_DB_QUERY_LEN);

	if (sprintf(query,
	        "SELECT DISTINCT "
	        "%.*s "
	        "FROM "
	        "%.*s",
	        id_col.len, id_col.s,
	        reg_table.len, reg_table.s) < 0) {
		LM_ERR("could not print query\n");
		return -1;
	}
	tmp.s = query;
	tmp.len = strlen(query);

	if (dbf->raw_query (dbh, &tmp, &res) < 0) {
		LM_ERR("in database query.\n");
		return -1;
	}

	if (RES_ROW_N (res) == 0) {
		dbf->free_result (dbh, res);
		LM_DBG ("no data found\n");
		return 1;
	}

	for (i = 0; i < RES_ROW_N (res); ++i) {
		row = RES_ROWS (res) + i;

		if((element = allocate_handle_list()) == NULL) {
			LM_ERR("couldnt allocate handle.\n");
			goto errout;
		}

		if (VAL_NULL (ROW_VALUES(row) + 0)) {
			LM_ERR("Weird: Empty ID-Field\n");
			goto errout;
		}

		id = VAL_INT (ROW_VALUES(row) + 0);
		if(load_data(dbf, dbh, element->handle, id) < 0){
			LM_ERR("couldn't load handle data.\n");
			goto errout;
		}
		element->next = db_handles;
		db_handles = element;
	}
	dbf->free_result (dbh, res);
	return 0;
errout:
	dbf->free_result (dbh, res);
	return -1;
}
コード例 #2
0
ファイル: trusted.c プロジェクト: AndreiPlesa/kamailio
/*
 * Reload trusted table to new hash table and when done, make new hash table
 * current one.
 */
int reload_trusted_table(void)
{
	db_key_t cols[6];
	db1_res_t* res = NULL;
	db_row_t* row;
	db_val_t* val;

	struct trusted_list **new_hash_table;
	struct trusted_list **old_hash_table;
	int i;
	int priority;

	char *pattern, *ruri_pattern, *tag;

	if (hash_table == 0) {
	    LM_ERR("in-memory hash table not initialized\n");
	    return -1;
	}

	if (db_handle == 0) {
	    LM_ERR("no connection to database\n");
	    return -1;
	}

	cols[0] = &source_col;
	cols[1] = &proto_col;
	cols[2] = &from_col;
	cols[3] = &ruri_col;
	cols[4] = &tag_col;
	cols[5] = &priority_col;

	if (perm_dbf.use_table(db_handle, &trusted_table) < 0) {
		LM_ERR("failed to use trusted table\n");
		return -1;
	}

	if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 6, 0, &res) < 0) {
		LM_ERR("failed to query database\n");
		return -1;
	}

	/* Choose new hash table and free its old contents */
	if (*hash_table == hash_table_1) {
		new_hash_table = hash_table_2;
	} else {
		new_hash_table = hash_table_1;
	}
	empty_hash_table(new_hash_table);

	row = RES_ROWS(res);

	LM_DBG("number of rows in trusted table: %d\n", RES_ROW_N(res));
		
	for (i = 0; i < RES_ROW_N(res); i++) {
	    val = ROW_VALUES(row + i);
	    if ((ROW_N(row + i) == 6) &&
		((VAL_TYPE(val) == DB1_STRING) || (VAL_TYPE(val) == DB1_STR) ) && 
		!VAL_NULL(val) &&
		((VAL_TYPE(val + 1) == DB1_STRING) || (VAL_TYPE(val + 1) == DB1_STR))
		&& !VAL_NULL(val + 1) &&
		(VAL_NULL(val + 2) ||
		 (((VAL_TYPE(val + 2) == DB1_STRING) || (VAL_TYPE(val + 2) == DB1_STR)) &&
		!VAL_NULL(val + 2))) && (VAL_NULL(val + 3) ||
		 (((VAL_TYPE(val + 3) == DB1_STRING) || (VAL_TYPE(val + 3) == DB1_STR) )&&
		!VAL_NULL(val + 3))) && (VAL_NULL(val + 4) ||
		 (((VAL_TYPE(val + 4) == DB1_STRING) || (VAL_TYPE(val + 4) == DB1_STR) )&&
		!VAL_NULL(val + 4)))) {
		if (VAL_NULL(val + 2)) {
		    pattern = 0;
		} else {
		    pattern = (char *)VAL_STRING(val + 2);
		}
		if (VAL_NULL(val + 3)) {
		    ruri_pattern = 0;
		} else {
		    ruri_pattern = (char *)VAL_STRING(val + 3);
		}
		if (VAL_NULL(val + 4)) {
		    tag = 0;
		} else {
		    tag = (char *)VAL_STRING(val + 4);
		}
		if (VAL_NULL(val + 5)) {
		    priority = 0;
		} else {
		    priority = (int)VAL_INT(val + 5);
		}
		if (hash_table_insert(new_hash_table,
				      (char *)VAL_STRING(val),
				      (char *)VAL_STRING(val + 1),
				      pattern, ruri_pattern, tag, priority) == -1) {
		    LM_ERR("hash table problem\n");
		    perm_dbf.free_result(db_handle, res);
		    empty_hash_table(new_hash_table);
		    return -1;
		}
		LM_DBG("tuple <%s, %s, %s, %s, %s> inserted into trusted hash "
		    "table\n", VAL_STRING(val), VAL_STRING(val + 1),
		    pattern, ruri_pattern, tag);
	    } else {
		LM_ERR("database problem\n");
		perm_dbf.free_result(db_handle, res);
		empty_hash_table(new_hash_table);
		return -1;
	    }
	}

	perm_dbf.free_result(db_handle, res);

	old_hash_table = *hash_table;
	*hash_table = new_hash_table;
	empty_hash_table(old_hash_table);

	LM_DBG("trusted table reloaded successfully.\n");
	
	return 1;
}
コード例 #3
0
ファイル: mtree_mod.c プロジェクト: TheGrandWazoo/kamailio
static int mt_pack_values(m_tree_t *pt, db1_res_t* db_res,
		int row, int cols, str *tvalue)
{
	static char vbuf[4096];
	int c;
	int len;
	char *p;
	str iv;

	len = 0;
	for(c=1; c<cols; c++) {
		if(VAL_NULL(&RES_ROWS(db_res)[row].values[c])) {
			len += 1;
		} else if(RES_ROWS(db_res)[row].values[c].type == DB1_STRING) {
			len += strlen(RES_ROWS(db_res)[row].values[c].val.string_val);
		} else if(RES_ROWS(db_res)[row].values[c].type == DB1_STR) {
			len += RES_ROWS(db_res)[row].values[c].val.str_val.len;
		} else if(RES_ROWS(db_res)[row].values[c].type == DB1_INT) {
			len += 12;
		} else {
			LM_ERR("unsupported data type for column %d\n", c);
			return -1;
		}
	}
	if(len + c>=4096) {
		LM_ERR("too large values (need %d)\n", len+c);
		return -1;
	}
	p = vbuf;
	for(c=1; c<cols; c++) {
		if(VAL_NULL(&RES_ROWS(db_res)[row].values[c])) {
			*p = pt->pack[2];
			p++;
		} else if(RES_ROWS(db_res)[row].values[c].type == DB1_STRING) {
			strcpy(p, RES_ROWS(db_res)[row].values[c].val.string_val);
			p += strlen(RES_ROWS(db_res)[row].values[c].val.string_val);
		} else if(RES_ROWS(db_res)[row].values[c].type == DB1_STR) {
			strncpy(p, RES_ROWS(db_res)[row].values[c].val.str_val.s,
				RES_ROWS(db_res)[row].values[c].val.str_val.len);
			p += RES_ROWS(db_res)[row].values[c].val.str_val.len;
		} else if(RES_ROWS(db_res)[row].values[c].type == DB1_INT) {
			iv.s = sint2str(RES_ROWS(db_res)[row].values[c].val.int_val, &iv.len);
			strncpy(p, iv.s, iv.len);
			p += iv.len;
		}
		if(c+1<cols) {
			*p = pt->pack[1];
			p++;
		}
	}
	tvalue->s = vbuf;
	tvalue->len = p - vbuf;
	LM_DBG("packed: [%.*s]\n", tvalue->len, tvalue->s);
	return 0;
}
コード例 #4
0
/*
 * Query table for specified rows
 * _con: structure representing database connection
 * _k: key names
 * _op: operators
 * _v: values of the keys that must match
 * _c: column names to return
 * _n: number of key=values pairs to compare
 * _nc: number of columns to return
 * _o: order by the specified column
 */
int bdb_query(db_con_t* _con, db_key_t* _k, db_op_t* _op, db_val_t* _v,
              db_key_t* _c, int _n, int _nc, db_key_t _o, db_res_t** _r)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    u_int32_t i, len, ret;
    int klen=MAX_ROW_SIZE;
    int *lkey=NULL, *lres=NULL;
    str s;
    DBT key, data;
    DB *db;
    DBC *dbcp;

    if ((!_con) || (!_r) || !CON_TABLE(_con))
    {
#ifdef BDB_EXTRA_DEBUG
        LM_ERR("Invalid parameter value\n");
#endif
        return -1;
    }
    *_r = NULL;

    /*check if underlying DB file has changed inode */
    if(auto_reload)
        bdb_check_reload(_con);

    s.s = (char*)CON_TABLE(_con);
    s.len = strlen(CON_TABLE(_con));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_con), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -1;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -1;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("QUERY in %.*s\n", _tp->name.len, _tp->name.s);

    if (_o)  LM_DBG("DONT-CARE : _o: order by the specified column \n");
    if (_op) LM_DBG("DONT-CARE : _op: operators for refining query \n");
#endif

    db = _tp->db;
    if(!db) return -1;

    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, MAX_ROW_SIZE);
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /* if _c is NULL and _nc is zero, you will get all table
       columns in the result
    */
    if (_c)
    {   lres = bdb_get_colmap(_tbc->dtp, _c, _nc);
        if(!lres)
        {   ret = -1;
            goto error;
        }
    }

    if(_k)
    {   lkey = bdb_get_colmap(_tbc->dtp, _k, _n);
        if(!lkey)
        {   ret = -1;
            goto error;
        }
    }
    else
    {
        DB_HASH_STAT st;
        memset(&st, 0, sizeof(DB_HASH_STAT));
        i =0 ;

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("SELECT * FROM %.*s\n", _tp->name.len, _tp->name.s);
#endif

        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        /*count the number of records*/
        while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
        {   if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;
            i++;
        }

        dbcp->c_close(dbcp);
        ret=0;

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("%i = SELECT COUNT(*) FROM %.*s\n", i, _tp->name.len, _tp->name.s);
#endif

        *_r = db_new_result();
        if (!*_r)
        {   LM_ERR("no memory left for result \n");
            ret = -2;
            goto error;
        }

        if(i == 0)
        {
            /*return empty table*/
            RES_ROW_N(*_r) = 0;
            BDB_CON_RESULT(_con) = *_r;
            return 0;
        }

        /*allocate N rows in the result*/
        RES_ROW_N(*_r) = i;
        len  = sizeof(db_row_t) * i;
        RES_ROWS(*_r) = (db_row_t*)pkg_malloc( len );
        memset(RES_ROWS(*_r), 0, len);

        /*fill in the column part of db_res_t (metadata) */
        if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
        {   LM_ERR("Error while getting column names\n");
            goto error;
        }

        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        /*convert each record into a row in the result*/
        i =0 ;
        while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
        {
            if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("KEY: [%.*s]\nDATA: [%.*s]\n"
                   , (int)   key.size
                   , (char *)key.data
                   , (int)   data.size
                   , (char *)data.data);
#endif

            /*fill in the row part of db_res_t */
            if ((ret=bdb_append_row( *_r, dbuf, lres, i)) < 0)
            {   LM_ERR("Error while converting row\n");
                goto error;
            }
            i++;
        }

        dbcp->c_close(dbcp);
        BDB_CON_RESULT(_con) = *_r;
        return 0;
    }

    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("error in query key \n");
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /*create an empty db_res_t which gets returned even if no result*/
    *_r = db_new_result();
    if (!*_r)
    {   LM_ERR("no memory left for result \n");
        ret = -2;
        goto error;
    }
    RES_ROW_N(*_r) = 0;
    BDB_CON_RESULT(_con) = *_r;

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("SELECT  KEY: [%.*s]\n"
           , (int)   key.size
           , (char *)key.data );
#endif

    /*query Berkely DB*/
    if ((ret = db->get(db, NULL, &key, &data, 0)) == 0)
    {
#ifdef BDB_EXTRA_DEBUG
        LM_DBG("RESULT\nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   data.size
               , (char *)data.data);
#endif

        /*fill in the col part of db_res_t */
        if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
        {   LM_ERR("Error while getting column names\n");
            goto error;
        }
        /*fill in the row part of db_res_t */
        if ((ret=bdb_convert_row( *_r, dbuf, lres)) < 0)
        {   LM_ERR("Error while converting row\n");
            goto error;
        }

    }
    else
    {
        /*Berkeley DB error handler*/
        switch(ret)
        {

        case DB_NOTFOUND:

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("NO RESULT for QUERY \n");
#endif

            ret=0;
            break;
        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        // The operation was selected to resolve a deadlock.
        case DB_SECONDARY_BAD:
        // A secondary index references a nonexistent primary key.
        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
            bdblib_recover(_tp,ret);
            goto error;
        }
    }

    if(lkey)
        pkg_free(lkey);
    if(lres)
        pkg_free(lres);

    return ret;

error:
    if(lkey)
        pkg_free(lkey);
    if(lres)
        pkg_free(lres);
    if(*_r)
        bdb_free_result(*_r);
    *_r = NULL;

    return ret;
}
コード例 #5
0
ファイル: km_dbase.c プロジェクト: mehulsbhatt/voip-foip
/**
 * \brief Gets a partial result set, fetch rows from a result
 *
 * Gets a partial result set, fetch a number of rows from a database result.
 * This function initialize the given result structure on the first run, and
 * fetches the nrows number of rows. On subsequenting runs, it uses the
 * existing result and fetches more rows, until it reaches the end of the
 * result set. Because of this the result needs to be null in the first
 * invocation of the function. If the number of wanted rows is zero, the
 * function returns anything with a result of zero.
 * \param _h structure representing the database connection
 * \param _r pointer to a structure representing the result
 * \param nrows number of fetched rows
 * \return zero on success, negative value on failure
 */
int db_mysql_fetch_result(const db1_con_t* _h, db1_res_t** _r, const int nrows)
{
	int rows, i, code;

	if (!_h || !_r || nrows < 0) {
		LM_ERR("Invalid parameter value\n");
		return -1;
	}

	/* exit if the fetch count is zero */
	if (nrows == 0) {
		db_free_result(*_r);
		*_r = 0;
		return 0;
	}

	if(*_r==0) {
		/* Allocate a new result structure */
		*_r = db_new_result();
		if (*_r == 0) {
			LM_ERR("no memory left\n");
			return -2;
		}

		CON_RESULT(_h) = mysql_store_result(CON_CONNECTION(_h));
		if (!CON_RESULT(_h)) {
			if (mysql_field_count(CON_CONNECTION(_h)) == 0) {
				(*_r)->col.n = 0;
				(*_r)->n = 0;
				return 0;
			} else {
				LM_ERR("driver error: %s\n", mysql_error(CON_CONNECTION(_h)));
				code = mysql_errno(CON_CONNECTION(_h));
				if (code == CR_SERVER_GONE_ERROR || code == CR_SERVER_LOST) {
					counter_inc(mysql_cnts_h.driver_err);
				}
				db_free_result(*_r);
				*_r = 0;
				return -3;
			}
		}
		if (db_mysql_get_columns(_h, *_r) < 0) {
			LM_ERR("error while getting column names\n");
			return -4;
		}

		RES_NUM_ROWS(*_r) = mysql_num_rows(CON_RESULT(_h));
		if (!RES_NUM_ROWS(*_r)) {
			LM_DBG("no rows returned from the query\n");
			RES_ROWS(*_r) = 0;
			return 0;
		}

	} else {
		/* free old rows */
		if(RES_ROWS(*_r)!=0)
			db_free_rows(*_r);
		RES_ROWS(*_r) = 0;
		RES_ROW_N(*_r) = 0;
	}

	/* determine the number of rows remaining to be processed */
	rows = RES_NUM_ROWS(*_r) - RES_LAST_ROW(*_r);

	/* If there aren't any more rows left to process, exit */
	if(rows<=0)
		return 0;

	/* if the fetch count is less than the remaining rows to process                 */
	/* set the number of rows to process (during this call) equal to the fetch count */
	if(nrows < rows)
		rows = nrows;

	RES_ROW_N(*_r) = rows;

	LM_DBG("converting row %d of %d count %d\n", RES_LAST_ROW(*_r),
			RES_NUM_ROWS(*_r), RES_ROW_N(*_r));

	RES_ROWS(*_r) = (struct db_row*)pkg_malloc(sizeof(db_row_t) * rows);
	if (!RES_ROWS(*_r)) {
		LM_ERR("no memory left\n");
		return -5;
	}

	for(i = 0; i < rows; i++) {
		CON_ROW(_h) = mysql_fetch_row(CON_RESULT(_h));
		if (!CON_ROW(_h)) {
			LM_ERR("driver error: %s\n", mysql_error(CON_CONNECTION(_h)));
			RES_ROW_N(*_r) = i;
			db_free_rows(*_r);
			return -6;
		}
		if (db_mysql_convert_row(_h, *_r, &(RES_ROWS(*_r)[i])) < 0) {
			LM_ERR("error while converting row #%d\n", i);
			RES_ROW_N(*_r) = i;
			db_free_rows(*_r);
			return -7;
		}
	}

	/* update the total number of rows processed */
	RES_LAST_ROW(*_r) += rows;
	return 0;
}
コード例 #6
0
ファイル: dlist.c プロジェクト: btriller/kamailio
/*!
 * \brief Get all contacts from the database, in partitions if wanted
 * \see get_all_ucontacts
 * \param buf target buffer
 * \param len length of buffer
 * \param flags contact flags
 * \param part_idx part index
 * \param part_max maximal part
 * \param options options
 * \return 0 on success, positive if buffer size was not sufficient, negative on failure
 */
static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
								unsigned int part_idx, unsigned int part_max,
								int options)
{
	struct socket_info *sock;
	unsigned int dbflags;
	db1_res_t* res = NULL;
	db_row_t *row;
	dlist_t *dom;
	int port, proto;
	char *p;
	str addr;
	str recv;
	str path;
	str ruid;
	str host;
	unsigned int aorhash;
	int i;
	void *cp;
	int shortage, needed;
	db_key_t keys1[4]; /* where */
	db_val_t vals1[4];
	db_op_t  ops1[4];
	db_key_t keys2[6]; /* select */
	int n[2] = {2,6}; /* number of dynamic values used on key1/key2 */

	cp = buf;
	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof(addr.len);

	aorhash = 0;

	/* select fields */
	keys2[0] = &received_col;
	keys2[1] = &contact_col;
	keys2[2] = &sock_col;
	keys2[3] = &cflags_col;
	keys2[4] = &path_col;
	keys2[5] = &ruid_col;

	/* where fields */
	keys1[0] = &expires_col;
	ops1[0] = OP_GT;
	vals1[0].nul = 0;
	UL_DB_EXPIRES_SET(&vals1[0], time(0));

	keys1[1] = &partition_col;
	ops1[1] = OP_EQ;
	vals1[1].type = DB1_INT;
	vals1[1].nul = 0;
	if(_ul_max_partition>0)
		vals1[1].val.int_val = part_idx;
	else
		vals1[1].val.int_val = 0;

	if (flags & nat_bflag) {
		keys1[n[0]] = &keepalive_col;
		ops1[n[0]] = OP_EQ;
		vals1[n[0]].type = DB1_INT;
		vals1[n[0]].nul = 0;
		vals1[n[0]].val.int_val = 1;
		n[0]++;
	}
	if(options&GAU_OPT_SERVER_ID) {
		keys1[n[0]] = &srv_id_col;
		ops1[n[0]] = OP_EQ;
		vals1[n[0]].type = DB1_INT;
		vals1[n[0]].nul = 0;
		vals1[n[0]].val.int_val = server_id;
		n[0]++;
	}

	/* TODO: use part_idx and part_max on keys1 */

	for (dom = root; dom!=NULL ; dom=dom->next) {
		if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) {
			LM_ERR("sql use_table failed\n");
			return -1;
		}
		if (ul_dbf.query(ul_dbh, keys1, ops1, vals1, keys2,
							n[0], n[1], NULL, &res) <0 ) {
			LM_ERR("query error\n");
			return -1;
		}
		if( RES_ROW_N(res)==0 ) {
			ul_dbf.free_result(ul_dbh, res);
			continue;
		}

		for(i = 0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;


			/* received */
			recv.s = (char*)VAL_STRING(ROW_VALUES(row));
			if ( VAL_NULL(ROW_VALUES(row)) || recv.s==0 || recv.s[0]==0 ) {
				recv.s = NULL;
				recv.len = 0;
			}
			else {
				recv.len = strlen(recv.s);
			}

			/* contact */
			addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1);
			if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) {
				LM_ERR("empty contact -> skipping\n");
				continue;
			}
			else {
				addr.len = strlen(addr.s);
			}

			/* path */
			path.s = (char*)VAL_STRING(ROW_VALUES(row)+4);
			if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){
				path.s = NULL;
				path.len = 0;
			} else {
				path.len = strlen(path.s);
			}

			/* ruid */
			ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5);
			if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){
				ruid.s = NULL;
				ruid.len = 0;
			} else {
				ruid.len = strlen(ruid.s);
			}

			needed = (int)(sizeof(addr.len) + addr.len
					+ sizeof(recv.len) + recv.len
					+ sizeof(sock) + sizeof(dbflags)
					+ sizeof(path.len) + path.len
					+ sizeof(ruid.len) + ruid.len
					+ sizeof(aorhash));
			if (len < needed) {
				shortage += needed ;
				continue;
			}

			/* write contact */
			memcpy(cp, &addr.len, sizeof(addr.len));
			cp = (char*)cp + sizeof(addr.len);
			memcpy(cp, addr.s, addr.len);
			cp = (char*)cp + addr.len;

			/* write received */
			memcpy(cp, &recv.len, sizeof(recv.len));
			cp = (char*)cp + sizeof(recv.len);
			/* copy received only if exist */
			if(recv.len){
				memcpy(cp, recv.s, recv.len);
				cp = (char*)cp + recv.len;
			}

			/* sock */
			p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
			if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
				sock = 0;
			} else {
				if (parse_phostport( p, &host.s, &host.len,
				&port, &proto)!=0) {
					LM_ERR("bad socket <%s>...set to 0\n", p);
					sock = 0;
				} else {
					sock = grep_sock_info( &host, (unsigned short)port, proto);
					if (sock==0) {
						LM_DBG("non-local socket <%s>...set to 0\n", p);
					}
				}
			}

			/* flags */
			dbflags = VAL_BITMAP(ROW_VALUES(row) + 3);

			/* write sock and flags */
			memcpy(cp, &sock, sizeof(sock));
			cp = (char*)cp + sizeof(sock);
			memcpy(cp, &dbflags, sizeof(dbflags));
			cp = (char*)cp + sizeof(dbflags);

			/* write path */
			memcpy(cp, &path.len, sizeof(path.len));
			cp = (char*)cp + sizeof(path.len);
			/* copy path only if exist */
			if(path.len){
				memcpy(cp, path.s, path.len);
				cp = (char*)cp + path.len;
			}

			/* write ruid */
			memcpy(cp, &ruid.len, sizeof(ruid.len));
			cp = (char*)cp + sizeof(ruid.len);
			/* copy ruid only if exist */
			if(ruid.len){
				memcpy(cp, ruid.s, ruid.len);
				cp = (char*)cp + ruid.len;
			}
			/* aorhash not used for db-only records, but it is added
			 * (as 0) to match the struct used for mem records */
			memcpy(cp, &aorhash, sizeof(aorhash));
			cp = (char*)cp + sizeof(aorhash);

			len -= needed;
		} /* row cycle */

		ul_dbf.free_result(ul_dbh, res);
	} /* domain cycle */

	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(addr.len));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
コード例 #7
0
ファイル: dbcassa_base.cpp プロジェクト: 2pac/kamailio
/*
 * Query table for specified rows
 * _h: structure representing database connection
 * _k: key names
 * _op: operators
 * _v: values of the keys that must match
 * _c: column names to return
 * _n: number of key=values pairs to compare
 * _nc: number of columns to return
 * _o: order by the specified column
 */
int db_cassa_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
		const db_val_t* _v, const db_key_t* _c, int _n, int _nc,
		const db_key_t _o, db1_res_t** _r)
{
	db1_res_t* db_res = 0;
	int rows_no;
	ColumnVecPtr cassa_result;
	dbcassa_table_p tbc;
	int seckey_len;

	if (!_h || !CON_TABLE(_h) || !_r) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}
	LM_DBG("query table=%s\n", _h->table->s);

	/** Construct and send the query to Cassandra Cluster **/

	cassa_result = cassa_translate_query(_h, _k, _v, _c, _n, _nc, &rows_no);

	if(cassa_result.get() == NULL) {
		LM_ERR("Failed to query Cassandra cluster\n");
		return -1;
	}

	/* compare the number of queried cols with the key cols*/
//	if(no_kc + no_sec_kc < _n) { /* TODO */
		/* filter manually for the rest of the values */
//	}

	db_res = db_new_result();
	if (!db_res) {
		LM_ERR("no memory left\n");
		goto error;
	}
	RES_COL_N(db_res)= _nc;
	if(!db_allocate_columns(db_res, _nc) < 0) {
		LM_ERR("no more memory\n");
		goto error;
	}

	tbc = dbcassa_db_get_table(&CON_CASSA(_h)->db_name, CON_TABLE(_h));
	if(!tbc) {
		LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
		return -1;
	}

	/** Convert the result from Cassandra **/
	/* fill in the columns name and type */
	for(int col = 0; col < _nc; col++) {
		RES_NAMES(db_res)[col] = (str*)pkg_malloc(sizeof(str));
		if (! RES_NAMES(db_res)[col]) {
			LM_ERR("no private memory left\n");
			dbcassa_lock_release(tbc);
			RES_COL_N(db_res) = col;
			db_free_columns(db_res);
			goto error;
		}

		*RES_NAMES(db_res)[col]   = *_c[col];

		/* search the column in table schema to get the type */
		dbcassa_column_p colp = cassa_search_col(tbc, _c[col]);
		if(!colp) {
			LM_ERR("No column with name [%.*s] found\n", _c[col]->len, _c[col]->s);
			dbcassa_lock_release(tbc);
			RES_COL_N(db_res) = col;
			db_free_columns(db_res);
			goto error;
		}
		RES_TYPES(db_res)[col] = colp->type;

		LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(db_res)[col], col,
				RES_NAMES(db_res)[col]->len, RES_NAMES(db_res)[col]->s);
	}
	/* TODO  if all columns asked - take from table schema */
	seckey_len = tbc->seckey_len;
	dbcassa_lock_release(tbc);

	if(!cassa_result->size()) {
		LM_DBG("The query returned no result\n");
		RES_ROW_N(db_res) = 0;
		goto done;
	}

	/* Initialize the row_slices vector for the case with one column and no secondary key */
	if(rows_no == 1) {
		row_slices[0][0]= cassa_result->size();
		row_slices[0][1]= 0;

		if(seckey_len) { /* if the table has a secondary key defined */
			/* pass through the result once to see how many rows there are */
			rows_no = cassa_result_separate_rows(*cassa_result);
			if(rows_no < 0) {
				LM_ERR("Wrong formated column names\n");
				goto error;
			}
		}
	}

	RES_ROW_N(db_res) = rows_no;

	if (db_allocate_rows(db_res) < 0) {
		LM_ERR("could not allocate rows");
		goto error;
	}

	for(int ri=0; ri < rows_no; ri++) {
		if (db_allocate_row(db_res, &(RES_ROWS(db_res)[ri])) != 0) {
			LM_ERR("could not allocate row");
			goto error;
		}

		/* complete the row with the columns */
		for(int col = 0; col< _nc; col++) {
			RES_ROWS(db_res)[ri].values[col].type = RES_TYPES(db_res)[col];
			cassa_convert_result(_c[col], *cassa_result, (ri>0?row_slices[ri-1][0]:0),  row_slices[ri][0],
					row_slices[ri][1], &RES_ROWS(db_res)[ri].values[col]);
		}
	}

done:
	*_r = db_res;
	LM_DBG("Exited with success\n");
	return 0;

error:
	if(db_res)
		db_free_result(db_res);
	return -1;
}
コード例 #8
0
ファイル: domainpolicy.c プロジェクト: adubovikov/kamailio
/*
 * input: rule straight from the DDDS + avp-stack.
 *
 * output: adds found rules to the stack and return
 * 	1 on success
 * 	0 on failure
 */
static int check_rule(str *rule, char *service, int service_len, struct avp_stack *stack) {

    /* for the select */
    db_key_t keys[2];
    db_val_t vals[2];
    db_key_t cols[4]; 
    db1_res_t* res;
    db_row_t* row;
    db_val_t* val;
    int	i;
    char *type;
    int type_len;

    LM_INFO("checking for '%.*s'.\n", rule->len, ZSW(rule->s));

    if ((service_len != 11) || (strncasecmp("d2p+sip:fed", service, 11) && 
	    strncasecmp("d2p+sip:std", service, 11)  && strncasecmp("d2p+sip:dom", service, 11))) {
    	LM_ERR("can only cope with d2p+sip:fed, d2p+sip:std,and d2p+sip:dom "
				"for now (and not %.*s).\n", service_len, service);
	return(0);
    }

    type = service + 8;
    type_len = service_len - 8;

    if (domainpolicy_dbf.use_table(db_handle, &domainpolicy_table) < 0) {
	    LM_ERR("failed to domainpolicy table\n");
	    return -1;
    }

    keys[0]=&domainpolicy_col_rule;
    keys[1]=&domainpolicy_col_type;
    cols[0]=&domainpolicy_col_rule;
    cols[1]=&domainpolicy_col_type;
    cols[2]=&domainpolicy_col_att;
    cols[3]=&domainpolicy_col_val;

    VAL_TYPE(&vals[0]) = DB1_STR;
    VAL_NULL(&vals[0]) = 0;
    VAL_STR(&vals[0]).s = rule->s;
    VAL_STR(&vals[0]).len = rule->len;

    VAL_TYPE(&vals[1]) = DB1_STR;
    VAL_NULL(&vals[1]) = 0;
    VAL_STR(&vals[1]).s = type;
    VAL_STR(&vals[1]).len = type_len;

    /*
     * SELECT rule, att, val from domainpolicy where rule = "..."
     */

    if (domainpolicy_dbf.query(db_handle, keys, 0, vals, cols, 2, 4, 0, &res) < 0
		    ) {
	    LM_ERR("querying database\n");
	    return -1;
    }
    
    LM_INFO("querying database OK\n");

    if (RES_ROW_N(res) == 0) {
	    LM_DBG("rule '%.*s' is not know.\n", 
		rule->len, ZSW(rule->s));
	    domainpolicy_dbf.free_result(db_handle, res);
	    return 0;
    } else {
	    LM_DBG("rule '%.*s' is known\n", rule->len, ZSW(rule->s));

	    row = RES_ROWS(res);

	    for(i = 0; i < RES_ROW_N(res); i++) {
			if (ROW_N(row + i) != 4) {
	    	    LM_ERR("unexpected cell count\n");
				return(-1);
			}

			val = ROW_VALUES(row + i);

			if ((VAL_TYPE(val) != DB1_STRING) || 
				(VAL_TYPE(val+1) != DB1_STRING) ||
				(VAL_TYPE(val+2) != DB1_STRING) ||
				(VAL_TYPE(val+3) != DB1_STRING)) {
					LM_ERR("unexpected cell types\n");
			    return(-1);
			}

			if (VAL_NULL(val+2) || VAL_NULL(val+3)) {
				LM_INFO("db returned NULL values. Fine with us.\n");
				continue;
			}

			LM_INFO("DB returned %s/%s \n",VAL_STRING(val+2),VAL_STRING(val+3));


			if (!stack_push(stack, (char *) VAL_STRING(val+2), 
					(char *) VAL_STRING(val+3))) {
			    return(-1);
			}
	    }
	    domainpolicy_dbf.free_result(db_handle, res);
	    return 1;
    }
}
コード例 #9
0
ファイル: msilo.c プロジェクト: miettal/armadillo420_standard
/**
 * dump message
 */
static int m_dump(struct sip_msg* msg, char* str1, char* str2)
{
	struct to_body to, *pto = NULL;
	db_key_t db_keys[1] = { DB_KEY_RURI };
	db_val_t db_vals[1];
	db_key_t db_cols[] = {	DB_KEY_MID, DB_KEY_FROM, DB_KEY_TO, DB_KEY_BODY,
							DB_KEY_CTYPE, DB_KEY_INC_TIME 
					};
	db_res_t* db_res = NULL;
	int i, db_no_cols = IDX_NO, db_no_keys = 1, *msg_id, mid, n;
	char hdr_buf[1024], body_buf[1024];

	str str_vals[IDX_NO], hdr_str , body_str;
	time_t rtime;

	DBG("MSILO:m_dump: ------------ start ------------\n");
	hdr_str.s=hdr_buf;
	hdr_str.len=1024;
	body_str.s=body_buf;
	body_str.len=1024;
	
	// check for TO header 
	if(parse_headers(msg, HDR_TO, 0)==-1 || !msg->to || !msg->to->body.s)
	{
		LOG(L_ERR,"MSILO:m_dump: ERROR cannot find TO HEADER!\n");
		goto error;
	}

	// check TO header
	if(msg->to->parsed != NULL)
	{
		pto = (struct to_body*)msg->to->parsed;
		DBG("MSILO:m_dump: 'To' header ALREADY PARSED: <%.*s>\n",
			pto->uri.len, pto->uri.s );	
	}
	else
	{
		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_dump: 'To' header NOT parsed\n");
			goto error;
		}
		pto = &to;
	}

	/**
	 * check if has expires=0 (REGISTER)
	 */
	if(parse_headers(msg, HDR_EXPIRES, 0) >= 0)
	{
		//check 'expires' > 0
		if(msg->expires && msg->expires->body.len > 0)
		{
			i = atoi(msg->expires->body.s);
			if(i <= 0)
			{ // user goes offline
				DBG("MSILO:m_dump: user <%.*s> goes offline - expires=%d\n",
						pto->uri.len, pto->uri.s, i);
				goto error;
			}
			else
				DBG("MSILO:m_dump: user <%.*s> online - expires=%d\n",
						pto->uri.len, pto->uri.s, i);
		}
	}
	else
	{
		DBG("MSILO:m_dump: 'exprires' threw error at parsing\n");
		goto error;
	}

	db_vals[0].type = DB_STR;
	db_vals[0].nul = 0;
	db_vals[0].val.str_val.s = pto->uri.s;
	db_vals[0].val.str_val.len = pto->uri.len;

	if((db_query(db_con,db_keys,NULL,db_vals,db_cols,db_no_keys,db_no_cols,
			NULL,&db_res)==0) && (RES_ROW_N(db_res) > 0))
	{
		DBG("MSILO:m_dump: dumping [%d] messages for <%.*s>!!!\n", 
				RES_ROW_N(db_res), pto->uri.len, pto->uri.s);

		for(i = 0; i < RES_ROW_N(db_res); i++) 
		{
			mid =  RES_ROWS(db_res)[i].values[DUMP_IDX_MID].val.int_val;
			if(msg_list_check_msg(ml, mid))
			{
				DBG("MSILO:m_dump: message[%d] mid=%d already sent.\n", 
					i, mid);
				continue;
			}
			
			memset(str_vals, 0, IDX_NO*sizeof(str));
			SET_STR_VAL(str_vals[STR_IDX_FROM], db_res, i, DUMP_IDX_FROM);
			SET_STR_VAL(str_vals[STR_IDX_TO], db_res, i, DUMP_IDX_TO);
			SET_STR_VAL(str_vals[STR_IDX_BODY], db_res, i, DUMP_IDX_BODY);
			SET_STR_VAL(str_vals[STR_IDX_CTYPE], db_res, i, DUMP_IDX_CTYPE);
			
			hdr_str.len = 1024;		
			if(m_build_headers(&hdr_str, str_vals[STR_IDX_CTYPE],
					str_vals[STR_IDX_FROM]) < 0)
			{
				DBG("MSILO:m_dump: headers bulding failed!!!\n");
				if (db_free_query(db_con, db_res) < 0)
					DBG("MSILO:m_dump: Error while freeing result of"
						" query\n");
				msg_list_set_flag(ml, mid, MS_MSG_ERRO);
				goto error;
			}
			
			if((msg_id = shm_malloc(sizeof(int))) == 0)
			{
				DBG("MSILO:m_dump: no more share memory!");
				if (db_free_query(db_con, db_res) < 0)
					DBG("MSILO:m_dump: Error while freeing result of"
						" query\n");
				msg_list_set_flag(ml, mid, MS_MSG_ERRO);
				goto error;
			}
						
			*msg_id = mid;
			
			DBG("MSILO:m_dump: msg [%d-%d] for: %.*s\n", i+1, *msg_id,
					pto->uri.len, pto->uri.s);
			
			/** sending using TM function: t_uac */

			body_str.len = 1024;
			rtime = 
				(time_t)RES_ROWS(db_res)[i].values[DUMP_IDX_INC_TIME].val.int_val;
			n = m_build_body(&body_str, rtime, str_vals[STR_IDX_BODY]);
			if(n<0)
				DBG("MSILO:m_dump: sending simple body\n");
			else
				DBG("MSILO:m_dump: sending composed body\n");
			
			//tmb.t_uac(&msg_type, &pto->uri, &hdr_str,
			//	&body_str, &str_vals[STR_IDX_FROM],
			//	m_tm_callback, (void*)msg_id, 0
			//);
			
			tmb.t_request(&msg_type,  /* Type of the message */
					&pto->uri,               /* Request-URI */
					&str_vals[STR_IDX_TO],   /* To */
					&str_vals[STR_IDX_FROM], /* From */
					&hdr_str,         /* Optional headers including CRLF */
					(n<0)?&str_vals[STR_IDX_BODY]:&body_str, /* Message body */
					m_tm_callback,    /* Callback function */
					(void*)msg_id     /* Callback parameter */
				);
		}
	}
	else
		DBG("MSILO:m_dump: no stored message for <%.*s>!\n", pto->uri.len,
					pto->uri.s);
	/**
	 * Free the result because we don't need it
	 * anymore
	 */
	if (db_free_query(db_con, db_res) < 0)
		DBG("MSILO:m_dump: Error while freeing result of query\n");

	return 1;
error:
	return -1;
}
コード例 #10
0
/*!
 * \brief Convert rows from mongodb to db API representation
 * \param _h database connection
 * \param _r database result set
 * \return 0 on success, negative on failure
 */
static int db_mongodb_convert_bson(const db1_con_t* _h, db1_res_t* _r,
		int _row, const bson_t *_rdoc)
{
	static str dummy_string = {"", 0};
	int col;
	db_mongodb_result_t *mgres;
	const char *colname;
	bson_type_t coltype;
	bson_iter_t riter;
	bson_iter_t citer;
	bson_iter_t *piter;
	db_val_t* dval;
	uint32_t i32tmp;
    bson_subtype_t subtype;
	bson_t *cdoc;

	mgres = (db_mongodb_result_t*)RES_PTR(_r);
	if(mgres->nrcols==0) {
		LM_ERR("no fields to convert\n");
		return -1;
	}
	if(mgres->colsdoc==NULL) {
		cdoc = (bson_t*)_rdoc;
	} else {
		cdoc = (bson_t*)mgres->colsdoc;
	}

	if (!bson_iter_init (&citer, cdoc)) {
		LM_ERR("failed to initialize columns iterator\n");
		return -3;
	}
	if(mgres->colsdoc) {
		if (!bson_iter_init (&riter, _rdoc)) {
			LM_ERR("failed to initialize result iterator\n");
			return -3;
		}
	}
	if (db_allocate_row(_r, &(RES_ROWS(_r)[_row])) != 0) {
		LM_ERR("could not allocate row: %d\n", _row);
		return -2;
	}
	col = 0;
	while (bson_iter_next (&citer)) {
		if(col >= RES_COL_N(_r)) {
			LM_ERR("invalid number of columns (%d/%d)\n", col, RES_COL_N(_r));
			return -4;
		}

		colname = bson_iter_key (&citer);
		LM_DBG("looking for field[%d] named: %s\n", col, colname);
		if(mgres->colsdoc) {
			if(!bson_iter_find(&riter, colname)) {
				LM_ERR("field [%s] not found in result iterator\n",
						colname);
				return -4;
			}
			piter = &riter;
		} else {
			piter = &citer;
		}
		coltype = bson_iter_type(piter);

		dval = &(ROW_VALUES(&(RES_ROWS(_r)[_row]))[col]);
		VAL_TYPE(dval) = RES_TYPES(_r)[col];

		switch(coltype) {
			case BSON_TYPE_BOOL:
				VAL_INT(dval) = (int)bson_iter_bool (piter);
				break;
			case BSON_TYPE_INT32:
				VAL_INT(dval) = bson_iter_int32 (piter);
				break;
			case BSON_TYPE_TIMESTAMP:
				bson_iter_timestamp (piter,
						(uint32_t*)&VAL_INT(dval), &i32tmp);
				break;

			case BSON_TYPE_INT64:
				VAL_BIGINT(dval) = bson_iter_int64 (piter);
				break;

			case BSON_TYPE_DOUBLE:
				VAL_DOUBLE(dval) = bson_iter_double (piter);
				break;

			case BSON_TYPE_DATE_TIME:
				VAL_TIME(dval) = (time_t)(bson_iter_date_time (piter)/1000);
				break;

			case BSON_TYPE_BINARY:
				bson_iter_binary (piter, &subtype,
                  (uint32_t*)&VAL_BLOB(dval).len, (const uint8_t**)&VAL_BLOB(dval).s);
				break;

			case BSON_TYPE_UTF8:
				VAL_STRING(dval) = (char*)bson_iter_utf8 (piter, &i32tmp);
				break;

			case BSON_TYPE_OID:
				break;

			case BSON_TYPE_NULL:
				memset(dval, 0, sizeof(db_val_t));
				/* Initialize the string pointers to a dummy empty
				 * string so that we do not crash when the NULL flag
				 * is set but the module does not check it properly
				 */
				VAL_STRING(dval) = dummy_string.s;
				VAL_STR(dval) = dummy_string;
				VAL_BLOB(dval) = dummy_string;
				VAL_TYPE(dval) = RES_TYPES(_r)[col];
				VAL_NULL(dval) = 1;
				break;

#if 0
			case BSON_TYPE_EOD:
			case BSON_TYPE_DOCUMENT:
			case BSON_TYPE_ARRAY:
			case BSON_TYPE_UNDEFINED:
			case BSON_TYPE_REGEX:
			case BSON_TYPE_DBPOINTER:
			case BSON_TYPE_CODE:
			case BSON_TYPE_SYMBOL:
			case BSON_TYPE_CODEWSCOPE:
			case BSON_TYPE_MAXKEY:
			case BSON_TYPE_MINKEY:
#endif

			default:
				LM_WARN("unhandled data type column (%.*s) type id (%d), "
						"use DB1_STRING as default\n", RES_NAMES(_r)[col]->len,
						RES_NAMES(_r)[col]->s, coltype);
				RES_TYPES(_r)[col] = DB1_STRING;
				break;
		}

		LM_DBG("RES_NAMES(%p)[%d]=[%.*s] (%d)\n", RES_NAMES(_r)[col], col,
				RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, coltype);
		col++;
	}
	return 0;
}
コード例 #11
0
ファイル: route_db.c プロジェクト: Enigmedia/opensips
/**
 * Loads the routing data from the database given in global
 * variable db_url and stores it in routing tree rd.
 *
 * @param rd Pointer to the route data tree where the routing data
 * shall be loaded into
 *
 * @return 0 means ok, -1 means an error occured
 *
 */
int load_route_data(struct rewrite_data * rd) {
	db_res_t * res = NULL;
	db_row_t * row = NULL;
	int i, ret;
	int carrier_count = 0;
	struct carrier * carriers = NULL, * tmp = NULL;
	static str query_str;
	str tmp_carrier;
	str tmp_domain;
	str tmp_scan_prefix;
	str tmp_rewrite_host;
	str tmp_rewrite_prefix;
	str tmp_rewrite_suffix;
	str tmp_host_name;
	str tmp_reply_code;
	str tmp_next_domain;
	str tmp_comment;
	int no_rows=10;

	if( (strlen("SELECT DISTINCT  FROM  WHERE = ")
			+ db_table.len + columns[COL_DOMAIN]->len
			+ columns[COL_CARRIER]->len + 20) >  QUERY_LEN) {
		LM_ERR("query too long\n");
		return -1;
	}

	if((carrier_count = store_carriers(&carriers)) <= 0){
		LM_ERR("error while retrieving carriers\n");
		goto errout;
	}

	if ((rd->carriers = shm_malloc(sizeof(struct carrier_tree *) * carrier_count)) == NULL) {
		LM_ERR("out of shared memory\n");
		goto errout;
	}
	memset(rd->carriers, 0, sizeof(struct carrier_tree *) * carrier_count);
	rd->tree_num = carrier_count;

	tmp = carriers;
	for (i=0; i<carrier_count; i++) {
		memset(query, 0, QUERY_LEN);
		ret = snprintf(query, QUERY_LEN, "SELECT DISTINCT %.*s FROM %.*s WHERE %.*s=%i",
		columns[COL_DOMAIN]->len, columns[COL_DOMAIN]->s, db_table.len, db_table.s,
		columns[COL_CARRIER]->len, columns[COL_CARRIER]->s, tmp->id);
		if (ret < 0) {
			LM_ERR("error in snprintf");
			goto errout;
		}
		query_str.s = query;
		query_str.len = ret;

		if (dbf.raw_query(dbh, &query_str, &res) < 0) {
			LM_ERR("Failed to query database.\n");
			goto errout;
		}
		LM_INFO("name %s, id %i, trees: %i\n", tmp->name, tmp->id, RES_ROW_N(res));
		tmp_carrier.s=tmp->name;
		tmp_carrier.len=strlen(tmp_carrier.s);
		if (add_carrier_tree(&tmp_carrier, tmp->id, rd, RES_ROW_N(res)) == NULL) {
			LM_ERR("can't add carrier %s\n", tmp->name);
			goto errout;
		}
		dbf.free_result(dbh, res);
		res = NULL;
		tmp = tmp->next;
	}

	if (dbf.use_table(dbh, &db_table) < 0) {
		LM_ERR("Cannot set database table '%.*s'.\n", db_table.len, db_table.s);
		return -1;
	}

	if (DB_CAPABILITY(dbf, DB_CAP_FETCH)) {
		if (dbf.query(dbh, NULL, NULL, NULL, (db_key_t *) columns, 0, COLUMN_NUM, NULL, NULL) < 0) {
			LM_ERR("Failed to query database to prepare fetchrow.\n");
			return -1;
		}
		no_rows = estimate_available_rows( 4+64+64+64+4+4+4+64+4+64+64+128,
			COLUMN_NUM);
		if (no_rows==0) no_rows = 10;
		if(dbf.fetch_result(dbh, &res, no_rows) < 0) {
			LM_ERR("Fetching rows failed\n");
			return -1;
		}
	} else {
		if (dbf.query(dbh, NULL, NULL, NULL, (db_key_t *)columns, 0, COLUMN_NUM, NULL, &res) < 0) {
			LM_ERR("Failed to query database.\n");
			return -1;
		}
	}
	int n = 0;
	do {
		LM_DBG("loading, cycle %d", n++);
			for (i = 0; i < RES_ROW_N(res); ++i) {
			row = &RES_ROWS(res)[i];
			tmp_domain.s=(char *)row->values[COL_DOMAIN].val.string_val;
			tmp_scan_prefix.s=(char *)row->values[COL_SCAN_PREFIX].val.string_val;
			tmp_rewrite_host.s=(char *)row->values[COL_REWRITE_HOST].val.string_val;
			tmp_rewrite_prefix.s=(char *)row->values[COL_REWRITE_PREFIX].val.string_val;
			tmp_rewrite_suffix.s=(char *)row->values[COL_REWRITE_SUFFIX].val.string_val;
			tmp_comment.s=(char *)row->values[COL_COMMENT].val.string_val;
			if (tmp_domain.s==NULL) tmp_domain.s="";
			if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
			if (tmp_rewrite_host.s==NULL) tmp_rewrite_host.s="";
			if (tmp_rewrite_prefix.s==NULL) tmp_rewrite_prefix.s="";
			if (tmp_rewrite_suffix.s==NULL) tmp_rewrite_suffix.s="";
			if (tmp_comment.s==NULL) tmp_comment.s="";
			tmp_domain.len=strlen(tmp_domain.s);
			tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
			tmp_rewrite_host.len=strlen(tmp_rewrite_host.s);
			tmp_rewrite_prefix.len=strlen(tmp_rewrite_prefix.s);
			tmp_rewrite_suffix.len=strlen(tmp_rewrite_suffix.s);
			tmp_comment.len=strlen(tmp_comment.s);
			if (add_route(rd,
					row->values[COL_CARRIER].val.int_val,
					&tmp_domain,
					&tmp_scan_prefix,
					row->values[COL_FLAGS].val.int_val,
					row->values[COL_MASK].val.int_val,
					0,
					row->values[COL_PROB].val.double_val,
					&tmp_rewrite_host,
					row->values[COL_STRIP].val.int_val,
					&tmp_rewrite_prefix,
					&tmp_rewrite_suffix,
					1,
					0,
					-1,
					NULL,
					&tmp_comment) == -1) {
				goto errout;
			}
		}
		if (DB_CAPABILITY(dbf, DB_CAP_FETCH)) {
			if(dbf.fetch_result(dbh, &res, no_rows) < 0) {
				LM_ERR("fetching rows failed\n");
				dbf.free_result(dbh, res);
				return -1;
			}
		} else {
			break;
		}
	} while(RES_ROW_N(res) > 0);

	dbf.free_result(dbh, res);
	res = NULL;

	if (dbf.use_table(dbh, &db_failure_table) < 0) {
		LM_ERR("cannot set database table '%.*s'.\n",
				db_failure_table.len, db_failure_table.s);
		return -1;
	}
	if (dbf.query(dbh, NULL, NULL, NULL, (db_key_t *)failure_columns, 0,
								FAILURE_COLUMN_NUM, NULL, &res) < 0) {
		LM_ERR("failed to query database.\n");
		return -1;
	}
	for (i = 0; i < RES_ROW_N(res); ++i) {
		row = &RES_ROWS(res)[i];
		tmp_domain.s=(char *)row->values[FCOL_DOMAIN].val.string_val;
		tmp_scan_prefix.s=(char *)row->values[FCOL_SCAN_PREFIX].val.string_val;
		tmp_host_name.s=(char *)row->values[FCOL_HOST_NAME].val.string_val;
		tmp_reply_code.s=(char *)row->values[FCOL_REPLY_CODE].val.string_val;
		tmp_next_domain.s=(char *)row->values[FCOL_NEXT_DOMAIN].val.string_val;
		tmp_comment.s=(char *)row->values[FCOL_COMMENT].val.string_val;
		if (tmp_domain.s==NULL) tmp_domain.s="";
		if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
		if (tmp_host_name.s==NULL) tmp_host_name.s="";
		if (tmp_reply_code.s==NULL) tmp_reply_code.s="";
		if (tmp_next_domain.s==NULL) tmp_next_domain.s="";
		if (tmp_comment.s==NULL) tmp_comment.s="";
		tmp_domain.len=strlen(tmp_domain.s);
		tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
		tmp_host_name.len=strlen(tmp_host_name.s);
		tmp_reply_code.len=strlen(tmp_reply_code.s);
		tmp_next_domain.len=strlen(tmp_next_domain.s);
		tmp_comment.len=strlen(tmp_comment.s);
		if (add_failure_route(rd,
				row->values[FCOL_CARRIER].val.int_val,
				&tmp_domain,
				&tmp_scan_prefix,
				&tmp_host_name,
				&tmp_reply_code,
				row->values[FCOL_FLAGS].val.int_val,
				row->values[FCOL_MASK].val.int_val,
				&tmp_next_domain,
				&tmp_comment) == -1) {
			goto errout;
		}
	}

	destroy_carriers(carriers);
	dbf.free_result(dbh, res);
	return 0;

errout:
	destroy_carriers(carriers);
	if (res) {
		dbf.free_result(dbh, res);
	}
	return -1;
}
コード例 #12
0
ファイル: res.c プロジェクト: AndreiPlesa/opensips
/*
 * Get rows and convert it from oracle to db API representation
 */
static int get_rows(ora_con_t* con, db_res_t* _r, OCIStmt* _c, dmap_t* _d)
{
	ub4 rcnt;
	sword status;
	unsigned n = RES_COL_N(_r);

	memcpy(_d->len, _d->ilen, sizeof(_d->len[0]) * n);

	// timelimited operation
	status = begin_timelimit(con, 0);
	if (status != OCI_SUCCESS) goto ora_err;
	do status = OCIStmtFetch2(_c, con->errhp, 1, OCI_FETCH_NEXT, 0,
		OCI_DEFAULT);
	while (wait_timelimit(con, status));
	if (done_timelimit(con, status)) goto stop_load;
	if (status != OCI_SUCCESS) {
		if (status != OCI_NO_DATA)
			goto ora_err;

		RES_ROW_N(_r) = 0;
		RES_ROWS(_r) = NULL;
		return 0;
	}

	status = OCIAttrGet(_c, OCI_HTYPE_STMT, &rcnt, NULL,
		OCI_ATTR_CURRENT_POSITION, con->errhp);
	if (status != OCI_SUCCESS) goto ora_err;
	if (!rcnt) {
		LM_ERR("lastpos==0\n");
		goto stop_load;
	}

	RES_ROW_N(_r) = rcnt;
	if (db_allocate_rows( _r, rcnt)!=0) {
		LM_ERR("no private memory left\n");
		return -1;
	}

	while ( 1 ) {
		if (convert_row(_r, &RES_ROWS(_r)[--rcnt], _d) < 0) {
			LM_ERR("error convert row\n");
			goto stop_load;
		}

		if (!rcnt)
			return 0;

		memcpy(_d->len, _d->ilen, sizeof(_d->len[0]) * n);
		// timelimited operation
		status = begin_timelimit(con, 0);
		if (status != OCI_SUCCESS) goto ora_err;
		do status = OCIStmtFetch2(_c, con->errhp, 1, OCI_FETCH_PRIOR, 0,
			OCI_DEFAULT);
		while (wait_timelimit(con, status));
		if (done_timelimit(con, status)) goto stop_load;
		if (status != OCI_SUCCESS) break;
	}
ora_err:
	LM_ERR("driver: %s\n", db_oracle_error(con, status));
stop_load:
	db_free_rows(_r);
	RES_ROW_N(_r) = 0;	/* TODO: skipped in db_res.c :) */
	return -3;
}
コード例 #13
0
ファイル: presence.c プロジェクト: AlessioCasco/kamailio
static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
{
	db_key_t query_cols[5], db_cols[3];
	db_val_t query_vals[5], db_vals[3];
	db_key_t result_cols[24];
	int n_query_cols=0, n_result_cols=0, n_update_cols=0;
	int event_col, pres_uri_col, watcher_user_col, watcher_domain_col;
	int r_pres_uri_col,r_to_user_col,r_to_domain_col;
	int r_from_user_col,r_from_domain_col,r_callid_col;
	int r_to_tag_col,r_from_tag_col,r_sockinfo_col;
	int r_event_id_col,r_local_contact_col,r_contact_col;
	int r_record_route_col, r_reason_col;
	int r_event_col, r_local_cseq_col, r_remote_cseq_col;
	int r_status_col, r_version_col;
	int r_expires_col, r_watcher_user_col, r_watcher_domain_col;
	db1_res_t *result= NULL;
 	db_val_t *row_vals;
	db_row_t *rows;
	int nr_rows, loop;
	subs_t s, *cs;
	str ev_sname;

	if(pa_db == NULL)
	{
		LM_ERR("null database connection\n");
		return(-1);
	}

	if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0) 
	{
		LM_ERR("use table failed\n");
		return(-1);
	}

	query_cols[event_col=n_query_cols]= &str_event_col;
	query_vals[event_col].nul= 0;
	query_vals[event_col].type= DB1_STR;
	query_vals[event_col].val.str_val= subs->event->name ;
	n_query_cols++;

	query_cols[pres_uri_col=n_query_cols]= &str_presentity_uri_col;
	query_vals[pres_uri_col].nul= 0;
	query_vals[pres_uri_col].type= DB1_STR;
	query_vals[pres_uri_col].val.str_val= subs->pres_uri;
	n_query_cols++;

	query_cols[watcher_user_col=n_query_cols]= &str_watcher_username_col;
	query_vals[watcher_user_col].nul= 0;
	query_vals[watcher_user_col].type= DB1_STR;
	query_vals[watcher_user_col].val.str_val= subs->watcher_user;
	n_query_cols++;

	query_cols[watcher_domain_col=n_query_cols]= &str_watcher_domain_col;
	query_vals[watcher_domain_col].nul= 0;
	query_vals[watcher_domain_col].type= DB1_STR;
	query_vals[watcher_domain_col].val.str_val= subs->watcher_domain;
	n_query_cols++;


	result_cols[r_to_user_col=n_result_cols++] = &str_to_user_col;
	result_cols[r_to_domain_col=n_result_cols++] = &str_to_domain_col;
	result_cols[r_from_user_col=n_result_cols++] = &str_from_user_col;
	result_cols[r_from_domain_col=n_result_cols++] = &str_from_domain_col;
	result_cols[r_watcher_user_col=n_result_cols++] = &str_watcher_username_col;
	result_cols[r_watcher_domain_col=n_result_cols++] = &str_watcher_domain_col;
	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
	result_cols[r_sockinfo_col=n_result_cols++] = &str_socket_info_col;
	result_cols[r_event_id_col=n_result_cols++] = &str_event_id_col;
	result_cols[r_local_contact_col=n_result_cols++] = &str_local_contact_col;
	result_cols[r_record_route_col=n_result_cols++] = &str_record_route_col;
	result_cols[r_reason_col=n_result_cols++] = &str_reason_col;
	result_cols[r_local_cseq_col=n_result_cols++] = &str_local_cseq_col;
	result_cols[r_version_col=n_result_cols++] = &str_version_col;
	result_cols[r_expires_col=n_result_cols++] = &str_expires_col;
	result_cols[r_event_col=n_result_cols++] = &str_event_col;
	result_cols[r_pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
	result_cols[r_contact_col=n_result_cols++] = &str_contact_col;

	/* these ones are unused for some reason !!! */
	result_cols[r_remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
	result_cols[r_status_col=n_result_cols++] = &str_status_col;
	/*********************************************/

	if(pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols, 
				n_query_cols, n_result_cols, 0, &result )< 0)
	{
		LM_ERR("Can't query db\n");
		if(result) pa_dbf.free_result(pa_db, result);
		return(-1);
	}

	if(result == NULL) return(-1);

	nr_rows = RES_ROW_N(result);

	LM_DBG("found %d matching dialogs\n", nr_rows);

	if (nr_rows <= 0)
	{
		pa_dbf.free_result(pa_db, result);
		return 0;
	}

	rows = RES_ROWS(result);
	/* get the results and fill in return data structure */
	for (loop=0; loop <nr_rows; loop++)
	{
		row_vals = ROW_VALUES(&rows[loop]);

		memset(&s, 0, sizeof(subs_t));
		s.status= subs->status;

		s.reason.s= subs->reason.s;
		s.reason.len= s.reason.s?strlen(s.reason.s):0;	//>>>>>>>>>>

		s.pres_uri.s= (char*)row_vals[r_pres_uri_col].val.string_val;
		s.pres_uri.len= s.pres_uri.s?strlen(s.pres_uri.s):0;

		s.to_user.s= (char*)row_vals[r_to_user_col].val.string_val;
		s.to_user.len= s.to_user.s?strlen(s.to_user.s):0;

		s.to_domain.s= (char*)row_vals[r_to_domain_col].val.string_val;
		s.to_domain.len= s.to_domain.s?strlen(s.to_domain.s):0;
		
		s.from_user.s= (char*)row_vals[r_from_user_col].val.string_val;
		s.from_user.len= s.from_user.s?strlen(s.from_user.s):0;
		
		s.from_domain.s= (char*)row_vals[r_from_domain_col].val.string_val;
		s.from_domain.len= s.from_domain.s?strlen(s.from_domain.s):0;
		
		s.watcher_user.s= (char*)row_vals[r_watcher_user_col].val.string_val;
		s.watcher_user.len= s.watcher_user.s?strlen(s.watcher_user.s):0;
		
		s.watcher_domain.s= (char*)row_vals[r_watcher_domain_col].val.string_val;
		s.watcher_domain.len= s.watcher_domain.s?strlen(s.watcher_domain.s):0;

		s.event_id.s=(char*)row_vals[r_event_id_col].val.string_val;
		s.event_id.len= (s.event_id.s)?strlen(s.event_id.s):0;
	
		s.to_tag.s= (char*)row_vals[r_to_tag_col].val.string_val;
		s.to_tag.len= s.to_tag.s?strlen(s.to_tag.s):0;
		
		s.from_tag.s= (char*)row_vals[r_from_tag_col].val.string_val; 
		s.from_tag.len= s.from_tag.s?strlen(s.from_tag.s):0;
		
		s.callid.s= (char*)row_vals[r_callid_col].val.string_val;
		s.callid.len= s.callid.s?strlen(s.callid.s):0;
		
		s.record_route.s=  (char*)row_vals[r_record_route_col].val.string_val;
		s.record_route.len= (s.record_route.s)?strlen(s.record_route.s):0;

		s.contact.s= (char*)row_vals[r_contact_col].val.string_val;
		s.contact.len= s.contact.s?strlen(s.contact.s):0;
		
		s.sockinfo_str.s = (char*)row_vals[r_sockinfo_col].val.string_val;
		s.sockinfo_str.len = s.sockinfo_str.s?strlen(s.sockinfo_str.s):0;

		s.local_contact.s = (char*)row_vals[r_local_contact_col].val.string_val;
		s.local_contact.len = s.local_contact.s?strlen(s.local_contact.s):0;

		ev_sname.s= (char*)row_vals[r_event_col].val.string_val;
		ev_sname.len= ev_sname.s?strlen(ev_sname.s):0;
		
		s.event = contains_event(&ev_sname, NULL);

		if(s.event == NULL)
		{
			LM_ERR("event not found and set to NULL\n");
		}
		
		s.local_cseq = row_vals[r_local_cseq_col].val.int_val;

		s.expires = row_vals[r_expires_col].val.int_val;

		if( s.expires > (int)time(NULL) + expires_offset)
		    s.expires -= (int)time(NULL);
		else
		    s.expires = 0;

		s.version = row_vals[r_version_col].val.int_val;

		cs = mem_copy_subs(&s, PKG_MEM_TYPE);
		if (cs == NULL)
		{
			LM_ERR("while copying subs_t structure\n");
			/* tidy up and return */
			pa_dbf.free_result(pa_db, result);
			return(-1);
		}
		cs->local_cseq++;
		cs->next= (*subs_array);
		(*subs_array)= cs;

		printf_subs(cs);
	}

	pa_dbf.free_result(pa_db, result);

	if (pres_notifier_processes == 0 && subs->status == TERMINATED_STATUS)
	{
		/* delete the records */
		if(pa_dbf.delete(pa_db, query_cols, 0, query_vals, n_query_cols)< 0)
		{
			LM_ERR("sql delete failed\n");
			return(-1);
		}

		return(0);
	}

	/* otherwise we update the records */
	db_cols[n_update_cols] = &str_status_col; 
	db_vals[n_update_cols].type = DB1_INT;
	db_vals[n_update_cols].nul = 0; 
	db_vals[n_update_cols].val.int_val = subs->status;
	n_update_cols++;
 
	db_cols[n_update_cols] = &str_reason_col; 
	db_vals[n_update_cols].type = DB1_STR;
	db_vals[n_update_cols].nul = 0; 
	db_vals[n_update_cols].val.str_val= subs->reason;
	n_update_cols++;

	db_cols[n_update_cols] = &str_updated_col; 
	db_vals[n_update_cols].type = DB1_INT;
	db_vals[n_update_cols].nul = 0;
	if (subs->callid.len == 0 || subs->from_tag.len == 0)
	{
		db_vals[n_update_cols].val.int_val = (int) ((rand() / (RAND_MAX + 1.0)) *
			  (pres_waitn_time * pres_notifier_poll_rate
					* pres_notifier_processes));
	} else {
		db_vals[n_update_cols].val.int_val = 
			core_case_hash(&subs->callid, &subs->from_tag, 0) %
				  (pres_waitn_time * pres_notifier_poll_rate
					* pres_notifier_processes);
	}
	n_update_cols++;


	if(pa_dbf.update(pa_db, query_cols, 0, query_vals,
				db_cols,db_vals,n_query_cols,n_update_cols) < 0)
	{
		LM_ERR("DB update failed\n");
		return(-1);
	}

	return(0);
}
コード例 #14
0
ファイル: ul_db_handle.c プロジェクト: kiryu/kamailio
int load_data(db_func_t * dbf, db1_con_t * dbh, ul_db_handle_t * handle, int id){
	db1_res_t *res;
	db_row_t *row;
	db_key_t cols[7];
	db_key_t keys[2];
	db_val_t key_vals[2];
	db_op_t op[2];
	db_key_t order;
	int i, ret = 0;

	if(!dbf || !dbh || !handle){
		LM_ERR("NULL-Pointer in Parameter\n");
		return -1;
	}

	memset(handle, 0, sizeof(ul_db_handle_t));
	
	cols[0] = &num_col;
	cols[1] = &url_col;
	cols[2] = &status_col;
	cols[3] = &failover_time_col;
	cols[4] = &spare_col;
	cols[5] = &error_col;
	cols[6] = &risk_group_col;
	
	order = &num_col;

	keys[0] = &id_col;
	op[0] = OP_EQ;
	key_vals[0].type = DB1_INT;
	key_vals[0].nul = 0;
	key_vals[0].val.int_val = id;
	
	if(dbf->use_table(dbh, &reg_table) < 0){
		LM_ERR("could't use table.\n");
		return -1;
	}
	if(dbf->query(dbh, keys, op, key_vals, cols, 1, 7, order, &res) < 0){
		LM_ERR("error while doing db query.\n");
		return -1;
	}
	if(RES_ROW_N(res) < DB_NUM) {
		LM_ERR("keys have too few location databases\n");
		ret = -1;
		goto ret;
	}

	handle->id = id;
	
	for(i=0; i<DB_NUM; i++) {
		row = RES_ROWS(res) + i;
		handle->db[i].no = (int)VAL_INT(ROW_VALUES(row));
		if(VAL_NULL(ROW_VALUES(row) + 1)){
			LM_ERR("Weird: Empty database URL\n");
			ret = -1;
			goto ret;
		}
		if(strlen((char *)VAL_STRING(ROW_VALUES(row) + 1)) >= (UL_DB_URL_LEN - 1)){
			LM_ERR("weird: very large URL (%d Bytes)\n",
					(int)(strlen((char *)VAL_STRING(ROW_VALUES(row) + 1)) + 1));
			ret = -1;
			goto ret;
		}
		strcpy(handle->db[i].url.s, (char *)VAL_STRING(ROW_VALUES(row) + 1));
		handle->db[i].url.len = strlen(handle->db[i].url.s);
		handle->db[i].status = (int)VAL_INT(ROW_VALUES(row) + 2);
		handle->db[i].failover_time = VAL_TIME (ROW_VALUES(row) + 3);
		handle->db[i].spare = VAL_INT (ROW_VALUES(row) + 4);
		handle->db[i].errors = VAL_INT (ROW_VALUES(row) + 5);
		handle->db[i].rg = VAL_INT (ROW_VALUES(row) + 6);
	}
ret:
	dbf->free_result(dbh, res);
	return ret;
}
コード例 #15
0
ファイル: authorize.c プロジェクト: mehulsbhatt/voip-foip
static inline int get_ha1(struct username* _username, str* _domain,
			  const str* _table, char* _ha1, db1_res_t** res)
{
	struct aaa_avp *cred;
	db_key_t keys[2];
	db_val_t vals[2];
	db_key_t *col;
	str result;

	int n, nc;

	col = pkg_malloc(sizeof(*col) * (credentials_n + 1));
	if (col == NULL) {
		LM_ERR("no more pkg memory\n");
		return -1;
	}

	keys[0] = &user_column;
	keys[1] = &domain_column;
	/* should we calculate the HA1, and is it calculated with domain? */
	col[0] = (_username->domain.len && !calc_ha1) ?
		(&pass_column_2) : (&pass_column);

	for (n = 0, cred=credentials; cred ; n++, cred=cred->next) {
		col[1 + n] = &cred->attr_name;
	}

	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB1_STR;
	VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;

	VAL_STR(vals).s = _username->user.s;
	VAL_STR(vals).len = _username->user.len;

	if (_username->domain.len) {
		VAL_STR(vals + 1) = _username->domain;
	} else {
		VAL_STR(vals + 1) = *_domain;
	}

	n = (use_domain ? 2 : 1);
	nc = 1 + credentials_n;
	if (auth_dbf.use_table(auth_db_handle, _table) < 0) {
		LM_ERR("failed to use_table\n");
		pkg_free(col);
		return -1;
	}

	if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0, res) < 0) {
		LM_ERR("failed to query database\n");
		pkg_free(col);
		return -1;
	}
	pkg_free(col);

	if (RES_ROW_N(*res) == 0) {
		LM_DBG("no result for user \'%.*s@%.*s\'\n",
				_username->user.len, ZSW(_username->user.s),
			(use_domain ? (_domain->len) : 0), ZSW(_domain->s));
		return 1;
	}

	result.s = (char*)ROW_VALUES(RES_ROWS(*res))[0].val.string_val;
	result.len = strlen(result.s);

	if (calc_ha1) {
		/* Only plaintext passwords are stored in database,
		 * we have to calculate HA1 */
		auth_api.calc_HA1(HA_MD5, &_username->whole, _domain, &result,
				0, 0, _ha1);
		LM_DBG("HA1 string calculated: %s\n", _ha1);
	} else {
		memcpy(_ha1, result.s, result.len);
		_ha1[result.len] = '\0';
	}

	return 0;
}
コード例 #16
0
ファイル: uac_reg.c プロジェクト: DileepNunna/kamailio
int uac_reg_load_db(void)
{
	db1_con_t *reg_db_con = NULL;
	db_func_t reg_dbf;
	reg_uac_t reg;
	db_key_t db_cols[10] = {
		&l_uuid_column,
		&l_username_column,
		&l_domain_column,
		&r_username_column,
		&r_domain_column,
		&realm_column,
		&auth_username_column,
		&auth_password_column,
		&auth_proxy_column,
		&expires_column
	};
	db1_res_t* db_res = NULL;
	int i, ret;

	/* binding to db module */
	if(reg_db_url.s==NULL)
	{
		LM_ERR("no db url\n");
		return -1;
	}

	if(db_bind_mod(&reg_db_url, &reg_dbf))
	{
		LM_ERR("database module not found\n");
		return -1;
	}

	if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL))
	{
		LM_ERR("database module does not "
		    "implement all functions needed by the module\n");
		return -1;
	}

	/* open a connection with the database */
	reg_db_con = reg_dbf.init(&reg_db_url);
	if(reg_db_con==NULL)
	{
		LM_ERR("failed to connect to the database\n");
		return -1;
	}
	if (reg_dbf.use_table(reg_db_con, &reg_db_table) < 0)
	{
		LM_ERR("failed to use_table\n");
		return -1;
	}

	if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) {
		if(reg_dbf.query(reg_db_con, 0, 0, 0, db_cols, 0, 10, 0, 0) < 0)
		{
			LM_ERR("Error while querying db\n");
			return -1;
		}
		if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0)
		{
			LM_ERR("Error while fetching result\n");
			if (db_res)
				reg_dbf.free_result(reg_db_con, db_res);
			goto error;
		} else {
			if(RES_ROW_N(db_res)==0)
			{
				goto done;
			}
		}
	} else {
		if((ret=reg_dbf.query(reg_db_con, NULL, NULL, NULL, db_cols,
				0, 10, 0, &db_res))!=0
			|| RES_ROW_N(db_res)<=0 )
		{
			reg_dbf.free_result(reg_db_con, db_res);
			if( ret==0)
			{
				return 0;
			} else {
				goto error;
			}
		}
	}

	do {
		for(i=0; i<RES_ROW_N(db_res); i++)
		{
			memset(&reg, 0, sizeof(reg_uac_t));;
			/* check for NULL values ?!?! */
			reg_db_set_attr(l_uuid, 0);
			reg_db_set_attr(l_username, 1);
			reg_db_set_attr(l_domain, 2);
			reg_db_set_attr(r_username, 3);
			reg_db_set_attr(r_domain, 4);
			/* realm may be empty */
			if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) {
				reg.realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val);
				reg.realm.len = strlen(reg.realm.s);
			}
			reg_db_set_attr(auth_username, 6);
			reg_db_set_attr(auth_password, 7);
			reg_db_set_attr(auth_proxy, 8);
			reg.expires
				= (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val;
			
			if(reg_ht_add(&reg)<0)
			{
				LM_ERR("Error adding reg to htable\n");
				goto error;
			}
	 	}
		if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) {
			if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0) {
				LM_ERR("Error while fetching!\n");
				if (db_res)
					reg_dbf.free_result(reg_db_con, db_res);
				goto error;
			}
		} else {
			break;
		}
	}  while(RES_ROW_N(db_res)>0);
	reg_dbf.free_result(reg_db_con, db_res);
	reg_dbf.close(reg_db_con);

done:
	return 0;

error:
	if (reg_db_con) {
		reg_dbf.free_result(reg_db_con, db_res);
		reg_dbf.close(reg_db_con);
	}
	return -1;
}
コード例 #17
0
ファイル: alookup.c プロジェクト: GreenfieldTech/kamailio
static int alias_db_query(struct sip_msg* _msg, str table,
			struct sip_uri *puri, unsigned long flags,
			set_alias_f set_alias, void *param)
{
	str user_s;
	db_key_t db_keys[2];
	db_val_t db_vals[2];
	db_key_t db_cols[2];
	db1_res_t* db_res = NULL;
	int i;

	if (flags&ALIAS_REVERSE_FLAG)
	{
		/* revert lookup: user->alias */
		db_keys[0] = &user_column;
		db_keys[1] = &domain_column;
		db_cols[0] = &alias_user_column;
		db_cols[1] = &alias_domain_column;
	} else {
		/* normal lookup: alias->user */
		db_keys[0] = &alias_user_column;
		db_keys[1] = &alias_domain_column;
		db_cols[0] = &user_column;
		db_cols[1] = &domain_column;
	}

	db_vals[0].type = DB1_STR;
	db_vals[0].nul = 0;
	db_vals[0].val.str_val.s = puri->user.s;
	db_vals[0].val.str_val.len = puri->user.len;

	if ( flags&ALIAS_DOMAIN_FLAG ) {
		db_vals[1].type = DB1_STR;
		db_vals[1].nul = 0;
		db_vals[1].val.str_val.s = puri->host.s;
		db_vals[1].val.str_val.len = puri->host.len;

		if (domain_prefix.s && domain_prefix.len>0
				&& domain_prefix.len<puri->host.len
				&& strncasecmp(puri->host.s,domain_prefix.s,
				domain_prefix.len)==0)
		{
			db_vals[1].val.str_val.s   += domain_prefix.len;
			db_vals[1].val.str_val.len -= domain_prefix.len;
		}
	}

	adbf.use_table(db_handle, &table);
	if(adbf.query( db_handle, db_keys, NULL, db_vals, db_cols,
			(flags&ALIAS_DOMAIN_FLAG)?2:1 /*no keys*/, 2 /*no cols*/,
			NULL, &db_res)!=0 || db_res==NULL)
	{
		LM_ERR("failed to query database\n");
		goto err_server;
	}

	if (RES_ROW_N(db_res)<=0 || RES_ROWS(db_res)[0].values[0].nul != 0)
	{
		LM_DBG("no alias found for R-URI\n");
		goto err_server;
	}

	memcpy(useruri_buf, "sip:", 4);
	for(i=0; i<RES_ROW_N(db_res); i++)
	{
		user_s.len = 4;
		user_s.s = useruri_buf+4;
		switch(RES_ROWS(db_res)[i].values[0].type)
		{ 
			case DB1_STRING:
				strcpy(user_s.s, 
					(char*)RES_ROWS(db_res)[i].values[0].val.string_val);
				user_s.len += strlen(user_s.s);
			break;
			case DB1_STR:
				strncpy(user_s.s, 
					(char*)RES_ROWS(db_res)[i].values[0].val.str_val.s,
					RES_ROWS(db_res)[i].values[0].val.str_val.len);
				user_s.len += RES_ROWS(db_res)[i].values[0].val.str_val.len;
			break;
			case DB1_BLOB:
				strncpy(user_s.s, 
					(char*)RES_ROWS(db_res)[i].values[0].val.blob_val.s,
					RES_ROWS(db_res)[i].values[0].val.blob_val.len);
				user_s.len += RES_ROWS(db_res)[i].values[0].val.blob_val.len;
			break;
			default:
				LM_ERR("unknown type of DB user column\n");
				goto err_server;
		}
	
		/* add the @*/
		useruri_buf[user_s.len] = '@';
		user_s.len++;
	
		/* add the domain */
		user_s.s = useruri_buf+user_s.len;
		switch(RES_ROWS(db_res)[i].values[1].type)
		{ 
			case DB1_STRING:
				strcpy(user_s.s, 
					(char*)RES_ROWS(db_res)[i].values[1].val.string_val);
				user_s.len += strlen(user_s.s);
			break;
			case DB1_STR:
				strncpy(user_s.s, 
					(char*)RES_ROWS(db_res)[i].values[1].val.str_val.s,
					RES_ROWS(db_res)[i].values[1].val.str_val.len);
				user_s.len += RES_ROWS(db_res)[i].values[1].val.str_val.len;
				useruri_buf[user_s.len] = '\0';
			break;
			case DB1_BLOB:
				strncpy(user_s.s, 
					(char*)RES_ROWS(db_res)[i].values[1].val.blob_val.s,
					RES_ROWS(db_res)[i].values[1].val.blob_val.len);
				user_s.len += RES_ROWS(db_res)[i].values[1].val.blob_val.len;
				useruri_buf[user_s.len] = '\0';
			break;
			default:
				LM_ERR("unknown type of DB user column\n");
				goto err_server;
		}
		user_s.s = useruri_buf;
		/* set the URI */
		LM_DBG("new URI [%d] is [%.*s]\n", i, user_s.len ,user_s.s );
		if (set_alias(_msg, &user_s, i, param)!=0) {
			LM_ERR("error while setting alias\n");
			goto err_server;
		}
	}

	/**
	 * Free the DB result
	 */
	if (adbf.free_result(db_handle, db_res) < 0) {
		LM_DBG("failed to freeing result of query\n");
	}

	return 1;

err_server:
	if (db_res!=NULL) {
		if(adbf.free_result(db_handle, db_res) < 0) {
			LM_DBG("failed to freeing result of query\n");
		}
	}
	return -1;
}
コード例 #18
0
ファイル: uac_reg.c プロジェクト: DileepNunna/kamailio
int uac_reg_db_refresh(str *pl_uuid)
{
	db1_con_t *reg_db_con = NULL;
	db_func_t reg_dbf;
	reg_uac_t reg;
	db_key_t db_cols[10] = {
		&l_uuid_column,
		&l_username_column,
		&l_domain_column,
		&r_username_column,
		&r_domain_column,
		&realm_column,
		&auth_username_column,
		&auth_password_column,
		&auth_proxy_column,
		&expires_column
	};
	db_key_t db_keys[1] = {&l_uuid_column};
	db_val_t db_vals[1];

	db1_res_t* db_res = NULL;
	int i, ret;

	/* binding to db module */
	if(reg_db_url.s==NULL)
	{
		LM_ERR("no db url\n");
		return -1;
	}

	if(db_bind_mod(&reg_db_url, &reg_dbf))
	{
		LM_ERR("database module not found\n");
		return -1;
	}

	if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL))
	{
		LM_ERR("database module does not "
		    "implement all functions needed by the module\n");
		return -1;
	}

	/* open a connection with the database */
	reg_db_con = reg_dbf.init(&reg_db_url);
	if(reg_db_con==NULL)
	{
		LM_ERR("failed to connect to the database\n");
		return -1;
	}
	if (reg_dbf.use_table(reg_db_con, &reg_db_table) < 0)
	{
		LM_ERR("failed to use_table\n");
		return -1;
	}

	db_vals[0].type = DB1_STR;
	db_vals[0].nul = 0;
	db_vals[0].val.str_val.s = pl_uuid->s;
	db_vals[0].val.str_val.len = pl_uuid->len;

	if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols,
			1 /*nr keys*/, 10 /*nr cols*/, 0, &db_res))!=0
		|| RES_ROW_N(db_res)<=0 )
	{
		reg_dbf.free_result(reg_db_con, db_res);
		if( ret==0)
		{
			return 0;
		} else {
			goto error;
		}
	}

	memset(&reg, 0, sizeof(reg_uac_t));;
	i = 0;
	/* check for NULL values ?!?! */
	reg_db_set_attr(l_uuid, 0);
	reg_db_set_attr(l_username, 1);
	reg_db_set_attr(l_domain, 2);
	reg_db_set_attr(r_username, 3);
	reg_db_set_attr(r_domain, 4);
	/* realm may be empty */
	if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) {
		reg.realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val);
		reg.realm.len = strlen(reg.realm.s);
	}
	reg_db_set_attr(auth_username, 6);
	reg_db_set_attr(auth_password, 7);
	reg_db_set_attr(auth_proxy, 8);
	reg.expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val;
	reg.h_uuid = reg_compute_hash(&reg.l_uuid);
	reg.h_user = reg_compute_hash(&reg.l_username);

	lock_get(_reg_htable_gc_lock);
	if(reg_ht_get_byuuid(pl_uuid)!=NULL)
	{
		if(reg_ht_update_password(&reg)<0)
		{
			lock_release(_reg_htable_gc_lock);
			LM_ERR("Error updating reg to htable\n");
			goto error;
		}
	} else {
		if(reg_ht_add(&reg)<0)
		{
			lock_release(_reg_htable_gc_lock);
			LM_ERR("Error adding reg to htable\n");
			goto error;
		}
	}
	lock_release(_reg_htable_gc_lock);

	reg_dbf.free_result(reg_db_con, db_res);
	reg_dbf.close(reg_db_con);

	return 0;

error:
	if (reg_db_con) {
		reg_dbf.free_result(reg_db_con, db_res);
		reg_dbf.close(reg_db_con);
	}
	return -1;
}
コード例 #19
0
ファイル: clusterer.c プロジェクト: Danfx/opensips
/* loads data from the db */
table_entry_t* load_info(db_func_t *dr_dbf, db_con_t* db_hdl, str *db_table)
{
	int int_vals[7];
	char *str_vals[2];
	int no_of_results;
	int i, n;
	int no_rows = 5;
	int db_cols = 10;
	unsigned long last_attempt;
	static db_key_t clusterer_machine_id_key = &machine_id_col;
	static db_val_t clusterer_machine_id_value = {
		.type = DB_INT,
		.nul = 0,
	};

	VAL_INT(&clusterer_machine_id_value) = server_id;

	/* the columns from the db table */
	db_key_t columns[10];
	/* result from a db query */
	db_res_t* res;
	/* a row from the db table */
	db_row_t* row;
	/* the processed result */
	table_entry_t *data;

	res = 0;
	data = 0;

	columns[0] = &cluster_id_col;
	columns[1] = &machine_id_col;
	columns[2] = &state_col;
	columns[3] = &description_col;
	columns[4] = &url_col;
	columns[5] = &id_col;
	columns[6] = &last_attempt_col;
	columns[7] = &failed_attempts_col;
	columns[8] = &no_tries_col;
	columns[9] = &duration_col;

	CON_OR_RESET(db_hdl);

	/* checking if the table version is up to date*/
	if (db_check_table_version(dr_dbf, db_hdl, db_table, 1/*version*/) != 0)
		goto error;

	/* read data */
	if (dr_dbf->use_table(db_hdl, db_table) < 0) {
		LM_ERR("cannot select table \"%.*s\"\n", db_table->len, db_table->s);
		goto error;
	}

	LM_DBG("DB query - retrieve the clusters list"
		"in which the specified server runs\n");

	/* first we see in which clusters the specified server runs*/
	if (dr_dbf->query(db_hdl, &clusterer_machine_id_key, &op_eq,
		&clusterer_machine_id_value, columns, 1, 1, 0, &res) < 0) {
		LM_ERR("DB query failed - cannot retrieve the clusters list in which"
			" the specified server runs\n");
		goto error;
	}

	LM_DBG("%d rows found in %.*s\n",
		RES_ROW_N(res), db_table->len, db_table->s);

	if (RES_ROW_N(res) == 0) {
		LM_WARN("No machines found in cluster %d\n", server_id);
		return 0;
	}

	clusterer_cluster_id_key = pkg_realloc(clusterer_cluster_id_key,
		RES_ROW_N(res) * sizeof(db_key_t));
	if (!clusterer_cluster_id_key) {
		LM_ERR("no more pkg memory\n");
		goto error;
	}

	for (i = 0; i < RES_ROW_N(res); i++)
		clusterer_cluster_id_key[i] = &cluster_id_col;

	clusterer_cluster_id_value = pkg_realloc(clusterer_cluster_id_value,
		RES_ROW_N(res) * sizeof(db_val_t));

	if (!clusterer_cluster_id_value) {
		LM_ERR("no more pkg memory\n");
		goto error;
	}

	for (i = 0; i < RES_ROW_N(res); i++) {
		VAL_TYPE(clusterer_cluster_id_value + i) = DB_INT;
		VAL_NULL(clusterer_cluster_id_value + i) = 0;
	}

	for (i = 0; i < RES_ROW_N(res); i++) {
		row = RES_ROWS(res) + i;

		check_val(cluster_id_col, ROW_VALUES(row), DB_INT, 1, 0);
		VAL_INT(clusterer_cluster_id_value + i) = VAL_INT(ROW_VALUES(row));
	}

	no_of_results = RES_ROW_N(res);
	dr_dbf->free_result(db_hdl, res);
	res = 0;

	LM_DBG("DB query - retrieve valid connections\n");

	/* fetch is the best strategy */
	CON_USE_OR_OP(db_hdl);
	if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {

		if (dr_dbf->query(db_hdl, clusterer_cluster_id_key, 0,
			clusterer_cluster_id_value, columns, no_of_results, db_cols, 0, 0) < 0) {
			LM_ERR("DB query failed - retrieve valid connections \n");
			goto error;
		}
		no_rows = estimate_available_rows(4 + 4 + 4 + 64 + 4 + 45 + 4 + 8 + 4 + 4, db_cols);
		if (no_rows == 0) no_rows = 5;
		if (dr_dbf->fetch_result(db_hdl, &res, no_rows) < 0) {
			LM_ERR("Error fetching rows\n");
			goto error;
		}
	} else {
		if (dr_dbf->query(db_hdl, clusterer_cluster_id_key, 0,
			clusterer_cluster_id_value, columns, no_of_results, db_cols, 0, &res) < 0) {
			LM_ERR("DB query failed - retrieve valid connections\n");
			goto error;
		}
	}

	LM_DBG("%d rows found in %.*s\n",
		RES_ROW_N(res), db_table->len, db_table->s);

	n = 0;
	do {
		for (i = 0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;
			/* CLUSTER ID column */
			check_val(cluster_id_col, ROW_VALUES(row), DB_INT, 1, 0);
			int_vals[INT_VALS_CLUSTER_ID_COL] = VAL_INT(ROW_VALUES(row));
			/* MACHINE ID column */
			check_val(machine_id_col, ROW_VALUES(row) + 1, DB_INT, 1, 0);
			int_vals[INT_VALS_MACHINE_ID_COL] = VAL_INT(ROW_VALUES(row) + 1);
			/* STATE column */
			check_val(state_col, ROW_VALUES(row) + 2, DB_INT, 1, 0);
			int_vals[INT_VALS_STATE_COL] = VAL_INT(ROW_VALUES(row) + 2);
			/* DESCRIPTION column */
			check_val(description_col, ROW_VALUES(row) + 3, DB_STRING, 0, 0);
			str_vals[STR_VALS_DESCRIPTION_COL] = (char*) VAL_STRING(ROW_VALUES(row) + 3);
			/* URL column */
			check_val(url_col, ROW_VALUES(row) + 4, DB_STRING, 1, 1);
			str_vals[STR_VALS_URL_COL] = (char*) VAL_STRING(ROW_VALUES(row) + 4);
			/* CLUSTERER_ID column */
			check_val(id_col, ROW_VALUES(row) + 5, DB_INT, 1, 0);
			int_vals[INT_VALS_CLUSTERER_ID_COL] = VAL_INT(ROW_VALUES(row) + 5);
			/* LAST_ATTEMPT column */
			check_val(last_attempt_col, ROW_VALUES(row) + 6, DB_BIGINT, 1, 0);
			last_attempt = VAL_BIGINT(ROW_VALUES(row) + 6);
			/* FAILED_ATTEMPTS column */
			check_val(failed_attempts_col, ROW_VALUES(row) + 7, DB_INT, 1, 0);
			int_vals[INT_VALS_FAILED_ATTEMPTS_COL] = VAL_INT(ROW_VALUES(row) + 7);
			/* NO_TRIES column */
			check_val(no_tries_col, ROW_VALUES(row) + 8, DB_INT, 1, 0);
			int_vals[INT_VALS_NO_TRIES_COL] = VAL_INT(ROW_VALUES(row) + 8);
			/* DURATION column */
			check_val(duration_col, ROW_VALUES(row) + 9, DB_INT, 1, 0);
			int_vals[INT_VALS_DURATION_COL] = VAL_INT(ROW_VALUES(row) + 9);


			/* store data */
			if (add_info(&data, int_vals, last_attempt, str_vals) < 0) {
				LM_DBG("error while adding info to shm\n");
				goto error;
			}

			LM_DBG("machine id %d\n", int_vals[0]);
			LM_DBG("cluster id %d\n", int_vals[1]);
			LM_DBG("state %d\n", int_vals[2]);
			LM_DBG("clusterer_id %d\n", int_vals[3]);
			LM_DBG("description %s\n", str_vals[0]);
			LM_DBG("url %s\n", str_vals[1]);

			n++;
		}
		if (n == 1)
			LM_WARN("The server is the only one in the cluster\n");

		if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
			if (dr_dbf->fetch_result(db_hdl, &res, no_rows) < 0) {
				LM_ERR("fetching rows (1)\n");
				goto error;
			}
		} else {
			break;
		}
	} while (RES_ROW_N(res) > 0);

	LM_DBG("%d records found in %.*s\n",
		n, db_table->len, db_table->s);

	dr_dbf->free_result(db_hdl, res);
	res = 0;

	return data;
error:
	if (res)
		dr_dbf->free_result(db_hdl, res);
	if (data)
		free_data(data);
	data = NULL;
	return 0;
}

/* deallocates data */
void free_data(table_entry_t *data)
{
	table_entry_t *tmp_entry;
	table_entry_info_t *info;
	table_entry_info_t *tmp_info;
	table_entry_value_t *value;
	table_entry_value_t *tmp_value;

	struct module_timestamp *timestamp;
	struct module_timestamp *tmp_timestamp;

	while (data != NULL) {
		tmp_entry = data;
		data = data->next;
		info = tmp_entry->info;
		while (info != NULL) {
			value = info->value;
			while (value != NULL) {
				if (value->path.s)
					shm_free(value->path.s);
				if (value->description.s)
					shm_free(value->description.s);
				timestamp = value->in_timestamps;
				while (timestamp != NULL) {
					tmp_timestamp = timestamp;
					timestamp = timestamp->next;
					shm_free(tmp_timestamp);
				}
				tmp_value = value;
				value = value->next;
				shm_free(tmp_value);
			}
			tmp_info = info;
			info = info->next;
			shm_free(tmp_info);
		}
		shm_free(tmp_entry);
	}
}
コード例 #20
0
ファイル: bdb_res.c プロジェクト: KISSMonX/opensips
/**
 * Convert rows from Berkeley DB to db API representation
 */
int bdb_convert_row(db_res_t* _res, char *bdb_result, int* _lres)
{
	int col, len, i, j;
	char **row_buf, *s;
	col = len = i = j = 0;
	struct db_row* row = NULL;

	if (!_res) {
		LM_ERR("invalid parameter\n");
		return -1;
	}

	/* Save the number of rows in the current fetch */
	RES_ROW_N(_res) = 1;
	row = RES_ROWS(_res);
	
	/* Save the number of columns in the ROW structure */
	ROW_N(row) = RES_COL_N(_res);

	/*
	 * Allocate an array of pointers one per column.
	 * It that will be used to hold the address of the string 
	 * representation of each column.
	 */
	len = sizeof(char *) * RES_COL_N(_res);
	row_buf = (char **)pkg_malloc(len);
	if (!row_buf) {
		LM_ERR("no private memory left\n");
		return -1;
	}
	LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n",
		RES_COL_N(_res), len, row_buf);
	memset(row_buf, 0, len);

	/*populate the row_buf with bdb_result*/
	/*bdb_result is memory from our callers stack so we copy here*/


	LM_DBG("Found: [%s]\n",bdb_result);

	s = strsep(&bdb_result, DELIM);
	while( s!=NULL)
	{
		if(_lres) {
			/*only requested cols (_c was specified)*/
			for(i=0; i<ROW_N(row); i++)
			{	if (col == _lres[i]) {
					len = strlen(s);
					row_buf[i] = pkg_malloc(len+1);
					if (!row_buf[i]) {
						LM_ERR("no private memory left\n");
						goto error;
					}
					LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, i, row_buf[i]);
					memset(row_buf[i], 0, len+1);
					strncpy(row_buf[i], s, len);
				}
				
			}
		}
		else {

			/* TODO: TEST */
			if( col >= RES_COL_N(_res))
				break;

			len = strlen(s);
			row_buf[col] = pkg_malloc(len+1);
			if (!row_buf[col]) {
				LM_ERR("no private memory left\n");
				return -1;
			}
				LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, col, row_buf[col]);
			memset(row_buf[col], 0, len+1);
			strncpy(row_buf[col], s, len);
		}
		s = strsep(&bdb_result, DELIM);
		col++;
	}

	/*do the type conversion per col*/
        for(col = 0; col < ROW_N(row); col++) {
		/*skip the unrequested cols (as already specified)*/
		if(!row_buf[col])  continue;

		/* Convert the string representation into the value representation */
		if (bdb_str2val(RES_TYPES(_res)[col], &(ROW_VALUES(row)[col])
				, row_buf[col], strlen(row_buf[col])) < 0) {
			LM_ERR("while converting value\n");
			goto error;
		}

		if( row->values[col].nul ||
		    row->values[col].type == DB_INT ||
		    row->values[col].type == DB_BIGINT ||
		    row->values[col].type == DB_DOUBLE ||
		    row->values[col].type == DB_DATETIME
		 )
			pkg_free(row_buf[col]);
		
	}

	
	LM_DBG("freeing row buffer at %p\n", row_buf);
	if( row_buf[col])
		pkg_free(row_buf);
	row_buf = NULL;

	return 0;

error:
	for(col = 0; col < ROW_N(row); col++)
		if( row_buf[col])
		pkg_free(row_buf[col]);

	if( row_buf )
		pkg_free(row_buf);
			return -1;

}
コード例 #21
0
/*
 *
 * pg_fetch_result: Gets a partial result set.
 *
 */
int db_postgres_fetch_result(const db_con_t* _con, db_res_t** _res, const int nrows)
{
	int rows;
	ExecStatusType pqresult;

	if (!_con || !_res || nrows < 0) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	/* exit if the fetch count is zero */
	if (nrows == 0) {
		if (*_res)
			db_free_result(*_res);

		*_res = 0;
		return 0;
	}

	if (*_res == NULL) {
		/* Allocate a new result structure */
		*_res = db_new_result();

		pqresult = PQresultStatus(CON_RESULT(_con));
		LM_DBG("%p PQresultStatus(%s) PQgetResult(%p)\n", _con,
			PQresStatus(pqresult), CON_RESULT(_con));

		switch(pqresult) {
			case PGRES_COMMAND_OK:
				/* Successful completion of a command returning no data 
				 * (such as INSERT or UPDATE). */
				return 0;

			case PGRES_TUPLES_OK:
				/* Successful completion of a command returning data 
				 * (such as a SELECT or SHOW). */
				if (db_postgres_get_columns(_con, *_res) < 0) {
					LM_ERR("failed to get column names\n");
					return -2;
				}
				break;

			case PGRES_FATAL_ERROR:
				LM_ERR("%p - invalid query, execution aborted\n", _con);
				LM_ERR("%p - PQresultStatus(%s)\n",_con,PQresStatus(pqresult));
				LM_ERR("%p: %s\n",_con,PQresultErrorMessage(CON_RESULT(_con)));
				if (*_res)
					db_free_result(*_res);
				*_res = 0;
				return -3;

			case PGRES_EMPTY_QUERY:
			/* notice or warning */
			case PGRES_NONFATAL_ERROR:
			/* status for COPY command, not used */
			case PGRES_COPY_OUT:
			case PGRES_COPY_IN:
			/* unexpected response */
			case PGRES_BAD_RESPONSE:
			default:
				LM_ERR("%p - probable invalid query\n", _con);
				LM_ERR("%p - PQresultStatus(%s)\n",_con,PQresStatus(pqresult));
				LM_ERR("%p: %s\n",_con,PQresultErrorMessage(CON_RESULT(_con)));
				if (*_res)
					db_free_result(*_res);
				*_res = 0;
				return -4;
		}

	} else {
		if(RES_ROWS(*_res) != NULL) {
			db_free_rows(*_res);
		}
		RES_ROWS(*_res) = 0;
		RES_ROW_N(*_res) = 0;
	}

	/* Get the number of rows (tuples) in the query result. */
	RES_NUM_ROWS(*_res) = PQntuples(CON_RESULT(_con));

	/* determine the number of rows remaining to be processed */
	rows = RES_NUM_ROWS(*_res) - RES_LAST_ROW(*_res);

	/* If there aren't any more rows left to process, exit */
	if (rows <= 0)
		return 0;

	/* if the fetch count is less than the remaining rows to process                 */
	/* set the number of rows to process (during this call) equal to 
	 * the fetch count */
	if (nrows < rows)
		rows = nrows;

	RES_ROW_N(*_res) = rows;

	LM_DBG("converting row %d of %d count %d\n", RES_LAST_ROW(*_res),
			RES_NUM_ROWS(*_res), RES_ROW_N(*_res));

	if (db_postgres_convert_rows(_con, *_res) < 0) {
		LM_ERR("failed to convert rows\n");
		if (*_res)
			db_free_result(*_res);

		*_res = 0;
		return -3;
	}

	/* update the total number of rows processed */
	RES_LAST_ROW(*_res) += rows;
	return 0;
}
コード例 #22
0
ファイル: frd_load.c プロジェクト: alias-neo/opensips
static int frd_load_data(dr_head_p drp, free_list_t **fl)
{
	static const size_t col_count = 16;
	db_res_t *res = NULL;
	unsigned int no_rows = 0, row_count, i;
	db_row_t *rows;
	db_val_t *values;

	db_key_t query_cols[] = {
		&rid_col, &pid_col, &prefix_col, &start_h_col, &end_h_col, &days_col,
		&cpm_thresh_warn_col, &cpm_thresh_crit_col, &calldur_thresh_warn_col,
		&calldur_thresh_crit_col, &totalc_thresh_warn_col, &totalc_thresh_crit_col,
		&concalls_thresh_warn_col, &concalls_thresh_crit_col, &seqcalls_thresh_warn_col,
		&seqcalls_thresh_crit_col
	};

	if (db_handle == NULL) {
		LM_ERR("Invalid db handler\n");
		return -1;
	}

	if (dbf.use_table(db_handle, &table_name) != 0) {
		LM_ERR("Cannot use table\n");
		return -1;
	}

	if (DB_CAPABILITY(dbf, DB_CAP_FETCH)) {
		if (dbf.query(db_handle, 0, 0, 0, query_cols, 0, col_count, 0, 0) != 0) {
			LM_ERR("Error while querying db\n");
			goto error;
		}
		/* estimate rows */
		no_rows = estimate_available_rows(4 + 64 + 5 + 5 + 64 + 5 * 2 * 4, col_count);

		if (no_rows == 0)
			no_rows = 10;

		if (dbf.fetch_result(db_handle, &res, no_rows) != 0) {
			LM_ERR("Error while fetching rows\n");
			goto error;
		}
	} else {
		/* No fetching capability */
		if (dbf.query(db_handle, 0, 0, 0, query_cols, 0, col_count, 0, &res) != 0) {
			LM_ERR("Error while querying db\n");
			goto error;
		}
	}

	/* Process the actual data */

	unsigned int rid, pid, j;
	str prefix, start_time, end_time, days;
	free_list_t *fl_it = NULL;
	*fl = NULL;

	do {
		row_count = RES_ROW_N(res);
		rows = RES_ROWS(res);
		fl_it = pkg_malloc(sizeof(free_list_t));
		if (fl_it == NULL) {
			LM_ERR ("no more pkg memory");
			dbf.free_result(db_handle, res);
			return -1;
		}
		fl_it ->next = *fl;
		*fl = fl_it;
		fl_it->trec = shm_malloc(sizeof(tmrec_t) * row_count);
		if (fl_it->trec == NULL)
			goto no_more_shm;
		fl_it->thr = shm_malloc(sizeof(frd_thresholds_t) * row_count);
		if (fl_it->thr == NULL)
			goto no_more_shm;
		fl_it->n = row_count;

		for (i = 0; i < row_count; ++i) {
			values = ROW_VALUES(rows + i);
			fl_it->trec[i].byday = NULL;

			/* rule id */
			if (VAL_NULL(values)) {
				LM_ERR("rule id cannot be NULL - skipping rule\n");
				continue;
			}
			rid = VAL_INT(values);

			/* profile id */
			if (VAL_NULL(values + 1)) {
				LM_ERR("profile id cannot be NULL - skipping rule\n");
				continue;
			}
			pid = VAL_INT(values + 1);

			get_str_from_dbval(prefix_col.s, values + 2, 1, 1, prefix, null_val);
			get_str_from_dbval(start_h_col.s, values + 3, 1, 1, start_time, null_val);
			get_str_from_dbval(end_h_col.s, values + 4, 1, 1, end_time, null_val);
			get_str_from_dbval(days_col.s, values + 5, 1, 1, days, null_val);

			if (create_time_rec(&start_time, &end_time, &days, fl_it->trec + i) != 0)
				goto null_val;

			/* Now load the thresholds */
			for (j = 0; j < 2 * 5; ++j) {
				if (VAL_NULL(values + 6 + j))
					goto null_val;
				memcpy((char*)fl_it->thr + i * sizeof(frd_thresholds_t) +
						j * sizeof(unsigned int), &VAL_INT(values + 6 + j),
						sizeof(unsigned int));
			}

			/* Rule OK, time to put it in DR */
			if (drb.add_rule(drp, rid, &prefix, pid, 0, fl_it->trec + i,
						(void*)(&fl_it->thr[i])) != 0) {

				LM_ERR("Cannot add rule in dr <%u>. Skipping...\n", rid);
			}

			null_val:
				continue;
		}

		if (DB_CAPABILITY(dbf, DB_CAP_FETCH)) {
			/* any more rows to fetch ? */
			if(dbf.fetch_result(db_handle, &res, no_rows)<0) {
				LM_ERR("error while fetching rows\n");
				goto error;
			}
			/* success in fetching more rows - continue the loop */
		} else
			break;

	} while (RES_ROW_N(res) > 0);

	dbf.free_result(db_handle, res);
	return 0;

no_more_shm:
	LM_ERR ("no more shm memory\n");
	dbf.free_result(db_handle, res);

error:
	return -1;
}
コード例 #23
0
ファイル: xjab_worker.c プロジェクト: x-talker/imscore
/**
 * worker implementation
 * - jwl : pointer to the workers list
 * - jaddress : address of the jabber server
 * - jport : port of the jabber server
 * - rank : worker's rank
 * - db_con : connection to database
 *   dbf: database module callbacks structure
 * #return : 0 on success or <0 on error
 */
int xj_worker_process(xj_wlist jwl, char* jaddress, int jport, int rank,
                      db_con_t* db_con, db_func_t* dbf)
{
    int pipe, ret, i, pos, maxfd, flag;
    xj_jcon_pool jcp;
    struct timeval tmv;
    fd_set set, mset;
    xj_sipmsg jsmsg;
    str sto;
    xj_jcon jbc = NULL;
    xj_jconf jcf = NULL;
    char *p, buff[1024], recv_buff[4096];
    int flags, nr, ltime = 0;

    db_key_t keys[] = {"sip_id", "type"};
    db_val_t vals[2];
    db_key_t col[] = {"jab_id", "jab_passwd"};
    db_res_t* res = NULL;

    vals[0].type=DB_STRING;
    vals[0].nul=0;
    vals[0].val.string_val=buff;
    vals[1].type=DB_INT;
    vals[1].nul=0;
    vals[1].val.int_val=0;

    _xj_pid = getpid();

    //signal(SIGTERM, xj_sig_handler);
    //signal(SIGINT, xj_sig_handler);
    //signal(SIGQUIT, xj_sig_handler);
    signal(SIGSEGV, xj_sig_handler);

    if(registrar)
    {
        jab_gw_name.s = registrar;
        jab_gw_name.len = strlen(registrar);
        if(registrar[0]== 's' && registrar[1]== 'i' &&
                registrar[2]== 'p' && registrar[3]== ':')
        {
            jab_gw_name.s += 4;
            jab_gw_name.len -= 4;
        }
    }

    if(!jwl || !jwl->aliases || !jwl->aliases->jdm
            || !jaddress || rank >= jwl->len)
    {
        DBG("XJAB:xj_worker[%d]:%d: exiting - wrong parameters\n",
            rank, _xj_pid);
        return -1;
    }

    pipe = jwl->workers[rank].rpipe;
    DBG("XJAB:xj_worker[%d]:%d: started - pipe=<%d> : 1st message delay"
        " <%d>\n", rank, _xj_pid, pipe, jwl->delayt);
    if((jcp=xj_jcon_pool_init(jwl->maxj,XJ_MSG_POOL_SIZE,jwl->delayt))==NULL)
    {
        DBG("XJAB:xj_worker: cannot allocate the pool\n");
        return -1;
    }

    maxfd = pipe;
    tmv.tv_sec = jwl->sleept;
    tmv.tv_usec = 0;

    FD_ZERO(&set);
    FD_SET(pipe, &set);
    while(main_loop)
    {
        mset = set;

        tmv.tv_sec = (jcp->jmqueue.size == 0)?jwl->sleept:1;
#ifdef XJ_EXTRA_DEBUG
        //DBG("XJAB:xj_worker[%d]:%d: select waiting %ds - queue=%d\n",rank,
        //		_xj_pid, (int)tmv.tv_sec, jcp->jmqueue.size);
#endif
        tmv.tv_usec = 0;

        ret = select(maxfd+1, &mset, NULL, NULL, &tmv);

        // check the msg queue
        xj_worker_check_qmsg(jwl, jcp);

        if(ret <= 0)
            goto step_x;

#ifdef XJ_EXTRA_DEBUG
        DBG("XJAB:xj_worker:%d: something is coming\n", _xj_pid);
#endif
        if(!FD_ISSET(pipe, &mset))
            goto step_y;

        if(read(pipe, &jsmsg, sizeof(jsmsg)) < sizeof(jsmsg))
        {
            DBG("XJAB:xj_worker:%d: BROKEN PIPE - exiting\n", _xj_pid);
            break;
        }

#ifdef XJ_EXTRA_DEBUG
        DBG("XJAB:xj_worker:%d: job <%p> from SER\n", _xj_pid, jsmsg);
#endif

        if(jsmsg == NULL || jsmsg->jkey==NULL || jsmsg->jkey->id==NULL)
            goto step_w;

        strncpy(buff, jsmsg->jkey->id->s, jsmsg->jkey->id->len);
        buff[jsmsg->jkey->id->len] = 0;

        jbc = xj_jcon_pool_get(jcp, jsmsg->jkey);

        switch(jsmsg->type)
        {
        case XJ_SEND_MESSAGE:
            if(!xj_jconf_check_addr(&jsmsg->to, jwl->aliases->dlm) &&
                    (!jbc||!xj_jcon_get_jconf(jbc,&jsmsg->to,jwl->aliases->dlm)))
            {
                xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                                 XJ_DMSG_ERR_NOTJCONF, NULL);
                goto step_w;
            }
            break;
        case XJ_REG_WATCHER:
        case XJ_JOIN_JCONF:
        case XJ_GO_ONLINE:
            break;
        case XJ_EXIT_JCONF:
            if(jbc == NULL)
                goto step_w;
            // close the conference session here
            if(jbc->nrjconf <= 0)
                goto step_w;
            if(!xj_jconf_check_addr(&jsmsg->to, jwl->aliases->dlm))
                xj_jcon_del_jconf(jbc, &jsmsg->to, jwl->aliases->dlm,
                                  XJ_JCMD_UNSUBSCRIBE);
            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_INF_JCONFEXIT, NULL);
            goto step_w;
        case XJ_GO_OFFLINE:
            if(jbc != NULL)
                jbc->expire = ltime = -1;
            goto step_w;
        case XJ_DEL_WATCHER:
        default:
            goto step_w;
        }

        if(jbc != NULL)
        {
#ifdef XJ_EXTRA_DEBUG
            DBG("XJAB:xj_worker:%d: connection already exists"
                " for <%s> ...\n", _xj_pid, buff);
#endif
            xj_jcon_update(jbc, jwl->cachet);
            goto step_z;
        }

        // NO OPEN CONNECTION FOR THIS SIP ID
#ifdef XJ_EXTRA_DEBUG
        DBG("XJAB:xj_worker:%d: new connection for <%s>.\n", _xj_pid, buff);
#endif
        if(dbf->query(db_con, keys, 0, vals, col, 2, 2, NULL, &res) != 0 ||
                RES_ROW_N(res) <= 0)
        {
#ifdef XJ_EXTRA_DEBUG
            DBG("XJAB:xj_worker:%d: no database result when looking"
                " for associated Jabber account\n", _xj_pid);
#endif
            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_ERR_JGWFORB, NULL);

            goto step_v;
        }

        jbc = xj_jcon_init(jaddress, jport);

        if(xj_jcon_connect(jbc))
        {
            DBG("XJAB:xj_worker:%d: Cannot connect"
                " to the Jabber server ...\n", _xj_pid);
            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_ERR_NOJSRV, NULL);

            goto step_v;
        }

#ifdef XJ_EXTRA_DEBUG
        DBG("XJAB:xj_worker: auth to jabber as: [%s] / [xxx]\n",
            (char*)(ROW_VALUES(RES_ROWS(res))[0].val.string_val));
//			(char*)(ROW_VALUES(RES_ROWS(res))[1].val.string_val));
#endif
        if(xj_jcon_user_auth(jbc,
                             (char*)(ROW_VALUES(RES_ROWS(res))[0].val.string_val),
                             (char*)(ROW_VALUES(RES_ROWS(res))[1].val.string_val),
                             XJAB_RESOURCE) < 0)
        {
            DBG("XJAB:xj_worker:%d: Authentication to the Jabber server"
                " failed ...\n", _xj_pid);
            xj_jcon_disconnect(jbc);

            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_ERR_JAUTH, NULL);

            xj_jcon_free(jbc);
            goto step_v;
        }

        if(xj_jcon_set_attrs(jbc, jsmsg->jkey, jwl->cachet, jwl->delayt)
                || xj_jcon_pool_add(jcp, jbc))
        {
            DBG("XJAB:xj_worker:%d: Keeping connection to Jabber server"
                " failed! Not enough memory ...\n", _xj_pid);
            xj_jcon_disconnect(jbc);
            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_ERR_JGWFULL, NULL);
            xj_jcon_free(jbc);
            goto step_v;
        }

        /** add socket descriptor to select */
#ifdef XJ_EXTRA_DEBUG
        DBG("XJAB:xj_worker:%d: add connection on <%d> \n", _xj_pid, jbc->sock);
#endif
        if(jbc->sock > maxfd)
            maxfd = jbc->sock;
        FD_SET(jbc->sock, &set);

        xj_jcon_get_roster(jbc);
        xj_jcon_send_presence(jbc, NULL, NULL, "Online", "9");

        /** wait for a while - the worker is tired */
        //sleep(3);

        if ((res != NULL) && (dbf->free_result(db_con,res) < 0))
        {
            DBG("XJAB:xj_worker:%d:Error while freeing"
                " SQL result - worker terminated\n", _xj_pid);
            return -1;
        }
        else
            res = NULL;

step_z:
        if(jsmsg->type == XJ_GO_ONLINE)
            goto step_w;

        if(jsmsg->type == XJ_REG_WATCHER)
        {   // update or register a presence watcher
            xj_worker_check_watcher(jwl, jcp, jbc, jsmsg);
            goto step_w;
        }

        flag = 0;
        if(!xj_jconf_check_addr(&jsmsg->to, jwl->aliases->dlm))
        {
            if((jcf = xj_jcon_get_jconf(jbc, &jsmsg->to, jwl->aliases->dlm))
                    != NULL)
            {
                if((jsmsg->type == XJ_JOIN_JCONF) &&
                        !(jcf->status & XJ_JCONF_READY ||
                          jcf->status & XJ_JCONF_WAITING))
                {
                    if(!xj_jcon_jconf_presence(jbc,jcf,NULL,"online"))
                        jcf->status = XJ_JCONF_WAITING;
                    else
                    {
                        // unable to join the conference
                        // --- send back to SIP user a msg
                        xj_send_sip_msgz(_PADDR(jwl),jsmsg->jkey->id,&jsmsg->to,
                                         XJ_DMSG_ERR_JOINJCONF, &jbc->jkey->flag);
                        goto step_w;
                    }
                }
                flag |= XJ_ADDRTR_CON;
            }
            else
            {
                // unable to get the conference
                // --- send back to SIP user a msg
                xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                                 XJ_DMSG_ERR_NEWJCONF, &jbc->jkey->flag);
                goto step_w;
            }
        }
        if(jsmsg->type != XJ_SEND_MESSAGE)
            goto step_w;

        // here will come only XJ_SEND_MESSAGE
        switch(xj_jcon_is_ready(jbc,jsmsg->to.s,jsmsg->to.len,jwl->aliases->dlm))
        {
        case 0:
#ifdef XJ_EXTRA_DEBUG
            DBG("XJAB:xj_worker:%d: SENDING the message to Jabber"
                " network ...\n", _xj_pid);
#endif
            /*** address correction ***/
            sto.s = buff;
            sto.len = 0;
            flag |= XJ_ADDRTR_S2J;
            if(xj_address_translation(&jsmsg->to, &sto, jwl->aliases,
                                      flag) == 0)
            {
                if(xj_jcon_send_msg(jbc, sto.s, sto.len,
                                    jsmsg->msg.s, jsmsg->msg.len,
                                    (flag&XJ_ADDRTR_CON)?XJ_JMSG_GROUPCHAT:XJ_JMSG_CHAT)<0)

                    xj_send_sip_msgz(_PADDR(jwl),jsmsg->jkey->id,&jsmsg->to,
                                     XJ_DMSG_ERR_SENDJMSG, &jbc->jkey->flag);
            }
            else
                DBG("XJAB:xj_worker:%d: ERROR SENDING as Jabber"
                    " message ...\n", _xj_pid);

            goto step_w;

        case 1:
#ifdef XJ_EXTRA_DEBUG
            DBG("XJAB:xj_worker:%d:SCHEDULING the message.\n", _xj_pid);
#endif
            if(xj_jcon_pool_add_jmsg(jcp, jsmsg, jbc) < 0)
            {
                DBG("XJAB:xj_worker:%d: SCHEDULING the message FAILED."
                    " Message was dropped.\n",_xj_pid);
                xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                                 XJ_DMSG_ERR_STOREJMSG, &jbc->jkey->flag);
                goto step_w;
            }
            else // skip freeing the SIP message - now is in queue
                goto step_y;

        case 2:
            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_ERR_NOREGIM, &jbc->jkey->flag);
            goto step_w;
        case 3: // not joined to Jabber conference
            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_ERR_NOTJCONF, &jbc->jkey->flag);
            goto step_w;

        default:
            xj_send_sip_msgz(_PADDR(jwl), jsmsg->jkey->id, &jsmsg->to,
                             XJ_DMSG_ERR_SENDJMSG, &jbc->jkey->flag);
            goto step_w;
        }

step_v: // error connecting to Jabber server

        // cleaning jab_wlist
        xj_wlist_del(jwl, jsmsg->jkey, _xj_pid);

        // cleaning db_query
        if ((res != NULL) && (dbf->free_result(db_con,res) < 0))
        {
            DBG("XJAB:xj_worker:%d:Error while freeing"
                " SQL result - worker terminated\n", _xj_pid);
            return -1;
        }
        else
            res = NULL;

step_w:
        if(jsmsg!=NULL)
        {
            xj_sipmsg_free(jsmsg);
            jsmsg = NULL;
        }

step_y:
        // check for new message from ... JABBER
        for(i = 0; i < jcp->len && main_loop; i++)
        {
            if(jcp->ojc[i] == NULL)
                continue;
#ifdef XJ_EXTRA_DEBUG
            DBG("XJAB:xj_worker:%d: checking socket <%d>"
                " ...\n", _xj_pid, jcp->ojc[i]->sock);
#endif
            if(!FD_ISSET(jcp->ojc[i]->sock, &mset))
                continue;
            pos = nr = 0;
            do
            {
                p = recv_buff;
                if(pos != 0)
                {
                    while(pos < nr)
                    {
                        *p = recv_buff[pos];
                        pos++;
                        p++;
                    }
                    *p = 0;
                    /**
                     * flush out the socket - set it to nonblocking
                     */
                    flags = fcntl(jcp->ojc[i]->sock, F_GETFL, 0);
                    if(flags!=-1 && !(flags & O_NONBLOCK))
                    {
                        /* set NONBLOCK bit to enable non-blocking */
                        fcntl(jcp->ojc[i]->sock, F_SETFL, flags|O_NONBLOCK);
                    }
                }

                if((nr = read(jcp->ojc[i]->sock, p,
                              sizeof(recv_buff)-(p-recv_buff))) == 0
                        ||(nr < 0 && errno != EAGAIN))
                {
                    DBG("XJAB:xj_worker:%d: ERROR -"
                        " connection to jabber lost on socket <%d> ...\n",
                        _xj_pid, jcp->ojc[i]->sock);
                    xj_send_sip_msgz(_PADDR(jwl), jcp->ojc[i]->jkey->id,
                                     &jab_gw_name,XJ_DMSG_ERR_DISCONNECTED,&jbc->jkey->flag);
                    // make sure that will ckeck expired connections
                    ltime = jcp->ojc[i]->expire = -1;
                    FD_CLR(jcp->ojc[i]->sock, &set);
                    goto step_xx;
                }
#ifdef XJ_EXTRA_DEBUG
                DBG("XJAB:xj_worker:%d: received: %dbytes Err:%d/EA:%d\n",
                    _xj_pid, nr, errno, EAGAIN);
#endif
                xj_jcon_update(jcp->ojc[i], jwl->cachet);

                if(nr>0)
                    p[nr] = 0;
                nr = strlen(recv_buff);
                pos = 0;
#ifdef XJ_EXTRA_DEBUG
                DBG("XJAB:xj_worker: JMSG START ----------\n%.*s\n"
                    " JABBER: JMSGL:%d END ----------\n", nr, recv_buff, nr);
#endif
            } while(xj_manage_jab(recv_buff, nr, &pos, jwl->aliases,
                                  jcp->ojc[i]) == 9	&& main_loop);

            /**
             * flush out the socket - set it back to blocking
             */
            flags = fcntl(jcp->ojc[i]->sock, F_GETFL, 0);
            if(flags!=-1 && (flags & O_NONBLOCK))
            {
                /* reset NONBLOCK bit to enable blocking */
                fcntl(jcp->ojc[i]->sock, F_SETFL, flags & ~O_NONBLOCK);
            }
#ifdef XJ_EXTRA_DEBUG
            DBG("XJAB:xj_worker:%d: msgs from socket <%d> parsed"
                " ...\n", _xj_pid, jcp->ojc[i]->sock);
#endif
        } // end FOR(i = 0; i < jcp->len; i++)

step_x:
        if(ret < 0)
        {
            DBG("XJAB:xj_worker:%d: SIGNAL received!!!!!!!!\n", _xj_pid);
            maxfd = pipe;
            FD_ZERO(&set);
            FD_SET(pipe, &set);
            for(i = 0; i < jcp->len; i++)
            {
                if(jcp->ojc[i] != NULL)
                {
                    FD_SET(jcp->ojc[i]->sock, &set);
                    if( jcp->ojc[i]->sock > maxfd )
                        maxfd = jcp->ojc[i]->sock;
                }
            }
        }
step_xx:
        if(ltime < 0 || ltime + jwl->sleept <= get_ticks())
        {
            ltime = get_ticks();
#ifdef XJ_EXTRA_DEBUG
            //DBG("XJAB:xj_worker:%d: scanning for expired connection\n",
            //	_xj_pid);
#endif
            xj_worker_check_jcons(jwl, jcp, ltime, &set);
        }
    } // END while

    DBG("XJAB:xj_worker:%d: cleaning procedure\n", _xj_pid);

    return 0;
} // end xj_worker_process
コード例 #24
0
ファイル: resource_notify.c プロジェクト: mattvv/kamailio
static void timer_send_full_state_notifies(int round)
{
	db_key_t query_cols[1], result_cols[22], update_cols[1];
	db_val_t query_vals[1], update_vals[1], *values;
	db_row_t *rows;
	db1_res_t *result = NULL;
	int n_result_cols = 0, i;
	int pres_uri_col, tuser_col, tdomain_col, fuser_col, fdomain_col;
	int wuser_col, wdomain_col, callid_col, to_tag_col, from_tag_col;
	int sockinfo_col, lcontact_col, contact_col, rroute_col, event_id_col;
	int reason_col, event_col, lcseq_col, rcseq_col, status_col;
	int version_col, expires_col;
	subs_t sub;
	str ev_sname;
	event_t parsed_event;
	xmlDocPtr doc = NULL;
	xmlNodePtr service_node = NULL;
	int now = (int)time(NULL);

	query_cols[0] = &str_updated_col;
	query_vals[0].type = DB1_INT;
	query_vals[0].nul = 0;
	query_vals[0].val.int_val = round;

	result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
	result_cols[tuser_col = n_result_cols++] = &str_to_user_col;
	result_cols[tdomain_col = n_result_cols++] = &str_to_domain_col;
	result_cols[fuser_col = n_result_cols++] = &str_from_user_col;
	result_cols[fdomain_col = n_result_cols++] = &str_from_domain_col;
	result_cols[wuser_col = n_result_cols++] = &str_watcher_username_col;
	result_cols[wdomain_col = n_result_cols++] = &str_watcher_domain_col;
	result_cols[callid_col = n_result_cols++] = &str_callid_col;
	result_cols[to_tag_col = n_result_cols++] = &str_to_tag_col;
	result_cols[from_tag_col = n_result_cols++] = &str_from_tag_col;
	result_cols[sockinfo_col = n_result_cols++] = &str_socket_info_col;
	result_cols[lcontact_col = n_result_cols++] = &str_local_contact_col;
	result_cols[contact_col = n_result_cols++] = &str_contact_col;
	result_cols[rroute_col = n_result_cols++] = &str_record_route_col;
	result_cols[event_id_col = n_result_cols++] = &str_event_id_col;
	result_cols[reason_col = n_result_cols++] = &str_reason_col;
	result_cols[event_col = n_result_cols++] = &str_event_col;
	result_cols[lcseq_col = n_result_cols++] = &str_local_cseq_col;
	result_cols[rcseq_col = n_result_cols++] = &str_remote_cseq_col;
	result_cols[status_col = n_result_cols++] = &str_status_col;
	result_cols[version_col = n_result_cols++] = &str_version_col;
	result_cols[expires_col = n_result_cols++] = &str_expires_col;

	update_cols[0] = &str_updated_col;
	update_vals[0].type = DB1_INT;
	update_vals[0].nul = 0;
	update_vals[0].val.int_val = NO_UPDATE_TYPE;

	if (rls_dbf.use_table(rls_db, &rlsubs_table) < 0)
	{
		LM_ERR("use table failed\n");
		goto done;
	}

	if (dbmode == RLS_DB_ONLY && rls_dbf.start_transaction)
	{
		if (rls_dbf.start_transaction(rls_db) < 0)
		{
			LM_ERR("in start_transaction\n");
			goto done;
		}
	}

	/* Step 1: Find rls_watchers that require full-state notification */
	if (rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols,
				1, n_result_cols, 0, &result) < 0)
	{
		LM_ERR("in sql query\n");
		goto done;
	}
	if(result== NULL || result->n<= 0)
		goto done;

	/* Step 2: Reset the update flag so we do not full-state notify
 	   these watchers again */
	if(rls_dbf.update(rls_db, query_cols, 0, query_vals, update_cols,
					update_vals, 1, 1)< 0)
	{
		LM_ERR("in sql update\n");
		goto done;
	}

	if (dbmode == RLS_DB_ONLY && rls_dbf.end_transaction)
	{
		if (rls_dbf.end_transaction(rls_db) < 0)
		{
			LM_ERR("in end_transaction\n");
			goto done;
		}
	}

	/* Step 3: Full-state notify each watcher we found */
	rows = RES_ROWS(result);
	for (i = 0; i < RES_ROW_N(result); i++)
	{
		memset(&sub, 0, sizeof(subs_t));
		values = ROW_VALUES(&rows[i]);
		EXTRACT_STRING(sub.pres_uri, VAL_STRING(&values[pres_uri_col]));
		EXTRACT_STRING(sub.to_user, VAL_STRING(&values[tuser_col]));
		EXTRACT_STRING(sub.to_domain, VAL_STRING(&values[tdomain_col]));
		EXTRACT_STRING(sub.from_user, VAL_STRING(&values[fuser_col]));
		EXTRACT_STRING(sub.from_domain, VAL_STRING(&values[fdomain_col]));
		EXTRACT_STRING(sub.watcher_user, VAL_STRING(&values[wuser_col]));
		EXTRACT_STRING(sub.watcher_domain, VAL_STRING(&values[wdomain_col]));
		EXTRACT_STRING(sub.callid, VAL_STRING(&values[callid_col]));
		EXTRACT_STRING(sub.to_tag, VAL_STRING(&values[to_tag_col]));
		EXTRACT_STRING(sub.from_tag, VAL_STRING(&values[from_tag_col]));
		EXTRACT_STRING(sub.sockinfo_str, VAL_STRING(&values[sockinfo_col]));
		EXTRACT_STRING(sub.local_contact, VAL_STRING(&values[lcontact_col]));
		EXTRACT_STRING(sub.contact, VAL_STRING(&values[contact_col]));
		EXTRACT_STRING(sub.record_route, VAL_STRING(&values[rroute_col]));
		EXTRACT_STRING(sub.event_id, VAL_STRING(&values[event_id_col]));
		EXTRACT_STRING(sub.reason, VAL_STRING(&values[reason_col]));
		EXTRACT_STRING(ev_sname, VAL_STRING(&values[event_col]));
		sub.event = pres_contains_event(&ev_sname, &parsed_event);
		if (sub.event == NULL)
		{
			LM_ERR("event not found and set to NULL\n");
			goto done;
		}

		sub.local_cseq = VAL_INT(&values[lcseq_col]);
		sub.remote_cseq = VAL_INT(&values[rcseq_col]);
		sub.status = VAL_INT(&values[status_col]);
		sub.version = VAL_INT(&values[version_col]);
		if (VAL_INT(&values[expires_col]) > now + rls_expires_offset)
		{
			sub.expires = VAL_INT(&values[expires_col]) - now;

			if (rls_get_service_list(&sub.pres_uri, &sub.watcher_user,
				&sub.watcher_domain, &service_node, &doc) < 0)
			{
				LM_ERR("failed getting resource list\n");
				goto done;
			}
			if (doc == NULL)
			{
				LM_WARN("no document returned for uri <%.*s>\n",
					sub.pres_uri.len, sub.pres_uri.s);
				goto done;
			}

			if (send_full_notify(&sub, service_node, &sub.pres_uri, 0) < 0)
			{
				LM_ERR("failed sending full state notify\n");
				goto done;
			}
			xmlFreeDoc(doc);
			doc = NULL;
		}
		else
		{
			sub.expires = 0;
			rls_send_notify(&sub, NULL, NULL, NULL);
			delete_rlsdb(&sub.callid, &sub.to_tag, &sub.from_tag);
		}
	}

done:
	if (result != NULL)
		rls_dbf.free_result(rls_db, result);
	if (doc != NULL)
		xmlFreeDoc(doc);
	if (dbmode == RLS_DB_ONLY && rls_dbf.abort_transaction)
	{
		if (rls_dbf.abort_transaction(rls_db) < 0)
			LM_ERR("in abort_transaction\n");
	}
}
コード例 #25
0
ファイル: trusted.c プロジェクト: AndreiPlesa/kamailio
/*
 * Matches from uri against patterns returned from database.  Returns number
 * of matches or -1 if none of the patterns match.
 */
static int match_res(struct sip_msg* msg, int proto, db1_res_t* _r)
{
	int i, tag_avp_type;
	str uri, ruri;
	char uri_string[MAX_URI_SIZE+1];
	char ruri_string[MAX_URI_SIZE+1];
	db_row_t* row;
	db_val_t* val;
	regex_t preg;
	int_str tag_avp, avp_val;
	int count = 0;

	if (IS_SIP(msg)) {
		if (parse_from_header(msg) < 0) return -1;
		uri = get_from(msg)->uri;
		if (uri.len > MAX_URI_SIZE) {
			LM_ERR("message has From URI too large\n");
			return -1;
		}
		memcpy(uri_string, uri.s, uri.len);
		uri_string[uri.len] = (char)0;
		ruri = msg->first_line.u.request.uri;
		if (ruri.len > MAX_URI_SIZE) {
			LM_ERR("message has Request URI too large\n");
			return -1;
		}
		memcpy(ruri_string, ruri.s, ruri.len);
		ruri_string[ruri.len] = (char)0;
	}
	get_tag_avp(&tag_avp, &tag_avp_type);

	row = RES_ROWS(_r);

	for(i = 0; i < RES_ROW_N(_r); i++) {
		val = ROW_VALUES(row + i);
		if ((ROW_N(row + i) == 4) &&
		    (VAL_TYPE(val) == DB1_STRING) && !VAL_NULL(val) &&
		    match_proto(VAL_STRING(val), proto) &&
		    (VAL_NULL(val + 1) ||
		      ((VAL_TYPE(val + 1) == DB1_STRING) && !VAL_NULL(val + 1))) &&
		    (VAL_NULL(val + 2) ||
		      ((VAL_TYPE(val + 2) == DB1_STRING) && !VAL_NULL(val + 2))) &&
		    (VAL_NULL(val + 3) ||
		      ((VAL_TYPE(val + 3) == DB1_STRING) && !VAL_NULL(val + 3))))
		{
			if (IS_SIP(msg)) {
			    if (!VAL_NULL(val + 1)) {
				if (regcomp(&preg, (char *)VAL_STRING(val + 1), REG_NOSUB)) {
					LM_ERR("invalid regular expression\n");
					if (VAL_NULL(val + 2)) {
						continue;
					}
				}
				if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
					regfree(&preg);
					continue;
				}
				regfree(&preg);
			    }
			    if (!VAL_NULL(val + 2)) {
				if (regcomp(&preg, (char *)VAL_STRING(val + 2), REG_NOSUB)) {
					LM_ERR("invalid regular expression\n");
					continue;
				}
				if (regexec(&preg, ruri_string, 0, (regmatch_t *)0, 0)) {
					regfree(&preg);
					continue;
				}
				regfree(&preg);
			    }
			}
			/* Found a match */
			if (tag_avp.n && !VAL_NULL(val + 3)) {
				avp_val.s.s = (char *)VAL_STRING(val + 3);
				avp_val.s.len = strlen(avp_val.s.s);
				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, avp_val) != 0) {
					LM_ERR("failed to set of tag_avp failed\n");
					return -1;
				}
			}
			if (!peer_tag_mode) 
				return 1;
			count++;
		}
	}
	if (!count)
		return -1;
	else 
		return count;
}
コード例 #26
0
ファイル: udomain.c プロジェクト: Gaoithe/openimscore_ims
int preload_udomain(db_con_t* _c, udomain_t* _d)
{
	char b[256];
	db_key_t columns[11];
	db_res_t* res;
	db_row_t* row;
	int i, cseq;
	unsigned int flags;
	struct socket_info* sock;
	str uid, contact, callid, ua, received, instance, aor;
	str* rec;
	time_t expires;
	qvalue_t q;

	urecord_t* r;
	ucontact_t* c;

	columns[0] = uid_col.s;
	columns[1] = contact_col.s;
	columns[2] = expires_col.s;
	columns[3] = q_col.s;
	columns[4] = callid_col.s;
	columns[5] = cseq_col.s;
	columns[6] = flags_col.s;
	columns[7] = user_agent_col.s;
	columns[8] = received_col.s;
	columns[9] = instance_col.s;
	columns[10] = aor_col.s;
	
	memcpy(b, _d->name->s, _d->name->len);
	b[_d->name->len] = '\0';

	if (ul_dbf.use_table(_c, b) < 0) {
		LOG(L_ERR, "preload_udomain(): Error in use_table\n");
		return -1;
	}

	if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, &res) < 0) {
		LOG(L_ERR, "preload_udomain(): Error while doing db_query\n");
		return -1;
	}

	if (RES_ROW_N(res) == 0) {
		DBG("preload_udomain(): Table is empty\n");
		ul_dbf.free_result(_c, res);
		return 0;
	}

	lock_udomain(_d);

	for(i = 0; i < RES_ROW_N(res); i++) {
		row = RES_ROWS(res) + i;
		
		uid.s      = (char*)VAL_STRING(ROW_VALUES(row));
		if (uid.s == 0) {
			LOG(L_CRIT, "preload_udomain: ERROR: bad uid "
							"record in table %s\n", b);
			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");
			continue;
		} else {
			uid.len = strlen(uid.s);
		}

		contact.s = (char*)VAL_STRING(ROW_VALUES(row) + 1);
		if (contact.s == 0) {
			LOG(L_CRIT, "preload_udomain: ERROR: bad contact "
							"record in table %s\n", b);
			LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s\n",
							uid.len, uid.s);
			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");
			continue;
		} else {
			contact.len = strlen(contact.s);
		}
		expires     = VAL_TIME  (ROW_VALUES(row) + 2);
		q           = double2q(VAL_DOUBLE(ROW_VALUES(row) + 3));
		cseq        = VAL_INT   (ROW_VALUES(row) + 5);
		callid.s    = (char*)VAL_STRING(ROW_VALUES(row) + 4);
		if (callid.s == 0) {
			LOG(L_CRIT, "preload_udomain: ERROR: bad callid record in"
							" table %s\n", b);
			LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s,"
							" contact %.*s\n",
							uid.len, uid.s, contact.len, contact.s);
			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");
			continue;
		} else {
			callid.len  = strlen(callid.s);
		}

		flags  = VAL_BITMAP(ROW_VALUES(row) + 6);

		ua.s  = (char*)VAL_STRING(ROW_VALUES(row) + 7);
		if (ua.s) {
			ua.len = strlen(ua.s);
		} else {
			ua.len = 0;
		}

		if (!VAL_NULL(ROW_VALUES(row) + 8)) {
			received.s  = (char*)VAL_STRING(ROW_VALUES(row) + 8);
			if (received.s) {
				received.len = strlen(received.s);
				rec = &received;

				sock = find_socket(&received);
			} else {
				received.len = 0;
				rec = 0;
				sock = 0;
			}
		} else {
			received.s = 0;
			received.len = 0;
			rec = 0;
			sock = 0;
		}

		if (!VAL_NULL(ROW_VALUES(row) + 9)) {
			instance.s  = (char*)VAL_STRING(ROW_VALUES(row) + 9);
			if (instance.s) {
				instance.len = strlen(instance.s);
			} else {
				instance.len = 0;
			}
		} else {
			instance.s = 0;
			instance.len = 0;
		}

		if (!VAL_NULL(ROW_VALUES(row) + 10)) {
			aor.s  = (char*)VAL_STRING(ROW_VALUES(row) + 10);
			if (aor.s) {
				aor.len = strlen(aor.s);
			} else {
				aor.len = 0;
			}
		} else {
			aor.s = 0;
			aor.len = 0;
		}

		if (get_urecord(_d, &uid, &r) > 0) {
			if (mem_insert_urecord(_d, &uid, &r) < 0) {
				LOG(L_ERR, "preload_udomain(): Can't create a record\n");
				ul_dbf.free_result(_c, res);
				unlock_udomain(_d);
				return -2;
			}
		}
		
		if (mem_insert_ucontact(r, &aor, &contact, expires, q, &callid, cseq, flags, &c, &ua, rec, sock, &instance) < 0) {
			LOG(L_ERR, "preload_udomain(): Error while inserting contact\n");
			ul_dbf.free_result(_c, res);
			unlock_udomain(_d);
			return -3;
		}

		db_read_reg_avps(_c, c);

		     /* We have to do this, because insert_ucontact sets state to CS_NEW
		      * and we have the contact in the database already
			  * we also store zombies in database so we have to restore
			  * the correct state
		      */
		c->state = CS_SYNC;
	}

	ul_dbf.free_result(_c, res);
	unlock_udomain(_d);
	return 0;
}
コード例 #27
0
ファイル: dbase.c プロジェクト: AndreiPlesa/opensips
/**
 * Gets a partial result set.
 * \param _h structure representing the database connection
 * \param _r pointer to a structure representing the result
 * \param nrows number of fetched rows
 * \return zero on success, negative value on failure
 */
int db_sqlite_fetch_result(const db_con_t* _h, db_res_t** _r, const int nrows)
{

	int ret;
	int rows, i;
	sqlite3_stmt* stmt;

	if (!_h || !_r || nrows < 0) {
		LM_ERR("Invalid parameter value\n");
		return -1;
	}

	/* exit if the fetch count is zero */
	if (nrows == 0) {
		db_free_result(*_r);
		*_r = 0;
		return 0;
	}

	if(*_r==0) {
		/* Allocate a new result structure */
		*_r = db_new_result();
		if (*_r == 0) {
			LM_ERR("no memory left\n");
			return -2;
		}

		if (db_sqlite_get_columns(_h, *_r) < 0) {
			LM_ERR("error while getting column names\n");
			return -4;
		}

		RES_NUM_ROWS(*_r) = CON_PS_ROWS(_h);

		if (!RES_NUM_ROWS(*_r)) {
			LM_DBG("no rows returned from the query\n");
			RES_ROWS(*_r) = 0;
			return 0;
		}
	} else {
		/* free old rows */
		if(RES_ROWS(*_r)!=0)
			db_free_rows(*_r);
		RES_ROWS(*_r) = 0;
		RES_ROW_N(*_r) = 0;
	}

	/* determine the number of rows remaining to be processed */
	rows = RES_NUM_ROWS(*_r) - RES_LAST_ROW(*_r);

	/* If there aren't any more rows left to process, exit */
	if(rows<=0)
		return 0;

	/* if the fetch count is less than the remaining rows to process */
	/* set the number of rows to process (during this call) equal
	to the fetch count */
	if(nrows < rows)
		rows = nrows;


	RES_ROW_N(*_r) = rows;


	if (db_sqlite_allocate_rows(*_r, rows)!=0) {
		LM_ERR("no memory left\n");
		return -5;
	}

	i = 0;
	ret=-1;

	stmt = CON_SQLITE_PS(_h);
	while (ret != SQLITE_DONE) {
		if (i == nrows) {
			RES_LAST_ROW(*_r) = i - 1;
			break;
		}

		ret = sqlite3_step(stmt);
		if (ret == SQLITE_DONE) {
			RES_ROW_N(*_r) = RES_LAST_ROW(*_r) = RES_NUM_ROWS(*_r) = i;
			sqlite3_finalize(CON_SQLITE_PS(_h));
			CON_SQLITE_PS(_h) = NULL;
			break;
		}

		if (i >= RES_ROW_N(*_r) && i < nrows) {
			db_sqlite_realloc_rows(*_r, RES_ROW_N(*_r) + db_sqlite_alloc_limit);
			RES_ROW_N(*_r) += db_sqlite_alloc_limit;
		}

		if ((ret=db_sqlite_convert_row(_h, *_r, &(RES_ROWS(*_r)[i]))) < 0) {
			LM_ERR("error while converting row #%d\n", i);
			RES_ROW_N(*_r) = i;
			db_free_rows(*_r);
			return -4;
		}

		i++;
	}

	return 0;
}
コード例 #28
0
ファイル: dr_load.c プロジェクト: SipSeb/kamailio
rt_data_t* dr_load_routing_info( db_func_t *dr_dbf, db1_con_t* db_hdl,
							str *drd_table, str *drl_table, str* drr_table )
{
	int    int_vals[4];
	char * str_vals[5];
	str tmp;
	db_key_t columns[7];
	db1_res_t* res;
	db_row_t* row;
	rt_info_t *ri;
	rt_data_t *rdata;
	tmrec_t   *time_rec;
	unsigned int id;
	str s_id;
	int i,n;

	res = 0;
	ri = 0;
	rdata = 0;

	/* init new data structure */
	if ( (rdata=build_rt_data())==0 ) {
		LM_ERR("failed to build rdata\n");
		goto error;
	}

	/* read the destinations */
	if (dr_dbf->use_table( db_hdl, drd_table) < 0) {
		LM_ERR("cannot select table \"%.*s\"\n", drd_table->len,drd_table->s);
		goto error;
	}

	columns[0] = &dst_id_drd_col;
	columns[1] = &address_drd_col;
	columns[2] = &strip_drd_col;
	columns[3] = &prefix_drd_col;
	columns[4] = &type_drd_col;
	columns[5] = &attrs_drd_col;

	if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 6, 0, 0 ) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
		if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
			LM_ERR("Error fetching rows\n");
			goto error;
		}
	} else {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 6, 0, &res) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
	}

	if (RES_ROW_N(res) == 0) {
		LM_WARN("table \"%.*s\" empty\n", drd_table->len,drd_table->s );
	}
	LM_DBG("%d records found in %.*s\n",
		RES_ROW_N(res), drd_table->len,drd_table->s);
	n = 0;
	do {
		for(i=0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;
			/* DST_ID column */
			check_val( ROW_VALUES(row), DB1_INT, 1, 0);
			int_vals[0] = VAL_INT   (ROW_VALUES(row));
			/* ADDRESS column */
			check_val( ROW_VALUES(row)+1, DB1_STRING, 1, 1);
			str_vals[0] = (char*)VAL_STRING(ROW_VALUES(row)+1);
			/* STRIP column */
			check_val( ROW_VALUES(row)+2, DB1_INT, 1, 0);
			int_vals[1] = VAL_INT   (ROW_VALUES(row)+2);
			/* PREFIX column */
			check_val( ROW_VALUES(row)+3, DB1_STRING, 0, 0);
			str_vals[1] = (char*)VAL_STRING(ROW_VALUES(row)+3);
			/* TYPE column */
			check_val( ROW_VALUES(row)+4, DB1_INT, 1, 0);
			int_vals[2] = VAL_INT(ROW_VALUES(row)+4);
			/* ATTRS column */
			check_val( ROW_VALUES(row)+5, DB1_STRING, 0, 0);
			str_vals[2] = (char*)VAL_STRING(ROW_VALUES(row)+5);

			/* add the destinaton definition in */
			if ( add_dst( rdata, int_vals[0], str_vals[0], int_vals[1],
					str_vals[1], int_vals[2], str_vals[2])<0 ) {
				LM_ERR("failed to add destination id %d -> skipping\n",
					int_vals[0]);
				continue;
			}
			n++;
		}
		if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
			if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
				LM_ERR( "fetching rows (1)\n");
				goto error;
			}
		} else {
			break;
		}
	} while(RES_ROW_N(res)>0);

	dr_dbf->free_result(db_hdl, res);
	res = 0;

	if (n==0) {
		LM_WARN("no valid "
			"destinations set -> ignoring the routing rules\n");
		return rdata;
	}

	/* read the gw lists, if any */
	if (dr_dbf->use_table( db_hdl, drl_table) < 0) {
		LM_ERR("cannot select table \"%.*s\"\n", drl_table->len,drl_table->s);
		goto error;
	}

	columns[0] = &id_drl_col;
	columns[1] = &gwlist_drl_col;

	if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 2, 0, 0 ) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
		if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
			LM_ERR("Error fetching rows\n");
			goto error;
		}
	} else {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 2, 0, &res) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
	}

	if (RES_ROW_N(res) == 0) {
		LM_DBG("table \"%.*s\" empty\n", drl_table->len,drl_table->s );
	} else {
		LM_DBG("%d records found in %.*s\n",
			RES_ROW_N(res), drl_table->len,drl_table->s);
		do {
			for(i=0; i < RES_ROW_N(res); i++) {
				row = RES_ROWS(res) + i;
				/* ID column */
				check_val( ROW_VALUES(row), DB1_INT, 1, 0);
				int_vals[0] = VAL_INT   (ROW_VALUES(row));
				/* GWLIST column */
				check_val( ROW_VALUES(row)+1, DB1_STRING, 1, 1);
				str_vals[0] = (char*)VAL_STRING(ROW_VALUES(row)+1);

				if (add_tmp_gw_list(int_vals[0], str_vals[0])!=0) {
					LM_ERR("failed to add temporary GW list\n");
					goto error;
				}
			}
			if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
				if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
					LM_ERR( "fetching rows (1)\n");
					goto error;
				}
			} else {
				break;
			}
		} while(RES_ROW_N(res)>0);
	}
	dr_dbf->free_result(db_hdl, res);
	res = 0;

	/* read the routing rules */
	if (dr_dbf->use_table( db_hdl, drr_table) < 0) {
		LM_ERR("cannot select table \"%.*s\"\n", drr_table->len, drr_table->s);
		goto error;
	}

	columns[0] = &rule_id_drr_col;
	columns[1] = &group_drr_col;
	columns[2] = &prefix_drr_col;
	columns[3] = &time_drr_col;
	columns[4] = &priority_drr_col;
	columns[5] = &routeid_drr_col;
	columns[6] = &dstlist_drr_col;

	if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 7, 0, 0) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
		if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
			LM_ERR("Error fetching rows\n");
			goto error;
		}
	} else {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 7, 0, &res) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
	}

	if (RES_ROW_N(res) == 0) {
		LM_WARN("table \"%.*s\" is empty\n", drr_table->len, drr_table->s);
	}

	LM_DBG("%d records found in %.*s\n", RES_ROW_N(res),
		drr_table->len, drr_table->s);

	n = 0;
	do {
		for(i=0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;
			/* RULE_ID column */
			check_val( ROW_VALUES(row), DB1_INT, 1, 0);
			int_vals[0] = VAL_INT (ROW_VALUES(row));
			/* GROUP column */
			check_val( ROW_VALUES(row)+1, DB1_STRING, 1, 1);
			str_vals[0] = (char*)VAL_STRING(ROW_VALUES(row)+1);
			/* PREFIX column - it may be null or empty */
			check_val( ROW_VALUES(row)+2, DB1_STRING, 0, 0);
			if ((ROW_VALUES(row)+2)->nul || VAL_STRING(ROW_VALUES(row)+2)==0){
				tmp.s = NULL;
				tmp.len = 0;
			} else {
				str_vals[1] = (char*)VAL_STRING(ROW_VALUES(row)+2);
				tmp.s = str_vals[1];
				tmp.len = strlen(str_vals[1]);
			}
			/* TIME column */
			check_val( ROW_VALUES(row)+3, DB1_STRING, 1, 1);
			str_vals[2] = (char*)VAL_STRING(ROW_VALUES(row)+3);
			/* PRIORITY column */
			check_val( ROW_VALUES(row)+4, DB1_INT, 1, 0);
			int_vals[2] = VAL_INT   (ROW_VALUES(row)+4);
			/* ROUTE_ID column */
			check_val( ROW_VALUES(row)+5, DB1_STRING, 1, 0);
			str_vals[3] = (char*)VAL_STRING(ROW_VALUES(row)+5);
			/* DSTLIST column */
			check_val( ROW_VALUES(row)+6, DB1_STRING, 1, 1);
			str_vals[4] = (char*)VAL_STRING(ROW_VALUES(row)+6);
			/* parse the time definition */
			if ((time_rec=parse_time_def(str_vals[2]))==0) {
				LM_ERR("bad time definition <%s> for rule id %d -> skipping\n",
					str_vals[2], int_vals[0]);
				continue;
			}
			/* lookup for the script route ID */
			if (str_vals[3][0] && str_vals[3][0]!='0') {
				int_vals[3] =  route_lookup(&main_rt, str_vals[3]);
				if (int_vals[3]==-1) {
					LM_WARN("route <%s> does not exist\n",str_vals[3]);
					int_vals[3] = 0;
				}
			} else {
				int_vals[3] = 0;
			}
			/* is gw_list a list or a list id? */
			if (str_vals[4][0]=='#') {
				s_id.s = str_vals[4]+1;
				s_id.len = strlen(s_id.s);
				if ( str2int( &s_id, &id)!=0 ||
				(str_vals[4]=get_tmp_gw_list(id))==NULL ) {
					LM_ERR("invalid reference to a GW list <%s> -> skipping\n",
						str_vals[4]);
					continue;
				}
			}
			/* build the routing rule */
			if ((ri = build_rt_info( int_vals[2], time_rec, int_vals[3],
					str_vals[4], rdata->pgw_l))== 0 ) {
				LM_ERR("failed to add routing info for rule id %d -> "
					"skipping\n", int_vals[0]);
				tmrec_free( time_rec );
				continue;
			}
			/* add the rule */
			if (add_rule( rdata, str_vals[0], &tmp, ri)!=0) {
				LM_ERR("failed to add rule id %d -> skipping\n", int_vals[0]);
				free_rt_info( ri );
				continue;
			}
			n++;
		}
		if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
			if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
				LM_ERR( "fetching rows (1)\n");
				goto error;
			}
		} else {
			break;
		}
	} while(RES_ROW_N(res)>0);

	dr_dbf->free_result(db_hdl, res);
	res = 0;

	free_tmp_gw_list();

	if (n==0) {
		LM_WARN("no valid routing rules -> discarding all destinations\n");
		free_rt_data( rdata, 0 );
	}

	return rdata;
error:
	if (res)
		dr_dbf->free_result(db_hdl, res);
	if (rdata)
		free_rt_data( rdata, 1 );
	rdata = NULL;
	return 0;
}
コード例 #29
0
ファイル: mtree_mod.c プロジェクト: TheGrandWazoo/kamailio
static int mt_load_db(m_tree_t *pt)
{
	db_key_t db_cols[MT_MAX_COLS] = {&tprefix_column, &tvalue_column};
	db_key_t key_cols[1];
	db_op_t op[1] = {OP_EQ};
	db_val_t vals[1];
	str tprefix, tvalue;
	db1_res_t* db_res = NULL;
	int i, ret, c;
	m_tree_t new_tree;
	m_tree_t *old_tree = NULL;
	mt_node_t *bk_head = NULL;

	if(pt->ncols>0) {
		for(c=0; c<pt->ncols; c++) {
			db_cols[c] = &pt->scols[c];
		}
	} else {
		db_cols[0] = &tprefix_column;
		db_cols[1] = &tvalue_column;
		c = 2;
	}
	key_cols[0] = &tname_column;
	VAL_TYPE(vals) = DB1_STRING;
	VAL_NULL(vals) = 0;
	VAL_STRING(vals) = pt->tname.s;

	if(db_con==NULL)
	{
		LM_ERR("no db connection\n");
		return -1;
	}

	old_tree = mt_get_tree(&(pt->tname));
	if(old_tree==NULL)
	{
		LM_ERR("tree definition not found [%.*s]\n", pt->tname.len,
				pt->tname.s);
		return -1;
	}
	memcpy(&new_tree, old_tree, sizeof(m_tree_t));
	new_tree.head = 0;
	new_tree.next = 0;
	new_tree.nrnodes = 0;
	new_tree.nritems = 0;
	new_tree.memsize = 0;
	new_tree.reload_count++;
	new_tree.reload_time = (unsigned int)time(NULL);


	if (mt_dbf.use_table(db_con, &old_tree->dbtable) < 0)
	{
		LM_ERR("failed to use_table\n");
		return -1;
	}

	if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
		if(mt_dbf.query(db_con, key_cols, op, vals, db_cols, pt->multi,
				c, 0, 0) < 0)
		{
			LM_ERR("Error while querying db\n");
			return -1;
		}
		if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0)
		{
			LM_ERR("Error while fetching result\n");
			goto error;
		} else {
			if(RES_ROW_N(db_res)==0)
			{
				goto dbreloaded;
			}
		}
	} else {
		if((ret=mt_dbf.query(db_con, key_cols, op, vals, db_cols,
						pt->multi, 2, 0, &db_res))!=0
				|| RES_ROW_N(db_res)<=0 )
		{
			if(ret==0)
			{
				goto dbreloaded;
			} else {
				goto error;
			}
		}
	}

	if(RES_ROW_N(db_res)>0)
	{
		if(RES_ROWS(db_res)[0].values[0].type != DB1_STRING
				|| RES_ROWS(db_res)[0].values[1].type != DB1_STRING)
		{
			LM_ERR("wrond column types in db table (%d / %d)\n",
					RES_ROWS(db_res)[0].values[0].type,
					RES_ROWS(db_res)[0].values[1].type);
			goto error;
		}
	}

	do {
		for(i=0; i<RES_ROW_N(db_res); i++)
		{
			/* check for NULL values ?!?! */
			tprefix.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val);
			tprefix.len = strlen(ZSW(tprefix.s));

			if(c>2) {
				if(mt_pack_values(&new_tree, db_res, i, c, &tvalue)<0) {
					LM_ERR("Error packing values\n");
					goto error;
				}
			} else {
				tvalue.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val);
				tvalue.len = strlen(ZSW(tvalue.s));
			}

			if(tprefix.s==NULL || tvalue.s==NULL
					|| tprefix.len<=0 || tvalue.len<=0)
			{
				LM_ERR("Error - bad record in db"
						" (prefix: %p/%d - value: %p/%d)\n",
						tprefix.s, tprefix.len, tvalue.s, tvalue.len);
				continue;
			}

			if(mt_add_to_tree(&new_tree, &tprefix, &tvalue)<0)
			{
				LM_ERR("Error adding info to tree\n");
				goto error;
			}
		}
		if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
			if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0) {
				LM_ERR("Error while fetching!\n");
				if (db_res)
					mt_dbf.free_result(db_con, db_res);
				goto error;
			}
		} else {
			break;
		}
	}  while(RES_ROW_N(db_res)>0);

dbreloaded:
	mt_dbf.free_result(db_con, db_res);


	/* block all readers */
	lock_get( mt_lock );
	mt_reload_flag = 1;
	lock_release( mt_lock );

	while (mt_tree_refcnt) {
		sleep_us(10);
	}

	bk_head = old_tree->head;
	old_tree->head = new_tree.head;
	old_tree->nrnodes = new_tree.nrnodes;
	old_tree->nritems = new_tree.nritems;
	old_tree->memsize = new_tree.memsize;
	old_tree->reload_count = new_tree.reload_count;
	old_tree->reload_time  = new_tree.reload_time;

	mt_reload_flag = 0;

	/* free old data */
	if (bk_head!=NULL)
		mt_free_node(bk_head, new_tree.type);

	return 0;

error:
	mt_dbf.free_result(db_con, db_res);
	if (new_tree.head!=NULL)
		mt_free_node(new_tree.head, new_tree.type);
	return -1;
}
コード例 #30
0
ファイル: dbase.c プロジェクト: albertollamaso/kamailio
/*!
 * \brief Gets a partial result set, fetch rows from a result
 *
 * Gets a partial result set, fetch a number of rows from a databae result.
 * This function initialize the given result structure on the first run, and
 * fetches the nrows number of rows. On subsequenting runs, it uses the
 * existing result and fetches more rows, until it reaches the end of the
 * result set. Because of this the result needs to be null in the first
 * invocation of the function. If the number of wanted rows is zero, the
 * function returns anything with a result of zero.
 * \param _h structure representing the database connection
 * \param _r pointer to a structure representing the result
 * \param nrows number of fetched rows
 * \return return zero on success, negative value on failure
 */
int db_unixodbc_fetch_result(const db1_con_t* _h, db1_res_t** _r, const int nrows)
{
	int row_n = 0, i = 0, ret = 0, len;
	SQLSMALLINT columns;
	list* rows = NULL;
	list* rowstart = NULL;
	strn* temp_row = NULL;

	if ((!_h) || (!_r) || nrows < 0)
	{
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	/* exit if the fetch count is zero */
	if (nrows == 0) {
		if (*_r)
			db_free_result(*_r);
		*_r = 0;
		return 0;
	}

	/* On the first fetch for a query, allocate structures and get columns */
	if(*_r == NULL) {
		/* Allocate a new result structure */
		*_r = db_new_result();
		LM_DBG("just allocated a new db result structure");

		if (*_r == NULL) {
			LM_ERR("no memory left\n");
			return -2;
		}

		/* Get columns names and count */
		if (db_unixodbc_get_columns(_h, *_r) < 0) {
			LM_ERR("getting column names failed\n");
			db_free_columns(*_r);
			return -2;
		}

	/* On subsequent fetch attempts, reuse already allocated structures */
	} else {
		LM_DBG("db result structure already exist, reusing\n");
		/* free old rows */
		if(RES_ROWS(*_r) != NULL)
			db_free_rows(*_r);
		RES_ROWS(*_r) = 0;
		RES_ROW_N(*_r) = 0;
	}

	SQLNumResultCols(CON_RESULT(_h), (SQLSMALLINT *)&columns);

	/* Now fetch nrows at most */
	len = sizeof(db_row_t) * nrows;
	RES_ROWS(*_r) = (struct db_row*)pkg_malloc(len);
	if (!RES_ROWS(*_r)) {
		LM_ERR("no memory left\n");
		return -5;
	}
	LM_DBG("allocated %d bytes for RES_ROWS at %p\n", len, RES_ROWS(*_r));

	LM_DBG("Now fetching %i rows at most\n", nrows);
	while(SQL_SUCCEEDED(ret = SQLFetch(CON_RESULT(_h)))) {
		/* Allocate a temporary row */
		temp_row = db_unixodbc_new_cellrow(columns);
		if (!temp_row) {
			LM_ERR("no private memory left\n");
			pkg_free(RES_ROWS(*_r));
			pkg_free(*_r);
			*_r = 0;
			return -1;
		}

		LM_DBG("fetching %d columns for row %d...\n",columns, row_n);
		for(i=0; i < columns; i++) {
			LM_DBG("fetching column %d\n",i);
			if (!db_unixodbc_load_cell(_h, i+1, temp_row + i, RES_TYPES(*_r)[i])) {
			    pkg_free(RES_ROWS(*_r));
			    db_unixodbc_free_cellrow(columns, temp_row);
			    pkg_free(*_r);
			    *_r = 0;
			    return -5;
			}
		}

		LM_DBG("got temp_row at %p\n", temp_row);

		if (db_unixodbc_list_insert(&rowstart, &rows, columns, temp_row) < 0) {
			LM_ERR("SQL result row insert failed\n");
			pkg_free(RES_ROWS(*_r));
			db_unixodbc_free_cellrow(columns, temp_row);
			pkg_free(*_r);
			*_r = 0;
			return -5;
		}

		/* Free temporary row data */
		LM_DBG("freeing temp_row at %p\n", temp_row);
		db_unixodbc_free_cellrow(columns, temp_row);
		temp_row = NULL;

		row_n++;
		if (row_n == nrows) {
			break;
		}
	}

	CON_ROW(_h) = NULL;

	RES_ROW_N(*_r) = row_n;
	if (!row_n) {
		LM_DBG("no more rows to process for db fetch");
		pkg_free(RES_ROWS(*_r));
		RES_ROWS(*_r) = 0;
		return 0;
	}

	/* Convert rows to internal format */
	memset(RES_ROWS(*_r), 0, len);
	i = 0;
	rows = rowstart;
	while(rows)
	{
		LM_DBG("converting row #%d\n", i);
		CON_ROW(_h) = rows->data;
		if (!CON_ROW(_h))
		{
			LM_ERR("string null\n");
			RES_ROW_N(*_r) = row_n;
			db_free_rows(*_r);
			return -3;
		}
		if (db_unixodbc_convert_row(_h, *_r, &(RES_ROWS(*_r)[i]), rows->lengths) < 0) {
			LM_ERR("converting fetched row #%d failed\n", i);
			RES_ROW_N(*_r) = i;
			db_free_rows(*_r);
			return -4;
		}
		i++;
		rows = rows->next;
	}
	db_unixodbc_list_destroy(rowstart);

	/* update the total number of rows processed */
	RES_LAST_ROW(*_r) += row_n;
	LM_DBG("fetch from db processed %d rows so far\n", RES_LAST_ROW(*_r));

	return 0;
}