mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-21 13:08:08 +00:00
- stun improvements (untested)
- support for one relay (work in progress) git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@18 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
d9e7d7b3ca
commit
d4c2c25cd5
6 changed files with 193 additions and 38 deletions
|
|
@ -436,7 +436,8 @@ int linphone_set_audio_offer(sdp_context_t *ctx)
|
|||
sdp_payload_init(&payload);
|
||||
payload.a_rtpmap=ortp_strdup_printf("%s/%i/1",codec->mime_type,codec->clock_rate);
|
||||
payload.pt=rtp_profile_get_payload_number_from_rtpmap(lc->local_profile,payload.a_rtpmap);
|
||||
payload.localport=lc->rtp_conf.audio_rtp_port;
|
||||
payload.localport=call->audio_params.natd_port > 0 ?
|
||||
call->audio_params.natd_port : lc->rtp_conf.audio_rtp_port;
|
||||
if (strcasecmp(codec->mime_type,"iLBC")==0){
|
||||
/* prefer the 30 ms mode */
|
||||
payload.a_fmtp="ptime=30";
|
||||
|
|
@ -511,7 +512,8 @@ int linphone_set_video_offer(sdp_context_t *ctx)
|
|||
sdp_payload_init(&payload);
|
||||
payload.line=1;
|
||||
payload.a_rtpmap=ortp_strdup_printf("%s/%i",codec->mime_type,codec->clock_rate);
|
||||
payload.localport=lc->rtp_conf.video_rtp_port;
|
||||
payload.localport=call->video_params.natd_port>0 ?
|
||||
call->video_params.natd_port : lc->rtp_conf.video_rtp_port;
|
||||
payload.pt=find_payload_type_number(lc->local_profile,codec);
|
||||
payload.a_fmtp=codec->recv_fmtp;
|
||||
if(firsttime){
|
||||
|
|
@ -628,7 +630,9 @@ int linphone_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload)
|
|||
params=&call->audio_params;
|
||||
if (params->initialized==0){
|
||||
/* this is the first codec we accept, it is going to be used*/
|
||||
params->localport=payload->localport=lc->rtp_conf.audio_rtp_port;
|
||||
params->localport=lc->rtp_conf.audio_rtp_port;
|
||||
payload->localport=params->natd_port>0 ?
|
||||
params->natd_port : lc->rtp_conf.audio_rtp_port;
|
||||
params->line=payload->line;
|
||||
params->pt=payload->pt; /* remember the first payload accepted */
|
||||
if (payload->relay_host!=NULL){
|
||||
|
|
@ -678,7 +682,8 @@ int linphone_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload)
|
|||
params=&call->video_params;
|
||||
if (params->initialized==0){
|
||||
/* this is the first codec we may accept*/
|
||||
params->localport=payload->localport=lc->rtp_conf.video_rtp_port;
|
||||
params->localport=lc->rtp_conf.video_rtp_port;
|
||||
payload->localport=params->natd_port>0 ? params->natd_port : lc->rtp_conf.video_rtp_port;
|
||||
params->line=payload->line;
|
||||
params->pt=payload->pt; /* remember the first payload accepted */
|
||||
if (payload->relay_host!=NULL){
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "sdphandler.h"
|
||||
|
||||
#include <ortp/telephonyevents.h>
|
||||
#include <ortp/stun.h>
|
||||
#include "exevents.h"
|
||||
|
||||
|
||||
|
|
@ -81,6 +80,8 @@ static void linphone_call_init_common(LinphoneCall *call, char *from, char *to)
|
|||
call->start_time=time(NULL);
|
||||
call->log=linphone_call_log_new(call, from, to);
|
||||
linphone_core_notify_all_friends(call->core,LINPHONE_STATUS_ONTHEPHONE);
|
||||
if (linphone_core_get_firewall_policy(call->core)==LINPHONE_POLICY_USE_STUN)
|
||||
linphone_core_run_stun_tests(call->core,call);
|
||||
}
|
||||
|
||||
void linphone_call_init_media_params(LinphoneCall *call){
|
||||
|
|
@ -112,10 +113,12 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const osip_f
|
|||
call->tid=-1;
|
||||
call->core=lc;
|
||||
linphone_core_get_local_ip(lc,to->url->host,localip);
|
||||
call->sdpctx=sdp_handler_create_context(&linphone_sdphandler,localip,from->url->username,NULL);
|
||||
osip_from_to_str(from,&fromstr);
|
||||
osip_to_to_str(to,&tostr);
|
||||
linphone_call_init_common(call,fromstr,tostr);
|
||||
call->sdpctx=sdp_handler_create_context(&linphone_sdphandler,
|
||||
call->audio_params.natd_port>0 ? call->audio_params.natd_addr : localip,
|
||||
from->url->username,NULL);
|
||||
discover_mtu(lc,to->url->host);
|
||||
return call;
|
||||
}
|
||||
|
|
@ -135,8 +138,10 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, const char *from, co
|
|||
osip_from_init(&from_url);
|
||||
osip_from_parse(from_url, from);
|
||||
linphone_core_get_local_ip(lc,from_url->url->host,localip);
|
||||
call->sdpctx=sdp_handler_create_context(&linphone_sdphandler,localip,me->url->username,NULL);
|
||||
linphone_call_init_common(call, osip_strdup(from), osip_strdup(to));
|
||||
call->sdpctx=sdp_handler_create_context(&linphone_sdphandler,
|
||||
call->audio_params.natd_port>0 ? call->audio_params.natd_addr : localip,
|
||||
me->url->username,NULL);
|
||||
discover_mtu(lc,from_url->url->host);
|
||||
osip_from_free(me);
|
||||
osip_from_free(from_url);
|
||||
|
|
@ -733,35 +738,6 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool_t stun_get_localip(LinphoneCore *lc, char *result, int *port){
|
||||
const char *server=linphone_core_get_stun_server(lc);
|
||||
StunAddress4 addr;
|
||||
StunAddress4 mapped;
|
||||
StunAddress4 changed;
|
||||
if (server!=NULL){
|
||||
if (stunParseServerName((char*)server,&addr)){
|
||||
if (lc->vtable.display_status!=NULL)
|
||||
lc->vtable.display_status(lc,_("Stun lookup in progress..."));
|
||||
if (stunTest(&addr,1,TRUE,NULL,&mapped,&changed)==0){
|
||||
struct in_addr inaddr;
|
||||
char *tmp;
|
||||
inaddr.s_addr=ntohl(mapped.addr);
|
||||
tmp=inet_ntoa(inaddr);
|
||||
*port=ntohs(mapped.port);
|
||||
strncpy(result,tmp,LINPHONE_IPADDR_SIZE);
|
||||
if (lc->vtable.display_status!=NULL)
|
||||
lc->vtable.display_status(lc,_("Stun lookup done..."));
|
||||
ms_message("Stun server says we have address %s:i",result,*port);
|
||||
return TRUE;
|
||||
}else{
|
||||
ms_warning("stun lookup failed.");
|
||||
}
|
||||
}else{
|
||||
ms_warning("Fail to resolv or parse %s",server);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*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){
|
||||
|
|
@ -777,14 +753,17 @@ void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result
|
|||
if (lc->sip_conf.ipv6_enabled){
|
||||
ms_warning("stun support is not implemented for ipv6");
|
||||
}else{
|
||||
/* we no more use stun for sip socket*/
|
||||
#if 0
|
||||
int mport=0;
|
||||
ms_message("doing stun lookup for local address...");
|
||||
if (stun_get_localip(lc,result,&mport)){
|
||||
if (stun_get_localip(lc,sock,linphone_core_get_sip_port(lc),result,&mport)){
|
||||
if (!lc->net_conf.nat_sdp_only)
|
||||
eXosip_masquerade_contact(result,mport);
|
||||
return;
|
||||
}
|
||||
ms_warning("stun lookup failed, falling back to a local interface...");
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "ortp/payloadtype.h"
|
||||
#include "mediastreamer2/mscommon.h"
|
||||
|
||||
#define LINPHONE_IPADDR_SIZE 64
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -145,6 +147,8 @@ typedef struct _StreamParams
|
|||
char *remoteaddr;
|
||||
int pt;
|
||||
char *relay_session_id;
|
||||
char natd_addr[LINPHONE_IPADDR_SIZE];
|
||||
int natd_port;
|
||||
} StreamParams;
|
||||
|
||||
typedef enum _LCState{
|
||||
|
|
@ -486,7 +490,7 @@ typedef struct _LinphoneCore
|
|||
#endif
|
||||
} LinphoneCore;
|
||||
|
||||
#define LINPHONE_IPADDR_SIZE 64
|
||||
|
||||
|
||||
/* THE main API */
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <ortp/stun.h>
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
|
|
@ -448,3 +450,165 @@ bool_t host_has_ipv6_network()
|
|||
|
||||
|
||||
#endif
|
||||
|
||||
static ortp_socket_t create_socket(int local_port){
|
||||
struct sockaddr_in laddr;
|
||||
ortp_socket_t sock;
|
||||
int optval;
|
||||
sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
|
||||
if (sock<0) {
|
||||
ms_error("Fail to create socket");
|
||||
return -1;
|
||||
}
|
||||
memset (&laddr,0,sizeof(laddr));
|
||||
laddr.sin_family=AF_INET;
|
||||
laddr.sin_addr.s_addr=INADDR_ANY;
|
||||
laddr.sin_port=htons(local_port);
|
||||
if (bind(sock,(struct sockaddr*)&laddr,sizeof(laddr))<0){
|
||||
ms_error("Bind to 0.0.0.0:%i failed: %s",local_port,strerror(errno));
|
||||
close_socket(sock);
|
||||
return -1;
|
||||
}
|
||||
optval=1;
|
||||
if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(SOCKET_OPTION_VALUE)&optval, sizeof (optval))<0){
|
||||
ms_warning("Fail to set SO_REUSEADDR");
|
||||
}
|
||||
set_non_blocking_socket(sock);
|
||||
return sock;
|
||||
}
|
||||
|
||||
static int sendStunRequest(int sock, const struct sockaddr *server, socklen_t addrlen, int id){
|
||||
char buf[STUN_MAX_MESSAGE_SIZE];
|
||||
int len = STUN_MAX_MESSAGE_SIZE;
|
||||
StunAtrString username;
|
||||
StunAtrString password;
|
||||
StunMessage req;
|
||||
int err;
|
||||
memset(&req, 0, sizeof(StunMessage));
|
||||
memset(&username,0,sizeof(username));
|
||||
memset(&password,0,sizeof(password));
|
||||
stunBuildReqSimple( &req, &username, FALSE , FALSE , id);
|
||||
len = stunEncodeMessage( &req, buf, len, &password, FALSE);
|
||||
if (len<=0){
|
||||
ms_error("Fail to encode stun message.");
|
||||
return -1;
|
||||
}
|
||||
err=sendto(sock,buf,len,0,server,addrlen);
|
||||
if (err<0){
|
||||
ms_error("sendto failed: %s",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_stun_server_addr(const char *server, struct sockaddr_storage *ss, socklen_t *socklen){
|
||||
struct addrinfo hints,*res=NULL;
|
||||
int ret;
|
||||
const char *port;
|
||||
char host[NI_MAXHOST];
|
||||
char *p;
|
||||
host[NI_MAXHOST-1]='\0';
|
||||
strncpy(host,server,sizeof(host)-1);
|
||||
p=strchr(server,':');
|
||||
if (p) {
|
||||
*p='\0';
|
||||
port=p+1;
|
||||
}else port="3478";
|
||||
memset(&hints,0,sizeof(hints));
|
||||
hints.ai_family=PF_INET;
|
||||
hints.ai_socktype=SOCK_DGRAM;
|
||||
hints.ai_protocol=IPPROTO_UDP;
|
||||
ret=getaddrinfo(host,port,&hints,&res);
|
||||
if (ret!=0){
|
||||
ms_error("getaddrinfo() failed for %s:%s : %s",host,port,gai_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
if (!res) return -1;
|
||||
memcpy(ss,res->ai_addr,res->ai_addrlen);
|
||||
*socklen=res->ai_addrlen;
|
||||
freeaddrinfo(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int recvStunResponse(ortp_socket_t sock, char *ipaddr, int *port){
|
||||
char buf[STUN_MAX_MESSAGE_SIZE];
|
||||
int len = STUN_MAX_MESSAGE_SIZE;
|
||||
StunMessage resp;
|
||||
len=recv(sock,buf,len,0);
|
||||
if (len>0){
|
||||
struct in_addr ia;
|
||||
stunParseMessage(buf,len, &resp,FALSE );
|
||||
*port = resp.changedAddress.ipv4.port;
|
||||
ia.s_addr=htonl(resp.changedAddress.ipv4.addr);
|
||||
strncpy(ipaddr,inet_ntoa(ia),LINPHONE_IPADDR_SIZE);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
|
||||
const char *server=linphone_core_get_stun_server(lc);
|
||||
|
||||
if (lc->sip_conf.ipv6_enabled){
|
||||
ms_warning("stun support is not implemented for ipv6");
|
||||
return;
|
||||
}
|
||||
if (server!=NULL){
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t ss_len;
|
||||
ortp_socket_t sock1=-1, sock2=-1;
|
||||
bool_t video_enabled=linphone_core_video_enabled(lc);
|
||||
bool_t got_audio,got_video;
|
||||
struct timeval init,cur;
|
||||
if (parse_stun_server_addr(server,&ss,&ss_len)<0){
|
||||
return;
|
||||
}
|
||||
if (lc->vtable.display_status!=NULL)
|
||||
lc->vtable.display_status(lc,_("Stun lookup in progress..."));
|
||||
|
||||
/*create the two audio and video RTP sockets, and send STUN message to our stun server */
|
||||
sock1=create_socket(linphone_core_get_audio_port(lc));
|
||||
if (sock1<0) return;
|
||||
if (video_enabled){
|
||||
sock2=create_socket(linphone_core_get_video_port(lc));
|
||||
if (sock2<0) return ;
|
||||
}
|
||||
sendStunRequest(sock1,(struct sockaddr*)&ss,ss_len,1);
|
||||
if (sock2>=0)
|
||||
sendStunRequest(sock2,(struct sockaddr*)&ss,ss_len,2);
|
||||
|
||||
got_audio=FALSE;
|
||||
got_video=FALSE;
|
||||
gettimeofday(&init,NULL);
|
||||
do{
|
||||
double elapsed;
|
||||
#ifdef WIN32
|
||||
Sleep(10);
|
||||
#else
|
||||
usleep(10000);
|
||||
#endif
|
||||
|
||||
if (recvStunResponse(sock1,call->audio_params.natd_addr,
|
||||
&call->audio_params.natd_port)>0){
|
||||
ms_message("STUN test result: local audio port maps to %s:%i",
|
||||
call->audio_params.natd_addr,
|
||||
call->audio_params.natd_port);
|
||||
got_audio=TRUE;
|
||||
}
|
||||
if (recvStunResponse(sock2,call->video_params.natd_addr,
|
||||
&call->video_params.natd_port)>0){
|
||||
ms_message("STUN test result: local video port maps to %s:%i",
|
||||
call->video_params.natd_addr,
|
||||
call->video_params.natd_port);
|
||||
got_video=TRUE;
|
||||
}
|
||||
gettimeofday(&cur,NULL);
|
||||
elapsed=((cur.tv_sec-init.tv_sec)*1000.0) + ((cur.tv_usec-init.tv_usec)/1000.0);
|
||||
if (elapsed>2000) break;
|
||||
}while(!(got_audio && (got_video||sock2<0) ) );
|
||||
close_socket(sock1);
|
||||
if (sock2>=0) close_socket(sock2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -117,5 +117,6 @@ LinphoneFriend *linphone_find_friend_by_nid(MSList *l, int nid);
|
|||
LinphoneFriend *linphone_find_friend_by_sid(MSList *l, int sid);
|
||||
|
||||
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc, const PayloadType *pt);
|
||||
void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
#endif /* _PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -2067,6 +2067,8 @@ stunTest( StunAddress4 *dest, int testNum, bool_t verbose, StunAddress4* sAddr ,
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
NatType
|
||||
stunNatType( StunAddress4 *dest,
|
||||
bool_t verbose,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue