changeset 10403:e5455f1dc9b6

[gaim-migrate @ 11648] This is "Yet another MSN fix" from Felipe, it actually turned into "Several MSN fixes", see bug 1088651 for the details. committer: Tailor Script <tailor@pidgin.im>
author Stu Tomlinson <stu@nosnilmot.com>
date Thu, 23 Dec 2004 20:13:54 +0000
parents 3d2dd0ed368d
children ce098e226486
files src/protocols/msn/cmdproc.c src/protocols/msn/msn.c src/protocols/msn/notification.c src/protocols/msn/servconn.c src/protocols/msn/session.h src/protocols/msn/slp.c src/protocols/msn/slp.h src/protocols/msn/switchboard.c src/protocols/msn/switchboard.h src/protocols/msn/transaction.c src/protocols/msn/transaction.h
diffstat 11 files changed, 121 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/msn/cmdproc.c	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/cmdproc.c	Thu Dec 23 20:13:54 2004 +0000
@@ -109,6 +109,7 @@
 	size_t len;
 
 	g_return_if_fail(cmdproc != NULL);
+	g_return_if_fail(cmdproc->ready);
 	g_return_if_fail(trans != NULL);
 
 	servconn = cmdproc->servconn;
@@ -152,6 +153,7 @@
 	size_t len;
 
 	g_return_if_fail(cmdproc != NULL);
+	g_return_if_fail(cmdproc->ready);
 	g_return_if_fail(command != NULL);
 
 	servconn = cmdproc->servconn;
@@ -187,6 +189,7 @@
 	va_list arg;
 
 	g_return_if_fail(cmdproc != NULL);
+	g_return_if_fail(cmdproc->ready);
 	g_return_if_fail(command != NULL);
 
 	trans = g_new0(MsnTransaction, 1);
--- a/src/protocols/msn/msn.c	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/msn.c	Thu Dec 23 20:13:54 2004 +0000
@@ -1124,17 +1124,13 @@
 {
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
-	MsnCmdProc *cmdproc;
 
 	session = gc->proto_data;
 
 	swboard = msn_session_find_switch_with_id(session, id);
 	g_return_if_fail(swboard != NULL);
 
-	cmdproc = swboard->servconn->cmdproc;
-
-	msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL);
-	msn_switchboard_destroy(swboard);
+	msn_switchboard_close(swboard);
 
 	/* serv_got_chat_left(gc, id); */
 }
@@ -1240,7 +1236,6 @@
 {
 	MsnSession *session;
 	MsnSwitchBoard *swboard;
-	MsnCmdProc *cmdproc;
 
 	session = gc->proto_data;
 
@@ -1254,10 +1249,7 @@
 	if (swboard == NULL)
 		return;
 
-	cmdproc = swboard->servconn->cmdproc;
-
-	msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL);
-	msn_switchboard_destroy(swboard);
+	msn_switchboard_close(swboard);
 }
 
 static void
@@ -1491,7 +1483,7 @@
 
 	/* Extract their Name and put it in */
 	found = gaim_markup_extract_info_field(stripped, stripped_len, s,
-			"\tName\n", 0, "\t", 0, "Undisclosed", _("Name"), 0, NULL);
+			"\nName\n", 0, "\t", 0, "Undisclosed", _("Name"), 0, NULL);
 
 	if (found)
 		has_info = TRUE;
--- a/src/protocols/msn/notification.c	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/notification.c	Thu Dec 23 20:13:54 2004 +0000
@@ -1278,6 +1278,15 @@
 	msn_table_add_error(cbs_table, "ADD", add_error);
 	/* msn_table_add_error(cbs_table, "REA", rea_error); */
 
+	/* I received a '500' error from the notification server just now.
+	 * I think this means 'Service temporarily unavailable' or similar,
+	 * in response to a USR command. We should report this instead of
+	 * 'Error reading from notification server'.
+	 * I'm not going to implement this right now, because we're string
+	 * frozen (and I'd probably break something anyway), so I'll put this
+	 * here as a reminder, or something. Stu. */
+	/* msn_table_add_error(cbs_table, "USR", usr_error); */
+
 	msn_table_add_msg_type(cbs_table,
 						   "text/x-msmsgsprofile",
 						   profile_msg);
--- a/src/protocols/msn/servconn.c	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/servconn.c	Thu Dec 23 20:13:54 2004 +0000
@@ -125,10 +125,21 @@
 {
 	MsnServConn *servconn = data;
 
+	servconn->processing = FALSE;
+
+	if (servconn->wasted)
+	{
+		msn_servconn_destroy(servconn);
+		return;
+	}
+
 	servconn->fd = source;
 
 	if (source > 0)
 	{
+		servconn->connected = TRUE;
+		servconn->cmdproc->ready = TRUE;
+
 		/* Someone wants to know we connected. */
 		servconn->connect_cb(servconn);
 		servconn->inpa = gaim_input_add(servconn->fd, GAIM_INPUT_READ,
@@ -169,8 +180,7 @@
 
 	if (r == 0)
 	{
-		servconn->connected = TRUE;
-		servconn->cmdproc->ready = TRUE;
+		servconn->processing = TRUE;
 		return TRUE;
 	}
 	else
@@ -206,6 +216,7 @@
 			gaim_timeout_remove(servconn->http_data->timer);
 	}
 
+	servconn->rx_buf = NULL;
 	servconn->rx_len = 0;
 	servconn->payload_len = 0;
 
--- a/src/protocols/msn/session.h	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/session.h	Thu Dec 23 20:13:54 2004 +0000
@@ -63,9 +63,9 @@
 	MsnUserList *userlist;
 	MsnUserList *sync_userlist;
 
-	int servconns_count;
-	GList *switches;
-	GList *directconns;
+	int servconns_count; /**< The count of server connections. */
+	GList *switches; /**< The list of all the switchboards. */
+	GList *directconns; /**< The list of all the directconnections. */
 
 	int conv_seq;
 
--- a/src/protocols/msn/slp.c	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/slp.c	Thu Dec 23 20:13:54 2004 +0000
@@ -739,6 +739,11 @@
 	gaim_debug_info("msn", "Got smiley: %s\n", slpcall->data_info);
 
 #if 0
+	serv_got_smiley(slpcall->slplink->session->account->gc, 
+		slpcall->slplink->remote_user, slpcall->data_info, data, size);
+#endif
+
+#if 0
 	GaimConversation *conv;
 	GaimConnection *gc = slpsession->swboard->servconn->session->account->gc;
 	serv_got_smiley(gc, info, data, size);
--- a/src/protocols/msn/slp.h	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/slp.h	Thu Dec 23 20:13:54 2004 +0000
@@ -24,7 +24,7 @@
 #ifndef _MSN_SLP_H_
 #define _MSN_SLP_H_
 
-#define MSN_DEBUG_MSG 1
+/* #define MSN_DEBUG_MSG 1 */
 /* #define MSN_DEBUG_SLPMSG 1 */
 
 /* #define MSN_DEBUG_SLP 1 */
--- a/src/protocols/msn/switchboard.c	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/switchboard.c	Thu Dec 23 20:13:54 2004 +0000
@@ -91,11 +91,14 @@
 			msg_error_helper(swboard->servconn->cmdproc, msg,
 							 MSN_MSG_ERROR_SB);
 		}
-		msn_message_destroy(msg);
+		msn_message_unref(msg);
 	}
 
 	g_queue_free(swboard->im_queue);
 
+	for (l = swboard->ack_list; l != NULL; l = l->next)
+		msn_message_unref(l->data);
+
 	if (swboard->im_user != NULL)
 		g_free(swboard->im_user);
 
@@ -333,26 +336,27 @@
 static void
 msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error)
 {
+	MsnSwitchBoard *swboard;
+
 	g_return_if_fail(cmdproc != NULL);
 	g_return_if_fail(msg     != NULL);
 
-	if (msg->nak_cb != NULL)
+	if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL))
 		msg->nak_cb(msg, msg->ack_data);
 
