}
-static MSList *make_codec_list(const MSList *codecs){
+static MSList *make_codec_list(const MSList *codecs, bool_t only_one_codec){
MSList *l=NULL;
const MSList *it;
for(it=codecs;it!=NULL;it=it->next){
PayloadType *pt=(PayloadType*)it->data;
if (pt->flags & PAYLOAD_TYPE_ENABLED){
l=ms_list_append(l,payload_type_clone(pt));
+ if (only_one_codec) break;
}
}
return l;
}
static SalMediaDescription *create_local_media_description(LinphoneCore *lc,
- const char *localip, const char *username){
+ const char *localip, const char *username, bool_t only_one_codec){
MSList *l;
PayloadType *pt;
SalMediaDescription *md=sal_media_description_new();
md->streams[0].port=linphone_core_get_audio_port(lc);
md->streams[0].proto=SalProtoRtpAvp;
md->streams[0].type=SalAudio;
- l=make_codec_list(lc->codecs_conf.audio_codecs);
+ l=make_codec_list(lc->codecs_conf.audio_codecs,only_one_codec);
pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event"));
l=ms_list_append(l,pt);
md->streams[0].payloads=l;
md->streams[1].port=linphone_core_get_video_port(lc);
md->streams[1].proto=SalProtoRtpAvp;
md->streams[1].type=SalVideo;
- l=make_codec_list(lc->codecs_conf.video_codecs);
+ l=make_codec_list(lc->codecs_conf.video_codecs,only_one_codec);
md->streams[1].payloads=l;
if (lc->dw_video_bw)
md->streams[1].bandwidth=lc->dw_video_bw;
call->core=lc;
linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
call->localdesc=create_local_media_description (lc,call->localip,
- linphone_address_get_username(from));
+ linphone_address_get_username(from),FALSE);
linphone_call_init_common(call,from,to);
discover_mtu(lc,linphone_address_get_domain (to));
return call;
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
LinphoneCall *call=ms_new0(LinphoneCall,1);
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
+ char *to_str;
+ char *from_str;
call->dir=LinphoneCallIncoming;
sal_op_set_user_pointer(op,call);
call->op=op;
call->core=lc;
+
+ if (lc->sip_conf.ping_with_options){
+ /*the following sends an option request back to the caller so that
+ we get a chance to discover our nat'd address before answering.*/
+ call->ping_op=sal_op_new(lc->sal);
+ to_str=linphone_address_as_string(to);
+ from_str=linphone_address_as_string(from);
+ sal_op_set_route(call->ping_op,sal_op_get_network_origin(call->op));
+ sal_ping(call->ping_op,to_str,from_str);
+ ms_free(to_str);
+ ms_free(from_str);
+ }
linphone_address_clean(from);
linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
call->localdesc=create_local_media_description (lc,call->localip,
- linphone_address_get_username(me));
+ linphone_address_get_username(me),lc->sip_conf.only_one_codec);
linphone_call_init_common(call, from, to);
discover_mtu(lc,linphone_address_get_domain(from));
linphone_address_destroy(me);
linphone_core_notify_all_friends(obj->core,obj->core->prev_mode);
linphone_call_log_completed(obj->log,obj);
linphone_core_update_allocated_audio_bandwidth(obj->core);
- if (obj->op!=NULL) sal_op_release(obj->op);
- if (obj->resultdesc!=NULL) sal_media_description_unref(obj->resultdesc);
- if (obj->localdesc!=NULL) sal_media_description_unref(obj->localdesc);
+ if (obj->op!=NULL) {
+ sal_op_release(obj->op);
+ obj->op=NULL;
+ }
+ if (obj->resultdesc!=NULL) {
+ sal_media_description_unref(obj->resultdesc);
+ obj->resultdesc=NULL;
+ }
+ if (obj->localdesc!=NULL) {
+ sal_media_description_unref(obj->localdesc);
+ obj->localdesc=NULL;
+ }
+ if (obj->ping_op) {
+ sal_op_release(obj->ping_op);
+ }
ms_free(obj);
}
calllog->duration=time(NULL)-call->start_time;
switch(call->state){
case LCStateInit:
+ case LCStatePreEstablishing:
calllog->status=LinphoneCallAborted;
break;
case LCStateRinging:
}
}
- /*for test*/
+ /*for tuning or test*/
lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
lc->sip_conf.only_one_codec=lp_config_get_int(lc->config,"sip","only_one_codec",0);
lc->sip_conf.register_only_when_network_is_up=
lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1);
+ lc->sip_conf.ping_with_options=lp_config_get_int(lc->config,"sip","ping_with_options",1);
}
static void rtp_config_read(LinphoneCore *lc)
if (lc->call!=NULL){
LinphoneCall *call=lc->call;
-
+ if (call->state==LCStatePreEstablishing && (curtime-call->start_time>=2)){
+ /*start the call even if the OPTIONS reply did not arrive*/
+ linphone_core_start_invite(lc,call,NULL);
+ }
if (call->dir==LinphoneCallIncoming && call->state==LCStateRinging){
elapsed=curtime-call->start_time;
ms_message("incoming call ringing for %i seconds",elapsed);
LinphoneAddress *ctt;
const char *localip=call->localip;
+ /* first use user's supplied ip address if asked*/
if (linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_NAT_ADDRESS){
ctt=linphone_core_get_primary_contact_parsed(lc);
return ms_strdup_printf("sip:%s@%s",linphone_address_get_username(ctt),
linphone_core_get_nat_address(lc));
}
-
+
+ /* if already choosed, don't change it */
if (call->op && sal_op_get_contact(call->op)!=NULL){
return NULL;
}
-
+ /*if using a proxy, use the contact address as guessed with the REGISTERs*/
if (dest_proxy && dest_proxy->op){
const char *fixed_contact=sal_op_get_contact(dest_proxy->op);
if (fixed_contact) {
return ms_strdup(fixed_contact);
}
}
+ /* if the ping OPTIONS request succeeded use the contact guessed from the
+ received, rport*/
+ if (call->ping_op){
+ const char *guessed=sal_op_get_contact(call->ping_op);
+ if (guessed){
+ ms_message("Contact has been fixed using OPTIONS to %s",guessed);
+ return ms_strdup(guessed);
+ }
+ }
+
ctt=linphone_core_get_primary_contact_parsed(lc);
if (ctt!=NULL){
return NULL;
}
+int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){
+ int err;
+ char *contact;
+ char *real_url,*barmsg;
+ char *from;
+ /*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);
+ ms_free(contact);
+ }
+ call->state=LCStateInit;
+ linphone_core_init_media_streams(lc,lc->call);
+ if (!lc->sip_conf.sdp_200_ack){
+ call->media_pending=TRUE;
+ sal_call_set_local_media_description(call->op,call->localdesc);
+ }
+ real_url=linphone_address_as_string(call->log->to);
+ from=linphone_address_as_string(call->log->from);
+ err=sal_call(call->op,from,real_url);
+
+ if (lc->sip_conf.sdp_200_ack){
+ call->media_pending=TRUE;
+ sal_call_set_local_media_description(call->op,call->localdesc);
+ }
+ barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
+ lc->vtable.display_status(lc,barmsg);
+ ms_free(barmsg);
+
+ if (err<0){
+ ms_warning("Could not initiate call.");
+ lc->vtable.display_status(lc,_("could not call"));
+ linphone_core_stop_media_streams(lc,call);
+ linphone_call_destroy(call);
+ lc->call=NULL;
+ }else gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, real_url);
+ ms_free(real_url);
+ ms_free(from);
+ return err;
+}
+
/**
* Initiates an outgoing call
*
**/
int linphone_core_invite(LinphoneCore *lc, const char *url)
{
- char *barmsg;
int err=0;
char *route=NULL;
const char *from=NULL;
- char *contact=NULL;
LinphoneProxyConfig *proxy=NULL;
LinphoneAddress *parsed_url2=NULL;
LinphoneAddress *real_parsed_url=NULL;
call=linphone_call_new_outgoing(lc,parsed_url2,real_parsed_url);
sal_op_set_route(call->op,route);
-
- /*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);
- ms_free(contact);
- }
-
+
lc->call=call;
-
- linphone_core_init_media_streams(lc,lc->call);
- if (!lc->sip_conf.sdp_200_ack){
- call->media_pending=TRUE;
- 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){
- call->media_pending=TRUE;
- sal_call_set_local_media_description(call->op,call->localdesc);
+ if (dest_proxy!=NULL || lc->sip_conf.ping_with_options==FALSE){
+ err=linphone_core_start_invite(lc,call,dest_proxy);
+ }else{
+ /*defer the start of the call after the OPTIONS ping*/
+ call->state=LCStatePreEstablishing;
+ call->ping_op=sal_op_new(lc->sal);
+ sal_ping(call->ping_op,from,real_url);
+ call->start_time=time(NULL);
}
- barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
- lc->vtable.display_status(lc,barmsg);
- ms_free(barmsg);
- if (err<0){
- ms_warning("Could not initiate call.");
- lc->vtable.display_status(lc,_("could not call"));
- linphone_core_stop_media_streams(lc,call);
- linphone_call_destroy(call);
- lc->call=NULL;
- }else gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, url);
-
if (real_url!=NULL) ms_free(real_url);
if (route!=NULL) ms_free(route);
- return (err<0) ? -1 : 0;
+ return err;
}
int linphone_core_refer(LinphoneCore *lc, const char *url)