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); + }; /**