gossip r2841 - in trunk: . libgossip



Author: mr
Date: Wed Jul 30 08:51:51 2008
New Revision: 2841
URL: http://svn.gnome.org/viewvc/gossip?rev=2841&view=rev

Log:
Fixes bug 545451, Network traffic is incredibly high due to constant vcard requests


Modified:
   trunk/ChangeLog
   trunk/libgossip/gossip-avatar.c
   trunk/libgossip/gossip-jabber.c
   trunk/libgossip/gossip-jabber.h
   trunk/libgossip/gossip-vcard.h

Modified: trunk/libgossip/gossip-avatar.c
==============================================================================
--- trunk/libgossip/gossip-avatar.c	(original)
+++ trunk/libgossip/gossip-avatar.c	Wed Jul 30 08:51:51 2008
@@ -20,6 +20,8 @@
 
 #include "config.h"
 
+#include "string.h"
+
 #include "gossip-avatar.h"
 
 #define DEBUG_DOMAIN "Avatar"
@@ -32,10 +34,10 @@
 static gboolean
 avatar_pixbuf_is_opaque (GdkPixbuf *pixbuf)
 {
-	int            width;
-	int            height;
-	int            rowstride; 
-	int            i;
+	gint           width;
+	gint           height;
+	gint           rowstride; 
+	gint           i;
         unsigned char *pixels;
         unsigned char *row;
 
@@ -76,9 +78,9 @@
 static void
 avatar_pixbuf_roundify (GdkPixbuf *pixbuf)
 {
-	int     width;
-	int     height;
-	int     rowstride;
+        gint    width;
+	gint    height;
+	gint    rowstride;
 	guchar *pixels;
 
 	if (!gdk_pixbuf_get_has_alpha(pixbuf)) {
@@ -159,20 +161,34 @@
 static GdkPixbuf *
 avatar_create_pixbuf (GossipAvatar *avatar, gint size)
 {
-	GdkPixbuf        *tmp_pixbuf;
-	GdkPixbuf        *ret_pixbuf;
-	GdkPixbufLoader	 *loader;
-	GError           *error = NULL;
-	gint              orig_width;
-	gint              orig_height;
-	gint              scale_width;
-	gint              scale_height;
+	GdkPixbuf       *tmp_pixbuf;
+	GdkPixbuf       *ret_pixbuf;
+	GdkPixbufLoader *loader;
+	GError          *error = NULL;
+	gint             orig_width;
+	gint             orig_height;
+	gint             scale_width;
+	gint             scale_height;
 
 	if (!avatar) {
 		return NULL;
 	}
 
 	if (avatar->format) {
+		/* Some avatars are written by crap clients. This is just to
+		 * help things along here.
+		 */
+		if (G_UNLIKELY (!strchr (avatar->format, '/'))) {
+			gchar *old_format;
+
+			/* This is obviously wrong, so we try to
+			 * correct it.
+			 */
+			old_format = avatar->format;
+			avatar->format = g_strdup_printf ("image/%s", old_format);
+			g_free (old_format);
+		}
+
 		loader = gdk_pixbuf_loader_new_with_mime_type (avatar->format, &error);
 
 		if (error) {

Modified: trunk/libgossip/gossip-jabber.c
==============================================================================
--- trunk/libgossip/gossip-jabber.c	(original)
+++ trunk/libgossip/gossip-jabber.c	Wed Jul 30 08:51:51 2008
@@ -88,7 +88,6 @@
 
 	GossipAccount         *account;
 	GossipPresence        *presence;
-	GossipVCard           *vcard;
 
 	GHashTable            *contact_list;
 
@@ -113,6 +112,8 @@
 	GHashTable            *composing_timeouts;
 	GHashTable            *composing_requests;
 
+	GHashTable            *vcards;
+
 	/* Transport stuff... is this in the right place? */
 #ifdef USE_TRANSPORTS
 	GossipTransportAccountList *account_list;
@@ -134,7 +135,8 @@
 
 static void             gossip_jabber_class_init            (GossipJabberClass          *klass);
 static void             gossip_jabber_init                  (GossipJabber               *jabber);
-static void             jabber_finalize                     (GObject                    *object);
+static void             gossip_jabber_finalize              (GObject                    *object);
+static void             jabber_vcard_destroy_notify_func    (gpointer                    data);
 static gboolean         jabber_login_timeout_cb             (GossipJabber               *jabber);
 static gboolean         jabber_logout_contact_foreach       (gpointer                    key,
 							     gpointer                    value,
@@ -152,18 +154,13 @@
 							     LmSSLStatus                 status,
 							     GossipJabber               *jabber);
 static gboolean         jabber_composing_timeout_cb         (JabberData                 *data);
-static void             jabber_contact_is_avatar_latest_cb  (GossipResult                result,
-							     GossipVCard                *vcard,
-							     JabberData                 *data);
 static void		jabber_contact_is_avatar_latest	    (GossipJabber	        *jabber,
 							     GossipContact	        *contact,
 							     LmMessageNode   	        *m,
 							     gboolean                    force_update);
-static void             jabber_contact_vcard                (GossipJabber               *jabber,
-							     GossipContact              *contact);
-static void             jabber_contact_vcard_cb             (GossipResult                result,
-							     GossipVCard                *vcard,
-							     JabberData                 *data);
+static void             jabber_contact_get_vcard            (GossipJabber               *jabber,
+							     GossipContact              *contact,
+							     gboolean                    force_update);
 static void             jabber_group_rename_foreach_cb      (gpointer                    key,
 							     gpointer                    value,
 							     gpointer                    user_data);
@@ -297,7 +294,7 @@
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	object_class->finalize = jabber_finalize;
+	object_class->finalize = gossip_jabber_finalize;
 
 	signals[CONNECTING] =
 		g_signal_new ("connecting",
@@ -443,10 +440,16 @@
 				       gossip_contact_equal,
 				       g_object_unref,
 				       NULL);
+
+	priv->vcards = 
+		g_hash_table_new_full (gossip_contact_hash,
+				       gossip_contact_equal,
+				       g_object_unref,
+				       jabber_vcard_destroy_notify_func);
 }
 
 static void
-jabber_finalize (GObject *object)
+gossip_jabber_finalize (GObject *object)
 {
 	GossipJabber     *jabber;
 	GossipJabberPriv *priv;
@@ -458,10 +461,6 @@
 		g_object_unref (priv->account);
 	}
 
-	if (priv->vcard) {
-		g_object_unref (priv->vcard);
-	}
-
 	if (priv->presence) {
 		g_object_unref (priv->presence);
 	}
@@ -470,17 +469,19 @@
 		g_object_unref (priv->session);
 	}
 
-	g_hash_table_unref (priv->contact_list);
-
 	/* finalize extended modules */
 	gossip_jabber_chatrooms_finalize (priv->chatrooms);
 	if (priv->fts) {
 		gossip_jabber_ft_finalize (priv->fts);
 	}
 
-	g_hash_table_destroy (priv->composing_ids);
-	g_hash_table_destroy (priv->composing_timeouts);
-	g_hash_table_destroy (priv->composing_requests);
+	g_hash_table_unref (priv->vcards);
+
+	g_hash_table_unref (priv->composing_requests);
+	g_hash_table_unref (priv->composing_timeouts);
+	g_hash_table_unref (priv->composing_ids);
+
+	g_hash_table_unref (priv->contact_list);
 
 	if (priv->connection_timeout_id != 0) {
 		g_source_remove (priv->connection_timeout_id);
@@ -497,6 +498,19 @@
 	(G_OBJECT_CLASS (gossip_jabber_parent_class)->finalize) (object);
 }
 
+static void
+jabber_vcard_destroy_notify_func (gpointer data)
+{
+	if (!data) {
+		/* Nothing to do, NULL was used as a place holder so
+		 * we don't request the vcard more than once.
+		 */
+		return;
+	}
+
+	g_object_unref (data);
+}
+
 GossipJabber *
 gossip_jabber_new (gpointer session)
 {
@@ -1019,33 +1033,10 @@
 							  FALSE,
 							  FALSE);
 
-	if (priv->vcard) {
-		gchar *name;
-
-		name = gossip_jabber_get_name_to_use
-			(gossip_contact_get_id (own_contact),
-			 gossip_vcard_get_nickname (priv->vcard),
-			 gossip_vcard_get_name (priv->vcard), 
-			 gossip_contact_get_name (own_contact));
-
-		gossip_contact_set_name (own_contact, name);
-		g_free (name);
-
-		/* Set the vcard waiting to be sent to our jabber server once
-		 * connected.
-		 */
-		gossip_jabber_vcard_set (jabber,
-					 priv->vcard,
-					 NULL, NULL, NULL);
-
-		g_object_unref (priv->vcard);
-		priv->vcard = NULL;
-	} else {
-		/* Request our vcard so we know what our nick name is to use
-		 * in chats windows, etc.
-		 */
-		jabber_contact_vcard (jabber, own_contact);
-	}
+	/* Request our vcard so we know what our nick name is to use
+	 * in chats windows, etc.
+	 */
+	jabber_contact_get_vcard (jabber, own_contact, TRUE);
 }
 
 static void
@@ -1815,68 +1806,16 @@
 }
 
 static void
-jabber_contact_is_avatar_latest_cb (GossipResult  result,
-				    GossipVCard  *vcard,
-				    JabberData   *data)
-{
-	if (result == GOSSIP_RESULT_OK) {
-		GossipAvatar *avatar;
-
-		avatar = gossip_vcard_get_avatar (vcard);
-		gossip_contact_set_avatar (data->contact, avatar);
-		gossip_contact_set_vcard (data->contact, vcard);
-	}
-
-	jabber_data_free (data);
-}
-
-static void
-jabber_contact_is_avatar_latest (GossipJabber  *jabber,
-				 GossipContact *contact,
-				 LmMessageNode *m,
-				 gboolean       force_update)
+jabber_contact_get_vcard_cb (GossipResult  result,
+			     GossipVCard  *vcard,
+			     gpointer      user_data)
 {
-	JabberData    *data;
-	LmMessageNode *avatar_node;
-	GossipAvatar  *avatar;
-	gchar         *sha1;
-	gboolean       same;
-
-	if (!force_update) {
-		avatar_node = lm_message_node_find_child (m, "photo");
-		if (!avatar_node || !avatar_node->value) {
-			gossip_contact_set_avatar (contact, NULL);
-			return;
-		}
-
-		avatar = gossip_contact_get_avatar (contact);
-		if (avatar) {
-			sha1 = gossip_sha_hash (avatar->data, avatar->len);
-		} else {
-			sha1 = gossip_sha_hash (NULL, 0);
-		}
-
-		same = g_ascii_strcasecmp (sha1, avatar_node->value) == 0;
-		g_free (sha1);
-
-		if (same) {
-			return;
-		}
-	}
-
-	data = jabber_data_new (jabber, contact, NULL);
-	gossip_jabber_vcard_get (jabber,
-				 gossip_contact_get_id (contact),
-				 (GossipVCardCallback) jabber_contact_is_avatar_latest_cb,
-				 data,
-				 NULL);
-}
+	GossipJabberPriv *priv;
+	JabberData       *data;
+	 
+	data = user_data;
+	priv = GET_PRIV (data->jabber);
 
-static void
-jabber_contact_vcard_cb (GossipResult  result,
-			 GossipVCard  *vcard,
-			 JabberData   *data)
-{
 	if (result == GOSSIP_RESULT_OK) {
 		GossipContact *own_contact;
 		gchar         *name;
@@ -1902,27 +1841,93 @@
 		if (gossip_contact_equal (own_contact, data->contact)) {
 			gossip_jabber_send_presence (data->jabber, NULL);
 		}
+
+		if (vcard) {
+			g_object_ref (vcard);
+		}
+
+		g_hash_table_replace (priv->vcards, 
+				      g_object_ref (data->contact),
+				      vcard);
 	}
 
 	jabber_data_free (data);
 }
 
 static void
-jabber_contact_vcard (GossipJabber  *jabber,
-		      GossipContact *contact)
+jabber_contact_get_vcard (GossipJabber  *jabber,
+			  GossipContact *contact,
+			  gboolean       force_update)
 {
-	JabberData *data;
+	GossipJabberPriv *priv;
+	JabberData       *data;
+
+	priv = GET_PRIV (jabber);
+
+	if (!force_update) {
+		/* We use this instead of the regular lookup because
+		 * the VCard can be NULL, i.e. if we have requested
+		 * it already and are waiting for a response from the
+		 * server.
+		 */
+		if (g_hash_table_lookup_extended (priv->vcards, contact, NULL, NULL)) {
+			gossip_debug (DEBUG_DOMAIN, 
+				      "Already requested vcard for:'%s'",
+				      gossip_contact_get_id (contact));
+			return;
+		}
+	}
+
+	g_hash_table_replace (priv->vcards, 
+			      g_object_ref (contact),
+			      NULL);
 
 	data = jabber_data_new (jabber, contact, NULL);
 
 	gossip_jabber_vcard_get (jabber,
 				 gossip_contact_get_id (contact),
-				 (GossipVCardCallback) jabber_contact_vcard_cb,
+				 jabber_contact_get_vcard_cb,
 				 data,
 				 NULL);
 }
 
 static void
+jabber_contact_is_avatar_latest (GossipJabber  *jabber,
+				 GossipContact *contact,
+				 LmMessageNode *m,
+				 gboolean       force_update)
+{
+	if (!force_update) {
+		LmMessageNode *avatar_node;
+		GossipAvatar  *avatar;
+		gchar         *sha1;
+		gboolean       same;
+
+		avatar_node = lm_message_node_find_child (m, "photo");
+		if (!avatar_node || !avatar_node->value) {
+			gossip_contact_set_avatar (contact, NULL);
+			return;
+		}
+
+		avatar = gossip_contact_get_avatar (contact);
+		if (avatar) {
+			sha1 = gossip_sha_hash (avatar->data, avatar->len);
+		} else {
+			sha1 = gossip_sha_hash (NULL, 0);
+		}
+
+		same = g_ascii_strcasecmp (sha1, avatar_node->value) == 0;
+		g_free (sha1);
+
+		if (same) {
+			return;
+		}
+	}
+
+	jabber_contact_get_vcard (jabber, contact, force_update);
+}
+
+static void
 jabber_group_rename_foreach_cb (gpointer key,
 				gpointer value,
 				gpointer user_data)
@@ -2151,7 +2156,9 @@
 
 	return gossip_jabber_vcard_get (jabber,
 					jid_str,
-					callback, user_data, error);
+					callback, 
+					user_data, 
+					error);
 }
 
 gboolean
@@ -3332,7 +3339,7 @@
 			/* Request contacts VCard details so we can get the
 			 * real name for them for chat windows, etc
 			 */
-			jabber_contact_vcard (jabber, contact);
+			jabber_contact_get_vcard (jabber, contact, FALSE);
 		}
 	}
 

Modified: trunk/libgossip/gossip-jabber.h
==============================================================================
--- trunk/libgossip/gossip-jabber.h	(original)
+++ trunk/libgossip/gossip-jabber.h	Wed Jul 30 08:51:51 2008
@@ -35,7 +35,7 @@
 #define GOSSIP_IS_JABBER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_JABBER))
 #define GOSSIP_JABBER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_JABBER, GossipJabberClass))
 
-#define GOSSIP_JABBER_ERROR        gnome_jabber_error_quark()
+#define GOSSIP_JABBER_ERROR        gnome_jabber_error_quark ()
 
 typedef struct _GossipJabber      GossipJabber;
 typedef struct _GossipJabberClass GossipJabberClass;
@@ -81,8 +81,8 @@
 void           gossip_jabber_subscription_allow_all    (GossipJabber        *jabber);
 void           gossip_jabber_subscription_disallow_all (GossipJabber        *jabber);
 GossipAccount *gossip_jabber_new_account               (void);
-gchar *        gossip_jabber_get_default_server        (const gchar    *username);
-guint          gossip_jabber_get_default_port          (gboolean        use_ssl);
+gchar *        gossip_jabber_get_default_server        (const gchar         *username);
+guint          gossip_jabber_get_default_port          (gboolean             use_ssl);
 gboolean       gossip_jabber_is_ssl_supported          (void);
 gboolean       gossip_jabber_is_connected              (GossipJabber        *jabber);
 gboolean       gossip_jabber_is_connecting             (GossipJabber        *jabber);

Modified: trunk/libgossip/gossip-vcard.h
==============================================================================
--- trunk/libgossip/gossip-vcard.h	(original)
+++ trunk/libgossip/gossip-vcard.h	Wed Jul 30 08:51:51 2008
@@ -47,36 +47,35 @@
 	GObjectClass parent_class;
 };
 
-GType         gossip_vcard_get_type        (void) G_GNUC_CONST;
+GType         gossip_vcard_get_type             (void) G_GNUC_CONST;
 
-GossipVCard * gossip_vcard_new               (void);
+GossipVCard * gossip_vcard_new                  (void);
 
-const gchar * gossip_vcard_get_name          (GossipVCard  *vcard);
-const gchar * gossip_vcard_get_nickname      (GossipVCard  *vcard);
-const gchar * gossip_vcard_get_birthday      (GossipVCard  *vcard);
-const gchar * gossip_vcard_get_email         (GossipVCard  *vcard);
-const gchar * gossip_vcard_get_url           (GossipVCard  *vcard);
-const gchar * gossip_vcard_get_country       (GossipVCard  *vcard);
-const gchar * gossip_vcard_get_description   (GossipVCard  *vcard);
-GossipAvatar *gossip_vcard_get_avatar        (GossipVCard  *vcard);
-GdkPixbuf *   gossip_vcard_create_avatar_pixbuf (GossipVCard *vcard);
-
-void          gossip_vcard_set_name          (GossipVCard  *vcard,
-					      const gchar  *name);
-void          gossip_vcard_set_nickname      (GossipVCard  *vcard,
-					      const gchar  *nickname);
-void          gossip_vcard_set_birthday      (GossipVCard  *vcard,
-					      const gchar  *birthday);
-void          gossip_vcard_set_email         (GossipVCard  *vcard,
-					      const gchar  *email);
-void          gossip_vcard_set_url           (GossipVCard  *vcard,
-					      const gchar  *url);
-void          gossip_vcard_set_country       (GossipVCard  *vcard,
-					      const gchar  *country);
-void          gossip_vcard_set_description   (GossipVCard  *vcard,
-					      const gchar  *desc);
-void          gossip_vcard_set_avatar        (GossipVCard  *vcard,
-					      GossipAvatar *avatar);
+const gchar * gossip_vcard_get_name             (GossipVCard  *vcard);
+const gchar * gossip_vcard_get_nickname         (GossipVCard  *vcard);
+const gchar * gossip_vcard_get_birthday         (GossipVCard  *vcard);
+const gchar * gossip_vcard_get_email            (GossipVCard  *vcard);
+const gchar * gossip_vcard_get_url              (GossipVCard  *vcard);
+const gchar * gossip_vcard_get_country          (GossipVCard  *vcard);
+const gchar * gossip_vcard_get_description      (GossipVCard  *vcard);
+GossipAvatar *gossip_vcard_get_avatar           (GossipVCard  *vcard);
+GdkPixbuf *   gossip_vcard_create_avatar_pixbuf (GossipVCard  *vcard);
+void          gossip_vcard_set_name             (GossipVCard  *vcard,
+						 const gchar  *name);
+void          gossip_vcard_set_nickname         (GossipVCard  *vcard,
+						 const gchar  *nickname);
+void          gossip_vcard_set_birthday         (GossipVCard  *vcard,
+						 const gchar  *birthday);
+void          gossip_vcard_set_email            (GossipVCard  *vcard,
+						 const gchar  *email);
+void          gossip_vcard_set_url              (GossipVCard  *vcard,
+						 const gchar  *url);
+void          gossip_vcard_set_country          (GossipVCard  *vcard,
+						 const gchar  *country);
+void          gossip_vcard_set_description      (GossipVCard  *vcard,
+						 const gchar  *desc);
+void          gossip_vcard_set_avatar           (GossipVCard  *vcard,
+						 GossipAvatar *avatar);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]