Merge pull request #225 from glyph/right-error

Don't randomly fail with KeyError in shutdown().
diff --git a/ChangeLog b/ChangeLog
index 95c891f..903216c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2015-04-14  Glyph Lefkowitz  <glyph@twistedmatrix.com>
+
+	* OpenSSL/SSL.py, OpenSSL/test/test_ssl.py: Fix a regression
+	  present in 0.15, where when an error occurs and no errno() is set,
+	  a KeyError is raised.  This happens, for example, if
+	  Connection.shutdown() is called when the underlying transport has
+	  gone away.
+
 2015-04-12  Jean-Paul Calderone  <exarkun@twistedmatrix.com>
 
 	* OpenSSL/rand.py, OpenSSL/SSL.py: APIs which previously accepted
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py
index 9296444..d0cc933 100644
--- a/OpenSSL/SSL.py
+++ b/OpenSSL/SSL.py
@@ -1175,7 +1175,7 @@
                         errno = _ffi.getwinerror()[0]
                     else:
                         errno = _ffi.errno
-                    raise SysCallError(errno, errorcode[errno])
+                    raise SysCallError(errno, errorcode.get(errno))
                 else:
                     raise SysCallError(-1, "Unexpected EOF")
             else:
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index 2055b6d..bb1c9ae 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -2303,6 +2303,26 @@
             self.assertEqual(exc.args[0], EPIPE)
 
 
+    def test_shutdown_truncated(self):
+        """
+        If the underlying connection is truncated, :obj:`Connection.shutdown`
+        raises an :obj:`Error`.
+        """
+        server_ctx = Context(TLSv1_METHOD)
+        client_ctx = Context(TLSv1_METHOD)
+        server_ctx.use_privatekey(
+            load_privatekey(FILETYPE_PEM, server_key_pem))
+        server_ctx.use_certificate(
+            load_certificate(FILETYPE_PEM, server_cert_pem))
+        server = Connection(server_ctx, None)
+        client = Connection(client_ctx, None)
+        self._handshakeInMemory(client, server)
+        self.assertEqual(server.shutdown(), False)
+        self.assertRaises(WantReadError, server.shutdown)
+        server.bio_shutdown()
+        self.assertRaises(Error, server.shutdown)
+
+
     def test_set_shutdown(self):
         """
         :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown