Backport usrloc RPC from master

Only change necessary has been delete the missing field last_keepalive
from rpc_dump_contact function.
pull/1/merge
Victor Seva 13 years ago
parent 124ceaf969
commit 621b3e27d0

@ -20,33 +20,186 @@
#include "../../ip_addr.h"
#include "../../dprint.h"
#include "../../lib/srutils/sruid.h"
#include "ul_rpc.h"
#include "dlist.h"
#include "ucontact.h"
#include "udomain.h"
#include "ul_mod.h"
#include "utime.h"
/*! CSEQ nr used */
#define RPC_UL_CSEQ 1
/*! call-id used for ul_add and ul_rm_contact */
static str rpc_ul_cid = str_init("dfjrewr12386fd6-343@kamailio.mi");
/*! path used for ul_add and ul_rm_contact */
static str rpc_ul_path = str_init("dummypath");
/*! user agent used for ul_add */
static str rpc_ul_ua = str_init("SIP Router MI Server");
extern sruid_t _ul_sruid;
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;
t = time(0);
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-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;
dlist_t* dl;
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;
@ -55,7 +208,6 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
if(brief.len==5 && (strncmp(brief.s, "brief", 5)==0))
summary = 1;
t = time(0);
for( dl=root ; dl ; dl=dl->next ) {
dom = dl->d;
if (rpc->add(ctx, "{", &th) < 0)
@ -82,7 +234,6 @@ static void ul_rpc_dump(rpc_t* rpc, void* ctx)
if(rpc->struct_add(ah, "S",
"AoR", &r->aor)<0)
{
unlock_ulslot( dom, i);
rpc->fault(ctx, 500, "Internal error creating aor struct");
return;
}
@ -98,196 +249,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");
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");
if (rpc_dump_contact(rpc, ctx, ih, c) == -1) {
unlock_ulslot(dom, i);
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;
}
}
}
}
@ -296,8 +261,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;
@ -312,8 +276,362 @@ 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};
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;
}
static void ul_rpc_rm_aor(rpc_t* rpc, void* ctx)
{
udomain_t* dom;
str table = {0, 0};
str aor = {0, 0};
if (rpc->scan(ctx, "SS", &table, &aor) != 2) {
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);
if (delete_urecord( dom, &aor, 0) < 0) {
unlock_udomain( dom, &aor);
rpc->fault(ctx, 500, "Failed to delete AOR");
return;
}
unlock_udomain( dom, &aor);
return;
}
static const char* ul_rpc_rm_aor_doc[2] = {
"Delete a address of record including its contacts",
0
};
static void ul_rpc_rm_contact(rpc_t* rpc, void* ctx)
{
udomain_t* dom;
str table = {0, 0};
str aor = {0, 0};
str contact = {0, 0};
urecord_t *rec;
ucontact_t* con;
int ret;
if (rpc->scan(ctx, "SSS", &table, &aor, &contact) != 3) {
rpc->fault(ctx, 500, "Not enough parameters (table, AOR and contact)");
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, 404, "AOR not found");
return;
}
ret = get_ucontact( rec, &contact, &rpc_ul_cid, &rpc_ul_path, RPC_UL_CSEQ+1, &con);
if (ret < 0) {
unlock_udomain( dom, &aor);
rpc->fault(ctx, 500, "Internal error (can't get contact)");
return;
}
if (ret > 0) {
unlock_udomain( dom, &aor);
rpc->fault(ctx, 404, "Contact not found");
return;
}
if (delete_ucontact(rec, con) < 0) {
unlock_udomain( dom, &aor);
rpc->fault(ctx, 500, "Internal error (can't delete contact)");
return;
}
release_urecord(rec);
unlock_udomain( dom, &aor);
return;
}
static const char* ul_rpc_rm_contact_doc[2] = {
"Delete a contact from an AOR record",
0
};
static void ul_rpc_flush(rpc_t* rpc, void* ctx)
{
synchronize_all_udomains(0, 1);
return;
}
static const char* ul_rpc_flush_doc[2] = {
"Flush the usrloc memory cache to DB",
0
};
/*!
* \brief Add a new contact for an address of record
* \note Expects 9 parameters: table name, AOR, contact, expires, Q,
* useless - backward compatible, flags, cflags, methods
*/
static void ul_rpc_add(rpc_t* rpc, void* ctx)
{
str table = {0, 0};
str aor = {0, 0};
str contact = {0, 0};
str useless = {0, 0};
double dtemp;
ucontact_info_t ci;
urecord_t* r;
ucontact_t* c;
udomain_t *dom;
int ret;
memset( &ci, 0, sizeof(ucontact_info_t));
ret = rpc->scan(ctx, "SSSdf.Sddd", &table, &aor, &contact, &ci.expires,
&dtemp, &useless, &ci.flags, &ci.cflags, &ci.methods);
LM_DBG("ret: %d table:%.*s aor:%.*s contact:%.*s expires:%d dtemp:%f useless:%.*s flags:%d bflags:%d methods:%d\n",
ret, table.len, table.s, aor.len, aor.s, contact.len, contact.s,
(int) ci.expires, dtemp, useless.len, useless.s, ci.flags, ci.cflags, (int) ci.methods);
if ( ret != 9) {
rpc->fault(ctx, 500, "Not enough parameters or wrong format");
return;
}
ci.q = double2q(dtemp);
useless.s = q2str(ci.q, (unsigned int*)&useless.len);
LM_DBG("q:%.*s\n", useless.len, useless.s);
/* 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;
}
if(sruid_next(&_ul_sruid)<0)
{
rpc->fault(ctx, 500, "Can't obtain next uid");
return;
}
ci.ruid = _ul_sruid.uid;
lock_udomain( dom, &aor);
ret = get_urecord( dom, &aor, &r);
if(ret==1) {
if (insert_urecord( dom, &aor, &r) < 0)
{
unlock_udomain( dom, &aor);
rpc->fault(ctx, 500, "Can't insert record");
return;
}
c = 0;
} else {
if (get_ucontact( r, &contact, &rpc_ul_cid, &rpc_ul_path, RPC_UL_CSEQ+1, &c) < 0)
{
unlock_udomain( dom, &aor);
rpc->fault(ctx, 500, "Can't get record");
return;
}
}
get_act_time();
ci.callid = &rpc_ul_cid;
ci.user_agent = &rpc_ul_ua;
ci.cseq = RPC_UL_CSEQ;
/* 0 expires means permanent contact */
if (ci.expires!=0)
ci.expires += act_time;
if (c) {
if (update_ucontact( r, c, &ci) < 0)
{
release_urecord(r);
unlock_udomain( dom, &aor);
rpc->fault(ctx, 500, "Can't update contact");
return;
}
} else {
if ( insert_ucontact( r, &contact, &ci, &c) < 0 )
{
release_urecord(r);
unlock_udomain( dom, &aor);
rpc->fault(ctx, 500, "Can't insert contact");
return;
}
}
release_urecord(r);
unlock_udomain( dom, &aor);
return;
}
static const char* ul_rpc_add_doc[2] = {
"Add a new contact for an address of record",
0
};
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},
{"ul.rm", ul_rpc_rm_aor, ul_rpc_rm_aor_doc, 0},
{"ul.rm_contact", ul_rpc_rm_contact, ul_rpc_rm_contact_doc, 0},
{"ul.flush", ul_rpc_flush, ul_rpc_flush_doc, 0},
{"ul.add", ul_rpc_add, ul_rpc_add_doc, 0},
{0, 0, 0, 0}
};

Loading…
Cancel
Save