Commit 06fc0526 authored by jehan's avatar jehan

multicast impl

parent ef810b10
......@@ -210,10 +210,18 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
/*only add a c= line within the stream description if address are differents*/
if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){
bool_t inet6;
belle_sdp_connection_t *connection;
if (strchr(rtp_addr,':')!=NULL){
inet6=TRUE;
}else inet6=FALSE;
belle_sdp_media_description_set_connection(media_desc,belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr));
connection = belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr);
if (ms_is_multicast(rtp_addr)) {
/*remove session cline in case of multicast*/
belle_sdp_session_description_set_connection(session_desc,NULL);
if (inet6 == FALSE)
belle_sdp_connection_set_ttl(connection,stream->ttl);
}
belle_sdp_media_description_set_connection(media_desc,connection);
}
if ( stream->bandwidth>0 )
......@@ -706,6 +714,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
}
if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ), sizeof ( stream->rtp_addr ) -1 );
stream->ttl=belle_sdp_connection_get_ttl(cnx);
}
stream->rtp_port=belle_sdp_media_get_media_port ( media );
......
......@@ -51,6 +51,7 @@ LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
* The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient.
*/
if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers);
return ncp;
}
......@@ -158,6 +159,21 @@ bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
return cp->has_video;
}
LinphoneCallParamsMediaDirection linphone_call_params_get_audio_direction(const LinphoneCallParams *cp) {
return cp->audio_dir;
}
LinphoneCallParamsMediaDirection linphone_call_params_get_video_direction(const LinphoneCallParams *cp) {
return cp->video_dir;
}
void linphone_call_params_set_audio_direction(LinphoneCallParams *cp,LinphoneCallParamsMediaDirection dir) {
cp->audio_dir=dir;
}
void linphone_call_params_set_video_direction(LinphoneCallParams *cp,LinphoneCallParamsMediaDirection dir) {
cp->video_dir=dir;
}
/*******************************************************************************
......
......@@ -30,6 +30,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/*******************************************************************************
* Structures and enums *
******************************************************************************/
/**
* Indicates for a given media the stream direction
* */
enum _LinphoneCallParamsMediaDirection {
LinphoneCallParamsMediaDirectionInactive, /** No active media not supported yet*/
LinphoneCallParamsMediaDirectionSendOnly, /** Send only mode*/
LinphoneCallParamsMediaDirectionRecvOnly, /** recv only mode*/
LinphoneCallParamsMediaDirectionSendRecv, /*send receive mode not supported yet*/
};
/**
* Typedef for enum
**/
typedef enum _LinphoneCallParamsMediaDirection LinphoneCallParamsMediaDirection;
/**
* Private structure definition for LinphoneCallParams.
......@@ -247,6 +261,34 @@ LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *c
**/
LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
/**
* Get the audio stream direction.
* @param[in] cl LinphoneCallParams object
* @return The audio stream direction associated with the call params.
**/
LINPHONE_PUBLIC LinphoneCallParamsMediaDirection linphone_call_params_get_audio_direction(const LinphoneCallParams *cp);
/**
* Get the video stream direction.
* @param[in] cl LinphoneCallParams object
* @return The video stream direction associated with the call params.
**/
LINPHONE_PUBLIC LinphoneCallParamsMediaDirection linphone_call_params_get_video_direction(const LinphoneCallParams *cp);
/**
* Set the audio stream direction. Only relevant for multicast
* @param[in] cl LinphoneCallParams object
* @param[in] The audio stream direction associated with this call params.
**/
/*LINPHONE_PUBLIC void linphone_call_params_set_audio_direction(LinphoneCallParams *cp, LinphoneCallParamsMediaDirection dir);*/
/**
* Set the video stream direction. Only relevant for multicast
* @param[in] cl LinphoneCallParams object
* @param[in] The video stream direction associated with this call params.
**/
/*LINPHONE_PUBLIC void linphone_call_params_set_video_direction(LinphoneCallParams *cp, LinphoneCallParamsMediaDirection dir);*/
/*******************************************************************************
* Reference and user data handling functions *
......
......@@ -546,7 +546,24 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
const char *me;
SalMediaDescription *md=sal_media_description_new();
LinphoneAddress *addr;
char* local_ip=call->localip;
const char* local_audio_ip;
const char* local_video_ip;
/*multicast is only set in case of outgoing call*/
if (call->dir == LinphoneCallOutgoing && linphone_core_audio_multicast_enabled(lc)) {
local_audio_ip=linphone_core_get_audio_multicast_addr(lc);
md->streams[0].ttl=linphone_core_get_audio_multicast_ttl(lc);
md->streams[0].multicast_role = SalMulticastRoleSender;
} else
local_audio_ip=call->localip;
if (call->dir == LinphoneCallOutgoing && linphone_core_video_multicast_enabled(lc)) {
local_video_ip=linphone_core_get_video_multicast_addr(lc);
md->streams[1].ttl=linphone_core_get_video_multicast_ttl(lc);
md->streams[1].multicast_role = SalMulticastRoleSender;
}else
local_video_ip=call->localip;
const char *subject=linphone_call_params_get_session_name(call->params);
CodecConstraints codec_hints={0};
......@@ -562,7 +579,7 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
md->nb_streams=(call->biggestdesc ? call->biggestdesc->nb_streams : 1);
strncpy(md->addr,local_ip,sizeof(md->addr));
strncpy(md->addr,call->localip,sizeof(md->addr));
strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
if (subject) strncpy(md->name,subject,sizeof(md->name));
......@@ -571,8 +588,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
else md->bandwidth=linphone_core_get_download_bandwidth(lc);
/*set audio capabilities */
strncpy(md->streams[0].rtp_addr,local_ip,sizeof(md->streams[0].rtp_addr));
strncpy(md->streams[0].rtcp_addr,local_ip,sizeof(md->streams[0].rtcp_addr));
strncpy(md->streams[0].rtp_addr,local_audio_ip,sizeof(md->streams[0].rtp_addr));
strncpy(md->streams[0].rtcp_addr,local_audio_ip,sizeof(md->streams[0].rtcp_addr));
strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1);
md->streams[0].rtp_port=call->media_ports[0].rtp_port;
md->streams[0].rtcp_port=call->media_ports[0].rtcp_port;
......@@ -599,8 +616,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
nb_active_streams++;
if (call->params->has_video){
strncpy(md->streams[1].rtp_addr,local_ip,sizeof(md->streams[1].rtp_addr));
strncpy(md->streams[1].rtcp_addr,local_ip,sizeof(md->streams[1].rtcp_addr));
strncpy(md->streams[1].rtp_addr,local_video_ip,sizeof(md->streams[1].rtp_addr));
strncpy(md->streams[1].rtcp_addr,local_video_ip,sizeof(md->streams[1].rtcp_addr));
strncpy(md->streams[1].name,"Video",sizeof(md->streams[1].name)-1);
md->streams[1].rtp_port=call->media_ports[1].rtp_port;
md->streams[1].rtcp_port=call->media_ports[1].rtcp_port;
......@@ -764,6 +781,9 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO);
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO);
/*by default local_audio_ip=local_video_ip=local_ip*/
strncpy(call->local_audio_ip,call->localip,sizeof(call->local_audio_ip));
strncpy(call->local_video_ip,call->localip,sizeof(call->local_video_ip));
}
void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
......@@ -935,6 +955,20 @@ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, c
if ((sal_media_description_has_srtp(md) == TRUE) && (ms_srtp_supported() == TRUE)) {
call->params->media_encryption = LinphoneMediaEncryptionSRTP;
}
//set both local audio & video
if (ms_is_multicast(md->streams[0].rtp_addr)) {
strncpy(call->local_audio_ip,md->streams[0].rtp_addr,sizeof(call->local_audio_ip));
ms_message("Disabling audio rtcp on call [%p] because of multicast",call);
call->media_ports[0].rtp_port=md->streams[0].rtp_port;
call->media_ports[0].rtcp_port=0;
}
if (ms_is_multicast(md->streams[1].rtp_addr)) {
strncpy(call->local_video_ip,md->streams[1].rtp_addr,sizeof(call->local_video_ip));
call->media_ports[1].rtp_port=md->streams[1].rtp_port;
call->media_ports[1].rtcp_port=0;
ms_message("Disabling video rtcp on call [%p] because of multicast",call);
}
}
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
......@@ -1767,11 +1801,12 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
int dscp;
char rtcp_tool[128]={0};
char* cname;
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
if (call->audiostream != NULL) return;
if (call->sessions[0].rtp_session==NULL){
call->audiostream=audiostream=audio_stream_new(call->media_ports[0].rtp_port,call->media_ports[0].rtcp_port,call->af==AF_INET6);
call->audiostream=audiostream=audio_stream_new2(call->local_audio_ip,call->media_ports[0].rtp_port,call->media_ports[0].rtcp_port);
cname = linphone_address_as_string_uri_only(call->me);
audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
ms_free(cname);
......@@ -1876,7 +1911,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){
const char *display_filter=linphone_core_get_video_display_filter(lc);
if (call->sessions[1].rtp_session==NULL){
call->videostream=video_stream_new(call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port, call->af==AF_INET6);
call->videostream=video_stream_new2(call->local_video_ip,call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port);
cname = linphone_address_as_string_uri_only(call->me);
video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
ms_free(cname);
......@@ -2259,7 +2294,9 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
}
/*Replace soundcard filters by inactive file players or recorders
when placed in recvonly or sendonly mode*/
if (stream->rtp_port==0 || stream->dir==SalStreamRecvOnly){
if (stream->rtp_port==0
|| stream->dir==SalStreamRecvOnly
|| (stream->multicast_role == SalMulticastRoleReceiver && ms_is_multicast(stream->rtp_addr))){
captcard=NULL;
playfile=NULL;
}else if (stream->dir==SalStreamSendOnly){
......@@ -2315,13 +2352,16 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
}
}
configure_rtp_session_for_rtcp_xr(lc, call, SalAudio);
if (ms_is_multicast(stream->rtp_addr))
rtp_session_set_multicast_ttl(call->audiostream->ms.sessions.rtp_session,stream->ttl);
audio_stream_start_full(
call->audiostream,
call->audio_profile,
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 ? stream->rtcp_port : stream->rtp_port+1) : 0,
(linphone_core_rtcp_enabled(lc) && !ms_is_multicast(stream->rtp_addr)) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port+1) : 0,
used_pt,
linphone_core_get_audio_jittcomp(lc),
playfile,
......@@ -2402,7 +2442,12 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
video_stream_set_native_preview_window_id (call->videostream,lc->preview_window_id);
video_stream_use_preview_video_window (call->videostream,lc->use_preview_window);
if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
if (ms_is_multicast(vstream->rtp_addr)){
if (vstream->multicast_role == SalMulticastRoleReceiver)
dir=VideoStreamRecvOnly;
else
dir=VideoStreamSendOnly;
} else if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
if (local_st_desc->dir==SalStreamSendOnly){
/* localdesc stream dir to SendOnly is when we want to put on hold, so use nowebcam in this case*/
cam=get_nowebcam_device();
......@@ -2440,6 +2485,9 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
video_stream_set_device_rotation(call->videostream, lc->device_rotation);
video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 0));
if (ms_is_multicast(vstream->rtp_addr))
rtp_session_set_multicast_ttl(call->videostream->ms.sessions.rtp_session,vstream->ttl);
if( lc->video_conf.reuse_preview_source && source ){
ms_message("video_stream_start_with_source kept: %p", source);
video_stream_start_with_source(call->videostream,
......@@ -2452,7 +2500,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
video_stream_start(call->videostream,
call->video_profile, rtp_addr, vstream->rtp_port,
rtcp_addr,
linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
(linphone_core_rtcp_enabled(lc) && !ms_is_multicast(vstream->rtp_addr)) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
used_pt, linphone_core_get_video_jittcomp(lc), cam);
}
}
......
......@@ -947,6 +947,8 @@ static void rtp_config_read(LinphoneCore *lc)
int nortp_timeout;
bool_t rtp_no_xmit_on_audio_mute;
bool_t adaptive_jitt_comp_enabled;
const char* tmp;
int tmp_int;
if (lp_config_get_range(lc->config, "rtp", "audio_rtp_port", &min_port, &max_port, 7078, 7078) == TRUE) {
if (min_port <= 0) min_port = 1;
......@@ -981,6 +983,26 @@ static void rtp_config_read(LinphoneCore *lc)
linphone_core_enable_video_adaptive_jittcomp(lc, adaptive_jitt_comp_enabled);
lc->rtp_conf.disable_upnp = lp_config_get_int(lc->config, "rtp", "disable_upnp", FALSE);
linphone_core_set_avpf_mode(lc,lp_config_get_int(lc->config,"rtp","avpf",0));
if ((tmp=lp_config_get_string(lc->config,"rtp","audio_multicast_addr",NULL)))
linphone_core_set_audio_multicast_addr(lc,tmp);
else
lc->rtp_conf.audio_multicast_addr=ms_strdup("224.1.2.3");
if ((tmp_int=lp_config_get_int(lc->config,"rtp","audio_multicast_enabled",-1)) >-1)
linphone_core_enable_audio_multicast(lc,tmp_int);
if ((tmp_int=lp_config_get_int(lc->config,"rtp","audio_multicast_ttl",-1))>0)
linphone_core_set_audio_multicast_ttl(lc,tmp_int);
else
lc->rtp_conf.audio_multicast_ttl=1;/*local network*/
if ((tmp=lp_config_get_string(lc->config,"rtp","video_multicast_addr",NULL)))
linphone_core_set_video_multicast_addr(lc,tmp);
else
lc->rtp_conf.video_multicast_addr=ms_strdup("224.1.2.3");
if ((tmp_int=lp_config_get_int(lc->config,"rtp","video_multicast_ttl",-1))>-1)
linphone_core_set_video_multicast_ttl(lc,tmp_int);
else
lc->rtp_conf.video_multicast_ttl=1;/*local network*/
if ((tmp_int=lp_config_get_int(lc->config,"rtp","video_multicast_enabled",-1)) >0)
linphone_core_enable_video_multicast(lc,tmp_int);
}
static PayloadType * find_payload(const MSList *default_list, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp){
......@@ -6123,6 +6145,8 @@ void rtp_config_uninit(LinphoneCore *lc)
lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout);
lp_config_set_int(lc->config,"rtp","audio_adaptive_jitt_comp_enabled",config->audio_adaptive_jitt_comp_enabled);
lp_config_set_int(lc->config,"rtp","video_adaptive_jitt_comp_enabled",config->video_adaptive_jitt_comp_enabled);
ms_free(lc->rtp_conf.audio_multicast_addr);
ms_free(lc->rtp_conf.video_multicast_addr);
ms_free(config->srtp_suites);
}
......@@ -6878,6 +6902,8 @@ void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *para
params->in_conference=FALSE;
params->privacy=LinphonePrivacyDefault;
params->avpf_enabled=FALSE;
params->audio_dir=LinphoneCallParamsMediaDirectionSendRecv;
params->video_dir=LinphoneCallParamsMediaDirectionSendRecv;
}
void linphone_core_set_device_identifier(LinphoneCore *lc,const char* device_id) {
......@@ -7216,3 +7242,81 @@ void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *v
ms_message("Vtable [%p] unregistered on core [%p]",lc,vtable);
lc->vtables=ms_list_remove(lc->vtables,(void*)vtable);
}
int linphone_core_set_audio_multicast_addr(LinphoneCore *lc, const char* ip) {
char* new_value;
if (ip && !ms_is_multicast(ip)) {
ms_error("Cannot set multicast audio addr to core [%p] because [%s] is not multicast",lc,ip);
return -1;
}
new_value = ip?ms_strdup(ip):NULL;
if (lc->rtp_conf.audio_multicast_addr) ms_free(lc->rtp_conf.audio_multicast_addr);
lp_config_set_string(lc->config,"rtp","audio_multicast_addr",lc->rtp_conf.audio_multicast_addr=new_value);
return 0;
}
int linphone_core_set_video_multicast_addr(LinphoneCore *lc, const char* ip) {
char* new_value;
if (ip && !ms_is_multicast(ip)) {
ms_error("Cannot set multicast video addr to core [%p] because [%s] is not multicast",lc,ip);
return -1;
}
new_value = ip?ms_strdup(ip):NULL;
if (lc->rtp_conf.video_multicast_addr) ms_free(lc->rtp_conf.video_multicast_addr);
lp_config_set_string(lc->config,"rtp","video_multicast_addr",lc->rtp_conf.video_multicast_addr=new_value);
return 0;
}
const char* linphone_core_get_audio_multicast_addr(const LinphoneCore *lc) {
return lc->rtp_conf.audio_multicast_addr;
}
const char* linphone_core_get_video_multicast_addr(const LinphoneCore *lc){
return lc->rtp_conf.video_multicast_addr;
}
int linphone_core_set_audio_multicast_ttl(LinphoneCore *lc, int ttl) {
if (ttl>255) {
ms_error("Cannot set multicast audio ttl to core [%p] to [%i] value must be <256",lc,ttl);
return -1;
}
lp_config_set_int(lc->config,"rtp","audio_multicast_ttl",lc->rtp_conf.audio_multicast_ttl=ttl);
return 0;
}
int linphone_core_set_video_multicast_ttl(LinphoneCore *lc, int ttl) {
if (ttl>255) {
ms_error("Cannot set multicast video ttl to core [%p] to [%i] value must be <256",lc,ttl);
return -1;
}
lp_config_set_int(lc->config,"rtp","video_multicast_ttl",lc->rtp_conf.video_multicast_ttl=ttl);
return 0;
}
int linphone_core_get_audio_multicast_ttl(const LinphoneCore *lc) {
return lc->rtp_conf.audio_multicast_ttl;
}
int linphone_core_get_video_multicast_ttl(const LinphoneCore *lc){
return lc->rtp_conf.video_multicast_ttl;
}
void linphone_core_enable_audio_multicast(LinphoneCore *lc, bool_t yesno) {
lp_config_set_int(lc->config,"rtp","audio_multicast_enabled",lc->rtp_conf.audio_multicast_enabled=yesno);
}
bool_t linphone_core_audio_multicast_enabled(const LinphoneCore *lc) {
return lc->rtp_conf.audio_multicast_enabled;
}
void linphone_core_enable_video_multicast(LinphoneCore *lc, bool_t yesno) {
lp_config_set_int(lc->config,"rtp","video_multicast_enabled",lc->rtp_conf.video_multicast_enabled=yesno);
}
bool_t linphone_core_video_multicast_enabled(const LinphoneCore *lc) {
return lc->rtp_conf.video_multicast_enabled;
}
......@@ -3305,6 +3305,105 @@ LINPHONE_PUBLIC void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int in
LINPHONE_PUBLIC int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc);
/**
* Use to set multicast address to be used for audio stream.
* @param core the core
* @param ip an ipv4/6 multicast address
* @return 0 in case of success
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_set_audio_multicast_addr(LinphoneCore *core, const char* ip);
/**
* Use to set multicast address to be used for video stream.
* @param core the core
* @param ip an ipv4/6 multicast address
* @return 0 in case of success
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_set_video_multicast_addr(LinphoneCore *lc, const char *ip);
/**
* Use to get multicast address to be used for audio stream.
* @param core the core
* @return an ipv4/6 multicast address or default value
* @ingroup media_parameters
**/
LINPHONE_PUBLIC const char* linphone_core_get_audio_multicast_addr(const LinphoneCore *core);
/**
* Use to get multicast address to be used for video stream.
* @param core the core
* @return an ipv4/6 multicast address, or default value
* @ingroup media_parameters
**/
LINPHONE_PUBLIC const char* linphone_core_get_video_multicast_addr(const LinphoneCore *core);
/**
* Use to set multicast ttl to be used for audio stream.
* @param core the core
* @param ip an ttl or -1 if not used [0..255] default value is 1
* @return 0 in case of success
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_set_audio_multicast_ttl(LinphoneCore *core, int ttl);
/**
* Use to set multicast ttl to be used for video stream.
* @param core the core
* @param ip an ttl or -1 if not used [0..255] default value is 1
* @return 0 in case of success
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_set_video_multicast_ttl(LinphoneCore *lc, int ttl);
/**
* Use to get multicast ttl to be used for audio stream.
* @param core the core
* @return an time to leave value or -1 if not set
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_get_audio_multicast_ttl(const LinphoneCore *core);
/**
* Use to get multicast ttl to be used for video stream.
* @param core the core
* @return an an time to leave value or -1 if not set
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_get_video_multicast_ttl(const LinphoneCore *core);
/**
* Use to enable multicast rtp for audio stream.
* @param core the core
* @param yesno if yes, subsequent calls propose multicast ip set by #linphone_core_set_audio_multicast_addr
* @return an ipv4/6 multicast address or null
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_core_enable_audio_multicast(LinphoneCore *core, bool_t yesno);
/**
* Use to get multicast state of audio stream.
* @param core the core
* @return true if subsequent calls propose multicast ip set by #linphone_core_set_audio_multicast_addr
* @ingroup media_parameters
**/
LINPHONE_PUBLIC bool_t linphone_core_audio_multicast_enabled(const LinphoneCore *core);
/**
* Use to enable multicast rtp for video stream.
* @param core the core
* @param yesno if yes, subsequent calls propose multicast ip set by #linphone_core_set_video_multicast_addr
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_core_enable_video_multicast(LinphoneCore *core, bool_t yesno);
/**
* Use to get multicast state of video stream.
* @param core the core
* @return true if subsequent calls propose multicast ip set by #linphone_core_set_audio_multicast_addr
* @ingroup media_parameters
**/
LINPHONE_PUBLIC bool_t linphone_core_video_multicast_enabled(const LinphoneCore *core);
#ifdef __cplusplus
}
#endif
......
......@@ -296,9 +296,81 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
SalStreamDescription *result){
if (remote_answer->rtp_port!=0)
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
else {
ms_message("Local stream description [%p] rejected by peer",local_offer);
result->rtp_port=0;
return;
}
result->proto=remote_answer->proto;
result->type=local_offer->type;
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
if (ms_is_multicast(local_offer->rtp_addr)) {
/*6.2 Multicast Streams
...
If a multicast stream is accepted, the address and port information
in the answer MUST match that of the offer. Similarly, the
directionality information in the answer (sendonly, recvonly, or
sendrecv) MUST equal that of the offer. This is because all
participants in a multicast session need to have equivalent views of
the parameters of the session, an underlying assumption of the
multicast bias of RFC 2327.*/
if (strcmp(local_offer->rtp_addr,remote_answer->rtp_addr) !=0 ) {
ms_message("Remote answered IP [%s] does not match offered [%s] for local stream description [%p]"
,remote_answer->rtp_addr
,local_offer->rtp_addr
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->rtp_port!=remote_answer->rtp_port) {
ms_message("Remote answered rtp port [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->rtp_port
,local_offer->rtp_port
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->dir!=remote_answer->dir) {
ms_message("Remote answered dir [%s] does not match offered [%s] for local stream description [%p]"
,sal_stream_dir_to_string(remote_answer->dir)
,sal_stream_dir_to_string(local_offer->dir)
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->bandwidth!=remote_answer->bandwidth) {
ms_message("Remote answered bandwidth [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->bandwidth
,local_offer->bandwidth
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->ptime > 0 && local_offer->ptime!=remote_answer->ptime) {
ms_message("Remote answered ptime [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->ptime
,local_offer->ptime
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->ttl > 0 && local_offer->ttl!=remote_answer->ttl) {
ms_message("Remote answered ttl [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->ttl
,local_offer->ttl
,local_offer);
result->rtp_port=0;
return;
}
result->ttl=local_offer->ttl;
result->dir=local_offer->dir;
result->multicast_role = SalMulticastRoleSender;
} else {
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
}
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->rtp_addr,remote_answer->rtp_addr);
......@@ -328,16 +400,34 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec);
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->rtp_port!=0 || remote_offer->rtp_port==SalStreamSendOnly)){
if (!result->payloads || only_telephone_event(result->payloads) || remote_offer->rtp_port==0 || remote_offer->rtp_port==SalStreamSendOnly){
result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir);
result->rtp_port=0;
return;
}
if (ms_is_multicast(remote_offer->rtp_addr)) {
if (sal_stream_description_has_srtp(result) == TRUE) {
ms_message("SAVP not supported for multicast address for remote stream [%p]",remote_offer);
result->rtp_port=0;
return;
}
result->dir=remote_offer->dir;
strcpy(result->rtp_addr,remote_offer->rtp_addr);
strcpy(result->rtcp_addr,remote_offer->rtcp_addr);
result->rtp_port=remote_offer->rtp_port;
/*result->rtcp_port=remote_offer->rtcp_port;*/
result->rtcp_port=0; /* rtcp not supported yet*/
result->bandwidth=remote_offer->bandwidth;
result->ptime=remote_offer->ptime;
result->ttl=remote_offer->ttl;
result->multicast_role = SalMulticastRoleReceiver;
} else {
strcpy(result->rtp_addr,local_cap->rtp_addr);
strcpy(result->rtcp_addr,local_cap->rtcp_addr);
result->rtp_port=local_cap->rtp_port;
result->rtcp_port=local_cap->rtcp_port;
result->bandwidth=local_cap->bandwidth;
result->ptime=local_cap->ptime;
}else{
result->rtp_port=0;
}
if (sal_stream_description_has_srtp(result) == TRUE) {
/* select crypto algo */
......@@ -358,6 +448,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
}
/**
* Returns a media description to run the streams with, based on a local offer
* and the returned response (remote).
......
......@@ -1796,6 +1796,8 @@ void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presen
return;
}
xmlTextWriterSetIndent(writer,1);
err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
if (err >= 0) {
err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"presence", (const xmlChar *)"urn:ietf:params:xml:ns:pidf");
......
......@@ -79,6 +79,7 @@ extern "C" {
#endif
#endif
struct _LinphoneCallParams{
belle_sip_object_t base;
void *user_data;
......@@ -105,6 +106,9 @@ struct _LinphoneCallParams{
bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/
uint16_t avpf_rr_interval; /*in milliseconds*/
LinphonePrivacyMask privacy;
LinphoneCallParamsMediaDirection audio_dir;
LinphoneCallParamsMediaDirection video_dir;
};
BELLE_SIP_DECLARE_VPTR(LinphoneCallParams);
......@@ -217,6 +221,8 @@ struct _LinphoneCall{
SalOp *op;
SalOp *ping_op;
char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
char local_audio_ip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call or what proposed in sdp in case of multicast*/
char local_video_ip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call or what proposed in sdp in case of multicast*/
LinphoneCallState state;
LinphoneCallState prevstate;
LinphoneCallState transfer_state; /*idle if no transfer*/
......@@ -589,6 +595,12 @@ typedef struct rtp_config
bool_t audio_adaptive_jitt_comp_enabled;
bool_t video_adaptive_jitt_comp_enabled;
bool_t pad;
char* audio_multicast_addr;
bool_t audio_multicast_enabled;
int audio_multicast_ttl;
char* video_multicast_addr;
int video_multicast_ttl;
bool_t video_multicast_enabled;
}rtp_config_t;
......
......@@ -196,6 +196,14 @@ typedef enum {
SalDtlsRoleUnset
} SalDtlsRole;
typedef enum {
SalMulticastInative=0,
SalMulticastRoleSender,
SalMulticastRoleReceiver,
SalMulticastSenderReceiver
} SalMulticastRole;