Преглед на файлове

modules/usrloc_pcscf: first commit of usrloc_pcscf module

Jason Penton преди 12 години
родител
ревизия
eda0f25661

+ 19 - 0
modules/usrloc_pcscf/Makefile

@@ -0,0 +1,19 @@
+# $Id$
+#
+# Usrloc_pcscf module Makefile
+#
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=usrloc_pcscf.so
+
+DEFS+=-DOPENSER_MOD_INTERFACE
+
+SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/kmi/kmi
+SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
+SER_LIBS+=$(SERLIBPATH)/kcore/kcore
+#SER_LIBS+=$(SERLIBPATH)/srutils/srutils
+include ../../Makefile.modules

+ 44 - 0
modules/usrloc_pcscf/blurb

@@ -0,0 +1,44 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */

+ 346 - 0
modules/usrloc_pcscf/dlist.c

@@ -0,0 +1,346 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "dlist.h"
+#include <stdlib.h>	       /* abort */
+#include <string.h>            /* strlen, memcmp */
+#include <stdio.h>             /* printf */
+#include "../../ut.h"
+#include "../../lib/srdb1/db_ut.h"
+#include "../../mem/shm_mem.h"
+#include "../../dprint.h"
+#include "../../ip_addr.h"
+#include "../../socket_info.h"
+#include "udomain.h"           /* new_udomain, free_udomain */
+#include "usrloc.h"
+#include "utime.h"
+#include "ul_mod.h"
+#include "pcontact.h"
+
+dlist_t* root = 0;
+
+static inline int find_dlist(str* _n, dlist_t** _d)
+{
+	dlist_t* ptr;
+
+	ptr = root;
+	while(ptr) {
+		if ((_n->len == ptr->name.len) &&
+		    !memcmp(_n->s, ptr->name.s, _n->len)) {
+			*_d = ptr;
+			return 0;
+		}
+		
+		ptr = ptr->next;
+	}
+	
+	return 1;
+}
+
+static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
+							unsigned int part_idx, unsigned int part_max)
+{
+	dlist_t *p;
+	pcontact_t *c;
+	void *cp;
+	int shortage;
+	int needed;
+	int i = 0;
+	cp = buf;
+	shortage = 0;
+	unsigned int received_len = 0;
+	char received_s[60]; // IPv6-Address (39) + "sip:" (4) + ":" (1) + Port (5); 60 should be plenty.
+	/* Reserve space for terminating 0000 */
+	len -= sizeof(int);
+
+	for (p = root; p != NULL; p = p->next) {
+
+		for(i=0; i<p->d->size; i++) {
+
+			if ( (i % part_max) != part_idx )
+				continue;
+
+			lock_ulslot(p->d, i);
+			if(p->d->table[i].n<=0)
+			{
+				unlock_ulslot(p->d, i);
+				continue;
+			}
+			for (c = p->d->table[i].first; c != NULL; c = c->next) {
+					if (c->received_host.s) {
+						received_len = snprintf(received_s, sizeof(received_s), "sip:%.*s:%x", c->received_host.len,
+							c->received_host.s, c->received_port) - 1; 
+
+						needed = (int)(sizeof(received_len)
+								+ received_len + sizeof(c->sock)
+								+ sizeof(unsigned int) + sizeof(c->path.len)
+								+ c->path.len);
+						if (len >= needed) {
+							cp = (char*)cp + received_len;
+							cp = (char*)cp + sizeof(received_len);
+
+							memcpy(cp, received_s, received_len);
+							cp = (char*)cp + received_len;
+
+							memcpy(cp, &c->sock, sizeof(c->sock));
+							cp = (char*)cp + sizeof(c->sock);
+
+							memset(cp, 0, sizeof(unsigned int));
+							cp = (char*)cp + sizeof(unsigned int);
+
+							memcpy(cp, &c->path.len, sizeof(c->path.len));
+							cp = (char*)cp + sizeof(c->path.len);
+							memcpy(cp, c->path.s, c->path.len);
+							cp = (char*)cp + c->path.len;
+							len -= needed;
+						} else {
+							shortage += needed;
+						}
+					}
+			}
+			unlock_ulslot(p->d, i);
+		}
+	}
+	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
+	if (len >= 0)
+		memset(cp, 0, sizeof(int));
+
+	/* Shouldn't happen */
+	if (shortage > 0 && len > shortage) {
+		abort();
+	}
+
+	shortage -= len;
+
+	return shortage > 0 ? shortage : 0;
+}
+
+int get_all_ucontacts(void *buf, int len, unsigned int flags,
+								unsigned int part_idx, unsigned int part_max)
+{
+	return get_all_mem_ucontacts( buf, len, flags, part_idx, part_max);
+}
+
+static inline int new_dlist(str* _n, dlist_t** _d)
+{
+	dlist_t* ptr;
+
+	/* Domains are created before ser forks,
+	 * so we can create them using pkg_malloc
+	 */
+	ptr = (dlist_t*)shm_malloc(sizeof(dlist_t));
+	if (ptr == 0) {
+		LM_ERR("no more share memory\n");
+		return -1;
+	}
+	memset(ptr, 0, sizeof(dlist_t));
+
+	/* copy domain name as null terminated string */
+	ptr->name.s = (char*)shm_malloc(_n->len+1);
+	if (ptr->name.s == 0) {
+		LM_ERR("no more memory left\n");
+		shm_free(ptr);
+		return -2;
+	}
+
+	memcpy(ptr->name.s, _n->s, _n->len);
+	ptr->name.len = _n->len;
+	ptr->name.s[ptr->name.len] = 0;
+
+	if (new_udomain(&(ptr->name), ul_hash_size, &(ptr->d)) < 0) {
+		LM_ERR("creating domain structure failed\n");
+		shm_free(ptr->name.s);
+		shm_free(ptr);
+		return -3;
+	}
+
+	*_d = ptr;
+	return 0;
+}
+
+int get_udomain(const char* _n, udomain_t** _d)
+{
+	dlist_t* d;
+	str s;
+
+	s.s = (char*)_n;
+	s.len = strlen(_n);
+
+	if (find_dlist(&s, &d) == 0) {
+		*_d = d->d;
+		return 0;
+	}
+	*_d = NULL;
+	return -1;
+}
+
+int register_udomain(const char* _n, udomain_t** _d)
+{
+	dlist_t* d;
+	str s;
+
+	s.s = (char*)_n;
+	s.len = strlen(_n);
+
+	if (find_dlist(&s, &d) == 0) {
+		*_d = d->d;
+		return 0;
+	}
+	
+	if (new_dlist(&s, &d) < 0) {
+		LM_ERR("failed to create new domain\n");
+		return -1;
+	}
+
+	d->next = root;
+	root = d;
+	
+	*_d = d->d;
+	return 0;
+}
+
+void free_all_udomains(void)
+{
+	dlist_t* ptr;
+
+	while(root) {
+		ptr = root;
+		root = root->next;
+
+		free_udomain(ptr->d);
+		shm_free(ptr->name.s);
+		shm_free(ptr);
+	}
+}
+
+void print_all_udomains(FILE* _f)
+{
+	dlist_t* ptr;
+	
+	ptr = root;
+
+	fprintf(_f, "===Domain list===\n");
+	while(ptr) {
+		print_udomain(_f, ptr->d);
+		ptr = ptr->next;
+	}
+	fprintf(_f, "===/Domain list===\n");
+}
+
+int synchronize_all_udomains(void)
+{
+	int res = 0;
+	dlist_t* ptr;
+
+	get_act_time(); /* Get and save actual time */
+
+	for( ptr=root ; ptr ; ptr=ptr->next)
+		mem_timer_udomain(ptr->d);
+
+	return res;
+}
+
+int find_domain(str* _d, udomain_t** _p)
+{
+	dlist_t* d;
+
+	if (find_dlist(_d, &d) == 0) {
+	        *_p = d->d;
+		return 0;
+	}
+
+	return 1;
+}
+
+unsigned long get_number_of_contacts(void)
+{
+        long numberOfUsers = 0;
+
+        dlist_t* current_dlist;
+
+        current_dlist = root;
+
+        while (current_dlist)
+        {
+                numberOfUsers += get_stat_val(current_dlist->d->contacts);
+                current_dlist  = current_dlist->next;
+        }
+
+        return numberOfUsers;
+}
+
+unsigned long get_number_of_expired(void)
+{
+        long numberOfExpired = 0;
+
+        dlist_t* current_dlist;
+
+        current_dlist = root;
+
+        while (current_dlist)
+        {
+                numberOfExpired += get_stat_val(current_dlist->d->expired);
+                current_dlist  = current_dlist->next;
+        }
+
+        return numberOfExpired;
+}
+
+unsigned long get_number_of_impu(void)
+{
+        long numberOfExpired = 0;
+
+        dlist_t* current_dlist;
+
+        current_dlist = root;
+
+        while (current_dlist)
+        {
+                numberOfExpired += get_stat_val(current_dlist->d->expired);
+                current_dlist  = current_dlist->next;
+        }
+
+        return numberOfExpired;
+}

+ 82 - 0
modules/usrloc_pcscf/dlist.h

@@ -0,0 +1,82 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DLIST_H
+#define DLIST_H
+
+#include <stdio.h>
+#include "../../str.h"
+#include "usrloc.h"
+#include "udomain.h"
+
+/*!
+ * List of all domains registered with usrloc
+ */
+typedef struct dlist {
+	str name;            /*!< Name of the domain (null terminated) */
+	udomain_t* d;        /*!< Payload */
+	struct dlist* next;  /*!< Next element in the list */
+} dlist_t;
+
+/*! \brief Global list of all registered domains */
+extern dlist_t* root;
+
+int register_udomain(const char* _n, udomain_t** _d);
+void free_all_udomains(void);
+void print_all_udomains(FILE* _f);
+int synchronize_all_udomains(void);
+int get_all_ucontacts(void *buf, int len, unsigned int flags,
+		unsigned int part_idx, unsigned int part_max);
+int get_udomain(const char* _n, udomain_t** _d);
+unsigned long get_number_of_users(void);
+int find_domain(str* _d, udomain_t** _p);
+
+/* stat retrieval functions */
+unsigned long get_number_of_contacts(void);
+unsigned long get_number_of_expired(void);
+unsigned long get_number_of_impu(void);
+
+
+#endif

+ 4 - 0
modules/usrloc_pcscf/doc/Makefile

@@ -0,0 +1,4 @@
+docs = usrloc_pcscf.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module

+ 72 - 0
modules/usrloc_pcscf/doc/stuff

