Browse Source

usrloc(k) Add RPC for AOR lookup

Copied from mi interface. RPC rocks!
Olle E. Johansson 12 years ago
parent
commit
2207618978
3 changed files with 311 additions and 210 deletions
  1. 12 0
      modules_k/usrloc/README
  2. 20 0
      modules_k/usrloc/doc/usrloc_admin.xml
  3. 279 210
      modules_k/usrloc/ul_rpc.c

+ 12 - 0
modules_k/usrloc/README

@@ -81,6 +81,7 @@ Bogdan-Andrei Iancu
         6. RPC Commands
 
               6.1. ul.dump
+              6.2. ul.lookup table AOR
 
         7. Statistics
 
@@ -207,6 +208,7 @@ Chapter 1. Admin Guide
    6. RPC Commands
 
         6.1. ul.dump
+        6.2. ul.lookup table AOR
 
    7. Statistics
 
@@ -798,6 +800,7 @@ modparam("usrloc", "xavp_contact", "ulattrs")
 6. RPC Commands
 
    6.1. ul.dump
+   6.2. ul.lookup table AOR
 
 6.1.  ul.dump
 
@@ -806,6 +809,15 @@ modparam("usrloc", "xavp_contact", "ulattrs")
    Parameters:
      * None.
 
+6.2.  ul.lookup table AOR
+
+   Looks up the contents of an AOR entry in the location table
+
+   Parameters:
+     * table name - table where the AOR resides (Ex: location).
+     * AOR - user AOR in username[@domain] format (domain must be supplied
+       only if use_domain option is on).
+
 7. Statistics
 
    7.1. users

+ 20 - 0
modules_k/usrloc/doc/usrloc_admin.xml

@@ -1012,6 +1012,26 @@ modparam("usrloc", "xavp_contact", "ulattrs")
 			</para></listitem>
 		</itemizedlist>
 	</section>
+	<section>
+		<title>
+		<function moreinfo="none">ul.lookup table AOR</function>
+		</title>
+		<para>
+		Looks up the contents of an AOR entry in the location table
+		</para>
+		<para>Parameters: </para>
+		<itemizedlist>
+			<listitem><para>
+				<emphasis>table name</emphasis> - table where the AOR
+				resides (Ex: location).
+			</para></listitem>
+			<listitem><para>
+				<emphasis>AOR</emphasis> - user AOR in username[@domain]
+				format (domain must be supplied only if use_domain option
+				is on).
+			</para></listitem>
+		</itemizedlist>
+	</section>
 	</section><!-- RPC commands -->
 
 

+ 279 - 210
modules_k/usrloc/ul_rpc.c

@@ -25,12 +25,162 @@
 #include "dlist.h"
 #include "ucontact.h"
 #include "udomain.h"
+#include "ul_mod.h"
+#include "utime.h"
 
 static const char* ul_rpc_dump_doc[2] = {
 	"Dump user location tables",
 	0
 };
 
+
+int rpc_dump_contact(rpc_t* rpc, void* ctx, void *ih, ucontact_t* c)
+{
+	void* vh;
+	str empty_str = {"[not set]", 9};
+	str state_str = {"[not set]", 9};
+	str socket_str = {"[not set]", 9};
+	time_t t;
+
+	if(rpc->struct_add(ih, "{", "Contact", &vh)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error creating contact struct");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "Address", &c->c)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding addr");
+		return -1;
+	}
+	if (c->expires == 0) { if(rpc->struct_add(vh, "s", "Expires", "permanent")<0)
+	{
+			rpc->fault(ctx, 500, "Internal error adding expire");
+			return -1;
+	}
+	} else if (c->expires == UL_EXPIRED_TIME) {
+		if(rpc->struct_add(vh, "s", "Expires", "deleted")<0)
+		{
+			rpc->fault(ctx, 500, "Internal error adding expire");
+			return -1;
+		}
+	} else if (t > c->expires) {
+		if(rpc->struct_add(vh, "s", "Expires", "expired")<0)
+		{
+			rpc->fault(ctx, 500, "Internal error adding expire");
+			return -1;
+		}
+	} else {
+		if(rpc->struct_add(vh, "d", "Expires", (int)(c->expires - t))<0)
+		{
+			rpc->fault(ctx, 500, "Internal error adding expire");
+			return -1;
+		}
+	}
+	if (c->state == CS_NEW) {
+		state_str.s = "CS_NEW";
+		state_str.len = 6;
+	} else if (c->state == CS_SYNC) {
+		state_str.s = "CS_SYNC";
+		state_str.len = 7;
+	} else if (c->state== CS_DIRTY) {
+		state_str.s = "CS_DIRTY";
+		state_str.len = 8;
+	} else {
+		state_str.s = "CS_UNKNOWN";
+		state_str.len = 10;
+	}
+	if(c->sock)
+	{
+		socket_str.s = c->sock->sock_str.s;
+		socket_str.len = c->sock->sock_str.len;
+	}
+	if(rpc->struct_add(vh, "f", "Q", c->q)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding q");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "Call-ID", &c->callid)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding callid");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "CSeq", c->cseq)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding cseq");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "User-Agent",
+			(c->user_agent.len)?&c->user_agent: &empty_str)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding user-agent");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "Received",
+			(c->received.len)?&c->received: &empty_str)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding received");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "Path",
+			(c->path.len)?&c->path: &empty_str)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding path");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "State", &state_str)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding state");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "Flags", c->flags)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding flags");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "CFlags", c->cflags)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding cflags");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "Socket", &socket_str)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding socket");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "Methods", c->methods)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding methods");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "Ruid", (c->ruid.len)?&c->ruid: &empty_str)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding ruid");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "S", "Instance",
+			(c->instance.len)?&c->instance: &empty_str)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding instance");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "Reg-Id", c->reg_id)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding reg_id");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "Last-Keepalive", (int)c->last_keepalive)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding reg_id");
+		return -1;
+	}
+	if(rpc->struct_add(vh, "d", "Last-Modified", (int)c->last_modified)<0)
+	{
+		rpc->fault(ctx, 500, "Internal error adding reg_id");
+		return -1;
+	}
+	return 0;
+}
+
 static void ul_rpc_dump(rpc_t* rpc, void* ctx)
 {
 	struct urecord* r;
@@ -38,15 +188,11 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
 	udomain_t* dom;
 	time_t t;
 	str brief = {0, 0};
-	str empty_str = {"[not set]", 9};
-	str state_str = {"[not set]", 9};
-	str socket_str = {"[not set]", 9};
 	int summary = 0;
 	ucontact_t* c;
 	void* th;
 	void* ah;
 	void* ih;
-	void* vh;
 	void* sh;
 	int max, n, i;
 
@@ -98,212 +244,10 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
 					}
 					for( c=r->contacts ; c ; c=c->next)
 					{
-						if(rpc->struct_add(ih, "{",
-							"Contact", &vh)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500, "Internal error creating contact struct");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-									"Address", &c->c)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding addr");
-								return;
-						}
-						if (c->expires == 0) {
-							if(rpc->struct_add(vh, "s",
-									"Expires", "permanent")<0)
-							{
-								unlock_ulslot( dom, i);
-								rpc->fault(ctx, 500,
-										"Internal error adding expire");
-								return;
-							}
-						} else if (c->expires == UL_EXPIRED_TIME) {
-							if(rpc->struct_add(vh, "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(vh, "s",
-									"Expires", "expired")<0)
-							{
-								unlock_ulslot( dom, i);
-								rpc->fault(ctx, 500,
-										"Internal error adding expire");
-								return;
-							}
-						} else {
-							if(rpc->struct_add(vh, "d",
-									"Expires", (int)(c->expires - t))<0)
-							{
-								unlock_ulslot( dom, i);
-								rpc->fault(ctx, 500,
-										"Internal error adding expire");
-								return;
-							}
-						}
-						if (c->state == CS_NEW) {
-							state_str.s = "CS_NEW";
-							state_str.len = 6;
-						} else if (c->state == CS_SYNC) {
-							state_str.s = "CS_SYNC";
-							state_str.len = 7;
-						} else if (c->state== CS_DIRTY) {
-							state_str.s = "CS_DIRTY";
-							state_str.len = 8;
-						} else {
-							state_str.s = "CS_UNKNOWN";
-							state_str.len = 10;
-						}
-						if(c->sock)
-						{
-							socket_str.s = c->sock->sock_str.s;
-							socket_str.len = c->sock->sock_str.len;
-						}
-						if(rpc->struct_add(vh, "f",
-									"Q", c->q)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding q");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-									"Call-ID", &c->callid)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding callid");
-							return;
-						}
-						if(rpc->struct_add(vh, "d",
-									"CSeq", c->cseq)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding cseq");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-									"User-Agent",
-										(c->user_agent.len)?&c->user_agent:
-												&empty_str)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding user-agent");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-									"Received",
-										(c->received.len)?&c->received:
-												&empty_str)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding received");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-									"Path",
-										(c->path.len)?&c->path:
-												&empty_str)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding path");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-									"State", &state_str)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding state");
-							return;
-						}
-						if(rpc->struct_add(vh, "d",
-									"Flags", c->flags)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding flags");
+						if (rpc_dump_contact(rpc, ctx, ih, c) == -1) {
+							unlock_ulslot(dom, i);
 							return;
 						}
-						if(rpc->struct_add(vh, "d",
-									"CFlags", c->cflags)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding cflags");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-									"Socket", &socket_str)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding socket");
-							return;
-						}
-						if(rpc->struct_add(vh, "d",
-									"Methods", c->methods)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding methods");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-								"Ruid", (c->ruid.len)?&c->ruid: &empty_str)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding ruid");
-							return;
-						}
-						if(rpc->struct_add(vh, "S",
-								"Instance",
-								(c->instance.len)?&c->instance: &empty_str)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding instance");
-							return;
-						}
-						if(rpc->struct_add(vh, "d",
-									"Reg-Id", c->reg_id)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding reg_id");
-							return;
-						}
-						if(rpc->struct_add(vh, "d",
-									"Last-Keepalive", (int)c->last_keepalive)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding reg_id");
-							return;
-						}
-						if(rpc->struct_add(vh, "d",
-									"Last-Modified", (int)c->last_modified)<0)
-						{
-							unlock_ulslot( dom, i);
-							rpc->fault(ctx, 500,
-									"Internal error adding reg_id");
-							return;
-						}
-
 					}
 				}
 			}
@@ -312,8 +256,7 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
 		}
 
 		/* extra attributes node */
-		if(rpc->struct_add(th, "{",
-					"Stats",    &sh)<0)
+		if(rpc->struct_add(th, "{", "Stats",    &sh)<0)
 		{
 			rpc->fault(ctx, 500, "Internal error creating stats struct");
 			return;
@@ -328,8 +271,134 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
 	}
 }
 
+static const char* ul_rpc_lookup_doc[2] = {
+	"Lookup one AOR in the usrloc location table",
+	0
+};
+
+/*!
+ * \brief Search a domain in the global domain list
+ * \param table domain (table) name
+ * \return pointer to domain if found, 0 if not found
+ */
+static inline udomain_t* rpc_find_domain(str* table)
+{
+	dlist_t* dom;
+
+	for( dom=root ; dom ; dom=dom->next ) {
+		if ((dom->name.len == table->len) &&
+		!memcmp(dom->name.s, table->s, table->len))
+			return dom->d;
+	}
+	return 0;
+}
+
+/*!
+ * \brief Convert address of record
+ *
+ * Convert an address of record string to lower case, and truncate
+ * it when use_domain is not set.
+ * \param aor address of record
+ * \return 0 on success, -1 on error
+ */
+static inline int rpc_fix_aor(str *aor)
+{
+	char *p;
+
+	p = memchr( aor->s, '@', aor->len);
+	if (use_domain) {
+		if (p==NULL)
+			return -1;
+	} else {
+		if (p)
+			aor->len = p - aor->s;
+	}
+	strlower(aor);
+
+	return 0;
+}
+
+/*!
+ * \brief Dumps the contacts of an AOR
+ * \param rpc	Handle to RPC structure
+ * \param ctx not used
+ * \note expects 2 arguments: the table name and the AOR
+ */
+static void ul_rpc_lookup(rpc_t* rpc, void* ctx)
+{
+	udomain_t* dom;
+	str table = {0, 0};
+	str aor = {0, 0};
+	ucontact_t* c;
+	void* th;
+	urecord_t *rec;
+	ucontact_t* con;
+	int ret;
+	int rpl_tree;
+
+	if (rpc->scan(ctx, "S", &table) != 1) {
+		rpc->fault(ctx, 500, "Not enough parameters (table and AOR to lookup)");
+		return;
+	}
+	if (rpc->scan(ctx, "S", &aor) != 1) {
+		rpc->fault(ctx, 500, "Not enough parameters (table and AOR to lookup)");
+		return;
+	}
+
+	/* look for table */
+	dom = rpc_find_domain( &table );
+	if (dom == NULL) {
+		rpc->fault(ctx, 500, "Domain not found");
+		return;
+	}
+
+	/* process the aor */
+	if ( rpc_fix_aor(&aor) != 0 ) {
+		rpc->fault(ctx, 500, "Domain missing in AOR");
+		return;
+	}
+
+	lock_udomain( dom, &aor);
+
+	ret = get_urecord( dom, &aor, &rec);
+	if (ret == 1) {
+		unlock_udomain( dom, &aor);
+		rpc->fault(ctx, 500, "AOR not found in location table");
+		return;
+	}
+
+	get_act_time();
+	rpl_tree = 0;
+
+	if (rpc->add(ctx, "{", &th) < 0)
+	{
+		rpc->fault(ctx, 500, "Internal error creating outer rpc");
+		return;
+	}
+
+	/* We have contacts, list them */
+	for( con=rec->contacts ; con ; con=con->next) {
+		if (VALID_CONTACT( con, act_time)) {
+			rpl_tree++;
+			if (rpc_dump_contact(rpc, ctx, th, con) == -1) {
+				unlock_udomain(dom, &aor);
+				return;
+			}
+		}
+	}
+
+	unlock_udomain( dom, &aor);
+
+	if (rpl_tree==0) {
+		rpc->fault(ctx, 500, "AOR has no contacts");
+		return;
+	}
+	return;
+}
+
 rpc_export_t ul_rpc[] = {
 	{"ul.dump",   ul_rpc_dump,   ul_rpc_dump_doc,   0},
+	{"ul.lookup",   ul_rpc_lookup,   ul_rpc_lookup_doc,   0},
 	{0, 0, 0, 0}
 };