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;
md->streams[i].crypto[1].algo = 0;
md->streams[i].crypto[2].algo = 0;
}
- if ((call->dir == LinphoneCallOutgoing) && (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce)){
- md->streams[i].ice_check_list = ice_check_list_new();
- ice_session_add_check_list(call->ice_session, md->streams[i].ice_check_list);
- }
- if ((call->dir == LinphoneCallIncoming) && (sal_call_get_remote_media_description(call->op)->streams[i].ice_check_list != NULL)) {
- md->streams[i].ice_check_list = sal_call_get_remote_media_description(call->op)->streams[i].ice_check_list;
+ if ((call->dir == LinphoneCallOutgoing) && (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (ice_session != NULL)){
+ ice_session_add_check_list(ice_session, ice_check_list_new());
}
}
- if ((call->dir == LinphoneCallIncoming) && (md->streams[0].ice_check_list != NULL)) {
- call->ice_session=md->streams[0].ice_check_list->session;
- }
linphone_address_destroy(addr);
return md;
linphone_call_init_common(call,from,to);
call->params=*params;
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
- call->ice_session=ice_session_new();
- ice_session_set_role(call->ice_session, IR_Controlling);
+ sal_op_set_ice_session(call->op, ice_session_new());
+ ice_session_set_role(sal_op_get_ice_session(call->op), IR_Controlling);
}
call->localdesc=create_local_media_description (lc,call);
call->camera_active=params->has_video;
sal_op_release(obj->op);
obj->op=NULL;
}
- if (obj->ice_session!=NULL) {
- ice_session_destroy(obj->ice_session);
- obj->ice_session=NULL;
- }
if (obj->resultdesc!=NULL) {
sal_media_description_unref(obj->resultdesc);
obj->resultdesc=NULL;
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].port,linphone_core_ipv6_enabled(lc));
if (linphone_core_echo_limiter_enabled(lc)){
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){
- rtp_session_set_pktinfo(audiostream->session,TRUE);
- if (call->dir == LinphoneCallOutgoing) audiostream->ice_check_list = call->localdesc->streams[0].ice_check_list;
- else audiostream->ice_check_list = sal_call_get_remote_media_description(call->op)->streams[0].ice_check_list;
+ if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (ice_session != NULL)){
+ rtp_session_set_pktinfo(audiostream->session, TRUE);
+ audiostream->ice_check_list = ice_session_check_list(ice_session, 0);
ice_check_list_register_success_cb(audiostream->ice_check_list, audio_stream_set_remote_from_ice, audiostream);
}
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){
- rtp_session_set_pktinfo(call->videostream->session,TRUE);
- if (call->dir == LinphoneCallOutgoing) call->videostream->ice_check_list = call->localdesc->streams[1].ice_check_list;
- else call->videostream->ice_check_list = sal_call_get_remote_media_description(call->op)->streams[1].ice_check_list;
+ if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (ice_session != NULL)){
+ rtp_session_set_pktinfo(call->videostream->session, TRUE);
+ call->videostream->ice_check_list = ice_session_check_list(ice_session, 1);
ice_check_list_register_success_cb(call->videostream->ice_check_list, video_stream_set_remote_from_ice, call->videostream);
}
call->videostream_app_evq = ortp_ev_queue_new();
/*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_pair_candidates(sal_op_get_ice_session(call->op));
goto end;
end:
IceCandidate *video_ice_bases[2];
IceCheckList *audio_check_list;
IceCheckList *video_check_list;
+ IceSession *ice_session = sal_op_get_ice_session(call->op);
struct sockaddr_storage ss;
socklen_t ss_len;
struct timeval init, cur;
int loops = 0;
const char *server = linphone_core_get_stun_server(lc);
- if (server == NULL) return;
+ if ((server == NULL) || (ice_session == NULL)) return;
+ audio_check_list = ice_session_check_list(ice_session, 0);
+ video_check_list = ice_session_check_list(ice_session, 1);
+ if (audio_check_list == NULL) return;
+
if (lc->sip_conf.ipv6_enabled){
ms_warning("stun support is not implemented for ipv6");
return;
video_responses[0] = video_responses[1] = FALSE;
audio_ice_bases[0] = audio_ice_bases[1] = NULL;
video_ice_bases[0] = video_ice_bases[1] = NULL;
- audio_check_list = call->localdesc->streams[0].ice_check_list;
- video_check_list = call->localdesc->streams[1].ice_check_list;
audio_socks[0] = create_socket(call->audio_port);
if (audio_socks[0] == -1) return;
audio_socks[1] = create_socket(call->audio_port + 1);
}
audio_ice_bases[0] = ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port, 1, NULL);
audio_ice_bases[1] = ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port + 1, 2, NULL);
- if (call->params.has_video) {
+ if (call->params.has_video && (video_check_list != NULL)) {
video_ice_bases[0] = ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port, 1, NULL);
video_ice_bases[1] = ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port + 1, 2, NULL);
}
ice_add_local_candidate(audio_check_list, "srflx", addr, port, 2, audio_ice_bases[1]);
audio_responses[1] = TRUE;
}
- if (call->params.has_video) {
+ if (call->params.has_video && (video_check_list != NULL)) {
if (recvStunResponse(video_socks[0], addr, &port, &id) > 0) {
ice_add_local_candidate(video_check_list, "srflx", addr, port, 1, video_ice_bases[0]);
video_responses[0] = TRUE;
} while (!((audio_responses[0] == TRUE) && (audio_responses[1] == TRUE)
&& (!call->params.has_video || ((video_responses[0] == TRUE) && (video_responses[1] == TRUE)))));
- ice_session_compute_candidates_foundations(call->ice_session);
- ice_session_choose_default_candidates(call->ice_session);
+ ice_session_compute_candidates_foundations(ice_session);
+ ice_session_choose_default_candidates(ice_session);
close_socket(audio_socks[0]);
close_socket(audio_socks[1]);
ice_dump_candidates(audio_check_list);
- if (call->params.has_video) {
+ if (call->params.has_video && (video_check_list != NULL)) {
if (video_socks[0] != -1) close_socket(video_socks[0]);
if (video_socks[1] != -1) close_socket(video_socks[1]);
ice_dump_candidates(video_check_list);
if (!match_crypto_algo(local_offer->crypto, remote_answer->crypto, &result->crypto[0], &result->crypto_local_tag, FALSE))
result->port = 0;
}
- result->ice_check_list = remote_answer->ice_check_list;
}
result->port = 0;
}
- result->ice_check_list = local_cap->ice_check_list;
}
/**
if (rs->type==SalOther){
strncpy(result->streams[i].typeother,rs->typeother,sizeof(rs->typeother)-1);
}
- result->streams[i].ice_check_list = remote_offer->streams[i].ice_check_list;
}
}
result->nstreams=i;
bool_t was_automatically_paused;
CallCallbackObj nextVideoFrameDecoded;
LinphoneCallStats stats[2];
- IceSession *ice_session;
};
((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;
}
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;
}
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);
}
SalSrtpCryptoAlgo crypto[SAL_CRYPTO_ALGO_MAX];
unsigned int crypto_local_tag;
int max_rate;
- IceCheckList *ice_check_list;
} SalStreamDescription;
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
char *remote_ua;
SalMediaDescription *local_media;
SalMediaDescription *remote_media;
+ IceSession *ice_session;
void *user_pointer;
} SalOpBase;
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);
/*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);
osip_free(sdp);
}
-static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc){
- sdp_message_t *msg=media_description_to_sdp(desc);
+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);
if (msg==NULL) {
ms_error("Fail to print sdp message !");
return;
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);
+ h->sdp_answer=media_description_to_sdp(h->result, sal_op_get_ice_session(h));
/*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);
}
if (h->base.local_media){
h->sdp_offering=TRUE;
- set_sdp_from_desc(invite,h->base.local_media);
+ set_sdp_from_desc(invite,h->base.local_media,sal_op_get_ice_session(h));
}else h->sdp_offering=FALSE;
if (h->replaces){
osip_message_set_header(invite,"Replaces",h->replaces);
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);
+ set_sdp_from_desc(msg,h->base.local_media,sal_op_get_ice_session(h));
}else{
if (h->sdp_answer==NULL) sdp_process(h);
if (h->sdp_answer){
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);
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
- sdp_to_media_description(sdp,op->base.remote_media);
+ 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_message_free(sdp);
}else op->sdp_offering=TRUE;
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 !");
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
- sdp_to_media_description(sdp,op->base.remote_media);
+ 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_message_free(sdp);
}else {
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 !");
if (op->base.remote_media)
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=sal_media_description_new();
- sdp_to_media_description(sdp,op->base.remote_media);
+ 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_process(op);
sdp_message_free(sdp);
}
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();
- sdp_to_media_description(sdp,op->base.remote_media);
+ 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_message_free(sdp);
if (op->base.local_media) sdp_process(op);
}
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.");
sdp=eXosip_get_sdp_info(ev->response);
if (sdp){
op->base.remote_media=sal_media_description_new();
- sdp_to_media_description(sdp,op->base.remote_media);
+ 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_message_free(sdp);
if (op->base.local_media) sdp_process(op);
}
}
if (h->base.local_media){
h->sdp_offering=TRUE;
- set_sdp_from_desc(reinvite,h->base.local_media);
+ set_sdp_from_desc(reinvite,h->base.local_media,sal_op_get_ice_session(h));
}else h->sdp_offering=FALSE;
eXosip_lock();
err = eXosip_call_send_request(h->did, reinvite);
-sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal);
-int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
+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);
struct Sal{
SalCallbacks callbacks;
return SalStreamSendRecv;
}
-static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
+static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const IceSession *ice_session)
{
sdp_message_t *local;
int inet6;
osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
osip_strdup (desc->addr));
sdp_message_s_name_set (local, osip_strdup ("Talk"));
- if (desc->streams[0].ice_check_list != NULL) {
- const IceCandidate *candidate = ice_check_list_default_local_candidate(desc->streams[0].ice_check_list);
+ if ((ice_session != NULL) && (ice_session_check_list(ice_session, 0) != NULL)) {
+ const IceCandidate *candidate = ice_check_list_default_local_candidate(ice_session_check_list(ice_session, 0));
if (candidate != NULL) {
addr=candidate->taddr.ip;
}
sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
if (desc->bandwidth>0) sdp_message_b_bandwidth_add (local, -1, osip_strdup ("AS"),
int_2char(desc->bandwidth));
- if (desc->streams[0].ice_check_list != NULL) {
+ if ((ice_session != NULL) && (ice_session_check_list(ice_session, 0) != NULL)) {
char buffer[512];
- snprintf(buffer ,sizeof(buffer), "%s", ice_session_local_pwd(desc->streams[0].ice_check_list->session));
+ 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(desc->streams[0].ice_check_list->session));
+ 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));
}
}
}
-static void add_ice_candidates(sdp_message_t *msg, int lineno, const SalStreamDescription *desc)
+static void add_ice_candidates(sdp_message_t *msg, int lineno, const SalStreamDescription *desc, const IceCheckList *ice_cl)
{
char buffer[1024];
const IceCandidate *candidate;
int i;
- if (desc->ice_check_list != NULL) {
- for (i = 0; i < ms_list_size(desc->ice_check_list->local_candidates); i++) {
- candidate = ms_list_nth_data(desc->ice_check_list->local_candidates, i);
+ if (ice_cl != NULL) {
+ for (i = 0; i < ms_list_size(ice_cl->local_candidates); i++) {
+ candidate = ms_list_nth_data(ice_cl->local_candidates, i);
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));
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){
+static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc, const IceCheckList *ice_cl){
const char *mt=NULL;
const MSList *elem;
const char *addr;
}
addr=desc->addr;
port=desc->port;
- if (desc->ice_check_list != NULL) {
- const IceCandidate *candidate = ice_check_list_default_local_candidate(desc->ice_check_list);
+ if (ice_cl != NULL) {
+ const IceCandidate *candidate = ice_check_list_default_local_candidate(ice_cl);
if (candidate != NULL) {
addr=candidate->taddr.ip;
port=candidate->taddr.port;
break;
}
if (dir) sdp_message_a_attribute_add (msg, lineno, osip_strdup (dir),NULL);
- add_ice_candidates(msg, lineno, desc);
+ add_ice_candidates(msg, lineno, desc, ice_cl);
}
-sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
+sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc, const IceSession *ice_session){
+ IceCheckList *ice_cl = NULL;
int i;
- sdp_message_t *msg=create_generic_sdp(desc);
+ sdp_message_t *msg=create_generic_sdp(desc, ice_session);
for(i=0;i<desc->nstreams;++i){
- add_line(msg,i,&desc->streams[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);
}
return msg;
}
return 0;
}
-int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
+int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceSession **ice_session){
int i,j;
const char *mtype,*proto,*port,*addr,*number;
const char *ice_ufrag, *ice_pwd;
- IceSession *ice_session = NULL;
sdp_bandwidth_t *sbw=NULL;
sdp_attribute_t *attr;
int media_attribute_nb;
int nb;
/* Allocate the ICE session if it has not been done yet. */
- if (ice_session == NULL) ice_session = ice_session_new();
+ if (*ice_session == NULL) *ice_session = ice_session_new();
/* Allocate the ICE check list if it has not been done yet. */
- if (desc->streams[i].ice_check_list == NULL) {
- desc->streams[i].ice_check_list = ice_check_list_new();
- ice_session_add_check_list(ice_session, desc->streams[i].ice_check_list);
+ 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) {
- ice_add_remote_candidate(desc->streams[i].ice_check_list, type, ip, port, componentID, priority, foundation);
+ ice_add_remote_candidate(ice_session_check_list(*ice_session, i), type, ip, port, componentID, priority, foundation);
}
} else if ((keywordcmp("ice-ufrag", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
ice_ufrag = attr->a_att_value;
ice_pwd = attr->a_att_value;
}
}
- if ((ice_ufrag != NULL) && (ice_pwd != NULL)) {
- ice_check_list_set_remote_credentials(desc->streams[i].ice_check_list, ice_ufrag, ice_pwd);
+ if ((*ice_session != NULL) && ice_session_check_list(*ice_session, i)) {
+ if ((ice_ufrag != NULL) && (ice_pwd != NULL)) {
+ ice_check_list_set_remote_credentials(ice_session_check_list(*ice_session, i), ice_ufrag, ice_pwd);
+ }
+ ice_dump_candidates(ice_session_check_list(*ice_session, i));
}
- if (desc->streams[i].ice_check_list) ice_dump_candidates(desc->streams[i].ice_check_list);
}
/* Get ICE remote ufrag and remote pwd */
ice_ufrag = ice_pwd = NULL;
ice_lite = TRUE;
}
}
- if (ice_session != NULL) {
+ if (*ice_session != NULL) {
if (ice_lite == TRUE) {
- ice_session_set_role(ice_session, IR_Controlling);
+ ice_session_set_role(*ice_session, IR_Controlling);
} else {
- ice_session_set_role(ice_session, IR_Controlled);
+ ice_session_set_role(*ice_session, IR_Controlled);
}
if ((ice_ufrag != NULL) && (ice_pwd != NULL)) {
- ice_session_set_remote_credentials(ice_session, ice_ufrag, ice_pwd);
- ice_dump_session(ice_session);
+ ice_session_set_remote_credentials(*ice_session, ice_ufrag, ice_pwd);
+ ice_dump_session(*ice_session);
}
}
desc->nstreams=i;