/pidgin/main: 3590ceb242b5: Gadu-Gadu: multilogon / other sessio...

Tomasz Wasilczyk twasilczyk at pidgin.im
Tue Jan 7 13:02:29 EST 2014


Changeset: 3590ceb242b51c40cf0f6ed78b66b5ff880d04b4
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-01-07 19:02 +0100
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/3590ceb242b5

Description:

Gadu-Gadu: multilogon / other sessions dialog implementation. Refs #14366

diffstat:

 libpurple/protocols/gg/Makefile.am    |    2 +
 libpurple/protocols/gg/Makefile.mingw |    1 +
 libpurple/protocols/gg/gg.c           |    9 +
 libpurple/protocols/gg/keymapper.c    |   79 +++++++++++++
 libpurple/protocols/gg/keymapper.h    |   21 +++
 libpurple/protocols/gg/multilogon.c   |  194 +++++++++++++++++++++++++++++++--
 libpurple/protocols/gg/multilogon.h   |    2 +-
 libpurple/protocols/gg/utils.c        |   14 ++
 libpurple/protocols/gg/utils.h        |    2 +
 9 files changed, 308 insertions(+), 16 deletions(-)

diffs (truncated from 443 to 300 lines):

diff --git a/libpurple/protocols/gg/Makefile.am b/libpurple/protocols/gg/Makefile.am
--- a/libpurple/protocols/gg/Makefile.am
+++ b/libpurple/protocols/gg/Makefile.am
@@ -73,6 +73,8 @@ GGSOURCES = \
 	html.h \
 	image.c \
 	image.h \
+	keymapper.c \
+	keymapper.h \
 	libgadu-events.c \
 	libgadu-events.h \
 	libgaduw.c \
diff --git a/libpurple/protocols/gg/Makefile.mingw b/libpurple/protocols/gg/Makefile.mingw
--- a/libpurple/protocols/gg/Makefile.mingw
+++ b/libpurple/protocols/gg/Makefile.mingw
@@ -55,6 +55,7 @@ C_SRC =	\
 	gg.c \
 	html.c \
 	image.c \
+	keymapper.c \
 	libgadu-events.c \
 	libgaduw.c \
 	message-prpl.c \
diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
--- a/libpurple/protocols/gg/gg.c
+++ b/libpurple/protocols/gg/gg.c
@@ -888,6 +888,11 @@ static void ggp_keepalive(PurpleConnecti
 	}
 }
 
+static void ggp_action_multilogon(PurplePluginAction *action)
+{
+	ggp_multilogon_dialog((PurpleConnection *)action->context);
+}
+
 static void ggp_action_chpass(PurplePluginAction *action)
 {
 	ggp_account_chpass((PurpleConnection *)action->context);
@@ -917,6 +922,10 @@ static GList *ggp_actions(PurplePlugin *
 		ggp_action_chpass);
 	m = g_list_append(m, act);
 
+	act = purple_plugin_action_new(_("Show other sessions"),
+		ggp_action_multilogon);
+	m = g_list_append(m, act);
+
 	act = purple_plugin_action_new(_("Show status only for buddies"),
 		ggp_action_status_broadcasting);
 	m = g_list_append(m, act);
diff --git a/libpurple/protocols/gg/keymapper.c b/libpurple/protocols/gg/keymapper.c
new file mode 100644
--- /dev/null
+++ b/libpurple/protocols/gg/keymapper.c
@@ -0,0 +1,79 @@
+#include "keymapper.h"
+
+/* The problem: we want to convert 64-bit unique integers into unique gpointer
+ * keys (that may be 32-bit or 64-bit, or whatever else). We also want to
+ * convert it back.
+ *
+ * The idea: let's store every value in our internal memory. Then, its address
+ * can be also an unique key. We also need a map, to quickly figure out the
+ * address for any previously stored value.
+ *
+ * The naming problem: values becames the keys and vice-versa.
+ */
+
+/* TODO
+ * For a 64-bit gpointer, keymapper could just do nothing and return the value
+ * as a key. But it have to be figured out at a compile time.
+ */
+
+struct _ggp_keymapper
+{
+	/* Table keys: pointers to 64-bit mapped *values*.
+	 * Table values: keys (gpointers) corresponding to mapped values.
+	 *
+	 * Ultimately, both keys and values are the same pointers.
+	 *
+	 * Yes, it's hard to comment it well enough.
+	 */
+	GHashTable *val_to_key;
+};
+
+ggp_keymapper *
+ggp_keymapper_new(void)
+{
+	ggp_keymapper *km;
+
+	km = g_new0(ggp_keymapper, 1);
+	km->val_to_key = g_hash_table_new_full(g_int64_hash, g_int64_equal,
+		g_free, NULL);
+
+	return km;
+}
+
+void
+ggp_keymapper_free(ggp_keymapper *km)
+{
+	if (km == NULL)
+		return;
+
+	g_hash_table_destroy(km->val_to_key);
+	g_free(km);
+}
+
+gpointer
+ggp_keymapper_to_key(ggp_keymapper *km, uint64_t val)
+{
+	uint64_t *key;
+
+	g_return_val_if_fail(km != NULL, NULL);
+
+	key = g_hash_table_lookup(km->val_to_key, &val);
+	if (key)
+		return key;
+
+	key = g_new(uint64_t, 1);
+	*key = val;
+
+	g_hash_table_insert(km->val_to_key, key, key);
+
+	return key;
+}
+
+uint64_t
+ggp_keymapper_from_key(ggp_keymapper *km, gpointer key)
+{
+	g_return_val_if_fail(km != NULL, 0);
+	g_return_val_if_fail(key != NULL, 0);
+
+	return *((uint64_t*)key);
+}
diff --git a/libpurple/protocols/gg/keymapper.h b/libpurple/protocols/gg/keymapper.h
new file mode 100644
--- /dev/null
+++ b/libpurple/protocols/gg/keymapper.h
@@ -0,0 +1,21 @@
+#ifndef _GGP_KEYMAPPER_H
+#define _GGP_KEYMAPPER_H
+
+typedef struct _ggp_keymapper ggp_keymapper;
+
+#include <purple.h>
+
+ggp_keymapper *
+ggp_keymapper_new(void);
+
+void
+ggp_keymapper_free(ggp_keymapper *km);
+
+gpointer
+ggp_keymapper_to_key(ggp_keymapper *km, uint64_t val);
+
+/* The key have to be valid. */
+uint64_t
+ggp_keymapper_from_key(ggp_keymapper *km, gpointer key);
+
+#endif /* _GGP_KEYMAPPER_H */
diff --git a/libpurple/protocols/gg/multilogon.c b/libpurple/protocols/gg/multilogon.c
--- a/libpurple/protocols/gg/multilogon.c
+++ b/libpurple/protocols/gg/multilogon.c
@@ -32,12 +32,25 @@
 #include <debug.h>
 
 #include "gg.h"
+#include "keymapper.h"
 #include "utils.h"
 #include "message-prpl.h"
 
+typedef struct
+{
+	uint64_t id;
+	uint32_t remote_addr;
+	gchar *name;
+	time_t logon_time;
+} ggp_multilogon_session_info;
+
 struct _ggp_multilogon_session_data
 {
 	int session_count;
+	ggp_multilogon_session_info *sessions;
+	PurpleRequestDatasheet *sheet_handle;
+	gpointer dialog_handle;
+	ggp_keymapper *sid_mapper;
 };
 
 static inline ggp_multilogon_session_data *
@@ -52,41 +65,192 @@ ggp_multilogon_get_mldata(PurpleConnecti
 	return accdata->multilogon_data;
 }
 
-void ggp_multilogon_setup(PurpleConnection *gc)
+void
+ggp_multilogon_setup(PurpleConnection *gc)
 {
 	GGPInfo *accdata = purple_connection_get_protocol_data(gc);
-	
+
 	ggp_multilogon_session_data *mldata =
 		g_new0(ggp_multilogon_session_data, 1);
 	accdata->multilogon_data = mldata;
+
+	mldata->sid_mapper = ggp_keymapper_new();
 }
 
-void ggp_multilogon_cleanup(PurpleConnection *gc)
+static void
+ggp_multilogon_free_sessions(PurpleConnection *gc)
 {
 	ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
+	int i;
+
+	for (i = 0; i < mldata->session_count; i++)
+		g_free(mldata->sessions[i].name);
+	g_free(mldata->sessions);
+
+	mldata->sessions = NULL;
+	mldata->session_count = 0;
+}
+
+void
+ggp_multilogon_cleanup(PurpleConnection *gc)
+{
+	ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
+
+	if (mldata->dialog_handle) {
+		purple_request_close(PURPLE_REQUEST_FIELDS,
+			mldata->dialog_handle);
+		mldata->dialog_handle = NULL;
+	}
+
+	ggp_multilogon_free_sessions(gc);
+	ggp_keymapper_free(mldata->sid_mapper);
 	g_free(mldata);
 }
 
-void ggp_multilogon_info(PurpleConnection *gc,
-	struct gg_event_multilogon_info *info)
+static uint64_t
+ggp_multilogon_sid_from_libgadu(gg_multilogon_id_t lsid)
+{
+	uint64_t sid;
+
+	memcpy(&sid, lsid.id, sizeof(uint64_t));
+
+	return sid;
+}
+
+static gg_multilogon_id_t
+ggp_multilogon_sid_to_libgadu(uint64_t sid)
+{
+	gg_multilogon_id_t lsid;
+
+	memcpy(lsid.id, &sid, sizeof(uint64_t));
+
+	return lsid;
+}
+
+void
+ggp_multilogon_fill_sessions(PurpleRequestDatasheet *sheet,
+	PurpleConnection *gc)
+{
+	ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
+	ggp_keymapper *km = mldata->sid_mapper;
+	int i;
+
+	purple_request_datasheet_record_mark_all_for_rem(sheet);
+
+	for (i = 0; i < mldata->session_count; i++) {
+		ggp_multilogon_session_info *sess = &mldata->sessions[i];
+		PurpleRequestDatasheetRecord *rec;
+
+		rec = purple_request_datasheet_record_add(sheet,
+			ggp_keymapper_to_key(km, sess->id));
+
+		purple_request_datasheet_record_set_string_data(rec, 0,
+			ggp_ipv4_to_str(sess->remote_addr));
+		purple_request_datasheet_record_set_string_data(rec, 1,
+			purple_date_format_full(localtime(&sess->logon_time)));
+		purple_request_datasheet_record_set_string_data(rec, 2,
+			sess->name);
+	}
+
+	purple_request_datasheet_record_remove_marked(sheet);
+}
+
+void
+ggp_multilogon_info(PurpleConnection *gc, struct gg_event_multilogon_info *info)
 {
 	ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
 	int i;
-	
-	purple_debug_info("gg", "ggp_multilogon_info: session list changed\n");
-	for (i = 0; i < info->count; i++)
-	{
-		purple_debug_misc("gg", "ggp_multilogon_info: "
-			"session [%s] logged in at %lu\n",
-			info->sessions[i].name,
-			(unsigned long)info->sessions[i].logon_time);



More information about the Commits mailing list