XmlRpc::XmlRpcServer Class Reference

#include <XmlRpcServer.h>

Inheritance diagram for XmlRpc::XmlRpcServer:

XmlRpc::XmlRpcSource DHTXMLRealworldApp XmlRpc::XmlRpcThreadedServer List of all members.

Detailed Description

A class to handle XML RPC requests.


Public Member Functions

 XmlRpcServer ()
 Create a server object.
virtual ~XmlRpcServer ()
 Destructor.
void enableIntrospection (bool enabled=true)
 Specify whether introspection is enabled or not. Default is not enabled.
void addMethod (XmlRpcServerMethod *method)
 Add a command to the RPC server.
void removeMethod (XmlRpcServerMethod *method)
 Remove a command from the RPC server.
void removeMethod (const std::string &methodName)
 Remove a command from the RPC server by name.
XmlRpcServerMethodfindMethod (const std::string &name) const
 Look up a method by name.
bool bindAndListen (int port, int backlog=5)
 Create a socket, bind to the specified port, and set it in listen mode to make it available for clients.
int getPort (void) const
 Get the port number this server is listening on.
void work (double msTime)
 Process client requests for the specified time.
void exit ()
 Temporarily stop processing client requests and exit the work() method.
void shutdown ()
 Close all connections with clients and the socket file descriptor.
void listMethods (XmlRpcValue &result)
 Introspection support.
virtual std::string executeRequest (std::string const &request)
 Parses the request xml, runs the method, generates the response (header+xml).
virtual unsigned handleEvent (unsigned eventType)
 Handle client connection requests.
virtual void removeConnection (XmlRpcServerConnection *)
 Remove a connection from the dispatcher.

Protected Types

typedef std::map< std::string,
XmlRpcServerMethod * > 
MethodMap
 Collection of methods. This could be a set keyed on method name if we wanted...

Protected Member Functions

virtual void acceptConnection ()
 Accept a client connection request.
virtual XmlRpcServerConnectioncreateConnection (int socket)
 Create a new connection object for processing requests from a specific client.
virtual void dispatchConnection (XmlRpcServerConnection *sc)
 Hand off a new connection object to a dispatcher.
std::string parseRequest (std::string const &request, XmlRpcValue &params)
 Parse the methodName and parameters from the request.
bool executeMethod (const std::string &methodName, XmlRpcValue &params, XmlRpcValue &result)
 Execute a named method with the specified params.
bool executeMulticall (const std::string &methodName, XmlRpcValue &params, XmlRpcValue &result)
 Execute multiple calls and return the results in an array.
std::string generateResponse (std::string const &resultXml)
 Construct a response from the result XML.
std::string generateFaultResponse (std::string const &msg, int errorCode=-1)
 Construct a fault response.
std::string generateHeader (std::string const &body)
 Return the appropriate headers for the response.

Protected Attributes

bool _introspectionEnabled
 Whether the introspection API is supported by this server.
XmlRpcDispatch _disp
 Event dispatcher.
MethodMap _methods
 Registered RPC methods.
XmlRpcServerMethod_listMethods
 List all registered RPC methods (only available if introspection is enabled).
XmlRpcServerMethod_methodHelp
 Return help string for a specified method (only available if introspection is enabled).

Static Protected Attributes

static const char METHODNAME_TAG []
static const char PARAMS_TAG []
static const char PARAMS_ETAG []
static const char PARAM_TAG []
static const char PARAM_ETAG []
static const std::string SYSTEM_MULTICALL
static const std::string METHODNAME
static const std::string PARAMS
static const std::string FAULTCODE
static const std::string FAULTSTRING


Member Typedef Documentation

typedef std::map< std::string, XmlRpcServerMethod* > XmlRpc::XmlRpcServer::MethodMap [protected]

Collection of methods. This could be a set keyed on method name if we wanted...


Constructor & Destructor Documentation

XmlRpcServer::XmlRpcServer (  ) 

Create a server object.

00031 {
00032   _introspectionEnabled = false;
00033   _listMethods = 0;
00034   _methodHelp = 0;
00035 }

XmlRpcServer::~XmlRpcServer (  )  [virtual]

Destructor.

00039 {
00040   this->shutdown();
00041   _methods.clear();
00042   delete _listMethods;
00043   delete _methodHelp;
00044 }


Member Function Documentation

void XmlRpcServer::enableIntrospection ( bool  enabled = true  ) 

Specify whether introspection is enabled or not. Default is not enabled.

00282 {
00283   if (_introspectionEnabled == enabled)
00284     return;
00285 
00286   _introspectionEnabled = enabled;
00287 
00288   if (enabled)
00289   {
00290     if ( ! _listMethods)
00291     {
00292       _listMethods = new ListMethods(this);
00293       _methodHelp = new MethodHelp(this);
00294     } else {
00295       addMethod(_listMethods);
00296       addMethod(_methodHelp);
00297     }
00298   }
00299   else
00300   {
00301     removeMethod(LIST_METHODS);
00302     removeMethod(METHOD_HELP);
00303   }
00304 }

