Selaa lähdekoodia

Ported gruu and outbound changes to p_usrloc module

Pawel Kuzak 13 vuotta sitten
vanhempi
commit
1f6bfa0b3b

+ 1 - 2
modules_k/p_usrloc/dlist.h

@@ -36,10 +36,9 @@
 #define DLIST_H
 #define DLIST_H
 
 
 #include <stdio.h>
 #include <stdio.h>
-#include "udomain.h"
 #include "../../str.h"
 #include "../../str.h"
 #include "../usrloc/usrloc.h"
 #include "../usrloc/usrloc.h"
-
+#include "udomain.h"
 
 
 /*!
 /*!
  * List of all domains registered with usrloc
  * List of all domains registered with usrloc

+ 12 - 0
modules_k/p_usrloc/p_usrloc_mod.c

@@ -74,6 +74,7 @@
 
 
 MODULE_VERSION
 MODULE_VERSION
 
 
+#define RUID_COL       "ruid"
 #define USER_COL       "username"
 #define USER_COL       "username"
 #define DOMAIN_COL     "domain"
 #define DOMAIN_COL     "domain"
 #define CONTACT_COL    "contact"
 #define CONTACT_COL    "contact"
@@ -88,6 +89,8 @@ MODULE_VERSION
 #define PATH_COL       "path"
 #define PATH_COL       "path"
 #define SOCK_COL       "socket"
 #define SOCK_COL       "socket"
 #define METHODS_COL    "methods"
 #define METHODS_COL    "methods"
+#define INSTANCE_COL   "instance"
+#define REG_ID_COL     "reg_id"
 #define LAST_MOD_COL   "last_modified"
 #define LAST_MOD_COL   "last_modified"
 
 
 static int mod_init(void);                          /*!< Module initialization function */
 static int mod_init(void);                          /*!< Module initialization function */
@@ -135,6 +138,7 @@ extern int ul_locks_no;
  * @param alg_location defines the algorithm for the location matching - based on crc32 for  now
  * @param alg_location defines the algorithm for the location matching - based on crc32 for  now
  */
  */
 
 
+str ruid_col        = str_init(RUID_COL); 		/*!< Name of column containing record unique id */
 str user_col        = str_init(USER_COL); 		/*!< Name of column containing usernames */
 str user_col        = str_init(USER_COL); 		/*!< Name of column containing usernames */
 str domain_col      = str_init(DOMAIN_COL); 		/*!< Name of column containing domains */
 str domain_col      = str_init(DOMAIN_COL); 		/*!< Name of column containing domains */
 str contact_col     = str_init(CONTACT_COL);		/*!< Name of column containing contact addresses */
 str contact_col     = str_init(CONTACT_COL);		/*!< Name of column containing contact addresses */
@@ -149,6 +153,8 @@ str received_col    = str_init(RECEIVED_COL);		/*!< Name of column containing tr
 str path_col        = str_init(PATH_COL);		/*!< Name of column containing the Path header */
 str path_col        = str_init(PATH_COL);		/*!< Name of column containing the Path header */
 str sock_col        = str_init(SOCK_COL);		/*!< Name of column containing the received socket */
 str sock_col        = str_init(SOCK_COL);		/*!< Name of column containing the received socket */
 str methods_col     = str_init(METHODS_COL);		/*!< Name of column containing the supported methods */
 str methods_col     = str_init(METHODS_COL);		/*!< Name of column containing the supported methods */
+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 last_mod_col     = str_init(LAST_MOD_COL);		/*!< Name of column containing the last modified date */
 int db_mode         = 3;				/*!< Database sync scheme:  1-write through, 2-write back, 3-only db */
 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 use_domain      = 0;				/*!< Whether usrloc should use domain part of aor */
@@ -207,6 +213,7 @@ static cmd_export_t cmds[] = {
  * Exported parameters 
  * Exported parameters 
  */
  */
 static param_export_t params[] = {
 static param_export_t params[] = {
+	{"ruid_column",         STR_PARAM, &ruid_col.s      },
 	{"user_column",       STR_PARAM, &user_col.s      },
 	{"user_column",       STR_PARAM, &user_col.s      },
 	{"domain_column",     STR_PARAM, &domain_col.s    },
 	{"domain_column",     STR_PARAM, &domain_col.s    },
 	{"contact_column",    STR_PARAM, &contact_col.s   },
 	{"contact_column",    STR_PARAM, &contact_col.s   },
@@ -232,6 +239,8 @@ static param_export_t params[] = {
 	{"default_db_url",    STR_PARAM, &default_db_url.s    },
 	{"default_db_url",    STR_PARAM, &default_db_url.s    },
 	{"default_db_type",   STR_PARAM, &default_db_type.s   },
 	{"default_db_type",   STR_PARAM, &default_db_type.s   },
 	{"domain_db",         STR_PARAM, &domain_db.s         },
 	{"domain_db",         STR_PARAM, &domain_db.s         },
+	{"instance_column",      STR_PARAM, &instance_col.s  	 },
+	{"reg_id_column",      	 STR_PARAM, &reg_id_col.s        },
 	{"write_db_url",         STR_PARAM, &write_db_url.s      },
 	{"write_db_url",         STR_PARAM, &write_db_url.s      },
 	{"read_db_url",          STR_PARAM, &read_db_url.s       },
 	{"read_db_url",          STR_PARAM, &read_db_url.s       },
 	{"reg_db_table",         STR_PARAM, &reg_table.s         },
 	{"reg_db_table",         STR_PARAM, &reg_table.s         },
@@ -319,6 +328,7 @@ static int mod_init(void)
 
 
 
 
 	/* Compute the lengths of string parameters */
 	/* Compute the lengths of string parameters */
+	ruid_col.len = strlen(ruid_col.s);
 	user_col.len = strlen(user_col.s);
 	user_col.len = strlen(user_col.s);
 	domain_col.len = strlen(domain_col.s);
 	domain_col.len = strlen(domain_col.s);
 	contact_col.len = strlen(contact_col.s);
 	contact_col.len = strlen(contact_col.s);
@@ -333,6 +343,8 @@ static int mod_init(void)
 	path_col.len = strlen(path_col.s);
 	path_col.len = strlen(path_col.s);
 	sock_col.len = strlen(sock_col.s);
 	sock_col.len = strlen(sock_col.s);
 	methods_col.len = strlen(methods_col.s);
 	methods_col.len = strlen(methods_col.s);
+	instance_col.len = strlen(instance_col.s);
+	reg_id_col.len = strlen(reg_id_col.s);
 	last_mod_col.len = strlen(last_mod_col.s);
 	last_mod_col.len = strlen(last_mod_col.s);
 	
 	
 	write_db_url.len = strlen (write_db_url.s);
 	write_db_url.len = strlen (write_db_url.s);

+ 3 - 0
modules_k/p_usrloc/p_usrloc_mod.h

@@ -71,6 +71,7 @@
 #define DEFAULT_DB_TYPE "single"
 #define DEFAULT_DB_TYPE "single"
 #define DEFAULT_DOMAIN_DB "location=cluster,cfa=single"
 #define DEFAULT_DOMAIN_DB "location=cluster,cfa=single"
 
 
+extern str ruid_col;
 extern str user_col;
 extern str user_col;
 extern str domain_col;
 extern str domain_col;
 extern str contact_col;
 extern str contact_col;
@@ -85,6 +86,8 @@ extern str received_col;
 extern str path_col;
 extern str path_col;
 extern str sock_col;
 extern str sock_col;
 extern str methods_col;
 extern str methods_col;
+extern str instance_col;
+extern str reg_id_col;
 extern str last_mod_col;
 extern str last_mod_col;
 
 
 extern int db_mode;
 extern int db_mode;

+ 78 - 8
modules_k/p_usrloc/ucontact.c

@@ -77,6 +77,12 @@ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _
 	if (_ci->path && _ci->path->len) {
 	if (_ci->path && _ci->path->len) {
 		if (shm_str_dup( &c->path, _ci->path) < 0) goto error;
 		if (shm_str_dup( &c->path, _ci->path) < 0) goto error;
 	}
 	}
+	if (_ci->ruid.s && _ci->ruid.len) {
+		if (shm_str_dup( &c->ruid, &_ci->ruid) < 0) goto error;
+	}
+	if (_ci->instance.s && _ci->instance.len) {
+		if (shm_str_dup( &c->instance, &_ci->instance) < 0) goto error;
+	}
 
 
 	c->domain = _dom;
 	c->domain = _dom;
 	c->aor = _aor;
 	c->aor = _aor;
@@ -88,6 +94,7 @@ ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _
 	c->flags = _ci->flags;
 	c->flags = _ci->flags;
 	c->cflags = _ci->cflags;
 	c->cflags = _ci->cflags;
 	c->methods = _ci->methods;
 	c->methods = _ci->methods;
+	c->reg_id = _ci->reg_id;
 	c->last_modified = _ci->last_modified;
 	c->last_modified = _ci->last_modified;
 
 
 	return c;
 	return c;
@@ -116,6 +123,8 @@ void free_ucontact(ucontact_t* _c)
 	if (_c->user_agent.s) shm_free(_c->user_agent.s);
 	if (_c->user_agent.s) shm_free(_c->user_agent.s);
 	if (_c->callid.s) shm_free(_c->callid.s);
 	if (_c->callid.s) shm_free(_c->callid.s);
 	if (_c->c.s) shm_free(_c->c.s);
 	if (_c->c.s) shm_free(_c->c.s);
+	if (_c->ruid.s) shm_free(_c->ruid.s);
+	if (_c->instance.s) shm_free(_c->instance.s);
 	shm_free( _c );
 	shm_free( _c );
 }
 }
 
 
@@ -169,6 +178,11 @@ void print_ucontact(FILE* _f, ucontact_t* _c)
 		fprintf(_f, "Sock      : none (null)\n");
 		fprintf(_f, "Sock      : none (null)\n");
 	}
 	}
 	fprintf(_f, "Methods   : %u\n", _c->methods);
 	fprintf(_f, "Methods   : %u\n", _c->methods);
+	fprintf(_f, "ruid      : '%.*s'\n",
+		_c->ruid.len, ZSW(_c->ruid.s));
+	fprintf(_f, "instance  : '%.*s'\n",
+		_c->instance.len, ZSW(_c->instance.s));
+	fprintf(_f, "reg-id    : %u\n", _c->reg_id);
 	fprintf(_f, "next      : %p\n", _c->next);
 	fprintf(_f, "next      : %p\n", _c->next);
 	fprintf(_f, "prev      : %p\n", _c->prev);
 	fprintf(_f, "prev      : %p\n", _c->prev);
 	fprintf(_f, "~~~/Contact~~~~\n");
 	fprintf(_f, "~~~/Contact~~~~\n");
@@ -385,12 +399,14 @@ int st_flush_ucontact(ucontact_t* _c)
  * \param _c inserted contact
  * \param _c inserted contact
  * \return 0 on success, -1 on failure
  * \return 0 on success, -1 on failure
  */
  */
+
 int db_insert_ucontact(ucontact_t* _c)
 int db_insert_ucontact(ucontact_t* _c)
 {
 {
 	char* dom;
 	char* dom;
-	db_key_t keys[15];
-	db_val_t vals[15];
-	int nr_cols  = 0;
+	db_key_t keys[18];
+	db_val_t vals[18];
+	int nr_cols = 0;
+
 	int nr_cols_key = 0;
 	int nr_cols_key = 0;
 	struct udomain * _d;
 	struct udomain * _d;
 	str user={0, 0};
 	str user={0, 0};
@@ -433,11 +449,10 @@ int db_insert_ucontact(ucontact_t* _c)
 			vals[nr_cols].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
 			vals[nr_cols].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
 		}
 		}
 		domain = vals[nr_cols].val.str_val;
 		domain = vals[nr_cols].val.str_val;
-		LM_DBG("** Username=%.*s  Domain=%.*s\n", vals[0].val.str_val.len, vals[0].val.str_val.s,
+		LM_INFO("** Username=%.*s  Domain=%.*s\n", vals[0].val.str_val.len, vals[0].val.str_val.s,
 				vals[nr_cols].val.str_val.len, vals[nr_cols].val.str_val.s);
 				vals[nr_cols].val.str_val.len, vals[nr_cols].val.str_val.s);
 		nr_cols++;
 		nr_cols++;
 	}
 	}
-	nr_cols_key  = nr_cols;
 	user = vals[0].val.str_val;
 	user = vals[0].val.str_val;
 
 
 	keys[nr_cols] = &expires_col;
 	keys[nr_cols] = &expires_col;
@@ -526,9 +541,39 @@ int db_insert_ucontact(ucontact_t* _c)
 	vals[nr_cols].type = DB1_DATETIME;
 	vals[nr_cols].type = DB1_DATETIME;
 	vals[nr_cols].nul = 0;
 	vals[nr_cols].nul = 0;
 	vals[nr_cols].val.time_val = _c->last_modified;
 	vals[nr_cols].val.time_val = _c->last_modified;
+	nr_cols++;
+
+	keys[nr_cols] = &ruid_col;
+	if(_c->ruid.len>0)
+	{
+		vals[nr_cols].type = DB1_STR;
+		vals[nr_cols].nul = 0;
+		vals[nr_cols].val.str_val = _c->ruid;
+	} else {
+		vals[nr_cols].nul = 1;
+	}
+	nr_cols++;
+
+	keys[nr_cols] = &instance_col;
+	if(_c->instance.len>0)
+	{
+		vals[nr_cols].type = DB1_STR;
+		vals[nr_cols].nul = 0;
+		vals[nr_cols].val.str_val = _c->instance;
+	} else {
+		vals[nr_cols].nul = 1;
+	}
+	nr_cols++;
 
 
+	keys[nr_cols] = &reg_id_col;
+	vals[nr_cols].type = DB1_INT;
+	vals[nr_cols].nul = 0;
+	vals[nr_cols].val.int_val = (int)_c->reg_id;
+	nr_cols++;
 
 
+	nr_cols_key  = nr_cols;
 	/* to prevent errors from the DB because of duplicated entries */
 	/* to prevent errors from the DB because of duplicated entries */
+	
 	if (ul_db_layer_replace(_d, &user, &domain, keys, vals, nr_cols, nr_cols_key) <0) {
 	if (ul_db_layer_replace(_d, &user, &domain, keys, vals, nr_cols, nr_cols_key) <0) {
 		LM_ERR("inserting contact in db failed\n");
 		LM_ERR("inserting contact in db failed\n");
 		return -1;
 		return -1;
@@ -549,8 +594,8 @@ int db_update_ucontact(ucontact_t* _c)
 	db_key_t keys1[4];
 	db_key_t keys1[4];
 	db_val_t vals1[4];
 	db_val_t vals1[4];
 
 
-	db_key_t keys2[11];
-	db_val_t vals2[11];
+	db_key_t keys2[14];
+	db_val_t vals2[14];
 
 
 	if (_c->flags & FL_MEM) {
 	if (_c->flags & FL_MEM) {
 		return 0;
 		return 0;
@@ -575,6 +620,9 @@ int db_update_ucontact(ucontact_t* _c)
 	keys2[8] = &sock_col;
 	keys2[8] = &sock_col;
 	keys2[9] = &methods_col;
 	keys2[9] = &methods_col;
 	keys2[10] = &last_mod_col;
 	keys2[10] = &last_mod_col;
+	keys2[11] = &ruid_col;
+	keys2[12] = &instance_col;
+	keys2[13] = &reg_id_col;
 
 
 	vals1[0].type = DB1_STR;
 	vals1[0].type = DB1_STR;
 	vals1[0].nul = 0;
 	vals1[0].nul = 0;
@@ -648,6 +696,28 @@ int db_update_ucontact(ucontact_t* _c)
 	vals2[10].nul = 0;
 	vals2[10].nul = 0;
 	vals2[10].val.time_val = _c->last_modified;
 	vals2[10].val.time_val = _c->last_modified;
 
 
+	if(_c->ruid.len>0)
+	{
+		vals2[11].type = DB1_STR;
+		vals2[11].nul = 0;
+		vals2[11].val.str_val = _c->ruid;
+	} else {
+		vals2[11].nul = 1;
+	}
+
+	if(_c->instance.len>0)
+	{
+		vals2[12].type = DB1_STR;
+		vals2[12].nul = 0;
+		vals2[12].val.str_val = _c->instance;
+	} else {
+		vals2[12].nul = 1;
+	}
+
+	vals2[13].type = DB1_INT;
+	vals2[13].nul = 0;
+	vals2[13].val.int_val = (int)_c->reg_id;
+
 	if (use_domain) {
 	if (use_domain) {
 		vals1[3].type = DB1_STR;
 		vals1[3].type = DB1_STR;
 		vals1[3].nul = 0;
 		vals1[3].nul = 0;
@@ -663,7 +733,7 @@ int db_update_ucontact(ucontact_t* _c)
 	}
 	}
 
 
 	if (ul_db_layer_update(_d, &vals1[0].val.str_val, &vals1[3].val.str_val, keys1, 0, vals1, keys2, vals2, 
 	if (ul_db_layer_update(_d, &vals1[0].val.str_val, &vals1[3].val.str_val, keys1, 0, vals1, keys2, vals2, 
-	(use_domain) ? (4) : (3), 11) < 0) {
+	(use_domain) ? (4) : (3), 14) < 0) {
 		LM_ERR("updating database failed\n");
 		LM_ERR("updating database failed\n");
 		return -1;
 		return -1;
 	}
 	}

+ 205 - 7
modules_k/p_usrloc/udomain.c

@@ -178,6 +178,7 @@ static inline void get_static_urecord(udomain_t* _d, str* _aor,
 
 
 	memset( &r, 0, sizeof(struct urecord) );
 	memset( &r, 0, sizeof(struct urecord) );
 	r.aor = *_aor;
 	r.aor = *_aor;
+	r.aorhash = ul_get_aorhash(_aor);
 	r.domain = _d->name;
 	r.domain = _d->name;
 	*_r = &r;
 	*_r = &r;
 }
 }
@@ -334,6 +335,23 @@ static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact)
 		ci.last_modified = VAL_TIME(vals+12);
 		ci.last_modified = VAL_TIME(vals+12);
 	}
 	}
 
 
+	/* record internal uid */
+	if (!VAL_NULL(vals+13)) {
+		ci.ruid.s = (char*)VAL_STRING(vals+13);
+		ci.ruid.len = strlen(ci.ruid.s);
+	}
+
+	/* sip instance */
+	if (!VAL_NULL(vals+14)) {
+		ci.instance.s = (char*)VAL_STRING(vals+14);
+		ci.instance.len = strlen(ci.instance.s);
+	}
+
+	/* reg-id */
+	if (!VAL_NULL(vals+15)) {
+		ci.reg_id = VAL_UINT(vals+15);
+	}
+
 	return &ci;
 	return &ci;
 }
 }
 
 
@@ -349,7 +367,7 @@ static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact)
 urecord_t* db_load_urecord(udomain_t* _d, str *_aor)
 urecord_t* db_load_urecord(udomain_t* _d, str *_aor)
 {
 {
 	ucontact_info_t *ci;
 	ucontact_info_t *ci;
-	db_key_t columns[13];
+	db_key_t columns[16];
 	db_key_t keys[2];
 	db_key_t keys[2];
 	db_key_t order;
 	db_key_t order;
 	db_val_t vals[2];
 	db_val_t vals[2];
@@ -395,13 +413,16 @@ urecord_t* db_load_urecord(udomain_t* _d, str *_aor)
 	columns[10] = &sock_col;
 	columns[10] = &sock_col;
 	columns[11] = &methods_col;
 	columns[11] = &methods_col;
 	columns[12] = &last_mod_col;
 	columns[12] = &last_mod_col;
+	columns[13] = &ruid_col;
+	columns[14] = &instance_col;
+	columns[15] = &reg_id_col;
 
 
 	if (desc_time_order)
 	if (desc_time_order)
 		order = &last_mod_col;
 		order = &last_mod_col;
 	else
 	else
 		order = &q_col;
 		order = &q_col;
 
 
-	if (ul_db_layer_query(_d,  &vals[0].val.str_val,  &vals[1].val.str_val, keys, 0, vals, columns, (use_domain)?2:1, 13, order,
+	if (ul_db_layer_query(_d,  &vals[0].val.str_val,  &vals[1].val.str_val, keys, 0, vals, columns, (use_domain)?2:1, 16, order,
 				&res) < 0) {
 				&res) < 0) {
 		LM_ERR("db_query failed\n");
 		LM_ERR("db_query failed\n");
 		return 0;
 		return 0;
@@ -443,6 +464,125 @@ urecord_t* db_load_urecord(udomain_t* _d, str *_aor)
 	return r;
 	return r;
 }
 }
 
 
+/*!
+ * \brief Loads from DB all contacts for a RUID
+ * \param _c database connection
+ * \param _d domain
+ * \param _aor address of record
+ * \return pointer to the record on success, 0 on errors or if nothing is found
+ */
+urecord_t* db_load_urecord_by_ruid(udomain_t* _d, str *_ruid)
+{
+	ucontact_info_t *ci;
+	db_key_t columns[18];
+	db_key_t keys[1];
+	db_key_t order;
+	db_val_t vals[1];
+	db1_res_t* res = NULL;
+	db_row_t *row;
+	str contact;
+	str aor;
+	char aorbuf[512];
+	str domain;
+
+	urecord_t* r;
+	ucontact_t* c;
+
+	keys[0] = &ruid_col;
+	vals[0].type = DB1_STR;
+	vals[0].nul = 0;
+	vals[0].val.str_val = *_ruid;
+
+	columns[0] = &contact_col;
+	columns[1] = &expires_col;
+	columns[2] = &q_col;
+	columns[3] = &callid_col;
+	columns[4] = &cseq_col;
+	columns[5] = &flags_col;
+	columns[6] = &cflags_col;
+	columns[7] = &user_agent_col;
+	columns[8] = &received_col;
+	columns[9] = &path_col;
+	columns[10] = &sock_col;
+	columns[11] = &methods_col;
+	columns[12] = &last_mod_col;
+	columns[13] = &ruid_col;
+	columns[14] = &instance_col;
+	columns[15] = &user_col;
+	columns[16] = &reg_id_col;
+	columns[17] = &domain_col;
+
+	if (desc_time_order)
+		order = &last_mod_col;
+	else
+		order = &q_col;
+
+	if (ul_db_layer_query(_d,  &vals[0].val.str_val,  &vals[1].val.str_val, keys, 0, vals, columns, 1, 18, order,
+				&res) < 0) {
+		LM_ERR("db_query failed\n");
+		return 0;
+	}
+
+	if (RES_ROW_N(res) == 0) {
+		LM_DBG("aor %.*s not found in table %.*s\n",_ruid->len, _ruid->s,
+				_d->name->len, _d->name->s);
+		ul_db_layer_free_result(_d, res);
+		return 0;
+	}
+
+	r = 0;
+
+	/* use first row - shouldn't be more */
+	row = RES_ROWS(res);
+
+	ci = dbrow2info(ROW_VALUES(RES_ROWS(res)), &contact);
+	if (ci==0) {
+		LM_ERR("skipping record for %.*s in table %s\n",
+				_ruid->len, _ruid->s, _d->name->s);
+		goto done;
+	}
+
+	aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 15);
+	aor.len = strlen(aor.s);
+
+	if (use_domain) {
+		domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 17);
+		if (VAL_NULL(ROW_VALUES(row)+17) || domain.s==0 || domain.s[0]==0){
+			LM_CRIT("empty domain record for user %.*s...skipping\n",
+					aor.len, aor.s);
+			goto done;
+		}
+		domain.len = strlen(domain.s);
+		if(aor.len + domain.len + 2 >= 512) {
+			LM_ERR("AoR is too big\n");
+			goto done;
+		}
+		memcpy(aorbuf, aor.s, aor.len);
+		aorbuf[aor.len] = '@';
+		memcpy(aorbuf + aor.len + 1, domain.s, domain.len);
+		aor.len += 1 + domain.len;
+		aor.s = aorbuf;
+		aor.s[aor.len] = '\0';
+	}
+	get_static_urecord( _d, &aor, &r);
+
+	if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) {
+		LM_ERR("mem_insert failed\n");
+		free_urecord(r);
+		ul_db_layer_free_result(_d, res);
+		return 0;
+	}
+
+	/* We have to do this, because insert_ucontact sets state to CS_NEW
+	 * and we have the contact in the database already */
+	c->state = CS_SYNC;
+
+done:
+	ul_db_layer_free_result(_d, res);
+	;
+	return r;
+}
+
 
 
 /*!
 /*!
  * \brief Timer function to cleanup expired contacts, DB_ONLY db_mode
  * \brief Timer function to cleanup expired contacts, DB_ONLY db_mode
@@ -551,8 +691,7 @@ void lock_udomain(udomain_t* _d, str* _aor)
 	unsigned int sl;
 	unsigned int sl;
 	if (db_mode!=DB_ONLY)
 	if (db_mode!=DB_ONLY)
 	{
 	{
-		sl = core_hash(_aor, 0, _d->size);
-
+		sl = ul_get_aorhash(_aor) & (_d->size - 1);
 #ifdef GEN_LOCK_T_PREFERED
 #ifdef GEN_LOCK_T_PREFERED
 		lock_get(_d->table[sl].lock);
 		lock_get(_d->table[sl].lock);
 #else
 #else
@@ -572,7 +711,7 @@ void unlock_udomain(udomain_t* _d, str* _aor)
 	unsigned int sl;
 	unsigned int sl;
 	if (db_mode!=DB_ONLY)
 	if (db_mode!=DB_ONLY)
 	{
 	{
-		sl = core_hash(_aor, 0, _d->size);
+		sl = ul_get_aorhash(_aor) & (_d->size - 1);
 #ifdef GEN_LOCK_T_PREFERED
 #ifdef GEN_LOCK_T_PREFERED
 		lock_release(_d->table[sl].lock);
 		lock_release(_d->table[sl].lock);
 #else
 #else
@@ -648,11 +787,11 @@ int get_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
 	urecord_t* r;
 	urecord_t* r;
 	if (db_mode!=DB_ONLY) {
 	if (db_mode!=DB_ONLY) {
 		/* search in cache */
 		/* search in cache */
-		aorhash = core_hash(_aor, 0, 0);
+		aorhash = ul_get_aorhash(_aor);
 		sl = aorhash&(_d->size-1);
 		sl = aorhash&(_d->size-1);
 		r = _d->table[sl].first;
 		r = _d->table[sl].first;
 
 
-		for(i = 0; i < _d->table[sl].n; i++) {
+		for(i = 0; r!=NULL && i < _d->table[sl].n; i++) {
 			if((r->aorhash==aorhash) && (r->aor.len==_aor->len)
 			if((r->aorhash==aorhash) && (r->aor.len==_aor->len)
 						&& !memcmp(r->aor.s,_aor->s,_aor->len)){
 						&& !memcmp(r->aor.s,_aor->s,_aor->len)){
 				*_r = r;
 				*_r = r;
@@ -673,6 +812,65 @@ int get_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
 	return 1;   /* Nothing found */
 	return 1;   /* Nothing found */
 }
 }
 
 
+/*!
+ * \brief Obtain a urecord pointer if the urecord exists in domain (lock slot)
+ * \param _d domain to search the record
+ * \param _aorhash hash id for address of record
+ * \param _ruid record internal unique id
+ * \param _r store pointer to location record
+ * \param _c store pointer to contact structure
+ * \return 0 if a record was found, 1 if nothing could be found
+ */
+int get_urecord_by_ruid(udomain_t* _d, unsigned int _aorhash,
+		str *_ruid, struct urecord** _r, struct ucontact** _c)
+{
+	unsigned int sl, i;
+	urecord_t* r;
+	ucontact_t* c;
+
+	sl = _aorhash&(_d->size-1);
+	lock_ulslot(_d, sl);
+
+	if (db_mode!=DB_ONLY) {
+		/* search in cache */
+		r = _d->table[sl].first;
+
+		for(i = 0; i < _d->table[sl].n; i++) {
+			if(r->aorhash==_aorhash) {
+				c = r->contacts;
+				while(c) {
+					if(c->ruid.len==_ruid->len
+							&& !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
+						*_r = r;
+						*_c = c;
+						return 0;
+					}
+				}
+			}
+			r = r->next;
+		}
+	} else {
+		/* search in DB */
+		r = db_load_urecord_by_ruid(_d, _ruid);
+		if (r) {
+			if(r->aorhash==_aorhash) {
+				c = r->contacts;
+				while(c) {
+					if(c->ruid.len==_ruid->len
+							&& !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
+						*_r = r;
+						*_c = c;
+						return 0;
+					}
+				}
+			}
+		}
+	}
+
+	unlock_ulslot(_d, (_aorhash & (_d->size - 1)));
+	return -1;   /* Nothing found */
+}
+
 
 
 /*!
 /*!
  * \brief Delete a urecord from domain
  * \brief Delete a urecord from domain

+ 12 - 0
modules_k/p_usrloc/udomain.h

@@ -175,6 +175,18 @@ int insert_urecord(udomain_t* _d, str* _aor, struct urecord** _r);
 int get_urecord(udomain_t* _d, str* _aor, struct urecord** _r);
 int get_urecord(udomain_t* _d, str* _aor, struct urecord** _r);
 
 
 
 
+/*!
+ * \brief Obtain a urecord pointer if the urecord exists in domain (lock slot)
+ * \param _d domain to search the record
+ * \param _aorhash hash id for address of record
+ * \param _ruid record internal unique id
+ * \param _r store pointer to location record
+ * \param _c store pointer to contact structure
+ * \return 0 if a record was found, 1 if nothing could be found
+ */
+int get_urecord_by_ruid(udomain_t* _d, unsigned int _aorhash,
+		str *_ruid, struct urecord** _r, struct ucontact** _c);
+
 /*!
 /*!
  * \brief Delete a urecord from domain
  * \brief Delete a urecord from domain
  * \param _d domain where the record should be deleted
  * \param _d domain where the record should be deleted

+ 30 - 0
modules_k/p_usrloc/ul_mi.c

@@ -119,6 +119,14 @@ static inline int mi_add_aor_node(struct mi_node *parent, urecord_t* r, time_t t
 	if (short_dump)
 	if (short_dump)
 		return 0;
 		return 0;
 
 
+#if 0
+	/* aor hash */
+	p = int2str((unsigned long)r->aorhash, &len);
+	node = add_mi_node_child( anode, MI_DUP_VALUE, "HashID", 6, p, len);
+	if (node==0)
+		return -1;
+#endif
+
 	for( c=r->contacts ; c ; c=c->next) {
 	for( c=r->contacts ; c ; c=c->next) {
 		/* contact */
 		/* contact */
 		cnode = add_mi_node_child( anode, MI_DUP_VALUE, "Contact", 7,
 		cnode = add_mi_node_child( anode, MI_DUP_VALUE, "Contact", 7,
@@ -221,6 +229,28 @@ static inline int mi_add_aor_node(struct mi_node *parent, urecord_t* r, time_t t
 		if (node==0)
 		if (node==0)
 			return -1;
 			return -1;
 
 
+		/* ruid */
+		if (c->ruid.len) {
+			node = add_mi_node_child( cnode, MI_DUP_VALUE, "Ruid", 4,
+				c->ruid.s, c->ruid.len);
+			if (node==0)
+				return -1;
+		}
+
+		/* instance */
+		if (c->instance.len) {
+			node = add_mi_node_child( cnode, MI_DUP_VALUE, "Instance", 8,
+				c->instance.s, c->instance.len);
+			if (node==0)
+				return -1;
+		}
+
+		/* reg-id */
+		p = int2str((unsigned long)c->reg_id, &len);
+		node = add_mi_node_child( cnode, MI_DUP_VALUE, "Reg-Id", 6, p, len);
+		if (node==0)
+			return -1;
+
 	} /* for */
 	} /* for */
 
 
 	return 0;
 	return 0;

+ 47 - 1
modules_k/p_usrloc/urecord.c

@@ -78,7 +78,7 @@ int new_urecord(str* _dom, str* _aor, urecord_t** _r)
 	memcpy((*_r)->aor.s, _aor->s, _aor->len);
 	memcpy((*_r)->aor.s, _aor->s, _aor->len);
 	(*_r)->aor.len = _aor->len;
 	(*_r)->aor.len = _aor->len;
 	(*_r)->domain = _dom;
 	(*_r)->domain = _dom;
-	(*_r)->aorhash = core_hash(_aor, 0, 0);
+	(*_r)->aorhash = ul_get_aorhash(_aor);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -628,3 +628,49 @@ int get_ucontact(urecord_t* _r, str* _c, str* _callid, str* _path, int _cseq,
 
 
 	return 1;
 	return 1;
 }
 }
+
+
+/*
+ * Get pointer to ucontact with given info (by address or sip.instance)
+ */
+int get_ucontact_by_instance(urecord_t* _r, str* _c, ucontact_info_t* _ci,
+		ucontact_t** _co)
+{
+	ucontact_t* ptr;
+	str i1;
+	str i2;
+	
+	if (_ci->instance.s == NULL || _ci->instance.len <= 0) {
+		return get_ucontact(_r, _c, _ci->callid, _ci->path, _ci->cseq, _co);
+	}
+
+	/* find by instance */
+	ptr = _r->contacts;
+	while(ptr) {
+		if (ptr->instance.len>0 && _ci->reg_id==ptr->reg_id)
+		{
+			i1 = _ci->instance;
+			i2 = ptr->instance;
+			if(i1.s[0]=='<' && i1.s[i1.len-1]=='>') {
+				i1.s++;
+				i1.len-=2;
+			}
+			if(i2.s[0]=='<' && i2.s[i2.len-1]=='>') {
+				i2.s++;
+				i2.len-=2;
+			}
+			if(i1.len==i2.len && memcmp(i1.s, i2.s, i2.len)==0) {
+				*_co = ptr;
+				return 0;
+			}
+		}
+		
+		ptr = ptr->next;
+	}
+	return 1;
+}
+
+unsigned int ul_get_aorhash(str *_aor)
+{
+	return core_hash(_aor, 0, 0);
+}

+ 11 - 1
modules_k/p_usrloc/urecord.h

@@ -162,6 +162,16 @@ int get_ucontact(urecord_t* _r, str* _c, str* _callid, str* _path,
  */
  */
 void release_urecord(urecord_t* _r);
 void release_urecord(urecord_t* _r);
 
 
-
+/*!
+ * \brief Get pointer to ucontact with given contact
+ * \param _r record where to search the contacts
+ * \param _c contact string
+ * \param _ci contact info (callid, cseq, instance, ...)
+ * \param _co found contact
+ * \return 0 - found, 1 - not found, -1 - invalid found, 
+ * -2 - found, but to be skipped (same cseq)
+ */
+int get_ucontact_by_instance(urecord_t* _r, str* _c, ucontact_info_t* _ci,
+		ucontact_t** _co);
 
 
 #endif
 #endif

+ 7 - 11
modules_k/p_usrloc/usrloc.c

@@ -34,12 +34,12 @@
  */
  */
 
 
 #include "../usrloc/usrloc.h"
 #include "../usrloc/usrloc.h"
-#include "../../sr_module.h"
-#include "p_usrloc_mod.h"
-#include "ucontact.h"
-#include "udomain.h"
 #include "dlist.h"
 #include "dlist.h"
 #include "urecord.h"
 #include "urecord.h"
+#include "ucontact.h"
+#include "udomain.h"
+#include "../../sr_module.h"
+#include "p_usrloc_mod.h"
 
 
 /*! nat branch flag */
 /*! nat branch flag */
 extern unsigned int nat_bflag;
 extern unsigned int nat_bflag;
@@ -58,15 +58,12 @@ int bind_usrloc(usrloc_api_t* api)
 		LM_ERR("invalid parameter value\n");
 		LM_ERR("invalid parameter value\n");
 		return -1;
 		return -1;
 	}
 	}
-
 	if (init_flag==0) {
 	if (init_flag==0) {
 		LM_ERR("configuration error - trying to bind to usrloc module"
 		LM_ERR("configuration error - trying to bind to usrloc module"
 				" before being initialized\n");
 				" before being initialized\n");
 		return -1;
 		return -1;
 	}
 	}
 
 
-	memset(api, 0, sizeof(usrloc_api_t));
-
 	api->register_udomain   = register_udomain;
 	api->register_udomain   = register_udomain;
 	api->get_all_ucontacts  = get_all_ucontacts;
 	api->get_all_ucontacts  = get_all_ucontacts;
 	api->insert_urecord     = insert_urecord;
 	api->insert_urecord     = insert_urecord;
@@ -80,11 +77,10 @@ int bind_usrloc(usrloc_api_t* api)
 	api->get_ucontact       = get_ucontact;
 	api->get_ucontact       = get_ucontact;
 	api->update_ucontact    = update_ucontact;
 	api->update_ucontact    = update_ucontact;
 	api->register_ulcb      = register_ulcb;
 	api->register_ulcb      = register_ulcb;
+	api->get_aorhash        = ul_get_aorhash;
 
 
-	api->get_udomain              = 0;
-	api->get_urecord_by_ruid      = 0;
-	api->get_ucontact_by_instance = 0;
-	api->get_aorhash              = 0;
+	api->get_urecord_by_ruid      = get_urecord_by_ruid;
+	api->get_ucontact_by_instance = get_ucontact_by_instance;
 
 
 	api->use_domain = use_domain;
 	api->use_domain = use_domain;
 	api->db_mode    = db_mode;
 	api->db_mode    = db_mode;