[evolution-data-server/camel-socks-proxy: 91/94] Do name resolution inside camel_tcp_stream_connect()
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/camel-socks-proxy: 91/94] Do name resolution inside camel_tcp_stream_connect()
- Date: Fri, 9 Jul 2010 22:54:29 +0000 (UTC)
commit 253e3552f615a65637e95d74067b45721e57fea0
Author: Federico Mena Quintero <federico novell com>
Date: Fri Jul 9 14:12:06 2010 -0500
Do name resolution inside camel_tcp_stream_connect()
This function and the associated vmethod used to take a struct addrinfo *.
However, this doesn't let us have SOCKS4a or SOCKS5 proxies that do name
resolution in the proxy. So, now the main camel_tcp_stream_connect() takes
a hostname and service name, and implementations do name resolution
by themselves. Later we will modify the proxy code to do name resolution
in the proxy.
We allow passing a fallback port to camel_tcp_stream_connect(), which
is used by Camel's providers when the system's services database
(/etc/services) doesn't have an entry for a particular service name.
If getaddrinfo() can't find the service name, then we use a
fallback/hardcoded port number. See bgo#267898
Also, camel_tcp_stream_connect() now returns a CamelException. This
will let us properly return errors from the camel_getaddrinfo() stage.
Signed-off-by: Federico Mena Quintero <federico novell com>
camel/camel-tcp-stream-raw.c | 53 +++++++++++++++++++++++++++++++++--------
camel/camel-tcp-stream-ssl.c | 53 ++++++++++++++++++++++++++++++++++--------
camel/camel-tcp-stream.c | 17 ++++++++----
camel/camel-tcp-stream.h | 5 ++-
4 files changed, 99 insertions(+), 29 deletions(-)
---
diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c
index 89a29e5..0f69050 100644
--- a/camel/camel-tcp-stream-raw.c
+++ b/camel/camel-tcp-stream-raw.c
@@ -61,7 +61,7 @@ static gssize stream_write (CamelStream *stream, const gchar *buffer, gsize n);
static gint stream_flush (CamelStream *stream);
static gint stream_close (CamelStream *stream);
-static gint stream_connect (CamelTcpStream *stream, struct addrinfo *host);
+static gint stream_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex);
static gint stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
static gint stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len);
@@ -439,7 +439,7 @@ connect_to_socks4_proxy (const gchar *proxy_host, gint proxy_port, struct addrin
goto error;
}
- g_assert (connect_addr->ai_addr->sa_family == AF_INET); /* FIXME: what to do about IPv6? Are we just screwed with SOCKS4? */
+ g_assert (connect_addr->ai_addr->sa_family == AF_INET); /* FMQ: check for AF_INET in the caller */
sin = (struct sockaddr_in *) connect_addr->ai_addr;
request[0] = 0x04; /* SOCKS4 */
@@ -476,29 +476,60 @@ out:
}
static gint
-stream_connect (CamelTcpStream *stream, struct addrinfo *host)
+stream_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex)
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
+ struct addrinfo *addr, *ai;
+ struct addrinfo hints;
+ CamelException my_ex;
+ gint retval;
const gchar *proxy_host;
gint proxy_port;
- g_return_val_if_fail (host != NULL, -1);
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
+
+ camel_exception_init (&my_ex);
+ addr = camel_getaddrinfo (host, service, &hints, &my_ex);
+ if (addr == NULL && fallback_port != 0 && camel_exception_get_id (&my_ex) != CAMEL_EXCEPTION_USER_CANCEL) {
+ char str_port[16];
+
+ camel_exception_clear (&my_ex);
+ sprintf (str_port, "%d", fallback_port);
+ addr = camel_getaddrinfo (host, str_port, &hints, &my_ex);
+ }
+
+ if (addr == NULL) {
+ camel_exception_xfer (ex, &my_ex);
+ return -1;
+ }
camel_tcp_stream_peek_socks_proxy (stream, &proxy_host, &proxy_port);
- while (host) {
+ ai = addr;
+
+ while (ai) {
if (proxy_host)
- raw->sockfd = connect_to_socks4_proxy (proxy_host, proxy_port, host);
+ raw->sockfd = connect_to_socks4_proxy (proxy_host, proxy_port, ai);
else
- raw->sockfd = socket_connect (host);
+ raw->sockfd = socket_connect (ai);
- if (raw->sockfd != -1)
- return 0;
+ if (raw->sockfd != -1) {
+ retval = 0;
+ goto out;
+ }
- host = host->ai_next;
+ ai = ai->ai_next;
}
- return -1;
+ retval = -1;
+
+out:
+
+ camel_freeaddrinfo (addr);
+
+ return retval;
}
static gint
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index 132c977..e48fdf0 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -79,7 +79,7 @@ static gint stream_close (CamelStream *stream);
static PRFileDesc *enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd);
-static gint stream_connect (CamelTcpStream *stream, struct addrinfo *host);
+static gint stream_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex);
static gint stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
static gint stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len);
@@ -1300,7 +1300,7 @@ connect_to_socks4_proxy (CamelTcpStreamSSL *ssl, const gchar *proxy_host, gint p
goto error;
}
- g_assert (connect_addr->ai_addr->sa_family == AF_INET); /* FIXME: what to do about IPv6? Are we just screwed with SOCKS4? */
+ g_assert (connect_addr->ai_addr->sa_family == AF_INET); /* FMQ: check for AF_INET in the caller */
sin = (struct sockaddr_in *) connect_addr->ai_addr;
request[0] = 0x04; /* SOCKS4 */
@@ -1368,27 +1368,60 @@ out:
}
static gint
-stream_connect(CamelTcpStream *stream, struct addrinfo *host)
+stream_connect(CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex)
{
CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
+ struct addrinfo *addr, *ai;
+ struct addrinfo hints;
+ CamelException my_ex;
+ gint retval;
const gchar *proxy_host;
gint proxy_port;
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
+
+ camel_exception_init (&my_ex);
+ addr = camel_getaddrinfo (host, service, &hints, &my_ex);
+ if (addr == NULL && fallback_port != 0 && camel_exception_get_id (&my_ex) != CAMEL_EXCEPTION_USER_CANCEL) {
+ char str_port[16];
+
+ camel_exception_clear (&my_ex);
+ sprintf (str_port, "%d", fallback_port);
+ addr = camel_getaddrinfo (host, str_port, &hints, &my_ex);
+ }
+
+ if (addr == NULL) {
+ camel_exception_xfer (ex, &my_ex);
+ return -1;
+ }
+
camel_tcp_stream_peek_socks_proxy (stream, &proxy_host, &proxy_port);
- while (host) {
+ ai = addr;
+
+ while (ai) {
if (proxy_host)
- ssl->priv->sockfd = connect_to_socks4_proxy (ssl, proxy_host, proxy_port, host);
+ ssl->priv->sockfd = connect_to_socks4_proxy (ssl, proxy_host, proxy_port, ai);
else
- ssl->priv->sockfd = socket_connect (stream, host, TRUE);
+ ssl->priv->sockfd = socket_connect (stream, ai, TRUE);
- if (ssl->priv->sockfd)
- return 0;
+ if (ssl->priv->sockfd) {
+ retval = 0;
+ goto out;
+ }
- host = host->ai_next;
+ ai = ai->ai_next;
}
- return -1;
+ retval = -1;
+
+out:
+
+ camel_freeaddrinfo (addr);
+
+ return retval;
}
static gint
diff --git a/camel/camel-tcp-stream.c b/camel/camel-tcp-stream.c
index 03707e8..f61e179 100644
--- a/camel/camel-tcp-stream.c
+++ b/camel/camel-tcp-stream.c
@@ -42,7 +42,7 @@ static CamelStreamClass *parent_class = NULL;
/* Returns the class for a CamelTcpStream */
#define CTS_CLASS(so) CAMEL_TCP_STREAM_CLASS (CAMEL_OBJECT_GET_CLASS(so))
-static gint tcp_connect (CamelTcpStream *stream, struct addrinfo *host);
+static gint tcp_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex);
static gint tcp_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
static gint tcp_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
static struct sockaddr *tcp_get_local_address (CamelTcpStream *stream, socklen_t *len);
@@ -108,7 +108,7 @@ camel_tcp_stream_get_type (void)
}
static gint
-tcp_connect (CamelTcpStream *stream, struct addrinfo *host)
+tcp_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex)
{
w(g_warning ("CamelTcpStream::connect called on default implementation"));
return -1;
@@ -117,19 +117,24 @@ tcp_connect (CamelTcpStream *stream, struct addrinfo *host)
/**
* camel_tcp_stream_connect:
* @stream: a #CamelTcpStream object
- * @host: a linked list of addrinfo structures to try to connect, in
- * the order of most likely to least likely to work.
+ * @host: Hostname for connection
+ * @service: Service name or port number in string form
+ * @fallback_port: Port number to retry if @service is not present in the system's services database, or 0 to avoid retrying.
+ * @ex: a #CamelException
*
* Create a socket and connect based upon the data provided.
*
* Returns: %0 on success or %-1 on fail
**/
gint
-camel_tcp_stream_connect (CamelTcpStream *stream, struct addrinfo *host)
+camel_tcp_stream_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex)
{
g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1);
+ g_return_val_if_fail (host != NULL, -1);
+ g_return_val_if_fail (service != NULL, -1);
+ g_return_val_if_fail (ex == NULL || !camel_exception_is_set (ex), -1);
- return CTS_CLASS (stream)->connect (stream, host);
+ return CTS_CLASS (stream)->connect (stream, host, service, fallback_port, ex);
}
static gint
diff --git a/camel/camel-tcp-stream.h b/camel/camel-tcp-stream.h
index a02cbb6..b3e5782 100644
--- a/camel/camel-tcp-stream.h
+++ b/camel/camel-tcp-stream.h
@@ -37,6 +37,7 @@
#endif
#include <unistd.h>
+#include <camel/camel-exception.h>
#include <camel/camel-stream.h>
#define CAMEL_TCP_STREAM_TYPE (camel_tcp_stream_get_type ())
@@ -100,7 +101,7 @@ typedef struct {
CamelStreamClass parent_class;
/* Virtual methods */
- gint (*connect) (CamelTcpStream *stream, struct addrinfo *host);
+ gint (*connect) (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex);
gint (*getsockopt) (CamelTcpStream *stream, CamelSockOptData *data);
gint (*setsockopt) (CamelTcpStream *stream, const CamelSockOptData *data);
@@ -112,7 +113,7 @@ typedef struct {
CamelType camel_tcp_stream_get_type (void);
/* public methods */
-gint camel_tcp_stream_connect (CamelTcpStream *stream, struct addrinfo *host);
+gint camel_tcp_stream_connect (CamelTcpStream *stream, const char *host, const char *service, gint fallback_port, CamelException *ex);
gint camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
gint camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]