linphonecall.c 140 KB
Newer Older
1 2 3

/*
linphone
4
Copyright (C) 2010  Belledonne Communications SARL
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 (simon.morlat@linphone.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
21 22 23
#ifdef WIN32
#include <time.h>
#endif
24 25 26 27
#include "linphonecore.h"
#include "sipsetup.h"
#include "lpconfig.h"
#include "private.h"
28
#include <ortp/event.h>
29
#include <ortp/b64.h>
Yann Diorcet's avatar
Yann Diorcet committed
30
#include <math.h>
31

32 33 34
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/msvolume.h"
#include "mediastreamer2/msequalizer.h"
35
#include "mediastreamer2/msfileplayer.h"
36
#include "mediastreamer2/msjpegwriter.h"
37
#include "mediastreamer2/mseventqueue.h"
38
#include "mediastreamer2/mssndcard.h"
39

40
static const char EC_STATE_STORE[] = ".linphone.ecstate";
41
#define EC_STATE_MAX_LEN 1048576 // 1Mo
42

Simon Morlat's avatar
Simon Morlat committed
43 44
static void linphone_call_stats_uninit(LinphoneCallStats *stats);

Simon Morlat's avatar
Simon Morlat committed
45
#ifdef VIDEO_ENABLED
46 47 48
static MSWebCam *get_nowebcam_device(){
	return ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"StaticImage: Static picture");
}
Simon Morlat's avatar
Simon Morlat committed
49
#endif
50

51
static bool_t generate_b64_crypto_key(int key_length, char* key_out, size_t key_out_size) {
52
	int b64_size;
53 54
	uint8_t* tmp = (uint8_t*) ms_malloc0(key_length);
	if (sal_get_random_bytes(tmp, key_length)==NULL) {
55
		ms_error("Failed to generate random key");
56
		ms_free(tmp);
57 58
		return FALSE;
	}
59

60
	b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
61 62 63 64 65 66 67 68 69 70 71
	if (b64_size == 0) {
		ms_error("Failed to get b64 result size");
		ms_free(tmp);
		return FALSE;
	}
	if (b64_size>=key_out_size){
		ms_error("Insufficient room for writing base64 SRTP key");
		ms_free(tmp);
		return FALSE;
	}
	b64_size=b64_encode((const char*)tmp, key_length, key_out, key_out_size);
72 73
	if (b64_size == 0) {
		ms_error("Failed to b64 encode key");
74
		ms_free(tmp);
75 76 77
		return FALSE;
	}
	key_out[b64_size] = '\0';
78
	ms_free(tmp);
79 80 81
	return TRUE;
}

82 83 84 85
LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
	return call->core;
}

86
const char* linphone_call_get_authentication_token(LinphoneCall *call){
87
	return call->auth_token;
88 89
}

90 91 92 93 94 95 96 97
/**
 * Returns whether ZRTP authentication token is verified.
 * If not, it must be verified by users as described in ZRTP procedure.
 * Once done, the application must inform of the results with linphone_call_set_authentication_token_verified().
 * @param call the LinphoneCall
 * @return TRUE if authentication token is verifed, false otherwise.
 * @ingroup call_control
**/
98
bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){
99
	return call->auth_token_verified;
100
}
Simon Morlat's avatar
Simon Morlat committed
101

102
static bool_t linphone_call_all_streams_encrypted(const LinphoneCall *call) {
jehan's avatar
jehan committed
103 104 105 106 107
	int number_of_encrypted_stream = 0;
	int number_of_active_stream = 0;
	if (call) {
		if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
			number_of_active_stream++;
108
			if(media_stream_secured((MediaStream *)call->audiostream))
jehan's avatar
jehan committed
109 110 111 112
				number_of_encrypted_stream++;
		}
		if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
			number_of_active_stream++;
113
			if (media_stream_secured((MediaStream *)call->videostream))
jehan's avatar
jehan committed
114
				number_of_encrypted_stream++;
115
		}
116
	}
117
	return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream;
118 119
}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
static bool_t linphone_call_all_streams_avpf_enabled(const LinphoneCall *call) {
	int nb_active_streams = 0;
	int nb_avpf_enabled_streams = 0;
	if (call) {
		if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
			nb_active_streams++;
			if (media_stream_avpf_enabled((MediaStream *)call->audiostream))
				nb_avpf_enabled_streams++;
		}
		if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
			nb_active_streams++;
			if (media_stream_avpf_enabled((MediaStream *)call->videostream))
				nb_avpf_enabled_streams++;
		}
	}
	return ((nb_active_streams > 0) && (nb_active_streams == nb_avpf_enabled_streams));
}

138 139 140
static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) {
	uint16_t rr_interval = 0;
	uint16_t stream_rr_interval;
141 142 143 144 145 146 147 148 149 150
	if (call) {
		if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
			stream_rr_interval = media_stream_get_avpf_rr_interval((MediaStream *)call->audiostream);
			if (stream_rr_interval > rr_interval) rr_interval = stream_rr_interval;
		}
		if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
			stream_rr_interval = media_stream_get_avpf_rr_interval((MediaStream *)call->videostream);
			if (stream_rr_interval > rr_interval) rr_interval = stream_rr_interval;
		}
	} else {
151
		rr_interval = 5000;
152 153 154 155
	}
	return rr_interval;
}

156
static void propagate_encryption_changed(LinphoneCall *call){
157
	if (!linphone_call_all_streams_encrypted(call)) {
158
		ms_message("Some streams are not encrypted");
159
		call->current_params->media_encryption=LinphoneMediaEncryptionNone;
160
		linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token);
161
	} else {
johan's avatar
johan committed
162 163 164 165 166
		if (call->auth_token) {/* ZRTP only is using auth_token */
			call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
		} else { /* otherwise it must be DTLS as SDES doesn't go through this function */
			call->current_params->media_encryption=LinphoneMediaEncryptionDTLS;
		}
167
		ms_message("All streams are encrypted key exchanged using %s", call->current_params->media_encryption==LinphoneMediaEncryptionZRTP?"ZRTP":call->current_params->media_encryption==LinphoneMediaEncryptionDTLS?"DTLS":"Unknown mechanism");
168
		linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token);
169 170 171 172
	}
}

static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) {
173
	char status[255]={0};
Sylvain Berfini's avatar
Sylvain Berfini committed
174
	LinphoneCall *call;
175

Sylvain Berfini's avatar
Sylvain Berfini committed
176
	call = (LinphoneCall *)data;
177

178
	if (encrypted) {
johan's avatar
johan committed
179 180 181 182
		if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { /* if encryption is DTLS, no status to be displayed */
			snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
			linphone_core_notify_display_status(call->core, status);
		}
183 184
	}

185 186 187 188 189
	propagate_encryption_changed(call);


#ifdef VIDEO_ENABLED
	// Enable video encryption
190 191 192
	{
		const LinphoneCallParams *params=linphone_call_get_current_params(call);
		if (params->has_video) {
193
			MSZrtpParams params;
194 195 196 197
			ms_message("Trying to enable encryption on video stream");
			params.zid_file=NULL; //unused
			video_stream_enable_zrtp(call->videostream,call->audiostream,&params);
		}
198 199 200 201 202 203 204
	}
#endif
}


static void linphone_call_audiostream_auth_token_ready(void *data, const char* auth_token, bool_t verified) {
	LinphoneCall *call=(LinphoneCall *)data;
205 206
	if (call->auth_token != NULL)
		ms_free(call->auth_token);
207

208 209
	call->auth_token=ms_strdup(auth_token);
	call->auth_token_verified=verified;
210 211 212 213

	ms_message("Authentication token is %s (%s)", auth_token, verified?"verified":"unverified");
}

214 215 216 217 218 219 220
/**
 * Set the result of ZRTP short code verification by user.
 * If remote party also does the same, it will update the ZRTP cache so that user's verification will not be required for the two users.
 * @param call the LinphoneCall
 * @param verified whether the ZRTP SAS is verified.
 * @ingroup call_control
**/
Simon Morlat's avatar
Simon Morlat committed
221 222 223 224
void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified){
	if (call->audiostream==NULL){
		ms_error("linphone_call_set_authentication_token_verified(): No audio stream");
	}
225
	if (call->audiostream->ms.sessions.zrtp_context==NULL){
Simon Morlat's avatar
Simon Morlat committed
226 227 228
		ms_error("linphone_call_set_authentication_token_verified(): No zrtp context.");
	}
	if (!call->auth_token_verified && verified){
229
		ms_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context);
Simon Morlat's avatar
Simon Morlat committed
230
	}else if (call->auth_token_verified && !verified){
231
		ms_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context);
Simon Morlat's avatar
Simon Morlat committed
232 233 234 235
	}
	call->auth_token_verified=verified;
	propagate_encryption_changed(call);
}
236

237 238
static int get_max_codec_sample_rate(const MSList *codecs){
	int max_sample_rate=0;
239 240 241
	const MSList *it;
	for(it=codecs;it!=NULL;it=it->next){
		PayloadType *pt=(PayloadType*)it->data;
242 243 244 245 246 247 248 249 250 251
		int sample_rate;
		
		if( strcasecmp("G722",pt->mime_type) == 0 ){
			/* G722 spec says 8000 but the codec actually requires 16000 */
			sample_rate = 16000;
		}else sample_rate=pt->clock_rate;
		if (sample_rate>max_sample_rate) max_sample_rate=sample_rate;
	}
	return max_sample_rate;
}
252

253 254 255 256 257 258 259 260 261 262 263 264
static int find_payload_type_number(const MSList *assigned, const PayloadType *pt){
	const MSList *elem;
	const PayloadType *candidate=NULL;
	for(elem=assigned;elem!=NULL;elem=elem->next){
		const PayloadType *it=(const PayloadType*)elem->data;
		if ((strcasecmp(pt->mime_type, payload_type_get_mime(it)) == 0)
			&& (it->clock_rate==pt->clock_rate)
			&& (it->channels==pt->channels || pt->channels<=0)) {
			candidate=it;
			if ((it->recv_fmtp!=NULL && pt->recv_fmtp!=NULL && strcasecmp(it->recv_fmtp, pt->recv_fmtp)==0)
				|| (it->recv_fmtp==NULL && pt->recv_fmtp==NULL)){
				break;/*exact match*/
265
			}
266 267 268 269 270 271 272 273 274 275 276 277 278
		}
	}
	return candidate ? payload_type_get_number(candidate) : -1;
}

bool_t is_payload_type_number_available(const MSList *l, int number, const PayloadType *ignore){
	const MSList *elem;
	for (elem=l; elem!=NULL; elem=elem->next){
		const PayloadType *pt=(PayloadType*)elem->data;
		if (pt!=ignore && payload_type_get_number(pt)==number) return FALSE;
	}
	return TRUE;
}
279

280 281 282 283 284 285 286 287 288 289 290 291
static void linphone_core_assign_payload_type_numbers(LinphoneCore *lc, MSList *codecs){
	MSList *elem;
	int dyn_number=lc->codecs_conf.dyn_pt;
	for (elem=codecs; elem!=NULL; elem=elem->next){
		PayloadType *pt=(PayloadType*)elem->data;
		int number=payload_type_get_number(pt);
		
		/*check if number is duplicated: it could be the case if the remote forced us to use a mapping with a previous offer*/
		if (number!=-1 && !(pt->flags & PAYLOAD_TYPE_FROZEN_NUMBER)){
			if (!is_payload_type_number_available(codecs, number, pt)){
				ms_message("Reassigning payload type %i %s/%i because already offered.", number, pt->mime_type, pt->clock_rate);
				number=-1; /*need to be re-assigned*/
292
			}
293 294 295 296 297 298 299 300 301 302 303 304 305 306
		}
		
		if (number==-1){
			while(dyn_number<127){
				if (is_payload_type_number_available(codecs, dyn_number, NULL)){
					payload_type_set_number(pt, dyn_number);
					dyn_number++;
					break;
				}
				dyn_number++;
			}
			if (dyn_number==127){
				ms_error("Too many payload types configured ! codec %s/%i is disabled.", pt->mime_type, pt->clock_rate);
				payload_type_set_enable(pt, FALSE);
307
			}
308 309
		}
	}
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
}

static bool_t has_telephone_event_at_rate(const MSList *tev, int rate){
	const MSList *it;
	for(it=tev;it!=NULL;it=it->next){
		const PayloadType *pt=(PayloadType*)it->data;
		if (pt->clock_rate==rate) return TRUE;
	}
	return FALSE;
}

static MSList * create_telephone_events(LinphoneCore *lc, const MSList *codecs){
	const MSList *it;
	MSList *ret=NULL;
	for(it=codecs;it!=NULL;it=it->next){
		const PayloadType *pt=(PayloadType*)it->data;
		if (!has_telephone_event_at_rate(ret,pt->clock_rate)){
			PayloadType *tev=payload_type_clone(&payload_type_telephone_event);
			tev->clock_rate=pt->clock_rate;
			/*let it choose the number dynamically as for normal codecs*/
			payload_type_set_number(tev, -1);
			if (ret==NULL){
				/*But for first telephone-event, prefer the number that was configured in the core*/
				if (is_payload_type_number_available(codecs, lc->codecs_conf.telephone_event_pt, NULL)){
					payload_type_set_number(tev, lc->codecs_conf.telephone_event_pt);
				}
336
			}
337 338 339 340 341 342
			ret=ms_list_append(ret,tev);
		}
	}
	return ret;
}

343 344 345 346 347 348 349 350 351 352
static MSList *create_special_payload_types(LinphoneCore *lc, const MSList *codecs){
	MSList *ret=create_telephone_events(lc, codecs);
	if (linphone_core_generic_confort_noise_enabled(lc)){
		PayloadType *cn=payload_type_clone(&payload_type_cn);
		payload_type_set_number(cn, 13);
		ret=ms_list_append(ret, cn);
	}
	return ret;
}

353 354 355 356 357 358
typedef struct _CodecConstraints{
	int bandwidth_limit;
	int max_codecs;
	MSList *previously_used;
}CodecConstraints;

359
static MSList *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalStreamType stype, const MSList *codecs){
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
	MSList *l=NULL;
	const MSList *it;
	int nb = 0;

	for(it=codecs;it!=NULL;it=it->next){
		PayloadType *pt=(PayloadType*)it->data;
		int num;
		
		if (!(pt->flags & PAYLOAD_TYPE_ENABLED))
			continue;
		if (hints->bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,hints->bandwidth_limit)){
			ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s",
					pt->mime_type,pt->clock_rate,hints->bandwidth_limit);
			continue;
		}
		if (!linphone_core_check_payload_type_usability(lc,pt)){
			continue;
		}
		pt=payload_type_clone(pt);
		
		/*look for a previously assigned number for this codec*/
		num=find_payload_type_number(hints->previously_used, pt);
		if (num!=-1){
			payload_type_set_number(pt,num);
			payload_type_set_flag(pt, PAYLOAD_TYPE_FROZEN_NUMBER);
385
		}
386 387 388 389
		
		l=ms_list_append(l, pt);
		nb++;
		if ((hints->max_codecs > 0) && (nb >= hints->max_codecs)) break;
390
	}
391 392 393 394
	if (stype==SalAudio){
		MSList *specials=create_special_payload_types(lc,l);
		l=ms_list_concat(l,specials);
	}
395
	linphone_core_assign_payload_type_numbers(lc, l);
396 397 398
	return l;
}

399
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
400
	int i;
401 402
	for (i = 0; i < md->nb_streams; i++) {
		if (!sal_stream_description_active(&md->streams[i])) continue;
403 404 405
		if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
			strcpy(md->streams[0].rtp_addr,ac->addr);
			md->streams[0].rtp_port=ac->port;
406
			if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || sal_media_description_get_nb_active_streams(md)==1){
407 408 409 410 411 412
				strcpy(md->addr,ac->addr);
			}
		}
		if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
			strcpy(md->streams[1].rtp_addr,vc->addr);
			md->streams[1].rtp_port=vc->port;
413 414 415 416
		}
	}
}

417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag){
	int keylen=0;
	crypto->tag=tag;
	crypto->algo=suite;
	switch(suite){
		case MS_AES_128_SHA1_80:
		case MS_AES_128_SHA1_32:
		case MS_AES_128_NO_AUTH:
		case MS_NO_CIPHER_SHA1_80: /*not sure for this one*/
			keylen=30;
		break;
		case MS_AES_256_SHA1_80:
		case MS_AES_256_SHA1_32:
			keylen=46;
		break;
		case MS_CRYPTO_SUITE_INVALID:
		break;
	}
	if (keylen==0 || !generate_b64_crypto_key(30, crypto->master_key, SAL_SRTP_KEY_SIZE)){
		ms_error("Could not generate SRTP key.");
		crypto->algo = 0;
		return -1;
	}
	return 0;
}
442 443 444 445 446 447 448 449 450 451 452
static void setup_dtls_keys(LinphoneCall *call, SalMediaDescription *md){
	int i;
	for(i=0; i<md->nb_streams; i++) {
		if (!sal_stream_description_active(&md->streams[i])) continue;
		/* if media encryption is set to DTLS check presence of fingerprint in the call which shall have been set at stream init but it may have failed when retrieving certificate resulting in no fingerprint present and then DTLS not usable */
		if (sal_stream_description_has_dtls(&md->streams[i]) == TRUE) {
			strncpy(md->streams[i].dtls_fingerprint, call->dtls_certificate_fingerprint, sizeof(md->streams[i].dtls_fingerprint)); /* get the self fingerprint from call(it's computed at stream init) */
			md->streams[i].dtls_role = SalDtlsRoleUnset; /* if we are offering, SDP will have actpass setup attribute when role is unset, if we are responding the result mediadescription will be set to SalDtlsRoleIsClient */
		} else {
			md->streams[i].dtls_fingerprint[0] = '\0';
			md->streams[i].dtls_role = SalDtlsRoleInvalid;
453

454 455 456 457
		}
	}

}
458 459
static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
	LinphoneCore *lc=call->core;
460
	int i,j;
461
	SalMediaDescription *old_md=call->localdesc;
462
	bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1);
463

464 465 466
	for(i=0; i<md->nb_streams; i++) {
		if (!sal_stream_description_active(&md->streams[i])) continue;
		if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) {
467
			if (keep_srtp_keys && old_md && (sal_stream_description_active(&old_md->streams[i]) == TRUE) && (sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE)) {
468 469 470 471 472 473
				int j;
				ms_message("Keeping same crypto keys.");
				for(j=0;j<SAL_CRYPTO_ALGO_MAX;++j){
					memcpy(&md->streams[i].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo));
				}
			}else{
474 475 476 477
				const MSCryptoSuite *suites=linphone_core_get_srtp_crypto_suites(lc);
				for(j=0;suites!=NULL && suites[j]!=MS_CRYPTO_SUITE_INVALID && j<SAL_CRYPTO_ALGO_MAX;++j){
					setup_encryption_key(&md->streams[i].crypto[j],suites[j],j+1);
				}
478 479 480 481 482
			}
		}
	}
}

483 484 485 486 487 488
static void setup_rtcp_fb(LinphoneCall *call, SalMediaDescription *md) {
	MSList *pt_it;
	PayloadType *pt;
	PayloadTypeAvpfParams avpf_params;
	int i;

489 490
	for (i = 0; i < md->nb_streams; i++) {
		if (!sal_stream_description_active(&md->streams[i])) continue;
491 492
		for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) {
			pt = (PayloadType *)pt_it->data;
493
			if (call->params->avpf_enabled == TRUE) {
494 495
				payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
				avpf_params = payload_type_get_avpf_params(pt);
496
				avpf_params.trr_interval = call->params->avpf_rr_interval;
497 498 499 500 501 502 503 504 505
			} else {
				payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
				memset(&avpf_params, 0, sizeof(avpf_params));
			}
			payload_type_set_avpf_params(pt, avpf_params);
		}
	}
}

506 507
static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) {
	LinphoneCore *lc = call->core;
508
	int i;
509

Simon Morlat's avatar
Simon Morlat committed
510
	md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1);
511
	if (md->rtcp_xr.enabled == TRUE) {
Simon Morlat's avatar
Simon Morlat committed
512
		const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all");
513 514 515 516
		if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll;
		else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender;
		else md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone;
		if (md->rtcp_xr.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) {
Simon Morlat's avatar
Simon Morlat committed
517
			md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000);
518
		}
Simon Morlat's avatar
Simon Morlat committed
519
		md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1);
520
		if (md->rtcp_xr.stat_summary_enabled == TRUE) {
521
			md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL;
522
		}
Simon Morlat's avatar
Simon Morlat committed
523
		md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1);
524
	}
525 526
	for (i = 0; i < md->nb_streams; i++) {
		if (!sal_stream_description_active(&md->streams[i])) continue;
527 528
		memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr));
	}
529 530
}

531 532 533 534 535
void linphone_call_increment_local_media_description(LinphoneCall *call){
	SalMediaDescription *md=call->localdesc;
	md->session_ver++;
}

536 537 538 539 540 541 542 543 544 545 546 547 548
void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call){
	if (call->ice_session != NULL) {
		_update_local_media_description_from_ice(call->localdesc, call->ice_session);
		linphone_core_update_ice_state_in_call_stats(call);
	}
#ifdef BUILD_UPNP
	if(call->upnp_session != NULL) {
		linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
		linphone_core_update_upnp_state_in_call_stats(call);
	}
#endif  //BUILD_UPNP
}

549 550 551 552 553 554 555 556
static void transfer_already_assigned_payload_types(SalMediaDescription *old, SalMediaDescription *md){
	int i;
	for(i=0;i<old->nb_streams;++i){
		md->streams[i].already_assigned_payloads=old->streams[i].already_assigned_payloads;
		old->streams[i].already_assigned_payloads=NULL;
	}
}

557 558
static const char *linphone_call_get_bind_ip_for_stream(LinphoneCall *call, int stream_index){
	const char *bind_ip=call->af==AF_INET6 ? "::0" : "0.0.0.0";
559

560 561
	if (stream_index<2 && call->media_ports[stream_index].multicast_ip[0]!='\0'){
		if (call->dir==LinphoneCallOutgoing){
562
			/*as multicast sender, we must decide a local interface to use to send multicast, and bind to it*/
563 564 565
			bind_ip=call->localip;
		}
	}
566 567 568
	return bind_ip;
}

569 570 571 572 573 574 575 576
static const char *linphone_call_get_public_ip_for_stream(LinphoneCall *call, int stream_index){
	const char *public_ip=call->localip;
	
	if (stream_index<2 && call->media_ports[stream_index].multicast_ip[0]!='\0') 
		public_ip=call->media_ports[stream_index].multicast_ip;
	return public_ip;
}

Simon Morlat's avatar
Simon Morlat committed
577
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
578
	MSList *l;
Simon Morlat's avatar
Simon Morlat committed
579
	SalMediaDescription *old_md=call->localdesc;
580
	int i;
581
	int nb_active_streams = 0;
582
	const char *me;
583
	SalMediaDescription *md=sal_media_description_new();
584
	LinphoneAddress *addr;
585 586 587
	const char *subject;
	CodecConstraints codec_hints={0};
	
jehan's avatar
jehan committed
588 589 590
	/*multicast is only set in case of outgoing call*/
	if (call->dir == LinphoneCallOutgoing && linphone_core_audio_multicast_enabled(lc)) {
		md->streams[0].ttl=linphone_core_get_audio_multicast_ttl(lc);
591 592
		md->streams[0].multicast_role = SalMulticastSender;
	}
jehan's avatar
jehan committed
593 594 595

	if (call->dir == LinphoneCallOutgoing && linphone_core_video_multicast_enabled(lc)) {
		md->streams[1].ttl=linphone_core_get_video_multicast_ttl(lc);
596 597
		md->streams[1].multicast_role = SalMulticastSender;
	}
jehan's avatar
jehan committed
598

599
	subject=linphone_call_params_get_session_name(call->params);
600

601
	linphone_core_adapt_to_network(lc,call->ping_time,call->params);
602

603 604
	if (call->dest_proxy)
		me=linphone_proxy_config_get_identity(call->dest_proxy);
605
	else
606 607
		me=linphone_core_get_identity(lc);
	addr=linphone_address_new(me);
608

Simon Morlat's avatar
Simon Morlat committed
609 610
	md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
	md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
611
	md->nb_streams=(call->biggestdesc ? call->biggestdesc->nb_streams : 1);
612

jehan's avatar
jehan committed
613
	strncpy(md->addr,call->localip,sizeof(md->addr));
614
	strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
Simon Morlat's avatar
Simon Morlat committed
615
	if (subject) strncpy(md->name,subject,sizeof(md->name));
616

617 618
	if (call->params->down_bw)
		md->bandwidth=call->params->down_bw;
619
	else md->bandwidth=linphone_core_get_download_bandwidth(lc);
620

621
	/*set audio capabilities */
622 623
	strncpy(md->streams[0].rtp_addr,linphone_call_get_public_ip_for_stream(call,0),sizeof(md->streams[0].rtp_addr));
	strncpy(md->streams[0].rtcp_addr,linphone_call_get_public_ip_for_stream(call,0),sizeof(md->streams[0].rtcp_addr));
624
	strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1);
625 626
	md->streams[0].rtp_port=call->media_ports[0].rtp_port;
	md->streams[0].rtcp_port=call->media_ports[0].rtcp_port;
627
	md->streams[0].proto=get_proto_from_call_params(call->params);
628
	md->streams[0].dir=get_audio_dir_from_call_params(call->params);
629
	md->streams[0].type=SalAudio;
630 631
	if (call->params->down_ptime)
		md->streams[0].ptime=call->params->down_ptime;
632
	else
633
		md->streams[0].ptime=linphone_core_get_download_ptime(lc);
634 635 636
	codec_hints.bandwidth_limit=call->params->audio_bw;
	codec_hints.max_codecs=-1;
	codec_hints.previously_used=old_md ? old_md->streams[0].already_assigned_payloads : NULL;
637
	l=make_codec_list(lc, &codec_hints, SalAudio, lc->codecs_conf.audio_codecs);
638
	md->streams[0].max_rate=get_max_codec_sample_rate(l);
639
	md->streams[0].payloads=l;
640 641 642 643 644 645 646 647
	if (call->audiostream && call->audiostream->ms.sessions.rtp_session) {
		char* me = linphone_address_as_string_uri_only(call->me);
		md->streams[0].rtp_ssrc=rtp_session_get_send_ssrc(call->audiostream->ms.sessions.rtp_session);
		strncpy(md->streams[0].rtcp_cname,me,sizeof(md->streams[0].rtcp_cname));
		ms_free(me);
	}
	else
		ms_warning("Cannot get audio local ssrc for call [%p]",call);
648
	nb_active_streams++;
649

650
	if (call->params->has_video){
651 652
		strncpy(md->streams[1].rtp_addr,linphone_call_get_public_ip_for_stream(call,1),sizeof(md->streams[1].rtp_addr));
		strncpy(md->streams[1].rtcp_addr,linphone_call_get_public_ip_for_stream(call,1),sizeof(md->streams[1].rtcp_addr));
653
		strncpy(md->streams[1].name,"Video",sizeof(md->streams[1].name)-1);
654 655
		md->streams[1].rtp_port=call->media_ports[1].rtp_port;
		md->streams[1].rtcp_port=call->media_ports[1].rtcp_port;
656
		md->streams[1].proto=md->streams[0].proto;
657
		md->streams[1].dir=get_video_dir_from_call_params(call->params);
658
		md->streams[1].type=SalVideo;
659 660 661
		codec_hints.bandwidth_limit=0;
		codec_hints.max_codecs=-1;
		codec_hints.previously_used=old_md ? old_md->streams[1].already_assigned_payloads : NULL;
662
		l=make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs);
663
		md->streams[1].payloads=l;
664 665 666 667 668 669 670 671
		if (call->videostream && call->videostream->ms.sessions.rtp_session) {
			char* me = linphone_address_as_string_uri_only(call->me);
			md->streams[0].rtp_ssrc=rtp_session_get_send_ssrc(call->videostream->ms.sessions.rtp_session);
			strncpy(md->streams[0].rtcp_cname,me,sizeof(md->streams[0].rtcp_cname));
			ms_free(me);
		}
		else
			ms_warning("Cannot get video local ssrc for call [%p]",call);
672
		nb_active_streams++;
673
	}
674 675 676

	if (md->nb_streams < nb_active_streams)
		md->nb_streams = nb_active_streams;
677 678

	/* Deactivate inactive streams. */
679
	for (i = nb_active_streams; i < md->nb_streams; i++) {
680 681
		md->streams[i].rtp_port = 0;
		md->streams[i].rtcp_port = 0;
682 683
		md->streams[i].proto = call->biggestdesc->streams[i].proto;
		md->streams[i].type = call->biggestdesc->streams[i].type;
684
		md->streams[i].dir = SalStreamInactive;
685 686 687
		codec_hints.bandwidth_limit=0;
		codec_hints.max_codecs=1;
		codec_hints.previously_used=NULL;
688
		l = make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs);
689 690
		md->streams[i].payloads = l;
	}
691
	setup_encryption_keys(call,md);
692
	setup_dtls_keys(call,md);
693
	setup_rtcp_fb(call, md);
694
	setup_rtcp_xr(call, md);
695

696
	update_media_description_from_stun(md,&call->ac,&call->vc);
Simon Morlat's avatar
Simon Morlat committed
697
	call->localdesc=md;
698 699
	linphone_call_update_local_media_description_from_ice_or_upnp(call);
	linphone_address_destroy(addr);
700
	if (old_md){
701
		transfer_already_assigned_payload_types(old_md,md);
702 703 704
		call->localdesc_changed=sal_media_description_equals(md,old_md);
		sal_media_description_unref(old_md);
	}
705 706
}

707
static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){
708 709
	int offset;
	MSList *elem;
710 711
	int tried_port;
	int existing_port;
712
	bool_t already_used=FALSE;
713

714
	for(offset=0;offset<100;offset+=2){
715
		tried_port=base_port+offset;
716 717 718
		already_used=FALSE;
		for(elem=lc->calls;elem!=NULL;elem=elem->next){
			LinphoneCall *call=(LinphoneCall*)elem->data;
719
			existing_port=call->media_ports[stream_index].rtp_port;
720
			if (existing_port==tried_port) {
721 722 723 724 725 726 727 728 729 730 731 732 733
				already_used=TRUE;
				break;
			}
		}
		if (!already_used) break;
	}
	if (offset==100){
		ms_error("Could not find any free port !");
		return -1;
	}
	return offset;
}

734
static int select_random_port(LinphoneCore *lc, int stream_index, int min_port, int max_port) {
735 736 737 738 739 740 741 742 743 744 745
	MSList *elem;
	int nb_tries;
	int tried_port = 0;
	int existing_port = 0;
	bool_t already_used = FALSE;

	tried_port = (rand() % (max_port - min_port) + min_port) & ~0x1;
	if (tried_port < min_port) tried_port = min_port + 2;
	for (nb_tries = 0; nb_tries < 100; nb_tries++) {
		for (elem = lc->calls; elem != NULL; elem = elem->next) {
			LinphoneCall *call = (LinphoneCall *)elem->data;
746
			existing_port=call->media_ports[stream_index].rtp_port;
747 748 749 750 751 752 753 754 755 756 757 758 759 760
			if (existing_port == tried_port) {
				already_used = TRUE;
				break;
			}
		}
		if (!already_used) break;
	}
	if (nb_tries == 100) {
		ms_error("Could not find any free port!");
		return -1;
	}
	return tried_port;
}

761 762 763 764 765 766
static void port_config_set_random(LinphoneCall *call, int stream_index){
	call->media_ports[stream_index].rtp_port=-1;
	call->media_ports[stream_index].rtcp_port=-1;
}

static void port_config_set(LinphoneCall *call, int stream_index, int min_port, int max_port){
767
	int port_offset;
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
	if (min_port>0 && max_port>0){
		if (min_port == max_port) {
			/* Used fixed RTP audio port. */
			port_offset=find_port_offset(call->core, stream_index, min_port);
			if (port_offset==-1) {
				port_config_set_random(call, stream_index);
				return;
			}
			call->media_ports[stream_index].rtp_port=min_port+port_offset;
		} else {
			/* Select random RTP audio port in the specified range. */
			call->media_ports[stream_index].rtp_port = select_random_port(call->core, stream_index, min_port, max_port);
		}
		call->media_ports[stream_index].rtcp_port=call->media_ports[stream_index].rtp_port+1;
	}else port_config_set_random(call,stream_index);
}

static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
786
	int min_port, max_port;
787
	ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version());
788
	call->state=LinphoneCallIdle;
789
	call->transfer_state = LinphoneCallIdle;
790
	call->log=linphone_call_log_new(call->dir, from, to);
791
	call->camera_enabled=TRUE;
792 793
	call->current_params = linphone_call_params_new();
	call->current_params->media_encryption=LinphoneMediaEncryptionNone;
johan's avatar
johan committed
794
	call->dtls_certificate_fingerprint = NULL;
