changeset 5506:4f72b611f0ee

[gaim-migrate @ 5905] A few changes here. - Messages now have reference counting. - There's a message queue API in servconn. This was needed for times when we have a message but need further information from a command before processing it, like initial e-mail notifications. - As a result of the two above, we now have initial e-mail notifications again! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Sun, 25 May 2003 09:04:32 +0000
parents 870207a49f2f
children b87d7459e7d2
files src/protocols/msn/buddyicon.c src/protocols/msn/buddyicon.h src/protocols/msn/msg.c src/protocols/msn/msg.h src/protocols/msn/msn.c src/protocols/msn/notification.c src/protocols/msn/servconn.c src/protocols/msn/servconn.h src/protocols/msn/switchboard.c
diffstat 9 files changed, 207 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/msn/buddyicon.c	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/buddyicon.c	Sun May 25 09:04:32 2003 +0000
@@ -464,7 +464,7 @@
 }
 
 gboolean
-msn_buddy_icon_msg(MsnServConn *servconn, const MsnMessage *msg)
+msn_buddy_icon_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	if (!strncmp(msn_message_get_body(msg), "ICON", 4))
 		return __process_data(servconn, msg);
--- a/src/protocols/msn/buddyicon.h	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/buddyicon.h	Sun May 25 09:04:32 2003 +0000
@@ -65,7 +65,7 @@
  *
  * @return TRUE
  */
-gboolean msn_buddy_icon_msg(MsnServConn *servconn, const MsnMessage *msg);
+gboolean msn_buddy_icon_msg(MsnServConn *servconn, MsnMessage *msg);
 
 /**
  * Sends a buddy icon invitation message.
--- a/src/protocols/msn/msg.c	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/msg.c	Sun May 25 09:04:32 2003 +0000
@@ -63,6 +63,8 @@
 	msn_message_set_charset(msg, "UTF-8");
 	msn_message_set_flag(msg, 'N');
 
+	msn_message_ref(msg);
+
 	return msg;
 }
 
@@ -174,6 +176,12 @@
 {
 	g_return_if_fail(msg != NULL);
 
+	if (msg->ref_count > 0) {
+		msn_message_unref(msg);
+
+		return;
+	}
+
 	if (msg->sender != NULL)
 		msn_user_unref(msg->sender);
 
@@ -192,9 +200,39 @@
 	g_hash_table_destroy(msg->attr_table);
 	g_list_free(msg->attr_list);
 
+	gaim_debug(GAIM_DEBUG_INFO, "msn", "Destroying message\n");
 	g_free(msg);
 }
 
+MsnMessage *
+msn_message_ref(MsnMessage *msg)
+{
+	g_return_val_if_fail(msg != NULL, NULL);
+
+	msg->ref_count++;
+
+	return msg;
+}
+
+MsnMessage *
+msn_message_unref(MsnMessage *msg)
+{
+	g_return_val_if_fail(msg != NULL, NULL);
+
+	if (msg->ref_count <= 0)
+		return NULL;
+
+	msg->ref_count--;
+
+	if (msg->ref_count == 0) {
+		msn_message_destroy(msg);
+
+		return NULL;
+	}
+
+	return msg;
+}
+
 char *
 msn_message_build_string(const MsnMessage *msg)
 {
--- a/src/protocols/msn/msg.h	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/msg.h	Sun May 25 09:04:32 2003 +0000
@@ -32,6 +32,8 @@
  */
 struct _MsnMessage
 {
+	size_t ref_count;           /**< The reference count.       */
+
 	MsnUser *sender;
 	MsnUser *receiver;
 
@@ -73,6 +75,26 @@
 void msn_message_destroy(MsnMessage *msg);
 
 /**
+ * Increments the reference count on a message.
+ *
+ * @param msg The message.
+ *
+ * @return @a msg
+ */
+MsnMessage *msn_message_ref(MsnMessage *msg);
+
+/**
+ * Decrements the reference count on a message.
+ *
+ * This will destroy the structure if the count hits 0.
+ *
+ * @param msg The message.
+ *
+ * @return @a msg, or @c NULL if the new count is 0.
+ */
+MsnMessage *msn_message_unref(MsnMessage *msg);
+
+/**
  * Converts a message to a string.
  *
  * @param msg The message.
--- a/src/protocols/msn/msn.c	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/msn.c	Sun May 25 09:04:32 2003 +0000
@@ -454,6 +454,7 @@
 		user = msn_user_new(session, who, NULL);
 
 		msg = msn_message_new();
+		msn_message_set_flag(msg, 'D');
 		msn_message_set_receiver(msg, user);
 		msn_message_set_attr(msg, "X-MMS-IM-Format",
 							 "FN=Arial; EF=; CO=0; PF=0");
--- a/src/protocols/msn/notification.c	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/notification.c	Sun May 25 09:04:32 2003 +0000
@@ -1139,7 +1139,7 @@
  * Message Types
  **************************************************************************/
 static gboolean
-__profile_msg(MsnServConn *servconn, const MsnMessage *msg)
+__profile_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	MsnSession *session = servconn->session;
 	const char *value;
@@ -1162,7 +1162,7 @@
 }
 
 static gboolean
-__initial_email_msg(MsnServConn *servconn, const MsnMessage *msg)
+__initial_email_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	MsnSession *session = servconn->session;
 	struct gaim_connection *gc = session->account->gc;
@@ -1176,6 +1176,9 @@
 
 	if (session->passport_info.file == NULL) {
 		msn_servconn_send_command(servconn, "URL", "INBOX");
+
+		msn_servconn_queue_message(servconn, "URL", msg);
+
 		return TRUE;
 	}
 
@@ -1193,7 +1196,7 @@
 }
 
 static gboolean
-__email_msg(MsnServConn *servconn, const MsnMessage *msg)
+__email_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	MsnSession *session = servconn->session;
 	struct gaim_connection *gc = session->account->gc;
@@ -1207,6 +1210,9 @@
 
 	if (session->passport_info.file == NULL) {
 		msn_servconn_send_command(servconn, "URL", "INBOX");
+
+		msn_servconn_queue_message(servconn, "URL", msg);
+
 		return TRUE;
 	}
 
@@ -1229,7 +1235,7 @@
 }
 
 static gboolean
-__system_msg(MsnServConn *servconn, const MsnMessage *msg)
+__system_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	GHashTable *table;
 	const char *type_s;
--- a/src/protocols/msn/servconn.c	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/servconn.c	Sun May 25 09:04:32 2003 +0000
@@ -22,10 +22,40 @@
 #include "msn.h"
 #include "servconn.h"
 
+typedef struct
+{
+	char *command;
+	MsnMessage *msg;
+
+} MsnQueueEntry;
+
+static gboolean
+__process_message(MsnServConn *servconn, MsnMessage *msg)
+{
+	MsnServConnMsgCb cb;
+
+	cb = g_hash_table_lookup(servconn->msg_types,
+							 msn_message_get_content_type(msg));
+
+	if (cb == NULL) {
+		gaim_debug(GAIM_DEBUG_WARNING, "msn",
+				   "Unhandled content-type '%s': %s\n",
+				   msn_message_get_content_type(msg),
+				   msn_message_get_body(msg));
+
+		return FALSE;
+	}
+
+	cb(servconn, msg);
+
+	return TRUE;
+}
+
 static gboolean
 __process_single_line(MsnServConn *servconn, char *str)
 {
 	MsnServConnCommandCb cb;
+	GSList *l, *l_next;
 	gboolean result;
 	size_t param_count = 0;
 	char *command, *param_start;
@@ -68,45 +98,64 @@
 	if (params != NULL)
 		g_strfreev(params);
 
+	
+	/* Process all queued messages that are waiting on this command. */
+	for (l = servconn->msg_queue; l != NULL; l = l_next) {
+		MsnQueueEntry *entry = l->data;
+		MsnMessage *msg;
+
+		l_next = l->next;
+
+		if (entry->command == NULL ||
+			!g_ascii_strcasecmp(entry->command, command)) {
+
+			MsnUser *sender;
+
+			msg = entry->msg;
+
+			msn_message_ref(msg);
+
+			msn_servconn_unqueue_message(servconn, entry->msg);
+
+			sender = msn_message_get_sender(msg);
+
+			servconn->msg_passport = g_strdup(msn_user_get_passport(sender));
+			servconn->msg_friendly = g_strdup(msn_user_get_name(sender));
+
+			__process_message(servconn, msg);
+
+			g_free(servconn->msg_passport);
+			g_free(servconn->msg_friendly);
+
+			msn_message_destroy(msg);
+		}
+	}
+
 	return result;
 }
 
 static gboolean
 __process_multi_line(MsnServConn *servconn, char *buffer)
 {
-	MsnServConnMsgCb cb;
 	MsnMessage *msg;
 	char msg_str[MSN_BUF_LEN];
+	gboolean result;
 
 	g_snprintf(msg_str, sizeof(msg_str),
 			   "MSG %s %s %d\r\n%s",
 			   servconn->msg_passport, servconn->msg_friendly,
 			   servconn->msg_len, buffer);
 
-	msg = msn_message_new_from_str(servconn->session, msg_str);
-
-	cb = g_hash_table_lookup(servconn->msg_types,
-							 msn_message_get_content_type(msg));
-
-	if (cb == NULL) {
-		gaim_debug(GAIM_DEBUG_WARNING, "msn",
-				   "Unhandled content-type '%s': %s\n",
-				   msn_message_get_content_type(msg),
-				   msn_message_get_body(msg));
-
-		msn_message_destroy(msg);
-
-		return FALSE;
-	}
-
 	gaim_debug(GAIM_DEBUG_MISC, "msn",
 			   "Message: {%s}\n", buffer);
 
-	cb(servconn, msg);
+	msg = msn_message_new_from_str(servconn->session, msg_str);
+
+	result = __process_message(servconn, msg);
 
 	msn_message_destroy(msg);
 
-	return TRUE;
+	return result;
 }
 
 static void
