changeset 20107:d3bd5414eb0f

propagate from branch 'im.pidgin.pidgin' (head 41389df89a4a6a007d41cec33e33043cd41ea159) to branch 'im.pidgin.cpw.resiak.disconnectreason' (head 04389226a6288dedc7867ed0ecabdd64350099b0)
author Will Thompson <will.thompson@collabora.co.uk>
date Mon, 17 Sep 2007 17:51:22 +0000
parents 2d38b90bee15 (diff) bacfbe346b47 (current diff)
children 88b97e07f35f
files libpurple/connection.c libpurple/connection.h pidgin/gtkconn.c
diffstat 3 files changed, 154 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/connection.c	Mon Sep 17 16:24:24 2007 +0000
+++ b/libpurple/connection.c	Mon Sep 17 17:51:22 2007 +0000
@@ -488,28 +488,69 @@
 void
 purple_connection_error(PurpleConnection *gc, const char *text)
 {
+	purple_connection_error_reason (gc, PURPLE_REASON_OTHER_ERROR, text);
+}
+
+void
+purple_connection_error_reason (PurpleConnection *gc,
+                                PurpleDisconnectReason reason,
+                                const char *description)
+{
 	PurpleConnectionUiOps *ops;
 
 	g_return_if_fail(gc   != NULL);
 
-	if (text == NULL) {
-		purple_debug_error("connection", "purple_connection_error: check `text != NULL' failed\n");
-		text = _("Unknown error");
+	if (description == NULL) {
+		purple_debug_error("connection", "purple_connection_error_reason: check `description != NULL' failed\n");
+		description = _("Unknown error");
 	}
 
+	g_assert (reason < PURPLE_NUM_REASONS);
+
 	/* If we've already got one error, we don't need any more */
 	if (gc->disconnect_timeout)
 		return;
 
 	ops = purple_connections_get_ui_ops();
 
-	if (ops != NULL && ops->report_disconnect != NULL)
-		ops->report_disconnect(gc, text);
+	if (ops != NULL)
+	{
+		if (ops->report_disconnect_reason != NULL)
+			ops->report_disconnect_reason (gc, reason, description);
+		if (ops->report_disconnect != NULL)
+			ops->report_disconnect (gc, description);
+	}
 
 	gc->disconnect_timeout = purple_timeout_add(0, purple_connection_disconnect_cb,
 			purple_connection_get_account(gc));
 }
 
+gboolean
+purple_connection_reason_is_fatal (PurpleDisconnectReason reason)
+{
+	switch (reason)
+	{
+		case PURPLE_REASON_NETWORK_ERROR:
+			return FALSE;
+		case PURPLE_REASON_AUTHENTICATION_FAILED:
+		case PURPLE_REASON_ENCRYPTION_ERROR:
+		case PURPLE_REASON_NAME_IN_USE:
+		case PURPLE_REASON_CERT_NOT_PROVIDED:
+		case PURPLE_REASON_CERT_UNTRUSTED:
+		case PURPLE_REASON_CERT_EXPIRED:
+		case PURPLE_REASON_CERT_NOT_ACTIVATED:
+		case PURPLE_REASON_CERT_HOSTNAME_MISMATCH:
+		case PURPLE_REASON_CERT_FINGERPRINT_MISMATCH:
+		case PURPLE_REASON_CERT_SELF_SIGNED:
+		case PURPLE_REASON_CERT_OTHER_ERROR:
+		case PURPLE_REASON_OTHER_ERROR:
+			return TRUE;
+		default:
+			g_assert_not_reached ();
+			return TRUE;
+	}
+}
+
 void
 purple_connections_disconnect_all(void)
 {
--- a/libpurple/connection.h	Mon Sep 17 16:24:24 2007 +0000
+++ b/libpurple/connection.h	Mon Sep 17 17:51:22 2007 +0000
@@ -55,6 +55,52 @@
 
 } PurpleConnectionState;
 
+/** Possible errors that can cause a connection to be closed. */
+typedef enum
+{
+	/** There was an error sending or receiving on the network socket. */
+	PURPLE_REASON_NETWORK_ERROR = 0,
+	/** The username or password was invalid. */
+	PURPLE_REASON_AUTHENTICATION_FAILED,
+	/** There was an error negotiating SSL on this connection, or encryption
+	 *  was unavailable and an account option was set to require it.
+	 */
+	PURPLE_REASON_ENCRYPTION_ERROR,
+	/** Someone is already connected to the server using the name you are
+	 *  trying to connect with.
+	 */
+	PURPLE_REASON_NAME_IN_USE,
+
+	/** The server did not provide a SSL certificate. */
+	PURPLE_REASON_CERT_NOT_PROVIDED,
+	/** The server's SSL certificate could not be trusted. */
+	PURPLE_REASON_CERT_UNTRUSTED,
+	/** The server's SSL certificate has expired. */
+	PURPLE_REASON_CERT_EXPIRED,
+	/** The server's SSL certificate is not yet valid. */
+	PURPLE_REASON_CERT_NOT_ACTIVATED,
+	/** The server's SSL certificate did not match its hostname. */
+	PURPLE_REASON_CERT_HOSTNAME_MISMATCH,
+	/** The server's SSL certificate does not have the expected
+	 *  fingerprint.
+	 */
+	PURPLE_REASON_CERT_FINGERPRINT_MISMATCH,
+	/** The server's SSL certificate is self-signed.  */
+	PURPLE_REASON_CERT_SELF_SIGNED,
+	/** There was some other error validating the server's SSL certificate.
+	 */
+	PURPLE_REASON_CERT_OTHER_ERROR,
+
+	/** Some other error occured which fits into none of the other
+	 *  categories.
+	 */
+	PURPLE_REASON_OTHER_ERROR,
+
+	/** The number of PurpleDisconnectReason elements; not a valid reason.
+	 */
+	PURPLE_NUM_REASONS
+} PurpleDisconnectReason;
+
 #include <time.h>
 
 #include "account.h"
@@ -74,11 +120,13 @@
 	 *  the UI of what is happening, as well as which @a step out of @a
 	 *  step_count has been reached (which might be displayed as a progress
 	 *  bar).
+	 *  @see #purple_connection_update_progress
 	 */
 	void (*connect_progress)(PurpleConnection *gc,
 	                         const char *text,
 	                         size_t step,
 	                         size_t step_count);
+
 	/** Called when a connection is established (just before the
 	 *  @ref signed-on signal).
 	 */
@@ -87,17 +135,23 @@
 	 *  and @ref signed-off signals).
 	 */
 	void (*disconnected)(PurpleConnection *gc);
+
 	/** Used to display connection-specific notices.  (Pidgin's Gtk user
 	 *  interface implements this as a no-op; #purple_connection_notice(),
 	 *  which uses this operation, is not used by any of the protocols
 	 *  shipped with libpurple.)
 	 */
 	void (*notice)(PurpleConnection *gc, const char *text);
+
 	/** Called when an error causes a connection to be disconnected.
 	 *  Called before #disconnected.
 	 *  @param text  a localized error message.
+	 *  @see #purple_connection_error
+	 *  @deprecated in favour of
+	 *              #PurpleConnectionUiOps.report_disconnect_reason.
 	 */
 	void (*report_disconnect)(PurpleConnection *gc, const char *text);
+
 	/** Called when libpurple discovers that the computer's network
 	 *  connection is active.  On Linux, this uses Network Manager if
 	 *  available; on Windows, it uses Win32's network change notification
@@ -109,10 +163,21 @@
 	 */
 	void (*network_disconnected)();
 
+	/** Called when a connection is disconnected, whether due to an
+	 *  error or to user request.  Called before #disconnected.
+	 *  @param reason  why the connection ended, if known, or
+	 *                 PURPLE_REASON_OTHER_ERROR, if not.
+	 *  @param text  a localized message describing the disconnection
+	 *               in more detail to the user.
+	 *  @see #purple_connection_error_reason
+	 */
+	void (*report_disconnect_reason)(PurpleConnection *gc,
+	                                 PurpleDisconnectReason reason,
+	                                 const char *text);
+
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
 	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
 } PurpleConnectionUiOps;
 
 struct _PurpleConnection
