diff options
-rw-r--r-- | camel/ChangeLog | 16 | ||||
-rw-r--r-- | camel/camel-file-utils.c | 63 | ||||
-rw-r--r-- | camel/camel-tcp-stream-ssl.c | 77 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 13 |
4 files changed, 95 insertions, 74 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index cba0110ce0..864fafa413 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,19 @@ +2004-05-06 Not Zed <NotZed@Ximian.com> + + * providers/imap/camel-imap-store.c (connect_to_server): set + nodelay and keepalive on the socket. + + * camel-file-utils.c (camel_read): put a timeout on the select. + Logic shuffle to match the ssl stuff. + (camel_write): Similar. + + * camel-tcp-stream-ssl.c (stream_connect): remove timeout, use + CONNECT_TIMEOUT directly. + (stream_read): put a timeout on the poll. IO_TIMEOUT. And a + little logic shuffle. + (stream_write): similar. + (CONNECT_TIMEOUT): make this 4 minutes === tcp-raw timeout. + 2004-05-05 Not Zed <NotZed@Ximian.com> * providers/imap/camel-imap-folder.c (get_message_simple): dont diff --git a/camel/camel-file-utils.c b/camel/camel-file-utils.c index 0d51795e32..f04cfa8278 100644 --- a/camel/camel-file-utils.c +++ b/camel/camel-file-utils.c @@ -43,6 +43,7 @@ #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif +#define IO_TIMEOUT (60*4) /** * camel_file_util_encode_uint32: @@ -404,27 +405,32 @@ camel_read (int fd, char *buf, size_t n) fcntl (fd, F_SETFL, flags | O_NONBLOCK); do { + struct timeval tv; + int res; + FD_ZERO (&rdset); FD_SET (fd, &rdset); FD_SET (cancel_fd, &rdset); fdmax = MAX (fd, cancel_fd) + 1; - + tv.tv_sec = IO_TIMEOUT; + tv.tv_usec = 0; nread = -1; - if (select (fdmax, &rdset, 0, 0, NULL) != -1) { - if (FD_ISSET (cancel_fd, &rdset)) { - fcntl (fd, F_SETFL, flags); - errno = EINTR; - return -1; - } - + + res = select(fdmax, &rdset, 0, 0, &tv); + if (res == -1) + ; + else if (res == 0) + errno = ETIMEDOUT; + else if (FD_ISSET (cancel_fd, &rdset)) { + errno = EINTR; + goto failed; + } else { do { nread = read (fd, buf, n); } while (nread == -1 && errno == EINTR); - } else if (errno == EINTR) { - errno = EAGAIN; } - } while (nread == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)); - + } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); + failed: errnosav = errno; fcntl (fd, F_SETFL, flags); errno = errnosav; @@ -475,36 +481,35 @@ camel_write (int fd, const char *buf, size_t n) fdmax = MAX (fd, cancel_fd) + 1; do { + struct timeval tv; + int res; + FD_ZERO (&rdset); FD_ZERO (&wrset); FD_SET (fd, &wrset); FD_SET (cancel_fd, &rdset); - + tv.tv_sec = IO_TIMEOUT; + tv.tv_usec = 0; w = -1; - if (select (fdmax, &rdset, &wrset, 0, NULL) != -1) { - if (FD_ISSET (cancel_fd, &rdset)) { - fcntl (fd, F_SETFL, flags); - errno = EINTR; - return -1; - } - + + res = select (fdmax, &rdset, &wrset, 0, &tv); + if (res == -1) { + if (errno == EINTR) + w = 0; + } else if (res == 0) + errno = ETIMEDOUT; + else if (FD_ISSET (cancel_fd, &rdset)) + errno = EINTR; + else { do { w = write (fd, buf + written, n - written); } while (w == -1 && errno == EINTR); if (w == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (errno == EAGAIN || errno == EWOULDBLOCK) w = 0; - } else { - errnosav = errno; - fcntl (fd, F_SETFL, flags); - errno = errnosav; - return -1; - } } else written += w; - } else if (errno == EINTR) { - w = 0; } } while (w != -1 && written < n); diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c index 1c8f1b34de..fd6f4ff550 100644 --- a/camel/camel-tcp-stream-ssl.c +++ b/camel/camel-tcp-stream-ssl.c @@ -65,6 +65,8 @@ /* from md5-utils.h */ void md5_get_digest (const char *buffer, int buffer_size, unsigned char digest[16]); +#define IO_TIMEOUT (PR_TicksPerSecond() * 4 * 60) +#define CONNECT_TIMEOUT (PR_TicksPerSecond () * 4 * 60) static CamelTcpStreamClass *parent_class = NULL; @@ -342,37 +344,38 @@ stream_read (CamelStream *stream, char *buffer, size_t n) nonblock = sockopts.value.non_blocking; sockopts.value.non_blocking = TRUE; PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - + pollfds[0].fd = tcp_stream_ssl->priv->sockfd; pollfds[0].in_flags = PR_POLL_READ; pollfds[1].fd = cancel_fd; pollfds[1].in_flags = PR_POLL_READ; do { + PRInt32 res; + pollfds[0].out_flags = 0; pollfds[1].out_flags = 0; - nread = -1; - if (PR_Poll (pollfds, 2, -1) != -1) { - if (pollfds[1].out_flags == PR_POLL_READ) { - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = EINTR; - return -1; - } - + + res = PR_Poll(pollfds, 2, IO_TIMEOUT); + if (res == -1) + set_errno(PR_GetError()); + else if (res == 0) + errno = ETIMEDOUT; + else if (pollfds[1].out_flags == PR_POLL_READ) { + errno = EINTR; + goto failed; + } else { do { nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); if (nread == -1) set_errno (PR_GetError ()); } while (nread == -1 && errno == EINTR); - } else { - errno = EAGAIN; } } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); /* restore O_NONBLOCK options */ + failed: error = errno; sockopts.option = PR_SockOpt_Nonblocking; sockopts.value.non_blocking = nonblock; @@ -427,19 +430,22 @@ stream_write (CamelStream *stream, const char *buffer, size_t n) pollfds[1].in_flags = PR_POLL_READ; do { + PRInt32 res; + pollfds[0].out_flags = 0; pollfds[1].out_flags = 0; - w = -1; - if (PR_Poll (pollfds, 2, -1) != -1) { - if (pollfds[1].out_flags == PR_POLL_READ) { - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = EINTR; - return -1; - } - + + res = PR_Poll (pollfds, 2, IO_TIMEOUT); + if (res == -1) { + set_errno(PR_GetError()); + if (errno == EINTR) + w = 0; + } else if (res == 0) + errno = ETIMEDOUT; + else if (pollfds[1].out_flags == PR_POLL_READ) { + errno = EINTR; + } else { do { w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); if (w == -1) @@ -447,22 +453,10 @@ stream_write (CamelStream *stream, const char *buffer, size_t n) } while (w == -1 && errno == EINTR); if (w == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (errno == EAGAIN || errno == EWOULDBLOCK) w = 0; - } else { - error = errno; - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = error; - return -1; - } } else written += w; - } else { - set_errno (PR_GetError ()); - if (errno == EINTR) - w = 0; } } while (w != -1 && written < n); @@ -1028,13 +1022,10 @@ enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd) return ssl_fd; } -#define CONNECT_TIMEOUT PR_TicksPerSecond () * 120 - static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port) { CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream); - PRIntervalTime timeout = CONNECT_TIMEOUT; PRNetAddr netaddr; PRFileDesc *fd; @@ -1079,7 +1070,7 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port) fd = ssl_fd; } - if (PR_Connect (fd, &netaddr, timeout) == PR_FAILURE) { + if (PR_Connect (fd, &netaddr, CONNECT_TIMEOUT) == PR_FAILURE) { int errnosave; set_errno (PR_GetError ()); @@ -1092,9 +1083,7 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port) poll.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; poll.out_flags = 0; - timeout = CONNECT_TIMEOUT; - - if (PR_Poll (&poll, 1, timeout) == PR_FAILURE) { + if (PR_Poll (&poll, 1, CONNECT_TIMEOUT) == PR_FAILURE) { set_errno (PR_GetError ()); goto exception; } @@ -1121,7 +1110,7 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port) } ssl->priv->sockfd = fd; - + return 0; } diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 146585e85c..da4a57b255 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -519,6 +519,7 @@ connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelE CamelImapStore *store = (CamelImapStore *) service; CamelImapResponse *response; CamelStream *tcp_stream; + CamelSockOptData sockopt; struct hostent *h; int clean_quit; int port, ret; @@ -576,7 +577,17 @@ connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelE store->connected = TRUE; store->preauthed = FALSE; store->command = 0; - + + /* Disable Nagle - we send a lot of small requests which nagle slows down */ + sockopt.option = CAMEL_SOCKOPT_NODELAY; + sockopt.value.no_delay = TRUE; + camel_tcp_stream_setsockopt((CamelTcpStream *)tcp_stream, &sockopt); + + /* Set keepalive - needed for some hosts/router configurations, we're idle a lot */ + sockopt.option = CAMEL_SOCKOPT_KEEPALIVE; + sockopt.value.keep_alive = TRUE; + camel_tcp_stream_setsockopt((CamelTcpStream *)tcp_stream, &sockopt); + /* Read the greeting, if any, and deal with PREAUTH */ if (camel_imap_store_readline (store, &buf, ex) < 0) { if (store->istream) { |