XmlRpc::XmlRpcServerConnection Class Reference

#include <XmlRpcServerConnection.h>

Inheritance diagram for XmlRpc::XmlRpcServerConnection:

XmlRpc::XmlRpcSource

List of all members.


Detailed Description

A class to handle XML RPC requests from a particular client.

Public Member Functions

 XmlRpcServerConnection (int fd, XmlRpcServer *server, bool deleteOnClose=false)
 Constructor.
virtual ~XmlRpcServerConnection ()
 Destructor.
virtual unsigned handleEvent (unsigned eventType)
 Handle IO on the client connection socket.

Protected Types

enum  ServerConnectionState { READ_HEADER, READ_REQUEST, WRITE_RESPONSE }
 Possible IO states for the connection. More...

Protected Member Functions

bool readHeader ()
 Reads the http header.
bool readRequest ()
 Reads the request (based on the content-length header value).
bool writeResponse ()
 Executes the request and writes the resulting response.
virtual void executeRequest ()
 Helper method to execute the client request.

Protected Attributes

XmlRpcServer_server
 The XmlRpc server that accepted this connection.
ServerConnectionState _connectionState
 Current IO state for the connection.
std::string _header
 Request headers.
int _contentLength
 Number of bytes expected in the request body (parsed from header).
std::string _request
 Request body.
std::string _response
 Response.
int _bytesWritten
 Number of bytes of the response written so far.
bool _keepAlive
 Whether to keep the current client connection open for further requests.

Member Enumeration Documentation

Possible IO states for the connection.

Enumerator:
READ_HEADER 
READ_REQUEST 
WRITE_RESPONSE 


Constructor & Destructor Documentation

XmlRpcServerConnection::XmlRpcServerConnection ( int  fd,
XmlRpcServer server,
bool  deleteOnClose = false 
)

Constructor.

00021                                                                                :
00022   XmlRpcSource(fd, deleteOnClose)
00023 {
00024   XmlRpcUtil::log(2,"XmlRpcServerConnection: new socket %d.", fd);
00025   _server = server;
00026   _connectionState = READ_HEADER;
00027   _keepAlive = true;
00028 }

XmlRpcServerConnection::~XmlRpcServerConnection (  )  [virtual]

Destructor.

00032 {
00033   XmlRpcUtil::log(4,"XmlRpcServerConnection dtor.");
00034   _server->removeConnection(this);
00035 }


Member Function Documentation

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

Handle IO on the client connection socket.

Parameters:
eventType Type of IO event that occurred.
See also:
XmlRpcDispatch::EventType.

Implements XmlRpc::XmlRpcSource.

00043 {
00044   if (_connectionState == READ_HEADER)
00045     if ( ! readHeader()) return 0;
00046 
00047   if (_connectionState == READ_REQUEST)
00048     if ( ! readRequest()) return 0;
00049 
00050   if (_connectionState == WRITE_RESPONSE)
00051     if ( ! writeResponse()) return 0;
00052 
00053   return (_connectionState == WRITE_RESPONSE) 
00054         ? XmlRpcDispatch::WritableEvent : XmlRpcDispatch::ReadableEvent;
00055 }

bool XmlRpcServerConnection::readHeader (  )  [protected]

Reads the http header.

Referenced by handleEvent().

00060 {
00061   // Read available data
00062   bool eof;
00063   if ( ! XmlRpcSocket::nbRead(this->getfd(), _header, &eof, _ssl_ssl)) {
00064     // Its only an error if we already have read some data
00065     if (_header.length() > 0)
00066       XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error while reading header (%s).",XmlRpcSocket::getErrorMsg().c_str());
00067     return false;
00068   }
00069 
00070   XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.", _header.length());
00071   char *hp = (char*)_header.c_str();  // Start of header
00072   char *ep = hp + _header.length();   // End of string
00073   char *bp = 0;                       // Start of body
00074   char *lp = 0;                       // Start of content-length value
00075   char *kp = 0;                       // Start of connection value
00076 
00077   for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
00078         if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
00079           lp = cp + 16;
00080         else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0))
00081           kp = cp + 12;
00082         else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
00083           bp = cp + 4;
00084         else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
00085           bp = cp + 2;
00086   }
00087 
00088   // If we haven't gotten the entire header yet, return (keep reading)
00089   if (bp == 0) {
00090     // EOF in the middle of a request is an error, otherwise its ok
00091     if (eof) {
00092       XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF");
00093       if (_header.length() > 0)
00094         XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header");
00095       return false;   // Either way we close the connection
00096     }
00097     
00098     return true;  // Keep reading
00099   }
00100 
00101   // Decode content length
00102   if (lp == 0) {
00103     XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified");
00104     return false;   // We could try to figure it out by parsing as we read, but for now...
00105   }
00106 
00107   _contentLength = atoi(lp);
00108   if (_contentLength <= 0) {
00109     XmlRpcUtil::error("XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).", _contentLength);
00110     return false;
00111   }
00112         
00113   XmlRpcUtil::log(3, "XmlRpcServerConnection::readHeader: specified content length is %d.", _contentLength);
00114 
00115   // Otherwise copy non-header data to request buffer and set state to read request.
00116   _request = bp;
00117 
00118   // Parse out any interesting bits from the header (HTTP version, connection)
00119   _keepAlive = true;
00120   if (_header.find("HTTP/1.0") != std::string::npos) {
00121     if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0)
00122       _keepAlive = false;           // Default for HTTP 1.0 is to close the connection
00123   } else {
00124     if (kp != 0 && strncasecmp(kp, "close", 5) == 0)
00125       _keepAlive = false;
00126   }
00127   XmlRpcUtil::log(3, "KeepAlive: %d", _keepAlive);
00128 
00129 
00130   _header = ""; 
00131   _connectionState = READ_REQUEST;
00132   return true;    // Continue monitoring this source
00133 }

bool XmlRpcServerConnection::readRequest (  )  [protected]

Reads the request (based on the content-length header value).

Referenced by handleEvent().

00139 {
00140   // If we dont have the entire request yet, read available data
00141   if (int(_request.length()) < _contentLength) {
00142     bool eof;
00143     if ( ! XmlRpcSocket::nbRead(this->getfd(), _request, &eof, _ssl_ssl)) {
00144       XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error (%s).",XmlRpcSocket::getErrorMsg().c_str());
00145       return false;
00146     }
00147 
00148     // If we haven't gotten the entire request yet, return (keep reading)
00149     if (int(_request.length()) < _contentLength) {
00150       if (eof) {
00151         XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request");
00152         return false;   // Either way we close the connection
00153       }
00154       return true;
00155     }
00156   }
00157 
00158   // Otherwise, parse and dispatch the request
00159   XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.", _request.length());
00160   //XmlRpcUtil::log(5, "XmlRpcServerConnection::readRequest:\n%s\n", _request.c_str());
00161 
00162   _connectionState = WRITE_RESPONSE;
00163 
00164   return true;    // Continue monitoring this source
00165 }

bool XmlRpcServerConnection::writeResponse (  )  [protected]

Executes the request and writes the resulting response.

Referenced by handleEvent().

00171 {
00172   if (_response.length() == 0) {
00173     executeRequest();
00174     _bytesWritten = 0;
00175     if (_response.length() == 0) {
00176       XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response.");
00177       return false;
00178     }
00179   }
00180 
00181   // Try to write the response
00182   if ( ! XmlRpcSocket::nbWrite(this->getfd(), _response, &_bytesWritten, _ssl_ssl)) {
00183     XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error (%s).",XmlRpcSocket::getErrorMsg().c_str());
00184     return false;
00185   }
00186   XmlRpcUtil::log(3, "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.", _bytesWritten, _response.length());
00187 
00188   // Prepare to read the next request
00189   if (_bytesWritten == int(_response.length())) {
00190     _header = "";
00191     _request = "";
00192     _response = "";
00193     _connectionState = READ_HEADER;
00194   }
00195 
00196   return _keepAlive;    // Continue monitoring this source if true
00197 }

void XmlRpcServerConnection::executeRequest (  )  [protected, virtual]

Helper method to execute the client request.

Referenced by writeResponse().

00202 {
00203   _response = _server->executeRequest(_request);
00204 }


Member Data Documentation

The XmlRpc server that accepted this connection.

Referenced by executeRequest(), XmlRpcServerConnection(), and ~XmlRpcServerConnection().

Current IO state for the connection.

Referenced by handleEvent(), readHeader(), readRequest(), writeResponse(), and XmlRpcServerConnection().

std::string XmlRpc::XmlRpcServerConnection::_header [protected]

Request headers.

Referenced by readHeader(), and writeResponse().

Number of bytes expected in the request body (parsed from header).

Referenced by readHeader(), and readRequest().

Request body.

Referenced by executeRequest(), readHeader(), readRequest(), and writeResponse().

Response.

Referenced by executeRequest(), and writeResponse().

Number of bytes of the response written so far.

Referenced by writeResponse().

Whether to keep the current client connection open for further requests.

Referenced by readHeader(), writeResponse(), and XmlRpcServerConnection().


The documentation for this class was generated from the following files:

Generated on Fri Sep 19 13:05:09 2008 for ITM OverSim by  doxygen 1.5.5