Merge pull request #358 from kjav/patch-3

Implemented state_string function
diff --git a/ChangeLog b/ChangeLog
index b7cfd9b..e872eca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-09-07 Sam Lee <sam.rr.lee@gmail.com>
+
+	* OpenSSL/SSL.py, OpenSSL/test/test_ssl.py: Implemented
+	  the ``Connection.state_string()`` function, using
+	  the OpenSSL binding state_string_long.
+
 2015-08-17  Maximilian Hils <pyopenssl@maximilianhils.com>
 
 	* OpenSSL/SSL.py, OpenSSL/test/test_ssl.py: Add support for
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py
index f8f5e02..190e4ac 100644
--- a/OpenSSL/SSL.py
+++ b/OpenSSL/SSL.py
@@ -1592,6 +1592,7 @@
 
         :return: A string representing the state
         """
+        return _ffi.string(_lib.SSL_state_string_long(self._ssl))
 
     def server_random(self):
         """
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index 55a4015..39e878f 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -2333,6 +2333,50 @@
         connection.set_shutdown(long(RECEIVED_SHUTDOWN))
         self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
 
+    def test_state_string(self):
+        """
+        :py:obj:`Connection.state_string` verbosely describes the current
+        state of the :py:obj:`Connection`.
+        """
+        (server, client) = socket_pair()
+        server = self._loopbackServerFactory(server)
+        client = self._loopbackClientFactory(client)
+
+        self.assertEqual('before/accept initialization',
+                         server.state_string().decode())
+        self.assertEqual('before/connect initialization',
+                         client.state_string().decode())
+
+        for conn in [server, client]:
+            try:
+                conn.do_handshake()
+            except WantReadError:
+                pass
+
+        self.assertEqual('SSLv3 read client hello B',
+                         server.state_string().decode())
+        self.assertEqual('SSLv3 read server hello A',
+                         client.state_string().decode())
+
+        for conn in [server, client]:
+            try:
+                conn.do_handshake()
+            except WantReadError:
+                pass
+
+        self.assertEqual('SSLv3 read client certificate A',
+                         server.state_string().decode())
+        self.assertEqual('SSLv3 read server session ticket A',
+                         client.state_string().decode())
+
+        for conn in [server, client]:
+            conn.do_handshake()
+
+        self.assertEqual('SSL negotiation finished successfully',
+                         server.state_string().decode())
+        self.assertEqual('SSL negotiation finished successfully',
+                         client.state_string().decode())
+
     def test_app_data_wrong_args(self):
         """
         :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called