Added possibility to modify parameters in call.route message.
Added option to call alternatives for an account. Improved reload. git-svn-id: http://yate.null.ro/svn/yate/trunk@3378 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
78d100265f
commit
4eb1b4bbfe
|
@ -16,10 +16,36 @@
|
|||
;
|
||||
; route: int: Priority of the call.route handler
|
||||
;route=100
|
||||
;
|
||||
; file: string. An auxiliary conf file used to save and load from it autocreated and registered entries
|
||||
; If file don't exists the registered entities will be lost on reload
|
||||
;file=filename
|
||||
|
||||
|
||||
; you have to put username as a category and password into key password
|
||||
; if password is missing the module will only register but not authenticate
|
||||
; if password exists and is empty will blindly authenticate anybody
|
||||
|
||||
|
||||
;[username]
|
||||
;password=something
|
||||
|
||||
; alternatives: list of called party numbers separated by coma
|
||||
; Note if multiple users share the same party number the call will go to all users.
|
||||
;alternatives= num1,num2,....
|
||||
;
|
||||
; Set/Modify call.route parameters when the caller matches this section
|
||||
; You can put call.route replacement ${variables} on the right side
|
||||
; Note: Any parameter except for "password" and "alternatives" will be used for set/modify
|
||||
;
|
||||
; Ex:
|
||||
; Modify caller name
|
||||
;callername=name
|
||||
;
|
||||
; Modify caller number
|
||||
;caller=number
|
||||
;
|
||||
; Replacement example
|
||||
;callername=John Doe from ${address}
|
||||
;
|
||||
;param=value
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Ask for a registration from this module.
|
||||
*
|
||||
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
||||
* Copyright (C) 2004-2006 Null Team
|
||||
* Copyright (C) 2004-2010 Null Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -27,13 +27,6 @@
|
|||
using namespace TelEngine;
|
||||
namespace { // anonymous
|
||||
|
||||
Mutex lmutex(false,"RegFile");
|
||||
|
||||
static Configuration s_cfg(Engine::configFile("regfile"));
|
||||
|
||||
static const String s_general = "general";
|
||||
static bool s_create = false;
|
||||
|
||||
|
||||
class AuthHandler : public MessageHandler
|
||||
{
|
||||
|
@ -62,9 +55,11 @@ public:
|
|||
class RouteHandler : public MessageHandler
|
||||
{
|
||||
public:
|
||||
RouteHandler(const char *name, unsigned prio = 100)
|
||||
: MessageHandler(name,prio) { }
|
||||
RouteHandler(const char *name, unsigned prio = 100);
|
||||
~RouteHandler();
|
||||
virtual bool received(Message &msg);
|
||||
private:
|
||||
ObjList* m_skip;
|
||||
};
|
||||
|
||||
class StatusHandler : public MessageHandler
|
||||
|
@ -75,144 +70,308 @@ public:
|
|||
virtual bool received(Message &msg);
|
||||
};
|
||||
|
||||
class ExpireHandler : public MessageHandler
|
||||
{
|
||||
public:
|
||||
ExpireHandler()
|
||||
: MessageHandler("engine.timer",100) { }
|
||||
virtual bool received(Message &msg);
|
||||
};
|
||||
|
||||
class ExpandedUser : public ObjList
|
||||
{
|
||||
public:
|
||||
inline ExpandedUser(const String& username)
|
||||
: m_username(username) {}
|
||||
virtual const String& toString () const
|
||||
{ return m_username; }
|
||||
private:
|
||||
String m_username;
|
||||
};
|
||||
|
||||
class RegfilePlugin : public Plugin
|
||||
{
|
||||
public:
|
||||
RegfilePlugin();
|
||||
~RegfilePlugin(){}
|
||||
~RegfilePlugin();
|
||||
virtual void initialize();
|
||||
void populate();
|
||||
private:
|
||||
AuthHandler *m_authhandler;
|
||||
bool m_init;
|
||||
};
|
||||
|
||||
|
||||
Mutex s_mutex(false,"RegFile");
|
||||
|
||||
static Configuration s_cfg(Engine::configFile("regfile"));
|
||||
static Configuration s_accounts;
|
||||
static bool s_create = false;
|
||||
static const String s_general = "general";
|
||||
static ObjList s_expand;
|
||||
|
||||
bool expired(const NamedList& list, unsigned int time)
|
||||
{
|
||||
// If eTime is 0 the registration will never expire
|
||||
unsigned int eTime = list.getIntValue("expires",0);
|
||||
return eTime && eTime < time;
|
||||
}
|
||||
|
||||
bool AuthHandler::received(Message &msg)
|
||||
{
|
||||
String username(msg.getValue("username"));
|
||||
if (username.null() || username == s_general)
|
||||
return false;
|
||||
const NamedList* sect = s_cfg.getSection(username);
|
||||
if (sect) {
|
||||
const String* pass = sect->getParam("password");
|
||||
if (!pass)
|
||||
return false;
|
||||
msg.retValue() = *pass;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Lock lock(s_mutex);
|
||||
const NamedList* usr = s_cfg.getSection(username);
|
||||
if (!usr)
|
||||
return false;
|
||||
const String* pass = usr->getParam("password");
|
||||
if (!pass)
|
||||
return false;
|
||||
msg.retValue() = *pass;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegistHandler::received(Message &msg)
|
||||
{
|
||||
String username(msg.getValue("username"));
|
||||
if (username.null() || username == s_general)
|
||||
return false;
|
||||
|
||||
const char *driver = msg.getValue("driver");
|
||||
const char *data = msg.getValue("data");
|
||||
const char* driver = msg.getValue("driver");
|
||||
const char* data = msg.getValue("data");
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
Lock lock(lmutex);
|
||||
Lock lock(s_mutex);
|
||||
int expire = msg.getIntValue("expires",0);
|
||||
NamedList* sect = s_cfg.getSection(username);
|
||||
if (s_create && !sect) {
|
||||
Debug("RegFile",DebugNote,"Auto creating new user '%s'",username.c_str());
|
||||
s_cfg.createSection(username);
|
||||
sect = s_cfg.getSection(username);
|
||||
sect = new NamedList(username);
|
||||
Debug("RegFile",DebugInfo,"Auto creating new user %s",username.c_str());
|
||||
}
|
||||
if (sect) {
|
||||
Debug("RegFile",DebugInfo,"Registered '%s' via '%s'",username.c_str(),data);
|
||||
sect->setParam("driver",driver);
|
||||
sect->setParam("data",data);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (!sect)
|
||||
return false;
|
||||
s_accounts.createSection(*sect);
|
||||
NamedList* s = s_accounts.getSection(*sect);
|
||||
if (driver)
|
||||
s->setParam("driver",driver);
|
||||
s->setParam("data",data);
|
||||
if (expire)
|
||||
s->setParam("expires",String(msg.msgTime().sec() + expire));
|
||||
Debug("RegFile",DebugAll,"Registered user %s via %s",username.c_str(),data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnRegistHandler::received(Message &msg)
|
||||
{
|
||||
String username(msg.getValue("username"));
|
||||
if (username.null() || username == s_general)
|
||||
return false;
|
||||
|
||||
Lock lock(lmutex);
|
||||
if (s_cfg.getSection(username)) {
|
||||
Debug("RegFile",DebugInfo,"Unregistered '%s'",username.c_str());
|
||||
s_cfg.clearKey(username,"data");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Lock lock(s_mutex);
|
||||
NamedList* nl = s_accounts.getSection(username);
|
||||
if (!nl)
|
||||
return false;
|
||||
Debug("RegFile",DebugAll,"Removing user %s, reson unregistered",username.c_str());
|
||||
s_accounts.clearSection(username);
|
||||
return true;
|
||||
}
|
||||
|
||||
RouteHandler::RouteHandler(const char *name, unsigned prio)
|
||||
: MessageHandler(name,prio)
|
||||
{
|
||||
m_skip = String("alternatives,password").split(',');
|
||||
}
|
||||
|
||||
RouteHandler::~RouteHandler()
|
||||
{
|
||||
TelEngine::destruct(m_skip);
|
||||
}
|
||||
|
||||
bool RouteHandler::received(Message &msg)
|
||||
{
|
||||
String user = msg.getValue("caller");
|
||||
Lock lock(s_mutex);
|
||||
NamedList* params = 0;
|
||||
if (user) {
|
||||
params = s_cfg.getSection(user);
|
||||
if (params) {
|
||||
unsigned int n = params->length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
const NamedString* s = params->getParam(i);
|
||||
if (s && !m_skip->find(s->name())) {
|
||||
String value = *s;
|
||||
msg.replaceParams(value);
|
||||
msg.setParam(s->name(),value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String username(msg.getValue("called"));
|
||||
if (username.null() || username == s_general)
|
||||
return false;
|
||||
|
||||
Lock lock(lmutex);
|
||||
const NamedList* sect = s_cfg.getSection(username);
|
||||
if (sect) {
|
||||
const char* data = sect->getValue("data");
|
||||
if (data) {
|
||||
Debug("RegFile",DebugInfo,"Routed '%s' via '%s'",username.c_str(),data);
|
||||
msg.retValue() = data;
|
||||
msg.setParam("driver",sect->getValue("driver"));
|
||||
return true;
|
||||
NamedList* ac = s_accounts.getSection(username);
|
||||
while (true) {
|
||||
String data;
|
||||
if (!ac) {
|
||||
if (s_cfg.getSection(username))
|
||||
break;
|
||||
ObjList* o = s_expand.find(username);
|
||||
if (!o)
|
||||
break;
|
||||
ExpandedUser* eu = static_cast<ExpandedUser*>(o->get());
|
||||
if (!eu)
|
||||
break;
|
||||
String d;
|
||||
int count = 0;
|
||||
for (ObjList* ob = eu->skipNull(); ob;ob = ob->skipNext()) {
|
||||
String* s = static_cast<String*>(ob->get());
|
||||
if (!s)
|
||||
continue;
|
||||
NamedList* n = s_accounts.getSection(*s);
|
||||
if (!n)
|
||||
continue;
|
||||
if (count > 0)
|
||||
d << " ";
|
||||
d << n->getValue("data");
|
||||
count ++;
|
||||
}
|
||||
if (count > 1)
|
||||
data = "fork ";
|
||||
data << d;
|
||||
} else {
|
||||
data = ac->getValue("data");
|
||||
msg.copyParams(*ac,"driver");
|
||||
}
|
||||
// signal to other modules we know about this user but it's offline
|
||||
msg.setParam("error","offline");
|
||||
msg.retValue() = data;
|
||||
Debug("RegFile",DebugInfo,"Routed '%s' via '%s'",username.c_str(),data.c_str());
|
||||
return true;
|
||||
}
|
||||
msg.setParam("error","offline");
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
static int s_count = 0;
|
||||
|
||||
bool ExpireHandler::received(Message &msg)
|
||||
{
|
||||
if ((s_count = (s_count+1) % 30)) // Check for timeouts once at 30 seconds
|
||||
return false;
|
||||
u_int64_t time = msg.msgTime().sec();
|
||||
Lock lock(s_mutex);
|
||||
int count = s_accounts.sections();
|
||||
for (int i = 0;i < count;) {
|
||||
NamedList* sec = s_accounts.getSection(i);
|
||||
if (sec && *sec != s_general && expired(*sec,time)) {
|
||||
Debug("RegFile",DebugAll,"Removing user %s, Reson: Registration expired",sec->c_str());
|
||||
s_accounts.clearSection(*sec);
|
||||
count--;
|
||||
} else
|
||||
i++;
|
||||
}
|
||||
if (s_accounts)
|
||||
s_accounts.save();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StatusHandler::received(Message &msg)
|
||||
{
|
||||
bool first = true;
|
||||
String dest(msg.getValue("module"));
|
||||
if (dest && (dest != "regfile") && (dest != "misc"))
|
||||
return false;
|
||||
Lock lock(lmutex);
|
||||
unsigned int n = s_cfg.sections();
|
||||
if (!s_cfg.getSection(0))
|
||||
--n;
|
||||
msg.retValue() << "name=regfile,type=misc;users=" << n << ",create=" << s_create;
|
||||
if (msg.getBoolValue("details",true)) {
|
||||
msg.retValue() << ";";
|
||||
bool first = true;
|
||||
for (unsigned int i=0;i<s_cfg.sections();i++) {
|
||||
NamedList *user = s_cfg.getSection(i);
|
||||
if (!user || (*user == s_general))
|
||||
continue;
|
||||
const char* data = s_cfg.getValue(*user,"data");
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
msg.retValue() << ",";
|
||||
msg.retValue() << *user << "=" << (data ? data : "offline");
|
||||
}
|
||||
return false;
|
||||
Lock lock(s_mutex);
|
||||
msg.retValue() << "name=regfile,type=misc;users=" << s_accounts.sections() << ";";
|
||||
unsigned int count = s_accounts.sections();
|
||||
for (unsigned int i = 0;i < count; i ++) {
|
||||
NamedList* ac = s_accounts.getSection(i);
|
||||
if (!ac)
|
||||
continue;
|
||||
const String data = ac->getValue("data");
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
msg.retValue() << ",";
|
||||
if (data)
|
||||
msg.retValue() << *ac << "=" << data;
|
||||
}
|
||||
msg.retValue() << "\r\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
RegfilePlugin::RegfilePlugin()
|
||||
: m_authhandler(0)
|
||||
: m_init(false)
|
||||
{
|
||||
Output("Loaded module Registration from file");
|
||||
}
|
||||
|
||||
RegfilePlugin::~RegfilePlugin()
|
||||
{
|
||||
Output("Unload module Registration from file");
|
||||
if (s_accounts)
|
||||
s_accounts.save();
|
||||
}
|
||||
|
||||
void RegfilePlugin::initialize()
|
||||
{
|
||||
Output("Initializing module Register for file");
|
||||
if (!m_authhandler) {
|
||||
s_cfg.load();
|
||||
s_create = s_cfg.getBoolValue("general","autocreate");
|
||||
Engine::install(m_authhandler = new AuthHandler("user.auth",s_cfg.getIntValue("general","auth",100)));
|
||||
Output("Initializing module Register from file");
|
||||
Lock lock(s_mutex);
|
||||
s_cfg.load();
|
||||
if (!m_init) {
|
||||
m_init = true;
|
||||
s_create = s_cfg.getBoolValue("general","autocreate",false);
|
||||
String conf = s_cfg.getValue("general","file");
|
||||
if (conf) {
|
||||
s_accounts = conf;
|
||||
s_accounts.load();
|
||||
}
|
||||
Engine::install(new AuthHandler("user.auth",s_cfg.getIntValue("general","auth",100)));
|
||||
Engine::install(new RegistHandler("user.register",s_cfg.getIntValue("general","register",100)));
|
||||
Engine::install(new UnRegistHandler("user.unregister",s_cfg.getIntValue("general","register",100)));
|
||||
Engine::install(new RouteHandler("call.route",s_cfg.getIntValue("general","route",100)));
|
||||
Engine::install(new StatusHandler("engine.status"));
|
||||
Engine::install(new ExpireHandler());
|
||||
}
|
||||
populate();
|
||||
}
|
||||
|
||||
void RegfilePlugin::populate()
|
||||
{
|
||||
s_expand.clear();
|
||||
int count = s_cfg.sections();
|
||||
for (int i = 0;i < count; i++) {
|
||||
NamedList* nl = s_cfg.getSection(i);
|
||||
if (!nl || *nl == s_general)
|
||||
continue;
|
||||
String* ids = nl->getParam("alternatives");
|
||||
if (!ids)
|
||||
continue;
|
||||
ObjList* ob = ids->split(',');
|
||||
for (ObjList* o = ob->skipNull(); o;o = o->skipNext()) {
|
||||
String* sec = static_cast<String*>(o->get());
|
||||
if (!sec)
|
||||
continue;
|
||||
ObjList* ret = s_expand.find(*sec);
|
||||
ExpandedUser* eu = 0;
|
||||
if (!ret) {
|
||||
eu = new ExpandedUser(*sec);
|
||||
s_expand.append(eu);
|
||||
} else
|
||||
eu = static_cast<ExpandedUser*>(ret->get());
|
||||
eu->append(new String(*nl));
|
||||
}
|
||||
}
|
||||
if (s_create)
|
||||
return;
|
||||
count = s_accounts.sections();
|
||||
for (int i = 0;i < count;i++) {
|
||||
NamedList* nl = s_accounts.getSection(i);
|
||||
if (!nl)
|
||||
continue;
|
||||
if (s_cfg.getSection(*nl))
|
||||
continue;
|
||||
s_accounts.clearSection(*nl);
|
||||
count--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue