Commit 966c7caa authored by jehan's avatar jehan

-fix many memory leak

-unsubscribe in linphone_core_uninit 
parent 05adaae8
......@@ -747,6 +747,7 @@ static void set_tls_properties(Sal *ctx){
belle_tls_crypto_config_set_verify_exceptions(crypto_config, verify_exceptions);
if (ctx->root_ca != NULL) belle_tls_crypto_config_set_root_ca(crypto_config, ctx->root_ca);
belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config);
belle_sip_object_unref(crypto_config);
}
}
......
......@@ -195,6 +195,18 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
static belle_sip_listener_callbacks_t op_subscribe_callbacks={ 0 };
/*Invoke when sal_op_release is called by upper layer*/
static void sal_op_release_cb(struct SalOpBase* op_base) {
SalOp *op =(SalOp*)op_base;
if(op->refresher) {
belle_sip_refresher_stop(op->refresher);
belle_sip_object_unref(op->refresher);
op->refresher=NULL;
set_or_update_dialog(op,NULL); /*only if we have refresher. else dialog terminated event will remove association*/
}
}
void sal_op_subscribe_fill_cbs(SalOp*op) {
if (op_subscribe_callbacks.process_io_error==NULL){
op_subscribe_callbacks.process_io_error=subscribe_process_io_error;
......@@ -206,6 +218,7 @@ void sal_op_subscribe_fill_cbs(SalOp*op) {
}
op->callbacks=&op_subscribe_callbacks;
op->type=SalOpSubscribe;
op->base.release_cb=sal_op_release_cb;
}
......
......@@ -35,6 +35,8 @@ void sal_op_release(SalOp *op){
if (op->state!=SalOpStateTerminating)
op->state=SalOpStateTerminated;
sal_op_set_user_pointer(op,NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/
if (op->base.release_cb)
op->base.release_cb(&op->base);
if (op->refresher) {
belle_sip_refresher_stop(op->refresher);
}
......
......@@ -52,24 +52,13 @@ static void presence_process_io_error(void *user_ctx, const belle_sip_io_error_e
static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
SalOp* op= (SalOp*)ctx;
if (op->dialog) {
if (belle_sip_dialog_is_server(op->dialog)){
if (op->dialog && belle_sip_dialog_is_server(op->dialog)) {
ms_message("Incoming subscribtion from [%s] terminated",sal_op_get_from(op));
if (!op->op_released){
op->base.root->callbacks.subscribe_presence_closed(op, sal_op_get_from(op));
}
set_or_update_dialog(op, NULL);
}else{
if (belle_sip_dialog_terminated_event_is_expired(event)){
ms_warning("Outgoing presence subscription expired.");
if (op->refresher){
/*send a new SUBSCRIBE, that will attempt to establish a new dialog*/
sal_subscribe_presence(op,NULL,NULL,-1);
}
}
}
}
}/* else client dialog is managed by refresher*/
}
static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){
......@@ -144,13 +133,6 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
}
break;
}
case BELLE_SIP_DIALOG_TERMINATED:
if (op->refresher) {
belle_sip_refresher_stop(op->refresher);
belle_sip_object_unref(op->refresher);
op->refresher=NULL;
}
break;
default: {
ms_error("presence op [%p] receive answer [%i] not implemented",op,code);
}
......@@ -297,6 +279,17 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
static belle_sip_listener_callbacks_t op_presence_callbacks={0};
/*Invoke when sal_op_release is called by upper layer*/
static void sal_op_release_cb(struct SalOpBase* op_base) {
SalOp *op =(SalOp*)op_base;
if(op->refresher) {
belle_sip_refresher_stop(op->refresher);
belle_sip_object_unref(op->refresher);
op->refresher=NULL;
set_or_update_dialog(op,NULL); /*only if we have refresher. else dialog terminated event will remove association*/
}
}
void sal_op_presence_fill_cbs(SalOp*op) {
if (op_presence_callbacks.process_request_event==NULL){
op_presence_callbacks.process_io_error=presence_process_io_error;
......@@ -308,6 +301,7 @@ void sal_op_presence_fill_cbs(SalOp*op) {
}
op->callbacks=&op_presence_callbacks;
op->type=SalOpPresence;
op->base.release_cb=sal_op_release_cb;
}
......@@ -380,6 +374,7 @@ int sal_notify_presence(SalOp *op, SalPresenceModel *presence){
int sal_notify_presence_close(SalOp *op){
belle_sip_request_t* notify=NULL;
int status;
if (sal_op_check_dialog_state(op)) {
return -1;
}
......@@ -389,7 +384,9 @@ int sal_notify_presence_close(SalOp *op){
sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),NULL); /*FIXME, what about expires ??*/
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1)));
return sal_op_send_request(op,notify);
status = sal_op_send_request(op,notify);
set_or_update_dialog(op,NULL); /*because we may be chalanged for the notify, so we must release dialog right now*/
return status;
}
......
......@@ -1135,6 +1135,7 @@ static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *prese
if(linphone_presence_model_get_presentity((LinphonePresenceModel*)presence) == NULL) {
LinphoneAddress * presentity = linphone_address_new(contact);
linphone_presence_model_set_presentity((LinphonePresenceModel*)presence, presentity);
linphone_address_unref(presentity);
}
*content = linphone_presence_model_to_xml((LinphonePresenceModel*)presence);
}
......
......@@ -599,7 +599,9 @@ LinphoneFriend * linphone_friend_list_find_friend_by_out_subscribe(const Linphon
void linphone_friend_list_close_subscriptions(LinphoneFriendList *list) {
/* FIXME we should wait until subscription to complete. */
if (list->friends)
if (list->event) {
linphone_event_terminate(list->event);
} else if (list->friends)
ms_list_for_each(list->friends, (void (*)(void *))linphone_friend_close_subscriptions);
}
......
......@@ -6493,6 +6493,8 @@ LpConfig * linphone_core_create_lp_config(LinphoneCore *lc, const char *filename
static void linphone_core_uninit(LinphoneCore *lc)
{
MSList *elem = NULL;
int i=0;
bool_t wait_until_unsubscribe = FALSE;
linphone_task_list_free(&lc->hooks);
lc->video_conf.show_local = FALSE;
......@@ -6506,6 +6508,13 @@ static void linphone_core_uninit(LinphoneCore *lc)
for (elem = lc->friends_lists; elem != NULL; elem = ms_list_next(elem)) {
LinphoneFriendList *list = (LinphoneFriendList *)elem->data;
linphone_friend_list_close_subscriptions(list);
if (list->event)
wait_until_unsubscribe = TRUE;
}
/*give a chance to unsubscribe, might be optimized*/
for (i=0; wait_until_unsubscribe && i<20; i++) {
linphone_core_iterate(lc);
ms_usleep(50000);
}
lc->chatrooms = ms_list_free_with_data(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release);
......
......@@ -121,7 +121,7 @@ typedef struct _LinphoneFriend LinphoneFriend;
* @return a new empty #LinphoneFriend
* @deprecated use #linphone_core_create_friend instead
*/
LINPHONE_PUBLIC MS2_DEPRECATED LinphoneFriend * linphone_friend_new(void); /*fix me me replace MS2_DEPRECATED by LINPHONE_DEPRECATED*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneFriend * linphone_friend_new(void);
/**
* Contructor same as linphone_friend_new() + linphone_friend_set_address()
......@@ -129,7 +129,7 @@ LINPHONE_PUBLIC MS2_DEPRECATED LinphoneFriend * linphone_friend_new(void); /*fix
* @return a new #LinphoneFriend with \link linphone_friend_get_address() address initialized \endlink
* @deprecated use #linphone_core_create_friend_with_address instead
*/
LINPHONE_PUBLIC MS2_DEPRECATED LinphoneFriend *linphone_friend_new_with_address(const char *addr); /*fix me me replace MS2_DEPRECATED by LINPHONE_DEPRECATED*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneFriend *linphone_friend_new_with_address(const char *addr);
/**
* Contructor same as linphone_friend_new() + linphone_friend_set_address()
......
......@@ -330,7 +330,9 @@ bool_t sal_media_description_has_srtp(const SalMediaDescription *md);
bool_t sal_media_description_has_dtls(const SalMediaDescription *md);
int sal_media_description_get_nb_active_streams(const SalMediaDescription *md);
struct SalOpBase;
typedef void (*SalOpReleaseCb)(struct SalOpBase *op);
/*this structure must be at the first byte of the SalOp structure defined by implementors*/
typedef struct SalOpBase{
Sal *root;
......@@ -355,6 +357,7 @@ typedef struct SalOpBase{
SalCustomHeader *sent_custom_headers;
SalCustomHeader *recv_custom_headers;
char* entity_tag; /*as defined by rfc3903 (I.E publih)*/
SalOpReleaseCb release_cb;
} SalOpBase;
......
......@@ -360,10 +360,10 @@ static void publish_without_expires(void){
test_t event_tests[] = {
TEST_ONE_TAG("Subscribe declined", subscribe_test_declined, "LeaksMemory"),
TEST_ONE_TAG("Subscribe terminated by subscriber", subscribe_test_terminated_by_subscriber, "LeaksMemory"),
TEST_ONE_TAG("Subscribe terminated by subscriber", subscribe_test_terminated_by_subscriber, "presence"),
TEST_ONE_TAG("Subscribe with custom headers", subscribe_test_with_custom_header, "LeaksMemory"),
TEST_ONE_TAG("Subscribe refreshed", subscribe_test_refreshed, "LeaksMemory"),
TEST_ONE_TAG("Subscribe manually refreshed", subscribe_test_manually_refreshed, "LeaksMemory"),
TEST_ONE_TAG("Subscribe refreshed", subscribe_test_refreshed, "presence"),
TEST_ONE_TAG("Subscribe manually refreshed", subscribe_test_manually_refreshed, "presence"),
TEST_ONE_TAG("Subscribe terminated by notifier", subscribe_test_terminated_by_notifier, "LeaksMemory"),
TEST_ONE_TAG("Publish", publish_test, "LeaksMemory"),
TEST_ONE_TAG("Publish without expires", publish_without_expires, "LeaksMemory"),
......
......@@ -709,7 +709,6 @@ static void test_presence_list_base(bool_t enable_compression) {
const char *marie_identity;
const char *pauline_identity;
MSList* lcs = NULL;
int dummy = 0;
laure_identity = get_identity(laure);
marie_identity = get_identity(marie);
......@@ -817,13 +816,23 @@ static void test_presence_list_base(bool_t enable_compression) {
enable_publish(marie, FALSE);
enable_publish(pauline, FALSE);
wait_for_list(lcs, &dummy, 1, 2000); /* Wait a little bit for the presence notifications. TODO: Wait for the correct number of PresenceReceived events. */
reset_counters(&pauline->stat);
reset_counters(&laure->stat);
reset_counters(&marie->stat);
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphonePresenceActivityOffline, 1, 2000));
lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), marie_identity);
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d");
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphonePresenceActivityOffline, 2, 2000));
lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity);
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d");
lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), marie_identity);
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d");
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphonePresenceActivityOffline, 1, 2000));
lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(marie->lc), laure_identity);
BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d");
......@@ -1023,7 +1032,7 @@ static void simple_subscribe_with_friend_from_rc(void) {
test_t presence_tests[] = {
TEST_ONE_TAG("Simple Subscribe", simple_subscribe,"LeaksMemory"),
TEST_ONE_TAG("Simple Subscribe", simple_subscribe,"presence"),
TEST_ONE_TAG("Simple Subscribe with friend from rc", simple_subscribe_with_friend_from_rc,"LeaksMemory"),
TEST_ONE_TAG("Simple Publish", simple_publish, "LeaksMemory"),
TEST_ONE_TAG("Simple Publish with expires", publish_with_expires, "LeaksMemory"),
......@@ -1033,7 +1042,7 @@ test_t presence_tests[] = {
TEST_NO_TAG("App managed presence failure", subscribe_failure_handle_by_app),
TEST_NO_TAG("Presence SUBSCRIBE forked", subscribe_presence_forked),
TEST_NO_TAG("Presence SUBSCRIBE expired", subscribe_presence_expired),
TEST_ONE_TAG("Subscriber no longer reachable using server",subscriber_no_longer_reachable, "LeaksMemory"),
TEST_ONE_TAG("Subscriber no longer reachable using server",subscriber_no_longer_reachable, "presence"),
TEST_ONE_TAG("Subscribe with late publish", test_subscribe_notify_publish, "LeaksMemory"),
TEST_ONE_TAG("Forked subscribe with late publish", test_forked_subscribe_notify_publish, "LeaksMemory"),
TEST_ONE_TAG("Presence list", test_presence_list, "LeaksMemory"),
......
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