#include <sstream>
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
-#include "polarssl/ssl.h"
+#include "pdns/lock.hh"
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
this->timeout = 2;
this->d_post = false;
this->d_post_json = false;
+ this->d_socket = NULL;
if (options.find("timeout") != options.end()) {
this->timeout = boost::lexical_cast<int>(options.find("timeout")->second)/1000;
this->d_post_json = true;
}
}
- if (options.find("capath") != options.end()) this->d_capath = options.find("capath")->second;
- if (options.find("cafile") != options.end()) this->d_cafile = options.find("cafile")->second;
}
HTTPConnector::~HTTPConnector() {
+ if (d_socket != NULL)
+ delete d_socket;
}
// converts json value into string
}
int HTTPConnector::send_message(const rapidjson::Document &input) {
- int rv,ec;
+ int rv,ec,fd;
std::vector<std::string> members;
std::string method;
restful_requestbuilder(input["method"].GetString(), input["parameters"], req);
rv = -1;
- req.headers["connection"] = "close"; // make sure the other ends knows we are not going to hang around
+ req.headers["connection"] = "Keep-Alive"; // see if we can streamline requests (not needed, strictly speaking)
out << req;
+ // try sending with current socket, if it fails retry with new socket
+ if (this->d_socket != NULL) {
+ fd = this->d_socket->getHandle();
+ // there should be no data waiting
+ if (waitForRWData(fd, true, 0, 1000) < 1) {
+ try {
+ d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout);
+ rv = 1;
+ } catch (NetworkError& ne) {
+ L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": "<<ne.what()<<std::endl;
+ } catch (...) {
+ L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": exception caught"<<std::endl;
+ }
+ }
+ }
+
+ if (rv == 1) return rv;
+
+ delete this->d_socket;
+ this->d_socket = NULL;
+
if (req.url.protocol == "unix") {
// connect using unix socket
} else {
// connect using tcp
- struct addrinfo *gAddr, *gAddrPtr;
+ struct addrinfo *gAddr, *gAddrPtr, hints;
std::string sPort = boost::lexical_cast<std::string>(req.url.port);
- if ((ec = getaddrinfo(req.url.host.c_str(), sPort.c_str(), NULL, &gAddr)) == 0) {
+ memset(&hints,0,sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_ADDRCONFIG;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 6; // tcp
+ if ((ec = getaddrinfo(req.url.host.c_str(), sPort.c_str(), &hints, &gAddr)) == 0) {
// try to connect to each address.
gAddrPtr = gAddr;
+
while(gAddrPtr) {
- d_socket = new Socket(gAddrPtr->ai_family, gAddrPtr->ai_socktype, gAddrPtr->ai_protocol);
try {
- ComboAddress addr = *reinterpret_cast<ComboAddress*>(gAddrPtr->ai_addr);
- d_socket->connect(addr);
+ d_socket = new Socket(gAddrPtr->ai_family, gAddrPtr->ai_socktype, gAddrPtr->ai_protocol);
+ d_addr.setSockaddr(gAddrPtr->ai_addr, gAddrPtr->ai_addrlen);
+ d_socket->connect(d_addr);
d_socket->setNonBlocking();
d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout);
rv = 1;
} catch (NetworkError& ne) {
- L<<Logger::Error<<"While writing to HTTP endpoint: "<<ne.what()<<std::endl;
+ L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": "<<ne.what()<<std::endl;
+ } catch (...) {
+ L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": exception caught"<<std::endl;
}
+
if (rv > -1) break;
delete d_socket;
d_socket = NULL;
gAddrPtr = gAddrPtr->ai_next;
+
}
freeaddrinfo(gAddr);
} else {
if (d_socket == NULL ) return -1; // cannot receive :(
char buffer[4096];
int rd = -1;
+ bool fail = false;
arl.initialize(&resp);
- while(arl.ready() == false) {
- rd = d_socket->readWithTimeout(buffer, sizeof(buffer), timeout);
- if (rd<0) {
- delete d_socket;
- d_socket = NULL;
- return -1;
- }
- buffer[rd] = 0;
- arl.feed(std::string(buffer, rd));
+ try {
+ while(arl.ready() == false) {
+ rd = d_socket->readWithTimeout(buffer, sizeof(buffer), timeout);
+ if (rd<0) {
+ delete d_socket;
+ d_socket = NULL;
+ fail = true;
+ break;
+ }
+ buffer[rd] = 0;
+ arl.feed(std::string(buffer, rd));
+ }
+ } catch (NetworkError &ne) {
+ L<<Logger::Error<<"While reading from HTTP endpoint "<<d_addr.toStringWithPort()<<": "<<ne.what()<<std::endl;
+ delete d_socket;
+ d_socket = NULL;
+ fail = true;
+ } catch (...) {
+ L<<Logger::Error<<"While reading from HTTP endpoint "<<d_addr.toStringWithPort()<<": exception caught"<<std::endl;
+ delete d_socket;
+ fail = true;
+ }
+
+ if (fail) {
+ return -1;
}
arl.finalize();
else
rv = -1;
- delete d_socket;
- d_socket = NULL;
-
return rv;
}