2006-04-19 Mikael Hallendal <micke@imendio.com>
authorhallski <hallski>
Wed, 19 Apr 2006 11:42:53 +0000
changeset 140 103227122f45
parent 139 2d0dcbb757b3
child 141 f918e888a0aa
2006-04-19 Mikael Hallendal <micke@imendio.com> * Landing a patch by Martyn Russell for Win32. * configure.ac: Updated for Win32 work * examples/*: Updated and improved. * loudmouth/Makefile.am: * loudmouth/lm-connection.c: - Abstracted out the low level socket handling to lm-sock.[ch] to make this file clean from OS dependant socket code. * loudmouth/lm-internals.h: * loudmouth/lm-parser.c: * loudmouth/lm-proxy.c: * loudmouth/lm-sha.c: * loudmouth/lm-utils.c: - Win32 work * loudmouth/lm-sock.[ch]: - Network abstraction layer.
.cvsignore
ChangeLog
configure.ac
docs/reference/tmpl/lm-connection.sgml
docs/reference/tmpl/lm-error.sgml
docs/reference/tmpl/lm-message-handler.sgml
docs/reference/tmpl/lm-message-node.sgml
docs/reference/tmpl/lm-message.sgml
docs/reference/tmpl/lm-proxy.sgml
docs/reference/tmpl/lm-ssl.sgml
docs/reference/tmpl/lm-utils.sgml
examples/lm-send-async.c
examples/lm-send-sync.c
examples/test-http-proxy.c
examples/test-lm.c
loudmouth/Makefile.am
loudmouth/lm-connection.c
loudmouth/lm-internals.h
loudmouth/lm-parser.c
loudmouth/lm-proxy.c
loudmouth/lm-sha.c
loudmouth/lm-sock.c
loudmouth/lm-sock.h
loudmouth/lm-ssl-openssl.c
loudmouth/lm-utils.c
--- a/.cvsignore	Tue Apr 18 13:47:21 2006 +0000
+++ b/.cvsignore	Wed Apr 19 11:42:53 2006 +0000
@@ -6,10 +6,13 @@
 config.log
 config.status
 config.cache
+config.guess
+config.sub
 configure
 libtool
 *.tar.gz
 loudmouth.spec
+ltmain.sh
 stamp-h*
 loudmouth-1.0.pc
 *.swp
--- a/ChangeLog	Tue Apr 18 13:47:21 2006 +0000
+++ b/ChangeLog	Wed Apr 19 11:42:53 2006 +0000
@@ -1,3 +1,22 @@
+2006-04-19  Mikael Hallendal  <micke@imendio.com>
+
+	* Landing a patch by Martyn Russell for Win32.
+
+	* configure.ac: Updated for Win32 work
+	* examples/*: Updated and improved.
+	* loudmouth/Makefile.am:
+	* loudmouth/lm-connection.c:
+	- Abstracted out the low level socket handling to lm-sock.[ch] to make
+	  this file clean from OS dependant socket code.
+	* loudmouth/lm-internals.h:
+	* loudmouth/lm-parser.c:
+	* loudmouth/lm-proxy.c:
+	* loudmouth/lm-sha.c: 
+	* loudmouth/lm-utils.c:
+	- Win32 work
+	* loudmouth/lm-sock.[ch]: 
+	- Network abstraction layer.
+
 2006-04-18  Mikael Hallendal  <micke@imendio.com>
 
 	* loudmouth/lm-ssl-openssl.c: (_lm_ssl_begin):
--- a/configure.ac	Tue Apr 18 13:47:21 2006 +0000
+++ b/configure.ac	Wed Apr 19 11:42:53 2006 +0000
@@ -1,4 +1,4 @@
-AC_INIT(Loudmouth, 1.0.3, loudmouth)
+AC_INIT(Loudmouth, 1.1.1, loudmouth)
 AC_PREREQ(2.59)
 AC_COPYRIGHT([Copyright (C) 2003-2006 Imendio AB])
 
@@ -8,13 +8,48 @@
 
 AM_MAINTAINER_MODE
 
+AC_CANONICAL_HOST
+
+os_win32=no
+
+case "$host_os" in
+  *mingw32*)
+    os_win32=yes
+esac
+
+if test "$os_win32" = "yes"; then
+  if test "$enable_static" = "yes" -o "$enable_static" = ""; then
+    AC_MSG_WARN([Disabling static library build, must build as DLL on Windows.])
+    enable_static=no
+  fi
+
+  if test "$enable_shared" = "no"; then
+    AC_MSG_WARN([Enabling shared library build, must build as DLL on Windows.])
+  fi
+
+  enable_shared=yes
+
+  CFLAGS="$CFLAGS -mms-bitfields"
+  LDFLAGS="$LDFLAGS -no-undefined"
+fi
+
 AC_PROG_CC
 AC_ISC_POSIX
 AC_HEADER_STDC
+AC_LIBTOOL_WIN32_DLL
 AM_PROG_LIBTOOL
 
 AM_PATH_GLIB_2_0
 
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h memory.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h]) 
+AC_CHECK_HEADERS([winsock2.h])
+
+if test "$ac_cv_header_winsock2_h" = "yes"; then
+  # If we have <winsock2.h>, assume we find the functions
+  # in -lws2_32 (ws2_32 is winsock v2, wsock32 is v1.1)
+  LIBS="-lws2_32 -lgdi32 $LIBS"
+fi
+
 IDT_COMPILE_WARNINGS
 
 changequote(,)dnl
@@ -50,7 +85,9 @@
 dnl | Check for gtk-doc. |-------------------------------
 dnl +--------------------+
 
-AC_ARG_WITH(html-dir, [  --with-html-dir=PATH path to installed docs ])
+AC_ARG_WITH(html-dir, 
+            AS_HELP_STRING([--with-html-dir=PATH],
+			   [path to installed docs]))
 
 if test "x$with_html_dir" = "x" ; then
   HTML_DIR='${datadir}/gtk-doc/html'
@@ -60,18 +97,28 @@
 
 AC_SUBST(HTML_DIR)
 
+AC_CHECK_PROG(GTKDOC, gtkdoc-mkdb, true, false)
+
 gtk_doc_min_version=1.0
-AC_MSG_CHECKING([gtk-doc version >= $gtk_doc_min_version])
-if pkg-config --atleast-version=$gtk_doc_min_version gtk-doc; then
-  AC_MSG_RESULT(yes)
-  GTKDOC=true
-else
-  AC_MSG_RESULT(no)
-  GTKDOC=false
+if $GTKDOC ; then 
+  gtk_doc_version=`gtkdoc-mkdb --version`
+  AC_MSG_CHECKING([for gtk-doc version ($gtk_doc_version) >= $gtk_doc_min_version])
+  if perl <<EOF ; then
+    exit (("$gtk_doc_version" =~ /^[[0-9]]+\.[[0-9]]+$/) &&
+          ("$gtk_doc_version" >= "$gtk_doc_min_version") ? 0 : 1);
+EOF
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+    GTKDOC=false
+  fi
 fi
 
 dnl Let people disable the gtk-doc stuff.
-AC_ARG_ENABLE(gtk-doc, [  --enable-gtk-doc  Use gtk-doc to build documentation [default=no]], enable_gtk_doc="$enableval", enable_gtk_doc=no)
+AC_ARG_ENABLE(gtk-doc,
+              AS_HELP_STRING([--enable-gtk-doc=@<:@no/yes/auto@:>@],
+                             [Use gtk-doc to build documentation [[default=auto]]]), ,
+              enable_gtk_doc=auto)
 
 if test x$enable_gtk_doc = xauto ; then
   if test x$GTKDOC = xtrue ; then
@@ -85,7 +132,11 @@
 
 dnl define a MAINT-like variable REBUILD which is set if Perl
 dnl and awk are found, so autogenerated sources can be rebuilt
-AC_ARG_ENABLE(rebuilds, [  --disable-rebuilds      disable all source autogeneration rules],,enable_rebuilds=yes)
+AC_ARG_ENABLE(rebuilds,
+              AS_HELP_STRING([--enable-rebuilds=@<:@no/yes/auto@:>@],
+                             [Enable source autogeneration rules [[default=yes]]]), ,
+              enable_rebuilds=yes)
+
 REBUILD=\#
 if test "x$enable_rebuilds" = "xyes" && \
      test -n "$PERL" && \
@@ -106,8 +157,8 @@
 dnl | Checking for SSL support                               |-
 dnl +--------------------------------------------------------+
 AC_ARG_WITH(ssl,
-	    AS_HELP_STRING([--with-ssl@<:@=gnutls|openssl|no@:>@], 
-			   [Which SSL implementation to use, default is gnutls]),
+	    AS_HELP_STRING([--with-ssl=@<:@gnutls|openssl|no@:>@], 
+			   [Which SSL implementation to use [[default=gnutls]]]),
 	    ac_ssl=$withval,
 	    ac_ssl=gnutls)
 
@@ -122,32 +173,43 @@
 	    )
 
 enable_ssl=no
-if test x$ac_ssl = xgnutls; then
-	dnl Look for GnuTLS
-	AM_PATH_LM_LIBGNUTLS($GNUTLS_REQUIRED, have_libgnutls=yes, have_libgnutls=no)
-	if test x$have_libgnutls = xyes; then
-		CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
-		LIBS="$LIBS $LIBGNUTLS_LIBS"
-		AC_DEFINE(HAVE_GNUTLS, 1, [whether to use GnuTSL support.])
-		enable_ssl=GnuTLS
-	else
-		AC_MSG_ERROR([GnuTLS was not found, use --with-ssl=no|openssl to build without SSL support or with OpenSSL])
-	fi
-elif test x$ac_ssl = xopenssl; then
-	dnl Look for OpenSSL
-	AC_CHECK_HEADERS([openssl/ssl.h])
-	OLDLIBS="$LIBS"
-	AC_CHECK_LIB(crypto, BIO_f_base64, [
-					    AC_CHECK_LIB(ssl, SSL_new, [ SSL_LIB="-lssl -lcrypto"
-									AC_DEFINE(HAVE_OPENSSL, [], [Have OpenSSL]) ], [ have_openssl=no ], [ -lcrypto ])
-					    ], [ have_openssl=no ], [])
+if test "x$ac_ssl" = "xgnutls"; then
+  dnl Look for GnuTLS
+  AM_PATH_LM_LIBGNUTLS($GNUTLS_REQUIRED, have_libgnutls=yes, have_libgnutls=no)
+  if test "x$have_libgnutls" = "xyes"; then
+    CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
+    LIBS="$LIBS $LIBGNUTLS_LIBS"
+    AC_DEFINE(HAVE_GNUTLS, 1, [whether to use GnuTSL support.])
+    enable_ssl=GnuTLS
+  else
+    AC_MSG_ERROR([GnuTLS was not found, use
+		--with-ssl=[[no|openssl]] to build without SSL support or
+		with OpenSSL])
+  fi
+elif test "$ac_ssl" = "openssl"; then
+  dnl Look for OpenSSL
+  AC_CHECK_HEADERS([openssl/ssl.h])
+  OLDLIBS="$LIBS"
+  AC_CHECK_LIB(crypto, 
+	       BIO_f_base64, 
+	       [AC_CHECK_LIB(ssl, 
+		             SSL_new, 
+                             [SSL_LIB="-lssl -lcrypto"
+		             AC_DEFINE(HAVE_OPENSSL, 
+				       [], 
+				       [Have OpenSSL])], 
+		             [have_openssl=no], 
+			     [-lcrypto])], 
+	       [have_openssl=no], 
+	       [])
 
-	if test x$have_openssl = xno; then
-		AC_MSG_ERROR([OpenSSL was not found, use --with-ssl=no|gnutls to build without SSL support or with GnuTLS])
-	else 
-		LIBS="$OLDLIBS $SSL_LIB"
-		enable_ssl=OpenSSL
-	fi
+  if test "x$have_openssl" = "xno"; then
+    AC_MSG_ERROR([OpenSSL was not found, use --with-ssl=[[no|gnutls]] to
+                  build without SSL support or with GnuTLS])
+  else 
+    LIBS="$OLDLIBS $SSL_LIB"
+    enable_ssl=OpenSSL
+  fi
 else
 	echo "Disabling SSL support"
 fi
@@ -178,9 +240,10 @@
 dnl | Debug output |-------------------------------------------
 dnl +--------------+
 
-AC_ARG_ENABLE(debug, 
-	      [  --enable-debug          Enable debug output [default=yes]],
-	      enable_debug="$enableval", enable_debug=yes, enable_debug=no)
+AC_ARG_ENABLE(debug,
+              AS_HELP_STRING([--enable-debug=@<:@no/yes/auto@:>@],
+                             [Enable debugging [[default=yes]]]), ,
+              enable_debug=yes)
 
 if test x$enable_debug = xno ; then
 	echo "Debugging disabled"
@@ -192,8 +255,6 @@
 AC_SUBST(LOUDMOUTH_CFLAGS)
 AC_SUBST(LOUDMOUTH_LIBS)
 
-dnl Gtk doc
-GTK_DOC_CHECK(1.0)
 
 dnl +--------------------------------------+
 dnl | Check if we shoudl build C# bindings |-------------------
@@ -245,7 +306,8 @@
         Enable SSL                ${enable_ssl}
         Enable Debug:             ${enable_debug}
 	Enable Unit Tests:        ${have_check}
-
+	Enable Documentation      ${enable_gtk_doc}
+	
         Now type 'make' to build Loudmouth
 "
 
--- a/docs/reference/tmpl/lm-connection.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-connection.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -51,6 +51,9 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### MACRO LM_CONNECTION ##### -->
 <para>
 Convenience macro used to cast a pointer to a #LmConnection.
--- a/docs/reference/tmpl/lm-error.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-error.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -14,6 +14,9 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### FUNCTION lm_error_quark ##### -->
 <para>
 -
--- a/docs/reference/tmpl/lm-message-handler.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-message-handler.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -14,6 +14,9 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### USER_FUNCTION LmHandleMessageFunction ##### -->
 <para>
 The actual callback function in an #LmMessageHandler. This function is called when an incoming message arrives that haven't been handled by an handler with higher priority.
--- a/docs/reference/tmpl/lm-message-node.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-message-node.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -14,6 +14,9 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT LmMessageNode ##### -->
 <para>
 A struct representing a node in a message. 
--- a/docs/reference/tmpl/lm-message.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-message.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -15,6 +15,9 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT LmMessage ##### -->
 <para>
 Struct 
--- a/docs/reference/tmpl/lm-proxy.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-proxy.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -24,6 +24,9 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT LmProxy ##### -->
 <para>
 This should not be accessed directly. Use the accessor functions as described below.
--- a/docs/reference/tmpl/lm-ssl.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-ssl.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -23,6 +23,9 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
 <!-- ##### STRUCT LmSSL ##### -->
 <para>
 This should not be accessed directly. Use the accessor functions as described below.
--- a/docs/reference/tmpl/lm-utils.sgml	Tue Apr 18 13:47:21 2006 +0000
+++ b/docs/reference/tmpl/lm-utils.sgml	Wed Apr 19 11:42:53 2006 +0000
@@ -14,3 +14,6 @@
 
 </para>
 
+<!-- ##### SECTION Stability_Level ##### -->
+
+
--- a/examples/lm-send-async.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/examples/lm-send-async.c	Wed Apr 19 11:42:53 2006 +0000
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2003 Imendio AB
+ * Copyright (C) 2003-2006 Imendio AB
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -28,159 +28,205 @@
 
 #include <stdlib.h>
 #include <string.h>
+
 #include <loudmouth/loudmouth.h>
 
-typedef struct {
-        const gchar *recipient;
-        const gchar *message;
-} MessageData;
+static GMainLoop *main_loop;
+static gboolean   test_success = FALSE;
+
+static gchar      expected_fingerprint[20];
+
+static gchar     *server = NULL;
+static gint       port = 5222;
+static gchar     *username = NULL;
+static gchar     *password = NULL;
+static gchar     *resource = "lm-send-async";
+static gchar     *recipient = NULL;
+static gchar     *fingerprint = NULL;
+static gchar     *message = "test asynchronous message";
 
-typedef struct {
-        const gchar *username;
-        const gchar *password;
-        const gchar *resource;
-        MessageData *msg_data;
-} ConnectData;
-
-static GMainLoop *main_loop;
+static GOptionEntry entries[] = 
+{
+  { "server", 's', 0, G_OPTION_ARG_STRING, &server, 
+    "Server to connect to", NULL },
+  { "port", 'P', 0, G_OPTION_ARG_INT, &port, 
+    "Port to connect to [default=5222]", NULL },
+  { "username", 'u', 0, G_OPTION_ARG_STRING, &username, 
+    "Username to connect with (e.g. 'user' in user@server.org)", NULL },
+  { "password", 'p', 0, G_OPTION_ARG_STRING, &password, 
+    "Password to try", NULL },
+  { "resource", 'r', 0, G_OPTION_ARG_STRING, &resource, 
+    "Resource connect with [default=lm-send-async]", NULL },
+  { "recipient", 'R', 0, G_OPTION_ARG_STRING, &recipient, 
+    "Recipient to send the message to (e.g. user@server.org)", NULL },
+  { "fingerprint", 'f', 0, G_OPTION_ARG_STRING, &fingerprint, 
+    "SSL Fingerprint to use", NULL },
+  { "message", 'm', 0, G_OPTION_ARG_STRING, &message, 
+    "Message to send to recipient [default=test message]", NULL },
+  { NULL }
+};
 
 static void
-print_usage (const gchar *exec_name) 
+print_finger (const char   *fpr,
+	      unsigned int  size)
+{
+	gint i;
+	for (i = 0; i < size-1; i++) {
+		g_printerr ("%02X:", fpr[i]);
+	}
+	
+	g_printerr ("%02X", fpr[size-1]);
+}
+
+static LmSSLResponse
+ssl_cb (LmSSL       *ssl, 
+	LmSSLStatus  status, 
+	gpointer     ud)
 {
-        g_print ("Usage: %s -s <server> -u <username> -p <password> -m <message> -t <recipient> [--port <port>] [-r <resource>]\n", exec_name);
+	g_print ("LmSendAsync: SSL status:%d\n", status);
+
+	switch (status) {
+	case LM_SSL_STATUS_NO_CERT_FOUND:
+		g_printerr ("LmSendAsync: No certificate found!\n");
+		break;
+	case LM_SSL_STATUS_UNTRUSTED_CERT:
+		g_printerr ("LmSendAsync: Certificate is not trusted!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_EXPIRED:
+		g_printerr ("LmSendAsync: Certificate has expired!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
+		g_printerr ("LmSendAsync: Certificate has not been activated!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
+		g_printerr ("LmSendAsync: Certificate hostname does not match expected hostname!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH: {
+		const char *fpr = lm_ssl_get_fingerprint (ssl);
+		g_printerr ("LmSendAsync: Certificate fingerprint does not match expected fingerprint!\n"); 
+		g_printerr ("LmSendAsync: Remote fingerprint: ");
+		print_finger (fpr, 16);
+
+		g_printerr ("\n"
+			    "LmSendAsync: Expected fingerprint: ");
+		print_finger (expected_fingerprint, 16);
+		g_printerr ("\n");
+		break;
+	}
+	case LM_SSL_STATUS_GENERIC_ERROR:
+		g_printerr ("LmSendAsync: Generic SSL error!\n"); 
+		break;
+	}
+
+	return LM_SSL_RESPONSE_CONTINUE;
 }
 
 static void
 connection_auth_cb (LmConnection *connection, 
                     gboolean      success, 
-                    MessageData  *data)
+                    gpointer      user_data)
 {
-        LmMessage *m;
-        gboolean   result;
-        GError    *error = NULL;
+	if (success) {
+		GError    *error = NULL;
+		LmMessage *m;
 
-        if (!success) {
-                g_error ("Authentication failed");
-        }
-        
-        m = lm_message_new (data->recipient, LM_MESSAGE_TYPE_MESSAGE);
-        lm_message_node_add_child (m->node, "body", data->message);
-        
-        result = lm_connection_send (connection, m, &error);
-        lm_message_unref (m);
-        
-        if (!result) {
-                g_error ("lm_connection_send failed");
-        }
+		g_print ("LmSendAsync: Authenticated successfully\n");
+		
+		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_printerr ("LmSendAsync: Failed to send message:'%s'\n", 
+				 lm_message_node_to_string (m->node));
+		} else {
+			g_print ("LmSendAsync: Sent message:'%s'\n", 
+				 lm_message_node_to_string (m->node));
+			test_success = TRUE;
+		}
+		
+		lm_message_unref (m);
+	} else {
+		g_printerr ("LmSendAsync: Failed to authenticate\n");
+	}
 
-        lm_connection_close (connection, NULL);
-        
-        g_main_loop_quit (main_loop);
+	lm_connection_close (connection, NULL);
+	g_main_loop_quit (main_loop);
 }
 
 static void
-connection_open_result_cb (LmConnection *connection,
-                           gboolean      success,
-                           ConnectData  *data)
+connection_open_cb (LmConnection *connection,
+		    gboolean      success,
+		    gpointer      user_data)
 {
-        GError *error = NULL;
-        
-        if (!success) {
-                g_error ("Connection failed");
-        }
-
-        if (!lm_connection_authenticate (connection, data->username,
-                                         data->password, data->resource,
-                                         (LmResultFunction) connection_auth_cb,
-                                         data->msg_data,
-                                         g_free,
-                                         &error)) {
-                g_error ("lm_connection_authenticate failed");
-        }
+	if (success) {
+		if (!lm_connection_authenticate (connection, username, 
+						 password, resource,
+						 connection_auth_cb, 
+						 NULL, FALSE,  NULL)) {
+			g_printerr ("LmSendAsync: Failed to send authentication\n");
+			g_main_loop_quit (main_loop);
+			return;
+		}
+		
+		g_print ("LmSendAsync: Sent authentication message\n");
+	} else {
+		g_printerr ("LmSendAsync: Failed to connect\n");
+		g_main_loop_quit (main_loop);
+	}
 }
 
 int
 main (int argc, char **argv)
 {
-        LmConnection *connection;
-	GMainContext *context;
-        const gchar  *server = NULL;
-        const gchar  *resource = "jabber-send";
-        const gchar  *recipient = NULL;
-        const gchar  *message = NULL;
-        const gchar  *username = NULL;
-        const gchar  *password = NULL;
-        guint         port = LM_CONNECTION_DEFAULT_PORT;
-        MessageData  *msg_data;
-        ConnectData  *connect_data;
-        GError       *error = NULL;
-        gint          i;
+	GMainContext   *main_context;
+	GOptionContext *context;
+        LmConnection   *connection;
+
+	context = g_option_context_new ("- test send message asynchronously");
+	g_option_context_add_main_entries (context, entries, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+	
+	if (!server || !username || !password || !recipient) {
+		g_printerr ("For usage, try %s --help\n", argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	main_context = g_main_context_new ();
+        connection = lm_connection_new_with_context (server, main_context);
+	lm_connection_set_port (connection, port);
 
-        for (i = 1; i < argc - 1; ++i) {
-                gboolean arg = FALSE;
-                
-                if (strcmp ("-s", argv[i]) == 0) {
-                        server = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("--port", argv[i]) == 0) {
-                        port = atoi (argv[i+1]);
-                        arg = TRUE;
-                }
-                else if (strcmp ("-m", argv[i]) == 0) {
-                        message = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-r", argv[i]) == 0) {
-                        resource = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-t", argv[i]) == 0) {
-                        recipient = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-u", argv[i]) == 0) {
-                        username = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-p", argv[i]) == 0) {
-                        password = argv[i+1];
-                        arg = TRUE;
-                }
+	if (fingerprint) {
+		LmSSL *ssl;
+		char  *p;
+		int    i;
+		
+		if (port == LM_CONNECTION_DEFAULT_PORT) {
+			lm_connection_set_port (connection,
+						LM_CONNECTION_DEFAULT_PORT_SSL);
+		}
 
-                if (arg) {
-                        ++i;
-                }
+		for (i = 0, p = fingerprint; *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,
+				  NULL, NULL);
+	
+		lm_connection_set_ssl (connection, ssl);
+		lm_ssl_unref (ssl);
+	}
+
+	if (!lm_connection_open (connection, 
+                                 (LmResultFunction) connection_open_cb,
+                                 NULL, NULL, NULL)) {
+                g_printerr ("LmSendAsync: Could not open a connection\n");
+		return EXIT_FAILURE;
         }
 
-        if (!server || !message || !recipient || !username || !password) {
-                print_usage (argv[0]);
-                return -1;
-        }
-        
-	context = g_main_context_new ();
-        connection = lm_connection_new_with_context (server, context);
-
-        msg_data = g_new0 (MessageData, 1);
-        msg_data->recipient = recipient;
-        msg_data->message = message;
-       
-        connect_data = g_new0 (ConnectData, 1);
-        connect_data->username = username;
-        connect_data->password = password;
-        connect_data->resource = resource;
-        connect_data->msg_data = msg_data;
-        
-        if (!lm_connection_open (connection, 
-                                 (LmResultFunction) connection_open_result_cb,
-                                 connect_data,
-                                 g_free,
-                                 &error)) {
-                g_error ("lm_connection_open failed");
-        }
-
-        main_loop = g_main_loop_new (context, FALSE);
+        main_loop = g_main_loop_new (main_context, FALSE);
         g_main_loop_run (main_loop);
 
-        return 0;
+	return (test_success ? EXIT_SUCCESS : EXIT_FAILURE);
 }
--- a/examples/lm-send-sync.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/examples/lm-send-sync.c	Wed Apr 19 11:42:53 2006 +0000
@@ -26,90 +26,159 @@
  * gcc -o lm-send-sync `pkg-config --cflags --libs loudmouth-1.0` lm-send-sync.c
  */
 
-#include <loudmouth/loudmouth.h>
 #include <string.h>
 #include <stdlib.h>
 
+#include <loudmouth/loudmouth.h>
+
+static gchar      expected_fingerprint[20];
+
+static gchar     *server = NULL;
+static gint       port = 5222;
+static gchar     *username = NULL;
+static gchar     *password = NULL;
+static gchar     *resource = "lm-send-sync";
+static gchar     *recipient = NULL;
+static gchar     *fingerprint = NULL;
+static gchar     *message = "test synchronous message";
+
+static GOptionEntry entries[] = 
+{
+  { "server", 's', 0, G_OPTION_ARG_STRING, &server, 
+    "Server to connect to", NULL },
+  { "port", 'P', 0, G_OPTION_ARG_INT, &port, 
+    "Port to connect to [default=5222]", NULL },
+  { "username", 'u', 0, G_OPTION_ARG_STRING, &username, 
+    "Username to connect with (e.g. 'user' in user@server.org)", NULL },
+  { "password", 'p', 0, G_OPTION_ARG_STRING, &password, 
+    "Password to try", NULL },
+  { "resource", 'r', 0, G_OPTION_ARG_STRING, &resource, 
+    "Resource connect with [default=lm-send-sync]", NULL },
+  { "recipient", 'R', 0, G_OPTION_ARG_STRING, &recipient, 
+    "Recipient to send the message to (e.g. user@server.org)", NULL },
+  { "fingerprint", 'f', 0, G_OPTION_ARG_STRING, &fingerprint, 
+    "SSL Fingerprint to use", NULL },
+  { "message", 'm', 0, G_OPTION_ARG_STRING, &message, 
+    "Message to send to recipient [default=test synchronous message]", NULL },
+  { NULL }
+};
+
 static void
-print_usage (const gchar *exec_name) 
+print_finger (const char   *fpr,
+	      unsigned int  size)
+{
+	gint i;
+	for (i = 0; i < size-1; i++) {
+		g_printerr ("%02X:", fpr[i]);
+	}
+	
+	g_printerr ("%02X", fpr[size-1]);
+}
+
+static LmSSLResponse
+ssl_cb (LmSSL       *ssl, 
+	LmSSLStatus  status, 
+	gpointer     ud)
 {
-        g_print ("Usage: %s -s <server> -u <username> -p <password> -m <message> -t <recipient> [--port <port>] [-r <resource>]\n", exec_name);
+	g_print ("LmSendSync: SSL status:%d\n", status);
+
+	switch (status) {
+	case LM_SSL_STATUS_NO_CERT_FOUND:
+		g_printerr ("LmSendSync: No certificate found!\n");
+		break;
+	case LM_SSL_STATUS_UNTRUSTED_CERT:
+		g_printerr ("LmSendSync: Certificate is not trusted!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_EXPIRED:
+		g_printerr ("LmSendSync: Certificate has expired!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
+		g_printerr ("LmSendSync: Certificate has not been activated!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
+		g_printerr ("LmSendSync: Certificate hostname does not match expected hostname!\n"); 
+		break;
+	case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH: {
+		const char *fpr = lm_ssl_get_fingerprint (ssl);
+		g_printerr ("LmSendSync: Certificate fingerprint does not match expected fingerprint!\n"); 
+		g_printerr ("LmSendSync: Remote fingerprint: ");
+		print_finger (fpr, 16);
+
+		g_printerr ("\n"
+			    "LmSendSync: Expected fingerprint: ");
+		print_finger (expected_fingerprint, 16);
+		g_printerr ("\n");
+		break;
+	}
+	case LM_SSL_STATUS_GENERIC_ERROR:
+		g_printerr ("LmSendSync: Generic SSL error!\n"); 
+		break;
+	}
+
+	return LM_SSL_RESPONSE_CONTINUE;
 }
 
 int
 main (int argc, char **argv)
 {
-        LmConnection *connection;
-        const gchar  *server = NULL;
-        const gchar  *resource = "jabber-send";
-        const gchar  *recipient = NULL;
-        const gchar  *message = NULL;
-        const gchar  *username = NULL;
-        const gchar  *password = NULL;
-        guint         port = LM_CONNECTION_DEFAULT_PORT;
-        GError       *error = NULL;
-        gint          i;
-	LmMessage    *m;
+	GOptionContext *context;
+	GError         *error = NULL;
+        LmConnection   *connection;
+	LmMessage      *m;
+
+	context = g_option_context_new ("- test send message synchronously");
+	g_option_context_add_main_entries (context, entries, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+	
+	if (!server || !username || !password || !recipient) {
+		g_printerr ("For usage, try %s --help\n", argv[0]);
+		return EXIT_FAILURE;
+	}
+
+        connection = lm_connection_new (server);
+	lm_connection_set_port (connection, port);
 
-        for (i = 1; i < argc - 1; ++i) {
-                gboolean arg = FALSE;
-                
-                if (strcmp ("-s", argv[i]) == 0) {
-                        server = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("--port", argv[i]) == 0) {
-                        port = atoi (argv[i+1]);
-                        arg = TRUE;
-                }
-                else if (strcmp ("-m", argv[i]) == 0) {
-                        message = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-r", argv[i]) == 0) {
-                        resource = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-t", argv[i]) == 0) {
-                        recipient = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-u", argv[i]) == 0) {
-                        username = argv[i+1];
-                        arg = TRUE;
-                }
-                else if (strcmp ("-p", argv[i]) == 0) {
-                        password = argv[i+1];
-                        arg = TRUE;
-                }
+	if (fingerprint) {
+		LmSSL *ssl;
+		char  *p;
+		int    i;
+		
+		if (port == LM_CONNECTION_DEFAULT_PORT) {
+			lm_connection_set_port (connection,
+						LM_CONNECTION_DEFAULT_PORT_SSL);
+		}
 
-                if (arg) {
-                        ++i;
-                }
-        }
-
-        if (!server || !message || !recipient || !username || !password) {
-                print_usage (argv[0]);
-                return -1;
-        }
-        
-        connection = lm_connection_new (server);
+		for (i = 0, p = fingerprint; *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,
+				  NULL, NULL);
+	
+		lm_connection_set_ssl (connection, ssl);
+		lm_ssl_unref (ssl);
+	}
 
         if (!lm_connection_open_and_block (connection, &error)) {
-                g_error ("Failed to open: %s\n", error->message);
+                g_printerr ("LmSendSync: Could not open a connection: %s\n", error->message);
+		return EXIT_FAILURE;
         }
 
 	if (!lm_connection_authenticate_and_block (connection,
 						   username, password, resource,
 						   &error)) {
-		g_error ("Failed to authenticate: %s\n", error->message);
+		g_printerr ("LmSendSync: Failed to authenticate: %s\n", error->message);
+		return EXIT_FAILURE;
 	}
 	
 	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);
+		g_printerr ("LmSendSync: Failed to send message: %s\n", error->message);
+		return EXIT_FAILURE;
 	}
 
 	lm_message_unref (m);
@@ -117,6 +186,6 @@
 	lm_connection_close (connection, NULL);
 	lm_connection_unref (connection);
 	
-        return 0;
+	return EXIT_SUCCESS;
 }
 
--- a/examples/test-http-proxy.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/examples/test-http-proxy.c	Wed Apr 19 11:42:53 2006 +0000
@@ -24,7 +24,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <loudmouth/loudmouth.h>
-#ifdef __WIN32__
+#ifdef G_OS_WIN32
 #include <winsock2.h>
 #endif
  
--- a/examples/test-lm.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/examples/test-lm.c	Wed Apr 19 11:42:53 2006 +0000
@@ -1,7 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2003 Imendio AB
- * Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
+ * Copyright (C) 2003-2006 Imendio AB
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License as
@@ -21,74 +20,90 @@
 
 #include <config.h>
 
-#include <glib.h>
 #include <string.h>
 #include <stdlib.h>
+
+#include <glib.h>
 #include <loudmouth/loudmouth.h>
-#ifdef __WIN32__
-#include <winsock2.h>
-#endif
+
+static GMainLoop *main_loop = NULL;
+static gboolean   test_success = FALSE;
 
-typedef struct {
-	gchar *name;
-	gchar *passwd;
-} UserInfo;
+static gchar      expected_fingerprint[20];
+
+static gchar     *server = NULL;
+static gint       port = 5222;
+static gchar     *username = NULL;
+static gchar     *password = NULL;
+static gchar     *resource = "test-lm";
+static gchar     *fingerprint = NULL;
 
-static void 
-free_user_info (UserInfo *info)
+static GOptionEntry entries[] = 
 {
-	g_free (info->name);
-	g_free (info->passwd);
-
-	g_free (info);
-}
-
-static char expected_fingerprint[20];
+  { "server", 's', 0, G_OPTION_ARG_STRING, &server, 
+    "Server to connect to", NULL },
+  { "port", 'P', 0, G_OPTION_ARG_INT, &port, 
+    "Port to connect to [default=5222]", NULL },
+  { "username", 'u', 0, G_OPTION_ARG_STRING, &username, 
+    "Username to connect with (e.g. 'user' in user@server.org)", NULL },
+  { "password", 'p', 0, G_OPTION_ARG_STRING, &password, 
+    "Password to try", NULL },
+  { "resource", 'r', 0, G_OPTION_ARG_STRING, &resource, 
+    "Resource connect with [default=test-lm]", NULL },
+  { "fingerprint", 'f', 0, G_OPTION_ARG_STRING, &fingerprint, 
+    "SSL Fingerprint to use", NULL },
+  { NULL }
+};
 
 static void
-print_finger (const char *fpr, unsigned int size)
+print_finger (const char   *fpr,
+	      unsigned int  size)
 {
 	gint i;
-	
 	for (i = 0; i < size-1; i++) {
-		g_print ("%02X:", fpr[i]);
+		g_printerr ("%02X:", fpr[i]);
 	}
 	
-	g_print ("%02X", fpr[size-1]);
+	g_printerr ("%02X", fpr[size-1]);
 }
 
 static LmSSLResponse
-ssl_cb (LmSSL *ssl, LmSSLStatus status, gpointer ud)
+ssl_cb (LmSSL       *ssl, 
+	LmSSLStatus  status, 
+	gpointer     ud)
 {
-	g_print ("SSL status: %d\n", status);
+	g_print ("TestLM: SSL status:%d\n", status);
+
 	switch (status) {
 	case LM_SSL_STATUS_NO_CERT_FOUND:
-		g_print ("No certificate found!\n");
+		g_printerr ("TestLM: No certificate found!\n");
 		break;
 	case LM_SSL_STATUS_UNTRUSTED_CERT:
-		g_print ("Certificate is not trusted!\n"); 
+		g_printerr ("TestLM: Certificate is not trusted!\n"); 
 		break;
 	case LM_SSL_STATUS_CERT_EXPIRED:
-		g_print ("Certificate has expired!\n"); 
+		g_printerr ("TestLM: Certificate has expired!\n"); 
 		break;
 	case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
-		g_print ("Certificate has not been activated!\n"); 
+		g_printerr ("TestLM: Certificate has not been activated!\n"); 
 		break;
 	case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
-		g_print ("Certificate hostname does not match expected hostname!\n"); 
+		g_printerr ("TestLM: Certificate hostname does not match expected hostname!\n"); 
 		break;
 	case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH: {
 		const char *fpr = lm_ssl_get_fingerprint (ssl);
-		g_print ("Certificate fingerprint does not match expected fingerprint!\n"); 
-		g_print ("Remote fingerprint: ");
+		g_printerr ("TestLM: Certificate fingerprint does not match expected fingerprint!\n"); 
+		g_printerr ("TestLM: Remote fingerprint: ");
 		print_finger (fpr, 16);
-		g_print ("\nExpected fingerprint: ");
+
+		g_printerr ("\n"
+			    "TestLM: Expected fingerprint: ");
 		print_finger (expected_fingerprint, 16);
-		g_print ("\n");
+		g_printerr ("\n");
 		break;
 	}
 	case LM_SSL_STATUS_GENERIC_ERROR:
-		g_print ("Generic SSL error!\n"); 
+		g_printerr ("TestLM: Generic SSL error!\n"); 
 		break;
 	}
 
@@ -96,31 +111,75 @@
 }
 
 static void
-authentication_cb (LmConnection *connection, gboolean result, gpointer ud)
+connection_auth_cb (LmConnection *connection,
+		    gboolean      success, 
+		    gpointer      user_data)
 {
-	g_print ("Auth: %d\n", result);
-
-	if (result == TRUE) {
+	if (success) {
 		LmMessage *m;
 		
+		test_success = TRUE;
+		g_print ("TestLM: Authenticated successfully\n");
+
 		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);
+		g_print ("TestLM: Sent presence message:'%s'\n", 
+			 lm_message_node_to_string (m->node));
+
 		lm_message_unref (m);
+	} else {
+		g_printerr ("TestLM: Failed to authenticate\n");
+		g_main_loop_quit (main_loop);
 	}
 }
 
 static void
-connection_open_cb (LmConnection *connection, gboolean result, UserInfo *info)
+connection_open_cb (LmConnection *connection, 
+		    gboolean      success,
+		    gpointer      user_data)
+{
+	if (success) {
+		lm_connection_authenticate (connection, username, 
+					    password, resource,
+					    connection_auth_cb, 
+					    NULL, FALSE,  NULL);
+		
+		g_print ("TestLM: Sent authentication message\n");
+	} else {
+		g_printerr ("TestLM: Failed to connect\n");
+		g_main_loop_quit (main_loop);
+	}
+}
+
+static void
+connection_close_cb (LmConnection       *connection, 
+		     LmDisconnectReason  reason,
+		     gpointer            user_data)
 {
-	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");
+	const char *str;
+	
+	switch (reason) {
+	case LM_DISCONNECT_REASON_OK:
+		str = "LM_DISCONNECT_REASON_OK";
+		break;
+	case LM_DISCONNECT_REASON_PING_TIME_OUT:
+		str = "LM_DISCONNECT_REASON_PING_TIME_OUT";
+		break;
+	case LM_DISCONNECT_REASON_HUP:
+		str = "LM_DISCONNECT_REASON_HUP";
+		break;
+	case LM_DISCONNECT_REASON_ERROR:
+		str = "LM_DISCONNECT_REASON_ERROR";
+		break;
+	case LM_DISCONNECT_REASON_UNKNOWN:
+	default:
+		str = "LM_DISCONNECT_REASON_UNKNOWN";
+		break;
+	}
+
+	g_print ("TestLM: Disconnected, reason:%d->'%s'\n", reason, str);
 }
 
 static LmHandlerResult
@@ -129,7 +188,7 @@
 		 LmMessage        *m,
 		 gpointer          user_data)
 {
-	g_print ("Incoming message from: %s\n",
+	g_print ("TestLM: Incoming message from: %s\n",
 		 lm_message_node_get_attribute (m->node, "from"));
 
 	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
@@ -138,56 +197,29 @@
 int 
 main (int argc, char **argv)
 {
-	GMainLoop        *main_loop;
+	GOptionContext   *context;
 	LmConnection     *connection;
 	LmMessageHandler *handler;
 	gboolean          result;
-	UserInfo         *info;
-#ifdef __WIN32__
-	WORD wVersionRequested;
-	WSADATA wsaData;
-	int err;
-#endif
+	GError           *error = NULL;
 	
-	if (argc < 4) {
-		g_print ("Usage: test-lm <server> <username> <password>\n"
-			 "       test-lm <server> <username> <password> <fingerprint>\n");
-		return 1;
+	context = g_option_context_new ("- test Loudmouth");
+	g_option_context_add_main_entries (context, entries, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+	
+	if (!server || !username || !password) {
+		g_printerr ("For usage, try %s --help\n", argv[0]);
+		return EXIT_FAILURE;
 	}
 
-/* 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;
+	if (fingerprint && !lm_ssl_is_supported ()) {
+		g_printerr ("TestLM: SSL is not supported in this build\n");
+		return EXIT_FAILURE;
 	}
 
-	/* 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);
-	}
-
+        connection = lm_connection_new (server);
+	lm_connection_set_port (connection, port);
 
 	handler = lm_message_handler_new (handle_messages, NULL, NULL);
 	lm_connection_register_message_handler (connection, handler, 
@@ -196,43 +228,45 @@
 	
 	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;
+	lm_connection_set_disconnect_function (connection,
+					       connection_close_cb,
+					       NULL, NULL);
+
+	if (fingerprint) {
 		LmSSL *ssl;
-		
-		lm_connection_set_port (connection,
-					LM_CONNECTION_DEFAULT_PORT_SSL);
+		char  *p;
+		int    i;
 		
-		for (i = 0, p = argv[4]; *p && *(p+1); i++, p += 3)
+		if (port == LM_CONNECTION_DEFAULT_PORT) {
+			lm_connection_set_port (connection,
+						LM_CONNECTION_DEFAULT_PORT_SSL);
+		}
+
+		for (i = 0, p = fingerprint; *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);
-		
+				  NULL, NULL);
+	
 		lm_connection_set_ssl (connection, ssl);
-
 		lm_ssl_unref (ssl);
 	}
 
 	result = lm_connection_open (connection,
 				     (LmResultFunction) connection_open_cb,
-				     info, NULL, NULL);
+				     NULL, NULL, &error);
 
 	if (!result) {
-		g_print ("Opening connection failed: %d\n", result);
-	} else {
-		g_print ("Returned from the connection_open\n");
+		g_printerr ("TestLM: Opening connection failed, error:%d->'%s'\n", 
+			 error->code, error->message);
+		g_free (error);
+		return EXIT_FAILURE;
 	}
 	
 	main_loop = g_main_loop_new (NULL, FALSE);
 	g_main_loop_run (main_loop);
 
-	return 0;
+	return (test_success ? EXIT_SUCCESS : EXIT_FAILURE);
 }
--- a/loudmouth/Makefile.am	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/Makefile.am	Wed Apr 19 11:42:53 2006 +0000
@@ -40,6 +40,8 @@
 	$(ssl_sources)                  \
 	lm-utils.c			\
 	lm-proxy.c                      \
+	lm-sock.h			\
+	lm-sock.c			\
 	$(NULL)
 
 libloudmouthinclude_HEADERS =		\
--- a/loudmouth/lm-connection.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/lm-connection.c	Wed Apr 19 11:42:53 2006 +0000
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2003-2005 Imendio AB
+ * Copyright (C) 2003-2006 Imendio AB
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License as
@@ -21,19 +21,14 @@
 #include <config.h>
 
 #include <string.h>
-#include <unistd.h>
+#include <sys/stat.h> 
 #include <sys/types.h>
 #include <fcntl.h>
 #include <errno.h>
-#ifndef __WIN32__
-  #include <netdb.h>
-  #include <sys/socket.h>
-  #include <netinet/in.h>
-  #include <sys/time.h>
-#else
-  #include <winsock2.h>
-#endif
 
+#include <glib.h>
+
+#include "lm-sock.h"
 #include "lm-debug.h"
 #include "lm-error.h"
 #include "lm-internals.h"
@@ -76,12 +71,15 @@
 	guint         io_watch_in;
 	guint         io_watch_err;
 	guint         io_watch_hup;
-	guint         fd;
+	LmSocket      fd;
 	guint         io_watch_connect;
 	
 	guint         open_id;
 	LmCallback   *open_cb;
 
+ 	gboolean      async_connect_waiting;
+	gboolean      blocking;
+
 	gboolean      cancel_open;
 	LmCallback   *close_cb;
 	LmCallback   *auth_cb;
@@ -309,12 +307,11 @@
 	g_queue_push_tail (connection->incoming_messages, m);
 }
 
-gboolean
+void
 _lm_connection_succeeded (LmConnectData *connect_data)
 {
 	LmConnection *connection;
 	LmMessage    *m;
-	GIOFlags      flags;
 	gchar        *server_from_jid;
 	gchar        *ch;
 
@@ -328,72 +325,86 @@
 
 	/* Need some way to report error/success */
 	if (connection->cancel_open) {
-		return FALSE;
+		lm_verbose ("Cancelling connection...\n");
+		return;
 	}
 	
 	connection->fd = connect_data->fd;
 	connection->io_channel = connect_data->io_channel;
 
 	freeaddrinfo (connect_data->resolved_addrs);
-
-	/* don't need this anymore */
-	g_free(connect_data);
-
-	flags = g_io_channel_get_flags (connection->io_channel);
-
-	/* unset the nonblock flag */
-	flags &= ~G_IO_FLAG_NONBLOCK;
-	
-	/* unset the nonblocking stuff for some time, because GNUTLS doesn't 
-	 * like that */
-	g_io_channel_set_flags (connection->io_channel, flags, NULL);
+	g_free (connect_data);
 
 	if (connection->ssl) {
+		GError *error = NULL;
+
+		lm_verbose ("Setting up SSL...\n");
+	
+#ifdef HAVE_GNUTLS
+		/* GNU TLS requires the socket to be blocking */
+		_lm_sock_set_blocking (connection->fd, TRUE);
+#endif
+
 		if (!_lm_ssl_begin (connection->ssl, connection->fd,
 				    connection->server,
-				    NULL)) {
-			shutdown (connection->fd, SHUT_RDWR);
-			close (connection->fd);
-		
+				    &error)) {
+			lm_verbose ("Could not begin SSL\n");
+				    
+			if (error) {
+				g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+				       "%s\n", error->message);
+				g_error_free (error);
+			}
+
+ 			_lm_sock_shutdown (connection->fd);
+ 			_lm_sock_close (connection->fd);
+
 			connection_do_close (connection);
-			return FALSE;
+
+			return;
 		}
+	
+#ifdef HAVE_GNUTLS
+		_lm_sock_set_blocking (connection->fd, FALSE); 
+#endif
 	}
-	
-	g_io_channel_set_close_on_unref (connection->io_channel, TRUE);
-	g_io_channel_set_encoding (connection->io_channel, NULL, NULL);
-	
-	g_io_channel_set_buffered (connection->io_channel, FALSE);
-	g_io_channel_set_flags (connection->io_channel,
-				flags & G_IO_FLAG_NONBLOCK, NULL);
-	
+
 	connection->io_watch_in = 
 		connection_add_watch (connection,
 				      connection->io_channel,
 				      G_IO_IN,
 				      (GIOFunc) connection_in_event,
 				      connection);
-	
-	connection->io_watch_err = 
-		connection_add_watch (connection,
-				      connection->io_channel, 
-				      G_IO_ERR,
-				      (GIOFunc) connection_error_event,
-						   connection);
-	connection->io_watch_hup = 
-		connection_add_watch (connection,
-				      connection->io_channel,
-				      G_IO_HUP,
-				      (GIOFunc) connection_hup_event,
-				      connection);
+
+	/* FIXME: if we add these, we don't get ANY
+	 * response from the server, this is to do with the way that
+	 * windows handles watches, see bug #331214.
+	 */
+#ifndef G_OS_WIN32
+		connection->io_watch_err =
+			connection_add_watch (connection,
+					      connection->io_channel,
+					      G_IO_ERR,
+					      (GIOFunc) connection_error_event,
+					      connection);
+		
+		connection->io_watch_hup =
+			connection_add_watch (connection,
+					      connection->io_channel,
+					      G_IO_HUP,
+					      (GIOFunc) connection_hup_event,
+					      connection);
+#endif
 
 	/* FIXME: Set up according to XMPP 1.0 specification */
 	/*        StartTLS and the like */
 	if (!connection_send (connection, 
 			      "<?xml version='1.0' encoding='UTF-8'?>", -1,
 			      NULL)) {
+		lm_verbose ("Failed to send xml version and encoding\n");
 		connection_do_close (connection);
-		return FALSE;
+
+		return;
 	}
 
 	if (connection->jid != NULL && (ch = strchr (connection->jid, '@')) != NULL) {
@@ -410,17 +421,13 @@
 					NULL);
 	
 	lm_verbose ("Opening stream...");
-	
+
 	if (!lm_connection_send (connection, m, NULL)) {
-		lm_message_unref (m);
+		lm_verbose ("Failed to send stream information\n");
 		connection_do_close (connection);
-		return FALSE;
 	}
 		
 	lm_message_unref (m);
-
-	/* Success */
-	return FALSE;
 }
 
 void 
@@ -430,7 +437,7 @@
 	
 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
 	       "Connection failed: %s (error %d)\n",
-	       strerror (error), error);
+	       _lm_sock_get_error_str (error), error);
 	
 	connection = connect_data->connection;
 	
@@ -444,6 +451,7 @@
 
 	if (connect_data->io_channel != NULL) {
 		g_io_channel_unref (connect_data->io_channel);
+		/* FIXME: need to check for last unref and close the socket */
 	}
 	
 	if (connect_data->current_addr == NULL) {
@@ -466,43 +474,106 @@
 void 
 _lm_connection_failed (LmConnectData *connect_data)
 {
-	_lm_connection_failed_with_error (connect_data,errno);
+	_lm_connection_failed_with_error (connect_data, 
+					  _lm_sock_get_last_error());
 }
 	
 static gboolean 
 connection_connect_cb (GIOChannel   *source, 
 		       GIOCondition  condition,
-		       gpointer      data) 
+		       LmConnectData *connect_data) 
 {
-	LmConnectData *connect_data;
-	int            error;
-	guint          len  = sizeof(error);
+	LmConnection    *connection;
+	struct addrinfo *addr;
+	int              err;
+	socklen_t        len;
+	LmSocket         fd; 
 
-	connect_data = (LmConnectData *) data;
+	connection = connect_data->connection;
+	addr = connect_data->current_addr;
+	fd = g_io_channel_unix_get_fd (source);
 	
 	if (condition == G_IO_ERR) {
-		/* get the real error from the socket */
-		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) {
-		_lm_connection_succeeded (connect_data);
-	} else {
-		g_assert_not_reached ();
+		_lm_sock_get_error (fd, &err, &len);
+		if (!_lm_sock_is_blocking_error (err)) {
+			g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+			       "Connection failed.\n");
+
+			_lm_connection_failed_with_error (connect_data, err);
+
+			connection->io_watch_connect = 0;
+			return FALSE;
+		}
 	}
 
-	return FALSE;
+	if (connection->async_connect_waiting) {
+		gint res;
+
+		fd = g_io_channel_unix_get_fd (source);
+
+		res = _lm_sock_connect (fd, addr->ai_addr, (int)addr->ai_addrlen);  
+		if (res < 0) {
+			err = _lm_sock_get_last_error ();
+			if (_lm_sock_is_blocking_success (err)) {
+				connection->async_connect_waiting = FALSE;
+
+				g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+				       "Connection success.\n");
+				
+				_lm_connection_succeeded (connect_data);
+			}
+			
+			if (connection->async_connect_waiting && 
+			    !_lm_sock_is_blocking_error (err)) {
+				g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+				       "Connection failed.\n");
+
+				_lm_sock_close (connect_data->fd);
+				_lm_connection_failed_with_error (connect_data, err);
+
+				connection->io_watch_connect = 0;
+				return FALSE;
+			}
+		} 
+	} else {		
+		/* for blocking sockets, G_IO_OUT means we are connected */
+		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+		       "Connection success.\n");
+		
+		_lm_connection_succeeded (connect_data);
+	}
+
+ 	return TRUE; 
+}
+
+static const char *
+connection_condition_to_str (GIOCondition condition)
+{
+	static char buf[256];
+
+	buf[0] = '\0';
+
+	if(condition & G_IO_ERR)
+		strcat(buf, "G_IO_ERR ");
+	if(condition & G_IO_HUP)
+		strcat(buf, "G_IO_HUP ");
+	if(condition & G_IO_NVAL)
+		strcat(buf, "G_IO_NVAL ");
+	if(condition & G_IO_IN)
+		strcat(buf, "G_IO_IN ");
+	if(condition & G_IO_OUT)
+		strcat(buf, "G_IO_OUT ");
+
+	return buf;
 }
 
 static void
 connection_do_connect (LmConnectData *connect_data) 
 {
 	LmConnection    *connection;
-	int              fd;
-	int              res;
+	LmSocket         fd;
+	int              res, err;
 	int              port;
-	int              flags;
 	char             name[NI_MAXHOST];
 	char             portname[NI_MAXSERV];
 	struct addrinfo *addr;
@@ -518,37 +589,47 @@
 	
 	((struct sockaddr_in *) addr->ai_addr)->sin_port = port;
 
-	getnameinfo (addr->ai_addr,
-		     addr->ai_addrlen,
-		     name,     sizeof (name),
-		     portname, sizeof (portname),
-		     NI_NUMERICHOST | NI_NUMERICSERV);
-
-	g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
-	       "Trying %s port %s...\n", name, portname);
+	res = getnameinfo (addr->ai_addr,
+			   (socklen_t)addr->ai_addrlen,
+			   name,     sizeof (name),
+			   portname, sizeof (portname),
+			   NI_NUMERICHOST | NI_NUMERICSERV);
 	
-	fd = socket (addr->ai_family, 
-		     addr->ai_socktype, 
-		     addr->ai_protocol);
-	
-	if (fd < 0) {
+	if (res < 0) {
 		_lm_connection_failed (connect_data);
 		return;
 	}
 
-	flags = fcntl (fd, F_GETFL, 0);
-	fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+	       "Trying %s port %s...\n", name, portname);
+	
+	fd = _lm_sock_makesocket (addr->ai_family,
+				  addr->ai_socktype, 
+				  addr->ai_protocol);
 	
-	res = connect (fd, addr->ai_addr, addr->ai_addrlen);
-	connect_data->fd = fd;
-	
-	if (res < 0 && errno != EINPROGRESS) {
-		close (fd);
+	if (!_LM_SOCK_VALID (fd)) {
+		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
+		       "Failed making socket, error:%d...\n",
+		       _lm_sock_get_last_error ());
+
 		_lm_connection_failed (connect_data);
+
 		return;
 	}
+
+	/* Even though it says _unix_new(), it is supported by glib on
+	 * win32 because glib does some cool stuff to find out if it
+	 * can treat it as a FD or a windows SOCKET.
+	 */
+	connect_data->fd = fd;
+	connect_data->io_channel = g_io_channel_unix_new (fd);
 	
-	connect_data->io_channel = g_io_channel_unix_new (fd);
+	g_io_channel_set_encoding (connect_data->io_channel, NULL, NULL);
+	g_io_channel_set_buffered (connect_data->io_channel, FALSE);
+
+	_lm_sock_set_blocking (connect_data->fd, 
+			       connection->blocking);
+	
 	if (connection->proxy) {
 		connection->io_watch_connect =
 		connection_add_watch (connection,
@@ -565,7 +646,19 @@
 				      connect_data);
 	}
 
-	return;
+	connection->async_connect_waiting = !connection->blocking;
+
+  	res = _lm_sock_connect (connect_data->fd, 
+				addr->ai_addr, (int)addr->ai_addrlen);  
+	if (res < 0) {
+		err = _lm_sock_get_last_error ();
+		if (!_lm_sock_is_blocking_error (err)) {
+			_lm_sock_close (connect_data->fd);
+			_lm_connection_failed_with_error (connect_data, err);
+
+			return;
+		}
+	}
 }
 
 static guint
@@ -595,7 +688,7 @@
 connection_send_keep_alive (LmConnection *connection)
 { 
 	if (!connection_send (connection, " ", -1, NULL)) {
-		lm_verbose ("Error while sending keep alive package");
+		lm_verbose ("Error while sending keep alive package!\n");
 	}
 
 	return TRUE;
@@ -653,9 +746,13 @@
 	g_string_erase (out_buf, 0, (gsize) b_written);
 	if (out_buf->len == 0) {
 		lm_verbose ("Output buffer is empty, going back to normal output\n");
-		g_source_destroy (g_main_context_find_source_by_id (
-			connection->context, connection->io_watch_out));
-		connection->io_watch_out = 0;
+
+		if (connection->io_watch_out != 0) {
+			g_source_destroy (g_main_context_find_source_by_id (
+						  connection->context, connection->io_watch_out));
+			connection->io_watch_out = 0;
+		}
+
 		g_string_free (out_buf, TRUE);
 		connection->out_buf = NULL;
 		return FALSE;
@@ -707,7 +804,7 @@
 	if (lm_connection_is_open (connection)) {
 		g_set_error (error,
 			     LM_ERROR,
-			     LM_ERROR_CONNECTION_OPEN,
+			     LM_ERROR_CONNECTION_NOT_OPEN,
 			     "Connection is already open, call lm_connection_close() first");
 		return FALSE;
 	}
@@ -735,33 +832,47 @@
 	
 	connection->cancel_open = FALSE;
 	connection->state = LM_CONNECTION_STATE_OPENING;
+	connection->async_connect_waiting = FALSE;
 	
 	if (connection->proxy) {
+		int          err;
 		const gchar *proxy_server;
 
 		proxy_server = lm_proxy_get_server (connection->proxy);
-		/* connect through proxy */
-		g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
-		       "Going to connect to %s\n", proxy_server);
+
+		/* Connect through proxy */
+		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+		       "Going to connect to proxy %s\n", proxy_server);
 
-		if (getaddrinfo (proxy_server, NULL, &req, &ans) != 0) {
+		err = getaddrinfo (proxy_server, NULL, &req, &ans);
+		if (err != 0) {
+			const char *str;
+
+			str = _lm_sock_addrinfo_get_error_str (err);
 			g_set_error (error,
 				     LM_ERROR,                 
 				     LM_ERROR_CONNECTION_FAILED,   
-				     "getaddrinfo() failed");
+				     str);
 			return FALSE;
 		}
-	} else { /* connect directly */
-		g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
+	} else { 
+		int err;
+
+		/* Connect directly */
+		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
 		       "Going to connect to %s\n", 
 		       connection->server);
 
-		if (getaddrinfo (connection->server,
-				 NULL, &req, &ans) != 0) {
+		err = getaddrinfo (connection->server, 
+				   NULL, &req, &ans);
+		if (err != 0) {
+			const char *str;
+
+			str = _lm_sock_addrinfo_get_error_str (err);
 			g_set_error (error,
 				     LM_ERROR,                 
 				     LM_ERROR_CONNECTION_FAILED,   
-				     "getaddrinfo() failed");
+				     str);
 			return FALSE;
 		}
 	}
@@ -789,12 +900,23 @@
 	connection_stop_keep_alive (connection);
 
 	if (connection->io_channel) {
-		g_source_destroy (g_main_context_find_source_by_id (
-			connection->context, connection->io_watch_in));
-		g_source_destroy (g_main_context_find_source_by_id (
-			connection->context, connection->io_watch_err));
-		g_source_destroy (g_main_context_find_source_by_id (
-			connection->context, connection->io_watch_hup));
+		if (connection->io_watch_in != 0) {
+			g_source_destroy (g_main_context_find_source_by_id (
+						  connection->context, connection->io_watch_in));
+			connection->io_watch_in = 0;
+		}
+
+		if (connection->io_watch_err != 0) {
+			g_source_destroy (g_main_context_find_source_by_id (
+						  connection->context, connection->io_watch_err));
+			connection->io_watch_err = 0;
+		}
+
+		if (connection->io_watch_hup != 0) {
+			g_source_destroy (g_main_context_find_source_by_id (
+						  connection->context, connection->io_watch_hup));
+			connection->io_watch_hup = 0;
+		}
 
 		if (connection->io_watch_out != 0) {
 			g_source_destroy (g_main_context_find_source_by_id (
@@ -820,10 +942,12 @@
 	if (!lm_connection_is_open (connection)) {
 		/* lm_connection_is_open is FALSE for state OPENING as well */
 		connection->state = LM_CONNECTION_STATE_CLOSED;
+		connection->async_connect_waiting = FALSE;
 		return;
 	}
 	
 	connection->state = LM_CONNECTION_STATE_CLOSED;
+	connection->async_connect_waiting = FALSE;
 	if (connection->ssl) {
 		_lm_ssl_close (connection->ssl);
 	}
@@ -911,7 +1035,7 @@
 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
 	       "-----------------------------------\n");
 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, "'%s'\n", buf);
-	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
+ 	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET, 
 	       "-----------------------------------\n");
 
 	lm_verbose ("Read: %d chars\n", (int)bytes_read);
@@ -926,12 +1050,13 @@
 			GIOCondition  condition,
 			LmConnection *connection)
 {
+	lm_verbose ("Error event: %d->'%s'\n", 
+		    condition, connection_condition_to_str (condition));
+
 	if (!connection->io_channel) {
 		return FALSE;
 	}
 
-	lm_verbose ("Error event: %d\n", condition);
-	
 	connection_do_close (connection);
 	connection_signal_disconnect (connection, LM_DISCONNECT_REASON_ERROR);
 	
@@ -943,12 +1068,13 @@
 		      GIOCondition  condition,
 		      LmConnection *connection)
 {
+	lm_verbose ("HUP event: %d->'%s'\n", 
+		    condition, connection_condition_to_str (condition));
+
 	if (!connection->io_channel) {
 		return FALSE;
 	}
 
-	lm_verbose ("HUP event\n");
-
 	connection_do_close (connection);
 	connection_signal_disconnect (connection, LM_DISCONNECT_REASON_HUP);
 	
@@ -964,6 +1090,9 @@
 	gint b_written;
 	
 	if (connection->state < LM_CONNECTION_STATE_OPENING) {
+		g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
+		       "Connection is not open.\n");
+
 		g_set_error (error,
 			     LM_ERROR,
 			     LM_ERROR_CONNECTION_NOT_OPEN,
@@ -1297,7 +1426,8 @@
 	gint          i;
 	
 	lm_debug_init ();
-	
+	_lm_sock_library_init ();
+
 	connection = g_new0 (LmConnection, 1);
 
 	if (server) {
@@ -1383,6 +1513,7 @@
 	
 	connection->open_cb = _lm_utils_new_callback (function, 
 						      user_data, notify);
+	connection->blocking = FALSE;
 
 	return connection_do_open (connection, error);
 }
@@ -1405,17 +1536,20 @@
 	g_return_val_if_fail (connection != NULL, FALSE);
 
 	connection->open_cb = NULL;
+	connection->blocking = TRUE;
+
 	result = connection_do_open (connection, error);
 
 	if (result == FALSE) {
 		return FALSE;
 	}
-	
+		
 	while ((state = lm_connection_get_state (connection)) == LM_CONNECTION_STATE_OPENING) {
 		if (g_main_context_pending (connection->context)) {
 			g_main_context_iteration (connection->context, TRUE);
 		} else {
-			usleep (10);
+			/* Sleep for 1 millisecond */
+			g_usleep (1000);
 		}
 	}
 
@@ -2008,7 +2142,7 @@
 
 	while (!reply) {
 		const gchar *m_id;
-		gint         n;
+		guint        n;
 
 		g_main_context_iteration (connection->context, TRUE);
 	
--- a/loudmouth/lm-internals.h	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/lm-internals.h	Wed Apr 19 11:42:53 2006 +0000
@@ -23,9 +23,20 @@
 #ifndef __LM_INTERNALS_H__
 #define __LM_INTERNALS_H__
 
+#include <glib.h>
+
+#include <sys/types.h>
+
 #include "lm-message.h"
 #include "lm-message-handler.h"
 #include "lm-message-node.h"
+#include "lm-sock.h"
+
+#ifndef G_OS_WIN32
+typedef int LmSocket;
+#else  /* G_OS_WIN32 */
+typedef SOCKET LmSocket;
+#endif /* G_OS_WIN32 */
 
 typedef struct {
 	gpointer       func;
@@ -39,14 +50,14 @@
 	/* struct to save resolved address */
 	struct addrinfo *resolved_addrs;
 	struct addrinfo *current_addr;
-	int              fd;
-	GIOChannel           *io_channel;
+	LmSocket         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);
+void             _lm_connection_succeeded         (LmConnectData *connect_data);
 LmCallback *     _lm_utils_new_callback             (gpointer          func, 
 						     gpointer          data,
 						     GDestroyNotify    notify);
@@ -70,6 +81,25 @@
 _lm_message_handler_handle_message                (LmMessageHandler *handler,
 						   LmConnection     *connection,
 						   LmMessage        *messag);
-
+gboolean         _lm_sock_library_init            (void);
+void             _lm_sock_library_shutdown        (void);
+void             _lm_sock_set_blocking            (LmSocket               sock,
+						   gboolean               block);
+void             _lm_sock_shutdown                (LmSocket               sock);
+void             _lm_sock_close                   (LmSocket               sock);
+LmSocket         _lm_sock_makesocket              (int                    af,
+						   int                    type,
+						   int                    protocol);
+int              _lm_sock_connect                 (LmSocket               sock,
+						   const struct sockaddr *name,
+						   int                    namelen);
+gboolean         _lm_sock_is_blocking_error       (int                    err);
+gboolean         _lm_sock_is_blocking_success     (int                    err);
+int              _lm_sock_get_last_error          (void);
+void             _lm_sock_get_error               (LmSocket               sock, 
+						   void                  *error, 
+						   socklen_t             *len);
+const gchar *    _lm_sock_get_error_str           (int                    err);
+const gchar *    _lm_sock_addrinfo_get_error_str  (int                    err);
 
 #endif /* __LM_INTERNALS_H__ */
--- a/loudmouth/lm-parser.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/lm-parser.c	Wed Apr 19 11:42:53 2006 +0000
@@ -252,7 +252,7 @@
         }
         
         if (g_markup_parse_context_parse (parser->context, string, 
-                                          strlen (string), NULL)) {
+                                          (gssize)strlen (string), NULL)) {
         } else {
                 g_warning ("Parsing failed\n");
         }
--- a/loudmouth/lm-proxy.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/lm-proxy.c	Wed Apr 19 11:42:53 2006 +0000
@@ -23,12 +23,17 @@
 
 #include <glib.h>
 #include <string.h>
+
+#ifndef G_OS_WIN32
+
 #include <unistd.h>
-#ifndef __WIN32__
-  #include <sys/socket.h>
-#else 
-  #include <winsock2.h>
-#endif
+#include <sys/socket.h>
+
+#else  /* G_OS_WIN32 */
+
+#include <winsock2.h>
+
+#endif /* G_OS_WIN32 */
 
 #include "lm-internals.h"
 #include "lm-proxy.h"
@@ -187,7 +192,7 @@
 	LmConnectData *connect_data;
 	LmProxy       *proxy;
 	int            error;
-	guint          len = sizeof(error);
+	socklen_t      len;
 
 	connect_data = (LmConnectData *) data;
 	connection = connect_data->connection;
@@ -196,8 +201,7 @@
 	g_return_val_if_fail (proxy != NULL, FALSE);
 
 	if (condition == G_IO_ERR) {
-		getsockopt (connect_data->fd, SOL_SOCKET, SO_ERROR,
-		            &error, &len);
+		_lm_sock_get_error (connect_data->fd, &error, &len);
 		_lm_connection_failed_with_error (connect_data, error);
 		return FALSE;
 	} else if (condition == G_IO_OUT) {
--- a/loudmouth/lm-sha.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/lm-sha.c	Wed Apr 19 11:42:53 2006 +0000
@@ -189,7 +189,7 @@
   setEndian ();
 #endif /* RUNTIME_ENDIAN */
 
-#ifdef __WIN32__
+#ifdef G_OS_WIN32
   sc->totalLength = 0L;
 #else
   sc->totalLength = 0LL;
@@ -597,7 +597,7 @@
   }
 }
 
