فهرست منبع

Merge branch 'master' into outbound

* master:
  modules_s/usrloc: moved to obsolete folder
  modules_s/registrar: moved to obsolete folder
  modules_s/.gitkeep: added a placeholder to keep empty modules_s folder for a while
  Makefile: make TAGS skips the obsolete folder
  usrloc(k): fixed position of xavp_contact parameter in docs
  usrloc: store per-contact attributes in database
  core: fixed xavp level cloning function
  core: added a fuction that adds an xavp with an xavp value
  kamctl: regenerated database creation scripts
  lib/srdb1: added location_attrs table
Peter Dunkley 12 سال پیش
والد
کامیت
3efe73dc00
85فایلهای تغییر یافته به همراه810 افزوده شده و 87 حذف شده
  1. 1 1
      Makefile.defs
  2. 8 4
      Makefile.rules
  3. 1 0
      lib/srdb1/schema/kamailio-usrloc.xml
  4. 101 0
      lib/srdb1/schema/location_attrs.xml
  5. 54 53
      modules_k/usrloc/README
  6. 8 9
      modules_k/usrloc/doc/usrloc_admin.xml
  7. 190 1
      modules_k/usrloc/ucontact.c
  8. 27 0
      modules_k/usrloc/ucontact.h
  9. 182 0
      modules_k/usrloc/udomain.c
  10. 12 0
      modules_k/usrloc/udomain.h
  11. 18 0
      modules_k/usrloc/ul_mod.c
  12. 9 0
      modules_k/usrloc/ul_mod.h
  13. 0 0
      modules_s/.gitkeep
  14. 0 0
      obsolete/registrar/Makefile
  15. 0 0
      obsolete/registrar/README
  16. 0 0
      obsolete/registrar/common.c
  17. 0 0
      obsolete/registrar/common.h
  18. 0 0
      obsolete/registrar/doc/Makefile
  19. 0 0
      obsolete/registrar/doc/functions.xml
  20. 0 0
      obsolete/registrar/doc/params.xml
  21. 0 0
      obsolete/registrar/doc/registrar.xml
  22. 0 0
      obsolete/registrar/lookup.c
  23. 0 0
      obsolete/registrar/lookup.h
  24. 0 0
      obsolete/registrar/reg_mod.c
  25. 0 0
      obsolete/registrar/reg_mod.h
  26. 0 0
      obsolete/registrar/regtime.c
  27. 0 0
      obsolete/registrar/regtime.h
  28. 0 0
      obsolete/registrar/reply.c
  29. 0 0
      obsolete/registrar/reply.h
  30. 0 0
      obsolete/registrar/rerrno.c
  31. 0 0
      obsolete/registrar/rerrno.h
  32. 0 0
      obsolete/registrar/save.c
  33. 0 0
      obsolete/registrar/save.h
  34. 0 0
      obsolete/registrar/sip_msg.c
  35. 0 0
      obsolete/registrar/sip_msg.h
  36. 0 0
      obsolete/usrloc/Makefile
  37. 0 0
      obsolete/usrloc/README
  38. 0 0
      obsolete/usrloc/dlist.c
  39. 0 0
      obsolete/usrloc/dlist.h
  40. 0 0
      obsolete/usrloc/doc/Makefile
  41. 0 0
      obsolete/usrloc/doc/api.xml
  42. 0 0
      obsolete/usrloc/doc/functions.xml
  43. 0 0
      obsolete/usrloc/doc/params.xml
  44. 0 0
      obsolete/usrloc/doc/usrloc.xml
  45. 0 0
      obsolete/usrloc/doc/usrloc_states_w_zombie.png
  46. 0 0
      obsolete/usrloc/doc/usrloc_states_w_zombie.vsd
  47. 0 0
      obsolete/usrloc/hslot.c
  48. 0 0
      obsolete/usrloc/hslot.h
  49. 0 0
      obsolete/usrloc/notify.c
  50. 0 0
      obsolete/usrloc/notify.h
  51. 0 0
      obsolete/usrloc/reg_avps.c
  52. 0 0
      obsolete/usrloc/reg_avps.h
  53. 0 0
      obsolete/usrloc/reg_avps_db.c
  54. 0 0
      obsolete/usrloc/reg_avps_db.h
  55. 0 0
      obsolete/usrloc/ucontact.c
  56. 0 0
      obsolete/usrloc/ucontact.h
  57. 0 0
      obsolete/usrloc/udomain.c
  58. 0 0
      obsolete/usrloc/udomain.h
  59. 0 0
      obsolete/usrloc/ul_callback.c
  60. 0 0
      obsolete/usrloc/ul_callback.h
  61. 0 0
      obsolete/usrloc/ul_mod.c
  62. 0 0
      obsolete/usrloc/ul_mod.h
  63. 0 0
      obsolete/usrloc/ul_rpc.c
  64. 0 0
      obsolete/usrloc/ul_rpc.h
  65. 0 0
      obsolete/usrloc/urecord.c
  66. 0 0
      obsolete/usrloc/urecord.h
  67. 0 0
      obsolete/usrloc/usrloc.c
  68. 0 0
      obsolete/usrloc/usrloc.h
  69. 0 0
      obsolete/usrloc/utime.c
  70. 0 0
      obsolete/usrloc/utime.h
  71. 12 0
      utils/kamctl/db_berkeley/kamailio/location_attrs
  72. 2 2
      utils/kamctl/db_sqlite/sca-create.sql
  73. 15 0
      utils/kamctl/db_sqlite/usrloc-create.sql
  74. 2 0
      utils/kamctl/dbtext/kamailio/location_attrs
  75. 2 2
      utils/kamctl/mysql/sca-create.sql
  76. 15 0
      utils/kamctl/mysql/usrloc-create.sql
  77. 1 1
      utils/kamctl/oracle/sca-create.sql
  78. 23 0
      utils/kamctl/oracle/usrloc-create.sql
  79. 2 2
      utils/kamctl/postgres/sca-create.sql
  80. 15 0
      utils/kamctl/postgres/usrloc-create.sql
  81. 41 11
      utils/kamctl/xhttp_pi/pi_framework.xml
  82. 17 0
      utils/kamctl/xhttp_pi/usrloc-mod
  83. 13 0
      utils/kamctl/xhttp_pi/usrloc-table
  84. 38 1
      xavp.c
  85. 1 0
      xavp.h

+ 1 - 1
Makefile.defs

@@ -270,7 +270,7 @@ CC_LONGVER:=$(shell if  $(CC) -v 2>/dev/null; then \
 					else \
 						$(CC) -V 2>&1 ; \
 					fi )
-MKTAGS=ctags -R .
+MKTAGS=ctags
 
 #find-out the compiler's name
 

+ 8 - 4
Makefile.rules

@@ -288,10 +288,14 @@ clean_doxygen:
 
 .PHONY: TAGS
 TAGS:
-	$(MKTAGS) 
-	
-	
-	
+	$(MKTAGS) --exclude="obsolete/*" -R .
+
+.PHONY: TAGS-ALL
+TAGS-ALL:
+	$(MKTAGS) -R .
+
+
+
 ifeq (,$(MAKECMDGOALS))
 -include $(depends)
 else

+ 1 - 0
lib/srdb1/schema/kamailio-usrloc.xml

@@ -9,4 +9,5 @@
 <database xmlns:xi="http://www.w3.org/2001/XInclude">
     <name>User location</name>
     <xi:include href="location.xml"/>
+    <xi:include href="location_attrs.xml"/>
 </database>

+ 101 - 0
lib/srdb1/schema/location_attrs.xml

@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE table PUBLIC "-//kamailio.org//DTD DBSchema V1.1//EN" 
+  "http://kamailio.org/pub/kamailio/dbschema/dtd/1.1/dbschema.dtd" [
+
+<!ENTITY % entities SYSTEM "entities.xml">
+%entities;
+
+]>
+
+<table id="location" xmlns:db="http://docbook.org/ns/docbook">
+    <name>location_attrs</name>
+    <version>1</version>
+    <type db="mysql">&MYSQL_TABLE_TYPE;</type>
+    <description>
+        <db:para>Persistent user location attributes for the usrloc module. More information can be found at: &KAMAILIO_MOD_DOC;usrloc.html
+        </db:para>
+    </description>
+
+    <column id="id">
+        <name>id</name>
+        <type>unsigned int</type>
+        <size>&table_id_len;</size>
+        <autoincrement/>
+        <primary/>
+        <type db="dbtext">int,auto</type>
+        <description>unique ID</description>
+    </column>
+
+    <column id="ruid">
+        <name>ruid</name>
+        <type>string</type>
+        <size>64</size>
+        <default/>
+        <description>Record internal unique id</description>
+        <natural/>
+    </column>
+
+	<column id="username">
+        <name>&USERCOL;</name>
+        <type>string</type>
+        <size>&user_len;</size>
+        <default/>
+        <description>Username / phone number </description>
+        <natural/>
+    </column>
+
+    <column id="domain">
+        <name>domain</name>
+        <type>string</type>
+        <size>&domain_len;</size>
+        <null/>
+        <default><null/></default>
+        <description>Domain name</description>
+        <natural/>
+    </column>
+
+    <column>
+        <name>aname</name>
+        <type>string</type>
+        <size>64</size>
+		<default/>
+        <description>Attribute name.</description>
+    </column>
+
+    <column>
+        <name>atype</name>
+        <type>int</type>
+        <size>11</size>
+        <default>0</default>
+        <description>Attribute type.</description>
+    </column>
+
+    <column>
+        <name>avalue</name>
+        <type>string</type>
+        <size>255</size>
+        <default/>
+        <description>Attribute value.</description>
+    </column>
+
+    <column id="last_modified">
+        <name>last_modified</name>
+        <type>datetime</type>
+        <default>&DEFAULT_DATETIME;</default>
+        <default db="oracle">to_date('&DEFAULT_DATETIME;','yyyy-mm-dd hh24:mi:ss')</default>
+        <description>Date and time when this entry was last modified.</description>
+    </column>
+
+    <index>
+        <name>account_record_idx</name>
+        <colref linkend="username"/>
+        <colref linkend="domain"/>
+        <colref linkend="ruid"/>
+    </index>
+    <index>
+        <name>last_modified_idx</name>
+        <colref linkend="last_modified"/>
+    </index>
+
+
+</table>

+ 54 - 53
modules_k/usrloc/README

@@ -66,24 +66,24 @@ Bogdan-Andrei Iancu
               3.28. db_update_as_insert (string)
               3.29. db_check_update (string)
               3.30. timer_procs (string)
+              3.31. xavp_contact (string)
 
         4. Functions
-        5. xavp_contact (string)
-        6. MI Commands
+        5. MI Commands
 
-              6.1. ul_rm
-              6.2. ul_rm_contact
-              6.3. ul_dump
-              6.4. ul_flush
-              6.5. ul_add
-              6.6. ul_show_contact
+              5.1. ul_rm
+              5.2. ul_rm_contact
+              5.3. ul_dump
+              5.4. ul_flush
+              5.5. ul_add
+              5.6. ul_show_contact
 
-        7. Statistics
+        6. Statistics
 
-              7.1. users
-              7.2. contacts
-              7.3. expires
-              7.4. registered_users
+              6.1. users
+              6.2. contacts
+              6.3. expires
+              6.4. registered_users
 
    2. Developer Guide
 
@@ -188,24 +188,24 @@ Chapter 1. Admin Guide
         3.28. db_update_as_insert (string)
         3.29. db_check_update (string)
         3.30. timer_procs (string)
+        3.31. xavp_contact (string)
 
    4. Functions
-   5. xavp_contact (string)
-   6. MI Commands
+   5. MI Commands
 
-        6.1. ul_rm
-        6.2. ul_rm_contact
-        6.3. ul_dump
-        6.4. ul_flush
-        6.5. ul_add
-        6.6. ul_show_contact
+        5.1. ul_rm
+        5.2. ul_rm_contact
+        5.3. ul_dump
+        5.4. ul_flush
+        5.5. ul_add
+        5.6. ul_show_contact
 
-   7. Statistics
+   6. Statistics
 
-        7.1. users
-        7.2. contacts
-        7.3. expires
-        7.4. registered_users
+        6.1. users
+        6.2. contacts
+        6.3. expires
+        6.4. registered_users
 
 1. Overview
 
@@ -295,6 +295,7 @@ Chapter 1. Admin Guide
    3.28. db_update_as_insert (string)
    3.29. db_check_update (string)
    3.30. timer_procs (string)
+   3.31. xavp_contact (string)
 
 3.1. nat_bflag (integer)
 
@@ -704,11 +705,7 @@ modparam("usrloc", "db_check_update", 1)
 modparam("usrloc", "timer_procs", 4)
 ...
 
-4. Functions
-
-   There are no exported functions that could be used in scripts.
-
-5. xavp_contact (string)
+3.31. xavp_contact (string)
 
    The name of XAVP storring the attributes per contact. They are saved in
    location record and restored at lookup.
@@ -720,16 +717,20 @@ modparam("usrloc", "timer_procs", 4)
 modparam("usrloc", "xavp_contact", "ulattrs")
 ...
 
-6. MI Commands
+4. Functions
+
+   There are no exported functions that could be used in scripts.
+
+5. MI Commands
 
-   6.1. ul_rm
-   6.2. ul_rm_contact
-   6.3. ul_dump
-   6.4. ul_flush
-   6.5. ul_add
-   6.6. ul_show_contact
+   5.1. ul_rm
+   5.2. ul_rm_contact
+   5.3. ul_dump
+   5.4. ul_flush
+   5.5. ul_add
+   5.6. ul_show_contact
 
-6.1. ul_rm
+5.1. ul_rm
 
    Deletes an entire AOR record (including its contacts).
 
@@ -738,7 +739,7 @@ modparam("usrloc", "xavp_contact", "ulattrs")
      * AOR - user AOR in username[@domain] format (domain must be supplied
        only if use_domain option is on).
 
-6.2. ul_rm_contact
+5.2. ul_rm_contact
 
    Deletes a contact from an AOR record.
 
@@ -748,7 +749,7 @@ modparam("usrloc", "xavp_contact", "ulattrs")
        only if use_domain option is on).
      * contact - exact contact to be removed
 
-6.3. ul_dump
+5.3. ul_dump
 
    Dumps the entire content of the USRLOC in memory cache
 
@@ -757,11 +758,11 @@ modparam("usrloc", "xavp_contact", "ulattrs")
        "brief", a brief dump will be done (only AOR and contacts, with no
        other details)
 
-6.4. ul_flush
+5.4. ul_flush
 
    Triggers the flush of USRLOC memory cache into DB.
 
-6.5. ul_add
+5.5. ul_add
 
    Adds a new contact for an user AOR.
 
@@ -777,7 +778,7 @@ modparam("usrloc", "xavp_contact", "ulattrs")
      * cflags - per branch flags of the contact
      * methods - mask with supported requests of the contact
 
-6.6. ul_show_contact
+5.6. ul_show_contact
 
    Dumps the contacts of an user AOR.
 
@@ -786,33 +787,33 @@ modparam("usrloc", "xavp_contact", "ulattrs")
      * AOR - user AOR in username[@domain] format (domain must be supplied
        only if use_domain option is on).
 
-7. Statistics
+6. Statistics
 
-   7.1. users
-   7.2. contacts
-   7.3. expires
-   7.4. registered_users
+   6.1. users
+   6.2. contacts
+   6.3. expires
+   6.4. registered_users
 
    Exported statistics are listed in the next sections.
 
-7.1. users
+6.1. users
 
    Number of AOR existing in the USRLOC memory cache for that domain - can
    not be resetted; this statistic will be register for each used domain
    (Ex: location).
 
-7.2. contacts
+6.2. contacts
 
    Number of contacts existing in the USRLOC memory cache for that domain
    - can not be resetted; this statistic will be register for each used
    domain (Ex: location).
 
-7.3. expires
+6.3. expires
 
    Total number of expired contacts for that domain - can be resetted;
    this statistic will be register for each used domain (Ex: location).
 
-7.4. registered_users
+6.4. registered_users
 
    Total number of AOR existing in the USRLOC memory cache for all domains
    - can not be resetted.

+ 8 - 9
modules_k/usrloc/doc/usrloc_admin.xml

@@ -823,15 +823,6 @@ modparam("usrloc", "timer_procs", 4)
 		</example>
 	</section>
 
-	</section>
-
-	<section>
-	<title>Functions</title>
-	<para>
-		There are no exported functions that could be used in scripts.
-	</para>
-	</section>
-
 	<section id="xavp_contact">
 		<title><varname>xavp_contact</varname> (string)</title>
 		<para>
@@ -853,6 +844,14 @@ modparam("usrloc", "xavp_contact", "ulattrs")
 		</example>
 	</section>
 
+	</section>
+
+	<section>
+	<title>Functions</title>
+	<para>
+		There are no exported functions that could be used in scripts.
+	</para>
+	</section>
 
 	<section>
 	<title>MI Commands</title>

+ 190 - 1
modules_k/usrloc/ucontact.c

@@ -75,6 +75,7 @@ void ucontact_xavp_store(ucontact_t *_c)
 	if(xavp==NULL)
 		return;
 	/* clone the xavp found in core */
+	LM_DBG("trying to clone per contact xavps\n");
 	_c->xavp = xavp_clone_level_nodata(xavp);
 	return;
 }
@@ -615,6 +616,9 @@ int db_insert_ucontact(ucontact_t* _c)
 		return -1;
 	}
 
+	uldb_insert_attrs(_c->domain, &vals[0].val.str_val, &vals[nr_cols-1].val.str_val,
+		&_c->ruid, _c->xavp);
+
 	return 0;
 }
 
@@ -786,9 +790,15 @@ int db_update_ucontact(ucontact_t* _c)
 		 * to do an INSERT */
 		if(ul_dbf.affected_rows(ul_dbh)==0) {
 			LM_DBG("affected rows by UPDATE was 0, doing an INSERT\n");
-			return db_insert_ucontact(_c);
+			if(db_insert_ucontact(_c)<0)
+				return -1;
 		}
 	}
+	/* delete old db attrs and add the current list */
+	uldb_delete_attrs(_c->domain, &vals1[0].val.str_val,
+			&vals1[3].val.str_val, &_c->ruid);
+	uldb_insert_attrs(_c->domain, &vals1[0].val.str_val, &vals1[3].val.str_val,
+		&_c->ruid, _c->xavp);
 
 	return 0;
 }
@@ -840,6 +850,9 @@ int db_delete_ucontact(ucontact_t* _c)
 		}
 	}
 
+	uldb_delete_attrs(_c->domain, &vals[0].val.str_val,
+			&vals[3].val.str_val, &_c->ruid);
+
 	if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
 		LM_ERR("sql use_table failed\n");
 		return -1;
@@ -969,3 +982,179 @@ int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
 	}
 	return 0;
 }
+
+/*!
+ * \brief Load all location attributes from a udomain
+ *
+ * Load all location attributes from a udomain, useful to populate the
+ * memory cache on startup.
+ * \param _dname loaded domain name
+ * \param _user sip username
+ * \param _domain sip domain
+ * \param _ruid usrloc record unique id
+ * \return 0 on success, -1 on failure
+ */
+int uldb_delete_attrs(str* _dname, str *_user, str *_domain, str *_ruid)
+{
+	char tname_buf[64];
+	str tname;
+	db_key_t keys[3];
+	db_val_t vals[3];
+
+	LM_DBG("trying to delete location attributes\n");
+
+	if(ul_xavp_contact_name.s==NULL) {
+		/* feature disabled by mod param */
+		return 0;
+	}
+
+	if(_dname->len+6>=64) {
+		LM_ERR("attributes table name is too big\n");
+		return -1;
+	}
+	strncpy(tname_buf, _dname->s, _dname->len);
+	tname_buf[_dname->len] = '\0';
+	strcat(tname_buf, "_attrs");
+	tname.s = tname_buf;
+	tname.len = _dname->len + 6;
+
+	keys[0] = &ulattrs_user_col;
+	keys[1] = &ulattrs_ruid_col;
+	keys[2] = &ulattrs_domain_col;
+
+	vals[0].type = DB1_STR;
+	vals[0].nul = 0;
+	vals[0].val.str_val = *_user;
+
+	vals[1].type = DB1_STR;
+	vals[1].nul = 0;
+	vals[1].val.str_val = *_ruid;
+
+	if (use_domain) {
+		vals[2].type = DB1_STR;
+		vals[2].nul = 0;
+		vals[2].val.str_val = *_domain;
+	}
+
+	if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
+		LM_ERR("sql use_table failed\n");
+		return -1;
+	}
+
+	if (ul_dbf.delete(ul_dbh, keys, 0, vals, (use_domain) ? (3) : (2)) < 0) {
+		LM_ERR("deleting from database failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*!
+ * \brief Insert contact attributes into the database
+ * \param _dname loaded domain name
+ * \param _user sip username
+ * \param _domain sip domain
+ * \param _ruid record unique id
+ * \param _xhead head of xavp list
+ * \return 0 on success, -1 on failure
+ */
+int uldb_insert_attrs(str *_dname, str *_user, str *_domain,
+		str *_ruid, sr_xavp_t *_xhead)
+{
+	char tname_buf[64];
+	str tname;
+	str avalue;
+	sr_xavp_t *xavp;
+	db_key_t keys[7];
+	db_val_t vals[7];
+	int nr_cols;
+
+	LM_DBG("trying to insert location attributes\n");
+
+	if(ul_xavp_contact_name.s==NULL) {
+		/* feature disabled by mod param */
+		LM_DBG("location attributes disabled\n");
+		return 0;
+	}
+
+	if(_xhead==NULL || _xhead->val.type!=SR_XTYPE_XAVP
+			|| _xhead->val.v.xavp==NULL) {
+		/* nothing to write */
+		LM_DBG("no location attributes\n");
+		return 0;
+	}
+
+	if(_dname->len+6>=64) {
+		LM_ERR("attributes table name is too big\n");
+		return -1;
+	}
+	strncpy(tname_buf, _dname->s, _dname->len);
+	tname_buf[_dname->len] = '\0';
+	strcat(tname_buf, "_attrs");
+	tname.s = tname_buf;
+	tname.len = _dname->len + 6;
+
+	if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
+		LM_ERR("sql use_table failed for %.*s\n", tname.len, tname.s);
+		return -1;
+	}
+
+	keys[0] = &ulattrs_user_col;
+	keys[1] = &ulattrs_ruid_col;
+	keys[2] = &ulattrs_last_mod_col;
+	keys[3] = &ulattrs_aname_col;
+	keys[4] = &ulattrs_atype_col;
+	keys[5] = &ulattrs_avalue_col;
+	keys[6] = &ulattrs_domain_col;
+
+	vals[0].type = DB1_STR;
+	vals[0].nul = 0;
+	vals[0].val.str_val = *_user;
+
+	vals[1].type = DB1_STR;
+	vals[1].nul = 0;
+	vals[1].val.str_val = *_ruid;
+
+	vals[2].type = DB1_DATETIME;
+	vals[2].nul = 0;
+	vals[2].val.time_val = time(NULL);
+
+	if (use_domain && _domain!=NULL && _domain->s!=NULL) {
+		nr_cols = 7;
+		vals[6].type = DB1_STR;
+		vals[6].nul = 0;
+		vals[6].val.str_val = *_domain;
+
+	} else {
+		nr_cols = 6;
+	}
+
+	for(xavp=_xhead->val.v.xavp; xavp; xavp=xavp->next) {
+		vals[3].type = DB1_STR;
+		vals[3].nul = 0;
+		vals[3].val.str_val = xavp->name;
+
+		vals[4].type = DB1_INT;
+		vals[4].nul = 0;
+		if(xavp->val.type==SR_XTYPE_STR) {
+			vals[4].val.int_val = 0;
+			avalue = xavp->val.v.s;
+		} else if(xavp->val.type==SR_XTYPE_INT) {
+			vals[4].val.int_val = 1;
+			avalue.s = sint2str((long)xavp->val.v.i, &avalue.len);
+		} else {
+			continue;
+		}
+
+		vals[5].type = DB1_STR;
+		vals[5].nul = 0;
+		vals[5].val.str_val = avalue;
+
+		if (ul_dbf.insert(ul_dbh, keys, vals, nr_cols) < 0) {
+			LM_ERR("inserting contact in db failed\n");
+			return -1;
+		}
+
+	}
+	return 0;
+}

+ 27 - 0
modules_k/usrloc/ucontact.h

@@ -37,6 +37,7 @@
 
 
 #include <stdio.h>
+#include "../../xavp.h"
 #include "usrloc.h"
 
 
@@ -149,4 +150,30 @@ int db_delete_ucontact(ucontact_t* _c);
  */
 int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci);
 
+/* ====== per contact attributes ====== */
+
+/*!
+ * \brief Load all location attributes from a udomain
+ *
+ * Load all location attributes from a udomain, useful to populate the
+ * memory cache on startup.
+ * \param _dname loaded domain name
+ * \param _user sip username
+ * \param _domain sip domain
+ * \param _ruid usrloc record unique id
+ * \return 0 on success, -1 on failure
+ */
+int uldb_delete_attrs(str* _dname, str *_user, str *_domain, str *_ruid);
+
+/*!
+ * \brief Insert contact attributes into the database
+ * \param _dname loaded domain name
+ * \param _user sip username
+ * \param _domain sip domain
+ * \param _ruid record unique id
+ * \param _xhead head of xavp list
+ * \return 0 on success, -1 on failure
+ */
+int uldb_insert_attrs(str *_dname, str *_user, str *_domain,
+        str *_ruid, sr_xavp_t *_xhead);
 #endif

+ 182 - 0
modules_k/usrloc/udomain.c

@@ -1123,3 +1123,185 @@ int delete_urecord(udomain_t* _d, str* _aor, struct urecord* _r)
 	release_urecord(_r);
 	return 0;
 }
+
+
+/*!
+ * \brief Load all location attributes from an udomain
+ *
+ * Load all location attributes from a udomain, useful to populate the
+ * memory cache on startup.
+ * \param _d loaded domain
+ * \return 0 on success, -1 on failure
+ */
+int uldb_preload_attrs(udomain_t *_d)
+{
+	char uri[MAX_URI_SIZE];
+	str  suri;
+	char tname_buf[64];
+	str tname;
+	db_row_t *row;
+	db_key_t columns[6];
+	db1_res_t* res = NULL;
+	str user = {0};
+	str domain = {0};
+	str ruid;
+	str aname;
+	str avalue;
+	sr_xval_t aval;
+	int i;
+	int n;
+
+	urecord_t* r;
+	ucontact_t* c;
+
+	if(ul_xavp_contact_name.s==NULL) {
+		/* feature disabled by mod param */
+		return 0;
+	}
+
+	if(_d->name->len + 6>=64) {
+		LM_ERR("attributes table name is too big\n");
+		return -1;
+	}
+	strncpy(tname_buf, _d->name->s, _d->name->len);
+	tname_buf[_d->name->len] = '\0';
+	strcat(tname_buf, "_attrs");
+	tname.s = tname_buf;
+	tname.len = _d->name->len + 6;
+
+	columns[0] = &ulattrs_user_col;
+	columns[1] = &ulattrs_ruid_col;
+	columns[2] = &ulattrs_aname_col;
+	columns[3] = &ulattrs_atype_col;
+	columns[4] = &ulattrs_avalue_col;
+	columns[5] = &ulattrs_domain_col;
+
+	if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
+		LM_ERR("sql use_table failed for %.*s\n", tname.len, tname.s);
+		return -1;
+	}
+
+#ifdef EXTRA_DEBUG
+	LM_NOTICE("load start time [%d]\n", (int)time(NULL));
+#endif
+
+	if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
+		if (ul_dbf.query(ul_dbh, 0, 0, 0, columns, 0, (use_domain)?(6):(5), 0,
+					0) < 0) {
+			LM_ERR("db_query (1) failed\n");
+			return -1;
+		}
+		if(ul_dbf.fetch_result(ul_dbh, &res, ul_fetch_rows)<0) {
+			LM_ERR("fetching rows failed\n");
+			return -1;
+		}
+	} else {
+		if (ul_dbf.query(ul_dbh, 0, 0, 0, columns, 0, (use_domain)?(6):(5), 0,
+		&res) < 0) {
+			LM_ERR("db_query failed\n");
+			return -1;
+		}
+	}
+
+	if (RES_ROW_N(res) == 0) {
+		LM_DBG("location attrs table is empty\n");
+		ul_dbf.free_result(ul_dbh, res);
+		return 0;
+	}
+
+
+	n = 0;
+	do {
+		LM_DBG("loading records - cycle [%d]\n", ++n);
+		for(i = 0; i < RES_ROW_N(res); i++) {
+			row = RES_ROWS(res) + i;
+
+			user.s = (char*)VAL_STRING(ROW_VALUES(row));
+			if (VAL_NULL(ROW_VALUES(row)) || user.s==0 || user.s[0]==0) {
+				LM_CRIT("empty username record in table %s...skipping\n",
+						_d->name->s);
+				continue;
+			}
+			user.len = strlen(user.s);
+
+			ruid.s = (char*)VAL_STRING(ROW_VALUES(row) + 1);
+			ruid.len = strlen(ruid.s);
+			aname.s = (char*)VAL_STRING(ROW_VALUES(row) + 2);
+			aname.len = strlen(aname.s);
+			avalue.s = (char*)VAL_STRING(ROW_VALUES(row) + 4);
+			avalue.len = strlen(avalue.s);
+			memset(&aval, 0, sizeof(sr_xval_t));
+			if(VAL_INT(ROW_VALUES(row)+3)==0) {
+				/* string value */
+				aval.v.s = avalue;
+				aval.type = SR_XTYPE_STR;
+			} else if(VAL_INT(ROW_VALUES(row)+3)==1) {
+				/* int value */
+				str2sint(&avalue, &aval.v.i);
+				aval.type = SR_XTYPE_INT;
+			} else {
+				/* unknown type - ignore */
+				continue;
+			}
+
+			if (use_domain) {
+				domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 6);
+				if (VAL_NULL(ROW_VALUES(row)+6) || domain.s==0 || domain.s[0]==0){
+					LM_CRIT("empty domain record for user %.*s...skipping\n",
+							user.len, user.s);
+					continue;
+				}
+				domain.len = strlen(domain.s);
+				/* user.s cannot be NULL - checked previosly */
+				suri.len = snprintf(uri, MAX_URI_SIZE, "%.*s@%s",
+					user.len, user.s, domain.s);
+				suri.s = uri;
+				if (suri.s[suri.len]!=0) {
+					LM_CRIT("URI '%.*s@%s' longer than %d\n", user.len, user.s,
+							domain.s, MAX_URI_SIZE);
+					continue;
+				}
+			} else {
+				suri = user;
+			}
+
+			lock_udomain(_d, &suri);
+			if (get_urecord_by_ruid(_d, ul_get_aorhash(&suri), &ruid, &r, &c) > 0) {
+				/* delete attrs records from db table */
+				LM_INFO("no contact record for this ruid\n");
+				uldb_delete_attrs(_d->name, &user, &domain, &ruid);
+			} else {
+				/* add xavp to contact */
+				if(c->xavp==NULL) {
+					if(xavp_add_xavp_value(&ul_xavp_contact_name, &aname,
+								&aval, &c->xavp)==NULL)
+						LM_INFO("cannot add first xavp to contact - ignoring\n");
+				} else {
+					if(c->xavp->val.type==SR_XTYPE_XAVP) {
+						if(xavp_add_value(&aname, &aval, &c->xavp->val.v.xavp)==NULL)
+							LM_INFO("cannot add values to contact xavp\n");
+					}
+				}
+			}
+			unlock_udomain(_d, &user);
+		}
+
+		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
+			if(ul_dbf.fetch_result(ul_dbh, &res, ul_fetch_rows)<0) {
+				LM_ERR("fetching rows (1) failed\n");
+				ul_dbf.free_result(ul_dbh, res);
+				return -1;
+			}
+		} else {
+			break;
+		}
+	} while(RES_ROW_N(res)>0);
+
+	ul_dbf.free_result(ul_dbh, res);
+
+#ifdef EXTRA_DEBUG
+	LM_NOTICE("load end time [%d]\n", (int)time(NULL));
+#endif
+
+	return 0;
+}

+ 12 - 0
modules_k/usrloc/udomain.h

@@ -213,4 +213,16 @@ int get_urecord_by_ruid(udomain_t* _d, unsigned int _aorhash,
 int delete_urecord(udomain_t* _d, str* _aor, struct urecord* _r);
 
 
+/* ===== per-contact attributes ======= */
+
+/*!
+ * \brief Load all location attributes from an udomain
+ *
+ * Load all location attributes from a udomain, useful to populate the
+ * memory cache on startup.
+ * \param _d loaded domain
+ * \return 0 on success, -1 on failure
+ */
+int uldb_preload_attrs(udomain_t *_d);
+
 #endif

+ 18 - 0
modules_k/usrloc/ul_mod.c

@@ -91,6 +91,14 @@ MODULE_VERSION
 #define REG_ID_COL     "reg_id"
 #define LAST_MOD_COL   "last_modified"
 
+#define ULATTRS_USER_COL       "username"
+#define ULATTRS_DOMAIN_COL     "domain"
+#define ULATTRS_RUID_COL       "ruid"
+#define ULATTRS_ANAME_COL      "aname"
+#define ULATTRS_ATYPE_COL      "atype"
+#define ULATTRS_AVALUE_COL     "avalue"
+#define ULATTRS_LAST_MOD_COL   "last_modified"
+
 static int mod_init(void);                          /*!< Module initialization function */
 static void destroy(void);                          /*!< Module destroy function */
 static void ul_core_timer(unsigned int ticks, void* param);  /*!< Core timer handler */
@@ -137,6 +145,15 @@ 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 ulattrs_user_col   = str_init(ULATTRS_USER_COL);   /*!< Name of column containing username */
+str ulattrs_domain_col = str_init(ULATTRS_DOMAIN_COL); /*!< Name of column containing domain */
+str ulattrs_ruid_col   = str_init(ULATTRS_RUID_COL);   /*!< Name of column containing record unique id */
+str ulattrs_aname_col  = str_init(ULATTRS_ANAME_COL);  /*!< Name of column containing attribute name */
+str ulattrs_atype_col  = str_init(ULATTRS_ATYPE_COL);  /*!< Name of column containing attribute type */
+str ulattrs_avalue_col = str_init(ULATTRS_AVALUE_COL); /*!< Name of column containing attribute value */
+str ulattrs_last_mod_col = str_init(ULATTRS_LAST_MOD_COL);	/*!< Name of column containing the last modified date */
+
 str db_url          = str_init(DEFAULT_DB_URL);	/*!< Database URL */
 int timer_interval  = 60;				/*!< Timer interval in seconds */
 int db_mode         = 0;				/*!< Database sync scheme: 0-no db, 1-write through, 2-write back, 3-only db */
@@ -423,6 +440,7 @@ static int child_init(int _rank)
 						_rank, ptr->name.len, ZSW(ptr->name.s));
 				return -1;
 			}
+			uldb_preload_attrs(ptr->d);
 		}
 	}
 

+ 9 - 0
modules_k/usrloc/ul_mod.h

@@ -64,6 +64,15 @@ extern str instance_col;
 extern str reg_id_col;
 extern str last_mod_col;
 
+extern str ulattrs_user_col;
+extern str ulattrs_domain_col;
+extern str ulattrs_ruid_col;
+extern str ulattrs_aname_col;
+extern str ulattrs_atype_col;
+extern str ulattrs_avalue_col;
+extern str ulattrs_last_mod_col;
+
+
 extern str db_url;
 extern int timer_interval;
 extern int db_mode;

+ 0 - 0
modules_s/.gitkeep


+ 0 - 0
modules_s/registrar/Makefile → obsolete/registrar/Makefile


+ 0 - 0
modules_s/registrar/README → obsolete/registrar/README


+ 0 - 0
modules_s/registrar/common.c → obsolete/registrar/common.c


+ 0 - 0
modules_s/registrar/common.h → obsolete/registrar/common.h


+ 0 - 0
modules_s/registrar/doc/Makefile → obsolete/registrar/doc/Makefile


+ 0 - 0
modules_s/registrar/doc/functions.xml → obsolete/registrar/doc/functions.xml


+ 0 - 0
modules_s/registrar/doc/params.xml → obsolete/registrar/doc/params.xml


+ 0 - 0
modules_s/registrar/doc/registrar.xml → obsolete/registrar/doc/registrar.xml


+ 0 - 0
modules_s/registrar/lookup.c → obsolete/registrar/lookup.c


+ 0 - 0
modules_s/registrar/lookup.h → obsolete/registrar/lookup.h


+ 0 - 0
modules_s/registrar/reg_mod.c → obsolete/registrar/reg_mod.c


+ 0 - 0
modules_s/registrar/reg_mod.h → obsolete/registrar/reg_mod.h


+ 0 - 0
modules_s/registrar/regtime.c → obsolete/registrar/regtime.c


+ 0 - 0
modules_s/registrar/regtime.h → obsolete/registrar/regtime.h


+ 0 - 0
modules_s/registrar/reply.c → obsolete/registrar/reply.c


+ 0 - 0
modules_s/registrar/reply.h → obsolete/registrar/reply.h


+ 0 - 0
modules_s/registrar/rerrno.c → obsolete/registrar/rerrno.c


+ 0 - 0
modules_s/registrar/rerrno.h → obsolete/registrar/rerrno.h


+ 0 - 0
modules_s/registrar/save.c → obsolete/registrar/save.c


+ 0 - 0
modules_s/registrar/save.h → obsolete/registrar/save.h


+ 0 - 0
modules_s/registrar/sip_msg.c → obsolete/registrar/sip_msg.c


+ 0 - 0
modules_s/registrar/sip_msg.h → obsolete/registrar/sip_msg.h


+ 0 - 0
modules_s/usrloc/Makefile → obsolete/usrloc/Makefile


+ 0 - 0
modules_s/usrloc/README → obsolete/usrloc/README


+ 0 - 0
modules_s/usrloc/dlist.c → obsolete/usrloc/dlist.c


+ 0 - 0
modules_s/usrloc/dlist.h → obsolete/usrloc/dlist.h


+ 0 - 0
modules_s/usrloc/doc/Makefile → obsolete/usrloc/doc/Makefile


+ 0 - 0
modules_s/usrloc/doc/api.xml → obsolete/usrloc/doc/api.xml


+ 0 - 0
modules_s/usrloc/doc/functions.xml → obsolete/usrloc/doc/functions.xml


+ 0 - 0
modules_s/usrloc/doc/params.xml → obsolete/usrloc/doc/params.xml


+ 0 - 0
modules_s/usrloc/doc/usrloc.xml → obsolete/usrloc/doc/usrloc.xml


+ 0 - 0
modules_s/usrloc/doc/usrloc_states_w_zombie.png → obsolete/usrloc/doc/usrloc_states_w_zombie.png


+ 0 - 0
modules_s/usrloc/doc/usrloc_states_w_zombie.vsd → obsolete/usrloc/doc/usrloc_states_w_zombie.vsd


+ 0 - 0
modules_s/usrloc/hslot.c → obsolete/usrloc/hslot.c


+ 0 - 0
modules_s/usrloc/hslot.h → obsolete/usrloc/hslot.h


+ 0 - 0
modules_s/usrloc/notify.c → obsolete/usrloc/notify.c


+ 0 - 0
modules_s/usrloc/notify.h → obsolete/usrloc/notify.h


+ 0 - 0
modules_s/usrloc/reg_avps.c → obsolete/usrloc/reg_avps.c


+ 0 - 0
modules_s/usrloc/reg_avps.h → obsolete/usrloc/reg_avps.h


+ 0 - 0
modules_s/usrloc/reg_avps_db.c → obsolete/usrloc/reg_avps_db.c


+ 0 - 0
modules_s/usrloc/reg_avps_db.h → obsolete/usrloc/reg_avps_db.h


+ 0 - 0
modules_s/usrloc/ucontact.c → obsolete/usrloc/ucontact.c


+ 0 - 0
modules_s/usrloc/ucontact.h → obsolete/usrloc/ucontact.h


+ 0 - 0
modules_s/usrloc/udomain.c → obsolete/usrloc/udomain.c


+ 0 - 0
modules_s/usrloc/udomain.h → obsolete/usrloc/udomain.h


+ 0 - 0
modules_s/usrloc/ul_callback.c → obsolete/usrloc/ul_callback.c


+ 0 - 0
modules_s/usrloc/ul_callback.h → obsolete/usrloc/ul_callback.h


+ 0 - 0
modules_s/usrloc/ul_mod.c → obsolete/usrloc/ul_mod.c


+ 0 - 0
modules_s/usrloc/ul_mod.h → obsolete/usrloc/ul_mod.h


+ 0 - 0
modules_s/usrloc/ul_rpc.c → obsolete/usrloc/ul_rpc.c


+ 0 - 0
modules_s/usrloc/ul_rpc.h → obsolete/usrloc/ul_rpc.h


+ 0 - 0
modules_s/usrloc/urecord.c → obsolete/usrloc/urecord.c


+ 0 - 0
modules_s/usrloc/urecord.h → obsolete/usrloc/urecord.h


+ 0 - 0
modules_s/usrloc/usrloc.c → obsolete/usrloc/usrloc.c


+ 0 - 0
modules_s/usrloc/usrloc.h → obsolete/usrloc/usrloc.h


+ 0 - 0
modules_s/usrloc/utime.c → obsolete/usrloc/utime.c


+ 0 - 0
modules_s/usrloc/utime.h → obsolete/usrloc/utime.h


+ 12 - 0
utils/kamctl/db_berkeley/kamailio/location_attrs

@@ -0,0 +1,12 @@
+METADATA_COLUMNS
+id(int) ruid(str) username(str) domain(str) aname(str) atype(int) avalue(str) last_modified(datetime)
+METADATA_KEY
+1 2 3 
+METADATA_READONLY
+0
+METADATA_LOGFLAGS
+0
+METADATA_DEFAULTS
+NIL|''|''|NULL|''|0|''|'1900-01-01 00:00:01'
+location_attrs|
+location_attrs|1

+ 2 - 2
utils/kamctl/db_sqlite/sca-create.sql

@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('sca_subscriptions','1');
+INSERT INTO version (table_name, table_version) values ('sca_subscriptions','0');
 CREATE TABLE sca_subscriptions (
     id INTEGER PRIMARY KEY NOT NULL,
     subscriber VARCHAR(255) NOT NULL,
@@ -10,7 +10,7 @@ CREATE TABLE sca_subscriptions (
     call_id VARCHAR(255) NOT NULL,
     from_tag VARCHAR(64) NOT NULL,
     to_tag VARCHAR(64) NOT NULL,
-    record_route TEXT DEFAULT NULL,
+    record_route TEXT,
     notify_cseq INTEGER NOT NULL,
     subscribe_cseq INTEGER NOT NULL,
     CONSTRAINT sca_subscriptions_sca_subscriptions_idx UNIQUE (subscriber, call_id, from_tag, to_tag)

+ 15 - 0
utils/kamctl/db_sqlite/usrloc-create.sql

@@ -25,3 +25,18 @@ CREATE TABLE location (
 CREATE INDEX location_account_contact_idx ON location (username, domain, contact);
 CREATE INDEX location_expires_idx ON location (expires);
 
+INSERT INTO version (table_name, table_version) values ('location_attrs','1');
+CREATE TABLE location_attrs (
+    id INTEGER PRIMARY KEY NOT NULL,
+    ruid VARCHAR(64) DEFAULT '' NOT NULL,
+    username VARCHAR(64) DEFAULT '' NOT NULL,
+    domain VARCHAR(64) DEFAULT NULL,
+    aname VARCHAR(64) DEFAULT '' NOT NULL,
+    atype INTEGER DEFAULT 0 NOT NULL,
+    avalue VARCHAR(255) DEFAULT '' NOT NULL,
+    last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL
+);
+
+CREATE INDEX location_attrs_account_record_idx ON location_attrs (username, domain, ruid);
+CREATE INDEX location_attrs_last_modified_idx ON location_attrs (last_modified);
+

+ 2 - 0
utils/kamctl/dbtext/kamailio/location_attrs

@@ -0,0 +1,2 @@
+id(int,auto) ruid(string) username(string) domain(string,null) aname(string) atype(int) avalue(string) last_modified(int) 
+location_attrs:1

+ 2 - 2
utils/kamctl/mysql/sca-create.sql

@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('sca_subscriptions','1');
+INSERT INTO version (table_name, table_version) values ('sca_subscriptions','0');
 CREATE TABLE sca_subscriptions (
     id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
     subscriber VARCHAR(255) NOT NULL,
@@ -10,7 +10,7 @@ CREATE TABLE sca_subscriptions (
     call_id VARCHAR(255) NOT NULL,
     from_tag VARCHAR(64) NOT NULL,
     to_tag VARCHAR(64) NOT NULL,
-    record_route TEXT DEFAULT NULL,
+    record_route TEXT,
     notify_cseq INT(11) NOT NULL,
     subscribe_cseq INT(11) NOT NULL,
     CONSTRAINT sca_subscriptions_idx UNIQUE (subscriber, call_id, from_tag, to_tag)

+ 15 - 0
utils/kamctl/mysql/usrloc-create.sql

@@ -25,3 +25,18 @@ CREATE TABLE location (
 CREATE INDEX account_contact_idx ON location (username, domain, contact);
 CREATE INDEX expires_idx ON location (expires);
 
+INSERT INTO version (table_name, table_version) values ('location_attrs','1');
+CREATE TABLE location_attrs (
+    id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
+    ruid VARCHAR(64) DEFAULT '' NOT NULL,
+    username VARCHAR(64) DEFAULT '' NOT NULL,
+    domain VARCHAR(64) DEFAULT NULL,
+    aname VARCHAR(64) DEFAULT '' NOT NULL,
+    atype INT(11) DEFAULT 0 NOT NULL,
+    avalue VARCHAR(255) DEFAULT '' NOT NULL,
+    last_modified DATETIME DEFAULT '1900-01-01 00:00:01' NOT NULL
+) ENGINE=MyISAM;
+
+CREATE INDEX account_record_idx ON location_attrs (username, domain, ruid);
+CREATE INDEX last_modified_idx ON location_attrs (last_modified);
+

+ 1 - 1
utils/kamctl/oracle/sca-create.sql

@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('sca_subscriptions','1');
+INSERT INTO version (table_name, table_version) values ('sca_subscriptions','0');
 CREATE TABLE sca_subscriptions (
     id NUMBER(10) PRIMARY KEY,
     subscriber VARCHAR2(255),

+ 23 - 0
utils/kamctl/oracle/usrloc-create.sql

@@ -33,3 +33,26 @@ BEGIN map2users('location'); END;
 CREATE INDEX location_account_contact_idx  ON location (username, domain, contact);
 CREATE INDEX location_expires_idx  ON location (expires);
 
+INSERT INTO version (table_name, table_version) values ('location_attrs','1');
+CREATE TABLE location_attrs (
+    id NUMBER(10) PRIMARY KEY,
+    ruid VARCHAR2(64) DEFAULT '',
+    username VARCHAR2(64) DEFAULT '',
+    domain VARCHAR2(64) DEFAULT NULL,
+    aname VARCHAR2(64) DEFAULT '',
+    atype NUMBER(10) DEFAULT 0 NOT NULL,
+    avalue VARCHAR2(255) DEFAULT '',
+    last_modified DATE DEFAULT to_date('1900-01-01 00:00:01','yyyy-mm-dd hh24:mi:ss')
+);
+
+CREATE OR REPLACE TRIGGER location_attrs_tr
+before insert on location_attrs FOR EACH ROW
+BEGIN
+  auto_id(:NEW.id);
+END location_attrs_tr;
+/
+BEGIN map2users('location_attrs'); END;
+/
+CREATE INDEX ORA_account_record_idx  ON location_attrs (username, domain, ruid);
+CREATE INDEX ORA_last_modified_idx  ON location_attrs (last_modified);
+

+ 2 - 2
utils/kamctl/postgres/sca-create.sql

@@ -1,4 +1,4 @@
-INSERT INTO version (table_name, table_version) values ('sca_subscriptions','1');
+INSERT INTO version (table_name, table_version) values ('sca_subscriptions','0');
 CREATE TABLE sca_subscriptions (
     id SERIAL PRIMARY KEY NOT NULL,
     subscriber VARCHAR(255) NOT NULL,
@@ -10,7 +10,7 @@ CREATE TABLE sca_subscriptions (
     call_id VARCHAR(255) NOT NULL,
     from_tag VARCHAR(64) NOT NULL,
     to_tag VARCHAR(64) NOT NULL,
-    record_route TEXT DEFAULT NULL,
+    record_route TEXT,
     notify_cseq INTEGER NOT NULL,
     subscribe_cseq INTEGER NOT NULL,
     CONSTRAINT sca_subscriptions_sca_subscriptions_idx UNIQUE (subscriber, call_id, from_tag, to_tag)

+ 15 - 0
utils/kamctl/postgres/usrloc-create.sql

@@ -25,3 +25,18 @@ CREATE TABLE location (
 CREATE INDEX location_account_contact_idx ON location (username, domain, contact);
 CREATE INDEX location_expires_idx ON location (expires);
 
+INSERT INTO version (table_name, table_version) values ('location_attrs','1');
+CREATE TABLE location_attrs (
+    id SERIAL PRIMARY KEY NOT NULL,
+    ruid VARCHAR(64) DEFAULT '' NOT NULL,
+    username VARCHAR(64) DEFAULT '' NOT NULL,
+    domain VARCHAR(64) DEFAULT NULL,
+    aname VARCHAR(64) DEFAULT '' NOT NULL,
+    atype INTEGER DEFAULT 0 NOT NULL,
+    avalue VARCHAR(255) DEFAULT '' NOT NULL,
+    last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL
+);
+
+CREATE INDEX location_attrs_account_record_idx ON location_attrs (username, domain, ruid);
+CREATE INDEX location_attrs_last_modified_idx ON location_attrs (last_modified);
+

+ 41 - 11
utils/kamctl/xhttp_pi/pi_framework.xml

@@ -212,17 +212,6 @@
 		<column><field>attrs</field><type>DB1_STR</type></column>
 		<column><field>description</field><type>DB1_STR</type></column>
 	</db_table>
-	<!-- Declaration of domainpolicy table-->
-	<db_table id="domainpolicy">
-		<table_name>domainpolicy</table_name>
-		<db_url_id>mysql</db_url_id>
-		<column><field>id</field><type>DB1_INT</type></column>
-		<column><field>rule</field><type>DB1_STR</type></column>
-		<column><field>type</field><type>DB1_STR</type></column>
-		<column><field>att</field><type>DB1_STR</type></column>
-		<column><field>val</field><type>DB1_STR</type></column>
-		<column><field>description</field><type>DB1_STR</type></column>
-	</db_table>
 	<!-- Declaration of domain table-->
 	<db_table id="domain">
 		<table_name>domain</table_name>
@@ -243,6 +232,17 @@
 		<column><field>value</field><type>DB1_STR</type></column>
 		<column><field>last_modified</field><type>DB1_DATETIME</type></column>
 	</db_table>
+	<!-- Declaration of domainpolicy table-->
+	<db_table id="domainpolicy">
+		<table_name>domainpolicy</table_name>
+		<db_url_id>mysql</db_url_id>
+		<column><field>id</field><type>DB1_INT</type></column>
+		<column><field>rule</field><type>DB1_STR</type></column>
+		<column><field>type</field><type>DB1_STR</type></column>
+		<column><field>att</field><type>DB1_STR</type></column>
+		<column><field>val</field><type>DB1_STR</type></column>
+		<column><field>description</field><type>DB1_STR</type></column>
+	</db_table>
 	<!-- Declaration of dr_gateways table-->
 	<db_table id="dr_gateways">
 		<table_name>dr_gateways</table_name>
@@ -755,6 +755,19 @@
 		<column><field>instance</field><type>DB1_STR</type></column>
 		<column><field>reg_id</field><type>DB1_INT</type></column>
 	</db_table>
+	<!-- Declaration of location_attrs table-->
+	<db_table id="location_attrs">
+		<table_name>location_attrs</table_name>
+		<db_url_id>mysql</db_url_id>
+		<column><field>id</field><type>DB1_INT</type></column>
+		<column><field>ruid</field><type>DB1_STR</type></column>
+		<column><field>username</field><type>DB1_STR</type></column>
+		<column><field>domain</field><type>DB1_STR</type></column>
+		<column><field>aname</field><type>DB1_STR</type></column>
+		<column><field>atype</field><type>DB1_INT</type></column>
+		<column><field>avalue</field><type>DB1_STR</type></column>
+		<column><field>last_modified</field><type>DB1_DATETIME</type></column>
+	</db_table>
 	<!-- Declare all mods
 		Each mod must have:
 		- a 'mod_name'
@@ -1739,4 +1752,21 @@
 			</query_cols>
 		</cmd>
 	</mod>
+	<!-- location_attrs provisionning -->
+	<mod><mod_name>location_attrs</mod_name>
+		<cmd><cmd_name>show</cmd_name>
+			<db_table_id>location_attrs</db_table_id>
+			<cmd_type>DB1_QUERY</cmd_type>
+			<query_cols>
+				<col><field>id</field></col>
+				<col><field>ruid</field></col>
+				<col><field>username</field></col>
+				<col><field>domain</field></col>
+				<col><field>aname</field></col>
+				<col><field>atype</field></col>
+				<col><field>avalue</field></col>
+				<col><field>last_modified</field></col>
+			</query_cols>
+		</cmd>
+	</mod>
 </framework>

+ 17 - 0
utils/kamctl/xhttp_pi/usrloc-mod

@@ -26,3 +26,20 @@
 			</query_cols>
 		</cmd>
 	</mod>
+	<!-- location_attrs provisionning -->
+	<mod><mod_name>location_attrs</mod_name>
+		<cmd><cmd_name>show</cmd_name>
+			<db_table_id>location_attrs</db_table_id>
+			<cmd_type>DB1_QUERY</cmd_type>
+			<query_cols>
+				<col><field>id</field></col>
+				<col><field>ruid</field></col>
+				<col><field>username</field></col>
+				<col><field>domain</field></col>
+				<col><field>aname</field></col>
+				<col><field>atype</field></col>
+				<col><field>avalue</field></col>
+				<col><field>last_modified</field></col>
+			</query_cols>
+		</cmd>
+	</mod>

+ 13 - 0
utils/kamctl/xhttp_pi/usrloc-table

@@ -22,3 +22,16 @@
 		<column><field>instance</field><type>DB1_STR</type></column>
 		<column><field>reg_id</field><type>DB1_INT</type></column>
 	</db_table>
+	<!-- Declaration of location_attrs table-->
+	<db_table id="location_attrs">
+		<table_name>location_attrs</table_name>
+		<db_url_id>mysql</db_url_id>
+		<column><field>id</field><type>DB1_INT</type></column>
+		<column><field>ruid</field><type>DB1_STR</type></column>
+		<column><field>username</field><type>DB1_STR</type></column>
+		<column><field>domain</field><type>DB1_STR</type></column>
+		<column><field>aname</field><type>DB1_STR</type></column>
+		<column><field>atype</field><type>DB1_INT</type></column>
+		<column><field>avalue</field><type>DB1_STR</type></column>
+		<column><field>last_modified</field><type>DB1_DATETIME</type></column>
+	</db_table>

+ 38 - 1
xavp.c

@@ -183,6 +183,38 @@ sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list)
 	return avp;
 }
 
+sr_xavp_t *xavp_add_xavp_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list)
+{
+	sr_xavp_t *ravp=0;
+	sr_xavp_t *cavp=0;
+	sr_xval_t rval;
+
+	cavp = xavp_new_value(name, val);
+	if (cavp==NULL)
+		return NULL;
+
+	memset(&rval, 0, sizeof(sr_xval_t));
+	rval.type = SR_XTYPE_XAVP;
+	rval.v.xavp = cavp;
+
+	ravp = xavp_new_value(rname, &rval);
+	if (ravp==NULL) {
+		xavp_destroy_list(&cavp);
+		return NULL;
+	}
+
+	/* Prepend new value to the list */
+	if(list) {
+		ravp->next = *list;
+		*list = ravp;
+	} else {
+		ravp->next = *_xavp_list_crt;
+		*_xavp_list_crt = ravp;
+	}
+
+	return ravp;
+}
+
 sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list)
 {
 	sr_xavp_t *avp;
@@ -517,7 +549,9 @@ sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
 	sr_xavp_t *pavp = NULL;
 
 	if(xold == NULL)
+	{
 		return NULL;
+	}
 	if(xold->val.type==SR_XTYPE_DATA)
 	{
 		LM_INFO("xavp value type is 'data' - ignoring in clone\n");
@@ -531,18 +565,21 @@ sr_xavp_t *xavp_clone_level_nodata(sr_xavp_t *xold)
 	}
 
 	if(xold->val.type!=SR_XTYPE_XAVP)
+	{
 		return xnew;
+	}
 
 	xnew->val.v.xavp = NULL;
 	oavp = xold->val.v.xavp;
 
 	while(oavp)
 	{
-		if(xold->val.type!=SR_XTYPE_DATA && xold->val.type!=SR_XTYPE_XAVP)
+		if(oavp->val.type!=SR_XTYPE_DATA && oavp->val.type!=SR_XTYPE_XAVP)
 		{
 			navp =  xavp_new_value(&oavp->name, &oavp->val);
 			if(navp==NULL)
 			{
+				LM_ERR("cannot create cloned embedded xavp\n");
 				if(xnew->val.v.xavp == NULL)
 				{
 					shm_free(xnew);

+ 1 - 0
xavp.h

@@ -81,6 +81,7 @@ void avpx_free(sr_xavp_t *xa);
 int xavp_add(sr_xavp_t *xavp, sr_xavp_t **list);
 int xavp_add_last(sr_xavp_t *xavp, sr_xavp_t **list);
 sr_xavp_t *xavp_add_value(str *name, sr_xval_t *val, sr_xavp_t **list);
+sr_xavp_t *xavp_add_xavp_value(str *rname, str *name, sr_xval_t *val, sr_xavp_t **list);
 sr_xavp_t *xavp_set_value(str *name, int idx, sr_xval_t *val, sr_xavp_t **list);
 sr_xavp_t *xavp_get(str *name, sr_xavp_t *start);
 sr_xavp_t *xavp_get_by_index(str *name, int idx, sr_xavp_t **start);