aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog14
-rw-r--r--camel/camel-tcp-stream-raw.c106
-rw-r--r--camel/camel-tcp-stream-ssl.c36
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