forked from mirrors/linphone-iphone
Redesign ICE integration to prevent Sal from depending on ICE.
- Move the ICE session from the Sal Op to the LinphoneCall. - Do not access directly to the ICE session to generate the SDP from the media description or to generate the media description from the SDP. Instead include ICE attributes in the media description.
This commit is contained in:
parent
93db3330b6
commit
6f2853c8a0
10 changed files with 187 additions and 311 deletions
|
|
@ -187,7 +187,7 @@ static void call_received(SalOp *h){
|
|||
linphone_core_add_call(lc,call);
|
||||
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
|
||||
|
||||
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && sal_op_get_ice_session(call->op)) {
|
||||
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;
|
||||
|
|
@ -254,7 +254,6 @@ static void call_ringing(SalOp *h){
|
|||
static void call_accepted(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
IceSession *ice_session=sal_op_get_ice_session(op);
|
||||
SalMediaDescription *md;
|
||||
|
||||
if (call==NULL){
|
||||
|
|
@ -262,7 +261,7 @@ static void call_accepted(SalOp *op){
|
|||
return ;
|
||||
}
|
||||
|
||||
if (ice_session == NULL) {
|
||||
if (call->ice_session == NULL) {
|
||||
/* Ensure the ICE check list pointers for the call streams are resetted to prevent crashes */
|
||||
if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL;
|
||||
if (call->videostream != NULL) call->videostream->ice_check_list = NULL;
|
||||
|
|
|
|||
|
|
@ -201,7 +201,6 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
LinphoneAddress *addr=linphone_address_new(me);
|
||||
const char *username=linphone_address_get_username (addr);
|
||||
SalMediaDescription *md=sal_media_description_new();
|
||||
IceSession *ice_session=sal_op_get_ice_session(call->op);
|
||||
|
||||
md->session_id=session_id;
|
||||
md->session_ver=session_ver;
|
||||
|
|
@ -249,8 +248,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
|
|||
md->streams[i].crypto[2].algo = 0;
|
||||
}
|
||||
if ((call->dir == LinphoneCallOutgoing) && (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce)
|
||||
&& (ice_session != NULL) && (ice_session_check_list(ice_session, i) == NULL)) {
|
||||
ice_session_add_check_list(ice_session, ice_check_list_new());
|
||||
&& (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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -346,8 +345,8 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
|
|||
linphone_call_init_common(call,from,to);
|
||||
call->params=*params;
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
|
||||
sal_op_set_ice_session(call->op, ice_session_new());
|
||||
ice_session_set_role(sal_op_get_ice_session(call->op), IR_Controlling);
|
||||
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;
|
||||
|
|
@ -403,9 +402,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
linphone_core_run_stun_tests(call->core,call);
|
||||
/* No break to also destroy ice session in this case. */
|
||||
default:
|
||||
if (sal_op_get_ice_session(call->op) != NULL) {
|
||||
linphone_call_delete_ice_session(call);
|
||||
}
|
||||
linphone_call_delete_ice_session(call);
|
||||
break;
|
||||
}
|
||||
discover_mtu(lc,linphone_address_get_domain(from));
|
||||
|
|
@ -552,11 +549,10 @@ void linphone_call_enable_video(LinphoneCall *call, bool_t enabled)
|
|||
{
|
||||
LinphoneCore *lc=linphone_call_get_core(call);
|
||||
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
|
||||
IceSession *ice_session=sal_op_get_ice_session(call->op);
|
||||
|
||||
linphone_call_params_enable_video(params, enabled);
|
||||
if (enabled == TRUE) {
|
||||
if (ice_session != NULL) {
|
||||
if (call->ice_session != NULL) {
|
||||
/* Defer call update until the ICE candidates gathering process has finished. */
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
call->params = *params;
|
||||
|
|
@ -572,8 +568,8 @@ void linphone_call_enable_video(LinphoneCall *call, bool_t enabled)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if ((ice_session != NULL) && (call->videostream != NULL)) {
|
||||
ice_session_remove_check_list(ice_session, call->videostream->ice_check_list);
|
||||
if ((call->ice_session != NULL) && (call->videostream != NULL)) {
|
||||
ice_session_remove_check_list(call->ice_session, call->videostream->ice_check_list);
|
||||
call->videostream->ice_check_list = NULL;
|
||||
}
|
||||
if (linphone_call_get_state(call) == LinphoneCallUpdatedByRemote) {
|
||||
|
|
@ -610,6 +606,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);
|
||||
}
|
||||
|
|
@ -971,7 +970,6 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
LinphoneCore *lc=call->core;
|
||||
SalMediaDescription *md=call->localdesc;
|
||||
AudioStream *audiostream;
|
||||
IceSession *ice_session = sal_op_get_ice_session(call->op);
|
||||
|
||||
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)){
|
||||
|
|
@ -1004,9 +1002,9 @@ void linphone_call_init_audio_stream(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) && (ice_session != NULL)){
|
||||
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
rtp_session_set_pktinfo(audiostream->session, TRUE);
|
||||
audiostream->ice_check_list = ice_session_check_list(ice_session, 0);
|
||||
audiostream->ice_check_list = ice_session_check_list(call->ice_session, 0);
|
||||
ice_check_list_set_rtp_session(audiostream->ice_check_list, audiostream->session);
|
||||
}
|
||||
|
||||
|
|
@ -1018,7 +1016,6 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=call->core;
|
||||
SalMediaDescription *md=call->localdesc;
|
||||
IceSession *ice_session = sal_op_get_ice_session(call->op);
|
||||
|
||||
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);
|
||||
|
|
@ -1034,9 +1031,9 @@ void linphone_call_init_video_stream(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) && (ice_session != NULL) && (ice_session_check_list(ice_session, 1))){
|
||||
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);
|
||||
call->videostream->ice_check_list = ice_session_check_list(ice_session, 1);
|
||||
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();
|
||||
|
|
@ -1495,8 +1492,8 @@ 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 ((sal_op_get_ice_session(call->op) != NULL) && (ice_session_state(sal_op_get_ice_session(call->op)) != IS_Completed)) {
|
||||
ice_session_start_connectivity_checks(sal_op_get_ice_session(call->op));
|
||||
if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed)) {
|
||||
ice_session_start_connectivity_checks(call->ice_session);
|
||||
}
|
||||
|
||||
goto end;
|
||||
|
|
@ -1513,10 +1510,9 @@ void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call){
|
|||
}
|
||||
|
||||
void linphone_call_delete_ice_session(LinphoneCall *call){
|
||||
IceSession *ice_session = sal_op_get_ice_session(call->op);
|
||||
if (ice_session != NULL) {
|
||||
ice_session_destroy(ice_session);
|
||||
sal_op_set_ice_session(call->op, NULL);
|
||||
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;
|
||||
}
|
||||
|
|
@ -1739,19 +1735,18 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
|
||||
if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
|
||||
if (ice_session_role(sal_op_get_ice_session(call->op)) == IR_Controlling) {
|
||||
if (ice_session_role(call->ice_session) == IR_Controlling) {
|
||||
linphone_core_update_call(call->core, call, &call->current_params);
|
||||
}
|
||||
} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
|
||||
IceSession *ice_session = sal_op_get_ice_session(call->op);
|
||||
LinphoneCallParams *params;
|
||||
switch (call->state) {
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
if (evd->info.ice_processing_successful==TRUE) {
|
||||
ice_session_compute_candidates_foundations(ice_session);
|
||||
ice_session_eliminate_redundant_candidates(ice_session);
|
||||
ice_session_choose_default_candidates(ice_session);
|
||||
ice_session_compute_candidates_foundations(call->ice_session);
|
||||
ice_session_eliminate_redundant_candidates(call->ice_session);
|
||||
ice_session_choose_default_candidates(call->ice_session);
|
||||
}
|
||||
params = linphone_call_params_copy(linphone_call_get_current_params(call));
|
||||
linphone_call_params_enable_video(params, TRUE);
|
||||
|
|
@ -1766,9 +1761,9 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
default:
|
||||
linphone_call_stop_media_streams(call);
|
||||
if (evd->info.ice_processing_successful==TRUE) {
|
||||
ice_session_compute_candidates_foundations(ice_session);
|
||||
ice_session_eliminate_redundant_candidates(ice_session);
|
||||
ice_session_choose_default_candidates(ice_session);
|
||||
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);
|
||||
}
|
||||
|
|
@ -1808,7 +1803,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
|
|||
OrtpEvent *ev;
|
||||
|
||||
/* Ensure there is no dangling ICE check list. */
|
||||
if (sal_op_get_ice_session(call->op) == NULL) call->videostream->ice_check_list = NULL;
|
||||
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.
|
||||
|
|
@ -1846,7 +1841,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
|
|||
OrtpEvent *ev;
|
||||
|
||||
/* Ensure there is no dangling ICE check list. */
|
||||
if (sal_op_get_ice_session(call->op) == NULL) call->audiostream->ice_check_list = NULL;
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -1852,7 +1852,7 @@ 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 (sal_op_get_ice_session(call->op) != NULL) {
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -569,12 +569,11 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
|
|||
socklen_t ss_len;
|
||||
IceCheckList *audio_check_list;
|
||||
IceCheckList *video_check_list;
|
||||
IceSession *ice_session = sal_op_get_ice_session(call->op);
|
||||
const char *server = linphone_core_get_stun_server(lc);
|
||||
|
||||
if ((server == NULL) || (ice_session == NULL)) return -1;
|
||||
audio_check_list = ice_session_check_list(ice_session, 0);
|
||||
video_check_list = ice_session_check_list(ice_session, 1);
|
||||
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){
|
||||
|
|
@ -602,7 +601,7 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
|
|||
}
|
||||
|
||||
/* Gather local srflx candidates. */
|
||||
ice_session_gather_candidates(ice_session, ss, ss_len);
|
||||
ice_session_gather_candidates(call->ice_session, ss, ss_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ struct _LinphoneCall
|
|||
bool_t was_automatically_paused;
|
||||
CallCallbackObj nextVideoFrameDecoded;
|
||||
LinphoneCallStats stats[2];
|
||||
IceSession *ice_session;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -234,10 +234,6 @@ void sal_op_set_user_pointer(SalOp *op, void *up){
|
|||
((SalOpBase*)op)->user_pointer=up;
|
||||
}
|
||||
|
||||
void sal_op_set_ice_session(SalOp *op, IceSession *ice_session){
|
||||
((SalOpBase*)op)->ice_session=ice_session;
|
||||
}
|
||||
|
||||
Sal *sal_op_get_sal(const SalOp *op){
|
||||
return ((SalOpBase*)op)->root;
|
||||
}
|
||||
|
|
@ -266,10 +262,6 @@ void *sal_op_get_user_pointer(const SalOp *op){
|
|||
return ((SalOpBase*)op)->user_pointer;
|
||||
}
|
||||
|
||||
IceSession *sal_op_get_ice_session(const SalOp *op){
|
||||
return ((SalOpBase*)op)->ice_session;
|
||||
}
|
||||
|
||||
const char *sal_op_get_proxy(const SalOp *op){
|
||||
return ((SalOpBase*)op)->route;
|
||||
}
|
||||
|
|
@ -318,8 +310,6 @@ void __sal_op_free(SalOp *op){
|
|||
sal_media_description_unref(b->local_media);
|
||||
if (b->remote_media)
|
||||
sal_media_description_unref(b->remote_media);
|
||||
if (b->ice_session)
|
||||
ice_session_destroy(b->ice_session);
|
||||
ms_free(op);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define sal_h
|
||||
|
||||
#include "mediastreamer2/mscommon.h"
|
||||
#include "mediastreamer2/ice.h"
|
||||
#include "ortp/ortp_srtp.h"
|
||||
|
||||
/*Dirty hack, keep in sync with mediastreamer2/include/mediastream.h */
|
||||
|
|
@ -113,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;
|
||||
|
|
@ -138,6 +164,11 @@ 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;
|
||||
} SalStreamDescription;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
|
||||
|
|
@ -151,10 +182,13 @@ 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
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES 10
|
||||
|
||||
SalMediaDescription *sal_media_description_new();
|
||||
void sal_media_description_ref(SalMediaDescription *md);
|
||||
|
|
@ -177,7 +211,6 @@ typedef struct SalOpBase{
|
|||
char *remote_ua;
|
||||
SalMediaDescription *local_media;
|
||||
SalMediaDescription *remote_media;
|
||||
IceSession *ice_session;
|
||||
void *user_pointer;
|
||||
} SalOpBase;
|
||||
|
||||
|
|
@ -322,7 +355,6 @@ void sal_op_release(SalOp *h);
|
|||
void sal_op_authenticate(SalOp *h, const SalAuthInfo *info);
|
||||
void sal_op_cancel_authentication(SalOp *h);
|
||||
void sal_op_set_user_pointer(SalOp *h, void *up);
|
||||
void sal_op_set_ice_session(SalOp *h, IceSession *ice_session);
|
||||
int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **username);
|
||||
const char *sal_op_get_from(const SalOp *op);
|
||||
const char *sal_op_get_to(const SalOp *op);
|
||||
|
|
@ -334,7 +366,6 @@ const char *sal_op_get_network_origin(const SalOp *op);
|
|||
/*returns far-end "User-Agent" string */
|
||||
const char *sal_op_get_remote_ua(const SalOp *op);
|
||||
void *sal_op_get_user_pointer(const SalOp *op);
|
||||
IceSession *sal_op_get_ice_session(const SalOp *op);
|
||||
|
||||
/*Call API*/
|
||||
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
|
||||
|
|
|
|||
|
|
@ -502,8 +502,8 @@ static void set_sdp(osip_message_t *sip,sdp_message_t *msg){
|
|||
osip_free(sdp);
|
||||
}
|
||||
|
||||
static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc, const IceSession *ice_session){
|
||||
sdp_message_t *msg=media_description_to_sdp(desc, ice_session);
|
||||
static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc){
|
||||
sdp_message_t *msg=media_description_to_sdp(desc);
|
||||
if (msg==NULL) {
|
||||
ms_error("Fail to print sdp message !");
|
||||
return;
|
||||
|
|
@ -526,7 +526,7 @@ static void sdp_process(SalOp *h){
|
|||
sdp_message_free(h->sdp_answer);
|
||||
}
|
||||
offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec);
|
||||
h->sdp_answer=media_description_to_sdp(h->result, sal_op_get_ice_session(h));
|
||||
h->sdp_answer=media_description_to_sdp(h->result);
|
||||
/*once we have generated the SDP answer, we modify the result description for processing by the upper layer.
|
||||
It should contains media parameters constraint from the remote offer, not our response*/
|
||||
strcpy(h->result->addr,h->base.remote_media->addr);
|
||||
|
|
@ -600,7 +600,7 @@ int sal_call(SalOp *h, const char *from, const char *to){
|
|||
}
|
||||
if (h->base.local_media){
|
||||
h->sdp_offering=TRUE;
|
||||
set_sdp_from_desc(invite,h->base.local_media,sal_op_get_ice_session(h));
|
||||
set_sdp_from_desc(invite,h->base.local_media);
|
||||
}else h->sdp_offering=FALSE;
|
||||
if (h->replaces){
|
||||
osip_message_set_header(invite,"Replaces",h->replaces);
|
||||
|
|
@ -668,7 +668,7 @@ int sal_call_accept(SalOp * h){
|
|||
if (h->base.local_media){
|
||||
/*this is the case where we received an invite without SDP*/
|
||||
if (h->sdp_offering) {
|
||||
set_sdp_from_desc(msg,h->base.local_media,sal_op_get_ice_session(h));
|
||||
set_sdp_from_desc(msg,h->base.local_media);
|
||||
}else{
|
||||
if (h->sdp_answer==NULL) sdp_process(h);
|
||||
if (h->sdp_answer){
|
||||
|
|
@ -990,7 +990,6 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
|
|||
osip_call_info_t *call_info;
|
||||
char *tmp;
|
||||
sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
|
||||
IceSession *ice_session;
|
||||
|
||||
set_network_origin(op,ev->request);
|
||||
set_remote_ua(op,ev->request);
|
||||
|
|
@ -999,9 +998,7 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
|
|||
if (sdp){
|
||||
op->sdp_offering=FALSE;
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
ice_session=sal_op_get_ice_session(op);
|
||||
sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
|
||||
sal_op_set_ice_session(op,ice_session);
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_message_free(sdp);
|
||||
}else op->sdp_offering=TRUE;
|
||||
|
||||
|
|
@ -1037,7 +1034,6 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
|
|||
static void handle_reinvite(Sal *sal, eXosip_event_t *ev){
|
||||
SalOp *op=find_op(sal,ev);
|
||||
sdp_message_t *sdp;
|
||||
IceSession *ice_session;
|
||||
|
||||
if (op==NULL) {
|
||||
ms_warning("Reinvite for non-existing operation !");
|
||||
|
|
@ -1057,9 +1053,7 @@ static void handle_reinvite(Sal *sal, eXosip_event_t *ev){
|
|||
if (sdp){
|
||||
op->sdp_offering=FALSE;
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
ice_session=sal_op_get_ice_session(op);
|
||||
sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
|
||||
sal_op_set_ice_session(op,ice_session);
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_message_free(sdp);
|
||||
|
||||
}else {
|
||||
|
|
@ -1071,7 +1065,6 @@ static void handle_reinvite(Sal *sal, eXosip_event_t *ev){
|
|||
static void handle_ack(Sal *sal, eXosip_event_t *ev){
|
||||
SalOp *op=find_op(sal,ev);
|
||||
sdp_message_t *sdp;
|
||||
IceSession *ice_session;
|
||||
|
||||
if (op==NULL) {
|
||||
ms_warning("ack for non-existing call !");
|
||||
|
|
@ -1088,9 +1081,7 @@ static void handle_ack(Sal *sal, eXosip_event_t *ev){
|
|||
if (op->base.remote_media)
|
||||
sal_media_description_unref(op->base.remote_media);
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
ice_session=sal_op_get_ice_session(op);
|
||||
sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
|
||||
sal_op_set_ice_session(op,ice_session);
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_process(op);
|
||||
sdp_message_free(sdp);
|
||||
}
|
||||
|
|
@ -1150,16 +1141,13 @@ static int call_proceeding(Sal *sal, eXosip_event_t *ev){
|
|||
static void call_ringing(Sal *sal, eXosip_event_t *ev){
|
||||
sdp_message_t *sdp;
|
||||
SalOp *op=find_op(sal,ev);
|
||||
IceSession *ice_session;
|
||||
if (call_proceeding(sal, ev)==-1) return;
|
||||
|
||||
set_remote_ua(op,ev->response);
|
||||
sdp=eXosip_get_sdp_info(ev->response);
|
||||
if (sdp){
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
ice_session=sal_op_get_ice_session(op);
|
||||
sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
|
||||
sal_op_set_ice_session(op,ice_session);
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_message_free(sdp);
|
||||
if (op->base.local_media) sdp_process(op);
|
||||
}
|
||||
|
|
@ -1171,7 +1159,6 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){
|
|||
osip_message_t *msg=NULL;
|
||||
SalOp *op=find_op(sal,ev);
|
||||
const char *contact;
|
||||
IceSession *ice_session;
|
||||
|
||||
if (op==NULL || op->terminated==TRUE) {
|
||||
ms_warning("This call has been already terminated.");
|
||||
|
|
@ -1187,9 +1174,7 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){
|
|||
sdp=eXosip_get_sdp_info(ev->response);
|
||||
if (sdp){
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
ice_session=sal_op_get_ice_session(op);
|
||||
sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
|
||||
sal_op_set_ice_session(op,ice_session);
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_message_free(sdp);
|
||||
if (op->base.local_media) sdp_process(op);
|
||||
}
|
||||
|
|
@ -2427,7 +2412,7 @@ int sal_call_update(SalOp *h, const char *subject){
|
|||
}
|
||||
if (h->base.local_media){
|
||||
h->sdp_offering=TRUE;
|
||||
set_sdp_from_desc(reinvite,h->base.local_media,sal_op_get_ice_session(h));
|
||||
set_sdp_from_desc(reinvite,h->base.local_media);
|
||||
}else h->sdp_offering=FALSE;
|
||||
eXosip_lock();
|
||||
err = eXosip_call_send_request(h->did, reinvite);
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
|
||||
|
||||
sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal, const IceSession *ice_session);
|
||||
int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc, IceSession **ice_session);
|
||||
sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal);
|
||||
int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
|
||||
|
||||
struct Sal{
|
||||
SalCallbacks callbacks;
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ static int _sdp_message_get_mline_dir(sdp_message_t *sdp, int mline){
|
|||
return SalStreamSendRecv;
|
||||
}
|
||||
|
||||
static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const IceSession *ice_session)
|
||||
static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
|
||||
{
|
||||
sdp_message_t *local;
|
||||
int inet6;
|
||||
|
|
@ -144,14 +144,6 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const
|
|||
osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr));
|
||||
sdp_message_s_name_set (local, osip_strdup ("Talk"));
|
||||
if ((ice_session != NULL) && (ice_session_check_list(ice_session, 0) != NULL)) {
|
||||
if (ice_session_state(ice_session) == IS_Completed) {
|
||||
ice_check_list_nominated_valid_local_candidate(ice_session_check_list(ice_session, 0), &rtp_addr, NULL, NULL, NULL);
|
||||
}
|
||||
else {
|
||||
ice_check_list_default_local_candidate(ice_session_check_list(ice_session, 0), &rtp_addr, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
if(!sal_media_description_has_dir (desc,SalStreamSendOnly))
|
||||
{
|
||||
sdp_message_c_connection_add (local, -1,
|
||||
|
|
@ -167,23 +159,9 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const
|
|||
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 ((ice_session != NULL) && (ice_session_check_list(ice_session, 0) != NULL)) {
|
||||
char buffer[512];
|
||||
switch (ice_session_state(ice_session)) {
|
||||
case IS_Completed:
|
||||
sdp_message_a_attribute_add(local, -1, osip_strdup("nortpproxy"), osip_strdup("yes"));
|
||||
/* No break to also include the ice-ufrag and ice-pwd attributes when ICE session is completed. */
|
||||
case IS_Running:
|
||||
case IS_Stopped:
|
||||
snprintf(buffer, sizeof(buffer), "%s", ice_session_local_pwd(ice_session));
|
||||
sdp_message_a_attribute_add(local, -1, osip_strdup("ice-pwd"), osip_strdup(buffer));
|
||||
snprintf(buffer, sizeof(buffer), "%s", ice_session_local_ufrag(ice_session));
|
||||
sdp_message_a_attribute_add(local, -1, osip_strdup("ice-ufrag"), osip_strdup(buffer));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
@ -224,83 +202,57 @@ static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt, boo
|
|||
}
|
||||
}
|
||||
|
||||
static void add_candidate_attribute(sdp_message_t *msg, int lineno, const IceCandidate *candidate)
|
||||
static void add_ice_candidates(sdp_message_t *msg, int lineno, const SalStreamDescription *desc)
|
||||
{
|
||||
char buffer[1024];
|
||||
const SalIceCandidate *candidate;
|
||||
int nb;
|
||||
int i;
|
||||
|
||||
nb = snprintf(buffer, sizeof(buffer), "%s %d UDP %d %s %d typ %s",
|
||||
candidate->foundation, candidate->componentID, candidate->priority, candidate->taddr.ip, candidate->taddr.port, ice_candidate_type(candidate));
|
||||
if (nb < 0) {
|
||||
ms_error("Cannot add ICE candidate attribute!");
|
||||
return;
|
||||
}
|
||||
if (candidate->type != ICT_HostCandidate) {
|
||||
nb = snprintf(buffer + nb, sizeof(buffer) - nb, " raddr %s rport %d", candidate->base->taddr.ip, candidate->base->taddr.port);
|
||||
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;
|
||||
}
|
||||
}
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("candidate"), osip_strdup(buffer));
|
||||
}
|
||||
|
||||
static void add_ice_candidates(sdp_message_t *msg, int lineno, const IceCheckList *ice_cl, const char *rtp_addr, int rtp_port, const char *rtcp_addr, int rtcp_port)
|
||||
{
|
||||
const IceCandidate *candidate;
|
||||
int i;
|
||||
|
||||
if ((ice_check_list_state(ice_cl) == ICL_Failed) && ice_check_list_is_mismatch(ice_cl)) {
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-mismatch"), NULL);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < ms_list_size(ice_cl->local_candidates); i++) {
|
||||
candidate = ms_list_nth_data(ice_cl->local_candidates, i);
|
||||
switch (ice_check_list_state(ice_cl)) {
|
||||
case ICL_Running:
|
||||
add_candidate_attribute(msg, lineno, candidate);
|
||||
break;
|
||||
case ICL_Completed:
|
||||
/* Only include the candidates matching the default destination for each component of the stream as specified in RFC5245 section 9.1.2.2. */
|
||||
if (((candidate->taddr.port == rtp_port) && (strlen(candidate->taddr.ip) == strlen(rtp_addr)) && (strcmp(candidate->taddr.ip, rtp_addr) == 0))
|
||||
|| ((candidate->taddr.port == rtcp_port) && (strlen(candidate->taddr.ip) == strlen(rtcp_addr)) && (strcmp(candidate->taddr.ip, rtcp_addr) == 0))) {
|
||||
add_candidate_attribute(msg, lineno, candidate);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void add_ice_remote_candidates(sdp_message_t *msg, int lineno, const IceCheckList *ice_cl)
|
||||
{
|
||||
char buffer[1024];
|
||||
const char *rtp_addr = NULL;
|
||||
const char *rtcp_addr = NULL;
|
||||
int rtp_port;
|
||||
int rtcp_port;
|
||||
int nb;
|
||||
|
||||
if ((ice_session_role(ice_cl->session) == IR_Controlling) && (ice_check_list_state(ice_cl) == ICL_Completed)) {
|
||||
ice_check_list_nominated_valid_remote_candidate(ice_cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
|
||||
nb = snprintf(buffer, sizeof(buffer), "1 %s %d", rtp_addr, rtp_port);
|
||||
if (nb < 0) {
|
||||
ms_error("Cannot add ICE remote-candidates attribute!");
|
||||
return;
|
||||
}
|
||||
if (rtcp_addr != NULL) {
|
||||
nb = snprintf(buffer + nb, sizeof(buffer) - nb, " 2 %s %d", rtcp_addr, rtcp_port);
|
||||
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 remote-candidates attribute!");
|
||||
ms_error("Cannot add ICE candidate attribute!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("remote-candidates"), osip_strdup(buffer));
|
||||
sdp_message_a_attribute_add(msg, lineno, osip_strdup("candidate"), osip_strdup(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc, const IceCheckList *ice_cl){
|
||||
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 *rtp_addr;
|
||||
|
|
@ -309,6 +261,7 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
int rtp_port;
|
||||
int rtcp_port;
|
||||
bool_t strip_well_known_rtpmaps;
|
||||
bool_t different_rtp_and_rtcp_addr;
|
||||
|
||||
switch (desc->type) {
|
||||
case SalAudio:
|
||||
|
|
@ -321,16 +274,11 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
mt=desc->typeother;
|
||||
break;
|
||||
}
|
||||
rtp_addr=rtcp_addr=desc->rtp_addr;
|
||||
rtp_addr=desc->rtp_addr;
|
||||
rtcp_addr=desc->rtcp_addr;
|
||||
rtp_port=desc->rtp_port;
|
||||
rtcp_port=desc->rtcp_port;
|
||||
if (ice_cl != NULL) {
|
||||
if (ice_check_list_state(ice_cl) == ICL_Completed) {
|
||||
ice_check_list_nominated_valid_local_candidate(ice_cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
|
||||
} else {
|
||||
ice_check_list_default_local_candidate(ice_cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
|
||||
}
|
||||
} else if (desc->candidates[0].addr[0]!='\0'){
|
||||
if (desc->candidates[0].addr[0]!='\0'){
|
||||
rtp_addr=desc->candidates[0].addr;
|
||||
rtp_port=desc->candidates[0].port;
|
||||
}
|
||||
|
|
@ -417,28 +365,34 @@ 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 (ice_cl != NULL) {
|
||||
if (strcmp(rtp_addr, rtcp_addr) != 0) {
|
||||
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 (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));
|
||||
}
|
||||
}
|
||||
add_ice_candidates(msg, lineno, ice_cl, rtp_addr, rtp_port, rtcp_addr, rtcp_port);
|
||||
add_ice_remote_candidates(msg, lineno, ice_cl);
|
||||
}
|
||||
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, const IceSession *ice_session){
|
||||
IceCheckList *ice_cl = NULL;
|
||||
sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
|
||||
int i;
|
||||
sdp_message_t *msg=create_generic_sdp(desc, ice_session);
|
||||
sdp_message_t *msg=create_generic_sdp(desc);
|
||||
for(i=0;i<desc->nstreams;++i){
|
||||
if (ice_session != NULL) ice_cl = ice_session_check_list(ice_session, i);
|
||||
else ice_cl = NULL;
|
||||
add_line(msg,i,&desc->streams[i], ice_cl);
|
||||
add_line(msg,i,&desc->streams[i]);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
|
@ -474,15 +428,12 @@ static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceSession **ice_session){
|
||||
int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
||||
int i,j;
|
||||
const char *mtype,*proto,*rtp_port,*rtp_addr,*number;
|
||||
const char *ice_ufrag, *ice_pwd, *ice_remote_candidates=NULL;
|
||||
sdp_bandwidth_t *sbw=NULL;
|
||||
sdp_attribute_t *attr;
|
||||
int media_attribute_nb;
|
||||
bool_t ice_session_just_created = FALSE;
|
||||
bool_t ice_lite = FALSE;
|
||||
int nb_ice_candidates;
|
||||
|
||||
rtp_addr=sdp_message_c_addr_get (msg, -1, 0);
|
||||
if (rtp_addr)
|
||||
|
|
@ -491,10 +442,22 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
|
|||
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);
|
||||
|
|
@ -527,7 +490,6 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
|
|||
if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
|
||||
}
|
||||
stream->dir=_sdp_message_get_mline_dir(msg,i);
|
||||
media_attribute_nb = 0;
|
||||
/* for each payload type */
|
||||
for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
|
||||
const char *rtpmap,*fmtp;
|
||||
|
|
@ -536,11 +498,9 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
|
|||
payload_type_set_number(pt,ptn);
|
||||
/* get the rtpmap associated to this codec, if any */
|
||||
rtpmap=sdp_message_a_attr_value_get_with_pt(msg, i,ptn,"rtpmap");
|
||||
if (rtpmap != NULL) media_attribute_nb++;
|
||||
if (payload_type_fill_from_rtpmap(pt,rtpmap)==0){
|
||||
/* get the fmtp, if any */
|
||||
fmtp=sdp_message_a_attr_value_get_with_pt(msg, i, ptn,"fmtp");
|
||||
if (fmtp != NULL) media_attribute_nb++;
|
||||
payload_type_set_send_fmtp(pt,fmtp);
|
||||
stream->payloads=ms_list_append(stream->payloads,pt);
|
||||
ms_message("Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
|
||||
|
|
@ -608,121 +568,37 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
|
|||
}
|
||||
|
||||
/* Get ICE candidate attributes if any */
|
||||
ice_ufrag = ice_pwd = NULL;
|
||||
for (j = 0; (j < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES) && ((attr = sdp_message_attribute_get(msg, i, media_attribute_nb + j)) != NULL); j++) {
|
||||
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)) {
|
||||
char ip[64];
|
||||
char foundation[32];
|
||||
char type[6];
|
||||
unsigned int priority;
|
||||
unsigned int componentID;
|
||||
unsigned int port;
|
||||
int nb;
|
||||
|
||||
/* Allocate the ICE session if it has not been done yet. */
|
||||
if (*ice_session == NULL) {
|
||||
*ice_session = ice_session_new();
|
||||
ice_session_just_created = TRUE;
|
||||
}
|
||||
/* Allocate the ICE check list if it has not been done yet. */
|
||||
if (ice_session_check_list(*ice_session, i) == NULL) {
|
||||
ice_session_add_check_list(*ice_session, ice_check_list_new());
|
||||
}
|
||||
nb = sscanf(attr->a_att_value, "%s %u UDP %u %s %u typ %s",
|
||||
foundation, &componentID, &priority, ip, &port, type);
|
||||
if (nb == 6) {
|
||||
char *default_ip = desc->addr;
|
||||
unsigned int default_port = stream->rtp_port;
|
||||
bool_t is_default_candidate = FALSE;
|
||||
if (componentID == 1) {
|
||||
if ((stream->rtp_addr == NULL) || (stream->rtp_addr[0] == '\0')) default_ip = desc->addr;
|
||||
else default_ip = stream->rtp_addr;
|
||||
default_port = stream->rtp_port;
|
||||
} else if (componentID == 2) {
|
||||
if ((stream->rtcp_addr == NULL) || (stream->rtcp_addr[0] == '\0')) default_ip = desc->addr;
|
||||
else default_ip = stream->rtcp_addr;
|
||||
default_port = stream->rtcp_port;
|
||||
}
|
||||
if ((port == default_port) && (strlen(ip) == strlen(default_ip)) && (strcmp(ip, default_ip) == 0)) is_default_candidate = TRUE;
|
||||
ice_add_remote_candidate(ice_session_check_list(*ice_session, i), type, ip, port, componentID, priority, foundation, is_default_candidate);
|
||||
}
|
||||
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)) {
|
||||
ice_remote_candidates = attr->a_att_value;
|
||||
} else if ((keywordcmp("ice-ufrag", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
ice_ufrag = attr->a_att_value;
|
||||
} else if ((keywordcmp("ice-pwd", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
ice_pwd = attr->a_att_value;
|
||||
} else if (keywordcmp("ice-mismatch", attr->a_att_field) == 0) {
|
||||
ice_check_list_set_state(ice_session_check_list(*ice_session, i), ICL_Failed);
|
||||
}
|
||||
}
|
||||
if ((*ice_session != NULL) && ice_session_check_list(*ice_session, i)) {
|
||||
if (ice_remote_candidates != NULL) {
|
||||
char ip[64];
|
||||
unsigned int port;
|
||||
SalIceRemoteCandidate candidate;
|
||||
unsigned int componentID;
|
||||
int offset;
|
||||
|
||||
while (3 == sscanf(ice_remote_candidates, "%u %s %u%n", &componentID, ip, &port, &offset)) {
|
||||
if (componentID == 1) {
|
||||
if ((stream->rtp_addr == NULL) || (stream->rtp_addr[0] == '\0')) rtp_addr = desc->addr;
|
||||
else rtp_addr = stream->rtp_addr;
|
||||
ice_add_losing_pair(ice_session_check_list(*ice_session, i), componentID, ip, port, rtp_addr, stream->rtp_port);
|
||||
} else if (componentID == 2) {
|
||||
if ((stream->rtcp_addr == NULL) || (stream->rtcp_addr[0] == '\0')) rtp_addr = desc->addr;
|
||||
else rtp_addr = stream->rtcp_addr;
|
||||
ice_add_losing_pair(ice_session_check_list(*ice_session, i), componentID, ip, port, rtp_addr, stream->rtcp_port);
|
||||
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;
|
||||
}
|
||||
ice_remote_candidates += offset;
|
||||
if (ice_remote_candidates[offset] == ' ') ice_remote_candidates += 1;
|
||||
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;
|
||||
}
|
||||
if ((ice_ufrag != NULL) && (ice_pwd != NULL)) {
|
||||
ice_check_list_set_remote_credentials(ice_session_check_list(*ice_session, i), ice_ufrag, ice_pwd);
|
||||
}
|
||||
if (stream->rtp_port == 0) {
|
||||
/* This stream has been deactivated by the peer, delete the check list. */
|
||||
ice_session_remove_check_list(*ice_session, ice_session_check_list(*ice_session, i));
|
||||
}
|
||||
ice_dump_candidates(ice_session_check_list(*ice_session, i));
|
||||
}
|
||||
}
|
||||
desc->nstreams=i;
|
||||
|
||||
/* Get ICE remote ufrag and remote pwd */
|
||||
ice_ufrag = ice_pwd = NULL;
|
||||
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)) {
|
||||
ice_ufrag = attr->a_att_value;
|
||||
} else if ((keywordcmp("ice-pwd", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
|
||||
ice_pwd = attr->a_att_value;
|
||||
} else if (keywordcmp("ice-lite", attr->a_att_field) == 0) {
|
||||
ice_lite = TRUE;
|
||||
}
|
||||
}
|
||||
if (*ice_session != NULL) {
|
||||
int nb_check_lists;
|
||||
if (ice_session_just_created == TRUE) {
|
||||
if (ice_lite == TRUE) {
|
||||
ice_session_set_role(*ice_session, IR_Controlling);
|
||||
} else {
|
||||
ice_session_set_role(*ice_session, IR_Controlled);
|
||||
}
|
||||
ice_session_check_mismatch(*ice_session);
|
||||
}
|
||||
while ((nb_check_lists = ice_session_nb_check_lists(*ice_session)) > desc->nstreams) {
|
||||
ice_session_remove_check_list(*ice_session, ice_session_check_list(*ice_session, nb_check_lists - 1));
|
||||
}
|
||||
if ((ice_ufrag != NULL) && (ice_pwd != NULL)) {
|
||||
ice_session_set_remote_credentials(*ice_session, ice_ufrag, ice_pwd);
|
||||
ice_dump_session(*ice_session);
|
||||
}
|
||||
if (((ice_session_just_created == FALSE) && ((ice_ufrag == NULL) || (ice_pwd == NULL)))
|
||||
|| (ice_session_state(*ice_session) == IS_Failed)) {
|
||||
/* We started with ICE activated but the peer apparently do not support ICE, so stop using it. */
|
||||
ice_session_destroy(*ice_session);
|
||||
*ice_session = NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue