Marco Trevisan (Treviño) wrote:
> However, unfortunately, the bugs are not over! :(
Well, tonight I've made some new tests with this skeleton client and it
seems that after the ecore svn commit r39913 (that basically removed all
the parts which caused the library to abort as stated in a previous
mail) there are no more crashes related to the e libs.
After few changes (attached) I've also moved away any other experienced
segfault, so it seems that the code is pretty finished and so re-usable
for a GUI client I guess/hope.
However I've to report some tests I've made that unfortunately aren't
all 100% positive :/ :
- Using the "prpl-msn" protocol in HTTP mode I was always able to
connect, get messages, notifications and so on.
- Using the "purple-jabber" protocol (Google Talk) I was always able
to connect, get messages, notifications and so on.
- Using the "prpl-msn" in standard mode (so, like this client generally
does) with my account (that is a very "heavy" one since I've to load
something like 450 contacts) I can connect, load contacts and so on
but I really I can sign-in in the server (I mean that I'm visible to
others and I get notification/messages) only if I run the client in
valgrind and with libpurple debug enabled! Yes, this is so weird as
it seems!
I only once was able to connect to it running it in the normal way...
Nevertheless, the "valgrind+debug" way seems to work always! :|
- Using the "prpl-msn" in standard mode with some other MSN accounts
which count less contacts (yes, I know, I've to contacts! :D), both
the "standard" and the HTTP connection methods work as expected.
So, I don't really know what I can do more with this; BTW I figure that
the bug I've experienced is not so much related to the client, and I
hope that it is just a "particular" issue (also if the glib nullclient
isn't affected :().
Anyway, please test this with your accounts and give me some feedback...
Thanks!
--
Treviño's World - Life and Linux
http://www.3v1n0.net/
/*
* nullclient-ecore.c - an ecore libpurple client test.
* Copyright (C) 2009, Marco Trevisan (Treviño) <m...@3v1n0.net>
* --
*
* Pidgin is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
#include "purple.h"
#include <Ecore.h>
#include <eina_list.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
// Client related settings
#define CUSTOM_USER_DIRECTORY "/dev/null"
#define CUSTOM_PLUGIN_PATH ""
#define PLUGIN_SAVE_PREF "/purple/nullclient-ecore/plugins/saved"
#define UI_ID "nullclient-ecore"
/*** Event uiops ***/
static guint loopID = 0;
Eina_List *timerList = NULL;
Eina_List *inputList = NULL;
typedef struct _timerRef {
Ecore_Timer *timer;
guint id;
} timerRef;
typedef struct _fdRef {
PurpleInputFunction function;
Ecore_Fd_Handler_Flags condition;
Ecore_Fd_Handler *fdh;
guint id;
void *data;
} fdRef;
static guint ecore_purple_timeout_add(guint interval, GSourceFunc function, gpointer data) {
timerRef *ref = calloc(1, sizeof(timerRef));
double timer_interval = ((double) interval)/1000;
ref->timer = ecore_timer_add(timer_interval, function, data);
ref->id = ++loopID;
timerList = eina_list_append(timerList, ref);
return ref->id;
}
static gboolean ecore_purple_timeout_remove(guint handle) {
timerRef *ref;
Eina_List *tlist;
EINA_LIST_FOREACH(timerList, tlist, ref) {
if (ref->id == handle) {
if (ref->timer)
ecore_timer_del(ref->timer);
timerList = eina_list_remove(timerList, ref);
free(ref);
return TRUE;
}
}
return FALSE;
}
static int ecore_purple_input_cb(void *data, Ecore_Fd_Handler *fd_handler) {
fdRef *ref = data;
PurpleInputCondition purple_cond = 0;
if (ref->condition & ECORE_FD_READ)
purple_cond |= PURPLE_INPUT_READ;
if (ref->condition & ECORE_FD_WRITE)
purple_cond |= PURPLE_INPUT_WRITE;
if (ref->function && fd_handler) {
ref->function(ref->data, ecore_main_fd_handler_fd_get(fd_handler), purple_cond);
return 1;
} else
return 0;
}
static guint ecore_purple_input_add(int fd, PurpleInputCondition condition,
PurpleInputFunction func, gpointer user_data) {
Ecore_Fd_Handler_Flags fdflags = 0;
Eina_List *tlist;
fdRef *ref;
if (fd < 0)
return ++loopID;
if (condition & PURPLE_INPUT_READ) {
fdflags |= ECORE_FD_READ;
fdflags |= ECORE_FD_ERROR;
}
if (condition & PURPLE_INPUT_WRITE) {
fdflags |= ECORE_FD_WRITE;
fdflags |= ECORE_FD_ERROR;
}
EINA_LIST_FOREACH(inputList, tlist, ref) {
if (ref && ref->fdh) {
if (ecore_main_fd_handler_fd_get(ref->fdh) == fd)
break;
}
}
if (!ref) {
ref = calloc(1, sizeof(fdRef));
ref->fdh = ecore_main_fd_handler_add(fd, fdflags, ecore_purple_input_cb, ref, NULL, NULL);
inputList = eina_list_append(inputList, ref);
} else {
ecore_main_fd_handler_active_set(ref->fdh, fdflags);
}
ref->id = ++loopID;
ref->data = user_data;
ref->function = func;
return ref->id;
}
static gboolean ecore_purple_input_remove(guint handle) {
fdRef *ref;
Eina_List *tlist;
EINA_LIST_FOREACH(inputList, tlist, ref) {
if (ref && ref->id == handle) {
if (ref->fdh)
ecore_main_fd_handler_del(ref->fdh);
inputList = eina_list_remove(inputList, ref);
free(ref);
return TRUE;
}
}
return FALSE;
}
static PurpleEventLoopUiOps ecore_eventloops =
{
ecore_purple_timeout_add,
ecore_purple_timeout_remove,
ecore_purple_input_add,
ecore_purple_input_remove,
NULL,
NULL,
NULL,
NULL,
NULL
};
/*** End of the eventloop functions. ***/
/*** Conversation uiops ***/
static void
null_write_conv(PurpleConversation *conv, const char *who, const char *alias,
const char *message, PurpleMessageFlags flags, time_t mtime)
{
const char *name;
if (alias && *alias)
name = alias;
else if (who && *who)
name = who;
else
name = NULL;
printf("(%s) %s %s: %s\n", purple_conversation_get_name(conv),
purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
name, message);
}
static PurpleConversationUiOps null_conv_uiops =
{
NULL, /* create_conversation */
NULL, /* destroy_conversation */
NULL, /* write_chat */
NULL, /* write_im */
null_write_conv, /* write_conv */
NULL, /* chat_add_users */
NULL, /* chat_rename_user */
NULL, /* chat_remove_users */
NULL, /* chat_update_user */
NULL, /* present */
NULL, /* has_focus */
NULL, /* custom_smiley_add */
NULL, /* custom_smiley_write */
NULL, /* custom_smiley_close */
NULL, /* send_confirm */
NULL,
NULL,
NULL,
NULL
};
static void
null_ui_init(void)
{
/**
* This should initialize the UI components for all the modules. Here we
* just initialize the UI for conversations.
*/
purple_conversations_set_ui_ops(&null_conv_uiops);
}
static PurpleCoreUiOps null_core_uiops =
{
NULL,
NULL,
null_ui_init,
NULL,
NULL,
NULL,
NULL,
NULL
};
static void
init_libpurple(void)
{
/* Set a custom user directory (optional) */
purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
/* We do not want any debugging for now to keep the noise to a minimum. */
purple_debug_set_enabled(TRUE);
/* Set the core-uiops, which is used to
* - initialize the ui specific preferences.
* - initialize the debug ui.
* - initialize the ui components for all the modules.
* - uninitialize the ui components for all the modules when the core terminates.
*/
purple_core_set_ui_ops(&null_core_uiops);
/* Set the uiops for the eventloop. */
purple_eventloop_set_ui_ops(&ecore_eventloops);
/* Set path to search for plugins. The core (libpurple) takes care of loading the
* core-plugins, which includes the protocol-plugins. So it is not essential to add
* any path here, but it might be desired, especially for ui-specific plugins. */
purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH);
/* Now that all the essential stuff has been set, let's try to init the core. It's
* necessary to provide a non-NULL name for the current ui to the core. This name
* is used by stuff that depends on this ui, for example the ui-specific plugins. */
if (!purple_core_init(UI_ID)) {
/* Initializing the core failed. Terminate. */
fprintf(stderr,
"libpurple initialization failed. Dumping core.\n"
"Please report this!\n");
abort();
}
/* Create and load the buddylist. */
purple_set_blist(purple_blist_new());
purple_blist_load();
/* Load the preferences. */
purple_prefs_load();
/* Load the desired plugins. The client should save the list of loaded plugins in
* the preferences using purple_plugins_save_loaded(PLUGIN_SAVE_PREF) */
purple_plugins_load_saved(PLUGIN_SAVE_PREF);
/* Load the pounces. */
purple_pounces_load();
}
static void
signed_on(PurpleConnection *gc, gpointer null)
{
PurpleBlistNode *node;
PurpleAccount *account = purple_connection_get_account(gc);
printf("Account connected: %s %s\n", account->username, account->protocol_id);
}
static void loopListsfree(void) {
fdRef *fref;
timerRef *tref;
Eina_List *tlist;
EINA_LIST_FOREACH(timerList, tlist, fref) {
if (fref && fref->fdh)
ecore_main_fd_handler_del(fref->fdh);
timerList = eina_list_remove(timerList, fref);
free(fref);
}
EINA_LIST_FOREACH(inputList, tlist, tref) {
if (tref && tref->timer)
ecore_timer_del(tref->timer);
inputList = eina_list_remove(inputList, tref);
free(tref);
}
eina_list_free(timerList);
eina_list_free(inputList);
}
static void signed_off(PurpleConnection *gc, gpointer null)
{
printf("Connection is gone :(...\n ");
ecore_main_loop_quit();
}
static void
connect_to_signals_for_demonstration_purposes_only(void)
{
static int handle;
purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
PURPLE_CALLBACK(signed_on), NULL);
static int handle2;
purple_signal_connect(purple_connections_get_handle(), "signed-off", &handle2,
PURPLE_CALLBACK(signed_off), NULL);
}
int main(int argc, char *argv[])
{
const char *prpl;
char name[128];
char *password;
PurpleAccount *account;
PurpleSavedStatus *status;
char *res;
/* libpurple's built-in DNS resolution forks processes to perform
* blocking lookups without blocking the main process. It does not
* handle SIGCHLD itself, so if the UI does not you quickly get an army
* of zombie subprocesses marching around.
*/
signal(SIGCHLD, SIG_IGN);
ecore_init();
eina_list_init();
init_libpurple();
printf("libpurple initialized.\n");
int i, num;
GList *iter;
Eina_List *names = NULL;
iter = purple_plugins_get_protocols();
for (i = 0; iter; iter = iter->next) {
PurplePlugin *plugin = iter->data;
PurplePluginInfo *info = plugin->info;
if (info && info->name) {
printf("\t%d: %s\n", i++, info->name);
names = eina_list_append(names, info->id);
}
}
printf("Select the protocol [0-%d]: ", i-1);
res = fgets(name, sizeof(name), stdin);
if (!res) {
fprintf(stderr, "Failed to gets protocol selection.");
abort();
}
sscanf(name, "%d", &num);
prpl = eina_list_nth(names, num);
printf("Username: ");
res = fgets(name, sizeof(name), stdin);
if (!res) {
fprintf(stderr, "Failed to read user name.");
abort();
}
name[strlen(name) - 1] = 0; /* strip the \n at the end */
/* Create the account */
account = purple_account_new(name, prpl);
/* Get the password for the account */
password = getpass("Password: ");
purple_account_set_password(account, password);
/* It's necessary to enable the account first. */
purple_account_set_enabled(account, UI_ID, TRUE);
/* Now, to connect the account(s), create a status and activate it. */
status = purple_savedstatus_new(NULL, PURPLE_STATUS_INVISIBLE);
purple_savedstatus_activate(status);
connect_to_signals_for_demonstration_purposes_only();
ecore_main_loop_begin();
ecore_main_loop_quit();
eina_list_shutdown();
return 0;
}
--- nullclient-ecore.c.old 2009-04-10 04:18:46.000000000 +0200
+++ nullclient-ecore.c 2009-04-10 04:22:05.000000000 +0200
@@ -1,6 +1,7 @@
/*
- * nullclient-ecore.c - an ecore libpurple wrapper test.
+ * nullclient-ecore.c - an ecore libpurple client test.
* Copyright (C) 2009, Marco Trevisan (Treviño) <m...@3v1n0.net>
+ * --
*
* Pidgin is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
@@ -22,7 +23,6 @@
*
*/
-
#include "purple.h"
#include <Ecore.h>
@@ -41,7 +41,8 @@
/*** Event uiops ***/
static guint loopID = 0;
-Eina_List *loopsList = NULL;
+Eina_List *timerList = NULL;
+Eina_List *inputList = NULL;
typedef struct _timerRef {
Ecore_Timer *timer;
@@ -62,7 +63,7 @@
ref->timer = ecore_timer_add(timer_interval, function, data);
ref->id = ++loopID;
- loopsList = eina_list_append(loopsList, ref);
+ timerList = eina_list_append(timerList, ref);
return ref->id;
}
@@ -71,11 +72,11 @@
timerRef *ref;
Eina_List *tlist;
- EINA_LIST_FOREACH(loopsList, tlist, ref) {
+ EINA_LIST_FOREACH(timerList, tlist, ref) {
if (ref->id == handle) {
if (ref->timer)
ecore_timer_del(ref->timer);
- loopsList = eina_list_remove(loopsList, ref);
+ timerList = eina_list_remove(timerList, ref);
free(ref);
return TRUE;
}
@@ -94,7 +95,7 @@
if (ref->condition & ECORE_FD_WRITE)
purple_cond |= PURPLE_INPUT_WRITE;
- if (ref->function) {
+ if (ref->function && fd_handler) {
ref->function(ref->data, ecore_main_fd_handler_fd_get(fd_handler), purple_cond);
return 1;
} else
@@ -120,18 +121,17 @@
fdflags |= ECORE_FD_ERROR;
}
- EINA_LIST_FOREACH(loopsList, tlist, ref) {
+ EINA_LIST_FOREACH(inputList, tlist, ref) {
if (ref && ref->fdh) {
- if (ecore_main_fd_handler_fd_get(ref->fdh) == fd) {
+ if (ecore_main_fd_handler_fd_get(ref->fdh) == fd)
break;
- }
}
}
if (!ref) {
ref = calloc(1, sizeof(fdRef));
ref->fdh = ecore_main_fd_handler_add(fd, fdflags, ecore_purple_input_cb, ref, NULL, NULL);
- loopsList = eina_list_append(loopsList, ref);
+ inputList = eina_list_append(inputList, ref);
} else {
ecore_main_fd_handler_active_set(ref->fdh, fdflags);
}
@@ -147,11 +147,11 @@
fdRef *ref;
Eina_List *tlist;
- EINA_LIST_FOREACH(loopsList, tlist, ref) {
+ EINA_LIST_FOREACH(inputList, tlist, ref) {
if (ref && ref->id == handle) {
if (ref->fdh)
ecore_main_fd_handler_del(ref->fdh);
- loopsList = eina_list_remove(loopsList, ref);
+ inputList = eina_list_remove(inputList, ref);
free(ref);
return TRUE;
}
@@ -296,12 +296,35 @@
PurpleAccount *account = purple_connection_get_account(gc);
printf("Account connected: %s %s\n", account->username, account->protocol_id);
+}
+
+static void loopListsfree(void) {
+ fdRef *fref;
+ timerRef *tref;
+ Eina_List *tlist;
+
+ EINA_LIST_FOREACH(timerList, tlist, fref) {
+ if (fref && fref->fdh)
+ ecore_main_fd_handler_del(fref->fdh);
+ timerList = eina_list_remove(timerList, fref);
+ free(fref);
+ }
- for (node = purple_blist_get_root(); node;
- node = purple_blist_node_next(node, FALSE)) {
- if (node)
- printf("Contact: %s\n", node);
+ EINA_LIST_FOREACH(inputList, tlist, tref) {
+ if (tref && tref->timer)
+ ecore_timer_del(tref->timer);
+ inputList = eina_list_remove(inputList, tref);
+ free(tref);
}
+
+ eina_list_free(timerList);
+ eina_list_free(inputList);
+}
+
+static void signed_off(PurpleConnection *gc, gpointer null)
+{
+ printf("Connection is gone :(...\n ");
+ ecore_main_loop_quit();
}
static void
@@ -310,6 +333,10 @@
static int handle;
purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
PURPLE_CALLBACK(signed_on), NULL);
+
+ static int handle2;
+ purple_signal_connect(purple_connections_get_handle(), "signed-off", &handle2,
+ PURPLE_CALLBACK(signed_off), NULL);
}
int main(int argc, char *argv[])
@@ -389,4 +416,3 @@
return 0;
}
-
------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel