[evolution-data-server/camel-socks-proxy-master] Make CamelTcpStreamRaw use PRFileDesc internally
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/camel-socks-proxy-master] Make CamelTcpStreamRaw use PRFileDesc internally
- Date: Wed, 28 Jul 2010 21:42:30 +0000 (UTC)
commit 5dde3619daf23df166777cec6fb48b652dbf7cab
Author: Federico Mena Quintero <federico novell com>
Date: Thu Jul 15 15:03:25 2010 -0500
Make CamelTcpStreamRaw use PRFileDesc internally
This is cut&pasted from CamelTcpStreamSSL, with the SSL bits removed.
This will let us make CamelTcpStreamSSL actually derive from
CamelTcpStreamRaw and just slap the SSL bits on top.
This also removes camel_tcp_stream_raw_get_fd(), in favor of the general
camel_tcp_stream_get_file_desc(), which only the imapx provider uses.
Signed-off-by: Federico Mena Quintero <federico novell com>
camel/camel-tcp-stream-raw.c | 682 +++++++++++++++++++++-------
camel/camel-tcp-stream-raw.h | 2 -
camel/providers/imapx/camel-imapx-server.c | 53 +--
camel/providers/imapx/camel-imapx-server.h | 1 -
4 files changed, 522 insertions(+), 216 deletions(-)
---
diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c
index ad2ca1d..4b5a6fe 100644
--- a/camel/camel-tcp-stream-raw.c
+++ b/camel/camel-tcp-stream-raw.c
@@ -32,36 +32,24 @@
#include <sys/time.h>
#include <sys/types.h>
+#include <nspr.h>
+#include <prio.h>
+#include <prerror.h>
+#include <prerr.h>
+
#include "camel-file-utils.h"
#include "camel-net-utils.h"
#include "camel-operation.h"
#include "camel-tcp-stream-raw.h"
-typedef struct _CamelTcpStreamRawPrivate {
- gint sockfd;
-#ifdef G_OS_WIN32
- gint is_nonblocking;
-#endif
-} CamelTcpStreamRawPrivate;
+#define d(x)
-#ifndef G_OS_WIN32
-#define SOCKET_ERROR_CODE() errno
-#define SOCKET_CLOSE(fd) close (fd)
-#define SOCKET_ERROR_IS_EINPROGRESS() (errno == EINPROGRESS)
-#define SOCKET_ERROR_IS_EINTR() (errno == EINTR)
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#define SOCKET_ERROR_CODE() WSAGetLastError ()
-#define SOCKET_CLOSE(fd) closesocket (fd)
-#define SOCKET_ERROR_IS_EINPROGRESS() (WSAGetLastError () == WSAEWOULDBLOCK)
-#define SOCKET_ERROR_IS_EINTR() 0 /* No WSAEINTR in WinSock2 */
+#define IO_TIMEOUT (PR_TicksPerSecond() * 4 * 60)
+#define CONNECT_TIMEOUT (PR_TicksPerSecond () * 4 * 60)
-#ifdef ETIMEDOUT
-#undef ETIMEDOUT
-#endif
-#define ETIMEDOUT EAGAIN
-#endif
+typedef struct _CamelTcpStreamRawPrivate {
+ PRFileDesc *sockfd;
+} CamelTcpStreamRawPrivate;
G_DEFINE_TYPE (CamelTcpStreamRaw, camel_tcp_stream_raw, CAMEL_TYPE_TCP_STREAM)
@@ -166,47 +154,6 @@ flaky_tcp_read (gint fd, gchar *buffer, gsize buflen)
#endif /* SIMULATE_FLAKY_NETWORK */
-static gint
-get_sockopt_level (const CamelSockOptData *data)
-{
- switch (data->option) {
- case CAMEL_SOCKOPT_MAXSEGMENT:
- case CAMEL_SOCKOPT_NODELAY:
- return IPPROTO_TCP;
- default:
- return SOL_SOCKET;
- }
-}
-
-static gint
-get_sockopt_optname (const CamelSockOptData *data)
-{
- switch (data->option) {
-#ifdef TCP_MAXSEG
- case CAMEL_SOCKOPT_MAXSEGMENT:
- return TCP_MAXSEG;
-#endif
- case CAMEL_SOCKOPT_NODELAY:
- return TCP_NODELAY;
- case CAMEL_SOCKOPT_BROADCAST:
- return SO_BROADCAST;
- case CAMEL_SOCKOPT_KEEPALIVE:
- return SO_KEEPALIVE;
- case CAMEL_SOCKOPT_LINGER:
- return SO_LINGER;
- case CAMEL_SOCKOPT_RECVBUFFERSIZE:
- return SO_RCVBUF;
- case CAMEL_SOCKOPT_SENDBUFFERSIZE:
- return SO_SNDBUF;
- case CAMEL_SOCKOPT_REUSEADDR:
- return SO_REUSEADDR;
- case CAMEL_SOCKOPT_IPTYPEOFSERVICE:
- return SO_TYPE;
- default:
- return -1;
- }
-}
-
/* this is a 'cancellable' connect, cancellable from camel_operation_cancel etc */
/* returns -1 & errno == EINTR if the connection was cancelled */
static gint
@@ -338,13 +285,179 @@ tcp_stream_raw_finalize (GObject *object)
CamelTcpStreamRaw *stream = CAMEL_TCP_STREAM_RAW (object);
CamelTcpStreamRawPrivate *priv = stream->priv;
- if (priv->sockfd != -1)
- SOCKET_CLOSE (priv->sockfd);
+ if (priv->sockfd != NULL) {
+ PR_Shutdown (priv->sockfd, PR_SHUTDOWN_BOTH);
+ PR_Close (priv->sockfd);
+ }
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (camel_tcp_stream_raw_parent_class)->finalize (object);
}
+static void
+set_errno (gint code)
+{
+ /* FIXME: this should handle more. */
+ switch (code) {
+ case PR_INVALID_ARGUMENT_ERROR:
+ errno = EINVAL;
+ break;
+ case PR_PENDING_INTERRUPT_ERROR:
+ errno = EINTR;
+ break;
+ case PR_IO_PENDING_ERROR:
+ errno = EAGAIN;
+ break;
+#ifdef EWOULDBLOCK
+ case PR_WOULD_BLOCK_ERROR:
+ errno = EWOULDBLOCK;
+ break;
+#endif
+#ifdef EINPROGRESS
+ case PR_IN_PROGRESS_ERROR:
+ errno = EINPROGRESS;
+ break;
+#endif
+#ifdef EALREADY
+ case PR_ALREADY_INITIATED_ERROR:
+ errno = EALREADY;
+ break;
+#endif
+#ifdef EHOSTUNREACH
+ case PR_NETWORK_UNREACHABLE_ERROR:
+ errno = EHOSTUNREACH;
+ break;
+#endif
+#ifdef ECONNREFUSED
+ case PR_CONNECT_REFUSED_ERROR:
+ errno = ECONNREFUSED;
+ break;
+#endif
+#ifdef ETIMEDOUT
+ case PR_CONNECT_TIMEOUT_ERROR:
+ case PR_IO_TIMEOUT_ERROR:
+ errno = ETIMEDOUT;
+ break;
+#endif
+#ifdef ENOTCONN
+ case PR_NOT_CONNECTED_ERROR:
+ errno = ENOTCONN;
+ break;
+#endif
+#ifdef ECONNRESET
+ case PR_CONNECT_RESET_ERROR:
+ errno = ECONNRESET;
+ break;
+#endif
+ case PR_IO_ERROR:
+ default:
+ errno = EIO;
+ break;
+ }
+}
+
+static void
+set_g_error_from_errno (GError *error, gboolean eintr_means_cancelled)
+{
+ /* This is stolen from camel_read() / camel_write() */
+ if (eintr_means_cancelled && errno == EINTR)
+ g_set_error (
+ error, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Cancelled"));
+ else
+ g_set_error (
+ error, G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ "%s", g_strerror (errno));
+}
+
+static gssize
+read_from_prfd (PRFileDesc *fd, gchar *buffer, gsize n, GError **error)
+{
+ PRFileDesc *cancel_fd;
+ gssize nread;
+
+ if (camel_operation_cancel_check (NULL)) {
+ errno = EINTR;
+ set_g_error_from_errno (error, TRUE);
+ return -1;
+ }
+
+ cancel_fd = camel_operation_cancel_prfd (NULL);
+ if (cancel_fd == NULL) {
+ do {
+ nread = PR_Read (fd, buffer, n);
+ if (nread == -1)
+ set_errno (PR_GetError ());
+ } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
+ PR_GetError () == PR_IO_PENDING_ERROR ||
+ PR_GetError () == PR_WOULD_BLOCK_ERROR));
+ } else {
+ PRSocketOptionData sockopts;
+ PRPollDesc pollfds[2];
+ gboolean nonblock;
+ gint error;
+
+ /* get O_NONBLOCK options */
+ sockopts.option = PR_SockOpt_Nonblocking;
+ PR_GetSocketOption (fd, &sockopts);
+ sockopts.option = PR_SockOpt_Nonblocking;
+ nonblock = sockopts.value.non_blocking;
+ sockopts.value.non_blocking = TRUE;
+ PR_SetSocketOption (fd, &sockopts);
+
+ pollfds[0].fd = fd;
+ pollfds[0].in_flags = PR_POLL_READ;
+ pollfds[1].fd = cancel_fd;
+ pollfds[1].in_flags = PR_POLL_READ;
+
+ do {
+ PRInt32 res;
+
+ pollfds[0].out_flags = 0;
+ pollfds[1].out_flags = 0;
+ nread = -1;
+
+ res = PR_Poll(pollfds, 2, IO_TIMEOUT);
+ if (res == -1)
+ set_errno(PR_GetError());
+ else if (res == 0) {
+#ifdef ETIMEDOUT
+ errno = ETIMEDOUT;
+#else
+ errno = EIO;
+#endif
+ goto failed;
+ } else if (pollfds[1].out_flags == PR_POLL_READ) {
+ errno = EINTR;
+ goto failed;
+ } else {
+ do {
+ nread = PR_Read (fd, buffer, n);
+ if (nread == -1)
+ set_errno (PR_GetError ());
+ } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
+ }
+ } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
+ PR_GetError () == PR_IO_PENDING_ERROR ||
+ PR_GetError () == PR_WOULD_BLOCK_ERROR));
+
+ /* restore O_NONBLOCK options */
+ failed:
+ error = errno;
+ sockopts.option = PR_SockOpt_Nonblocking;
+ sockopts.value.non_blocking = nonblock;
+ PR_SetSocketOption (fd, &sockopts);
+ errno = error;
+ }
+
+ if (nread == -1)
+ set_g_error_from_errno (error, TRUE);
+
+ return nread;
+}
+
static gssize
tcp_stream_raw_read (CamelStream *stream,
gchar *buffer,
@@ -354,7 +467,102 @@ tcp_stream_raw_read (CamelStream *stream,
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
CamelTcpStreamRawPrivate *priv = raw->priv;
- return camel_read_socket (priv->sockfd, buffer, n, error);
+ return read_from_prfd (priv->sockfd, buffer, n, error);
+}
+
+static gssize
+write_to_prfd (PRFileDesc *fd, const gchar *buffer, gsize n, GError **error)
+{
+ gssize w, written = 0;
+ PRFileDesc *cancel_fd;
+
+ if (camel_operation_cancel_check (NULL)) {
+ errno = EINTR;
+ set_g_error_from_errno (error, TRUE);
+ return -1;
+ }
+
+ cancel_fd = camel_operation_cancel_prfd (NULL);
+ if (cancel_fd == NULL) {
+ do {
+ do {
+ w = PR_Write (fd, buffer + written, n - written);
+ if (w == -1)
+ set_errno (PR_GetError ());
+ } while (w == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
+ PR_GetError () == PR_IO_PENDING_ERROR ||
+ PR_GetError () == PR_WOULD_BLOCK_ERROR));
+
+ if (w > 0)
+ written += w;
+ } while (w != -1 && written < n);
+ } else {
+ PRSocketOptionData sockopts;
+ PRPollDesc pollfds[2];
+ gboolean nonblock;
+ gint error;
+
+ /* get O_NONBLOCK options */
+ sockopts.option = PR_SockOpt_Nonblocking;
+ PR_GetSocketOption (fd, &sockopts);
+ sockopts.option = PR_SockOpt_Nonblocking;
+ nonblock = sockopts.value.non_blocking;
+ sockopts.value.non_blocking = TRUE;
+ PR_SetSocketOption (fd, &sockopts);
+
+ pollfds[0].fd = fd;
+ pollfds[0].in_flags = PR_POLL_WRITE;
+ pollfds[1].fd = cancel_fd;
+ pollfds[1].in_flags = PR_POLL_READ;
+
+ do {
+ PRInt32 res;
+
+ pollfds[0].out_flags = 0;
+ pollfds[1].out_flags = 0;
+ w = -1;
+
+ res = PR_Poll (pollfds, 2, IO_TIMEOUT);
+ if (res == -1) {
+ set_errno(PR_GetError());
+ if (PR_GetError () == PR_PENDING_INTERRUPT_ERROR)
+ w = 0;
+ } else if (res == 0) {
+#ifdef ETIMEDOUT
+ errno = ETIMEDOUT;
+#else
+ errno = EIO;
+#endif
+ } else if (pollfds[1].out_flags == PR_POLL_READ) {
+ errno = EINTR;
+ } else {
+ do {
+ w = PR_Write (fd, buffer + written, n - written);
+ if (w == -1)
+ set_errno (PR_GetError ());
+ } while (w == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
+
+ if (w == -1) {
+ if (PR_GetError () == PR_IO_PENDING_ERROR ||
+ PR_GetError () == PR_WOULD_BLOCK_ERROR)
+ w = 0;
+ } else
+ 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 (fd, &sockopts);
+ errno = error;
+ }
+
+ if (w == -1)
+ set_g_error_from_errno (error, TRUE);
+
+ return written;
}
static gssize
@@ -366,13 +574,19 @@ tcp_stream_raw_write (CamelStream *stream,
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
CamelTcpStreamRawPrivate *priv = raw->priv;
- return camel_write_socket (priv->sockfd, buffer, n, error);
+ return write_to_prfd (priv->sockfd, buffer, n, error);
}
static gint
tcp_stream_raw_flush (CamelStream *stream,
GError **error)
{
+#if 0
+ CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
+ CamelTcpStreamRawPrivate *priv = raw->priv;
+
+ return PR_Sync (priv->sockfd);
+#endif
return 0;
}
@@ -383,28 +597,156 @@ tcp_stream_raw_close (CamelStream *stream,
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
CamelTcpStreamRawPrivate *priv = raw->priv;
- if (SOCKET_CLOSE (priv->sockfd) == -1) {
- g_set_error (
- error, G_IO_ERROR,
- g_io_error_from_errno (errno),
- "%s", g_strerror (errno));
- return -1;
+ if (priv->sockfd == NULL)
+ errno = EINVAL;
+ else {
+ gboolean err;
+
+ PR_Shutdown (priv->sockfd, PR_SHUTDOWN_BOTH);
+
+ err = (PR_Close (priv->sockfd) == PR_FAILURE);
+ priv->sockfd = NULL;
+
+ if (err)
+ set_errno (PR_GetError());
+ else
+ return 0;
}
- priv->sockfd = -1;
- return 0;
+ set_g_error_from_errno (error, FALSE);
+ return -1;
+}
+
+static gint
+sockaddr_to_praddr (struct sockaddr *s, gint len, PRNetAddr *addr)
+{
+ /* We assume the ip addresses are the same size - they have to be anyway.
+ We could probably just use memcpy *shrug* */
+
+ memset(addr, 0, sizeof(*addr));
+
+ if (s->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)s;
+
+ if (len < sizeof(*sin))
+ return -1;
+
+ addr->inet.family = PR_AF_INET;
+ addr->inet.port = sin->sin_port;
+ memcpy(&addr->inet.ip, &sin->sin_addr, sizeof(addr->inet.ip));
+
+ return 0;
+ }
+#ifdef ENABLE_IPv6
+ else if (s->sa_family == PR_AF_INET6) {
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *)s;
+
+ if (len < sizeof(*sin))
+ return -1;
+
+ addr->ipv6.family = PR_AF_INET6;
+ addr->ipv6.port = sin->sin6_port;
+ addr->ipv6.flowinfo = sin->sin6_flowinfo;
+ memcpy(&addr->ipv6.ip, &sin->sin6_addr, sizeof(addr->ipv6.ip));
+ addr->ipv6.scope_id = sin->sin6_scope_id;
+
+ return 0;
+ }
+#endif
+
+ return -1;
+}
+
+static PRFileDesc *
+socket_connect (struct addrinfo *host, GError *error)
+{
+ PRNetAddr netaddr;
+ PRFileDesc *fd, *cancel_fd;
+
+ if (sockaddr_to_praddr(host->ai_addr, host->ai_addrlen, &netaddr) != 0) {
+ errno = EINVAL;
+ set_g_error_from_errno (error, FALSE);
+ return NULL;
+ }
+
+ fd = PR_OpenTCPSocket(netaddr.raw.family);
+ if (fd == NULL) {
+ set_errno (PR_GetError ());
+ set_g_error_from_errno (error, FALSE);
+ return NULL;
+ }
+
+ cancel_fd = camel_operation_cancel_prfd(NULL);
+
+ if (PR_Connect (fd, &netaddr, cancel_fd?0:CONNECT_TIMEOUT) == PR_FAILURE) {
+ gint errnosave;
+
+ set_errno (PR_GetError ());
+ if (PR_GetError () == PR_IN_PROGRESS_ERROR ||
+ (cancel_fd && (PR_GetError () == PR_CONNECT_TIMEOUT_ERROR ||
+ PR_GetError () == PR_IO_TIMEOUT_ERROR))) {
+ gboolean connected = FALSE;
+ PRPollDesc poll[2];
+
+ poll[0].fd = fd;
+ poll[0].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ poll[1].fd = cancel_fd;
+ poll[1].in_flags = PR_POLL_READ;
+
+ do {
+ poll[0].out_flags = 0;
+ poll[1].out_flags = 0;
+
+ if (PR_Poll (poll, cancel_fd?2:1, CONNECT_TIMEOUT) == PR_FAILURE) {
+ set_errno (PR_GetError ());
+ goto exception;
+ }
+
+ if (poll[1].out_flags == PR_POLL_READ) {
+ errno = EINTR;
+ goto exception;
+ }
+
+ if (PR_ConnectContinue(fd, poll[0].out_flags) == PR_FAILURE) {
+ set_errno (PR_GetError ());
+ if (PR_GetError () != PR_IN_PROGRESS_ERROR)
+ goto exception;
+ } else {
+ connected = TRUE;
+ }
+ } while (!connected);
+ } else {
+ exception:
+ errnosave = errno;
+ PR_Shutdown (fd, PR_SHUTDOWN_BOTH);
+ PR_Close (fd);
+ errno = errnosave;
+ fd = NULL;
+
+ goto out;
+ }
+
+ errno = 0;
+ }
+
+out:
+
+ if (!fd)
+ set_g_error_from_errno (error, TRUE);
+
+ return fd;
}
/* Returns the FD of a socket, already connected to and validated by the SOCKS4
- * proxy that is configured in the stream. Otherwise returns -1. Assumes that
+ * proxy that is configured in the stream. Otherwise returns NULL. Assumes that
* a proxy *is* configured with camel_tcp_stream_set_socks_proxy().
*/
-static gint
-connect_to_socks4_proxy (const gchar *proxy_host, gint proxy_port, struct addrinfo *connect_addr)
+static PRFileDesc *
+connect_to_socks4_proxy (const gchar *proxy_host, gint proxy_port, struct addrinfo *connect_addr, GError **error)
{
struct addrinfo *ai, hints;
gchar serv[16];
- gint fd;
+ PRFileDesc *fd;
gchar request[9];
struct sockaddr_in *sin;
gchar reply[8];
@@ -412,27 +754,25 @@ connect_to_socks4_proxy (const gchar *proxy_host, gint proxy_port, struct addrin
g_assert (proxy_host != NULL);
+ d (g_print ("TcpStreamRaw %p: connecting to SOCKS4 proxy %s:%d {\n resolving proxy host\n", ssl, proxy_host, proxy_port));
+
sprintf (serv, "%d", proxy_port);
memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_STREAM;
- ai = camel_getaddrinfo (proxy_host, serv, &hints, NULL); /* NULL-GError */
- if (!ai) {
-#ifdef G_OS_WIN32
- errno = WSAEHOSTUNREACH;
-#else
- errno = EHOSTUNREACH; /* FIXME: this is not an accurate error; we should translate the GError to an errno */
-#endif
- return -1;
- }
+ ai = camel_getaddrinfo (proxy_host, serv, &hints, error);
+ if (!ai)
+ return NULL;
+
+ d (g_print (" creating socket and connecting\n"));
- fd = socket_connect (ai);
+ fd = socket_connect (ai, error);
save_errno = errno;
camel_freeaddrinfo (ai);
- if (fd == -1) {
+ if (!fd) {
errno = save_errno;
goto error;
}
@@ -446,11 +786,17 @@ connect_to_socks4_proxy (const gchar *proxy_host, gint proxy_port, struct addrin
memcpy (request + 4, &sin->sin_addr.s_addr, 4); /* address in network byte order */
request[8] = 0x00; /* terminator */
- if (camel_write_socket (fd, request, sizeof (request), NULL) != sizeof (request))
+ d (g_print (" writing SOCKS4 request to connect to actual host\n"));
+ if (write_to_prfd (fd, request, sizeof (request), error) != sizeof (request)) {
+ d (g_print (" failed: %d\n", errno));
goto error;
+ }
- if (camel_read_socket (fd, reply, sizeof (reply), NULL) != sizeof (reply))
+ d (g_print (" reading SOCKS4 reply\n"));
+ if (read_from_prfd (fd, reply, sizeof (reply), error) != sizeof (reply)) {
+ d (g_print (" failed: %d\n", errno));
goto error;
+ }
if (!(reply[0] == 0 /* first byte of reply is 0 */
&& reply[1] == 90)) { /* 90 means "request granted" */
@@ -459,19 +805,27 @@ connect_to_socks4_proxy (const gchar *proxy_host, gint proxy_port, struct addrin
#else
errno = ECONNREFUSED;
#endif
+ set_g_error_from_errno (error, FALSE);
goto error;
}
+ /* We are now proxied; we are ready to send "normal" data through the socket */
+
+ d (g_print (" success\n"));
+
goto out;
error:
- if (fd != -1) {
+ if (fd) {
save_errno = errno;
- SOCKET_CLOSE (fd);
+ PR_Shutdown (fd, PR_SHUTDOWN_BOTH);
+ PR_Close (fd);
errno = save_errno;
- fd = -1;
+ fd = NULL;
}
+ d (g_print (" returning errno %d\n", errno));
+
out:
return fd;
@@ -520,7 +874,7 @@ tcp_stream_raw_connect (CamelTcpStream *stream,
else
priv->sockfd = socket_connect (ai);
- if (priv->sockfd != -1) {
+ if (priv->sockfd) {
retval = 0;
goto out;
}
@@ -543,31 +897,17 @@ tcp_stream_raw_getsockopt (CamelTcpStream *stream,
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
CamelTcpStreamRawPrivate *priv = raw->priv;
- gint optname, optlen;
+ PRSocketOptionData sodata;
- if ((optname = get_sockopt_optname (data)) == -1)
- return -1;
-
- if (data->option == CAMEL_SOCKOPT_NONBLOCKING) {
-#ifndef G_OS_WIN32
- gint flags;
+ memset ((gpointer) &sodata, 0, sizeof (sodata));
+ memcpy ((gpointer) &sodata, (gpointer) data, sizeof (CamelSockOptData));
- flags = fcntl (priv->sockfd, F_GETFL);
- if (flags == -1)
- return -1;
+ if (PR_GetSocketOption (priv->sockfd, &sodata) == PR_FAILURE)
+ return -1;
- data->value.non_blocking = flags & O_NONBLOCK ? TRUE : FALSE;
-#else
- data->value.non_blocking = priv->is_nonblocking;
-#endif
- return 0;
- }
+ memcpy ((gpointer) data, (gpointer) &sodata, sizeof (CamelSockOptData));
- return getsockopt (priv->sockfd,
- get_sockopt_level (data),
- optname,
- (gpointer) &data->value,
- (socklen_t *) &optlen);
+ return 0;
}
static gint
@@ -576,38 +916,48 @@ tcp_stream_raw_setsockopt (CamelTcpStream *stream,
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
CamelTcpStreamRawPrivate *priv = raw->priv;
- gint optname;
+ PRSocketOptionData sodata;
- if ((optname = get_sockopt_optname (data)) == -1)
+ memset ((gpointer) &sodata, 0, sizeof (sodata));
+ memcpy ((gpointer) &sodata, (gpointer) data, sizeof (CamelSockOptData));
+
+ if (PR_SetSocketOption (priv->sockfd, &sodata) == PR_FAILURE)
return -1;
- if (data->option == CAMEL_SOCKOPT_NONBLOCKING) {
-#ifndef G_OS_WIN32
- gint flags, set;
+ return 0;
+}
- flags = fcntl (priv->sockfd, F_GETFL);
- if (flags == -1)
- return -1;
+static struct sockaddr *
+sockaddr_from_praddr(PRNetAddr *addr, socklen_t *len)
+{
+ /* We assume the ip addresses are the same size - they have to be anyway */
- set = data->value.non_blocking ? O_NONBLOCK : 0;
- flags = (flags & ~O_NONBLOCK) | set;
+ if (addr->raw.family == PR_AF_INET) {
+ struct sockaddr_in *sin = g_malloc0(sizeof(*sin));
- if (fcntl (priv->sockfd, F_SETFL, flags) == -1)
- return -1;
-#else
- u_long fionbio = data->value.non_blocking ? 1 : 0;
- if (ioctlsocket (priv->sockfd, FIONBIO, &fionbio) == SOCKET_ERROR)
- return -1;
- priv->is_nonblocking = data->value.non_blocking ? 1 : 0;
-#endif
- return 0;
+ sin->sin_family = AF_INET;
+ sin->sin_port = addr->inet.port;
+ memcpy(&sin->sin_addr, &addr->inet.ip, sizeof(sin->sin_addr));
+ *len = sizeof(*sin);
+
+ return (struct sockaddr *)sin;
+ }
+#ifdef ENABLE_IPv6
+ else if (addr->raw.family == PR_AF_INET6) {
+ struct sockaddr_in6 *sin = g_malloc0(sizeof(*sin));
+
+ sin->sin6_family = AF_INET6;
+ sin->sin6_port = addr->ipv6.port;
+ sin->sin6_flowinfo = addr->ipv6.flowinfo;
+ memcpy(&sin->sin6_addr, &addr->ipv6.ip, sizeof(sin->sin6_addr));
+ sin->sin6_scope_id = addr->ipv6.scope_id;
+ *len = sizeof(*sin);
+
+ return (struct sockaddr *)sin;
}
+#endif
- return setsockopt (priv->sockfd,
- get_sockopt_level (data),
- optname,
- (gpointer) &data->value,
- sizeof (data->value));
+ return NULL;
}
static struct sockaddr *
@@ -616,21 +966,12 @@ tcp_stream_raw_get_local_address (CamelTcpStream *stream,
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
CamelTcpStreamRawPrivate *priv = raw->priv;
-#ifdef ENABLE_IPv6
- struct sockaddr_in6 sin;
-#else
- struct sockaddr_in sin;
-#endif
- struct sockaddr *saddr = (struct sockaddr *)&sin;
+ PRNetAddr addr;
- *len = sizeof(sin);
- if (getsockname (priv->sockfd, saddr, len) == -1)
+ if (PR_GetSockName(priv->sockfd, &addr) != PR_SUCCESS)
return NULL;
- saddr = g_malloc(*len);
- memcpy(saddr, &sin, *len);
-
- return saddr;
+ return sockaddr_from_praddr(&addr, len);
}
static struct sockaddr *
@@ -639,21 +980,21 @@ tcp_stream_raw_get_remote_address (CamelTcpStream *stream,
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
CamelTcpStreamRawPrivate *priv = raw->priv;
-#ifdef ENABLE_IPv6
- struct sockaddr_in6 sin;
-#else
- struct sockaddr_in sin;
-#endif
- struct sockaddr *saddr = (struct sockaddr *)&sin;
+ PRNetAddr addr;
- *len = sizeof(sin);
- if (getpeername (priv->sockfd, saddr, len) == -1)
+ if (PR_GetPeerName(priv->sockfd, &addr) != PR_SUCCESS)
return NULL;
- saddr = g_malloc(*len);
- memcpy(saddr, &sin, *len);
+ return sockaddr_from_praddr(&addr, len);
+}
- return saddr;
+static PRFileDesc *
+tcp_stream_raw_get_file_desc (CamelTcpStream *stream)
+{
+ CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
+ CamelTcpStreamRawPrivate *priv = raw->priv;
+
+ return priv->sockfd;
}
#define CAMEL_TCP_STREAM_RAW_GET_PRIVATE(obj) \
@@ -684,6 +1025,7 @@ camel_tcp_stream_raw_class_init (CamelTcpStreamRawClass *class)
tcp_stream_class->setsockopt = tcp_stream_raw_setsockopt;
tcp_stream_class->get_local_address = tcp_stream_raw_get_local_address;
tcp_stream_class->get_remote_address = tcp_stream_raw_get_remote_address;
+ tcp_stream_class->tcp_stream_raw_get_file_desc = tcp_stream_raw_get_file_desc;
}
static void
@@ -694,7 +1036,7 @@ camel_tcp_stream_raw_init (CamelTcpStreamRaw *stream)
stream->priv = CAMEL_TCP_STREAM_RAW_GET_PRIVATE (stream);
priv = stream->priv;
- priv->sockfd = -1;
+ priv->sockfd = NULL;
}
/**
@@ -709,11 +1051,3 @@ camel_tcp_stream_raw_new (void)
{
return g_object_new (CAMEL_TYPE_TCP_STREAM_RAW, NULL);
}
-
-gint
-camel_tcp_stream_raw_get_fd (CamelTcpStreamRaw *raw)
-{
- CamelTcpStreamRawPrivate *priv = raw->priv;
-
- return priv->sockfd;
-}
diff --git a/camel/camel-tcp-stream-raw.h b/camel/camel-tcp-stream-raw.h
index fa21aff..0171e60 100644
--- a/camel/camel-tcp-stream-raw.h
+++ b/camel/camel-tcp-stream-raw.h
@@ -68,8 +68,6 @@ GType camel_tcp_stream_raw_get_type (void);
/* public methods */
CamelStream *camel_tcp_stream_raw_new (void);
-gint camel_tcp_stream_raw_get_fd (CamelTcpStreamRaw *raw);
-
G_END_DECLS
#endif /* CAMEL_TCP_STREAM_RAW_H */
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 8bf9593..d11f659 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -2719,14 +2719,11 @@ imapx_connect_to_server (CamelIMAPXServer *is, GError **error)
}
tcp_stream = camel_tcp_stream_ssl_new(is->session, is->url->host, SSL_PORT_FLAGS);
}
- is->is_ssl_stream = TRUE;
} else {
tcp_stream = camel_tcp_stream_raw_new ();
- is->is_ssl_stream = FALSE;
}
#else
tcp_stream = camel_tcp_stream_raw_new ();
- is->is_ssl_stream = FALSE;
#endif /* HAVE_SSL */
camel_session_get_socks_proxy (is->session, &socks_host, &socks_port);
@@ -4593,29 +4590,6 @@ imapx_parser_thread (gpointer d)
while (local_error == NULL && is->stream) {
camel_operation_uncancel (op);
-#ifdef HAVE_SSL
- if (is->is_ssl_stream) {
- PRPollDesc pollfds[2] = { };
- gint res;
-
- pollfds[0].fd = camel_tcp_stream_get_file_desc (CAMEL_TCP_STREAM (is->stream->source));
- pollfds[0].in_flags = PR_POLL_READ;
- pollfds[1].fd = camel_operation_cancel_prfd (op);
- pollfds[1].in_flags = PR_POLL_READ;
-
-#include <prio.h>
-
- res = PR_Poll(pollfds, 2, PR_MillisecondsToInterval (30 * 1000));
- if (res == -1)
- g_usleep(1) /* ?? */ ;
- else if (res == 0) {
- /* timed out */
- } else if ((pollfds[0].out_flags & PR_POLL_READ)) {
- parse_contents (is, &local_error);
- } else if (pollfds[1].out_flags & PR_POLL_READ)
- errno = EINTR;
- }
-#endif
#ifndef G_OS_WIN32
if (is->is_process_stream) {
GPollFD fds[2] = { {0, 0, 0}, {0, 0, 0} };
@@ -4634,26 +4608,27 @@ imapx_parser_thread (gpointer d)
parse_contents (is, &local_error);
} else if (fds[1].revents & G_IO_IN)
errno = EINTR;
- }
+ } else
#endif
-
- if (!is->is_ssl_stream && !is->is_process_stream) {
- GPollFD fds[2] = { {0, 0, 0}, {0, 0, 0} };
+ {
+ PRPollDesc pollfds[2] = { };
gint res;
- fds[0].fd = camel_tcp_stream_raw_get_fd ((CamelTcpStreamRaw *)->stream->source);
- fds[0].events = G_IO_IN;
- fds[1].fd = camel_operation_cancel_fd (op);
- fds[1].events = G_IO_IN;
+ pollfds[0].fd = camel_tcp_stream_get_file_desc (CAMEL_TCP_STREAM (is->stream->source));
+ pollfds[0].in_flags = PR_POLL_READ;
+ pollfds[1].fd = camel_operation_cancel_prfd (op);
+ pollfds[1].in_flags = PR_POLL_READ;
- res = g_poll(fds, 2, 1000*30);
+#include <prio.h>
+
+ res = PR_Poll(pollfds, 2, PR_MillisecondsToInterval (30 * 1000));
if (res == -1)
g_usleep(1) /* ?? */ ;
- else if (res == 0)
- /* timed out */;
- else if (fds[0].revents & G_IO_IN) {
+ else if (res == 0) {
+ /* timed out */
+ } else if ((pollfds[0].out_flags & PR_POLL_READ)) {
parse_contents (is, &local_error);
- } else if (fds[1].revents & G_IO_IN)
+ } else if (pollfds[1].out_flags & PR_POLL_READ)
errno = EINTR;
}
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index 69bf5d3..6e4885d 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -69,7 +69,6 @@ struct _CamelIMAPXServer {
CamelURL *url;
CamelIMAPXStream *stream;
struct _capability_info *cinfo;
- gboolean is_ssl_stream;
gboolean is_process_stream;
CamelIMAPXNamespaceList *nsl;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]