linphonecall.c 190 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
#ifdef _WIN32
22 23
#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
#include "mediastreamer2/msrtt4103.h"
40

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

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

49

50
MSWebCam *get_nowebcam_device(){
51
#ifdef VIDEO_ENABLED
52
	return ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"StaticImage: Static picture");
53 54
#else
	return NULL;
Simon Morlat's avatar
Simon Morlat committed
55
#endif
56 57
}

58

59 60
static bool_t generate_b64_crypto_key(size_t key_length, char* key_out, size_t key_out_size) {
	size_t b64_size;
61 62
	uint8_t* tmp = (uint8_t*) ms_malloc0(key_length);
	if (sal_get_random_bytes(tmp, key_length)==NULL) {
63
		ms_error("Failed to generate random key");
64
		ms_free(tmp);
65 66
		return FALSE;
	}
67

68
	b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
69 70 71 72 73 74 75 76 77 78 79
	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);
80 81
	if (b64_size == 0) {
		ms_error("Failed to b64 encode key");
82
		ms_free(tmp);
83 84 85
		return FALSE;
	}
	key_out[b64_size] = '\0';
86
	ms_free(tmp);
87 88 89
	return TRUE;
}

90 91 92 93
LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
	return call->core;
}

94
const char* linphone_call_get_authentication_token(LinphoneCall *call){
95
	return call->auth_token;
96 97
}

98 99 100 101 102 103 104 105
/**
 * 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
**/
106
bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){
107
	return call->auth_token_verified;
108
}
Simon Morlat's avatar
Simon Morlat committed
109

110 111 112 113 114 115
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);
}

116
static bool_t linphone_call_all_streams_encrypted(const LinphoneCall *call) {
jehan's avatar
jehan committed
117 118
	int number_of_encrypted_stream = 0;
	int number_of_active_stream = 0;
119

120 121 122 123 124 125 126 127 128 129 130 131 132 133
	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++;
134
	}
135
	return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream;
136 137
}

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
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));
}

156 157 158
static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) {
	uint16_t rr_interval = 0;
	uint16_t stream_rr_interval;
159 160 161 162 163 164 165 166 167 168
	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 {
169
		rr_interval = 5000;
170 171 172 173
	}
	return rr_interval;
}

174
static void propagate_encryption_changed(LinphoneCall *call){
175
	if (!linphone_call_all_streams_encrypted(call)) {
176
		ms_message("Some streams are not encrypted");
177
		call->current_params->media_encryption=LinphoneMediaEncryptionNone;
178
		linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token);
179
	} else {
johan's avatar
johan committed
180 181 182 183 184
		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;
		}
185
		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");
186
		linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token);
187 188 189 190
	}
}

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

Sylvain Berfini's avatar
Sylvain Berfini committed
194
	call = (LinphoneCall *)data;
195

196
	if (encrypted) {
johan's avatar
johan committed
197 198 199 200
		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);
		}
201 202
	}

203 204 205 206 207
	propagate_encryption_changed(call);


#ifdef VIDEO_ENABLED
	// Enable video encryption
208 209 210
	{
		const LinphoneCallParams *params=linphone_call_get_current_params(call);
		if (params->has_video) {
211
			MSZrtpParams params;
212 213 214 215
			ms_message("Trying to enable encryption on video stream");
			params.zid_file=NULL; //unused
			video_stream_enable_zrtp(call->videostream,call->audiostream,&params);
		}
216 217 218 219 220 221 222
	}
#endif
}


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

226 227
	call->auth_token=ms_strdup(auth_token);
	call->auth_token_verified=verified;
228 229 230 231

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

232 233 234 235 236 237 238
/**
 * 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
239 240 241 242
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");
	}
243
	if (call->audiostream->ms.sessions.zrtp_context==NULL){
Simon Morlat's avatar
Simon Morlat committed
244 245 246
		ms_error("linphone_call_set_authentication_token_verified(): No zrtp context.");
	}
	if (!call->auth_token_verified && verified){
247
		ms_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context);
Simon Morlat's avatar
Simon Morlat committed
248
	}else if (call->auth_token_verified && !verified){
249
		ms_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context);
Simon Morlat's avatar
Simon Morlat committed
250 251 252 253
	}
	call->auth_token_verified=verified;
	propagate_encryption_changed(call);
}
254

255 256
static int get_max_codec_sample_rate(const MSList *codecs){
	int max_sample_rate=0;
257 258 259
	const MSList *it;
	for(it=codecs;it!=NULL;it=it->next){
		PayloadType *pt=(PayloadType*)it->data;
260
		int sample_rate;
261

262 263 264 265 266 267 268 269
		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;
}
270

271 272 273 274 275 276 277 278 279 280 281 282
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*/
283
			}
284 285 286 287 288 289 290 291 292 293 294 295 296
		}
	}
	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;
}
297

298 299 300
static void linphone_core_assign_payload_type_numbers(LinphoneCore *lc, MSList *codecs){
	MSList *elem;
	int dyn_number=lc->codecs_conf.dyn_pt;
301
	PayloadType *red = NULL, *t140 = NULL;
302
	
303 304 305
	for (elem=codecs; elem!=NULL; elem=elem->next){
		PayloadType *pt=(PayloadType*)elem->data;
		int number=payload_type_get_number(pt);
306

307 308 309 310 311
		/*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*/
312
			}
313
		}
314

315 316 317 318 319 320 321 322 323 324 325 326
		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);
327
			}
328
		}
329
		
330
		if (strcmp(pt->mime_type, payload_type_t140_red.mime_type) == 0) {
331 332 333
			red = pt;
		} else if (strcmp(pt->mime_type, payload_type_t140.mime_type) == 0) {
			t140 = pt;
334
		}
335
	}
336 337 338 339 340 341
	
	if (t140 && red) {
		int t140_payload_type_number = payload_type_get_number(t140);
		const char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_type_number, t140_payload_type_number, t140_payload_type_number);
		payload_type_set_recv_fmtp(red, red_fmtp);
	}
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
}

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);
				}
368
			}
369 370 371 372 373 374
			ret=ms_list_append(ret,tev);
		}
	}
	return ret;
}

375 376 377 378 379 380 381 382 383 384
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;
}

385 386 387 388 389 390
typedef struct _CodecConstraints{
	int bandwidth_limit;
	int max_codecs;
	MSList *previously_used;
}CodecConstraints;

391
static MSList *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalStreamType stype, const MSList *codecs){
392 393 394 395 396 397 398
	MSList *l=NULL;
	const MSList *it;
	int nb = 0;

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

Sylvain Berfini's avatar
Sylvain Berfini committed
400
		if (!payload_type_enabled(pt)) {
401
			continue;
Sylvain Berfini's avatar
Sylvain Berfini committed
402
		}
403 404 405 406 407 408 409 410 411
		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);
412