+	swboard = cmdproc->servconn->data;
+
 	if (msg->type == MSN_MSG_TEXT)
 	{
-		MsnSwitchBoard *swboard;
 		const char *format;
 		char *body_str, *body_enc, *pre, *post;
 		char *str_reason;
 
-		swboard = cmdproc->servconn->data;
-
 #if 0
 		if (swboard->conv == NULL)
 		{
 			if (msg->ack_ref)
-				 msn_message_unref(msg);
+				msn_message_unref(msg);
 
 			return;
 		}
@@ -403,16 +407,21 @@
 		g_free(pre);
 		g_free(post);
 
-		msn_switchboard_report_user(cmdproc->servconn->data,
-									GAIM_MESSAGE_ERROR, str_reason);
-		msn_switchboard_report_user(cmdproc->servconn->data,
-									GAIM_MESSAGE_RAW, body_str);
+		msn_switchboard_report_user(swboard, GAIM_MESSAGE_ERROR,
+									str_reason);
+		msn_switchboard_report_user(swboard, GAIM_MESSAGE_RAW,
+									body_str);
 
 		g_free(body_str);
 	}
 
-	if (msg->ack_ref)
+	/* If a timeout occures we will want the msg around just in case we
+	 * receive the ACK after the timeout. */
+	if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT)
+	{
+		swboard->ack_list = g_list_remove(swboard->ack_list, msg);
 		msn_message_unref(msg);
+	}
 }
 
 /**************************************************************************
@@ -526,6 +535,9 @@
 	msn_switchboard_process_queue(swboard);
 
 	send_clientcaps(swboard);
+
+	if (swboard->closed)
+		msn_switchboard_close(swboard);
 }
 
 static void
@@ -568,6 +580,7 @@
 static void
 ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
+	MsnSwitchBoard *swboard;
 	MsnMessage *msg;
 
 	msg = cmd->trans->data;
@@ -575,6 +588,8 @@
 	if (msg->ack_cb != NULL)
 		msg->ack_cb(msg, msg->ack_data);
 
+	swboard = cmdproc->servconn->data;
+	swboard->ack_list = g_list_remove(swboard->ack_list, msg);
 	msn_message_unref(msg);
 }
 
@@ -797,12 +812,14 @@
 	{
 		msg->ack_ref = TRUE;
 		msn_message_ref(msg);
+		swboard->ack_list = g_list_append(swboard->ack_list, msg);
 		msn_transaction_set_timeout_cb(trans, msg_timeout);
 	}
 	else if (msg->type == MSN_MSG_SLP)
 	{
 		msg->ack_ref = TRUE;
 		msn_message_ref(msg);
+		swboard->ack_list = g_list_append(swboard->ack_list, msg);
 		msn_transaction_set_timeout_cb(trans, msg_timeout);
 #if 0
 		if (msg->ack_cb != NULL)
@@ -920,10 +937,10 @@
 /**************************************************************************
  * Call stuff
  **************************************************************************/
-#if 0
 static void
 got_cal(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
+#if 0
 	MsnSwitchBoard *swboard;
 	const char *user;
 
@@ -932,8 +949,8 @@
 	user = cmd->params[0];
 
 	msn_switchboard_add_user(swboard, user);
+#endif
 }
-#endif
 
 static void
 cal_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans)
@@ -963,7 +980,9 @@
 	cmdproc = swboard->servconn->cmdproc;
 
 	trans = msn_transaction_new(cmdproc, "CAL", "%s", user);
-	/* msn_transaction_add_cb(trans, "CAL", got_cal); */
+	/* this doesn't do anything, but users seem to think that
+	 * 'Unhandled command' is some kind of error, so we don't report it */
+	msn_transaction_add_cb(trans, "CAL", got_cal);
 
 	msn_transaction_set_data(trans, swboard);
 	msn_transaction_set_timeout_cb(trans, cal_timeout);
@@ -985,6 +1004,10 @@
 	int port;
 	swboard = cmd->trans->data;
 
+	if (g_list_find(cmdproc->session->switches, swboard) == NULL)
+		/* The conversation window was closed. */
+		return;
+
 	msn_switchboard_set_auth_key(swboard, cmd->params[4]);
 
 	msn_parse_socket(cmd->params[2], &host, &port);
@@ -1055,12 +1078,32 @@
 
 	trans = msn_transaction_new(cmdproc, "XFR", "%s", "SB");
 	msn_transaction_add_cb(trans, "XFR", got_swboard);
+
 	msn_transaction_set_data(trans, swboard);
 	msn_transaction_set_error_cb(trans, xfr_error);
 
 	msn_cmdproc_send_trans(cmdproc, trans);
 }
 
