diff --git a/src/lib/utils/httpclient.cpp b/src/lib/utils/httpclient.cpp
index 83afba46..72284254 100755
--- a/src/lib/utils/httpclient.cpp
+++ b/src/lib/utils/httpclient.cpp
@@ -71,11 +71,10 @@ bool HttpClient::parseUrl(const string& url, string& proto, string& host, uint16
bool HttpClient::connect(const string& host, const uint16_t port, const string& userAgent, const int timeout) {
disconnect();
- m_socket = m_client.connect(host, port);
+ m_socket = m_client.connect(host, port, timeout);
if (!m_socket) {
return false;
}
- m_socket->setTimeout(timeout);
m_host = host;
m_port = port;
m_timeout = timeout;
@@ -88,11 +87,10 @@ bool HttpClient::reconnect() {
if (m_host.empty() || !m_port) {
return false;
}
- m_socket = m_client.connect(m_host, m_port);
+ m_socket = m_client.connect(m_host, m_port, m_timeout);
if (!m_socket) {
return false;
}
- m_socket->setTimeout(m_timeout);
return true;
}
diff --git a/src/lib/utils/tcpsocket.cpp b/src/lib/utils/tcpsocket.cpp
index 6e632e57..f9bf01cc 100755
--- a/src/lib/utils/tcpsocket.cpp
+++ b/src/lib/utils/tcpsocket.cpp
@@ -16,11 +16,18 @@
* along with this program. If not, see .
*/
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
#include "lib/utils/tcpsocket.h"
#include
#include
#include
#include
+#ifdef HAVE_PPOLL
+# include
+#endif
#include
namespace ebusd {
@@ -37,7 +44,7 @@ bool TCPSocket::isValid() {
}
-TCPSocket* TCPClient::connect(const string& server, const uint16_t& port) {
+TCPSocket* TCPClient::connect(const string& server, const uint16_t& port, int timeout) {
socketaddress address;
int ret;
@@ -65,11 +72,53 @@ TCPSocket* TCPClient::connect(const string& server, const uint16_t& port) {
if (sfd < 0) {
return NULL;
}
- ret = ::connect(sfd, (struct sockaddr*) &address, sizeof(address));
- if (ret < 0) {
+#ifndef HAVE_PPOLL
+#ifndef HAVE_PSELECT
+ timeout = 0;
+#endif
+#endif
+ if (timeout > 0 && fcntl(sfd, F_SETFL, O_NONBLOCK) < 0) { // set non-blocking
+ close(sfd);
return NULL;
}
- return new TCPSocket(sfd, &address);
+ ret = ::connect(sfd, (struct sockaddr *) &address, sizeof(address));
+ if (ret != 0) {
+ if (ret < 0 && (timeout <= 0 || errno != EINPROGRESS)) {
+ close(sfd);
+ return NULL;
+ }
+ if (timeout > 0) {
+ struct timespec tdiff;
+ tdiff.tv_sec = timeout;
+ tdiff.tv_nsec = 0;
+#ifdef HAVE_PPOLL
+ nfds_t nfds = 1;
+ struct pollfd fds[nfds];
+ memset(fds, 0, sizeof(fds));
+ fds[0].fd = sfd;
+ fds[0].events = POLLIN|POLLOUT;
+ ret = ppoll(fds, nfds, &tdiff, NULL);
+#else
+ fd_set readfds, writefds;
+ FD_ZERO(&readfds);
+ FD_SET(sfd, &readfds);
+ ret = pselect(sfd + 1, &readfds, &writefds, NULL, &tdiff, NULL);
+#endif
+ if (ret == -1 || ret == 0) {
+ close(sfd);
+ return NULL;
+ }
+ }
+ }
+ if (timeout > 0 && fcntl(sfd, F_SETFL, 0) < 0) { // set blocking again
+ close(sfd);
+ return NULL;
+ }
+ TCPSocket* s = new TCPSocket(sfd, &address);
+ if (timeout > 0) {
+ s->setTimeout(timeout);
+ }
+ return s;
}
diff --git a/src/lib/utils/tcpsocket.h b/src/lib/utils/tcpsocket.h
index 32663436..d715cd71 100755
--- a/src/lib/utils/tcpsocket.h
+++ b/src/lib/utils/tcpsocket.h
@@ -133,9 +133,11 @@ class TCPClient {
* initiate a tcp socket connection to a listening server.
* @param server the server name or ip address to connect.
* @param port the tcp port.
+ * @param timeout the connect, send, and receive timeout in seconds, or 0.
* @return pointer to an opened tcp socket.
*/
- TCPSocket* connect(const string& server, const uint16_t& port);
+ TCPSocket* connect(const string& server, const uint16_t& port, int timeout = 0);
+
};
/**