diff --git a/uppsrc/Core/Inet.h b/uppsrc/Core/Inet.h index 30324393c..dd61abb7d 100644 --- a/uppsrc/Core/Inet.h +++ b/uppsrc/Core/Inet.h @@ -88,6 +88,7 @@ class TcpSocket { char *end; bool is_eof; bool is_error; + bool is_timeout; bool is_abort; bool ipv6; @@ -185,12 +186,15 @@ public: bool IsAbort() const { return is_abort; } void ClearAbort() { is_abort = false; } + bool IsTimeout() const { return is_timeout; } + SOCKET GetSOCKET() const { return socket; } String GetPeerAddr() const; void Attach(SOCKET socket); bool Connect(const char *host, int port); bool Connect(IpAddrInfo& info); + bool WaitConnect(); bool Listen(int port, int listen_count = 5, bool ipv6 = false, bool reuse = true, void* addr = NULL); bool Listen(const IpAddrInfo& addr, int port, int listen_count = 5, bool ipv6 = false, bool reuse = true); bool Accept(TcpSocket& listen_socket); diff --git a/uppsrc/Core/Socket.cpp b/uppsrc/Core/Socket.cpp index 94ea233e3..473b0eb41 100644 --- a/uppsrc/Core/Socket.cpp +++ b/uppsrc/Core/Socket.cpp @@ -268,6 +268,7 @@ void TcpSocket::Reset() ptr = end = buffer; is_error = false; is_abort = false; + is_timeout = false; mode = NONE; ssl.Clear(); sslinfo.Clear(); @@ -493,6 +494,23 @@ bool TcpSocket::Connect(const char *host, int port) return Connect(info); } +bool TcpSocket::WaitConnect() +{ + if(WaitWrite()) { + int optval = 0; + socklen_t optlen = sizeof(optval); + if (getsockopt(GetSOCKET(), SOL_SOCKET, SO_ERROR, (char*)&optval, &optlen) == 0) { + if (optval == 0) + return true; + else { + SetSockError("wait connect", -1, Nvl(String(TcpSocketErrorDesc(optval)), "failed")); + return false; + } + } + } + return false; +} + void TcpSocket::RawClose() { LLOG("close " << (int)socket); @@ -584,6 +602,7 @@ bool TcpSocket::IsGlobalTimeout() bool TcpSocket::RawWait(dword flags, int end_time) { // wait till end_time LLOG("RawWait end_time: " << end_time << ", current time " << msecs()); + is_timeout = false; if((flags & WAIT_READ) && ptr != end) return true; if(socket == INVALID_SOCKET) @@ -623,13 +642,15 @@ bool TcpSocket::RawWait(dword flags, int end_time) #endif return true; } - if(IsGlobalTimeout()) - return false; - if(to <= 0 && timeout) + if(IsGlobalTimeout() || to <= 0 && timeout) { + is_timeout = true; return false; + } WhenWait(); - if(timeout == 0) + if(timeout == 0) { + is_timeout = true; return false; + } } } diff --git a/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp b/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp index 9d5456060..c11bd8a13 100644 --- a/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp +++ b/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp @@ -77,6 +77,10 @@ request are ignored. Intended to be called from WhenWait routine.&] [s2;%% Clears the aborted state.&] [s3; &] [s4; &] +[s5;:TcpSocket`:`:IsTimeout`(`)const: [@(0.0.255) bool]_[* IsTimeout]()_[@(0.0.255) const]&] +[s2;%% Returns true if the last operation time`-outed.&] +[s3; &] +[s4; &] [s5;:TcpSocket`:`:GetSOCKET`(`)const: [_^SOCKET^ SOCKET]_[* GetSOCKET]()_[@(0.0.255) const]&] [s2;%% Returns socket handle. Note that all TcpSocket sockets are non`-blocking from host OS perspective.&]