diff -r 43ae2a243eca Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py Thu Jul 26 00:47:15 2012 +0200 +++ b/Lib/test/test_ssl.py Fri Jul 27 11:07:41 2012 +1000 @@ -752,6 +752,18 @@ finally: s.close() + def test_connect_with_msg_callback(self): + with support.transient_internet("svn.python.org"): + def cb(packet): + self.assertGreater(len(packet), 0) + ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + ctx.set_msg_callback(cb) + s = ctx.wrap_socket(socket.socket(socket.AF_INET)) + try: + s.connect(("svn.python.org", 443)) + finally: + s.close() + def test_connect_capath(self): # Verify server certificates using the `capath` argument # NOTE: the subject hashing algorithm has been changed between diff -r 43ae2a243eca Modules/_ssl.c --- a/Modules/_ssl.c Thu Jul 26 00:47:15 2012 +0200 +++ b/Modules/_ssl.c Fri Jul 27 11:07:41 2012 +1000 @@ -181,6 +181,7 @@ char *npn_protocols; int npn_protocols_len; #endif + PyObject *msg_callback; } PySSLContext; typedef struct { @@ -1713,6 +1714,7 @@ return NULL; } self->ctx = ctx; + self->msg_callback = NULL; /* Defaults */ SSL_CTX_set_verify(self->ctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_options(self->ctx, @@ -1726,6 +1728,55 @@ return (PyObject *)self; } +void +_msg_callback(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg) +{ + PyObject *args, *result; + +#ifdef WITH_THREAD + PyGILState_STATE threadstate; +#endif + + args = Py_BuildValue("(y#)", (char *)buf, len); + if(args == NULL) + return; + +#ifdef WITH_THREAD + threadstate = PyGILState_Ensure(); +#endif + + result = PyObject_CallObject(((PySSLContext *)arg)->msg_callback, args); + Py_DECREF(args); + if (result == NULL) + PyErr_Print(); + Py_DECREF(result); + +#ifdef WITH_THREAD + PyGILState_Release(threadstate); +#endif +} + +static PyObject * +set_msg_callback(PySSLContext *self, PyObject *args) +{ + PyObject *temp; + + if (PyArg_ParseTuple(args, "O", &temp)) { + if(!PyCallable_Check(temp)) { + PyErr_SetString(PyExc_TypeError, "parameter must be callable"); + return NULL; + } + Py_XINCREF(temp); + if (self->msg_callback) + Py_XDECREF(self->msg_callback); + self->msg_callback = temp; + SSL_CTX_set_msg_callback(self->ctx, _msg_callback); + SSL_CTX_set_msg_callback_arg(self->ctx, self); + } + Py_RETURN_NONE; +} + static void context_dealloc(PySSLContext *self) { @@ -2314,6 +2365,8 @@ METH_VARARGS | METH_KEYWORDS, NULL}, {"set_ciphers", (PyCFunction) set_ciphers, METH_VARARGS, NULL}, + {"set_msg_callback", (PyCFunction) set_msg_callback, + METH_VARARGS, NULL}, {"_set_npn_protocols", (PyCFunction) _set_npn_protocols, METH_VARARGS, NULL}, {"load_cert_chain", (PyCFunction) load_cert_chain,