From 7a1f2be30ea68c4ee7ab71a32c88e31d136e7b71 Mon Sep 17 00:00:00 2001 From: petermarianF <62649923+petermarianF@users.noreply.github.com> Date: Tue, 6 Dec 2022 10:51:58 +0100 Subject: [PATCH] ims_usrloc_pcscf: implementation of db_mode DB_ONLY (value 3) (#3279) * ims_usrloc_pcscf: implementation of db_mode DB_ONLY (value 3) In order to support a redundant PCSCF configuration - i.e. a logical PCSCF consists of 2 physical nodes (node1 and node2) some enhancements were introduced for handling of contacts. Redundancy means that SIP messages for a client are normally handled by node1 but in case node1 is not reachable SIP messages are redirected to node2. Of course the DB_ONLY mode must work also for single PCSCF node configuration. Important aspects of this implementation are database integrity - i.e. avoid invalid table entries (for example data which are expired long time ago or have invalid states) - and keeping PCSCF cache in sync with database tables. * A wrapper was built for method get_pcontact which tries to find the pcontact in cache and if search is not successful tries to download and insert from db location table - also some effort is added here to find the pcontact if it exists in cache. The contact expiry handler was modified to sync contact expiry in cache with db location entry and in case of real contact expiry sends PUBLISH to SCSCF to let NOTIFY finally delete the contact. * An audit for older expired pcontacts was introduced which cares for getting rid of these contacts. Some code was introduced to help registering callbacks for contacts which are inserted into cache when being downloaded from database - for example ims_qos callback as at the time of insertion the message that triggered the original callback registering is long gone. * changes required for PR #3279 * add modparam db_mode to usrloc_api * remove unused method db_delete_presentity_uri_from_pua Co-authored-by: Annemarie Mandl --- src/modules/ims_usrloc_pcscf/README | 11 + .../doc/ims_usrloc_pcscf_admin.xml | 64 +++ .../ims_usrloc_pcscf/ims_usrloc_pcscf_mod.c | 51 +- .../ims_usrloc_pcscf/ims_usrloc_pcscf_mod.h | 1 + src/modules/ims_usrloc_pcscf/pcontact.c | 66 ++- src/modules/ims_usrloc_pcscf/udomain.c | 439 ++++++++++++++---- src/modules/ims_usrloc_pcscf/udomain.h | 4 +- src/modules/ims_usrloc_pcscf/ul_callback.c | 52 ++- src/modules/ims_usrloc_pcscf/ul_callback.h | 9 + src/modules/ims_usrloc_pcscf/ul_rpc.c | 156 ++++--- src/modules/ims_usrloc_pcscf/usrloc.c | 12 +- src/modules/ims_usrloc_pcscf/usrloc.h | 10 +- src/modules/ims_usrloc_pcscf/usrloc_db.c | 14 +- src/modules/ims_usrloc_pcscf/usrloc_db.h | 2 +- 14 files changed, 699 insertions(+), 192 deletions(-) diff --git a/src/modules/ims_usrloc_pcscf/README b/src/modules/ims_usrloc_pcscf/README index 553ee25bbed..7aaf195d422 100644 --- a/src/modules/ims_usrloc_pcscf/README +++ b/src/modules/ims_usrloc_pcscf/README @@ -175,6 +175,17 @@ modparam("ims_usrloc_pcscf", "db_url", reflected in the database. This is slow but very reliable. This mode will ensure that no registration data is lost as a result of a restart or crash. + * 3 - DB_ONLY Scheme. All changes to usrloc are immediately + reflected in the database and additionally PCSCF usrloc data are downloaded + from db and inserted into PCSCF usrloc cache if required - i.e. If + contact data cannot be found in cache a db + query for the contact is done in table location and when contact is + found there its respective data are inserted in PCSCF usrloc cache. + Also an audit had been added for removal of long expired PCSCF usrloc data + in table location. + Some of the db queries do only support Mysql. + This mode will ensure that no registration data is lost as a result of a + restart or crash. Default value is 0. diff --git a/src/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml b/src/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml index da4f99a7b9b..3c715352462 100644 --- a/src/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml +++ b/src/modules/ims_usrloc_pcscf/doc/ims_usrloc_pcscf_admin.xml @@ -142,6 +142,20 @@ modparam("ims_usrloc_pcscf", "db_url", reliable. This mode will ensure that no registration data is lost as a result of a restart or crash. + + + 3 - DB_ONLY Scheme. All changes to usrloc are immediately + reflected in the database and additionally PCSCF usrloc data are downloaded + from db and inserted into PCSCF usrloc cache if required - i.e. If + contact data cannot be found in cache a db + query for the contact is done in table location and when contact is + found there its respective data are inserted in PCSCF usrloc cache. + Also an audit had been added for removal of long expired PCSCF usrloc data + in table location. + This mode will ensure that no registration data is lost as a result of a + restart or crash. + + Default value is 0. @@ -198,6 +212,55 @@ modparam("ims_usrloc_pcscf", "match_contact_host_port", 0) ... modparam("ims_usrloc_pcscf", "expires_grace", 1800) ... + + + + +
+ audit_expired_pcontacts_interval (int) + + Number of seconds between two audit runs. + Note: audit is used for db_mode DB_ONLY (3) only. + The module uses this audit to + delete expired contacts found in db table location which are expired + at least as the audit_expired_pcontacts_timeout value. + Such expired contacts in location may appear when these contacts + are not present in usrloc cache because PCSCF crashed before + contact expiry. + + + Default value is 60. + + + Set audit_expired_pcontacts_interval parameter + + ... +modparam("ims_usrloc_pcscf", "audit_expired_pcontacts_interval", 120) +... + + +
+ +
+ audit_expired_pcontacts_timeout (int) + + Number of seconds the contacts must be already expired before the audit + starts working on them. + It is recommended to set only values greater than the Default value 40. + The module uses this audit to + delete expired contacts found in db table location which are expired + at least as many seconds as the sum of this timeout parameter value plus + the value of the expires_grace parameter. + + + Default value is 40. + + + Set audit_expired_pcontacts_timeout parameter + + ... +modparam("ims_usrloc_pcscf", "audit_expired_pcontacts_timeout", 120) +...
@@ -241,3 +304,4 @@ modparam("ims_usrloc_pcscf", "expires_grace", 1800) + diff --git a/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.c b/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.c index 26aaa2773bb..8e7c74ce632 100644 --- a/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.c +++ b/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.c @@ -40,6 +40,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ + #include #include "ims_usrloc_pcscf_mod.h" @@ -62,6 +63,11 @@ MODULE_VERSION #define DEFAULT_DBG_FILE "/var/log/usrloc_debug" static FILE *debug_file; +int audit_expired_pcontacts_timeout = 40; +int audit_expired_pcontacts_interval = 60; + +static void audit_usrloc_expired_pcontacts_timer(unsigned int ticks, void* param); + static int mod_init(void); /*!< Module initialization function */ static void destroy(void); /*!< Module destroy function */ static void timer(unsigned int ticks, void* param); /*!< Timer handler */ @@ -110,8 +116,10 @@ static param_export_t params[] = { {"timer_interval", INT_PARAM, &timer_interval }, {"db_mode", INT_PARAM, &db_mode }, - {"match_contact_host_port", INT_PARAM, &match_contact_host_port }, - {"expires_grace", INT_PARAM, &expires_grace }, + {"match_contact_host_port", INT_PARAM, &match_contact_host_port }, + {"audit_expired_pcontacts_timeout", INT_PARAM, &audit_expired_pcontacts_timeout }, + {"audit_expired_pcontacts_interval", INT_PARAM, &audit_expired_pcontacts_interval }, + {"expires_grace", INT_PARAM, &expires_grace }, {0, 0, 0} }; @@ -178,6 +186,11 @@ static int mod_init(void) { LM_DBG("Registering cache timer"); register_timer(timer, 0, timer_interval); + /* Register audit timer */ + if (db_mode == DB_ONLY) + register_timer(audit_usrloc_expired_pcontacts_timer, 0, audit_expired_pcontacts_interval); + + /* init the callbacks list */ if (init_ulcb_list() < 0) { LM_ERR("usrloc/callbacks initialization failed\n"); @@ -191,10 +204,15 @@ static int mod_init(void) { return -1; } - if (init_db(&db_url, timer_interval, ul_fetch_rows) != 0) { - LM_ERR("Error initializing db connection\n"); - return -1; - } + if (db_bind_mod(&db_url, &ul_dbf) < 0) { /* Find database module */ + LM_ERR("failed to bind database module\n"); + return -1; + } + if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) { + LM_ERR("database module does not implement all functions" + " needed by the module\n"); + return -1; + } LM_DBG("Running in DB mode %i\n", db_mode); } @@ -225,10 +243,12 @@ static int child_init(int _rank) } LM_DBG("Connecting to usrloc_pcscf DB for rank %d\n", _rank); - if (connect_db(&db_url) != 0) { - LM_ERR("child(%d): failed to connect to database\n", _rank); - return -1; - } + ul_dbh = ul_dbf.init(&db_url); /* Get a database connection per child */ + + if (!ul_dbh) { + LM_ERR("child(%d): failed to connect to database\n", _rank); + return -1; + } /* _rank==PROC_SIPINIT is used even when fork is disabled */ if (_rank==PROC_SIPINIT && db_mode!=DB_ONLY) { // if cache is used, populate domains from DB @@ -261,6 +281,17 @@ static void destroy(void) if (db_mode) destroy_db(); + + if (cbp_qos) + shm_free(cbp_qos); + + if (cbp_registrar) + shm_free(cbp_registrar); +} + +static void audit_usrloc_expired_pcontacts_timer(unsigned int ticks, void* param) { + + audit_usrloc_expired_pcontacts(root->d); } diff --git a/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.h b/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.h index 198ffc19879..0a7a75e52cf 100644 --- a/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.h +++ b/src/modules/ims_usrloc_pcscf/ims_usrloc_pcscf_mod.h @@ -59,5 +59,6 @@ extern int desc_time_order; extern int cseq_delay; extern int ul_fetch_rows; extern int ul_hash_size; +extern int db_mode; #endif /* UL_MOD_H */ diff --git a/src/modules/ims_usrloc_pcscf/pcontact.c b/src/modules/ims_usrloc_pcscf/pcontact.c index e597a0daf4b..c4c8c012fdf 100644 --- a/src/modules/ims_usrloc_pcscf/pcontact.c +++ b/src/modules/ims_usrloc_pcscf/pcontact.c @@ -277,6 +277,16 @@ int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, s (*_c)->num_service_routes = _ci->num_service_routes; } } + // add the rx session id + if ((_ci->rx_regsession_id) && (_ci->rx_regsession_id->len > 0) && (_ci->rx_regsession_id->s)) { + (*_c)->rx_session_id.s = shm_malloc(_ci->rx_regsession_id->len); + if (!((*_c)->rx_session_id.s)) { + LM_ERR("no more shm mem\n"); + goto out_of_memory; + } + memcpy((*_c)->rx_session_id.s, _ci->rx_regsession_id->s, _ci->rx_regsession_id->len); + (*_c)->rx_session_id.len = _ci->rx_regsession_id->len; + } LM_DBG("New contact host:port [%.*s:%d]\n", (*_c)->contact_host.len, (*_c)->contact_host.s, (*_c)->contact_port); LM_DBG("New contact via host:port:proto: [%.*s:%d:%d]\n", (*_c)->via_host.len, (*_c)->via_host.s, (*_c)->via_port, (*_c)->via_proto); @@ -357,18 +367,54 @@ static inline void nodb_timer(pcontact_t* _c) if ((_c->expires - act_time) + expires_grace <= 0) {//we've allowed some grace time TODO: add as parameter //if ((_c->expires - act_time) <= -10) {//we've allowed some grace time TODO: add as parameter - LM_DBG("pcscf contact <%.*s> has expired and will be removed\n", _c->aor.len, _c->aor.s); - if (exists_ulcb_type(PCSCF_CONTACT_EXPIRE)) { - run_ul_callbacks(PCSCF_CONTACT_EXPIRE, _c); - } - - if (db_mode == WRITE_THROUGH && db_delete_pcontact(_c) != 0) { + LM_DBG("pcscf contact <%.*s> has expired and will be removed\n", _c->aor.len, _c->aor.s); + + if (db_mode == DB_ONLY){ + if (db_load_pcontact(_c->slot->d, &_c->aor, 0/*insert_cache*/, &_c, NULL)){ + if ((_c->reg_state == PCONTACT_REG_PENDING_AAR) || (_c->reg_state == PCONTACT_REG_PENDING)){ + //we do not need expires_grace here as contact is not registered in scscf + if ((_c->expires - act_time) <= 0) { + _c->reg_state = PCONTACT_DEREG_PENDING_PUBLISH; + delete_pcontact(_c->slot->d, _c); + return; + } + } + else{ + if ((_c->expires - act_time) + expires_grace >= 0) { + return; + } + } + } + else{ + // not found in DB: better delete in cache also + update_stat(_c->slot->d->expired, 1); + mem_delete_pcontact(_c->slot->d, _c); + return; + } + + _c->reg_state = PCONTACT_DEREG_PENDING_PUBLISH; + if(db_delete_pcontact(_c) !=0) { LM_ERR("Error deleting ims_usrloc_pcscf record in DB"); + } //delete contact in DB to not process this contact in several units + if (exists_ulcb_type(PCSCF_CONTACT_UPDATE)) { + run_ul_callbacks(PCSCF_CONTACT_UPDATE, _c); + LM_INFO("pcscf contact <%.*s> has expired - sending PUBLISH\n", _c->aor.len, _c->aor.s); + return; + } + } + else{ + if (exists_ulcb_type(PCSCF_CONTACT_EXPIRE)) { + run_ul_callbacks(PCSCF_CONTACT_EXPIRE, _c); + } + + if (db_mode == WRITE_THROUGH && db_delete_pcontact(_c) != 0) { + LM_ERR("Error deleting ims_usrloc_pcscf record in DB"); + } + + update_stat(_c->slot->d->expired, 1); + mem_delete_pcontact(_c->slot->d, _c); + return; } - - update_stat(_c->slot->d->expired, 1); - mem_delete_pcontact(_c->slot->d, _c); - return; } //TODO: this is just for tmp debugging diff --git a/src/modules/ims_usrloc_pcscf/udomain.c b/src/modules/ims_usrloc_pcscf/udomain.c index d26ca2e1e70..e988d2ec8eb 100644 --- a/src/modules/ims_usrloc_pcscf/udomain.c +++ b/src/modules/ims_usrloc_pcscf/udomain.c @@ -57,12 +57,14 @@ #include "usrloc.h" #include "utime.h" #include "usrloc.h" +#include "ul_callback.h" #include "usrloc_db.h" #include "../../core/parser/parse_uri.h" #include "../../lib/ims/useful_defs.h" #include "../../modules/presence/presence.h" - +extern int expires_grace; +extern int audit_expired_pcontacts_timeout; extern int db_mode; extern int db_mode_ext; extern int match_contact_host_port; @@ -406,9 +408,9 @@ int update_pcontact(struct udomain* _d, struct pcontact_info* _ci, struct pconta //TODO: update path, etc - if (db_mode == WRITE_THROUGH && db_update_pcontact(_c) != 0) { - LM_ERR("Error updating record in DB"); - return -1; + if (((db_mode == WRITE_THROUGH) || (db_mode == DB_ONLY)) && (db_update_pcontact(_c) != 0)){ + LM_ERR("Error updating record in DB"); + return -1; } run_ul_callbacks(PCSCF_CONTACT_UPDATE, _c); @@ -428,7 +430,7 @@ int insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci run_ul_create_callbacks(*_c); } - if (db_mode == WRITE_THROUGH && db_insert_pcontact(*_c) != 0) { + if (((db_mode == WRITE_THROUGH) || (db_mode == DB_ONLY)) && db_insert_pcontact(*_c) != 0) { LM_ERR("error inserting contact into db"); goto error; } @@ -447,7 +449,7 @@ int insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci * @int reverse_search - reverse search for a contact in the memory * @return 0 if found <>0 if not */ -int get_pcontact(udomain_t* _d, pcontact_info_t* contact_info, struct pcontact** _c, int reverse_search) { +int get_pcontact_from_cache(udomain_t* _d, pcontact_info_t* contact_info, struct pcontact** _c, int reverse_search) { unsigned int sl, i, j, aorhash, params_len, has_rinstance=0; struct pcontact* c; struct sip_uri needle_uri; @@ -468,7 +470,7 @@ int get_pcontact(udomain_t* _d, pcontact_info_t* contact_info, struct pcontact** LM_DBG("Have an AOR to search for\n"); if (parse_uri(contact_info->aor.s, contact_info->aor.len, &needle_uri) != 0) { LM_ERR("Unable to parse contact aor in get_pcontact [%.*s]\n", contact_info->aor.len, contact_info->aor.s); - return 0; + return 1; } LM_DBG("checking for rinstance"); /*check for alias - NAT */ @@ -570,12 +572,33 @@ int get_pcontact(udomain_t* _d, pcontact_info_t* contact_info, struct pcontact** LM_DBG("confirming rinstance is the same - search has [%.*s] and proposed found contact has [%.*s]", rinstance.len, rinstance.s, c->rinstance.len, c->rinstance.s); - if ((rinstance.len == c->rinstance.len) && memcmp(rinstance.s, c->rinstance.s, rinstance.len) != 0) { + if ((rinstance.len != c->rinstance.len) || (memcmp(rinstance.s, c->rinstance.s, rinstance.len) != 0) ) { LM_DBG("rinstance does not match - no match here...\n"); c = reverse_search ? c->prev : c->next; continue; } } + if ((contact_info->aor.len>0) && (needle_uri.user.len != 0)){ + if ((needle_uri.user.len != c->contact_user.len) || + (memcmp(needle_uri.user.s, c->contact_user.s, needle_uri.user.len) != 0)) { + LM_ERR("user name does not match - no match here...\n"); + LM_DBG("found pcontact username [%d]: [%.*s]\n", i, c->contact_user.len, c->contact_user.s); + LM_DBG("incoming contact username: [%.*s]\n", needle_uri.user.len, needle_uri.user.s); + c = c->next; + continue; + } + if ((contact_info->aor.len >= 4) && (memcmp(contact_info->aor.s, c->aor.s, 4) != 0)) { // do not mix up sip- and tel-URIs. + LM_ERR("scheme does not match - no match here...\n"); + LM_DBG("found pcontact scheme [%d]: [%.*s]\n", i, 4, c->aor.s); + LM_DBG("incoming contact scheme: [%.*s]\n", 4, contact_info->aor.s); + c = c->next; + continue; + } + } + else{ + LM_DBG("No user name present - abort user name check\n"); + } + if ((contact_info->extra_search_criteria & SEARCH_SERVICE_ROUTES) && contact_info->num_service_routes > 0) { LM_DBG("have %d service routes to search for\n", contact_info->num_service_routes); @@ -626,7 +649,7 @@ int get_pcontact(udomain_t* _d, pcontact_info_t* contact_info, struct pcontact** } int update_security(udomain_t* _d, security_type _t, security_t* _s, struct pcontact* _c) { - if (db_mode == WRITE_THROUGH && db_update_pcontact_security(_c, _t, _s) != 0) { + if (((db_mode == WRITE_THROUGH) || (db_mode == DB_ONLY)) && db_update_pcontact_security(_c, _t, _s) != 0) { LM_ERR("Error updating security for contact in DB\n"); return -1; } @@ -635,7 +658,7 @@ int update_security(udomain_t* _d, security_type _t, security_t* _s, struct pcon } int update_temp_security(udomain_t* _d, security_type _t, security_t* _s, struct pcontact* _c) { - if (db_mode == WRITE_THROUGH && db_update_pcontact_security_temp(_c, _t, _s) != 0) { + if (((db_mode == WRITE_THROUGH) || (db_mode == DB_ONLY)) && db_update_pcontact_security_temp(_c, _t, _s) != 0) { LM_ERR("Error updating temp security for contact in DB\n"); return -1; } @@ -698,8 +721,7 @@ int delete_pcontact(udomain_t* _d, /*str* _aor, str* _received_host, int _receiv if (exists_ulcb_type(PCSCF_CONTACT_DELETE)) { run_ul_callbacks(PCSCF_CONTACT_DELETE, _c); } - - if (db_mode == WRITE_THROUGH && db_delete_pcontact(_c) != 0) { + if (((db_mode == WRITE_THROUGH) || (db_mode == DB_ONLY)) && db_delete_pcontact(_c) != 0) { LM_ERR("Error deleting contact from DB"); return -1; } @@ -1045,11 +1067,23 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d) if ( (mem_insert_pcontact(_d, &aor, ci, &c)) != 0) { LM_ERR("inserting contact failed\n"); unlock_udomain(_d, &ci->via_host, ci->via_port, ci->via_prot); + if(ci->public_ids){ + pkg_free(ci->public_ids); + } + if(ci->service_routes){ + pkg_free(ci->service_routes); + } goto error1; } //c->flags = c->flags|(1<via_host, ci->via_port, ci->via_prot); + if(ci->public_ids){ + pkg_free(ci->public_ids); + } + if(ci->service_routes){ + pkg_free(ci->service_routes); + } } if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) { @@ -1077,91 +1111,328 @@ int preload_udomain(db1_con_t* _c, udomain_t* _d) return -1; } -pcontact_t* db_load_pcontact(db1_con_t* _c, udomain_t* _d, str *_aor) +int db_load_pcontact(udomain_t* _d, str *_aor, int insert_cache, struct pcontact** _c, pcontact_info_t* contact_info) { pcontact_info_t *ci; - db_key_t columns[15]; - db_key_t keys[1]; - db_val_t vals[1]; - db1_res_t* res = NULL; - db_row_t *row; - int i; - str aor; + db_key_t columns[15]; + db_key_t keys[2]; + db_val_t vals[2]; + db_op_t op[2]; + db1_res_t* res = NULL; + db_row_t *row; + int i; + str aor, port={0,0}; + pcontact_t* c = NULL; + + keys[0] = &aor_col; + vals[0].type = DB1_STR; + vals[0].nul = 0; + vals[0].val.str_val = *_aor; + op[0] = OP_EQ; + op[1] = OP_EQ; + + + columns[0] = &domain_col; + columns[1] = &aor_col; + columns[2] = &host_col; + columns[3] = &port_col; + columns[4] = &protocol_col; + columns[5] = &received_col; + columns[6] = &received_port_col; + columns[7] = &received_proto_col; + columns[8] = &rx_session_id_col; + columns[9] = ®_state_col; + columns[10] = &expires_col; + columns[11] = &socket_col; + columns[12] = &service_routes_col; + columns[13] = &public_ids_col; + columns[14] = &path_col; + + + + if (_aor->len>0 && _aor->s){ + LM_DBG("Querying database for P-CSCF contact [%.*s]\n", _aor->len, _aor->s); + } else { + LM_DBG("Querying database for P-CSCF received_host [%.*s] and received_port [%d]\n", contact_info->received_host.len, contact_info->received_host.s, contact_info->received_port); + keys[0] = &received_col; + vals[0].type = DB1_STR; + vals[0].nul = 0; + vals[0].val.str_val = contact_info->received_host; + keys[1] = &received_port_col; + vals[1].type = DB1_INT; + vals[1].nul = 0; + port.s = int2str(contact_info->received_port, &port.len); + vals[1].val.int_val = contact_info->received_port; + + } + + if (ul_dbf.use_table(ul_dbh, _d->name) < 0) { + LM_ERR("sql use_table failed\n"); + return -1; + } + + + if (ul_dbf.query(ul_dbh, keys, op, vals, columns, port.s ? 2 : 1, 15, 0, &res) < 0) { + if (!port.s) { + LM_ERR("Unable to query DB for location associated with aor [%.*s]\n", _aor->len, _aor->s); + } + else { + LM_ERR("Unable to query DB for location associated with host [%.*s] and port [%.*s]\n", contact_info->received_host.len, contact_info->received_host.s, port.len, port.s); + } + ul_dbf.free_result(ul_dbh, res); + return 0; + } + + if (RES_ROW_N(res) == 0) { + if (!port.s) { + LM_DBG("aor [%.*s] not found in table %.*s\n",_aor->len, _aor->s, _d->name->len, _d->name->s); + } + else { + LM_DBG("host [%.*s] and port [%.*s] not found in table %.*s\n", contact_info->received_host.len, contact_info->received_host.s, port.len, port.s, _d->name->len, _d->name->s); + } + + ul_dbf.free_result(ul_dbh, res); + return 0; + } + LM_DBG("Handling Result for query received\n"); + + for(i = 0; i < RES_ROW_N(res); i++) { + row = RES_ROWS(res) + i; + + aor.s = (char*) VAL_STRING(ROW_VALUES(row) + 1); + if (VAL_NULL(ROW_VALUES(row) + 1) || aor.s == 0 || aor.s[0] == 0) { + LM_ERR("empty aor record in table %s...skipping\n", _d->name->s); + continue; + } + aor.len = strlen(aor.s); + + if ((_aor->len==0 && !_aor->s) && (VAL_NULL(ROW_VALUES(row) + 5) || VAL_NULL(ROW_VALUES(row) + 6))){ + LM_ERR("empty received_host or received_port record in table %s...skipping\n", _d->name->s); + continue; + } + LM_DBG("Convert database values extracted with AOR."); + ci = dbrow2info(ROW_VALUES(row) + 1, &aor); + if (!ci) { + LM_WARN("Failed to get contact info from DB.... continuing...\n"); + continue; + } + + if(!(insert_cache)){ + (*_c)->expires = ci->expires; + ul_dbf.free_result(ul_dbh, res); + if(ci->public_ids){ + pkg_free(ci->public_ids); + } + if(ci->service_routes){ + pkg_free(ci->service_routes); + } + LM_DBG("Freed memory in db_load_pcontact"); + return 1; + } + if(ci->reg_state==PCONTACT_REGISTERED){ + if ( (mem_insert_pcontact(_d, &aor, ci, &c)) != 0) { + if(ci->public_ids){ + pkg_free(ci->public_ids); + } + if(ci->service_routes){ + pkg_free(ci->service_routes); + } + LM_ERR("inserting contact failed\n"); + goto error; + } + }else { + if(ci->public_ids){ + pkg_free(ci->public_ids); + } + if(ci->service_routes){ + pkg_free(ci->service_routes); + } + LM_ERR("inserting contact failed\n"); + goto error1; + } + if (exists_ulcb_type(PCSCF_CONTACT_INSERT)) { + run_ul_create_callbacks(c); + } - pcontact_t* c; + register_ulcb(c, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE | PCSCF_CONTACT_UPDATE, cbp_registrar->callback, NULL); - keys[0] = &aor_col; - vals[0].type = DB1_STR; - vals[0].nul = 0; - vals[0].val.str_val = *_aor; + if (c->rx_session_id.len > 0){ + register_ulcb(c, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE, cbp_qos->callback, NULL); + } + + //c->flags = c->flags|(1<public_ids){ + pkg_free(ci->public_ids); + } + if(ci->service_routes){ + pkg_free(ci->service_routes); + } - columns[0] = &domain_col; - columns[1] = &aor_col; - columns[2] = &host_col; - columns[3] = &port_col; - columns[4] = &protocol_col; - columns[5] = &received_col; - columns[6] = &received_port_col; - columns[7] = &received_proto_col; - columns[8] = &rx_session_id_col; - columns[9] = ®_state_col; - columns[10] = &expires_col; - columns[11] = &socket_col; - columns[12] = &service_routes_col; - columns[13] = &public_ids_col; - columns[14] = &path_col; - - LM_DBG("Querying database for P-CSCF contact [%.*s]\n", _aor->len, _aor->s); - - if (ul_dbf.use_table(_c, _d->name) < 0) { - LM_ERR("failed to use table %.*s\n", _d->name->len, _d->name->s); - return 0; } - if (ul_dbf.query(_c, keys, 0, vals, columns, 1, 15, 0, &res) < 0) { - LM_ERR("db_query failed\n"); - return 0; - } + ul_dbf.free_result(ul_dbh, res); + return 1; - if (RES_ROW_N(res) == 0) { - LM_DBG("aor %.*s not found in table %.*s\n",_aor->len, _aor->s, _d->name->len, _d->name->s); - ul_dbf.free_result(_c, res); - return 0; - } +error: + free_pcontact(c); +error1: + ul_dbf.free_result(ul_dbh, res); + return 0; +} - for(i = 0; i < RES_ROW_N(res); i++) { - row = RES_ROWS(res) + i; - aor.s = (char*) VAL_STRING(ROW_VALUES(row) + 1); - if (VAL_NULL(ROW_VALUES(row) + 1) || aor.s == 0 || aor.s[0] == 0) { - LM_CRIT("empty aor record in table %s...skipping\n", _d->name->s); - continue; - } - aor.len = strlen(aor.s); - ci = dbrow2info(ROW_VALUES(row) + 1, &aor); - if (!ci) { - LM_WARN("Failed to get contact info from DB.... continuing...\n"); - continue; - } - lock_udomain(_d, &ci->via_host, ci->via_port, ci->via_prot); - if ( (mem_insert_pcontact(_d, &aor, ci, &c)) != 0) { - LM_ERR("inserting contact failed\n"); - unlock_udomain(_d, &ci->via_host, ci->via_port, ci->via_prot); - goto error; - } - //c->flags = c->flags|(1<via_host, ci->via_port, ci->via_prot); - } - ul_dbf.free_result(_c, res); +int get_pcontact(udomain_t* _d, pcontact_info_t* contact_info, struct pcontact** _c, int reverse_search) { - return c; + int ret = get_pcontact_from_cache(_d, contact_info, _c, reverse_search); + + if (ret && (db_mode == DB_ONLY)){ + LM_DBG("contact not found in cache for contact_info->received_port [%d]\n", contact_info->received_port); + if (contact_info->searchflag == SEARCH_RECEIVED){ + LM_DBG("Trying contact_info.extra_search_criteria = 0\n"); + contact_info->extra_search_criteria = 0; + ret = get_pcontact_from_cache(_d, contact_info, _c, reverse_search); + if (ret == 0){ + return ret; + } + LM_DBG("contact not found in cache for contact_info->via_port [%d]\n", contact_info->via_port); + contact_info->extra_search_criteria = SEARCH_SERVICE_ROUTES; + + contact_info->searchflag = SEARCH_NORMAL; + LM_DBG("Trying contact_info.searchflag = SEARCH_NORMAL\n"); + ret = get_pcontact_from_cache(_d, contact_info, _c, reverse_search); + if (ret == 0){ + return ret; + } + else { + LM_DBG("Trying contact_info.extra_search_criteria = 0\n"); + contact_info->extra_search_criteria = 0; + ret = get_pcontact_from_cache(_d, contact_info, _c, reverse_search); + if (ret == 0){ + return ret; + } + LM_DBG("contact not found in cache for contact_info->via_port [%d]\n", contact_info->via_port); + contact_info->extra_search_criteria = SEARCH_SERVICE_ROUTES; + contact_info->searchflag = SEARCH_RECEIVED; + } + } + else { + LM_DBG("Trying contact_info.extra_search_criteria = 0\n"); + contact_info->extra_search_criteria = 0; + ret = get_pcontact_from_cache(_d, contact_info, _c, reverse_search); + if (ret == 0){ + return ret; + } + LM_DBG("contact not found in cache for contact_info->via_port [%d]\n", contact_info->via_port); + contact_info->extra_search_criteria = SEARCH_SERVICE_ROUTES; + } + if (db_load_pcontact(_d, &contact_info->aor, 1/*insert_cache*/, _c, contact_info)){ + LM_DBG("loaded location from db for AOR [%.*s]\n", contact_info->aor.len, contact_info->aor.s); + return 0; + } else { + LM_DBG("download location DB failed for AOR [%.*s]\n", contact_info->aor.len, contact_info->aor.s); + return 1; + } + } -error: - free_pcontact(c); + return ret; - ul_dbf.free_result(_c, res); - return 0; } +int audit_usrloc_expired_pcontacts(udomain_t* _d) { + + db1_res_t* location_rs = NULL; + pcontact_info_t *ci; + db_key_t columns[15]; + db_key_t keys[1]; + db_val_t vals[1]; + db_op_t op[1]; + db_row_t *row; + int i; + str aor; + pcontact_t* c = NULL; + + keys[0] = &expires_col; + vals[0].type = DB1_DATETIME; + vals[0].nul = 0; + vals[0].val.time_val = time(0) - expires_grace - audit_expired_pcontacts_timeout;; + op[0] = OP_LT; + + + columns[0] = &domain_col; + columns[1] = &aor_col; + columns[2] = &host_col; + columns[3] = &port_col; + columns[4] = &protocol_col; + columns[5] = &received_col; + columns[6] = &received_port_col; + columns[7] = &received_proto_col; + columns[8] = &rx_session_id_col; + columns[9] = ®_state_col; + columns[10] = &expires_col; + columns[11] = &socket_col; + columns[12] = &service_routes_col; + columns[13] = &public_ids_col; + columns[14] = &path_col; + + if (ul_dbf.use_table(ul_dbh, _d->name) < 0) { + LM_ERR("sql use_table failed\n"); + return -1; + } + + if (ul_dbf.query(ul_dbh, keys, op, vals, columns, 1, 15, 0, &location_rs) < 0) { + LM_ERR("Unable to query DB for expired pcontacts\n"); + ul_dbf.free_result(ul_dbh, location_rs); + } else { + if (RES_ROW_N(location_rs) == 0) { + LM_DBG("no expired pcontacts found in DB\n"); + ul_dbf.free_result(ul_dbh, location_rs); + goto done; + } + + for(i = 0; i < RES_ROW_N(location_rs); i++) { + row = RES_ROWS(location_rs) + i; + + aor.s = (char*) VAL_STRING(ROW_VALUES(row) + 1); + + if (VAL_NULL(ROW_VALUES(row) + 1) || aor.s == 0 || aor.s[0] == 0) { + LM_ERR("empty aor record in table %s...skipping\n", _d->name->s); + continue; + } + aor.len = strlen(aor.s); + ci = dbrow2info(ROW_VALUES(row) + 1, &aor); + if (!ci) { + LM_ERR("Failed to get contact info from DB.... continuing...\n"); + continue; + } + ci->aor = aor; + ci->searchflag = SEARCH_NORMAL; + ci->reg_state = PCONTACT_ANY; + lock_udomain(_d, &ci->via_host, ci->via_port, ci->via_prot); + if (get_pcontact_from_cache(_d, ci, &c, 0) == 0){ + LM_DBG("found pcontact [%.*s] in cache.....should have been cleared by expiry handler\n", aor.len, aor.s); + } + else{ + // insert pcontact + if (!(db_load_pcontact(_d, &aor, 1/*insert_cache*/, &c, ci))){ + LM_ERR("could not insert pcontact [%.*s] into cache\n", aor.len, aor.s); + } + } + unlock_udomain(_d, &ci->via_host, ci->via_port, ci->via_prot); + if(ci->public_ids){ + pkg_free(ci->public_ids); + } + if(ci->service_routes){ + pkg_free(ci->service_routes); + } + } + ul_dbf.free_result(ul_dbh, location_rs); + } +done: + return 0; +} + diff --git a/src/modules/ims_usrloc_pcscf/udomain.h b/src/modules/ims_usrloc_pcscf/udomain.h index 0b0594cb82e..5e190af2031 100644 --- a/src/modules/ims_usrloc_pcscf/udomain.h +++ b/src/modules/ims_usrloc_pcscf/udomain.h @@ -40,6 +40,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ + #ifndef UDOMAIN_H #define UDOMAIN_H @@ -82,5 +83,6 @@ int update_security(udomain_t* _d, security_type _t, security_t* _s, struct pcon int update_temp_security(udomain_t* _d, security_type _t, security_t* _s, struct pcontact* _c); int preload_udomain(db1_con_t* _c, udomain_t* _d); - +int audit_usrloc_expired_pcontacts(udomain_t* _d); +int db_load_pcontact(udomain_t* _d, str *_aor, int insert_cache, struct pcontact** _c, pcontact_info_t* contact_info); #endif diff --git a/src/modules/ims_usrloc_pcscf/ul_callback.c b/src/modules/ims_usrloc_pcscf/ul_callback.c index ad2d4958097..957c4b9a2ef 100644 --- a/src/modules/ims_usrloc_pcscf/ul_callback.c +++ b/src/modules/ims_usrloc_pcscf/ul_callback.c @@ -44,14 +44,14 @@ * */ + #include #include "../../core/dprint.h" #include "../../core/error.h" #include "../../core/mem/shm_mem.h" -#include "ul_callback.h" -#include "usrloc.h" - +//#include "ul_callback.h" +#include "../ims_usrloc_pcscf/usrloc.h" struct ulcb_head_list* ulcb_list = 0; /*PCSCF_MAX ) { + LM_CRIT("invalid callback types: mask=%d\n",types); + return E_BUG; + } + /* we don't register null functions */ + if (f==0) { + LM_CRIT("null callback function\n"); + return E_BUG; + } + + /* build a new callback structure */ + if ( types & PCSCF_CONTACT_UPDATE){ + if (!(cbp_registrar=(struct ul_callback*)shm_malloc(sizeof( struct ul_callback)))) { + LM_ERR("no more share mem\n"); + return E_OUT_OF_MEM; + } + cbp_registrar->callback = f; + } + else{ + if (!(cbp_qos=(struct ul_callback*)shm_malloc(sizeof( struct ul_callback)))) { + LM_ERR("no more share mem\n"); + return E_OUT_OF_MEM; + } + cbp_qos->callback = f; + } + return 1; +} + int register_ulcb( struct pcontact *c, int types, ul_cb f, void *param ) { struct ul_callback *cbp; @@ -182,6 +215,19 @@ void delete_ulcb(struct pcontact* c, int type) LM_DBG("No ulcb has been deleted for contact: aor[%.*s], via port %u, received port %u\n", c->aor.len, c->aor.s, c->via_port, c->received_port); } +int is_ulcb_registered( struct pcontact *c, ul_cb f) +{ + struct ul_callback *cbp; + + for (cbp=c->cbs.first; cbp; cbp=cbp->next) { + if (cbp->callback == f) + return 1; + } + return 0; + +}; + + /*! \brief run all transaction callbacks for an event type */ void run_ul_callbacks( int type , struct pcontact *c) { diff --git a/src/modules/ims_usrloc_pcscf/ul_callback.h b/src/modules/ims_usrloc_pcscf/ul_callback.h index ec1a96ccc22..a2c36eec8cf 100644 --- a/src/modules/ims_usrloc_pcscf/ul_callback.h +++ b/src/modules/ims_usrloc_pcscf/ul_callback.h @@ -42,11 +42,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ + #ifndef _UL_CALLBACKS_H #define _UL_CALLBACKS_H #include "../../core/dprint.h" +#include "../../core/parser/msg_parser.h" +#include "../../core/parser/contact/parse_contact.h" +#include "../../core/ut.h" +#include "../ims_usrloc_pcscf/usrloc.h" +#include "../../lib/ims/ims_getters.h" struct pcontact; @@ -58,6 +64,7 @@ struct pcontact; typedef void (ul_cb) (struct pcontact *c, int type, void *param); /*! \brief callback function prototype */ typedef int (*register_ulcb_t)(struct pcontact *c, int cb_types, ul_cb f, void *param); /*! \brief register callback function prototype */ +typedef int (*is_ulcb_registered_t)(struct pcontact *c, ul_cb f); struct ul_callback { int types; /*!< types of events that trigger the callback*/ @@ -82,7 +89,9 @@ void destroy_ulcb_list(void); void destroy_ul_callbacks_list(struct ul_callback* cb); int register_ulcb( struct pcontact *c, int types, ul_cb f, void *param); void delete_ulcb(struct pcontact* c, int type); +int register_ulcb_method( struct pcontact *c, int types, ul_cb f, void *param); void run_ul_callbacks( int type , struct pcontact *c); void run_ul_create_callbacks(struct pcontact *c); +int is_ulcb_registered(struct pcontact *c, ul_cb f); #endif diff --git a/src/modules/ims_usrloc_pcscf/ul_rpc.c b/src/modules/ims_usrloc_pcscf/ul_rpc.c index 907adc23e73..91d95dd59f9 100644 --- a/src/modules/ims_usrloc_pcscf/ul_rpc.c +++ b/src/modules/ims_usrloc_pcscf/ul_rpc.c @@ -42,13 +42,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ - + #include "../../core/ip_addr.h" #include "../../core/dprint.h" #include "ul_rpc.h" #include "dlist.h" #include "udomain.h" +#include "pcontact.h" +#include "utime.h" static const char* ul_rpc_dump_doc[2] = { "Dump PCSCF contacts and associated identitites", @@ -58,13 +60,15 @@ static const char* ul_rpc_dump_doc[2] = { static void ul_rpc_dump(rpc_t* rpc, void* ctx) { dlist_t* dl; udomain_t* dom; -// time_t t; + time_t t; void* th; void* ah; void* sh; int max, n, i; -// t = time(0); + pcontact_t* c; + + t = time(0); for (dl = root; dl; dl = dl->next) { dom = dl->d; if (rpc->add(ctx, "{", &th) < 0) { @@ -78,82 +82,82 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx) { } for (i = 0, n = 0, max = 0; i < dom->size; i++) { -// lock_ulslot(dom, i); + lock_ulslot(dom, i); n += dom->table[i].n; if (max < dom->table[i].n) max = dom->table[i].n; -// for (c = dom->table[i].first; c; c = c->next) { -// if (rpc->struct_add(ah, "S", "AoR", &c->aor) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error creating aor struct"); -// return; -// } -// if (rpc->struct_add(ah, "s", "State", reg_state_to_string(c->reg_state)) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error creating reg state struct"); -// return; -// } -// if (c->expires == 0) { -// if (rpc->struct_add(ah, "s", "Expires", "permanent") < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error adding expire"); -// return; -// } -// } else if (c->expires == -1/*UL_EXPIRED_TIME*/) { -// if (rpc->struct_add(ah, "s", "Expires", "deleted") < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error adding expire"); -// return; -// } -// } else if (t > c->expires) { -// if (rpc->struct_add(ah, "s", "Expires", "expired") < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error adding expire"); -// return; -// } -// } else { -// if (rpc->struct_add(ah, "d", "Expires", (int) (c->expires - t)) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error adding expire"); -// return; -// } -// } -// -// if (rpc->struct_add(ah, "S", "Path", &c->path) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error creating path struct"); -// return; -// } -// -// if (rpc->struct_add(ah, "{", "Service Routes", &sr) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error creating Service Routes"); -// return; -// } -// -// for (j = 0; j < c->num_service_routes; j++) { -// if (rpc->struct_add(sr, "S", "Route", &c->service_routes[j]) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error creating Service Route struct"); -// return; -// } -// } -// -// if (rpc->struct_add(ah, "{", "Public Identities", &ih) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error creating IMPU struct"); -// return; -// } -// -// for (p = c->head; p; p = p->next) { -// if (rpc->struct_add(ih, "S", "IMPU", &p->public_identity) < 0) { -// unlock_ulslot(dom, i); -// rpc->fault(ctx, 500, "Internal error creating IMPU struct"); -// return; -// } -// } -// } -// unlock_ulslot(dom, i); + for (c = dom->table[i].first; c; c = c->next) { + if (rpc->struct_add(ah, "S", "AoR", &c->aor) < 0) { + unlock_ulslot(dom, i); + rpc->fault(ctx, 500, "Internal error creating aor struct"); + return; + } + if (rpc->struct_add(ah, "s", "State", reg_state_to_string(c->reg_state)) < 0) { + unlock_ulslot(dom, i); + rpc->fault(ctx, 500, "Internal error creating reg state struct"); + return; + } + if (c->expires == 0) { + if (rpc->struct_add(ah, "s", "Expires", "permanent") < 0) { + unlock_ulslot(dom, i); + rpc->fault(ctx, 500, "Internal error adding expire"); + return; + } + } else if (c->expires == -1/*UL_EXPIRED_TIME*/) { + if (rpc->struct_add(ah, "s", "Expires", "deleted") < 0) { + unlock_ulslot(dom, i); + rpc->fault(ctx, 500, "Internal error adding expire"); + return; + } + } else if (t > c->expires) { + if (rpc->struct_add(ah, "s", "Expires", "expired") < 0) { + unlock_ulslot(dom, i); + rpc->fault(ctx, 500, "Internal error adding expire"); + return; + } + } else { + if (rpc->struct_add(ah, "d", "Expires", (int) (c->expires - t)) < 0) { + unlock_ulslot(dom, i); + rpc->fault(ctx, 500, "Internal error adding expire"); + return; + } + } + + if (rpc->struct_add(ah, "S", "Path", &c->path) < 0) { + unlock_ulslot(dom, i); + rpc->fault(ctx, 500, "Internal error creating path struct"); + return; + } + + // if (rpc->struct_add(ah, "{", "Service Routes", &sr) < 0) { + // unlock_ulslot(dom, i); + // rpc->fault(ctx, 500, "Internal error creating Service Routes"); + // return; + // } + + // for (j = 0; j < c->num_service_routes; j++) { + // if (rpc->struct_add(sr, "S", "Route", &c->service_routes[j]) < 0) { + // unlock_ulslot(dom, i); + // rpc->fault(ctx, 500, "Internal error creating Service Route struct"); + // return; + // } + // } + + // if (rpc->struct_add(ah, "{", "Public Identities", &ih) < 0) { + // unlock_ulslot(dom, i); + // rpc->fault(ctx, 500, "Internal error creating IMPU struct"); + // return; + // } + + // for (p = c->head; p; p = p->next) { + // if (rpc->struct_add(ih, "S", "IMPU", &p->public_identity) < 0) { + // unlock_ulslot(dom, i); + // rpc->fault(ctx, 500, "Internal error creating IMPU struct"); + // return; + // } + // } + } + unlock_ulslot(dom, i); } if (rpc->struct_add(ah, "{", "Stats", &sh) > 0) { rpc->fault(ctx, 500, "Internal error creating stats"); diff --git a/src/modules/ims_usrloc_pcscf/usrloc.c b/src/modules/ims_usrloc_pcscf/usrloc.c index 418e1859bc6..f3aa7be7ca5 100644 --- a/src/modules/ims_usrloc_pcscf/usrloc.c +++ b/src/modules/ims_usrloc_pcscf/usrloc.c @@ -42,7 +42,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ - + #include "usrloc.h" #include "dlist.h" #include "pcontact.h" @@ -53,6 +53,10 @@ extern int ims_ulp_init_flag; +struct ul_callback *cbp_registrar = 0; +struct ul_callback *cbp_qos = 0; + + int bind_usrloc(usrloc_api_t* api) { if (!api) { LM_ERR("invalid parameter value\n"); @@ -70,7 +74,7 @@ int bind_usrloc(usrloc_api_t* api) { api->unlock_udomain = unlock_udomain; api->insert_pcontact = insert_pcontact; api->delete_pcontact = delete_pcontact; - api->unreg_pending_contacts_cb = unreg_pending_contacts_cb; + api->unreg_pending_contacts_cb = unreg_pending_contacts_cb; api->get_pcontact = get_pcontact; api->assert_identity = assert_identity; api->update_pcontact = update_pcontact; @@ -80,6 +84,10 @@ int bind_usrloc(usrloc_api_t* api) { api->update_temp_security = update_temp_security; api->register_ulcb = register_ulcb; api->get_number_of_contacts = get_number_of_contacts; + api->is_ulcb_registered = is_ulcb_registered; + api->register_ulcb_method = register_ulcb_method; + + api->db_mode = db_mode; return 0; } diff --git a/src/modules/ims_usrloc_pcscf/usrloc.h b/src/modules/ims_usrloc_pcscf/usrloc.h index 1804ab1a512..1596666b267 100644 --- a/src/modules/ims_usrloc_pcscf/usrloc.h +++ b/src/modules/ims_usrloc_pcscf/usrloc.h @@ -41,6 +41,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ + #ifndef USRLOC_H #define USRLOC_H @@ -56,7 +57,7 @@ #define NO_DB 0 #define WRITE_THROUGH 1 #define WRITE_BACK 2 //not implemented yet -#define DB_ONLY 3 //not implemented yet +#define DB_ONLY 3 #define SEARCH_NORMAL 0 #define SEARCH_RECEIVED 1 @@ -239,6 +240,9 @@ typedef struct pcontact { typedef int (*get_pcontact_t)(struct udomain* _d, pcontact_info_t* contact_info, struct pcontact** _c, int reverse_search); +typedef int (*db_load_pcontact_t)(udomain_t* _d, str *_aor, int insert_cache, struct pcontact** _c, pcontact_info_t* contact_info); +extern struct ul_callback *cbp_registrar; +extern struct ul_callback *cbp_qos; typedef int (*assert_identity_t)(struct udomain* _d, str * _host, unsigned short _port, unsigned short _proto, str * _identity); typedef int (*insert_pcontact_t)(struct udomain* _d, str* _aor, struct pcontact_info* ci, struct pcontact** _c); @@ -286,6 +290,10 @@ typedef struct usrloc_api { register_ulcb_t register_ulcb; get_number_of_contacts_t get_number_of_contacts; + + is_ulcb_registered_t is_ulcb_registered; + register_ulcb_t register_ulcb_method; + db_load_pcontact_t db_load_pcontact; } usrloc_api_t; /*! usrloc API export bind function */ diff --git a/src/modules/ims_usrloc_pcscf/usrloc_db.c b/src/modules/ims_usrloc_pcscf/usrloc_db.c index 5f0df126fa2..4b6b05ec3f7 100644 --- a/src/modules/ims_usrloc_pcscf/usrloc_db.c +++ b/src/modules/ims_usrloc_pcscf/usrloc_db.c @@ -122,6 +122,11 @@ int use_location_pcscf_table(str* domain) return 0; } +db1_con_t* get_db_handle () +{ + return ul_dbh; + +} int db_update_pcontact(pcontact_t* _c) { @@ -129,7 +134,7 @@ int db_update_pcontact(pcontact_t* _c) db_val_t match_values[2]; db_key_t match_keys[2] = { &aor_col, &received_port_col }; - db_op_t op[2]; + db_op_t op[2]; db_key_t update_keys[8] = { &expires_col, ®_state_col, &service_routes_col, &received_col, &received_port_col, &received_proto_col, @@ -146,8 +151,8 @@ int db_update_pcontact(pcontact_t* _c) VAL_NULL(match_values + 1) = 0; VAL_INT(match_values + 1) = _c->received_port; - op[0]=OP_EQ; - op[1]=OP_EQ; + op[0]=OP_EQ; + op[1]=OP_EQ; if (use_location_pcscf_table(_c->domain) < 0) { LM_ERR("Error trying to use table %.*s\n", _c->domain->len, _c->domain->s); @@ -200,6 +205,7 @@ int db_update_pcontact(pcontact_t* _c) return -1; } + if (ul_dbf.affected_rows && ul_dbf.affected_rows(ul_dbh) == 0) { LM_DBG("no existing rows for an update... doing insert\n"); if (db_insert_pcontact(_c) != 0) { @@ -301,7 +307,7 @@ int db_insert_pcontact(struct pcontact* _c) SET_PROPER_NULL_FLAG(_c->rinstance, values, LP_RINSTANCE_IDX); SET_PROPER_NULL_FLAG(_c->rx_session_id, values, LP_RX_SESSION_ID_IDX); - VAL_DOUBLE(GET_FIELD_IDX(values, LP_REG_STATE_IDX)) = _c->reg_state; + VAL_INT(GET_FIELD_IDX(values, LP_REG_STATE_IDX)) = _c->reg_state; VAL_TIME(GET_FIELD_IDX(values, LP_EXPIRES_IDX)) = _c->expires; VAL_NULL(GET_FIELD_IDX(values, LP_REG_STATE_IDX)) = 0; VAL_NULL(GET_FIELD_IDX(values, LP_EXPIRES_IDX)) = 0; diff --git a/src/modules/ims_usrloc_pcscf/usrloc_db.h b/src/modules/ims_usrloc_pcscf/usrloc_db.h index 9e14eecd129..3deeea813c7 100644 --- a/src/modules/ims_usrloc_pcscf/usrloc_db.h +++ b/src/modules/ims_usrloc_pcscf/usrloc_db.h @@ -142,5 +142,5 @@ int db_delete_pcontact(pcontact_t* _c); int db_update_pcontact(pcontact_t* _c); int db_update_pcontact_security_temp(struct pcontact* _c, security_type _t, security_t* _s); int db_update_pcontact_security(struct pcontact* _c, security_type _t, security_t* _s); - +db1_con_t* get_db_handle (); #endif /* USRLOC_DB_H_ */