linphonecall.c 200 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
 (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
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
*/
21
#ifdef _WIN32
22 23
#include <time.h>
#endif
24 25 26
#include "linphone/core.h"
#include "linphone/sipsetup.h"
#include "linphone/lpconfig.h"
27
#include "private.h"
28
#include "conference_private.h"
29

30
#include <ortp/event.h>
31
#include <ortp/b64.h>
32
#include <math.h>
33

34 35 36
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/msvolume.h"
#include "mediastreamer2/msequalizer.h"
37
#include "mediastreamer2/msfileplayer.h"
38
#include "mediastreamer2/msjpegwriter.h"
39
#include "mediastreamer2/mseventqueue.h"
40
#include "mediastreamer2/mssndcard.h"
41
#include "mediastreamer2/msrtt4103.h"
42

43
static const char *EC_STATE_STORE = ".linphone.ecstate";
44
#define EC_STATE_MAX_LEN 1048576 // 1Mo
45

Simon Morlat's avatar
Simon Morlat committed
46
static void linphone_call_stats_uninit(LinphoneCallStats *stats);
47
static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr);
48
static void _linphone_call_set_next_video_frame_decoded_trigger(LinphoneCall *call);
49
void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index);
Simon Morlat's avatar
Simon Morlat committed
50

51

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
bool_t linphone_call_state_is_early(LinphoneCallState state){
	switch (state){
		case LinphoneCallIdle:
		case LinphoneCallOutgoingInit:
		case LinphoneCallOutgoingEarlyMedia:
		case LinphoneCallOutgoingRinging:
		case LinphoneCallOutgoingProgress:
		case LinphoneCallIncomingReceived:
		case LinphoneCallIncomingEarlyMedia:
		case LinphoneCallEarlyUpdatedByRemote:
		case LinphoneCallEarlyUpdating:
			return TRUE;
		case LinphoneCallResuming:
		case LinphoneCallEnd:
		case LinphoneCallUpdating:
		case LinphoneCallRefered:
		case LinphoneCallPausing:
		case LinphoneCallPausedByRemote:
		case LinphoneCallPaused:
		case LinphoneCallConnected:
		case LinphoneCallError:
		case LinphoneCallUpdatedByRemote:
		case LinphoneCallReleased:
		case LinphoneCallStreamsRunning:
		break;
	}
	return FALSE;
}

81
MSWebCam *get_nowebcam_device(MSFactory* f){
82
#ifdef VIDEO_ENABLED
83
	return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(f),"StaticImage: Static picture");
84 85
#else
	return NULL;
86
#endif
87 88
}

89 90
static bool_t generate_b64_crypto_key(size_t key_length, char* key_out, size_t key_out_size) {
	size_t b64_size;
91 92
	uint8_t* tmp = (uint8_t*) ms_malloc0(key_length);
	if (sal_get_random_bytes(tmp, key_length)==NULL) {
93
		ms_error("Failed to generate random key");
94
		ms_free(tmp);
95 96
		return FALSE;
	}
97

98
	b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
99 100 101 102 103 104 105 106 107 108 109
	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);
110 111
	if (b64_size == 0) {
		ms_error("Failed to b64 encode key");
112
		ms_free(tmp);
113 114 115
		return FALSE;
	}
	key_out[b64_size] = '\0';
116
	ms_free(tmp);
117 118 119
	return TRUE;
}

120 121 122 123 124 125 126 127
static bool_t linphone_call_encryption_mandatory(LinphoneCall *call){
	if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
		ms_message("Forced encryption mandatory on call [%p] due to SRTP-DTLS",call);
		return TRUE;
	}
	return call->params->encryption_mandatory;
}

128 129 130 131
LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
	return call->core;
}

132
const char* linphone_call_get_authentication_token(LinphoneCall *call){
133
	return call->auth_token;
134 135 136
}

bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){
137
	return call->auth_token_verified;
138
}
139

140 141 142 143 144 145
static bool_t at_least_one_stream_started(const LinphoneCall *call){
	return (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted )
		|| (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted)
		|| (call->textstream && media_stream_get_state((MediaStream *)call->textstream) == MSStreamStarted);
}

146
static bool_t linphone_call_all_streams_encrypted(const LinphoneCall *call) {
147 148
	int number_of_encrypted_stream = 0;
	int number_of_active_stream = 0;
149

150 151 152 153 154 155 156 157 158 159 160 161 162 163
	if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
		number_of_active_stream++;
		if(media_stream_secured((MediaStream *)call->audiostream))
			number_of_encrypted_stream++;
	}
	if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
		number_of_active_stream++;
		if (media_stream_secured((MediaStream *)call->videostream))
			number_of_encrypted_stream++;
	}
	if (call->textstream && media_stream_get_state((MediaStream *)call->textstream) == MSStreamStarted) {
		number_of_active_stream++;
		if (media_stream_secured((MediaStream *)call->textstream))
			number_of_encrypted_stream++;
164
	}
165
	return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream;
166 167
}

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
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));
}

186 187 188
static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) {
	uint16_t rr_interval = 0;
	uint16_t stream_rr_interval;
189 190 191 192 193 194 195 196 197 198
	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 {
199
		rr_interval = 5000;
200 201 202 203
	}
	return rr_interval;
}

204
static void propagate_encryption_changed(LinphoneCall *call){
205
	if (!linphone_call_all_streams_encrypted(call)) {
206
		ms_message("Some streams are not encrypted");
207
		call->current_params->media_encryption=LinphoneMediaEncryptionNone;
208
		linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token);
209
	} else {
johan's avatar
johan committed
210 211 212 213 214
		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;
		}
215
		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");
216
		linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token);
jehan's avatar
jehan committed
217
#ifdef VIDEO_ENABLED
218
		if (linphone_call_encryption_mandatory(call) && call->videostream && media_stream_started((MediaStream *)call->videostream)) {
219 220
			video_stream_send_vfu(call->videostream); /*nothing could have been sent yet so generating key frame*/
		}
jehan's avatar
jehan committed
221
#endif
222 223 224 225
	}
}

static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) {
226
	char status[255]={0};
227
	LinphoneCall *call;
228

229
	call = (LinphoneCall *)data;
230

231
	if (encrypted) {
johan's avatar
johan committed
232 233 234 235
		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);
		}
236 237
	}

238 239 240 241
	propagate_encryption_changed(call);

#ifdef VIDEO_ENABLED
	// Enable video encryption
johan's avatar
johan committed
242
	if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) {
243 244
		const LinphoneCallParams *params=linphone_call_get_current_params(call);
		if (params->has_video) {
johan's avatar
johan committed
245 246
			ms_message("Trying to start ZRTP encryption on video stream");
			video_stream_start_zrtp(call->videostream);
247
		}
248 249 250 251 252 253
	}
#endif
}

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

257 258
	call->auth_token=ms_strdup(auth_token);
	call->auth_token_verified=verified;
259 260 261 262

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

263
void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified){
264 265 266
	if (call->audiostream==NULL || !media_stream_started(&call->audiostream->ms)){
		ms_error("linphone_call_set_authentication_token_verified(): No audio stream or not started");
		return;
267
	}
268
	if (call->audiostream->ms.sessions.zrtp_context==NULL){
269
		ms_error("linphone_call_set_authentication_token_verified(): No zrtp context.");
270
		return;
271 272
	}
	if (!call->auth_token_verified && verified){
273
		ms_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context);
274
	}else if (call->auth_token_verified && !verified){
275
		ms_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context);
276 277 278 279
	}
	call->auth_token_verified=verified;
	propagate_encryption_changed(call);
}
280

281
static int get_max_codec_sample_rate(const bctbx_list_t *codecs){
282
	int max_sample_rate=0;
283
	const bctbx_list_t *it;
284 285
	for(it=codecs;it!=NULL;it=it->next){
		PayloadType *pt=(PayloadType*)it->data;
286
		int sample_rate;
287

288 289 290 291 292 293 294 295
		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;
}
296

297 298
static int find_payload_type_number(const bctbx_list_t *assigned, const PayloadType *pt){
	const bctbx_list_t *elem;
299 300 301 302 303 304 305 306 307 308
	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*/
309
			}
310 311 312 313 314
		}
	}
	return candidate ? payload_type_get_number(candidate) : -1;
}

315 316
bool_t is_payload_type_number_available(const bctbx_list_t *l, int number, const PayloadType *ignore){
	const bctbx_list_t *elem;
317 318 319 320 321 322
	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;
}
323

324 325
static void linphone_core_assign_payload_type_numbers(LinphoneCore *lc, bctbx_list_t *codecs){
	bctbx_list_t *elem;
326
	int dyn_number=lc->codecs_conf.dyn_pt;
327
	PayloadType *red = NULL, *t140 = NULL;
328

329 330 331
	for (elem=codecs; elem!=NULL; elem=elem->next){
		PayloadType *pt=(PayloadType*)elem->data;
		int number=payload_type_get_number(pt);
332

333 334 335 336 337
		/*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*/
338
			}
339
		}
340

341 342 343 344 345 346 347 348 349 350 351 352
		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);
353
			}
354
		}
355

356
		if (strcmp(pt->mime_type, payload_type_t140_red.mime_type) == 0) {
357 358 359
			red = pt;
		} else if (strcmp(pt->mime_type, payload_type_t140.mime_type) == 0) {
			t140 = pt;
360
		}
361
	}
362

363 364
	if (t140 && red) {
		int t140_payload_type_number = payload_type_get_number(t140);
365
		char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_type_number, t140_payload_type_number, t140_payload_type_number);
366
		payload_type_set_recv_fmtp(red, red_fmtp);
367
		ms_free(red_fmtp);
368
	}
369 370
}

371 372
static bool_t has_telephone_event_at_rate(const bctbx_list_t *tev, int rate){
	const bctbx_list_t *it;
373 374 375 376 377 378 379
	for(it=tev;it!=NULL;it=it->next){
		const PayloadType *pt=(PayloadType*)it->data;
		if (pt->clock_rate==rate) return TRUE;
	}
	return FALSE;
}

380 381 382
static bctbx_list_t * create_telephone_events(LinphoneCore *lc, const bctbx_list_t *codecs){
	const bctbx_list_t *it;
	bctbx_list_t *ret=NULL;
383 384 385 386 387 388 389 390 391 392 393 394
	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);
				}
395
			}
396
			ret=bctbx_list_append(ret,tev);
397 398 399 400 401
		}
	}
	return ret;
}

402 403
static bctbx_list_t *create_special_payload_types(LinphoneCore *lc, const bctbx_list_t *codecs){
	bctbx_list_t *ret=create_telephone_events(lc, codecs);
404
	if (linphone_core_generic_comfort_noise_enabled(lc)){
405 406
		PayloadType *cn=payload_type_clone(&payload_type_cn);
		payload_type_set_number(cn, 13);
407
		ret=bctbx_list_append(ret, cn);
408 409 410 411
	}
	return ret;
}

412 413 414
typedef struct _CodecConstraints{
	int bandwidth_limit;
	int max_codecs;
415
	bctbx_list_t *previously_used;
416 417
}CodecConstraints;

418 419 420
static bctbx_list_t *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalStreamType stype, const bctbx_list_t *codecs){
	bctbx_list_t *l=NULL;
	const bctbx_list_t *it;
421 422 423 424 425
	int nb = 0;

	for(it=codecs;it!=NULL;it=it->next){
		PayloadType *pt=(PayloadType*)it->data;
		int num;
426

Sylvain Berfini's avatar
Sylvain Berfini committed
427
		if (!payload_type_enabled(pt)) {
428
			continue;
Sylvain Berfini's avatar
Sylvain Berfini committed
429
		}
430 431 432 433 434 435 436 437 438
		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);
439

440 441 442 443 444
		/*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);
445
		}
446

447
		l=bctbx_list_append(l, pt);
448 449
		nb++;
		if ((hints->max_codecs > 0) && (nb >= hints->max_codecs)) break;
450
	}
451
	if (stype==SalAudio){
452 453
		bctbx_list_t *specials=create_special_payload_types(lc,l);
		l=bctbx_list_concat(l,specials);
454
	}
455
	linphone_core_assign_payload_type_numbers(lc, l);
456 457 458
	return l;
}

459
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc, const StunCandidate *tc){
460
	int i;
461
	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
462
		if (!sal_stream_description_active(&md->streams[i])) continue;
463
		if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
464 465
			strcpy(md->streams[i].rtp_addr,ac->addr);
			md->streams[i].rtp_port=ac->port;
466
			if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || sal_media_description_get_nb_active_streams(md)==1){
467 468
				strcpy(md->addr,ac->addr);
			}
469 470 471 472 473 474
		} else if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
			strcpy(md->streams[i].rtp_addr,vc->addr);
			md->streams[i].rtp_port=vc->port;
		} else if ((md->streams[i].type == SalText) && (tc->port != 0)) {
			strcpy(md->streams[i].rtp_addr,tc->addr);
			md->streams[i].rtp_port=tc->port;
475 476 477 478
		}
	}
}

479
static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag){
480
	size_t keylen=0;
481 482 483 484 485 486 487 488 489 490
	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:
491
		case MS_AES_CM_256_SHA1_80:
492 493 494 495 496 497
		case MS_AES_256_SHA1_32:
			keylen=46;
		break;
		case MS_CRYPTO_SUITE_INVALID:
		break;
	}
498
	if (keylen==0 || !generate_b64_crypto_key(keylen, crypto->master_key, SAL_SRTP_KEY_SIZE)){
499 500 501 502 503 504
		ms_error("Could not generate SRTP key.");
		crypto->algo = 0;
		return -1;
	}
	return 0;
}
505 506
static void setup_dtls_keys(LinphoneCall *call, SalMediaDescription *md){
	int i;
507
	for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
508 509 510 511 512 513 514 515
		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;
516

517 518 519 520
		}
	}

}
521 522
static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
	LinphoneCore *lc=call->core;
523
	int i,j;
524
	SalMediaDescription *old_md=call->localdesc;
525
	bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1);
526

527
	for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
528 529
		if (!sal_stream_description_active(&md->streams[i])) continue;
		if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) {
530
			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)) {
531 532 533 534 535 536
				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{
537 538 539 540
				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);
				}
541 542 543 544 545
			}
		}
	}
}

johan's avatar
johan committed
546 547 548

static void setup_zrtp_hash(LinphoneCall *call, SalMediaDescription *md) {
	int i;
549
	if (linphone_core_media_encryption_supported(call->core, LinphoneMediaEncryptionZRTP)) { /* set the hello hash for all streams */
johan's avatar
johan committed
550 551 552 553
		for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
			if (!sal_stream_description_active(&md->streams[i])) continue;
			if (call->sessions[i].zrtp_context!=NULL) {
				ms_zrtp_getHelloHash(call->sessions[i].zrtp_context, md->streams[i].zrtphash, 128);
johan's avatar
johan committed
554 555 556 557 558
				if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { /* turn on the flag to use it if ZRTP is set */
					md->streams[i].haveZrtpHash = 1;
				} else {
					md->streams[i].haveZrtpHash = 0;
				}
johan's avatar
johan committed
559 560 561 562 563 564 565
			} else {
				md->streams[i].haveZrtpHash = 0;
			}
		}
	}
}

