diff options
author | Ng Pheng Siong <ngps@netmemetic.com> | 2002-12-29 14:01:40 +0000 |
---|---|---|
committer | Ng Pheng Siong <ngps@netmemetic.com> | 2002-12-29 14:01:40 +0000 |
commit | a829adca99a69164e2ec032f94e7157891bbd76d (patch) | |
tree | 1a184c2d5683ec19056337e5330d3e0181552300 /contrib | |
parent | ff453c308e7587d401e62addf85dc324fa23415e (diff) | |
download | m2crypto-a829adca99a69164e2ec032f94e7157891bbd76d.tar.gz |
*** empty log message ***
git-svn-id: http://svn.osafoundation.org/m2crypto/trunk@156 2715db39-9adf-0310-9c64-84f055769b4b
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/README | 9 | ||||
-rw-r--r-- | contrib/dave.README | 64 | ||||
-rw-r--r-- | contrib/dave.patch | 180 |
3 files changed, 251 insertions, 2 deletions
diff --git a/contrib/README b/contrib/README index 956d0cc..f8c66d9 100644 --- a/contrib/README +++ b/contrib/README @@ -1,13 +1,18 @@ ------------- - 03 Jun 2001 + 29 Dec 2002 ------------- This directory contains contributions by users of M2Crypto. Some of these may get folded into the main distribution in time. - - dispatcher.py by Ilya Etingof <ilya@glas.net>. - m2crypto.spec by Sean Reifschneider <jafo-rpms@tummy.com>. +- Smarter non-blocking behaviour patch by Dave Brueck + <dave@pythonapocrypha.com>. + + +Thanks guys! + diff --git a/contrib/dave.README b/contrib/dave.README new file mode 100644 index 0000000..1a3339a --- /dev/null +++ b/contrib/dave.README @@ -0,0 +1,64 @@ +From dave@pythonapocrypha.com Wed Dec 11 07:57:55 2002 +Date: Tue, 10 Dec 2002 15:05:26 -0800 (PST) +From: Dave Brueck <dave@pythonapocrypha.com> +To: ngps@netmemetic.com +Subject: M2Crypto problem with asynch sockets + +Hi and thanks for M2Crypto - great stuff! + +I wrote an asynchronous socket layer and decided to use M2Crypto to add +SSL support to it. Unfortunately, I've found a small problem in +_m2crypto_wrap.c - hopefully I'm just not understanding something. + +The ssl_connect, ssl_read_nbio, etc. calls don't differentiate between +SSL_ERROR_WANT_WRITE and SSL_ERROR_WANT_READ when a non-blocking call +couldn't finish. But without this information, I don't know whether the +socket needs to do more reading or more writing before a subsequent +attempt will work without blocking. The demo applications (e.g. +echod-async.py) don't seem to care about this but they get around it by +simply trying the operation over and over again, which I can't do for +performance reasons. + +Am I missing something? I thought about just calling SSL_get_error when +the above calls return None (indicating WANT_READ or WANT_WRITE), but by +then the error has already been removed from the SSL error queue. + +Any help or suggestions would be appreciated. I'd be happy to submit a +patch fixing those calls, but by not returning None they would break +existing code. + +Thanks again for M2Crypto though! + +-Dave + + +From dave@pythonapocrypha.com Fri Dec 13 00:46:39 2002 +Date: Thu, 12 Dec 2002 09:52:08 -0800 (PST) +From: Dave Brueck <dave@pythonapocrypha.com> +To: ngps@netmemetic.com +Subject: Re: M2Crypto problem with asynch sockets + +Hello again, + +Here is a patch to M2Crypto's _ssl.i that illustrates the fix I had in +mind in my previous message. You might not want to use it as is since it +changes the error semantics of the affected functions (they now raise an +exception that contains the SSL_WANT_READ or SSL_WANT_WRITE flag instead +of returning None or whatever), but if you tell me how you'd like it +instead then I'd be happy to fix the patch and send it back to you. + +Just to refresh your memory, this patch fixes the problem where a +non-blocking call to accept/connect/etc results in an SSL_NEED_READ/WRITE; +currently there's no way for the caller to know _which_ of the two +occurred and so it must try again once the socket has become readable OR +writeable, instead of waiting specifically for one or the other. For many +people this won't matter because their performance requirements are low +enough that trying the ssl_accept/etc call again prematurely won't hurt +too much, but for servers with lots of connections or high throughput it's +much more critical to wait until you know the SSL call has a better chance +of success. + +Thanks! +-Dave Brueck + + diff --git a/contrib/dave.patch b/contrib/dave.patch new file mode 100644 index 0000000..6e41073 --- /dev/null +++ b/contrib/dave.patch @@ -0,0 +1,180 @@ +--- _ssl.i.orig Tue Sep 18 06:06:34 2001 ++++ _ssl.i Thu Dec 12 08:57:39 2002 +@@ -238,9 +238,18 @@ + return ret; + } + ++void SetWantRWError(int which) { ++ PyObject *o = Py_BuildValue("(is)", which, ++ +ERR_reason_error_string(ERR_get_error())); ++ if (o != NULL) { ++ PyErr_SetObject(_ssl_err, o); ++ Py_DECREF(o); ++ } ++} ++ + PyObject *ssl_accept(SSL *ssl) { + PyObject *obj; +- int r, err; ++ int r, err, which; + PyThreadState *_save; + + if (thread_mode) { +@@ -252,14 +261,15 @@ + _save = (PyThreadState *)SSL_get_app_data(ssl); + PyEval_RestoreThread(_save); + } +- switch (SSL_get_error(ssl, r)) { ++ switch ((which = SSL_get_error(ssl, r))) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + obj = PyInt_FromLong((long)1); + break; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: +- obj = PyInt_FromLong((long)0); ++ SetWantRWError(which); ++ obj = NULL; + break; + case SSL_ERROR_SSL: + PyErr_SetString(_ssl_err, +ERR_reason_error_string(ERR_get_error())); +@@ -281,7 +291,7 @@ + + PyObject *ssl_connect(SSL *ssl) { + PyObject *obj; +- int r, err; ++ int r, err, which; + PyThreadState *_save; + + if (thread_mode) { +@@ -293,14 +303,15 @@ + _save = (PyThreadState *)SSL_get_app_data(ssl); + PyEval_RestoreThread(_save); + } +- switch (SSL_get_error(ssl, r)) { ++ switch ((which = SSL_get_error(ssl, r))) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + obj = PyInt_FromLong((long)1); + break; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: +- obj = PyInt_FromLong((long)0); ++ SetWantRWError(which); ++ obj = NULL; + break; + case SSL_ERROR_SSL: + PyErr_SetString(_ssl_err, +ERR_reason_error_string(ERR_get_error())); +@@ -327,7 +338,7 @@ + PyObject *ssl_read(SSL *ssl, int num) { + PyObject *obj; + void *buf; +- int r, err; ++ int r, err, which; + PyThreadState *_save; + + if (!(buf = PyMem_Malloc(num))) { +@@ -343,7 +354,7 @@ + _save = (PyThreadState *)SSL_get_app_data(ssl); + PyEval_RestoreThread(_save); + } +- switch (SSL_get_error(ssl, r)) { ++ switch ((which = SSL_get_error(ssl, r))) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + buf = PyMem_Realloc(buf, r); +@@ -352,8 +363,8 @@ + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_X509_LOOKUP: +- Py_INCREF(Py_None); +- obj = Py_None; ++ SetWantRWError(which); ++ obj = NULL; + break; + case SSL_ERROR_SSL: + PyErr_SetString(_ssl_err, +ERR_reason_error_string(ERR_get_error())); +@@ -377,14 +388,14 @@ + PyObject *ssl_read_nbio(SSL *ssl, int num) { + PyObject *obj; + void *buf; +- int r, err; ++ int r, err, which; + + if (!(buf = PyMem_Malloc(num))) { + PyErr_SetString(PyExc_MemoryError, "ssl_read"); + return NULL; + } + r = SSL_read(ssl, buf, num); +- switch (SSL_get_error(ssl, r)) { ++ switch ((which = SSL_get_error(ssl, r))) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + buf = PyMem_Realloc(buf, r); +@@ -392,6 +403,9 @@ + break; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: ++ SetWantRWError(which); ++ obj = NULL; ++ break; + case SSL_ERROR_WANT_X509_LOOKUP: + Py_INCREF(Py_None); + obj = Py_None; +@@ -417,7 +431,7 @@ + + int ssl_write(SSL *ssl, PyObject *blob) { + const void *buf; +- int len, r, err; ++ int len, r, err, which; + PyThreadState *_save; + + #if PYTHON_API_VERSION >= 1009 +@@ -440,12 +454,14 @@ + _save = (PyThreadState *)SSL_get_app_data(ssl); + PyEval_RestoreThread(_save); + } +- switch (SSL_get_error(ssl, r)) { ++ switch ((which = SSL_get_error(ssl, r))) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + return r; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: ++ SetWantRWError(which); ++ return -1; + case SSL_ERROR_WANT_X509_LOOKUP: + return -1; + case SSL_ERROR_SSL: +@@ -466,7 +482,7 @@ + + int ssl_write_nbio(SSL *ssl, PyObject *blob) { + const void *buf; +- int len, r, err; ++ int len, r, err, which; + + #if PYTHON_API_VERSION >= 1009 + if (PyObject_AsReadBuffer(blob, &buf, &len) == -1) +@@ -480,12 +496,14 @@ + buf = (const void *)PyString_AsString(blob); + #endif + r = SSL_write(ssl, buf, len); +- switch (SSL_get_error(ssl, r)) { ++ switch ((which = SSL_get_error(ssl, r))) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + return r; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: ++ SetWantRWError(which); ++ return -1; + case SSL_ERROR_WANT_X509_LOOKUP: + return -1; + case SSL_ERROR_SSL: + + + |