void XmlRpcServer::addMethod ( XmlRpcServerMethod method  ) 

Add a command to the RPC server.

00050 {
00051   _methods[method->name()] = method;
00052 }

void XmlRpcServer::removeMethod ( XmlRpcServerMethod method  ) 

Remove a command from the RPC server.

00057 {
00058   MethodMap::iterator i = _methods.find(method->name());
00059   if (i != _methods.end())
00060     _methods.erase(i);
00061 }

void XmlRpcServer::removeMethod ( const std::string &  methodName  ) 

Remove a command from the RPC server by name.

00066 {
00067   MethodMap::iterator i = _methods.find(methodName);
00068   if (i != _methods.end())
00069     _methods.erase(i);
00070 }

XmlRpcServerMethod * XmlRpcServer::findMethod ( const std::string &  name  )  const

Look up a method by name.

00076 {
00077   MethodMap::const_iterator i = _methods.find(name);
00078   if (i == _methods.end())
00079     return 0;
00080   return i->second;
00081 }

bool XmlRpcServer::bindAndListen ( int  port,
int  backlog = 5 
)

Create a socket, bind to the specified port, and set it in listen mode to make it available for clients.

Parameters:
port The port to bind and listen on (zero to choose an arbitrary port)
00088 {
00089   int fd = XmlRpcSocket::socket();
00090   if (fd < 0)
00091   {
00092     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not create socket (%s).", XmlRpcSocket::getErrorMsg().c_str());
00093     return false;
00094   }
00095 
00096   this->setfd(fd);
00097 
00098   // Don't block on reads/writes
00099   if ( ! XmlRpcSocket::setNonBlocking(fd))
00100   {
00101     this->close();
00102     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
00103     return false;
00104   }
00105 
00106   // Allow this port to be re-bound immediately so server re-starts are not delayed
00107   if ( ! XmlRpcSocket::setReuseAddr(fd))
00108   {
00109     this->close();
00110     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set SO_REUSEADDR socket option (%s).", XmlRpcSocket::getErrorMsg().c_str());
00111     return false;
00112   }
00113 
00114   // Bind to the specified port on the default interface
00115   if ( ! XmlRpcSocket::bind(fd, port))
00116   {
00117     this->close();
00118     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not bind to specified port (%s).", XmlRpcSocket::getErrorMsg().c_str());
00119     return false;
00120   }
00121 
00122   // Set in listening mode
00123   if ( ! XmlRpcSocket::listen(fd, backlog))
00124   {
00125     this->close();
00126     XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket in listening mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
00127     return false;
00128   }
00129 
00130   XmlRpcUtil::log(2, "XmlRpcServer::bindAndListen: server listening on port %d fd %d", port, fd);
00131 
00132   // Notify the dispatcher to listen on this source when we are in work()
00133   _disp.addSource(this, XmlRpcDispatch::ReadableEvent);
00134 
00135   return true;
00136 }

int XmlRpcServer::getPort ( void   )  const

Get the port number this server is listening on.

00142 {
00143   return XmlRpcSocket::getPort(getfd());
00144 }

void XmlRpcServer::work ( double  msTime  ) 

Process client requests for the specified time.

00151 {
00152   XmlRpcUtil::log(2, "XmlRpcServer::work: waiting for a connection");
00153   _disp.work(msTime);
00154 }

void XmlRpcServer::exit (  ) 

Temporarily stop processing client requests and exit the work() method.

00222 {
00223   _disp.exit();
00224 }

void XmlRpcServer::shutdown (  ) 

Close all connections with clients and the socket file descriptor.

00230 {
00231   // This closes and destroys all connections as well as closing this socket
00232   _disp.clear();
00233 }

void XmlRpcServer::listMethods ( XmlRpcValue result  ) 

Introspection support.

00309 {
00310   int i = 0;
00311   result.setSize(_methods.size()+1);
00312   for (MethodMap::iterator it=_methods.begin(); it != _methods.end(); ++it)
00313     result[i++] = it->first;
00314 
00315   // Multicall support is built into XmlRpcServer::executeRequest
00316   result[i] = MULTICALL;
00317 }

std::string XmlRpcServer::executeRequest ( std::string const &  request  )  [virtual]

Parses the request xml, runs the method, generates the response (header+xml).

Returns a fault response if an error occurs during method execution.

00324 {
00325   XmlRpcValue params, resultValue;
00326   std::string methodName = parseRequest(request, params);
00327   XmlRpcUtil::log(2, "XmlRpcServer::executeRequest: server calling method '%s'", 
00328                     methodName.c_str());
00329 
00330   std::string response;
00331   try {
00332 
00333     if ( ! executeMethod(methodName, params, resultValue) &&
00334          ! executeMulticall(methodName, params, resultValue))
00335       response = generateFaultResponse(methodName + ": unknown method name");
00336     else
00337       response = generateResponse(resultValue.toXml());
00338 
00339   } catch (const XmlRpcException& fault) {
00340     XmlRpcUtil::log(2, "XmlRpcServer::executeRequest: fault %s.",
00341                     fault.getMessage().c_str()); 
00342     response = generateFaultResponse(fault.getMessage(), fault.getCode());
00343   }
00344 
00345   return response;
00346 }

unsigned XmlRpcServer::handleEvent ( unsigned  eventType  )  [virtual]

Handle client connection requests.

Implements XmlRpc::XmlRpcSource.

00162 {
00163   acceptConnection();
00164   return XmlRpcDispatch::ReadableEvent;         // Continue to monitor this fd
00165 }

void XmlRpcServer::removeConnection ( XmlRpcServerConnection  )  [virtual]

Remove a connection from the dispatcher.

00214 {
00215   _disp.removeSource(sc);
00216 }

void XmlRpcServer::acceptConnection (  )  [protected, virtual]

Accept a client connection request.

00172 {
00173   int s = XmlRpcSocket::accept(this->getfd());
00174   XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: socket %d", s);
00175   if (s < 0)
00176   {
00177     //this->close();
00178     XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not accept connection (%s).", XmlRpcSocket::getErrorMsg().c_str());
00179   }
00180   else if ( ! XmlRpcSocket::setNonBlocking(s))
00181   {
00182     XmlRpcSocket::close(s);
00183     XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
00184   }
00185   else  // Notify the dispatcher to listen for input on this source when we are in work()
00186   {
00187     XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: creating a connection");
00188     XmlRpcServerConnection* c = this->createConnection(s);
00189     if (c) this->dispatchConnection(c);
00190   }
00191 }

XmlRpcServerConnection * XmlRpcServer::createConnection ( int  socket  )  [protected, virtual]

Create a new connection object for processing requests from a specific client.

If the client is not authorized to connect, close the socket and return 0.

00197 {
00198   // Specify that the connection object be deleted when it is closed
00199   return new XmlRpcServerConnection(s, this, true);
00200 }

void XmlRpcServer::dispatchConnection ( XmlRpcServerConnection sc  )  [protected, virtual]

Hand off a new connection object to a dispatcher.

00206 {
00207   _disp.addSource(sc, XmlRpcDispatch::ReadableEvent);
00208 }

std::string XmlRpcServer::parseRequest ( std::string const &  request,
XmlRpcValue params 
) [protected]

Parse the methodName and parameters from the request.

Returns:
the methodName
00351 {
00352   int offset = 0;   // Number of chars parsed from the request
00353 
00354   std::string methodName = XmlRpcUtil::parseTag(METHODNAME_TAG, request, &offset);
00355 
00356   if (methodName.size() > 0 && XmlRpcUtil::findTag(PARAMS_TAG, request, &offset))
00357   {
00358     int nArgs = 0;
00359     while (XmlRpcUtil::nextTagIs(PARAM_TAG, request, &offset)) {
00360       params[nArgs++] = XmlRpcValue(request, &offset);
00361       (void) XmlRpcUtil::nextTagIs(PARAM_ETAG, request, &offset);
00362     }
00363 
00364     (void) XmlRpcUtil::nextTagIs(PARAMS_ETAG, request, &offset);
00365   }
00366 
00367   return methodName;
00368 }

bool XmlRpcServer::executeMethod ( const std::string &  methodName,
XmlRpcValue params,
XmlRpcValue result 
) [protected]

Execute a named method with the specified params.

00375 {
00376   XmlRpcServerMethod* method = findMethod(methodName);
00377 
00378   if ( ! method) return false;
00379 
00380   method->execute(params, result);
00381 
00382   // Ensure a valid result value
00383   if ( ! result.valid())
00384       result = std::string();
00385 
00386   return true;
00387 }

bool XmlRpcServer::executeMulticall ( const std::string &  methodName,
XmlRpcValue params,
XmlRpcValue result 
) [protected]

Execute multiple calls and return the results in an array.

System.multicall implementation

