mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-18 03:28:07 +00:00
Merge branch 'dev_ice'
This commit is contained in:
commit
4e511fe479
20 changed files with 1094 additions and 302 deletions
|
|
@ -850,6 +850,16 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
|
|||
{
|
||||
linphone_core_set_firewall_policy(lc,LinphonePolicyNoFirewall);
|
||||
}
|
||||
else if (strcmp(args,"ice")==0)
|
||||
{
|
||||
setting = linphone_core_get_stun_server(lc);
|
||||
if ( ! setting )
|
||||
{
|
||||
linphonec_out("No stun server address is defined, use 'stun <address>' first\n");
|
||||
return 1;
|
||||
}
|
||||
linphone_core_set_firewall_policy(lc,LinphonePolicyUseIce);
|
||||
}
|
||||
else if (strcmp(args,"stun")==0)
|
||||
{
|
||||
setting = linphone_core_get_stun_server(lc);
|
||||
|
|
@ -883,6 +893,9 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
|
|||
case LinphonePolicyUseNatAddress:
|
||||
linphonec_out("Using supplied nat address %s.\n", setting ? setting : linphone_core_get_nat_address(lc));
|
||||
break;
|
||||
case LinphonePolicyUseIce:
|
||||
linphonec_out("Using ice with stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ void call_accept(Call *call)
|
|||
osip_message_set_content_type(msg,"application/sdp");
|
||||
osip_message_set_body(msg,call->sdpc->answerstr,strlen(call->sdpc->answerstr));
|
||||
eXosip_call_send_answer(call->tid,200,msg);
|
||||
call->audio_stream=audio_stream_new(call->audio.localport,call->root->ipv6);
|
||||
call->audio_stream=audio_stream_new(call->audio.localport,call->audio.localport+1,call->root->ipv6);
|
||||
audio_stream_start_with_files(call->audio_stream, call->profile,
|
||||
call->audio.remaddr,call->audio.remoteport,call->audio.remoteport+1,
|
||||
call->audio.pt,20,hellofile,record_file);
|
||||
|
|
|
|||
|
|
@ -140,16 +140,10 @@ static bool_t already_a_call_pending(LinphoneCore *lc){
|
|||
|
||||
static void call_received(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
char *barmesg;
|
||||
LinphoneCall *call;
|
||||
const char *from,*to;
|
||||
char *tmp;
|
||||
LinphoneAddress *from_parsed;
|
||||
LinphoneAddress *from_addr, *to_addr;
|
||||
SalMediaDescription *md;
|
||||
bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
|
||||
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",TRUE);
|
||||
const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
|
||||
|
||||
/* first check if we can answer successfully to this invite */
|
||||
if (lc->presence_mode==LinphoneStatusBusy ||
|
||||
|
|
@ -188,72 +182,18 @@ static void call_received(SalOp *h){
|
|||
|
||||
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
|
||||
sal_call_set_local_media_description(h,call->localdesc);
|
||||
md=sal_call_get_final_media_description(h);
|
||||
|
||||
if (md && sal_media_description_empty(md)){
|
||||
sal_call_decline(h,SalReasonMedia,NULL);
|
||||
linphone_call_unref(call);
|
||||
return;
|
||||
}
|
||||
|
||||
/* the call is acceptable so we can now add it to our list */
|
||||
linphone_core_add_call(lc,call);
|
||||
|
||||
from_parsed=linphone_address_new(sal_op_get_from(h));
|
||||
linphone_address_clean(from_parsed);
|
||||
tmp=linphone_address_as_string(from_parsed);
|
||||
linphone_address_destroy(from_parsed);
|
||||
barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
|
||||
(sal_call_autoanswer_asked(h)) ?_(" and asked autoanswer."):_("."));
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,barmesg);
|
||||
|
||||
/* play the ring if this is the only call*/
|
||||
if (ms_list_size(lc->calls)==1){
|
||||
lc->current_call=call;
|
||||
if (lc->ringstream && lc->dmfs_playing_start_time!=0){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
lc->dmfs_playing_start_time=0;
|
||||
}
|
||||
if (lc->sound_conf.ring_sndcard!=NULL){
|
||||
if(lc->ringstream==NULL && lc->sound_conf.local_ring){
|
||||
MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
|
||||
ms_message("Starting local ring...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
|
||||
}
|
||||
else
|
||||
{
|
||||
ms_message("the local ring is already started");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* else play a tone within the context of the current call */
|
||||
call->ringing_beep=TRUE;
|
||||
linphone_core_play_tone(lc);
|
||||
}
|
||||
|
||||
|
||||
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
|
||||
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
|
||||
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL);
|
||||
|
||||
if (propose_early_media || ringback_tone!=NULL){
|
||||
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
|
||||
md=sal_call_get_final_media_description(h);
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
}
|
||||
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
|
||||
linphone_core_accept_call(lc,call);
|
||||
}
|
||||
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
|
||||
/* Defer ringing until the end of the ICE candidates gathering process. */
|
||||
ms_message("Defer ringing to gather ICE candidates");
|
||||
return;
|
||||
}
|
||||
linphone_call_unref(call);
|
||||
|
||||
ms_free(barmesg);
|
||||
ms_free(tmp);
|
||||
linphone_core_notify_incoming_call(lc,call);
|
||||
}
|
||||
|
||||
static void call_ringing(SalOp *h){
|
||||
|
|
@ -320,7 +260,12 @@ static void call_accepted(SalOp *op){
|
|||
ms_warning("No call to accept.");
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/* Handle remote ICE attributes if any. */
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
|
||||
}
|
||||
|
||||
md=sal_call_get_final_media_description(op);
|
||||
|
||||
if (call->state==LinphoneCallOutgoingProgress ||
|
||||
|
|
@ -414,6 +359,11 @@ static void call_ack(SalOp *op){
|
|||
|
||||
static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
|
||||
SalMediaDescription *md;
|
||||
SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
|
||||
if ((rmd!=NULL) && (call->ice_session!=NULL)) {
|
||||
linphone_core_update_ice_from_remote_media_description(call,rmd);
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session);
|
||||
}
|
||||
sal_call_accept(call->op);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && !sal_media_description_empty(md))
|
||||
|
|
@ -810,7 +760,8 @@ static void ping_reply(SalOp *op){
|
|||
ms_message("ping reply !");
|
||||
if (call){
|
||||
if (call->state==LinphoneCallOutgoingInit){
|
||||
linphone_core_start_invite(call->core,call,NULL);
|
||||
call->ping_replied=TRUE;
|
||||
linphone_core_proceed_with_invite_if_ready(call->core,call,NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ static RtpProfile *make_dummy_profile(int samplerate){
|
|||
static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
|
||||
/*create a dummy audiostream in order to extract the local part of it */
|
||||
/* network address and ports have no meaning and are not used here. */
|
||||
AudioStream *st=audio_stream_new(65000,FALSE);
|
||||
AudioStream *st=audio_stream_new(65000,65001,FALSE);
|
||||
MSSndCard *playcard=lc->sound_conf.lsd_card ?
|
||||
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
|
||||
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
|
||||
|
|
@ -114,6 +114,7 @@ static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
|
|||
audio_stream_start_full(st, conf->local_dummy_profile,
|
||||
"127.0.0.1",
|
||||
65000,
|
||||
"127.0.0.1",
|
||||
65001,
|
||||
0,
|
||||
40,
|
||||
|
|
|
|||
|
|
@ -202,7 +202,6 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
const char *username=linphone_address_get_username (addr);
|
||||
SalMediaDescription *md=sal_media_description_new();
|
||||
|
||||
|
||||
md->session_id=session_id;
|
||||
md->session_ver=session_ver;
|
||||
md->nstreams=1;
|
||||
|
|
@ -211,8 +210,10 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
md->bandwidth=linphone_core_get_download_bandwidth(lc);
|
||||
|
||||
/*set audio capabilities */
|
||||
strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr));
|
||||
md->streams[0].port=call->audio_port;
|
||||
strncpy(md->streams[0].rtp_addr,call->localip,sizeof(md->streams[0].rtp_addr));
|
||||
strncpy(md->streams[0].rtcp_addr,call->localip,sizeof(md->streams[0].rtcp_addr));
|
||||
md->streams[0].rtp_port=call->audio_port;
|
||||
md->streams[0].rtcp_port=call->audio_port+1;
|
||||
md->streams[0].proto=(call->params.media_encryption == LinphoneMediaEncryptionSRTP) ?
|
||||
SalProtoRtpSavp : SalProtoRtpAvp;
|
||||
md->streams[0].type=SalAudio;
|
||||
|
|
@ -226,7 +227,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
|
||||
if (call->params.has_video){
|
||||
md->nstreams++;
|
||||
md->streams[1].port=call->video_port;
|
||||
md->streams[1].rtp_port=call->video_port;
|
||||
md->streams[1].rtcp_port=call->video_port+1;
|
||||
md->streams[1].proto=md->streams[0].proto;
|
||||
md->streams[1].type=SalVideo;
|
||||
l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL);
|
||||
|
|
@ -245,6 +247,9 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
md->streams[i].crypto[1].algo = 0;
|
||||
md->streams[i].crypto[2].algo = 0;
|
||||
}
|
||||
if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL) && (ice_session_check_list(call->ice_session, i) == NULL)) {
|
||||
ice_session_add_check_list(call->ice_session, ice_check_list_new());
|
||||
}
|
||||
}
|
||||
|
||||
linphone_address_destroy(addr);
|
||||
|
|
@ -338,10 +343,15 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
|
|||
linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
|
||||
linphone_call_init_common(call,from,to);
|
||||
call->params=*params;
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
|
||||
call->ice_session = ice_session_new();
|
||||
ice_session_set_role(call->ice_session, IR_Controlling);
|
||||
}
|
||||
call->localdesc=create_local_media_description (lc,call);
|
||||
call->camera_active=params->has_video;
|
||||
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
|
||||
linphone_core_run_stun_tests(call->core,call);
|
||||
}
|
||||
discover_mtu(lc,linphone_address_get_domain (to));
|
||||
if (params->referer){
|
||||
sal_call_set_referer(call->op,params->referer->op);
|
||||
|
|
@ -377,8 +387,27 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
call->params.has_video &= !!lc->video_policy.automatically_accept;
|
||||
call->localdesc=create_local_media_description (lc,call);
|
||||
call->camera_active=call->params.has_video;
|
||||
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
|
||||
linphone_core_run_stun_tests(call->core,call);
|
||||
switch (linphone_core_get_firewall_policy(call->core)) {
|
||||
case LinphonePolicyUseIce:
|
||||
call->ice_session = ice_session_new();
|
||||
ice_session_set_role(call->ice_session, IR_Controlled);
|
||||
linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_call_init_media_streams(call);
|
||||
linphone_call_start_media_streams_for_ice_gathering(call);
|
||||
if (linphone_core_gather_ice_candidates(call->core,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LinphonePolicyUseStun:
|
||||
linphone_core_run_stun_tests(call->core,call);
|
||||
/* No break to also destroy ice session in this case. */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
discover_mtu(lc,linphone_address_get_domain(from));
|
||||
return call;
|
||||
}
|
||||
|
|
@ -545,6 +574,9 @@ static void linphone_call_destroy(LinphoneCall *obj)
|
|||
if (obj->auth_token) {
|
||||
ms_free(obj->auth_token);
|
||||
}
|
||||
if (obj->ice_session) {
|
||||
ice_session_destroy(obj->ice_session);
|
||||
}
|
||||
|
||||
ms_free(obj);
|
||||
}
|
||||
|
|
@ -585,7 +617,7 @@ const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *
|
|||
}
|
||||
|
||||
static bool_t is_video_active(const SalStreamDescription *sd){
|
||||
return sd->port!=0 && sd->dir!=SalStreamInactive;
|
||||
return sd->rtp_port!=0 && sd->dir!=SalStreamInactive;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -902,12 +934,12 @@ void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, Lin
|
|||
#endif
|
||||
}
|
||||
|
||||
void linphone_call_init_media_streams(LinphoneCall *call){
|
||||
void linphone_call_init_audio_stream(LinphoneCall *call){
|
||||
LinphoneCore *lc=call->core;
|
||||
SalMediaDescription *md=call->localdesc;
|
||||
AudioStream *audiostream;
|
||||
|
||||
call->audiostream=audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc));
|
||||
call->audiostream=audiostream=audio_stream_new(md->streams[0].rtp_port,md->streams[0].rtcp_port,linphone_core_ipv6_enabled(lc));
|
||||
if (linphone_core_echo_limiter_enabled(lc)){
|
||||
const char *type=lp_config_get_string(lc->config,"sound","el_type","mic");
|
||||
if (strcasecmp(type,"mic")==0)
|
||||
|
|
@ -940,18 +972,28 @@ void linphone_call_init_media_streams(LinphoneCall *call){
|
|||
RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->audio_port+1);
|
||||
rtp_session_set_transports(audiostream->session,artp,artcp);
|
||||
}
|
||||
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
rtp_session_set_pktinfo(audiostream->session, TRUE);
|
||||
rtp_session_set_symmetric_rtp(audiostream->session, FALSE);
|
||||
audiostream->ice_check_list = ice_session_check_list(call->ice_session, 0);
|
||||
ice_check_list_set_rtp_session(audiostream->ice_check_list, audiostream->session);
|
||||
}
|
||||
|
||||
call->audiostream_app_evq = ortp_ev_queue_new();
|
||||
rtp_session_register_event_queue(audiostream->session,call->audiostream_app_evq);
|
||||
}
|
||||
|
||||
void linphone_call_init_video_stream(LinphoneCall *call){
|
||||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=call->core;
|
||||
SalMediaDescription *md=call->localdesc;
|
||||
|
||||
if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0){
|
||||
if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].rtp_port>0){
|
||||
int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
|
||||
call->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc));
|
||||
call->videostream=video_stream_new(md->streams[1].rtp_port,md->streams[1].rtcp_port,linphone_core_ipv6_enabled(lc));
|
||||
video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0));
|
||||
if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->session,video_recv_buf_size);
|
||||
|
||||
|
||||
if( lc->video_conf.displaytype != NULL)
|
||||
video_stream_set_display_filter_name(call->videostream,lc->video_conf.displaytype);
|
||||
video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
|
||||
|
|
@ -960,6 +1002,12 @@ void linphone_call_init_media_streams(LinphoneCall *call){
|
|||
RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1);
|
||||
rtp_session_set_transports(call->videostream->session,vrtp,vrtcp);
|
||||
}
|
||||
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL) && (ice_session_check_list(call->ice_session, 1))){
|
||||
rtp_session_set_pktinfo(call->videostream->session, TRUE);
|
||||
rtp_session_set_symmetric_rtp(call->videostream->session, FALSE);
|
||||
call->videostream->ice_check_list = ice_session_check_list(call->ice_session, 1);
|
||||
ice_check_list_set_rtp_session(call->videostream->ice_check_list, call->videostream->session);
|
||||
}
|
||||
call->videostream_app_evq = ortp_ev_queue_new();
|
||||
rtp_session_register_event_queue(call->videostream->session,call->videostream_app_evq);
|
||||
#ifdef TEST_EXT_RENDERER
|
||||
|
|
@ -971,6 +1019,11 @@ void linphone_call_init_media_streams(LinphoneCall *call){
|
|||
#endif
|
||||
}
|
||||
|
||||
void linphone_call_init_media_streams(LinphoneCall *call){
|
||||
linphone_call_init_audio_stream(call);
|
||||
linphone_call_init_video_stream(call);
|
||||
}
|
||||
|
||||
|
||||
static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
|
||||
|
||||
|
|
@ -1160,7 +1213,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalAudio);
|
||||
|
||||
if (stream && stream->dir!=SalStreamInactive && stream->port!=0){
|
||||
if (stream && stream->dir!=SalStreamInactive && stream->rtp_port!=0){
|
||||
MSSndCard *playcard=lc->sound_conf.lsd_card ?
|
||||
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
|
||||
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
|
||||
|
|
@ -1179,7 +1232,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
}
|
||||
/*Replace soundcard filters by inactive file players or recorders
|
||||
when placed in recvonly or sendonly mode*/
|
||||
if (stream->port==0 || stream->dir==SalStreamRecvOnly){
|
||||
if (stream->rtp_port==0 || stream->dir==SalStreamRecvOnly){
|
||||
captcard=NULL;
|
||||
playfile=NULL;
|
||||
}else if (stream->dir==SalStreamSendOnly){
|
||||
|
|
@ -1213,9 +1266,10 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
audio_stream_start_full(
|
||||
call->audiostream,
|
||||
call->audio_profile,
|
||||
stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr,
|
||||
stream->port,
|
||||
linphone_core_rtcp_enabled(lc) ? (stream->port+1) : 0,
|
||||
stream->rtp_addr[0]!='\0' ? stream->rtp_addr : call->resultdesc->addr,
|
||||
stream->rtp_port,
|
||||
stream->rtcp_addr[0]!='\0' ? stream->rtcp_addr : call->resultdesc->addr,
|
||||
linphone_core_rtcp_enabled(lc) ? (stream->rtcp_port) : 0,
|
||||
used_pt,
|
||||
jitt_comp,
|
||||
playfile,
|
||||
|
|
@ -1283,8 +1337,9 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
lc->previewstream=NULL;
|
||||
}
|
||||
|
||||
if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->port!=0) {
|
||||
const char *addr=vstream->addr[0]!='\0' ? vstream->addr : call->resultdesc->addr;
|
||||
if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->rtp_port!=0) {
|
||||
const char *rtp_addr=vstream->rtp_addr[0]!='\0' ? vstream->rtp_addr : call->resultdesc->addr;
|
||||
const char *rtcp_addr=vstream->rtcp_addr[0]!='\0' ? vstream->rtcp_addr : call->resultdesc->addr;
|
||||
call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt);
|
||||
if (used_pt!=-1){
|
||||
call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
|
||||
|
|
@ -1330,8 +1385,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
|
||||
video_stream_set_device_rotation(call->videostream, lc->device_rotation);
|
||||
video_stream_start(call->videostream,
|
||||
call->video_profile, addr, vstream->port,
|
||||
linphone_core_rtcp_enabled(lc) ? (vstream->port+1) : 0,
|
||||
call->video_profile, rtp_addr, vstream->rtp_port,
|
||||
rtcp_addr, linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port) : 0,
|
||||
used_pt, lc->rtp_conf.audio_jitt_comp, cam);
|
||||
video_stream_set_rtcp_information(call->videostream, cname,LINPHONE_RTCP_SDES_TOOL);
|
||||
}
|
||||
|
|
@ -1409,6 +1464,9 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
/*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again
|
||||
* further in the call, for example during pause,resume, conferencing reINVITEs*/
|
||||
linphone_call_fix_call_parameters(call);
|
||||
if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed)) {
|
||||
ice_session_start_connectivity_checks(call->ice_session);
|
||||
}
|
||||
|
||||
goto end;
|
||||
end:
|
||||
|
|
@ -1416,6 +1474,24 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
linphone_address_destroy(me);
|
||||
}
|
||||
|
||||
void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call){
|
||||
audio_stream_prepare_sound(call->audiostream, NULL, NULL);
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream) {
|
||||
video_stream_prepare_video(call->videostream);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void linphone_call_delete_ice_session(LinphoneCall *call){
|
||||
if (call->ice_session != NULL) {
|
||||
ice_session_destroy(call->ice_session);
|
||||
call->ice_session = NULL;
|
||||
if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL;
|
||||
if (call->videostream != NULL) call->videostream->ice_check_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
|
||||
audio_stream_get_local_rtp_stats (st,&log->local_stats);
|
||||
log->quality=audio_stream_get_average_quality_rating(st);
|
||||
|
|
@ -1423,9 +1499,11 @@ static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
|
|||
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call){
|
||||
if (call->audiostream!=NULL) {
|
||||
call->audiostream->ice_check_list = NULL;
|
||||
rtp_session_unregister_event_queue(call->audiostream->session,call->audiostream_app_evq);
|
||||
ortp_ev_queue_flush(call->audiostream_app_evq);
|
||||
ortp_ev_queue_destroy(call->audiostream_app_evq);
|
||||
call->audiostream_app_evq=NULL;
|
||||
|
||||
if (call->audiostream->ec){
|
||||
const char *state_str=NULL;
|
||||
|
|
@ -1446,9 +1524,11 @@ void linphone_call_stop_media_streams(LinphoneCall *call){
|
|||
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream!=NULL){
|
||||
call->videostream->ice_check_list = NULL;
|
||||
rtp_session_unregister_event_queue(call->videostream->session,call->videostream_app_evq);
|
||||
ortp_ev_queue_flush(call->videostream_app_evq);
|
||||
ortp_ev_queue_destroy(call->videostream_app_evq);
|
||||
call->videostream_app_evq=NULL;
|
||||
video_stream_stop(call->videostream);
|
||||
call->videostream=NULL;
|
||||
}
|
||||
|
|
@ -1624,6 +1704,57 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
|
|||
linphone_core_terminate_call(lc,call);
|
||||
}
|
||||
|
||||
static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
|
||||
if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
|
||||
switch (ice_session_state(call->ice_session)) {
|
||||
case IS_Completed:
|
||||
if (ice_session_role(call->ice_session) == IR_Controlling) {
|
||||
ice_session_select_candidates(call->ice_session);
|
||||
linphone_core_update_call(call->core, call, &call->current_params);
|
||||
}
|
||||
break;
|
||||
case IS_Failed:
|
||||
linphone_call_delete_ice_session(call);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
|
||||
if (evd->info.ice_processing_successful==TRUE) {
|
||||
ice_session_compute_candidates_foundations(call->ice_session);
|
||||
ice_session_eliminate_redundant_candidates(call->ice_session);
|
||||
ice_session_choose_default_candidates(call->ice_session);
|
||||
} else {
|
||||
linphone_call_delete_ice_session(call);
|
||||
}
|
||||
switch (call->state) {
|
||||
case LinphoneCallStreamsRunning:
|
||||
linphone_core_start_update_call(call->core, call);
|
||||
break;
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
linphone_core_start_accept_call_update(call->core, call);
|
||||
break;
|
||||
case LinphoneCallOutgoingInit:
|
||||
linphone_call_stop_media_streams(call);
|
||||
linphone_core_proceed_with_invite_if_ready(call->core, call, NULL);
|
||||
break;
|
||||
default:
|
||||
linphone_call_stop_media_streams(call);
|
||||
linphone_core_notify_incoming_call(call->core, call);
|
||||
break;
|
||||
}
|
||||
} else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
|
||||
linphone_core_start_accept_call_update(call->core, call);
|
||||
} else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
|
||||
ice_session_restart(call->ice_session);
|
||||
ice_session_set_role(call->ice_session, IR_Controlling);
|
||||
linphone_core_update_call(call->core, call, &call->current_params);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){
|
||||
LinphoneCore* lc = call->core;
|
||||
int disconnect_timeout = linphone_core_get_nortp_timeout(call->core);
|
||||
|
|
@ -1647,72 +1778,82 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
|
|||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream!=NULL) {
|
||||
OrtpEvent *ev;
|
||||
|
||||
/* Ensure there is no dangling ICE check list. */
|
||||
if (call->ice_session == NULL) call->videostream->ice_check_list = NULL;
|
||||
|
||||
// Beware that the application queue should not depend on treatments fron the
|
||||
// mediastreamer queue.
|
||||
video_stream_iterate(call->videostream);
|
||||
|
||||
if (call->videostream_app_evq){
|
||||
OrtpEvent *ev;
|
||||
while (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq))){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
|
||||
linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->session);
|
||||
if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
||||
memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->session), sizeof(jitter_stats_t));
|
||||
if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
|
||||
}
|
||||
ortp_event_destroy(ev);
|
||||
while (call->videostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq)))){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
|
||||
linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->session);
|
||||
if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
||||
memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->session), sizeof(jitter_stats_t));
|
||||
if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
|
||||
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|
||||
|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
|
||||
handle_ice_events(call, ev);
|
||||
}
|
||||
ortp_event_destroy(ev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (call->audiostream!=NULL) {
|
||||
OrtpEvent *ev;
|
||||
|
||||
/* Ensure there is no dangling ICE check list. */
|
||||
if (call->ice_session == NULL) call->audiostream->ice_check_list = NULL;
|
||||
|
||||
// Beware that the application queue should not depend on treatments fron the
|
||||
// mediastreamer queue.
|
||||
audio_stream_iterate(call->audiostream);
|
||||
|
||||
if (call->audiostream_app_evq){
|
||||
OrtpEvent *ev;
|
||||
while (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq))){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
|
||||
linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
|
||||
} else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
|
||||
linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->session);
|
||||
if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
||||
memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->session), sizeof(jitter_stats_t));
|
||||
if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
|
||||
}
|
||||
ortp_event_destroy(ev);
|
||||
while (call->audiostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq)))){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
|
||||
linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
|
||||
} else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
|
||||
linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->session);
|
||||
if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
||||
memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->session), sizeof(jitter_stats_t));
|
||||
if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
|
||||
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|
||||
|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
|
||||
handle_ice_events(call, ev);
|
||||
}
|
||||
ortp_event_destroy(ev);
|
||||
}
|
||||
}
|
||||
if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 )
|
||||
|
|
|
|||
|
|
@ -1855,6 +1855,11 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
linphone_call_background_tasks(call,one_second_elapsed);
|
||||
if (call->state==LinphoneCallOutgoingInit && (curtime-call->start_time>=2)){
|
||||
/*start the call even if the OPTIONS reply did not arrive*/
|
||||
if (call->ice_session != NULL) {
|
||||
/* ICE candidates gathering has not finished yet, proceed with the call without ICE anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
}
|
||||
linphone_core_start_invite(lc,call,NULL);
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
|
|
@ -2103,6 +2108,27 @@ static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphonePr
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){
|
||||
bool_t ice_ready = FALSE;
|
||||
bool_t ping_ready = FALSE;
|
||||
|
||||
if (call->ice_session != NULL) {
|
||||
if (ice_session_candidates_gathered(call->ice_session)) ice_ready = TRUE;
|
||||
} else {
|
||||
ice_ready = TRUE;
|
||||
}
|
||||
if (call->ping_op != NULL) {
|
||||
if (call->ping_replied == TRUE) ping_ready = TRUE;
|
||||
} else {
|
||||
ping_ready = TRUE;
|
||||
}
|
||||
|
||||
if ((ice_ready == TRUE) && (ping_ready == TRUE)) {
|
||||
return linphone_core_start_invite(lc, call, dest_proxy);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){
|
||||
int err;
|
||||
char *contact;
|
||||
|
|
@ -2121,6 +2147,8 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphonePro
|
|||
audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
|
||||
if (!lc->sip_conf.sdp_200_ack){
|
||||
call->media_pending=TRUE;
|
||||
if (call->ice_session != NULL)
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
real_url=linphone_address_as_string(call->log->to);
|
||||
|
|
@ -2243,6 +2271,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
char *real_url=NULL;
|
||||
LinphoneProxyConfig *dest_proxy=NULL;
|
||||
LinphoneCall *call;
|
||||
bool_t use_ice = FALSE;
|
||||
|
||||
linphone_core_preempt_sound_resources(lc);
|
||||
|
||||
|
|
@ -2284,14 +2313,29 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
/* this call becomes now the current one*/
|
||||
lc->current_call=call;
|
||||
linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call");
|
||||
if (dest_proxy!=NULL || lc->sip_conf.ping_with_options==FALSE){
|
||||
linphone_core_start_invite(lc,call,dest_proxy);
|
||||
}else{
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
|
||||
/* Defer the start of the call after the ICE gathering process. */
|
||||
linphone_call_init_media_streams(call);
|
||||
linphone_call_start_media_streams_for_ice_gathering(call);
|
||||
call->start_time=time(NULL);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
} else {
|
||||
use_ice = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){
|
||||
/*defer the start of the call after the OPTIONS ping*/
|
||||
call->ping_replied=FALSE;
|
||||
call->ping_op=sal_op_new(lc->sal);
|
||||
sal_ping(call->ping_op,from,real_url);
|
||||
sal_op_set_user_pointer(call->ping_op,call);
|
||||
call->start_time=time(NULL);
|
||||
}else{
|
||||
if (use_ice==FALSE) linphone_core_start_invite(lc,call,dest_proxy);
|
||||
}
|
||||
|
||||
if (real_url!=NULL) ms_free(real_url);
|
||||
|
|
@ -2355,6 +2399,96 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
char *barmesg;
|
||||
char *tmp;
|
||||
LinphoneAddress *from_parsed;
|
||||
SalMediaDescription *md;
|
||||
bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
|
||||
const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
|
||||
|
||||
if (call->ice_session != NULL)
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && sal_media_description_empty(md)){
|
||||
sal_call_decline(call->op,SalReasonMedia,NULL);
|
||||
linphone_call_unref(call);
|
||||
return;
|
||||
}
|
||||
|
||||
from_parsed=linphone_address_new(sal_op_get_from(call->op));
|
||||
linphone_address_clean(from_parsed);
|
||||
tmp=linphone_address_as_string(from_parsed);
|
||||
linphone_address_destroy(from_parsed);
|
||||
barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
|
||||
(sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_("."));
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,barmesg);
|
||||
|
||||
/* play the ring if this is the only call*/
|
||||
if (ms_list_size(lc->calls)==1){
|
||||
lc->current_call=call;
|
||||
if (lc->ringstream && lc->dmfs_playing_start_time!=0){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
lc->dmfs_playing_start_time=0;
|
||||
}
|
||||
if (lc->sound_conf.ring_sndcard!=NULL){
|
||||
if(lc->ringstream==NULL && lc->sound_conf.local_ring){
|
||||
MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
|
||||
ms_message("Starting local ring...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
|
||||
}
|
||||
else
|
||||
{
|
||||
ms_message("the local ring is already started");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* else play a tone within the context of the current call */
|
||||
call->ringing_beep=TRUE;
|
||||
linphone_core_play_tone(lc);
|
||||
}
|
||||
|
||||
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
|
||||
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
sal_call_notify_ringing(call->op,propose_early_media || ringback_tone!=NULL);
|
||||
|
||||
if (propose_early_media || ringback_tone!=NULL){
|
||||
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
}
|
||||
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
|
||||
linphone_core_accept_call(lc,call);
|
||||
}
|
||||
}
|
||||
linphone_call_unref(call);
|
||||
|
||||
ms_free(barmesg);
|
||||
ms_free(tmp);
|
||||
}
|
||||
|
||||
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
const char *subject;
|
||||
call->camera_active=call->params.has_video;
|
||||
update_local_media_description(lc,call);
|
||||
if (call->ice_session != NULL)
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
|
||||
if (call->params.in_conference){
|
||||
subject="Conference";
|
||||
}else{
|
||||
subject="Media change";
|
||||
}
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Modifying call parameters..."));
|
||||
sal_call_set_local_media_description (call->op,call->localdesc);
|
||||
return sal_call_update(call->op,subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup call_control
|
||||
* Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore.
|
||||
|
|
@ -2372,20 +2506,27 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
|
|||
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
int err=0;
|
||||
if (params!=NULL){
|
||||
const char *subject;
|
||||
call->params=*params;
|
||||
call->camera_active=call->params.has_video;
|
||||
update_local_media_description(lc,call);
|
||||
|
||||
if (params->in_conference){
|
||||
subject="Conference";
|
||||
}else{
|
||||
subject="Media change";
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((call->ice_session != NULL) && (call->videostream != NULL) && !params->has_video) {
|
||||
ice_session_remove_check_list(call->ice_session, call->videostream->ice_check_list);
|
||||
call->videostream->ice_check_list = NULL;
|
||||
}
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Modifying call parameters..."));
|
||||
sal_call_set_local_media_description (call->op,call->localdesc);
|
||||
err=sal_call_update(call->op,subject);
|
||||
if ((call->ice_session != NULL) && ((ice_session_state(call->ice_session) != IS_Completed) || (call->params.has_video != params->has_video))) {
|
||||
/* Defer call update until the ICE candidates gathering process has finished. */
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
call->params = *params;
|
||||
update_local_media_description(lc, call);
|
||||
if (call->params.has_video) {
|
||||
linphone_call_init_video_stream(call);
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
} else return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
err = linphone_core_start_update_call(lc, call);
|
||||
}else{
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream!=NULL){
|
||||
|
|
@ -2423,6 +2564,24 @@ int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
|
|||
return -1;
|
||||
}
|
||||
|
||||
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call){
|
||||
SalMediaDescription *md;
|
||||
if (call->ice_session != NULL) {
|
||||
if (ice_session_nb_losing_pairs(call->ice_session) > 0) {
|
||||
/* Defer the sending of the answer until there are no losing pairs left. */
|
||||
return 0;
|
||||
}
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
}
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
sal_call_accept(call->op);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && !sal_media_description_empty(md))
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup call_control
|
||||
* Accept call modifications initiated by other end.
|
||||
|
|
@ -2443,14 +2602,14 @@ int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
|
|||
* @return 0 if sucessful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state).
|
||||
**/
|
||||
int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
SalMediaDescription *md;
|
||||
bool_t old_has_video = call->params.has_video;
|
||||
if (call->state!=LinphoneCallUpdatedByRemote){
|
||||
ms_error("linphone_core_accept_update(): invalid state %s to call this function.",
|
||||
linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
if (params==NULL){
|
||||
call->params.has_video=lc->video_policy.automatically_accept;
|
||||
call->params.has_video=lc->video_policy.automatically_accept || call->current_params.has_video;
|
||||
}else
|
||||
call->params=*params;
|
||||
|
||||
|
|
@ -2460,12 +2619,22 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const
|
|||
}
|
||||
call->camera_active=call->params.has_video;
|
||||
update_local_media_description(lc,call);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
sal_call_accept(call->op);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && !sal_media_description_empty(md))
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((call->ice_session != NULL) &&!ice_session_candidates_gathered(call->ice_session)) {
|
||||
if ((call->params.has_video) && (call->params.has_video != old_has_video)) {
|
||||
linphone_call_init_video_stream(call);
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
} else return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
linphone_core_start_accept_call_update(lc, call);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2728,6 +2897,8 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
|
|||
return -1;
|
||||
}
|
||||
update_local_media_description(lc,call);
|
||||
if (call->ice_session != NULL)
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){
|
||||
sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
|
||||
subject="Call on hold";
|
||||
|
|
@ -2805,6 +2976,8 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call)
|
|||
if (call->audiostream) audio_stream_play(call->audiostream, NULL);
|
||||
|
||||
update_local_media_description(lc,the_call);
|
||||
if (call->ice_session != NULL)
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
|
||||
if (call->params.in_conference && !call->current_params.in_conference) subject="Conference";
|
||||
|
|
|
|||
|
|
@ -742,7 +742,8 @@ typedef struct _LCCallbackObj
|
|||
typedef enum _LinphoneFirewallPolicy{
|
||||
LinphonePolicyNoFirewall,
|
||||
LinphonePolicyUseNatAddress,
|
||||
LinphonePolicyUseStun
|
||||
LinphonePolicyUseStun,
|
||||
LinphonePolicyUseIce
|
||||
} LinphoneFirewallPolicy;
|
||||
|
||||
typedef enum _LinphoneWaitingState{
|
||||
|
|
|
|||
243
coreapi/misc.c
243
coreapi/misc.c
|
|
@ -563,6 +563,249 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
|
|||
}
|
||||
}
|
||||
|
||||
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
|
||||
{
|
||||
char local_addr[64];
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t ss_len;
|
||||
IceCheckList *audio_check_list;
|
||||
IceCheckList *video_check_list;
|
||||
const char *server = linphone_core_get_stun_server(lc);
|
||||
|
||||
if ((server == NULL) || (call->ice_session == NULL)) return -1;
|
||||
audio_check_list = ice_session_check_list(call->ice_session, 0);
|
||||
video_check_list = ice_session_check_list(call->ice_session, 1);
|
||||
if (audio_check_list == NULL) return -1;
|
||||
|
||||
if (lc->sip_conf.ipv6_enabled){
|
||||
ms_warning("stun support is not implemented for ipv6");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parse_hostname_to_addr(server, &ss, &ss_len) < 0) {
|
||||
ms_error("Fail to parser stun server address: %s", server);
|
||||
return -1;
|
||||
}
|
||||
if (lc->vtable.display_status != NULL)
|
||||
lc->vtable.display_status(lc, _("ICE local candidates gathering in progress..."));
|
||||
|
||||
/* Gather local host candidates. */
|
||||
if (linphone_core_get_local_ip_for(AF_INET, NULL, local_addr) < 0) {
|
||||
ms_error("Fail to get local ip");
|
||||
return -1;
|
||||
}
|
||||
ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port, 1, NULL);
|
||||
ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port + 1, 2, NULL);
|
||||
if (call->params.has_video && (video_check_list != NULL)) {
|
||||
ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port, 1, NULL);
|
||||
ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port + 1, 2, NULL);
|
||||
}
|
||||
|
||||
/* Gather local srflx candidates. */
|
||||
ice_session_gather_candidates(call->ice_session, ss, ss_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session)
|
||||
{
|
||||
const char *rtp_addr, *rtcp_addr;
|
||||
IceSessionState session_state = ice_session_state(session);
|
||||
int nb_candidates;
|
||||
int i, j;
|
||||
|
||||
if (session_state == IS_Completed) {
|
||||
desc->ice_completed = TRUE;
|
||||
ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, 0), &rtp_addr, NULL, NULL, NULL);
|
||||
strncpy(desc->addr, rtp_addr, sizeof(desc->addr));
|
||||
}
|
||||
else {
|
||||
desc->ice_completed = FALSE;
|
||||
}
|
||||
strncpy(desc->ice_pwd, ice_session_local_pwd(session), sizeof(desc->ice_pwd));
|
||||
strncpy(desc->ice_ufrag, ice_session_local_ufrag(session), sizeof(desc->ice_ufrag));
|
||||
for (i = 0; i < desc->nstreams; i++) {
|
||||
SalStreamDescription *stream = &desc->streams[i];
|
||||
IceCheckList *cl = ice_session_check_list(session, i);
|
||||
nb_candidates = 0;
|
||||
if (cl == NULL) continue;
|
||||
if (cl->state == ICL_Completed) {
|
||||
stream->ice_completed = TRUE;
|
||||
ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, i), &rtp_addr, &stream->rtp_port, &rtcp_addr, &stream->rtcp_port);
|
||||
strncpy(stream->rtp_addr, rtp_addr, sizeof(stream->rtp_addr));
|
||||
strncpy(stream->rtcp_addr, rtcp_addr, sizeof(stream->rtcp_addr));
|
||||
} else {
|
||||
stream->ice_completed = FALSE;
|
||||
}
|
||||
if ((strlen(ice_check_list_local_pwd(cl)) != strlen(desc->ice_pwd)) || (strcmp(ice_check_list_local_pwd(cl), desc->ice_pwd)))
|
||||
strncpy(stream->ice_pwd, ice_check_list_local_pwd(cl), sizeof(stream->ice_pwd));
|
||||
else
|
||||
memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd));
|
||||
if ((strlen(ice_check_list_local_ufrag(cl)) != strlen(desc->ice_ufrag)) || (strcmp(ice_check_list_local_ufrag(cl), desc->ice_ufrag)))
|
||||
strncpy(stream->ice_ufrag, ice_check_list_local_ufrag(cl), sizeof(stream->ice_ufrag));
|
||||
else
|
||||
memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd));
|
||||
stream->ice_mismatch = ice_check_list_is_mismatch(cl);
|
||||
if ((cl->state == ICL_Running) || (cl->state == ICL_Completed)) {
|
||||
memset(stream->ice_candidates, 0, sizeof(stream->ice_candidates));
|
||||
for (j = 0; j < MIN(ms_list_size(cl->local_candidates), SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES); j++) {
|
||||
SalIceCandidate *sal_candidate = &stream->ice_candidates[nb_candidates];
|
||||
IceCandidate *ice_candidate = ms_list_nth_data(cl->local_candidates, j);
|
||||
const char *default_addr = NULL;
|
||||
int default_port = 0;
|
||||
if (ice_candidate->componentID == 1) {
|
||||
default_addr = stream->rtp_addr;
|
||||
default_port = stream->rtp_port;
|
||||
} else if (ice_candidate->componentID == 2) {
|
||||
default_addr = stream->rtcp_addr;
|
||||
default_port = stream->rtcp_port;
|
||||
} else continue;
|
||||
if (default_addr[0] == '\0') default_addr = desc->addr;
|
||||
/* Only include the candidates matching the default destination for each component of the stream if the state is Completed as specified in RFC5245 section 9.1.2.2. */
|
||||
if ((cl->state == ICL_Completed)
|
||||
&& !((ice_candidate->taddr.port == default_port) && (strlen(ice_candidate->taddr.ip) == strlen(default_addr)) && (strcmp(ice_candidate->taddr.ip, default_addr) == 0)))
|
||||
continue;
|
||||
strncpy(sal_candidate->foundation, ice_candidate->foundation, sizeof(sal_candidate->foundation));
|
||||
sal_candidate->componentID = ice_candidate->componentID;
|
||||
sal_candidate->priority = ice_candidate->priority;
|
||||
strncpy(sal_candidate->type, ice_candidate_type(ice_candidate), sizeof(sal_candidate->type));
|
||||
strncpy(sal_candidate->addr, ice_candidate->taddr.ip, sizeof(sal_candidate->addr));
|
||||
sal_candidate->port = ice_candidate->taddr.port;
|
||||
if ((ice_candidate->base != NULL) && (ice_candidate->base != ice_candidate)) {
|
||||
strncpy(sal_candidate->raddr, ice_candidate->base->taddr.ip, sizeof(sal_candidate->raddr));
|
||||
sal_candidate->rport = ice_candidate->base->taddr.port;
|
||||
}
|
||||
nb_candidates++;
|
||||
}
|
||||
}
|
||||
if ((cl->state == ICL_Completed) && (ice_session_role(session) == IR_Controlling)) {
|
||||
int rtp_port, rtcp_port;
|
||||
memset(stream->ice_remote_candidates, 0, sizeof(stream->ice_remote_candidates));
|
||||
ice_check_list_selected_valid_remote_candidate(cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
|
||||
strncpy(stream->ice_remote_candidates[0].addr, rtp_addr, sizeof(stream->ice_remote_candidates[0].addr));
|
||||
stream->ice_remote_candidates[0].port = rtp_port;
|
||||
strncpy(stream->ice_remote_candidates[1].addr, rtcp_addr, sizeof(stream->ice_remote_candidates[1].addr));
|
||||
stream->ice_remote_candidates[1].port = rtcp_port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_default_addr_and_port(uint16_t componentID, const SalMediaDescription *md, const SalStreamDescription *stream, const char **addr, int *port)
|
||||
{
|
||||
if (componentID == 1) {
|
||||
*addr = stream->rtp_addr;
|
||||
*port = stream->rtp_port;
|
||||
} else if (componentID == 2) {
|
||||
*addr = stream->rtcp_addr;
|
||||
*port = stream->rtcp_port;
|
||||
} else return;
|
||||
if ((*addr)[0] == '\0') *addr = md->addr;
|
||||
}
|
||||
|
||||
void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md)
|
||||
{
|
||||
bool_t ice_restarted = FALSE;
|
||||
|
||||
if ((md->ice_pwd[0] != '\0') && (md->ice_ufrag[0] != '\0')) {
|
||||
int i, j;
|
||||
|
||||
/* Check for ICE restart and set remote credentials. */
|
||||
if ((strcmp(md->addr, "0.0.0.0") == 0) || (strcmp(md->addr, "::0") == 0)) {
|
||||
ice_session_restart(call->ice_session);
|
||||
ice_restarted = TRUE;
|
||||
} else {
|
||||
for (i = 0; i < md->nstreams; i++) {
|
||||
const SalStreamDescription *stream = &md->streams[i];
|
||||
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
|
||||
if (cl && (strcmp(stream->rtp_addr, "0.0.0.0") == 0)) {
|
||||
ice_session_restart(call->ice_session);
|
||||
ice_restarted = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ice_session_remote_ufrag(call->ice_session) == NULL) && (ice_session_remote_pwd(call->ice_session) == NULL)) {
|
||||
ice_session_set_remote_credentials(call->ice_session, md->ice_ufrag, md->ice_pwd);
|
||||
} else if (ice_session_remote_credentials_changed(call->ice_session, md->ice_ufrag, md->ice_pwd)) {
|
||||
if (ice_restarted == FALSE) {
|
||||
ice_session_restart(call->ice_session);
|
||||
ice_restarted = TRUE;
|
||||
}
|
||||
ice_session_set_remote_credentials(call->ice_session, md->ice_ufrag, md->ice_pwd);
|
||||
}
|
||||
for (i = 0; i < md->nstreams; i++) {
|
||||
const SalStreamDescription *stream = &md->streams[i];
|
||||
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
|
||||
if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) {
|
||||
if (ice_check_list_remote_credentials_changed(cl, stream->ice_ufrag, stream->ice_pwd)) {
|
||||
if (ice_restarted == FALSE) {
|
||||
ice_session_restart(call->ice_session);
|
||||
ice_restarted = TRUE;
|
||||
}
|
||||
ice_session_set_remote_credentials(call->ice_session, md->ice_ufrag, md->ice_pwd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create ICE check lists if needed and parse ICE attributes. */
|
||||
for (i = 0; i < md->nstreams; i++) {
|
||||
const SalStreamDescription *stream = &md->streams[i];
|
||||
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
|
||||
if (cl == NULL) {
|
||||
cl = ice_check_list_new();
|
||||
ice_session_add_check_list(call->ice_session, cl);
|
||||
switch (stream->type) {
|
||||
case SalAudio:
|
||||
if (call->audiostream != NULL) call->audiostream->ice_check_list = cl;
|
||||
break;
|
||||
case SalVideo:
|
||||
if (call->videostream != NULL) call->videostream->ice_check_list = cl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stream->ice_mismatch == TRUE) {
|
||||
ice_check_list_set_state(cl, ICL_Failed);
|
||||
} else {
|
||||
if ((stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0'))
|
||||
ice_check_list_set_remote_credentials(cl, stream->ice_ufrag, stream->ice_pwd);
|
||||
for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES; j++) {
|
||||
const SalIceCandidate *candidate = &stream->ice_candidates[j];
|
||||
bool_t default_candidate = FALSE;
|
||||
const char *addr = NULL;
|
||||
int port = 0;
|
||||
if (candidate->addr[0] == '\0') break;
|
||||
if ((candidate->componentID == 0) || (candidate->componentID > 2)) continue;
|
||||
get_default_addr_and_port(candidate->componentID, md, stream, &addr, &port);
|
||||
if (addr && (candidate->port == port) && (strlen(candidate->addr) == strlen(addr)) && (strcmp(candidate->addr, addr) == 0))
|
||||
default_candidate = TRUE;
|
||||
ice_add_remote_candidate(cl, candidate->type, candidate->addr, candidate->port, candidate->componentID,
|
||||
candidate->priority, candidate->foundation, default_candidate);
|
||||
}
|
||||
if (ice_restarted == FALSE) {
|
||||
for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) {
|
||||
const SalIceRemoteCandidate *candidate = &stream->ice_remote_candidates[j];
|
||||
const char *addr = NULL;
|
||||
int port = 0;
|
||||
int componentID = j + 1;
|
||||
if (candidate->addr[0] == '\0') break;
|
||||
get_default_addr_and_port(componentID, md, stream, &addr, &port);
|
||||
ice_add_losing_pair(ice_session_check_list(call->ice_session, i), j + 1, candidate->addr, candidate->port, addr, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = ice_session_nb_check_lists(call->ice_session); i > md->nstreams; i--) {
|
||||
ice_session_remove_check_list(call->ice_session, ice_session_check_list(call->ice_session, i - 1));
|
||||
}
|
||||
ice_session_check_mismatch(call->ice_session);
|
||||
}
|
||||
if ((ice_session_state(call->ice_session) == IS_Failed) || (ice_session_nb_check_lists(call->ice_session) == 0)) {
|
||||
linphone_call_delete_ice_session(call);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneCall * is_a_linphone_call(void *user_pointer){
|
||||
LinphoneCall *call=(LinphoneCall*)user_pointer;
|
||||
if (call==NULL) return NULL;
|
||||
|
|
|
|||
|
|
@ -205,25 +205,27 @@ static SalStreamDir compute_dir_incoming(SalStreamDir local, SalStreamDir offere
|
|||
static void initiate_outgoing(const SalStreamDescription *local_offer,
|
||||
const SalStreamDescription *remote_answer,
|
||||
SalStreamDescription *result){
|
||||
if (remote_answer->port!=0)
|
||||
if (remote_answer->rtp_port!=0)
|
||||
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
|
||||
result->proto=remote_answer->proto;
|
||||
result->type=local_offer->type;
|
||||
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
|
||||
|
||||
if (result->payloads && !only_telephone_event(result->payloads)){
|
||||
strcpy(result->addr,remote_answer->addr);
|
||||
result->port=remote_answer->port;
|
||||
strcpy(result->rtp_addr,remote_answer->rtp_addr);
|
||||
strcpy(result->rtcp_addr,remote_answer->rtcp_addr);
|
||||
result->rtp_port=remote_answer->rtp_port;
|
||||
result->rtcp_port=remote_answer->rtcp_port;
|
||||
result->bandwidth=remote_answer->bandwidth;
|
||||
result->ptime=remote_answer->ptime;
|
||||
}else{
|
||||
result->port=0;
|
||||
result->rtp_port=0;
|
||||
}
|
||||
if (result->proto == SalProtoRtpSavp) {
|
||||
/* verify crypto algo */
|
||||
memset(result->crypto, 0, sizeof(result->crypto));
|
||||
if (!match_crypto_algo(local_offer->crypto, remote_answer->crypto, &result->crypto[0], &result->crypto_local_tag, FALSE))
|
||||
result->port = 0;
|
||||
result->rtp_port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -235,22 +237,30 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
|
|||
result->proto=remote_offer->proto;
|
||||
result->type=local_cap->type;
|
||||
result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir);
|
||||
if (result->payloads && !only_telephone_event(result->payloads) && (remote_offer->port!=0 || remote_offer->port==SalStreamSendOnly)){
|
||||
strcpy(result->addr,local_cap->addr);
|
||||
if (result->payloads && !only_telephone_event(result->payloads) && (remote_offer->rtp_port!=0 || remote_offer->rtp_port==SalStreamSendOnly)){
|
||||
strcpy(result->rtp_addr,local_cap->rtp_addr);
|
||||
strcpy(result->rtcp_addr,local_cap->rtcp_addr);
|
||||
memcpy(result->candidates,local_cap->candidates,sizeof(result->candidates));
|
||||
result->port=local_cap->port;
|
||||
result->rtp_port=local_cap->rtp_port;
|
||||
result->rtcp_port=local_cap->rtcp_port;
|
||||
result->bandwidth=local_cap->bandwidth;
|
||||
result->ptime=local_cap->ptime;
|
||||
result->ptime=local_cap->ptime;
|
||||
}else{
|
||||
result->port=0;
|
||||
result->rtp_port=0;
|
||||
}
|
||||
if (result->proto == SalProtoRtpSavp) {
|
||||
/* select crypto algo */
|
||||
memset(result->crypto, 0, sizeof(result->crypto));
|
||||
if (!match_crypto_algo(local_cap->crypto, remote_offer->crypto, &result->crypto[0], &result->crypto_local_tag, TRUE))
|
||||
result->port = 0;
|
||||
result->rtp_port = 0;
|
||||
|
||||
}
|
||||
strcpy(result->ice_pwd, local_cap->ice_pwd);
|
||||
strcpy(result->ice_ufrag, local_cap->ice_ufrag);
|
||||
result->ice_mismatch = local_cap->ice_mismatch;
|
||||
result->ice_completed = local_cap->ice_completed;
|
||||
memcpy(result->ice_candidates, local_cap->ice_candidates, sizeof(result->ice_candidates));
|
||||
memcpy(result->ice_remote_candidates, local_cap->ice_remote_candidates, sizeof(result->ice_remote_candidates));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -305,7 +315,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
|
|||
else {
|
||||
/* create an inactive stream for the answer, as there where no matching stream a local capability */
|
||||
result->streams[i].dir=SalStreamInactive;
|
||||
result->streams[i].port=0;
|
||||
result->streams[i].rtp_port=0;
|
||||
result->streams[i].type=rs->type;
|
||||
result->streams[i].proto=rs->proto;
|
||||
if (rs->type==SalOther){
|
||||
|
|
@ -319,5 +329,9 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
|
|||
result->bandwidth=local_capabilities->bandwidth;
|
||||
result->session_ver=local_capabilities->session_ver;
|
||||
result->session_id=local_capabilities->session_id;
|
||||
strcpy(result->ice_pwd, local_capabilities->ice_pwd);
|
||||
strcpy(result->ice_ufrag, local_capabilities->ice_ufrag);
|
||||
result->ice_lite = local_capabilities->ice_lite;
|
||||
result->ice_completed = local_capabilities->ice_completed;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ extern "C" {
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "mediastreamer2/ice.h"
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
#include "mediastreamer2/msconference.h"
|
||||
|
||||
|
|
@ -133,8 +134,10 @@ struct _LinphoneCall
|
|||
bool_t auth_token_verified;
|
||||
bool_t defer_update;
|
||||
bool_t was_automatically_paused;
|
||||
bool_t ping_replied;
|
||||
CallCallbackObj nextVideoFrameDecoded;
|
||||
LinphoneCallStats stats[2];
|
||||
IceSession *ice_session;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -218,6 +221,9 @@ MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *fri, LinphoneFri
|
|||
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc);
|
||||
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt);
|
||||
void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call);
|
||||
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
|
||||
void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
|
||||
|
||||
void linphone_core_send_initial_subscribes(LinphoneCore *lc);
|
||||
void linphone_core_write_friends_config(LinphoneCore* lc);
|
||||
|
|
@ -241,9 +247,13 @@ void linphone_core_play_tone(LinphoneCore *lc);
|
|||
|
||||
void linphone_call_init_stats(LinphoneCallStats *stats, int type);
|
||||
|
||||
void linphone_call_init_audio_stream(LinphoneCall *call);
|
||||
void linphone_call_init_video_stream(LinphoneCall *call);
|
||||
void linphone_call_init_media_streams(LinphoneCall *call);
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone);
|
||||
void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call);
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call);
|
||||
void linphone_call_delete_ice_session(LinphoneCall *call);
|
||||
|
||||
const char * linphone_core_get_identity(LinphoneCore *lc);
|
||||
const char * linphone_core_get_route(LinphoneCore *lc);
|
||||
|
|
@ -251,8 +261,12 @@ void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose);
|
|||
void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses);
|
||||
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, LinphoneProxyConfig *dest_proxy);
|
||||
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call);
|
||||
void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
extern SalCallbacks linphone_sal_callbacks;
|
||||
void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg, LinphoneReason error);
|
||||
bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ bool_t sal_media_description_empty(const SalMediaDescription *md){
|
|||
int i;
|
||||
for(i=0;i<md->nstreams;++i){
|
||||
const SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->port!=0) return FALSE;
|
||||
if (ss->rtp_port!=0) return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
|
|||
const SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->dir==stream_dir) return TRUE;
|
||||
/*compatibility check for phones that only used the null address and no attributes */
|
||||
if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->addr)))
|
||||
if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr)))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
|
@ -180,8 +180,10 @@ static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
|
|||
bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){
|
||||
if (sd1->proto!=sd2->proto) return FALSE;
|
||||
if (sd1->type!=sd2->type) return FALSE;
|
||||
if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE;
|
||||
if (sd1->port!=sd2->port) return FALSE;
|
||||
if (strcmp(sd1->rtp_addr,sd2->rtp_addr)!=0) return FALSE;
|
||||
if (sd1->rtp_port!=sd2->rtp_port) return FALSE;
|
||||
if (strcmp(sd1->rtcp_addr,sd2->rtcp_addr)!=0) return FALSE;
|
||||
if (sd1->rtcp_port!=sd2->rtcp_port) return FALSE;
|
||||
if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE;
|
||||
if (sd1->bandwidth!=sd2->bandwidth) return FALSE;
|
||||
if (sd1->ptime!=sd2->ptime) return FALSE;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,33 @@ typedef struct SalEndpointCandidate{
|
|||
|
||||
#define SAL_ENDPOINT_CANDIDATE_MAX 2
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN 64
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_FOUNDATION_LEN 32
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_TYPE_LEN 6
|
||||
|
||||
typedef struct SalIceCandidate {
|
||||
char addr[SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN];
|
||||
char raddr[SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN];
|
||||
char foundation[SAL_MEDIA_DESCRIPTION_MAX_ICE_FOUNDATION_LEN];
|
||||
char type[SAL_MEDIA_DESCRIPTION_MAX_ICE_TYPE_LEN];
|
||||
unsigned int componentID;
|
||||
unsigned int priority;
|
||||
int port;
|
||||
int rport;
|
||||
} SalIceCandidate;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES 10
|
||||
|
||||
typedef struct SalIceRemoteCandidate {
|
||||
char addr[SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN];
|
||||
int port;
|
||||
} SalIceRemoteCandidate;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES 2
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN 256
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN 256
|
||||
|
||||
typedef struct SalSrtpCryptoAlgo {
|
||||
unsigned int tag;
|
||||
enum ortp_srtp_crypto_suite_t algo;
|
||||
|
|
@ -125,8 +152,10 @@ typedef struct SalStreamDescription{
|
|||
SalMediaProto proto;
|
||||
SalStreamType type;
|
||||
char typeother[32];
|
||||
char addr[64];
|
||||
int port;
|
||||
char rtp_addr[64];
|
||||
char rtcp_addr[64];
|
||||
int rtp_port;
|
||||
int rtcp_port;
|
||||
MSList *payloads; //<list of PayloadType
|
||||
int bandwidth;
|
||||
int ptime;
|
||||
|
|
@ -135,6 +164,12 @@ typedef struct SalStreamDescription{
|
|||
SalSrtpCryptoAlgo crypto[SAL_CRYPTO_ALGO_MAX];
|
||||
unsigned int crypto_local_tag;
|
||||
int max_rate;
|
||||
SalIceCandidate ice_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES];
|
||||
SalIceRemoteCandidate ice_remote_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES];
|
||||
char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN];
|
||||
char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN];
|
||||
bool_t ice_mismatch;
|
||||
bool_t ice_completed;
|
||||
} SalStreamDescription;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
|
||||
|
|
@ -148,8 +183,14 @@ typedef struct SalMediaDescription{
|
|||
unsigned int session_ver;
|
||||
unsigned int session_id;
|
||||
SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
|
||||
char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN];
|
||||
char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN];
|
||||
bool_t ice_lite;
|
||||
bool_t ice_completed;
|
||||
} SalMediaDescription;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
|
||||
|
||||
SalMediaDescription *sal_media_description_new();
|
||||
void sal_media_description_ref(SalMediaDescription *md);
|
||||
void sal_media_description_unref(SalMediaDescription *md);
|
||||
|
|
|
|||
|
|
@ -533,11 +533,13 @@ static void sdp_process(SalOp *h){
|
|||
h->result->bandwidth=h->base.remote_media->bandwidth;
|
||||
|
||||
for(i=0;i<h->result->nstreams;++i){
|
||||
if (h->result->streams[i].port>0){
|
||||
strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr);
|
||||
if (h->result->streams[i].rtp_port>0){
|
||||
strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
|
||||
strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
|
||||
h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
|
||||
h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
|
||||
h->result->streams[i].port=h->base.remote_media->streams[i].port;
|
||||
h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
|
||||
h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
|
||||
|
||||
if (h->result->streams[i].proto == SalProtoRtpSavp) {
|
||||
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
|
||||
|
|
@ -2404,6 +2406,10 @@ int sal_call_update(SalOp *h, const char *subject){
|
|||
eXosip_unlock();
|
||||
osip_message_set_subject(reinvite,subject);
|
||||
osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
|
||||
if (h->base.contact){
|
||||
_osip_list_set_empty(&reinvite->contacts,(void (*)(void*))osip_contact_free);
|
||||
osip_message_set_contact(reinvite,h->base.contact);
|
||||
}
|
||||
if (h->base.root->session_expires!=0){
|
||||
osip_message_set_header(reinvite, "Session-expires", "200");
|
||||
osip_message_set_supported(reinvite, "timer");
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
|
|||
int inet6;
|
||||
char sessid[16];
|
||||
char sessver[16];
|
||||
const char *rtp_addr = desc->addr;
|
||||
|
||||
snprintf(sessid,16,"%i",desc->session_id);
|
||||
snprintf(sessver,16,"%i",desc->session_ver);
|
||||
|
|
@ -143,11 +144,12 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
|
|||
osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr));
|
||||
sdp_message_s_name_set (local, osip_strdup ("Talk"));
|
||||
if(!sal_media_description_has_dir (desc,SalStreamSendOnly))
|
||||
/* Do not set the c= line to 0.0.0.0 if there is an ICE session. */
|
||||
if((desc->ice_ufrag[0] != '\0') || !sal_media_description_has_dir (desc,SalStreamSendOnly))
|
||||
{
|
||||
sdp_message_c_connection_add (local, -1,
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr), NULL, NULL);
|
||||
osip_strdup (rtp_addr), NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -158,6 +160,10 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
|
|||
sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
|
||||
if (desc->bandwidth>0) sdp_message_b_bandwidth_add (local, -1, osip_strdup ("AS"),
|
||||
int_2char(desc->bandwidth));
|
||||
if (desc->ice_completed == TRUE) sdp_message_a_attribute_add(local, -1, osip_strdup("nortpproxy"), osip_strdup("yes"));
|
||||
if (desc->ice_pwd[0] != '\0') sdp_message_a_attribute_add(local, -1, osip_strdup("ice-pwd"), osip_strdup(desc->ice_pwd));
|
||||
if (desc->ice_ufrag[0] != '\0') sdp_message_a_attribute_add(local, -1, osip_strdup("ice-ufrag"), osip_strdup(desc->ice_ufrag));
|
||||
|
||||
return local;
|
||||
}
|
||||
|
||||
|
|
@ -197,14 +203,66 @@ static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt, boo
|
|||
}
|
||||
}
|
||||
|
||||
static void add_ice_candidates(sdp_message_t *msg, int lineno, const SalStreamDescription *desc)
|
||||
{
|
||||
char buffer[1024];
|
||||
const SalIceCandidate *candidate;
|
||||
int nb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES; i++) {
|
||||
candidate = &desc->ice_candidates[i];
|
||||
if ((candidate->addr[0] == '\0') || (candidate->port == 0)) break;
|
||||
nb = snprintf(buffer, sizeof(buffer), "%s %u UDP %u %s %d typ %s",
|
||||
candidate->foundation, candidate->componentID, candidate->priority, candidate->addr, candidate->port, candidate->type);
|
||||
if (nb < 0) {
|
||||
ms_error("Cannot add ICE candidate attribute!");
|
||||
return;
|
||||
}
|
||||
if (candidate->raddr[0] != '\0') {
|
||||
nb = snprintf(buffer + nb, sizeof(buffer) - nb, " raddr %s rport %d", candidate->raddr, candidate->rport);
|
||||
if (nb < 0) {
|
||||
ms_error("Cannot add ICE candidate attribute!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("candidate"), osip_strdup(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
static void add_ice_remote_candidates(sdp_message_t *msg, int lineno, const SalStreamDescription *desc)
|
||||
{
|
||||
char buffer[1024];
|
||||
char *ptr = buffer;
|
||||
const SalIceRemoteCandidate *candidate;
|
||||
int offset = 0;
|
||||
int i;
|
||||
|
||||
buffer[0] = '\0';
|
||||
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; i++) {
|
||||
candidate = &desc->ice_remote_candidates[i];
|
||||
if ((candidate->addr[0] != '\0') && (candidate->port != 0)) {
|
||||
offset = snprintf(ptr, buffer + sizeof(buffer) - ptr, "%s%d %s %d", (i > 0) ? " " : "", i + 1, candidate->addr, candidate->port);
|
||||
if (offset < 0) {
|
||||
ms_error("Cannot add ICE remote-candidates attribute!");
|
||||
return;
|
||||
}
|
||||
ptr += offset;
|
||||
}
|
||||
}
|
||||
if (buffer[0] != '\0') sdp_message_a_attribute_add(msg, lineno, osip_strdup("remote-candidates"), osip_strdup(buffer));
|
||||
}
|
||||
|
||||
static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc){
|
||||
const char *mt=NULL;
|
||||
const MSList *elem;
|
||||
const char *addr;
|
||||
const char *rtp_addr;
|
||||
const char *rtcp_addr;
|
||||
const char *dir="sendrecv";
|
||||
int port;
|
||||
int rtp_port;
|
||||
int rtcp_port;
|
||||
bool_t strip_well_known_rtpmaps;
|
||||
bool_t different_rtp_and_rtcp_addr;
|
||||
|
||||
switch (desc->type) {
|
||||
case SalAudio:
|
||||
|
|
@ -217,29 +275,20 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
mt=desc->typeother;
|
||||
break;
|
||||
}
|
||||
rtp_addr=desc->rtp_addr;
|
||||
rtcp_addr=desc->rtcp_addr;
|
||||
rtp_port=desc->rtp_port;
|
||||
rtcp_port=desc->rtcp_port;
|
||||
if (desc->candidates[0].addr[0]!='\0'){
|
||||
addr=desc->candidates[0].addr;
|
||||
port=desc->candidates[0].port;
|
||||
}else{
|
||||
addr=desc->addr;
|
||||
port=desc->port;
|
||||
rtp_addr=desc->candidates[0].addr;
|
||||
rtp_port=desc->candidates[0].port;
|
||||
}
|
||||
/*only add a c= line within the stream description if address are differents*/
|
||||
if (strcmp(addr,sdp_message_c_addr_get(msg, -1, 0))!=0){
|
||||
bool_t inet6;
|
||||
if (strchr(addr,':')!=NULL){
|
||||
inet6=TRUE;
|
||||
}else inet6=FALSE;
|
||||
sdp_message_c_connection_add (msg, lineno,
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (addr), NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (desc->proto == SalProtoRtpSavp) {
|
||||
int i;
|
||||
|
||||
sdp_message_m_media_add (msg, osip_strdup (mt),
|
||||
int_2char (port), NULL,
|
||||
int_2char (rtp_port), NULL,
|
||||
osip_strdup ("RTP/SAVP"));
|
||||
|
||||
/* add crypto lines */
|
||||
|
|
@ -271,10 +320,22 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
|
||||
} else {
|
||||
sdp_message_m_media_add (msg, osip_strdup (mt),
|
||||
int_2char (port), NULL,
|
||||
int_2char (rtp_port), NULL,
|
||||
osip_strdup ("RTP/AVP"));
|
||||
|
||||
}
|
||||
|
||||
/*only add a c= line within the stream description if address are differents*/
|
||||
if (rtp_addr[0]!='\0' && strcmp(rtp_addr,sdp_message_c_addr_get(msg, -1, 0))!=0){
|
||||
bool_t inet6;
|
||||
if (strchr(rtp_addr,':')!=NULL){
|
||||
inet6=TRUE;
|
||||
}else inet6=FALSE;
|
||||
sdp_message_c_connection_add (msg, lineno,
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (rtp_addr), NULL, NULL);
|
||||
}
|
||||
|
||||
if (desc->bandwidth>0) sdp_message_b_bandwidth_add (msg, lineno, osip_strdup ("AS"),
|
||||
int_2char(desc->bandwidth));
|
||||
if (desc->ptime>0) sdp_message_a_attribute_add(msg,lineno,osip_strdup("ptime"),
|
||||
|
|
@ -305,8 +366,32 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
break;
|
||||
}
|
||||
if (dir) sdp_message_a_attribute_add (msg, lineno, osip_strdup (dir),NULL);
|
||||
if (rtp_port != 0) {
|
||||
different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0);
|
||||
if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) {
|
||||
if (different_rtp_and_rtcp_addr == TRUE) {
|
||||
char buffer[1024];
|
||||
snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr);
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("rtcp"), osip_strdup(buffer));
|
||||
} else {
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("rtcp"), int_2char(rtcp_port));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (desc->ice_completed == TRUE) {
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("nortpproxy"), osip_strdup("yes"));
|
||||
}
|
||||
if (desc->ice_mismatch == TRUE) {
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-mismatch"), NULL);
|
||||
} else {
|
||||
if (desc->ice_pwd[0] != '\0') sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-pwd"), osip_strdup(desc->ice_pwd));
|
||||
if (desc->ice_ufrag[0] != '\0') sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-ufrag"), osip_strdup(desc->ice_ufrag));
|
||||
add_ice_candidates(msg, lineno, desc);
|
||||
add_ice_remote_candidates(msg, lineno, desc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
|
||||
int i;
|
||||
sdp_message_t *msg=create_generic_sdp(desc);
|
||||
|
|
@ -349,25 +434,39 @@ static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){
|
|||
|
||||
int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
||||
int i,j;
|
||||
const char *mtype,*proto,*port,*addr,*number;
|
||||
const char *mtype,*proto,*rtp_port,*rtp_addr,*number;
|
||||
sdp_bandwidth_t *sbw=NULL;
|
||||
|
||||
addr=sdp_message_c_addr_get (msg, -1, 0);
|
||||
if (addr)
|
||||
strncpy(desc->addr,addr,sizeof(desc->addr));
|
||||
sdp_attribute_t *attr;
|
||||
int nb_ice_candidates;
|
||||
|
||||
rtp_addr=sdp_message_c_addr_get (msg, -1, 0);
|
||||
if (rtp_addr)
|
||||
strncpy(desc->addr,rtp_addr,sizeof(desc->addr));
|
||||
for(j=0;(sbw=sdp_message_bandwidth_get(msg,-1,j))!=NULL;++j){
|
||||
if (strcasecmp(sbw->b_bwtype,"AS")==0) desc->bandwidth=atoi(sbw->b_bandwidth);
|
||||
}
|
||||
|
||||
|
||||
/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
|
||||
for (i = 0; (i < SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES) && ((attr = sdp_message_attribute_get(msg, -1, i)) != NULL); i++) {
|
||||
if ((keywordcmp("ice-ufrag", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
strncpy(desc->ice_ufrag, attr->a_att_value, sizeof(desc->ice_ufrag));
|
||||
} else if ((keywordcmp("ice-pwd", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
strncpy(desc->ice_pwd, attr->a_att_value, sizeof(desc->ice_pwd));
|
||||
} else if (keywordcmp("ice-lite", attr->a_att_field) == 0) {
|
||||
desc->ice_lite = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* for each m= line */
|
||||
for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++)
|
||||
{
|
||||
SalStreamDescription *stream=&desc->streams[i];
|
||||
nb_ice_candidates = 0;
|
||||
|
||||
memset(stream,0,sizeof(*stream));
|
||||
mtype = sdp_message_m_media_get(msg, i);
|
||||
proto = sdp_message_m_proto_get (msg, i);
|
||||
port = sdp_message_m_port_get(msg, i);
|
||||
rtp_port = sdp_message_m_port_get(msg, i);
|
||||
stream->proto=SalProtoUnknown;
|
||||
if (proto){
|
||||
if (strcasecmp(proto,"RTP/AVP")==0)
|
||||
|
|
@ -376,11 +475,11 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
|||
stream->proto=SalProtoRtpSavp;
|
||||
}
|
||||
}
|
||||
addr = sdp_message_c_addr_get (msg, i, 0);
|
||||
if (addr != NULL)
|
||||
strncpy(stream->addr,addr,sizeof(stream->addr));
|
||||
if (port)
|
||||
stream->port=atoi(port);
|
||||
rtp_addr = sdp_message_c_addr_get (msg, i, 0);
|
||||
if (rtp_addr != NULL)
|
||||
strncpy(stream->rtp_addr,rtp_addr,sizeof(stream->rtp_addr));
|
||||
if (rtp_port)
|
||||
stream->rtp_port=atoi(rtp_port);
|
||||
|
||||
stream->ptime=_sdp_message_get_a_ptime(msg,i);
|
||||
if (strcasecmp("audio", mtype) == 0){
|
||||
|
|
@ -394,7 +493,7 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
|||
for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){
|
||||
if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
|
||||
}
|
||||
stream->dir=_sdp_message_get_mline_dir(msg,i);
|
||||
stream->dir=_sdp_message_get_mline_dir(msg,i);
|
||||
/* for each payload type */
|
||||
for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
|
||||
const char *rtpmap,*fmtp;
|
||||
|
|
@ -412,11 +511,27 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
|||
pt->send_fmtp ? pt->send_fmtp : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get media specific RTCP attribute */
|
||||
stream->rtcp_port = stream->rtp_port + 1;
|
||||
snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), stream->rtp_addr);
|
||||
for (j = 0; ((attr = sdp_message_attribute_get(msg, i, j)) != NULL); j++) {
|
||||
if ((keywordcmp("rtcp", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
char tmp[256];
|
||||
int nb = sscanf(attr->a_att_value, "%d IN IP4 %s", &stream->rtcp_port, tmp);
|
||||
if (nb == 1) {
|
||||
/* SDP rtcp attribute only contains the port */
|
||||
} else if (nb == 2) {
|
||||
strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr));
|
||||
} else {
|
||||
ms_warning("sdp has a strange a= line (%s) nb=%i", attr->a_att_value, nb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* read crypto lines if any */
|
||||
if (stream->proto == SalProtoRtpSavp) {
|
||||
int k, valid_count = 0;
|
||||
sdp_attribute_t *attr;
|
||||
|
||||
memset(&stream->crypto, 0, sizeof(stream->crypto));
|
||||
for (k=0;valid_count < SAL_CRYPTO_ALGO_MAX && (attr=sdp_message_attribute_get(msg,i,k))!=NULL;k++){
|
||||
|
|
@ -455,6 +570,38 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
|||
}
|
||||
ms_message("Found: %d valid crypto lines", valid_count);
|
||||
}
|
||||
|
||||
/* Get ICE candidate attributes if any */
|
||||
for (j = 0; (attr = sdp_message_attribute_get(msg, i, j)) != NULL; j++) {
|
||||
if ((keywordcmp("candidate", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates];
|
||||
int nb = sscanf(attr->a_att_value, "%s %u UDP %u %s %d typ %s raddr %s rport %d",
|
||||
candidate->foundation, &candidate->componentID, &candidate->priority, candidate->addr, &candidate->port,
|
||||
candidate->type, candidate->raddr, &candidate->rport);
|
||||
if ((nb == 6) || (nb == 8)) nb_ice_candidates++;
|
||||
else memset(candidate, 0, sizeof(*candidate));
|
||||
} else if ((keywordcmp("remote-candidates", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
SalIceRemoteCandidate candidate;
|
||||
unsigned int componentID;
|
||||
int offset;
|
||||
char *ptr = attr->a_att_value;
|
||||
while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
|
||||
if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
|
||||
SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
|
||||
strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr));
|
||||
remote_candidate->port = candidate.port;
|
||||
}
|
||||
ptr += offset;
|
||||
if (ptr[offset] == ' ') ptr += 1;
|
||||
}
|
||||
} else if ((keywordcmp("ice-ufrag", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
strncpy(stream->ice_ufrag, attr->a_att_value, sizeof(stream->ice_ufrag));
|
||||
} else if ((keywordcmp("ice-pwd", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
strncpy(stream->ice_pwd, attr->a_att_value, sizeof(stream->ice_pwd));
|
||||
} else if (keywordcmp("ice-mismatch", attr->a_att_field) == 0) {
|
||||
stream->ice_mismatch = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
desc->nstreams=i;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -557,6 +557,7 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m
|
|||
guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
|
||||
gboolean in_conf=linphone_call_params_local_conference_mode(linphone_call_get_current_params(call));
|
||||
|
||||
if ((callview==NULL) || (status==NULL)) return;
|
||||
if (error_msg==NULL)
|
||||
gtk_label_set_markup(GTK_LABEL(status),_("<b>Call ended.</b>"));
|
||||
else{
|
||||
|
|
|
|||
|
|
@ -354,8 +354,10 @@ static void entry_unmapped(GtkWidget *entry){
|
|||
}
|
||||
|
||||
GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
|
||||
GtkBuilder *builder=(GtkBuilder*)g_object_get_data(G_OBJECT(window),"builder");
|
||||
GtkBuilder *builder;
|
||||
GObject *w;
|
||||
if (window==NULL) return NULL;
|
||||
builder=(GtkBuilder*)g_object_get_data(G_OBJECT(window),"builder");
|
||||
if (builder==NULL){
|
||||
g_error("Fail to retrieve builder from window !");
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.18"/>
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="lower">500</property>
|
||||
<property name="upper">3001</property>
|
||||
|
|
@ -206,10 +207,10 @@
|
|||
<child>
|
||||
<object class="GtkCheckButton" id="mtu_set">
|
||||
<property name="label" translatable="yes">Set Maximum Transmission Unit:</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_mtu_set" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -225,6 +226,8 @@
|
|||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<property name="adjustment">adjustment1</property>
|
||||
<signal name="value-changed" handler="linphone_gtk_mtu_changed" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -244,10 +247,10 @@
|
|||
<child>
|
||||
<object class="GtkCheckButton" id="dtmf_sipinfo">
|
||||
<property name="label" translatable="yes">Send DTMFs as SIP info</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_use_sip_info_dtmf_toggled" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -260,11 +263,11 @@
|
|||
<child>
|
||||
<object class="GtkCheckButton" id="ipv6_enabled">
|
||||
<property name="label" translatable="yes">Use IPv6 instead of IPv4</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_ipv6_toggled" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -335,6 +338,8 @@
|
|||
<property name="invisible_char_set">True</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<property name="adjustment">adjustment7</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
@ -379,9 +384,9 @@
|
|||
<child>
|
||||
<object class="GtkButton" id="tunnel_edit_button">
|
||||
<property name="label" translatable="yes">edit</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_edit_tunnel" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
@ -422,6 +427,10 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<property name="adjustment">adjustment_audio_port</property>
|
||||
<property name="numeric">True</property>
|
||||
<signal name="value-changed" handler="linphone_gtk_audio_port_changed" swapped="no"/>
|
||||
|
|
@ -438,6 +447,10 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<property name="adjustment">adjustment_video_port</property>
|
||||
<property name="numeric">True</property>
|
||||
<signal name="value-changed" handler="linphone_gtk_video_port_changed" swapped="no"/>
|
||||
|
|
@ -483,10 +496,10 @@
|
|||
<child>
|
||||
<object class="GtkRadioButton" id="no_nat">
|
||||
<property name="label" translatable="yes">Direct connection to the Internet</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_no_firewall_toggled" swapped="no"/>
|
||||
|
|
@ -504,10 +517,10 @@
|
|||
<child>
|
||||
<object class="GtkRadioButton" id="use_nat_address">
|
||||
<property name="label" translatable="yes">Behind NAT / Firewall (specify gateway IP below)</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">no_nat</property>
|
||||
|
|
@ -545,6 +558,8 @@
|
|||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<signal name="changed" handler="linphone_gtk_nat_address_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
@ -568,20 +583,51 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox5">
|
||||
<object class="GtkRadioButton" id="use_stun">
|
||||
<property name="label" translatable="yes">Behind NAT / Firewall (use STUN to resolve)</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">no_nat</property>
|
||||
<signal name="toggled" handler="linphone_gtk_use_stun_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="use_ice">
|
||||
<property name="label" translatable="yes">Behind NAT / Firewall (use ICE)</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">no_nat</property>
|
||||
<signal name="toggled" handler="linphone_gtk_use_ice_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox24">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="use_stun">
|
||||
<property name="label" translatable="yes">Behind NAT / Firewall (use STUN to resolve)</property>
|
||||
<object class="GtkLabel" id="label42">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">no_nat</property>
|
||||
<signal name="toggled" handler="linphone_gtk_use_stun_toggled" swapped="no"/>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">Stun server:</property>
|
||||
<property name="justify">right</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
|
|
@ -590,39 +636,17 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox24">
|
||||
<object class="GtkEntry" id="stun_server">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label42">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">Stun server:</property>
|
||||
<property name="justify">right</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="stun_server">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<signal name="changed" handler="linphone_gtk_stun_server_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="invisible_char_set">True</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<signal name="changed" handler="linphone_gtk_stun_server_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
|
|
@ -632,9 +656,9 @@
|
|||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
|
@ -719,6 +743,9 @@
|
|||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="n_rows">6</property>
|
||||
<property name="n_columns">2</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="ring_sound_box">
|
||||
<property name="visible">True</property>
|
||||
|
|
@ -740,11 +767,11 @@
|
|||
<child>
|
||||
<object class="GtkButton" id="play_ring">
|
||||
<property name="label">gtk-media-play</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="linphone_gtk_play_ring_file" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -783,6 +810,8 @@
|
|||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<signal name="editing-done" handler="linphone_gtk_alsa_special_device_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
@ -915,10 +944,10 @@
|
|||
<child>
|
||||
<object class="GtkCheckButton" id="echo_cancelation">
|
||||
<property name="label" translatable="yes">Enable echo cancellation</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_echo_cancelation_toggled" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -929,9 +958,6 @@
|
|||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
@ -1134,6 +1160,8 @@
|
|||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<signal name="changed" handler="linphone_gtk_update_my_contact" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
@ -1172,6 +1200,8 @@
|
|||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<signal name="changed" handler="linphone_gtk_update_my_contact" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
@ -1189,6 +1219,8 @@
|
|||
<property name="editable">False</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
|
|
@ -1245,9 +1277,6 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
@ -1264,10 +1293,10 @@
|
|||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="wizard">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_display_wizard" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox5">
|
||||
|
|
@ -1311,11 +1340,11 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="add_proxy">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_add_proxy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox14">
|
||||
|
|
@ -1359,11 +1388,11 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="edit_proxy">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_edit_proxy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox16">
|
||||
|
|
@ -1407,11 +1436,11 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_proxy">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_remove_proxy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox7">
|
||||
|
|
@ -1455,9 +1484,9 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="create_phonics">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_create_fonics_account" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox1">
|
||||
|
|
@ -1544,11 +1573,11 @@ virtual network !</property>
|
|||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="erase_passwords">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_clear_passwords" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox18">
|
||||
|
|
@ -1713,9 +1742,6 @@ virtual network !</property>
|
|||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="has_tooltip">True</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection2"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
@ -1733,11 +1759,11 @@ virtual network !</property>
|
|||
<child>
|
||||
<object class="GtkButton" id="button4">
|
||||
<property name="label">gtk-go-up</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="linphone_gtk_codec_up" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -1750,11 +1776,11 @@ virtual network !</property>
|
|||
<child>
|
||||
<object class="GtkButton" id="up_codec">
|
||||
<property name="label">gtk-go-down</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="linphone_gtk_codec_down" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -1766,11 +1792,11 @@ virtual network !</property>
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="enable_codec">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_codec_enable" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox8">
|
||||
|
|
@ -1814,11 +1840,11 @@ virtual network !</property>
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="disable_codec">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_codec_disable" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox9">
|
||||
|
|
@ -1922,6 +1948,8 @@ virtual network !</property>
|
|||
<property name="tooltip_text" translatable="yes">0 stands for "unlimited"</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<property name="adjustment">adjustment5</property>
|
||||
<signal name="value-changed" handler="linphone_gtk_upload_bw_changed" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -1942,6 +1970,8 @@ virtual network !</property>
|
|||
<property name="tooltip_text" translatable="yes">0 stands for "unlimited"</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<property name="adjustment">adjustment6</property>
|
||||
<signal name="value-changed" handler="linphone_gtk_download_bw_changed" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -1977,10 +2007,10 @@ virtual network !</property>
|
|||
<child>
|
||||
<object class="GtkCheckButton" id="adaptive_rate_control">
|
||||
<property name="label" translatable="yes">Enable adaptive rate control</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_adaptive_rate_control_toggled" swapped="no"/>
|
||||
|
|
@ -2132,10 +2162,10 @@ virtual network !</property>
|
|||
<child>
|
||||
<object class="GtkCheckButton" id="ui_level">
|
||||
<property name="label" translatable="yes">Show advanced settings</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_ui_level_toggled" swapped="no"/>
|
||||
</object>
|
||||
|
|
@ -2212,11 +2242,11 @@ virtual network !</property>
|
|||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button5">
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_parameters_closed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox3">
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@ void linphone_gtk_use_stun_toggled(GtkWidget *w){
|
|||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseStun);
|
||||
}
|
||||
|
||||
void linphone_gtk_use_ice_toggled(GtkWidget *w){
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseIce);
|
||||
}
|
||||
|
||||
void linphone_gtk_mtu_changed(GtkWidget *w){
|
||||
if (GTK_WIDGET_SENSITIVE(w))
|
||||
linphone_core_set_mtu(linphone_gtk_get_core(),gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)));
|
||||
|
|
@ -956,6 +961,9 @@ void linphone_gtk_show_parameters(void){
|
|||
case LinphonePolicyUseStun:
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_stun")),TRUE);
|
||||
break;
|
||||
case LinphonePolicyUseIce:
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_ice")),TRUE);
|
||||
break;
|
||||
}
|
||||
mtu=linphone_core_get_mtu(lc);
|
||||
if (mtu<=0){
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@ public interface LinphoneCore {
|
|||
* Use stun server to discover RTP addresses and ports.
|
||||
*/
|
||||
static public FirewallPolicy UseStun = new FirewallPolicy(2,"UseStun");
|
||||
/**
|
||||
* Use ICE.
|
||||
*/
|
||||
static public FirewallPolicy UseIce = new FirewallPolicy(3,"UseIce");
|
||||
|
||||
private final int mValue;
|
||||
private final String mStringValue;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ MSFilter *set_MSFilter(EndPoint *endpoint, int type, FlowDirections *fdir){
|
|||
switch(endpoint->protocol){
|
||||
case MEDIA_RTP:
|
||||
rtps = rtp_session_new(RTP_SESSION_RECVONLY);
|
||||
rtp_session_set_local_addr(rtps,"0.0.0.0",8000);
|
||||
rtp_session_set_local_addr(rtps,"0.0.0.0",8000,8001);
|
||||
rtp_session_set_scheduling_mode(rtps,0);
|
||||
rtp_session_set_blocking_mode(rtps,0);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue