19 using namespace XmlRpc;
24 "<?xml version=\"1.0\"?>\r\n"
25 "<methodCall><methodName>";
39 XmlRpcUtil::log(1,
"XmlRpcClient new client: host %s, port %d.", host, port);
47 _connectionState = NO_CONNECTION;
50 _ssl =
false; _ssl_ssl = (
SSL *) NULL;
57 XmlRpcUtil::log(1,
"XmlRpcClient new client: host %s, port %d.", host, port);
65 _connectionState = NO_CONNECTION;
69 if (!_ssl) { _ssl_ssl = (
SSL *) NULL; }
77 const char* login,
const char* password,
const char* uri)
79 XmlRpcUtil::log(1,
"XmlRpcClient new client: host %s, port %d, login %s.", host, port, login);
91 _connectionState = NO_CONNECTION;
100 const char* login,
const char* password,
101 const char* uri,
bool ssl)
103 XmlRpcUtil::log(1,
"XmlRpcClient new client: host %s, port %d, login %s.", host, port, login);
113 _password = password;
115 _connectionState = NO_CONNECTION;
119 if (!_ssl) { _ssl_ssl = (
SSL *) NULL; }
128 XmlRpcUtil::log(1,
"XmlRpcClient dtor client: host %s, port %d.", _host.c_str(), _port);
129 if (_connectionState != NO_CONNECTION) close();
138 _connectionState = NO_CONNECTION;
140 _disp.removeSource(
this);
152 XmlRpcUtil::log(4,
"XmlRpcClient::close: before SSL_CTX_free(_ssl_ctx)");
173 XmlRpcUtil::log(1,
"XmlRpcClient::execute: method %s (_connectionState %d).", method, _connectionState);
187 if ( ! setupConnection())
190 if ( ! generateRequest(method, params))
194 double msTime = -1.0;
197 if (_connectionState != IDLE || ! parseResponse(result))
200 XmlRpcUtil::log(1,
"XmlRpcClient::execute: method %s completed.", method);
216 if (_connectionState == WRITE_REQUEST && _bytesWritten == 0)
217 XmlRpcUtil::error(
"Error in XmlRpcClient::handleEvent: could not connect to server (%s).",
225 if (_connectionState == WRITE_REQUEST)
226 if ( ! writeRequest())
return 0;
228 if (_connectionState == READ_HEADER)
229 if ( ! readHeader())
return 0;
231 if (_connectionState == READ_RESPONSE)
232 if ( ! readResponse())
return 0;
235 return (_connectionState == WRITE_REQUEST)
245 if ((_connectionState != NO_CONNECTION && _connectionState != IDLE) || _eof)
249 if (_connectionState == NO_CONNECTION)
254 _connectionState = WRITE_REQUEST;
258 _disp.removeSource(
this);
315 std::string body = REQUEST_BEGIN;
317 body += REQUEST_END_METHODNAME;
324 for (
int i=0; i<params.
size(); ++i) {
326 body += params[i].
toXml();
333 body += params.
toXml();
341 std::string header = generateHeader(body);
342 XmlRpcUtil::log(4,
"XmlRpcClient::generateRequest: header is %d bytes, content-length is %d.",
343 header.length(), body.length());
345 _request = header + body;
354 "POST " + _uri +
" HTTP/1.1\r\n"
357 header +=
"\r\nHost: ";
361 sprintf(buff,
":%d\r\n", _port);
365 if (_login.length() != 0)
368 std::vector<char> base64data;
371 std::back_insert_iterator<std::vector<char> > ins =
372 std::back_inserter(base64data);
374 std::string authBuf = _login +
":" + _password;
376 encoder.
put(authBuf.begin(), authBuf.end(), ins, iostatus,
379 header +=
"Authorization: Basic ";
380 std::string authEnc(base64data.begin(), base64data.end());
382 string::size_type lf;
383 while ( (lf = authEnc.find(
"\r")) != string::npos ) {
384 authEnc.erase(lf, 1);
386 while ( (lf = authEnc.find(
"\n")) != string::npos ) {
387 authEnc.erase(lf, 1);
393 header +=
"Content-Type: text/xml\r\nContent-length: ";
395 sprintf(buff,
"%zu\r\n\r\n", body.size());
397 return header + buff;
403 if (_bytesWritten == 0)
404 XmlRpcUtil::log(5,
"XmlRpcClient::writeRequest (attempt %d):\n%s\n", _sendAttempts+1, _request.c_str());
412 XmlRpcUtil::log(3,
"XmlRpcClient::writeRequest: wrote %d of %d bytes.", _bytesWritten, _request.length());
415 if (_bytesWritten ==
int(_request.length())) {
418 _connectionState = READ_HEADER;
430 (_eof && _header.length() == 0)) {
434 if (getKeepOpen() && _header.length() == 0 && _sendAttempts++ == 0) {
437 _connectionState = NO_CONNECTION;
439 return setupConnection();
442 XmlRpcUtil::error(
"Error in XmlRpcClient::readHeader: error while reading header (%s) on fd %d.",
447 XmlRpcUtil::log(4,
"XmlRpcClient::readHeader: client has read %d bytes", _header.length());
449 char *hp = (
char*)_header.c_str();
450 char *ep = hp + _header.length();
454 for (
char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
455 if ((ep - cp > 16) && (strncasecmp(cp,
"Content-length: ", 16) == 0))
457 else if ((ep - cp > 4) && (strncmp(cp,
"\r\n\r\n", 4) == 0))
459 else if ((ep - cp > 2) && (strncmp(cp,
"\n\n", 2) == 0))
467 XmlRpcUtil::error(
"Error in XmlRpcClient::readHeader: EOF while reading header");
476 XmlRpcUtil::error(
"Error XmlRpcClient::readHeader: No Content-length specified");
480 _contentLength = atoi(lp);
481 if (_contentLength <= 0) {
482 XmlRpcUtil::error(
"Error in XmlRpcClient::readHeader: Invalid Content-length specified (%d).", _contentLength);
491 _connectionState = READ_RESPONSE;
500 if (
int(_response.length()) < _contentLength) {
507 if (
int(_response.length()) < _contentLength) {
509 XmlRpcUtil::error(
"Error in XmlRpcClient::readResponse: EOF while reading response");
517 XmlRpcUtil::log(3,
"XmlRpcClient::readResponse (read %d bytes)", _response.length());
520 _connectionState = IDLE;
533 XmlRpcUtil::error(
"Error in XmlRpcClient::parseResponse: Invalid response - no methodResponse. Response:\n%s", _response.c_str());
542 if ( ! result.
fromXml(_response, &offset)) {
543 XmlRpcUtil::error(
"Error in XmlRpcClient::parseResponse: Invalid response value. Response:\n%s", _response.c_str());
548 XmlRpcUtil::error(
"Error in XmlRpcClient::parseResponse: Invalid response - no param or fault tag. Response:\n%s", _response.c_str());