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; }
/* * 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; }
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; }
/* * 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; }
/** * \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; }
/*! * \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; }
/* * 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; }
/* * 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; } }
/** * 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; }
/*! * \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; }
/** * 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; }
/* * 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; }
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); }
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, ®_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; }
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; }
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(®_db_url, ®_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(®_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, ®_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(®, 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(®)<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; }
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; }
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(®_db_url, ®_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(®_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, ®_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(®, 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(®.l_uuid); reg.h_user = reg_compute_hash(®.l_username); lock_get(_reg_htable_gc_lock); if(reg_ht_get_byuuid(pl_uuid)!=NULL) { if(reg_ht_update_password(®)<0) { lock_release(_reg_htable_gc_lock); LM_ERR("Error updating reg to htable\n"); goto error; } } else { if(reg_ht_add(®)<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; }
/* 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); } }
/** * 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; }
/* * * 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; }
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; }
/** * 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
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"); } }
/* * 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; }
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; }
/** * 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; }
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; }
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; }
/*! * \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; }