diff -r 0d8fa49ad7a7 Lib/_socket.py
--- a/Lib/_socket.py Mon Feb 29 15:53:49 2016 +1100
+++ b/Lib/_socket.py Wed Mar 09 22:11:10 2016 -0700
@@ -21,7 +21,7 @@
import java
from java.io import IOException, InterruptedIOException
-from java.lang import Thread, IllegalStateException
+from java.lang import Thread, ArrayIndexOutOfBoundsException, IllegalStateException
from java.net import InetAddress, InetSocketAddress
from java.nio.channels import ClosedChannelException
from java.security.cert import CertificateException
@@ -41,6 +41,8 @@
from org.python.netty.channel.nio import NioEventLoopGroup
from org.python.netty.channel.socket import DatagramPacket
from org.python.netty.channel.socket.nio import NioDatagramChannel, NioSocketChannel, NioServerSocketChannel
+ from org.python.netty.handler.ssl import NotSslRecordException
+
except ImportError:
# dev version from extlibs
from io.netty.bootstrap import Bootstrap, ChannelFactory, ServerBootstrap
@@ -49,7 +51,7 @@
from io.netty.channel.nio import NioEventLoopGroup
from io.netty.channel.socket import DatagramPacket
from io.netty.channel.socket.nio import NioDatagramChannel, NioSocketChannel, NioServerSocketChannel
-
+ from io.netty.handler.ssl import NotSslRecordException
log = logging.getLogger("_socket")
log.setLevel(level=logging.WARNING)
@@ -248,7 +250,7 @@
class herror(error): pass
class gaierror(error): pass
class timeout(error): pass
-class SSLError(error): pass
+class SSLError(error): pass # FIXME import from ssl, solving the usual mutual import schema
SSL_ERROR_SSL = 1
SSL_ERROR_WANT_READ = 2
@@ -259,6 +261,7 @@
SSL_ERROR_WANT_CONNECT = 7
SSL_ERROR_EOF = 8
SSL_ERROR_INVALID_ERROR_CODE = 9
+SSL_UNKNOWN_PROTOCOL = 10 # FIXME check code from OpenSSL
def _add_exception_attrs(exc):
@@ -321,6 +324,12 @@
java.nio.channels.UnsupportedAddressTypeException : None,
SSLPeerUnverifiedException: lambda x: SSLError(SSL_ERROR_SSL, x.message),
+ # FIXME
+ # CPython wraps with a message like so:
+ # ssl.SSLError: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)
+ # Currently this error handler produces this message:
+ # _socket.SSLError: [Errno 1] not an SSL/TLS record: 48692c2049276d206120636c69656e7421
+ NotSslRecordException: lambda x: SSLError(SSL_UNKNOWN_PROTOCOL, x.message),
}
@@ -605,10 +614,11 @@
child.proto = IPPROTO_TCP
child._init_client_mode(child_channel)
- # Get most current options from the parent. This enables any subsequent divergence.
+ # Get most current options from the parent. This enables any
+ # subsequent divergence.
#
- # It's OK that this copy could occur without a mutex, given that such iteration
- # is guaranteed to be weakly consistent
+ # It's OK that this copy could occur without a mutex, given
+ # that such iteration is guaranteed to be weakly consistent
child.options = dict(((option, value) for option, value in self.parent_socket.options.iteritems()))
if child.options:
log.debug("Setting inherited options %s", child.options, extra={"sock": child})
@@ -616,29 +626,51 @@
for option, value in child.options.iteritems():
_set_option(config.setOption, option, value)
- log.debug("Notifing listeners of parent socket %s", self.parent_socket, extra={"sock": child})
- self.parent_socket.child_queue.put(child)
- self.parent_socket._notify_selectors()
- log.debug("Notified listeners of parent socket %s with queue %s",
- self.parent_socket, self.parent_socket.child_queue, extra={"sock": child})
+ # Ensure that this handler will not block if the channel is
+ # closed, otherwise this handler will simply sit idly as a
+ # pending task in the Netty thread pool
+ child_channel.closeFuture().addListener(child._make_active)
- # Must block until the child socket is actually "used". This is
- # because there may be some additional setup required, such as
- # wrapping the socket, before the child is ready to read.
+ # Parent socket is wrapping, so we know intent and we can
+ # return as soon as handshaking is completed, if any
+ if hasattr(self.parent_socket, "ssl_wrap_child_socket"):
+ log.debug("Wrapping child socket for a wrapped parent=%s", self.parent_socket, extra={"sock": self})
+ child._wrapper_socket = self.parent_socket.ssl_wrap_child_socket(child)
+ child._handshake_future.sync()
+ child._post_connect()
+ self.parent_socket.child_queue.put(child)
+ log.debug("Notifing listeners of parent socket %s", self.parent_socket, extra={"sock": child})
+ self.parent_socket._notify_selectors()
+ log.debug("Notified listeners of parent socket %s with queue %s",
+ self.parent_socket, self.parent_socket.child_queue, extra={"sock": child})
+ return
- def unlatch_child(_):
- # FIXME when bound methods are supported for single method interfaces
- child._unlatch()
+ # Otherwise, must wait on this barrier until the child socket
+ # is activated, as demonstrated by use or other setup
+ # info. This is because the child may still be OPTIONALLY
+ # wrapped with an SSL socket. Not blocking here will cause
+ # corruption in send/recv data because it will overlap with
+ # the handshaking in that case.
+ with child._activation_cv:
+ def wait_for_barrier():
+ with child._activation_cv:
+ self.parent_socket.child_queue.put(child)
+ log.debug("Notifing listeners of parent socket %s", self.parent_socket, extra={"sock": child})
+ self.parent_socket._notify_selectors()
+ log.debug("Notified listeners of parent socket %s with queue %s",
+ self.parent_socket, self.parent_socket.child_queue, extra={"sock": child})
+ self.parent_socket.parent_group.submit(wait_for_barrier)
+ while not child._activated:
+ log.debug("Waiting for optional wrapping", extra={"sock": child})
+ child._activation_cv.wait()
- # Ensure that this handler will not block if the channel is closed,
- # otherwise this handler will simply sit idly as a pending task in the Netty
- # thread pool
- child_channel.closeFuture().addListener(unlatch_child)
-
- if self.parent_socket.timeout is None:
- child._ensure_post_connect()
- child._wait_on_latch()
- log.debug("Socket initChannel completed waiting on latch", extra={"sock": child})
+ log.debug("Completed waiting for optional wrapping", extra={"sock": child})
+ if hasattr(child, "ssl_wrap_self"):
+ log.debug("Wrapping self", extra={"sock": child})
+ child.ssl_wrap_self()
+ log.debug("Activating child socket by adding inbound handler", extra={"sock": child})
+ child._post_connect()
+ child._channel_is_initialized = True
# FIXME raise exceptions for ops not permitted on client socket, server socket
@@ -651,8 +683,6 @@
}
-
-
def _identity(value):
return value
@@ -725,7 +755,6 @@
self.timeout = _defaulttimeout
self.channel = None
self.bind_addr = _EPHEMERAL_ADDRESS
- self.bind_timestamp = None # Handle Netty race condition on bound addresses
self.selectors = CopyOnWriteArrayList()
self.options = {} # deferred options until bootstrap
self.peer_closed = False
@@ -748,10 +777,11 @@
return "<_realsocket at {:#x} type={} open_count={} channel={} timeout={}>".format(
id(self), _socket_types[self.socket_type], self.open_count, self.channel, self.timeout)
- def _unlatch(self):
- pass # no-op once mutated from ChildSocket to normal _socketobject
+ def _make_active(self):
+ pass
def _register_selector(self, selector):
+ self._make_active() # attempting to poll/select on a socket means waiting for wrap intent is done
self.selectors.addIfAbsent(selector)
def _unregister_selector(self, selector):
@@ -759,6 +789,8 @@
return self.selectors.remove(selector)
except ValueError:
return None
+ except ArrayIndexOutOfBoundsException:
+ return None
def _notify_selectors(self, exception=None, hangup=False):
for selector in self.selectors:
@@ -867,7 +899,6 @@
self.connect_future = self.channel.connect(addr)
self._handle_channel_future(self.connect_future, "connect")
- self.bind_timestamp = time.time()
def _post_connect(self):
# Post-connect step is necessary to handle SSL setup,
@@ -882,6 +913,7 @@
self.incoming.put(_PEER_CLOSED)
self._notify_selectors(hangup=True)
+ log.debug("Add _peer_closed to channel close", extra={"sock": self})
self.channel.closeFuture().addListener(_peer_closed)
def connect(self, addr):
@@ -906,7 +938,7 @@
if was_connecting:
try:
# Timing is based on CPython and was empirically
- # guestimated. Of course this means user code is
+ # guesstimated. Of course this means user code is
# polling, so the the best we can do is wait like
# this in supposedly nonblocking mode without
# completely busy waiting!
@@ -961,7 +993,6 @@
self.bind_future = b.bind(self.bind_addr.getAddress(), self.bind_addr.getPort())
self._handle_channel_future(self.bind_future, "listen")
- self.bind_timestamp = time.time()
self.channel = self.bind_future.channel()
log.debug("Bound server socket to %s", self.bind_addr, extra={"sock": self})
@@ -1157,6 +1188,7 @@
sendall = send # FIXME see note above!
def _get_incoming_msg(self, reason):
+ log.debug("head=%s incoming=%s" % (self.incoming_head, self.incoming), extra={"sock": self})
if self.incoming_head is None:
if self.timeout is None:
if self.peer_closed:
@@ -1403,28 +1435,25 @@
socket = SocketType = _socketobject
+# FIXME handshake_future - gates all requests. should be cheap (comparable to the old self.active)
+
class ChildSocket(_realsocket):
def __init__(self, parent_socket):
super(ChildSocket, self).__init__(type=parent_socket.type)
self.parent_socket = parent_socket
- self.active = AtomicBoolean()
- self.active_latch = CountDownLatch(1)
+ self._activation_cv = Condition()
+ self._activated = False
self.accepted = False
self.timeout = parent_socket.timeout
- def _ensure_post_connect(self):
- do_post_connect = not self.active.getAndSet(True)
- if do_post_connect:
- if hasattr(self.parent_socket, "ssl_wrap_child_socket"):
- self.parent_socket.ssl_wrap_child_socket(self)
- self._post_connect()
- self.active_latch.countDown()
-
- def _wait_on_latch(self):
- log.debug("Waiting for activity", extra={"sock": self})
- self.active_latch.await()
- log.debug("Latch released, can now proceed", extra={"sock": self})
+ def _make_active(self, *ignore): # ignore result arg when used as a listener on a future
+ if self._activated:
+ return
+ with self._activation_cv:
+ self._activated = True
+ self._activation_cv.notify()
+ log.debug("Child socket is now activated", extra={"sock": self})
# FIXME raise exception for accept, listen, bind, connect, connect_ex
@@ -1434,25 +1463,25 @@
# connection, not metadata.
def send(self, data):
- self._ensure_post_connect()
+ self._make_active()
return super(ChildSocket, self).send(data)
sendall = send
def recv(self, bufsize, flags=0):
- self._ensure_post_connect()
+ self._make_active()
return super(ChildSocket, self).recv(bufsize, flags)
def recvfrom(self, bufsize, flags=0):
- self._ensure_post_connect()
+ self._make_active()
return super(ChildSocket, self).recvfrom(bufsize, flags)
def setblocking(self, mode):
- self._ensure_post_connect()
+ self._make_active()
return super(ChildSocket, self).setblocking(mode)
def close(self):
- self._ensure_post_connect()
+ self._make_active()
super(ChildSocket, self).close()
if self.open_count > 0:
return
@@ -1465,7 +1494,7 @@
self.parent_socket.child_group.shutdownGracefully(0, 100, TimeUnit.MILLISECONDS)
def shutdown(self, how):
- self._ensure_post_connect()
+ self._make_active()
super(ChildSocket, self).shutdown(how)
def __del__(self):
@@ -1474,7 +1503,7 @@
# handler is released when a GC happens, not necessarily
# before shutdown of course. Naturally no extra work will be
# done in setting up the channel.
- self.active_latch.countDown()
+ self._make_active()
self.close()
diff -r 0d8fa49ad7a7 Lib/_sslcerts.py
--- a/Lib/_sslcerts.py Mon Feb 29 15:53:49 2016 +1100
+++ b/Lib/_sslcerts.py Wed Mar 09 22:11:10 2016 -0700
@@ -24,8 +24,9 @@
# http://bugs.jython.org/issue2469, due to the fact that jarjar-ed
# jars - like other shading - lose their signatures. For most jars
# this is not an issue, and we have been removing signature files
- # since 2.7.0, but it causes conflicts Java's security provider
- # model.
+ # since 2.7.0. But in this specific case, removing signatures then
+ # causes conflicts with Java's security provider model, because it
+ # requires signing.
from org.bouncycastle.asn1.pkcs import PrivateKeyInfo
from org.bouncycastle.cert import X509CertificateHolder
from org.bouncycastle.cert.jcajce import JcaX509CertificateConverter
diff -r 0d8fa49ad7a7 Lib/ssl.py
--- a/Lib/ssl.py Mon Feb 29 15:53:49 2016 +1100
+++ b/Lib/ssl.py Wed Mar 09 22:11:10 2016 -0700
@@ -52,6 +52,7 @@
from java.util import ArrayList, Locale, TimeZone, NoSuchElementException
from java.util.concurrent import CountDownLatch
from javax.naming.ldap import LdapName
+from javax.net.ssl import SSLException, SSLHandshakeException
from javax.security.auth.x500 import X500Principal
from org.ietf.jgss import Oid
@@ -393,7 +394,7 @@
All Python stdlib modules shall use this function to create SSLContext
objects in order to keep common settings in one place. The configuration
- is less restrict than create_default_context()'s to increase backward
+ is less restricted than create_default_context()'s to increase backward
compatibility.
"""
if not isinstance(purpose, _ASN1Object):
@@ -443,17 +444,6 @@
pipeline = ch.pipeline()
pipeline.addFirst("ssl", self.ssl_handler)
-class RaceFreeSslHandler(SslHandler):
- """
- This is a temporary workaround to solve a race condition that is present in
- Netty 4.0.33. The race condition causes an NPE because 'this.ctx' isn't set when
- calling channelActive. Once we upgrade to a version of Netty that fixes the race
- condition, we should remove this.
- """
-
- def channelActive(self, ctx):
- self.ctx = ctx
- SslHandler.channelActive(self)
class SSLSocket(object):
@@ -465,6 +455,14 @@
self.sock = sock
self.do_handshake_on_connect = do_handshake_on_connect
self._sock = sock._sock # the real underlying socket
+
+ # FIXME in CPython, a check like so is performed - but this is
+ # not quite correct, based on tests. We should revisit to see
+ # if we can make this work as desired.
+
+ # if do_handshake_on_connect and self._sock.timeout == 0:
+ # raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
+
self._connected = False
if _context:
self._context = _context
@@ -507,30 +505,72 @@
self.ssl_handler = None
# We use _sslobj here to support the CPython convention that
- # an object means we have handshaked, as used by existing code
- # in the wild that looks at this ostensibly internal attribute
- self._sslobj = None
- self.handshake_count = 0
+ # an object means we have handshaked. It is used by existing code
+ # in the wild that looks at this ostensibly internal attribute.
+
+ # FIXME CPython uses _sslobj to track the OpenSSL wrapper
+ # object that's implemented in C, with the following
+ # properties:
+ #
+ # 'cipher', 'compression', 'context', 'do_handshake',
+ # 'peer_certificate', 'pending', 'read', 'shutdown',
+ # 'tls_unique_cb', 'version', 'write'
+ self._sslobj = self # setting to self is not quite right
self.engine = None
if self.do_handshake_on_connect and self._sock.connected:
+ log.debug("Handshaking socket on connect", extra={"sock": self._sock})
if isinstance(self._sock, ChildSocket):
- log.debug("Child socket - do not handshake! type=%s parent=%s", type(self._sock), self._sock.parent_socket,
- extra={"sock": self._sock})
+ # Need to handle child sockets differently depending
+ # on whether the parent socket is wrapped or not.
+ #
+ # In either case, we cannot handshake here in this
+ # thread - it must be done in the child pool and
+ # before the child is activated.
+ #
+ # 1. If wrapped, this is going through SSLSocket.accept
+
+ if isinstance(self._sock.parent_socket, SSLSocket):
+ # already wrapped, via `wrap_child` function a few lines below
+ log.debug(
+ "Child socket - will handshake in child loop type=%s parent=%s",
+ type(self._sock), self._sock.parent_socket,
+ extra={"sock": self._sock})
+ self._sock._make_active()
+
+ # 2. If not, using code will be calling SSLContext.wrap_socket
+ # *after* accept from an unwrapped socket
+
+ else:
+ log.debug("Child socket will wrap self with handshake", extra={"sock": self._sock})
+ setup_handshake_latch = CountDownLatch(1)
+
+ def setup_handshake():
+ handshake_future = self.do_handshake()
+ setup_handshake_latch.countDown()
+ return handshake_future
+
+ self._sock.ssl_wrap_self = setup_handshake
+ self._sock._make_active()
+ setup_handshake_latch.await()
+ log.debug("Child socket waiting on handshake=%s", self._handshake_future, extra={"sock": self._sock})
+ self._sock._handle_channel_future(self._handshake_future, "SSL handshake")
else:
self.do_handshake()
if hasattr(self._sock, "accepted_children"):
def wrap_child(child):
- log.debug("Wrapping child socket - about to handshake! parent=%s", self._sock, extra={"sock": child})
+ log.debug(
+ "Wrapping child socket - about to handshake! parent=%s",
+ self._sock, extra={"sock": child})
child._wrapper_socket = self.context.wrap_socket(
_socketobject(_sock=child),
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs,
server_side=True)
-
if self.do_handshake_on_connect:
+ # this handshake will be done in the child pool - initChannel will block on it
child._wrapper_socket.do_handshake()
self._sock.ssl_wrap_child_socket = wrap_child
@@ -583,15 +623,21 @@
SSL channel, and the address of the remote client."""
child, addr = self._sock.accept()
if self.do_handshake_on_connect:
- child.active_latch.await()
-
- log.debug("accepted sock=%s wrapped=%s addr=%s", child, child._wrapper_socket, addr, extra={"sock": self._sock})
- wrapped_child_socket = child._wrapper_socket
- del child._wrapper_socket
- return wrapped_child_socket, addr
+ wrapped_child_socket = child._wrapper_socket
+ del child._wrapper_socket
+ return wrapped_child_socket, addr
+ else:
+ return self.context.wrap_socket(
+ _socketobject(_sock=child),
+ do_handshake_on_connect=self.do_handshake_on_connect,
+ suppress_ragged_eofs=self.suppress_ragged_eofs,
+ server_side=True)
def unwrap(self):
- self._sock.channel.pipeline().remove("ssl")
+ try:
+ self._sock.channel.pipeline().remove("ssl")
+ except NoSuchElementException:
+ pass
self.ssl_handler.close()
return self._sock
@@ -601,16 +647,10 @@
def handshake_step(result):
log.debug("SSL handshaking completed %s", result, extra={"sock": self._sock})
-
- if not hasattr(self._sock, "active_latch"):
- log.debug("Post connect step", extra={"sock": self._sock})
- self._sock._post_connect()
- self._sock._unlatch()
- self._sslobj = object() # we have now handshaked
self._notify_selectors()
if self.ssl_handler is None:
- self.ssl_handler = RaceFreeSslHandler(self.engine)
+ self.ssl_handler = SslHandler(self.engine)
self.ssl_handler.handshakeFuture().addListener(handshake_step)
if hasattr(self._sock, "connected") and self._sock.connected:
@@ -621,38 +661,52 @@
log.debug("Not connected, adding SSL initializer...", extra={"sock": self._sock})
self._sock.connect_handlers.append(SSLInitializer(self.ssl_handler))
- handshake = self.ssl_handler.handshakeFuture()
- time.sleep(0.001) # Necessary apparently for the handler to get into a good state
+ self._handshake_future = self.ssl_handler.handshakeFuture()
if isinstance(self._sock, ChildSocket):
+ pass
# see
# http://stackoverflow.com/questions/24628271/exception-in-netty-io-netty-util-concurrent-blockingoperationexception
- # - we are doing this in the handler thread!
- return
-
- self._sock._handle_channel_future(handshake, "SSL handshake")
+ # - handshake in the child thread pool
+ else:
+ self._sock._handle_channel_future(self._handshake_future, "SSL handshake")
def dup(self):
raise NotImplemented("Can't dup() %s instances" %
self.__class__.__name__)
+ @raises_java_exception
+ def _ensure_handshake(self):
+ log.debug("Ensure handshake", extra={"sock": self})
+ self._sock._make_active()
+ # nonblocking code should never wait here, but only attempt to
+ # come to this point when notified via a selector
+ if not hasattr(self, "_handshake_future"):
+ self.do_handshake()
+ # additional synchronization guard if this is a child socket
+ self._handshake_future.sync()
+ log.debug("Completed post connect", extra={"sock": self})
+
# Various pass through methods to the wrapped socket
def send(self, data):
+ self._ensure_handshake()
return self.sock.send(data)
write = send
def sendall(self, data):
+ self._ensure_handshake()
return self.sock.sendall(data)
def recv(self, bufsize, flags=0):
+ self._ensure_handshake()
return self.sock.recv(bufsize, flags)
def read(self, len=0, buffer=None):
"""Read up to LEN bytes and return them.
Return zero-length string on EOF."""
-
self._checkClosed()
+ self._ensure_handshake()
# FIXME? breaks test_smtpnet.py
# if not self._sslobj:
# raise ValueError("Read on closed or unwrapped SSL socket.")
@@ -672,17 +726,21 @@
raise
def recvfrom(self, bufsize, flags=0):
+ self._ensure_handshake()
return self.sock.recvfrom(bufsize, flags)
def recvfrom_into(self, buffer, nbytes=0, flags=0):
+ self._ensure_handshake()
return self.sock.recvfrom_into(buffer, nbytes, flags)
def recv_into(self, buffer, nbytes=0, flags=0):
+ self._ensure_handshake()
return self.sock.recv_into(buffer, nbytes, flags)
def sendto(self, string, arg1, arg2=None):
# as observed on CPython, sendto when wrapped ignores the
# destination address, thereby behaving just like send
+ self._ensure_handshake()
return self.sock.send(string)
def close(self):
diff -r 0d8fa49ad7a7 Lib/test/regrtest.py
--- a/Lib/test/regrtest.py Mon Feb 29 15:53:49 2016 +1100
+++ b/Lib/test/regrtest.py Wed Mar 09 22:11:10 2016 -0700
@@ -1313,7 +1313,6 @@
# fails on Windows standalone, probably shouldn't
test_netrc # KeyError: 'foo.domain.com'
- test_shutil # Operation not permitted errors
test_zipfile
# fails on Windows standalone too, but more embarassing as java specific
@@ -1336,18 +1335,16 @@
# Unreliable tests
test_asynchat
- test_gc # Rare failures depending on timing of Java gc
- test_logging
- test_select_new
- test_socket # flakey (Windows)
+ # test_gc # Rare failures depending on timing of Java gc
+ # test_logging
test_tarfile # flakey (Windows)
- test_threading
- test_urllib2net # unexpected output makes this a failure to regrtest.py
+ # test_urllib2net # unexpected output makes this a failure to regrtest.py
- # Tests that should work with socket-reboot, but currently fail/hang
- test_ftplib # NoSuchElementException ssl
+ # Failing tests here are because of lack of STARTTLS; see http://bugs.jython.org/issue2447
+ # (which produces "'NoneType' is not iterable" in the server accept loop)
+ test_ftplib
test_httplib
- test_poplib # 'NoneType' is not iterable
+ test_poplib
test_smtplib
# Problems with the latest JSR 223 changes; see http://bugs.jython.org/issue2154
diff -r 0d8fa49ad7a7 Lib/test/test_socket_jy.py
--- a/Lib/test/test_socket_jy.py Mon Feb 29 15:53:49 2016 +1100
+++ b/Lib/test/test_socket_jy.py Wed Mar 09 22:11:10 2016 -0700
@@ -51,11 +51,11 @@
connect_errno = 0
connect_attempt = 0
- while connect_errno != errno.EISCONN and connect_attempt < 5000:
+ while connect_errno != errno.EISCONN and connect_attempt < 10000:
connect_attempt += 1
connect_errno = sock.connect_ex(self.address)
results[index].append(connect_errno)
- time.sleep(0.001)
+ time.sleep(0.01)
sock.close()
def do_workout(self, num_threads=10):
@@ -108,10 +108,11 @@
connect_attempt = 0
sock = ssl.wrap_socket(sock, certfile=CERTFILE, do_handshake_on_connect=True)
- while connect_errno != errno.EISCONN and connect_attempt < 500:
+ while connect_errno != errno.EISCONN and connect_attempt < 10000:
connect_attempt += 1
connect_errno = sock.connect_ex(self.address)
results[index].append(connect_errno)
+ time.sleep(0.01)
sock.close()
def do_workout(self, num_threads=10):
diff -r 0d8fa49ad7a7 build.xml
--- a/build.xml Mon Feb 29 15:53:49 2016 +1100
+++ b/build.xml Wed Mar 09 22:11:10 2016 -0700
@@ -161,11 +161,11 @@
-
-
-
-
-
+
+
+
+
+
@@ -573,15 +573,15 @@
-
+
-
+
-
+
-
+
-
+
diff -r 0d8fa49ad7a7 extlibs/netty-buffer-4.0.33.Final.jar
Binary file extlibs/netty-buffer-4.0.33.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-buffer-4.0.34.Final.jar
Binary file extlibs/netty-buffer-4.0.34.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-codec-4.0.33.Final.jar
Binary file extlibs/netty-codec-4.0.33.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-codec-4.0.34.Final.jar
Binary file extlibs/netty-codec-4.0.34.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-common-4.0.33.Final.jar
Binary file extlibs/netty-common-4.0.33.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-common-4.0.34.Final.jar
Binary file extlibs/netty-common-4.0.34.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-handler-4.0.33.Final.jar
Binary file extlibs/netty-handler-4.0.33.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-handler-4.0.34.Final.jar
Binary file extlibs/netty-handler-4.0.34.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-transport-4.0.33.Final.jar
Binary file extlibs/netty-transport-4.0.33.Final.jar has changed
diff -r 0d8fa49ad7a7 extlibs/netty-transport-4.0.34.Final.jar
Binary file extlibs/netty-transport-4.0.34.Final.jar has changed