added connect timeout, fixed non-closed sockets on connect error

This commit is contained in:
john30
2018-04-04 17:25:39 +02:00
parent c7c5feaea6
commit 230abbb9fb
3 changed files with 58 additions and 9 deletions
+2 -4
View File
@@ -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) { bool HttpClient::connect(const string& host, const uint16_t port, const string& userAgent, const int timeout) {
disconnect(); disconnect();
m_socket = m_client.connect(host, port); m_socket = m_client.connect(host, port, timeout);
if (!m_socket) { if (!m_socket) {
return false; return false;
} }
m_socket->setTimeout(timeout);
m_host = host; m_host = host;
m_port = port; m_port = port;
m_timeout = timeout; m_timeout = timeout;
@@ -88,11 +87,10 @@ bool HttpClient::reconnect() {
if (m_host.empty() || !m_port) { if (m_host.empty() || !m_port) {
return false; 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) { if (!m_socket) {
return false; return false;
} }
m_socket->setTimeout(m_timeout);
return true; return true;
} }
+53 -4
View File
@@ -16,11 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "lib/utils/tcpsocket.h" #include "lib/utils/tcpsocket.h"
#include <fcntl.h> #include <fcntl.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <string.h> #include <string.h>
#ifdef HAVE_PPOLL
# include <poll.h>
#endif
#include <cstdlib> #include <cstdlib>
namespace ebusd { 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; socketaddress address;
int ret; int ret;
@@ -65,11 +72,53 @@ TCPSocket* TCPClient::connect(const string& server, const uint16_t& port) {
if (sfd < 0) { if (sfd < 0) {
return NULL; return NULL;
} }
ret = ::connect(sfd, (struct sockaddr*) &address, sizeof(address)); #ifndef HAVE_PPOLL
if (ret < 0) { #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 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;
} }
+3 -1
View File
@@ -133,9 +133,11 @@ class TCPClient {
* initiate a tcp socket connection to a listening server. * initiate a tcp socket connection to a listening server.
* @param server the server name or ip address to connect. * @param server the server name or ip address to connect.
* @param port the tcp port. * @param port the tcp port.
* @param timeout the connect, send, and receive timeout in seconds, or 0.
* @return pointer to an opened tcp socket. * @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);
}; };
/** /**