diff --git a/src/modules/p_usrloc/config.c b/src/modules/p_usrloc/config.c index 16d9f3f0cfe..bf24a972291 100644 --- a/src/modules/p_usrloc/config.c +++ b/src/modules/p_usrloc/config.c @@ -47,7 +47,7 @@ cfg_def_t p_usrloc_cfg_def[] = { " Specifies the error value on which a database shall be turned off. "}, {"failover_level", CFG_VAR_INT | CFG_ATOMIC, 0, 0, 0, 0, "Specifies the manner a failover is done (1 = turn off, 2 = find a spare) "}, - {"db_ops_ruid", CFG_VAR_INT | CFG_ATOMIC, 0, 1, 0, 0, + {"db_ops_ruid", CFG_VAR_INT | CFG_ATOMIC, 0, 2, 0, 0, "Set this if you want to update / delete from DB using ruid value "}, {"db_update_as_insert", CFG_VAR_INT | CFG_ATOMIC, 0, 1, 0, 0, "Set this parameter if you want to do INSERT DB operations instead of UPDATE DB operations. "}, diff --git a/src/modules/p_usrloc/doc/p_usrloc_admin.xml b/src/modules/p_usrloc/doc/p_usrloc_admin.xml index f1c78cd9410..80d4233eeb9 100644 --- a/src/modules/p_usrloc/doc/p_usrloc_admin.xml +++ b/src/modules/p_usrloc/doc/p_usrloc_admin.xml @@ -626,13 +626,28 @@ modparam("p_usrloc", "default_db_type", "cluster")
<varname>db_ops_ruid</varname> (int) - If set to 1, database queries for update or delete are done using - ruid value. If it is set to 0, the old style using aor, contact and - call-id is done. + Defines how database queries are done: + + + + 0 uses the old style using aor, contact and call-id + + + + + 1 uses ruid value + + + + + 2 uses the new style using aor, contact and call-id + + + - Default value is 0. + Default value is 0 @@ -645,7 +660,7 @@ modparam("p_usrloc", "default_db_type", "cluster") Set <varname>db_ops_ruid</varname> parameter ... -modparam("p_usrloc", "db_ops_ruid", 0) +modparam("p_usrloc", "db_ops_ruid", 2) ... diff --git a/src/modules/p_usrloc/location.sql b/src/modules/p_usrloc/location.sql index 9f39dd42185..092a0c65e52 100644 --- a/src/modules/p_usrloc/location.sql +++ b/src/modules/p_usrloc/location.sql @@ -18,7 +18,8 @@ CREATE TABLE location ( socket VARCHAR(64) DEFAULT NULL, methods INT(11) DEFAULT NULL, instance VARCHAR(255) DEFAULT NULL, - reg_id INTEGER DEFAULT 0 NOT NULL + reg_id INTEGER DEFAULT 0 NOT NULL, + uniq VARCHAR(255) DEFAULT NULL ) ENGINE=MyISAM; CREATE INDEX account_contact_idx ON location (username, domain, contact); diff --git a/src/modules/p_usrloc/p_usrloc_mod.c b/src/modules/p_usrloc/p_usrloc_mod.c index 3da7d06b0d6..b91e543f5ef 100644 --- a/src/modules/p_usrloc/p_usrloc_mod.c +++ b/src/modules/p_usrloc/p_usrloc_mod.c @@ -80,6 +80,7 @@ MODULE_VERSION #define INSTANCE_COL "instance" #define REG_ID_COL "reg_id" #define LAST_MOD_COL "last_modified" +#define UNIQ_COL "uniq" static int mod_init(void); /*!< Module initialization function */ static void destroy(void); /*!< Module destroy function */ @@ -143,6 +144,7 @@ str methods_col = str_init(METHODS_COL); /*!< Name of column containing the str instance_col = str_init(INSTANCE_COL); /*!< Name of column containing the SIP instance value */ str reg_id_col = str_init(REG_ID_COL); /*!< Name of column containing the reg-id value */ str last_mod_col = str_init(LAST_MOD_COL); /*!< Name of column containing the last modified date */ +str uniq_col = str_init(UNIQ_COL); /*!< Name of column containing the uniq value*/ int db_mode = 3; /*!< Database sync scheme: 1-write through, 2-write back, 3-only db */ int use_domain = 0; /*!< Whether usrloc should use domain part of aor */ int desc_time_order = 0; /*!< By default do not enable timestamp ordering */ @@ -247,7 +249,7 @@ static param_export_t params[] = { {"write_on_master_db", INT_PARAM, &db_master_write }, {"connection_expires", INT_PARAM, &connection_expires }, {"alg_location", INT_PARAM, &alg_location }, - {"db_ops_ruid", INT_PARAM, &default_p_usrloc_cfg.db_ops_ruid}, + {"db_ops_ruid", INT_PARAM, &default_p_usrloc_cfg.db_ops_ruid}, {"db_update_as_insert", INT_PARAM, &default_p_usrloc_cfg.db_update_as_insert}, {"mdb_availability_control", INT_PARAM, &mdb_availability_control}, {0, 0, 0} diff --git a/src/modules/p_usrloc/p_usrloc_mod.h b/src/modules/p_usrloc/p_usrloc_mod.h index 77e32073978..b0e572dedba 100644 --- a/src/modules/p_usrloc/p_usrloc_mod.h +++ b/src/modules/p_usrloc/p_usrloc_mod.h @@ -84,6 +84,7 @@ extern str methods_col; extern str instance_col; extern str reg_id_col; extern str last_mod_col; +extern str uniq_col; extern int db_mode; extern int use_domain; diff --git a/src/modules/p_usrloc/ucontact.c b/src/modules/p_usrloc/ucontact.c index 5e254a380a7..7888050095c 100644 --- a/src/modules/p_usrloc/ucontact.c +++ b/src/modules/p_usrloc/ucontact.c @@ -608,6 +608,259 @@ int db_insert_ucontact(ucontact_t* _c) * \param _c updated contact * \return 0 on success, -1 on failure */ + +int db_update_ucontact_addr_new(ucontact_t* _c) +{ + char* dom; + db_key_t keys1[4]; + db_val_t vals1[4]; + int n1 = 0; + + db_key_t keys2[18]; + db_val_t vals2[18]; + int nr_cols2 = 0; + + + if (_c->flags & FL_MEM) { + return 0; + } + + struct udomain * _d; + if(register_udomain(_c->domain->s, &_d) < 0){ + return -1; + } + + keys1[n1] = &user_col; + vals1[n1].type = DB1_STR; + vals1[n1].nul = 0; + vals1[n1].val.str_val = *_c->aor; + LM_DBG("aor:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s); + n1++; + + keys1[n1] = &contact_col; + vals1[n1].type = DB1_STR; + vals1[n1].nul = 0; + vals1[n1].val.str_val = _c->c; + LM_DBG("contact:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s); + n1++; + + switch (cfg_get(p_usrloc,p_usrloc_cfg,matching_mode)) { + case CONTACT_ONLY: + /* update call-id */ + keys2[nr_cols2] = &callid_col; + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->callid; + nr_cols2++; + /* update path */ + keys2[nr_cols2] = &path_col; + vals2[nr_cols2].type = DB1_STR; + if (_c->path.s == 0) { + vals2[nr_cols2].nul = 1; + } else { + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->path; + } + nr_cols2++; + break; + case CONTACT_CALLID: + keys1[n1] = &callid_col; + vals1[n1].type = DB1_STR; + vals1[n1].nul = 0; + vals1[n1].val.str_val = _c->callid; + LM_DBG("callid:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s); + n1++; + /* update path */ + keys2[nr_cols2] = &path_col; + vals2[nr_cols2].type = DB1_STR; + if (_c->path.s == 0) { + vals2[nr_cols2].nul = 1; + } else { + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->path; + } + nr_cols2++; + break; + case CONTACT_PATH: + keys1[n1] = &path_col; + vals1[n1].type = DB1_STR; + if (_c->path.s == 0) { + vals1[n1].nul = 1; + LM_DBG("path: NULL\n"); + } else { + vals1[n1].nul = 0; + vals1[n1].val.str_val = _c->path; + LM_DBG("path:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s); + } + n1++; + /* update call-id */ + keys2[nr_cols2] = &callid_col; + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->callid; + nr_cols2++; + break; + default: + LM_CRIT("unknown matching_mode %d\n", cfg_get(p_usrloc,p_usrloc_cfg,matching_mode)); + return -1; + } + + keys2[nr_cols2] = &expires_col; + vals2[nr_cols2].type = DB1_DATETIME; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.time_val = _c->expires; + nr_cols2++; + + keys2[nr_cols2] = &q_col; + vals2[nr_cols2].type = DB1_DOUBLE; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.double_val = q2double(_c->q); + nr_cols2++; + + keys2[nr_cols2] = &cseq_col; + vals2[nr_cols2].type = DB1_INT; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.int_val = _c->cseq; + nr_cols2++; + + keys2[nr_cols2] = &flags_col; + vals2[nr_cols2].type = DB1_INT; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.bitmap_val = _c->flags; + nr_cols2++; + + keys2[nr_cols2] = &cflags_col; + vals2[nr_cols2].type = DB1_INT; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.bitmap_val = _c->cflags; + nr_cols2++; + + keys2[nr_cols2] = &user_agent_col; + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->user_agent; + nr_cols2++; + + keys2[nr_cols2] = &received_col; + vals2[nr_cols2].type = DB1_STR; + if (_c->received.s == 0) { + vals2[nr_cols2].nul = 1; + } else { + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->received; + } + nr_cols2++; + + keys2[nr_cols2] = &sock_col; + vals2[nr_cols2].type = DB1_STR; + if (_c->sock) { + vals2[nr_cols2].val.str_val = _c->sock->sock_str; + vals2[nr_cols2].nul = 0; + } else { + vals2[nr_cols2].nul = 1; + } + nr_cols2++; + + keys2[nr_cols2] = &methods_col; + vals2[nr_cols2].type = DB1_BITMAP; + if (_c->methods == 0xFFFFFFFF) { + vals2[nr_cols2].nul = 1; + } else { + vals2[nr_cols2].val.bitmap_val = _c->methods; + vals2[nr_cols2].nul = 0; + } + nr_cols2++; + + keys2[nr_cols2] = &last_mod_col; + vals2[nr_cols2].type = DB1_DATETIME; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.time_val = _c->last_modified; + nr_cols2++; + + keys2[nr_cols2] = &ruid_col; + if(_c->ruid.len>0) + { + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->ruid; + } else { + vals2[nr_cols2].nul = 1; + } + nr_cols2++; + + keys2[nr_cols2] = &instance_col; + if(_c->instance.len>0) + { + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->instance; + } else { + vals2[nr_cols2].nul = 1; + } + nr_cols2++; + + keys2[nr_cols2] = ®_id_col; + vals2[nr_cols2].type = DB1_INT; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.int_val = (int)_c->reg_id; + nr_cols2++; + + keys2[nr_cols2] = &uniq_col; + if(_c->uniq.len>0) + { + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->uniq; + } else { + vals2[nr_cols2].nul = 1; + } + nr_cols2++; + keys2[nr_cols2] = &contact_col; + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = _c->c; + LM_DBG("contact:%.*s\n", vals2[nr_cols2].val.str_val.len, vals2[nr_cols2].val.str_val.s); + nr_cols2++; + + keys2[nr_cols2] = &user_col; + vals2[nr_cols2].type = DB1_STR; + vals2[nr_cols2].nul = 0; + vals2[nr_cols2].val.str_val = *_c->aor; + LM_DBG("aor:%.*s\n", vals2[nr_cols2].val.str_val.len, vals2[nr_cols2].val.str_val.s); + nr_cols2++; + if (use_domain) { + keys1[n1] = &domain_col; + vals1[n1].type = DB1_STR; + vals1[n1].nul = 0; + dom = memchr(_c->aor->s, '@', _c->aor->len); + if (dom==0) { + vals1[0].val.str_val.len = 0; + vals1[n1].val.str_val = *_c->aor; + } else { + vals1[0].val.str_val.len = dom - _c->aor->s; + vals1[n1].val.str_val.s = dom + 1; + vals1[n1].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1; + } + n1++; + } +/* + if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) { + LM_ERR("sql use_table failed\n"); + return -1; + } +*/ + + if (ul_db_layer_update(_d, &vals1[0].val.str_val, &vals1[n1-1].val.str_val, keys1, 0, vals1, keys2, vals2, + n1, nr_cols2) < 0) + { + LM_ERR("updating database failed\n"); + return -1; + } + + + return 0; +} + int db_update_ucontact_addr(ucontact_t* _c) { char* dom; @@ -959,10 +1212,16 @@ int db_update_ucontact_ruid(ucontact_t* _c) */ int db_update_ucontact(ucontact_t* _c) { - if(cfg_get(p_usrloc, p_usrloc_cfg, db_ops_ruid)==0) + unsigned int db_ops_ruid_cfg = cfg_get(p_usrloc, p_usrloc_cfg, db_ops_ruid); + + if (db_ops_ruid_cfg == 0) return db_update_ucontact_addr(_c); - else + else if (db_ops_ruid_cfg == 1) return db_update_ucontact_ruid(_c); + else if (db_ops_ruid_cfg == 2) + return db_update_ucontact_addr_new(_c); + + return -1; } @@ -1092,10 +1351,16 @@ int db_delete_ucontact_ruid(ucontact_t* _c) */ int db_delete_ucontact(ucontact_t* _c) { - if (cfg_get(p_usrloc, p_usrloc_cfg, db_ops_ruid) == 0) + unsigned int db_ops_ruid_cfg = cfg_get(p_usrloc, p_usrloc_cfg, db_ops_ruid); + + if (db_ops_ruid_cfg == 0) return db_delete_ucontact_addr(_c); - else + else if (db_ops_ruid_cfg == 1) return db_delete_ucontact_ruid(_c); + else if (db_ops_ruid_cfg == 2) + return db_delete_ucontact_addr(_c); + + return -1; } /*! diff --git a/src/modules/usrloc/usrloc.h b/src/modules/usrloc/usrloc.h index fed89d1c705..a1e26da2115 100644 --- a/src/modules/usrloc/usrloc.h +++ b/src/modules/usrloc/usrloc.h @@ -85,6 +85,7 @@ typedef struct ucontact { unsigned int flags; /*!< Various flags (NAT, ping type, etc) */ unsigned int cflags; /*!< Custom contact flags (from script) */ str user_agent; /*!< User-Agent header field */ + str uniq; /*!< Uniq header field */ struct socket_info *sock; /*!< received socket */ time_t last_modified; /*!< When the record was last modified */ time_t last_keepalive; /*!< last keepalive timestamp */