From 36dc1f666931a0b63bf351274033fc4fb0d34113 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 28 May 2007 23:29:11 +0000 Subject: [PATCH] xmlrpc2di makes xmlrpc calls to DI interface possible git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@339 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/examples/xmlrpc2di/Makefile | 20 +++ apps/examples/xmlrpc2di/Readme.xmlrpc2di | 42 ++++++ apps/examples/xmlrpc2di/XMLRPC2DI.cpp | 163 +++++++++++++++++++++ apps/examples/xmlrpc2di/XMLRPC2DI.h | 80 ++++++++++ apps/examples/xmlrpc2di/etc/xmlrpc2di.conf | 2 + 5 files changed, 307 insertions(+) create mode 100644 apps/examples/xmlrpc2di/Makefile create mode 100644 apps/examples/xmlrpc2di/Readme.xmlrpc2di create mode 100644 apps/examples/xmlrpc2di/XMLRPC2DI.cpp create mode 100644 apps/examples/xmlrpc2di/XMLRPC2DI.h create mode 100644 apps/examples/xmlrpc2di/etc/xmlrpc2di.conf diff --git a/apps/examples/xmlrpc2di/Makefile b/apps/examples/xmlrpc2di/Makefile new file mode 100644 index 00000000..a14a16ff --- /dev/null +++ b/apps/examples/xmlrpc2di/Makefile @@ -0,0 +1,20 @@ +XMLRPCPP_DIR = xmlrpc++0.7 + +plug_in_name = xmlrpc2di + +module_ldflags = +module_cflags = -I$(XMLRPCPP_DIR)/src + +module_extra_objs = $(XMLRPCPP_DIR)/libXmlRpc.a + +extra_clean = clean_libxmlrpc + + +COREPATH ?=../../../core +include $(COREPATH)/plug-in/Makefile.app_module + +$(XMLRPCPP_DIR)/libXmlRpc.a: + $(MAKE) -C $(XMLRPCPP_DIR) libXmlRpc.a + +clean_libxmlrpc: + $(MAKE) -C $(XMLRPCPP_DIR) clean diff --git a/apps/examples/xmlrpc2di/Readme.xmlrpc2di b/apps/examples/xmlrpc2di/Readme.xmlrpc2di new file mode 100644 index 00000000..f28f6699 --- /dev/null +++ b/apps/examples/xmlrpc2di/Readme.xmlrpc2di @@ -0,0 +1,42 @@ +xmlrpc2di: DI call via XMLRPC + +This module makes the Dynamic Invocation (DI) Interfaces exported +by component modules accessible from XMLRPC. Additionaly the methods +calls, get_loglevel and set_loglevel are implemented (like in the +stats UDP server). + +This module uses the XmlRpc++ library (http://xmlrpcpp.sourceforge.net/). +In order to compile it, the xmlrpc library is needed: +cd apps/examples/xmlrpc2di +wget http://switch.dl.sourceforge.net/sourceforge/xmlrpcpp/xmlrpc++0.7.tar.gz && tar xzvf xmlrpc++0.7.tar.gz +If xmlrpcpp is extracted to a different directory, the path in +the Makefile needs to be adapted. + +The first parameter to 'di' is alway the factory name, the second the +function name. Further parameters to XMLRPC calls are converted to DI +ArgArray structure, and result of DI calls are converted back to XMLRPC +parameters. At the moment only string, int and double types are implemented +(no DateTime, struct, binary, ...). + + +Examples (that hopefully trigger some creativity in the reader ;) +----------------------------------------------------------------- + +Register fritz at iptel.org using registrar client over XMLRPC +from python: + +import xmlrpclib +server = ServerProxy("http://127.0.0.1:8090") +server.di('registrar_client', 'createRegistration', + 'iptel.org', 'fritz', 'Frotz', + 'fritz', 'secretpass', '') + +To call someone into conference over an account at sparvoip.de +using di_dial: + +import xmlrpclib +server = ServerProxy("http://127.0.0.1:8090") +server.di('di_dial', 'dial_auth','conference', 'roomname', + 'sip:myuser@sparvoip.de', 'sip:0049301234567@sparvoip.de', + 'sparvoip.de','myuser','passwd') + diff --git a/apps/examples/xmlrpc2di/XMLRPC2DI.cpp b/apps/examples/xmlrpc2di/XMLRPC2DI.cpp new file mode 100644 index 00000000..8886bdfd --- /dev/null +++ b/apps/examples/xmlrpc2di/XMLRPC2DI.cpp @@ -0,0 +1,163 @@ +/* + * $Id: XMLRPC2DI.cpp 145 2006-11-26 00:01:18Z sayer $ + * + * Copyright (C) 2007 iptego GmbH + * + * This file is part of sems, a free SIP media server. + * + * sems 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 sems 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 + * + * sems 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "XMLRPC2DI.h" + +#include "AmSessionContainer.h" +#include "AmPlugIn.h" +#include "log.h" +#include "AmConfigReader.h" +#include "AmUtils.h" + +#define MOD_NAME "xmlrpc2di" + +#define XMLRPC_PORT "8090" // default port +EXPORT_PLUGIN_CLASS_FACTORY(XMLRPC2DI, MOD_NAME) + +XMLRPC2DI::XMLRPC2DI(string mod_name) + : AmDynInvokeFactory(mod_name) +{ +} + +int XMLRPC2DI::onLoad() { + + AmConfigReader cfg; + if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf"))) + return -1; + + string conf_xmlrpc_port = cfg.getParameter("xmlrpc_port",XMLRPC_PORT); + if (conf_xmlrpc_port.empty()) { + ERROR("configuration: xmlrpc_port must be defined!\n"); + return -1; + } + + if (str2i(conf_xmlrpc_port, XMLRPCPort)) { + ERROR("configuration: unable to decode xmlrpc_port value '%s'!\n", + conf_xmlrpc_port.c_str()); + return -1; + } + server = new XMLRPC2DIServer(XMLRPCPort); + server->start(); + return 0; +} + +// XMLRPC server functions + +XMLRPC2DIServer::XMLRPC2DIServer(unsigned int port) + : port(port), + calls_method(&s), + setloglevel_method(&s), + getloglevel_method(&s), + di_method(&s) +{ + DBG("Initialized XMLRPC2DIServer with: \n"); + DBG(" port = %u\n", port); +} + +void XMLRPC2DIServer::run() { + DBG("Binding XMLRPC2DIServer to port %u \n", port); + s.bindAndListen(port); + DBG("starting XMLRPC2DIServer...\n"); + s.work(-1.0); +} +void XMLRPC2DIServer::on_stop() { + DBG("sorry, don't know how to stop the server.\n"); +} + +void XMLRPC2DIServerCallsMethod::execute(XmlRpcValue& params, XmlRpcValue& result) { + int res = AmSessionContainer::instance()->getSize(); + DBG("XMLRPC2DI: calls = %d\n", res); + result = res; +} + +void XMLRPC2DIServerGetLoglevelMethod::execute(XmlRpcValue& params, XmlRpcValue& result) { + int res = log_level; + DBG("XMLRPC2DI: get_loglevel returns %d\n", res); + result = res; +} + +void XMLRPC2DIServerSetLoglevelMethod::execute(XmlRpcValue& params, XmlRpcValue& result) { + log_level = params[0]; + DBG("XMLRPC2DI: set log level to %d.\n", (int)params[0]); + result = "200 OK"; +} + + +void XMLRPC2DIServerDIMethod::execute(XmlRpcValue& params, XmlRpcValue& result) { + if (params.size() < 2) { + DBG("XMLRPC2DI: ERROR: need at least factory name and function name to call\n"); + throw XmlRpcException("need at least factory name and function name to call", 400); + } + + string fact_name = params[0]; + string fct_name = params[1]; + + DBG("XMLRPC2DI: factory '%s' function '%s'\n", + fact_name.c_str(), fct_name.c_str()); + + // get args + AmArgArray args; + for (int i=2; igetFactory4Di(fact_name); + if(!di_f){ + throw XmlRpcException("could not get factory", 500); + } + AmDynInvoke* di = di_f->getInstance(); + if(!di){ + throw XmlRpcException("could not get instance from factory", 500); + } + AmArgArray ret; + di->invoke(fct_name, args, ret); + + if (ret.size()) { + result.setSize(ret.size()); + + for (unsigned int i=0;i