From 511606835d1d58fce342e39a3e9371b29c11205f Mon Sep 17 00:00:00 2001 From: Vlad-Mihai Sima Date: Sun, 1 Jan 2012 20:09:18 +0100 Subject: [PATCH 1/2] Bug fix: when using tls, if a stanza is bigger than the buffer of 4096 in event.c, the stanza will not be read as select will return 0 on the ssl socket and the data will be in ssl buffers. Partial fix, only for Linux for now --- src/event.c | 12 +++++++++--- src/tls.h | 1 + src/tls_dummy.c | 5 +++++ src/tls_gnutls.c | 5 +++++ src/tls_openssl.c | 5 +++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/event.c b/src/event.c index b51b2e1..1eaa643 100644 --- a/src/event.c +++ b/src/event.c @@ -85,6 +85,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout) char buf[4096]; uint64_t next; long usec; + int tls_read_bytes = 0; if (ctx->loop_status == XMPP_LOOP_QUIT) return; ctx->loop_status = XMPP_LOOP_RUNNING; @@ -215,6 +216,11 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout) break; } + /* Check if there is something in the SSL buffer. */ + if (conn->tls) { + tls_read_bytes += tls_pending(conn->tls); + } + if (conn->sock > max) max = conn->sock; connitem = connitem->next; @@ -232,8 +238,8 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout) } /* no events happened */ - if (ret == 0) return; - + if (ret == 0 && tls_read_bytes == 0) return; + /* process events */ connitem = ctx->connlist; while (connitem) { @@ -262,7 +268,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout) break; case XMPP_STATE_CONNECTED: - if (FD_ISSET(conn->sock, &rfds)) { + if (FD_ISSET(conn->sock, &rfds) || (conn->tls && tls_pending(conn->tls))) { if (conn->tls) { ret = tls_read(conn->tls, buf, 4096); } else { diff --git a/src/tls.h b/src/tls.h index d89fe3e..fa670b9 100644 --- a/src/tls.h +++ b/src/tls.h @@ -37,6 +37,7 @@ int tls_stop(tls_t *tls); int tls_error(tls_t *tls); +int tls_pending(tls_t *tls); int tls_read(tls_t *tls, void * const buff, const size_t len); int tls_write(tls_t *tls, const void * const buff, const size_t len); diff --git a/src/tls_dummy.c b/src/tls_dummy.c index c7d5214..00505fe 100644 --- a/src/tls_dummy.c +++ b/src/tls_dummy.c @@ -68,6 +68,11 @@ int tls_error(tls_t *tls) return 0; } +int tls_pending(tls_t *tls) +{ + return 0; +} + int tls_read(tls_t *tls, void * const buff, const size_t len) { return -1; diff --git a/src/tls_gnutls.c b/src/tls_gnutls.c index a751ec5..7841331 100644 --- a/src/tls_gnutls.c +++ b/src/tls_gnutls.c @@ -107,6 +107,11 @@ int tls_error(tls_t *tls) return 0; } +int tls_pending(tls_t *tls) +{ + return gnutls_record_check_pending (tls->session); +} + int tls_read(tls_t *tls, void * const buff, const size_t len) { int ret; diff --git a/src/tls_openssl.c b/src/tls_openssl.c index a8a76d3..7e59f8e 100644 --- a/src/tls_openssl.c +++ b/src/tls_openssl.c @@ -152,6 +152,11 @@ int tls_is_recoverable(int error) || error == SSL_ERROR_WANT_ACCEPT); } +int tls_pending(tls_t *tls) +{ + return SSL_pending(tls->ssl); +} + int tls_read(tls_t *tls, void * const buff, const size_t len) { int ret = SSL_read(tls->ssl, buff, len); From 5344669bb76cffd53cb72982cd958ac5274f8b35 Mon Sep 17 00:00:00 2001 From: "U-vladms-pc\\vladms" Date: Tue, 10 Jan 2012 17:35:53 +0100 Subject: [PATCH 2/2] Added tls_pending to windows schannel implementation of tls --- src/tls_schannel.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tls_schannel.c b/src/tls_schannel.c index 1723b2a..c1db394 100644 --- a/src/tls_schannel.c +++ b/src/tls_schannel.c @@ -398,6 +398,22 @@ int tls_is_recoverable(int error) || error == WSAEINPROGRESS); } +int tls_pending(tls_t *tls) { + // There are 3 cases: + // - there is data in ready buffer, so it is by default pending + // - there is data in recv buffer. If it is not decrypted yet, means it + // was incomplete. This should be processed again only if there is data + // on the physical connection + // - there is data on the physical connection. This case is treated + // outside the tls (in event.c) + + if (tls->readybufferpos < tls->readybufferlen) { + return tls->readybufferlen - tls->readybufferpos; + } + + return 0; +} + int tls_read(tls_t *tls, void * const buff, const size_t len) { int bytes;