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.
--- 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"