From 56e58d0cee2e970822ba460dc6f8f8c3936f4552 Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Wed, 18 Feb 2015 14:52:34 +0100 Subject: [PATCH] Change the SDP removal mechanism for something a bit more tunable. There is now an "SDP handling mode": you can choose between normal, simulate removal of SDP or simulate SDP error. This allows for simulating 200 OK without SDP, for instance (a unit test is coming for this). --- coreapi/bellesip_sal/sal_impl.c | 6 ++-- coreapi/bellesip_sal/sal_impl.h | 6 ++-- coreapi/bellesip_sal/sal_op_call.c | 22 ++++++++++---- coreapi/bellesip_sal/sal_op_impl.c | 8 ++--- include/sal/sal.h | 22 +++++++++++--- tester/call_tester.c | 48 +++++++++++++++++------------- tester/liblinphone_tester.h | 9 +++--- 7 files changed, 76 insertions(+), 45 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 3b3c24955..9829d22b3 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -1149,7 +1149,7 @@ void sal_enable_sip_update_method(Sal *ctx,bool_t value) { ctx->enable_sip_update=value; } -void sal_default_enable_sdp_removal(Sal *sal, bool_t enable) { - if (enable) ms_message("Enabling SDP removal feature by default for all new SalOp in Sal[%p]!", sal); - sal->default_sdp_removal = enable; +void sal_default_set_sdp_handling(Sal *sal, SalOpSDPHandling sdp_handling_method) { + if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", sal); + sal->default_sdp_handling = sdp_handling_method; } diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 21aeadc74..a2ec659f7 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -24,8 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "belle-sip/belle-sip.h" #include "belle-sip/belle-sdp.h" - - struct Sal{ SalCallbacks callbacks; MSList *pending_auths;/*MSList of SalOp */ @@ -52,7 +50,7 @@ struct Sal{ bool_t enable_test_features; bool_t no_initial_route; bool_t enable_sip_update; /*true by default*/ - bool_t default_sdp_removal; + SalOpSDPHandling default_sdp_handling; }; typedef enum SalOpState { @@ -107,7 +105,7 @@ struct SalOp{ bool_t call_released; bool_t manual_refresher; bool_t has_auth_pending; - bool_t sdp_removal; /* do not add SDP in outgoing INVITE and remove it from incoming INVITE */ + SalOpSDPHandling sdp_handling; int auth_requests; /*number of auth requested for this op*/ }; diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 7cf64947e..9b1bfeb5a 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -392,19 +392,23 @@ static int extract_sdp(SalOp *op, belle_sip_message_t* message,belle_sdp_session const char *body; belle_sip_header_content_type_t* content_type; - if (op&&op->sdp_removal){ - ms_error("Removed willingly SDP because sal_call_enable_sdp_removal was set to TRUE."); + if (op&&op->sdp_handling == SalOpSDPSimulateError){ + ms_error("Simulating SDP parsing error for op %p", op); *session_desc=NULL; *error=SalReasonNotAcceptable; return -1; + } else if( op && op->sdp_handling == SalOpSDPSimulateRemove){ + ms_error("Simulating no SDP for op %p", op); + *session_desc = NULL; + return 0; } - + body = belle_sip_message_get_body(message); if(body == NULL) { *session_desc = NULL; return 0; } - + content_type = belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t); if (content_type){ if (strcmp("application",belle_sip_header_content_type_get_type(content_type))==0 @@ -735,8 +739,14 @@ static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* respon set_sdp_from_desc(BELLE_SIP_MESSAGE(response),op->base.local_media); }else{ - if (op->sdp_answer==NULL) - sdp_process(op); + if ( op->sdp_answer==NULL ) + { + if( op->sdp_handling == SalOpSDPSimulateRemove ){ + ms_warning("Simulating SDP removal in answer for op %p", op); + } else { + sdp_process(op); + } + } if (op->sdp_answer){ set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer); diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 5c953ffc5..bdd120ae9 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -25,7 +25,7 @@ SalOp * sal_op_new(Sal *sal){ op->type=SalOpUnknown; op->privacy=SalPrivacyNone; op->manual_refresher=FALSE;/*tells that requests with expiry (SUBSCRIBE, PUBLISH) will be automatically refreshed*/ - op->sdp_removal=sal->default_sdp_removal; + op->sdp_handling=sal->default_sdp_handling; sal_op_ref(op); return op; } @@ -799,7 +799,7 @@ void sal_op_stop_refreshing(SalOp *op){ } } -void sal_call_enable_sdp_removal(SalOp *h, bool_t enable) { - if (enable) ms_message("Enabling SDP removal feature for SalOp[%p]!", h); - h->sdp_removal = enable; +void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) { + if (handling != SalOpSDPNormal) ms_message("Enabling special SDP handling for SalOp[%p]!", h); + h->sdp_handling = handling; } diff --git a/include/sal/sal.h b/include/sal/sal.h index 0b7775b9b..e1a0c3e66 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -203,6 +203,11 @@ typedef enum { SalMulticastSenderReceiver } SalMulticastRole; +typedef enum { + SalOpSDPNormal = 0, /** No special handling for SDP */ + SalOpSDPSimulateError, /** Will simulate an SDP parsing error */ + SalOpSDPSimulateRemove /** Will simulate no SDP in the op */ +} SalOpSDPHandling; typedef struct SalStreamDescription{ char name[16]; /*unique name of stream, in order to ease offer/answer model algorithm*/ @@ -682,11 +687,20 @@ void sal_call_send_vfu_request(SalOp *h); int sal_call_is_offerer(const SalOp *h); int sal_call_notify_refer_state(SalOp *h, SalOp *newcall); /* Call test API */ -/*willingly fails to parse SDP from received packets (INVITE and/or ACK) if value=true */ -/* First version: for all new SalOp created (eg. each incoming or outgoing call). Do not forget to reset previous value when you are done!*/ -void sal_default_enable_sdp_removal(Sal* h, bool_t enable) ; + + +/** + * @brief Invoking this on the SAL will modify every subsequent SalOp to have a special handling for SDP. + * @details This is especially useful while testing, to simulate some specific behaviors, like missing SDP or an error in parsing. + * + * @warning Don't forget to reset the handling method to SalOpSDPNormal afterwards. + * + * @param h the Sal instance + * @param handling_method Could be SalOpSDPNormal, SalOpSDPSimulateError, SalOpSDPSimulateRemoval (\ref SalOpSDPHandling) + */ +void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handling_method) ; /* Second version: for a specific call*/ -void sal_call_enable_sdp_removal(SalOp *h, bool_t enable) ; +void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) ; /*Registration*/ int sal_register(SalOp *op, const char *proxy, const char *from, int expires); diff --git a/tester/call_tester.c b/tester/call_tester.c index 42068f327..2d1e93e1d 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -178,6 +178,14 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana linphone_call_unref(c2); } +static void setup_sdp_handling(const LinphoneCallTestParams* params, LinphoneCoreManager* mgr ){ + if( params->sdp_removal ){ + sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateRemove); + } else if( params->sdp_simulate_error ){ + sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateError); + } +} + bool_t call_with_params2(LinphoneCoreManager* caller_mgr ,LinphoneCoreManager* callee_mgr , const LinphoneCallTestParams *caller_test_params @@ -189,10 +197,10 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr bool_t result=FALSE; LinphoneCallParams *caller_params = caller_test_params->base; LinphoneCallParams *callee_params = callee_test_params->base; - bool_t did_received_call; + bool_t did_receive_call; - sal_default_enable_sdp_removal(caller_mgr->lc->sal, caller_test_params->sdp_removal); - sal_default_enable_sdp_removal(callee_mgr->lc->sal, callee_test_params->sdp_removal); + setup_sdp_handling(caller_test_params, caller_mgr); + setup_sdp_handling(callee_test_params, callee_mgr); if (!caller_params){ CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity)); @@ -200,16 +208,16 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params)); } - did_received_call = wait_for(callee_mgr->lc + did_receive_call = wait_for(callee_mgr->lc ,caller_mgr->lc ,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived ,initial_callee.number_of_LinphoneCallIncomingReceived+1); - CU_ASSERT_EQUAL(did_received_call, !callee_test_params->sdp_removal); + CU_ASSERT_EQUAL(did_receive_call, !callee_test_params->sdp_simulate_error); - sal_default_enable_sdp_removal(caller_mgr->lc->sal, FALSE); - sal_default_enable_sdp_removal(callee_mgr->lc->sal, FALSE); + sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); - if (!did_received_call) return 0; + if (!did_receive_call) return 0; CU_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc)); @@ -913,7 +921,7 @@ static void call_with_no_sdp_ack_without_sdp(void){ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallIncomingReceived,1)); call=linphone_core_get_current_call(pauline->lc); if (call){ - sal_call_enable_sdp_removal(call->op, TRUE); /*this will have the effect that the SDP received in the ACK will be ignored*/ + sal_call_set_sdp_handling(call->op, SalOpSDPSimulateRemove); /*this will have the effect that the SDP received in the ACK will be ignored*/ linphone_core_accept_call(pauline->lc, call); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1)); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); @@ -3371,7 +3379,7 @@ static void incoming_invite_without_sdp() { LinphoneCoreManager* callee = linphone_core_manager_new( "marie_rc"); LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0}; - callee_test_params.sdp_removal = TRUE; + callee_test_params.sdp_simulate_error = TRUE; CU_ASSERT_FALSE(call_with_params2(caller,callee,&caller_test_params, &callee_test_params, FALSE)); CU_ASSERT_PTR_NULL(linphone_core_get_current_call(callee->lc)); @@ -3388,7 +3396,7 @@ static void outgoing_invite_without_sdp() { LinphoneCoreManager* callee = linphone_core_manager_new( "marie_rc"); LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0}; - caller_test_params.sdp_removal = TRUE; + caller_test_params.sdp_simulate_error = TRUE; CU_ASSERT_FALSE(call_with_params2(caller,callee,&caller_test_params, &callee_test_params, FALSE)); CU_ASSERT_PTR_NULL(linphone_core_get_current_call(callee->lc)); @@ -3415,8 +3423,8 @@ static void incoming_reinvite_without_ack_sdp() { const LinphoneCallParams *caller_params; stats initial_caller_stat=caller->stat; stats initial_callee_stat=callee->stat; - sal_call_enable_sdp_removal(inc_call->op, TRUE); - CU_ASSERT_PTR_NOT_NULL(setup_video(caller, callee)); + sal_call_set_sdp_handling(inc_call->op, SalOpSDPSimulateRemove); /*this will have the effect that the SDP received in the ACK will be ignored*/ + CU_ASSERT_PTR_NOT_NULL(setup_video(caller, callee)); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1)); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1)); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,initial_caller_stat.number_of_LinphoneCallStreamsRunning)); @@ -3431,7 +3439,7 @@ static void incoming_reinvite_without_ack_sdp() { caller_params = linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,(int*)&caller_params->has_video,FALSE)); - sal_call_enable_sdp_removal(inc_call->op, FALSE); + sal_call_set_sdp_handling(inc_call->op, SalOpSDPNormal); } linphone_core_terminate_all_calls(caller->lc); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallEnd,1)); @@ -3456,8 +3464,8 @@ static void outgoing_reinvite_without_ack_sdp() { if (out_call) { stats initial_caller_stat=caller->stat; stats initial_callee_stat=callee->stat; - sal_call_enable_sdp_removal(out_call->op, TRUE); - CU_ASSERT_PTR_NOT_NULL(setup_video(caller, callee)); + sal_call_set_sdp_handling(out_call->op, SalOpSDPSimulateRemove); /*this will have the effect that the SDP received in the ACK will be ignored*/ + CU_ASSERT_PTR_NOT_NULL(setup_video(caller, callee)); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1)); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1)); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,initial_caller_stat.number_of_LinphoneCallStreamsRunning)); @@ -3470,7 +3478,7 @@ static void outgoing_reinvite_without_ack_sdp() { CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))); - sal_call_enable_sdp_removal(out_call->op, FALSE); + sal_call_set_sdp_handling(out_call->op, SalOpSDPNormal); } linphone_core_terminate_all_calls(caller->lc); CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallEnd,1)); @@ -3576,18 +3584,18 @@ static void call_with_generic_cn(void) { CU_ASSERT_TRUE(rtps->packet_recv<=300 && rtps->packet_recv>=200); } end_call(marie,pauline); - + if (pauline_call){ struct stat stbuf; int err; - + err=stat(recorded_file,&stbuf); CU_ASSERT_EQUAL(err, 0); if (err==0){ CU_ASSERT_TRUE(stbuf.st_size>120000); } } - + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 22dbcd6f6..c25f61d6c 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -93,12 +93,12 @@ extern const char* liblinphone_tester_get_xml_output(void); /** * @brief Tells the tester whether or not to clean the accounts it has created between runs. * @details Setting this to 1 will not clear the list of created accounts between successive - * calls to liblinphone_run_tests(). Some testing APIs call this function for *each* test, + * calls to liblinphone_run_tests(). Some testing APIs call this function for *each* test, * in which case we should keep the accounts that were created for further testing. - * - * You are supposed to manually call liblinphone_tester_clear_account when all the tests are + * + * You are supposed to manually call liblinphone_tester_clear_account when all the tests are * finished. - * + * * @param keep 1 to keep the accounts in-between runs, 0 to clear them after each run. */ extern void liblinphone_tester_keep_accounts( int keep ); @@ -255,6 +255,7 @@ typedef struct _LinphoneCoreManager { typedef struct _LinphoneCallTestParams { LinphoneCallParams *base; bool_t sdp_removal; + bool_t sdp_simulate_error; } LinphoneCallTestParams; LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_for_proxies);