413 414 415 416 417
		/*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);
418
		}
419

420 421 422
		l=ms_list_append(l, pt);
		nb++;
		if ((hints->max_codecs > 0) && (nb >= hints->max_codecs)) break;
423
	}
424 425 426 427
	if (stype==SalAudio){
		MSList *specials=create_special_payload_types(lc,l);
		l=ms_list_concat(l,specials);
	}
428
	linphone_core_assign_payload_type_numbers(lc, l);
429 430 431
	return l;
}

432
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc, const StunCandidate *tc){
433
	int i;
434
	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
435
		if (!sal_stream_description_active(&md->streams[i])) continue;
436
		if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
437 438
			strcpy(md->streams[i].rtp_addr,ac->addr);
			md->streams[i].rtp_port=ac->port;
439
			if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || sal_media_description_get_nb_active_streams(md)==1){
440 441
				strcpy(md->addr,ac->addr);
			}
442 443 444 445 446 447
		} 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;
448 449 450 451
		}
	}
}

452
static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag){
453
	size_t keylen=0;
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
	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;
	}
johan's avatar
johan committed
470
	if (keylen==0 || !generate_b64_crypto_key(keylen, crypto->master_key, SAL_SRTP_KEY_SIZE)){
471 472 473 474 475 476
		ms_error("Could not generate SRTP key.");
		crypto->algo = 0;
		return -1;
	}
	return 0;
}
477 478
static void setup_dtls_keys(LinphoneCall *call, SalMediaDescription *md){
	int i;
479
	for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
480 481 482 483 484 485 486 487
		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;
488

489 490 491 492
		}
	}

}
493 494
static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
	LinphoneCore *lc=call->core;
495
	int i,j;
496
	SalMediaDescription *old_md=call->localdesc;
497
	bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1);
498

499
	for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
500 501
		if (!sal_stream_description_active(&md->streams[i])) continue;
		if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) {
502
			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)) {
503 504 505 506 507 508
				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{
509 510 511 512
				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);
				}
513 514 515 516 517
			}
		}
	}
}

518 519 520 521
static void setup_rtcp_fb(LinphoneCall *call, SalMediaDescription *md) {
	MSList *pt_it;
	PayloadType *pt;
	PayloadTypeAvpfParams avpf_params;
522
	LinphoneCore *lc = call->core;
523 524
	int i;

525
	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
526
		if (!sal_stream_description_active(&md->streams[i])) continue;
527 528
		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);
529 530
		for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) {
			pt = (PayloadType *)pt_it->data;
531
			if (call->params->avpf_enabled == TRUE) {
532 533
				payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
				avpf_params = payload_type_get_avpf_params(pt);
534
				avpf_params.trr_interval = call->params->avpf_rr_interval;
535 536 537 538 539 540 541 542 543
			} 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);
		}
	}
}

544 545
static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) {
	LinphoneCore *lc = call->core;
546
	int i;
547

Simon Morlat's avatar
Simon Morlat committed
548
	md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1);
549
	if (md->rtcp_xr.enabled == TRUE) {
Simon Morlat's avatar
Simon Morlat committed
550
		const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all");
551 552 553 554
		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
555
			md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000);
556
		}
Simon Morlat's avatar
Simon Morlat committed
557
		md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1);
558
		if (md->rtcp_xr.stat_summary_enabled == TRUE) {
559
			md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL;
560
		}
Simon Morlat's avatar
Simon Morlat committed
561
		md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1);
562
	}
563
	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
564
		if (!sal_stream_description_active(&md->streams[i])) continue;
565 566
		memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr));
	}
567 568
}

569 570 571 572 573
void linphone_call_increment_local_media_description(LinphoneCall *call){
	SalMediaDescription *md=call->localdesc;
	md->session_ver++;
}

574 575 576 577 578 579 580 581 582 583 584 585 586
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
}

587 588
static void transfer_already_assigned_payload_types(SalMediaDescription *old, SalMediaDescription *md){
	int i;
589
	for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
590 591 592 593 594
		md->streams[i].already_assigned_payloads=old->streams[i].already_assigned_payloads;
		old->streams[i].already_assigned_payloads=NULL;
	}
}

595
static const char *linphone_call_get_bind_ip_for_stream(LinphoneCall *call, int stream_index){
596
	const char *bind_ip = lp_config_get_string(call->core->config,"rtp","bind_address",call->af==AF_INET6 ? "::0" : "0.0.0.0");
597

598 599
	if (stream_index<2 && call->media_ports[stream_index].multicast_ip[0]!='\0'){
		if (call->dir==LinphoneCallOutgoing){
600
			/*as multicast sender, we must decide a local interface to use to send multicast, and bind to it*/
601
			bind_ip=call->media_localip;
602 603
		}
	}
604 605 606
	return bind_ip;
}

607
static const char *linphone_call_get_public_ip_for_stream(LinphoneCall *call, int stream_index){
608
	const char *public_ip=call->media_localip;
609 610

	if (stream_index<2 && call->media_ports[stream_index].multicast_ip[0]!='\0')
611 612 613 614
		public_ip=call->media_ports[stream_index].multicast_ip;
	return public_ip;
}

615 616 617 618 619 620 621 622 623 624 625 626
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);
	}
}

627 628
static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDescription *md){
	int i;
629

630 631 632 633 634 635 636 637
	switch (call->state){
		case LinphoneCallPausing:
		case LinphoneCallPaused:
		break;
		default:
			return;
		break;
	}
638

639
	for (i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
640
		SalStreamDescription *sd = &md->streams[i];
641 642 643 644 645 646
		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;
				}
647 648 649
			}
		}
	}
650 651
}

652
void linphone_call_make_local_media_description(LinphoneCall *call) {
653
	MSList *l;
Simon Morlat's avatar
Simon Morlat committed
654
	SalMediaDescription *old_md=call->localdesc;
655
	int i;
656
	int max_index = 0;
657
	SalMediaDescription *md=sal_media_description_new();
658
	LinphoneAddress *addr;
659 660
	const char *subject;
	CodecConstraints codec_hints={0};
661 662
	LinphoneCallParams *params = call->params;
	LinphoneCore *lc = call->core;
663
	bool_t rtcp_mux = lp_config_get_int(lc->config, "rtp", "rtcp_mux", 0);
664

jehan's avatar
jehan committed
665
	/*multicast is only set in case of outgoing call*/
666
	if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) {
667 668
		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;
669
	}
jehan's avatar
jehan committed
670

671
	if (call->dir == LinphoneCallOutgoing && linphone_call_params_video_multicast_enabled(params)) {
672 673
		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;
674
	}
jehan's avatar
jehan committed
675

676
	subject=linphone_call_params_get_session_name(params);
677

678
	linphone_core_adapt_to_network(lc,call->ping_time,params);
679

680 681 682 683 684
	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));
	}
685

