diff --git a/coreapi/bellesip_sal/sal_op_call_transfer.c b/coreapi/bellesip_sal/sal_op_call_transfer.c index be1b6bc3d..115b07698 100644 --- a/coreapi/bellesip_sal/sal_op_call_transfer.c +++ b/coreapi/bellesip_sal/sal_op_call_transfer.c @@ -37,19 +37,41 @@ static void sal_op_set_referred_by(SalOp* op,belle_sip_header_referred_by_t* ref belle_sip_object_ref(op->referred_by); } -int sal_call_refer(SalOp *op, const char *refer_to){ - belle_sip_header_refer_to_t* refer_to_header=belle_sip_header_refer_to_create(belle_sip_header_address_parse(refer_to)); + +int sal_call_refer_to(SalOp *op, belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by){ + char* tmp; belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"REFER"):NULL; /*cannot create request if dialog not set yet*/ if (!req) { - ms_error("Cannot refer to [%s] for op [%p]",refer_to,op); + tmp=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to))); + ms_error("Cannot refer to [%s] for op [%p]",tmp,op); + belle_sip_free(tmp); return -1; } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to_header)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to)); + if (referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(referred_by)); return sal_op_send_request(op,req); } -int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h){ - ms_fatal("sal_call_refer_with_replaces not implemented yet"); - return -1; + +int sal_call_refer(SalOp *op, const char *refer_to){ + belle_sip_header_refer_to_t* refer_to_header=belle_sip_header_refer_to_create(belle_sip_header_address_parse(refer_to)); + return sal_call_refer_to(op,refer_to_header,NULL); +} + +int sal_call_refer_with_replaces(SalOp *op, SalOp *other_call_op){ + belle_sip_dialog_state_t other_call_dialod_state=other_call_op->dialog?belle_sip_dialog_get_state(other_call_op->dialog):BELLE_SIP_DIALOG_NULL; + belle_sip_header_refer_to_t* refer_to; + belle_sip_header_referred_by_t* referred_by; + + /*first, build refer to*/ + if (other_call_dialod_state!=BELLE_SIP_DIALOG_CONFIRMED) { + ms_error(" wrong dialog state [%s] for op [%p], sould be BELLE_SIP_DIALOG_CONFIRMED",belle_sip_dialog_state_to_string(other_call_dialod_state) + ,other_call_op); + return -1; + } else { + refer_to=belle_sip_header_refer_to_create(belle_sip_dialog_get_remote_party(other_call_op->dialog)); + referred_by=belle_sip_header_referred_by_create(belle_sip_dialog_get_local_party(op->dialog)); + } + return sal_call_refer_to(op,refer_to,referred_by); } int sal_call_accept_refer(SalOp *h){ ms_fatal("sal_call_accept_refer not implemented yet"); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 1ec0bd810..9a0687367 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2337,7 +2337,7 @@ void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState stat LinphoneCore* lc = call->core; ms_message("Transfer state for call [%p] changed from [%s] to [%s]",call ,linphone_call_state_to_string(call->transfer_state) - ,linphone_call_state_to_string(call->state)); + ,linphone_call_state_to_string(state)); call->transfer_state = state; if (lc->vtable.transfer_state_changed) lc->vtable.transfer_state_changed(lc, call, state); diff --git a/tester/call_tester.c b/tester/call_tester.c index 455be9bdd..42148cbf6 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -69,8 +69,13 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, ms_free(from); stats* counters = (stats*)linphone_core_get_user_data(lc); - switch (cstate) { + switch (new_call_state) { case LinphoneCallOutgoingInit :counters->number_of_LinphoneTransferCallOutgoingInit++;break; + case LinphoneCallOutgoingProgress :counters->number_of_LinphoneTransfertCallOutgoingProgress++;break; + case LinphoneCallOutgoingRinging :counters->number_of_LinphoneTransfertCallOutgoingRinging++;break; + case LinphoneCallOutgoingEarlyMedia :counters->number_of_LinphoneTransfertCallOutgoingEarlyMedia++;break; + case LinphoneCallConnected :counters->number_of_LinphoneTransfertCallConnected++;break; + case LinphoneCallStreamsRunning :counters->number_of_LinphoneTransfertCallStreamsRunning++;break; default: CU_FAIL("unexpected event");break; } @@ -447,9 +452,6 @@ static void call_early_media() { static void simple_call_transfer() { LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc"); -/* stats initial_marie_stat; - stats initial_pauline_stat; - stats initial_laure_stat;*/ LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc"); LinphoneCoreManager* laure = linphone_core_manager_new("./tester/laure_rc"); @@ -460,7 +462,7 @@ static void simple_call_transfer() { LinphoneCall* marie_call_pauline; LinphoneCall* pauline_called_by_marie; -/* LinphoneCall* marie_call_laure;*/ + CU_ASSERT_TRUE(call(marie,pauline)); marie_call_pauline=linphone_core_get_current_call(marie->lc); @@ -479,42 +481,81 @@ static void simple_call_transfer() { CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallPaused,1,2000)); /*marie calling laure*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingProgress,1,2000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneTransferCallOutgoingInit,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallIncomingReceived,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingRinging,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneTransfertCallOutgoingProgress,1,2000)); + linphone_core_accept_call(laure->lc,linphone_core_get_current_call(laure->lc)); + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallConnected,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallConnected,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneTransfertCallConnected,1,2000)); - -/* - initial_marie_stat=marie->stat; - initial_pauline_stat=pauline->stat; - initial_laure_stat=laure->stat; - - marie_call_laure=linphone_core_get_current_call(marie->lc); - - - linphone_core_transfer_call() - CU_ASSERT_TRUE(wait_for(marie->lc,laure->lc,&marie->stat.number_of_LinphoneCallUpdating,initial_marie_stat.number_of_LinphoneCallUpdating+1)); - - - - linphone_core_add_to_conference(marie->lc,marie_call_pauline); - - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallResuming,initial_marie_stat.number_of_LinphoneCallResuming+1,2000)); - - CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,initial_pauline_stat.number_of_LinphoneCallStreamsRunning+1,2000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,initial_marie_stat.number_of_LinphoneCallStreamsRunning+2,2000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning,initial_laure_stat.number_of_LinphoneCallStreamsRunning+1,2000)); - - CU_ASSERT_TRUE(linphone_core_is_in_conference(marie->lc)); - CU_ASSERT_EQUAL(linphone_core_get_conference_size(marie->lc),3) - - linphone_core_terminate_conference(marie->lc); - + /*terminate marie to pauline call*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,2000)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); + ms_list_free(lcs); +} + +static void call_transfer_existing_call_outgoing_call() { + LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc"); + LinphoneCoreManager* laure = linphone_core_manager_new("./tester/laure_rc"); + + MSList* lcs=ms_list_append(NULL,marie->lc); + lcs=ms_list_append(lcs,pauline->lc); + lcs=ms_list_append(lcs,laure->lc); + + LinphoneCall* marie_call_pauline; + LinphoneCall* pauline_called_by_marie; + LinphoneCall* marie_call_laure; + LinphoneCall* laure_called_by_marie; + + /*marie call pauline*/ + CU_ASSERT_TRUE(call(marie,pauline)); + marie_call_pauline=linphone_core_get_current_call(marie->lc); + pauline_called_by_marie=linphone_core_get_current_call(pauline->lc); + /*marie pause pauline*/ + CU_ASSERT_TRUE(pause_call_1(marie,marie_call_pauline,pauline,pauline_called_by_marie)); + + /*marie call laure*/ + CU_ASSERT_TRUE(call(marie,laure)); + marie_call_laure=linphone_core_get_current_call(marie->lc); + laure_called_by_marie=linphone_core_get_current_call(laure->lc); + /*marie pause pauline*/ + CU_ASSERT_TRUE(pause_call_1(marie,marie_call_laure,laure,laure_called_by_marie)); + + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + reset_counters(&laure->stat); + + + linphone_core_transfer_call_to_another(marie->lc,marie_call_pauline,marie_call_laure); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallRefered,1,2000)); + + /*pauline calling laure*/ + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingProgress,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallOutgoingInit,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallIncomingReceived,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransfertCallOutgoingProgress,1,2000)); + linphone_core_accept_call(laure->lc,linphone_core_get_current_call(laure->lc)); + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallConnected,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallConnected,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransfertCallConnected,1,2000)); + + /*terminate marie to pauline/laure call*/ + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,2,2000)); CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,1,2000)); - -*/ linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(laure); @@ -559,7 +600,9 @@ int call_test_suite () { if (NULL == CU_add_test(pSuite, "simple_call_transfer", simple_call_transfer)) { return CU_get_error(); } - + if (NULL == CU_add_test(pSuite, "call_transfer_existing_call_outgoing_call", call_transfer_existing_call_outgoing_call)) { + return CU_get_error(); + } return 0; } diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 55428cb05..46263bf46 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -57,6 +57,11 @@ typedef struct _stats { int number_of_LinphoneCallReleased; int number_of_LinphoneTransferCallOutgoingInit; + int number_of_LinphoneTransfertCallOutgoingProgress; + int number_of_LinphoneTransfertCallOutgoingRinging; + int number_of_LinphoneTransfertCallOutgoingEarlyMedia; + int number_of_LinphoneTransfertCallConnected; + int number_of_LinphoneTransfertCallStreamsRunning; int number_of_LinphoneMessageReceived; int number_of_LinphoneMessageReceivedLegacy; @@ -91,7 +96,7 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf); void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *message); void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* message); -Qvoid new_subscribtion_request(LinphoneCore *lc, LinphoneFriend *lf, const char *url); +void new_subscribtion_request(LinphoneCore *lc, LinphoneFriend *lf, const char *url); void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username); LinphoneCore* create_lc_with_auth(unsigned int with_auth) ;