def recv(self, bufsiz, flags=None):
pending = self._connection.pending()
if pending:
return self._connection.recv(min(pending, bufsiz))
try:
return self.__iowait(self._connection.recv, bufsiz, flags)
except SSL.ZeroReturnError as e:
if self._connection.get_shutdown() == SSL.RECEIVED_SHUTDOWN:
return b''
raise e
except SSL.SysCallError as e:
if e.args == zero_EOF_error:
return b''
elif e.args[0] in zero_errno:
return b''
raise e
python类RECEIVED_SHUTDOWN的实例源码
def recv_into(self, buffer, nbytes=None, flags=None):
pending = self._connection.pending()
if pending:
return self._connection.recv_into(buffer)
try:
return self.__iowait(self._connection.recv_into, buffer, nbytes, flags)
except SSL.ZeroReturnError as e:
if self._connection.get_shutdown() == SSL.RECEIVED_SHUTDOWN:
return 0
raise e
except SSL.SysCallError as e:
if e.args == zero_EOF_error:
return 0
elif e.args[0] in zero_errno:
return 0
raise e
def _postLoseConnection(self):
"""Gets called after loseConnection(), after buffered data is sent.
We try to send an SSL shutdown alert, but if it doesn't work, retry
when the socket is writable.
"""
self.disconnected=1
if hasattr(self.socket, 'set_shutdown'):
self.socket.set_shutdown(SSL.RECEIVED_SHUTDOWN)
return self._sendCloseAlert()
def test_shutdown(self):
"""
`Connection.shutdown` performs an SSL-level connection shutdown.
"""
server, client = loopback()
assert not server.shutdown()
assert server.get_shutdown() == SENT_SHUTDOWN
with pytest.raises(ZeroReturnError):
client.recv(1024)
assert client.get_shutdown() == RECEIVED_SHUTDOWN
client.shutdown()
assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
with pytest.raises(ZeroReturnError):
server.recv(1024)
assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
def test_set_shutdown(self):
"""
`Connection.set_shutdown` sets the state of the SSL connection
shutdown process.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
connection.set_shutdown(RECEIVED_SHUTDOWN)
assert connection.get_shutdown() == RECEIVED_SHUTDOWN
def test_set_shutdown_long(self):
"""
On Python 2 `Connection.set_shutdown` accepts an argument
of type `long` as well as `int`.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
connection.set_shutdown(long(RECEIVED_SHUTDOWN))
assert connection.get_shutdown() == RECEIVED_SHUTDOWN
def _postLoseConnection(self):
"""Gets called after loseConnection(), after buffered data is sent.
We try to send an SSL shutdown alert, but if it doesn't work, retry
when the socket is writable.
"""
self.disconnected=1
if hasattr(self.socket, 'set_shutdown'):
self.socket.set_shutdown(SSL.RECEIVED_SHUTDOWN)
return self._sendCloseAlert()
def test_shutdown(self):
"""
:py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
"""
server, client = self._loopback()
self.assertFalse(server.shutdown())
self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
self.assertRaises(ZeroReturnError, client.recv, 1024)
self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
client.shutdown()
self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
self.assertRaises(ZeroReturnError, server.recv, 1024)
self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
def test_set_shutdown(self):
"""
:py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
process.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
connection.set_shutdown(RECEIVED_SHUTDOWN)
self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
def test_set_shutdown_long(self):
"""
On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
of type :py:obj:`long` as well as :py:obj:`int`.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
connection.set_shutdown(long(RECEIVED_SHUTDOWN))
self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
def test_shutdown(self):
"""
:py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
"""
server, client = self._loopback()
self.assertFalse(server.shutdown())
self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
self.assertRaises(ZeroReturnError, client.recv, 1024)
self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
client.shutdown()
self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
self.assertRaises(ZeroReturnError, server.recv, 1024)
self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
def test_set_shutdown(self):
"""
:py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
process.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
connection.set_shutdown(RECEIVED_SHUTDOWN)
self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
def test_set_shutdown_long(self):
"""
On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
of type :py:obj:`long` as well as :py:obj:`int`.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
connection.set_shutdown(long(RECEIVED_SHUTDOWN))
self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
def test_shutdown(self):
"""
L{Connection.shutdown} performs an SSL-level connection shutdown.
"""
server, client = self._loopback()
self.assertFalse(server.shutdown())
self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
self.assertRaises(ZeroReturnError, client.recv, 1024)
self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
client.shutdown()
self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
self.assertRaises(ZeroReturnError, server.recv, 1024)
self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
def test_set_shutdown(self):
"""
L{Connection.set_shutdown} sets the state of the SSL connection shutdown
process.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
connection.set_shutdown(RECEIVED_SHUTDOWN)
self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
def _sendCloseAlert(self):
# Okay, *THIS* is a bit complicated.
# Basically, the issue is, OpenSSL seems to not actually return
# errors from SSL_shutdown. Therefore, the only way to
# determine if the close notification has been sent is by
# SSL_shutdown returning "done". However, it will not claim it's
# done until it's both sent *and* received a shutdown notification.
# I don't actually want to wait for a received shutdown
# notification, though, so, I have to set RECEIVED_SHUTDOWN
# before calling shutdown. Then, it'll return True once it's
# *SENT* the shutdown.
# However, RECEIVED_SHUTDOWN can't be left set, because then
# reads will fail, breaking half close.
# Also, since shutdown doesn't report errors, an empty write call is
# done first, to try to detect if the connection has gone away.
# (*NOT* an SSL_write call, because that fails once you've called
# shutdown)
try:
os.write(self.socket.fileno(), '')
except OSError, se:
if se.args[0] in (EINTR, EWOULDBLOCK, ENOBUFS):
return 0
# Write error, socket gone
return main.CONNECTION_LOST
try:
if hasattr(self.socket, 'set_shutdown'):
laststate = self.socket.get_shutdown()
self.socket.set_shutdown(laststate | SSL.RECEIVED_SHUTDOWN)
done = self.socket.shutdown()
if not (laststate & SSL.RECEIVED_SHUTDOWN):
self.socket.set_shutdown(SSL.SENT_SHUTDOWN)
else:
#warnings.warn("SSL connection shutdown possibly unreliable, "
# "please upgrade to ver 0.XX", category=UserWarning)
self.socket.shutdown()
done = True
except SSL.Error, e:
return e
if done:
self.stopWriting()
# Note that this is tested for by identity below.
return main.CONNECTION_DONE
else:
self.startWriting()
return None
def _sendCloseAlert(self):
# Okay, *THIS* is a bit complicated.
# Basically, the issue is, OpenSSL seems to not actually return
# errors from SSL_shutdown. Therefore, the only way to
# determine if the close notification has been sent is by
# SSL_shutdown returning "done". However, it will not claim it's
# done until it's both sent *and* received a shutdown notification.
# I don't actually want to wait for a received shutdown
# notification, though, so, I have to set RECEIVED_SHUTDOWN
# before calling shutdown. Then, it'll return True once it's
# *SENT* the shutdown.
# However, RECEIVED_SHUTDOWN can't be left set, because then
# reads will fail, breaking half close.
# Also, since shutdown doesn't report errors, an empty write call is
# done first, to try to detect if the connection has gone away.
# (*NOT* an SSL_write call, because that fails once you've called
# shutdown)
try:
os.write(self.socket.fileno(), '')
except OSError, se:
if se.args[0] in (EINTR, EWOULDBLOCK, ENOBUFS):
return 0
# Write error, socket gone
return main.CONNECTION_LOST
try:
if hasattr(self.socket, 'set_shutdown'):
laststate = self.socket.get_shutdown()
self.socket.set_shutdown(laststate | SSL.RECEIVED_SHUTDOWN)
done = self.socket.shutdown()
if not (laststate & SSL.RECEIVED_SHUTDOWN):
self.socket.set_shutdown(SSL.SENT_SHUTDOWN)
else:
#warnings.warn("SSL connection shutdown possibly unreliable, "
# "please upgrade to ver 0.XX", category=UserWarning)
self.socket.shutdown()
done = True
except SSL.Error, e:
return e
if done:
self.stopWriting()
# Note that this is tested for by identity below.
return main.CONNECTION_DONE
else:
self.startWriting()
return None