@@ -0,0 +1,72 @@
+/** Full Diameter Peer configuration. */
+typedef struct {
+	str fqdn;					/**< own FQDN */
+	str realm;					/**< own Realm */
+	str identity;				/**< own diameter URI */
+	int vendor_id;				/**< own vendorid */
+	str product_name;			/**< own product name */
+	int accept_unknown_peers;	/**< if to accept connections from peers that are not configured initially */
+	int drop_unknown_peers;		/**< if to drop the peers that are not initially configured on disconnected;
+									 usually, you want to do this, unless you want your list of peers to
+									 grow and you want to try and connect back to everybody that connected 
+									 to you before */
+	int tc;						/**< Tc timer duration (30 seconds should be) */
+	int workers;				/**< Number of worker-processes to fork */
+	int queue_length;			/**< Length of the message queue; when it is filled, the server part will
+									 block until workers will finish work on at least one item in the queue */
+	int connect_timeout;		/**< Connect timeout for outbound connections */
+	int transaction_timeout;	/**< Transaction timeout duration */
+	
+	int sessions_hash_size;		/**< Size of the sessions hash table */									 
+	int default_auth_session_timeout; /** The default Authorization Session Timeout to use if none other indicated */ 
+	int max_auth_session_timeout;	  /** The max Authorization Session Timeout limit */ 
+	
+	peer_config *peers;			/**< list of peers */
+	int peers_cnt;				/**< size of the list of peers */
+	
+	acceptor_config *acceptors;	/**< list of acceptors */
+	int acceptors_cnt;			/**< size of the list of acceptors */
+	
+	app_config *applications;	/**< list of supporter applications */
+	int applications_cnt;		/**< size of list of supported applications*/
+
+	int *supported_vendors;		/**< list of supported vendor ids */
+	int supported_vendors_cnt;	/**< size of list of supported vendor ids */
+	
+	routing_table *r_table;		/**< realm routing table */
+} dp_config;
+
+/**
+ * Exported functions. This is the API available for use from other SER modules.
+ * If you require more, please add them here.
+ * <p>
+ * - load_cdp() - find and load the CDiameterPeer function bindings
+ * <p>
+ * - AAACreateRequest() - create a diameter request #AAAMessage
+ * - AAACreateResponse() - create a diameter response #AAAMessage
+ * - AAAFreeMessage() - free up the memory used in a Diameter message
+ * <p>
+ * - AAASendMessage() - asynchronously send a message
+ * - AAASendMessageToPeer() - asynchronously send a message to a forced peer
+ * - AAASendRecvMessage() - synchronously send a message and get the response
+ * - AAASendRecvMessageToPeer() - synchronously send a message and get the response to a forced peer 
+ * <p>
+ * - AAACreateSession() - create a diameter #AAASessionId
+ * - AAADropSession() - drop a diameter #AAASessionId
+ * <p>
+ * - AAACreateTransaction() - create a diameter #AAATransaction
+ * - AAADropTransaction() - drop a diameter #AAATransaction
+ * <p>
+ * - AAACreateAVP() - create an #AAA_AVP
+ * - AAAAddAVPToMessage() - add an #AAA_AVP to a #AAAMessage
+ * - AAAFindMatchingAVP() - find an #AAA_AVP inside a #AAAMessage
+ * - AAAGetNextAVP() - get the next #AAA_AVP from the #AAAMessage
+ * - AAAFreeAVP() - free the memory taken by the #AAA_AVP
+ * - AAAGroupAVPS() - group a #AAA_AVP_LIST of #AAA_AVP into a grouped #AAA_AVP 
+ * - AAAUngroupAVPS() - ungroup a grouped #AAA_AVP into a #AAA_AVP_LIST of #AAA_AVP
+ * - AAAFindMatchingAVPList() - find an #AAA_AVP inside a #AAA_AVP_LIST
+ * - AAAFreeAVPList() - free the memory taken by the all members of #AAA_AVP_LIST
+ * <p>
+ * - AAAAddRequestHandler() - add a #AAARequestHandler_f callback to request being received
+ * - AAAAddResponseHandler() - add a #AAAResponseHandler_f callback to responses being received
+ */

+ 61 - 0
modules/usrloc_pcscf/doc/usrloc_pcscf.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+]>
+<book>
+  <bookinfo>
+    <title>cdp Module</title>
+
+    <productname class="trade">&kamailioname;</productname>
+
+    <authorgroup>
+      <author>
+        <firstname>Jason Penton</firstname>
+
+        <surname/>
+
+        <affiliation>
+          <orgname>Smile Communications</orgname>
+        </affiliation>
+
+        <address>
+			<email>[email protected]</email>
+		</address>
+      </author>
+
+      <editor>
+        <firstname>Richard</firstname>
+
+        <surname>Good</surname>
+        
+	<affiliation>
+          <orgname>Smile Communications</orgname>
+        </affiliation>
+
+        <address>
+			<email>[email protected]</email>
+		</address>
+      </editor>
+    </authorgroup>
+
+    <copyright>
+      <year>2012</year>
+
+      <holder>Smile Communications</holder>
+    </copyright>
+  </bookinfo>
+
+  <toc/>
+
+  <xi:include href="usrloc_pcscf_admin.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+  <xi:include href="usrloc_pcscf_devel.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+  <xi:include href="usrloc_pcscf_faq.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude"/>
+</book>

+ 153 - 0
modules/usrloc_pcscf/doc/usrloc_pcscf_admin.xml

@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+]>
+<!-- Module User's Guide -->
+<chapter>
+  <title>&adminguide;</title>
+
+  <section>
+    <title>Overview</title>
+
+    <para>This module serves as a storage engine for PCSCF contacts, much like
+    the standard Kamailio module, usrloc, is a storage engine for standard SIP
+    contacts. The concept of a contact in IMS, PCSCF specifically, is very
+    different to that of std. SIP and as a result we have built this new
+    module. Alot of the design has been borrowed from the std. usrloc module.
+    For example. An IMS contact, in PCSCF, needs things like:</para>
+
+    <para><itemizedlist>
+        <listitem>
+          <para>Diameter Rx session for signalling bearer status. i.e. this is
+          effectively QoS from the network to make sure the signalling link
+          can be 'trusted'</para>
+        </listitem>
+
+        <listitem>
+          <para>IPSEC Security Assocation for secure signalling between UE and
+          PCSCF (first point of contact)</para>
+        </listitem>
+
+        <listitem>
+          <para>IMPU, each contact can have a number of associated public
+          identities (IMPU).</para>
+        </listitem>
+      </itemizedlist></para>
+  </section>
+
+  <section>
+    <title>Dependencies</title>
+
+    <section>
+      <title>&kamailio; Modules</title>
+
+      <para>The following modules must be loaded before this module:
+      <itemizedlist>
+          <listitem>
+            <para><emphasis>None</emphasis>.</para>
+          </listitem>
+        </itemizedlist></para>
+    </section>
+
+    <section>
+      <title>External Libraries or Applications</title>
+
+      <para>The following libraries or applications must be installed before
+      running &kamailio; with this module loaded: <itemizedlist>
+          <listitem>
+            <para><emphasis>None</emphasis>.</para>
+          </listitem>
+        </itemizedlist></para>
+    </section>
+  </section>
+
+  <section>
+    <title>Parameters</title>
+
+    <section>
+      <title>hash_size (int)</title>
+
+      <para>The number of entries of the hash table used by to store the
+      contact records is 2^hash_size. For hash_size=4, the number of entries
+      of the hash table is 16. </para>
+
+      <para><emphasis> Default value is 9. </emphasis></para>
+
+      <example>
+        <title>Set <varname>hash_size</varname> parameter</title>
+
+        <programlisting format="linespecific">...
+modparam("usrloc_pcscf", "hash_size", 10)
+...
+</programlisting>
+      </example>
+    </section>
+
+    <section>
+      <title>timer_interval (int)</title>
+
+      <para>Number of seconds between two timer runs. The module uses timer to
+      delete expired contacts. </para>
+
+      <para><emphasis> Default value is 60. </emphasis></para>
+
+      <example>
+        <title>Set timer_interval parameter</title>
+
+        <programlisting format="linespecific">...
+modparam("usrloc_pcscf", "timer_interval", 30)
+...
+</programlisting>
+      </example>
+    </section>
+  </section>
+
+  <section>
+    <title>Functions</title>
+
+    <section>
+      <para>There are no exported functions that could be used in scripts.
+      </para>
+    </section>
+  </section>
+
+  <section>
+    <title>RPC Commands</title>
+
+    <para>exported RPC commands.</para>
+
+    <section>
+      <title>ulpcscf.status</title>
+
+      <para>Status of pcscf_usrloc, AORs, max slots, etc.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>Statistics</title>
+
+    <para>Exported statistics are listed in the next sections. </para>
+
+    <section>
+      <title>registered contacts</title>
+
+      <para>Number of AOR contacts in registered state - cannot be
+      reset.</para>
+    </section>
+
+    <section>
+      <title>impus</title>
+
+      <para>Number of IMPUs - cannot be reset.</para>
+    </section>
+
+    <section>
+      <title>expired contacts</title>
+
+      <para>Number of expired contacts - can be reset.</para>
+    </section>
+  </section>
+</chapter>

+ 682 - 0
modules/usrloc_pcscf/doc/usrloc_pcscf_devel.xml

@@ -0,0 +1,682 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+]>
+<!-- Module Developer's Guide -->
+<chapter>
+  <title>&develguide;</title>
+
+  <section>
+    <title>Available Functions</title>
+
+    <section>
+      <title><function moreinfo="none">load_cdp(struct cdp_binds
+      *cdpb)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>struct cdp_binds *cdpb</emphasis> - structure
+          holding function pointers</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAACreateRequest(AAAApplicationId
+      app_id, AAACommandCode command_code, AAAMsgFlag flags, AAASession
+      *session)</function></title>
+
+      <para>Create a Diameter request</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAApplicationId app_id</emphasis> - structure
+          holding function pointers</para>
+        </listitem>
+
+        <listitem>
+          <para>AAACommandCode command_code - command code for the
+          message</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAMsgFlag flags - flags to be set</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASession *session - session id to be set</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAACreateResponse(AAAMessage
+      *request)</function></title>
+
+      <para>Create a Diameter response to a give request</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *request</emphasis> - request that this
+          response is for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode AAAFreeMessage(AAAMessage
+      **msg)</function></title>
+
+      <para>Free up memory used by Diameter message</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage **msg</emphasis> - pointer to the pointer
+          containing the message</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode AAASendMessage(AAAMessage
+      *message, AAATransactionCallback_f *callback_f, void
+      *callback_param)</function></title>
+
+      <para>Send Diameter message asynchronously</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *message</emphasis> - request message to
+          be sent</para>
+        </listitem>
+
+        <listitem>
+          <para>AAATransactionCallback_f *callback_f - When the response is
+          received, the callback_f(callback_param,...) is called</para>
+        </listitem>
+
+        <listitem>
+          <para>void *callback_param - generic param for callback</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode
+      AAASendMessageToPeer(AAAMessage *message, str *peer_id,
+      AAATransactionCallback_f *callback_f, void
+      *callback_param)</function></title>
+
+      <para>Send Diameter message to specific peer asynchronously</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAMessage *message - request message to send</para>
+        </listitem>
+
+        <listitem>
+          <para>str *peer_id - FQDN of peer to send to</para>
+        </listitem>
+
+        <listitem>
+          <para>AAATransactionCallback_f *callback_f - When the response is
+          received, the callback_f(callback_param,...) is called</para>
+        </listitem>
+
+        <listitem>
+          <para>void *callback_param - generic param for callback</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAMessage*
+      AAASendRecvMessage(AAAMessage *message)</function></title>
+
+      <para>Send Diameter message synchronously. This blocks until a response
+      is received or a transactional time-out happens.</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAMessage *message - request message to be sent</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAMessage*
+      AAASendRecvMessageToPeer(AAAMessage *message, str
+      *peer_id)</function></title>
+
+      <para>Send Diameter message to specific peer synchronously. This blocks
+      until a response is received or a transactional time-out happens.</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *message</emphasis> - request message to
+          send</para>
+        </listitem>
+
+        <listitem>
+          <para>str *peer_id - FQDN of peer to send to.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAACreateSession(void
+      *generic_data)</function></title>
+
+      <para>Create a generic Diameter session</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>void *generic_data - data to be save to session, useful for
+          attaching app specific data to the session</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAAMakeSession(int
+      app_id,int type,str session_id)</function></title>
+
+      <para>Create a Diameter session using already known params</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>int app_id - app id to use</para>
+        </listitem>
+
+        <listitem>
+          <para>int type - type of session</para>
+        </listitem>
+
+        <listitem>
+          <para>str session_id - session ID</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAAGetSession(str
+      id)</function></title>
+
+      <para>Retrieve a Diameter session. Returns with a lock on
+      AAASession-&gt;hash - Unlock when done working with result</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>str id - Diameter session ID to search for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAADropSession(AAASession
+      *s)</function></title>
+
+      <para>Drop a Diameter session - deallocating all memory</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAASession *s - session to drop</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASessionLock(unsigned int
+      hash)</function></title>
+
+      <para>Lock a Diameter session (hash table row)</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>unsigned int hash - hash to lock</emphasis></para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASessionUnLock(unsigned int
+      hash)</function></title>
+
+      <para>Unlock a Diameter session (hash table row)</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>unsigned int hash - hash to unlock</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession*
+      AAACreateClientAuthSession(int is_statefull,AAASessionCallback_f
+      *cb,void *generic_data)</function></title>
+
+      <para>Creates an Authorisation session for the Client. It generate a new
+      ID and adds to the list of CDP sessions. Returns with a lock on
+      AAASession-&gt;hash</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>int is_statefull - is session stateful or
+          not</emphasis></para>
+        </listitem>
+
+        <listitem>
+          <para>AAASessionCallback_f *cb - callback function on session state
+          change</para>
+        </listitem>
+
+        <listitem>
+          <para>void *generic_data - generic callback data</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession*
+      AAACreateServerAuthSession(AAMessage *msg,int
+      is_statefull,AAASessionCallback_f *cb,void
+      *generic_data)</function></title>
+
+      <para>Create authorisation session for the Server. Generates a new ID
+      and add to CDP list of sessions. Returns with a lock on
+      AAASession-&gt;hash.</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAMessage *msg - request message from which to create server
+          session</para>
+        </listitem>
+
+        <listitem>
+          <para>int is_statefull - is session stateful or not</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASessionCallback_f *cb - callback function on session state
+          change</para>
+        </listitem>
+
+        <listitem>
+          <para>void *generic_data - generic callback data</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAAGetAuthSession(str
+      id)</function></title>
+
+      <para>Look for an authorisation session. Returns with lock on
+      AAASession-&gt;hash</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>str id - ID of Auth session to search for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAADropAuthSession(AAASession
+      *s)</function></title>
+
+      <para>Deallocates the memory taken by a Authorisation session</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAASession *s</emphasis> - Session to drop and
+          deallocate memory for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAATerminateAuthSession(AAASession
+      *s)</function></title>
+
+      <para>Sends a service terminated event to the session</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAASession *s</emphasis> - authhorisation session to
+          terminate</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAATransaction*
+      AAACreateTransaction(AAAApplicationId app_id,AAACommandCode
+      cmd_code)</function></title>
+
+      <para>Create a AAATransaction for the given request</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAApplicationId app_id - ID of the request's
+          application</para>
+        </listitem>
+
+        <listitem>
+          <para>AAACommandCode cmd_code - request's code</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">int AAADropTransaction(AAATransaction
+      *trans)</function></title>
+
+      <para>Deallocates the memory taken by AAA transaction</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAATransaction *trans - transaction to free</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP* AAACreateAVP(AAA_AVPCode code,
+      AAA_AVPFlag flags, AAAVendorId vendorId, char *data, size_t length,
+      AVPDataStatus data_status)</function></title>
+
+      <para>Create new AVP and return pointer to it</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAA_AVPCode code</emphasis> - code for new
+          AVP</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVPFlag flags - flags to set</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAVendorId vendorId - vendor ID for AVP</para>
+        </listitem>
+
+        <listitem>
+          <para>char *data - generic payload data</para>
+        </listitem>
+
+        <listitem>
+          <para>size_t length - length of payload data</para>
+        </listitem>
+
+        <listitem>
+          <para>AVPDataStatus data_status - what to do with the payload,
+          duplicate, free with message, etc</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode
+      AAAAddAVPToMessage(AAAMessage *msg, AAA_AVP *avp, AAA_AVP
+      *position)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *msg</emphasis> - the message to add
+          to</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *avp - the AVP to add</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *position - AVP to add after. if NULL, we add at
+          beginning</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP* AAAFindMatchingAVP(AAAMessage
+      *msg, AAA_AVP *startAvp, AAA_AVPCode avpCode, AAAVendorId vendorId,
+      AAASearchType searchType)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAMessage *msg - the message to search in</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *startAvp - at which AVP to start the search. usefull
+          for looking for more of the same name</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVPCode avpCode - AVP code to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAVendorId vendorId - AVP vendor ID to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASearchType searchType - look forward or backward</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP * AAAGetNextAVP(AAA_AVP
+      *avp)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP *avp - reference AVP</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode AAAFreeAVP(AAA_AVP
+      **avp)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP **avp - pointer memory to be freed</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">str AAAGroupAVPS(AAA_AVP_LIST
+      avps)</function></title>
+
+      <para>Groups a list of AVPS into a data buffer</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP_LIST avps - list of AVPS to group</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP_LIST AAAUnGroupAVPS(str
+      buf)</function></title>
+
+      <para>Ungroup a data buffer into a list of AVPs</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>str buf - payload to ungroup list from</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP*
+      AAAFindMatchingAVPList(AAA_AVP_LIST avpList, AAA_AVP *startAvp,
+      AAA_AVPCode avpCode, AAAVendorId vendorId, AAASearchType
+      searchType)</function></title>
+
+      <para>Find an AVP in an AVP list</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP_LIST avpList - AVP list to search</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *startAvp - where to start the search</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVPCode avpCode - AVP code to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAVendorId vendorId - vendor ID to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASearchType searchType - forwards or backwards</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAFreeAVPList(AAA_AVP_LIST
+      *avpList)</function></title>
+
+      <para>Free AVP list and all its members</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP_LIST *avpList - list to be freed</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">int
+      AAAAddRequestHandler(AAARequestHandler_f *f,void
+      *param)</function></title>
+
+      <para>add a #AAARequestHandler_f callback to request being
+      received</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAARequestHandler_f *f - callback function to be called on
+          incoming requests</para>
+        </listitem>
+
+        <listitem>
+          <para>void *param - generic data passed to callback function</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">int
+      AAAAddResponseHandler(AAAResponseHandler_f *f,void
+      *param)</function></title>
+
+      <para>add a #AAAResponseHandler_f callback to responses being
+      received</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAResponseHandler_f *f</emphasis> - callback
+          function to be called on incoming responses</para>
+        </listitem>
+
+        <listitem>
+          <para>void *param - generic data to be bassed to callback
+          function</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+  </section>
+</chapter>

+ 68 - 0
modules/usrloc_pcscf/doc/usrloc_pcscf_faq.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<!-- Module FAQ -->
+
+<chapter>
+	
+	<title>&faqguide;</title>
+	<qandaset defaultlabel="number">
+	<qandaentry>
+		<question>
+		<para>Where can I find more about &kamailio;?</para>
+		</question>
+		<answer>
+		<para>
+			Take a look at &kamailiohomelink;.
+		</para>
+		</answer>
+	</qandaentry>
+	<qandaentry>
+		<question>
+		<para>Where can I post a question about this module?</para>
+		</question>
+		<answer>
+		<para>
+			First at all check if your question was already answered on one of
+			our mailing lists: 
+		</para>
+		<itemizedlist>
+			<listitem>
+			<para>User Mailing List - &kamailiouserslink;</para>
+			</listitem>
+			<listitem>
+			<para>Developer Mailing List - &kamailiodevlink;</para>
+			</listitem>
+		</itemizedlist>
+		<para>
+			E-mails regarding any stable &kamailio; release should be sent to 
+			&kamailiousersmail; and e-mails regarding development versions
+			should be sent to &kamailiodevmail;.
+		</para>
+		<para>
+			If you want to keep the mail private, send it to 
+			&kamailiohelpmail;.
+		</para>
+		</answer>
+	</qandaentry>
+	<qandaentry>
+		<question>
+		<para>How can I report a bug?</para>
+		</question>
+		<answer>
+		<para>
+			Please follow the guidelines provided at:
+			&kamailiobugslink;.
+		</para>
+		</answer>
+	</qandaentry>
+	</qandaset>
+</chapter>
+

+ 177 - 0
modules/usrloc_pcscf/hslot.c