Simon Morlat's avatar
Simon Morlat committed
686 687
	md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
	md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
688
	md->nb_streams=(call->biggestdesc ? call->biggestdesc->nb_streams : 1);
689

690 691
	/*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);
692
	strncpy(md->addr,call->media_localip,sizeof(md->addr));
jehan's avatar
jehan committed
693 694
	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
695
	if (subject) strncpy(md->name,subject,sizeof(md->name));
696

697 698
	if (params->down_bw)
		md->bandwidth=params->down_bw;
699
	else md->bandwidth=linphone_core_get_download_bandwidth(lc);
700

701 702 703
	if (params->custom_sdp_attributes)
		md->custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_attributes);

704
	/*set audio capabilities */
705 706 707 708 709 710 711 712 713
	if (params->has_audio) {
		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;
714
		md->streams[call->main_audio_stream_index].rtcp_mux = rtcp_mux;
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
		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);
		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);
		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;
735 736 737
	} else {
		ms_message("Don't put audio stream on local offer for call [%p]",call);
		md->streams[call->main_audio_stream_index].dir = SalStreamInactive;
738
	}
739 740
	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]);
741

742 743 744
	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;
745
	md->streams[call->main_video_stream_index].rtcp_mux = rtcp_mux;
746
	strncpy(md->streams[call->main_video_stream_index].name,"Video",sizeof(md->streams[call->main_video_stream_index].name)-1);
747

748
	if (params->has_video){
749 750 751 752
		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;
753 754
		codec_hints.bandwidth_limit=0;
		codec_hints.max_codecs=-1;
755
		codec_hints.previously_used=old_md ? old_md->streams[call->main_video_stream_index].already_assigned_payloads : NULL;
756
		l=make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs);
757
		md->streams[call->main_video_stream_index].payloads=l;
758 759
		if (call->videostream && call->videostream->ms.sessions.rtp_session) {
			char* me = linphone_address_as_string_uri_only(call->me);
760 761
			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));
762 763 764 765
			ms_free(me);
		}
		else
			ms_warning("Cannot get video local ssrc for call [%p]",call);
766 767
		if (call->main_video_stream_index > max_index)
			max_index = call->main_video_stream_index;
768 769
	} else {
		ms_message("Don't put video stream on local offer for call [%p]",call);
770
		md->streams[call->main_video_stream_index].dir = SalStreamInactive;
771
	}
772 773 774
	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]);

775
	md->streams[call->main_text_stream_index].proto=md->streams[call->main_audio_stream_index].proto;
776 777
	md->streams[call->main_text_stream_index].dir=SalStreamSendRecv;
	md->streams[call->main_text_stream_index].type=SalText;
778
	md->streams[call->main_text_stream_index].rtcp_mux = rtcp_mux;
779
	strncpy(md->streams[call->main_text_stream_index].name,"Text",sizeof(md->streams[call->main_text_stream_index].name)-1);
780 781 782
	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));
783

784 785
		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;
786

787 788 789 790 791 792 793 794 795 796 797 798 799
		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);
800 801
		if (call->main_text_stream_index > max_index)
			max_index = call->main_text_stream_index;
802 803
	} else {
		ms_message("Don't put text stream on local offer for call [%p]",call);
804
		md->streams[call->main_text_stream_index].dir = SalStreamInactive;
805
	}
806 807
	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]);
808

809
	md->nb_streams = MAX(md->nb_streams,max_index+1);
810

811 812
	/* Deactivate unused streams. */
	for (i = md->nb_streams; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
813 814
		if (md->streams[i].rtp_port == 0) {
			md->streams[i].dir = SalStreamInactive;
815 816 817 818 819
			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;
			}
		}
820
	}
821
	setup_encryption_keys(call,md);
822
	setup_dtls_keys(call,md);
823
	setup_rtcp_fb(call, md);
824
	setup_rtcp_xr(call, md);
825

826
	update_media_description_from_stun(md, &call->ac, &call->vc, &call->tc);
Simon Morlat's avatar
Simon Morlat committed
827
	call->localdesc=md;
828 829
	linphone_call_update_local_media_description_from_ice_or_upnp(call);
	linphone_address_destroy(addr);
830
	if (old_md){
831
		transfer_already_assigned_payload_types(old_md,md);
832 833 834
		call->localdesc_changed=sal_media_description_equals(md,old_md);
		sal_media_description_unref(old_md);
	}
835
	force_streams_dir_according_to_state(call, md);
836 837
}

838
static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){
839 840
	int offset;
	MSList *elem;
841 842
	int tried_port;
	int existing_port;
843
	bool_t already_used=FALSE;