mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
407 lines
8.7 KiB
407 lines
8.7 KiB
/*
|
|
* $Id$
|
|
*
|
|
* Usrloc module interface
|
|
*
|
|
* Copyright (C) 2001-2003 FhG Fokus
|
|
*
|
|
* This file is part of ser, a free SIP server.
|
|
*
|
|
* ser 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
|
|
*
|
|
* For a license to use the ser software under conditions
|
|
* other than those described here, or to purchase support for this
|
|
* software, please contact iptel.org by e-mail at the following addresses:
|
|
* info@iptel.org
|
|
*
|
|
* ser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "../../dprint.h"
|
|
#include "../../ut.h"
|
|
#include "../../globals.h"
|
|
#include "dlist.h"
|
|
#include "utime.h"
|
|
#include "ul_mod.h"
|
|
#include "ul_rpc.h"
|
|
|
|
|
|
static inline void rpc_find_domain(str* _name, udomain_t** _d)
|
|
{
|
|
dlist_t* ptr;
|
|
|
|
ptr = root;
|
|
while(ptr) {
|
|
if ((ptr->name.len == _name->len) &&
|
|
!memcmp(ptr->name.s, _name->s, _name->len)) {
|
|
break;
|
|
}
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
if (ptr) {
|
|
*_d = ptr->d;
|
|
} else {
|
|
*_d = 0;
|
|
}
|
|
}
|
|
|
|
static inline int add_contact(udomain_t* _d, str* _u, str* _c, time_t _e, qvalue_t _q, int _f, int sid)
|
|
{
|
|
urecord_t* r;
|
|
ucontact_t* c = 0;
|
|
int res;
|
|
str cid;
|
|
str ua;
|
|
str aor = STR_NULL;
|
|
|
|
if (_e == 0 && !(_f & FL_PERMANENT)) {
|
|
LOG(L_ERR, "rpc_add_contact(): expires == 0 and not persistent contact, giving up\n");
|
|
return -1;
|
|
}
|
|
|
|
get_act_time();
|
|
|
|
res = get_urecord(_d, _u, &r);
|
|
if (res < 0) {
|
|
LOG(L_ERR, "rpc_add_contact(): Error while getting record\n");
|
|
return -2;
|
|
}
|
|
|
|
if (res > 0) { /* Record not found */
|
|
if (insert_urecord(_d, _u, &r) < 0) {
|
|
LOG(L_ERR, "rpc_add_contact(): Error while creating new urecord\n");
|
|
return -3;
|
|
}
|
|
} else {
|
|
if (get_ucontact(r, _c, &c) < 0) {
|
|
LOG(L_ERR, "rpc_add_contact(): Error while obtaining ucontact\n");
|
|
return -4;
|
|
}
|
|
}
|
|
|
|
cid.s = "RPC-Call-ID";
|
|
cid.len = strlen(cid.s);
|
|
|
|
ua.s = "SER-RPC";
|
|
ua.len = strlen(ua.s);
|
|
|
|
if (c) {
|
|
if (update_ucontact(c, &aor, _c, _e + act_time, _q, &cid, 42, _f, FL_NONE, &ua, 0, 0, 0,
|
|
sid == -1 ? server_id : sid) < 0) {
|
|
LOG(L_ERR, "rpc_add_contact(): Error while updating contact\n");
|
|
release_urecord(r);
|
|
return -5;
|
|
}
|
|
} else {
|
|
if (insert_ucontact(r, &aor, _c, _e + act_time, _q, &cid, 42, _f, &c, &ua, 0, 0, 0,
|
|
sid == -1 ? server_id : sid) < 0) {
|
|
LOG(L_ERR, "rpc_add_contact(): Error while inserting contact\n");
|
|
release_urecord(r);
|
|
return -6;
|
|
}
|
|
}
|
|
|
|
release_urecord(r);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static const char* rpc_stats_doc[2] = {
|
|
"Print usrloc statistics",
|
|
0
|
|
};
|
|
|
|
static void rpc_stats(rpc_t* rpc, void* c)
|
|
{
|
|
dlist_t* ptr;
|
|
void* handle;
|
|
|
|
ptr = root;
|
|
while(ptr) {
|
|
rpc->add(c, "{", &handle);
|
|
rpc->struct_add(handle, "Sdd",
|
|
"domain", ptr->d->name,
|
|
"users", ptr->d->users,
|
|
"expired", ptr->d->expired);
|
|
ptr = ptr->next;
|
|
}
|
|
}
|
|
|
|
|
|
static const char* rpc_delete_uid_doc[2] = {
|
|
"Delete all registered contacts for address of record.",
|
|
0
|
|
};
|
|
|
|
|
|
static void rpc_delete_uid(rpc_t* rpc, void* c)
|
|
{
|
|
udomain_t* d;
|
|
str uid, t;
|
|
|
|
if (rpc->scan(c, "SS", &t, &uid) < 2) return;
|
|
|
|
rpc_find_domain(&t, &d);
|
|
if (d) {
|
|
lock_udomain(d);
|
|
if (delete_urecord(d, &uid) < 0) {
|
|
ERR("Error while deleting user %.*s\n", uid.len, uid.s);
|
|
unlock_udomain(d);
|
|
rpc->fault(c, 500, "Error While Deleting Record");
|
|
return;
|
|
}
|
|
unlock_udomain(d);
|
|
} else {
|
|
rpc->fault(c, 400, "Table Not Found");
|
|
}
|
|
}
|
|
|
|
|
|
static const char* rpc_delete_contact_doc[2] = {
|
|
"Delete a contact if it exists.",
|
|
0
|
|
};
|
|
|
|
|
|
static void rpc_delete_contact(rpc_t* rpc, void* ctx)
|
|
{
|
|
udomain_t* d;
|
|
urecord_t* r;
|
|
ucontact_t* con;
|
|
str uid, t, c;
|
|
int res;
|
|
|
|
if (rpc->scan(ctx, "SSS", &t, &uid, &c) < 3) return;
|
|
|
|
rpc_find_domain(&t, &d);
|
|
|
|
if (d) {
|
|
lock_udomain(d);
|
|
|
|
res = get_urecord(d, &uid, &r);
|
|
if (res < 0) {
|
|
rpc->fault(ctx, 500, "Error While Searching Table");
|
|
ERR("Error while looking for uid %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s);
|
|
unlock_udomain(d);
|
|
return;
|
|
}
|
|
|
|
if (res > 0) {
|
|
rpc->fault(ctx, 404, "AOR Not Found");
|
|
unlock_udomain(d);
|
|
return;
|
|
}
|
|
|
|
res = get_ucontact(r, &c, &con);
|
|
if (res < 0) {
|
|
rpc->fault(ctx, 500, "Error While Searching for Contact");
|
|
ERR("Error while looking for contact %.*s\n", c.len, c.s);
|
|
unlock_udomain(d);
|
|
return;
|
|
}
|
|
|
|
if (res > 0) {
|
|
rpc->fault(ctx, 404, "Contact Not Found");
|
|
unlock_udomain(d);
|
|
return;
|
|
}
|
|
|
|
if (delete_ucontact(r, con) < 0) {
|
|
rpc->fault(ctx, 500, "Error While Deleting Contact");
|
|
unlock_udomain(d);
|
|
return;
|
|
}
|
|
|
|
release_urecord(r);
|
|
unlock_udomain(d);
|
|
} else {
|
|
rpc->fault(ctx, 404, "Table Not Found");
|
|
}
|
|
}
|
|
|
|
|
|
static const char* rpc_dump_doc[2] = {
|
|
"Print all registered contacts.",
|
|
0
|
|
};
|
|
|
|
|
|
static void rpc_dump(rpc_t* rpc, void* c)
|
|
{
|
|
rpc->fault(c, 500, "Not Yet Implemented");
|
|
}
|
|
|
|
static const char* rpc_dump_file_doc[2] = {
|
|
"Print all registered contacts into a file.",
|
|
0
|
|
};
|
|
|
|
|
|
static void rpc_dump_file(rpc_t* rpc, void* c)
|
|
{
|
|
str filename;
|
|
FILE *file;
|
|
|
|
if (rpc->scan(c, "S", &filename) < 1) {
|
|
return;
|
|
}
|
|
|
|
DBG("dumping to file '%.*s'.\n", filename.len, ZSW(filename.s));
|
|
if (! (file = fopen(filename.s, "w"))) {
|
|
ERR("failed to open file `%s'.\n", filename.s);
|
|
rpc->fault(rpc, 500, "failed to open file `%s'.\n", filename.s);
|
|
return;
|
|
}
|
|
print_all_udomains(file);
|
|
fclose(file);
|
|
}
|
|
|
|
|
|
static const char* rpc_flush_doc[2] = {
|
|
"Flush cache into database.",
|
|
0
|
|
};
|
|
|
|
static void rpc_flush(rpc_t* rpc, void* c)
|
|
{
|
|
synchronize_all_udomains();
|
|
}
|
|
|
|
|
|
static const char* rpc_add_contact_doc[2] = {
|
|
"Create a new contact.",
|
|
0
|
|
};
|
|
|
|
|
|
static void rpc_add_contact(rpc_t* rpc, void* c)
|
|
{
|
|
udomain_t* d;
|
|
int expires, flags, sid;
|
|
double q;
|
|
qvalue_t qval;
|
|
|
|
str table, uid, contact;
|
|
|
|
if (rpc->scan(c, "SSSdfd", &table, &uid, &contact, &expires, &q, &flags) < 6) return;
|
|
qval = double2q(q);
|
|
if (rpc->scan(c, "d", &sid) < 1) sid = -1;
|
|
|
|
rpc_find_domain(&table, &d);
|
|
if (d) {
|
|
lock_udomain(d);
|
|
|
|
if (add_contact(d, &uid, &contact, expires, qval, flags, sid) < 0) {
|
|
unlock_udomain(d);
|
|
ERR("Error while adding contact ('%.*s','%.*s') in table '%.*s'\n",
|
|
uid.len, ZSW(uid.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
|
|
rpc->fault(c, 500, "Error while adding Contact");
|
|
return;
|
|
}
|
|
unlock_udomain(d);
|
|
} else {
|
|
rpc->fault(c, 400, "Table Not Found");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Build Contact HF for reply
|
|
*/
|
|
static inline int print_contacts(rpc_t* rpc, void* ctx, ucontact_t* _c)
|
|
{
|
|
int cnt = 0;
|
|
void* handle;
|
|
|
|
while(_c) {
|
|
if (VALID_CONTACT(_c, act_time)) {
|
|
cnt++;
|
|
|
|
if (rpc->add(ctx, "{", &handle) < 0) return -1;
|
|
rpc->struct_add(handle, "SfdSS",
|
|
"contact", &_c->c,
|
|
"q", q2double(_c->q),
|
|
"expires", (int)(_c->expires - act_time),
|
|
"ua", &_c->user_agent,
|
|
"recv", &_c->received);
|
|
}
|
|
|
|
_c = _c->next;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
|
|
static const char* rpc_show_contacts_doc[2] = {
|
|
"List all registered contacts for address of record",
|
|
0
|
|
};
|
|
|
|
static void rpc_show_contacts(rpc_t* rpc, void* c)
|
|
{
|
|
udomain_t* d;
|
|
urecord_t* r;
|
|
int res;
|
|
str t, uid;
|
|
|
|
if (rpc->scan(c, "SS", &t, &uid) < 2) return;
|
|
|
|
rpc_find_domain(&t, &d);
|
|
if (d) {
|
|
lock_udomain(d);
|
|
|
|
res = get_urecord(d, &uid, &r);
|
|
if (res < 0) {
|
|
rpc->fault(c, 500, "Error While Searching AOR");
|
|
ERR("Error while looking for username %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s);
|
|
unlock_udomain(d);
|
|
return;
|
|
}
|
|
|
|
if (res > 0) {
|
|
rpc->fault(c, 404, "AOR Not Found");
|
|
unlock_udomain(d);
|
|
return;
|
|
}
|
|
|
|
get_act_time();
|
|
|
|
if (!print_contacts(rpc, c, r->contacts)) {
|
|
unlock_udomain(d);
|
|
rpc->fault(c, 404, "No Registered Contacts Found");
|
|
return;
|
|
}
|
|
|
|
unlock_udomain(d);
|
|
} else {
|
|
rpc->fault(c, 400, "Table Not Found");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
rpc_export_t ul_rpc[] = {
|
|
{"usrloc.stats", rpc_stats, rpc_stats_doc, RET_ARRAY},
|
|
{"usrloc.delete_uid", rpc_delete_uid, rpc_delete_uid_doc, 0},
|
|
{"usrloc.delete_contact", rpc_delete_contact, rpc_delete_contact_doc, 0},
|
|
{"usrloc.dump", rpc_dump, rpc_dump_doc, 0},
|
|
{"usrloc.dump_file", rpc_dump_file, rpc_dump_file_doc, 0},
|
|
{"usrloc.flush", rpc_flush, rpc_flush_doc, 0},
|
|
{"usrloc.add_contact", rpc_add_contact, rpc_add_contact_doc, 0},
|
|
{"usrloc.show_contacts", rpc_show_contacts, rpc_show_contacts_doc, RET_ARRAY},
|
|
{0, 0, 0, 0}
|
|
};
|