@@ -0,0 +1,177 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "hslot.h"
+
+/*! number of locks */
+int ul_locks_no=4;
+/*! global list of locks */
+gen_lock_set_t* ul_locks=0;
+
+int ul_init_locks(void)
+{
+	int i;
+	i = ul_locks_no;
+	do {
+		if ((( ul_locks=lock_set_alloc(i))!=0)&&
+				(lock_set_init(ul_locks)!=0))
+		{
+			ul_locks_no = i;
+			LM_INFO("locks array size %d\n", ul_locks_no);
+			return 0;
+
+		}
+		if (ul_locks){
+			lock_set_dealloc(ul_locks);
+			ul_locks=0;
+		}
+		i--;
+		if(i==0)
+		{
+			LM_ERR("failed to allocate locks\n");
+			return -1;
+		}
+	} while (1);
+}
+
+
+void ul_unlock_locks(void)
+{
+	unsigned int i;
+
+	if (ul_locks==0)
+		return;
+
+	for (i=0;i<ul_locks_no;i++) {
+#ifdef GEN_LOCK_T_PREFERED
+		lock_release(&ul_locks->locks[i]);
+#else
+		ul_release_idx(i);
+#endif
+	};
+}
+
+void ul_destroy_locks(void)
+{
+	if (ul_locks !=0){
+		lock_set_destroy(ul_locks);
+		lock_set_dealloc(ul_locks);
+	};
+}
+
+#ifndef GEN_LOCK_T_PREFERED
+
+void ul_lock_idx(int idx)
+{
+	lock_set_get(ul_locks, idx);
+}
+
+void ul_release_idx(int idx)
+{
+	lock_set_release(ul_locks, idx);
+}
+#endif
+
+void init_slot(struct udomain* _d, hslot_t* _s, int n)
+{
+	_s->n = 0;
+	_s->first = 0;
+	_s->last = 0;
+	_s->d = _d;
+
+#ifdef GEN_LOCK_T_PREFERED
+	_s->lock = &ul_locks->locks[n%ul_locks_no];
+#else
+	_s->lockidx = n%ul_locks_no;
+#endif
+}
+
+void deinit_slot(hslot_t* _s)
+{
+	struct pcontact* ptr;
+	
+	     /* Remove all elements */
+	while(_s->first) {
+		ptr = _s->first;
+		_s->first = _s->first->next;
+		free_pcontact(ptr);
+	}
+	
+	_s->n = 0;
+	_s->last = 0;
+    _s->d = 0;
+}
+
+void slot_add(hslot_t* _s, struct pcontact* _r)
+{
+	if (_s->n == 0) {
+		_s->first = _s->last = _r;
+	} else {
+		_r->prev = _s->last;
+		_s->last->next = _r;
+		_s->last = _r;
+	}
+	_s->n++;
+	_r->slot = _s;
+}
+
+void slot_rem(hslot_t* _s, struct pcontact* _r)
+{
+	if (_r->prev) {
+		_r->prev->next = _r->next;
+	} else {
+		_s->first = _r->next;
+	}
+
+	if (_r->next) {
+		_r->next->prev = _r->prev;
+	} else {
+		_s->last = _r->prev;
+	}
+
+	_r->prev = _r->next = 0;
+	_r->slot = 0;
+	_s->n--;
+}

+ 84 - 0
modules/usrloc_pcscf/hslot.h

@@ -0,0 +1,84 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef HSLOT_H
+#define HSLOT_H
+
+#include "../../locking.h"
+
+#include "udomain.h"
+#include "pcontact.h"
+
+
+struct udomain;
+struct pcontact;
+
+
+typedef struct hslot {
+	int n;                  	/*!< Number of elements in the collision slot */
+	struct pcontact* first;  	/*!< First element in the list */
+	struct pcontact* last;   	/*!< Last element in the list */
+	struct udomain* d;      	/*!< Domain we belong to */
+#ifdef GEN_LOCK_T_PREFERED
+	gen_lock_t *lock;       	/*!< Lock for hash entry - fastlock */
+#else
+	int lockidx;            	/*!< Lock index for hash entry - the rest*/
+#endif
+} hslot_t;
+
+void init_slot(struct udomain* _d, hslot_t* _s, int n);
+void deinit_slot(hslot_t* _s);
+void slot_add(hslot_t* _s, struct pcontact* _r);
+void slot_rem(hslot_t* _s, struct pcontact* _r);
+int ul_init_locks(void);
+void ul_unlock_locks(void);
+void ul_destroy_locks(void);
+
+#ifndef GEN_LOCK_T_PREFERED
+void ul_lock_idx(int idx);
+void ul_release_idx(int idx);
+#endif
+
+#endif /* HSLOT_H */

+ 271 - 0
modules/usrloc_pcscf/pcontact.c

@@ -0,0 +1,271 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "pcontact.h"
+#include <string.h>
+#include "../../hashes.h"
+#include "../../mem/shm_mem.h"
+#include "../../dprint.h"
+#include "../../ut.h"
+#include "ul_mod.h"
+#include "usrloc.h"
+#include "utime.h"
+#include "ul_callback.h"
+#include "usrloc.h"
+#include "../../lib/ims/useful_defs.h"
+
+/*! retransmission detection interval in seconds */
+int cseq_delay = 20;
+
+void insert_ppublic(struct pcontact* _c, ppublic_t* _p)
+{
+	LM_DBG("linking IMPU <%.*s> to contact <%.*s>\n",
+			_p->public_identity.len,_p->public_identity.s,
+			_c->aor.len, _c->aor.s);
+
+	if (_c->head == 0) {//first entry
+		_c->head = _c->tail = _p;
+	} else {
+		_p->prev = _c->tail;
+		_c->tail->next = _p;
+		_c->tail = _p;
+	}
+}
+int new_ppublic(str* public_identity, int is_default, ppublic_t** _p)
+{
+	*_p = (ppublic_t*)shm_malloc(sizeof(ppublic_t));
+	if (!*_p) {
+		LM_ERR("no more shm memory\n");
+		return -1;
+	}
+	(*_p)->next=(*_p)->prev=0;
+	(*_p)->public_identity.s = (char*)shm_malloc(public_identity->len);
+	if (!(*_p)->public_identity.s) {
+		LM_ERR("no more shm memory\n");
+		if (*_p) {
+			shm_free(*_p);
+		}
+		return -1;
+	}
+
+	(*_p)->is_default = is_default;
+	memcpy((*_p)->public_identity.s, public_identity->s, public_identity->len);
+	(*_p)->public_identity.len = public_identity->len;
+	return 0;
+}
+
+void free_ppublic(ppublic_t* _p)
+{
+	if (!_p)
+		return;
+	if (_p->public_identity.s) {
+		shm_free(_p->public_identity.s);
+	}
+	shm_free(_p);
+}
+
+int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c)
+{
+	int i;
+	ppublic_t* ppublic_ptr;
+	int is_default = 1;
+
+	*_c = (pcontact_t*)shm_malloc(sizeof(pcontact_t));
+	if (*_c == 0) {
+		LM_ERR("no more shared memory\n");
+		return -1;
+	}
+	memset(*_c, 0, sizeof(pcontact_t));
+
+	LM_DBG("New contact [<%.*s>] with %d associated IMPUs in state: [%s]\n",
+			_contact->len, _contact->s,
+			_ci->num_public_ids,
+			reg_state_to_string(_ci->reg_state));
+
+	(*_c)->aor.s = (char*) shm_malloc(_contact->len);
+	if ((*_c)->aor.s == 0) {
+		LM_ERR("no more share memory\n");
+		shm_free(*_c);
+		*_c = 0;
+		return -2;
+	}
+	memcpy((*_c)->aor.s, _contact->s, _contact->len);
+	(*_c)->aor.len = _contact->len;
+	(*_c)->domain = (str*)_d;
+	(*_c)->aorhash = core_hash(_contact, 0, 0);
+	(*_c)->expires = _ci->expires;
+	(*_c)->reg_state = _ci->reg_state;
+
+	// Add received Info:
+	if (_ci->received_host.len > 0 && _ci->received_host.s) {
+		(*_c)->received_host.s = (char*) shm_malloc(_ci->received_host.len);
+		if ((*_c)->received_host.s == 0) {
+			LM_ERR("no more share memory\n");
+			shm_free((*_c)->aor.s);
+			shm_free(*_c);
+			*_c = 0;
+			return -2;
+		}
+		memcpy((*_c)->received_host.s, _ci->received_host.s, _ci->received_host.len);
+		(*_c)->received_host.len = _ci->received_host.len;
+		(*_c)->received_port = _ci->received_port;
+		(*_c)->received_proto = _ci->received_proto;
+	}
+
+	//setup public ids
+	for (i=0; i<_ci->num_public_ids; i++) {
+		if (i>0) is_default = 0; //only the first one is default - P-Associated-uri (first one is default)
+		if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr)!=0) {
+			LM_ERR("unable to create new ppublic\n");
+		} else {
+			insert_ppublic(*_c, ppublic_ptr);
+		}
+	}
+	//add the service routes
+	if (_ci->num_service_routes > 0) {
+		(*_c)->service_routes = shm_malloc(_ci->num_service_routes * sizeof(str));
+		if (!(*_c)->service_routes) {
+			LM_ERR("no more shm mem\n");
+			goto out_of_memory;
+		} else {
+			for (i = 0; i < _ci->num_service_routes; i++) {
+				STR_SHM_DUP((*_c)->service_routes[i], _ci->service_routes[i], "new_pcontact");
+			}
+			(*_c)->num_service_routes = _ci->num_service_routes;
+		}
+	}
+	return 0;
+
+out_of_memory:
+	return -1;
+}
+
+void free_pcontact(pcontact_t* _c) {
+	ppublic_t* p, *tmp;
+	int i;
+
+	if (!_c)
+		return;
+
+	/*free callbacks*/
+	if (_c->cbs.first) {
+		destroy_ul_callbacks_list(_c->cbs.first);
+	}
+
+	LM_DBG("freeing pcontact: <%.*s>\n", _c->aor.len, _c->aor.s);
+	//free ppublics
+	p = _c->head;
+	while (p) {
+		LM_DBG("freeing linked IMPI: <%.*s>\n", p->public_identity.len, p->public_identity.s);
+		tmp = p->next;
+		free_ppublic(p);
+		p = tmp;
+	}
+	//free service_routes
+	if (_c->service_routes) { //remove old service routes
+		for (i = 0; i < _c->num_service_routes; i++) {
+			if (_c->service_routes[i].s)
+				shm_free(_c->service_routes[i].s);
+			shm_free(_c->service_routes);
+			_c->service_routes = 0;
+			_c->num_service_routes = 0;
+		}
+	}
+	//free URI
+	if (_c->aor.s) {
+		shm_free(_c->aor.s);
+	}
+
+	//free received host
+	if (_c->received_host.s) {
+		shm_free(_c->received_host.s);
+	}
+
+	if (_c->rx_session_id.len > 0 && _c->rx_session_id.s)
+		shm_free(_c->rx_session_id.s);
+	shm_free(_c);
+}
+
+static inline void nodb_timer(pcontact_t* _c)
+{
+	LM_DBG("Running nodb timer on <%.*s> which has expires %d and expires in %d seconds\n", _c->aor.len, _c->aor.s, (int)_c->expires, (int)(_c->expires - time(NULL)));
+
+	get_act_time();
+	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);
+		}
+		update_stat(_c->slot->d->expired, 1);
+		mem_delete_pcontact(_c->slot->d, _c);
+		return;
+	}
+
+	//TODO: this is just for tmp debugging
+//	p = _c->head;
+//	while (p) {
+//		if (p->is_default)
+//			LM_DBG("public identity %i (default): <%.*s>\n", i, p->public_identity.len, p->public_identity.s);
+//		else
+//			LM_DBG("public identity %i: <%.*s>\n", i, p->public_identity.len, p->public_identity.s);
+//		i++;
+//		p=p->next;
+//	}
+//
+//	LM_DBG("There are %i service routes as follows:\n", _c->num_service_routes);
+//	for (i=0; i<_c->num_service_routes; i++) {
+//		LM_DBG("service route %i: <%.*s>\n", i+1, _c->service_routes[i].len, _c->service_routes[i].s);
+//	}
+}
+
+void timer_pcontact(pcontact_t* _r)
+{
+	nodb_timer(_r);
+}
+
+void print_pcontact(FILE* _f, pcontact_t* _r)
+{
+
+}

