Moved GreenSSLObject into eventlet.green.socket, cleaned up imports slightly, removed PyOpenSSL dependency -- it will warn you if you need to install it.

This commit is contained in:
Ryan Williams
2009-11-24 12:59:42 -05:00
parent 8e27d09a32
commit 5d72de3d03
6 changed files with 91 additions and 103 deletions

View File

@@ -9,10 +9,8 @@ except AttributeError:
pass
from eventlet.api import get_hub
from eventlet.util import wrap_ssl_obj
from eventlet.greenio import GreenSocket as socket
from eventlet.greenio import GreenSSL as _GreenSSL
from eventlet.greenio import GreenSSLObject as _GreenSSLObject
from eventlet.greenio import SSL as _SSL
def fromfd(*args):
return socket(__socket.fromfd(*args))
@@ -78,5 +76,73 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT):
raise error, msg
def _convert_to_sslerror(ex):
""" Transliterates SSL.SysCallErrors to socket.sslerrors"""
return socket.sslerror((ex[0], ex[1]))
class GreenSSLObject(object):
""" Wrapper object around the SSLObjects returned by socket.ssl, which have a
slightly different interface from SSL.Connection objects. """
def __init__(self, green_ssl_obj):
""" Should only be called by a 'green' socket.ssl """
self.connection = green_ssl_obj
try:
# if it's already connected, do the handshake
self.connection.getpeername()
except:
pass
else:
try:
self.connection.do_handshake()
except _SSL.SysCallError, e:
raise _convert_to_sslerror(e)
def read(self, n=None):
"""If n is provided, read n bytes from the SSL connection, otherwise read
until EOF. The return value is a string of the bytes read."""
if n is None:
# don't support this until someone needs it
raise NotImplementedError("GreenSSLObject does not support "\
" unlimited reads until we hear of someone needing to use them.")
else:
try:
return self.connection.read(n)
except _SSL.ZeroReturnError:
return ''
except _SSL.SysCallError, e:
raise _convert_to_sslerror(e)
def write(self, s):
"""Writes the string s to the on the object's SSL connection.
The return value is the number of bytes written. """
try:
return self.connection.write(s)
except _SSL.SysCallError, e:
raise _convert_to_sslerror(e)
def server(self):
""" Returns a string describing the server's certificate. Useful for debugging
purposes; do not parse the content of this string because its format can't be
parsed unambiguously. """
return str(self.connection.get_peer_certificate().get_subject())
def issuer(self):
"""Returns a string describing the issuer of the server's certificate. Useful
for debugging purposes; do not parse the content of this string because its
format can't be parsed unambiguously."""
return str(self.connection.get_peer_certificate().get_issuer())
try:
from eventlet.green import ssl
def ssl(sock, certificate=None, private_key=None):
return wrap_ssl_obj(sock, certificate, private_key)
warnings.warn("socket.ssl() is deprecated. Use ssl.wrap_socket() instead.",
DeprecationWarning, stacklevel=2)
return ssl.sslwrap_simple(sock, keyfile, certfile)
except ImportError:
def ssl(sock, certificate=None, private_key=None):
from eventlet import util
wrapped = util.wrap_ssl(sock, certificate, private_key)
return GreenSSLObject(wrapped)

View File

@@ -8,7 +8,7 @@ import time
from eventlet.api import trampoline, getcurrent
from thread import get_ident
from eventlet.greenio import set_nonblocking, GreenSocket, GreenSSLObject, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS
from eventlet.greenio import set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS
orig_socket = __import__('socket')
socket = orig_socket.socket
@@ -290,6 +290,7 @@ def sslwrap_simple(sock, keyfile=None, certfile=None):
"""A replacement for the old socket.ssl function. Designed
for compability with Python 2.5 and earlier. Will disappear in
Python 3.0."""
from eventlet.green.socket import GreenSSLObject
ssl_sock = GreenSSLSocket(sock, 0, keyfile, certfile, CERT_NONE,
PROTOCOL_SSLv23, None)
return GreenSSLObject(ssl_sock)

View File

@@ -1,6 +1,4 @@
from eventlet.api import trampoline, get_hub
from eventlet import util
BUFFER_SIZE = 4096
@@ -712,67 +710,3 @@ def shutdown_safe(sock):
if e[0] != errno.ENOTCONN:
raise
def _convert_to_sslerror(ex):
""" Transliterates SSL.SysCallErrors to socket.sslerrors"""
return socket.sslerror((ex[0], ex[1]))
class GreenSSLObject(object):
""" Wrapper object around the SSLObjects returned by socket.ssl, which have a
slightly different interface from SSL.Connection objects. """
def __init__(self, green_ssl_obj):
""" Should only be called by a 'green' socket.ssl """
try:
from eventlet.green.ssl import GreenSSLSocket
except ImportError:
class GreenSSLSocket(object):
pass
assert isinstance(green_ssl_obj, (GreenSSL, GreenSSLSocket))
self.connection = green_ssl_obj
try:
# if it's already connected, do the handshake
self.connection.getpeername()
except:
pass
else:
try:
self.connection.do_handshake()
except SSL.SysCallError, e:
raise _convert_to_sslerror(e)
def read(self, n=None):
"""If n is provided, read n bytes from the SSL connection, otherwise read
until EOF. The return value is a string of the bytes read."""
if n is None:
# don't support this until someone needs it
raise NotImplementedError("GreenSSLObject does not support "\
" unlimited reads until we hear of someone needing to use them.")
else:
try:
return self.connection.read(n)
except SSL.ZeroReturnError:
return ''
except SSL.SysCallError, e:
raise _convert_to_sslerror(e)
def write(self, s):
"""Writes the string s to the on the object's SSL connection.
The return value is the number of bytes written. """
try:
return self.connection.write(s)
except SSL.SysCallError, e:
raise _convert_to_sslerror(e)
def server(self):
""" Returns a string describing the server's certificate. Useful for debugging
purposes; do not parse the content of this string because its format can't be
parsed unambiguously. """
return str(self.connection.get_peer_certificate().get_subject())
def issuer(self):
"""Returns a string describing the issuer of the server's certificate. Useful
for debugging purposes; do not parse the content of this string because its
format can't be parsed unambiguously."""
return str(self.connection.get_peer_certificate().get_issuer())

View File

@@ -3,6 +3,8 @@ import select
import socket
import errno
from eventlet import greenio
def g_log(*args):
import sys
from eventlet.support import greenlets as greenlet
@@ -37,27 +39,21 @@ def tcp_socket():
try:
# if ssl is available, use eventlet.green.ssl for our ssl implementation
import ssl as _ssl
def wrap_ssl(sock, certificate=None, private_key=None, server_side=False):
from eventlet.green import ssl
def wrap_ssl(sock, certificate=None, private_key=None, server_side=False):
return ssl.wrap_socket(sock,
keyfile=private_key, certfile=certificate,
server_side=server_side, cert_reqs=ssl.CERT_NONE,
ssl_version=ssl.PROTOCOL_SSLv23, ca_certs=None,
do_handshake_on_connect=True,
suppress_ragged_eofs=True)
def wrap_ssl_obj(sock, certificate=None, private_key=None):
from eventlet import ssl
warnings.warn("socket.ssl() is deprecated. Use ssl.wrap_socket() instead.",
DeprecationWarning, stacklevel=2)
return ssl.sslwrap_simple(sock, keyfile, certfile)
except ImportError:
# if ssl is not available, use PyOpenSSL
def wrap_ssl(sock, certificate=None, private_key=None, server_side=False):
try:
from OpenSSL import SSL
from eventlet import greenio
except ImportError:
raise ImportError("To use SSL with Eventlet, you must install PyOpenSSL or use Python 2.6 or later.")
context = SSL.Context(SSL.SSLv23_METHOD)
if certificate is not None:
context.use_certificate_file(certificate)
@@ -72,25 +68,15 @@ except ImportError:
connection.set_connect_state()
return greenio.GreenSSL(connection)
def wrap_ssl_obj(sock, certificate=None, private_key=None):
""" For 100% compatibility with the socket module, this wraps and handshakes an
open connection, returning a SSLObject."""
from eventlet import greenio
wrapped = wrap_ssl(sock, certificate, private_key)
return greenio.GreenSSLObject(wrapped)
socket_already_wrapped = False
def wrap_socket_with_coroutine_socket(use_thread_pool=True):
global socket_already_wrapped
if socket_already_wrapped:
return
def new_socket(*args, **kw):
from eventlet import greenio
return greenio.GreenSocket(__original_socket__(*args, **kw))
socket.socket = new_socket
socket.ssl = wrap_ssl_obj
import eventlet.green.socket
socket.socket = eventlet.green.socket.socket
socket.ssl = eventlet.green.socket.ssl
try:
import ssl as _ssl
from eventlet.green import ssl
@@ -115,7 +101,6 @@ def wrap_socket_with_coroutine_socket(use_thread_pool=True):
if __original_fromfd__ is not None:
def new_fromfd(*args, **kw):
from eventlet import greenio
return greenio.GreenSocket(__original_fromfd__(*args, **kw))
socket.fromfd = new_fromfd
@@ -136,7 +121,6 @@ def wrap_pipes_with_coroutine_pipes():
if pipes_already_wrapped:
return
def new_fdopen(*args, **kw):
from eventlet import greenio
return greenio.GreenPipe(__original_fdopen__(*args, **kw))
def new_read(fd, *args, **kw):
from eventlet import api

View File

@@ -6,8 +6,7 @@ from eventlet import __version__
import sys
requirements = []
for flag, req in [('--without-greenlet','greenlet >= 0.2'),
('--without-pyopenssl', 'pyopenssl')]:
for flag, req in [('--without-greenlet','greenlet >= 0.2')]:
if flag in sys.argv:
sys.argv.remove(flag)
else:

View File

@@ -1,6 +1,7 @@
from tests import skipped, LimitedTestCase, skip_with_libevent, TestIsTakingTooLong
from unittest import main
from eventlet import api, util, coros, proc, greenio
from eventlet.green.socket import GreenSSLObject
import os
import socket
import sys
@@ -282,7 +283,7 @@ class SSLTest(LimitedTestCase):
self.private_key_file)
killer = api.spawn(serve, listener)
client = util.wrap_ssl(api.connect_tcp(('localhost', listener.getsockname()[1])))
client = greenio.GreenSSLObject(client)
client = GreenSSLObject(client)
self.assertEquals(client.read(1024), 'content')
self.assertEquals(client.read(1024), '')
@@ -290,7 +291,10 @@ class SSLTest(LimitedTestCase):
def serve(listener):
sock, addr = listener.accept()
stuff = sock.read(8192)
empt = sock.read(8192)
try:
self.assertEquals("", sock.read(8192))
except greenio.SSL.ZeroReturnError:
pass
sock = api.ssl_listener(('127.0.0.1', 0), self.certificate_file, self.private_key_file)
server_coro = coros.execute(serve, sock)