diff options
Diffstat (limited to 'src/tls_timeoutio.c')
-rw-r--r-- | src/tls_timeoutio.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/tls_timeoutio.c b/src/tls_timeoutio.c new file mode 100644 index 0000000..c5f40a2 --- /dev/null +++ b/src/tls_timeoutio.c @@ -0,0 +1,99 @@ +/* This is essentially taken from Eric Vermeulen's TLS patch */ +#include "select.h" +#include "error.h" +#include "ndelay.h" +#include "now.h" +#include "logmsg.h" +#include "ucspissl.h" +#include "tls_timeoutio.h" + +int tls_timeoutio(int (*fun)(), + int t, int rfd, int wfd, SSL *ssl, char *buf, int len) +{ + int n; + const datetime_sec end = (datetime_sec)t + now(); + + do { + fd_set fds; + struct timeval tv; + + const int r = buf ? fun(ssl,buf,len) : fun(ssl); + if (r > 0) return r; + + t = end - now(); + if (t < 0) break; + tv.tv_sec = (time_t)t; tv.tv_usec = 0; + + FD_ZERO(&fds); + switch (SSL_get_error(ssl,r)) { + default: return r; /* some other error */ + case SSL_ERROR_WANT_READ: + FD_SET(rfd,&fds); n = select(rfd + 1,&fds,NULL,NULL,&tv); + break; + case SSL_ERROR_WANT_WRITE: + FD_SET(wfd,&fds); n = select(wfd + 1,NULL,&fds,NULL,&tv); + break; + } + + /* n is the number of descriptors that changed status */ + } while (n > 0); + + if (n != -1) errno = ETIMEDOUT; + return -1; +} + +int tls_timeoutaccept(int t,int rfd,int wfd,SSL *ssl) +{ + int r; + + /* if connection is established, keep NDELAY */ + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1; + r = tls_timeoutio(SSL_accept,t,rfd,wfd,ssl,NULL,0); + + if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); } + else SSL_set_mode(ssl,SSL_MODE_ENABLE_PARTIAL_WRITE); + + return r; +} + +int tls_timeoutconn(int t,int rfd,int wfd,SSL *ssl) +{ + int r; + + /* if connection is established, keep NDELAY */ + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1; + r = tls_timeoutio(SSL_connect,t,rfd,wfd,ssl,NULL,0); + + if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); } + else SSL_set_mode(ssl,SSL_MODE_ENABLE_PARTIAL_WRITE); + + return r; +} + +int tls_timeoutrehandshake(int t,int rfd,int wfd,SSL *ssl) +{ + int r; + + SSL_renegotiate(ssl); + r = tls_timeoutio(SSL_do_handshake,t,rfd,wfd,ssl,NULL,0); + if (r <= 0) return r; + if (SSL_get_state(ssl) & SSL_ST_CONNECT) return -2; /* now a macro in ssl.h */ + + /* this is for the client only */ + SSL_set_connect_state(ssl); + + return tls_timeoutio(SSL_do_handshake,t,rfd,wfd,ssl,NULL,0); +} + +int tls_timeoutread(int t,int rfd,int wfd,SSL *ssl,char *buf,int len) +{ + if (!buf) return 0; + if (SSL_pending(ssl)) return SSL_read(ssl,buf,len); + return tls_timeoutio(SSL_read,t,rfd,wfd,ssl,buf,len); +} + +int tls_timeoutwrite(int t,int rfd,int wfd,SSL *ssl,char *buf,int len) +{ + if (!buf) return 0; + return tls_timeoutio(SSL_write,t,rfd,wfd,ssl,buf,len); +} |