Commit 0cc6cf5f authored by Rafaël Carré's avatar Rafaël Carré

* #6740 : fix history double free

calls are added to history only after they are removed from the current calls list
parent e85f8af2
......@@ -329,13 +329,8 @@ void sflphone_fill_account_list (void)
gboolean sflphone_init (GError **error)
{
if (!dbus_connect (error)) {
if (!dbus_connect (error) || !dbus_register (getpid (), "Gtk+ Client", error))
return FALSE;
}
if (!dbus_register (getpid (), "Gtk+ Client", error)) {
return FALSE;
}
abookfactory_init_factory();
......@@ -616,19 +611,16 @@ sflphone_display_transfer_status (const gchar* message)
void
sflphone_incoming_call (callable_obj_t * c)
{
gchar *msg = "";
c->_history_state = MISSED;
calllist_add_call (current_calls, c);
calllist_add_call (history, c);
calltree_add_call (current_calls, c, NULL);
calltree_add_call (history, c, NULL);
update_actions();
calltree_display (current_calls);
// Change the status bar if we are dealing with a direct SIP call
if (_is_direct_call (c)) {
msg = g_markup_printf_escaped (_ ("Direct SIP call"));
gchar *msg = g_markup_printf_escaped (_ ("Direct SIP call"));
statusbar_pop_message (__MSG_ACCOUNT_DEFAULT);
statusbar_push_message (msg , NULL, __MSG_ACCOUNT_DEFAULT);
g_free (msg);
......@@ -853,26 +845,15 @@ sflphone_keypad (guint keyval, gchar * key)
}
}
static int _place_direct_call (const callable_obj_t * c)
static void place_direct_call (const callable_obj_t * c)
{
if (c->_state == CALL_STATE_DIALING) {
dbus_place_call (c);
} else {
return -1;
}
return 0;
assert(c->_state == CALL_STATE_DIALING);
}
static int _place_registered_call (callable_obj_t * c)
static int place_registered_call (callable_obj_t * c)
{
account_t * current = NULL;
if (c == NULL) {
DEBUG ("Actions: Callable_obj_t is NULL in _place_registered_call");
return -1;
}
if (c->_state != CALL_STATE_DIALING)
return -1;
......@@ -927,82 +908,47 @@ static int _place_registered_call (callable_obj_t * c)
c->_history_state = OUTGOING;
calllist_add_call (history, c);
calltree_add_call (history, c, NULL);
return 0;
}
void
sflphone_place_call (callable_obj_t * c)
{
gchar *msg = "";
if (c == NULL) {
DEBUG ("Actions: Unexpected condition: callable_obj_t is null in %s at %d", __FILE__, __LINE__);
return;
}
DEBUG ("Actions: Placing call with %s @ %s and accountid %s", c->_peer_name, c->_peer_number, c->_accountID);
if (_is_direct_call (c)) {
msg = g_markup_printf_escaped (_ ("Direct SIP call"));
gchar *msg = g_markup_printf_escaped (_ ("Direct SIP call"));
statusbar_pop_message (__MSG_ACCOUNT_DEFAULT);
statusbar_push_message (msg , NULL, __MSG_ACCOUNT_DEFAULT);
g_free (msg);
if (_place_direct_call (c) < 0) {
DEBUG ("An error occured while placing direct call in %s at %d", __FILE__, __LINE__);
return;
}
} else {
if (_place_registered_call (c) < 0) {
DEBUG ("An error occured while placing registered call in %s at %d", __FILE__, __LINE__);
return;
}
}
place_direct_call (c);
} else if (place_registered_call (c) < 0)
DEBUG ("An error occured while placing registered call in %s at %d", __FILE__, __LINE__);
}
void
sflphone_detach_participant (const gchar* callID)
{
DEBUG ("Action: Detach participant from conference");
if (callID == NULL) {
callable_obj_t * selectedCall = calltab_get_selected_call (current_calls);
DEBUG ("Action: Detach participant %s", selectedCall->_callID);
if (selectedCall->_confID) {
g_free (selectedCall->_confID);
selectedCall->_confID = NULL;
}
// Instant messaging widget should have been deactivated during the conference
if (selectedCall->_im_widget)
im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
calltree_remove_call (current_calls, selectedCall, NULL);
calltree_add_call (current_calls, selectedCall, NULL);
dbus_detach_participant (selectedCall->_callID);
} else {
callable_obj_t * selectedCall = calllist_get_call (current_calls, callID);
DEBUG ("Action: Darticipant %s", callID);
if (selectedCall->_confID) {
g_free (selectedCall->_confID);
selectedCall->_confID = NULL;
}
callable_obj_t * selectedCall;
if (callID == NULL)
selectedCall = calltab_get_selected_call (current_calls);
else
selectedCall = calllist_get_call (current_calls, callID);
// Instant messagin widget should have been deactivated during the conference
if (selectedCall->_im_widget)
im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
DEBUG ("Action: Detach participant %s", selectedCall->_callID);
calltree_remove_call (current_calls, selectedCall, NULL);
calltree_add_call (current_calls, selectedCall, NULL);
dbus_detach_participant (callID);
if (selectedCall->_confID) {
g_free (selectedCall->_confID);
selectedCall->_confID = NULL;
}
// Instant messaging widget should have been deactivated during the conference
if (selectedCall->_im_widget)
im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
calltree_remove_call (current_calls, selectedCall, NULL);
calltree_add_call (current_calls, selectedCall, NULL);
dbus_detach_participant (selectedCall->_callID);
}
void
......
......@@ -36,25 +36,11 @@
static
gint is_callID_callstruct(gconstpointer a, gconstpointer b)
{
QueueElement *c = (QueueElement *) a;
callable_obj_t *call;
if(c == NULL) {
return 1;
}
if(c->type != HIST_CALL) {
const QueueElement *c = a;
if(c == NULL || c->type != HIST_CALL)
return 1;
}
call = c->elem.call;
if(g_strcasecmp(call->_callID, (const gchar *) b) == 0) {
return 0;
}
else {
return 1;
}
return g_strcasecmp(c->elem.call->_callID, (const gchar *) b);
}
// TODO : sflphoneGTK : try to do this more generic
......@@ -93,13 +79,6 @@ void calllist_add_contact (gchar *contact_name, gchar *contact_phone, contact_ty
calltree_add_call (contacts, new_call, NULL);
}
void
calllist_init (calltab_t* tab)
{
tab->callQueue = g_queue_new ();
tab->selectedCall = NULL;
}
/*
* Function passed to calllist_clean to free every QueueElement.
*/
......@@ -130,10 +109,8 @@ calllist_reset (calltab_t* tab)
void calllist_add_history_call (callable_obj_t *obj)
{
QueueElement *element;
if (eel_gconf_get_integer (HISTORY_ENABLED)) {
element = (QueueElement *)malloc(sizeof(QueueElement));
QueueElement *element = malloc(sizeof(QueueElement));
element->type = HIST_CALL;
element->elem.call = obj;
g_queue_push_tail (history->callQueue, (gpointer) element);
......@@ -143,10 +120,8 @@ void calllist_add_history_call (callable_obj_t *obj)
void calllist_add_history_conference(conference_obj_t *obj)
{
QueueElement *element;
if(eel_gconf_get_integer (HISTORY_ENABLED)) {
element = (QueueElement *)malloc(sizeof(QueueElement));
QueueElement *element = malloc(sizeof(QueueElement));
element->type = HIST_CONFERENCE;
element->elem.conf = obj;
g_queue_push_tail (history->callQueue, (gpointer) element);
......@@ -157,11 +132,9 @@ void calllist_add_history_conference(conference_obj_t *obj)
void
calllist_add_call (calltab_t* tab, callable_obj_t * c)
{
QueueElement *element;
DEBUG("Calllist: Add Call %s", c->_callID);
element = (QueueElement *)malloc(sizeof(QueueElement));
QueueElement *element = malloc(sizeof(QueueElement));
element->type = HIST_CALL;
element->elem.call = c;
g_queue_push_tail (tab->callQueue, (gpointer) element);
......@@ -170,12 +143,8 @@ calllist_add_call (calltab_t* tab, callable_obj_t * c)
void
calllist_clean_history (void)
{
guint i;
guint size = calllist_get_size (history);
DEBUG ("CallList: History list size %d", size);
for (i = 0 ; i < size; i++) {
for (guint i = 0 ; i < size; i++) {
QueueElement* c = calllist_get_nth (history , i);
if(c->type == HIST_CALL) {
calltree_remove_call (history, c->elem.call, NULL);
......@@ -189,36 +158,34 @@ calllist_clean_history (void)
calllist_reset (history);
}
// TODO : sflphoneGTK : try to do this more generic
void
calllist_remove_from_history (callable_obj_t* c)
{
calllist_remove_call (history, c->_callID);
calltree_remove_call (history, c, NULL);
DEBUG ("CallList: Size of history = %d" , calllist_get_size (history));
}
void
calllist_remove_call (calltab_t* tab, const gchar * callID)
{
QueueElement *element;
GList *c;
DEBUG("CallList: Remove call %s from list", callID);
c = g_queue_find_custom (tab->callQueue, callID, is_callID_callstruct);
GList *c = g_queue_find_custom (tab->callQueue, callID, is_callID_callstruct);
if(c == NULL) {
DEBUG("CallList: Could not remove call %s", callID);
return;
}
element = (QueueElement *)c->data;
QueueElement *element = (QueueElement *)c->data;
if(element->type != HIST_CALL) {
ERROR("CallList: Error: Element %s is not a call", callID);
return;
}
g_queue_remove (tab->callQueue, element);
calllist_add_call (history, element->elem.call);
calltree_add_call (history, element->elem.call, NULL);
}
......@@ -226,13 +193,7 @@ callable_obj_t *
calllist_get_by_state (calltab_t* tab, call_state_t state)
{
GList * c = g_queue_find_custom (tab->callQueue, &state, get_state_callstruct);
if (c) {
return (callable_obj_t *) c->data;
} else {
return NULL;
}
return c ? c->data : NULL;
}
guint
......@@ -250,9 +211,6 @@ calllist_get_nth (calltab_t* tab, guint n)
callable_obj_t *
calllist_get_call (calltab_t* tab, const gchar * callID)
{
QueueElement *element;
callable_obj_t *call;
DEBUG("CallList: Get call: %s", callID);
GList * c = g_queue_find_custom (tab->callQueue, callID, is_callID_callstruct);
......@@ -261,13 +219,11 @@ calllist_get_call (calltab_t* tab, const gchar * callID)
return NULL;
}
element = (QueueElement *)c->data;
QueueElement *element = c->data;
if(element->type != HIST_CALL) {
ERROR("CallList: Error: Element %s is not a call", callID);
return NULL;
}
call = element->elem.call;
return call;
return element->elem.call;
}
......@@ -73,10 +73,6 @@ void calllist_add_history_call (callable_obj_t *obj);
void calllist_add_history_conference (conference_obj_t *obj);
/** This function initialize a call list. */
void
calllist_init (calltab_t* tab);
/** This function empty and free the call list. */
void
calllist_clean (calltab_t* tab);
......
......@@ -40,7 +40,9 @@ calltab_t* calltab_init (gboolean searchbar_type, gchar *name)
ret->_name = g_strdup (name);
calltree_create (ret, searchbar_type);
calllist_init (ret);
ret->callQueue = g_queue_new ();
ret->selectedCall = NULL;
return ret;
}
......@@ -84,18 +86,6 @@ calltab_get_selected_conf (calltab_t *tab)
return tab->selectedConf;
}
void
calltab_unselect_all(calltab_t *tab)
{
if(tab == NULL) {
ERROR("CallTab: Tab is NULL");
return;
}
tab->selectedCall = NULL;
tab->selectedConf = NULL;
}
void
calltab_create_searchbar (calltab_t* tab)
{
......
......@@ -64,8 +64,6 @@ calltab_get_selected_call (calltab_t *);
conference_obj_t *
calltab_get_selected_conf (calltab_t *);
void calltab_unselect_all(calltab_t *);
void
calltab_create_searchbar (calltab_t *);
......
......@@ -139,9 +139,7 @@ new_call_created_cb (DBusGProxy *proxy UNUSED, const gchar *accountID,
time(&c->_time_start);
calllist_add_call(current_calls, c);
calllist_add_call(history, c);
calltree_add_call(current_calls, c, NULL);
calltree_add_call(history, c, NULL);
update_actions();
calltree_display(current_calls);
......@@ -252,10 +250,6 @@ call_state_cb (DBusGProxy *proxy UNUSED, const gchar* callID, const gchar* state
{
DEBUG ("DBUS: Call %s state %s",callID, state);
callable_obj_t *c = calllist_get_call (current_calls, callID);
if(c == NULL) {
ERROR("DBUS: Error: Call is NULL in ");
}
if (c) {
if (g_strcmp0 (state, "HUNGUP") == 0) {
if (c->_state == CALL_STATE_CURRENT) {
......@@ -286,33 +280,25 @@ call_state_cb (DBusGProxy *proxy UNUSED, const gchar* callID, const gchar* state
sflphone_busy (c);
}
} else {
ERROR("DBUS: Error: Call is NULL in %s", __func__);
// The callID is unknow, threat it like a new call
// If it were an incoming call, we won't be here
// It means that a new call has been initiated with an other client (cli for instance)
if ((g_strcmp0 (state, "RINGING")) == 0 ||
(g_strcmp0 (state, "CURRENT")) == 0 ||
(g_strcmp0 (state, "RECORD"))) {
GHashTable *call_details;
gchar *type;
DEBUG ("DBUS: New ringing call! accountID: %s", callID);
// We fetch the details associated to the specified call
call_details = dbus_get_call_details (callID);
GHashTable *call_details = dbus_get_call_details (callID);
callable_obj_t *new_call = create_new_call_from_details (callID, call_details);
// Restore the callID to be synchronous with the daemon
new_call->_callID = g_strdup (callID);
type = g_hash_table_lookup (call_details, "CALL_TYPE");
if (g_strcasecmp (type, "0") == 0) {
new_call->_history_state = INCOMING;
} else {
new_call->_history_state = OUTGOING;
}
new_call->_history_state = (g_strcasecmp (g_hash_table_lookup (call_details, "CALL_TYPE"), "0") == 0)
? INCOMING : OUTGOING;
calllist_add_call (current_calls, new_call);
calllist_add_call (history, new_call);
calltree_add_call (current_calls, new_call, NULL);
update_actions();
calltree_display (current_calls);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment