2003-12-19 Mikael Hallendal <micke@imendio.com>
authorhallski <hallski>
Fri, 19 Dec 2003 22:13:29 +0000
changeset 59 ef952e8c114d
parent 58 fd8010f00952
child 60 8166883bfc54
2003-12-19 Mikael Hallendal <micke@imendio.com> * loudmouth/lm-connection.c: (connection_free): cleaned up a bit. (connection_connect_nonblocking): added, nonblocking connect (connection_do_open): - Use the nonblocking connect - set state (connection_do_close): cleaned up (connection_auth_reply): set state (lm_connection_cancel_open): added (lm_connection_authenticate): set state (lm_connection_is_open): use state (lm_connection_is_authenticated): use state (lm_connection_get_state): added - Part fixes bug #122326
ChangeLog
loudmouth/lm-connection.c
loudmouth/lm-connection.h
loudmouth/lm-error.h
mono/Elements.cs
--- a/ChangeLog	Mon Dec 15 16:26:17 2003 +0000
+++ b/ChangeLog	Fri Dec 19 22:13:29 2003 +0000
@@ -1,3 +1,20 @@
+2003-12-19  Mikael Hallendal  <micke@imendio.com>
+
+	* loudmouth/lm-connection.c: 
+	(connection_free): cleaned up a bit.
+	(connection_connect_nonblocking): added, nonblocking connect
+	(connection_do_open):
+	- Use the nonblocking connect
+	- set state
+	(connection_do_close): cleaned up 
+	(connection_auth_reply): set state
+	(lm_connection_cancel_open): added
+	(lm_connection_authenticate): set state
+	(lm_connection_is_open): use state
+	(lm_connection_is_authenticated): use state
+	(lm_connection_get_state): added
+	- Part fixes bug #122326
+
 2003-12-15  Mikael Hallendal  <micke@imendio.com>
 
 	* README: Updated information about bug reporting
--- a/loudmouth/lm-connection.c	Mon Dec 15 16:26:17 2003 +0000
+++ b/loudmouth/lm-connection.c	Fri Dec 19 22:13:29 2003 +0000
@@ -28,6 +28,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
 #ifndef __WIN32__
   #include <netdb.h>
   #include <sys/socket.h>
@@ -69,9 +71,6 @@
 	gnutls_certificate_client_credentials gnutls_xcred;
 #endif
 	
-	gboolean    is_open;
-	gboolean    is_authenticated;
-	
 	LmParser   *parser;
 	gchar      *stream_id;
 
@@ -84,6 +83,7 @@
 	guint       io_watch_err;
 	guint       io_watch_hup;
 
+	gboolean    cancel_open;
 	LmCallback *open_cb;
 	LmCallback *close_cb;
 	LmCallback *auth_cb;
@@ -94,6 +94,8 @@
 	LmQueue    *incoming_messages;
 	GSource    *incoming_source;
 
+	LmConnectionState state;
+
 	gint        ref_count;
 };
 
@@ -193,8 +195,8 @@
 	}
 
 	g_hash_table_destroy (connection->id_handlers);
-	
-	if (connection->is_open) {
+
+	if (lm_connection_is_open (connection)) {
 		connection_do_close (connection);
 	}
 
@@ -339,6 +341,83 @@
 }
 #endif
 
+static int
+connection_connect_nonblocking (LmConnection *connection,
+				struct  addrinfo *addr,
+				char   *name, 
+				char   *portname)
+{
+	int res;
+	int fd;
+	int flags;
+	fd_set rset, wset;
+	struct timeval tval;
+	
+	((struct sockaddr_in *) addr->ai_addr)->sin_port = htons (connection->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);
+
+	fd = socket (addr->ai_family, 
+		     addr->ai_socktype, 
+		     addr->ai_protocol);
+	if (fd < 0) {
+		return -1;
+	}
+
+	flags = fcntl (fd, F_GETFL, 0);
+	fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+	
+	g_print ("Connecting...");
+	res = connect (fd, addr->ai_addr, addr->ai_addrlen);
+	if (res == 0) {
+		/* connection successfull */
+		return fd;
+	} 
+	
+	if (errno != EINPROGRESS) {
+		close (fd);
+		return -1;
+	}
+
+	FD_ZERO (&rset);
+	FD_SET (fd, &rset);
+	wset = rset;
+	
+	do {
+		if (connection->cancel_open) {
+			return -1;
+		}
+		g_print (".");
+		tval.tv_sec = 0;
+		tval.tv_usec = 10;
+		while (g_main_context_pending (NULL)) {
+			g_main_context_iteration (NULL, FALSE);
+			if (connection->cancel_open) {
+				return -1;
+			}
+		}
+	} while (select (fd + 1, &rset, &wset, NULL, &tval) == 0);
+
+	g_print (" done!\n");
+	
+	/* Either things went fine or we have an error */
+
+	if (FD_ISSET (fd, &rset) && FD_ISSET (fd, &wset)) {
+		close (fd);
+		return -1;
+	}
+
+	return fd;
+}
+							
+
 static gboolean
 connection_do_open (LmConnection    *connection,
 		    const gchar     *fingerprint,
@@ -346,8 +425,8 @@
 		    gpointer         user_data,
 		    GError         **error)
 {
+	gint             err = -1;
 	gint             fd = -1;
-	int              err = -1;
 	struct addrinfo  req;
 	struct addrinfo *ans;
 	struct addrinfo *tmpaddr;
@@ -364,6 +443,9 @@
 
 	g_log (LM_LOG_DOMAIN,LM_LOG_LEVEL_NET,
 	       "Going to connect to %s\n",connection->server);
+
+	connection->cancel_open = FALSE;
+	connection->state = LM_CONNECTION_STATE_CONNECTING;
 	
 	if ((err = getaddrinfo (connection->server, NULL, &req, &ans)) != 0) {
 		g_set_error (error,
@@ -381,6 +463,16 @@
 #endif
 
 	for (tmpaddr = ans ; tmpaddr != NULL ; tmpaddr = tmpaddr->ai_next) {
+		if (connection->cancel_open) {
+			break;
+		}
+		fd = connection_connect_nonblocking (connection, 
+						     tmpaddr, name, portname);
+		if (fd < 0) {
+			break;
+		}
+						     
+#if 0
 		((struct sockaddr_in *) tmpaddr->ai_addr)->sin_port = htons (connection->port);
 
 		getnameinfo (tmpaddr->ai_addr,
@@ -406,6 +498,7 @@
 		}
 		
 		close (fd);
+#endif
 	}
 	
 	freeaddrinfo (ans);
@@ -489,7 +582,7 @@
 						   (GIOFunc) connection_hup_event,
 						   connection);
 
-	connection->is_open = TRUE;
+	connection->state = LM_CONNECTION_STATE_CONNECTED;
 
 	if (!connection_send (connection,
 			      "<?xml version='1.0' encoding='UTF-8'?>", -1, 
@@ -515,11 +608,11 @@
 	g_source_remove (g_source_get_id (connection->incoming_source));
 	g_source_unref (connection->incoming_source);
 
-	if (!connection->is_open) {
+	if (!lm_connection_is_open (connection)) {
 		return;
 	}
 
-	connection->is_open = FALSE;
+	connection->state = LM_CONNECTION_STATE_DISCONNECTED;
 
 #ifdef HAVE_GNUTLS
 	if (connection->use_ssl) {
@@ -845,9 +938,11 @@
 	type = lm_message_node_get_attribute (m->node, "type");
 	if (strcmp (type, "result") == 0) {
 		result = TRUE;
+		connection->state = LM_CONNECTION_STATE_AUTHENTICATED;
 	} 
 	else if (strcmp (type, "error") == 0) {
 		result = FALSE;
+		connection->state = LM_CONNECTION_STATE_CONNECTED;
 	}
 	
 	lm_verbose ("AUTH reply: %d\n", result);
@@ -989,6 +1084,8 @@
 	connection->fingerprint[0]    = '\0';
 	connection->disconnect_cb     = NULL;
 	connection->incoming_messages = lm_queue_new ();
+	connection->cancel_open       = FALSE;
+	connection->state             = LM_CONNECTION_STATE_DISCONNECTED;
 	
 	connection->id_handlers = g_hash_table_new_full (g_str_hash, 
 							 g_str_equal,
@@ -1211,7 +1308,22 @@
 lm_connection_open_and_block (LmConnection *connection,
 			      GError **error)
 {
-	return lm_connection_open_and_block_ssl (connection, NULL, NULL, NULL, error);
+	return lm_connection_open_and_block_ssl (connection, NULL, NULL, 
+						 NULL, error);
+}
+
+/**
+ * lm_connection_cancel_open:
+ * @connection: an #LmConnection to cancel opening on
+ *
+ * Cancels the open operation of a connection. The connection should be in the state #LM_CONNECTION_STATE_CONNECTING.
+ **/
+void
+lm_connection_cancel_open (LmConnection *connection)
+{
+	g_return_if_fail (connection != NULL);
+
+	connection->cancel_open = TRUE;
 }
 
 /**
@@ -1295,6 +1407,8 @@
 			     "Connection is not open, call lm_connection_open() first");
 		return FALSE;
 	}
+
+	connection->state = LM_CONNECTION_STATE_AUTHENTICATING;
 	
 	connection->auth_cb = _lm_utils_new_callback (function, 
 						      user_data, 
@@ -1407,7 +1521,7 @@
 gboolean
 lm_connection_is_open (LmConnection *connection)
 {
-	return connection->is_open;
+	return connection->state >= LM_CONNECTION_STATE_CONNECTED;
 }
 
 /**
@@ -1421,7 +1535,7 @@
 gboolean 
 lm_connection_is_authenticated (LmConnection *connection)
 {
-	return connection->is_authenticated;
+	return connection->state >= LM_CONNECTION_STATE_AUTHENTICATED;
 }
 
 /**
@@ -1784,6 +1898,22 @@
 
 	return connection_send (connection, str, -1, error);
 }
+/**
+ * lm_connection_get_state:
+ * @connection: Connection to get state on
+ *
+ * Returns the state of the connection.
+ *
+ * Return value: The state of the connection.
+ **/
+LmConnectionState 
+lm_connection_get_state (LmConnection *connection)
+{
+	g_return_val_if_fail (connection != NULL, 
+			      LM_CONNECTION_STATE_DISCONNECTED);
+
+	return connection->state;
+}
 
 /**
  * lm_connection_ref:
--- a/loudmouth/lm-connection.h	Mon Dec 15 16:26:17 2003 +0000
+++ b/loudmouth/lm-connection.h	Fri Dec 19 22:13:29 2003 +0000
@@ -1,5 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
+ * Copyright (C) 2003 Imendio HB
  * Copyright (C) 2003 Mikael Hallendal <micke@imendio.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -76,6 +77,14 @@
 	LM_SSL_RESPONSE_STOP,
 } LmSSLResponse;
 
+typedef enum {
+	LM_CONNECTION_STATE_DISCONNECTED,
+	LM_CONNECTION_STATE_CONNECTING,
+	LM_CONNECTION_STATE_CONNECTED,
+	LM_CONNECTION_STATE_AUTHENTICATING,
+	LM_CONNECTION_STATE_AUTHENTICATED
+} LmConnectionState;
+
 typedef void          (* LmResultFunction)     (LmConnection       *connection,
 						gboolean            success,
 						gpointer            user_data);
@@ -111,6 +120,8 @@
 						LmSSLFunction      ssl_function,
 						gpointer           user_data,
 						GError           **error);
+void          lm_connection_cancel_open        (LmConnection      *connection);
+						
 
 gboolean      lm_connection_close             (LmConnection       *connection,
 					       GError            **error);
@@ -173,6 +184,7 @@
 gboolean      lm_connection_send_raw          (LmConnection       *connection,
 					       const gchar        *str,
 					       GError            **error);
+LmConnectionState lm_connection_get_state     (LmConnection       *connection);
 LmConnection* lm_connection_ref               (LmConnection       *connection);
 void          lm_connection_unref             (LmConnection       *connection);
 
--- a/loudmouth/lm-error.h	Mon Dec 15 16:26:17 2003 +0000
+++ b/loudmouth/lm-error.h	Fri Dec 19 22:13:29 2003 +0000
@@ -32,7 +32,8 @@
 typedef enum {
         LM_ERROR_CONNECTION_NOT_OPEN,
         LM_ERROR_CONNECTION_OPEN,
-        LM_ERROR_AUTH_FAILED
+        LM_ERROR_AUTH_FAILED,
+	LM_ERROR_CONNECTION_FAILED
 } LmError;
 
 GQuark lm_error_quark (void) G_GNUC_CONST;
--- a/mono/Elements.cs	Mon Dec 15 16:26:17 2003 +0000
+++ b/mono/Elements.cs	Fri Dec 19 22:13:29 2003 +0000
@@ -102,7 +102,7 @@
     public class Message : Element {
 	public MessageType Type {
 	    get {
-		return (MessageType) lm_message_get_sub_type(this._obj);
+		return (MessageType) this.GetElementSubType ();
 	    }
 	}
 	public string Body {