+ 74 - 0
modules/usrloc_pcscf/pcontact.h

@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef IMPURECORD_H
+#define IMPURECORD_H
+
+#include <stdio.h>
+#include <time.h>
+#include "hslot.h"
+#include "../../str.h"
+#include "../../qvalue.h"
+#include "usrloc.h"
+
+struct hslot; 	/*!< Hash table slot */
+
+
+void insert_ppublic(struct pcontact* _c, ppublic_t* _p);
+int new_ppublic(str* public_identity, int is_default, ppublic_t** _p);
+void free_ppublic(ppublic_t* _p);
+
+int new_pcontact(/*str* _dom, str* public_identity, int reg_state, int barring, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, impurecord_t** _r*/);
+void free_pcontact(pcontact_t* _c);
+void print_pcontact(FILE* _f, pcontact_t* _r);
+ppublic_t* mem_insert_ppublic(pcontact_t* _r/*, str* _c, ucontact_info_t* _ci*/);
+void mem_remove_ppublic(pcontact_t* _r/*, ucontact_t* _c*/);
+void mem_delete_ppublic(pcontact_t* _r/*, ucontact_t* _c*/);
+void timer_pcontact(pcontact_t* _r);
+int delete_ppublic(pcontact_t* _r/*, struct ucontact* _c*/);
+int get_ppublic(pcontact_t* _r);
+
+
+#endif

+ 50 - 0
modules/usrloc_pcscf/reginfo.c

@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "reginfo.h"
+
+
+
+

+ 71 - 0
modules/usrloc_pcscf/reginfo.h

@@ -0,0 +1,71 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef REGINFO_H_
+#define REGINFO_H_
+
+#include "../../locking.h"
+
+/** reg Subscription Structure */
+typedef struct _reginfo_subscription {
+	unsigned int hash;
+	str req_uri; 					/**< public id of the user, same thing for To:  */
+	int duration; 					/**< duration of subscription  */
+	time_t expires; 				/**< time of expiration    */
+	char attempts_left; 			/**< number of unsuccessful attempts to subscribe*/
+
+	struct _reginfo_subscription *next, *prev;
+} reginfo_subscription;
+
+/** Subscription list */
+typedef struct {
+	gen_lock_t *lock; 				/**< lock fo subscription list operations       */
+	reginfo_subscription *head; 	/**< first subscription in the list    */
+	reginfo_subscription *tail; 	/**< last subscription in the list   */
+} reginfo_subscription_hash_slot;
+
+
+
+#endif /* REGINFO_H_ */

+ 476 - 0
modules/usrloc_pcscf/udomain.c

@@ -0,0 +1,476 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "udomain.h"
+#include <string.h>
+#include "../../hashes.h"
+#include "../../parser/parse_methods.h"
+#include "../../mem/shm_mem.h"
+#include "../../dprint.h"
+#include "../../lib/srdb1/db.h"
+#include "../../socket_info.h"
+#include "../../ut.h"
+#include "ul_mod.h"            /* usrloc module parameters */
+#include "usrloc.h"
+#include "utime.h"
+#include "usrloc.h"
+
+#include "../../lib/ims/useful_defs.h"
+
+#ifdef STATISTICS
+static char *build_stat_name( str* domain, char *var_name)
+{
+	int n;
+	char *s;
+	char *p;
+
+	n = domain->len + 1 + strlen(var_name) + 1;
+	s = (char*)shm_malloc( n );
+	if (s==0) {
+		LM_ERR("no more shm mem\n");
+		return 0;
+	}
+	memcpy( s, domain->s, domain->len);
+	p = s + domain->len;
+	*(p++) = '-';
+	memcpy( p , var_name, strlen(var_name));
+	p += strlen(var_name);
+	*(p++) = 0;
+	return s;
+}
+#endif
+
+int new_udomain(str* _n, int _s, udomain_t** _d)
+{
+	int i;
+#ifdef STATISTICS
+	char *name;
+#endif
+
+	/* Must be always in shared memory, since
+	 * the cache is accessed from timer which
+	 * lives in a separate process
+	 */
+	*_d = (udomain_t*)shm_malloc(sizeof(udomain_t));
+	if (!(*_d)) {
+		LM_ERR("new_udomain(): No memory left\n");
+		goto error0;
+	}
+	memset(*_d, 0, sizeof(udomain_t));
+
+	(*_d)->table = (hslot_t*)shm_malloc(sizeof(hslot_t) * _s);
+	if (!(*_d)->table) {
+		LM_ERR("no memory left 2\n");
+		goto error1;
+	}
+
+	(*_d)->name = _n;
+
+	for(i = 0; i < _s; i++) {
+		init_slot(*_d, &((*_d)->table[i]), i);
+	}
+
+	(*_d)->size = _s;
+
+#ifdef STATISTICS
+	/* register the statistics */
+	if ( (name=build_stat_name(_n,"contacts"))==0 || register_stat("usrloc",
+	name, &(*_d)->contacts, STAT_NO_RESET|STAT_SHM_NAME)!=0 ) {
+		LM_ERR("failed to add stat variable\n");
+		goto error2;
+	}
+	if ( (name=build_stat_name(_n,"expires"))==0 || register_stat("usrloc",
+	name, &(*_d)->expired, STAT_SHM_NAME)!=0 ) {
+		LM_ERR("failed to add stat variable\n");
+		goto error2;
+	}
+#endif
+
+	return 0;
+#ifdef STATISTICS
+error2:
+	shm_free((*_d)->table);
+#endif
+error1:
+	shm_free(*_d);
+error0:
+	return -1;
+}
+
+void free_udomain(udomain_t* _d)
+{
+	int i;
+
+	if (_d->table) {
+		for(i = 0; i < _d->size; i++) {
+			lock_ulslot(_d, i);
+			deinit_slot(_d->table + i);
+			unlock_ulslot(_d, i);
+		}
+		shm_free(_d->table);
+	}
+	shm_free(_d);
+}
+
+void print_udomain(FILE* _f, udomain_t* _d)
+{
+	int i;
+	int max=0, slot=0, n=0;
+	struct pcontact* r;
+	fprintf(_f, "---Domain---\n");
+	fprintf(_f, "name : '%.*s'\n", _d->name->len, ZSW(_d->name->s));
+	fprintf(_f, "size : %d\n", _d->size);
+	fprintf(_f, "table: %p\n", _d->table);
+	/*fprintf(_f, "lock : %d\n", _d->lock); -- can be a structure --andrei*/
+	fprintf(_f, "\n");
+	for(i=0; i<_d->size; i++)
+	{
+		r = _d->table[i].first;
+		n += _d->table[i].n;
+		if(max<_d->table[i].n){
+			max= _d->table[i].n;
+			slot = i;
+		}
+		while(r) {
+			print_pcontact(_f, r);
+			r = r->next;
+		}
+	}
+	fprintf(_f, "\nMax slot: %d (%d/%d)\n", max, slot, n);
+	fprintf(_f, "\n---/Domain---\n");
+}
+
+
+inline int time2str(time_t _v, char* _s, int* _l)
+{
+	struct tm* t;
+	int l;
+
+	if ((!_s) || (!_l) || (*_l < 2)) {
+		LM_ERR("Invalid parameter value\n");
+		return -1;
+	}
+
+	*_s++ = '\'';
+
+	/* Convert time_t structure to format accepted by the database */
+	t = localtime(&_v);
+	l = strftime(_s, *_l -1, "%Y-%m-%d %H:%M:%S", t);
+
+	if (l == 0) {
+		LM_ERR("Error during time conversion\n");
+		/* the value of _s is now unspecified */
+		_s = NULL;
+		_l = 0;
+		return -1;
+	}
+	*_l = l;
+
+	*(_s + l) = '\'';
+	*_l = l + 2;
+	return 0;
+}
+
+int mem_insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c){
+	int sl;
+
+	if (new_pcontact(_d->name, _contact, _ci, _c) < 0) {
+		LM_ERR("creating pcontact failed\n");
+		return -1;
+	}
+
+	sl = ((*_c)->aorhash) & (_d->size - 1);
+	slot_add(&_d->table[sl], *_c);
+	update_stat(_d->contacts, 1);
+	return 0;
+}
+
+void mem_delete_pcontact(udomain_t* _d, struct pcontact* _c)
+{
+	slot_rem(_c->slot, _c);
+	free_pcontact(_c);
+	update_stat( _d->contacts, -1);
+}
+
+void mem_timer_udomain(udomain_t* _d)
+{
+	struct pcontact* ptr;
+	int i;
+
+	for(i=0; i<_d->size; i++)
+	{
+		lock_ulslot(_d, i);
+
+		ptr = _d->table[i].first;
+
+		while(ptr) {
+			timer_pcontact(ptr);
+			/* Remove the entire record if it is empty */
+			//if (ptr->contacts == 0) {
+			//	t = ptr;
+			//	ptr = ptr->next;
+			//	mem_delete_pcontact(_d, t);
+			//}//// else {
+			//	ptr = ptr->next;
+			//}
+			ptr = ptr->next;
+		}
+		unlock_ulslot(_d, i);
+	}
+}
+
+void lock_udomain(udomain_t* _d, str* _aor)
+{
+	unsigned int sl;
+	sl = core_hash(_aor, 0, _d->size);
+
+#ifdef GEN_LOCK_T_PREFERED
+	lock_get(_d->table[sl].lock);
+#else
+	ul_lock_idx(_d->table[sl].lockidx);
+#endif
+}
+
+void unlock_udomain(udomain_t* _d, str* _aor)
+{
+	unsigned int sl;
+	sl = core_hash(_aor, 0, _d->size);
+#ifdef GEN_LOCK_T_PREFERED
+	lock_release(_d->table[sl].lock);
+#else
+	ul_release_idx(_d->table[sl].lockidx);
+#endif
+}
+
+void lock_ulslot(udomain_t* _d, int i)
+{
+#ifdef GEN_LOCK_T_PREFERED
+	lock_get(_d->table[i].lock);
+#else
+	ul_lock_idx(_d->table[i].lockidx);
+#endif
+}
+
+
+void unlock_ulslot(udomain_t* _d, int i)
+{
+#ifdef GEN_LOCK_T_PREFERED
+	lock_release(_d->table[i].lock);
+#else
+	ul_release_idx(_d->table[i].lockidx);
+#endif
+}
+
+int update_rx_regsession(struct udomain* _d, str* session_id, struct pcontact* _c) {
+	if (session_id->len > 0 && session_id->s) {
+		if (_c->rx_session_id.len > 0 && _c->rx_session_id.s) {
+			_c->rx_session_id.len = 0;
+			shm_free(_c->rx_session_id.s);
+		}
+		_c->rx_session_id.s = shm_malloc(session_id->len);
+		if (!_c->rx_session_id.s) {
+			LM_ERR("no more shm_mem\n");
+			return -1;
+		}
+		memcpy(_c->rx_session_id.s, session_id->s, session_id->len);
+		_c->rx_session_id.len = session_id->len;
+	} else {
+		return -1;
+	}
+	return 0;
+}
+
+int update_pcontact(struct udomain* _d, struct pcontact_info* _ci, struct pcontact* _c) //TODO: should prob move this to pcontact
+{
+	int is_default = 1;
+	ppublic_t* ppublic_ptr;
+	int i;
+
+	_c->reg_state = _ci->reg_state;
+
+	if (_ci->expires > 0) {
+		_c->expires = _ci->expires;
+	}
+
+	if (_ci->num_service_routes > 0 && _ci->service_routes) {
+		//replace all existing service routes
+		if (_c->service_routes) { //remove old service routes
+			for (i=0; i<_c->num_service_routes; i++) {
+				if (_c->service_routes[i].s)
+					shm_free(_c->service_routes[i].s);
+				shm_free(_c->service_routes);
+				_c->service_routes=0;
+				_c->num_service_routes=0;
+			}
+		}
+		//now add the new service routes
+		if (_ci->num_service_routes > 0) {
+			_c->service_routes = shm_malloc(_ci->num_service_routes*sizeof(str));
+			if (!_c->service_routes) {
+				LM_ERR("no more shm mem trying to allocate [%ld bytes]\n", _ci->num_service_routes*sizeof(str));
+				goto out_of_memory;
+			} else {
+				for (i=0; i<_ci->num_service_routes; i++) {
+					STR_SHM_DUP(_c->service_routes[i], _ci->service_routes[i], "update_pcontact");
+				}
+				_c->num_service_routes = _ci->num_service_routes;
+			}
+		}
+	}
+
+	if (_ci->num_public_ids > 0 && _ci->public_ids) {
+		if (_c->head) {
+			LM_DBG("ppublic's already exist.... .not updating\n");
+		} else {
+			for (i = 0; i < _ci->num_public_ids; i++) {
+				if (i > 0)
+					is_default = 0; //only the first one is default - P-Associated-uri (first one is default)
+				if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr) != 0) {
+					LM_ERR("unable to create new ppublic\n");
+				} else {
+					insert_ppublic(_c, ppublic_ptr);
+				}
+			}
+		}
+	}
+
+	// update received info:
+	if (_ci->received_host.len > 0) {
+		if (_c->received_host.s)
+			shm_free(_c->received_host.s);
+		STR_SHM_DUP(_c->received_host, _ci->received_host, "update_pcontact");
+	}
+	if (_ci->received_port > 0) _c->received_port = _ci->received_port;
+	if (_ci->received_proto > 0) _c->received_proto = _ci->received_proto;
+
+	//TODO: update path, etc
+	run_ul_callbacks(PCSCF_CONTACT_UPDATE, _c);
+	return 0;
+
+out_of_memory:
+	return -1;
+}
+
+int insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c) {
+
+    if (mem_insert_pcontact(_d, _contact, _ci, _c)){
+        LM_ERR("inserting pcontact failed\n");
+        goto error;
+    }
+    if (exists_ulcb_type(PCSCF_CONTACT_INSERT)) {
+		run_ul_create_callbacks(*_c);
+	}
+    return 0;
+
+error:
+    return -1;
+}
+
+int get_pcontact(udomain_t* _d, str* _contact, struct pcontact** _c) {
+	unsigned int sl, i, aorhash;
+	struct pcontact* c;
+
+	/* search in cache */
+	aorhash = core_hash(_contact, 0, 0);
+	sl = aorhash & (_d->size - 1);
+	c = _d->table[sl].first;
+
+	for (i = 0; i < _d->table[sl].n; i++) {
+		if ((c->aorhash == aorhash) && (c->aor.len == _contact->len)
+				&& !memcmp(c->aor.s, _contact->s, _contact->len)) {
+			*_c = c;
+			return 0;
+		}
+
+		c = c->next;
+	}
+	return 1; /* Nothing found */
+}
+
+int get_pcontact_by_src(udomain_t* _d, str * _host, unsigned short _port, unsigned short _proto, struct pcontact** _c) {
+	int i;
+	struct pcontact* c;
+
+	if (_d->table) {
+		for(i = 0; i < _d->size; i++) {
+		}
+	}
+
+
+	for(i=0; i<_d->size; i++)
+	{
+		c = _d->table[i].first;
+		while(c) {
+			// First check, if Proto and Port matches:
+			if ((c->reg_state == PCONTACT_REGISTERED) && (c->received_port == _port) && (c->received_proto == _proto)) {
+				// Then check the length:
+				if (c->received_host.len == _host->len) {
+					// Finally really compare the "received_host"
+					if (!memcmp(c->received_host.s, _host->s, _host->len)) {
+						*_c = c;
+						return 0;
+					}
+				}
+			}
+			c = c->next;
+		}
+	}
+	return 1; /* Nothing found */
+}
+
+int delete_pcontact(udomain_t* _d, str* _aor, struct pcontact* _c)
+{
+	if (_c==0) {
+		if (get_pcontact(_d, _aor, &_c) > 0) {
+			return 0;
+		}
+	}
+	if (exists_ulcb_type(PCSCF_CONTACT_DELETE)) {
+		run_ul_callbacks(PCSCF_CONTACT_DELETE, _c);
+	}
+	mem_delete_pcontact(_d, _c);
+
+	return 0;
+}

+ 83 - 0
modules/usrloc_pcscf/udomain.h

@@ -0,0 +1,83 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef UDOMAIN_H
+#define UDOMAIN_H
+
+
+#include <stdio.h>
+#include "../../lib/kcore/statistics.h"
+#include "../../locking.h"
+#include "../../str.h"
+#include "../../lib/srdb1/db.h"
+#include "pcontact.h"
+#include "hslot.h"
+#include "usrloc.h"
+
+struct hslot;   /*!< Hash table slot */
+struct pcontact; /*!< contact record */
+
+int new_udomain(str* _n, int _s, udomain_t** _d);
+void free_udomain(udomain_t* _d);
+void print_udomain(FILE* _f, udomain_t* _d);
+
+void mem_timer_udomain(udomain_t* _d);
+int mem_insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c);
+void mem_delete_pcontact(udomain_t* _d, struct pcontact* _r);
+
+void lock_udomain(udomain_t* _d, str *_aor);
+void unlock_udomain(udomain_t* _d, str *_aor);
+
+void lock_ulslot(udomain_t* _d, int i);
+void unlock_ulslot(udomain_t* _d, int i);
+
+int update_rx_regsession(struct udomain* _d, str* session_id, struct pcontact* _c);
+int update_pcontact(struct udomain* _d, struct pcontact_info* _ci, struct pcontact* _c);
+int insert_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _r);
+int get_pcontact(udomain_t* _d, str* _aor, struct pcontact** _r);
+int get_pcontact_by_src(udomain_t* _d, str * _host, unsigned short _port, unsigned short _proto, struct pcontact** _c);
+int delete_pcontact(udomain_t* _d, str* _aor, struct pcontact* _r);
+
+#endif

+ 167 - 0
modules/usrloc_pcscf/ul_callback.c

