diff options
author | Jeffrey Stedfast <fejj@ximian.com> | 2002-11-23 06:29:56 +0800 |
---|---|---|
committer | Jeffrey Stedfast <fejj@src.gnome.org> | 2002-11-23 06:29:56 +0800 |
commit | eaa2814a05c8c3a094a00400cc5651e408ee9e18 (patch) | |
tree | 4a53b01741ec0655bd6499123263716b74d98e0e /camel/camel-tcp-stream-ssl.c | |
parent | 554b987da7d9579b23a62c50f95b8305e1c5a72c (diff) | |
download | gsoc2013-evolution-eaa2814a05c8c3a094a00400cc5651e408ee9e18.tar.gz gsoc2013-evolution-eaa2814a05c8c3a094a00400cc5651e408ee9e18.tar.zst gsoc2013-evolution-eaa2814a05c8c3a094a00400cc5651e408ee9e18.zip |
Use the new camel_operation_cancel_prfd() function to get the cancellation
2002-11-21 Jeffrey Stedfast <fejj@ximian.com>
* camel-tcp-stream-ssl.c (stream_read): Use the new
camel_operation_cancel_prfd() function to get the cancellation fd
so we can poll on it for cancellation stuff.
(stream_write): Same.
2002-11-22 Not Zed <NotZed@Ximian.com>
* camel-operation.c (camel_operation_cancel_prfd): Implement, gets
a nspr pr filedesc to poll/wait on
(struct _CamelOperation): include a pr filedesc.
svn path=/trunk/; revision=18894
Diffstat (limited to 'camel/camel-tcp-stream-ssl.c')
-rw-r--r-- | camel/camel-tcp-stream-ssl.c | 165 |
1 files changed, 145 insertions, 20 deletions
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c index 3aa841d9df..b20b6d255e 100644 --- a/camel/camel-tcp-stream-ssl.c +++ b/camel/camel-tcp-stream-ssl.c @@ -299,18 +299,71 @@ static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n) { CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); + PRFileDesc *cancel_fd; ssize_t nread; - do { - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } + if (camel_operation_cancel_check (NULL)) { + errno = EINTR; + return -1; + } + + cancel_fd = camel_operation_cancel_prfd (NULL); + if (cancel_fd == NULL) { + do { + nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); + if (nread == -1) + set_errno (PR_GetError ()); + } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); + } else { + PRSocketOptionData sockopts; + PRPollDesc pollfds[2]; + gboolean nonblock; + int error; - nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); - if (nread == -1) - set_errno (PR_GetError ()); - } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); + /* get O_NONBLOCK options */ + sockopts.option = PR_SockOpt_Nonblocking; + PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); + sockopts.option = PR_SockOpt_Nonblocking; + 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 { + 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; + } + + 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 */ + error = errno; + sockopts.option = PR_SockOpt_Nonblocking; + sockopts.value.non_blocking = nonblock; + PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); + errno = error; + } return nread; } @@ -320,22 +373,94 @@ stream_write (CamelStream *stream, const char *buffer, size_t n) { CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); ssize_t w, written = 0; + PRFileDesc *cancel_fd; - do { - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } + if (camel_operation_cancel_check (NULL)) { + errno = EINTR; + return -1; + } + + cancel_fd = camel_operation_cancel_prfd (NULL); + if (cancel_fd == NULL) { + do { + 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); + } else { + PRSocketOptionData sockopts; + PRPollDesc pollfds[2]; + gboolean nonblock; + int error; + + /* get O_NONBLOCK options */ + sockopts.option = PR_SockOpt_Nonblocking; + PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); + sockopts.option = PR_SockOpt_Nonblocking; + 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_WRITE; + pollfds[1].fd = cancel_fd; + pollfds[1].in_flags = PR_POLL_READ; do { - w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); - if (w == -1) + 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; + } + + 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); + + if (w == -1) { + 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 ()); - } while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); + if (errno == EINTR) + w = 0; + } + } while (w != -1 && written < n); - if (w > 0) - written += w; - } while (w != -1 && written < n); + /* restore O_NONBLOCK options */ + error = errno; + sockopts.option = PR_SockOpt_Nonblocking; + sockopts.value.non_blocking = nonblock; + PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); + errno = error; + } + + if (w == -1) + return -1; return written; } |