00394 {
00395   if (methodName != MULTICALL) return false;
00396 
00397   // There ought to be 1 parameter, an array of structs
00398   if (params.size() != 1 || params[0].getType() != XmlRpcValue::TypeArray)
00399     throw XmlRpcException(MULTICALL + ": Invalid argument (expected an array)");
00400 
00401   int nc = params[0].size();
00402   result.setSize(nc);
00403 
00404   for (int i=0; i<nc; ++i) {
00405 
00406     if ( ! params[0][i].hasMember(METHODNAME) ||
00407          ! params[0][i].hasMember(PARAMS)) {
00408       result[i][FAULTCODE] = -1;
00409       result[i][FAULTSTRING] = MULTICALL +
00410               ": Invalid argument (expected a struct with members methodName and params)";
00411       continue;
00412     }
00413 
00414     const std::string& methodName = params[0][i][METHODNAME];
00415     XmlRpcValue& methodParams = params[0][i][PARAMS];
00416 
00417     XmlRpcValue resultValue;
00418     resultValue.setSize(1);
00419     try {
00420       if ( ! executeMethod(methodName, methodParams, resultValue[0]) &&
00421            ! executeMulticall(methodName, params, resultValue[0]))
00422       {
00423         result[i][FAULTCODE] = -1;
00424         result[i][FAULTSTRING] = methodName + ": unknown method name";
00425       }
00426       else
00427         result[i] = resultValue;
00428 
00429     } catch (const XmlRpcException& fault) {
00430         result[i][FAULTCODE] = fault.getCode();
00431         result[i][FAULTSTRING] = fault.getMessage();
00432     }
00433   }
00434 
00435   return true;
00436 }

std::string XmlRpcServer::generateResponse ( std::string const &  resultXml  )  [protected]

Construct a response from the result XML.

00442 {
00443   const char RESPONSE_1[] = 
00444     "<?xml version=\"1.0\"?>\r\n"
00445     "<methodResponse><params><param>\r\n\t";
00446   const char RESPONSE_2[] =
00447     "\r\n</param></params></methodResponse>\r\n";
00448 
00449   std::string body = RESPONSE_1 + resultXml + RESPONSE_2;
00450   std::string header = generateHeader(body);
00451   std::string response = header + body;
00452 
00453   XmlRpcUtil::log(5, "XmlRpcServer::generateResponse:\n%s\n", response.c_str());
00454   return response;
00455 }

std::string XmlRpcServer::generateFaultResponse ( std::string const &  msg,
int  errorCode = -1 
) [protected]

Construct a fault response.

00479 {
00480   const char RESPONSE_1[] = 
00481     "<?xml version=\"1.0\"?>\r\n"
00482     "<methodResponse><fault>\r\n\t";
00483   const char RESPONSE_2[] =
00484     "\r\n</fault></methodResponse>\r\n";
00485 
00486   XmlRpcValue faultStruct;
00487   faultStruct[FAULTCODE] = errorCode;
00488   faultStruct[FAULTSTRING] = errorMsg;
00489   std::string body = RESPONSE_1 + faultStruct.toXml() + RESPONSE_2;
00490   std::string header = generateHeader(body);
00491 
00492   return header + body;
00493 }

std::string XmlRpcServer::generateHeader ( std::string const &  body  )  [protected]

Return the appropriate headers for the response.

00461 {
00462   std::string header = 
00463     "HTTP/1.1 200 OK\r\n"
00464     "Server: ";
00465   header += XMLRPC_VERSION;
00466   header += "\r\n"
00467     "Content-Type: text/xml\r\n"
00468     "Content-length: ";
00469 
00470   char buffLen[40];
00471   sprintf(buffLen,"%d\r\n\r\n", body.size());
00472 
00473   return header + buffLen;
00474 }


Member Data Documentation

const char XmlRpcServer::METHODNAME_TAG [static, protected]

const char XmlRpcServer::PARAMS_TAG [static, protected]

const char XmlRpcServer::PARAMS_ETAG [static, protected]

const char XmlRpcServer::PARAM_TAG [static, protected]

const char XmlRpcServer::PARAM_ETAG [static, protected]

const std::string XmlRpc::XmlRpcServer::SYSTEM_MULTICALL [static, protected]

const std::string XmlRpcServer::METHODNAME [static, protected]

const std::string XmlRpcServer::PARAMS [static, protected]

const std::string XmlRpcServer::FAULTCODE [static, protected]

const std::string XmlRpcServer::FAULTSTRING [static, protected]

bool XmlRpc::XmlRpcServer::_introspectionEnabled [protected]

Whether the introspection API is supported by this server.

XmlRpcDispatch XmlRpc::XmlRpcServer::_disp [protected]

Event dispatcher.

MethodMap XmlRpc::XmlRpcServer::_methods [protected]

Registered RPC methods.

XmlRpcServerMethod* XmlRpc::XmlRpcServer::_listMethods [protected]

List all registered RPC methods (only available if introspection is enabled).

XmlRpcServerMethod* XmlRpc::XmlRpcServer::_methodHelp [protected]

Return help string for a specified method (only available if introspection is enabled).


The documentation for this class was generated from the following files:
Generated on Tue Jul 24 16:51:19 2007 for ITM OverSim by  doxygen 1.5.1