aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-tcp-stream-raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-tcp-stream-raw.c')
-rw-r--r--camel/camel-tcp-stream-raw.c106
1 files changed, 73 insertions, 33 deletions
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)
{