mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-18 03:28:07 +00:00
Implement fully compatible IPv4/IPv6 mode.
Requires belle-sip upgrade.
This commit is contained in:
parent
fda6a31d1f
commit
ffaf96828f
8 changed files with 104 additions and 19 deletions
|
|
@ -179,6 +179,17 @@ void sal_address_unref(SalAddress *addr){
|
|||
belle_sip_object_unref(BELLE_SIP_HEADER_ADDRESS(addr));
|
||||
}
|
||||
|
||||
bool_t sal_address_is_ipv6(SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri){
|
||||
const char *host=belle_sip_uri_get_host(uri);
|
||||
if (host && strchr(host,':')!=NULL)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void sal_address_destroy(SalAddress *addr){
|
||||
sal_address_unref(addr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -612,3 +612,29 @@ bool_t sal_op_is_secure(const SalOp* op) {
|
|||
void sal_op_set_manual_refresher_mode(SalOp *op, bool_t enabled){
|
||||
op->manual_refresher=enabled;
|
||||
}
|
||||
|
||||
bool_t sal_op_is_ipv6(SalOp *op){
|
||||
belle_sip_transaction_t *tr=NULL;
|
||||
belle_sip_header_address_t *contact;
|
||||
belle_sip_request_t *req;
|
||||
|
||||
if (op->refresher)
|
||||
tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(op->refresher);
|
||||
|
||||
if (tr==NULL)
|
||||
tr=(belle_sip_transaction_t *)op->pending_client_trans;
|
||||
if (tr==NULL)
|
||||
tr=(belle_sip_transaction_t *)op->pending_server_trans;
|
||||
|
||||
if (tr==NULL){
|
||||
ms_error("Unable to determine IP version from signaling operation.");
|
||||
return FALSE;
|
||||
}
|
||||
req=belle_sip_transaction_get_request(tr);
|
||||
contact=(belle_sip_header_address_t*)belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t);
|
||||
if (!contact){
|
||||
ms_error("Unable to determine IP version from signaling operation, no contact header found.");
|
||||
}
|
||||
return sal_address_is_ipv6((SalAddress*)contact);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -501,12 +501,32 @@ void linphone_call_create_op(LinphoneCall *call){
|
|||
/*else privacy might be set by proxy */
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose IP version we are going to use for RTP socket.
|
||||
* The algorithm is as follows:
|
||||
* - if ipv6 is disabled at the core level, it is always AF_INET
|
||||
* - Otherwise, if the destination address for the call is an IPv6 address, use IPv6.
|
||||
* - Otherwise, if the call is done through a known proxy config, then use the information obtained during REGISTER
|
||||
* to know if IPv6 is supported by the server.
|
||||
**/
|
||||
static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, LinphoneAddress *to, LinphoneProxyConfig *cfg){
|
||||
if (linphone_core_ipv6_enabled(call->core)){
|
||||
call->af=AF_INET;
|
||||
if (sal_address_is_ipv6((SalAddress*)to)){
|
||||
call->af=AF_INET6;
|
||||
}else if (cfg && cfg->op){
|
||||
call->af=sal_op_is_ipv6(cfg->op) ? AF_INET6 : AF_INET;
|
||||
}
|
||||
}else call->af=AF_INET;
|
||||
}
|
||||
|
||||
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
|
||||
LinphoneCall *call=ms_new0(LinphoneCall,1);
|
||||
|
||||
call->dir=LinphoneCallOutgoing;
|
||||
call->core=lc;
|
||||
linphone_core_get_local_ip(lc,NULL,call->localip);
|
||||
linphone_call_outgoing_select_ip_version(call,to,cfg);
|
||||
linphone_core_get_local_ip(lc,call->af,call->localip);
|
||||
linphone_call_init_common(call,from,to);
|
||||
_linphone_call_params_copy(&call->params,params);
|
||||
|
||||
|
|
@ -535,6 +555,12 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
|
|||
return call;
|
||||
}
|
||||
|
||||
static void linphone_call_incoming_select_ip_version(LinphoneCall *call){
|
||||
if (linphone_core_ipv6_enabled(call->core)){
|
||||
call->af=sal_op_is_ipv6(call->op) ? AF_INET6 : AF_INET;
|
||||
}else call->af=AF_INET;
|
||||
}
|
||||
|
||||
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
|
||||
LinphoneCall *call=ms_new0(LinphoneCall,1);
|
||||
char *from_str;
|
||||
|
|
@ -544,7 +570,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
sal_op_set_user_pointer(op,call);
|
||||
call->op=op;
|
||||
call->core=lc;
|
||||
|
||||
linphone_call_incoming_select_ip_version(call);
|
||||
|
||||
if (lc->sip_conf.ping_with_options){
|
||||
#ifdef BUILD_UPNP
|
||||
|
|
@ -565,7 +591,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
}
|
||||
|
||||
linphone_address_clean(from);
|
||||
linphone_core_get_local_ip(lc,NULL,call->localip);
|
||||
linphone_core_get_local_ip(lc,call->af,call->localip);
|
||||
linphone_call_init_common(call, from, to);
|
||||
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
|
||||
linphone_core_init_default_params(lc, &call->params);
|
||||
|
|
@ -1331,7 +1357,7 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
int dscp;
|
||||
|
||||
if (call->audiostream != NULL) return;
|
||||
call->audiostream=audiostream=audio_stream_new(call->audio_port,call->audio_port+1,linphone_core_ipv6_enabled(lc));
|
||||
call->audiostream=audiostream=audio_stream_new(call->audio_port,call->audio_port+1,call->af==AF_INET6);
|
||||
dscp=linphone_core_get_audio_dscp(lc);
|
||||
if (dscp!=-1)
|
||||
audio_stream_set_dscp(audiostream,dscp);
|
||||
|
|
@ -1395,7 +1421,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
int dscp=linphone_core_get_video_dscp(lc);
|
||||
const char *display_filter=linphone_core_get_video_display_filter(lc);
|
||||
|
||||
call->videostream=video_stream_new(call->video_port,call->video_port+1,linphone_core_ipv6_enabled(lc));
|
||||
call->videostream=video_stream_new(call->video_port,call->video_port+1,call->af==AF_INET6);
|
||||
if (dscp!=-1)
|
||||
video_stream_set_dscp(call->videostream,dscp);
|
||||
video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0));
|
||||
|
|
|
|||
|
|
@ -1443,8 +1443,9 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
|
|||
}
|
||||
|
||||
|
||||
/*Returns the local ip that routes to the internet, or guessed by other special means (upnp)*/
|
||||
/*result must be an array of chars at least LINPHONE_IPADDR_SIZE */
|
||||
void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result){
|
||||
void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){
|
||||
const char *ip;
|
||||
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress
|
||||
&& (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){
|
||||
|
|
@ -1459,10 +1460,23 @@ void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result
|
|||
return;
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
if (linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,dest,result)==0)
|
||||
if (af==AF_UNSPEC){
|
||||
if (linphone_core_ipv6_enabled(lc)){
|
||||
bool_t has_ipv6;
|
||||
has_ipv6=linphone_core_get_local_ip_for(AF_INET6,NULL,result)==0;
|
||||
if (strcmp(result,"::1")!=0)
|
||||
return; /*this machine has real ipv6 connectivity*/
|
||||
if (linphone_core_get_local_ip_for(AF_INET,NULL,result)==0 && strcmp(result,"::1")!=0)
|
||||
return; /*this machine has only ipv4 connectivity*/
|
||||
if (has_ipv6){
|
||||
/*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/
|
||||
strncpy(result,"::1",LINPHONE_IPADDR_SIZE);
|
||||
return;
|
||||
}
|
||||
}else af=AF_INET;
|
||||
}
|
||||
if (linphone_core_get_local_ip_for(af,NULL,result)==0)
|
||||
return;
|
||||
/*else fallback to SAL routine that will attempt to find the most realistic interface */
|
||||
sal_get_default_local_ip(lc->sal,lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,result,LINPHONE_IPADDR_SIZE);
|
||||
}
|
||||
|
||||
static void update_primary_contact(LinphoneCore *lc){
|
||||
|
|
@ -1479,7 +1493,7 @@ static void update_primary_contact(LinphoneCore *lc){
|
|||
ms_error("Could not parse identity contact !");
|
||||
url=linphone_address_new("sip:unknown@unkwownhost");
|
||||
}
|
||||
linphone_core_get_local_ip(lc, NULL, tmp);
|
||||
linphone_core_get_local_ip(lc, AF_UNSPEC, tmp);
|
||||
if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){
|
||||
ms_warning("Local loopback network only !");
|
||||
lc->sip_conf.loopback_only=TRUE;
|
||||
|
|
@ -2027,7 +2041,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){
|
|||
|
||||
/* only do the network up checking every five seconds */
|
||||
if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){
|
||||
linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,NULL,result);
|
||||
linphone_core_get_local_ip(lc,AF_UNSPEC,result);
|
||||
if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
|
||||
new_status=TRUE;
|
||||
}else new_status=FALSE;
|
||||
|
|
|
|||
|
|
@ -637,12 +637,16 @@ static void stun_server_resolved(LinphoneCore *lc, const char *name, struct addr
|
|||
}
|
||||
|
||||
void linphone_core_resolve_stun_server(LinphoneCore *lc){
|
||||
/*
|
||||
* WARNING: stun server resolution only done in IPv4.
|
||||
* TODO: use IPv6 resolution if linphone_core_ipv6_enabled()==TRUE and use V4Mapped addresses for ICE gathering.
|
||||
*/
|
||||
const char *server=lc->net_conf.stun_server;
|
||||
if (lc->sal && server){
|
||||
char host[NI_MAXHOST];
|
||||
int port=3478;
|
||||
linphone_parse_host_port(server,host,sizeof(host),&port);
|
||||
lc->net_conf.stun_res=sal_resolve_a(lc->sal,host,port,AF_UNSPEC,(SalResolverCallback)stun_server_resolved,lc);
|
||||
lc->net_conf.stun_res=sal_resolve_a(lc->sal,host,port,AF_INET,(SalResolverCallback)stun_server_resolved,lc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -685,8 +689,8 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
|
|||
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");
|
||||
if (call->af==AF_INET6){
|
||||
ms_warning("Ice gathering is not implemented for ipv6");
|
||||
return -1;
|
||||
}
|
||||
ai=linphone_core_get_stun_server_addrinfo(lc);
|
||||
|
|
@ -1133,12 +1137,12 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
|
|||
socklen_t s;
|
||||
|
||||
memset(&hints,0,sizeof(hints));
|
||||
hints.ai_family=(type==AF_INET6) ? PF_INET6 : PF_INET;
|
||||
hints.ai_family=type;
|
||||
hints.ai_socktype=SOCK_DGRAM;
|
||||
/*hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME;*/
|
||||
err=getaddrinfo(dest,"5060",&hints,&res);
|
||||
if (err!=0){
|
||||
ms_error("getaddrinfo() error: %s",gai_strerror(err));
|
||||
ms_error("getaddrinfo() error for %s : %s",dest, gai_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
if (res==NULL){
|
||||
|
|
@ -1153,7 +1157,8 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
|
|||
}
|
||||
err=connect(sock,res->ai_addr,res->ai_addrlen);
|
||||
if (err<0) {
|
||||
ms_error("Error in connect: %s",strerror(errno));
|
||||
/*the network isn't reachable*/
|
||||
if (getSocketErrorCode()!=ENETUNREACH) ms_error("Error in connect: %s",strerror(errno));
|
||||
freeaddrinfo(res);
|
||||
close_socket(sock);
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ struct _LinphoneCall
|
|||
{
|
||||
int magic; /*used to distinguish from proxy config*/
|
||||
struct _LinphoneCore *core;
|
||||
int af; /*the address family to prefer for RTP path, guessed from signaling path*/
|
||||
SalMediaDescription *localdesc;
|
||||
SalMediaDescription *resultdesc;
|
||||
LinphoneCallDir dir;
|
||||
|
|
@ -263,7 +264,7 @@ int set_lock_file();
|
|||
int get_lock_file();
|
||||
int remove_lock_file();
|
||||
void check_sound_device(LinphoneCore *lc);
|
||||
void linphone_core_get_local_ip(LinphoneCore *lc, const char *to, char *result);
|
||||
void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result);
|
||||
bool_t host_has_ipv6_network();
|
||||
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret);
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ void sal_address_set_transport(SalAddress* addr,SalTransport transport);
|
|||
void sal_address_set_transport_name(SalAddress* addr,const char* transport);
|
||||
void sal_address_set_params(SalAddress *addr, const char *params);
|
||||
void sal_address_set_uri_params(SalAddress *addr, const char *params);
|
||||
bool_t sal_address_is_ipv6(SalAddress *addr);
|
||||
|
||||
Sal * sal_init();
|
||||
void sal_uninit(Sal* sal);
|
||||
|
|
@ -556,6 +557,7 @@ const SalAddress* sal_op_get_service_route(const SalOp *op);
|
|||
void sal_op_set_service_route(SalOp *op,const SalAddress* service_route);
|
||||
|
||||
void sal_op_set_manual_refresher_mode(SalOp *op, bool_t enabled);
|
||||
bool_t sal_op_is_ipv6(SalOp *op);
|
||||
|
||||
/*Call API*/
|
||||
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
|
||||
|
|
|
|||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit fcc51caa15def815189a388e878877a5354850e6
|
||||
Subproject commit 123ef1a55c321826966a3a375bee09b558ae170d
|
||||
Loading…
Add table
Reference in a new issue