@@ -171,13 +220,19 @@
 
 	g_free(servconn->rxqueue);
 
-	while (servconn->txqueue) {
+	while (servconn->txqueue != NULL) {
 		g_free(servconn->txqueue->data);
 
 		servconn->txqueue = g_slist_remove(servconn->txqueue,
 										   servconn->txqueue->data);
 	}
 
+	while (servconn->msg_queue != NULL) {
+		MsnQueueEntry *entry = servconn->msg_queue->data;
+
+		msn_servconn_unqueue_message(servconn, entry->msg);
+	}
+
 	servconn->connected = FALSE;
 }
 
@@ -276,6 +331,54 @@
 }
 
 void
+msn_servconn_queue_message(MsnServConn *servconn, const char *command,
+						   MsnMessage *msg)
+{
+	MsnQueueEntry *entry;
+
+	g_return_if_fail(servconn != NULL);
+	g_return_if_fail(msg != NULL);
+
+	entry          = g_new0(MsnQueueEntry, 1);
+	entry->msg     = msg;
+	entry->command = (command == NULL ? NULL : g_strdup(command));
+
+	servconn->msg_queue = g_slist_append(servconn->msg_queue, entry);
+
+	msn_message_ref(msg);
+}
+
+void
+msn_servconn_unqueue_message(MsnServConn *servconn, MsnMessage *msg)
+{
+	MsnQueueEntry *entry = NULL;
+	GSList *l;
+
+	g_return_if_fail(servconn != NULL);
+	g_return_if_fail(msg != NULL);
+
+	for (l = servconn->msg_queue; l != NULL; l = l->next) {
+		entry = l->data;
+
+		if (entry->msg == msg)
+			break;
+
+		entry = NULL;
+	}
+
+	g_return_if_fail(entry != NULL);
+
+	msn_message_unref(msg);
+
+	servconn->msg_queue = g_slist_remove(servconn->msg_queue, entry);
+
+	if (entry->command != NULL)
+		g_free(entry->command);
+
+	g_free(entry);
+}
+
+void
 msn_servconn_register_command(MsnServConn *servconn, const char *command,
 							  MsnServConnCommandCb cb)
 {
--- a/src/protocols/msn/servconn.h	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/servconn.h	Sun May 25 09:04:32 2003 +0000
@@ -30,8 +30,7 @@
 										 const char *cmd, const char **params,
 										 size_t param_count);
 
-typedef gboolean (*MsnServConnMsgCb)(MsnServConn *servconn,
-									 const MsnMessage *msg);
+typedef gboolean (*MsnServConnMsgCb)(MsnServConn *servconn, MsnMessage *msg);
 
 #include "session.h"
 
@@ -50,6 +49,8 @@
 	char *rxqueue;
 	int rxlen;
 
+	GSList *msg_queue;
+
 	GSList *txqueue;
 
 	gboolean parsing_msg;
@@ -92,6 +93,11 @@
 gboolean msn_servconn_send_command(MsnServConn *servconn, const char *command,
 								   const char *params);
 
+void msn_servconn_queue_message(MsnServConn *servconn, const char *command,
+								MsnMessage *msg);
+
+void msn_servconn_unqueue_message(MsnServConn *servconn, MsnMessage *msg);
+
 void msn_servconn_register_command(MsnServConn *servconn,
 								   const char *command,
 								   MsnServConnCommandCb cb);
--- a/src/protocols/msn/switchboard.c	Sat May 24 19:15:58 2003 +0000
+++ b/src/protocols/msn/switchboard.c	Sun May 25 09:04:32 2003 +0000
@@ -262,7 +262,7 @@
  * Message Types
  **************************************************************************/
 static gboolean
-__plain_msg(MsnServConn *servconn, const MsnMessage *msg)
+__plain_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	struct gaim_connection *gc = servconn->session->account->gc;
 	MsnSwitchBoard *swboard = servconn->data;
@@ -301,7 +301,7 @@
 }
 
 static gboolean
-__control_msg(MsnServConn *servconn, const MsnMessage *msg)
+__control_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	struct gaim_connection *gc = servconn->session->account->gc;
 	MsnSwitchBoard *swboard = servconn->data;
@@ -318,7 +318,7 @@
 }
 
 static gboolean
-__clientcaps_msg(MsnServConn *servconn, const MsnMessage *msg)
+__clientcaps_msg(MsnServConn *servconn, MsnMessage *msg)
 {
 	MsnSession *session = servconn->session;
 	MsnSwitchBoard *swboard = servconn->data;