adds shutdownmode, in which calls are replied with defined err

based on a patch by Robert Szokovacs
sayer/1.4-spce2.6
Stefan Sayer 15 years ago
parent 8e2a4655eb
commit 7774944f12

@ -329,14 +329,21 @@ XMLRPC2DIServer::XMLRPC2DIServer(unsigned int port,
s(s),
// register method 'calls'
calls_method(s),
// register method 'get_loglevel'
setloglevel_method(s),
// register method 'set_loglevel'
getloglevel_method(s)
setloglevel_method(s),
// register method 'get_loglevel'
getloglevel_method(s),
// register method 'set_shutdownmode'
setshutdownmode_method(s),
// register method 'get_shutdownmode'
getshutdownmode_method(s)
{
DBG("XMLRPC Server: enabled builtin method 'calls'\n");
DBG("XMLRPC Server: enabled builtin method 'get_loglevel'\n");
DBG("XMLRPC Server: enabled builtin method 'set_loglevel'\n");
DBG("XMLRPC Server: enabled builtin method 'get_shutdownmode'\n");
DBG("XMLRPC Server: enabled builtin method 'set_shutdownmode'\n");
// export all methods via 'di' function?
if (di_export) {
@ -441,6 +448,18 @@ void XMLRPC2DIServerSetLoglevelMethod::execute(XmlRpcValue& params, XmlRpcValue&
result = "200 OK";
}
void XMLRPC2DIServerGetShutdownmodeMethod::execute(XmlRpcValue& params, XmlRpcValue& result) {
DBG("XMLRPC2DI: get_shutdownmode returns %s\n", AmConfig::ShutdownMode?"true":"false");
result = (bool)AmConfig::ShutdownMode;
}
void XMLRPC2DIServerSetShutdownmodeMethod::execute(XmlRpcValue& params, XmlRpcValue& result) {
AmConfig::ShutdownMode = params[0];
DBG("XMLRPC2DI: set shutdownmode to %s.\n", AmConfig::ShutdownMode?"true":"false");
result = "200 OK";
}
void XMLRPC2DIServerDIMethod::execute(XmlRpcValue& params, XmlRpcValue& result) {
try {
if (params.size() < 2) {

@ -57,6 +57,9 @@ DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerCallsMethod, "calls");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerSetLoglevelMethod, "set_loglevel");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetLoglevelMethod, "get_loglevel");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerSetShutdownmodeMethod, "set_shutdownmode");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetShutdownmodeMethod, "get_shutdownmode");
class XMLRPC2DIServerDIMethod
: public XmlRpcServerMethod {
@ -90,6 +93,8 @@ class XMLRPC2DIServer : public AmThread {
XMLRPC2DIServerCallsMethod calls_method;
XMLRPC2DIServerSetLoglevelMethod setloglevel_method;
XMLRPC2DIServerGetLoglevelMethod getloglevel_method;
XMLRPC2DIServerSetShutdownmodeMethod setshutdownmode_method;
XMLRPC2DIServerGetShutdownmodeMethod getshutdownmode_method;
XMLRPC2DIServerDIMethod* di_method;
void registerMethods(const std::string& iface);

@ -76,27 +76,35 @@ void AmSessionFactory::configureSession(AmSession* sess) {
void AmSessionFactory::onOoDRequest(const AmSipRequest& req)
{
if(req.method == "OPTIONS"){
// Basic OPTIONS support
if (!AmConfig::OptionsSessionLimit ||
(AmSession::getSessionNum() < AmConfig::OptionsSessionLimit)) {
AmSipDialog::reply_error(req, 200, "OK");
} else {
if (req.method == "OPTIONS") {
// Basic OPTIONS support
if (AmConfig::OptionsSessionLimit &&
(AmSession::getSessionNum() >= AmConfig::OptionsSessionLimit)) {
// return error code if near to overload
AmSipDialog::reply_error(req,
AmConfig::OptionsSessionLimitErrCode,
AmConfig::OptionsSessionLimitErrReason);
return;
}
if (AmConfig::ShutdownMode) {
// return error code if in shutdown mode
AmSipDialog::reply_error(req,
AmConfig::ShutdownModeErrCode,
AmConfig::ShutdownModeErrReason);
return;
}
AmSipDialog::reply_error(req, 200, "OK");
return;
}
ERROR("sorry, we don't support beginning a new session with "
ERROR("sorry, we don't support beginning a new session with "
"a '%s' message\n", req.method.c_str());
AmSipDialog::reply_error(req,501,"Not Implemented");
return;
AmSipDialog::reply_error(req,501,"Not Implemented");
return;
}
// void AmSessionFactory::postEvent(AmEvent* ev) {

@ -94,6 +94,10 @@ unsigned int AmConfig::OptionsSessionLimit = 0;
unsigned int AmConfig::OptionsSessionLimitErrCode = 503;
string AmConfig::OptionsSessionLimitErrReason = "Server overload";
bool AmConfig::ShutdownMode = false;
unsigned int AmConfig::ShutdownModeErrCode = 503;
string AmConfig::ShutdownModeErrReason = "Server shutting down";
AmSipDialog::provisional_100rel AmConfig::rel100 = REL100_SUPPORTED;
vector <string> AmConfig::CodecOrder;
@ -487,6 +491,24 @@ int AmConfig::readConfiguration()
}
}
if(cfg.hasParameter("shutdown_mode_reply")){
string c_reply = cfg.getParameter("shutdown_mode_reply");
size_t spos = c_reply.find(" ");
if (spos == string::npos || spos == c_reply.length()) {
ERROR("invalid shutdown_mode_reply specified, expected \"<code> <reason>\","
"e.g. shutdown_mode_reply=\"503 Not At The Moment, Please\".\n");
ret = -1;
} else {
if (str2i(c_reply.substr(0, spos), ShutdownModeErrCode)) {
ERROR("invalid shutdown_mode_reply specified, expected \"<code> <reason>\","
"e.g. shutdown_mode_reply=\"503 Not At The Moment, Please\".\n");
ret = -1;
}
ShutdownModeErrReason = c_reply.substr(spos+1);
}
}
if (cfg.hasParameter("100rel")) {
string rel100s = cfg.getParameter("100rel");
if (rel100s == "disabled" || rel100s == "off") {

@ -162,6 +162,10 @@ struct AmConfig
static unsigned int OptionsSessionLimitErrCode;
static string OptionsSessionLimitErrReason;
static bool ShutdownMode;
static unsigned int ShutdownModeErrCode;
static string ShutdownModeErrReason;
static AmSipDialog::provisional_100rel rel100;
/** Time of no RTP after which Session is regarded as dead, 0 for no Timeout */

@ -367,6 +367,15 @@ bool AmSessionContainer::postEvent(const string& local_tag,
AmSession* AmSessionContainer::createSession(AmSipRequest& req,
AmArg* session_params)
{
if (AmConfig::ShutdownMode) {
_run_cond.set(true); // so that thread stops
DBG("Shutdown mode. Not creating session.\n");
AmSipDialog::reply_error(req,AmConfig::ShutdownModeErrCode,
AmConfig::ShutdownModeErrReason);
return NULL;
}
if (AmConfig::SessionLimit &&
AmConfig::SessionLimit <= AmSession::session_num) {

@ -228,15 +228,6 @@ stderr=no
# (same as -D)
loglevel=2
# optional parameter: max_shutdown_time=<time in seconds>
#
# Limit on server shutdown time (time to send/resend BYE
# to active calls). 0 to disable (infinite).
#
# Default: 10
#
#max_shutdown_time = 10
# optional parameter: syslog_facility={DAEMON|USER|LOCAL[0-7]}
#
# - sets the log facility that is used for syslog. Using this,
@ -266,6 +257,22 @@ loglevel=2
#
# log_events=yes
# optional parameter: max_shutdown_time=<time in seconds>
#
# Limit on server shutdown time (time to send/resend BYE
# to active calls). 0 to disable (infinite).
#
# Default: 10
#
#max_shutdown_time = 10
# optional parameter: shutdown_mode_reply="<code> <reason>"
#
# Error reply that is used as reply to INVITE and OPTION
# when SEMS is shutting down.
#
# Default: shutdown_mode_reply="503 Server shutting down"
############################################################
# tuning

@ -292,8 +292,13 @@ int StatsUDPServer::execute(char* msg_buf, string& reply,
"which - print available commands\n"
"set_loglevel <loglevel> - set log level\n"
"get_loglevel - get log level\n"
"\n"
"set_shutdownmode <1 or 0> - turns on and off shutdown mode\n"
"get_shutdownmode - returns the shutdown mode's current state\n"
"DI <factory> <function> (<args>)* - invoke DI command\n"
"\n"
"When in shutdown mode, SEMS will answer with the configured 5xx errorcode to\n"
"new INVITE and OPTIONS requests.\n"
;
}
else if (cmd_str.length() > 4 && cmd_str.substr(0, 4) == "set_") {
@ -305,6 +310,25 @@ int StatsUDPServer::execute(char* msg_buf, string& reply,
reply= "loglevel set to "+int2str(log_level)+".\n";
}
else if (cmd_str.substr(4, 12) == "shutdownmode") {
int tmp;
if(sscanf(&cmd_str.c_str()[17],"%u",&tmp) != 1)
reply= "invalid shutdownmode\n";
else
{
if(tmp)
{
AmConfig::ShutdownMode = true;
reply= "Shutdownmode activated!\n";
}
else
{
AmConfig::ShutdownMode = false;
reply= "Shutdownmode deactivated!\n";
}
}
}
else reply = "Unknown command: '" + cmd_str + "'\n";
}
else if (cmd_str.length() > 4 && cmd_str.substr(0, 4) == "get_") {
@ -313,6 +337,17 @@ int StatsUDPServer::execute(char* msg_buf, string& reply,
reply= "loglevel is "+int2str(log_level)+".\n";
}
else if (cmd_str.substr(4, 12) == "shutdownmode") {
if(AmConfig::ShutdownMode)
{
reply= "Shutdownmode active!\n";
}
else
{
reply= "Shutdownmode inactive!\n";
}
}
else reply = "Unknown command: '" + cmd_str + "'\n";
}
else if (cmd_str.length() > 4 && cmd_str.substr(0, 3) == "DI ") {

@ -2,8 +2,8 @@ xmlrpc2di: DI call via XMLRPC
This module makes the Dynamic Invocation (DI) Interfaces exported
by component modules accessible from XMLRPC. Additionaly the builtin
methods calls, get_loglevel and set_loglevel are implemented (like in the
stats UDP server).
methods "calls", "get_loglevel"/"set_loglevel" and
"get_shutdownmode"/"set_shutdownmode" are implemented.
Additionally, it can be used as client to access XMLRPC servers. Applications
can use the DI function newConnection to add a new server entry, and sendRequest
@ -11,20 +11,9 @@ to send a request. If sendRequest is executed, an active server is selected from
the list and used to send the request. If sending the request failes, the server
is put inactive for a (configurable) while, and only then retried.
This module uses the XmlRpc++ library (http://xmlrpcpp.sourceforge.net/).
In order to compile it, the xmlrpc library is needed; install it by
make install-xmlrpcpp, or by hand:
cd apps/examples/xmlrpc2di
wget http://switch.dl.sourceforge.net/sourceforge/xmlrpcpp/xmlrpc++0.7.tar.gz
&& tar xzvf xmlrpc++0.7.tar.gz
A small patch set needs to be applied as well:
patch -p0 < xmlrpcpp07_sems.patch
If xmlrpcpp is extracted to a different directory, the path in
the Makefile needs to be adapted. If your xmlrpc++ installation has the
SSL for xmlrpc client option, you may need to add -DHAVE_XMLRPCPP_SSL
to module_cflags due to some ambiguity in the header.
This module uses the XmlRpc++ library (http://xmlrpcpp.sourceforge.net/), which
is included, as it is currently not any more maintained by the major distributions.
Some patches have been applied to that library (multi threading, SSL etc).
The XMLRPC server can be configured to run as single threaded server (if
one request is executed, the next ones have to wait), or a multi-threaded server
@ -38,6 +27,8 @@ Configuration parameters
function default description
+---------------------------------------
server_ip ANY if set, bind only to the specific interface
xmlrpc_port 8090 port to bind XMLRPC server to
export_di yes enable 'di' function (see below)

Loading…
Cancel
Save