-#ifdef __WIN32__
+#ifdef G_OS_WIN32
 #define snprintf _snprintf
 #endif
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/lm-sock.c	Wed Apr 19 11:42:53 2006 +0000
@@ -0,0 +1,291 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * 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 <glib/gi18n.h>
+
+#ifndef G_OS_WIN32
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#define LM_SHUTDOWN SHUT_RDWR
+
+#else  /* G_OS_WIN32 */
+
+#include <winsock2.h>
+#define LM_SHUTDOWN SD_BOTH
+
+#endif /* G_OS_WIN32 */
+
+#include "lm-internals.h"
+#include "lm-connection.h"
+#include "lm-sock.h"
+#include "lm-debug.h"
+
+static gboolean initialised = FALSE;
+
+gboolean
+_lm_sock_library_init (void)
+{
+#ifdef G_OS_WIN32
+	WORD    version;
+	WSADATA data;
+	int     error;
+#endif /* G_OS_WIN32 */
+	
+	if (initialised) {
+		return TRUE;
+	}
+
+	lm_verbose ("Socket library initialising...\n");
+	
+#ifdef G_OS_WIN32
+	lm_verbose ("Checking for winsock 2.0 or above...\n");
+	
+	version = MAKEWORD (2, 0);
+		
+	error = WSAStartup (version, &data);
+	if (error != 0) {
+		g_printerr ("WSAStartup() failed, error:%d\n", error);
+		return FALSE;
+	}
+	
+	/* Confirm that the WinSock DLL supports 2.0.
+	 * Note that if the DLL supports versions greater  
+	 * than 2.0 in addition to 2.0, it will still return 
+	 * 2.0 in wVersion since that is the version we      
+	 * requested.                                        
+	 */
+	if (LOBYTE (data.wVersion) != 2 ||
+	    HIBYTE (data.wVersion) != 0) {
+		/* Tell the user that we could not find a usable
+		 * WinSock DLL.                                  
+		 */
+		g_printerr ("Socket library version is not sufficient!\n");
+		WSACleanup ();
+		return FALSE;
+	}
+#endif /* G_OS_WIN32 */
+
+	initialised = TRUE;
+	
+	return TRUE;
+}
+
+void
+_lm_sock_library_shutdown (void)
+{
+	if (!initialised) {
+		return;
+	}
+
+	lm_verbose ("Socket library shutting down...\n");
+
+#ifdef G_OS_WIN32
+	WSACleanup ();
+#endif /* G_OS_WIN32 */
+
+	initialised = FALSE;
+}
+
+void
+_lm_sock_set_blocking (LmSocket sock, 
+		       gboolean block)
+{
+	int res;
+
+#ifndef G_OS_WIN32
+	res = fcntl (sock, F_SETFL, block ? 0 : O_NONBLOCK);
+#else  /* G_OS_WIN32 */
+	u_long mode = (block ? 0 : 1);
+	res = ioctlsocket (sock, FIONBIO, &mode);
+#endif /* G_OS_WIN32 */
+
+	if (res != 0) {
+		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
+		       "Could not set connection to be %s\n",
+		       block ? "blocking" : "non-blocking");
+	}
+}
+
+void
+_lm_sock_shutdown (LmSocket sock)
+{
+	shutdown (sock, LM_SHUTDOWN);
+}
+
+void
+_lm_sock_close (LmSocket sock)
+{
+#ifndef G_OS_WIN32
+	close (sock);
+#else  /* G_OS_WIN32 */
+	closesocket (sock);
+#endif /* G_OS_WIN32 */
+}
+
+LmSocket 
+_lm_sock_makesocket (int af,
+		     int type, 
+		     int protocol)
+{
+	return (LmSocket)socket (af, type, protocol);
+}
+
+int 
+_lm_sock_connect (LmSocket               sock, 
+		  const struct sockaddr *name, 
+		  int                    namelen)
+{
+	return connect (sock, name, namelen);
+}
+
+gboolean
+_lm_sock_is_blocking_error (int err)
+{
+#ifndef G_OS_WIN32
+	return (err == _LM_SOCK_EINPROGRESS);
+#else  /* G_OS_WIN32 */
+	return (err == _LM_SOCK_EINPROGRESS || 
+		err == _LM_SOCK_EWOULDBLOCK || 
+		err == _LM_SOCK_EINVAL);
+#endif /* G_OS_WIN32 */
+}
+
+gboolean
+_lm_sock_is_blocking_success (int err)
+{
+	return (err == _LM_SOCK_EALREADY || err == _LM_SOCK_EISCONN);
+}
+
+int 
+_lm_sock_get_last_error (void)
+{
+#ifndef G_OS_WIN32
+	return errno;
+#else  /* G_OS_WIN32 */
+	return WSAGetLastError ();
+#endif /* G_OS_WIN32 */
+}
+
+void 
+_lm_sock_get_error (LmSocket   sock, 
+		    void      *error, 
+		    socklen_t *len)
+{
+	getsockopt (sock, SOL_SOCKET, SO_ERROR, (void*) error, len);
+}
+
+const gchar *
+_lm_sock_get_error_str (int err)
+{
+#ifndef G_OS_WIN32
+	return strerror (err);
+#else  /* G_OS_WIN32 */
+	switch (err) {
+	case WSAEINTR:              return _("Connect interrupted and canceled");
+	case WSAEACCES:             return _("Permission denied"); 
+	case WSAEFAULT:             return _("Bad address");
+	case WSAEINVAL:             return _("Invalid argument");
+	case WSAEMFILE:             return _("Too many open sockets");
+	case WSAEWOULDBLOCK:        return _("Resource temporarily unavailable");
+	case WSAEINPROGRESS:        return _("Operation now in progress");
+	case WSAEALREADY:           return _("Operation already in progress");
+	case WSAENOTSOCK:           return _("Socket operation on nonsocket");
+	case WSAEDESTADDRREQ:       return _("Destination address required");
+	case WSAEMSGSIZE:           return _("Message too long");
+	case WSAEPROTOTYPE:         return _("Protocol wrong type for socket");
+	case WSAENOPROTOOPT:        return _("Bad protocol option");
+	case WSAEPROTONOSUPPORT:    return _("Protocol not supported");
+	case WSAESOCKTNOSUPPORT:    return _("Socket type not supported");
+	case WSAEOPNOTSUPP:         return _("Operation not supported");
+	case WSAEPFNOSUPPORT:       return _("Protocol family not supported");
+	case WSAEAFNOSUPPORT:       return _("Address family not supported by protocol family");
+	case WSAEADDRINUSE:         return _("Address already in use");
+	case WSAEADDRNOTAVAIL:      return _("Can not assign requested address");
+	case WSAENETDOWN:           return _("Network is down");
+	case WSAENETUNREACH:        return _("Network is unreachable");
+	case WSAENETRESET:          return _("Network dropped connection on reset");
+	case WSAECONNABORTED:       return _("Software caused connection abort");
+	case WSAECONNRESET:         return _("Connection reset by peer");
+	case WSAENOBUFS:            return _("No buffer space available");
+	case WSAEISCONN:            return _("Socket is already connected");
+	case WSAENOTCONN:           return _("Socket is not connected");
+	case WSAESHUTDOWN:          return _("Can not send after socket shutdown");
+	case WSAETIMEDOUT:          return _("Connection timed out");
+	case WSAECONNREFUSED:       return _("Connection refused");
+	case WSAEHOSTDOWN:          return _("Host is down");
+	case WSAEHOSTUNREACH:       return _("No route to host");
+	case WSAEPROCLIM:           return _("Too many processes");
+	case WSASYSNOTREADY:        return _("Network subsystem is unavailable");
+	case WSAVERNOTSUPPORTED:    return _("Winsock library version is out of range ");
+	case WSANOTINITIALISED:     return _("Successful WSAStartup not yet performed");
+	case WSAEDISCON:            return _("Graceful shutdown in progress");
+	case WSATYPE_NOT_FOUND:     return _("Class type not found");
+	case WSAHOST_NOT_FOUND:     return _("Host not found");
+	case WSATRY_AGAIN:          return _("Nonauthoritative host not found");
+	case WSANO_RECOVERY:        return _("This is a nonrecoverable error");
+	case WSANO_DATA:            return _("Valid name, no data record of requested type");
+	case WSA_INVALID_HANDLE:    return _("Specified event object handle is invalid");
+	case WSA_INVALID_PARAMETER: return _("One or more parameters are invalid");
+	case WSA_IO_INCOMPLETE:     return _("Overlapped I/O event object no in signaled state");
+	case WSA_IO_PENDING:        return _("Overlapped operations will complete later");
+	case WSA_NOT_ENOUGH_MEMORY: return _("Insufficient memory available");
+	case WSA_OPERATION_ABORTED: return _("Overlapped operation aborted");
+		/* os dependent */
+	case WSASYSCALLFAILURE:     return _("System call failure");
+	}
+	
+	return _("Unknown");
+#endif /* G_OS_WIN32 */
+}
+
+const gchar *
+_lm_sock_addrinfo_get_error_str (int err)
+{
+	switch (err) {
+	case EAI_AGAIN:    
+		return _("The nameserver failed to return an "
+			 "address, try again later");
+	case EAI_BADFLAGS: 
+		return _("Internal error trying to obtain remote address");
+	case EAI_FAIL:     
+		return _("The nameserver encountered errors "
+			 "looking up this address");
+	case EAI_NODATA:   
+		return _("The remote host exists but no address "
+			 "is available");
+	case EAI_NONAME:   
+		return _("The remote address is unknown");
+	case EAI_FAMILY:
+	case EAI_SERVICE:
+	case EAI_SOCKTYPE:
+		return _("The remote address is not obtainable "
+			 "for that socket type.");
+	default:
+		break;
+	}
+
+	return _("The remote address could not be obtained ");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/lm-sock.h	Wed Apr 19 11:42:53 2006 +0000
@@ -0,0 +1,80 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB 
+ *
+ * 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.
+ */
+
+#ifndef __LM_SOCK_H__
+#define __LM_SOCK_H__
+
+G_BEGIN_DECLS
+
+#if !defined (LM_INSIDE_LOUDMOUTH_H) && !defined (LM_COMPILATION)
+#error "Only <loudmouth/loudmouth.h> can be included directly, this file may di\sappear or change contents."
+#endif
+
+#include <glib.h>
+
+#ifndef G_OS_WIN32
+
+#include <unistd.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#define _LM_SOCK_EINPROGRESS EINPROGRESS
+#define _LM_SOCK_EWOULDBLOCK EWOULDBLOOK
+#define _LM_SOCK_EALREADY    EALREADY
+#define _LM_SOCK_EISCONN     EISCONN
+#define _LM_SOCK_EINVAL      EINVAL
+#define _LM_SOCK_VALID(S)    ((S) >= 0)
+
+#else  /* G_OS_WIN32 */
+
+/* This means that we require Windows XP or above to build on
+ * Windows, the reason for this, is that getaddrinfo() and
+ * freeaddrinfo() require ws2tcpip.h functions that are only available
+ * on these platforms. 
+ *
+ * This MUST be defined before windows.h is included.
+ */
+
+
+#if (_WIN32_WINNT < 0x0501)
+#undef  WINVER
+#define WINVER 0x0501
+#undef  _WIN32_WINNT
+#define _WIN32_WINNT WINVER
+#endif
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#define _LM_SOCK_EINPROGRESS WSAEINPROGRESS
+#define _LM_SOCK_EWOULDBLOCK WSAEWOULDBLOCK
+#define _LM_SOCK_EALREADY    WSAEALREADY
+#define _LM_SOCK_EISCONN     WSAEISCONN
+#define _LM_SOCK_EINVAL      WSAEINVAL
+#define _LM_SOCK_VALID(S)    ((S) != INVALID_SOCKET)
+
+#endif /* G_OS_WIN32 */
+
+G_END_DECLS
+
+#endif /* __LM_SOCK__ */
--- a/loudmouth/lm-ssl-openssl.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/lm-ssl-openssl.c	Wed Apr 19 11:42:53 2006 +0000
@@ -116,7 +116,6 @@
 
 	meth = SSLv23_method ();
 	ssl->ctx = SSL_CTX_new (meth);
-
 }
 
 gboolean
--- a/loudmouth/lm-utils.c	Tue Apr 18 13:47:21 2006 +0000
+++ b/loudmouth/lm-utils.c	Wed Apr 19 11:42:53 2006 +0000
@@ -23,6 +23,12 @@
 #include <stdio.h>
 #include <time.h>
 
+#include <glib.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
 #include "lm-internals.h"
 #include "lm-utils.h"