566
static void setup_rtcp_fb(LinphoneCall *call, SalMediaDescription *md) {
567
	bctbx_list_t *pt_it;
568 569
	PayloadType *pt;
	PayloadTypeAvpfParams avpf_params;
570
	LinphoneCore *lc = call->core;
571 572
	int i;

573
	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
574
		if (!sal_stream_description_active(&md->streams[i])) continue;
575 576
		md->streams[i].rtcp_fb.generic_nack_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_generic_nack_enabled", 0);
		md->streams[i].rtcp_fb.tmmbr_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_tmmbr_enabled", 0);
577
		md->streams[i].implicit_rtcp_fb = call->params->implicit_rtcp_fb;
578

579
		for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) {
580
			pt = (PayloadType *)pt_it->data;
581 582 583 584 585 586 587 588 589

			if (call->params->avpf_enabled == FALSE && call->params->implicit_rtcp_fb == FALSE)  {
				payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
				memset(&avpf_params, 0, sizeof(avpf_params));
			}else {
				payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
				avpf_params = payload_type_get_avpf_params(pt);
				avpf_params.trr_interval = call->params->avpf_rr_interval;
			}
590 591 592 593 594
			payload_type_set_avpf_params(pt, avpf_params);
		}
	}
}

595 596
static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) {
	LinphoneCore *lc = call->core;
597
	int i;
598

599
	md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1);
600
	if (md->rtcp_xr.enabled == TRUE) {
601
		const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all");
602 603 604 605
		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) {
606
			md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000);
607
		}
608
		md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1);
609
		if (md->rtcp_xr.stat_summary_enabled == TRUE) {
610
			md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL;
611
		}
612
		md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1);
613
	}
614
	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
615
		if (!sal_stream_description_active(&md->streams[i])) continue;
616 617
		memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr));
	}
618 619
}

620 621 622 623 624
void linphone_call_increment_local_media_description(LinphoneCall *call){
	SalMediaDescription *md=call->localdesc;
	md->session_ver++;
}

625
void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call){
626
	LinphoneCore *lc = call->core;
627
	if (call->ice_session != NULL) {
628
		/*set this to FALSE once flexisip are updated everywhere, let's say in December 2016.*/
629 630
		bool_t use_nortpproxy = lp_config_get_int(lc->config, "sip", "ice_uses_nortpproxy", TRUE);
		_update_local_media_description_from_ice(call->localdesc, call->ice_session, use_nortpproxy);
631 632 633 634 635 636 637 638 639 640
		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
}

641 642
static void transfer_already_assigned_payload_types(SalMediaDescription *old, SalMediaDescription *md){
	int i;
643
	for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
644 645 646 647 648
		md->streams[i].already_assigned_payloads=old->streams[i].already_assigned_payloads;
		old->streams[i].already_assigned_payloads=NULL;
	}
}

649
static const char *linphone_call_get_bind_ip_for_stream(LinphoneCall *call, int stream_index){
650
	const char *bind_ip = lp_config_get_string(call->core->config,"rtp","bind_address",
651
				call->af == AF_INET6 ? "::0" : "0.0.0.0");
652
	PortConfig *pc = &call->media_ports[stream_index];
653
	if (pc->multicast_ip[0]!='\0'){
654
		if (call->dir==LinphoneCallOutgoing){
655
			/*as multicast sender, we must decide a local interface to use to send multicast, and bind to it*/
656 657 658
			linphone_core_get_local_ip_for(strchr(pc->multicast_ip,':') ? AF_INET6 : AF_INET,
				NULL, pc->multicast_bind_ip);
			bind_ip = pc->multicast_bind_ip;
659 660 661 662
		}else{
			/*otherwise we shall use an address family of the same family of the multicast address, because
			 * dual stack socket and multicast don't work well on Mac OS (linux is OK, as usual).*/
			bind_ip = strchr(pc->multicast_ip,':') ? "::0" : "0.0.0.0";
663 664
		}
	}
665 666 667
	return bind_ip;
}

668
static const char *linphone_call_get_public_ip_for_stream(LinphoneCall *call, int stream_index){
669
	const char *public_ip=call->media_localip;
670

671
	if (call->media_ports[stream_index].multicast_ip[0]!='\0')
672 673 674 675
		public_ip=call->media_ports[stream_index].multicast_ip;
	return public_ip;
}

676 677 678 679 680 681 682 683 684 685 686 687
void linphone_call_update_biggest_desc(LinphoneCall *call, SalMediaDescription *md){
	if (call->biggestdesc==NULL || md->nb_streams>call->biggestdesc->nb_streams){
		/*we have been offered and now are ready to proceed, or we added a new stream*/
		/*store the media description to remember the mapping of calls*/
		if (call->biggestdesc){
			sal_media_description_unref(call->biggestdesc);
			call->biggestdesc=NULL;
		}
		call->biggestdesc=sal_media_description_ref(md);
	}
}

688 689
static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDescription *md){
	int i;
690

691 692 693 694 695 696 697 698
	switch (call->state){
		case LinphoneCallPausing:
		case LinphoneCallPaused:
		break;
		default:
			return;
		break;
	}
699

700
	for (i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
701
		SalStreamDescription *sd = &md->streams[i];
702 703 704 705 706 707
		if (sd->dir != SalStreamInactive) {
			sd->dir = SalStreamSendOnly;
			if (sd->type == SalVideo){
				if (lp_config_get_int(call->core->config, "sip", "inactive_video_on_pause", 0)) {
					sd->dir = SalStreamInactive;
				}
708 709 710
			}
		}
	}
711 712
}

713
void linphone_call_make_local_media_description(LinphoneCall *call) {
714
	bctbx_list_t *l;
Simon Morlat's avatar
Simon Morlat committed
715
	SalMediaDescription *old_md=call->localdesc;
716
	int i;
717
	int max_index = 0;
718
	SalMediaDescription *md=sal_media_description_new();
719
	LinphoneAddress *addr;
720 721
	const char *subject;
	CodecConstraints codec_hints={0};
722 723
	LinphoneCallParams *params = call->params;
	LinphoneCore *lc = call->core;
724
	bool_t rtcp_mux = lp_config_get_int(lc->config, "rtp", "rtcp_mux", 0);
725

jehan's avatar
jehan committed
726
	/*multicast is only set in case of outgoing call*/
727
	if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) {
728 729
		md->streams[call->main_audio_stream_index].ttl=linphone_core_get_audio_multicast_ttl(lc);
		md->streams[call->main_audio_stream_index].multicast_role = SalMulticastSender;
730
	}
jehan's avatar
jehan committed
731

732
	if (call->dir == LinphoneCallOutgoing && linphone_call_params_video_multicast_enabled(params)) {
733 734
		md->streams[call->main_video_stream_index].ttl=linphone_core_get_video_multicast_ttl(lc);
		md->streams[call->main_video_stream_index].multicast_role = SalMulticastSender;
735
	}
jehan's avatar
jehan committed
736

737
	subject=linphone_call_params_get_session_name(params);
738

739
	linphone_core_adapt_to_network(lc,call->ping_time,params);
740

741 742 743 744 745
	if (call->dest_proxy) {
		addr=linphone_address_clone(linphone_proxy_config_get_identity_address(call->dest_proxy));
	} else {
		addr=linphone_address_new(linphone_core_get_identity(lc));
	}
746

Simon Morlat's avatar
Simon Morlat committed
747 748
	md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
	md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
749
	md->nb_streams=(call->biggestdesc ? call->biggestdesc->nb_streams : 1);
750

751 752
	/*re-check local ip address each time we make a new offer, because it may change in case of network reconnection*/
	linphone_call_get_local_ip(call, call->dir == LinphoneCallOutgoing ?  call->log->to : call->log->from);
753
	strncpy(md->addr,call->media_localip,sizeof(md->addr));
754 755
	if (linphone_address_get_username(addr)) /*might be null in case of identity without userinfo*/
		strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
Simon Morlat's avatar
Simon Morlat committed
756
	if (subject) strncpy(md->name,subject,sizeof(md->name));
757

758 759
	if (params->down_bw)
		md->bandwidth=params->down_bw;
760
	else md->bandwidth=linphone_core_get_download_bandwidth(lc);
761

762 763 764
	if (params->custom_sdp_attributes)
		md->custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_attributes);

765
	/*set audio capabilities */
766

767 768 769 770
	codec_hints.bandwidth_limit=params->audio_bw;
	codec_hints.max_codecs=-1;
	codec_hints.previously_used=old_md ? old_md->streams[call->main_audio_stream_index].already_assigned_payloads : NULL;
	l=make_codec_list(lc, &codec_hints, SalAudio, lc->codecs_conf.audio_codecs);
771

772
	if (params->has_audio && l != NULL) {
773 774 775 776 777 778 779 780
		strncpy(md->streams[call->main_audio_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_audio_stream_index),sizeof(md->streams[call->main_audio_stream_index].rtp_addr));
		strncpy(md->streams[call->main_audio_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_audio_stream_index),sizeof(md->streams[call->main_audio_stream_index].rtcp_addr));
		strncpy(md->streams[call->main_audio_stream_index].name,"Audio",sizeof(md->streams[call->main_audio_stream_index].name)-1);
		md->streams[call->main_audio_stream_index].rtp_port=call->media_ports[call->main_audio_stream_index].rtp_port;
		md->streams[call->main_audio_stream_index].rtcp_port=call->media_ports[call->main_audio_stream_index].rtcp_port;
		md->streams[call->main_audio_stream_index].proto=get_proto_from_call_params(params);
		md->streams[call->main_audio_stream_index].dir=get_audio_dir_from_call_params(params);
		md->streams[call->main_audio_stream_index].type=SalAudio;
781
		md->streams[call->main_audio_stream_index].rtcp_mux = rtcp_mux;
782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
		if (params->down_ptime)
			md->streams[call->main_audio_stream_index].ptime=params->down_ptime;
		else
			md->streams[call->main_audio_stream_index].ptime=linphone_core_get_download_ptime(lc);
		md->streams[call->main_audio_stream_index].max_rate=get_max_codec_sample_rate(l);
		md->streams[call->main_audio_stream_index].payloads=l;
		if (call->audiostream && call->audiostream->ms.sessions.rtp_session) {
			char* me = linphone_address_as_string_uri_only(call->me);
			md->streams[call->main_audio_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->audiostream->ms.sessions.rtp_session);
			strncpy(md->streams[call->main_audio_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_audio_stream_index].rtcp_cname));
			ms_free(me);
		}
		else
			ms_warning("Cannot get audio local ssrc for call [%p]",call);
		if (call->main_audio_stream_index > max_index)
			max_index = call->main_audio_stream_index;
798 799 800
	} else {
		ms_message("Don't put audio stream on local offer for call [%p]",call);
		md->streams[call->main_audio_stream_index].dir = SalStreamInactive;
801
		if(l) l=bctbx_list_free_with_data(l, (void (*)(void *))payload_type_destroy);
802
	}
803 804
	if (params->custom_sdp_media_attributes[LinphoneStreamTypeAudio])
		md->streams[call->main_audio_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeAudio]);
805

806 807 808
	md->streams[call->main_video_stream_index].proto=md->streams[call->main_audio_stream_index].proto;
	md->streams[call->main_video_stream_index].dir=get_video_dir_from_call_params(params);
	md->streams[call->main_video_stream_index].type=SalVideo;
809
	md->streams[call->main_video_stream_index].rtcp_mux = rtcp_mux;
810
	strncpy(md->streams[call->main_video_stream_index].name,"Video",sizeof(md->streams[call->main_video_stream_index].name)-1);
811

812 813 814 815
	codec_hints.bandwidth_limit=0;
	codec_hints.max_codecs=-1;
	codec_hints.previously_used=old_md ? old_md->streams[call->main_video_stream_index].already_assigned_payloads : NULL;
	l=make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs);
816

817
	if (params->has_video && l != NULL){
818 819 820 821
		strncpy(md->streams[call->main_video_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_video_stream_index),sizeof(md->streams[call->main_video_stream_index].rtp_addr));
		strncpy(md->streams[call->main_video_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_video_stream_index),sizeof(md->streams[call->main_video_stream_index].rtcp_addr));
		md->streams[call->main_video_stream_index].rtp_port=call->media_ports[call->main_video_stream_index].rtp_port;
		md->streams[call->main_video_stream_index].rtcp_port=call->media_ports[call->main_video_stream_index].rtcp_port;
822
		md->streams[call->main_video_stream_index].payloads=l;
823 824
		if (call->videostream && call->videostream->ms.sessions.rtp_session) {
			char* me = linphone_address_as_string_uri_only(call->me);
825 826
			md->streams[call->main_video_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->videostream->ms.sessions.rtp_session);
			strncpy(md->streams[call->main_video_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_video_stream_index].rtcp_cname));
827 828 829 830
			ms_free(me);
		}
		else
			ms_warning("Cannot get video local ssrc for call [%p]",call);
831 832
		if (call->main_video_stream_index > max_index)
			max_index = call->main_video_stream_index;
833 834
	} else {
		ms_message("Don't put video stream on local offer for call [%p]",call);
835
		md->streams[call->main_video_stream_index].dir = SalStreamInactive;
836
		if(l) l=bctbx_list_free_with_data(l, (void (*)(void *))payload_type_destroy);
837
	}
838 839 840
	if (params->custom_sdp_media_attributes[LinphoneStreamTypeVideo])
		md->streams[call->main_video_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeVideo]);

841
	md->streams[call->main_text_stream_index].proto=md->streams[call->main_audio_stream_index].proto;
842 843
	md->streams[call->main_text_stream_index].dir=SalStreamSendRecv;
	md->streams[call->main_text_stream_index].type=SalText;
844
	md->streams[call->main_text_stream_index].rtcp_mux = rtcp_mux;
845
	strncpy(md->streams[call->main_text_stream_index].name,"Text",sizeof(md->streams[call->main_text_stream_index].name)-1);
846 847 848
	if (params->realtimetext_enabled) {
		strncpy(md->streams[call->main_text_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_text_stream_index),sizeof(md->streams[call->main_text_stream_index].rtp_addr));
		strncpy(md->streams[call->main_text_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_text_stream_index),sizeof(md->streams[call->main_text_stream_index].rtcp_addr));
849

850 851
		md->streams[call->main_text_stream_index].rtp_port=call->media_ports[call->main_text_stream_index].rtp_port;
		md->streams[call->main_text_stream_index].rtcp_port=call->media_ports[call->main_text_stream_index].rtcp_port;
852

853 854 855 856 857 858 859 860 861 862 863 864 865
		codec_hints.bandwidth_limit=0;
		codec_hints.max_codecs=-1;
		codec_hints.previously_used=old_md ? old_md->streams[call->main_text_stream_index].already_assigned_payloads : NULL;
		l=make_codec_list(lc, &codec_hints, SalText, lc->codecs_conf.text_codecs);
		md->streams[call->main_text_stream_index].payloads=l;
		if (call->textstream && call->textstream->ms.sessions.rtp_session) {
			char* me = linphone_address_as_string_uri_only(call->me);
			md->streams[call->main_text_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->textstream->ms.sessions.rtp_session);
			strncpy(md->streams[call->main_text_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_text_stream_index].rtcp_cname));
			ms_free(me);
		}
		else
			ms_warning("Cannot get text local ssrc for call [%p]",call);
