From b57f8b1526e3ea128480a9672e84215c6fbc26cc Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Tue, 18 Feb 2014 15:55:56 +0100 Subject: [PATCH] Added 302 redirection support. + removed macros for sal_op_get_contact compatibility --- coreapi/bellesip_sal/sal_impl.c | 10 ++++ coreapi/bellesip_sal/sal_op_call.c | 2 +- coreapi/bellesip_sal/sal_op_impl.c | 10 +++- coreapi/bellesip_sal/sal_op_message.c | 2 +- coreapi/bellesip_sal/sal_op_publish.c | 4 +- coreapi/callbacks.c | 20 ++++++- coreapi/linphonecall.c | 23 ++++++-- coreapi/linphonecore.c | 32 +++++----- coreapi/linphonecore.h | 1 + coreapi/presence.c | 4 +- coreapi/private.h | 2 +- coreapi/proxy.c | 4 +- coreapi/sal.c | 32 +++++----- include/sal/sal.h | 6 +- tester/call_tester.c | 84 ++++++++++++++++++++++++--- 15 files changed, 171 insertions(+), 65 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 70f04673c..eacc38686 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -198,6 +198,7 @@ static void process_request_event(void *ud, const belle_sip_request_event_t *eve belle_sip_response_t* resp; belle_sip_header_t *evh; const char *method=belle_sip_request_get_method(req); + belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); @@ -257,6 +258,9 @@ static void process_request_event(void *ud, const belle_sip_request_event_t *eve belle_sip_object_unref(address); } + if( remote_contact ){ + __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); + } if (!op->base.to_address) { to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); @@ -303,6 +307,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even } else { SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(response, belle_sip_header_contact_t); if (op->state == SalOpStateTerminated) { belle_sip_message("Op is terminated, nothing to do with this [%i]",response_code); @@ -311,6 +316,11 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even if (!op->base.remote_ua) { sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response)); } + + if(remote_contact) { + __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); + } + if (!op->base.call_id) { op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t)))); } diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 7fe5982c7..a51792706 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -725,7 +725,7 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti if (reason==SalReasonRedirect){ if (redirection!=NULL) { if (strstr(redirection,"sip:")!=0) status=302; - status=380; + else status=380; contact= belle_sip_header_contact_new(); belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); } else { diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index cade07854..e1b5d7a0b 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -210,7 +210,7 @@ static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *m if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){ belle_sip_header_contact_t* newct; /*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/ - sal_op_set_contact(op,(SalAddress*)BELLE_SIP_HEADER_ADDRESS(h)); + sal_op_set_contact_address(op,(SalAddress*)BELLE_SIP_HEADER_ADDRESS(h)); newct = sal_op_create_contact(op); belle_sip_message_set_header(BELLE_SIP_MESSAGE(msg),BELLE_SIP_HEADER(newct)); return; @@ -381,6 +381,10 @@ SalReason sal_reason_to_sip_code(SalReason r){ void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) { switch(code) { + case 302: + *sal_reason=SalReasonRedirect; + *sal_err=SalErrorFailure; + break; case 400: *sal_err=SalErrorUnknown; break; @@ -560,7 +564,9 @@ void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){ } const char *sal_op_get_remote_contact(const SalOp *op){ - return sal_custom_header_find(op->base.recv_custom_headers,"Contact"); + // remote contact is filled in process_response +// return sal_custom_header_find(op->base.recv_custom_headers,"Contact"); + return op->base.remote_contact; } void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body){ diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c index 0db775a3c..c147b649b 100644 --- a/coreapi/bellesip_sal/sal_op_message.c +++ b/coreapi/bellesip_sal/sal_op_message.c @@ -162,7 +162,7 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co op->dir=SalOpDirOutgoing; req=sal_op_build_request(op,"MESSAGE"); - if (sal_op_get_contact(op)){ + if (sal_op_get_contact_address(op)){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type); diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c index 196167095..a55042919 100644 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ b/coreapi/bellesip_sal/sal_op_publish.c @@ -72,7 +72,7 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expire op->type=SalOpPublish; req=sal_op_build_request(op,"PUBLISH"); - if (sal_op_get_contact(op)){ + if (sal_op_get_contact_address(op)){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event","presence")); @@ -97,7 +97,7 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna sal_op_publish_fill_cbs(op); req=sal_op_build_request(op,"PUBLISH"); - if (sal_op_get_contact(op)){ + if (sal_op_get_contact_address(op)){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 2a98769e7..a31ac04d7 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -76,7 +76,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia SalMediaDescription *oldmd=call->resultdesc; bool_t all_muted=FALSE; bool_t send_ringbacktone=FALSE; - + linphone_core_stop_ringing(lc); if (!new_md) { ms_error("linphone_core_update_streams() called with null media description"); @@ -620,9 +620,27 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de lc->vtable.display_status(lc,msg486); break; case SalReasonRedirect: + { + ms_error("case SalReasonRedirect"); + linphone_call_stop_media_streams(call); + if ( call->state==LinphoneCallOutgoingInit + || call->state==LinphoneCallOutgoingProgress + || call->state==LinphoneCallOutgoingRinging /*push case*/ + || call->state==LinphoneCallOutgoingEarlyMedia){ + LinphoneAddress* redirection_to = linphone_call_get_remote_contact_address(call); + if( redirection_to ){ + char* url = linphone_address_as_string(redirection_to); + ms_error("Redirecting call [%p] to %s",call, url); + ms_free(url); + linphone_call_create_op(call); + linphone_core_start_invite(lc, call, redirection_to); + return; + } + } msg=_("Redirected"); if (lc->vtable.display_status) lc->vtable.display_status(lc,msg); + } break; case SalReasonTemporarilyUnavailable: msg=msg480; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index c28c83576..bbae572d4 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1064,6 +1064,17 @@ const char *linphone_call_get_remote_contact(LinphoneCall *call){ return NULL; } +/** + * Returns the far end's sip contact as a string, if available. +**/ +LinphoneAddress *linphone_call_get_remote_contact_address(LinphoneCall *call){ + if (call->op){ + return (LinphoneAddress*)sal_op_get_remote_contact_address(call->op); + } + return NULL; +} + + /** * Returns true if this calls has received a transfer that has not been * executed yet. @@ -2792,18 +2803,18 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , ctt=linphone_core_get_primary_contact_parsed(lc); linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc)); ret=ctt; - } else if (call->op && sal_op_get_contact(call->op)!=NULL){ + } else if (call->op && sal_op_get_contact_address(call->op)!=NULL){ /* if already choosed, don't change it */ return NULL; - } else if (call->ping_op && sal_op_get_contact(call->ping_op)) { + } else if (call->ping_op && sal_op_get_contact_address(call->ping_op)) { /* if the ping OPTIONS request succeeded use the contact guessed from the received, rport*/ ms_message("Contact has been fixed using OPTIONS"/* to %s",guessed*/); - ret=linphone_address_clone(sal_op_get_contact(call->ping_op));; - } else if (dest_proxy && dest_proxy->op && sal_op_get_contact(dest_proxy->op)){ + ret=linphone_address_clone(sal_op_get_contact_address(call->ping_op));; + } else if (dest_proxy && dest_proxy->op && sal_op_get_contact_address(dest_proxy->op)){ /*if using a proxy, use the contact address as guessed with the REGISTERs*/ ms_message("Contact has been fixed using proxy" /*to %s",fixed_contact*/); - ret=linphone_address_clone(sal_op_get_contact(dest_proxy->op)); + ret=linphone_address_clone(sal_op_get_contact_address(dest_proxy->op)); } else { ctt=linphone_core_get_primary_contact_parsed(lc); if (ctt!=NULL){ @@ -2832,7 +2843,7 @@ void linphone_call_set_contact_op(LinphoneCall* call) { SalTransport tport=sal_address_get_transport((SalAddress*)contact); sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/ sal_address_set_transport((SalAddress*)contact,tport); - sal_op_set_contact(call->op, contact); + sal_op_set_contact_address(call->op, contact); linphone_address_destroy(contact); } } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index b20ea9c8f..812565ac9 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2265,7 +2265,7 @@ void linphone_core_iterate(LinphoneCore *lc){ linphone_call_delete_upnp_session(call); } #endif //BUILD_UPNP - linphone_core_start_invite(lc,call); + linphone_core_start_invite(lc,call, NULL); } if (call->state==LinphoneCallIncomingReceived){ if (one_second_elapsed) ms_message("incoming call ringing for %i seconds",elapsed); @@ -2572,17 +2572,17 @@ int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *c } if ((ice_ready == TRUE) && (upnp_ready == TRUE) && (ping_ready == TRUE)) { - return linphone_core_start_invite(lc, call); + return linphone_core_start_invite(lc, call, NULL); } return 0; } int linphone_core_restart_invite(LinphoneCore *lc, LinphoneCall *call){ linphone_call_create_op(call); - return linphone_core_start_invite(lc,call); + return linphone_core_start_invite(lc,call, NULL); } -int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){ +int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const LinphoneAddress* destination /* = NULL if to be taken from the call log */){ int err; char *real_url,*barmsg; char *from; @@ -2592,7 +2592,7 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){ linphone_core_stop_dtmf_stream(lc); linphone_call_init_media_streams(call); linphone_call_make_local_media_description(lc,call); - + if (lc->ringstream==NULL) { if (lc->sound_conf.play_sndcard && lc->sound_conf.capt_sndcard){ /*give a chance a set card prefered sampling frequency*/ @@ -2602,20 +2602,20 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){ audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard); } } - real_url=linphone_address_as_string(call->log->to); + real_url=linphone_address_as_string( destination ? destination : call->log->to); from=linphone_address_as_string(call->log->from); - + if (!lc->sip_conf.sdp_200_ack){ /*we are offering, set local media description before sending the call*/ sal_call_set_local_media_description(call->op,call->localdesc); } err=sal_call(call->op,from,real_url); if (lc->sip_conf.sdp_200_ack){ - /*we are NOT offering, set local media description after sending the call so that we are ready to + /*we are NOT offering, set local media description after sending the call so that we are ready to process the remote offer when it will arrive*/ sal_call_set_local_media_description(call->op,call->localdesc); } - + call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/ barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url); @@ -2735,12 +2735,12 @@ void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *d sal_op_set_sent_custom_header(op,headers); if (with_contact && proxy && proxy->op){ const SalAddress *contact; - if ((contact=sal_op_get_contact(proxy->op))){ + if ((contact=sal_op_get_contact_address(proxy->op))){ SalTransport tport=sal_address_get_transport((SalAddress*)contact); SalAddress *new_contact=sal_address_clone(contact); sal_address_clean(new_contact); /* clean out contact_params that come from proxy config*/ sal_address_set_transport(new_contact,tport); - sal_op_set_contact(op,new_contact); + sal_op_set_contact_address(op,new_contact); sal_address_destroy(new_contact); } } @@ -2791,14 +2791,14 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const parsed_url2=linphone_address_new(from); call=linphone_call_new_outgoing(lc,parsed_url2,linphone_address_clone(addr),params,proxy); - + if(linphone_core_add_call(lc,call)!= 0) { ms_warning("we had a problem in adding the call into the invite ... weird"); linphone_call_unref(call); return NULL; } - + /* this call becomes now the current one*/ lc->current_call=call; linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); @@ -2845,7 +2845,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const } } - if (defer==FALSE) linphone_core_start_invite(lc,call); + if (defer==FALSE) linphone_core_start_invite(lc,call,NULL); if (real_url!=NULL) ms_free(real_url); return call; @@ -3033,8 +3033,8 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){ sal_call_set_local_media_description (call->op,call->localdesc); if (call->dest_proxy && call->dest_proxy->op){ /*give a chance to update the contact address if connectivity has changed*/ - sal_op_set_contact(call->op,sal_op_get_contact(call->dest_proxy->op)); - }else sal_op_set_contact(call->op,NULL); + sal_op_set_contact_address(call->op,sal_op_get_contact_address(call->dest_proxy->op)); + }else sal_op_set_contact_address(call->op,NULL); return sal_call_update(call->op,subject); } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 7d3bee804..291748312 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -655,6 +655,7 @@ LINPHONE_PUBLIC int linphone_call_take_video_snapshot(LinphoneCall *call, const LINPHONE_PUBLIC LinphoneReason linphone_call_get_reason(const LinphoneCall *call); LINPHONE_PUBLIC const char *linphone_call_get_remote_user_agent(LinphoneCall *call); LINPHONE_PUBLIC const char *linphone_call_get_remote_contact(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneAddress *linphone_call_get_remote_contact_address(LinphoneCall *call); LINPHONE_PUBLIC float linphone_call_get_play_volume(LinphoneCall *call); LINPHONE_PUBLIC float linphone_call_get_record_volume(LinphoneCall *call); LINPHONE_PUBLIC float linphone_call_get_current_quality(LinphoneCall *call); diff --git a/coreapi/presence.c b/coreapi/presence.c index 668d8ad4b..af4c5184d 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1476,8 +1476,8 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ cfg=linphone_core_lookup_known_proxy(lc,uri); if (cfg!=NULL){ if (cfg->op){ - if (sal_op_get_contact(cfg->op)) { - sal_op_set_contact (op,sal_op_get_contact(cfg->op)); + if (sal_op_get_contact_address(cfg->op)) { + sal_op_set_contact_address (op,sal_op_get_contact_address(cfg->op)); ms_message("Contact for next subscribe answer has been fixed using proxy "/*to %s",fixed_contact*/); } } diff --git a/coreapi/private.h b/coreapi/private.h index 7ba09d33b..948bac604 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -368,7 +368,7 @@ void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float void linphone_core_stop_waiting(LinphoneCore *lc); int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy); -int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call); +int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const LinphoneAddress* destination/* = NULL if to be taken from the call log */); int linphone_core_restart_invite(LinphoneCore *lc, LinphoneCall *call); int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call); int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 0c710cb3a..6bc8e5588 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -329,7 +329,7 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ sal_op_release(obj->op); obj->op=sal_op_new(obj->lc->sal); if ((contact=guess_contact_for_register(obj))) { - sal_op_set_contact(obj->op,contact); + sal_op_set_contact_address(obj->op,contact); linphone_address_destroy(contact); } sal_op_set_user_pointer(obj->op,obj); @@ -815,7 +815,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy)); if (lp_config_get_int(proxy->lc->config,"sip","publish_msg_with_contact",0)){ SalAddress *addr=sal_address_new(linphone_proxy_config_get_identity(proxy)); - sal_op_set_contact(proxy->publish_op,addr); + sal_op_set_contact_address(proxy->publish_op,addr); sal_address_unref(addr); } } diff --git a/coreapi/sal.c b/coreapi/sal.c index de5f235df..46f7325df 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -253,7 +253,6 @@ static void assign_string(char **str, const char *arg){ *str=ms_strdup(arg); } -#ifdef USE_BELLESIP void sal_op_set_contact_address(SalOp *op, const SalAddress *address){ if (((SalOpBase*)op)->contact_address) sal_address_destroy(((SalOpBase*)op)->contact_address); ((SalOpBase*)op)->contact_address=address?sal_address_clone(address):NULL; @@ -261,7 +260,12 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress *address){ const SalAddress* sal_op_get_contact_address(const SalOp *op) { return ((SalOpBase*)op)->contact_address; } -#endif + +const SalAddress*sal_op_get_remote_contact_address(const SalOp* op) +{ + return ((SalOpBase*)op)->remote_contact_address; +} + #define SET_PARAM(op,name) \ char* name##_string=NULL; \ assign_address(&((SalOpBase*)op)->name##_address,name); \ @@ -271,14 +275,7 @@ const SalAddress* sal_op_get_contact_address(const SalOp *op) { assign_string(&((SalOpBase*)op)->name,name##_string); \ if(name##_string) ms_free(name##_string); -#ifndef USE_BELLESIP -void sal_op_set_contact(SalOp *op, const char *contact){ - assign_string(&((SalOpBase*)op)->contact,contact); -} -const char *sal_op_get_contact(const SalOp *op){ - return ((SalOpBase*)op)->contact; -} -#endif + void sal_op_set_route(SalOp *op, const char *route){ char* route_string=(void *)0; SalOpBase* op_base = (SalOpBase*)op; @@ -384,9 +381,10 @@ void __sal_op_set_network_origin(SalOp *op, const char *origin){ SET_PARAM(op,origin); } -void __sal_op_set_remote_contact(SalOp *op, const char *ct){ - assign_string(&((SalOpBase*)op)->remote_contact,ct); +void __sal_op_set_remote_contact(SalOp *op, const char* remote_contact){ + SET_PARAM(op,remote_contact); } + void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin){ char* address_string=sal_address_as_string(origin); /*can probably be optimized*/ __sal_op_set_network_origin(op,address_string); @@ -426,16 +424,9 @@ void __sal_op_free(SalOp *op){ ms_free(b->route); b->route=NULL; } -#ifndef USE_BELLESIP - if (b->contact) { - ms_free(b->contact); - b->contact=NULL; - } -#else if (b->contact_address) { sal_address_destroy(b->contact_address); } -#endif if (b->origin){ ms_free(b->origin); b->origin=NULL; @@ -448,6 +439,9 @@ void __sal_op_free(SalOp *op){ ms_free(b->remote_contact); b->remote_contact=NULL; } + if (b->remote_contact_address){ + sal_address_destroy(b->remote_contact_address); + } if (b->local_media) sal_media_description_unref(b->local_media); if (b->remote_media) diff --git a/include/sal/sal.h b/include/sal/sal.h index 87092cfad..8ff57dc12 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -256,11 +256,12 @@ typedef struct SalOpBase{ char *origin; SalAddress* origin_address; char *remote_ua; + SalAddress* remote_contact_address; + char *remote_contact; SalMediaDescription *local_media; SalMediaDescription *remote_media; void *user_pointer; const char* call_id; - char *remote_contact; SalAddress* service_route; /*as defined by rfc3608, might be a list*/ SalCustomHeader *sent_custom_headers; SalCustomHeader *recv_custom_headers; @@ -517,7 +518,6 @@ SalOp * sal_op_new(Sal *sal); /*generic SalOp API, working for all operations */ Sal *sal_op_get_sal(const SalOp *op); -#define sal_op_set_contact sal_op_set_contact_address /*for liblinphone compatibility*/ void sal_op_set_contact_address(SalOp *op, const SalAddress* address); void sal_op_set_route(SalOp *op, const char *route); void sal_op_set_route_address(SalOp *op, const SalAddress* address); @@ -537,11 +537,11 @@ const SalAddress *sal_op_get_from_address(const SalOp *op); const char *sal_op_get_to(const SalOp *op); const SalAddress *sal_op_get_to_address(const SalOp *op); const SalAddress *sal_op_get_contact_address(const SalOp *op); -#define sal_op_get_contact sal_op_get_contact_address /*for liblinphone compatibility*/ const char *sal_op_get_route(const SalOp *op); const MSList* sal_op_get_route_addresses(const SalOp *op); const char *sal_op_get_proxy(const SalOp *op); const char *sal_op_get_remote_contact(const SalOp *op); +const SalAddress* sal_op_get_remote_contact_address(const SalOp *op); /*for incoming requests, returns the origin of the packet as a sip uri*/ const char *sal_op_get_network_origin(const SalOp *op); const SalAddress *sal_op_get_network_origin_address(const SalOp *op); diff --git a/tester/call_tester.c b/tester/call_tester.c index ecf0068bf..2b40e6bf0 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -548,10 +548,15 @@ static void call_with_ice(void) { static void call_with_custom_headers(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - LinphoneCall *c1,*c2; + LinphoneCall *call_marie,*call_pauline; LinphoneCallParams *params; const LinphoneCallParams *remote_params; const char *hvalue; + const char *pauline_remote_contact_header, + *pauline_remote_contact, + *marie_remote_contact, + *marie_remote_contact_header; + char* tmp=linphone_address_as_string_uri_only(marie->identity); char tmp2[256]; snprintf(tmp2,sizeof(tmp2),"%s?uriHeader=myUriHeader",tmp); @@ -567,13 +572,13 @@ static void call_with_custom_headers(void) { CU_ASSERT_TRUE(call_with_caller_params(pauline,marie,params)); linphone_call_params_destroy(params); - c1=linphone_core_get_current_call(marie->lc); - c2=linphone_core_get_current_call(pauline->lc); + call_marie=linphone_core_get_current_call(marie->lc); + call_pauline=linphone_core_get_current_call(pauline->lc); - CU_ASSERT_PTR_NOT_NULL(c1); - CU_ASSERT_PTR_NOT_NULL(c2); + CU_ASSERT_PTR_NOT_NULL(call_marie); + CU_ASSERT_PTR_NOT_NULL(call_pauline); - remote_params=linphone_call_get_remote_params(c1); + remote_params=linphone_call_get_remote_params(call_marie); hvalue=linphone_call_params_get_custom_header(remote_params,"Weather"); CU_ASSERT_PTR_NOT_NULL(hvalue); CU_ASSERT_STRING_EQUAL(hvalue,"bad"); @@ -581,8 +586,18 @@ static void call_with_custom_headers(void) { CU_ASSERT_PTR_NOT_NULL(hvalue); CU_ASSERT_STRING_EQUAL(hvalue,"myUriHeader"); - CU_ASSERT_PTR_NOT_NULL(linphone_call_get_remote_contact(c1)); - + + pauline_remote_contact_header = linphone_call_params_get_custom_header(linphone_call_get_remote_params(call_pauline), "Contact"); + pauline_remote_contact = linphone_call_get_remote_contact(call_pauline); + marie_remote_contact = linphone_call_get_remote_contact(call_marie); + marie_remote_contact_header = linphone_call_params_get_custom_header(remote_params, "Contact"); + CU_ASSERT_PTR_NOT_NULL(pauline_remote_contact); + CU_ASSERT_PTR_NOT_NULL(pauline_remote_contact_header); + CU_ASSERT_PTR_NOT_NULL(marie_remote_contact); + CU_ASSERT_PTR_NOT_NULL(marie_remote_contact_header); + CU_ASSERT_STRING_EQUAL(pauline_remote_contact,pauline_remote_contact_header); + CU_ASSERT_STRING_EQUAL(marie_remote_contact,marie_remote_contact_header); + /*just to sleep*/ linphone_core_terminate_all_calls(pauline->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); @@ -1377,6 +1392,56 @@ static void call_established_with_rejected_incoming_reinvite(void) { linphone_core_manager_destroy(pauline); } +static void call_redirect(void){ + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_rc"); + LinphoneCoreManager* laure = linphone_core_manager_new("laure_rc"); + MSList* lcs = NULL; + char *margaux_url = NULL; + LinphoneCall* marie_call; + + lcs = ms_list_append(lcs,marie->lc); + lcs = ms_list_append(lcs,pauline->lc); + lcs = ms_list_append(lcs,laure->lc); + /* + Marie calls Pauline, which will redirect the call to Laure via a 302 + */ + + marie_call = linphone_core_invite_address(marie->lc, pauline->identity); + + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived,1,1000)); + + margaux_url = linphone_address_as_string(laure->identity); + linphone_core_redirect_call(pauline->lc, linphone_core_get_current_call(pauline->lc), margaux_url); + ms_free(margaux_url); + + /* laure should be ringing now */ + CU_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallIncomingReceived,1,6000)); + /* pauline should have ended the call */ + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEnd,1,1000)); + /* the call should still be ringing on marie's side */ + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1,1000)); + + linphone_core_accept_call(laure->lc, linphone_core_get_current_call(laure->lc)); + + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); + + CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); + + liblinphone_tester_check_rtcp(marie, laure); + + linphone_core_terminate_all_calls(laure->lc); + + CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); + +} + static void call_established_with_rejected_reinvite_with_error(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -1503,7 +1568,8 @@ test_t call_tests[] = { { "Call established with rejected INFO",call_established_with_rejected_info}, { "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite}, { "Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite }, - { "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error} + { "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error}, + { "Call redirected by callee", call_redirect} }; test_suite_t call_test_suite = {