Merge branch 'master' into ecdhe-support

Conflicts:
	.gitignore
	OpenSSL/test/test_ssl.py
diff --git a/.gitignore b/.gitignore
index 539da74..276d4e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
 *.py[co]
+build
+dist
+*.egg-info
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py
index 62ce6c1..03aa47b 100644
--- a/OpenSSL/SSL.py
+++ b/OpenSSL/SSL.py
@@ -1,9 +1,12 @@
-
+from sys import platform
 from functools import wraps, partial
 from itertools import count
 from weakref import WeakValueDictionary
 from errno import errorcode
 
+from six import text_type as _text_type
+from six import integer_types as integer_types
+
 from OpenSSL._util import (
     ffi as _ffi,
     lib as _lib,
@@ -204,16 +207,15 @@
 
 def _asFileDescriptor(obj):
     fd = None
-
-    if not isinstance(obj, int):
+    if not isinstance(obj, integer_types):
         meth = getattr(obj, "fileno", None)
         if meth is not None:
             obj = meth()
 
-    if isinstance(obj, int):
+    if isinstance(obj, integer_types):
         fd = obj
 
-    if not isinstance(fd, int):
+    if not isinstance(fd, integer_types):
         raise TypeError("argument must be an int, or have a fileno() method.")
     elif fd < 0:
         raise ValueError(
@@ -261,7 +263,7 @@
         :param method: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or
             TLSv1_METHOD.
         """
-        if not isinstance(method, int):
+        if not isinstance(method, integer_types):
             raise TypeError("method must be an integer")
 
         try:
@@ -367,8 +369,12 @@
         :param certfile: The name of the certificate chain file
         :return: None
         """
+        if isinstance(certfile, _text_type):
+            # Perhaps sys.getfilesystemencoding() could be better?
+            certfile = certfile.encode("utf-8")
+
         if not isinstance(certfile, bytes):
-            raise TypeError("certfile must be a byte string")
+            raise TypeError("certfile must be bytes or unicode")
 
         result = _lib.SSL_CTX_use_certificate_chain_file(self._context, certfile)
         if not result:
@@ -383,9 +389,12 @@
         :param filetype: (optional) The encoding of the file, default is PEM
         :return: None
         """
+        if isinstance(certfile, _text_type):
+            # Perhaps sys.getfilesystemencoding() could be better?
+            certfile = certfile.encode("utf-8")
         if not isinstance(certfile, bytes):
-            raise TypeError("certfile must be a byte string")
-        if not isinstance(filetype, int):
+            raise TypeError("certfile must be bytes or unicode")
+        if not isinstance(filetype, integer_types):
             raise TypeError("filetype must be an integer")
 
         use_result = _lib.SSL_CTX_use_certificate_file(self._context, certfile, filetype)
@@ -442,12 +451,16 @@
         :param filetype: (optional) The encoding of the file, default is PEM
         :return: None
         """
+        if isinstance(keyfile, _text_type):
+            # Perhaps sys.getfilesystemencoding() could be better?
+            keyfile = keyfile.encode("utf-8")
+
         if not isinstance(keyfile, bytes):
             raise TypeError("keyfile must be a byte string")
 
         if filetype is _unspecified:
             filetype = FILETYPE_PEM
-        elif not isinstance(filetype, int):
+        elif not isinstance(filetype, integer_types):
             raise TypeError("filetype must be an integer")
 
         use_result = _lib.SSL_CTX_use_PrivateKey_file(
@@ -506,7 +519,7 @@
             bitwise or)
         :returns: The previously set caching mode.
         """
-        if not isinstance(mode, int):
+        if not isinstance(mode, integer_types):
             raise TypeError("mode must be an integer")
 
         return _lib.SSL_CTX_set_session_cache_mode(self._context, mode)
@@ -530,7 +543,7 @@
 
         See SSL_CTX_set_verify(3SSL) for further details.
         """
-        if not isinstance(mode, int):
+        if not isinstance(mode, integer_types):
             raise TypeError("mode must be an integer")
 
         if not callable(callback):
@@ -548,7 +561,7 @@
         :param depth: An integer specifying the verify depth
         :return: None
         """
-        if not isinstance(depth, int):
+        if not isinstance(depth, integer_types):
             raise TypeError("depth must be an integer")
 
         _lib.SSL_CTX_set_verify_depth(self._context, depth)
@@ -619,8 +632,11 @@
         :param cipher_list: A cipher list, see ciphers(1)
         :return: None
         """
+        if isinstance(cipher_list, _text_type):
+            cipher_list = cipher_list.encode("ascii")
+
         if not isinstance(cipher_list, bytes):
-            raise TypeError("cipher_list must be a byte string")
+            raise TypeError("cipher_list must be bytes or unicode")
 
         result = _lib.SSL_CTX_set_cipher_list(self._context, cipher_list)
         if not result:
@@ -690,7 +706,7 @@
         :param timeout: The timeout in seconds
         :return: The previous session timeout
         """
-        if not isinstance(timeout, int):
+        if not isinstance(timeout, integer_types):
             raise TypeError("timeout must be an integer")
 
         return _lib.SSL_CTX_set_timeout(self._context, timeout)
@@ -714,7 +730,7 @@
         """
         @wraps(callback)
         def wrapper(ssl, where, return_code):
-            callback(self, where, return_code)
+            callback(Connection._reverse_mapping[ssl], where, return_code)
         self._info_callback = _ffi.callback(
             "void (*)(const SSL *, int, int)", wrapper)
         _lib.SSL_CTX_set_info_callback(self._context, self._info_callback)
@@ -762,7 +778,7 @@
         :param options: The options to add.
         :return: The new option bitmask.
         """
-        if not isinstance(options, int):
+        if not isinstance(options, integer_types):
             raise TypeError("options must be an integer")
 
         return _lib.SSL_CTX_set_options(self._context, options)
@@ -775,7 +791,7 @@
         :param mode: The mode to add.
         :return: The new mode bitmask.
         """
-        if not isinstance(mode, int):
+        if not isinstance(mode, integer_types):
             raise TypeError("mode must be an integer")
 
         return _lib.SSL_CTX_set_mode(self._context, mode)
@@ -870,8 +886,11 @@
         elif error == _lib.SSL_ERROR_SYSCALL:
             if _lib.ERR_peek_error() == 0:
                 if result < 0:
-                    raise SysCallError(
-                        _ffi.errno, errorcode[_ffi.errno])
+                    if platform == "win32":
+                        errno = _ffi.getwinerror()[0]
+                    else:
+                        errno = _ffi.errno
+                    raise SysCallError(errno, errorcode[errno])
                 else:
                     raise SysCallError(-1, "Unexpected EOF")
             else:
@@ -957,8 +976,6 @@
             buf = buf.tobytes()
         if not isinstance(buf, bytes):
             raise TypeError("data must be a byte string")
-        if not isinstance(flags, int):
-            raise TypeError("flags must be an integer")
 
         result = _lib.SSL_write(self._ssl, buf, len(buf))
         self._raise_ssl_error(self._ssl, result)
@@ -981,8 +998,6 @@
             buf = buf.tobytes()
         if not isinstance(buf, bytes):
             raise TypeError("buf must be a byte string")
-        if not isinstance(flags, int):
-            raise TypeError("flags must be an integer")
 
         left_to_send = len(buf)
         total_sent = 0
@@ -1043,7 +1058,7 @@
         if self._from_ssl is None:
             raise TypeError("Connection sock was not None")
 
-        if not isinstance(bufsiz, int):
+        if not isinstance(bufsiz, integer_types):
             raise TypeError("bufsiz must be an integer")
 
         buf = _ffi.new("char[]", bufsiz)
@@ -1266,7 +1281,7 @@
         :param state - bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
         :return: None
         """
-        if not isinstance(state, int):
+        if not isinstance(state, integer_types):
             raise TypeError("state must be an integer")
 
         _lib.SSL_set_shutdown(self._ssl, state)
@@ -1433,3 +1448,7 @@
             _raise_current_error()
 
 ConnectionType = Connection
+
+# This is similar to the initialization calls at the end of OpenSSL/crypto.py
+# but is exercised mostly by the Context initializer.
+_lib.SSL_library_init()
diff --git a/OpenSSL/__init__.py b/OpenSSL/__init__.py
index 396a97f..db96e1f 100644
--- a/OpenSSL/__init__.py
+++ b/OpenSSL/__init__.py
@@ -10,6 +10,3 @@
 
 __all__ = [
     'rand', 'crypto', 'SSL', 'tsafe', '__version__']
-
-
-# ERR_load_crypto_strings, SSL_library_init, ERR_load_SSL_strings
diff --git a/OpenSSL/_util.py b/OpenSSL/_util.py
index 7c606b9..baeecc6 100644
--- a/OpenSSL/_util.py
+++ b/OpenSSL/_util.py
@@ -6,15 +6,18 @@
 lib = binding.lib
 
 def exception_from_error_queue(exceptionType):
+    def text(charp):
+        return native(ffi.string(charp))
+
     errors = []
     while True:
         error = lib.ERR_get_error()
         if error == 0:
             break
         errors.append((
-                ffi.string(lib.ERR_lib_error_string(error)),
-                ffi.string(lib.ERR_func_error_string(error)),
-                ffi.string(lib.ERR_reason_error_string(error))))
+                text(lib.ERR_lib_error_string(error)),
+                text(lib.ERR_func_error_string(error)),
+                text(lib.ERR_reason_error_string(error))))
 
     raise exceptionType(errors)
 
diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py
index 0a9e8a2..d0026bd 100644
--- a/OpenSSL/crypto.py
+++ b/OpenSSL/crypto.py
@@ -1202,6 +1202,9 @@
 
     :return: The X509 object
     """
+    if isinstance(buffer, _text_type):
+        buffer = buffer.encode("ascii")
+
     bio = _new_mem_buf(buffer)
 
     if type == FILETYPE_PEM:
@@ -1988,6 +1991,9 @@
 
     :return: The PKey object
     """
+    if isinstance(buffer, _text_type):
+        buffer = buffer.encode("ascii")
+
     bio = _new_mem_buf(buffer)
 
     helper = _PassphraseHelper(type, passphrase)
@@ -2044,6 +2050,9 @@
     :param buffer: The buffer the certificate request is stored in
     :return: The X509Req object
     """
+    if isinstance(buffer, _text_type):
+        buffer = buffer.encode("ascii")
+
     bio = _new_mem_buf(buffer)
 
     if type == FILETYPE_PEM:
@@ -2137,6 +2146,9 @@
 
     :return: The PKey object
     """
+    if isinstance(buffer, _text_type):
+        buffer = buffer.encode("ascii")
+
     bio = _new_mem_buf(buffer)
 
     if type == FILETYPE_PEM:
@@ -2163,6 +2175,9 @@
     :param buffer: The buffer with the pkcs7 data.
     :return: The PKCS7 object
     """
+    if isinstance(buffer, _text_type):
+        buffer = buffer.encode("ascii")
+
     bio = _new_mem_buf(buffer)
 
     if type == FILETYPE_PEM:
@@ -2191,6 +2206,9 @@
     :param passphrase: (Optional) The password to decrypt the PKCS12 lump
     :returns: The PKCS12 object
     """
+    if isinstance(buffer, _text_type):
+        buffer = buffer.encode("ascii")
+
     bio = _new_mem_buf(buffer)
 
     p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
@@ -2290,3 +2308,7 @@
 # OpenSSL library (and is linked against the same one that cryptography is
 # using)).
 _lib.OpenSSL_add_all_algorithms()
+
+# This is similar but exercised mainly by exception_from_error_queue.  It calls
+# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
+_lib.SSL_load_error_strings()
diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py
index 51da99b..4e42f70 100644
--- a/OpenSSL/test/test_crypto.py
+++ b/OpenSSL/test/test_crypto.py
@@ -1941,7 +1941,7 @@
         """
         passwd = 'whatever'
         e = self.assertRaises(Error, load_pkcs12, b'fruit loops', passwd)
-        self.assertEqual( e.args[0][0][0], b'asn1 encoding routines')
+        self.assertEqual( e.args[0][0][0], 'asn1 encoding routines')
         self.assertEqual( len(e.args[0][0]), 3)
 
 
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index 5e08e9b..70c1f3e 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -6,7 +6,7 @@
 """
 
 from gc import collect, get_referrers
-from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE
+from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
 from sys import platform, version_info
 from socket import SHUT_RDWR, error, socket
 from os import makedirs
@@ -14,6 +14,8 @@
 from unittest import main
 from weakref import ref
 
+from six import PY3, u
+
 from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
 from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
 from OpenSSL.crypto import dump_privatekey, load_privatekey
@@ -336,6 +338,16 @@
         self.assertRaises(ValueError, Context, 10)
 
 
+    if not PY3:
+        def test_method_long(self):
+            """
+            On Python 2 :py:class:`Context` accepts values of type
+            :py:obj:`long` as well as :py:obj:`int`.
+            """
+            Context(long(TLSv1_METHOD))
+
+
+
     def test_type(self):
         """
         :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
@@ -365,6 +377,25 @@
         self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
 
 
+    if not PY3:
+        def test_use_privatekey_file_long(self):
+            """
+            On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
+            filetype of type :py:obj:`long` as well as :py:obj:`int`.
+            """
+            pemfile = self.mktemp()
+
+            key = PKey()
+            key.generate_key(TYPE_RSA, 128)
+
+            with open(pemfile, "wt") as pem:
+                pem.write(
+                    dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
+
+            ctx = Context(TLSv1_METHOD)
+            ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
+
+
     def test_use_certificate_wrong_args(self):
         """
         :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
@@ -444,6 +475,20 @@
         ctx.use_certificate_file(pem_filename)
 
 
+    if not PY3:
+        def test_use_certificate_file_long(self):
+            """
+            On Python 2 :py:obj:`Context.use_certificate_file` accepts a
+            filetype of type :py:obj:`long` as well as :py:obj:`int`.
+            """
+            pem_filename = self.mktemp()
+            with open(pem_filename, "wb") as pem_file:
+                pem_file.write(cleartextCertificatePEM)
+
+            ctx = Context(TLSv1_METHOD)
+            ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
+
+
     def test_set_app_data_wrong_args(self):
         """
         :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
@@ -485,6 +530,26 @@
         self.assertRaises(TypeError, context.set_options, 1, None)
 
 
+    def test_set_options(self):
+        """
+        :py:obj:`Context.set_options` returns the new options value.
+        """
+        context = Context(TLSv1_METHOD)
+        options = context.set_options(OP_NO_SSLv2)
+        self.assertTrue(OP_NO_SSLv2 & options)
+
+
+    if not PY3:
+        def test_set_options_long(self):
+            """
+            On Python 2 :py:obj:`Context.set_options` accepts values of type
+            :py:obj:`long` as well as :py:obj:`int`.
+            """
+            context = Context(TLSv1_METHOD)
+            options = context.set_options(long(OP_NO_SSLv2))
+            self.assertTrue(OP_NO_SSLv2 & options)
+
+
     def test_set_mode_wrong_args(self):
         """
         :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
@@ -505,6 +570,16 @@
             context = Context(TLSv1_METHOD)
             self.assertTrue(
                 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
+
+        if not PY3:
+            def test_set_mode_long(self):
+                """
+                On Python 2 :py:obj:`Context.set_mode` accepts values of type
+                :py:obj:`long` as well as :py:obj:`int`.
+                """
+                context = Context(TLSv1_METHOD)
+                mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
+                self.assertTrue(MODE_RELEASE_BUFFERS & mode)
     else:
         "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
 
@@ -539,6 +614,17 @@
         self.assertEquals(context.get_timeout(), 1234)
 
 
+    if not PY3:
+        def test_timeout_long(self):
+            """
+            On Python 2 :py:obj:`Context.set_timeout` accepts values of type
+            `long` as well as int.
+            """
+            context = Context(TLSv1_METHOD)
+            context.set_timeout(long(1234))
+            self.assertEquals(context.get_timeout(), 1234)
+
+
     def test_set_verify_depth_wrong_args(self):
         """
         :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
@@ -569,6 +655,17 @@
         self.assertEquals(context.get_verify_depth(), 11)
 
 
+    if not PY3:
+        def test_verify_depth_long(self):
+            """
+            On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
+            type `long` as well as int.
+            """
+            context = Context(TLSv1_METHOD)
+            context.set_verify_depth(long(11))
+            self.assertEquals(context.get_verify_depth(), 11)
+
+
     def _write_encrypted_pem(self, passphrase):
         """
         Write a new private key out to a new file, encrypted using the given
@@ -699,15 +796,19 @@
         serverSSL = Connection(context, server)
         serverSSL.set_accept_state()
 
-        while not called:
-            for ssl in clientSSL, serverSSL:
-                try:
-                    ssl.do_handshake()
-                except WantReadError:
-                    pass
+        handshake(clientSSL, serverSSL)
 
-        # Kind of lame.  Just make sure it got called somehow.
-        self.assertTrue(called)
+        # The callback must always be called with a Connection instance as the
+        # first argument.  It would probably be better to split this into
+        # separate tests for client and server side info callbacks so we could
+        # assert it is called with the right Connection instance.  It would
+        # also be good to assert *something* about `where` and `ret`.
+        notConnections = [
+            conn for (conn, where, ret) in called
+            if not isinstance(conn, Connection)]
+        self.assertEqual(
+            [], notConnections,
+            "Some info callback arguments were not Connection instaces.")
 
 
     def _load_verify_locations_test(self, *args):
@@ -961,11 +1062,11 @@
 
         # Write out the chain file.
         chainFile = self.mktemp()
-        fObj = open(chainFile, 'w')
+        fObj = open(chainFile, 'wb')
         # Most specific to least general.
-        fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
-        fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
-        fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
+        fObj.write(dump_certificate(FILETYPE_PEM, scert))
+        fObj.write(dump_certificate(FILETYPE_PEM, icert))
+        fObj.write(dump_certificate(FILETYPE_PEM, cacert))
         fObj.close()
 
         serverContext = Context(TLSv1_METHOD)
@@ -1011,7 +1112,7 @@
         self.assertRaises(TypeError, context.get_verify_mode, None)
 
 
-    def test_get_verify_mode(self):
+    def test_set_verify_mode(self):
         """
         :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
         passed to :py:obj:`Context.set_verify`.
@@ -1024,6 +1125,20 @@
             context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
 
 
+    if not PY3:
+        def test_set_verify_mode_long(self):
+            """
+            On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
+            type :py:obj:`long` as well as :py:obj:`int`.
+            """
+            context = Context(TLSv1_METHOD)
+            self.assertEquals(context.get_verify_mode(), 0)
+            context.set_verify(
+                long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
+            self.assertEquals(
+                context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
+
+
     def test_load_tmp_dh_wrong_args(self):
         """
         :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
@@ -1069,10 +1184,11 @@
             # XXX What should I assert here? -alex
 
 
-    def test_set_cipher_list(self):
+    def test_set_cipher_list_bytes(self):
         """
-        :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which
-        connections created with the context object will be able to choose from.
+        :py:obj:`Context.set_cipher_list` accepts a :py:obj:`bytes` naming the
+        ciphers which connections created with the context object will be able
+        to choose from.
         """
         context = Context(TLSv1_METHOD)
         context.set_cipher_list(b"hello world:EXP-RC4-MD5")
@@ -1080,11 +1196,23 @@
         self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
 
 
+    def test_set_cipher_list_text(self):
+        """
+        :py:obj:`Context.set_cipher_list` accepts a :py:obj:`unicode` naming
+        the ciphers which connections created with the context object will be
+        able to choose from.
+        """
+        context = Context(TLSv1_METHOD)
+        context.set_cipher_list(u("hello world:EXP-RC4-MD5"))
+        conn = Connection(context, None)
+        self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
+
+
     def test_set_cipher_list_wrong_args(self):
         """
-        :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when passed
-        zero arguments or more than one argument or when passed a non-byte
-        string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
+        :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when
+        passed zero arguments or more than one argument or when passed a
+        non-string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
         passed an incorrect cipher list string.
         """
         context = Context(TLSv1_METHOD)
@@ -1092,13 +1220,13 @@
         self.assertRaises(TypeError, context.set_cipher_list, object())
         self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
 
-        self.assertRaises(Error, context.set_cipher_list, b"imaginary-cipher")
+        self.assertRaises(Error, context.set_cipher_list, "imaginary-cipher")
 
 
     def test_set_session_cache_mode_wrong_args(self):
         """
-        L{Context.set_session_cache_mode} raises L{TypeError} if called with
-        other than one integer argument.
+        :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
+        called with other than one integer argument.
         """
         context = Context(TLSv1_METHOD)
         self.assertRaises(TypeError, context.set_session_cache_mode)
@@ -1107,8 +1235,8 @@
 
     def test_get_session_cache_mode_wrong_args(self):
         """
-        L{Context.get_session_cache_mode} raises L{TypeError} if called with any
-        arguments.
+        :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
+        called with any arguments.
         """
         context = Context(TLSv1_METHOD)
         self.assertRaises(TypeError, context.get_session_cache_mode, 1)
@@ -1116,15 +1244,27 @@
 
     def test_session_cache_mode(self):
         """
-        L{Context.set_session_cache_mode} specifies how sessions are cached.
-        The setting can be retrieved via L{Context.get_session_cache_mode}.
+        :py:obj:`Context.set_session_cache_mode` specifies how sessions are
+        cached.  The setting can be retrieved via
+        :py:obj:`Context.get_session_cache_mode`.
         """
         context = Context(TLSv1_METHOD)
-        old = context.set_session_cache_mode(SESS_CACHE_OFF)
+        context.set_session_cache_mode(SESS_CACHE_OFF)
         off = context.set_session_cache_mode(SESS_CACHE_BOTH)
         self.assertEqual(SESS_CACHE_OFF, off)
         self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
 
+    if not PY3:
+        def test_session_cache_mode_long(self):
+            """
+            On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
+            of type :py:obj:`long` as well as :py:obj:`int`.
+            """
+            context = Context(TLSv1_METHOD)
+            context.set_session_cache_mode(long(SESS_CACHE_BOTH))
+            self.assertEqual(
+                SESS_CACHE_BOTH, context.get_session_cache_mode())
+
 
     def test_get_cert_store(self):
         """
@@ -1532,6 +1672,17 @@
         self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
 
 
+    if not PY3:
+        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_app_data_wrong_args(self):
         """
         :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
@@ -1827,13 +1978,14 @@
     """
     def test_wrong_args(self):
         """
-        When called with arguments other than a single string,
-        :py:obj:`Connection.send` raises :py:obj:`TypeError`.
+        When called with arguments other than string argument for its first
+        parameter or more than two arguments, :py:obj:`Connection.send` raises
+        :py:obj:`TypeError`.
         """
         connection = Connection(Context(TLSv1_METHOD), None)
         self.assertRaises(TypeError, connection.send)
         self.assertRaises(TypeError, connection.send, object())
-        self.assertRaises(TypeError, connection.send, "foo", "bar")
+        self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
 
 
     def test_short_bytes(self):
@@ -1870,13 +2022,15 @@
     """
     def test_wrong_args(self):
         """
-        When called with arguments other than a single string,
-        :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
+        When called with arguments other than a string argument for its first
+        parameter or with more than two arguments, :py:obj:`Connection.sendall`
+        raises :py:obj:`TypeError`.
         """
         connection = Connection(Context(TLSv1_METHOD), None)
         self.assertRaises(TypeError, connection.sendall)
         self.assertRaises(TypeError, connection.sendall, object())
-        self.assertRaises(TypeError, connection.sendall, "foo", "bar")
+        self.assertRaises(
+            TypeError, connection.sendall, "foo", object(), "bar")
 
 
     def test_short(self):
@@ -1932,7 +2086,10 @@
         server, client = self._loopback()
         server.sock_shutdown(2)
         exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
-        self.assertEqual(exc.args[0], EPIPE)
+        if platform == "win32":
+            self.assertEqual(exc.args[0], ESHUTDOWN)
+        else:
+            self.assertEqual(exc.args[0], EPIPE)
 
 
 
@@ -2057,66 +2214,68 @@
 
     def test_sess_cache_off(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
-        L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
+        :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
         """
         self.assertEqual(0x0, SESS_CACHE_OFF)
 
 
     def test_sess_cache_client(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
-        L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
+        :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
         """
         self.assertEqual(0x1, SESS_CACHE_CLIENT)
 
 
     def test_sess_cache_server(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
-        L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
+        :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
         """
         self.assertEqual(0x2, SESS_CACHE_SERVER)
 
 
     def test_sess_cache_both(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
-        L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
+        :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
         """
         self.assertEqual(0x3, SESS_CACHE_BOTH)
 
 
     def test_sess_cache_no_auto_clear(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
-        L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
+        value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
+        ``openssl/ssl.h``.
         """
         self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
 
 
     def test_sess_cache_no_internal_lookup(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
-        value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
-        I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
+        the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
+        ``openssl/ssl.h``.
         """
         self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
 
 
     def test_sess_cache_no_internal_store(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
-        value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
-        I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
+        the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
+        ``openssl/ssl.h``.
         """
         self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
 
 
     def test_sess_cache_no_internal(self):
         """
-        The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
-        L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
+        The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
+        value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
+        ``openssl/ssl.h``.
         """
         self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
 
@@ -2527,6 +2686,40 @@
         self.assertRaises(WantReadError, conn.bio_read, 1024)
 
 
+    def test_buffer_size(self):
+        """
+        :py:obj:`Connection.bio_read` accepts an integer giving the maximum
+        number of bytes to read and return.
+        """
+        ctx = Context(TLSv1_METHOD)
+        conn = Connection(ctx, None)
+        conn.set_connect_state()
+        try:
+            conn.do_handshake()
+        except WantReadError:
+            pass
+        data = conn.bio_read(2)
+        self.assertEqual(2, len(data))
+
+
+    if not PY3:
+        def test_buffer_size_long(self):
+            """
+            On Python 2 :py:obj:`Connection.bio_read` accepts values of type
+            :py:obj:`long` as well as :py:obj:`int`.
+            """
+            ctx = Context(TLSv1_METHOD)
+            conn = Connection(ctx, None)
+            conn.set_connect_state()
+            try:
+                conn.do_handshake()
+            except WantReadError:
+                pass
+            data = conn.bio_read(long(2))
+            self.assertEqual(2, len(data))
+
+
+
 
 class InfoConstantTests(TestCase):
     """
diff --git a/OpenSSL/test/util.py b/OpenSSL/test/util.py
index 011e7da..4e4d812 100644
--- a/OpenSSL/test/util.py
+++ b/OpenSSL/test/util.py
@@ -17,7 +17,11 @@
 from OpenSSL._util import exception_from_error_queue
 from OpenSSL.crypto import Error
 
-import memdbg
+try:
+    import memdbg
+except Exception:
+    class _memdbg(object): heap = None
+    memdbg = _memdbg()
 
 from OpenSSL._util import ffi, lib, byte_string as b
 
diff --git a/README b/README
index afe4ddc..1b2a093 100644
--- a/README
+++ b/README
@@ -3,3 +3,7 @@
 ------------------------------------------------------------------------------
 
 See the file INSTALL for installation instructions.
+
+See http://github.com/pyca/pyopenssl for development.
+
+See https://mail.python.org/mailman/listinfo/pyopenssl-users for the discussion mailing list.
diff --git a/doc/index.rst b/doc/index.rst
index a63df87..e4a5a23 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -14,7 +14,6 @@
    :maxdepth: 3
 
    introduction
-   install
    api
    internals
 
diff --git a/doc/install.rst b/doc/install.rst
deleted file mode 100644
index f525726..0000000
--- a/doc/install.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-.. _building:
-
-Building and Installing
-=======================
-
-These instructions can also be found in the file ``INSTALL``.
-
-I have tested this on Debian Linux systems (woody and sid), Solaris 2.6 and
-2.7. Others have successfully compiled it on Windows and NT.
-
-.. _building-unix:
-
-Building the Module on a Unix System
-------------------------------------
-
-pyOpenSSL uses distutils, so there really shouldn't be any problems. To build
-the library::
-
-    python setup.py build
-
-If your OpenSSL header files aren't in ``/usr/include``, you may need to supply
-the ``-I`` flag to let the setup script know where to look. The same goes for
-the libraries of course, use the ``-L`` flag. Note that ``build`` won't accept
-these flags, so you have to run first ``build_ext`` and then ``build``!
-Example::
-
-    python setup.py build_ext -I/usr/local/ssl/include -L/usr/local/ssl/lib
-    python setup.py build
-
-Now you should have a directory called ``OpenSSL`` that contains e.g.
-``SSL.so`` and ``__init__.py`` somewhere in the build dicrectory,
-so just::
-
-    python setup.py install
-
-If you, for some arcane reason, don't want the module to appear in the
-``site-packages`` directory, use the ``--prefix`` option.
-
-You can, of course, do::
-
-    python setup.py --help
-
-to find out more about how to use the script.
-
-.. _building-windows:
-
-Building the Module on a Windows System
----------------------------------------
-
-Big thanks to Itamar Shtull-Trauring and Oleg Orlov for their help with
-Windows build instructions.  Same as for Unix systems, we have to separate
-the ``build_ext`` and the ``build``.
-
-Building the library::
-
-    setup.py build_ext -I ...\openssl\inc32 -L ...\openssl\out32dll
-    setup.py build
-
-Where ``...\openssl`` is of course the location of your OpenSSL installation.
-
-Installation is the same as for Unix systems::
-
-    setup.py install
-
-And similarily, you can do::
-
-    setup.py --help
-
-to get more information.
diff --git a/doc/internals.rst b/doc/internals.rst
index 839c446..a2a4cdc 100644
--- a/doc/internals.rst
+++ b/doc/internals.rst
@@ -27,38 +27,10 @@
 Callbacks
 ---------
 
-There are a number of problems with callbacks. First of all, OpenSSL is written
-as a C library, it's not meant to have Python callbacks, so a way around that
-is needed. Another problem is thread support. A lot of the OpenSSL I/O
-functions can block if the socket is in blocking mode, and then you want other
-Python threads to be able to do other things. The real trouble is if you've
-released the global CPython interpreter lock to do a potentially blocking
-operation, and the operation calls a callback. Then we must take the GIL back,
-since calling Python APIs without holding it is not allowed.
-
-There are two solutions to the first problem, both of which are necessary. The
-first solution to use is if the C callback allows ''userdata'' to be passed to
-it (an arbitrary pointer normally). This is great! We can set our Python
-function object as the real userdata and emulate userdata for the Python
-function in another way. The other solution can be used if an object with an
-''app_data'' system always is passed to the callback. For example, the SSL
-object in OpenSSL has app_data functions and in e.g. the verification
-callbacks, you can retrieve the related SSL object. What we do is to set our
-wrapper :py:class:`.Connection` object as app_data for the SSL object, and we can
-easily find the Python callback.
-
-The other problem is solved using thread local variables.  Whenever the GIL is
-released before calling into an OpenSSL API, the PyThreadState pointer returned
-by :c:func:`PyEval_SaveState` is stored in a global thread local variable
-(using Python's own TLS API, :c:func:`PyThread_set_key_value`).  When it is
-necessary to re-acquire the GIL, either after the OpenSSL API returns or in a C
-callback invoked by that OpenSSL API, the value of the thread local variable is
-retrieved (:c:func:`PyThread_get_key_value`) and used to re-acquire the GIL.
-This allows Python threads to execute while OpenSSL APIs are running and allows
-use of any particular pyOpenSSL object from any Python thread, since there is
-no per-thread state associated with any of these objects and since OpenSSL is
-threadsafe (as long as properly initialized, as pyOpenSSL initializes it).
-
+Callbacks were more of a problem when pyOpenSSL was written in C.
+Having switched to being written in Python using cffi, callbacks are now straightforward.
+The problems that originally existed no longer do
+(if you are interested in the details you can find descriptions of those problems in the version control history for this document).
 
 .. _socket-methods:
 
diff --git a/runtests.py b/runtests.py
index 2ec425b..13f5c4c 100644
--- a/runtests.py
+++ b/runtests.py
@@ -2,7 +2,10 @@
 sys.modules['ssl'] = None
 sys.modules['_hashlib'] = None
 
-import memdbg
+try:
+   import memdbg
+except Exception as e:
+   pass
 
 from twisted.scripts.trial import run
 run()