@@ -0,0 +1,167 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <stdlib.h>
+
+#include "../../dprint.h"
+#include "../../error.h"
+#include "../../mem/shm_mem.h"
+#include "ul_callback.h"
+#include "usrloc.h"
+
+struct ulcb_head_list* ulcb_list = 0;			/*<! list for create callbacks */
+
+int init_ulcb_list(void)
+{
+	ulcb_list = (struct ulcb_head_list*)shm_malloc( sizeof(struct ulcb_head_list) );
+	if (ulcb_list==0) {
+		LM_CRIT("no more shared mem\n");
+		return -1;
+	}
+	ulcb_list->first = 0;
+	ulcb_list->reg_types = 0;
+	return 1;
+}
+
+void destroy_ulcb_list(void)
+{
+	struct ul_callback *cbp, *cbp_tmp;
+
+	if (!ulcb_list)
+		return;
+
+	for( cbp=ulcb_list->first; cbp ; ) {
+		cbp_tmp = cbp;
+		cbp = cbp->next;
+		if (cbp_tmp->param) shm_free( cbp_tmp->param );
+		shm_free( cbp_tmp );
+	}
+
+	shm_free(ulcb_list);
+}
+
+void destroy_ul_callbacks_list(struct ul_callback* cb) {
+
+	struct ul_callback *cb_t;
+
+	while (cb) {
+		cb_t = cb;
+		cb = cb->next;
+//		if (cb_t->callback_param_free && cb_t->param) {
+//			cb_t->callback_param_free(cb_t->param);
+//			cb_t->param = NULL;
+//		} //TODO: this is if we need/require a freeparam function
+		shm_free(cb_t);
+	}
+}
+
+int register_ulcb( struct pcontact *c, int types, ul_cb f, void *param )
+{
+	struct ul_callback *cbp;
+
+	/* are the callback types valid?... */
+	if ( types<0 || types>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 (!(cbp=(struct ul_callback*)shm_malloc(sizeof( struct ul_callback)))) {
+		LM_ERR("no more share mem\n");
+		return E_OUT_OF_MEM;
+	}
+
+	cbp->callback = f;
+	cbp->param = param;
+	cbp->types = types;
+
+	if ( types==PCSCF_CONTACT_INSERT ) {
+		LM_DBG("TODO: check for registering callback before/after init\n");
+		/* link it into the proper place... */
+		cbp->next = ulcb_list->first;
+		ulcb_list->first = cbp;
+		ulcb_list->reg_types |= types;
+	} else {
+		/* link it into pcontact structure */
+		cbp->next = c->cbs.first;
+		c->cbs.first = cbp;
+		c->cbs.reg_types |= types;
+	}
+
+	return 1;
+}
+
+/*! \brief run all transaction callbacks for an event type */
+void run_ul_callbacks( int type , struct pcontact *c)
+{
+	struct ul_callback *cbp;
+
+	if (c->cbs.first == 0 || ((c->cbs.reg_types) & type) == 0)
+		return;
+
+	for (cbp=c->cbs.first; cbp; cbp=cbp->next) {
+		if ((cbp->types) & type) {
+			LM_DBG("contact=%p, callback type %d/%d entered\n", c, type, cbp->types);
+			cbp->callback( c, type, cbp->param );
+		}
+	}
+	return;
+}
+
+void run_ul_create_callbacks(struct pcontact *c)
+{
+	struct ul_callback *cbp;
+
+	for (cbp = ulcb_list->first; cbp; cbp = cbp->next) {
+			LM_DBG("contact=%p, callback type PCSCF_CONTACT_INSERT entered\n", c);
+		cbp->callback(c, PCSCF_CONTACT_INSERT, cbp->param);
+	}
+}
+

+ 87 - 0
modules/usrloc_pcscf/ul_callback.h

@@ -0,0 +1,87 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef _UL_CALLBACKS_H
+#define _UL_CALLBACKS_H
+
+#include "../../dprint.h"
+
+struct pcontact;
+
+#define PCSCF_CONTACT_INSERT      (1<<0)
+#define PCSCF_CONTACT_UPDATE      (1<<1)
+#define PCSCF_CONTACT_DELETE      (1<<2)
+#define PCSCF_CONTACT_EXPIRE      (1<<3)
+#define PCSCF_MAX                 ((1<<4)-1)
+
+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 */
+
+struct ul_callback {
+	int types;                   /*!< types of events that trigger the callback*/
+	ul_cb* callback;             /*!< callback function */
+	void *param;                 /*!< param to be passed to callback function */
+	//param_free_cb* callback_param_free;
+	struct ul_callback* next;
+};
+
+struct ulcb_head_list {
+	struct ul_callback *first;
+	int reg_types;
+};
+
+extern struct ulcb_head_list*  ulcb_list;		/*!< this is the list for the INSERT callbacks*/
+
+#define exists_ulcb_type(_types_) \
+	( (ulcb_list->reg_types)|(_types_) )
+
+int init_ulcb_list(void);
+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 run_ul_callbacks( int type , struct pcontact *c);
+void run_ul_create_callbacks(struct pcontact *c);
+
+#endif

+ 216 - 0
modules/usrloc_pcscf/ul_mod.c

@@ -0,0 +1,216 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <stdio.h>
+#include "ul_mod.h"
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../rpc_lookup.h"
+#include "../../timer.h"     /* register_timer */
+#include "../../globals.h"   /* is_main */
+#include "../../ut.h"        /* str_init */
+#include "dlist.h"           /* register_udomain */
+#include "udomain.h"         /* {insert,delete,get,release}_urecord */
+#include "pcontact.h"         /* {insert,delete,get}_ucontact */
+#include "ul_rpc.h"
+#include "ul_callback.h"
+#include "usrloc.h"
+
+MODULE_VERSION
+
+#define DEFAULT_DBG_FILE "/var/log/usrloc_debug"
+static FILE *debug_file;
+
+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 */
+static int child_init(int rank);                    /*!< Per-child init function */
+
+extern int bind_usrloc(usrloc_api_t* api);
+extern int ul_locks_no;
+
+/*
+ * Module parameters and their default values
+ */
+str usrloc_debug_file = str_init(DEFAULT_DBG_FILE);
+int timer_interval  = 60;				/*!< Timer interval in seconds */
+int usrloc_debug 	= 0;
+int ul_hash_size = 9;
+int init_flag = 0;
+
+/*! \brief
+ * Exported functions
+ */
+static cmd_export_t cmds[] = {
+	{"ul_bind_usrloc_pcscf",        (cmd_function)bind_usrloc,        1, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0}
+};
+
+/*! \brief
+ * Exported parameters
+ */
+static param_export_t params[] = {
+	{"hash_size",         INT_PARAM, &ul_hash_size    },
+	{"timer_interval",    INT_PARAM, &timer_interval  },
+	{"usrloc_debug_file", STR_PARAM, &usrloc_debug_file.s},
+	{"enable_debug_file", INT_PARAM, &usrloc_debug},
+	{0, 0, 0}
+};
+
+stat_export_t mod_stats[] = {
+	{"registered_contacts" ,  STAT_IS_FUNC, (stat_var**)get_number_of_contacts  },
+	{"registered_impus" ,  STAT_IS_FUNC, (stat_var**)get_number_of_impu  },
+	{"expired_contacts" ,  STAT_IS_FUNC, (stat_var**)get_number_of_expired  },
+	{0,0,0}
+};
+
+static mi_export_t mi_cmds[] = {
+	{ 0, 0, 0, 0, 0}
+};
+
+struct module_exports exports = {
+	"usrloc_pcscf",
+	DEFAULT_DLFLAGS, /*!< dlopen flags */
+	cmds,       /*!< Exported functions */
+	params,     /*!< Export parameters */
+	mod_stats,  /*!< exported statistics */
+	mi_cmds,    /*!< exported MI functions */
+	0,          /*!< exported pseudo-variables */
+	0,          /*!< extra processes */
+	mod_init,   /*!< Module initialization function */
+	0,          /*!< Response function */
+	destroy,    /*!< Destroy function */
+	child_init  /*!< Child initialization function */
+};
+
+
+/*! \brief
+ * Module initialization function
+ */
+static int mod_init(void) {
+
+	if (usrloc_debug){
+		LM_INFO("Logging usrloc records to %.*s\n", usrloc_debug_file.len, usrloc_debug_file.s);
+		debug_file = fopen(usrloc_debug_file.s, "a");
+		fprintf(debug_file, "starting\n");
+		fflush(debug_file);
+	}
+
+#ifdef STATISTICS
+	/* register statistics */
+	if (register_module_stats( exports.name, mod_stats)!=0 ) {
+		LM_ERR("failed to register core statistics\n");
+		return -1;
+	}
+#endif
+
+	/* Compute the lengths of string parameters */
+	usrloc_debug_file.len = strlen(usrloc_debug_file.s);
+
+	if (ul_hash_size <= 1)
+		ul_hash_size = 512;
+	else
+		ul_hash_size = 1 << ul_hash_size;
+	ul_locks_no = ul_hash_size;
+
+	if (ul_init_locks() != 0) {
+		LM_ERR("locks array initialization failed\n");
+		return -1;
+	}
+
+	/* Regsiter RPC */
+	if (rpc_register_array(ul_rpc) != 0) {
+		LM_ERR("failed to register RPC commands\n");
+		return -1;
+	}
+
+	/* Register cache timer */
+	LM_DBG("Registering cache timer");
+	register_timer(timer, 0, timer_interval);
+
+	/* init the callbacks list */
+	if (init_ulcb_list() < 0) {
+		LM_ERR("usrloc/callbacks initialization failed\n");
+		return -1;
+	}
+
+	init_flag = 1;
+
+	return 0;
+}
+
+static int child_init(int rank)
+{
+	return 0;
+}
+
+/*! \brief
+ * Module destroy function
+ */
+static void destroy(void)
+{
+	free_all_udomains();
+	ul_destroy_locks();
+
+	/* free callbacks list */
+	destroy_ulcb_list();
+}
+
+
+/*! \brief
+ * Timer handler
+ */
+static void timer(unsigned int ticks, void* param) {
+	LM_DBG("Syncing cache\n");
+	if (usrloc_debug) {
+		print_all_udomains(debug_file);
+		fflush(debug_file);
+	}
+
+	if (synchronize_all_udomains() != 0) {
+		LM_ERR("synchronizing cache failed\n");
+	}
+}
+

+ 63 - 0
modules/usrloc_pcscf/ul_mod.h

@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef UL_MOD_H
+#define UL_MOD_H
+
+#include "../../lib/srdb1/db.h"
+#include "../../str.h"
+
+/*
+ * Module parameters
+ */
+#define UL_TABLE_VERSION 1004
+
+extern int timer_interval;
+extern int desc_time_order;
+extern int cseq_delay;
+extern int ul_fetch_rows;
+extern int ul_hash_size;
+
+#endif /* UL_MOD_H */

+ 176 - 0
modules/usrloc_pcscf/ul_rpc.c

@@ -0,0 +1,176 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "../../ip_addr.h"
+#include "../../dprint.h"
+
+#include "ul_rpc.h"
+#include "dlist.h"
+#include "udomain.h"
+
+static const char* ul_rpc_dump_doc[2] = {
+	"Dump PCSCF contacts and associated identitites",
+	0
+};
+
+static void ul_rpc_dump(rpc_t* rpc, void* ctx) {
+	struct pcontact* c;
+	ppublic_t* p;
+	dlist_t* dl;
+	udomain_t* dom;
+	time_t t;
+	void* th;
+	void* ah;
+	void* ih;
+	void* sr;
+	void* sh;
+	int max, n, i, j;
+
+	t = time(0);
+	for (dl = root; dl; dl = dl->next) {
+		dom = dl->d;
+		if (rpc->add(ctx, "{", &th) < 0) {
+			rpc->fault(ctx, 500, "Internal error creating top rpc");
+			return;
+		}
+		if (rpc->struct_add(th, "Sd{", "Domain", &dl->name, "Size",
+				(int) dom->size, "AoRs", &ah) < 0) {
+			rpc->fault(ctx, 500, "Internal error creating inner struct");
+			return;
+		}
+
+		for (i = 0, n = 0, max = 0; i < dom->size; 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);
+		}
+		if (rpc->struct_add(ah, "{", "Stats", &sh) > 0) {
+			rpc->fault(ctx, 500, "Internal error creating stats");
+		}
+		if (rpc->struct_add(sh, "dd", "Records", n, "Max-Slots", max) < 0) {
+			rpc->fault(ctx, 500, "Internal error creating stats struct");
+		}
+	}
+}
+
+rpc_export_t ul_rpc[] = {
+	{"ulpcscf.status",   ul_rpc_dump,   ul_rpc_dump_doc,   0},
+	{0, 0, 0, 0}
+};
+
+

