2003-12-27 Mikael Hallendal <micke@imendio.com>
* docs/reference/tmpl/lm-error.sgml:
* loudmouth/lm-connection.c:
* loudmouth/lm-connection.h:
(connection_connect_nonblocking),
(connection_do_open),
(connection_http_proxy_negotiate),
(lm_connection_new),
(lm_connection_get_proxy_type),
(lm_connection_set_proxy_type),
(lm_connection_get_proxy_server),
(lm_connection_set_proxy_server),
(lm_connection_get_proxy_port),
(lm_connection_set_proxy_port):
- Add support for HTTP proxy
- Patch from Josh Beam <josh@3ddrome.com>
- Needed changes to Loudmouth to fix bug #117757 in Gossip.
--- a/ChangeLog Fri Dec 19 22:20:01 2003 +0000
+++ b/ChangeLog Sat Dec 27 04:00:01 2003 +0000
@@ -1,3 +1,22 @@
+2003-12-27 Mikael Hallendal <micke@imendio.com>
+
+ * docs/reference/tmpl/lm-error.sgml:
+ * loudmouth/lm-connection.c:
+ * loudmouth/lm-connection.h:
+ (connection_connect_nonblocking),
+ (connection_do_open),
+ (connection_http_proxy_negotiate),
+ (lm_connection_new),
+ (lm_connection_get_proxy_type),
+ (lm_connection_set_proxy_type),
+ (lm_connection_get_proxy_server),
+ (lm_connection_set_proxy_server),
+ (lm_connection_get_proxy_port),
+ (lm_connection_set_proxy_port):
+ - Add support for HTTP proxy
+ - Patch from Josh Beam <josh@3ddrome.com>
+ - Needed changes to Loudmouth to fix bug #117757 in Gossip.
+
2003-12-19 Mikael Hallendal <micke@imendio.com>
* loudmouth/lm-connection.c:
--- a/docs/reference/tmpl/lm-error.sgml Fri Dec 19 22:20:01 2003 +0000
+++ b/docs/reference/tmpl/lm-error.sgml Sat Dec 27 04:00:01 2003 +0000
@@ -30,6 +30,7 @@
@LM_ERROR_CONNECTION_NOT_OPEN: Connection not open when trying to send a message
@LM_ERROR_CONNECTION_OPEN: Connection is already open when trying to open it again.
@LM_ERROR_AUTH_FAILED: Authentication failed while opening connection
+@LM_ERROR_CONNECTION_FAILED:
<!-- ##### MACRO LM_ERROR ##### -->
<para>
--- a/loudmouth/lm-connection.c Fri Dec 19 22:20:01 2003 +0000
+++ b/loudmouth/lm-connection.c Sat Dec 27 04:00:01 2003 +0000
@@ -34,6 +34,7 @@
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
+ #include <sys/time.h>
#else
#include <winsock2.h>
#endif
@@ -66,6 +67,10 @@
gboolean use_ssl;
char fingerprint[20];
+ LmProxyType proxy_type;
+ gchar *proxy_server;
+ guint proxy_port;
+
#ifdef HAVE_GNUTLS
gnutls_session gnutls_session;
gnutls_certificate_client_credentials gnutls_xcred;
@@ -166,6 +171,8 @@
static void connection_signal_disconnect (LmConnection *connection,
LmDisconnectReason reason);
+static gboolean connection_http_proxy_negotiate (gint fd, LmConnection *connection);
+
static GSourceFuncs incoming_funcs = {
connection_incoming_prepare,
connection_incoming_check,
@@ -353,7 +360,10 @@
fd_set rset, wset;
struct timeval tval;
- ((struct sockaddr_in *) addr->ai_addr)->sin_port = htons (connection->port);
+ if (connection->proxy_type != LM_PROXY_TYPE_NONE)
+ ((struct sockaddr_in *) addr->ai_addr)->sin_port = htons (connection->proxy_port);
+ else
+ ((struct sockaddr_in *) addr->ai_addr)->sin_port = htons (connection->port);
getnameinfo (addr->ai_addr,
addr->ai_addrlen,
@@ -371,15 +381,21 @@
return -1;
}
+ res = connect (fd, addr->ai_addr, addr->ai_addrlen);
+ if (res == 0) {
+ if (connection->proxy_type == LM_PROXY_TYPE_HTTP) {
+ if (connection_http_proxy_negotiate(fd, connection) == TRUE) {
+ return fd;
+ }
+ } else {
+ /* connection successfull */
+ return fd;
+ }
+ }
+
flags = fcntl (fd, F_GETFL, 0);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
- res = connect (fd, addr->ai_addr, addr->ai_addrlen);
- if (res == 0) {
- /* connection successfull */
- return fd;
- }
-
if (errno != EINPROGRESS) {
close (fd);
return -1;
@@ -437,18 +453,34 @@
req.ai_socktype = SOCK_STREAM;
req.ai_protocol = IPPROTO_TCP;
- g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
- "Going to connect to %s\n",connection->server);
+ if (connection->proxy_type != LM_PROXY_TYPE_NONE) { /* connect through proxy */
+ g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
+ "Going to connect to %s\n",connection->proxy_server);
- connection->cancel_open = FALSE;
- connection->state = LM_CONNECTION_STATE_CONNECTING;
+ connection->cancel_open = FALSE;
+ connection->state = LM_CONNECTION_STATE_CONNECTING;
- if ((err = getaddrinfo (connection->server, NULL, &req, &ans)) != 0) {
- g_set_error (error,
- LM_ERROR,
- LM_ERROR_CONNECTION_OPEN,
- "getaddrinfo() failed");
- return FALSE;
+ if ((err = getaddrinfo (connection->proxy_server, NULL, &req, &ans)) != 0) {
+ g_set_error (error,
+ LM_ERROR,
+ LM_ERROR_CONNECTION_OPEN,
+ "getaddrinfo() failed");
+ return FALSE;
+ }
+ } else { /* connect directly */
+ g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
+ "Going to connect to %s\n",connection->server);
+
+ connection->cancel_open = FALSE;
+ connection->state = LM_CONNECTION_STATE_CONNECTING;
+
+ if ((err = getaddrinfo (connection->server, NULL, &req, &ans)) != 0) {
+ g_set_error (error,
+ LM_ERROR,
+ LM_ERROR_CONNECTION_OPEN,
+ "getaddrinfo() failed");
+ return FALSE;
+ }
}
#ifdef HAVE_GNUTLS
@@ -1050,6 +1082,52 @@
}
}
+static gboolean
+connection_http_proxy_negotiate (gint fd, LmConnection *connection)
+{
+ gint i, len;
+ gchar buf[1024];
+ gchar *str;
+
+ str = g_strdup_printf ("CONNECT %s:%u HTTP/1.1\r\nHost: %s:%u\r\n\r\n",
+ connection->server, connection->port,
+ connection->server, connection->port);
+
+ send (fd, str, strlen (str), 0);
+
+ g_free (str);
+
+ len = read (fd, buf, 12);
+ if (len <= 0) {
+ return FALSE;
+ }
+
+ buf[len] = '\0';
+ if (strcmp (buf, "HTTP/1.1 200") != 0 && strcmp (buf, "HTTP/1.0 200") != 0) {
+ return FALSE;
+ }
+
+ /* discard any headers that we don't need */
+ for (i = 0; i < 4; i++) {
+ len = read (fd, buf + i, 1);
+ if (len <= 0) {
+ return FALSE;
+ }
+ }
+ while (strncmp (buf, "\r\n\r\n", 4) != 0) {
+ for (i = 0; i < 3; i++) {
+ buf[i] = buf[i + 1];
+ }
+
+ len = read (fd, buf + 3, 1);
+ if (len <= 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
/**
* lm_connection_new:
* @server: The hostname to the server for the connection.
@@ -1078,6 +1156,9 @@
connection->port = LM_CONNECTION_DEFAULT_PORT;
connection->use_ssl = FALSE;
connection->fingerprint[0] = '\0';
+ connection->proxy_type = LM_PROXY_TYPE_NONE;
+ connection->proxy_server = NULL;
+ connection->proxy_port = 8080;
connection->disconnect_cb = NULL;
connection->incoming_messages = lm_queue_new ();
connection->cancel_open = FALSE;
@@ -1603,6 +1684,106 @@
}
/**
+ * lm_connection_get_proxy_type:
+ * @connection: an #LmConnection
+ *
+ * Fetches the proxy type that @connection is using.
+ *
+ * Return value:
+ **/
+LmProxyType
+lm_connection_get_proxy_type (LmConnection *connection)
+{
+ return connection->proxy_type;
+}
+
+/**
+ * lm_connection_set_proxy_type:
+ * @connection: an #LmConnection
+ * @type: an LmProxyType
+ *
+ * Sets the proxy server type for @connection to @type. Notice that @connection can't be open while doing this.
+ **/
+void
+lm_connection_set_proxy_type (LmConnection *connection, LmProxyType type)
+{
+ if (lm_connection_is_open (connection)) {
+ g_warning ("Can't change proxy type while connected");
+ return;
+ }
+
+ connection->proxy_type = type;
+}
+
+/**
+ * lm_connection_get_proxy_server:
+ * @connection: an #LmConnection
+ *
+ * Fetches the proxy server address that @connection is using.
+ *
+ * Return value: the proxy server address
+ **/
+const gchar *
+lm_connection_get_proxy_server (LmConnection *connection)
+{
+ return connection->proxy_server;
+}
+
+/**
+ * lm_connection_set_proxy_server:
+ * @connection: an #LmConnection
+ * @server: Address of the proxy server
+ *
+ * Sets the proxy server address for @connection to @server. Notice that @connection can't be open while doing this.
+ **/
+void
+lm_connection_set_proxy_server (LmConnection *connection, const gchar *server)
+{
+ if (lm_connection_is_open (connection)) {
+ g_warning ("Can't change proxy server address while connected");
+ return;
+ }
+
+ if (connection->proxy_server) {
+ g_free (connection->proxy_server);
+ }
+
+ connection->proxy_server = g_strdup (server);
+}
+
+/**
+ * lm_connection_get_proxy_port:
+ * @connection: an #LmConnection
+ *
+ * Fetches the proxy port that @connection is using.
+ *
+ * Return value:
+ **/
+guint
+lm_connection_get_proxy_port (LmConnection *connection)
+{
+ return connection->proxy_port;
+}
+
+/**
+ * lm_connection_set_proxy_port:
+ * @connection: an #LmConnection
+ * @port: proxy server port
+ *
+ * Sets the proxy server port that @connection will be using.
+ **/
+void
+lm_connection_set_proxy_port (LmConnection *connection, guint port)
+{
+ if (lm_connection_is_open (connection)) {
+ g_warning ("Can't change proxy server port while connected");
+ return;
+ }
+
+ connection->proxy_port = port;
+}
+
+/**
* lm_connection_supports_ssl:
*
* Checks whether Loudmouth supports SSL or not.
--- a/loudmouth/lm-connection.h Fri Dec 19 22:20:01 2003 +0000
+++ b/loudmouth/lm-connection.h Sat Dec 27 04:00:01 2003 +0000
@@ -57,6 +57,11 @@
} LmDisconnectReason;
typedef enum {
+ LM_PROXY_TYPE_NONE = 0,
+ LM_PROXY_TYPE_HTTP
+} LmProxyType;
+
+typedef enum {
LM_CERT_INVALID,
LM_CERT_ISSUER_NOT_FOUND,
LM_CERT_REVOKED,
@@ -152,6 +157,18 @@
gboolean lm_connection_supports_ssl (void);
gboolean lm_connection_get_use_ssl (LmConnection *connection);
+LmProxyType lm_connection_get_proxy_type (LmConnection *connection);
+void lm_connection_set_proxy_type (LmConnection *connection,
+ LmProxyType type);
+
+const gchar * lm_connection_get_proxy_server (LmConnection *connection);
+void lm_connection_set_proxy_server (LmConnection *connection,
+ const gchar *server);
+
+guint lm_connection_get_proxy_port (LmConnection *connection);
+void lm_connection_set_proxy_port (LmConnection *connection,
+ guint port);
+
const unsigned char *
lm_connection_get_fingerprint (LmConnection *connection);