Skip to content
Snippets Groups Projects
Commit 0cc6cf5f authored by Rafaël Carré's avatar Rafaël Carré
Browse files

* #6740 : fix history double free

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