866 867
		if (call->main_text_stream_index > max_index)
			max_index = call->main_text_stream_index;
868 869
	} else {
		ms_message("Don't put text stream on local offer for call [%p]",call);
870
		md->streams[call->main_text_stream_index].dir = SalStreamInactive;
871
	}
872 873
	if (params->custom_sdp_media_attributes[LinphoneStreamTypeText])
		md->streams[call->main_text_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeText]);
874

875
	md->nb_streams = MAX(md->nb_streams,max_index+1);
876

877 878
	/* Deactivate unused streams. */
	for (i = md->nb_streams; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
879 880
		if (md->streams[i].rtp_port == 0) {
			md->streams[i].dir = SalStreamInactive;
881 882 883 884 885
			if (call->biggestdesc && i < call->biggestdesc->nb_streams) {
				md->streams[i].proto = call->biggestdesc->streams[i].proto;
				md->streams[i].type = call->biggestdesc->streams[i].type;
			}
		}
886
	}
887
	setup_encryption_keys(call,md);
888
	setup_dtls_keys(call,md);
johan's avatar
johan committed
889
	setup_zrtp_hash(call, md);
890

891
	setup_rtcp_fb(call, md);
892
	setup_rtcp_xr(call, md);
893

894
	update_media_description_from_stun(md, &call->ac, &call->vc, &call->tc);
Simon Morlat's avatar
Simon Morlat committed
895
	call->localdesc=md;
896 897
	linphone_call_update_local_media_description_from_ice_or_upnp(call);
	linphone_address_destroy(addr);
898
	if (old_md){
899
		transfer_already_assigned_payload_types(old_md,md);
900 901
		call->localdesc_changed=sal_media_description_equals(md,old_md);
		sal_media_description_unref(old_md);
902 903 904 905 906 907 908 909
		if (call->params->internal_call_update){
			/*
			 * An internal call update (ICE reINVITE) is not expected to modify the actual media stream parameters.
			 * However, the localdesc may change between first INVITE and ICE reINVITE, for example if the remote party has declined a video stream.
			 * We use the internal_call_update flag to prevent trigger an unnecessary media restart.
			 */
			call->localdesc_changed = 0;
		}
910
	}
911
	force_streams_dir_according_to_state(call, md);
912 913
}

914
static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){
915
	int offset;
916
	bctbx_list_t *elem;
917 918
	int tried_port;
	int existing_port;
919
	bool_t already_used=FALSE;
920

921
	for(offset=0;offset<100;offset+=2){
922
		tried_port=base_port+offset;
923 924 925
		already_used=FALSE;
		for(elem=lc->calls;elem!=NULL;elem=elem->next){
			LinphoneCall *call=(LinphoneCall*)elem->data;
926
			existing_port=call->media_ports[stream_index].rtp_port;
927
			if (existing_port==tried_port) {
928 929 930 931 932 933 934 935 936 937 938 939 940
				already_used=TRUE;
				break;
			}
		}
		if (!already_used) break;
	}
	if (offset==100){
		ms_error("Could not find any free port !");
		return -1;
	}
	return offset;
}

941
static int select_random_port(LinphoneCore *lc, int stream_index, int min_port, int max_port) {
942
	bctbx_list_t *elem;
943 944 945 946 947
	int nb_tries;
	int tried_port = 0;
	int existing_port = 0;
	bool_t already_used = FALSE;

948
	tried_port = (ortp_random() % (max_port - min_port) + min_port) & ~0x1;
949 950 951 952
	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;
953
			existing_port=call->media_ports[stream_index].rtp_port;
954 955 956 957 958 959 960 961 962 963 964 965 966 967
			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;
}

968 969 970 971 972 973
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){
974
	int port_offset;
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
	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){
993
	int min_port, max_port;
994
	ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version());
995
	call->core->send_call_stats_periodical_updates = lp_config_get_int(call->core->config, "misc", "send_call_stats_periodical_updates", 0);
996 997 998
	call->main_audio_stream_index = LINPHONE_CALL_STATS_AUDIO;
	call->main_video_stream_index = LINPHONE_CALL_STATS_VIDEO;
	call->main_text_stream_index = LINPHONE_CALL_STATS_TEXT;
999
	call->state=LinphoneCallIdle;
1000
	call->transfer_state = LinphoneCallIdle;
1001
	call->log=linphone_call_log_new(call->dir, from, to);
1002
	call->camera_enabled=TRUE;
1003 1004
	call->current_params = linphone_call_params_new();
	call->current_params->media_encryption=LinphoneMediaEncryptionNone;
johan's avatar
johan committed
1005
	call->dtls_certificate_fingerprint = NULL;
jehan's avatar
jehan committed
1006 1007 1008 1009 1010
	if (call->dir == LinphoneCallIncoming)
		call->me=to;
	 else
		call->me=from;
	linphone_address_ref(call->me);
1011

1012
	linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
1013
	port_config_set(call,call->main_audio_stream_index,min_port,max_port);
1014

1015
	linphone_core_get_video_port_range(call->core, &min_port, &max_port);
1016 1017
	port_config_set(call,call->main_video_stream_index,min_port,max_port);

1018 1019
	linphone_core_get_text_port_range(call->core, &min_port, &max_port);
	port_config_set(call,call->main_text_stream_index,min_port,max_port);
1020

1021 1022
	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);
1023
	linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_TEXT], LINPHONE_CALL_STATS_TEXT);
1024
}
1025

1026
void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
Yann Diorcet's avatar
Yann Diorcet committed
1027
	stats->type = type;
1028 1029
	stats->received_rtcp = NULL;
	stats->sent_rtcp = NULL;
1030
	stats->ice_state = LinphoneIceStateNotActivated;
Yann Diorcet's avatar
Yann Diorcet committed
1031 1032 1033 1034 1035
#ifdef BUILD_UPNP
	stats->upnp_state = LinphoneUpnpStateIdle;
#else
	stats->upnp_state = LinphoneUpnpStateNotAvailable;
#endif //BUILD_UPNP
1036 1037 1038 1039 1040 1041 1042 1043
}

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){
1044
			ms_factory_set_mtu(lc->factory, mtu);
1045
			ms_message("Discovered mtu is %i, RTP payload max size is %i",
1046
				mtu, ms_factory_get_payload_max_size(lc->factory));
1047 1048 1049 1050
		}
	}
}

Simon Morlat's avatar
Simon Morlat committed
1051 1052 1053 1054
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);
1055 1056 1057 1058 1059
	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);
1060
	/*else privacy might be set by proxy */
Simon Morlat's avatar
Simon Morlat committed
1061 1062
}

1063
/*
1064
 * Choose IP version we are going to use for RTP streams IP address advertised in SDP.
1065 1066
 * The algorithm is as follows:
 * - if ipv6 is disabled at the core level, it is always AF_INET
1067
 * - Otherwise, if the destination address for the call is an IPv6 address, use IPv6.
1068 1069 1070 1071 1072 1073 1074 1075
 * - 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)){
		if (sal_address_is_ipv6((SalAddress*)to)){
			call->af=AF_INET6;
		}else if (cfg && cfg->op){
1076
			call->af=sal_op_get_address_family(cfg->op);
1077
		}else{
1078 1079 1080
			call->af=AF_UNSPEC;
		}
		if (call->af == AF_UNSPEC) {
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
			char ipv4[LINPHONE_IPADDR_SIZE];
			char ipv6[LINPHONE_IPADDR_SIZE];
			bool_t have_ipv6 = FALSE;
			bool_t have_ipv4 = FALSE;
			/*check connectivity for IPv4 and IPv6*/
			if (linphone_core_get_local_ip_for(AF_INET6, NULL, ipv6) == 0){
				have_ipv6 = TRUE;
			}
			if (linphone_core_get_local_ip_for(AF_INET, NULL, ipv4) == 0){
				have_ipv4 = TRUE;
			}
			if (have_ipv6){
				if (!have_ipv4) {
					call->af = AF_INET6;
				}else if (lp_config_get_int(call->core->config, "rtp", "prefer_ipv6", 1)){ /*this property tells whether ipv6 is prefered if two versions are available*/
					call->af = AF_INET6;
				}else{
					call->af = AF_INET;
				}
			}else call->af = AF_INET;
			/*fill the media_localip default value since we have it here*/
			strncpy(call->media_localip,call->af == AF_INET6 ? ipv6 : ipv4, LINPHONE_IPADDR_SIZE);
1103 1104 1105 1106
		}
	}else call->af=AF_INET;
}

1107 1108 1109 1110
/**
 * 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){
1111
	const char *ip = NULL;
1112 1113
	int af = call->af;
	const char *dest = NULL;
1114

1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
	if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
		&& (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){
		strncpy(call->media_localip,ip,LINPHONE_IPADDR_SIZE);
		return;
	}
#ifdef BUILD_UPNP
	else if (call->core->upnp != NULL && linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseUpnp &&
			linphone_upnp_context_get_state(call->core->upnp) == LinphoneUpnpStateOk) {
		ip = linphone_upnp_context_get_external_ipaddress(call->core->upnp);
		strncpy(call->media_localip,ip,LINPHONE_IPADDR_SIZE);
		goto found;
	}
#endif //BUILD_UPNP

	/*next, sometime, override from config*/
	if ((ip=lp_config_get_string(call->core->config,"rtp","bind_address",NULL)) != NULL)
		goto found;

	/*if a known proxy was identified for this call, then we may have a chance to take the local ip address
	* from the socket that connect to this proxy */
	if (call->dest_proxy && call->dest_proxy->op){
		if ((ip = sal_op_get_local_address(call->dest_proxy->op, NULL)) != NULL){
			ms_message("Found media local-ip from signaling.");
			goto found;
		}
	}

	/*in last resort, attempt to find the local ip that routes to destination if given as an IP address,
	 or the default route (dest=NULL)*/
1144 1145 1146 1147
	if (call->dest_proxy == NULL) {
		struct addrinfo hints;
		struct addrinfo *res = NULL;
		int err;
Simon Morlat's avatar