XmlRpcServerConnection.cc
Go to the documentation of this file.00001
00008 #include "XmlRpcServerConnection.h"
00009
00010 #include "XmlRpcSocket.h"
00011 #ifndef MAKEDEPEND
00012 # include <stdio.h>
00013 # include <stdlib.h>
00014 # include <string.h>
00015 #endif
00016
00017 #include "XmlRpcDispatch.h"
00018 #include "XmlRpcServer.h"
00019 #include "XmlRpcUtil.h"
00020
00021 using namespace XmlRpc;
00022
00023
00024
00025
00026 XmlRpcServerConnection::XmlRpcServerConnection(int fd,
00027 XmlRpcServer* server,
00028 bool deleteOnClose ) :
00029 XmlRpcSource(fd, deleteOnClose)
00030 {
00031 XmlRpcUtil::log(2,"XmlRpcServerConnection: new socket %d.", fd);
00032 _server = server;
00033 _connectionState = READ_HEADER;
00034 _keepAlive = true;
00035 }
00036
00037
00038 XmlRpcServerConnection::~XmlRpcServerConnection()
00039 {
00040 XmlRpcUtil::log(4,"XmlRpcServerConnection dtor.");
00041 _server->removeConnection(this);
00042 }
00043
00044
00045
00046
00047
00048 unsigned
00049 XmlRpcServerConnection::handleEvent(unsigned )
00050 {
00051 if (_connectionState == READ_HEADER)
00052 if ( ! readHeader()) return 0;
00053
00054 if (_connectionState == READ_REQUEST)
00055 if ( ! readRequest()) return 0;
00056
00057 if (_connectionState == WRITE_RESPONSE)
00058 if ( ! writeResponse()) return 0;
00059
00060 return (_connectionState == WRITE_RESPONSE)
00061 ? XmlRpcDispatch::WritableEvent : XmlRpcDispatch::ReadableEvent;
00062 }
00063
00064
00065 bool
00066 XmlRpcServerConnection::readHeader()
00067 {
00068
00069 bool eof;
00070 if ( ! XmlRpcSocket::nbRead(this->getfd(), _header, &eof, _ssl_ssl)) {
00071
00072 if (_header.length() > 0)
00073 XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error while reading header (%s).",XmlRpcSocket::getErrorMsg().c_str());
00074 return false;
00075 }
00076
00077 XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.", _header.length());
00078 char *hp = (char*)_header.c_str();
00079 char *ep = hp + _header.length();
00080 char *bp = 0;
00081 char *lp = 0;
00082 char *kp = 0;
00083
00084 for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
00085 if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
00086 lp = cp + 16;
00087 else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0))
00088 kp = cp + 12;
00089 else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
00090 bp = cp + 4;
00091 else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
00092 bp = cp + 2;
00093 }
00094
00095
00096 if (bp == 0) {
00097
00098 if (eof) {
00099 XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF");
00100 if (_header.length() > 0)
00101 XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header");
00102 return false;
00103 }
00104
00105 return true;
00106 }
00107
00108
00109 if (lp == 0) {
00110 XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified");
00111 return false;
00112 }
00113
00114 _contentLength = atoi(lp);
00115 if (_contentLength <= 0) {
00116 XmlRpcUtil::error("XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).", _contentLength);
00117 return false;
00118 }
00119
00120 XmlRpcUtil::log(3, "XmlRpcServerConnection::readHeader: specified content length is %d.", _contentLength);
00121
00122
00123 _request = bp;
00124
00125
00126 _keepAlive = true;
00127 if (_header.find("HTTP/1.0") != std::string::npos) {
00128 if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0)
00129 _keepAlive = false;
00130 } else {
00131 if (kp != 0 && strncasecmp(kp, "close", 5) == 0)
00132 _keepAlive = false;
00133 }
00134 XmlRpcUtil::log(3, "KeepAlive: %d", _keepAlive);
00135
00136
00137 _header = "";
00138 _connectionState = READ_REQUEST;
00139 return true;
00140 }
00141
00142
00143
00144 bool
00145 XmlRpcServerConnection::readRequest()
00146 {
00147
00148 if (int(_request.length()) < _contentLength) {
00149 bool eof;
00150 if ( ! XmlRpcSocket::nbRead(this->getfd(), _request, &eof, _ssl_ssl)) {
00151 XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error (%s).",XmlRpcSocket::getErrorMsg().c_str());
00152 return false;
00153 }
00154
00155
00156 if (int(_request.length()) < _contentLength) {
00157 if (eof) {
00158 XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request");
00159 return false;
00160 }
00161 return true;
00162 }
00163 }
00164
00165
00166 XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.", _request.length());
00167
00168
00169 _connectionState = WRITE_RESPONSE;
00170
00171 return true;
00172 }
00173
00174
00175
00176 bool
00177 XmlRpcServerConnection::writeResponse()
00178 {
00179 if (_response.length() == 0) {
00180 executeRequest();
00181 _bytesWritten = 0;
00182 if (_response.length() == 0) {
00183 XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response.");
00184 return false;
00185 }
00186 }
00187
00188
00189 if ( ! XmlRpcSocket::nbWrite(this->getfd(), _response, &_bytesWritten, _ssl_ssl)) {
00190 XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error (%s).",XmlRpcSocket::getErrorMsg().c_str());
00191 return false;
00192 }
00193 XmlRpcUtil::log(3, "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.", _bytesWritten, _response.length());
00194
00195
00196 if (_bytesWritten == int(_response.length())) {
00197 _header = "";
00198 _request = "";
00199 _response = "";
00200 _connectionState = READ_HEADER;
00201 }
00202
00203 return _keepAlive;
00204 }
00205
00206
00208 void XmlRpcServerConnection::executeRequest()
00209 {
00210 _response = _server->executeRequest(_request);
00211 }
00212