[pypy-svn] r63903 - in pypy/trunk/pypy/module/_ssl: . test
afa at codespeak.net
afa at codespeak.net
Thu Apr 9 16:51:26 CEST 2009
Author: afa
Date: Thu Apr 9 16:51:25 2009
New Revision: 63903
Removed:
pypy/trunk/pypy/module/_ssl/_ssl.c
pypy/trunk/pypy/module/_ssl/bio.py
pypy/trunk/pypy/module/_ssl/ssl.py
Modified:
pypy/trunk/pypy/module/_ssl/__init__.py
pypy/trunk/pypy/module/_ssl/interp_ssl.py
pypy/trunk/pypy/module/_ssl/test/test_ssl.py
Log:
Re-enable the _ssl module.
It works and translates, at least on Windows.
I tested with urllib2, on a https:// query, with and without timeout.
Modified: pypy/trunk/pypy/module/_ssl/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/_ssl/__init__.py (original)
+++ pypy/trunk/pypy/module/_ssl/__init__.py Thu Apr 9 16:51:25 2009
@@ -1,10 +1,3 @@
-#import py # FINISHME - more thinking needed
-raise ImportError
-#skip("The _ssl module is only usable when running on the exact "
-# "same platform from which the ssl.py was computed.")
-
-# This module is imported by socket.py. It should *not* be used
-# directly.
from pypy.interpreter.mixedmodule import MixedModule
class Module(MixedModule):
@@ -16,19 +9,22 @@
'__doc__': 'app_ssl.__doc__',
'sslerror': 'app_ssl.sslerror',
}
-
+
+ @classmethod
def buildloaders(cls):
# init the SSL module
- from pypy.module._ssl.interp_ssl import _init_ssl, constants, HAVE_OPENSSL_RAND
- _init_ssl()
-
+ from pypy.module._ssl.interp_ssl import constants, HAVE_OPENSSL_RAND
+
for constant, value in constants.iteritems():
Module.interpleveldefs[constant] = "space.wrap(%r)" % value
-
+
if HAVE_OPENSSL_RAND:
Module.interpleveldefs['RAND_add'] = "interp_ssl.RAND_add"
Module.interpleveldefs['RAND_status'] = "interp_ssl.RAND_status"
Module.interpleveldefs['RAND_egd'] = "interp_ssl.RAND_egd"
-
+
super(Module, cls).buildloaders()
- buildloaders = classmethod(buildloaders)
+
+ def startup(self, space):
+ from pypy.module._ssl.interp_ssl import _init_ssl
+ _init_ssl()
Modified: pypy/trunk/pypy/module/_ssl/interp_ssl.py
==============================================================================
--- pypy/trunk/pypy/module/_ssl/interp_ssl.py (original)
+++ pypy/trunk/pypy/module/_ssl/interp_ssl.py Thu Apr 9 16:51:25 2009
@@ -1,25 +1,36 @@
-from pypy.rpython.rctypes.tool import ctypes_platform
-from pypy.rpython.rctypes.tool.libc import libc
-import pypy.rpython.rctypes.implementation # this defines rctypes magic
+from pypy.rpython.lltypesystem import rffi, lltype
from pypy.interpreter.error import OperationError
from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app
-from ctypes import *
-import ctypes.util
-import sys
-import socket
-import select
+from pypy.rpython.tool import rffi_platform
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+
+from pypy.rlib import rpoll
-from ssl import SSL_CTX, SSL, X509, SSL_METHOD, X509_NAME
-from bio import BIO
+import sys
-c_void = None
-libssl = cdll.LoadLibrary(ctypes.util.find_library("ssl"))
+if sys.platform == 'win32':
+ libraries = ['libeay32', 'ssleay32', 'user32', 'advapi32', 'gdi32']
+else:
+ libraries = ['ssl']
+
+eci = ExternalCompilationInfo(
+ libraries = libraries,
+ includes = ['openssl/ssl.h',
+ ],
+ export_symbols = ['SSL_load_error_strings'],
+ )
+
+eci = rffi_platform.configure_external_library(
+ 'openssl', eci,
+ [dict(prefix='openssl-',
+ include_dir='inc32', library_dir='out32'),
+ ])
## user defined constants
X509_NAME_MAXLEN = 256
-# these mirror ssl.h
+## # these mirror ssl.h
PY_SSL_ERROR_NONE, PY_SSL_ERROR_SSL = 0, 1
PY_SSL_ERROR_WANT_READ, PY_SSL_ERROR_WANT_WRITE = 2, 3
PY_SSL_ERROR_WANT_X509_LOOKUP = 4
@@ -33,69 +44,56 @@
SOCKET_HAS_TIMED_OUT, SOCKET_HAS_BEEN_CLOSED = 2, 3
SOCKET_TOO_LARGE_FOR_SELECT, SOCKET_OPERATION_OK = 4, 5
+# WinSock does not use a bitmask in select, and uses
+# socket handles greater than FD_SETSIZE
+if sys.platform == 'win32':
+ MAX_FD_SIZE = None
+else:
+ from pypy.rlib._rsocket_rffi import FD_SETSIZE as MAX_FD_SIZE
+
+HAVE_RPOLL = True # Even win32 has rpoll.poll
class CConfig:
- _header_ = """
- #include <openssl/ssl.h>
- #include <openssl/opensslv.h>
- #include <openssl/bio.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/poll.h>
- """
- OPENSSL_VERSION_NUMBER = ctypes_platform.ConstantInteger(
+ _compilation_info_ = eci
+
+ OPENSSL_VERSION_NUMBER = rffi_platform.ConstantInteger(
"OPENSSL_VERSION_NUMBER")
- SSL_FILETYPE_PEM = ctypes_platform.ConstantInteger("SSL_FILETYPE_PEM")
- SSL_OP_ALL = ctypes_platform.ConstantInteger("SSL_OP_ALL")
- SSL_VERIFY_NONE = ctypes_platform.ConstantInteger("SSL_VERIFY_NONE")
- SSL_ERROR_WANT_READ = ctypes_platform.ConstantInteger(
+ SSL_FILETYPE_PEM = rffi_platform.ConstantInteger("SSL_FILETYPE_PEM")
+ SSL_OP_ALL = rffi_platform.ConstantInteger("SSL_OP_ALL")
+ SSL_VERIFY_NONE = rffi_platform.ConstantInteger("SSL_VERIFY_NONE")
+ SSL_ERROR_WANT_READ = rffi_platform.ConstantInteger(
"SSL_ERROR_WANT_READ")
- SSL_ERROR_WANT_WRITE = ctypes_platform.ConstantInteger(
+ SSL_ERROR_WANT_WRITE = rffi_platform.ConstantInteger(
"SSL_ERROR_WANT_WRITE")
- SSL_ERROR_ZERO_RETURN = ctypes_platform.ConstantInteger(
+ SSL_ERROR_ZERO_RETURN = rffi_platform.ConstantInteger(
"SSL_ERROR_ZERO_RETURN")
- SSL_ERROR_WANT_X509_LOOKUP = ctypes_platform.ConstantInteger(
+ SSL_ERROR_WANT_X509_LOOKUP = rffi_platform.ConstantInteger(
"SSL_ERROR_WANT_X509_LOOKUP")
- SSL_ERROR_WANT_CONNECT = ctypes_platform.ConstantInteger(
+ SSL_ERROR_WANT_CONNECT = rffi_platform.ConstantInteger(
"SSL_ERROR_WANT_CONNECT")
- SSL_ERROR_SYSCALL = ctypes_platform.ConstantInteger("SSL_ERROR_SYSCALL")
- SSL_ERROR_SSL = ctypes_platform.ConstantInteger("SSL_ERROR_SSL")
- FD_SETSIZE = ctypes_platform.ConstantInteger("FD_SETSIZE")
- SSL_CTRL_OPTIONS = ctypes_platform.ConstantInteger("SSL_CTRL_OPTIONS")
- BIO_C_SET_NBIO = ctypes_platform.ConstantInteger("BIO_C_SET_NBIO")
- pollfd = ctypes_platform.Struct("struct pollfd",
- [("fd", c_int), ("events", c_short), ("revents", c_short)])
- nfds_t = ctypes_platform.SimpleType("nfds_t", c_uint)
- POLLOUT = ctypes_platform.ConstantInteger("POLLOUT")
- POLLIN = ctypes_platform.ConstantInteger("POLLIN")
-
-class cConfig:
- pass
-
-cConfig.__dict__.update(ctypes_platform.configure(CConfig))
-
-OPENSSL_VERSION_NUMBER = cConfig.OPENSSL_VERSION_NUMBER
-HAVE_OPENSSL_RAND = OPENSSL_VERSION_NUMBER >= 0x0090500fL
-SSL_FILETYPE_PEM = cConfig.SSL_FILETYPE_PEM
-SSL_OP_ALL = cConfig.SSL_OP_ALL
-SSL_VERIFY_NONE = cConfig.SSL_VERIFY_NONE
-SSL_ERROR_WANT_READ = cConfig.SSL_ERROR_WANT_READ
-SSL_ERROR_WANT_WRITE = cConfig.SSL_ERROR_WANT_WRITE
-SSL_ERROR_ZERO_RETURN = cConfig.SSL_ERROR_ZERO_RETURN
-SSL_ERROR_WANT_X509_LOOKUP = cConfig.SSL_ERROR_WANT_X509_LOOKUP
-SSL_ERROR_WANT_CONNECT = cConfig.SSL_ERROR_WANT_CONNECT
-SSL_ERROR_SYSCALL = cConfig.SSL_ERROR_SYSCALL
-SSL_ERROR_SSL = cConfig.SSL_ERROR_SSL
-FD_SETSIZE = cConfig.FD_SETSIZE
-SSL_CTRL_OPTIONS = cConfig.SSL_CTRL_OPTIONS
-BIO_C_SET_NBIO = cConfig.BIO_C_SET_NBIO
-POLLOUT = cConfig.POLLOUT
-POLLIN = cConfig.POLLIN
-
-pollfd = cConfig.pollfd
-nfds_t = cConfig.nfds_t
+ SSL_ERROR_SYSCALL = rffi_platform.ConstantInteger("SSL_ERROR_SYSCALL")
+ SSL_ERROR_SSL = rffi_platform.ConstantInteger("SSL_ERROR_SSL")
+ SSL_CTRL_OPTIONS = rffi_platform.ConstantInteger("SSL_CTRL_OPTIONS")
+ BIO_C_SET_NBIO = rffi_platform.ConstantInteger("BIO_C_SET_NBIO")
+
+for k, v in rffi_platform.configure(CConfig).items():
+ globals()[k] = v
+
+# opaque structures
+SSL_METHOD = rffi.VOIDP
+SSL_CTX = rffi.VOIDP
+SSL = rffi.VOIDP
+BIO = rffi.VOIDP
+X509 = rffi.VOIDP
+X509_NAME = rffi.VOIDP
+
+SSL_CTX_P = rffi.CArrayPtr(SSL_CTX)
+BIO_P = rffi.CArrayPtr(BIO)
+SSL_P = rffi.CArrayPtr(SSL)
+X509_P = rffi.CArrayPtr(X509)
+X509_NAME_P = rffi.CArrayPtr(X509_NAME)
-arr_x509 = c_char * X509_NAME_MAXLEN
+HAVE_OPENSSL_RAND = OPENSSL_VERSION_NUMBER >= 0x0090500f
constants = {}
constants["SSL_ERROR_ZERO_RETURN"] = PY_SSL_ERROR_ZERO_RETURN
@@ -108,73 +106,48 @@
constants["SSL_ERROR_EOF"] = PY_SSL_ERROR_EOF
constants["SSL_ERROR_INVALID_ERROR_CODE"] = PY_SSL_ERROR_INVALID_ERROR_CODE
-libssl.SSL_load_error_strings.restype = c_void
-libssl.SSL_library_init.restype = c_int
+def ssl_external(name, argtypes, restype, **kw):
+ kw['compilation_info'] = eci
+ globals()['libssl_' + name] = rffi.llexternal(
+ name, argtypes, restype, **kw)
+
+ssl_external('SSL_load_error_strings', [], lltype.Void)
+ssl_external('SSL_library_init', [], rffi.INT)
if HAVE_OPENSSL_RAND:
- libssl.RAND_add.argtypes = [c_char_p, c_int, c_double]
- libssl.RAND_add.restype = c_void
- libssl.RAND_status.restype = c_int
- libssl.RAND_egd.argtypes = [c_char_p]
- libssl.RAND_egd.restype = c_int
-libssl.SSL_CTX_new.argtypes = [POINTER(SSL_METHOD)]
-libssl.SSL_CTX_new.restype = POINTER(SSL_CTX)
-libssl.SSLv23_method.restype = POINTER(SSL_METHOD)
-libssl.SSL_CTX_use_PrivateKey_file.argtypes = [POINTER(SSL_CTX), c_char_p, c_int]
-libssl.SSL_CTX_use_PrivateKey_file.restype = c_int
-libssl.SSL_CTX_use_certificate_chain_file.argtypes = [POINTER(SSL_CTX), c_char_p]
-libssl.SSL_CTX_use_certificate_chain_file.restype = c_int
-libssl.SSL_CTX_ctrl.argtypes = [POINTER(SSL_CTX), c_int, c_int, c_void_p]
-libssl.SSL_CTX_ctrl.restype = c_int
-libssl.SSL_CTX_set_verify.argtypes = [POINTER(SSL_CTX), c_int, c_void_p]
-libssl.SSL_CTX_set_verify.restype = c_void
-libssl.SSL_new.argtypes = [POINTER(SSL_CTX)]
-libssl.SSL_new.restype = POINTER(SSL)
-libssl.SSL_set_fd.argtypes = [POINTER(SSL), c_int]
-libssl.SSL_set_fd.restype = c_int
-libssl.BIO_ctrl.argtypes = [POINTER(BIO), c_int, c_int, c_void_p]
-libssl.BIO_ctrl.restype = c_int
-libssl.SSL_get_rbio.argtypes = [POINTER(SSL)]
-libssl.SSL_get_rbio.restype = POINTER(BIO)
-libssl.SSL_get_wbio.argtypes = [POINTER(SSL)]
-libssl.SSL_get_wbio.restype = POINTER(BIO)
-libssl.SSL_set_connect_state.argtypes = [POINTER(SSL)]
-libssl.SSL_set_connect_state.restype = c_void
-libssl.SSL_connect.argtypes = [POINTER(SSL)]
-libssl.SSL_connect.restype = c_int
-libssl.SSL_get_error.argtypes = [POINTER(SSL), c_int]
-libssl.SSL_get_error.restype = c_int
-have_poll = False
-if hasattr(libc, "poll"):
- have_poll = True
- libc.poll.argtypes = [POINTER(pollfd), nfds_t, c_int]
- libc.poll.restype = c_int
-libssl.ERR_get_error.restype = c_int
-libssl.ERR_error_string.argtypes = [c_int, c_char_p]
-libssl.ERR_error_string.restype = c_char_p
-libssl.SSL_get_peer_certificate.argtypes = [POINTER(SSL)]
-libssl.SSL_get_peer_certificate.restype = POINTER(X509)
-libssl.X509_get_subject_name.argtypes = [POINTER(X509)]
-libssl.X509_get_subject_name.restype = POINTER(X509_NAME)
-libssl.X509_get_issuer_name.argtypes = [POINTER(X509)]
-libssl.X509_get_issuer_name.restype = POINTER(X509_NAME)
-libssl.X509_NAME_oneline.argtypes = [POINTER(X509_NAME), arr_x509, c_int]
-libssl.X509_NAME_oneline.restype = c_char_p
-libssl.X509_free.argtypes = [POINTER(X509)]
-libssl.X509_free.restype = c_void
-libssl.SSL_free.argtypes = [POINTER(SSL)]
-libssl.SSL_free.restype = c_void
-libssl.SSL_CTX_free.argtypes = [POINTER(SSL_CTX)]
-libssl.SSL_CTX_free.restype = c_void
-libssl.SSL_write.argtypes = [POINTER(SSL), c_char_p, c_int]
-libssl.SSL_write.restype = c_int
-libssl.SSL_pending.argtypes = [POINTER(SSL)]
-libssl.SSL_pending.restype = c_int
-libssl.SSL_read.argtypes = [POINTER(SSL), c_char_p, c_int]
-libssl.SSL_read.restype = c_int
+ ssl_external('RAND_add', [rffi.CCHARP, rffi.INT, rffi.DOUBLE], lltype.Void)
+ ssl_external('RAND_status', [], rffi.INT)
+ ssl_external('RAND_egd', [rffi.CCHARP], rffi.INT)
+ssl_external('SSL_CTX_new', [rffi.CArrayPtr(SSL_METHOD)], SSL_CTX_P)
+ssl_external('SSLv23_method', [], rffi.CArrayPtr(SSL_METHOD))
+ssl_external('SSL_CTX_use_PrivateKey_file', [SSL_CTX_P, rffi.CCHARP, rffi.INT], rffi.INT)
+ssl_external('SSL_CTX_use_certificate_chain_file', [SSL_CTX_P, rffi.CCHARP], rffi.INT)
+ssl_external('SSL_CTX_ctrl', [SSL_CTX_P, rffi.INT, rffi.INT, rffi.VOIDP], rffi.INT)
+ssl_external('SSL_CTX_set_verify', [SSL_CTX_P, rffi.INT, rffi.VOIDP], lltype.Void)
+ssl_external('SSL_new', [SSL_CTX_P], SSL_P)
+ssl_external('SSL_set_fd', [SSL_P, rffi.INT], rffi.INT)
+ssl_external('BIO_ctrl', [BIO_P, rffi.INT, rffi.INT, rffi.VOIDP], rffi.INT)
+ssl_external('SSL_get_rbio', [SSL_P], BIO_P)
+ssl_external('SSL_get_wbio', [SSL_P], BIO_P)
+ssl_external('SSL_set_connect_state', [SSL_P], lltype.Void)
+ssl_external('SSL_connect', [SSL_P], rffi.INT)
+ssl_external('SSL_get_error', [SSL_P, rffi.INT], rffi.INT)
+
+ssl_external('ERR_get_error', [], rffi.INT)
+ssl_external('ERR_error_string', [rffi.INT, rffi.CCHARP], rffi.CCHARP)
+ssl_external('SSL_get_peer_certificate', [SSL_P], X509_P)
+ssl_external('X509_get_subject_name', [X509_P], X509_NAME_P)
+ssl_external('X509_get_issuer_name', [X509_P], X509_NAME_P)
+ssl_external('X509_NAME_oneline', [X509_NAME_P, rffi.CCHARP, rffi.INT], rffi.CCHARP)
+ssl_external('X509_free', [X509_P], lltype.Void)
+ssl_external('SSL_free', [SSL_P], lltype.Void)
+ssl_external('SSL_CTX_free', [SSL_CTX_P], lltype.Void)
+ssl_external('SSL_write', [SSL_P, rffi.CCHARP, rffi.INT], rffi.INT)
+ssl_external('SSL_pending', [SSL_P], rffi.INT)
+ssl_external('SSL_read', [SSL_P, rffi.CCHARP, rffi.INT], rffi.INT)
def _init_ssl():
- libssl.SSL_load_error_strings()
- libssl.SSL_library_init()
+ libssl_SSL_load_error_strings()
+ libssl_SSL_library_init()
if HAVE_OPENSSL_RAND:
# helper routines for seeding the SSL PRNG
@@ -185,9 +158,11 @@
Mix string into the OpenSSL PRNG state. entropy (a float) is a lower
bound on the entropy contained in string."""
- buf = c_char_p(string)
-
- libssl.RAND_add(buf, len(string), entropy)
+ buf = rffi.str2charp(string)
+ try:
+ libssl_RAND_add(buf, len(string), entropy)
+ finally:
+ rffi.free_charp(buf)
RAND_add.unwrap_spec = [ObjSpace, str, float]
def RAND_status(space):
@@ -197,7 +172,7 @@
It is necessary to seed the PRNG with RAND_add() on some platforms before
using the ssl() function."""
- res = libssl.RAND_status()
+ res = libssl_RAND_status()
return space.wrap(res)
RAND_status.unwrap_spec = [ObjSpace]
@@ -208,8 +183,11 @@
of bytes read. Raises socket.sslerror if connection to EGD fails or
if it does provide enough data to seed PRNG."""
- socket_path = c_char_p(path)
- bytes = libssl.RAND_egd(socket_path)
+ socket_path = rffi.str2charp(path)
+ try:
+ bytes = libssl_RAND_egd(socket_path)
+ finally:
+ rffi.free_charp(socket_path)
if bytes == -1:
msg = "EGD connection failed or EGD did not return"
msg += " enough data to seed the PRNG"
@@ -221,34 +199,33 @@
def __init__(self, space):
self.space = space
self.w_socket = None
- self.ctx = POINTER(SSL_CTX)()
- self.ssl = POINTER(SSL)()
- self.server_cert = POINTER(X509)()
- self._server = arr_x509()
- self._issuer = arr_x509()
+ self.ctx = lltype.malloc(SSL_CTX_P.TO, 1, flavor='raw')
+ self.ssl = lltype.malloc(SSL_P.TO, 1, flavor='raw')
+ self.server_cert = lltype.malloc(X509_P.TO, 1, flavor='raw')
+ self._server = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw')
+ self._issuer = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw')
def server(self):
- return self.space.wrap(self._server.value)
+ return self.space.wrap(rffi.charp2str(self._server))
server.unwrap_spec = ['self']
def issuer(self):
- return self.space.wrap(self._issuer.value)
+ return self.space.wrap(rffi.charp2str(self._issuer))
issuer.unwrap_spec = ['self']
def __del__(self):
if self.server_cert:
- libssl.X509_free(self.server_cert)
+ libssl_X509_free(self.server_cert)
if self.ssl:
- libssl.SSL_free(self.ssl)
+ libssl_SSL_free(self.ssl)
if self.ctx:
- libssl.SSL_CTX_free(self.ctx)
+ libssl_SSL_CTX_free(self.ctx)
def write(self, data):
"""write(s) -> len
Writes the string s into the SSL object. Returns the number
of bytes written."""
-
sockstate = check_socket_and_wait_for_timeout(self.space,
self.w_socket, True)
if sockstate == SOCKET_HAS_TIMED_OUT:
@@ -265,8 +242,8 @@
while True:
err = 0
- num_bytes = libssl.SSL_write(self.ssl, data, len(data))
- err = libssl.SSL_get_error(self.ssl, num_bytes)
+ num_bytes = libssl_SSL_write(self.ssl, data, len(data))
+ err = libssl_SSL_get_error(self.ssl, num_bytes)
if err == SSL_ERROR_WANT_READ:
sockstate = check_socket_and_wait_for_timeout(self.space,
@@ -279,7 +256,7 @@
if sockstate == SOCKET_HAS_TIMED_OUT:
raise OperationError(self.space.w_Exception,
- self.space.wrap("The connect operation timed out"))
+ self.space.wrap("The write operation timed out"))
elif sockstate == SOCKET_HAS_BEEN_CLOSED:
raise OperationError(self.space.w_Exception,
self.space.wrap("Underlying socket has been closed."))
@@ -304,7 +281,7 @@
Read up to len bytes from the SSL socket."""
- count = libssl.SSL_pending(self.ssl)
+ count = libssl_SSL_pending(self.ssl)
if not count:
sockstate = check_socket_and_wait_for_timeout(self.space,
self.w_socket, False)
@@ -314,13 +291,13 @@
elif sockstate == SOCKET_TOO_LARGE_FOR_SELECT:
raise OperationError(self.space.w_Exception,
self.space.wrap("Underlying socket too large for select()."))
-
- buf = create_string_buffer(num_bytes)
+
+ raw_buf, gc_buf = rffi.alloc_buffer(num_bytes)
while True:
err = 0
- count = libssl.SSL_read(self.ssl, buf, num_bytes)
- err = libssl.SSL_get_error(self.ssl, count)
+ count = libssl_SSL_read(self.ssl, raw_buf, num_bytes)
+ err = libssl_SSL_get_error(self.ssl, count)
if err == SSL_ERROR_WANT_READ:
sockstate = check_socket_and_wait_for_timeout(self.space,
@@ -346,20 +323,10 @@
errstr, errval = _ssl_seterror(self.space, self, count)
raise OperationError(self.space.w_Exception,
self.space.wrap("%s: %d" % (errstr, errval)))
-
- if count != num_bytes:
- # resize
- data = buf.raw
- assert count >= 0
- try:
- new_data = data[0:count]
- except:
- raise OperationError(self.space.w_MemoryException,
- self.space.wrap("error in resizing of the buffer."))
- buf = create_string_buffer(count)
- buf.raw = new_data
-
- return self.space.wrap(buf.value)
+
+ result = rffi.str_from_buffer(raw_buf, gc_buf, num_bytes, count)
+ rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+ return self.space.wrap(result)
read.unwrap_spec = ['self', int]
@@ -397,41 +364,41 @@
raise OperationError(space.w_Exception,
space.wrap("Both the key & certificate files must be specified"))
- ss.ctx = libssl.SSL_CTX_new(libssl.SSLv23_method()) # set up context
+ ss.ctx = libssl_SSL_CTX_new(libssl_SSLv23_method()) # set up context
if not ss.ctx:
raise OperationError(space.w_Exception, space.wrap("SSL_CTX_new error"))
if key_file:
- ret = libssl.SSL_CTX_use_PrivateKey_file(ss.ctx, key_file,
+ ret = libssl_SSL_CTX_use_PrivateKey_file(ss.ctx, key_file,
SSL_FILETYPE_PEM)
if ret < 1:
raise OperationError(space.w_Exception,
space.wrap("SSL_CTX_use_PrivateKey_file error"))
- ret = libssl.SSL_CTX_use_certificate_chain_file(ss.ctx, cert_file)
- libssl.SSL_CTX_ctrl(ss.ctx, SSL_CTRL_OPTIONS, SSL_OP_ALL, c_void_p())
+ ret = libssl_SSL_CTX_use_certificate_chain_file(ss.ctx, cert_file)
+ libssl_SSL_CTX_ctrl(ss.ctx, SSL_CTRL_OPTIONS, SSL_OP_ALL, None)
if ret < 1:
raise OperationError(space.w_Exception,
space.wrap("SSL_CTX_use_certificate_chain_file error"))
- libssl.SSL_CTX_set_verify(ss.ctx, SSL_VERIFY_NONE, c_void_p()) # set verify level
- ss.ssl = libssl.SSL_new(ss.ctx) # new ssl struct
- libssl.SSL_set_fd(ss.ssl, sock_fd) # set the socket for SSL
+ libssl_SSL_CTX_set_verify(ss.ctx, SSL_VERIFY_NONE, None) # set verify level
+ ss.ssl = libssl_SSL_new(ss.ctx) # new ssl struct
+ libssl_SSL_set_fd(ss.ssl, sock_fd) # set the socket for SSL
# If the socket is in non-blocking mode or timeout mode, set the BIO
# to non-blocking mode (blocking is the default)
if has_timeout:
# Set both the read and write BIO's to non-blocking mode
- libssl.BIO_ctrl(libssl.SSL_get_rbio(ss.ssl), BIO_C_SET_NBIO, 1, c_void_p())
- libssl.BIO_ctrl(libssl.SSL_get_wbio(ss.ssl), BIO_C_SET_NBIO, 1, c_void_p())
- libssl.SSL_set_connect_state(ss.ssl)
+ libssl_BIO_ctrl(libssl_SSL_get_rbio(ss.ssl), BIO_C_SET_NBIO, 1, None)
+ libssl_BIO_ctrl(libssl_SSL_get_wbio(ss.ssl), BIO_C_SET_NBIO, 1, None)
+ libssl_SSL_set_connect_state(ss.ssl)
# Actually negotiate SSL connection
# XXX If SSL_connect() returns 0, it's also a failure.
sockstate = 0
while True:
- ret = libssl.SSL_connect(ss.ssl)
- err = libssl.SSL_get_error(ss.ssl, ret)
+ ret = libssl_SSL_connect(ss.ssl)
+ err = libssl_SSL_get_error(ss.ssl, ret)
if err == SSL_ERROR_WANT_READ:
sockstate = check_socket_and_wait_for_timeout(space, w_sock, False)
@@ -462,11 +429,11 @@
raise OperationError(space.w_Exception,
space.wrap("%s: %d" % (errstr, errval)))
- ss.server_cert = libssl.SSL_get_peer_certificate(ss.ssl)
+ ss.server_cert = libssl_SSL_get_peer_certificate(ss.ssl)
if ss.server_cert:
- libssl.X509_NAME_oneline(libssl.X509_get_subject_name(ss.server_cert),
+ libssl_X509_NAME_oneline(libssl_X509_get_subject_name(ss.server_cert),
ss._server, X509_NAME_MAXLEN)
- libssl.X509_NAME_oneline(libssl.X509_get_issuer_name(ss.server_cert),
+ libssl_X509_NAME_oneline(libssl_X509_get_issuer_name(ss.server_cert),
ss._issuer, X509_NAME_MAXLEN)
ss.w_socket = w_sock
@@ -481,62 +448,50 @@
w_timeout = space.call_method(w_sock, "gettimeout")
if space.is_w(w_timeout, space.w_None):
return SOCKET_IS_BLOCKING
- elif space.int_w(w_timeout) == 0.0:
+ elif space.float_w(w_timeout) == 0.0:
return SOCKET_IS_NONBLOCKING
- sock_timeout = space.int_w(w_timeout)
+ sock_timeout = space.float_w(w_timeout)
# guard against closed socket
try:
space.call_method(w_sock, "fileno")
except:
return SOCKET_HAS_BEEN_CLOSED
-
+
sock_fd = space.int_w(space.call_method(w_sock, "fileno"))
+ # see if the socket is ready
+
# Prefer poll, if available, since you can poll() any fd
# which can't be done with select().
- if have_poll:
- _pollfd = pollfd()
- _pollfd.fd = sock_fd
+ if HAVE_RPOLL:
if writing:
- _pollfd.events = POLLOUT
+ fddict = {sock_fd: rpoll.POLLOUT}
else:
- _pollfd.events = POLLIN
+ fddict = {sock_fd: rpoll.POLLIN}
+
# socket's timeout is in seconds, poll's timeout in ms
timeout = int(sock_timeout * 1000 + 0.5)
- rc = libc.poll(byref(_pollfd), 1, timeout)
- if rc == 0:
- return SOCKET_HAS_TIMED_OUT
- else:
- return SOCKET_OPERATION_OK
-
- if sock_fd >= FD_SETSIZE:
- return SOCKET_TOO_LARGE_FOR_SELECT
+ ready = rpoll.poll(fddict, timeout)
+ else:
+ if MAX_FD_SIZE is not None and sock_fd >= MAX_FD_SIZE:
+ return SOCKET_TOO_LARGE_FOR_SELECT
- # construct the arguments for select
- sec = int(sock_timeout)
- usec = int((sock_timeout - sec) * 1e6)
- timeout = sec + usec * 0.000001
- # see if the socket is ready
- if writing:
- ret = select.select([], [sock_fd], [], timeout)
- r, w, e = ret
- if not w:
- return SOCKET_HAS_TIMED_OUT
+ if writing:
+ r, w, e = rpoll.select([], [sock_fd], [], sock_timeout)
+ ready = w
else:
- return SOCKET_OPERATION_OK
+ r, w, e = rpoll.select([sock_fd], [], [], sock_timeout)
+ ready = r
+ if ready:
+ return SOCKET_OPERATION_OK
else:
- ret = select.select([sock_fd], [], [], timeout)
- r, w, e = ret
- if not r:
- return SOCKET_HAS_TIMED_OUT
- else:
- return SOCKET_OPERATION_OK
+ return SOCKET_HAS_TIMED_OUT
def _ssl_seterror(space, ss, ret):
assert ret <= 0
- err = libssl.SSL_get_error(ss.ssl, ret)
+ err = libssl_SSL_get_error(ss.ssl, ret)
errstr = ""
errval = 0
@@ -556,7 +511,7 @@
errstr = "The operation did not complete (connect)"
errval = PY_SSL_ERROR_WANT_CONNECT
elif err == SSL_ERROR_SYSCALL:
- e = libssl.ERR_get_error()
+ e = libssl_ERR_get_error()
if e == 0:
if ret == 0 or space.is_w(ss.w_socket, space.w_None):
errstr = "EOF occurred in violation of protocol"
@@ -568,19 +523,19 @@
errstr = "Some I/O error occurred"
errval = PY_SSL_ERROR_SYSCALL
else:
- errstr = libssl.ERR_error_string(e, None)
+ errstr = rffi.charp2str(libssl_ERR_error_string(e, None))
errval = PY_SSL_ERROR_SYSCALL
elif err == SSL_ERROR_SSL:
- e = libssl.ERR_get_error()
+ e = libssl_ERR_get_error()
errval = PY_SSL_ERROR_SSL
if e != 0:
- errstr = libssl.ERR_error_string(e, None)
+ errstr = rffi.charp2str(libssl_ERR_error_string(e, None))
else:
errstr = "A failure in the SSL library occurred"
else:
errstr = "Invalid error code"
errval = PY_SSL_ERROR_INVALID_ERROR_CODE
-
+
return errstr, errval
Modified: pypy/trunk/pypy/module/_ssl/test/test_ssl.py
==============================================================================
--- pypy/trunk/pypy/module/_ssl/test/test_ssl.py (original)
+++ pypy/trunk/pypy/module/_ssl/test/test_ssl.py Thu Apr 9 16:51:25 2009
@@ -2,15 +2,9 @@
import os
import py
-py.test.skip("Module not working yet")
-
-if os.name == "nt":
- from py.test import skip
- skip("Windows is not supported")
-
class AppTestSSL:
def setup_class(cls):
- space = gettestobjspace(usemodules=('_ssl',))
+ space = gettestobjspace(usemodules=('_ssl', '_socket'))
cls.space = space
def test_init_module(self):
@@ -48,94 +42,95 @@
_ssl.RAND_status()
def test_RAND_egd(self):
- import _ssl
+ import _ssl, os, stat
if not hasattr(_ssl, "RAND_egd"):
skip("RAND_egd is not available on this machine")
raises(TypeError, _ssl.RAND_egd, 4)
-
+
# you need to install http://egd.sourceforge.net/ to test this
# execute "egd.pl entropy" in the current dir
+ if (not os.access("entropy", 0) or
+ not stat.S_ISSOCK(os.stat("entropy").st_mode)):
+ skip("This test needs a running entropy gathering daemon")
_ssl.RAND_egd("entropy")
-
- def test_connect(self):
- import socket
-
+
+class AppTestConnectedSSL:
+ def setup_class(cls):
+ space = gettestobjspace(usemodules=('_ssl', '_socket'))
+ cls.space = space
+
+ def setup_method(self, method):
# https://connect.sigen-ca.si/index-en.html
ADDR = "connect.sigen-ca.si", 443
- s = socket.socket()
- try:
- s.connect(ADDR)
- except:
- skip("no network available or issues with connection")
- ss = socket.ssl(s)
- s.close()
-
+ ADDR = "intranet", 443
+
+ self.w_s = self.space.appexec([self.space.wrap(ADDR)], """(ADDR):
+ import socket
+ s = socket.socket()
+ try:
+ s.connect(ADDR)
+ except:
+ skip("no network available or issues with connection")
+ return s
+ """)
+
+ def test_connect(self):
+ import socket
+ ss = socket.ssl(self.s)
+ self.s.close()
+
def test_server(self):
import socket
- ADDR = "connect.sigen-ca.si", 443
- s = socket.socket()
- try:
- s.connect(ADDR)
- except:
- skip("no network available or issues with connection")
- ss = socket.ssl(s)
+ ss = socket.ssl(self.s)
assert isinstance(ss.server(), str)
- s.close()
-
+ self.s.close()
+
def test_issuer(self):
import socket
- ADDR = "connect.sigen-ca.si", 443
- s = socket.socket()
- try:
- s.connect(ADDR)
- except:
- skip("no network available or issues with connection")
- ss = socket.ssl(s)
+ ss = socket.ssl(self.s)
assert isinstance(ss.issuer(), str)
- s.close()
-
+ self.s.close()
+
def test_write(self):
import socket
- ADDR = "connect.sigen-ca.si", 443
- s = socket.socket()
- try:
- s.connect(ADDR)
- except:
- skip("no network available or issues with connection")
- ss = socket.ssl(s)
+ ss = socket.ssl(self.s)
raises(TypeError, ss.write, 123)
num_bytes = ss.write("hello\n")
assert isinstance(num_bytes, int)
assert num_bytes >= 0
- s.close()
-
+ self.s.close()
+
def test_read(self):
import socket
- ADDR = "connect.sigen-ca.si", 443
- s = socket.socket()
- try:
- s.connect(ADDR)
- except:
- skip("no network available or issues with connection")
- ss = socket.ssl(s)
+ ss = socket.ssl(self.s)
raises(TypeError, ss.read, "foo")
ss.write("hello\n")
data = ss.read()
assert isinstance(data, str)
- s.close()
+ self.s.close()
def test_read_upto(self):
import socket
- ADDR = "connect.sigen-ca.si", 443
- s = socket.socket()
- try:
- s.connect(ADDR)
- except:
- skip("no network available or issues with connection")
- ss = socket.ssl(s)
+ ss = socket.ssl(self.s)
raises(TypeError, ss.read, "foo")
ss.write("hello\n")
data = ss.read(10)
assert isinstance(data, str)
assert len(data) == 10
- s.close()
+ self.s.close()
+
+class AppTestConnectedSSL_Timeout(AppTestConnectedSSL):
+ # Same tests, with a socket timeout
+ # to exercise the poll() calls
+
+ def setup_class(cls):
+ space = gettestobjspace(usemodules=('_ssl', '_socket'))
+ cls.space = space
+ cls.space.appexec([], """():
+ import socket; socket.setdefaulttimeout(1)
+ """)
+
+ def teardown_class(cls):
+ cls.space.appexec([], """():
+ import socket; socket.setdefaulttimeout(1)
+ """)
More information about the Pypy-commit
mailing list