From f6f2381a09736b507869840f0084c08a515e1d06 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 15 Feb 2013 11:30:22 +0100 Subject: [PATCH] start call transfert, fix upnp crash, imp[lement incoming OPTION --- coreapi/bellesip_sal/sal_impl.c | 7 +- coreapi/bellesip_sal/sal_impl.h | 2 +- coreapi/bellesip_sal/sal_op_call.c | 188 ++++++++++++++++++----------- coreapi/bellesip_sal/sal_op_impl.c | 3 + coreapi/linphonecore.c | 15 ++- tester/call_tester.c | 15 ++- 6 files changed, 149 insertions(+), 81 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index f1336a491..0cd5aa3a6 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -145,11 +145,14 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev op->dir=SalOpDirIncoming; sal_op_message_fill_cbs(op); - } else { + } else if (strcmp("OPTION",belle_sip_request_get_method(req))==0) { + resp=belle_sip_response_create_from_request(req,200); + belle_sip_provider_send_response(((Sal*)sal)->prov,resp); + return; + }else { ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); resp=belle_sip_response_create_from_request(req,501); belle_sip_provider_send_response(((Sal*)sal)->prov,resp); - return; } diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 2f7262c6f..1e3962221 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -61,7 +61,7 @@ struct SalOp{ bool_t sdp_offering; belle_sip_dialog_t* dialog; belle_sip_header_replaces_t *replaces; - belle_sip_header_t *referred_by; + belle_sip_header_referred_by_t *referred_by; bool_t auto_answer_asked; SalMediaDescription *result; belle_sdp_session_description_t *sdp_answer; diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 2c6401d81..f0acc8112 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -19,6 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sal_impl.h" #include "offeranswer.h" +static void process_refer(SalOp *op, const belle_sip_request_event_t *event); + static void sdp_process(SalOp *h){ ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming"); if (h->result){ @@ -367,7 +369,9 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } resp=belle_sip_response_create_from_request(req,200); belle_sip_server_transaction_send_response(server_transaction,resp); - }else{ + }else if (strcmp("REFER",belle_sip_request_get_method(req))==0) { + process_refer(op,event); + } else{ ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); unsupported_method(server_transaction,req); } @@ -381,6 +385,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } + /*Call API*/ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ if (desc) @@ -548,36 +553,6 @@ SalMediaDescription * sal_call_get_final_media_description(SalOp *h){ } return h->result; } -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)); - 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); - return -1; - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to_header)); - 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_accept_refer(SalOp *h){ - ms_fatal("sal_call_accept_refer not implemented yet"); - return -1; -} -/*informs this call is consecutive to an incoming refer */ -int sal_call_set_referer(SalOp *h, SalOp *refered_call){ - ms_fatal("sal_call_set_referer not implemented yet"); - return -1; -} -/* returns the SalOp of a call that should be replaced by h, if any */ -SalOp *sal_call_get_replaces(SalOp *h){ - if (h!=NULL && h->replaces!=NULL){ - ms_fatal("sal_call_get_replaces not implemented yet"); - } - return NULL; -} int sal_call_send_dtmf(SalOp *h, char dtmf){ ms_fatal("sal_call_send_dtmf not implemented yet"); return -1; @@ -653,10 +628,91 @@ int sal_call_is_offerer(const SalOp *h){ return h->sdp_offering; } -int sal_call_notify_refer_state(SalOp *h, SalOp *newcall){ - ms_fatal("sal_call_notify_refer_state not implemented yet"); + +/*call transfer*/ +static void sal_op_set_replaces(SalOp* op,belle_sip_header_replaces_t* replaces) { + if (op->replaces){ + belle_sip_object_unref(op->replaces); + } + op->replaces=replaces; + belle_sip_object_ref(op->replaces); +} +static void sal_op_set_referred_by(SalOp* op,belle_sip_header_referred_by_t* referred_by) { + if (op->referred_by){ + belle_sip_object_unref(op->referred_by); + } + op->referred_by=referred_by; + 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)); + 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); + return -1; + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to_header)); + 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_accept_refer(SalOp *h){ + ms_fatal("sal_call_accept_refer not implemented yet"); + return -1; +} +/*informs this call is consecutive to an incoming refer */ +int sal_call_set_referer(SalOp *h, SalOp *refered_call){ + if (refered_call->replaces) + sal_op_set_replaces(h,refered_call->replaces); + if (refered_call->referred_by) + sal_op_set_referred_by(h,refered_call->referred_by); + return 0; +} +/* returns the SalOp of a call that should be replaced by h, if any */ +SalOp *sal_call_get_replaces(SalOp *h){ + if (h!=NULL && h->replaces!=NULL){ + ms_fatal("sal_call_get_replaces not implemented yet"); + } + return NULL; +} + +static int send_notify_for_refer(SalOp* op, const char *sipfrag){ + belle_sip_request_t* notify=belle_sip_dialog_create_request(op->dialog,"NOTIFY"); + size_t content_length=strlen(sipfrag); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,-1))); + + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),belle_sip_header_create("Event","refer")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_type_create("message","sipfrag"))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),sipfrag,content_length); + + return sal_op_send_request(op,notify); +} + +int sal_call_notify_refer_state(SalOp *op, SalOp *newcall){ + belle_sip_dialog_state_t state=newcall->dialog?belle_sip_dialog_get_state(newcall->dialog):BELLE_SIP_DIALOG_NULL; + switch(state) { + case BELLE_SIP_DIALOG_NULL: + case BELLE_SIP_DIALOG_EARLY: + send_notify_for_refer(op,"SIP/2.0 100 Trying\r\n"); + break; + case BELLE_SIP_DIALOG_CONFIRMED: + if(send_notify_for_refer(op,"SIP/2.0 200 Ok\r\n")) { + /* we need previous notify transaction to complete, so buffer the request for later*/ + /*op->sipfrag_pending="SIP/2.0 200 Ok\r\n";*/ + ms_error("Cannot notify 200 ok frag to [%p] for new op [%p]",op,newcall); + } + break; + default: + break; + } + return 0; +} + void sal_expire_old_registration_contacts(Sal *ctx, bool_t enabled){ ms_warning("sal_expire_old_registration_contacts not implemented "); } @@ -664,49 +720,37 @@ void sal_expire_old_registration_contacts(Sal *ctx, bool_t enabled){ void sal_use_dates(Sal *ctx, bool_t enabled){ ms_warning("sal_use_dates not implemented yet"); } -/* -static void process_refer(SalOp *op, belle_sip_request_event_t *event){ + + + +static void process_refer(SalOp *op, const belle_sip_request_event_t *event){ belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t);; - belle_sip_uri_t* refer_to_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)); + belle_sip_header_referred_by_t *referred_by= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_referred_by_t);; + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); + belle_sip_response_t* resp; + belle_sip_uri_t* refer_to_uri; + char* refer_to_uri_str; ms_message("Receiving REFER request on op [%p]",op); - if (refer_to){ - char *tmp; - if (refer_to_uri){ - if (op ){ - osip_uri_header_t *uh=NULL; - osip_header_t *referred_by=NULL; - osip_uri_header_get_byname(&from->url->url_headers,(char*)"Replaces",&uh); - if (belle_sip_uri_get_header(refer_to_uri,"Replaces")) - if (uh!=NULL && uh->gvalue && uh->gvalue[0]!='\0'){ - ms_message("Found replaces in Refer-To"); - if (op->replaces){ - ms_free(op->replaces); - } - op->replaces=ms_strdup(uh->gvalue); - } - osip_message_header_get_byname(ev->request,"Referred-By",0,&referred_by); - if (referred_by && referred_by->hvalue && referred_by->hvalue[0]!='\0'){ - if (op->referred_by) - ms_free(op->referred_by); - op->referred_by=ms_strdup(referred_by->hvalue); - } - } - osip_uri_header_freelist(&from->url->url_headers); - osip_from_to_str(from,&tmp); - sal->callbacks.refer_received(sal,op,tmp); - osip_free(tmp); - osip_from_free(from); + if (refer_to) { + refer_to_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)); + + if (refer_to_uri && belle_sip_uri_get_header(refer_to_uri,"Replaces")) { + sal_op_set_replaces(op,belle_sip_header_replaces_create2(belle_sip_uri_get_header(refer_to_uri,"Replaces"))); } - eXosip_lock(); - eXosip_call_build_answer(ev->tid,202,&ans); - if (ans) - eXosip_call_send_answer(ev->tid,202,ans); - eXosip_unlock(); - } - else - { + if (referred_by){ + sal_op_set_referred_by(op,referred_by); + } + refer_to_uri_str=belle_sip_uri_to_string(refer_to_uri); + resp = belle_sip_response_create_from_request(req,202); + belle_sip_server_transaction_send_response(server_transaction,resp); + op->base.root->callbacks.refer_received(op->base.root,op,refer_to_uri_str); + belle_sip_free(refer_to_uri_str); + } else { ms_warning("cannot do anything with the refer without destination\n"); + resp = belle_sip_response_create_from_request(req,501); + belle_sip_server_transaction_send_response(server_transaction,resp); } + } -*/ + diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 6d6b7a955..7f052e358 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -34,6 +34,9 @@ void sal_op_release(SalOp *op){ belle_sip_refresher_stop(op->registration_refresher); belle_sip_object_unref(op->registration_refresher); } + if(op->replaces) belle_sip_object_unref(op->replaces); + if(op->referred_by) belle_sip_object_unref(op->referred_by); + if (op->pending_inv_client_trans) belle_sip_object_unref(op->pending_inv_client_trans); __sal_op_free(op); return ; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 36f3f6b82..f0d6e6da1 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -5232,10 +5232,7 @@ static void linphone_core_uninit(LinphoneCore *lc) #endif } -#ifdef BUILD_UPNP - linphone_upnp_context_destroy(lc->upnp); - lc->upnp = NULL; -#endif //BUILD_UPNP + if (lc->friends) /* FIXME we should wait until subscription to complete*/ ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions); @@ -5257,10 +5254,18 @@ static void linphone_core_uninit(LinphoneCore *lc) codecs_config_uninit(lc); ui_config_uninit(lc); sip_config_uninit(lc); + + + sip_setup_unregister_all(); + +#ifdef BUILD_UPNP + if (lc->upnp) linphone_upnp_context_destroy(lc->upnp); + lc->upnp = NULL; +#endif //BUILD_UPNP + if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config); lp_config_destroy(lc->config); lc->config = NULL; /* Mark the config as NULL to block further calls */ - sip_setup_unregister_all(); ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy); lc->call_logs=ms_list_free(lc->call_logs); diff --git a/tester/call_tester.c b/tester/call_tester.c index 3ca6ebe71..b44b17ad6 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -385,7 +385,6 @@ static void simple_conference() { 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); @@ -439,6 +438,7 @@ static void simple_call_transfer() { stats initial_laure_stat;*/ LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc"); LinphoneCoreManager* laure = linphone_core_manager_new("./tester/laure_rc"); + char* laure_identity=linphone_address_as_string(laure->identity); MSList* lcs=ms_list_append(NULL,marie->lc); lcs=ms_list_append(lcs,pauline->lc); @@ -452,8 +452,21 @@ static void simple_call_transfer() { marie_call_pauline=linphone_core_get_current_call(marie->lc); pauline_called_by_marie=linphone_core_get_current_call(pauline->lc); + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + reset_counters(&laure->stat); + linphone_core_transfer_call(pauline->lc,pauline_called_by_marie,laure_identity); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallRefered,1,2000)); + /*marie pausing pauline*/ + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallPausing,1,2000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallPausedByRemote,1,2000)); + 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,&marie->stat.number_of_LinphoneCallOutgoingProgress,2,2000)); /* initial_marie_stat=marie->stat;