Added disconnect error for resource conflict. Fixes LM-55.
authorMikael Hallendal <micke@imendio.com>
Sun, 29 Apr 2007 14:16:02 +0200
changeset 262 d372a2b61b1d
parent 261 703c5734ec61
child 263 23192c7973c0
Added disconnect error for resource conflict. Fixes LM-55. Added a disconnection reason for resource conflict (when another client connects with the same resourc). Patch from Martyn Russell.
loudmouth/lm-connection.c
loudmouth/lm-connection.h
--- a/loudmouth/lm-connection.c	Sun Apr 29 13:22:36 2007 +0200
+++ b/loudmouth/lm-connection.c	Sun Apr 29 14:16:02 2007 +0200
@@ -100,6 +100,8 @@
 
 	LmConnectData *connect_data;
 
+	LmDisconnectReason disconnect_reason;
+
 	gint          ref_count;
 };
 
@@ -156,6 +158,8 @@
 					      LmMessage           *m,
 					      gpointer             user_data);
 
+static void     connection_stream_error      (LmConnection        *connection,
+					      LmMessage           *m);
 static void     connection_stream_received   (LmConnection        *connection, 
 					      LmMessage           *m);
 
@@ -279,6 +283,10 @@
 		connection_stream_received (connection, m);
 		goto out;
 	}
+	else if (lm_message_get_type (m) == LM_MESSAGE_TYPE_STREAM_ERROR) {
+		connection_stream_error (connection, m);
+		goto out;
+	}
 	
 	id = lm_message_node_get_attribute (m->node, "id");
 	
@@ -591,6 +599,9 @@
 		_lm_connection_succeeded (connect_data);
 	}
 
+	/* set the default disconnect reason to unknown */
+	connection->disconnect_reason = LM_DISCONNECT_REASON_UNKNOWN;
+
  	return TRUE; 
 }
 
@@ -1108,16 +1119,23 @@
 		switch (status) {
 		case G_IO_STATUS_EOF:
 			reason = LM_DISCONNECT_REASON_HUP;
+			lm_verbose ("Disconnect reason: %d\n", reason);
 			break;
 		case G_IO_STATUS_AGAIN:
 			/* No data readable but we didn't hangup */
 			return FALSE;
 			break;
 		case G_IO_STATUS_ERROR:
-			reason = LM_DISCONNECT_REASON_ERROR;
-			break;
+			/* If no reason set, we set it to ERROR here,
+			 * otherwise it might already have been set by
+			 * the stream error handler.
+			 */
+			if (connection->disconnect_reason == LM_DISCONNECT_REASON_UNKNOWN) {
+				connection->disconnect_reason = LM_DISCONNECT_REASON_ERROR;
+			}
 		default:
-			reason = LM_DISCONNECT_REASON_UNKNOWN;
+			reason = connection->disconnect_reason;
+			lm_verbose ("Disconnect reason: %d\n", reason);
 		}
 
 		connection_do_close (connection);
@@ -1440,6 +1458,35 @@
 	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
 }
 
+static void
+connection_stream_error (LmConnection *connection, LmMessage *m)
+{
+	LmMessageNode *node;
+
+	g_return_if_fail (connection != NULL);
+	g_return_if_fail (m != NULL);
+
+	node = m->node;
+
+	/* Resource conflict */
+	node = lm_message_node_get_child (node, "conflict");
+	if (node) {
+		lm_verbose ("Stream error: Conflict (resource connected elsewhere)\n");
+		connection->disconnect_reason = LM_DISCONNECT_REASON_RESOURCE_CONFLICT;
+		return;
+	}
+
+	/* XML is crack */
+	node = lm_message_node_get_child (node, "xml-not-well-formed");
+	if (node) {
+		lm_verbose ("Stream error: XML not well formed\n");
+		connection->disconnect_reason = LM_DISCONNECT_REASON_INVALID_XML;
+		return;
+	}
+
+	lm_verbose ("Stream error: Unrecognised error\n");
+	connection->disconnect_reason = LM_DISCONNECT_REASON_ERROR;
+}
 
 static void
 connection_stream_received (LmConnection *connection, LmMessage *m)
@@ -1585,6 +1632,7 @@
 							 g_str_equal,
 							 g_free, 
 							 (GDestroyNotify) lm_message_handler_unref);
+	connection->disconnect_reason = LM_DISCONNECT_REASON_UNKNOWN;
 	connection->ref_count         = 1;
 	
 	for (i = 0; i < LM_MESSAGE_TYPE_UNKNOWN; ++i) {
--- a/loudmouth/lm-connection.h	Sun Apr 29 13:22:36 2007 +0200
+++ b/loudmouth/lm-connection.h	Sun Apr 29 14:16:02 2007 +0200
@@ -56,7 +56,9 @@
 	LM_DISCONNECT_REASON_PING_TIME_OUT,
 	LM_DISCONNECT_REASON_HUP,
 	LM_DISCONNECT_REASON_ERROR,
-	LM_DISCONNECT_REASON_UNKNOWN
+	LM_DISCONNECT_REASON_UNKNOWN,
+	LM_DISCONNECT_REASON_RESOURCE_CONFLICT,
+	LM_DISCONNECT_REASON_INVALID_XML
 } LmDisconnectReason;
 
 typedef enum {