--------------------- PatchSet 5991 Date: 2003/10/25 15:32:23 Author: hno Branch: ssl-2_5 Tag: (none) Log: Add primitive support for SSL_read/write indicating they need to do the opposite low-level I/O operation, as may happen if there is a renegotiation taking place. Also tries to add support for TurboSSL which adds yet another SSL I/O case where the SSL_read/write simply needs to be retried again a little later. The trouble is that the current design does not really allow the function performing the I/O logics (i.e. clientReadRequest etc) to know what the low level I/O functions need. It simply assumes that it needs to commSetSelect for read if it is a read function, while the low-level I/O function may in fact have other demands. To address this two new fields are added in the fd_table descriptors: pending_read: low level read requirements pending_write: low level write requirements possible values for these are COMM_PENDING_NORMAL, COMM_PENDING_WANTS_READ, COMM_PENDING_WANTS_WRITE, COMM_PENDING_NOW, where COMM_PENDING_NORMAL is the normal situation behaving as instructed by commSetSelect(). This replaces the flags.pending_read flag which was previously used by SSL to indicate there is already data buffered by the SSL and immediately ready for reading. This case is now F->read_pending = COMM_PENDING_NOW; Members: src/client_side.c:1.47.2.21.2.9->1.47.2.21.2.10 src/comm_select.c:1.8.6.2.2.2->1.8.6.2.2.3 src/enums.h:1.29.2.7.2.2->1.29.2.7.2.3 src/forward.c:1.13.6.1.8.5->1.13.6.1.8.6 src/ssl_support.c:1.6.6.1.2.4->1.6.6.1.2.5 src/ssl_support.h:1.5.44.2->1.5.44.3 src/structs.h:1.48.2.8.2.7->1.48.2.8.2.8 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.47.2.21.2.9 retrieving revision 1.47.2.21.2.10 diff -u -r1.47.2.21.2.9 -r1.47.2.21.2.10 --- squid/src/client_side.c 2 Sep 2003 12:54:00 -0000 1.47.2.21.2.9 +++ squid/src/client_side.c 25 Oct 2003 15:32:23 -0000 1.47.2.21.2.10 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.47.2.21.2.9 2003/09/02 12:54:00 hno Exp $ + * $Id: client_side.c,v 1.47.2.21.2.10 2003/10/25 15:32:23 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -3434,6 +3434,13 @@ case SSL_ERROR_WANT_WRITE: commSetSelect(fd, COMM_SELECT_WRITE, clientNegotiateSSL, conn, 0); return; +#ifdef CAVIUM_SSL + case SSL_ERROR_WANT_CAVIUM_CRYPTO: + i = -1; + fd_table[fd].read_pending = COMM_PENDING_NOW; + commSetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, conn, 0); + return; +#endif default: debug(81, 1) ("clientNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret); Index: squid/src/comm_select.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/comm_select.c,v retrieving revision 1.8.6.2.2.2 retrieving revision 1.8.6.2.2.3 diff -u -r1.8.6.2.2.2 -r1.8.6.2.2.3 --- squid/src/comm_select.c 15 May 2003 11:15:15 -0000 1.8.6.2.2.2 +++ squid/src/comm_select.c 25 Oct 2003 15:32:26 -0000 1.8.6.2.2.3 @@ -1,6 +1,6 @@ /* - * $Id: comm_select.c,v 1.8.6.2.2.2 2003/05/15 11:15:15 hno Exp $ + * $Id: comm_select.c,v 1.8.6.2.2.3 2003/10/25 15:32:26 hno Exp $ * * DEBUG: section 5 Socket Functions * @@ -312,7 +312,6 @@ #if DELAY_POOLS fd_set slowfds; #endif - PF *hdl = NULL; int fd; unsigned int i; unsigned int maxfd; @@ -349,30 +348,63 @@ events = 0; /* Check each open socket for a handler. */ if (fd_table[i].read_handler) { + int dopoll = 1; switch (commDeferRead(i)) { case 0: - events |= POLLRDNORM; break; case 1: + dopoll = 0; break; #if DELAY_POOLS case -1: - events |= POLLRDNORM; FD_SET(i, &slowfds); break; #endif default: fatalf("bad return value from commDeferRead(FD %d)\n", i); + /* NOTREACHED */ + } + if (dopoll) { + switch (fd_table[i].read_pending) { + case COMM_PENDING_NORMAL: + events |= POLLRDNORM; + break; + case COMM_PENDING_WANTS_WRITE: + events |= POLLWRNORM; + break; + case COMM_PENDING_WANTS_READ: + events |= POLLRDNORM; + break; + case COMM_PENDING_NOW: + events |= POLLRDNORM; + npending++; + } } + } - if (fd_table[i].write_handler) + if (fd_table[i].write_handler) { + switch (fd_table[i].read_pending) { + case COMM_PENDING_NORMAL: + events |= POLLWRNORM; + break; + case COMM_PENDING_WANTS_WRITE: + events |= POLLWRNORM; + break; + case COMM_PENDING_WANTS_READ: + events |= POLLRDNORM; + break; + case COMM_PENDING_NOW: + events |= POLLWRNORM; + npending++; + } events |= POLLWRNORM; + } if (events) { pfds[nfds].fd = i; pfds[nfds].events = events; pfds[nfds].revents = 0; nfds++; - if ((events & POLLRDNORM) && fd_table[i].flags.read_pending) + if ((events & POLLRDNORM) && fd_table[i].read_pending) npending++; } } @@ -384,14 +416,10 @@ msec = 0; if (msec > MAX_POLL_TIME) msec = MAX_POLL_TIME; - for (;;) { - statCounter.syscalls.polls++; - num = poll(pfds, nfds, msec); - statCounter.select_loops++; - if (num >= 0 || npending > 0) - break; - if (ignoreErrno(errno)) - continue; + statCounter.syscalls.polls++; + num = poll(pfds, nfds, msec); + statCounter.select_loops++; + if (num < 0 && !ignoreErrno(errno)) { debug(5, 0) ("comm_poll: poll failure: %s\n", xstrerror()); assert(errno != EINVAL); return COMM_ERROR; @@ -415,8 +443,30 @@ fd = pfds[i].fd; if (fd == -1) continue; - if (fd_table[fd].flags.read_pending) + switch(fd_table[fd].read_pending) { + case COMM_PENDING_NORMAL: + case COMM_PENDING_WANTS_READ: + break; + case COMM_PENDING_WANTS_WRITE: + if (pfds[i].revents & (POLLOUT | POLLWRNORM)) + revents |= POLLIN; + break; + case COMM_PENDING_NOW: revents |= POLLIN; + break; + } + switch(fd_table[fd].write_pending) { + case COMM_PENDING_NORMAL: + case COMM_PENDING_WANTS_WRITE: + break; + case COMM_PENDING_WANTS_READ: + if (pfds[i].revents & (POLLIN | POLLRDNORM)) + revents |= POLLOUT; + break; + case COMM_PENDING_NOW: + revents |= POLLOUT; + break; + } if (revents == 0) continue; if (fdIsIcp(fd)) { @@ -433,15 +483,17 @@ } F = &fd_table[fd]; if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { + PF *hdl = F->read_handler; debug(5, 6) ("comm_poll: FD %d ready for reading\n", fd); - if (NULL == (hdl = F->read_handler)) - (void) 0; + if (hdl == NULL) + (void) 0; /* Nothing to do */ #if DELAY_POOLS else if (FD_ISSET(fd, &slowfds)) commAddSlowFd(fd); #endif else { F->read_handler = NULL; + F->read_pending = COMM_PENDING_NORMAL; hdl(fd, F->read_data); statCounter.select_fds++; if (commCheckICPIncoming) @@ -453,9 +505,11 @@ } } if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { + PF *hdl = F->write_handler; debug(5, 5) ("comm_poll: FD %d ready for writing\n", fd); - if ((hdl = F->write_handler)) { + if (hdl != NULL) { F->write_handler = NULL; + F->write_pending = COMM_PENDING_NORMAL; hdl(fd, F->write_data); statCounter.select_fds++; if (commCheckICPIncoming) @@ -500,9 +554,11 @@ #if DELAY_POOLS while ((fd = commGetSlowFd()) != -1) { fde *F = &fd_table[fd]; + PF *hdl = F->read_handler; debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd); - if ((hdl = F->read_handler)) { + if (hdl != NULL) { F->read_handler = NULL; + F->read_pending = COMM_PENDING_NORMAL; hdl(fd, F->read_data); statCounter.select_fds++; if (commCheckICPIncoming) Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.29.2.7.2.2 retrieving revision 1.29.2.7.2.3 diff -u -r1.29.2.7.2.2 -r1.29.2.7.2.3 --- squid/src/enums.h 3 Feb 2003 15:27:52 -0000 1.29.2.7.2.2 +++ squid/src/enums.h 25 Oct 2003 15:32:26 -0000 1.29.2.7.2.3 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.29.2.7.2.2 2003/02/03 15:27:52 hno Exp $ + * $Id: enums.h,v 1.29.2.7.2.3 2003/10/25 15:32:26 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -746,4 +746,15 @@ #endif +/* + * Special case pending filedescriptors. Set in fd_table[fd].read/write_pending + */ +typedef enum { + COMM_PENDING_NORMAL, /* No special processing required */ + COMM_PENDING_WANTS_READ, /* need to read, no matter what commSetSelect indicates */ + COMM_PENDING_WANTS_WRITE, /* need to write, no matter what commSetSelect indicates */ + COMM_PENDING_NOW /* needs to be called again, without needing to wait for readiness + * for example when data is already buffered etc */ +} comm_pending; + #endif /* SQUID_ENUMS_H */ Index: squid/src/forward.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/forward.c,v retrieving revision 1.13.6.1.8.5 retrieving revision 1.13.6.1.8.6 diff -u -r1.13.6.1.8.5 -r1.13.6.1.8.6 --- squid/src/forward.c 18 Aug 2003 12:13:30 -0000 1.13.6.1.8.5 +++ squid/src/forward.c 25 Oct 2003 15:32:26 -0000 1.13.6.1.8.6 @@ -1,6 +1,6 @@ /* - * $Id: forward.c,v 1.13.6.1.8.5 2003/08/18 12:13:30 hno Exp $ + * $Id: forward.c,v 1.13.6.1.8.6 2003/10/25 15:32:26 hno Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -229,6 +229,12 @@ case SSL_ERROR_WANT_WRITE: commSetSelect(fd, COMM_SELECT_WRITE, fwdNegotiateSSL, fwdState, 0); return; +#ifdef CAVIUM_SSL + case SSL_ERROR_WANT_CAVIUM_CRYPTO: + fd_table[fd].read_pending = COMM_PENDING_NOW; + commSetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, conn, 0); + return; +#endif default: debug(81, 1) ("fwdNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret); err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); Index: squid/src/ssl_support.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ssl_support.c,v retrieving revision 1.6.6.1.2.4 retrieving revision 1.6.6.1.2.5 diff -u -r1.6.6.1.2.4 -r1.6.6.1.2.5 --- squid/src/ssl_support.c 17 Apr 2003 15:24:39 -0000 1.6.6.1.2.4 +++ squid/src/ssl_support.c 25 Oct 2003 15:32:26 -0000 1.6.6.1.2.5 @@ -618,9 +618,35 @@ if (i > 0 && SSL_pending(fd_table[fd].ssl) > 0) { debug(83, 2) ("SSL fd %d is pending\n", fd); - fd_table[fd].flags.read_pending = 1; - } else - fd_table[fd].flags.read_pending = 0; + fd_table[fd].read_pending = COMM_PENDING_NOW; + } else if (i <= 0) { + int err = SSL_get_error(fd_table[fd].ssl, i); + switch (err) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + i = 0; + break; + case SSL_ERROR_WANT_READ: + i = -1; + errno = EAGAIN; + break; + case SSL_ERROR_WANT_WRITE: + fd_table[fd].read_pending = COMM_PENDING_WANTS_WRITE; + i = -1; + errno = EAGAIN; + break; +#ifdef CAVIUM_SSL + case SSL_ERROR_WANT_CAVIUM_CRYPTO: + i = -1; + fd_table[fd].read_pending = COMM_PENDING_NOW; + errno = EAGAIN; + break; +#endif + default: + i = -1; + break; + } + } return i; } @@ -631,13 +657,44 @@ const char *buf; int len; { - return (SSL_write(fd_table[fd].ssl, buf, len)); + int i = SSL_write(fd_table[fd].ssl, buf, len); + + if (i <= 0) { + int err = SSL_get_error(fd_table[fd].ssl, i); + switch (err) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + i = 0; + break; + case SSL_ERROR_WANT_READ: + fd_table[fd].write_pending = COMM_PENDING_WANTS_READ; + i = -1; + errno = EAGAIN; + break; + case SSL_ERROR_WANT_WRITE: + i = -1; + errno = EAGAIN; + break; +#ifdef CAVIUM_SSL + case SSL_ERROR_WANT_CAVIUM_CRYPTO: + i = -1; + fd_table[fd].write_pending = COMM_PENDING_NOW; + errno = EAGAIN; + break; +#endif + default: + i = -1; + break; + } + } + return i; } -void +int ssl_shutdown_method(fd) { SSL *ssl = fd_table[fd].ssl; + int ret; if (!fd_table[fd].ssl_shutdown) { fd_table[fd].ssl_shutdown = 1; if (Config.SSL.unclean_shutdown) @@ -645,7 +702,38 @@ else SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); } - SSL_shutdown(ssl); + ret = SSL_shutdown(ssl); + if (ret <= 0) { + int err = SSL_get_error(ssl, ret); + switch (err) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + ret = 1; + break; + case SSL_ERROR_WANT_READ: + fd_table[fd].read_pending = COMM_PENDING_WANTS_READ; + ret = -1; + errno = EAGAIN; + break; + case SSL_ERROR_WANT_WRITE: + /* Should CommSetSelect for write, but the Squid API does not allow this.. */ + fd_table[fd].read_pending = COMM_PENDING_WANTS_WRITE; + ret = -1; + errno = EAGAIN; + break; +#ifdef CAVIUM_SSL + case SSL_ERROR_WANT_CAVIUM_CRYPTO: + ret = -1; + fd_table[fd].read_pending = COMM_PENDING_NOW; + errno = EAGAIN; + break; +#endif + default: + ret = -1; + break; + } + } + return ret; } static const char * Index: squid/src/ssl_support.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ssl_support.h,v retrieving revision 1.5.44.2 retrieving revision 1.5.44.3 diff -u -r1.5.44.2 -r1.5.44.3 --- squid/src/ssl_support.h 17 Apr 2003 15:24:41 -0000 1.5.44.2 +++ squid/src/ssl_support.h 25 Oct 2003 15:32:26 -0000 1.5.44.3 @@ -50,7 +50,7 @@ SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath); int ssl_read_method(int, char *, int); int ssl_write_method(int, const char *, int); -void ssl_shutdown_method(int); +int ssl_shutdown_method(int); const char *sslGetUserEmail(SSL *ssl); const char *sslGetUserAttribute(SSL *ssl, const char *attribute); Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.48.2.8.2.7 retrieving revision 1.48.2.8.2.8 diff -u -r1.48.2.8.2.7 -r1.48.2.8.2.8 --- squid/src/structs.h 17 Sep 2003 14:51:33 -0000 1.48.2.8.2.7 +++ squid/src/structs.h 25 Oct 2003 15:32:26 -0000 1.48.2.8.2.8 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.48.2.8.2.7 2003/09/17 14:51:33 hno Exp $ + * $Id: structs.h,v 1.48.2.8.2.8 2003/10/25 15:32:26 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -798,8 +798,9 @@ unsigned int called_connect:1; unsigned int nodelay:1; unsigned int close_on_exec:1; - unsigned int read_pending:1; } flags; + comm_pending read_pending; + comm_pending write_pending; int bytes_read; int bytes_written; int uses; /* ie # req's over persistent conn */