jehan's avatar
jehan committed
795 796 797 798 799
	if (call->dir == LinphoneCallIncoming)
		call->me=to;
	 else
		call->me=from;
	linphone_address_ref(call->me);
800

801
	linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
802
	port_config_set(call,0,min_port,max_port);
803

804
	linphone_core_get_video_port_range(call->core, &min_port, &max_port);
805
	port_config_set(call,1,min_port,max_port);
806 807 808 809 810 811 812 813 814 815 816
	
	if (call->dir==LinphoneCallOutgoing){
		if ( linphone_core_audio_multicast_enabled(call->core)){
			strncpy(call->media_ports[0].multicast_ip,
				linphone_core_get_audio_multicast_addr(call->core), sizeof(call->media_ports[0].multicast_ip));
		}
		if ( linphone_core_video_multicast_enabled(call->core)){
			strncpy(call->media_ports[1].multicast_ip,
				linphone_core_get_video_multicast_addr(call->core), sizeof(call->media_ports[1].multicast_ip));
		}
	}
817

Yann Diorcet's avatar
Yann Diorcet committed
818 819
	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);
820
	
Yann Diorcet's avatar
Yann Diorcet committed
821
}
822

Yann Diorcet's avatar
Yann Diorcet committed
823
void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
Yann Diorcet's avatar
Yann Diorcet committed
824
	stats->type = type;
Yann Diorcet's avatar
Yann Diorcet committed
825 826
	stats->received_rtcp = NULL;
	stats->sent_rtcp = NULL;
827
	stats->ice_state = LinphoneIceStateNotActivated;
Yann Diorcet's avatar
Yann Diorcet committed
828 829 830 831 832
#ifdef BUILD_UPNP
	stats->upnp_state = LinphoneUpnpStateIdle;
#else
	stats->upnp_state = LinphoneUpnpStateNotAvailable;
#endif //BUILD_UPNP
833 834
}

835

836 837 838 839 840 841 842 843 844 845 846 847 848
static void discover_mtu(LinphoneCore *lc, const char *remote){
	int mtu;
	if (lc->net_conf.mtu==0	){
		/*attempt to discover mtu*/
		mtu=ms_discover_mtu(remote);
		if (mtu>0){
			ms_set_mtu(mtu);
			ms_message("Discovered mtu is %i, RTP payload max size is %i",
				mtu, ms_get_payload_max_size());
		}
	}
}

Simon Morlat's avatar
Simon Morlat committed
849 850 851 852
void linphone_call_create_op(LinphoneCall *call){
	if (call->op) sal_op_release(call->op);
	call->op=sal_op_new(call->core->sal);
	sal_op_set_user_pointer(call->op,call);
853 854 855 856 857
	if (call->params->referer)
		sal_call_set_referer(call->op,call->params->referer->op);
	linphone_configure_op(call->core,call->op,call->log->to,call->params->custom_headers,FALSE);
	if (call->params->privacy != LinphonePrivacyDefault)
		sal_op_set_privacy(call->op,(SalPrivacyMask)call->params->privacy);
jehan's avatar
jehan committed
858
	/*else privacy might be set by proxy */
Simon Morlat's avatar
Simon Morlat committed
859 860
}

861 862 863 864
/*
 * Choose IP version we are going to use for RTP socket.
 * The algorithm is as follows:
 * - if ipv6 is disabled at the core level, it is always AF_INET
865
 * - Otherwise, if the destination address for the call is an IPv6 address, use IPv6.
866 867 868 869 870 871 872 873 874 875 876 877 878 879
 * - Otherwise, if the call is done through a known proxy config, then use the information obtained during REGISTER
 * to know if IPv6 is supported by the server.
**/
static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, LinphoneAddress *to, LinphoneProxyConfig *cfg){
	if (linphone_core_ipv6_enabled(call->core)){
		call->af=AF_INET;
		if (sal_address_is_ipv6((SalAddress*)to)){
			call->af=AF_INET6;
		}else if (cfg && cfg->op){
			call->af=sal_op_is_ipv6(cfg->op) ? AF_INET6 : AF_INET;
		}
	}else call->af=AF_INET;
}

880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899
/**
 * Fill the local ip that routes to the internet according to the destination, or guess it by other special means (upnp).
 */
static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr){
	const char *ip;
	int af = call->af;
	const char *dest = NULL;
	if (call->dest_proxy == NULL) {
		struct addrinfo hints;
		struct addrinfo *res = NULL;
		int err;
		const char *domain = linphone_address_get_domain(remote_addr);
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_flags = AI_NUMERICHOST;
		err = getaddrinfo(domain, NULL, &hints, &res);
		if (err == 0) {
			dest = domain;
		}
Ghislain MARY's avatar
Ghislain MARY committed
900
		if (res != NULL) freeaddrinfo(res);
901
	}
jehan's avatar
jehan committed
902
	if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
903 904 905 906 907 908 909 910 911 912 913 914
		&& (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){
		strncpy(call->loca