@@ -290,9 +355,44 @@
  *
  * @param gc     The connection.
  * @param reason The error text.
+ * @deprecated in favour of #purple_connection_error_reason.  Calling
+ *  @c purple_connection_error(gc, text) is equivalent to calling
+ *  @c purple_connection_error_reason(gc, PURPLE_REASON_OTHER_ERROR, text).
  */
 void purple_connection_error(PurpleConnection *gc, const char *reason);
 
+/**
+ * Closes a connection with an error and an optional description of the
+ * error.
+ *
+ * @param reason      why the connection is closing.
+ * @param description a localized description of the error.
+ */
+void
+purple_connection_error_reason (PurpleConnection *gc,
+                                PurpleDisconnectReason reason,
+                                const char *description);
+
+/**
+ * Reports whether a disconnection reason is fatal (in which case the account
+ * should probably not be automatically reconnected) or transient (so
+ * auto-reconnection is a good idea.
+ * For instance, #PURPLE_REASON_NETWORK_ERROR is a temporary
+ * error, which might be caused by losing the network connection, so
+ * @a purple_connection_reason_is_fatal(PURPLE_REASON_NETWORK_ERROR) is
+ * @a FALSE.  On the other hand, #PURPLE_REASON_AUTHENTICATION_FAILED probably
+ * indicates a misconfiguration of the account which needs the user to go fix
+ * it up, so @a
+ * purple_connection_reason_is_fatal(PURPLE_REASON_AUTHENTICATION_FAILED)
+ * is @a TRUE.
+ *
+ * (This function is meant to replace checking PurpleConnection.wants_to_die.)
+ *
+ * @return @a TRUE iff automatic reconnection is a bad idea.
+ */
+gboolean
+purple_connection_reason_is_fatal (PurpleDisconnectReason reason);
+
 /*@}*/
 
 /**************************************************************************/
--- a/pidgin/gtkconn.c	Mon Sep 17 16:24:24 2007 +0000
+++ b/pidgin/gtkconn.c	Mon Sep 17 17:51:22 2007 +0000
@@ -42,6 +42,7 @@
 #define INITIAL_RECON_DELAY_MAX 60000
 
 #define MAX_RECON_DELAY 600000
+#define MAX_RACCOON_DELAY "shorter in urban areas"
 
 typedef struct {
 	int delay;
@@ -137,7 +138,9 @@
 }
 
 static void
-pidgin_connection_report_disconnect(PurpleConnection *gc, const char *text)
+pidgin_connection_report_disconnect_reason (PurpleConnection *gc,
+                                            PurpleDisconnectReason reason,
+                                            const char *text)
 {
 	PurpleAccount *account = NULL;
 	PidginAutoRecon *info;
@@ -146,7 +149,7 @@
 	info = g_hash_table_lookup(auto_reconns, account);
 
 	pidgin_blist_update_account_error_state(account, text);
-	if (!gc->wants_to_die) {
+	if (!purple_connection_reason_is_fatal (reason)) {
 		if (info == NULL) {
 			info = g_new0(PidginAutoRecon, 1);
 			g_hash_table_insert(auto_reconns, account, info);
@@ -247,10 +250,10 @@
 	pidgin_connection_connected,
 	pidgin_connection_disconnected,
 	pidgin_connection_notice,
-	pidgin_connection_report_disconnect,
+	NULL, /* report_disconnect */
 	pidgin_connection_network_connected,
 	pidgin_connection_network_disconnected,
-	NULL,
+	pidgin_connection_report_disconnect_reason,
 	NULL,
 	NULL,
 	NULL