/home/bes3soft/bes3soft/Boss/7.0.2/dist/7.0.2/Utilities/JobInfoSvc/JobInfoSvc-00-00-02/xmlrpc++0.7/src/XmlRpcServer.cpp

Go to the documentation of this file.
00001 
00002 #include "XmlRpcServer.h"
00003 #include "XmlRpcServerConnection.h"
00004 #include "XmlRpcServerMethod.h"
00005 #include "XmlRpcSocket.h"
00006 #include "XmlRpcUtil.h"
00007 #include "XmlRpcException.h"
00008 
00009 
00010 using namespace XmlRpc;
00011 
00012 
00013 XmlRpcServer::XmlRpcServer()
00014 {
00015   _introspectionEnabled = false;
00016   _listMethods = 0;
00017   _methodHelp = 0;
00018 }
00019 
00020 
00021 XmlRpcServer::~XmlRpcServer()
00022 {
00023   this->shutdown();
00024   _methods.clear();
00025   delete _listMethods;
00026   delete _methodHelp;
00027 }
00028 
00029 
00030 // Add a command to the RPC server
00031 void 
00032 XmlRpcServer::addMethod(XmlRpcServerMethod* method)
00033 {
00034   _methods[method->name()] = method;
00035 }
00036 
00037 // Remove a command from the RPC server
00038 void 
00039 XmlRpcServer::removeMethod(XmlRpcServerMethod* method)
00040 {
00041   MethodMap::iterator i = _methods.find(method->name());
00042   if (i != _methods.end())
00043     _methods.erase(i);
00044 }
00045 
00046 // Remove a command from the RPC server by name
00047 void 
00048 XmlRpcServer::removeMethod(const std::string& methodName)
00049 {
00050   MethodMap::iterator i = _methods.find(methodName);
00051   if (i != _methods.end())
00052     _methods.erase(i);
00053 }
00054 
00055 
00056 // Look up a method by name
00057 XmlRpcServerMethod* 
00058 XmlRpcServer::findMethod(const std::string& name) const
00059 {
00060   MethodMap::const_iterator i = _methods.find(name);
00061   if (i == _methods.end())
00062     return 0;
00063   return i->second;
00064 }
00065 
00066 
00067 // Create a socket, bind to the specified port, and
00068 // set it in listen mode to make it available for clients.
00069 bool 
00070 XmlRpcServer::bindAndListen(int port, int backlog /*= 5*/)
00071 {
00072   int fd = XmlRpcSocket::socket();
00073   if (fd < 0)
00074   {
00075     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not create socket (%s).", XmlRpcSocket::getErrorMsg().c_str());
00076     return false;
00077   }
00078 
00079   this->setfd(fd);
00080 
00081   // Don't block on reads/writes
00082   if ( ! XmlRpcSocket::setNonBlocking(fd))
00083   {
00084     this->close();
00085     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
00086     return false;
00087   }
00088 
00089   // Allow this port to be re-bound immediately so server re-starts are not delayed
00090   if ( ! XmlRpcSocket::setReuseAddr(fd))
00091   {
00092     this->close();
00093     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set SO_REUSEADDR socket option (%s).", XmlRpcSocket::getErrorMsg().c_str());
00094     return false;
00095   }
00096 
00097   // Bind to the specified port on the default interface
00098   if ( ! XmlRpcSocket::bind(fd, port))
00099   {
00100     this->close();
00101     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not bind to specified port (%s).", XmlRpcSocket::getErrorMsg().c_str());
00102     return false;
00103   }
00104 
00105   // Set in listening mode
00106   if ( ! XmlRpcSocket::listen(fd, backlog))
00107   {
00108     this->close();
00109     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket in listening mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
00110     return false;
00111   }
00112 
00113   XmlRpcUtil::log(2, "XmlRpcServer::bindAndListen: server listening on port %d fd %d", port, fd);
00114 
00115   // Notify the dispatcher to listen on this source when we are in work()
00116   _disp.addSource(this, XmlRpcDispatch::ReadableEvent);
00117 
00118   return true;
00119 }
00120 
00121 
00122 // Process client requests for the specified time
00123 void 
00124 XmlRpcServer::work(double msTime)
00125 {
00126   XmlRpcUtil::log(2, "XmlRpcServer::work: waiting for a connection");
00127   _disp.work(msTime);
00128 }
00129 
00130 
00131 
00132 // Handle input on the server socket by accepting the connection
00133 // and reading the rpc request.
00134 unsigned
00135 XmlRpcServer::handleEvent(unsigned mask)
00136 {
00137   acceptConnection();
00138   return XmlRpcDispatch::ReadableEvent;         // Continue to monitor this fd
00139 }
00140 
00141 
00142 // Accept a client connection request and create a connection to
00143 // handle method calls from the client.
00144 void
00145 XmlRpcServer::acceptConnection()
00146 {
00147   int s = XmlRpcSocket::accept(this->getfd());
00148   XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: socket %d", s);
00149   if (s < 0)
00150   {
00151     //this->close();
00152     XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not accept connection (%s).", XmlRpcSocket::getErrorMsg().c_str());
00153   }
00154   else if ( ! XmlRpcSocket::setNonBlocking(s))
00155   {
00156     XmlRpcSocket::close(s);
00157     XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
00158   }
00159   else  // Notify the dispatcher to listen for input on this source when we are in work()
00160   {
00161     XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: creating a connection");
00162     _disp.addSource(this->createConnection(s), XmlRpcDispatch::ReadableEvent);
00163   }
00164 }
00165 
00166 
00167 // Create a new connection object for processing requests from a specific client.
00168 XmlRpcServerConnection*
00169 XmlRpcServer::createConnection(int s)
00170 {
00171   // Specify that the connection object be deleted when it is closed
00172   return new XmlRpcServerConnection(s, this, true);
00173 }
00174 
00175 
00176 void 
00177 XmlRpcServer::removeConnection(XmlRpcServerConnection* sc)
00178 {
00179   _disp.removeSource(sc);
00180 }
00181 
00182 
00183 // Stop processing client requests
00184 void 
00185 XmlRpcServer::exit()
00186 {
00187   _disp.exit();
00188 }
00189 
00190 
00191 // Close the server socket file descriptor and stop monitoring connections
00192 void 
00193 XmlRpcServer::shutdown()
00194 {
00195   // This closes and destroys all connections as well as closing this socket
00196   _disp.clear();
00197 }
00198 
00199 
00200 // Introspection support
00201 static const std::string LIST_METHODS("system.listMethods");
00202 static const std::string METHOD_HELP("system.methodHelp");
00203 static const std::string MULTICALL("system.multicall");
00204 
00205 
00206 // List all methods available on a server
00207 class ListMethods : public XmlRpcServerMethod
00208 {
00209 public:
00210   ListMethods(XmlRpcServer* s) : XmlRpcServerMethod(LIST_METHODS, s) {}
00211 
00212   void execute(XmlRpcValue& params, XmlRpcValue& result)
00213   {
00214     _server->listMethods(result);
00215   }
00216 
00217   std::string help() { return std::string("List all methods available on a server as an array of strings"); }
00218 };
00219 
00220 
00221 // Retrieve the help string for a named method
00222 class MethodHelp : public XmlRpcServerMethod
00223 {
00224 public:
00225   MethodHelp(XmlRpcServer* s) : XmlRpcServerMethod(METHOD_HELP, s) {}
00226 
00227   void execute(XmlRpcValue& params, XmlRpcValue& result)
00228   {
00229     if (params[0].getType() != XmlRpcValue::TypeString)
00230       throw XmlRpcException(METHOD_HELP + ": Invalid argument type");
00231 
00232     XmlRpcServerMethod* m = _server->findMethod(params[0]);
00233     if ( ! m)
00234       throw XmlRpcException(METHOD_HELP + ": Unknown method name");
00235 
00236     result = m->help();
00237   }
00238 
00239   std::string help() { return std::string("Retrieve the help string for a named method"); }
00240 };
00241 
00242     
00243 // Specify whether introspection is enabled or not. Default is enabled.
00244 void 
00245 XmlRpcServer::enableIntrospection(bool enabled)
00246 {
00247   if (_introspectionEnabled == enabled)
00248     return;
00249 
00250   _introspectionEnabled = enabled;
00251 
00252   if (enabled)
00253   {
00254     if ( ! _listMethods)
00255     {
00256       _listMethods = new ListMethods(this);
00257       _methodHelp = new MethodHelp(this);
00258     } else {
00259       addMethod(_listMethods);
00260       addMethod(_methodHelp);
00261     }
00262   }
00263   else
00264   {
00265     removeMethod(LIST_METHODS);
00266     removeMethod(METHOD_HELP);
00267   }
00268 }
00269 
00270 
00271 void
00272 XmlRpcServer::listMethods(XmlRpcValue& result)
00273 {
00274   int i = 0;
00275   result.setSize(_methods.size()+1);
00276   for (MethodMap::iterator it=_methods.begin(); it != _methods.end(); ++it)
00277     result[i++] = it->first;
00278 
00279   // Multicall support is built into XmlRpcServerConnection
00280   result[i] = MULTICALL;
00281 }
00282 
00283 
00284 

Generated on Tue Nov 29 23:14:44 2016 for BOSS_7.0.2 by  doxygen 1.4.7