aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog27
-rw-r--r--camel/camel-remote-store.c11
-rw-r--r--camel/camel-stream-buffer.c10
-rw-r--r--camel/camel-stream-buffer.h4
-rw-r--r--camel/camel-tcp-stream-openssl.c110
-rw-r--r--camel/camel-tcp-stream-ssl.c35
6 files changed, 110 insertions, 87 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index fbf87612d3..0659ce16e3 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,30 @@
+2001-10-29 Jeffrey Stedfast <fejj@ximian.com>
+
+ * camel-tcp-stream-openssl.c (my_SSL_write): Removed.
+ (stream_write): Keep looping (non-blocking case) if errno is
+ EAGAIN, EINTR or EWOULDBLOCK. For NONBLOCKing I/O, sync up with
+ CamelTcpStreamRaw. As with CamelTcpStreamRaw/SSL - make sure to
+ write out everything before returning.
+ (my_SSL_read): Removed.
+ (stream_read): Just call ssl_error_to_errno() and check the errno
+ values that we care about so we can keep the general look of all
+ this stream code the same. Also when checking the return value of
+ SSL_read, check for <0 instead of ==-1 since the man page for
+ SSL_read doesn't say it will return -1 on fail, it just says <0.
+ (stream_flush): Don't fsync() since syncing on a socket is a Bad
+ Thing (tm).
+
+ * camel-tcp-stream-ssl.c (stream_write): Make sure we write out
+ everything just like in camel-tcp-stream-raw.c.
+
+ * camel-stream-buffer.c (camel_stream_buffer_gets): If
+ camel_stream_read() returns -1, don't necessarily return -1 to our
+ caller since it's possible that we did actually "read" some data
+ (ie, we copied some pre-buffered data into the out buffer).
+
+ * camel-stream-buffer.h: Removed CAMEL_STREAM_BUFFER_NEWLINE since
+ it never got used anywhere and it isn't supported anyway.
+
2001-10-30 <NotZed@Ximian.com>
* providers/imap/camel-imap-store.c
diff --git a/camel/camel-remote-store.c b/camel/camel-remote-store.c
index 4148a72c7f..8c299cec0c 100644
--- a/camel/camel-remote-store.c
+++ b/camel/camel-remote-store.c
@@ -458,7 +458,6 @@ static int
remote_recv_line (CamelRemoteStore *store, char **dest, CamelException *ex)
{
CamelStreamBuffer *stream;
- CamelException internal_ex;
char *buf;
*dest = NULL;
@@ -477,18 +476,14 @@ remote_recv_line (CamelRemoteStore *store, char **dest, CamelException *ex)
buf = camel_stream_buffer_read_line (stream);
- camel_exception_init (&internal_ex);
if (buf == NULL) {
if (errno == EINTR)
- camel_exception_set (&internal_ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
+ camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
else
- camel_exception_setv (&internal_ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Server unexpectedly disconnected: %s"),
g_strerror (errno));
- }
-
- if (camel_exception_is_set (&internal_ex)) {
- camel_exception_xfer (ex, &internal_ex);
+
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
return -1;
}
diff --git a/camel/camel-stream-buffer.c b/camel/camel-stream-buffer.c
index 3d7ac5e845..fe3458a93f 100644
--- a/camel/camel-stream-buffer.c
+++ b/camel/camel-stream-buffer.c
@@ -401,9 +401,13 @@ int camel_stream_buffer_gets(CamelStreamBuffer *sbf, char *buf, unsigned int max
if (outptr == outend)
break;
- bytes_read = camel_stream_read(sbf->stream, sbf->buf, sbf->size);
- if (bytes_read == -1)
- return -1;
+ bytes_read = camel_stream_read (sbf->stream, sbf->buf, sbf->size);
+ if (bytes_read == -1) {
+ if (buf == outptr)
+ return -1;
+ else
+ bytes_read = 0;
+ }
inptr = sbf->ptr = sbf->buf;
inend = sbf->end = sbf->buf + bytes_read;
} while (bytes_read>0);
diff --git a/camel/camel-stream-buffer.h b/camel/camel-stream-buffer.h
index db93971fd2..03a8517066 100644
--- a/camel/camel-stream-buffer.h
+++ b/camel/camel-stream-buffer.h
@@ -41,10 +41,8 @@ extern "C" {
#define CAMEL_STREAM_BUFFER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_STREAM_BUFFER_TYPE, CamelStreamBufferClass))
#define CAMEL_IS_STREAM_BUFFER(o) (CAMEL_CHECK_TYPE((o), CAMEL_STREAM_BUFFER_TYPE))
-typedef enum
-{
+typedef enum {
CAMEL_STREAM_BUFFER_BUFFER = 0,
- CAMEL_STREAM_BUFFER_NEWLINE,
CAMEL_STREAM_BUFFER_NONE,
CAMEL_STREAM_BUFFER_READ = 0x00,
CAMEL_STREAM_BUFFER_WRITE = 0x80,
diff --git a/camel/camel-tcp-stream-openssl.c b/camel/camel-tcp-stream-openssl.c
index 6e94b29487..17d5ab0961 100644
--- a/camel/camel-tcp-stream-openssl.c
+++ b/camel/camel-tcp-stream-openssl.c
@@ -176,8 +176,8 @@ errlib_error_to_errno (int ret)
if (error == 0) {
if (ret == 0)
errno = EINVAL; /* unexpected EOF */
- /* otherwise errno should be set */
- } else {
+ errno = 0;
+ } else if (!errno) {
/* ok, we get the shaft now. */
errno = EINTR;
}
@@ -210,22 +210,11 @@ ssl_error_to_errno (SSL *ssl, int ret)
}
}
-static int
-my_SSL_read (SSL *ssl, void *buf, int num)
-{
- int ret;
-
- do
- ret = SSL_read (ssl, buf, num);
- while (ret < 0 && (SSL_get_error (ssl, ret) == SSL_ERROR_WANT_READ ||
- SSL_get_error (ssl, ret) == SSL_ERROR_WANT_WRITE));
- return ret;
-}
-
static ssize_t
stream_read (CamelStream *stream, char *buffer, size_t n)
{
CamelTcpStreamOpenSSL *tcp_stream_openssl = CAMEL_TCP_STREAM_OPENSSL (stream);
+ SSL *ssl = tcp_stream_openssl->priv->ssl;
ssize_t nread;
int cancel_fd;
@@ -237,8 +226,10 @@ stream_read (CamelStream *stream, char *buffer, size_t n)
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
do {
- nread = my_SSL_read (tcp_stream_openssl->priv->ssl, buffer, n);
- } while (nread == -1 && errno == EINTR);
+ nread = SSL_read (ssl, buffer, n);
+ if (nread < 0)
+ ssl_error_to_errno (ssl, nread);
+ } while (nread < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
} else {
int flags, fdmax;
fd_set rdset;
@@ -247,51 +238,36 @@ stream_read (CamelStream *stream, char *buffer, size_t n)
fcntl (tcp_stream_openssl->priv->sockfd, F_SETFL, flags | O_NONBLOCK);
do {
- nread = my_SSL_read (tcp_stream_openssl->priv->ssl, buffer, n);
-
- if (nread == 0)
- return nread;
+ FD_ZERO (&rdset);
+ FD_SET (tcp_stream_openssl->priv->sockfd, &rdset);
+ FD_SET (cancel_fd, &rdset);
+ fdmax = MAX (tcp_stream_openssl->priv->sockfd, cancel_fd) + 1;
- if (nread == -1 && errno == EAGAIN) {
- FD_ZERO (&rdset);
- FD_SET (tcp_stream_openssl->priv->sockfd, &rdset);
- FD_SET (cancel_fd, &rdset);
- fdmax = MAX (tcp_stream_openssl->priv->sockfd, cancel_fd) + 1;
-
- select (fdmax, &rdset, 0, 0, NULL);
- if (FD_ISSET (cancel_fd, &rdset)) {
- fcntl (tcp_stream_openssl->priv->sockfd, F_SETFL, flags);
- errno = EINTR;
- return -1;
- }
+ select (fdmax, &rdset, 0, 0, NULL);
+ if (FD_ISSET (cancel_fd, &rdset)) {
+ fcntl (tcp_stream_openssl->priv->sockfd, F_SETFL, flags);
+ errno = EINTR;
+ return -1;
}
- } while (nread == -1 && errno == EAGAIN);
+
+ do {
+ nread = SSL_read (ssl, buffer, n);
+ if (nread < 0)
+ ssl_error_to_errno (ssl, nread);
+ } while (nread < 0 && errno == EINTR);
+ } while (nread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK));
fcntl (tcp_stream_openssl->priv->sockfd, F_SETFL, flags);
}
- if (nread == -1)
- ssl_error_to_errno (tcp_stream_openssl->priv->ssl, -1);
-
return nread;
}
-static int
-my_SSL_write (SSL *ssl, const void *buf, int num)
-{
- int ret;
-
- do
- ret = SSL_write (ssl, buf, num);
- while (ret < 0 && (SSL_get_error (ssl, ret) == SSL_ERROR_WANT_READ ||
- SSL_get_error (ssl, ret) == SSL_ERROR_WANT_WRITE));
- return ret;
-}
-
static ssize_t
stream_write (CamelStream *stream, const char *buffer, size_t n)
{
CamelTcpStreamOpenSSL *tcp_stream_openssl = CAMEL_TCP_STREAM_OPENSSL (stream);
+ SSL *ssl = tcp_stream_openssl->priv->ssl;
ssize_t w, written = 0;
int cancel_fd;
@@ -303,8 +279,15 @@ stream_write (CamelStream *stream, const char *buffer, size_t n)
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
do {
- written = my_SSL_write (tcp_stream_openssl->priv->ssl, buffer, n);
- } while (written == -1 && errno == EINTR);
+ do {
+ w = SSL_write (ssl, buffer + written, n - written);
+ if (w < 0)
+ ssl_error_to_errno (SSL_get_error (ssl, w));
+ } while (w < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
+
+ if (w > 0)
+ written += w;
+ } while (w != -1 && written < n);
} else {
fd_set rdset, wrset;
int flags, fdmax;
@@ -326,26 +309,35 @@ stream_write (CamelStream *stream, const char *buffer, size_t n)
return -1;
}
- w = my_SSL_write (tcp_stream_openssl->priv->ssl, buffer + written, n - written);
- if (w > 0)
+ do {
+ w = SSL_write (ssl, buffer + written, n - written);
+ if (w < 0)
+ ssl_error_to_errno (ssl, w);
+ } while (w < 0 && errno == EINTR);
+
+ if (w < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ w = 0;
+ } else {
+ error = errno;
+ fcntl (tcp_stream_raw->sockfd, F_SETFL, flags);
+ errno = error;
+ return -1;
+ }
+ } else
written += w;
- } while (w != -1 && written < n);
+ } while (w >= 0 && written < n);
fcntl (tcp_stream_openssl->priv->sockfd, F_SETFL, flags);
- if (w == -1)
- written = -1;
}
- if (written == -1)
- ssl_error_to_errno (tcp_stream_openssl->priv->ssl, -1);
-
return written;
}
static int
stream_flush (CamelStream *stream)
{
- return fsync (((CamelTcpStreamOpenSSL *)stream)->priv->sockfd);
+ return 0;
}
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index 4b1ac726f8..9adf49837a 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -159,15 +159,20 @@ set_errno (int code)
{
/* FIXME: this should handle more. */
switch (code) {
+ case PR_PENDING_INTERRUPT_ERROR:
+ errno = EINTR;
+ break;
+ case PR_IO_PENDING_ERROR:
case PR_IO_TIMEOUT_ERROR:
errno = EAGAIN;
break;
+ case PR_WOULD_BLOCK_ERROR:
+ errno = EWOULDBLOCK;
+ break;
case PR_IO_ERROR:
+ default:
errno = EIO;
break;
- default:
- /* what to set by default?? */
- errno = EINTR;
}
}
@@ -179,10 +184,9 @@ stream_read (CamelStream *stream, char *buffer, size_t n)
do {
nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n);
- } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
-
- if (nread == -1)
- set_errno (PR_GetError ());
+ if (nread == -1)
+ set_errno (PR_GetError ());
+ } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
return nread;
}
@@ -191,14 +195,18 @@ static ssize_t
stream_write (CamelStream *stream, const char *buffer, size_t n)
{
CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream);
- ssize_t written = 0;
+ ssize_t w, written = 0;
do {
- written = PR_Write (tcp_stream_ssl->priv->sockfd, buffer, n);
- } while (written == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
-
- if (written == -1)
- set_errno (PR_GetError ());
+ do {
+ w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written);
+ if (w == -1)
+ set_errno (PR_GetError ());
+ } while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
+
+ if (w > 0)
+ written += w;
+ } while (w != -1 && written < n);
return written;
}
@@ -367,7 +375,6 @@ ssl_cert_is_saved (const char *certid)
{
char *filename;
struct stat st;
- int ret;
filename = g_strdup_printf ("%s/.camel_certs/%s", getenv ("HOME"), certid);