+ if (iBytesRead < (ssize_t)len && *iError == 0)
+ *iError = ETIMEDOUT;
+
+ return iBytesRead;
+ }
+
+ inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info)
+ {
+ struct addrinfo hints;
+ char service[33];
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ sprintf(service, "%d", iPort);
+
+ *iError = getaddrinfo(strHost, service, &hints, info);
+ return !(*iError);
+ }
+
+ inline int TcpGetSocketError(tcp_socket_t socket)
+ {
+ int iReturn(0);
+ socklen_t optLen = sizeof(tcp_socket_t);
+ getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)&iReturn, &optLen);
+ return iReturn;
+ }
+
+ inline bool TcpSetNoDelay(tcp_socket_t socket)
+ {
+ int iSetTo(1);
+ setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&iSetTo, sizeof(iSetTo));
+ return true;
+ }
+
+ inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0)
+ {
+ TcpSocketSetBlocking(socket, false);
+
+ *iError = 0;
+ int iConnectResult = connect(socket, addr->ai_addr, (int)addr->ai_addrlen);
+ if (iConnectResult == -1)
+ {
+ if (GetSocketError() == EINPROGRESS ||
+ GetSocketError() == EAGAIN)
+ {
+ fd_set fd_write, fd_except;
+ struct timeval tv;
+ tv.tv_sec = (long)(iTimeout / 1000);
+ tv.tv_usec = 1000 * (long)(iTimeout % 1000);
+
+ FD_ZERO(&fd_write);
+ FD_ZERO(&fd_except);
+ FD_SET(socket, &fd_write);
+ FD_SET(socket, &fd_except);
+
+ int iPollResult = select(sizeof(socket)*8, NULL, &fd_write, &fd_except, &tv);
+ if (iPollResult == 0)
+ *iError = ETIMEDOUT;
+ else if (iPollResult == -1)
+ *iError = GetSocketError();
+ else
+ {
+ socklen_t errlen = sizeof(int);
+ getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)iError, &errlen);
+ }
+ }
+ else
+ {
+ *iError = GetSocketError();
+ }
+ }
+
+ TcpSocketSetBlocking(socket, true);
+
+ return *iError == 0;