From 2e9f166eba309e50c1c1f52ff8d2694f058ab2cf Mon Sep 17 00:00:00 2001 From: Brian Carlstrom Date: Sun, 18 Apr 2010 11:42:20 -0700 Subject: b/2599994 Should call prepareSocket on underlying socket, not layered socket DefaultClientConnectionOperator.openConnection was recently changed to use LayeredSocketFactory.createSocket(Socket, ...) to create an SSLSocket around a plain java.net.Socket. However, this means code in LayeredSocketFactory.createSocket(Socket, ...) is called before socket options such as timeout are set by DefaultClientConnectionOperator.prepareSocket. However, the default org.apache.http.conn.ssl.SSLSocketFactory.createSocket(Socket, ...) performes the SSL handshake to perform hostname verification, meaning the handshake is performed without timeouts set. This change to DefaultClientConnectionOperator.openConnection moves the call prepareSocket to be on the underlying java.net.Socket before it is has the SSLSocket layered on top of it to prevent hangs during SSL handshakes. Change-Id: If705cc1acfe524281ec1338f73eccf7c0f4d1227 --- .../http/impl/conn/DefaultClientConnectionOperator.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/org/apache/http/impl/conn/DefaultClientConnectionOperator.java b/src/org/apache/http/impl/conn/DefaultClientConnectionOperator.java index 854b2b0..67e6bb0 100644 --- a/src/org/apache/http/impl/conn/DefaultClientConnectionOperator.java +++ b/src/org/apache/http/impl/conn/DefaultClientConnectionOperator.java @@ -148,6 +148,18 @@ public class DefaultClientConnectionOperator sock = connsock; conn.opening(sock, target); } + /* + * prepareSocket is called on the just connected + * socket before the creation of the layered socket to + * ensure that desired socket options such as + * TCP_NODELAY, SO_RCVTIMEO, SO_LINGER will be set + * before any I/O is performed on the socket. This + * happens in the common case as + * SSLSocketFactory.createSocket performs hostname + * verification which requires that SSL handshaking be + * performed. + */ + prepareSocket(sock, context, params); if (layered_sf != null) { Socket layeredsock = layered_sf.createSocket(sock, target.getHostName(), @@ -156,10 +168,8 @@ public class DefaultClientConnectionOperator if (layeredsock != sock) { conn.opening(layeredsock, target); } - prepareSocket(layeredsock, context, params); conn.openCompleted(sf.isSecure(layeredsock), params); } else { - prepareSocket(sock, context, params); conn.openCompleted(sf.isSecure(sock), params); } break; -- cgit v1.1