2004-03-17 Mikael Hallendal <micke@imendio.com>
authorhallski <hallski>
Thu, 18 Mar 2004 00:04:59 +0000
changeset 82 a32b54e654e2
parent 81 b9dfe6efc011
child 83 9c89653e79a1
2004-03-17 Mikael Hallendal <micke@imendio.com> * Synced from SVN. * Released 0.16 * configure.in: Bumped to 0.16 * NEWS: Updated for 0.16 2004-03-17 Mikael Hallendal <micke@imendio.com> * docs/reference/*: Updated documentation. * loudmouth/*: Fixed the documentation in a couple of places. 2004-03-17 Mikael Hallendal <micke@imendio.com> * loudmouth/lm-connection.[ch] (lm_connection_new_with_context): - Added to be able to give what context the connection should be running in. - All internal functions are updated to use the context or NULL if lm_connection_new was called. - Should make it possible to use several LmConnections in various threads. 2004-03-17 Mikael Hallendal <micke@imendio.com> * loudmouth/lm-connection.c: * loudmouth/lm-internal.h: * loudmouth/lm-proxy.c: - Make the HTTP proxy support asynchronous. Patch from Josh Beam. - Re-enable the HTTP proxy support. * examples/lm-send-sync.c: * examples/lm-send-async.c: * examples/test-http-proxy.c: - Added two of the old examples and a new one to test out the HTTP proxy support. 2004-03-17 Mikael Hallendal <micke@imendio.com> * configure.in: Generate examples/Makefile * loudmouth/test-jid.c: Removed * loudmouth/test-lm.c: Moved to examples/ * exmples/*: Moved out from loudmouth/
AUTHORS
ChangeLog
Makefile.am
NEWS
configure.in
docs/reference/loudmouth-docs.sgml
docs/reference/loudmouth-sections.txt
docs/reference/tmpl/lm-connection.sgml
docs/reference/tmpl/lm-ssl.sgml
loudmouth/Makefile.am
loudmouth/lm-connection.c
loudmouth/lm-connection.h
loudmouth/lm-internals.h
loudmouth/lm-proxy.c
loudmouth/lm-proxy.h
loudmouth/loudmouth.h
loudmouth/test-jid.c
loudmouth/test-lm.c
--- a/AUTHORS	Thu Feb 05 22:18:20 2004 +0000
+++ b/AUTHORS	Thu Mar 18 00:04:59 2004 +0000
@@ -1,2 +1,1 @@
 Mikael Hallendal <micke@imendio.com>
-
--- a/ChangeLog	Thu Feb 05 22:18:20 2004 +0000
+++ b/ChangeLog	Thu Mar 18 00:04:59 2004 +0000
@@ -1,3 +1,48 @@
+2004-03-17  Mikael Hallendal  <micke@imendio.com>
+
+	* Synced from SVN.
+
+	* Released 0.16
+	
+	* configure.in: Bumped to 0.16 
+	* NEWS: Updated for 0.16
+ 
+2004-03-17  Mikael Hallendal  <micke@imendio.com>
+
+	* docs/reference/*: Updated documentation.
+	* loudmouth/*: Fixed the documentation in a couple of places. 
+
+2004-03-17  Mikael Hallendal  <micke@imendio.com>
+
+	* loudmouth/lm-connection.[ch]
+	(lm_connection_new_with_context): 
+ 	- Added to be able to give what context the connection should be 
+	  running in. 
+	- All internal functions are updated to use the context or NULL if 
+	  lm_connection_new was called.
+	- Should make it possible to use several LmConnections in various 
+	  threads.
+
+2004-03-17  Mikael Hallendal  <micke@imendio.com>
+
+	* loudmouth/lm-connection.c: 
+	* loudmouth/lm-internal.h:
+	* loudmouth/lm-proxy.c: 
+	- Make the HTTP proxy support asynchronous. Patch from Josh Beam.
+	- Re-enable the HTTP proxy support.
+	* examples/lm-send-sync.c: 
+	* examples/lm-send-async.c:
+	* examples/test-http-proxy.c:
+	- Added two of the old examples and a new one to test out the HTTP 
+	  proxy support.
+
+2004-03-17  Mikael Hallendal  <micke@imendio.com>
+
+	* configure.in: Generate examples/Makefile
+	* loudmouth/test-jid.c: Removed
+	* loudmouth/test-lm.c: Moved to examples/
+	* exmples/*: Moved out from loudmouth/
+
 2004-02-05  Mikael Hallendal  <micke@imendio.com>
 
 	* README: Updated information about website and bug reporting
--- a/Makefile.am	Thu Feb 05 22:18:20 2004 +0000
+++ b/Makefile.am	Thu Mar 18 00:04:59 2004 +0000
@@ -2,7 +2,7 @@
     MONO_SUBDIR = mono
 endif
 
-SUBDIRS = loudmouth docs 
+SUBDIRS = loudmouth docs examples
 
 EXTRA_DIST =			\
 	loudmouth-1.0.pc.in     \
--- a/NEWS	Thu Feb 05 22:18:20 2004 +0000
+++ b/NEWS	Thu Mar 18 00:04:59 2004 +0000
@@ -1,3 +1,12 @@
+Changes in 0.16:
+----------------
+* Support for giving the context to which an LmConnection should run in
+  (should solve issues when wanting to run several LmConnections in various
+   threads)
+* HTTP proxy support
+* Memory leak fix
+* Distribute the win32-config.h file needed to build on Windows.
+ 
 Changes in 0.15.1:
 ------------------
 * Require GnuTLS >= 1.0.0
--- a/configure.in	Thu Feb 05 22:18:20 2004 +0000
+++ b/configure.in	Thu Mar 18 00:04:59 2004 +0000
@@ -2,7 +2,7 @@
 
 AM_CONFIG_HEADER(config.h)
 
-AM_INIT_AUTOMAKE(loudmouth, 0.15.1)
+AM_INIT_AUTOMAKE(loudmouth, 0.16)
 
 AM_MAINTAINER_MODE
 
@@ -179,6 +179,7 @@
 docs/Makefile
 docs/reference/Makefile
 loudmouth/Makefile
+examples/Makefile
 loudmouth-1.0.pc
 loudmouth.spec])
 
@@ -188,13 +189,11 @@
 dnl ==========================================================================
 echo "
 
-                    Loudmouth $VERSION
-	=========================================
+          Loudmouth $VERSION from Imendio HB
+	==================================
 
         prefix:                   ${prefix}
         compiler:                 ${CC}
-        cflags:                   ${CFLAGS}
-
 	"
 		    
 dnl if test x$enable_mono = xyes ; then
@@ -208,15 +207,12 @@
 dnl "
 dnl fi
 
-echo \
 
 echo \
-"        Enable SSL               ${ac_ssl}
-"
+"        Enable SSL               ${ac_ssl}"
 echo \
 "        Enable Debug:            ${enable_debug}
 "
-
 echo \
 "        Now type 'make' to build Loudmouth
 "
--- a/docs/reference/loudmouth-docs.sgml	Thu Feb 05 22:18:20 2004 +0000
+++ b/docs/reference/loudmouth-docs.sgml	Thu Mar 18 00:04:59 2004 +0000
@@ -14,5 +14,6 @@
     <xi:include href="xml/lm-message-handler.xml"/>
     <xi:include href="xml/lm-message-node.xml"/>
     <xi:include href="xml/lm-ssl.xml"/>
+    <xi:include href="xml/lm-proxy.xml"/>
   </chapter>
 </book>
--- a/docs/reference/loudmouth-sections.txt	Thu Feb 05 22:18:20 2004 +0000
+++ b/docs/reference/loudmouth-sections.txt	Thu Mar 18 00:04:59 2004 +0000
@@ -21,9 +21,10 @@
 lm_connection_set_server
 lm_connection_get_port
 lm_connection_set_port
-lm_connection_supports_ssl
-lm_connection_get_use_ssl
-lm_connection_set_use_ssl
+lm_connection_get_ssl
+lm_connection_set_ssl
+lm_connection_get_proxy
+lm_connection_set_proxy
 lm_connection_send
 lm_connection_send_with_reply
 lm_connection_send_with_reply_and_block
@@ -90,6 +91,7 @@
 
 <SECTION>
 <FILE>lm-ssl</FILE>
+LmSSL
 LmCertificateStatus
 LmSSLStatus
 LmSSLResponse
@@ -100,3 +102,23 @@
 lm_ssl_ref
 lm_ssl_unref
 </SECTION>
+
+<SECTION>
+<FILE>lm-proxy</FILE>
+LmProxy
+LmProxyType
+lm_proxy_new
+lm_proxy_new_with_server
+lm_proxy_get_type
+lm_proxy_set_type
+lm_proxy_get_server
+lm_proxy_set_server
+lm_proxy_get_port
+lm_proxy_set_port
+lm_proxy_get_username
+lm_proxy_set_username
+lm_proxy_get_password
+lm_proxy_set_password
+lm_proxy_ref
+lm_proxy_unref
+</SECTION>
--- a/docs/reference/tmpl/lm-connection.sgml	Thu Feb 05 22:18:20 2004 +0000
+++ b/docs/reference/tmpl/lm-connection.sgml	Thu Mar 18 00:04:59 2004 +0000
@@ -6,7 +6,44 @@
 
 <!-- ##### SECTION Long_Description ##### -->
 <para>
+An example of how to use Loudmouth with the synchronous API.
+<informalexample><programlisting><![CDATA[
+int
+main (int argc, char **argv)
+{
+        LmConnection *connection;
+        GError       *error = NULL;
+        gint          i;
+	LmMessage    *m;
 
+        connection = lm_connection_new ("myserver");
+
+        if (!lm_connection_open_and_block (connection, &error)) {
+                g_error ("Failed to open: %s\n", error->message);
+        }
+
+	if (!lm_connection_authenticate_and_block (connection,
+						   "username", "password", 
+						   "resource",
+						   &error)) {
+		g_error ("Failed to authenticate: %s\n", error->message);
+	}
+	
+	m = lm_message_new ("recipient", LM_MESSAGE_TYPE_MESSAGE);
+	lm_message_node_add_child (m->node, "body", "message");
+	
+	if (!lm_connection_send (connection, m, &error)) {
+		g_error ("Send failed: %s\n", error->message);
+	}
+
+	lm_message_unref (m);
+
+	lm_connection_close (connection, NULL);
+	lm_connection_unref (connection);
+	
+        return 0;
+}
+]]></programlisting></informalexample>
 </para>
 
 <!-- ##### SECTION See_Also ##### -->
@@ -215,6 +252,42 @@
 @port: 
 
 
+<!-- ##### FUNCTION lm_connection_get_ssl ##### -->
+<para>
+
+</para>
+
+@connection: 
+@Returns: 
+
+
+<!-- ##### FUNCTION lm_connection_set_ssl ##### -->
+<para>
+
+</para>
+
+@connection: 
+@ssl: 
+
+
+<!-- ##### FUNCTION lm_connection_get_proxy ##### -->
+<para>
+
+</para>
+
+@connection: 
+@Returns: 
+
+
+<!-- ##### FUNCTION lm_connection_set_proxy ##### -->
+<para>
+
+</para>
+
+@connection: 
+@proxy: 
+
+
 <!-- ##### FUNCTION lm_connection_send ##### -->
 <para>
 
--- a/docs/reference/tmpl/lm-ssl.sgml	Thu Feb 05 22:18:20 2004 +0000
+++ b/docs/reference/tmpl/lm-ssl.sgml	Thu Mar 18 00:04:59 2004 +0000
@@ -6,14 +6,29 @@
 
 <!-- ##### SECTION Long_Description ##### -->
 <para>
-Use this together with an #LmConnection to get the connection to use SSL.
+Use this together with an #LmConnection to get the connection to use SSL. Example of how to use the #LmSSL API.
 </para>
+<informalexample><programlisting><![CDATA[
+LmConnection *connection;
+LmSSL        *ssl;
+
+connection = lm_connection_new ("myserver");
+ssl = lm_ssl_new (NULL, my_ssl_func, NULL, NULL);
+lm_connection_set_ssl (connection, ssl);
+...
+]]></programlisting></informalexample>
 
 <!-- ##### SECTION See_Also ##### -->
 <para>
 
 </para>
 
+<!-- ##### STRUCT LmSSL ##### -->
+<para>
+This should not be accessed directly. Use the accessor functions as described below.
+</para>
+
+
 <!-- ##### ENUM LmCertificateStatus ##### -->
 <para>
 Provides information of the status of a certain certificate.
@@ -49,7 +64,7 @@
 This function is called if something goes wrong during the connecting phase.
 </para>
 
-@ssl: An #LmSSL. 
+@ssl: An #LmSSL.
 @status: The status informing what went wrong.
 @user_data: User data provided in the callback.
 @Returns: User should return #LM_SSL_RESPONSE_CONTINUE if connection should proceed and otherwise #LM_SSL_RESPONSE_STOP.
--- a/loudmouth/Makefile.am	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/Makefile.am	Thu Mar 18 00:04:59 2004 +0000
@@ -49,15 +49,3 @@
 
 # an explicit dependency here so alm generated files get built
 $(OBJECTS): $(built_sources)
-
-noinst_PROGRAMS = test-lm
-
-test_lm_SOURCES =			\
-	test-lm.c
-
-test_lm_LDADD =			 	\
-	$(LOUDMOUTH_LIBS)		\
-	libloudmouth-1.la		\
-	$(NULL)
-
-
--- a/loudmouth/lm-connection.c	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/lm-connection.c	Thu Mar 18 00:04:59 2004 +0000
@@ -51,58 +51,49 @@
 } HandlerData;
 
 typedef struct {
-	LmConnection    *connection;
-	
-	/* struct to save resolved address */
-	struct addrinfo *resolved_addrs;
-	struct addrinfo *current_addr;
-	int              fd;
-	GIOChannel           *io_channel;
-} LmConnectData;
-
-typedef struct {
 	GSource       source;
 	LmConnection *connection;
 } LmIncomingSource;
 
 struct _LmConnection {
 	/* Parameters */
-	gchar      *server;
-	guint       port;
+	GMainContext *context;
+	gchar        *server;
+	guint         port;
 
-	LmSSL      *ssl;
+	LmSSL        *ssl;
 
-	LmProxy    *proxy;
+	LmProxy      *proxy;
 	
-	LmParser   *parser;
-	gchar      *stream_id;
+	LmParser     *parser;
+	gchar        *stream_id;
 
-	GHashTable *id_handlers;
-	GSList     *handlers[LM_MESSAGE_TYPE_UNKNOWN];
+	GHashTable   *id_handlers;
+	GSList       *handlers[LM_MESSAGE_TYPE_UNKNOWN];
 
 	/* Communication */
-	GIOChannel *io_channel;
-	guint       io_watch_in;
-	guint       io_watch_err;
-	guint       io_watch_hup;
-	guint       fd;
+	GIOChannel   *io_channel;
+	guint         io_watch_in;
+	guint         io_watch_err;
+	guint         io_watch_hup;
+	guint         fd;
 	
-	guint       open_id;
-	LmCallback *open_cb;
+	guint         open_id;
+	LmCallback   *open_cb;
 
-	gboolean    cancel_open;
-	LmCallback *close_cb;
-	LmCallback *auth_cb;
-	LmCallback *register_cb;
+	gboolean      cancel_open;
+	LmCallback   *close_cb;
+	LmCallback   *auth_cb;
+	LmCallback   *register_cb;
 
-	LmCallback *disconnect_cb;
+	LmCallback   *disconnect_cb;
 
-	LmQueue    *incoming_messages;
-	GSource    *incoming_source;
+	LmQueue      *incoming_messages;
+	GSource      *incoming_source;
 
 	LmConnectionState state;
 
-	gint        ref_count;
+	gint          ref_count;
 };
 
 typedef enum {
@@ -170,6 +161,12 @@
 						 LmDisconnectReason reason);
 
 static void     connection_do_connect           (LmConnectData *connect_data);
+static guint    connection_add_watch            (LmConnection  *connection,
+						 GIOChannel    *channel,
+						 GIOCondition   condition,
+						 GIOFunc        func,
+						 gpointer       user_data);
+
 
 
 static GSourceFuncs incoming_funcs = {
@@ -265,8 +262,8 @@
 	lm_queue_push_tail (connection->incoming_messages, m);
 }
 
-static gboolean
-connection_succeeded (LmConnectData *connect_data)
+gboolean
+_lm_connection_succeeded (LmConnectData *connect_data)
 {
 	LmConnection *connection = connect_data->connection;
 	LmMessage    *m;
@@ -313,20 +310,26 @@
 	g_io_channel_set_flags (connection->io_channel,
 				flags & G_IO_FLAG_NONBLOCK, NULL);
 	
-	connection->io_watch_in = g_io_add_watch (connection->io_channel,
-						  G_IO_IN,
-						  (GIOFunc) connection_in_event,
-						  connection);
+	connection->io_watch_in = 
+		connection_add_watch (connection,
+				      connection->io_channel,
+				      G_IO_IN,
+				      (GIOFunc) connection_in_event,
+				      connection);
 	
-	connection->io_watch_err = g_io_add_watch (connection->io_channel, 
-						   G_IO_ERR,
-						   (GIOFunc) connection_error_event,
+	connection->io_watch_err = 
+		connection_add_watch (connection,
+				      connection->io_channel, 
+				      G_IO_ERR,
+				      (GIOFunc) connection_error_event,
 						   connection);
-	connection->io_watch_hup = g_io_add_watch (connection->io_channel,
-						   G_IO_HUP,
-						   (GIOFunc) connection_hup_event,
-						   connection);
-
+	connection->io_watch_hup = 
+		connection_add_watch (connection,
+				      connection->io_channel,
+				      G_IO_HUP,
+				      (GIOFunc) connection_hup_event,
+				      connection);
+	
 	if (!connection_send (connection, 
 			      "<?xml version='1.0' encoding='UTF-8'?>", -1,
 			      NULL)) {
@@ -355,8 +358,8 @@
 	return FALSE;
 }
 
-static void 
-connection_failed_with_error (LmConnectData *connect_data, int error) 
+void 
+_lm_connection_failed_with_error (LmConnectData *connect_data, int error) 
 {
 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
 	       "Connection failed: %s (error %d)\n",
@@ -377,10 +380,10 @@
 	}
 }
 
-static void 
-connection_failed (LmConnectData *connect_data)
+void 
+_lm_connection_failed (LmConnectData *connect_data)
 {
-	connection_failed_with_error (connect_data,errno);
+	_lm_connection_failed_with_error (connect_data,errno);
 }
 	
 static gboolean 
@@ -400,16 +403,10 @@
 		/* get the real error from the socket */
 		getsockopt (connect_data->fd, SOL_SOCKET, SO_ERROR, 
 			    &error, &len);
-		connection_failed_with_error (connect_data, error);
+		_lm_connection_failed_with_error (connect_data, error);
 		return FALSE;
 	} else if (condition == G_IO_OUT) {
-		if (connect_data->connection->proxy) {
-			if (!_lm_proxy_negotiate (connection->proxy, connect_data->fd, connection->server, connection->port)) {
-				connection_failed (connect_data);
-				return FALSE;
-			}
-		}
-		connection_succeeded (connect_data);
+		_lm_connection_succeeded (connect_data);
 	} else {
 		g_assert_not_reached ();
 	}
@@ -454,7 +451,7 @@
 		     addr->ai_protocol);
 	
 	if (fd < 0) {
-		connection_failed (connect_data);
+		_lm_connection_failed (connect_data);
 		return;
 	}
 
@@ -466,16 +463,50 @@
 	
 	if (res < 0 && errno != EINPROGRESS) {
 		close (fd);
-		connection_failed (connect_data);
+		_lm_connection_failed (connect_data);
 		return;
 	}
 	
 	connect_data->io_channel = g_io_channel_unix_new (fd);
-	g_io_add_watch (connect_data->io_channel, G_IO_OUT|G_IO_ERR,
-			(GIOFunc) connection_connect_cb, connect_data);
+	if (connection->proxy) {
+		connection_add_watch (connection,
+				      connect_data->io_channel,
+				      G_IO_OUT|G_IO_ERR,
+				      (GIOFunc) _lm_proxy_connect_cb, 
+				      connect_data);
+	} else {
+		connection_add_watch (connection,
+				      connect_data->io_channel,
+				      G_IO_OUT|G_IO_ERR,
+				      (GIOFunc) connection_connect_cb,
+				      connect_data);
+	}
+
 	return;
 }
 
+static guint
+connection_add_watch (LmConnection *connection,
+		      GIOChannel   *channel,
+		      GIOCondition  condition,
+		      GIOFunc       func,
+		      gpointer      user_data)
+{
+	GSource *source;
+	guint    id;
+                                                                                
+	g_return_val_if_fail (channel != NULL, 0);
+                                                                                
+	source = g_io_create_watch (channel, condition);
+                                                                                
+	g_source_set_callback (source, (GSourceFunc)func, user_data, NULL);
+                                                                                
+	id = g_source_attach (source, connection->context);
+	g_source_unref (source);
+  
+	return id;
+}
+
 /* Returns directly */
 /* Setups all data needed to start the connection attempts */
 static gboolean
@@ -503,7 +534,7 @@
 
 	/* source thingie for messages and stuff */
 	connection->incoming_source = connection_create_source (connection);
-	g_source_attach (connection->incoming_source,NULL);
+	g_source_attach (connection->incoming_source, connection->context);
 	
 	lm_verbose ("Connecting to: %s:%d\n", 
 		    connection->server, connection->port);
@@ -1022,7 +1053,8 @@
 	} else {
 		connection->server = NULL;
 	}
-	
+
+	connection->context           = NULL;
 	connection->port              = LM_CONNECTION_DEFAULT_PORT;
 	connection->ssl               = NULL;
 	connection->proxy             = NULL;
@@ -1048,6 +1080,29 @@
 	return connection;
 }
 
+/**
+ * lm_connection_new_with_context:
+ * @server: The hostname to the server for the connection.
+ * @context: The context this connection should be running in.
+ * 
+ * Creates a new closed connection running in a certain context. To open the 
+ * connection call #lm_connection_open. @server can be #NULL but must be set 
+ * before calling #lm_connection_open.
+ * 
+ * Return value: A newly created LmConnection, should be unreffed with lm_connection_unref().
+ **/
+LmConnection *
+lm_connection_new_with_context (const gchar *server, GMainContext *context)
+{
+	LmConnection *connection;
+
+	connection = lm_connection_new (server);
+	connection->context = context;
+
+	g_main_context_ref (connection->context);
+
+	return connection;
+}
 
 /**
  * lm_connection_open:
@@ -1101,8 +1156,8 @@
 	}
 	
 	while ((state = lm_connection_get_state (connection)) == LM_CONNECTION_STATE_CONNECTING) {
-		if (g_main_context_pending (NULL)) {
-			g_main_context_iteration (NULL, TRUE);
+		if (g_main_context_pending (connection->context)) {
+			g_main_context_iteration (connection->context, TRUE);
 		} else {
 			usleep (10);
 		}
@@ -1461,7 +1516,6 @@
 	}
 }
 
-#if 0
 /**
  * lm_connection_get_proxy: 
  * @connection: an #LmConnection
@@ -1485,7 +1539,6 @@
  *
  * Sets the proxy to use for this connection.
  * 
- * Return value: The proxy or %NULL if no proxy is used. Notice that @connection can't be open while doing this.
  **/
 void
 lm_connection_set_proxy (LmConnection *connection, LmProxy *proxy)
@@ -1504,7 +1557,6 @@
 
 	connection->proxy = lm_proxy_ref (proxy);
 }
-#endif
 
 /**
  * lm_connection_send: 
@@ -1614,7 +1666,7 @@
 		const gchar *m_id;
 		gint         n;
 
-		g_main_context_iteration (NULL, TRUE);
+		g_main_context_iteration (connection->context, TRUE);
 	
 		if (lm_queue_is_empty (connection->incoming_messages)) {
 			continue;
@@ -1637,7 +1689,7 @@
 
 	g_free (id);
 	connection->incoming_source = connection_create_source (connection);
-	g_source_attach (connection->incoming_source, NULL);
+	g_source_attach (connection->incoming_source, connection->context);
 
 	return reply;
 }
--- a/loudmouth/lm-connection.h	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/lm-connection.h	Thu Mar 18 00:04:59 2004 +0000
@@ -75,6 +75,8 @@
 						gpointer            user_data);
 
 LmConnection *lm_connection_new               (const gchar        *server);
+LmConnection *lm_connection_new_with_context  (const gchar        *server,
+					       GMainContext       *context);
 gboolean      lm_connection_open              (LmConnection       *connection,
 					       LmResultFunction    function,
 					       gpointer            user_data,
@@ -117,13 +119,9 @@
 LmSSL *       lm_connection_get_ssl           (LmConnection       *connection);
 void          lm_connection_set_ssl           (LmConnection       *connection,
 					       LmSSL              *ssl);
-/*
- * These will most likely change in the API 
- *
 LmProxy *     lm_connection_get_proxy         (LmConnection       *connection);
 void          lm_connection_set_proxy         (LmConnection       *connection,
 					       LmProxy            *proxy);
-*/
 gboolean      lm_connection_send              (LmConnection       *connection,
 					       LmMessage          *message,
 					       GError            **error);
--- a/loudmouth/lm-internals.h	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/lm-internals.h	Thu Mar 18 00:04:59 2004 +0000
@@ -33,6 +33,20 @@
 	GDestroyNotify notify;
 } LmCallback;
 
+typedef struct {
+	LmConnection    *connection;
+
+	/* struct to save resolved address */
+	struct addrinfo *resolved_addrs;
+	struct addrinfo *current_addr;
+	int              fd;
+	GIOChannel           *io_channel;
+} LmConnectData;
+
+void             _lm_connection_failed_with_error (LmConnectData *connect_data,
+                                                   int error);
+void             _lm_connection_failed            (LmConnectData *connect_data);
+gboolean         _lm_connection_succeeded (LmConnectData *connect_data);
 LmCallback *     _lm_utils_new_callback             (gpointer          func, 
 						     gpointer          data,
 						     GDestroyNotify    notify);
@@ -52,6 +66,9 @@
 						     gint              fd,
 						     const gchar      *server,
 						     guint             port);
+gboolean         _lm_proxy_connect_cb               (GIOChannel *source,
+                                                     GIOCondition condition,
+                                                     gpointer data);
 void             _lm_ssl_initialize                 (LmSSL            *ssl);
 gboolean         _lm_ssl_begin                      (LmSSL            *ssl,
 						     gint              fd,
--- a/loudmouth/lm-proxy.c	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/lm-proxy.c	Thu Mar 18 00:04:59 2004 +0000
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2004 Imendio HB
- * Copyright (C) Josh Beam <josh@3ddrome.com>
+ * Copyright (C) 2004 Josh Beam <josh@3ddrome.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License as
@@ -39,6 +39,7 @@
 	guint        port;
 	gchar       *username;
 	gchar       *password;
+	guint        io_watch;
 
         gint         ref_count;
 };
@@ -48,6 +49,12 @@
 					      gint         fd, 
 					      const gchar *server,
 					      guint        port);
+static gboolean      proxy_http_read_cb      (GIOChannel *source,
+                                              GIOCondition condition,
+                                              gpointer data);
+static gboolean      proxy_read_cb      (GIOChannel *source,
+                                              GIOCondition condition,
+                                              gpointer data);
 
 static void
 proxy_free (LmProxy *proxy)
@@ -62,10 +69,10 @@
 static gboolean
 proxy_http_negotiate (LmProxy *proxy, gint fd, const gchar *server, guint port)
 {
-	gint   i, len;
-	gchar  buf[1024];
 	gchar *str;
 
+	g_print ("http negotiate\n");
+	
 	if (proxy->username && proxy->password) {
 		gchar *tmp1;
 		gchar *tmp2;
@@ -88,39 +95,69 @@
 	}
 
 	send (fd, str, strlen (str), 0);
-
 	g_free (str);
+	return TRUE;
+}
 
-	len = read (fd, buf, 12);
-	if (len <= 0) {
+/* returns TRUE when connected through proxy */
+static gboolean
+proxy_http_read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	gchar          buf[512];
+	gsize          bytes_read;
+	GError        *error = NULL;
+
+	g_io_channel_read_chars (source, buf, 512, &bytes_read, &error);
+
+	if (bytes_read < 16) {
 		return FALSE;
 	}
 
-	buf[len] = '\0';
-	if (strcmp (buf, "HTTP/1.1 200") != 0 && 
-	    strcmp (buf, "HTTP/1.0 200") != 0) {
+	if (strncmp (buf, "HTTP/1.1 200", 12) != 0 &&
+	    strncmp (buf, "HTTP/1.0 200", 12) != 0) {
+		return FALSE;
+	}
+
+	if (strncmp (buf + (bytes_read - 4), "\r\n\r\n", 4) != 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;
+}
+
+static gboolean
+proxy_read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	LmConnectData *connect_data;
+	LmConnection  *connection;
+	LmProxy       *proxy;
+	gboolean       retval = FALSE;
+
+	connect_data = (LmConnectData *) data;
+	connection = connect_data->connection;
+	proxy = lm_connection_get_proxy (connection);
+
+	g_return_val_if_fail (proxy != NULL, FALSE);
+
+	if (lm_connection_is_open (connection))
+		return FALSE;
+
+	switch (lm_proxy_get_type (proxy)) {
+	default:
+	case LM_PROXY_TYPE_NONE:
+		g_assert_not_reached ();
+		break;
+	case LM_PROXY_TYPE_HTTP:
+		retval = proxy_http_read_cb (source, condition, data);
+		break;
 	}
 
-	return TRUE;
+	if (retval == TRUE) {
+		g_source_remove (proxy->io_watch);
+		_lm_connection_succeeded ((LmConnectData *) data);
+	}
+
+	return FALSE;
 }
 
 gboolean
@@ -140,6 +177,42 @@
 	return FALSE;
 }
 
+gboolean
+_lm_proxy_connect_cb (GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	LmConnection  *connection;
+	LmConnectData *connect_data;
+	LmProxy       *proxy;
+	int            error;
+	int            len = sizeof(error);
+
+	connect_data = (LmConnectData *) data;
+	connection = connect_data->connection;
+	proxy = lm_connection_get_proxy (connection);
+
+	g_return_val_if_fail (proxy != NULL, FALSE);
+
+	if (condition == G_IO_ERR) {
+		getsockopt (connect_data->fd, SOL_SOCKET, SO_ERROR,
+		            &error, &len);
+		_lm_connection_failed_with_error (connect_data, error);
+		return FALSE;
+	} else if (condition == G_IO_OUT) {
+		if (!_lm_proxy_negotiate (lm_connection_get_proxy (connection), connect_data->fd, lm_connection_get_server (connection), lm_connection_get_port (connection))) {
+			_lm_connection_failed (connect_data);
+			return FALSE;
+		}
+		proxy->io_watch = g_io_add_watch (connect_data->io_channel,
+						  G_IO_IN|G_IO_ERR,
+						  (GIOFunc) proxy_read_cb,
+						  connect_data);
+	} else {
+		g_assert_not_reached ();
+	}
+
+	return FALSE;
+}
+
 /**
  * lm_proxy_new
  * @type: the type of the new proxy
@@ -171,6 +244,31 @@
 }
 
 /**
+ * lm_proxy_new_with_server
+ * @type: the type of the new proxy
+ * @server: the proxy server
+ * @port: the proxy server port
+ * 
+ * Creates a new Proxy. Use #lm_connection_set_proxy to make a connection 
+ * user this proxy.
+ * 
+ * Return value: a newly create proxy
+ **/
+LmProxy *
+lm_proxy_new_with_server (LmProxyType  type,
+			  const gchar *server,
+			  guint        port)
+{
+	LmProxy *proxy;
+
+	proxy = lm_proxy_new (type);
+	lm_proxy_set_server (proxy, server);
+	lm_proxy_set_port (proxy, port);
+
+	return proxy;
+}
+
+/**
  * lm_proxy_get_type
  * @proxy: an #LmProxy
  * 
--- a/loudmouth/lm-proxy.h	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/lm-proxy.h	Thu Mar 18 00:04:59 2004 +0000
@@ -33,6 +33,9 @@
 } LmProxyType;
 
 LmProxy *     lm_proxy_new              (LmProxyType         type);
+LmProxy *     lm_proxy_new_with_server  (LmProxyType         type,
+					 const gchar        *server,
+					 guint               port);
 
 LmProxyType   lm_proxy_get_type         (LmProxy            *proxy);
 void          lm_proxy_set_type         (LmProxy            *proxy,
--- a/loudmouth/loudmouth.h	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/loudmouth.h	Thu Mar 18 00:04:59 2004 +0000
@@ -28,6 +28,7 @@
 #include <loudmouth/lm-message.h>
 #include <loudmouth/lm-message-handler.h>
 #include <loudmouth/lm-message-node.h>
+#include <loudmouth/lm-proxy.h>
 #include <loudmouth/lm-utils.h>
 
 #undef LM_INSIDE_LOUDMOUTH_H
--- a/loudmouth/test-jid.c	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/test-jid.c	Thu Mar 18 00:04:59 2004 +0000
@@ -1,28 +0,0 @@
-#include "lm-jid.h"
-
-int 
-main (int argc, char **argv)
-{
-        int i;
-        
-        if (argc < 2) {
-                g_print ("Usage: %s <jid> <jid> ...\n", argv[0]);
-                exit (1);
-        }
-
-        for (i = 1; i < argc; ++i) {
-                LmJID *jid;
-                
-                jid = lm_jid_new (argv[i]);
-                
-                g_print ("=======( JID[%i] )=======\n", i);
-                g_print ("# Name: '%s'\n", jid->name);
-                g_print ("# Host: '%s'\n", jid->host);
-                if (jid->resource) {
-                        g_print ("# Resource: '%s'\n", jid->resource);
-                }
-                g_print ("-------------------------\n");
-                g_print ("# JID: '%s'\n", lm_jid_to_string (jid));
-                g_print ("=========================\n\n");
-        }
-}
--- a/loudmouth/test-lm.c	Thu Feb 05 22:18:20 2004 +0000
+++ b/loudmouth/test-lm.c	Thu Mar 18 00:04:59 2004 +0000
@@ -1,236 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2003 Imendio HB
- * Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include <glib.h>
-#include <string.h>
-#include <stdlib.h>
-#include <loudmouth/loudmouth.h>
-#ifdef __WIN32__
-#include <winsock2.h>
-#endif
-#include "lm-internals.h"
-
-typedef struct {
-	gchar *name;
-	gchar *passwd;
-} UserInfo;
-
-static void 
-free_user_info (UserInfo *info)
-{
-	g_free (info->name);
-	g_free (info->passwd);
-
-	g_free (info);
-}
-
-static unsigned char expected_fingerprint[20];
-
-static void
-print_finger (const unsigned char *fpr, unsigned int size)
-{
-	gint i;
-	for (i = 0; i < size-1; i++)
-		g_print ("%02X:", (unsigned char) fpr[i]);
-	g_print ("%02X", (unsigned char) fpr[size-1]);
-}
-
-static LmSSLResponse
-ssl_cb (LmSSL *ssl, LmSSLStatus status, gpointer ud)
-{
-	g_print ("SSL status: %d\n", status);
-	switch (status) {
-	case LM_SSL_STATUS_NO_CERT_FOUND:
-		g_print ("No certificate found!\n");
-		break;
-	case LM_SSL_STATUS_UNTRUSTED_CERT:
-		g_print ("Certificate is not trusted!\n"); 
-		break;
-	case LM_SSL_STATUS_CERT_EXPIRED:
-		g_print ("Certificate has expired!\n"); 
-		break;
-	case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
-		g_print ("Certificate has not been activated!\n"); 
-		break;
-	case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
-		g_print ("Certificate hostname does not match expected hostname!\n"); 
-		break;
-	case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH: {
-		const unsigned char *fpr = lm_ssl_get_fingerprint (ssl);
-		g_print ("Certificate fingerprint does not match expected fingerprint!\n"); 
-		g_print ("Remote fingerprint: ");
-		print_finger (fpr, 16);
-		g_print ("\nExpected fingerprint: ");
-		print_finger (expected_fingerprint, 16);
-		g_print ("\n");
-		break;
-	}
-	case LM_SSL_STATUS_GENERIC_ERROR:
-		g_print ("Generic SSL error!\n"); 
-		break;
-	}
-
-	return LM_SSL_RESPONSE_CONTINUE;
-}
-
-static void
-authentication_cb (LmConnection *connection, gboolean result, gpointer ud)
-{
-	g_print ("Auth: %d\n", result);
-
-	if (result == TRUE) {
-		LmMessage *m;
-		
-		m = lm_message_new_with_sub_type (NULL,
-						  LM_MESSAGE_TYPE_PRESENCE,
-						  LM_MESSAGE_SUB_TYPE_AVAILABLE);
-		g_print (":: %s\n", lm_message_node_to_string (m->node));
-		
-		lm_connection_send (connection, m, NULL);
-		lm_message_unref (m);
-	}
-}
-
-static void
-connection_open_cb (LmConnection *connection, gboolean result, UserInfo *info)
-{
-	g_print ("Connected callback\n");
-	lm_connection_authenticate (connection,
-				    info->name, info->passwd, "TestLM",
-				    authentication_cb, NULL,FALSE,  NULL);
-	g_print ("Sent auth message\n");
-}
-
-static LmHandlerResult
-handle_messages (LmMessageHandler *handler,
-		 LmConnection     *connection,
-		 LmMessage        *m,
-		 gpointer          user_data)
-{
-	g_print ("Incoming message from: %s\n",
-		 lm_message_node_get_attribute (m->node, "from"));
-
-	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-int 
-main (int argc, char **argv)
-{
-	GMainLoop        *main_loop;
-	LmConnection     *connection;
-	LmMessageHandler *handler;
-	gboolean          result;
-	UserInfo         *info;
-#ifdef __WIN32__
-	WORD wVersionRequested;
-	WSADATA wsaData;
-	int err;
-#endif
-	
-	if (argc < 4) {
-		g_print ("Usage: test-lm <server> <username> <password>\n"
-			 "       test-lm <server> <username> <password> <fingerprint>\n");
-		return 1;
-	}
-
-/* Needed to build on Win32. */
-#ifdef __WIN32__
-	wVersionRequested = MAKEWORD( 2, 2 );
-
-	err = WSAStartup( wVersionRequested, &wsaData );
-	if ( err != 0 ) {
-		/* Tell the user that we could not find a usable */
-		/* WinSock DLL.                                  */
-		return;
-	}
-
-	/* Confirm that the WinSock DLL supports 2.2.*/
-	/* Note that if the DLL supports versions greater    */
-	/* than 2.2 in addition to 2.2, it will still return */
-	/* 2.2 in wVersion since that is the version we      */
-	/* requested.                                        */
-
-	if ( LOBYTE( wsaData.wVersion ) != 2 ||
-			HIBYTE( wsaData.wVersion ) != 2 ) {
-		/* Tell the user that we could not find a usable */
-		/* WinSock DLL.                                  */
-		WSACleanup( );
-		return;
-	}
-#endif
-
-        connection = lm_connection_new (argv[1]);
-
-	if (argc > 4 && !lm_ssl_is_supported ()) {
-		g_error ("No SSL support!");
-		exit (1);
-	}
-
-
-	handler = lm_message_handler_new (handle_messages, NULL, NULL);
-	lm_connection_register_message_handler (connection, handler, 
-						LM_MESSAGE_TYPE_MESSAGE, 
-						LM_HANDLER_PRIORITY_NORMAL);
-	
-	lm_message_handler_unref (handler);
-	
-	info = g_new0 (UserInfo, 1);
-	info->name = g_strdup (argv[2]);
-	info->passwd = g_strdup (argv[3]);
-	
-	if (argc > 4) {
-		int    i;
-		char  *p;
-		LmSSL *ssl;
-		
-		lm_connection_set_port (connection,
-					LM_CONNECTION_DEFAULT_PORT_SSL);
-		
-		for (i = 0, p = argv[4]; *p && *(p+1); i++, p += 3)
-			expected_fingerprint[i] = (unsigned char) g_ascii_strtoull (p, NULL, 16);
-		
-		ssl = lm_ssl_new (expected_fingerprint,
-				  (LmSSLFunction) ssl_cb,
-				  info, 
-				  (GDestroyNotify) free_user_info);
-		
-		lm_connection_set_ssl (connection, ssl);
-
-		lm_ssl_unref (ssl);
-	}
-
-	result = lm_connection_open (connection,
-				     (LmResultFunction) connection_open_cb,
-				     info, NULL, NULL);
-
-	if (!result) {
-		g_print ("Opening connection failed: %d\n", result);
-	} else {
-		g_print ("Returned from the connection_open\n");
-	}
-	
-	main_loop = g_main_loop_new (NULL, FALSE);
-	g_main_loop_run (main_loop);
-
-	return 0;
-}