summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorNg Pheng Siong <ngps@netmemetic.com>2002-12-29 14:01:40 +0000
committerNg Pheng Siong <ngps@netmemetic.com>2002-12-29 14:01:40 +0000
commita829adca99a69164e2ec032f94e7157891bbd76d (patch)
tree1a184c2d5683ec19056337e5330d3e0181552300 /contrib
parentff453c308e7587d401e62addf85dc324fa23415e (diff)
downloadm2crypto-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/README9
-rw-r--r--contrib/dave.README64
-rw-r--r--contrib/dave.patch180
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:
+
+
+