From c5f239101b2d2b0c480fdca8f3d37a7d7840bc65 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Mon, 18 Mar 2013 19:32:38 +0100 Subject: [PATCH] implement minimal prack support --- coreapi/bellesip_sal/sal_op_call.c | 16 ++++- coreapi/linphonecall.c | 80 ++++++++++++++++++++++++ coreapi/linphonecore.c | 99 ++---------------------------- coreapi/linphonecore.h | 6 +- coreapi/private.h | 3 +- coreapi/proxy.c | 40 +++++++++++- 6 files changed, 143 insertions(+), 101 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 2b484ac18..061fe1d87 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -352,6 +352,9 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_server_transaction_send_response(server_transaction ,belle_sip_response_create_from_request(req,481)); } + } else if (strcmp("PRACK",belle_sip_request_get_method(req))==0) { + resp=belle_sip_response_create_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); } else { belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY"); unsupported_method(server_transaction,req); @@ -495,10 +498,21 @@ static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* respon } int sal_call_notify_ringing(SalOp *op, bool_t early_media){ int status_code =early_media?183:180; - belle_sip_response_t* ringing_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status_code); + belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)); + belle_sip_response_t* ringing_response = belle_sip_response_create_from_request(req,status_code); if (early_media){ handle_offer_answer_response(op,ringing_response); } + /*fixme it should support PRACK in the right way*/ + if (belle_sip_message_get_header((belle_sip_message_t*)req,"Require")) { + belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op); + belle_sip_header_contact_t* contact_header; + belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_message_get_header((belle_sip_message_t*)req,"Require")); + belle_sip_message_add_header((belle_sip_message_t*)ringing_response,BELLE_SIP_HEADER(belle_sip_header_extension_create("RSeq","1"))); + if (contact && (contact_header=belle_sip_header_contact_create(contact))) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header)); + } + } belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response); return 0; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index fd92ba42e..1f8a288b0 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2420,3 +2420,83 @@ void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, }else ms_warning("Could not apply zoom: video output wasn't activated."); } +#ifndef USE_BELLESIP +static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){ +#else +static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){ +#endif + LinphoneAddress *ctt=NULL; +#ifdef USE_BELLESIP + LinphoneAddress *ret=NULL; +#else + char* ret; +#endif + const char *localip=call->localip; + + /* first use user's supplied ip address if asked*/ + if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){ + ctt=linphone_core_get_primary_contact_parsed(lc); + linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc)); + #ifdef USE_BELLESIP + ret=ctt; + #else + ret=linphone_adress_as_string(ctt); + #endif + } else if (call->op && sal_op_get_contact(call->op)!=NULL){ + /* if already choosed, don't change it */ + return NULL; + } else if (call->ping_op && sal_op_get_contact(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*/); +#ifdef USE_BELLESIP + ret=linphone_address_clone(sal_op_get_contact(call->ping_op));; +#else + ret=ms_strdup(sal_op_get_contact(call->ping_op)); +#endif + } else if (dest_proxy && dest_proxy->op && sal_op_get_contact(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*/); +#ifdef USE_BELLESIP + ret=linphone_address_clone(sal_op_get_contact(dest_proxy->op)); +#else + ret=ms_strdup(sal_op_get_contact(dest_proxy->op)); +#endif + } else { + ctt=linphone_core_get_primary_contact_parsed(lc); + if (ctt!=NULL){ + /*otherwise use supllied localip*/ + linphone_address_set_domain(ctt,localip); + linphone_address_set_port_int(ctt,linphone_core_get_sip_port(lc)); + ms_message("Contact has been fixed using local ip"/* to %s",ret*/); +#ifdef USE_BELLESIP + ret=ctt; +#else + ret=linphone_address_as_string_uri_only(ctt); +#endif + } + } +#ifndef USE_BELLESIP + if (ctt) linphone_address_destroy(ctt); +#endif + return ret; + + +} + +void linphone_call_set_contact_op(LinphoneCall* call) { +#ifndef USE_BELLESIP + char *contact; +#else + LinphoneAddress *contact; +#endif + contact=get_fixed_contact(call->core,call,call->dest_proxy); + if (contact){ + sal_op_set_contact(call->op, contact); +#ifndef USE_BELLESIP + ms_free(contact); +#else + linphone_address_destroy(contact); +#endif +} +} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 5ea3fb763..36ac9eed2 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2323,69 +2323,7 @@ const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAdd } return linphone_core_get_primary_contact (lc); } -#ifndef USE_BELLESIP -static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){ -#else -static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){ -#endif - LinphoneAddress *ctt=NULL; -#ifdef USE_BELLESIP - LinphoneAddress *ret=NULL; -#else - char* ret; -#endif - const char *localip=call->localip; - /* first use user's supplied ip address if asked*/ - if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){ - ctt=linphone_core_get_primary_contact_parsed(lc); - linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc)); - #ifdef USE_BELLESIP - ret=ctt; - #else - ret=linphone_adress_as_string(ctt); - #endif - } else if (call->op && sal_op_get_contact(call->op)!=NULL){ - /* if already choosed, don't change it */ - return NULL; - } else if (call->ping_op && sal_op_get_contact(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*/); -#ifdef USE_BELLESIP - ret=linphone_address_clone(sal_op_get_contact(call->ping_op));; -#else - ret=ms_strdup(sal_op_get_contact(call->ping_op)); -#endif - } else if (dest_proxy && dest_proxy->op && sal_op_get_contact(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*/); -#ifdef USE_BELLESIP - ret=linphone_address_clone(sal_op_get_contact(dest_proxy->op)); -#else - ret=ms_strdup(sal_op_get_contact(dest_proxy->op)); -#endif - } else { - ctt=linphone_core_get_primary_contact_parsed(lc); - if (ctt!=NULL){ - /*otherwise use supllied localip*/ - linphone_address_set_domain(ctt,localip); - linphone_address_set_port_int(ctt,linphone_core_get_sip_port(lc)); - ms_message("Contact has been fixed using local ip"/* to %s",ret*/); -#ifdef USE_BELLESIP - ret=ctt; -#else - ret=linphone_address_as_string_uri_only(ctt); -#endif - } - } -#ifndef USE_BELLESIP - if (ctt) linphone_address_destroy(ctt); -#endif - return ret; - - -} int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){ bool_t ice_ready = FALSE; @@ -2420,27 +2358,11 @@ int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *c int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){ int err; -#ifndef USE_BELLESIP - char *contact; -#else - LinphoneAddress *contact; -#endif - char *real_url,*barmsg; char *from; - LinphoneProxyConfig *dest_proxy=call->dest_proxy; - /*try to be best-effort in giving real local or routable contact address */ - contact=get_fixed_contact(lc,call,dest_proxy); - if (contact){ - sal_op_set_contact(call->op, contact); -#ifndef USE_BELLESIP - ms_free(contact); -#else - linphone_address_destroy(contact); -#endif + linphone_call_set_contact_op(call); - } linphone_core_stop_dtmf_stream(lc); linphone_call_init_media_streams(call); if (lc->ringstream==NULL) @@ -2838,6 +2760,8 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call"); if (call->state==LinphoneCallIncomingReceived){ + /*try to be best-effort in giving real local or routable contact address for 100Rel case*/ + linphone_call_set_contact_op(call); sal_call_notify_ringing(call->op,propose_early_media || ringback_tone!=NULL); if (propose_early_media || ringback_tone!=NULL){ @@ -3132,11 +3056,6 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call){ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) { LinphoneProxyConfig *cfg=NULL; -#ifndef USE_BELLESIP - char *contact=NULL; -#else - LinphoneAddress *contact=NULL; -#endif SalOp *replaced; SalMediaDescription *new_md; bool_t was_ringing=FALSE; @@ -3190,16 +3109,8 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, ms_message("Overriding default proxy setting for this call:"); ms_message("The used identity will be %s",linphone_proxy_config_get_identity(call->dest_proxy)); } - /*try to be best-effort in giving real local or routable contact address*/ - contact=get_fixed_contact(lc,call,call->dest_proxy); - if (contact) { - sal_op_set_contact(call->op,contact); -#ifdef USE_BELLESIP - linphone_address_destroy(contact); -#else - ms_free(contact); -#endif - } + /*try to be best-effort in giving real local or routable contact address */ + linphone_call_set_contact_op(call); if (params){ const SalMediaDescription *md = sal_call_get_remote_media_description(call->op); _linphone_call_params_copy(&call->params,params); diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 5a327b7c1..0b547c52a 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -51,14 +51,14 @@ typedef struct _LinphoneCore LinphoneCore; struct _LpConfig; -struct _LCSipTransports{ +typedef struct _LCSipTransports{ int udp_port; int tcp_port; int dtls_port; int tls_port; -}; +} LCSipTransports; + -typedef struct _LCSipTransports LCSipTransports; /** * Object that represents a SIP address. diff --git a/coreapi/private.h b/coreapi/private.h index dfa061c51..8645edbff 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -218,7 +218,7 @@ struct _LinphoneCall LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op); void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); - +void linphone_call_set_contact_op(LinphoneCall* call); /* private: */ LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *local, LinphoneAddress * remote); void linphone_call_log_completed(LinphoneCall *call); @@ -230,6 +230,7 @@ void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo void linphone_core_update_proxy_register(LinphoneCore *lc); void linphone_core_refresh_subscribes(LinphoneCore *lc); int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error); +const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineStatus os); void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index aaf851e9f..1094f10f4 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -344,14 +344,49 @@ LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *obj){ } return ret; } - +/*use for compatibility with linphone supporting only 1 transport at a time*/ +const char* guess_transport(const LinphoneProxyConfig *obj) { + LCSipTransports transports; + const char* transport_name; + unsigned char transports_count=0; + linphone_core_get_sip_transports(obj->lc,&transports); + if (transports.udp_port>0) { + transports_count++; + transport_name="udp"; + } + if (transports.tcp_port>0) { + transports_count++; + transport_name="tcp"; + } + if (transports.tls_port>0) { + transports_count++; + transport_name="tls"; + } + if (transports.dtls_port>0) { + transports_count++; + transport_name="dtls"; + } + if (transports_count==1) { + return transport_name; + } else { + /*cannot guess transport*/ + return NULL; + } +} static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ if (obj->reg_sendregister){ + LinphoneAddress* proxy=linphone_address_new(obj->reg_proxy); + char* proxy_string; #ifndef USE_BELLESIP char *contact; #else LinphoneAddress *contact; + if (guess_transport(obj) && !sal_address_get_transport((SalAddress*)proxy)) { + sal_address_set_transport((SalAddress*)proxy,sal_transport_parse(guess_transport(obj))); + } #endif + proxy_string=linphone_address_as_string_uri_only(proxy); + linphone_address_destroy(proxy); if (obj->op) sal_op_release(obj->op); obj->op=sal_op_new(obj->lc->sal); @@ -364,11 +399,12 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ #endif } sal_op_set_user_pointer(obj->op,obj); - if (sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires)==0) { + if (sal_register(obj->op,proxy_string,obj->reg_identity,obj->expires)==0) { linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress"); } else { linphone_proxy_config_set_state(obj,LinphoneRegistrationFailed,"Registration failed"); } + ms_free(proxy_string); } }