+ 53 - 0
modules/usrloc_pcscf/ul_rpc.h

@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef _UL_RPC_H_
+#define _UL_RPC_H_
+
+#include "../../rpc.h"
+
+extern rpc_export_t ul_rpc[];
+
+#endif

+ 84 - 0
modules/usrloc_pcscf/usrloc.c

@@ -0,0 +1,84 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "usrloc.h"
+#include "dlist.h"
+#include "pcontact.h"
+#include "udomain.h"
+#include "../../sr_module.h"
+#include "ul_mod.h"
+
+extern unsigned int init_flag;
+
+int bind_usrloc(usrloc_api_t* api) {
+	if (!api) {
+		LM_ERR("invalid parameter value\n");
+		return -1;
+	}
+	if (init_flag == 0) {
+		LM_ERR("configuration error - trying to bind to usrloc module"
+				" before being initialized\n");
+		return -1;
+	}
+
+	api->register_udomain = register_udomain;
+	api->get_udomain = get_udomain;
+	api->lock_udomain = lock_udomain;
+	api->unlock_udomain = unlock_udomain;
+
+	api->insert_pcontact = insert_pcontact;
+	api->delete_pcontact = delete_pcontact;
+	api->get_pcontact = get_pcontact;
+	api->get_pcontact_by_src = get_pcontact_by_src;
+
+	api->update_pcontact = update_pcontact;
+	api->update_rx_regsession = update_rx_regsession;
+
+	api->get_all_ucontacts = get_all_ucontacts;
+
+	api->register_ulcb = register_ulcb;
+
+	return 0;
+}

+ 234 - 0
modules/usrloc_pcscf/usrloc.h

@@ -0,0 +1,234 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef USRLOC_H
+#define USRLOC_H
+
+#include <time.h>
+#include "../../lib/kcore/statistics.h"
+#include "ul_callback.h"
+#include "../../qvalue.h"
+#include "../../str.h"
+#include "../../modules/tm/dlg.h"
+#include "../cdp/diameter_ims_code_avp.h"
+
+#define VALID_CONTACT(c, t)   ((c->expires>t) || (c->expires==0))
+
+struct hslot;		/*!< Hash table slot */
+struct socket_info;
+
+struct udomain {
+	str* name;                 /*!< Domain name (NULL terminated) */
+	int size;                  /*!< Hash table size */
+	struct hslot* table;       /*!< Hash table - array of collision slots */
+	/* statistics */
+	stat_var *contacts;        /*!< no of registered contacts */
+	stat_var *expired;         /*!< no of expires */
+};
+typedef struct udomain udomain_t;
+
+/** Public Identity Structure */
+typedef struct {
+	char barring; /**< Barring state									*/
+	str public_identity; /**< Public Identity string							*/
+	str wildcarded_psi; /** if exists is the wildcarded psi					*/
+} ims_public_identity;
+
+/** IPSec SA Information */
+typedef struct ipsec {
+	unsigned int spi_uc; 		/**< SPI Client to use					*/
+	unsigned int spi_us; 		/**< SPI Server to use					*/
+	unsigned int spi_pc; 		/**< SPI Client to use					*/
+	unsigned int spi_ps; 		/**< SPI Server to use					*/
+	unsigned short port_uc; 	/**< Port UE Client						*/
+	unsigned short port_us; 	/**< Port UE Server						*/
+
+	str ealg; 					/**< Cypher Algorithm - ESP				*/
+	str r_ealg; 				/**< received Cypher Algorithm - ESP	*/
+	str ck; 					/**< Cypher Key							*/
+	str alg; 					/**< Integrity Algorithm - AH			*/
+	str r_alg; 					/**<received Integrity Algorithm - AH	*/
+	str ik; 					/**< Integrity Key						*/
+	str prot; 					/**< Protocol (ah/esp) */
+	str mod; 					/**< Mode (transport/tunnel) */
+} ipsec_t;
+
+typedef enum sec_type {
+	SECURITY_NONE = 0,
+	SECURITY_IPSEC = 1,
+} security_type;
+
+typedef struct security {
+	str sec_header; 		/**< Security Header value 				*/
+	security_type type; 	/**< Type of security in use			*/
+
+	union {
+		ipsec_t *ipsec; 	/**< IPSec SA information, if any		*/
+	} data;
+	float q;
+} security_t;
+
+typedef struct udomain_head {
+	str* name;
+} udomain_head_t;
+
+/* public identity structure. To be associated with a contact */
+typedef struct ppublic {
+	str public_identity;					/**< Public identity */
+	char is_default;						/**< is this the default identity for the contact */
+	struct ppublic* next;
+	struct ppublic* prev;
+} ppublic_t;
+
+/** Enumeration for public identity Registration States */
+enum pcontact_reg_states {
+	PCONTACT_NOT_REGISTERED 	= 0, 			/**< User not-registered, no profile stored	*/
+	PCONTACT_REGISTERED 		= 1, 			/**< User registered						*/
+	PCONTACT_REG_PENDING 		= -1,			/**< User not-registered, profile stored	*/
+	PCONTACT_REG_PENDING_AAR 	= -2,			/**< User not-registered, profile stored, AAR sent	*/
+	PCONTACT_DEREGISTERED 		= -3,
+    PCONTACT_DEREG_PENDING_PUBLISH	= -4
+};
+
+static inline char* reg_state_to_string(enum pcontact_reg_states reg_state) {
+	switch (reg_state) {
+		case PCONTACT_NOT_REGISTERED:
+			return "not registered";
+		case PCONTACT_REGISTERED:
+			return "registered";
+		case PCONTACT_REG_PENDING:
+			return "registration pending";
+		case PCONTACT_DEREGISTERED:
+			return "unregistered";
+                case PCONTACT_DEREG_PENDING_PUBLISH:
+			return "deregistration pending, publish sent";
+		case PCONTACT_REG_PENDING_AAR:
+			return "registration pending, aar sent";
+		default:
+			return "unknown";
+	}
+}
+typedef struct pcontact_info {
+	str received_host;
+	unsigned short received_port;
+	unsigned short received_proto; /*!< from transport */
+	str* path;
+	time_t expires;
+	str* callid;
+	str* public_ids;
+	int num_public_ids;
+	str* service_routes;
+	int num_service_routes;
+	str* rx_regsession_id;
+	enum pcontact_reg_states reg_state;
+}pcontact_info_t;
+
+/*! \brief
+ * Basic hash table element
+ */
+typedef struct pcontact {
+	unsigned int aorhash; 					/*!< Hash over address of record */
+	struct hslot* slot; 					/*!< Collision slot in the hash table array we belong to */
+	str* domain; 							/*!< Pointer to domain we belong to (null terminated string) */
+	str aor;			 					/*!< Address of record */
+	// str received;           				/*!< IP+port+protocol we received the REGISTER from */
+	str received_host;
+	unsigned short received_port;
+	unsigned short received_proto; /*!< from transport */ ;
+	str path;               				/*!< Path header */
+	str rx_session_id;						/*!< Rx Session ID for registration Rx AF session - not used if not using diameter_rx */
+	enum pcontact_reg_states reg_state;		/*!< Reg state of contact */
+	time_t expires;							/*!< expires time for contact */
+	str* service_routes;					/*!< Array of service routes */
+	unsigned short num_service_routes;		/*!< Number of service routes */
+	ppublic_t* head;						/*!< list of associated public identities */
+	ppublic_t* tail;
+	struct socket_info *sock; 				/*!< received socket */
+	struct ulcb_head_list cbs;				/*!< contact callback list */
+	struct pcontact* prev; 					/*!< Next item in the hash entry */
+	struct pcontact* next; 					/*!< Previous item in the hash entry */
+} pcontact_t;
+
+typedef int (*get_pcontact_t)(struct udomain* _d, str* _contact, struct pcontact** _c);
+
+typedef int (*get_pcontact_by_src_t)(struct udomain* _d, str * _host, unsigned short _port, unsigned short _proto, struct pcontact** _c);
+
+typedef int (*insert_pcontact_t)(struct udomain* _d, str* _aor, struct pcontact_info* ci, struct pcontact** _c);
+typedef int (*delete_pcontact_t)(struct udomain* _d, str* _aor, struct pcontact* _c);
+typedef int (*update_pcontact_t)(struct udomain* _d, struct pcontact_info* ci, struct pcontact* _c);
+typedef int (*update_rx_regsession_t)(struct udomain* _d, str* session_id, struct pcontact* _c);
+
+typedef void (*lock_udomain_t)(struct udomain* _d, str *_aor);
+typedef void (*unlock_udomain_t)(struct udomain* _d, str *_aor);
+typedef int (*register_udomain_t)(const char* _n, struct udomain** _d);
+typedef int (*get_udomain_t)(const char* _n, udomain_t** _d);
+typedef int (*get_all_ucontacts_t)(void* buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max);
+
+/*! usrloc API export structure */
+typedef struct usrloc_api {
+	int use_domain; /*! use_domain module parameter */
+	int db_mode; /*! db_mode module parameter */
+
+	register_udomain_t register_udomain;
+	get_udomain_t get_udomain;
+	lock_udomain_t lock_udomain;
+	unlock_udomain_t unlock_udomain;
+
+	insert_pcontact_t insert_pcontact;
+	delete_pcontact_t delete_pcontact;
+	get_pcontact_t get_pcontact;
+	get_pcontact_by_src_t get_pcontact_by_src;
+
+	update_pcontact_t update_pcontact;
+	update_rx_regsession_t update_rx_regsession;
+	get_all_ucontacts_t get_all_ucontacts;
+
+	register_ulcb_t register_ulcb;
+} usrloc_api_t;
+
+/*! usrloc API export bind function */
+typedef int (*bind_usrloc_t)(usrloc_api_t* api);
+
+#endif

+ 53 - 0
modules/usrloc_pcscf/utime.c

@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "utime.h"
+
+time_t act_time;
+
+void get_act_time(void)
+{
+	act_time = time(0);
+}

+ 55 - 0
modules/usrloc_pcscf/utime.h

@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * Copyright (C) 2012 Smile Communications, [email protected]
+ * 
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Fokus. 
+ * Copyright (C) 2004-2006 FhG Fokus
+ * Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef UTIME_H
+#define UTIME_H
+
+#include <time.h>
+
+extern time_t act_time;
+
+void get_act_time(void);
+
+#endif /* UTIME_H */