From 0b0741103e7a11e37708eff6ba072de38ad3f4c7 Mon Sep 17 00:00:00 2001 From: mwilliams Date: Fri, 5 Jul 2013 09:37:24 -0700 Subject: [PATCH] Set proper timeouts for SSLSocket If no timeout was specified in fsockopen, we passed in 0.0, which was then used as the actual timeout, meaning that while the socket opened, it almost always failed to open in ssl mode due to timeout, and then read garbage data from the socket. We also failed to pass in the specified timeout for non-ssl sockets, but there we did use the default timeout rather than 0.0. I've changed that to use the passed in timeout instead. --- hphp/runtime/base/file/socket.cpp | 11 ++++++++--- hphp/runtime/base/file/socket.h | 3 ++- hphp/runtime/ext/ext_socket.cpp | 11 +++++++---- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/hphp/runtime/base/file/socket.cpp b/hphp/runtime/base/file/socket.cpp index ca93e58e84f..ba4fcd57671 100644 --- a/hphp/runtime/base/file/socket.cpp +++ b/hphp/runtime/base/file/socket.cpp @@ -53,15 +53,20 @@ Socket::Socket() } Socket::Socket(int sockfd, int type, const char *address /* = NULL */, - int port /* = 0 */) + int port /* = 0 */, double timeout /* = 0 */) : File(true), m_port(port), m_type(type), m_error(0), m_eof(false), m_timeout(0), m_timedOut(false), m_bytesSent(0) { if (address) m_address = address; m_fd = sockfd; struct timeval tv; - tv.tv_sec = RuntimeOption::SocketDefaultTimeout; - tv.tv_usec = 0; + if (timeout <= 0) { + tv.tv_sec = RuntimeOption::SocketDefaultTimeout; + tv.tv_usec = 0; + } else { + tv.tv_sec = (int)timeout; + tv.tv_usec = (timeout - tv.tv_sec) * 1e6; + } setsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); s_socket_data->m_lastErrno = errno; setsockopt(m_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); diff --git a/hphp/runtime/base/file/socket.h b/hphp/runtime/base/file/socket.h index f1713d315e3..aef78125b14 100644 --- a/hphp/runtime/base/file/socket.h +++ b/hphp/runtime/base/file/socket.h @@ -38,7 +38,8 @@ public: // we need to support pfsockopen() that can make a socket persistent. Socket(); - Socket(int sockfd, int type, const char *address = nullptr, int port = 0); + Socket(int sockfd, int type, const char *address = nullptr, int port = 0, + double timeout = 0); virtual ~Socket(); static StaticString s_class_name; diff --git a/hphp/runtime/ext/ext_socket.cpp b/hphp/runtime/ext/ext_socket.cpp index 84f46f8f10f..0bfd99bd4c7 100644 --- a/hphp/runtime/ext/ext_socket.cpp +++ b/hphp/runtime/ext/ext_socket.cpp @@ -281,7 +281,8 @@ static int php_read(Socket *sock, void *buf, int maxlen, int flags) { } static bool create_new_socket(const char *&name, int port, Variant &errnum, - Variant &errstr, Object &ret, Socket *&sock) { + Variant &errstr, Object &ret, Socket *&sock, + double timeout) { int domain = AF_INET; int type = SOCK_STREAM; if (strncmp(name, "udp://", 6) == 0 || strncmp(name, "udg://", 6) == 0) { @@ -294,7 +295,7 @@ static bool create_new_socket(const char *&name, int port, Variant &errnum, name += 7; } - sock = new Socket(socket(domain, type, 0), domain, name, port); + sock = new Socket(socket(domain, type, 0), domain, name, port, timeout); ret = Object(sock); if (!sock->valid()) { SOCKET_ERROR(sock, "unable to create socket", errno); @@ -664,7 +665,7 @@ Variant f_socket_server(CStrRef hostname, int port /* = -1 */, Object ret; Socket *sock = NULL; const char *name = hostname.data(); - if (!create_new_socket(name, port, errnum, errstr, ret, sock)) { + if (!create_new_socket(name, port, errnum, errstr, ret, sock, 0.0)) { return false; } assert(ret.get() && sock); @@ -1000,12 +1001,14 @@ static Variant sockopen_impl(CStrRef hostname, int port, Variant &errnum, const char *name = hostname.data(); Socket *sock = NULL; + if (timeout <= 0) timeout = RuntimeOption::SocketDefaultTimeout; // test if protocol is SSL SSLSocket *sslsock = SSLSocket::Create(name, port, timeout); if (sslsock) { sock = sslsock; ret = sock; - } else if (!create_new_socket(name, port, errnum, errstr, ret, sock)) { + } else if (!create_new_socket(name, port, errnum, errstr, + ret, sock, timeout)) { return false; } assert(ret.get() && sock); -- 2.11.4.GIT