diff options
-rw-r--r-- | camel/ChangeLog | 14 | ||||
-rw-r--r-- | camel/camel-tcp-stream-raw.c | 106 | ||||
-rw-r--r-- | camel/camel-tcp-stream-ssl.c | 36 |
3 files changed, 114 insertions, 42 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 9dbebe0469..12ee379fde 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,5 +1,19 @@ 2001-03-13 Jeffrey Stedfast <fejj@ximian.com> + * camel-tcp-stream-raw.c (stream_read): Made cancellable. + (stream_write): Same. + (stream_connect): Removed checks for DIVINE_INTERVENTION as the + code worked fine. + + * camel-tcp-stream-ssl.c (stream_write): get rid of 'w' as it + wasn't really needed. + (set_errno): New function to set errno based on the NSPR error + code. + (stream_read): If an error occured, call set_errno(). + (stream_write): Same. + +2001-03-13 Jeffrey Stedfast <fejj@ximian.com> + * Makefile.am: Added camel-tcp-stream-ssl to the build. * camel-remote-store.h: Add a use_ssl member to the diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c index bc9223a267..fcf087fbd8 100644 --- a/camel/camel-tcp-stream-raw.c +++ b/camel/camel-tcp-stream-raw.c @@ -125,10 +125,40 @@ stream_read (CamelStream *stream, char *buffer, size_t n) { CamelTcpStreamRaw *tcp_stream_raw = CAMEL_TCP_STREAM_RAW (stream); ssize_t nread; + int cancel_fd; + + if (camel_operation_cancel_check (NULL)) { + errno = EINTR; + return -1; + } - do { + cancel_fd = camel_operation_cancel_fd (NULL); + if (cancel_fd == -1) { + do { + nread = read (tcp_stream_raw->sockfd, buffer, n); + } while (nread == -1 && errno == EINTR); + } else { + int flags, fdmax; + fd_set rdset; + + flags = fcntl (tcp_stream_raw->sockfd, F_GETFL); + fcntl (tcp_stream_raw->sockfd, F_SETFL, flags | O_NONBLOCK); + + FD_ZERO (&rdset); + FD_SET (tcp_stream_raw->sockfd, &rdset); + FD_SET (cancel_fd, &rdset); + fdmax = MAX (tcp_stream_raw->sockfd, cancel_fd) + 1; + + select (fdmax, &rdset, 0, 0, NULL); + if (FD_ISSET (cancel_fd, &rdset)) { + fcntl (tcp_stream_raw->sockfd, F_SETFL, flags); + errno = EINTR; + return -1; + } + nread = read (tcp_stream_raw->sockfd, buffer, n); - } while (nread == -1 && errno == EINTR); + fcntl (tcp_stream_raw->sockfd, F_SETFL, flags); + } return nread; } @@ -137,18 +167,49 @@ static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n) { CamelTcpStreamRaw *tcp_stream_raw = CAMEL_TCP_STREAM_RAW (stream); - ssize_t v, written = 0; + ssize_t w, written = 0; + int cancel_fd; - do { - v = write (tcp_stream_raw->sockfd, buffer, n); - if (v > 0) - written += v; - } while (v == -1 && errno == EINTR); + if (camel_operation_cancel_check (NULL)) { + errno = EINTR; + return -1; + } - if (v == -1) - return -1; - else - return written; + cancel_fd = camel_operation_cancel_fd (NULL); + if (cancel_fd == -1) { + do { + written = write (tcp_stream_raw->sockfd, buffer, n); + } while (written == -1 && errno == EINTR); + } else { + fd_set rdset, wrset; + int flags, fdmax; + + flags = fcntl (tcp_stream_raw->sockfd, F_GETFL); + fcntl (tcp_stream_raw->sockfd, F_SETFL, flags | O_NONBLOCK); + + fdmax = MAX (tcp_stream_raw->sockfd, cancel_fd) + 1; + do { + FD_ZERO (&rdset); + FD_ZERO (&wrset); + FD_SET (tcp_stream_raw->sockfd, &wrset); + FD_SET (cancel_fd, &rdset); + + select (fdmax, &rdset, &wrset, 0, NULL); + if (FD_ISSET (cancel_fd, &rdset)) { + fcntl (tcp_stream_raw->sockfd, F_SETFL, flags); + errno = EINTR; + return -1; + } + + w = write (tcp_stream_raw->sockfd, buffer + written, n - written); + if (w > 0) + written += w; + } while (w != -1 && written < n); + + fcntl (tcp_stream_raw->sockfd, F_SETFL, flags); + } + + return written; } static int @@ -258,44 +319,23 @@ socket_connect (struct hostent *h, int port) return fd; } -#define DIVINE_INTERVENTION static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port) { CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); -#ifndef DIVINE_INTERVENTION - struct sockaddr_in sin; -#endif int fd; g_return_val_if_fail (host != NULL, -1); -#ifdef DIVINE_INTERVENTION fd = socket_connect (host, port); if (fd == -1) return -1; -#else - sin.sin_family = host->h_addrtype; - sin.sin_port = htons (port); - - memcpy (&sin.sin_addr, host->h_addr, sizeof (sin.sin_addr)); - - fd = socket (host->h_addrtype, SOCK_STREAM, 0); - - if (fd == -1 || connect (fd, (struct sockaddr *)&sin, sizeof (sin)) == -1) { - if (fd > -1) - close (fd); - - return -1; - } -#endif raw->sockfd = fd; return 0; } - static int get_sockopt_level (const CamelSockOptData *data) { diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c index 15b907845a..8d4ac47746 100644 --- a/camel/camel-tcp-stream-ssl.c +++ b/camel/camel-tcp-stream-ssl.c @@ -142,6 +142,23 @@ camel_tcp_stream_ssl_new (CamelSession *session, const char *expected_host) return CAMEL_STREAM (stream); } +static void +set_errno (int code) +{ + /* FIXME: this should handle more. */ + switch (code) { + case PR_IO_TIMEOUT_ERROR: + errno = EAGAIN; + break; + case PR_IO_ERROR: + errno = EIO; + break; + default: + /* what to set by default?? */ + errno = EINTR; + } +} + static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n) { @@ -152,6 +169,9 @@ stream_read (CamelStream *stream, char *buffer, size_t n) nread = PR_Read (tcp_stream_ssl->sockfd, buffer, n); } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); + if (nread == -1) + set_errno (PR_GetError ()); + return nread; } @@ -159,18 +179,16 @@ static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n) { CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); - ssize_t w, written = 0; + ssize_t written; do { - w = PR_Write (tcp_stream_ssl->sockfd, buffer, n); - if (w > 0) - written += w; - } while (w == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); + written = PR_Write (tcp_stream_ssl->sockfd, buffer, n); + } while (written == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); - if (w == -1) - return -1; - else - return written; + if (written == -1) + set_errno (PR_GetError ()); + + return written; } static int |