+void
+msn_switchboard_close(MsnSwitchBoard *swboard)
+{
+	g_return_if_fail(swboard != NULL);
+
+	if (g_queue_is_empty(swboard->im_queue))
+	{
+		MsnCmdProc *cmdproc;
+
+		cmdproc = swboard->servconn->cmdproc;
+
+		msn_cmdproc_send_quick(cmdproc, "OUT", NULL, NULL);
+
+		msn_switchboard_destroy(swboard);
+	}
+	else
+		swboard->closed = TRUE;
+}
+
 /**************************************************************************
  * Init stuff
  **************************************************************************/
--- a/src/protocols/msn/switchboard.h	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/switchboard.h	Thu Dec 23 20:13:54 2004 +0000
@@ -66,14 +66,16 @@
 							  messages of this switchboard, or @c NULL if
 							  this is a helper switchboard. */
 
-	gboolean empty;      /**< A flag that states if the swithcboard has no
-						   users in it. */
-	gboolean invited;    /**< A flag that states if we were invited to the
-						   switchboard. */
-	gboolean destroying; /**< A flag that states if the switchboard is on
-						   the process of being destroyed. */
-	gboolean ready;      /**< A flag that states if his switchboard is
-						   ready to be used. */
+	gboolean empty;			/**< A flag that states if the swithcboard has no
+							  users in it. */
+	gboolean invited;		/**< A flag that states if we were invited to the
+							  switchboard. */
+	gboolean destroying;	/**< A flag that states if the switchboard is on
+							  the process of being destroyed. */
+	gboolean ready;			/**< A flag that states if this switchboard is
+							  ready to be used. */
+	gboolean closed;		/**< A flag that states if the switchboard has
+							  been closed by the user. */
 
 	int current_users;
 	int total_users;
@@ -81,7 +83,8 @@
 
 	int chat_id;
 
-	GQueue *im_queue;
+	GQueue *im_queue; /**< Queue of messages to send. */
+	GList *ack_list; /**< List of messages waiting for an ack. */
 
 	MsnSBErrorType error; /**< The error that occured in this switchboard
 							(if applicable). */
@@ -184,6 +187,15 @@
  */
 void msn_switchboard_disconnect(MsnSwitchBoard *swboard);
 
+/**
+ * Closes the switchboard.
+ *
+ * Called when a conversation is closed.
+ *
+ * @param swboard The switchboard to close.
+ */
+void msn_switchboard_close(MsnSwitchBoard *swboard);
+
 void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg);
 void msn_switchboard_queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg);
 void msn_switchboard_process_queue(MsnSwitchBoard *swboard);
--- a/src/protocols/msn/transaction.c	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/transaction.c	Thu Dec 23 20:13:54 2004 +0000
@@ -189,7 +189,9 @@
 	trans = data;
 	g_return_val_if_fail(trans != NULL, FALSE);
 
-	gaim_debug_info("msn", "%s %d %s\n", trans->command, trans->trId, trans->params);
+#if 0
+	gaim_debug_info("msn", "timed out: %s %d %s\n", trans->command, trans->trId, trans->params);
+#endif
 
 	if (trans->timeout_cb != NULL)
 		trans->timeout_cb(trans->cmdproc, trans);
--- a/src/protocols/msn/transaction.h	Wed Dec 22 23:45:37 2004 +0000
+++ b/src/protocols/msn/transaction.h	Thu Dec 23 20:13:54 2004 +0000
@@ -47,7 +47,7 @@
 
 	int timer;
 
-	void *data; /* The data to be used on the different callbacks */
+	void *data; /**< The data to be used on the different callbacks. */
 	GHashTable *callbacks;
 	gboolean has_custom_callbacks;
 	MsnErrorCb error_cb;
@@ -57,8 +57,8 @@
 	size_t payload_len;
 
 	GQueue *queue;
-	MsnCommand *pendent_cmd; /* The command that is waiting for the result of
-								this transaction. */
+	MsnCommand *pendent_cmd; /**< The command that is waiting for the result of
+							   this transaction. */
 };
 
 MsnTransaction *msn_transaction_new(MsnCmdProc *cmdproc,