1 
2 /*
3 linphone
4 Copyright (C) 2010  Belledonne Communications SARL
5  (simon.morlat@linphone.org)
6 
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 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 #include <time.h>
23 #endif
24 #include "linphone/core.h"
25 #include "linphone/sipsetup.h"
26 #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 #include "mediastreamer2/mediastream.h"
35 #include "mediastreamer2/msvolume.h"
36 #include "mediastreamer2/msequalizer.h"
37 #include "mediastreamer2/msfileplayer.h"
38 #include "mediastreamer2/msjpegwriter.h"
39 #include "mediastreamer2/msogl.h"
40 #include "mediastreamer2/mseventqueue.h"
41 #include "mediastreamer2/mssndcard.h"
42 #include "mediastreamer2/msrtt4103.h"
43 
44 #include <bctoolbox/defs.h>
45 
46 
47 static const char *EC_STATE_STORE = ".linphone.ecstate";
48 #define EC_STATE_MAX_LEN 1048576 // 1Mo
49 
50 static void linphone_call_stats_uninit(LinphoneCallStats *stats);
51 static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr);
52 static void _linphone_call_set_next_video_frame_decoded_trigger(LinphoneCall *call);
53 void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index);
54 
55 
56 typedef belle_sip_object_t_vptr_t LinphoneCallCbs_vptr_t;
57 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallCbs);
58 BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallCbs, belle_sip_object_t,
59 	NULL, // destroy
60 	NULL, // clone
61 	NULL, // Marshall
62 	FALSE
63 );
64 
_linphone_call_cbs_new(void)65 LinphoneCallCbs *_linphone_call_cbs_new(void) {
66 	LinphoneCallCbs *obj = belle_sip_object_new(LinphoneCallCbs);
67 	return obj;
68 }
69 
linphone_call_cbs_ref(LinphoneCallCbs * cbs)70 LinphoneCallCbs *linphone_call_cbs_ref(LinphoneCallCbs *cbs) {
71 	return (LinphoneCallCbs *)belle_sip_object_ref(cbs);
72 }
73 
linphone_call_cbs_unref(LinphoneCallCbs * cbs)74 void linphone_call_cbs_unref(LinphoneCallCbs *cbs) {
75 	belle_sip_object_unref(cbs);
76 }
77 
linphone_call_cbs_get_user_data(const LinphoneCallCbs * cbs)78 void *linphone_call_cbs_get_user_data(const LinphoneCallCbs *cbs) {
79 	return cbs->user_data;
80 }
81 
linphone_call_cbs_set_user_data(LinphoneCallCbs * cbs,void * user_data)82 void linphone_call_cbs_set_user_data(LinphoneCallCbs *cbs, void *user_data) {
83 	cbs->user_data = user_data;
84 }
85 
linphone_call_cbs_get_dtmf_received(LinphoneCallCbs * cbs)86 LinphoneCallCbsDtmfReceivedCb linphone_call_cbs_get_dtmf_received(LinphoneCallCbs *cbs) {
87 	return cbs->dtmf_received_cb;
88 }
89 
linphone_call_cbs_set_dtmf_received(LinphoneCallCbs * cbs,LinphoneCallCbsDtmfReceivedCb cb)90 void linphone_call_cbs_set_dtmf_received(LinphoneCallCbs *cbs, LinphoneCallCbsDtmfReceivedCb cb) {
91 	cbs->dtmf_received_cb = cb;
92 }
93 
linphone_call_cbs_get_encryption_changed(LinphoneCallCbs * cbs)94 LinphoneCallCbsEncryptionChangedCb linphone_call_cbs_get_encryption_changed(LinphoneCallCbs *cbs) {
95 	return cbs->encryption_changed_cb;
96 }
97 
linphone_call_cbs_set_encryption_changed(LinphoneCallCbs * cbs,LinphoneCallCbsEncryptionChangedCb cb)98 void linphone_call_cbs_set_encryption_changed(LinphoneCallCbs *cbs, LinphoneCallCbsEncryptionChangedCb cb) {
99 	cbs->encryption_changed_cb = cb;
100 }
101 
linphone_call_cbs_get_info_message_received(LinphoneCallCbs * cbs)102 LinphoneCallCbsInfoMessageReceivedCb linphone_call_cbs_get_info_message_received(LinphoneCallCbs *cbs) {
103 	return cbs->info_message_received_cb;
104 }
105 
linphone_call_cbs_set_info_message_received(LinphoneCallCbs * cbs,LinphoneCallCbsInfoMessageReceivedCb cb)106 void linphone_call_cbs_set_info_message_received(LinphoneCallCbs *cbs, LinphoneCallCbsInfoMessageReceivedCb cb) {
107 	cbs->info_message_received_cb = cb;
108 }
109 
linphone_call_cbs_get_state_changed(LinphoneCallCbs * cbs)110 LinphoneCallCbsStateChangedCb linphone_call_cbs_get_state_changed(LinphoneCallCbs *cbs) {
111 	return cbs->state_changed_cb;
112 }
113 
linphone_call_cbs_set_state_changed(LinphoneCallCbs * cbs,LinphoneCallCbsStateChangedCb cb)114 void linphone_call_cbs_set_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsStateChangedCb cb) {
115 	cbs->state_changed_cb = cb;
116 }
117 
linphone_call_cbs_get_stats_updated(LinphoneCallCbs * cbs)118 LinphoneCallCbsStatsUpdatedCb linphone_call_cbs_get_stats_updated(LinphoneCallCbs *cbs) {
119 	return cbs->stats_updated_cb;
120 }
121 
linphone_call_cbs_set_stats_updated(LinphoneCallCbs * cbs,LinphoneCallCbsStatsUpdatedCb cb)122 void linphone_call_cbs_set_stats_updated(LinphoneCallCbs *cbs, LinphoneCallCbsStatsUpdatedCb cb) {
123 	cbs->stats_updated_cb = cb;
124 }
125 
linphone_call_cbs_get_transfer_state_changed(LinphoneCallCbs * cbs)126 LinphoneCallCbsTransferStateChangedCb linphone_call_cbs_get_transfer_state_changed(LinphoneCallCbs *cbs) {
127 	return cbs->transfer_state_changed_cb;
128 }
129 
linphone_call_cbs_set_transfer_state_changed(LinphoneCallCbs * cbs,LinphoneCallCbsTransferStateChangedCb cb)130 void linphone_call_cbs_set_transfer_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsTransferStateChangedCb cb) {
131 	cbs->transfer_state_changed_cb = cb;
132 }
133 
linphone_call_cbs_get_ack_processing(LinphoneCallCbs * cbs)134 LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_processing(LinphoneCallCbs *cbs){
135 	return cbs->ack_processing;
136 }
137 
linphone_call_cbs_set_ack_processing(LinphoneCallCbs * cbs,LinphoneCallCbsAckProcessingCb cb)138 void linphone_call_cbs_set_ack_processing(LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb){
139 	cbs->ack_processing = cb;
140 }
141 
142 
linphone_call_state_is_early(LinphoneCallState state)143 bool_t linphone_call_state_is_early(LinphoneCallState state){
144 	switch (state){
145 		case LinphoneCallIdle:
146 		case LinphoneCallOutgoingInit:
147 		case LinphoneCallOutgoingEarlyMedia:
148 		case LinphoneCallOutgoingRinging:
149 		case LinphoneCallOutgoingProgress:
150 		case LinphoneCallIncomingReceived:
151 		case LinphoneCallIncomingEarlyMedia:
152 		case LinphoneCallEarlyUpdatedByRemote:
153 		case LinphoneCallEarlyUpdating:
154 			return TRUE;
155 		case LinphoneCallResuming:
156 		case LinphoneCallEnd:
157 		case LinphoneCallUpdating:
158 		case LinphoneCallRefered:
159 		case LinphoneCallPausing:
160 		case LinphoneCallPausedByRemote:
161 		case LinphoneCallPaused:
162 		case LinphoneCallConnected:
163 		case LinphoneCallError:
164 		case LinphoneCallUpdatedByRemote:
165 		case LinphoneCallReleased:
166 		case LinphoneCallStreamsRunning:
167 		break;
168 	}
169 	return FALSE;
170 }
171 
get_nowebcam_device(MSFactory * f)172 MSWebCam *get_nowebcam_device(MSFactory* f){
173 #ifdef VIDEO_ENABLED
174 	return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(f),"StaticImage: Static picture");
175 #else
176 	return NULL;
177 #endif
178 }
179 
generate_b64_crypto_key(size_t key_length,char * key_out,size_t key_out_size)180 static bool_t generate_b64_crypto_key(size_t key_length, char* key_out, size_t key_out_size) {
181 	size_t b64_size;
182 	uint8_t* tmp = (uint8_t*) ms_malloc0(key_length);
183 	if (sal_get_random_bytes(tmp, key_length)==NULL) {
184 		ms_error("Failed to generate random key");
185 		ms_free(tmp);
186 		return FALSE;
187 	}
188 
189 	b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
190 	if (b64_size == 0) {
191 		ms_error("Failed to get b64 result size");
192 		ms_free(tmp);
193 		return FALSE;
194 	}
195 	if (b64_size>=key_out_size){
196 		ms_error("Insufficient room for writing base64 SRTP key");
197 		ms_free(tmp);
198 		return FALSE;
199 	}
200 	b64_size=b64_encode((const char*)tmp, key_length, key_out, key_out_size);
201 	if (b64_size == 0) {
202 		ms_error("Failed to b64 encode key");
203 		ms_free(tmp);
204 		return FALSE;
205 	}
206 	key_out[b64_size] = '\0';
207 	ms_free(tmp);
208 	return TRUE;
209 }
210 
linphone_call_encryption_mandatory(LinphoneCall * call)211 static bool_t linphone_call_encryption_mandatory(LinphoneCall *call){
212 	if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
213 		ms_message("Forced encryption mandatory on call [%p] due to SRTP-DTLS",call);
214 		return TRUE;
215 	}
216 	return call->params->encryption_mandatory;
217 }
218 
linphone_call_get_core(const LinphoneCall * call)219 LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
220 	return call->core;
221 }
222 
linphone_call_get_authentication_token(LinphoneCall * call)223 const char* linphone_call_get_authentication_token(LinphoneCall *call){
224 	return call->auth_token;
225 }
226 
linphone_call_get_authentication_token_verified(LinphoneCall * call)227 bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){
228 	return call->auth_token_verified;
229 }
230 
at_least_one_stream_started(const LinphoneCall * call)231 static bool_t at_least_one_stream_started(const LinphoneCall *call){
232 	return (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted )
233 		|| (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted)
234 		|| (call->textstream && media_stream_get_state((MediaStream *)call->textstream) == MSStreamStarted);
235 }
236 
linphone_call_all_streams_encrypted(const LinphoneCall * call)237 static bool_t linphone_call_all_streams_encrypted(const LinphoneCall *call) {
238 	int number_of_encrypted_stream = 0;
239 	int number_of_active_stream = 0;
240 
241 	if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
242 		number_of_active_stream++;
243 		if(media_stream_secured((MediaStream *)call->audiostream))
244 			number_of_encrypted_stream++;
245 	}
246 	if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
247 		number_of_active_stream++;
248 		if (media_stream_secured((MediaStream *)call->videostream))
249 			number_of_encrypted_stream++;
250 	}
251 	if (call->textstream && media_stream_get_state((MediaStream *)call->textstream) == MSStreamStarted) {
252 		number_of_active_stream++;
253 		if (media_stream_secured((MediaStream *)call->textstream))
254 			number_of_encrypted_stream++;
255 	}
256 	return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream;
257 }
258 
linphone_call_all_streams_avpf_enabled(const LinphoneCall * call)259 static bool_t linphone_call_all_streams_avpf_enabled(const LinphoneCall *call) {
260 	int nb_active_streams = 0;
261 	int nb_avpf_enabled_streams = 0;
262 	if (call) {
263 		if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
264 			nb_active_streams++;
265 			if (media_stream_avpf_enabled((MediaStream *)call->audiostream))
266 				nb_avpf_enabled_streams++;
267 		}
268 		if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
269 			nb_active_streams++;
270 			if (media_stream_avpf_enabled((MediaStream *)call->videostream))
271 				nb_avpf_enabled_streams++;
272 		}
273 	}
274 	return ((nb_active_streams > 0) && (nb_active_streams == nb_avpf_enabled_streams));
275 }
276 
linphone_call_get_avpf_rr_interval(const LinphoneCall * call)277 static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) {
278 	uint16_t rr_interval = 0;
279 	uint16_t stream_rr_interval;
280 	if (call) {
281 		if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
282 			stream_rr_interval = media_stream_get_avpf_rr_interval((MediaStream *)call->audiostream);
283 			if (stream_rr_interval > rr_interval) rr_interval = stream_rr_interval;
284 		}
285 		if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
286 			stream_rr_interval = media_stream_get_avpf_rr_interval((MediaStream *)call->videostream);
287 			if (stream_rr_interval > rr_interval) rr_interval = stream_rr_interval;
288 		}
289 	} else {
290 		rr_interval = 5000;
291 	}
292 	return rr_interval;
293 }
294 
propagate_encryption_changed(LinphoneCall * call)295 static void propagate_encryption_changed(LinphoneCall *call){
296 	if (!linphone_call_all_streams_encrypted(call)) {
297 		ms_message("Some streams are not encrypted");
298 		call->current_params->media_encryption=LinphoneMediaEncryptionNone;
299 		linphone_call_notify_encryption_changed(call, FALSE, call->auth_token);
300 	} else {
301 		if (call->auth_token) {/* ZRTP only is using auth_token */
302 			call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
303 		} else { /* otherwise it must be DTLS as SDES doesn't go through this function */
304 			call->current_params->media_encryption=LinphoneMediaEncryptionDTLS;
305 		}
306 		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");
307 		linphone_call_notify_encryption_changed(call, TRUE, call->auth_token);
308 #ifdef VIDEO_ENABLED
309 		if (linphone_call_encryption_mandatory(call) && call->videostream && media_stream_started((MediaStream *)call->videostream)) {
310 			video_stream_send_vfu(call->videostream); /*nothing could have been sent yet so generating key frame*/
311 		}
312 #endif
313 	}
314 }
315 
linphone_call_audiostream_encryption_changed(void * data,bool_t encrypted)316 static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) {
317 	char status[255]={0};
318 	LinphoneCall *call;
319 
320 	call = (LinphoneCall *)data;
321 
322 	if (encrypted) {
323 		if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { /* if encryption is DTLS, no status to be displayed */
324 			snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
325 			linphone_core_notify_display_status(call->core, status);
326 		}
327 	}
328 
329 	propagate_encryption_changed(call);
330 
331 #ifdef VIDEO_ENABLED
332 	// Enable video encryption
333 	if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) {
334 		const LinphoneCallParams *params=linphone_call_get_current_params(call);
335 		if (params->has_video) {
336 			ms_message("Trying to start ZRTP encryption on video stream");
337 			video_stream_start_zrtp(call->videostream);
338 		}
339 	}
340 #endif
341 }
342 
linphone_call_audiostream_auth_token_ready(void * data,const char * auth_token,bool_t verified)343 static void linphone_call_audiostream_auth_token_ready(void *data, const char* auth_token, bool_t verified) {
344 	LinphoneCall *call=(LinphoneCall *)data;
345 	if (call->auth_token != NULL)
346 		ms_free(call->auth_token);
347 
348 	call->auth_token=ms_strdup(auth_token);
349 	call->auth_token_verified=verified;
350 
351 	ms_message("Authentication token is %s (%s)", auth_token, verified?"verified":"unverified");
352 }
353 
linphone_call_set_authentication_token_verified(LinphoneCall * call,bool_t verified)354 void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified){
355 	if (call->audiostream==NULL || !media_stream_started(&call->audiostream->ms)){
356 		ms_error("linphone_call_set_authentication_token_verified(): No audio stream or not started");
357 		return;
358 	}
359 	if (call->audiostream->ms.sessions.zrtp_context==NULL){
360 		ms_error("linphone_call_set_authentication_token_verified(): No zrtp context.");
361 		return;
362 	}
363 	if (!call->auth_token_verified && verified){
364 		ms_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context);
365 	}else if (call->auth_token_verified && !verified){
366 		ms_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context);
367 	}
368 	call->auth_token_verified=verified;
369 	propagate_encryption_changed(call);
370 }
371 
get_max_codec_sample_rate(const bctbx_list_t * codecs)372 static int get_max_codec_sample_rate(const bctbx_list_t *codecs){
373 	int max_sample_rate=0;
374 	const bctbx_list_t *it;
375 	for(it=codecs;it!=NULL;it=it->next){
376 		PayloadType *pt=(PayloadType*)it->data;
377 		int sample_rate;
378 
379 		if( strcasecmp("G722",pt->mime_type) == 0 ){
380 			/* G722 spec says 8000 but the codec actually requires 16000 */
381 			sample_rate = 16000;
382 		}else sample_rate=pt->clock_rate;
383 		if (sample_rate>max_sample_rate) max_sample_rate=sample_rate;
384 	}
385 	return max_sample_rate;
386 }
387 
find_payload_type_number(const bctbx_list_t * assigned,const PayloadType * pt)388 static int find_payload_type_number(const bctbx_list_t *assigned, const PayloadType *pt){
389 	const bctbx_list_t *elem;
390 	const PayloadType *candidate=NULL;
391 	for(elem=assigned;elem!=NULL;elem=elem->next){
392 		const PayloadType *it=(const PayloadType*)elem->data;
393 		if ((strcasecmp(pt->mime_type, payload_type_get_mime(it)) == 0)
394 			&& (it->clock_rate==pt->clock_rate)
395 			&& (it->channels==pt->channels || pt->channels<=0)) {
396 			candidate=it;
397 			if ((it->recv_fmtp!=NULL && pt->recv_fmtp!=NULL && strcasecmp(it->recv_fmtp, pt->recv_fmtp)==0)
398 				|| (it->recv_fmtp==NULL && pt->recv_fmtp==NULL)){
399 				break;/*exact match*/
400 			}
401 		}
402 	}
403 	return candidate ? payload_type_get_number(candidate) : -1;
404 }
405 
is_payload_type_number_available(const bctbx_list_t * l,int number,const PayloadType * ignore)406 bool_t is_payload_type_number_available(const bctbx_list_t *l, int number, const PayloadType *ignore){
407 	const bctbx_list_t *elem;
408 	for (elem=l; elem!=NULL; elem=elem->next){
409 		const PayloadType *pt=(PayloadType*)elem->data;
410 		if (pt!=ignore && payload_type_get_number(pt)==number) return FALSE;
411 	}
412 	return TRUE;
413 }
414 
linphone_core_assign_payload_type_numbers(LinphoneCore * lc,bctbx_list_t * codecs)415 static void linphone_core_assign_payload_type_numbers(LinphoneCore *lc, bctbx_list_t *codecs){
416 	bctbx_list_t *elem;
417 	int dyn_number=lc->codecs_conf.dyn_pt;
418 	PayloadType *red = NULL, *t140 = NULL;
419 
420 	for (elem=codecs; elem!=NULL; elem=elem->next){
421 		PayloadType *pt=(PayloadType*)elem->data;
422 		int number=payload_type_get_number(pt);
423 
424 		/*check if number is duplicated: it could be the case if the remote forced us to use a mapping with a previous offer*/
425 		if (number!=-1 && !(pt->flags & PAYLOAD_TYPE_FROZEN_NUMBER)){
426 			if (!is_payload_type_number_available(codecs, number, pt)){
427 				ms_message("Reassigning payload type %i %s/%i because already offered.", number, pt->mime_type, pt->clock_rate);
428 				number=-1; /*need to be re-assigned*/
429 			}
430 		}
431 
432 		if (number==-1){
433 			while(dyn_number<127){
434 				if (is_payload_type_number_available(codecs, dyn_number, NULL)){
435 					payload_type_set_number(pt, dyn_number);
436 					dyn_number++;
437 					break;
438 				}
439 				dyn_number++;
440 			}
441 			if (dyn_number==127){
442 				ms_error("Too many payload types configured ! codec %s/%i is disabled.", pt->mime_type, pt->clock_rate);
443 				payload_type_set_enable(pt, FALSE);
444 			}
445 		}
446 
447 		if (strcmp(pt->mime_type, payload_type_t140_red.mime_type) == 0) {
448 			red = pt;
449 		} else if (strcmp(pt->mime_type, payload_type_t140.mime_type) == 0) {
450 			t140 = pt;
451 		}
452 	}
453 
454 	if (t140 && red) {
455 		int t140_payload_type_number = payload_type_get_number(t140);
456 		char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_type_number, t140_payload_type_number, t140_payload_type_number);
457 		payload_type_set_recv_fmtp(red, red_fmtp);
458 		ms_free(red_fmtp);
459 	}
460 }
461 
has_telephone_event_at_rate(const bctbx_list_t * tev,int rate)462 static bool_t has_telephone_event_at_rate(const bctbx_list_t *tev, int rate){
463 	const bctbx_list_t *it;
464 	for(it=tev;it!=NULL;it=it->next){
465 		const PayloadType *pt=(PayloadType*)it->data;
466 		if (pt->clock_rate==rate) return TRUE;
467 	}
468 	return FALSE;
469 }
470 
create_telephone_events(LinphoneCore * lc,const bctbx_list_t * codecs)471 static bctbx_list_t * create_telephone_events(LinphoneCore *lc, const bctbx_list_t *codecs){
472 	const bctbx_list_t *it;
473 	bctbx_list_t *ret=NULL;
474 	for(it=codecs;it!=NULL;it=it->next){
475 		const PayloadType *pt=(PayloadType*)it->data;
476 		if (!has_telephone_event_at_rate(ret,pt->clock_rate)){
477 			PayloadType *tev=payload_type_clone(&payload_type_telephone_event);
478 			tev->clock_rate=pt->clock_rate;
479 			/*let it choose the number dynamically as for normal codecs*/
480 			payload_type_set_number(tev, -1);
481 			if (ret==NULL){
482 				/*But for first telephone-event, prefer the number that was configured in the core*/
483 				if (is_payload_type_number_available(codecs, lc->codecs_conf.telephone_event_pt, NULL)){
484 					payload_type_set_number(tev, lc->codecs_conf.telephone_event_pt);
485 				}
486 			}
487 			ret=bctbx_list_append(ret,tev);
488 		}
489 	}
490 	return ret;
491 }
492 
create_special_payload_types(LinphoneCore * lc,const bctbx_list_t * codecs)493 static bctbx_list_t *create_special_payload_types(LinphoneCore *lc, const bctbx_list_t *codecs){
494 	bctbx_list_t *ret=create_telephone_events(lc, codecs);
495 	if (linphone_core_generic_comfort_noise_enabled(lc)){
496 		PayloadType *cn=payload_type_clone(&payload_type_cn);
497 		payload_type_set_number(cn, 13);
498 		ret=bctbx_list_append(ret, cn);
499 	}
500 	return ret;
501 }
502 
503 typedef struct _CodecConstraints{
504 	int bandwidth_limit;
505 	int max_codecs;
506 	bctbx_list_t *previously_used;
507 }CodecConstraints;
508 
make_codec_list(LinphoneCore * lc,CodecConstraints * hints,SalStreamType stype,const bctbx_list_t * codecs)509 static bctbx_list_t *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalStreamType stype, const bctbx_list_t *codecs){
510 	bctbx_list_t *l=NULL;
511 	const bctbx_list_t *it;
512 	int nb = 0;
513 
514 	for(it=codecs;it!=NULL;it=it->next){
515 		PayloadType *pt=(PayloadType*)it->data;
516 		int num;
517 
518 		if (!payload_type_enabled(pt)) {
519 			continue;
520 		}
521 		if (hints->bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,hints->bandwidth_limit)){
522 			ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s",
523 					pt->mime_type,pt->clock_rate,hints->bandwidth_limit);
524 			continue;
525 		}
526 		if (!_linphone_core_check_payload_type_usability(lc, pt)) {
527 			continue;
528 		}
529 		pt=payload_type_clone(pt);
530 
531 		/*look for a previously assigned number for this codec*/
532 		num=find_payload_type_number(hints->previously_used, pt);
533 		if (num!=-1){
534 			payload_type_set_number(pt,num);
535 			payload_type_set_flag(pt, PAYLOAD_TYPE_FROZEN_NUMBER);
536 		}
537 
538 		l=bctbx_list_append(l, pt);
539 		nb++;
540 		if ((hints->max_codecs > 0) && (nb >= hints->max_codecs)) break;
541 	}
542 	if (stype==SalAudio){
543 		bctbx_list_t *specials=create_special_payload_types(lc,l);
544 		l=bctbx_list_concat(l,specials);
545 	}
546 	linphone_core_assign_payload_type_numbers(lc, l);
547 	return l;
548 }
549 
update_media_description_from_stun(SalMediaDescription * md,const StunCandidate * ac,const StunCandidate * vc,const StunCandidate * tc)550 static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc, const StunCandidate *tc){
551 	int i;
552 	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
553 		if (!sal_stream_description_active(&md->streams[i])) continue;
554 		if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
555 			strcpy(md->streams[i].rtp_addr,ac->addr);
556 			md->streams[i].rtp_port=ac->port;
557 			if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || sal_media_description_get_nb_active_streams(md)==1){
558 				strcpy(md->addr,ac->addr);
559 			}
560 		} else if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
561 			strcpy(md->streams[i].rtp_addr,vc->addr);
562 			md->streams[i].rtp_port=vc->port;
563 		} else if ((md->streams[i].type == SalText) && (tc->port != 0)) {
564 			strcpy(md->streams[i].rtp_addr,tc->addr);
565 			md->streams[i].rtp_port=tc->port;
566 		}
567 	}
568 }
569 
setup_encryption_key(SalSrtpCryptoAlgo * crypto,MSCryptoSuite suite,unsigned int tag)570 static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag){
571 	size_t keylen=0;
572 	crypto->tag=tag;
573 	crypto->algo=suite;
574 	switch(suite){
575 		case MS_AES_128_SHA1_80:
576 		case MS_AES_128_SHA1_32:
577 		case MS_AES_128_NO_AUTH:
578 		case MS_NO_CIPHER_SHA1_80: /*not sure for this one*/
579 			keylen=30;
580 		break;
581 		case MS_AES_256_SHA1_80:
582 		case MS_AES_CM_256_SHA1_80:
583 		case MS_AES_256_SHA1_32:
584 			keylen=46;
585 		break;
586 		case MS_CRYPTO_SUITE_INVALID:
587 		break;
588 	}
589 	if (keylen==0 || !generate_b64_crypto_key(keylen, crypto->master_key, SAL_SRTP_KEY_SIZE)){
590 		ms_error("Could not generate SRTP key.");
591 		crypto->algo = 0;
592 		return -1;
593 	}
594 	return 0;
595 }
setup_dtls_keys(LinphoneCall * call,SalMediaDescription * md)596 static void setup_dtls_keys(LinphoneCall *call, SalMediaDescription *md){
597 	int i;
598 	for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
599 		if (!sal_stream_description_active(&md->streams[i])) continue;
600 		/* 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 */
601 		if (sal_stream_description_has_dtls(&md->streams[i]) == TRUE) {
602 			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) */
603 			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 */
604 		} else {
605 			md->streams[i].dtls_fingerprint[0] = '\0';
606 			md->streams[i].dtls_role = SalDtlsRoleInvalid;
607 
608 		}
609 	}
610 
611 }
setup_encryption_keys(LinphoneCall * call,SalMediaDescription * md)612 static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
613 	LinphoneCore *lc=call->core;
614 	int i,j;
615 	SalMediaDescription *old_md=call->localdesc;
616 	bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1);
617 
618 	for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
619 		if (!sal_stream_description_active(&md->streams[i])) continue;
620 		if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) {
621 			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)) {
622 				int j;
623 				ms_message("Keeping same crypto keys.");
624 				for(j=0;j<SAL_CRYPTO_ALGO_MAX;++j){
625 					memcpy(&md->streams[i].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo));
626 				}
627 			}else{
628 				const MSCryptoSuite *suites=linphone_core_get_srtp_crypto_suites(lc);
629 				for(j=0;suites!=NULL && suites[j]!=MS_CRYPTO_SUITE_INVALID && j<SAL_CRYPTO_ALGO_MAX;++j){
630 					setup_encryption_key(&md->streams[i].crypto[j],suites[j],j+1);
631 				}
632 			}
633 		}
634 	}
635 }
636 
637 
setup_zrtp_hash(LinphoneCall * call,SalMediaDescription * md)638 static void setup_zrtp_hash(LinphoneCall *call, SalMediaDescription *md) {
639 	int i;
640 	if (linphone_core_media_encryption_supported(call->core, LinphoneMediaEncryptionZRTP)) { /* set the hello hash for all streams */
641 		for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
642 			if (!sal_stream_description_active(&md->streams[i])) continue;
643 			if (call->sessions[i].zrtp_context!=NULL) {
644 				ms_zrtp_getHelloHash(call->sessions[i].zrtp_context, md->streams[i].zrtphash, 128);
645 				if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { /* turn on the flag to use it if ZRTP is set */
646 					md->streams[i].haveZrtpHash = 1;
647 				} else {
648 					md->streams[i].haveZrtpHash = 0;
649 				}
650 			} else {
651 				md->streams[i].haveZrtpHash = 0;
652 			}
653 		}
654 	}
655 }
656 
setup_rtcp_fb(LinphoneCall * call,SalMediaDescription * md)657 static void setup_rtcp_fb(LinphoneCall *call, SalMediaDescription *md) {
658 	bctbx_list_t *pt_it;
659 	PayloadType *pt;
660 	PayloadTypeAvpfParams avpf_params;
661 	LinphoneCore *lc = call->core;
662 	int i;
663 
664 	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
665 		if (!sal_stream_description_active(&md->streams[i])) continue;
666 		md->streams[i].rtcp_fb.generic_nack_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_generic_nack_enabled", 0);
667 		md->streams[i].rtcp_fb.tmmbr_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_tmmbr_enabled", 1);
668 		md->streams[i].implicit_rtcp_fb = call->params->implicit_rtcp_fb;
669 
670 		for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) {
671 			pt = (PayloadType *)pt_it->data;
672 
673 			if (call->params->avpf_enabled == FALSE && call->params->implicit_rtcp_fb == FALSE)  {
674 				payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
675 				memset(&avpf_params, 0, sizeof(avpf_params));
676 			}else {
677 				payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
678 				avpf_params = payload_type_get_avpf_params(pt);
679 				avpf_params.trr_interval = call->params->avpf_rr_interval;
680 			}
681 			payload_type_set_avpf_params(pt, avpf_params);
682 		}
683 	}
684 }
685 
setup_rtcp_xr(LinphoneCall * call,SalMediaDescription * md)686 static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) {
687 	LinphoneCore *lc = call->core;
688 	int i;
689 
690 	md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1);
691 	if (md->rtcp_xr.enabled == TRUE) {
692 		const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all");
693 		if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll;
694 		else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender;
695 		else md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone;
696 		if (md->rtcp_xr.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) {
697 			md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000);
698 		}
699 		md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1);
700 		if (md->rtcp_xr.stat_summary_enabled == TRUE) {
701 			md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL;
702 		}
703 		md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1);
704 	}
705 	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
706 		if (!sal_stream_description_active(&md->streams[i])) continue;
707 		memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr));
708 	}
709 }
710 
linphone_call_increment_local_media_description(LinphoneCall * call)711 void linphone_call_increment_local_media_description(LinphoneCall *call){
712 	SalMediaDescription *md=call->localdesc;
713 	md->session_ver++;
714 }
715 
linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall * call)716 void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call){
717 	LinphoneCore *lc = call->core;
718 	if (call->ice_session != NULL) {
719 		/*set this to FALSE once flexisip are updated everywhere, let's say in December 2016.*/
720 		bool_t use_nortpproxy = lp_config_get_int(lc->config, "sip", "ice_uses_nortpproxy", TRUE);
721 		_update_local_media_description_from_ice(call->localdesc, call->ice_session, use_nortpproxy);
722 		linphone_call_update_ice_state_in_call_stats(call);
723 	}
724 #ifdef BUILD_UPNP
725 	if(call->upnp_session != NULL) {
726 		linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
727 		linphone_call_update_upnp_state_in_call_stats(call);
728 	}
729 #endif  //BUILD_UPNP
730 }
731 
transfer_already_assigned_payload_types(SalMediaDescription * old,SalMediaDescription * md)732 static void transfer_already_assigned_payload_types(SalMediaDescription *old, SalMediaDescription *md){
733 	int i;
734 	for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
735 		md->streams[i].already_assigned_payloads=old->streams[i].already_assigned_payloads;
736 		old->streams[i].already_assigned_payloads=NULL;
737 	}
738 }
739 
linphone_call_get_bind_ip_for_stream(LinphoneCall * call,int stream_index)740 static const char *linphone_call_get_bind_ip_for_stream(LinphoneCall *call, int stream_index){
741 	const char *bind_ip = lp_config_get_string(call->core->config,"rtp","bind_address",
742 				call->af == AF_INET6 ? "::0" : "0.0.0.0");
743 	PortConfig *pc = &call->media_ports[stream_index];
744 	if (pc->multicast_ip[0]!='\0'){
745 		if (call->dir==LinphoneCallOutgoing){
746 			/*as multicast sender, we must decide a local interface to use to send multicast, and bind to it*/
747 			linphone_core_get_local_ip_for(strchr(pc->multicast_ip,':') ? AF_INET6 : AF_INET,
748 				NULL, pc->multicast_bind_ip);
749 			bind_ip = pc->multicast_bind_ip;
750 		}else{
751 			/*otherwise we shall use an address family of the same family of the multicast address, because
752 			 * dual stack socket and multicast don't work well on Mac OS (linux is OK, as usual).*/
753 			bind_ip = strchr(pc->multicast_ip,':') ? "::0" : "0.0.0.0";
754 		}
755 	}
756 	return bind_ip;
757 }
758 
linphone_call_get_public_ip_for_stream(LinphoneCall * call,int stream_index)759 static const char *linphone_call_get_public_ip_for_stream(LinphoneCall *call, int stream_index){
760 	const char *public_ip=call->media_localip;
761 
762 	if (call->media_ports[stream_index].multicast_ip[0]!='\0')
763 		public_ip=call->media_ports[stream_index].multicast_ip;
764 	return public_ip;
765 }
766 
linphone_call_update_biggest_desc(LinphoneCall * call,SalMediaDescription * md)767 void linphone_call_update_biggest_desc(LinphoneCall *call, SalMediaDescription *md){
768 	if (call->biggestdesc==NULL || md->nb_streams>call->biggestdesc->nb_streams){
769 		/*we have been offered and now are ready to proceed, or we added a new stream*/
770 		/*store the media description to remember the mapping of calls*/
771 		if (call->biggestdesc){
772 			sal_media_description_unref(call->biggestdesc);
773 			call->biggestdesc=NULL;
774 		}
775 		call->biggestdesc=sal_media_description_ref(md);
776 	}
777 }
778 
force_streams_dir_according_to_state(LinphoneCall * call,SalMediaDescription * md)779 static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDescription *md){
780 	int i;
781 
782 	for (i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
783 		SalStreamDescription *sd = &md->streams[i];
784 
785 		switch (call->state){
786 			case LinphoneCallPausing:
787 			case LinphoneCallPaused:
788 				if (sd->dir != SalStreamInactive) {
789 					sd->dir = SalStreamSendOnly;
790 					if (sd->type == SalVideo){
791 						if (lp_config_get_int(call->core->config, "sip", "inactive_video_on_pause", 0)) {
792 							sd->dir = SalStreamInactive;
793 						}
794 					}
795 				}
796 				break;
797 			default:
798 				break;
799 		}
800 
801 		/* Reflect the stream directions in the call params */
802 		if (i == call->main_audio_stream_index) {
803 			linphone_call_params_set_audio_direction(call->current_params, media_direction_from_sal_stream_dir(sd->dir));
804 		} else if (i == call->main_video_stream_index) {
805 			linphone_call_params_set_video_direction(call->current_params, media_direction_from_sal_stream_dir(sd->dir));
806 		}
807 	}
808 }
809 
linphone_call_make_local_media_description(LinphoneCall * call)810 void linphone_call_make_local_media_description(LinphoneCall *call) {
811 	bctbx_list_t *l;
812 	SalMediaDescription *old_md=call->localdesc;
813 	int i;
814 	int max_index = 0;
815 	SalMediaDescription *md=sal_media_description_new();
816 	LinphoneAddress *addr;
817 	const char *subject;
818 	CodecConstraints codec_hints={0};
819 	LinphoneCallParams *params = call->params;
820 	LinphoneCore *lc = call->core;
821 	bool_t rtcp_mux = lp_config_get_int(lc->config, "rtp", "rtcp_mux", 0);
822 
823 	/*multicast is only set in case of outgoing call*/
824 	if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) {
825 		md->streams[call->main_audio_stream_index].ttl=linphone_core_get_audio_multicast_ttl(lc);
826 		md->streams[call->main_audio_stream_index].multicast_role = SalMulticastSender;
827 	}
828 
829 	if (call->dir == LinphoneCallOutgoing && linphone_call_params_video_multicast_enabled(params)) {
830 		md->streams[call->main_video_stream_index].ttl=linphone_core_get_video_multicast_ttl(lc);
831 		md->streams[call->main_video_stream_index].multicast_role = SalMulticastSender;
832 	}
833 
834 	subject=linphone_call_params_get_session_name(params);
835 
836 	linphone_core_adapt_to_network(lc,call->ping_time,params);
837 
838 	if (call->dest_proxy) {
839 		addr=linphone_address_clone(linphone_proxy_config_get_identity_address(call->dest_proxy));
840 	} else {
841 		addr=linphone_address_new(linphone_core_get_identity(lc));
842 	}
843 
844 	md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
845 	md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
846 	md->nb_streams=(call->biggestdesc ? call->biggestdesc->nb_streams : 1);
847 
848 	/*re-check local ip address each time we make a new offer, because it may change in case of network reconnection*/
849 	linphone_call_get_local_ip(call, call->dir == LinphoneCallOutgoing ?  call->log->to : call->log->from);
850 	strncpy(md->addr,call->media_localip,sizeof(md->addr));
851 	if (linphone_address_get_username(addr)) /*might be null in case of identity without userinfo*/
852 		strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
853 	if (subject) strncpy(md->name,subject,sizeof(md->name));
854 
855 	if (params->down_bw)
856 		md->bandwidth=params->down_bw;
857 	else md->bandwidth=linphone_core_get_download_bandwidth(lc);
858 
859 	if (params->custom_sdp_attributes)
860 		md->custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_attributes);
861 
862 	/*set audio capabilities */
863 
864 	codec_hints.bandwidth_limit=params->audio_bw;
865 	codec_hints.max_codecs=-1;
866 	codec_hints.previously_used=old_md ? old_md->streams[call->main_audio_stream_index].already_assigned_payloads : NULL;
867 	l=make_codec_list(lc, &codec_hints, SalAudio, lc->codecs_conf.audio_codecs);
868 
869 	if (params->has_audio && l != NULL) {
870 		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));
871 		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));
872 		strncpy(md->streams[call->main_audio_stream_index].name,"Audio",sizeof(md->streams[call->main_audio_stream_index].name)-1);
873 		md->streams[call->main_audio_stream_index].rtp_port=call->media_ports[call->main_audio_stream_index].rtp_port;
874 		md->streams[call->main_audio_stream_index].rtcp_port=call->media_ports[call->main_audio_stream_index].rtcp_port;
875 		md->streams[call->main_audio_stream_index].proto=get_proto_from_call_params(params);
876 		md->streams[call->main_audio_stream_index].dir=get_audio_dir_from_call_params(params);
877 		md->streams[call->main_audio_stream_index].type=SalAudio;
878 		md->streams[call->main_audio_stream_index].rtcp_mux = rtcp_mux;
879 		if (params->down_ptime)
880 			md->streams[call->main_audio_stream_index].ptime=params->down_ptime;
881 		else
882 			md->streams[call->main_audio_stream_index].ptime=linphone_core_get_download_ptime(lc);
883 		md->streams[call->main_audio_stream_index].max_rate=get_max_codec_sample_rate(l);
884 		md->streams[call->main_audio_stream_index].payloads=l;
885 		if (call->audiostream && call->audiostream->ms.sessions.rtp_session) {
886 			char* me = linphone_address_as_string_uri_only(call->me);
887 			md->streams[call->main_audio_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->audiostream->ms.sessions.rtp_session);
888 			strncpy(md->streams[call->main_audio_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_audio_stream_index].rtcp_cname));
889 			ms_free(me);
890 		}
891 		else
892 			ms_warning("Cannot get audio local ssrc for call [%p]",call);
893 		if (call->main_audio_stream_index > max_index)
894 			max_index = call->main_audio_stream_index;
895 	} else {
896 		ms_message("Don't put audio stream on local offer for call [%p]",call);
897 		md->streams[call->main_audio_stream_index].dir = SalStreamInactive;
898 		if(l) l=bctbx_list_free_with_data(l, (void (*)(void *))payload_type_destroy);
899 	}
900 	if (params->custom_sdp_media_attributes[LinphoneStreamTypeAudio])
901 		md->streams[call->main_audio_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeAudio]);
902 
903 	md->streams[call->main_video_stream_index].proto=md->streams[call->main_audio_stream_index].proto;
904 	md->streams[call->main_video_stream_index].dir=get_video_dir_from_call_params(params);
905 	md->streams[call->main_video_stream_index].type=SalVideo;
906 	md->streams[call->main_video_stream_index].rtcp_mux = rtcp_mux;
907 	strncpy(md->streams[call->main_video_stream_index].name,"Video",sizeof(md->streams[call->main_video_stream_index].name)-1);
908 
909 	codec_hints.bandwidth_limit=0;
910 	codec_hints.max_codecs=-1;
911 	codec_hints.previously_used=old_md ? old_md->streams[call->main_video_stream_index].already_assigned_payloads : NULL;
912 	l=make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs);
913 
914 	if (params->has_video && l != NULL){
915 		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));
916 		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));
917 		md->streams[call->main_video_stream_index].rtp_port=call->media_ports[call->main_video_stream_index].rtp_port;
918 		md->streams[call->main_video_stream_index].rtcp_port=call->media_ports[call->main_video_stream_index].rtcp_port;
919 		md->streams[call->main_video_stream_index].payloads=l;
920 		if (call->videostream && call->videostream->ms.sessions.rtp_session) {
921 			char* me = linphone_address_as_string_uri_only(call->me);
922 			md->streams[call->main_video_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->videostream->ms.sessions.rtp_session);
923 			strncpy(md->streams[call->main_video_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_video_stream_index].rtcp_cname));
924 			ms_free(me);
925 		}
926 		else
927 			ms_warning("Cannot get video local ssrc for call [%p]",call);
928 		if (call->main_video_stream_index > max_index)
929 			max_index = call->main_video_stream_index;
930 	} else {
931 		ms_message("Don't put video stream on local offer for call [%p]",call);
932 		md->streams[call->main_video_stream_index].dir = SalStreamInactive;
933 		if(l) l=bctbx_list_free_with_data(l, (void (*)(void *))payload_type_destroy);
934 	}
935 	if (params->custom_sdp_media_attributes[LinphoneStreamTypeVideo])
936 		md->streams[call->main_video_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeVideo]);
937 
938 	md->streams[call->main_text_stream_index].proto=md->streams[call->main_audio_stream_index].proto;
939 	md->streams[call->main_text_stream_index].dir=SalStreamSendRecv;
940 	md->streams[call->main_text_stream_index].type=SalText;
941 	md->streams[call->main_text_stream_index].rtcp_mux = rtcp_mux;
942 	strncpy(md->streams[call->main_text_stream_index].name,"Text",sizeof(md->streams[call->main_text_stream_index].name)-1);
943 	if (params->realtimetext_enabled) {
944 		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));
945 		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));
946 
947 		md->streams[call->main_text_stream_index].rtp_port=call->media_ports[call->main_text_stream_index].rtp_port;
948 		md->streams[call->main_text_stream_index].rtcp_port=call->media_ports[call->main_text_stream_index].rtcp_port;
949 
950 		codec_hints.bandwidth_limit=0;
951 		codec_hints.max_codecs=-1;
952 		codec_hints.previously_used=old_md ? old_md->streams[call->main_text_stream_index].already_assigned_payloads : NULL;
953 		l=make_codec_list(lc, &codec_hints, SalText, lc->codecs_conf.text_codecs);
954 		md->streams[call->main_text_stream_index].payloads=l;
955 		if (call->textstream && call->textstream->ms.sessions.rtp_session) {
956 			char* me = linphone_address_as_string_uri_only(call->me);
957 			md->streams[call->main_text_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->textstream->ms.sessions.rtp_session);
958 			strncpy(md->streams[call->main_text_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_text_stream_index].rtcp_cname));
959 			ms_free(me);
960 		}
961 		else
962 			ms_warning("Cannot get text local ssrc for call [%p]",call);
963 		if (call->main_text_stream_index > max_index)
964 			max_index = call->main_text_stream_index;
965 	} else {
966 		ms_message("Don't put text stream on local offer for call [%p]",call);
967 		md->streams[call->main_text_stream_index].dir = SalStreamInactive;
968 	}
969 	if (params->custom_sdp_media_attributes[LinphoneStreamTypeText])
970 		md->streams[call->main_text_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeText]);
971 
972 	md->nb_streams = MAX(md->nb_streams,max_index+1);
973 
974 	/* Deactivate unused streams. */
975 	for (i = md->nb_streams; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
976 		if (md->streams[i].rtp_port == 0) {
977 			md->streams[i].dir = SalStreamInactive;
978 			if (call->biggestdesc && i < call->biggestdesc->nb_streams) {
979 				md->streams[i].proto = call->biggestdesc->streams[i].proto;
980 				md->streams[i].type = call->biggestdesc->streams[i].type;
981 			}
982 		}
983 	}
984 	setup_encryption_keys(call,md);
985 	setup_dtls_keys(call,md);
986 	setup_zrtp_hash(call, md);
987 
988 	setup_rtcp_fb(call, md);
989 	setup_rtcp_xr(call, md);
990 
991 	update_media_description_from_stun(md, &call->ac, &call->vc, &call->tc);
992 	call->localdesc=md;
993 	linphone_call_update_local_media_description_from_ice_or_upnp(call);
994 	linphone_address_unref(addr);
995 	if (old_md){
996 		transfer_already_assigned_payload_types(old_md,md);
997 		call->localdesc_changed=sal_media_description_equals(md,old_md);
998 		sal_media_description_unref(old_md);
999 		if (call->params->internal_call_update){
1000 			/*
1001 			 * An internal call update (ICE reINVITE) is not expected to modify the actual media stream parameters.
1002 			 * However, the localdesc may change between first INVITE and ICE reINVITE, for example if the remote party has declined a video stream.
1003 			 * We use the internal_call_update flag to prevent trigger an unnecessary media restart.
1004 			 */
1005 			call->localdesc_changed = 0;
1006 		}
1007 	}
1008 	force_streams_dir_according_to_state(call, md);
1009 }
1010 
find_port_offset(LinphoneCore * lc,int stream_index,int base_port)1011 static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){
1012 	int offset;
1013 	bctbx_list_t *elem;
1014 	int tried_port;
1015 	int existing_port;
1016 	bool_t already_used=FALSE;
1017 
1018 	for(offset=0;offset<100;offset+=2){
1019 		tried_port=base_port+offset;
1020 		already_used=FALSE;
1021 		for(elem=lc->calls;elem!=NULL;elem=elem->next){
1022 			LinphoneCall *call=(LinphoneCall*)elem->data;
1023 			existing_port=call->media_ports[stream_index].rtp_port;
1024 			if (existing_port==tried_port) {
1025 				already_used=TRUE;
1026 				break;
1027 			}
1028 		}
1029 		if (!already_used) break;
1030 	}
1031 	if (offset==100){
1032 		ms_error("Could not find any free port !");
1033 		return -1;
1034 	}
1035 	return offset;
1036 }
1037 
select_random_port(LinphoneCore * lc,int stream_index,int min_port,int max_port)1038 static int select_random_port(LinphoneCore *lc, int stream_index, int min_port, int max_port) {
1039 	bctbx_list_t *elem;
1040 	int nb_tries;
1041 	int tried_port = 0;
1042 	int existing_port = 0;
1043 	bool_t already_used = FALSE;
1044 
1045 	tried_port = (ortp_random() % (max_port - min_port) + min_port) & ~0x1;
1046 	if (tried_port < min_port) tried_port = min_port + 2;
1047 	for (nb_tries = 0; nb_tries < 100; nb_tries++) {
1048 		for (elem = lc->calls; elem != NULL; elem = elem->next) {
1049 			LinphoneCall *call = (LinphoneCall *)elem->data;
1050 			existing_port=call->media_ports[stream_index].rtp_port;
1051 			if (existing_port == tried_port) {
1052 				already_used = TRUE;
1053 				break;
1054 			}
1055 		}
1056 		if (!already_used) break;
1057 	}
1058 	if (nb_tries == 100) {
1059 		ms_error("Could not find any free port!");
1060 		return -1;
1061 	}
1062 	return tried_port;
1063 }
1064 
port_config_set_random(LinphoneCall * call,int stream_index)1065 static void port_config_set_random(LinphoneCall *call, int stream_index){
1066 	call->media_ports[stream_index].rtp_port=-1;
1067 	call->media_ports[stream_index].rtcp_port=-1;
1068 }
1069 
port_config_set(LinphoneCall * call,int stream_index,int min_port,int max_port)1070 static void port_config_set(LinphoneCall *call, int stream_index, int min_port, int max_port){
1071 	int port_offset;
1072 	if (min_port>0 && max_port>0){
1073 		if (min_port == max_port) {
1074 			/* Used fixed RTP audio port. */
1075 			port_offset=find_port_offset(call->core, stream_index, min_port);
1076 			if (port_offset==-1) {
1077 				port_config_set_random(call, stream_index);
1078 				return;
1079 			}
1080 			call->media_ports[stream_index].rtp_port=min_port+port_offset;
1081 		} else {
1082 			/* Select random RTP audio port in the specified range. */
1083 			call->media_ports[stream_index].rtp_port = select_random_port(call->core, stream_index, min_port, max_port);
1084 		}
1085 		call->media_ports[stream_index].rtcp_port=call->media_ports[stream_index].rtp_port+1;
1086 	}else port_config_set_random(call,stream_index);
1087 }
1088 
linphone_call_init_common(LinphoneCall * call,LinphoneAddress * from,LinphoneAddress * to)1089 static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
1090 	int min_port, max_port;
1091 	ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version());
1092 	call->ei = linphone_error_info_new();
1093 	call->core->send_call_stats_periodical_updates = lp_config_get_int(call->core->config, "misc", "send_call_stats_periodical_updates", 0);
1094 	call->main_audio_stream_index = LINPHONE_CALL_STATS_AUDIO;
1095 	call->main_video_stream_index = LINPHONE_CALL_STATS_VIDEO;
1096 	call->main_text_stream_index = LINPHONE_CALL_STATS_TEXT;
1097 	call->state=LinphoneCallIdle;
1098 	call->transfer_state = LinphoneCallIdle;
1099 	call->log=linphone_call_log_new(call->dir, from, to);
1100 	call->camera_enabled=TRUE;
1101 	call->current_params = linphone_call_params_new();
1102 	call->current_params->media_encryption=LinphoneMediaEncryptionNone;
1103 	call->dtls_certificate_fingerprint = NULL;
1104 	if (call->dir == LinphoneCallIncoming)
1105 		call->me=to;
1106 	 else
1107 		call->me=from;
1108 	linphone_address_ref(call->me);
1109 
1110 	linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
1111 	port_config_set(call,call->main_audio_stream_index,min_port,max_port);
1112 
1113 	linphone_core_get_video_port_range(call->core, &min_port, &max_port);
1114 	port_config_set(call,call->main_video_stream_index,min_port,max_port);
1115 
1116 	linphone_core_get_text_port_range(call->core, &min_port, &max_port);
1117 	port_config_set(call,call->main_text_stream_index,min_port,max_port);
1118 
1119 	linphone_call_init_stats(call->audio_stats, LINPHONE_CALL_STATS_AUDIO);
1120 	linphone_call_init_stats(call->video_stats, LINPHONE_CALL_STATS_VIDEO);
1121 	linphone_call_init_stats(call->text_stats, LINPHONE_CALL_STATS_TEXT);
1122 
1123 	if (call->dest_proxy == NULL) {
1124 		/* Try to define the destination proxy if it has not already been done to have a correct contact field in the SIP messages */
1125 		call->dest_proxy = linphone_core_lookup_known_proxy(call->core, call->log->to);
1126 	}
1127 
1128 
1129 	if (call->dest_proxy != NULL)
1130 		call->nat_policy = linphone_proxy_config_get_nat_policy(call->dest_proxy);
1131 	if (call->nat_policy == NULL)
1132 		call->nat_policy = linphone_core_get_nat_policy(call->core);
1133 
1134 	linphone_nat_policy_ref(call->nat_policy);
1135 
1136 }
1137 
linphone_call_init_stats(LinphoneCallStats * stats,int type)1138 void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
1139 	stats->type = type;
1140 	stats->received_rtcp = NULL;
1141 	stats->sent_rtcp = NULL;
1142 	stats->ice_state = LinphoneIceStateNotActivated;
1143 #ifdef BUILD_UPNP
1144 	stats->upnp_state = LinphoneUpnpStateIdle;
1145 #else
1146 	stats->upnp_state = LinphoneUpnpStateNotAvailable;
1147 #endif //BUILD_UPNP
1148 }
1149 
discover_mtu(LinphoneCore * lc,const char * remote)1150 static void discover_mtu(LinphoneCore *lc, const char *remote){
1151 	int mtu;
1152 	if (lc->net_conf.mtu==0	){
1153 		/*attempt to discover mtu*/
1154 		mtu=ms_discover_mtu(remote);
1155 		if (mtu>0){
1156 			ms_factory_set_mtu(lc->factory, mtu);
1157 			ms_message("Discovered mtu is %i, RTP payload max size is %i",
1158 				mtu, ms_factory_get_payload_max_size(lc->factory));
1159 		}
1160 	}
1161 }
1162 
linphone_call_create_op(LinphoneCall * call)1163 void linphone_call_create_op(LinphoneCall *call){
1164 	if (call->op) sal_op_release(call->op);
1165 	call->op=sal_op_new(call->core->sal);
1166 	sal_op_set_user_pointer(call->op,call);
1167 	if (call->params->referer)
1168 		sal_call_set_referer(call->op,call->params->referer->op);
1169 	linphone_configure_op(call->core,call->op,call->log->to,call->params->custom_headers,FALSE);
1170 	if (call->params->privacy != LinphonePrivacyDefault)
1171 		sal_op_set_privacy(call->op,(SalPrivacyMask)call->params->privacy);
1172 	/*else privacy might be set by proxy */
1173 }
1174 
1175 /*
1176  * Choose IP version we are going to use for RTP streams IP address advertised in SDP.
1177  * The algorithm is as follows:
1178  * - if ipv6 is disabled at the core level, it is always AF_INET
1179  * - Otherwise, if the destination address for the call is an IPv6 address, use IPv6.
1180  * - Otherwise, if the call is done through a known proxy config, then use the information obtained during REGISTER
1181  * to know if IPv6 is supported by the server.
1182 **/
linphone_call_outgoing_select_ip_version(LinphoneCall * call,LinphoneAddress * to,LinphoneProxyConfig * cfg)1183 static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, LinphoneAddress *to, LinphoneProxyConfig *cfg){
1184 	if (linphone_core_ipv6_enabled(call->core)){
1185 		if (sal_address_is_ipv6((SalAddress*)to)){
1186 			call->af=AF_INET6;
1187 		}else if (cfg && cfg->op){
1188 			call->af=sal_op_get_address_family(cfg->op);
1189 		}else{
1190 			call->af=AF_UNSPEC;
1191 		}
1192 		if (call->af == AF_UNSPEC) {
1193 			char ipv4[LINPHONE_IPADDR_SIZE];
1194 			char ipv6[LINPHONE_IPADDR_SIZE];
1195 			bool_t have_ipv6 = FALSE;
1196 			bool_t have_ipv4 = FALSE;
1197 			/*check connectivity for IPv4 and IPv6*/
1198 			if (linphone_core_get_local_ip_for(AF_INET6, NULL, ipv6) == 0){
1199 				have_ipv6 = TRUE;
1200 			}
1201 			if (linphone_core_get_local_ip_for(AF_INET, NULL, ipv4) == 0){
1202 				have_ipv4 = TRUE;
1203 			}
1204 			if (have_ipv6){
1205 				if (!have_ipv4) {
1206 					call->af = AF_INET6;
1207 				}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*/
1208 					call->af = AF_INET6;
1209 				}else{
1210 					call->af = AF_INET;
1211 				}
1212 			}else call->af = AF_INET;
1213 			/*fill the media_localip default value since we have it here*/
1214 			strncpy(call->media_localip,call->af == AF_INET6 ? ipv6 : ipv4, LINPHONE_IPADDR_SIZE);
1215 		}
1216 	}else call->af=AF_INET;
1217 }
1218 
1219 /**
1220  * Fill the local ip that routes to the internet according to the destination, or guess it by other special means (upnp).
1221  */
linphone_call_get_local_ip(LinphoneCall * call,const LinphoneAddress * remote_addr)1222 static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr){
1223 	const char *ip = NULL;
1224 	int af = call->af;
1225 	const char *dest = NULL;
1226 
1227 	if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
1228 		&& (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){
1229 		strncpy(call->media_localip,ip,LINPHONE_IPADDR_SIZE);
1230 		return;
1231 	}
1232 #ifdef BUILD_UPNP
1233 	else if (call->core->upnp != NULL && linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseUpnp &&
1234 			linphone_upnp_context_get_state(call->core->upnp) == LinphoneUpnpStateOk) {
1235 		ip = linphone_upnp_context_get_external_ipaddress(call->core->upnp);
1236 		strncpy(call->media_localip,ip,LINPHONE_IPADDR_SIZE);
1237 		goto found;
1238 	}
1239 #endif //BUILD_UPNP
1240 
1241 	/*next, sometime, override from config*/
1242 	if ((ip=lp_config_get_string(call->core->config,"rtp","bind_address",NULL)) != NULL)
1243 		goto found;
1244 
1245 	/*if a known proxy was identified for this call, then we may have a chance to take the local ip address
1246 	* from the socket that connect to this proxy */
1247 	if (call->dest_proxy && call->dest_proxy->op){
1248 		if ((ip = sal_op_get_local_address(call->dest_proxy->op, NULL)) != NULL){
1249 			ms_message("Found media local-ip from signaling.");
1250 			goto found;
1251 		}
1252 	}
1253 
1254 	/*in last resort, attempt to find the local ip that routes to destination if given as an IP address,
1255 	 or the default route (dest=NULL)*/
1256 	if (call->dest_proxy == NULL) {
1257 		struct addrinfo hints;
1258 		struct addrinfo *res = NULL;
1259 		int err;
1260 		/*FIXME the following doesn't work for IPv6 address because of brakets*/
1261 		const char *domain = linphone_address_get_domain(remote_addr);
1262 		memset(&hints, 0, sizeof(hints));
1263 		hints.ai_family = AF_UNSPEC;
1264 		hints.ai_socktype = SOCK_DGRAM;
1265 		hints.ai_flags = AI_NUMERICHOST;
1266 		err = getaddrinfo(domain, NULL, &hints, &res);
1267 		if (err == 0) {
1268 			dest = domain;
1269 		}
1270 		if (res != NULL) freeaddrinfo(res);
1271 	}
1272 
1273 	if (dest != NULL || call->media_localip[0] == '\0' || call->need_localip_refresh){
1274 		call->need_localip_refresh = FALSE;
1275 		linphone_core_get_local_ip(call->core, af, dest, call->media_localip);
1276 	}
1277 	return;
1278 found:
1279 	strncpy(call->media_localip,ip,LINPHONE_IPADDR_SIZE);
1280 }
1281 
1282 static void linphone_call_destroy(LinphoneCall *obj);
1283 
1284 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCall);
1285 
1286 BELLE_SIP_INSTANCIATE_VPTR(LinphoneCall, belle_sip_object_t,
1287 	(belle_sip_object_destroy_t)linphone_call_destroy,
1288 	NULL, // clone
1289 	NULL, // marshal
1290 	FALSE
1291 );
1292 
linphone_call_fill_media_multicast_addr(LinphoneCall * call)1293 void linphone_call_fill_media_multicast_addr(LinphoneCall *call) {
1294 	if (linphone_call_params_audio_multicast_enabled(call->params)){
1295 		strncpy(call->media_ports[call->main_audio_stream_index].multicast_ip,
1296 				linphone_core_get_audio_multicast_addr(call->core), sizeof(call->media_ports[call->main_audio_stream_index].multicast_ip));
1297 	} else
1298 		call->media_ports[call->main_audio_stream_index].multicast_ip[0]='\0';
1299 
1300 	if (linphone_call_params_video_multicast_enabled(call->params)){
1301 		strncpy(call->media_ports[call->main_video_stream_index].multicast_ip,
1302 				linphone_core_get_video_multicast_addr(call->core), sizeof(call->media_ports[call->main_video_stream_index].multicast_ip));
1303 	} else
1304 		call->media_ports[call->main_video_stream_index].multicast_ip[0]='\0';
1305 }
1306 
linphone_call_check_ice_session(LinphoneCall * call,IceRole role,bool_t is_reinvite)1307 void linphone_call_check_ice_session(LinphoneCall *call, IceRole role, bool_t is_reinvite){
1308 	if (call->ice_session) return; /*already created*/
1309 
1310 	if (!linphone_nat_policy_ice_enabled(call->nat_policy)){
1311 		return;
1312 	}
1313 
1314 	if (is_reinvite && lp_config_get_int(call->core->config, "net", "allow_late_ice", 0) == 0) return;
1315 
1316 	call->ice_session = ice_session_new();
1317 	/*for backward compatibility purposes, shall be enabled by default in futur*/
1318 	ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(call->core->config,"net","ice_session_enable_message_integrity_check",1));
1319 	if (lp_config_get_int(call->core->config, "net", "dont_default_to_stun_candidates", 0)){
1320 		IceCandidateType types[ICT_CandidateTypeMax];
1321 		types[0] = ICT_HostCandidate;
1322 		types[1] = ICT_RelayedCandidate;
1323 		types[2] = ICT_CandidateInvalid;
1324 		ice_session_set_default_candidates_types(call->ice_session, types);
1325 	}
1326 	ice_session_set_role(call->ice_session, role);
1327 }
1328 
linphone_call_new_outgoing(struct _LinphoneCore * lc,LinphoneAddress * from,LinphoneAddress * to,const LinphoneCallParams * params,LinphoneProxyConfig * cfg)1329 LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
1330 	LinphoneCall *call = belle_sip_object_new(LinphoneCall);
1331 	call->dir=LinphoneCallOutgoing;
1332 	call->core=lc;
1333 	call->dest_proxy=cfg;
1334 	call->audio_stats = linphone_call_stats_ref(linphone_call_stats_new());
1335 	call->video_stats = linphone_call_stats_ref(linphone_call_stats_new());
1336 	call->text_stats = linphone_call_stats_ref(linphone_call_stats_new());
1337 	linphone_call_outgoing_select_ip_version(call,to,cfg);
1338 	linphone_call_get_local_ip(call, to);
1339 	call->params = linphone_call_params_copy(params);
1340 	linphone_call_init_common(call, from, to);
1341 
1342 	call->current_params->update_call_when_ice_completed = call->params->update_call_when_ice_completed; /*copy param*/
1343 
1344 	linphone_call_fill_media_multicast_addr(call);
1345 
1346 	linphone_call_check_ice_session(call, IR_Controlling, FALSE);
1347 
1348 	if (linphone_nat_policy_ice_enabled(call->nat_policy)) {
1349 		call->ping_time=linphone_core_run_stun_tests(call->core,call);
1350 	}
1351 #ifdef BUILD_UPNP
1352 	if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
1353 		if(!lc->rtp_conf.disable_upnp) {
1354 			call->upnp_session = linphone_upnp_session_new(call);
1355 		}
1356 	}
1357 #endif //BUILD_UPNP
1358 
1359 	discover_mtu(lc,linphone_address_get_domain (to));
1360 	if (params->referer){
1361 		call->referer=linphone_call_ref(params->referer);
1362 	}
1363 
1364 	linphone_call_create_op(call);
1365 	return call;
1366 }
1367 
1368 /*Select IP version to use for advertising local addresses of RTP streams, for an incoming call.
1369  *If the call is received through a know proxy that is IPv6, use IPv6.
1370  *Otherwise check the remote contact address.
1371  *If later the resulting media description tells that we have to send IPv4, it won't be a problem because the RTP sockets
1372  * are dual stack.
1373  */
linphone_call_incoming_select_ip_version(LinphoneCall * call,LinphoneProxyConfig * cfg)1374 static void linphone_call_incoming_select_ip_version(LinphoneCall *call, LinphoneProxyConfig *cfg){
1375 	if (linphone_core_ipv6_enabled(call->core)){
1376 		if (cfg && cfg->op){
1377 			call->af=sal_op_get_address_family(cfg->op);
1378 		}else{
1379 			call->af=sal_op_get_address_family(call->op);
1380 		}
1381 	}else call->af=AF_INET;
1382 }
1383 
1384 /**
1385  * Fix call parameters on incoming call to eg. enable AVPF if the incoming call propose it and it is not enabled locally.
1386  */
linphone_call_set_compatible_incoming_call_parameters(LinphoneCall * call,SalMediaDescription * md)1387 void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, SalMediaDescription *md) {
1388 	/* Handle AVPF, SRTP and DTLS. */
1389 	call->params->avpf_enabled = sal_media_description_has_avpf(md);
1390 	if (call->dest_proxy != NULL) {
1391 		call->params->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000;
1392 	} else {
1393 		call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000;
1394 	}
1395 
1396 	if ((sal_media_description_has_zrtp(md) == TRUE) && (linphone_core_media_encryption_supported(call->core, LinphoneMediaEncryptionZRTP) == TRUE)) {
1397 		call->params->media_encryption = LinphoneMediaEncryptionZRTP;
1398 	}else if ((sal_media_description_has_dtls(md) == TRUE) && (media_stream_dtls_supported() == TRUE)) {
1399 		call->params->media_encryption = LinphoneMediaEncryptionDTLS;
1400 	}else if ((sal_media_description_has_srtp(md) == TRUE) && (ms_srtp_supported() == TRUE)) {
1401 		call->params->media_encryption = LinphoneMediaEncryptionSRTP;
1402 	}else if (call->params->media_encryption != LinphoneMediaEncryptionZRTP){
1403 		call->params->media_encryption = LinphoneMediaEncryptionNone;
1404 	}
1405 
1406 	/*in case of nat64, even ipv4 addresses are reachable from v6. Should be enhanced to manage stream by stream connectivity (I.E v6 or v4)*/
1407 	/*if (!sal_media_description_has_ipv6(md)){
1408 		ms_message("The remote SDP doesn't seem to offer any IPv6 connectivity, so disabling IPv6 for this call.");
1409 		call->af = AF_INET;
1410 	}*/
1411 	linphone_call_fix_call_parameters(call, md);
1412 }
1413 
linphone_call_compute_streams_indexes(LinphoneCall * call,const SalMediaDescription * md)1414 static void linphone_call_compute_streams_indexes(LinphoneCall *call, const SalMediaDescription *md) {
1415 	int i, j;
1416 	bool_t audio_found = FALSE, video_found = FALSE, text_found = FALSE;
1417 
1418 	for (i = 0; i < md->nb_streams; i++) {
1419 		if (md->streams[i].type == SalAudio) {
1420 			if (!audio_found) {
1421 				call->main_audio_stream_index = i;
1422 				audio_found = TRUE;
1423 				ms_message("audio stream index found: %i, updating main audio stream index", i);
1424 			} else {
1425 				ms_message("audio stream index found: %i, but main audio stream already set to %i", i, call->main_audio_stream_index);
1426 			}
1427 
1428 			// Check that the default value of a another stream doesn't match the new one
1429 			if (i == call->main_video_stream_index) {
1430 				for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) {
1431 					if (sal_stream_description_active(&md->streams[j])) continue;
1432 					if (j != call->main_video_stream_index && j != call->main_text_stream_index) {
1433 						ms_message("%i was used for video stream ; now using %i", i, j);
1434 						call->main_video_stream_index = j;
1435 						break;
1436 					}
1437 				}
1438 			}
1439 			if (i == call->main_text_stream_index) {
1440 				for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) {
1441 					if (sal_stream_description_active(&md->streams[j])) continue;
1442 					if (j != call->main_video_stream_index && j != call->main_text_stream_index) {
1443 						ms_message("%i was used for text stream ; now using %i", i, j);
1444 						call->main_text_stream_index = j;
1445 						break;
1446 					}
1447 				}
1448 			}
1449 		} else if (md->streams[i].type == SalVideo) {
1450 			if (!video_found) {
1451 				call->main_video_stream_index = i;
1452 				video_found = TRUE;
1453 				ms_message("video stream index found: %i, updating main video stream index", i);
1454 			} else {
1455 				ms_message("video stream index found: %i, but main video stream already set to %i", i, call->main_video_stream_index);
1456 			}
1457 
1458 			// Check that the default value of a another stream doesn't match the new one
1459 			if (i == call->main_audio_stream_index) {
1460 				for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) {
1461 					if (sal_stream_description_active(&md->streams[j])) continue;
1462 					if (j != call->main_audio_stream_index && j != call->main_text_stream_index) {
1463 						ms_message("%i was used for audio stream ; now using %i", i, j);
1464 						call->main_audio_stream_index = j;
1465 						break;
1466 					}
1467 				}
1468 			}
1469 			if (i == call->main_text_stream_index) {
1470 				for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) {
1471 					if (sal_stream_description_active(&md->streams[j])) continue;
1472 					if (j != call->main_audio_stream_index && j != call->main_text_stream_index) {
1473 						ms_message("%i was used for text stream ; now using %i", i, j);
1474 						call->main_text_stream_index = j;
1475 						break;
1476 					}
1477 				}
1478 			}
1479 		} else if (md->streams[i].type == SalText) {
1480 			if (!text_found) {
1481 				call->main_text_stream_index = i;
1482 				text_found = TRUE;
1483 				ms_message("text stream index found: %i, updating main text stream index", i);
1484 			} else {
1485 				ms_message("text stream index found: %i, but main text stream already set to %i", i, call->main_text_stream_index);
1486 			}
1487 
1488 			// Check that the default value of a another stream doesn't match the new one
1489 			if (i == call->main_audio_stream_index) {
1490 				for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) {
1491 					if (sal_stream_description_active(&md->streams[j])) continue;
1492 					if (j != call->main_video_stream_index && j != call->main_audio_stream_index) {
1493 						ms_message("%i was used for audio stream ; now using %i", i, j);
1494 						call->main_audio_stream_index = j;
1495 						break;
1496 					}
1497 				}
1498 			}
1499 			if (i == call->main_video_stream_index) {
1500 				for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) {
1501 					if (sal_stream_description_active(&md->streams[j])) continue;
1502 					if (j != call->main_video_stream_index && j != call->main_audio_stream_index) {
1503 						ms_message("%i was used for video stream ; now using %i", i, j);
1504 						call->main_video_stream_index = j;
1505 						break;
1506 					}
1507 				}
1508 			}
1509 		}
1510 	}
1511 }
1512 
linphone_call_new_incoming(LinphoneCore * lc,LinphoneAddress * from,LinphoneAddress * to,SalOp * op)1513 LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
1514 	LinphoneCall *call = belle_sip_object_new(LinphoneCall);
1515 	SalMediaDescription *md;
1516 	LinphoneNatPolicy *nat_policy = NULL;
1517 	int i;
1518 	call->dir=LinphoneCallIncoming;
1519 	call->audio_stats = linphone_call_stats_ref(linphone_call_stats_new());
1520 	call->video_stats = linphone_call_stats_ref(linphone_call_stats_new());
1521 	call->text_stats = linphone_call_stats_ref(linphone_call_stats_new());
1522 	sal_op_set_user_pointer(op,call);
1523 	call->op=op;
1524 	call->core=lc;
1525 
1526 	call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to);
1527 	linphone_call_incoming_select_ip_version(call, call->dest_proxy);
1528 	/*note that the choice of IP version for streams is later refined by
1529 	 * linphone_call_set_compatible_incoming_call_parameters() when examining the remote offer, if any.
1530 	 * If the remote offer contains IPv4 addresses, we should propose IPv4 as well*/
1531 
1532 	sal_op_cnx_ip_to_0000_if_sendonly_enable(op,lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0));
1533 
1534 	md = sal_call_get_remote_media_description(op);
1535 
1536 	if (lc->sip_conf.ping_with_options){
1537 #ifdef BUILD_UPNP
1538 		if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
1539 			linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
1540 #else //BUILD_UPNP
1541 		{
1542 #endif //BUILD_UPNP
1543 			/*the following sends an option request back to the caller so that
1544 			 we get a chance to discover our nat'd address before answering.*/
1545 			call->ping_op=sal_op_new(lc->sal);
1546 
1547 			linphone_configure_op(lc, call->ping_op, from, NULL, FALSE);
1548 
1549 			sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
1550 			sal_op_set_user_pointer(call->ping_op,call);
1551 
1552 			sal_ping(call->ping_op,sal_op_get_from(call->ping_op), sal_op_get_to(call->ping_op));
1553 		}
1554 	}
1555 
1556 	linphone_address_clean(from);
1557 	linphone_call_get_local_ip(call, from);
1558 	call->params = linphone_call_params_new();
1559 	linphone_call_init_common(call, from, to);
1560 	call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
1561 	linphone_core_init_default_params(lc, call->params);
1562 
1563 	/*
1564 	 * Initialize call parameters according to incoming call parameters. This is to avoid to ask later (during reINVITEs) for features that the remote
1565 	 * end apparently does not support. This features are: privacy, video
1566 	 */
1567 	/*set privacy*/
1568 	call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
1569 	/*config params*/
1570 	call->current_params->update_call_when_ice_completed = call->params->update_call_when_ice_completed; /*copy config params*/
1571 
1572 	/*set video support */
1573 	call->params->has_video = linphone_core_video_enabled(lc) && lc->video_policy.automatically_accept;
1574 	if (md) {
1575 		// It is licit to receive an INVITE without SDP
1576 		// In this case WE chose the media parameters according to policy.
1577 		linphone_call_set_compatible_incoming_call_parameters(call, md);
1578 		/* set multicast role & address if any*/
1579 		if (!sal_call_is_offerer(op)){
1580 			for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
1581 				if (md->streams[i].dir == SalStreamInactive) {
1582 					continue;
1583 				}
1584 
1585 				if (md->streams[i].rtp_addr[0]!='\0' && ms_is_multicast(md->streams[i].rtp_addr)){
1586 					md->streams[i].multicast_role = SalMulticastReceiver;
1587 					strncpy(call->media_ports[i].multicast_ip,md->streams[i].rtp_addr,sizeof(call->media_ports[i].multicast_ip));
1588 				}
1589 			}
1590 		}
1591 	}
1592 
1593 	nat_policy=call->nat_policy;
1594 	if ((nat_policy != NULL) && linphone_nat_policy_ice_enabled(nat_policy)) {
1595 		/* Create the ice session now if ICE is required */
1596 		if (md){
1597 			linphone_call_check_ice_session(call, IR_Controlled, FALSE);
1598 		}else{
1599 			nat_policy = NULL;
1600 			ms_warning("ICE not supported for incoming INVITE without SDP.");
1601 		}
1602 	}
1603 
1604 	/*reserve the sockets immediately*/
1605 	linphone_call_init_media_streams(call);
1606 	if (nat_policy != NULL) {
1607 		if (linphone_nat_policy_ice_enabled(nat_policy)) {
1608 			call->defer_notify_incoming = linphone_call_prepare_ice(call,TRUE) == 1;
1609 		} else if (linphone_nat_policy_stun_enabled(nat_policy)) {
1610 			call->ping_time=linphone_core_run_stun_tests(call->core,call);
1611 		} else if (linphone_nat_policy_upnp_enabled(nat_policy)) {
1612 #ifdef BUILD_UPNP
1613 			if(!lc->rtp_conf.disable_upnp) {
1614 				call->upnp_session = linphone_upnp_session_new(call);
1615 				if (call->upnp_session != NULL) {
1616 					if (linphone_call_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) {
1617 						/* uPnP port mappings failed, proceed with the call anyway. */
1618 						linphone_call_delete_upnp_session(call);
1619 					}
1620 				}
1621 			}
1622 #endif //BUILD_UPNP
1623 		}
1624 	}
1625 
1626 	discover_mtu(lc,linphone_address_get_domain(from));
1627 	return call;
1628 }
1629 
1630 /*
1631  * Frees the media resources of the call.
1632  * This has to be done at the earliest, unlike signaling resources that sometimes need to be kept a bit more longer.
1633  * It is called by linphone_call_set_terminated() (for termination of calls signaled to the application), or directly by the destructor of LinphoneCall
1634  * (_linphone_call_destroy) if the call was never notified to the application.
1635  */
1636 static void linphone_call_free_media_resources(LinphoneCall *call){
1637 	int i;
1638 
1639 	linphone_call_stop_media_streams(call);
1640 	linphone_call_delete_upnp_session(call);
1641 	linphone_call_delete_ice_session(call);
1642 	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
1643 		ms_media_stream_sessions_uninit(&call->sessions[i]);
1644 	}
1645 	linphone_call_stats_uninit(call->audio_stats);
1646 	linphone_call_stats_uninit(call->video_stats);
1647 	linphone_call_stats_uninit(call->text_stats);
1648 }
1649 
1650 /*
1651  * Called internally when reaching the Released state, to perform cleanups to break circular references.
1652 **/
1653 static void linphone_call_set_released(LinphoneCall *call){
1654 	if (call->op!=NULL) {
1655 		/*transfer the last error so that it can be obtained even in Released state*/
1656 		if (!call->non_op_error){
1657 			linphone_error_info_from_sal_op(call->ei, call->op);
1658 		}
1659 		/* so that we cannot have anymore upcalls for SAL
1660 			concerning this call*/
1661 		sal_op_release(call->op);
1662 		call->op=NULL;
1663 	}
1664 	/*it is necessary to reset pointers to other call to prevent circular references that would result in memory never freed.*/
1665 	if (call->referer){
1666 		linphone_call_unref(call->referer);
1667 		call->referer=NULL;
1668 	}
1669 	if (call->transfer_target){
1670 		linphone_call_unref(call->transfer_target);
1671 		call->transfer_target=NULL;
1672 	}
1673 	if (call->chat_room){
1674 		linphone_chat_room_unref(call->chat_room);
1675 		call->chat_room = NULL;
1676 	}
1677 	linphone_call_unref(call);
1678 }
1679 
1680 /* this function is called internally to get rid of a call that was notified to the application, because it reached the end or error state.
1681  It performs the following tasks:
1682  - remove the call from the internal list of calls
1683  - update the call logs accordingly
1684 */
1685 static void linphone_call_set_terminated(LinphoneCall *call){
1686 	LinphoneCore *lc=call->core;
1687 
1688 	linphone_call_free_media_resources(call);
1689 	linphone_call_log_completed(call);
1690 
1691 	if (call == lc->current_call){
1692 		ms_message("Resetting the current call");
1693 		lc->current_call=NULL;
1694 	}
1695 
1696 	if (linphone_core_del_call(lc,call) != 0){
1697 		ms_error("Could not remove the call from the list !!!");
1698 	}
1699 	if(lc->conf_ctx) linphone_conference_on_call_terminating(lc->conf_ctx, call);
1700 	if (call->ringing_beep){
1701 		linphone_core_stop_dtmf(lc);
1702 		call->ringing_beep=FALSE;
1703 	}
1704 	if (call->chat_room){
1705 		call->chat_room->call = NULL;
1706 	}
1707 }
1708 
1709 /*function to be called at each incoming reINVITE, in order to adjust various local parameters to what is being offered by remote:
1710  * - the video enablement parameter according to what is offered and our local policy.
1711  * Fixing the call->params to proper values avoid request video by accident during internal call updates, pauses and resumes
1712  * - the stream indexes.
1713  */
1714 void linphone_call_fix_call_parameters(LinphoneCall *call, SalMediaDescription *rmd){
1715 	const LinphoneCallParams* rcp;
1716 
1717 	if (rmd) {
1718 		linphone_call_compute_streams_indexes(call, rmd);
1719 		linphone_call_update_biggest_desc(call, rmd);
1720 		/* Why disabling implicit_rtcp_fb ? It is a local policy choice actually. It doesn't disturb to propose it again and again
1721 		 * even if the other end apparently doesn't support it.
1722 		 * The following line of code is causing trouble, while for example making an audio call, then adding video.
1723 		 * Due to the 200Ok response of the audio-only offer where no rtcp-fb attribute is present, implicit_rtcp_fb is set to
1724 		 * FALSE, which is then preventing it to be eventually used when video is later added to the call.
1725 		 * I did the choice of commenting it out.
1726 		 */
1727 		/*call->params->implicit_rtcp_fb &= sal_media_description_has_implicit_avpf(rmd);*/
1728 	}
1729 	rcp = linphone_call_get_remote_params(call);
1730 	if (rcp){
1731 		if (call->params->has_audio && !rcp->has_audio){
1732 			ms_message("Call [%p]: disabling audio in our call params because the remote doesn't want it.", call);
1733 			call->params->has_audio = FALSE;
1734 		}
1735 		if (call->params->has_video && !rcp->has_video){
1736 			ms_message("Call [%p]: disabling video in our call params because the remote doesn't want it.", call);
1737 			call->params->has_video = FALSE;
1738 		}
1739 
1740 		if (rcp->has_video && call->core->video_policy.automatically_accept && linphone_core_video_enabled(call->core) && !call->params->has_video){
1741 			ms_message("Call [%p]: re-enabling video in our call params because the remote wants it and the policy allows to automatically accept.", call);
1742 			linphone_call_params_enable_video(call->params, TRUE);
1743 		}
1744 
1745 		if (rcp->realtimetext_enabled && !call->params->realtimetext_enabled) {
1746 			call->params->realtimetext_enabled = TRUE;
1747 		}
1748 	}
1749 }
1750 
1751 const char *linphone_call_state_to_string(LinphoneCallState cs){
1752 	switch (cs){
1753 		case LinphoneCallIdle:
1754 			return "LinphoneCallIdle";
1755 		case LinphoneCallIncomingReceived:
1756 			return "LinphoneCallIncomingReceived";
1757 		case LinphoneCallOutgoingInit:
1758 			return "LinphoneCallOutgoingInit";
1759 		case LinphoneCallOutgoingProgress:
1760 			return "LinphoneCallOutgoingProgress";
1761 		case LinphoneCallOutgoingRinging:
1762 			return "LinphoneCallOutgoingRinging";
1763 		case LinphoneCallOutgoingEarlyMedia:
1764 			return "LinphoneCallOutgoingEarlyMedia";
1765 		case LinphoneCallConnected:
1766 			return "LinphoneCallConnected";
1767 		case LinphoneCallStreamsRunning:
1768 			return "LinphoneCallStreamsRunning";
1769 		case LinphoneCallPausing:
1770 			return "LinphoneCallPausing";
1771 		case LinphoneCallPaused:
1772 			return "LinphoneCallPaused";
1773 		case LinphoneCallResuming:
1774 			return "LinphoneCallResuming";
1775 		case LinphoneCallRefered:
1776 			return "LinphoneCallRefered";
1777 		case LinphoneCallError:
1778 			return "LinphoneCallError";
1779 		case LinphoneCallEnd:
1780 			return "LinphoneCallEnd";
1781 		case LinphoneCallPausedByRemote:
1782 			return "LinphoneCallPausedByRemote";
1783 		case LinphoneCallUpdatedByRemote:
1784 			return "LinphoneCallUpdatedByRemote";
1785 		case LinphoneCallIncomingEarlyMedia:
1786 			return "LinphoneCallIncomingEarlyMedia";
1787 		case LinphoneCallUpdating:
1788 			return "LinphoneCallUpdating";
1789 		case LinphoneCallReleased:
1790 			return "LinphoneCallReleased";
1791 		case LinphoneCallEarlyUpdatedByRemote:
1792 			return "LinphoneCallEarlyUpdatedByRemote";
1793 		case LinphoneCallEarlyUpdating:
1794 			return "LinphoneCallEarlyUpdating";
1795 	}
1796 	return "undefined state";
1797 }
1798 
1799 void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
1800 	LinphoneCore *lc=call->core;
1801 
1802 	if (call->state!=cstate){
1803 		call->prevstate=call->state;
1804 
1805 		/*Make sanity checks with call state changes. Any bad transition can result in unpredictable results
1806 		 *or irrecoverable errors in the application*/
1807 		if (call->state==LinphoneCallEnd || call->state==LinphoneCallError){
1808 			if (cstate!=LinphoneCallReleased){
1809 				ms_fatal("Abnormal call resurection from %s to %s, aborting."	,linphone_call_state_to_string(call->state)
1810 																				,linphone_call_state_to_string(cstate));
1811 				return;
1812 			}
1813 		}else if (cstate == LinphoneCallReleased && (call->prevstate != LinphoneCallError && call->prevstate != LinphoneCallEnd)){
1814 			ms_fatal("Attempt to move call [%p] to Released state while it was not previously in Error or End state. Aborting.", call);
1815 			return;
1816 		}
1817 		ms_message("Call %p: moving from state %s to %s",call
1818 														,linphone_call_state_to_string(call->state)
1819 														,linphone_call_state_to_string(cstate));
1820 
1821 		if (cstate!=LinphoneCallRefered){
1822 			/*LinphoneCallRefered is rather an event, not a state.
1823 			 Indeed it does not change the state of the call (still paused or running)*/
1824 			call->state=cstate;
1825 		}
1826 
1827 		switch (cstate) {
1828 		case LinphoneCallOutgoingInit:
1829 		case LinphoneCallIncomingReceived:
1830 #ifdef __ANDROID__
1831 			ms_message("Call [%p] acquires both wifi and multicast lock",call);
1832 			linphone_core_wifi_lock_acquire(call->core);
1833 			linphone_core_multicast_lock_acquire(call->core); /*does no affect battery more than regular rtp traffic*/
1834 #endif
1835 			break;
1836 		case LinphoneCallEnd:
1837 		case LinphoneCallError:
1838 			switch(linphone_error_info_get_reason(linphone_call_get_error_info(call))) {
1839 			case LinphoneReasonDeclined:
1840 				call->log->status=LinphoneCallDeclined;
1841 				break;
1842 			case LinphoneReasonNotAnswered:
1843 				if (call->log->dir == LinphoneCallIncoming){
1844 					call->log->status=LinphoneCallMissed;
1845 				}
1846 				break;
1847 			default:
1848 				break;
1849 			}
1850 			linphone_call_set_terminated(call);
1851 			break;
1852 		case LinphoneCallConnected:
1853 			call->log->status=LinphoneCallSuccess;
1854 			call->log->connected_date_time = ms_time(NULL);
1855 			break;
1856 		case LinphoneCallReleased:
1857 #ifdef __ANDROID__
1858 			ms_message("Call [%p] releases wifi/multicast lock",call);
1859 			linphone_core_wifi_lock_release(call->core);
1860 			linphone_core_multicast_lock_release(call->core);
1861 #endif
1862 			break;
1863 		case LinphoneCallStreamsRunning:
1864 			if (call->prevstate == LinphoneCallUpdating || call->prevstate == LinphoneCallUpdatedByRemote) {
1865 				LinphoneReason reason = linphone_call_get_reason(call);
1866 				char *msg;
1867 				if (reason != LinphoneReasonNone) {
1868 					msg = ms_strdup_printf(_("Call parameters could not be modified: %s."), linphone_reason_to_string(reason));
1869 				} else {
1870 					msg = ms_strdup(_("Call parameters were successfully modified."));
1871 				}
1872 				linphone_core_notify_display_status(lc, msg);
1873 				ms_free(msg);
1874 			}
1875 			break;
1876 		default:
1877 			break;
1878 		}
1879 
1880 		if(cstate!=LinphoneCallStreamsRunning) {
1881 			if (call->dtmfs_timer!=NULL){
1882 				/*cancelling DTMF sequence, if any*/
1883 				linphone_call_cancel_dtmfs(call);
1884 			}
1885 		}
1886 		if (!message) {
1887 			ms_error("%s(): You must fill a reason when changing call state (from %s o %s)."
1888 					, __FUNCTION__
1889 					, linphone_call_state_to_string(call->prevstate)
1890 					, linphone_call_state_to_string(call->state));
1891 		}
1892 		linphone_call_notify_state_changed(call, cstate, message ? message : "");
1893 		linphone_reporting_call_state_updated(call);
1894 		if (cstate==LinphoneCallReleased) {/*shall be performed after  app notification*/
1895 			linphone_call_set_released(call);
1896 		}
1897 	}
1898 }
1899 
1900 static void linphone_call_destroy(LinphoneCall *obj){
1901 	ms_message("Call [%p] freed.",obj);
1902 	bctbx_list_free_with_data(obj->callbacks, (bctbx_list_free_func)linphone_call_cbs_unref);
1903 	if (obj->audiostream || obj->videostream){
1904 		linphone_call_free_media_resources(obj);
1905 	}
1906 	if (obj->audio_stats) {
1907 		linphone_call_stats_unref(obj->audio_stats);
1908 		obj->audio_stats = NULL;
1909 	}
1910 	if (obj->video_stats) {
1911 		linphone_call_stats_unref(obj->video_stats);
1912 		obj->video_stats = NULL;
1913 	}
1914 	if (obj->text_stats) {
1915 		linphone_call_stats_unref(obj->text_stats);
1916 		obj->text_stats = NULL;
1917 	}
1918 	if (obj->op!=NULL) {
1919 		sal_op_release(obj->op);
1920 		obj->op=NULL;
1921 	}
1922 	if (obj->biggestdesc!=NULL){
1923 		sal_media_description_unref(obj->biggestdesc);
1924 		obj->biggestdesc=NULL;
1925 	}
1926 	if (obj->resultdesc!=NULL) {
1927 		sal_media_description_unref(obj->resultdesc);
1928 		obj->resultdesc=NULL;
1929 	}
1930 	if (obj->localdesc!=NULL) {
1931 		sal_media_description_unref(obj->localdesc);
1932 		obj->localdesc=NULL;
1933 	}
1934 	if (obj->ping_op) {
1935 		sal_op_release(obj->ping_op);
1936 		obj->ping_op=NULL;
1937 	}
1938 	if (obj->refer_to){
1939 		ms_free(obj->refer_to);
1940 		obj->refer_to=NULL;
1941 	}
1942 	if (obj->referer){
1943 		linphone_call_unref(obj->referer);
1944 		obj->referer=NULL;
1945 	}
1946 	if (obj->transfer_target){
1947 		linphone_call_unref(obj->transfer_target);
1948 		obj->transfer_target=NULL;
1949 	}
1950 	if (obj->log) {
1951 		linphone_call_log_unref(obj->log);
1952 		obj->log=NULL;
1953 	}
1954 	if (obj->auth_token) {
1955 		ms_free(obj->auth_token);
1956 		obj->auth_token=NULL;
1957 	}
1958 	if (obj->dtls_certificate_fingerprint) {
1959 		ms_free(obj->dtls_certificate_fingerprint);
1960 		obj->dtls_certificate_fingerprint=NULL;
1961 	}
1962 	if (obj->dtmfs_timer) {
1963 		linphone_call_cancel_dtmfs(obj);
1964 	}
1965 	if (obj->params){
1966 		linphone_call_params_unref(obj->params);
1967 		obj->params=NULL;
1968 	}
1969 	if (obj->current_params){
1970 		linphone_call_params_unref(obj->current_params);
1971 		obj->current_params=NULL;
1972 	}
1973 	if (obj->remote_params != NULL) {
1974 		linphone_call_params_unref(obj->remote_params);
1975 		obj->remote_params=NULL;
1976 	}
1977 	if (obj->me) {
1978 		linphone_address_unref(obj->me);
1979 		obj->me = NULL;
1980 	}
1981 	if (obj->onhold_file) ms_free(obj->onhold_file);
1982 
1983 	if (obj->ei) linphone_error_info_unref(obj->ei);
1984 	if (obj->nat_policy)
1985 		linphone_nat_policy_unref(obj->nat_policy);
1986 }
1987 
1988 LinphoneCall * linphone_call_ref(LinphoneCall *obj){
1989 	belle_sip_object_ref(obj);
1990 	return obj;
1991 }
1992 
1993 void linphone_call_unref(LinphoneCall *obj){
1994 	belle_sip_object_unref(obj);
1995 }
1996 
1997 static unsigned int linphone_call_get_n_active_streams(const LinphoneCall *call) {
1998 	SalMediaDescription *md=NULL;
1999 	if (call->op)
2000 		md = sal_call_get_remote_media_description(call->op);
2001 	if (!md)
2002 		return 0;
2003 	return sal_media_description_nb_active_streams_of_type(md, SalAudio) + sal_media_description_nb_active_streams_of_type(md, SalVideo) + sal_media_description_nb_active_streams_of_type(md, SalText);
2004 }
2005 
2006 const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
2007 	SalMediaDescription *md=call->resultdesc;
2008 	int all_streams_encrypted = 0;
2009 #ifdef VIDEO_ENABLED
2010 	VideoStream *vstream;
2011 #endif
2012 	MS_VIDEO_SIZE_ASSIGN(call->current_params->sent_vsize, UNKNOWN);
2013 	MS_VIDEO_SIZE_ASSIGN(call->current_params->recv_vsize, UNKNOWN);
2014 #ifdef VIDEO_ENABLED
2015 	if (call->current_params->sent_vdef != NULL) linphone_video_definition_unref(call->current_params->sent_vdef);
2016 	call->current_params->sent_vdef = NULL;
2017 	if (call->current_params->recv_vdef != NULL) linphone_video_definition_unref(call->current_params->recv_vdef);
2018 	call->current_params->recv_vdef = NULL;
2019 	vstream = call->videostream;
2020 	if (vstream != NULL) {
2021 		call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream);
2022 		call->current_params->recv_vsize = video_stream_get_received_video_size(vstream);
2023 		call->current_params->sent_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition(
2024 			linphone_factory_get(), call->current_params->sent_vsize.width, call->current_params->sent_vsize.height));
2025 		call->current_params->recv_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition(
2026 			linphone_factory_get(), call->current_params->recv_vsize.width, call->current_params->recv_vsize.height));
2027 		call->current_params->sent_fps = video_stream_get_sent_framerate(vstream);
2028 		call->current_params->received_fps = video_stream_get_received_framerate(vstream);
2029 	}
2030 #endif
2031 
2032 	/* REVISITED
2033 	 * Previous code was buggy.
2034 	 * Relying on the mediastream's state (added by jehan: only) to know the current encryption is unreliable.
2035 	 * For (added by jehan: both DTLS and) ZRTP it is though necessary.
2036 	 * But for all others the current_params->media_encryption state should reflect (added by jehan: both) what is agreed by the offer/answer
2037 	 * mechanism  (added by jehan: and encryption status from media which is much stronger than only result of offer/answer )
2038 	 * Typically there can be inactive streams for which the media layer has no idea of whether they are encrypted or not.
2039 	 */
2040 
2041 	switch (call->params->media_encryption) {
2042 	case LinphoneMediaEncryptionZRTP:
2043 		if (at_least_one_stream_started(call)){
2044 			if ((all_streams_encrypted = linphone_call_all_streams_encrypted(call)) && linphone_call_get_authentication_token(call)) {
2045 				call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
2046 			} else {
2047 				/*to avoid to many traces*/
2048 				ms_debug("Encryption was requested to be %s, but isn't effective (all_streams_encrypted=%i, auth_token=%s)",
2049 					linphone_media_encryption_to_string(call->params->media_encryption), all_streams_encrypted, call->auth_token == NULL ? "" : call->auth_token);
2050 				call->current_params->media_encryption=LinphoneMediaEncryptionNone;
2051 			}
2052 		}//else don't update the state if all streams are shutdown.
2053 		break;
2054 	case LinphoneMediaEncryptionDTLS:
2055 	case LinphoneMediaEncryptionSRTP:
2056 		if (at_least_one_stream_started(call)){
2057 			if (linphone_call_get_n_active_streams(call)==0 || (all_streams_encrypted = linphone_call_all_streams_encrypted(call))) {
2058 				call->current_params->media_encryption = call->params->media_encryption;
2059 			} else {
2060 				/*to avoid to many traces*/
2061 				ms_debug("Encryption was requested to be %s, but isn't effective (all_streams_encrypted=%i)",
2062 					linphone_media_encryption_to_string(call->params->media_encryption), all_streams_encrypted);
2063 				call->current_params->media_encryption=LinphoneMediaEncryptionNone;
2064 			}
2065 		}//else don't update the state if all streams are shutdown.
2066 		break;
2067 	case LinphoneMediaEncryptionNone:
2068 		/* check if we actually switched to ZRTP */
2069 		if (at_least_one_stream_started(call) && (all_streams_encrypted = linphone_call_all_streams_encrypted(call)) && linphone_call_get_authentication_token(call)) {
2070 				call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
2071 		} else {
2072 			call->current_params->media_encryption=LinphoneMediaEncryptionNone;
2073 		}
2074 		break;
2075 	}
2076 	call->current_params->avpf_enabled = linphone_call_all_streams_avpf_enabled(call) && sal_media_description_has_avpf(md);
2077 	if (call->current_params->avpf_enabled == TRUE) {
2078 		call->current_params->avpf_rr_interval = linphone_call_get_avpf_rr_interval(call);
2079 	} else {
2080 		call->current_params->avpf_rr_interval = 0;
2081 	}
2082 	if (md){
2083 		const char *rtp_addr;
2084 
2085 		SalStreamDescription *sd=sal_media_description_find_best_stream(md,SalAudio);
2086 
2087 		call->current_params->audio_dir=sd ? media_direction_from_sal_stream_dir(sd->dir) : LinphoneMediaDirectionInactive;
2088 		if (call->current_params->audio_dir != LinphoneMediaDirectionInactive) {
2089 			rtp_addr = sd->rtp_addr[0]!='\0' ? sd->rtp_addr : call->resultdesc->addr;
2090 			call->current_params->audio_multicast_enabled = ms_is_multicast(rtp_addr);
2091 		} else
2092 			call->current_params->audio_multicast_enabled = FALSE;
2093 
2094 		sd=sal_media_description_find_best_stream(md,SalVideo);
2095 		call->current_params->implicit_rtcp_fb = sd ? sal_stream_description_has_implicit_avpf(sd): FALSE;
2096 		call->current_params->video_dir=sd ? media_direction_from_sal_stream_dir(sd->dir) : LinphoneMediaDirectionInactive;
2097 		if (call->current_params->video_dir != LinphoneMediaDirectionInactive) {
2098 			rtp_addr = sd->rtp_addr[0]!='\0' ? sd->rtp_addr : call->resultdesc->addr;
2099 			call->current_params->video_multicast_enabled = ms_is_multicast(rtp_addr);
2100 		} else
2101 			call->current_params->video_multicast_enabled = FALSE;
2102 
2103 	}
2104 
2105 	return call->current_params;
2106 }
2107 
2108 const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
2109 	if (call->op){
2110 		LinphoneCallParams *cp;
2111 		SalMediaDescription *md;
2112 		const SalCustomHeader *ch;
2113 
2114 		md=sal_call_get_remote_media_description(call->op);
2115 		if (md) {
2116 			SalStreamDescription *sd;
2117 			unsigned int i;
2118 			unsigned int nb_audio_streams = sal_media_description_nb_active_streams_of_type(md, SalAudio);
2119 			unsigned int nb_video_streams = sal_media_description_nb_active_streams_of_type(md, SalVideo);
2120 			unsigned int nb_text_streams = sal_media_description_nb_active_streams_of_type(md, SalText);
2121 			if (call->remote_params != NULL) linphone_call_params_unref(call->remote_params);
2122 			cp = call->remote_params = linphone_call_params_new();
2123 
2124 			for (i = 0; i < nb_video_streams; i++) {
2125 				sd = sal_media_description_get_active_stream_of_type(md, SalVideo, i);
2126 				if (sal_stream_description_active(sd) == TRUE) cp->has_video = TRUE;
2127 				if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP;
2128 			}
2129 			for (i = 0; i < nb_audio_streams; i++) {
2130 				sd = sal_media_description_get_active_stream_of_type(md, SalAudio, i);
2131 				if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP;
2132 			}
2133 			for (i = 0; i < nb_text_streams; i++) {
2134 				sd = sal_media_description_get_active_stream_of_type(md, SalText, i);
2135 				if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP;
2136 				cp->realtimetext_enabled = TRUE;
2137 			}
2138 			if (!cp->has_video){
2139 				if (md->bandwidth>0 && md->bandwidth<=linphone_core_get_edge_bw(call->core)){
2140 					cp->low_bandwidth=TRUE;
2141 				}
2142 			}
2143 			if (md->name[0]!='\0') linphone_call_params_set_session_name(cp,md->name);
2144 
2145 			linphone_call_params_set_custom_sdp_attributes(call->remote_params, md->custom_sdp_attributes);
2146 			linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeAudio, md->streams[call->main_audio_stream_index].custom_sdp_attributes);
2147 			linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeVideo, md->streams[call->main_video_stream_index].custom_sdp_attributes);
2148 			linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeText, md->streams[call->main_text_stream_index].custom_sdp_attributes);
2149 		}
2150 		ch = sal_op_get_recv_custom_header(call->op);
2151 		if (ch){
2152 			/*instanciate a remote_params only if a SIP message was received before (custom headers indicates this).*/
2153 			if (call->remote_params == NULL) call->remote_params = linphone_call_params_new();
2154 			linphone_call_params_set_custom_headers(call->remote_params, ch);
2155 		}
2156 		return call->remote_params;
2157 	}
2158 	return NULL;
2159 }
2160 
2161 const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call){
2162 	return call->dir==LinphoneCallIncoming ? call->log->from : call->log->to;
2163 }
2164 
2165 const LinphoneAddress * linphone_call_get_to_address(const LinphoneCall *call){
2166   return (const LinphoneAddress *)sal_op_get_to_address(call->op);
2167 }
2168 
2169 char *linphone_call_get_remote_address_as_string(const LinphoneCall *call){
2170 	return linphone_address_as_string(linphone_call_get_remote_address(call));
2171 }
2172 
2173 const LinphoneAddress * linphone_call_get_diversion_address(const LinphoneCall *call){
2174 	return call->op?(const LinphoneAddress *)sal_op_get_diversion_address(call->op):NULL;
2175 }
2176 
2177 LinphoneCallState linphone_call_get_state(const LinphoneCall *call){
2178 	return call->state;
2179 }
2180 
2181 LinphoneReason linphone_call_get_reason(const LinphoneCall *call){
2182 	return linphone_error_info_get_reason(linphone_call_get_error_info(call));
2183 }
2184 
2185 const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){
2186 	if (!call->non_op_error){
2187 		linphone_error_info_from_sal_op(call->ei, call->op);
2188 	}
2189 	return call->ei;
2190 }
2191 
2192 void *linphone_call_get_user_data(const LinphoneCall *call)
2193 {
2194 	return call->user_data;
2195 }
2196 
2197 void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer)
2198 {
2199 	call->user_data = user_pointer;
2200 }
2201 
2202 LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call){
2203 	return call->log;
2204 }
2205 
2206 const char *linphone_call_get_refer_to(const LinphoneCall *call){
2207 	return call->refer_to;
2208 }
2209 
2210 LinphoneCall *linphone_call_get_transferer_call(const LinphoneCall *call){
2211 	return call->referer;
2212 }
2213 
2214 LinphoneCall *linphone_call_get_transfer_target_call(const LinphoneCall *call){
2215 	return call->transfer_target;
2216 }
2217 
2218 LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call){
2219 	return call->log->dir;
2220 }
2221 
2222 const char *linphone_call_get_remote_user_agent(LinphoneCall *call){
2223 	if (call->op){
2224 		return sal_op_get_remote_ua (call->op);
2225 	}
2226 	return NULL;
2227 }
2228 
2229 const char *linphone_call_get_remote_contact(LinphoneCall *call){
2230 	if( call->op ){
2231 		/*sal_op_get_remote_contact preserves header params*/
2232 		return sal_op_get_remote_contact(call->op);
2233 	}
2234 	return NULL;
2235 }
2236 
2237 bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){
2238 	return call->refer_pending;
2239 }
2240 
2241 static int _linphone_call_compute_duration (const LinphoneCall *call) {
2242 	if (call->log->connected_date_time == 0) return 0;
2243 	else return (int)(ms_time(NULL) - call->log->connected_date_time);
2244 }
2245 
2246 int linphone_call_get_duration(const LinphoneCall *call) {
2247 	switch (call->state) {
2248 	  case LinphoneCallEnd:
2249 	  case LinphoneCallError:
2250 	  case LinphoneCallReleased:
2251 	    return call->log->duration;
2252 	  default:
2253 		return _linphone_call_compute_duration(call);
2254 	}
2255 }
2256 
2257 LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call){
2258 	SalOp *op=sal_call_get_replaces(call->op);
2259 	if (op){
2260 		return (LinphoneCall*)sal_op_get_user_pointer(op);
2261 	}
2262 	return NULL;
2263 }
2264 
2265 void linphone_call_enable_camera (LinphoneCall *call, bool_t enable){
2266 #ifdef VIDEO_ENABLED
2267 	call->camera_enabled=enable;
2268 	switch(call->state) {
2269 		case LinphoneCallStreamsRunning:
2270 		case LinphoneCallOutgoingEarlyMedia:
2271 		case LinphoneCallIncomingEarlyMedia:
2272 		case LinphoneCallConnected:
2273 			if(call->videostream!=NULL
2274 				&& video_stream_started(call->videostream)
2275 				&& video_stream_get_camera(call->videostream) != linphone_call_get_video_device(call)) {
2276 				const char *cur_cam, *new_cam;
2277 				cur_cam = video_stream_get_camera(call->videostream) ? ms_web_cam_get_name(video_stream_get_camera(call->videostream)) : "NULL";
2278 				new_cam = linphone_call_get_video_device(call) ? ms_web_cam_get_name(linphone_call_get_video_device(call)) : "NULL";
2279 				ms_message("Switching video cam from [%s] to [%s] on call [%p]"	, cur_cam, new_cam, call);
2280 				video_stream_change_camera(call->videostream, linphone_call_get_video_device(call));
2281 			}
2282 			break;
2283 
2284 		default: break;
2285 	}
2286 #endif
2287 }
2288 
2289 void linphone_call_send_vfu_request(LinphoneCall *call) {
2290 #ifdef VIDEO_ENABLED
2291 	const LinphoneCallParams *current_params = linphone_call_get_current_params(call);
2292 	if ((current_params->avpf_enabled || current_params->implicit_rtcp_fb  )&& call->videostream && media_stream_get_state((const MediaStream *)call->videostream) == MSStreamStarted) { // || sal_media_description_has_implicit_avpf((const SalMediaDescription *)call->resultdesc)
2293 		ms_message("Request Full Intra Request on call [%p]", call);
2294 		video_stream_send_fir(call->videostream);
2295 	} else if (call->core->sip_conf.vfu_with_info) {
2296 		ms_message("Request SIP INFO FIR on call [%p]", call);
2297 		if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
2298 			sal_call_send_vfu_request(call->op);
2299 	} else {
2300 		ms_message("vfu request using sip disabled from config [sip,vfu_with_info]");
2301 	}
2302 #endif
2303 }
2304 
2305 LinphoneStatus linphone_call_take_video_snapshot(LinphoneCall *call, const char *file) {
2306 #ifdef VIDEO_ENABLED
2307 	if (call->videostream!=NULL && call->videostream->jpegwriter!=NULL){
2308 		return ms_filter_call_method(call->videostream->jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file);
2309 	}
2310 	ms_warning("Cannot take snapshot: no currently running video stream on this call.");
2311 #endif
2312 	return -1;
2313 }
2314 
2315 LinphoneStatus linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file) {
2316 #ifdef VIDEO_ENABLED
2317 	if (call->videostream!=NULL && call->videostream->local_jpegwriter!=NULL){
2318 		return ms_filter_call_method(call->videostream->local_jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file);
2319 	}
2320 	ms_warning("Cannot take local snapshot: no currently running video stream on this call.");
2321 	return -1;
2322 #endif
2323 	return -1;
2324 }
2325 
2326 bool_t linphone_call_camera_enabled (const LinphoneCall *call){
2327 	return call->camera_enabled;
2328 }
2329 
2330 /**
2331  * @ingroup call_control
2332  * @return string value of LinphonePrivacy enum
2333  **/
2334 const char* linphone_privacy_to_string(LinphonePrivacy privacy) {
2335 	switch(privacy) {
2336 	case LinphonePrivacyDefault: return "LinphonePrivacyDefault";
2337 	case LinphonePrivacyUser: return "LinphonePrivacyUser";
2338 	case LinphonePrivacyHeader: return "LinphonePrivacyHeader";
2339 	case LinphonePrivacySession: return "LinphonePrivacySession";
2340 	case LinphonePrivacyId: return "LinphonePrivacyId";
2341 	case LinphonePrivacyNone: return "LinphonePrivacyNone";
2342 	case LinphonePrivacyCritical: return "LinphonePrivacyCritical";
2343 	default: return "Unknown privacy mode";
2344 	}
2345 }
2346 
2347 
2348 #ifdef TEST_EXT_RENDERER
2349 static void rendercb(void *data, const MSPicture *local, const MSPicture *remote){
2350 	ms_message("rendercb, local buffer=%p, remote buffer=%p",
2351 			   local ? local->planes[0] : NULL, remote? remote->planes[0] : NULL);
2352 }
2353 #endif
2354 
2355 #ifdef VIDEO_ENABLED
2356 static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args){
2357 	LinphoneCall* call = (LinphoneCall*) user_pointer;
2358 	switch (event_id) {
2359 		case MS_VIDEO_DECODER_DECODING_ERRORS:
2360 			ms_warning("MS_VIDEO_DECODER_DECODING_ERRORS");
2361 			if (call->videostream && (video_stream_is_decoding_error_to_be_reported(call->videostream, 5000) == TRUE)) {
2362 				video_stream_decoding_error_reported(call->videostream);
2363 				linphone_call_send_vfu_request(call);
2364 			}
2365 			break;
2366 		case MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS:
2367 			ms_message("MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS");
2368 			if (call->videostream) {
2369 				video_stream_decoding_error_recovered(call->videostream);
2370 			}
2371 			break;
2372 		case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
2373 			ms_message("First video frame decoded successfully");
2374 			if (call->nextVideoFrameDecoded._func != NULL){
2375 				call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
2376 				call->nextVideoFrameDecoded._func = NULL;
2377 				call->nextVideoFrameDecoded._user_data = NULL;
2378 			}
2379 			break;
2380 		case MS_VIDEO_DECODER_SEND_PLI:
2381 		case MS_VIDEO_DECODER_SEND_SLI:
2382 		case MS_VIDEO_DECODER_SEND_RPSI:
2383 			/* Handled internally by mediastreamer2. */
2384 			break;
2385 		default:
2386 			ms_warning("Unhandled event %i", event_id);
2387 			break;
2388 	}
2389 }
2390 #endif
2391 
2392 static void _linphone_call_set_next_video_frame_decoded_trigger(LinphoneCall *call){
2393 #ifdef VIDEO_ENABLED
2394 	if (call->nextVideoFrameDecoded._func && call->videostream && call->videostream->ms.decoder)
2395 		ms_filter_call_method_noarg(call->videostream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION);
2396 #endif
2397 }
2398 
2399 void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data) {
2400 	call->nextVideoFrameDecoded._func = cb;
2401 	call->nextVideoFrameDecoded._user_data = user_data;
2402 	_linphone_call_set_next_video_frame_decoded_trigger(call);
2403 }
2404 
2405 static void port_config_set_random_choosed(LinphoneCall *call, int stream_index, RtpSession *session){
2406 	call->media_ports[stream_index].rtp_port=rtp_session_get_local_port(session);
2407 	call->media_ports[stream_index].rtcp_port=rtp_session_get_local_rtcp_port(session);
2408 }
2409 
2410 static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){
2411 	MediaStream *ms = stream_index == call->main_audio_stream_index ? (MediaStream*)call->audiostream : stream_index == call->main_video_stream_index ? (MediaStream*)call->videostream : (MediaStream*)call->textstream;
2412 	if (linphone_nat_policy_ice_enabled(call->nat_policy) && (call->ice_session != NULL)){
2413 		IceCheckList *cl;
2414 		rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE);
2415 		cl=ice_session_check_list(call->ice_session, stream_index);
2416 		if (cl == NULL && create_checklist) {
2417 			cl=ice_check_list_new();
2418 			ice_session_add_check_list(call->ice_session, cl, stream_index);
2419 			ms_message("Created new ICE check list for stream [%i]",stream_index);
2420 		}
2421 		if (cl) {
2422 			media_stream_set_ice_check_list(ms, cl);
2423 		}
2424 	}
2425 }
2426 
2427 int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
2428 	SalMediaDescription *remote = NULL;
2429 	int err;
2430 	bool_t has_video=FALSE;
2431 
2432 	if (linphone_nat_policy_ice_enabled(call->nat_policy) && (call->ice_session != NULL)){
2433 		if (incoming_offer){
2434 			remote=sal_call_get_remote_media_description(call->op);
2435 			has_video=linphone_core_video_enabled(call->core) && linphone_core_media_description_contains_video_stream(remote);
2436 		}else has_video=call->params->has_video;
2437 
2438 		_linphone_call_prepare_ice_for_stream(call,call->main_audio_stream_index,TRUE);
2439 		if (has_video) _linphone_call_prepare_ice_for_stream(call,call->main_video_stream_index,TRUE);
2440 		if (call->params->realtimetext_enabled) _linphone_call_prepare_ice_for_stream(call,call->main_text_stream_index,TRUE);
2441 		/*start ICE gathering*/
2442 		if (incoming_offer)
2443 			linphone_call_update_ice_from_remote_media_description(call, remote, TRUE); /*this may delete the ice session*/
2444 		if (call->ice_session && !ice_session_candidates_gathered(call->ice_session)){
2445 			if (call->audiostream->ms.state==MSStreamInitialized)
2446 				audio_stream_prepare_sound(call->audiostream, NULL, NULL);
2447 #ifdef VIDEO_ENABLED
2448 			if (has_video && call->videostream && call->videostream->ms.state==MSStreamInitialized) {
2449 				video_stream_prepare_video(call->videostream);
2450 			}
2451 #endif
2452 			if (call->params->realtimetext_enabled && call->textstream->ms.state==MSStreamInitialized) {
2453 				text_stream_prepare_text(call->textstream);
2454 			}
2455 			err = linphone_core_gather_ice_candidates(call->core,call);
2456 			if (err == 0) {
2457 				/* Ice candidates gathering wasn't started, but we can proceed with the call anyway. */
2458 				linphone_call_stop_media_streams_for_ice_gathering(call);
2459 			}else if (err == -1) {
2460 				linphone_call_stop_media_streams_for_ice_gathering(call);
2461 				linphone_call_delete_ice_session(call);
2462 			}
2463 			return err;/* 1= gathering in progress, wait; 0=proceed*/
2464 		}
2465 	}
2466 	return 0;
2467 }
2468 
2469 /*eventually join to a multicast group if told to do so*/
2470 static void linphone_call_join_multicast_group(LinphoneCall *call, int stream_index, MediaStream *ms){
2471 	if (call->media_ports[stream_index].multicast_ip[stream_index]!='\0'){
2472 		media_stream_join_multicast_group(ms, call->media_ports[stream_index].multicast_ip);
2473 	} else
2474 		ms_error("Cannot join multicast group if multicast ip is not set for call [%p]",call);
2475 }
2476 
2477 static SalMulticastRole linphone_call_get_multicast_role(const LinphoneCall *call,SalStreamType type) {
2478 	SalMulticastRole multicast_role=SalMulticastInactive;
2479 	SalMediaDescription *remotedesc, *localdesc;
2480 	SalStreamDescription *stream_desc = NULL;
2481 	if (!call->op) goto end;
2482 	remotedesc = sal_call_get_remote_media_description(call->op);
2483 	localdesc = call->localdesc;
2484 	if (!localdesc && !remotedesc && call->dir == LinphoneCallOutgoing) {
2485 		/*well using call dir*/
2486 		if ((type == SalAudio && linphone_call_params_audio_multicast_enabled(call->params))
2487 			|| (type == SalVideo && linphone_call_params_video_multicast_enabled(call->params)))
2488 			multicast_role=SalMulticastSender;
2489 	} else	if (localdesc && (!remotedesc || sal_call_is_offerer(call->op))) {
2490 		stream_desc = sal_media_description_find_best_stream(localdesc, type);
2491 	} else if (!sal_call_is_offerer(call->op) && remotedesc)
2492 		stream_desc = sal_media_description_find_best_stream(remotedesc, type);
2493 
2494 	if (stream_desc)
2495 		multicast_role = stream_desc->multicast_role;
2496 
2497 	end:
2498 	ms_message("Call [%p], stream type [%s], multicast role is [%s]",call, sal_stream_type_to_string(type),
2499 		sal_multicast_role_to_string(multicast_role));
2500 	return multicast_role;
2501 }
2502 
2503 static void setup_dtls_params(LinphoneCall *call, MediaStream* stream) {
2504 	LinphoneCore *lc=call->core;
2505 	if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
2506 		MSDtlsSrtpParams params;
2507 		char *certificate, *key;
2508 		memset(&params,0,sizeof(MSDtlsSrtpParams));
2509 		/* TODO : search for a certificate with CNAME=sip uri(retrieved from variable me) or default : linphone-dtls-default-identity */
2510 		/* This will parse the directory to find a matching fingerprint or generate it if not found */
2511 		/* returned string must be freed */
2512 		sal_certificates_chain_parse_directory(&certificate, &key, &call->dtls_certificate_fingerprint, lc->user_certificates_path, "linphone-dtls-default-identity", SAL_CERTIFICATE_RAW_FORMAT_PEM, TRUE, TRUE);
2513 
2514 		if (key!= NULL && certificate!=NULL) {
2515 			params.pem_certificate = (char *)certificate;
2516 			params.pem_pkey = (char *)key;
2517 			params.role = MSDtlsSrtpRoleUnset; /* default is unset, then check if we have a result SalMediaDescription */
2518 			media_stream_enable_dtls(stream,&params);
2519 			ms_free(certificate);
2520 			ms_free(key);
2521 		} else {
2522 			ms_error("Unable to retrieve or generate DTLS certificate and key - DTLS disabled");
2523 			/* TODO : check if encryption forced, if yes, stop call */
2524 		}
2525 	}
2526 }
2527 
2528 static void setZrtpCryptoTypesParameters(MSZrtpParams *params, LinphoneCore *lc)
2529 {
2530 	int i;
2531 	const MSCryptoSuite *srtp_suites;
2532 	MsZrtpCryptoTypesCount ciphersCount, authTagsCount;
2533 
2534 	if (params == NULL) return;
2535 	if (lc == NULL) return;
2536 
2537 	srtp_suites = linphone_core_get_srtp_crypto_suites(lc);
2538 	if (srtp_suites!=NULL) {
2539 		for(i=0; srtp_suites[i]!=MS_CRYPTO_SUITE_INVALID && i<SAL_CRYPTO_ALGO_MAX && i<MS_MAX_ZRTP_CRYPTO_TYPES; ++i){
2540 			switch (srtp_suites[i]) {
2541 				case MS_AES_128_SHA1_32:
2542 					params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1;
2543 					params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS32;
2544 					break;
2545 				case MS_AES_128_NO_AUTH:
2546 					params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1;
2547 					break;
2548 				case MS_NO_CIPHER_SHA1_80:
2549 					params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80;
2550 					break;
2551 				case MS_AES_128_SHA1_80:
2552 					params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1;
2553 					params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80;
2554 					break;
2555 				case MS_AES_CM_256_SHA1_80:
2556 				    ms_warning("Deprecated crypto suite MS_AES_CM_256_SHA1_80, use MS_AES_256_SHA1_80 instead");
2557 					BCTBX_NO_BREAK;
2558 				case MS_AES_256_SHA1_80:
2559 				    params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES3;
2560                     params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80;
2561                     break;
2562 				case MS_AES_256_SHA1_32:
2563 					params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES3;
2564 					params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS32;
2565 					break;
2566 				case MS_CRYPTO_SUITE_INVALID:
2567 					break;
2568 			}
2569 		}
2570 	}
2571 
2572 	/* linphone_core_get_srtp_crypto_suites is used to determine sensible defaults; here each can be overridden */
2573 	ciphersCount = linphone_core_get_zrtp_cipher_suites(lc, params->ciphers); /* if not present in config file, params->ciphers is not modified */
2574 	if (ciphersCount!=0) { /* use zrtp_cipher_suites config only when present, keep config from srtp_crypto_suite otherwise */
2575 		params->ciphersCount = ciphersCount;
2576 	}
2577 	params->hashesCount = linphone_core_get_zrtp_hash_suites(lc, params->hashes);
2578 	authTagsCount = linphone_core_get_zrtp_auth_suites(lc, params->authTags); /* if not present in config file, params->authTags is not modified */
2579 	if (authTagsCount!=0) {
2580 		params->authTagsCount = authTagsCount; /* use zrtp_auth_suites config only when present, keep config from srtp_crypto_suite otherwise */
2581 	}
2582 	params->sasTypesCount = linphone_core_get_zrtp_sas_suites(lc, params->sasTypes);
2583 	params->keyAgreementsCount = linphone_core_get_zrtp_key_agreement_suites(lc, params->keyAgreements);
2584 }
2585 
2586 static OrtpJitterBufferAlgorithm name_to_jb_algo(const char *value){
2587 	if (value){
2588 		if (strcasecmp(value, "basic") == 0) return OrtpJitterBufferBasic;
2589 		else if (strcasecmp(value, "rls") == 0) return OrtpJitterBufferRecursiveLeastSquare;
2590 	}
2591 	ms_error("Invalid jitter buffer algorithm: %s", value);
2592 	return OrtpJitterBufferRecursiveLeastSquare;
2593 }
2594 
2595 static void apply_jitter_buffer_params(LinphoneCore *lc, RtpSession *session, LinphoneStreamType type){
2596 	JBParameters params;
2597 
2598 	rtp_session_get_jitter_buffer_params(session, &params);
2599 	params.min_size = lp_config_get_int(lc->config, "rtp", "jitter_buffer_min_size", 40);
2600 	params.max_size = lp_config_get_int(lc->config, "rtp", "jitter_buffer_max_size", 250);
2601 	params.max_packets = params.max_size * 200 / 1000; /*allow 200 packet per seconds, quite large*/
2602 	params.buffer_algorithm = name_to_jb_algo(lp_config_get_string(lc->config, "rtp", "jitter_buffer_algorithm", "rls"));
2603 	params.refresh_ms = lp_config_get_int(lc->config, "rtp", "jitter_buffer_refresh_period", 5000);
2604 	params.ramp_refresh_ms = lp_config_get_int(lc->config, "rtp", "jitter_buffer_ramp_refresh_period", 5000);
2605 	params.ramp_step_ms = lp_config_get_int(lc->config, "rtp", "jitter_buffer_ramp_step", 20);
2606 	params.ramp_threshold = lp_config_get_int(lc->config, "rtp", "jitter_buffer_ramp_threshold", 70);
2607 
2608 	switch (type){
2609 		case LinphoneStreamTypeAudio:
2610 		case LinphoneStreamTypeText: /*let's use the same params for text as for audio.*/
2611 			params.nom_size = linphone_core_get_audio_jittcomp(lc);
2612 			params.adaptive = linphone_core_audio_adaptive_jittcomp_enabled(lc);
2613 		break;
2614 		case LinphoneStreamTypeVideo:
2615 			params.nom_size = linphone_core_get_video_jittcomp(lc);
2616 			params.adaptive = linphone_core_video_adaptive_jittcomp_enabled(lc);
2617 		break;
2618 		case LinphoneStreamTypeUnknown:
2619 			ms_fatal("apply_jitter_buffer_params: should not happen");
2620 		break;
2621 	}
2622 	params.enabled = params.nom_size > 0;
2623 	if (params.enabled){
2624 		if (params.min_size > params.nom_size){
2625 			params.min_size = params.nom_size;
2626 		}
2627 		if (params.max_size < params.nom_size){
2628 			params.max_size = params.nom_size;
2629 		}
2630 	}
2631 	rtp_session_set_jitter_buffer_params(session, &params);
2632 }
2633 
2634 void linphone_call_init_audio_stream(LinphoneCall *call){
2635 	LinphoneCore *lc=call->core;
2636 	AudioStream *audiostream;
2637 	const char *location;
2638 	int dscp;
2639 	const char *rtcp_tool=linphone_core_get_user_agent(call->core);
2640 	char* cname;
2641 
2642 	if (call->audiostream != NULL) return;
2643 	if (call->sessions[call->main_audio_stream_index].rtp_session==NULL){
2644 		SalMulticastRole multicast_role = linphone_call_get_multicast_role(call,SalAudio);
2645 		SalMediaDescription *remotedesc=NULL;
2646 		SalStreamDescription *stream_desc = NULL;
2647 		if (call->op) remotedesc = sal_call_get_remote_media_description(call->op);
2648 		if (remotedesc)
2649 				stream_desc = sal_media_description_find_best_stream(remotedesc, SalAudio);
2650 
2651 		call->audiostream=audiostream=audio_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_audio_stream_index),
2652 				multicast_role ==  SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_audio_stream_index].rtp_port,
2653 				multicast_role ==  SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_audio_stream_index].rtcp_port);
2654 		if (multicast_role == SalMulticastReceiver)
2655 			linphone_call_join_multicast_group(call, call->main_audio_stream_index, &audiostream->ms);
2656 		rtp_session_enable_network_simulation(call->audiostream->ms.sessions.rtp_session, &lc->net_conf.netsim_params);
2657 		apply_jitter_buffer_params(lc, call->audiostream->ms.sessions.rtp_session, LinphoneStreamTypeAudio);
2658 		cname = linphone_address_as_string_uri_only(call->me);
2659 		audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
2660 		ms_free(cname);
2661 		rtp_session_set_symmetric_rtp(audiostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
2662 		setup_dtls_params(call, &audiostream->ms);
2663 
2664 		/* init zrtp even if we didn't explicitely set it, just in case peer offers it */
2665 		if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)) {
2666 			char *peerUri = linphone_address_as_string_uri_only((call->dir==LinphoneCallIncoming) ? call->log->from : call->log->to);
2667 			char *selfUri = linphone_address_as_string_uri_only((call->dir==LinphoneCallIncoming) ? call->log->to : call->log->from);
2668 			MSZrtpParams params;
2669 			memset(&params,0,sizeof(MSZrtpParams));
2670 			/*call->current_params.media_encryption will be set later when zrtp is activated*/
2671 			params.zidCacheDB = linphone_core_get_zrtp_cache_db(lc);
2672 			params.peerUri=peerUri;
2673 			params.selfUri=selfUri;
2674 			params.limeKeyTimeSpan = bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0")); /* get key lifespan from config file, default is 0:forever valid */
2675 			setZrtpCryptoTypesParameters(&params,call->core);
2676 			audio_stream_enable_zrtp(call->audiostream,&params);
2677 			if (peerUri != NULL) ms_free(peerUri);
2678 			if (selfUri != NULL) ms_free(selfUri);
2679 		}
2680 
2681 		media_stream_reclaim_sessions(&audiostream->ms, &call->sessions[call->main_audio_stream_index]);
2682 	}else{
2683 		call->audiostream=audio_stream_new_with_sessions(lc->factory, &call->sessions[call->main_audio_stream_index]);
2684 
2685 	}
2686 	audiostream=call->audiostream;
2687 	if (call->media_ports[call->main_audio_stream_index].rtp_port==-1){
2688 		port_config_set_random_choosed(call,call->main_audio_stream_index,audiostream->ms.sessions.rtp_session);
2689 	}
2690 	dscp=linphone_core_get_audio_dscp(lc);
2691 	if (dscp!=-1)
2692 		audio_stream_set_dscp(audiostream,dscp);
2693 	if (linphone_core_echo_limiter_enabled(lc)){
2694 		const char *type=lp_config_get_string(lc->config,"sound","el_type","mic");
2695 		if (strcasecmp(type,"mic")==0)
2696 			audio_stream_enable_echo_limiter(audiostream,ELControlMic);
2697 		else if (strcasecmp(type,"full")==0)
2698 			audio_stream_enable_echo_limiter(audiostream,ELControlFull);
2699 	}
2700 
2701 	/* equalizer location in the graph: 'mic' = in input graph, otherwise in output graph.
2702 		Any other value than mic will default to output graph for compatibility */
2703 	location = lp_config_get_string(lc->config,"sound","eq_location","hp");
2704 	audiostream->eq_loc = (strcasecmp(location,"mic") == 0) ? MSEqualizerMic : MSEqualizerHP;
2705 	ms_message("Equalizer location: %s", location);
2706 
2707 	audio_stream_enable_gain_control(audiostream,TRUE);
2708 	if (linphone_core_echo_cancellation_enabled(lc)){
2709 		int len,delay,framesize;
2710 		len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
2711 		delay=lp_config_get_int(lc->config,"sound","ec_delay",0);
2712 		framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0);
2713 		audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize);
2714 		if (audiostream->ec) {
2715 			char *statestr=ms_malloc0(EC_STATE_MAX_LEN);
2716 			if (lp_config_relative_file_exists(lc->config, EC_STATE_STORE)
2717 				 && lp_config_read_relative_file(lc->config, EC_STATE_STORE, statestr, EC_STATE_MAX_LEN) == 0) {
2718 				ms_filter_call_method(audiostream->ec, MS_ECHO_CANCELLER_SET_STATE_STRING, statestr);
2719 			}
2720 			ms_free(statestr);
2721 		}
2722 	}
2723 	audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc));
2724 	{
2725 		int enabled=lp_config_get_int(lc->config,"sound","noisegate",0);
2726 		audio_stream_enable_noise_gate(audiostream,enabled);
2727 	}
2728 
2729 	audio_stream_set_features(audiostream,linphone_core_get_audio_features(lc));
2730 
2731 	if (lc->rtptf){
2732 		RtpTransport *meta_rtp;
2733 		RtpTransport *meta_rtcp;
2734 
2735 		rtp_session_get_transports(audiostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
2736 		if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
2737 			ms_message("LinphoneCall[%p]: using custom audio RTP transport endpoint.", call);
2738 			meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[call->main_audio_stream_index].rtp_port));
2739 		}
2740 		if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
2741 			meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[call->main_audio_stream_index].rtcp_port));
2742 		}
2743 	}
2744 
2745 	call->audiostream_app_evq = ortp_ev_queue_new();
2746 	rtp_session_register_event_queue(audiostream->ms.sessions.rtp_session,call->audiostream_app_evq);
2747 
2748 	_linphone_call_prepare_ice_for_stream(call,call->main_audio_stream_index,FALSE);
2749 }
2750 
2751 void linphone_call_init_video_stream(LinphoneCall *call){
2752 #ifdef VIDEO_ENABLED
2753 	LinphoneCore *lc=call->core;
2754 	char* cname;
2755 	const char *rtcp_tool = linphone_core_get_user_agent(call->core);
2756 
2757 	if (call->videostream == NULL){
2758 		int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
2759 		int dscp=linphone_core_get_video_dscp(lc);
2760 		const char *display_filter=linphone_core_get_video_display_filter(lc);
2761 
2762 		if (call->sessions[call->main_video_stream_index].rtp_session==NULL){
2763 			SalMulticastRole multicast_role = linphone_call_get_multicast_role(call,SalVideo);
2764 			SalMediaDescription *remotedesc=NULL;
2765 			SalStreamDescription *stream_desc = NULL;
2766 			if (call->op) remotedesc = sal_call_get_remote_media_description(call->op);
2767 			if (remotedesc)
2768 					stream_desc = sal_media_description_find_best_stream(remotedesc, SalVideo);
2769 
2770 			call->videostream=video_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_video_stream_index),
2771 					multicast_role ==  SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_video_stream_index].rtp_port,
2772 					multicast_role ==  SalMulticastReceiver ?  0 /*disabled for now*/ : call->media_ports[call->main_video_stream_index].rtcp_port);
2773 			if (multicast_role == SalMulticastReceiver)
2774 				linphone_call_join_multicast_group(call, call->main_video_stream_index, &call->videostream->ms);
2775 			rtp_session_enable_network_simulation(call->videostream->ms.sessions.rtp_session, &lc->net_conf.netsim_params);
2776 			apply_jitter_buffer_params(lc, call->videostream->ms.sessions.rtp_session, LinphoneStreamTypeVideo);
2777 			cname = linphone_address_as_string_uri_only(call->me);
2778 			video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
2779 			ms_free(cname);
2780 			rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
2781 			setup_dtls_params(call, &call->videostream->ms);
2782 			/* init zrtp even if we didn't explicitely set it, just in case peer offers it */
2783 			if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)) {
2784 				video_stream_enable_zrtp(call->videostream, call->audiostream);
2785 			}
2786 
2787 			media_stream_reclaim_sessions(&call->videostream->ms, &call->sessions[call->main_video_stream_index]);
2788 		}else{
2789 			call->videostream=video_stream_new_with_sessions(lc->factory, &call->sessions[call->main_video_stream_index]);
2790 		}
2791 
2792 		if (call->media_ports[call->main_video_stream_index].rtp_port==-1){
2793 			port_config_set_random_choosed(call,call->main_video_stream_index,call->videostream->ms.sessions.rtp_session);
2794 		}
2795 		if (dscp!=-1)
2796 			video_stream_set_dscp(call->videostream,dscp);
2797 		video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0));
2798 		if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->ms.sessions.rtp_session,video_recv_buf_size);
2799 
2800 		if (display_filter != NULL)
2801 			video_stream_set_display_filter_name(call->videostream,display_filter);
2802 		video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
2803 
2804 		if (lc->rtptf){
2805 			RtpTransport *meta_rtp;
2806 			RtpTransport *meta_rtcp;
2807 
2808 			rtp_session_get_transports(call->videostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
2809 			if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
2810 				ms_message("LinphoneCall[%p]: using custom video RTP transport endpoint.", call);
2811 				meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[call->main_video_stream_index].rtp_port));
2812 			}
2813 			if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
2814 				meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[call->main_video_stream_index].rtcp_port));
2815 			}
2816 		}
2817 		call->videostream_app_evq = ortp_ev_queue_new();
2818 		rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq);
2819 		_linphone_call_prepare_ice_for_stream(call,call->main_video_stream_index,FALSE);
2820 #ifdef TEST_EXT_RENDERER
2821 		video_stream_set_render_callback(call->videostream,rendercb,NULL);
2822 #endif
2823 	}
2824 #else
2825 	call->videostream=NULL;
2826 #endif
2827 }
2828 
2829 void linphone_call_init_text_stream(LinphoneCall *call){
2830 	TextStream *textstream;
2831 	LinphoneCore *lc=call->core;
2832 	char* cname;
2833 
2834 	if (call->textstream != NULL) return;
2835 	if (call->sessions[call->main_text_stream_index].rtp_session == NULL) {
2836 		SalMulticastRole multicast_role = linphone_call_get_multicast_role(call, SalText);
2837 		SalMediaDescription *remotedesc = NULL;
2838 		SalStreamDescription *stream_desc = NULL;
2839 		if (call->op) remotedesc = sal_call_get_remote_media_description(call->op);
2840 		if (remotedesc) stream_desc = sal_media_description_find_best_stream(remotedesc, SalText);
2841 
2842 		call->textstream = textstream = text_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_text_stream_index),
2843 				multicast_role ==  SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_text_stream_index].rtp_port,
2844 				multicast_role ==  SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_text_stream_index].rtcp_port);
2845 		if (multicast_role == SalMulticastReceiver)
2846 			linphone_call_join_multicast_group(call, call->main_text_stream_index, &textstream->ms);
2847 		rtp_session_enable_network_simulation(call->textstream->ms.sessions.rtp_session, &lc->net_conf.netsim_params);
2848 		apply_jitter_buffer_params(lc, call->textstream->ms.sessions.rtp_session, LinphoneStreamTypeText);
2849 		cname = linphone_address_as_string_uri_only(call->me);
2850 		ms_free(cname);
2851 		rtp_session_set_symmetric_rtp(textstream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
2852 		setup_dtls_params(call, &textstream->ms);
2853 		media_stream_reclaim_sessions(&textstream->ms, &call->sessions[call->main_text_stream_index]);
2854 	} else {
2855 		call->textstream = text_stream_new_with_sessions(lc->factory, &call->sessions[call->main_text_stream_index]);
2856 	}
2857 	textstream = call->textstream;
2858 	if (call->media_ports[call->main_text_stream_index].rtp_port == -1) {
2859 		port_config_set_random_choosed(call, call->main_text_stream_index, textstream->ms.sessions.rtp_session);
2860 	}
2861 
2862 	if (lc->rtptf){
2863 		RtpTransport *meta_rtp;
2864 		RtpTransport *meta_rtcp;
2865 
2866 		rtp_session_get_transports(textstream->ms.sessions.rtp_session, &meta_rtp, &meta_rtcp);
2867 		if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
2868 			meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[call->main_text_stream_index].rtp_port));
2869 		}
2870 		if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
2871 			meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[call->main_text_stream_index].rtcp_port));
2872 		}
2873 	}
2874 
2875 	call->textstream_app_evq = ortp_ev_queue_new();
2876 	rtp_session_register_event_queue(textstream->ms.sessions.rtp_session, call->textstream_app_evq);
2877 
2878 	_linphone_call_prepare_ice_for_stream(call, call->main_text_stream_index, FALSE);
2879 }
2880 
2881 void linphone_call_init_media_streams(LinphoneCall *call){
2882 	linphone_call_init_audio_stream(call);
2883 	linphone_call_init_video_stream(call);
2884 	linphone_call_init_text_stream(call);
2885 }
2886 
2887 
2888 static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
2889 
2890 static void linphone_core_dtmf_received(LinphoneCall *call, int dtmf){
2891 	if (dtmf<0 || dtmf>15){
2892 		ms_warning("Bad dtmf value %i",dtmf);
2893 		return;
2894 	}
2895 	linphone_call_notify_dtmf_received(call, dtmf_tab[dtmf]);
2896 }
2897 
2898 static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
2899 	const char *eq_active = lp_config_get_string(lc->config, "sound", "eq_active", NULL);
2900 	const char *eq_gains = lp_config_get_string(lc->config, "sound", "eq_gains", NULL);
2901 
2902 	if(eq_active) ms_warning("'eq_active' linphonerc parameter has not effect anymore. Please use 'mic_eq_active' or 'spk_eq_active' instead");
2903 	if(eq_gains) ms_warning("'eq_gains' linphonerc parameter has not effect anymore. Please use 'mic_eq_gains' or 'spk_eq_gains' instead");
2904 	if (st->mic_equalizer){
2905 		MSFilter *f=st->mic_equalizer;
2906 		int enabled=lp_config_get_int(lc->config,"sound","mic_eq_active",0);
2907 		const char *gains=lp_config_get_string(lc->config,"sound","mic_eq_gains",NULL);
2908 		ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled);
2909 		if (enabled && gains){
2910 			bctbx_list_t *gains_list = ms_parse_equalizer_string(gains);
2911 			bctbx_list_t *it;
2912 			for(it=gains_list; it; it=it->next) {
2913 				MSEqualizerGain *g = (MSEqualizerGain *)it->data;
2914 				ms_message("Read microphone equalizer gains: %f(~%f) --> %f",g->frequency,g->width,g->gain);
2915 				ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN, g);
2916 			}
2917 			if(gains_list) bctbx_list_free_with_data(gains_list, ms_free);
2918 		}
2919 	}
2920 	if (st->spk_equalizer){
2921 		MSFilter *f=st->spk_equalizer;
2922 		int enabled=lp_config_get_int(lc->config,"sound","spk_eq_active",0);
2923 		const char *gains=lp_config_get_string(lc->config,"sound","spk_eq_gains",NULL);
2924 		ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled);
2925 		if (enabled && gains){
2926 			bctbx_list_t *gains_list = ms_parse_equalizer_string(gains);
2927 			bctbx_list_t *it;
2928 			for(it=gains_list; it; it=it->next) {
2929 				MSEqualizerGain *g = (MSEqualizerGain *)it->data;
2930 				ms_message("Read speaker equalizer gains: %f(~%f) --> %f",g->frequency,g->width,g->gain);
2931 				ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN, g);
2932 			}
2933 			if(gains_list) bctbx_list_free_with_data(gains_list, ms_free);
2934 		}
2935 	}
2936 }
2937 
2938 void set_mic_gain_db(AudioStream *st, float gain){
2939 	audio_stream_set_mic_gain_db(st, gain);
2940 }
2941 
2942 void set_playback_gain_db(AudioStream *st, float gain){
2943 	if (st->volrecv){
2944 		ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain);
2945 	}else ms_warning("Could not apply playback gain: gain control wasn't activated.");
2946 }
2947 
2948 /*This function is not static because used internally in linphone-daemon project*/
2949 void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){
2950 	float mic_gain=lc->sound_conf.soft_mic_lev;
2951 	float thres = 0;
2952 	float recv_gain;
2953 	float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05f);
2954 	float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0);
2955 	int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0);
2956 	float speed;
2957 	float force;
2958 	int sustain;
2959 	float transmit_thres;
2960 	MSFilter *f=NULL;
2961 	float floorgain;
2962 	int spk_agc;
2963 
2964 	if (!muted)
2965 		set_mic_gain_db(st,mic_gain);
2966 	else
2967 		audio_stream_set_mic_gain(st,0);
2968 
2969 	recv_gain = lc->sound_conf.soft_play_lev;
2970 	if (recv_gain != 0) {
2971 		set_playback_gain_db(st,recv_gain);
2972 	}
2973 
2974 	if (st->volsend){
2975 		ms_filter_call_method(st->volsend,MS_VOLUME_REMOVE_DC,&dc_removal);
2976 		speed=lp_config_get_float(lc->config,"sound","el_speed",-1);
2977 		thres=lp_config_get_float(lc->config,"sound","el_thres",-1);
2978 		force=lp_config_get_float(lc->config,"sound","el_force",-1);
2979 		sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1);
2980 		transmit_thres=lp_config_get_float(lc->config,"sound","el_transmit_thres",-1);
2981 		f=st->volsend;
2982 		if (speed==-1) speed=0.03f;
2983 		if (force==-1) force=25;
2984 		ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed);
2985 		ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force);
2986 		if (thres!=-1)
2987 			ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres);
2988 		if (sustain!=-1)
2989 			ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain);
2990 		if (transmit_thres!=-1)
2991 				ms_filter_call_method(f,MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD,&transmit_thres);
2992 
2993 		ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres);
2994 		ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain);
2995 	}
2996 	if (st->volrecv){
2997 		/* parameters for a limited noise-gate effect, using echo limiter threshold */
2998 		floorgain = (float)(1/pow(10,mic_gain/10));
2999 		spk_agc=lp_config_get_int(lc->config,"sound","speaker_agc_enabled",0);
3000 		ms_filter_call_method(st->volrecv, MS_VOLUME_ENABLE_AGC, &spk_agc);
3001 		ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres);
3002 		ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&floorgain);
3003 	}
3004 	parametrize_equalizer(lc,st);
3005 }
3006 
3007 static void post_configure_audio_streams(LinphoneCall *call, bool_t muted){
3008 	AudioStream *st=call->audiostream;
3009 	LinphoneCore *lc=call->core;
3010 	_post_configure_audio_stream(st,lc,muted);
3011 	if (linphone_core_dtmf_received_has_listener(lc)){
3012 		audio_stream_play_received_dtmfs(call->audiostream,FALSE);
3013 	}
3014 	if (call->record_active)
3015 		linphone_call_start_recording(call);
3016 }
3017 
3018 static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){
3019 	int remote_bw=0;
3020 	int upload_bw;
3021 	int total_upload_bw=linphone_core_get_upload_bandwidth(call->core);
3022 	const LinphoneCallParams *params=call->params;
3023 	bool_t will_use_video=linphone_core_media_description_contains_video_stream(md);
3024 	bool_t forced=FALSE;
3025 
3026 	if (desc->bandwidth>0) remote_bw=desc->bandwidth;
3027 	else if (md->bandwidth>0) {
3028 		/*case where b=AS is given globally, not per stream*/
3029 		remote_bw=md->bandwidth;
3030 	}
3031 	if (params->up_bw>0){
3032 		forced=TRUE;
3033 		upload_bw=params->up_bw;
3034 	}else upload_bw=total_upload_bw;
3035 	upload_bw=get_min_bandwidth(upload_bw,remote_bw);
3036 	if (!will_use_video || forced) return upload_bw;
3037 
3038 	if (bandwidth_is_greater(upload_bw,512)){
3039 		upload_bw=100;
3040 	}else if (bandwidth_is_greater(upload_bw,256)){
3041 		upload_bw=64;
3042 	}else if (bandwidth_is_greater(upload_bw,128)){
3043 		upload_bw=40;
3044 	}else if (bandwidth_is_greater(upload_bw,0)){
3045 		upload_bw=24;
3046 	}
3047 	return upload_bw;
3048 }
3049 
3050 static int get_video_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){
3051 	int remote_bw=0;
3052 	int bw;
3053 	if (desc->bandwidth>0) remote_bw=desc->bandwidth;
3054 	else if (md->bandwidth>0) {
3055 		/*case where b=AS is given globally, not per stream*/
3056 		remote_bw=get_remaining_bandwidth_for_video(md->bandwidth,call->audio_bw);
3057 	} else {
3058 		remote_bw = lp_config_get_int(call->core->config, "net", "default_max_bandwidth", 1500);
3059 	}
3060 	bw=get_min_bandwidth(get_remaining_bandwidth_for_video(linphone_core_get_upload_bandwidth(call->core),call->audio_bw),remote_bw);
3061 	return bw;
3062 }
3063 
3064 static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
3065 	int bw=0;
3066 	const bctbx_list_t *elem;
3067 	RtpProfile *prof=rtp_profile_new("Call profile");
3068 	bool_t first=TRUE;
3069 	LinphoneCore *lc=call->core;
3070 	int up_ptime=0;
3071 	const LinphoneCallParams *params=call->params;
3072 
3073 	*used_pt=-1;
3074 
3075 	if (desc->type==SalAudio)
3076 		bw=get_ideal_audio_bw(call,md,desc);
3077 	else if (desc->type==SalVideo)
3078 		bw=get_video_bw(call,md,desc);
3079 	//else if (desc->type== SalText)
3080 
3081 
3082 	for(elem=desc->payloads;elem!=NULL;elem=elem->next){
3083 		PayloadType *pt=(PayloadType*)elem->data;
3084 		int number;
3085 		/* make a copy of the payload type, so that we left the ones from the SalStreamDescription unchanged.
3086 		 If the SalStreamDescription is freed, this will have no impact on the running streams*/
3087 		pt=payload_type_clone(pt);
3088 
3089 		if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) {
3090 			/*first codec in list is the selected one*/
3091 			if (desc->type==SalAudio){
3092 				/*this will update call->audio_bw*/
3093 				linphone_core_update_allocated_audio_bandwidth_in_call(call,pt,bw);
3094 				bw=call->audio_bw;
3095 				if (params->up_ptime)
3096 					up_ptime=params->up_ptime;
3097 				else up_ptime=linphone_core_get_upload_ptime(lc);
3098 			}
3099 			first=FALSE;
3100 		}
3101 		if (*used_pt == -1){
3102 			/*don't select telephone-event as a payload type*/
3103 			if (strcasecmp(pt->mime_type, "telephone-event") != 0){
3104 				*used_pt = payload_type_get_number(pt);
3105 			}
3106 		}
3107 
3108 		if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){
3109 			ms_message("Payload type [%s/%i] has explicit bitrate [%i] kbit/s", pt->mime_type, pt->clock_rate, pt->normal_bitrate/1000);
3110 			pt->normal_bitrate=get_min_bandwidth(pt->normal_bitrate,bw*1000);
3111 		} else pt->normal_bitrate=bw*1000;
3112 		if (desc->ptime>0){
3113 			up_ptime=desc->ptime;
3114 		}
3115 		if (up_ptime>0){
3116 			char tmp[40];
3117 			snprintf(tmp,sizeof(tmp),"ptime=%i",up_ptime);
3118 			payload_type_append_send_fmtp(pt,tmp);
3119 		}
3120 		number=payload_type_get_number(pt);
3121 		if (rtp_profile_get_payload(prof,number)!=NULL){
3122 			ms_warning("A payload type with number %i already exists in profile !",number);
3123 		}else
3124 			rtp_profile_set_payload(prof,number,pt);
3125 	}
3126 	return prof;
3127 }
3128 
3129 static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){
3130 	int pause_time=3000;
3131 	audio_stream_play(call->audiostream,lc->sound_conf.ringback_tone);
3132 	ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
3133 }
3134 
3135 static bool_t linphone_call_sound_resources_available(LinphoneCall *call){
3136 	LinphoneCore *lc=call->core;
3137 	LinphoneCall *current=linphone_core_get_current_call(lc);
3138 	return !linphone_core_is_in_conference(lc) &&
3139 		(current==NULL || current==call);
3140 }
3141 
3142 static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned char tag) {
3143 	int i;
3144 	for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
3145 		if (crypto[i].tag == tag) {
3146 			return i;
3147 		}
3148 	}
3149 	return -1;
3150 }
3151 
3152 static void configure_rtp_session_for_rtcp_fb(LinphoneCall *call, const SalStreamDescription *stream) {
3153 	RtpSession *session = NULL;
3154 
3155 	if (stream->type == SalAudio) {
3156 		session = call->audiostream->ms.sessions.rtp_session;
3157 	} else if (stream->type == SalVideo) {
3158 		session = call->videostream->ms.sessions.rtp_session;
3159 	} else {
3160 		// Do nothing for streams that are not audio or video
3161 		return;
3162 	}
3163 	if (stream->rtcp_fb.generic_nack_enabled)
3164 		rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, TRUE);
3165 	else
3166 		rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, FALSE);
3167 	if (stream->rtcp_fb.tmmbr_enabled)
3168 		rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, TRUE);
3169 	else
3170 		rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, FALSE);
3171 }
3172 
3173 static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *call, SalStreamType type) {
3174 	RtpSession *session = NULL;
3175 	const OrtpRtcpXrConfiguration *localconfig;
3176 	const OrtpRtcpXrConfiguration *remoteconfig;
3177 	OrtpRtcpXrConfiguration currentconfig;
3178 	const SalStreamDescription *localstream;
3179 	const SalStreamDescription *remotestream;
3180 	SalMediaDescription *remotedesc = sal_call_get_remote_media_description(call->op);
3181 
3182 	if (!remotedesc) return;
3183 
3184 	localstream = sal_media_description_find_best_stream(call->localdesc, type);
3185 	if (!localstream) return;
3186 	localconfig = &localstream->rtcp_xr;
3187 	remotestream = sal_media_description_find_best_stream(remotedesc, type);
3188 	if (!remotestream) return;
3189 	remoteconfig = &remotestream->rtcp_xr;
3190 
3191 	if (localstream->dir == SalStreamInactive) return;
3192 	else if (localstream->dir == SalStreamRecvOnly) {
3193 		/* Use local config for unilateral parameters and remote config for collaborative parameters. */
3194 		memcpy(&currentconfig, localconfig, sizeof(currentconfig));
3195 		currentconfig.rcvr_rtt_mode = remoteconfig->rcvr_rtt_mode;
3196 		currentconfig.rcvr_rtt_max_size = remoteconfig->rcvr_rtt_max_size;
3197 	} else {
3198 		memcpy(&currentconfig, remoteconfig, sizeof(currentconfig));
3199 	}
3200 	if (type == SalAudio) {
3201 		session = call->audiostream->ms.sessions.rtp_session;
3202 	} else if (type == SalVideo) {
3203 		session = call->videostream->ms.sessions.rtp_session;
3204 	} else if (type == SalText) {
3205 		session = call->textstream->ms.sessions.rtp_session;
3206 	}
3207 	rtp_session_configure_rtcp_xr(session, &currentconfig);
3208 }
3209 
3210 static void start_dtls( MSMediaStreamSessions *sessions,  const SalStreamDescription *sd,const SalStreamDescription *remote) {
3211 	if (sal_stream_description_has_dtls(sd) == TRUE) {
3212 		/*DTLS*/
3213 		SalDtlsRole salRole = sd->dtls_role;
3214 		if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */
3215 			/* give the peer certificate fingerprint to dtls context */
3216 			ms_dtls_srtp_set_peer_fingerprint(sessions->dtls_context, remote->dtls_fingerprint);
3217 			ms_dtls_srtp_set_role(sessions->dtls_context, (salRole == SalDtlsRoleIsClient)?MSDtlsSrtpRoleIsClient:MSDtlsSrtpRoleIsServer); /* set the role to client */
3218 			ms_dtls_srtp_start(sessions->dtls_context);  /* then start the engine, it will send the DTLS client Hello */
3219 		} else {
3220 			ms_warning("unable to start DTLS engine on stream session [%p], Dtls role in resulting media description is invalid",sessions);
3221 		}
3222 	}
3223 }
3224 
3225 static void start_dtls_on_all_streams(LinphoneCall *call) {
3226 	SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
3227 	SalMediaDescription *result_desc = sal_call_get_final_media_description(call->op);
3228 	if( remote_desc == NULL || result_desc == NULL ){
3229 		/* this can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */
3230 		return;
3231 	}
3232 
3233 	if (call->audiostream && (media_stream_get_state((const MediaStream *)call->audiostream) == MSStreamStarted))/*dtls must start at the end of ice*/
3234 			start_dtls(&call->audiostream->ms.sessions
3235 							,sal_media_description_find_best_stream(result_desc,SalAudio)
3236 							,sal_media_description_find_best_stream(remote_desc,SalAudio));
3237 #if VIDEO_ENABLED
3238 	if (call->videostream && (media_stream_get_state((const MediaStream *)call->videostream) == MSStreamStarted))/*dtls must start at the end of ice*/
3239 			start_dtls(&call->videostream->ms.sessions
3240 						,sal_media_description_find_best_stream(result_desc,SalVideo)
3241 						,sal_media_description_find_best_stream(remote_desc,SalVideo));
3242 #endif
3243 	if (call->textstream && (media_stream_get_state((const MediaStream *)call->textstream) == MSStreamStarted))/*dtls must start at the end of ice*/
3244 	start_dtls(&call->textstream->ms.sessions
3245 					,sal_media_description_find_best_stream(result_desc,SalText)
3246 					,sal_media_description_find_best_stream(remote_desc,SalText));
3247 	return;
3248 }
3249 
3250 static void set_dtls_fingerprint( MSMediaStreamSessions *sessions,  const SalStreamDescription *sd,const SalStreamDescription *remote) {
3251 	if (sal_stream_description_has_dtls(sd) == TRUE) {
3252 		/*DTLS*/
3253 		SalDtlsRole salRole = sd->dtls_role;
3254 		if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */
3255 			/* give the peer certificate fingerprint to dtls context */
3256 			ms_dtls_srtp_set_peer_fingerprint(sessions->dtls_context, remote->dtls_fingerprint);
3257 		} else {
3258 			ms_warning("unable to start DTLS engine on stream session [%p], Dtls role in resulting media description is invalid",sessions);
3259 		}
3260 	}
3261 }
3262 
3263 static void set_dtls_fingerprint_on_all_streams(LinphoneCall *call) {
3264 	SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
3265 	SalMediaDescription *result_desc = sal_call_get_final_media_description(call->op);
3266 
3267 	if( remote_desc == NULL || result_desc == NULL ){
3268 		/* this can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */
3269 		return;
3270 	}
3271 
3272 	if (call->audiostream && (media_stream_get_state((const MediaStream *)call->audiostream) == MSStreamStarted))/*dtls must start at the end of ice*/
3273 			set_dtls_fingerprint(&call->audiostream->ms.sessions
3274 							,sal_media_description_find_best_stream(result_desc,SalAudio)
3275 							,sal_media_description_find_best_stream(remote_desc,SalAudio));
3276 #if VIDEO_ENABLED
3277 	if (call->videostream && (media_stream_get_state((const MediaStream *)call->videostream) == MSStreamStarted))/*dtls must start at the end of ice*/
3278 			set_dtls_fingerprint(&call->videostream->ms.sessions
3279 						,sal_media_description_find_best_stream(result_desc,SalVideo)
3280 						,sal_media_description_find_best_stream(remote_desc,SalVideo));
3281 #endif
3282 	if (call->textstream && (media_stream_get_state((const MediaStream *)call->textstream) == MSStreamStarted))/*dtls must start at the end of ice*/
3283 	set_dtls_fingerprint(&call->textstream->ms.sessions
3284 					,sal_media_description_find_best_stream(result_desc,SalText)
3285 					,sal_media_description_find_best_stream(remote_desc,SalText));
3286 	return;
3287 }
3288 
3289 static RtpSession * create_audio_rtp_io_session(LinphoneCall *call) {
3290 	PayloadType *pt;
3291 	LinphoneCore *lc = call->core;
3292 	const char *local_ip = lp_config_get_string(lc->config, "sound", "rtp_local_addr", "127.0.0.1");
3293 	const char *remote_ip = lp_config_get_string(lc->config, "sound", "rtp_remote_addr", "127.0.0.1");
3294 	int local_port = lp_config_get_int(lc->config, "sound", "rtp_local_port", 17076);
3295 	int remote_port = lp_config_get_int(lc->config, "sound", "rtp_remote_port", 17078);
3296 	int ptnum = lp_config_get_int(lc->config, "sound", "rtp_ptnum", 0);
3297 	const char *rtpmap = lp_config_get_string(lc->config, "sound", "rtp_map", "pcmu/8000/1");
3298 	int symmetric = lp_config_get_int(lc->config, "sound", "rtp_symmetric", 0);
3299 	int jittcomp = lp_config_get_int(lc->config, "sound", "rtp_jittcomp", 0); /* 0 means no jitter buffer*/
3300 	RtpSession *rtp_session = NULL;
3301 	pt = rtp_profile_get_payload_from_rtpmap(call->audio_profile, rtpmap);
3302 	if (pt != NULL) {
3303 		call->rtp_io_audio_profile = rtp_profile_new("RTP IO audio profile");
3304 		rtp_profile_set_payload(call->rtp_io_audio_profile, ptnum, payload_type_clone(pt));
3305 		rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1, ms_factory_get_mtu(lc->factory));
3306 		rtp_session_set_profile(rtp_session, call->rtp_io_audio_profile);
3307 		rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1);
3308 		rtp_session_enable_rtcp(rtp_session, FALSE);
3309 		rtp_session_set_payload_type(rtp_session, ptnum);
3310 		rtp_session_set_jitter_compensation(rtp_session, jittcomp);
3311 		rtp_session_enable_jitter_buffer(rtp_session, jittcomp>0);
3312 		rtp_session_set_symmetric_rtp(rtp_session, (bool_t)symmetric);
3313 	}
3314 	return rtp_session;
3315 }
3316 
3317 static void linphone_call_set_on_hold_file(LinphoneCall *call, const char *file){
3318 	if (call->onhold_file){
3319 		ms_free(call->onhold_file);
3320 		call->onhold_file = NULL;
3321 	}
3322 	if (file){
3323 		call->onhold_file = ms_strdup(file);
3324 	}
3325 }
3326 
3327 static void configure_adaptive_rate_control(LinphoneCall *call, MediaStream *ms, PayloadType *pt, bool_t video_will_be_used){
3328 	LinphoneCore *lc = call->core;
3329 	bool_t enabled = linphone_core_adaptive_rate_control_enabled(lc);
3330 
3331 	if (enabled){
3332 		const char *algo = linphone_core_get_adaptive_rate_algorithm(lc);
3333 		bool_t is_advanced = TRUE;
3334 		if (strcasecmp(algo, "basic") == 0) is_advanced = FALSE;
3335 		else if (strcasecmp(algo, "advanced") == 0) is_advanced = TRUE;
3336 
3337 		if (is_advanced){
3338 			/*we can't use media_stream_avpf_enabled() here because the active PayloadType is not set yet in the MediaStream.*/
3339 			if (!pt || !(pt->flags & PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED)){
3340 				ms_warning("LinphoneCall[%p] - advanced adaptive rate control requested but avpf is not activated in this stream. Reverting to basic rate control instead.", call);
3341 				is_advanced = FALSE;
3342 			}else{
3343 				ms_message("LinphoneCall[%p] - setting up advanced rate control.", call);
3344 			}
3345 		}
3346 
3347 		if (is_advanced){
3348 			ms_bandwidth_controller_add_stream(lc->bw_controller, ms);
3349 			media_stream_enable_adaptive_bitrate_control(ms, FALSE);
3350 		}else{
3351 			media_stream_set_adaptive_bitrate_algorithm(ms, MSQosAnalyzerAlgorithmSimple);
3352 			if (ms->type == MSAudio && video_will_be_used){
3353 				enabled = FALSE; /*if this is an audio stream but video is going to be used, there is
3354 				no need to perform basic rate control on the audio stream, just the video stream.*/
3355 			}
3356 			media_stream_enable_adaptive_bitrate_control(ms, enabled);
3357 		}
3358 	}else{
3359 		media_stream_enable_adaptive_bitrate_control(ms, FALSE);
3360 	}
3361 }
3362 
3363 static void linphone_call_start_audio_stream(LinphoneCall *call, LinphoneCallState next_state, bool_t video_will_be_used){
3364 	LinphoneCore *lc=call->core;
3365 	int used_pt=-1;
3366 	const SalStreamDescription *stream;
3367 	MSSndCard *playcard;
3368 	MSSndCard *captcard;
3369 	bool_t use_ec;
3370 	bool_t mute;
3371 	const char *playfile;
3372 	const char *recfile;
3373 	const char *file_to_play = NULL;
3374 	const SalStreamDescription *local_st_desc;
3375 	int crypto_idx;
3376 	MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER;
3377 	bool_t use_rtp_io = lp_config_get_int(lc->config, "sound", "rtp_io", FALSE);
3378 	bool_t use_rtp_io_enable_local_output = lp_config_get_int(lc->config, "sound", "rtp_io_enable_local_output", FALSE);
3379 
3380 	stream = sal_media_description_find_best_stream(call->resultdesc, SalAudio);
3381 	if (stream && stream->dir!=SalStreamInactive && stream->rtp_port!=0){
3382 		/* get remote stream description to check for zrtp-hash presence */
3383 		SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
3384 		const SalStreamDescription *remote_stream = sal_media_description_find_best_stream(remote_desc, SalAudio);
3385 
3386 		const char *rtp_addr=stream->rtp_addr[0]!='\0' ? stream->rtp_addr : call->resultdesc->addr;
3387 		bool_t is_multicast=ms_is_multicast(rtp_addr);
3388 		playcard=lc->sound_conf.lsd_card ?
3389 			lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
3390 		captcard=lc->sound_conf.capt_sndcard;
3391 		playfile=lc->play_file;
3392 		recfile=lc->rec_file;
3393 		call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
3394 
3395 		if (used_pt!=-1){
3396 			bool_t ok = TRUE;
3397 			call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt);
3398 			call->current_params->has_audio = TRUE;
3399 			if (playcard==NULL) {
3400 				ms_warning("No card defined for playback !");
3401 			}
3402 			if (captcard==NULL) {
3403 				ms_warning("No card defined for capture !");
3404 			}
3405 			/*Don't use file or soundcard capture when placed in recv-only mode*/
3406 			if (stream->rtp_port==0
3407 					|| stream->dir==SalStreamRecvOnly
3408 					|| (stream->multicast_role == SalMulticastReceiver && is_multicast)){
3409 				captcard=NULL;
3410 				playfile=NULL;
3411 			}
3412 			if (next_state == LinphoneCallPaused){
3413 				/*in paused state, we never use soundcard*/
3414 				playcard=NULL;
3415 				captcard=NULL;
3416 				recfile=NULL;
3417 				/*And we will eventually play "playfile" if set by the user*/
3418 			}
3419 			if (call->playing_ringbacktone){
3420 				captcard=NULL;
3421 				playfile=NULL;/* it is setup later*/
3422 				if (lp_config_get_int(lc->config,"sound","send_ringback_without_playback", 0) == 1){
3423 					playcard = NULL;
3424 					recfile = NULL;
3425 				}
3426 			}
3427 			/*if playfile are supplied don't use soundcards*/
3428 			if (lc->use_files || (use_rtp_io && !use_rtp_io_enable_local_output)) {
3429 				captcard=NULL;
3430 				playcard=NULL;
3431 			}
3432 			if (call->params->in_conference){
3433 				/* first create the graph without soundcard resources*/
3434 				captcard=playcard=NULL;
3435 			}
3436 			if (!linphone_call_sound_resources_available(call)){
3437 				ms_message("Sound resources are used by another call, not using soundcard.");
3438 				captcard=playcard=NULL;
3439 			}
3440 			use_ec=captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc);
3441 			audio_stream_enable_echo_canceller(call->audiostream, use_ec);
3442 			if (playcard &&  stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(playcard, stream->max_rate);
3443 			if (captcard &&  stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate);
3444 
3445 			rtp_session_enable_rtcp_mux(call->audiostream->ms.sessions.rtp_session, stream->rtcp_mux);
3446 			if (!call->params->in_conference && call->params->record_file){
3447 				audio_stream_mixed_record_open(call->audiostream,call->params->record_file);
3448 				call->current_params->record_file=ms_strdup(call->params->record_file);
3449 			}
3450 			/* valid local tags are > 0 */
3451 			if (sal_stream_description_has_srtp(stream) == TRUE) {
3452 				local_st_desc=sal_media_description_find_stream(call->localdesc,stream->proto,SalAudio);
3453 				crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
3454 
3455 				if (crypto_idx >= 0) {
3456 					ms_media_stream_sessions_set_srtp_recv_key_b64(&call->audiostream->ms.sessions, stream->crypto[0].algo,stream->crypto[0].master_key);
3457 					ms_media_stream_sessions_set_srtp_send_key_b64(&call->audiostream->ms.sessions, stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
3458 				} else {
3459 					ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
3460 				}
3461 			}
3462 			configure_rtp_session_for_rtcp_fb(call, stream);
3463 			configure_rtp_session_for_rtcp_xr(lc, call, SalAudio);
3464 			configure_adaptive_rate_control(call, (MediaStream*)call->audiostream, call->current_params->audio_codec, video_will_be_used);
3465 			if (is_multicast)
3466 				rtp_session_set_multicast_ttl(call->audiostream->ms.sessions.rtp_session,stream->ttl);
3467 
3468 			if (use_rtp_io) {
3469 				if(use_rtp_io_enable_local_output){
3470 					io.input.type = MSResourceRtp;
3471 					io.input.session = create_audio_rtp_io_session(call);
3472 
3473 					if (playcard){
3474 						io.output.type = MSResourceSoundcard;
3475 						io.output.soundcard = playcard;
3476 					}else{
3477 						io.output.type = MSResourceFile;
3478 						io.output.file = recfile;
3479 					}
3480 				}
3481 				else {
3482 					io.input.type = io.output.type = MSResourceRtp;
3483 					io.input.session = io.output.session = create_audio_rtp_io_session(call);
3484 				}
3485 
3486 				if (io.input.session == NULL) {
3487 					ok = FALSE;
3488 				}
3489 			}else  {
3490 				if (playcard){
3491 					io.output.type = MSResourceSoundcard;
3492 					io.output.soundcard = playcard;
3493 				}else{
3494 					io.output.type = MSResourceFile;
3495 					io.output.file = recfile;
3496 				}
3497 				if (captcard){
3498 					io.input.type = MSResourceSoundcard;
3499 					io.input.soundcard = captcard;
3500 				}else{
3501 					io.input.type = MSResourceFile;
3502 					file_to_play = playfile;
3503 					io.input.file = NULL; /*we prefer to use the remote_play api, that allows to play multimedia files */
3504 				}
3505 
3506 			}
3507 			if (ok == TRUE) {
3508 				int err = audio_stream_start_from_io(call->audiostream,
3509 					call->audio_profile,
3510 					rtp_addr,
3511 					stream->rtp_port,
3512 					stream->rtcp_addr[0]!='\0' ? stream->rtcp_addr : call->resultdesc->addr,
3513 					(linphone_core_rtcp_enabled(lc) && !is_multicast) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port+1) : 0,
3514 					used_pt,
3515 					&io);
3516 				if (err == 0){
3517 					post_configure_audio_streams(call, (call->all_muted || call->audio_muted) && !call->playing_ringbacktone);
3518 				}
3519 			}
3520 
3521 			ms_media_stream_sessions_set_encryption_mandatory(&call->audiostream->ms.sessions, linphone_call_encryption_mandatory(call));
3522 
3523 			if (next_state == LinphoneCallPaused && captcard == NULL && playfile != NULL){
3524 				int pause_time=500;
3525 				ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
3526 			}
3527 			if (call->playing_ringbacktone){
3528 				setup_ring_player(lc,call);
3529 			}
3530 
3531 			if (call->params->in_conference && lc->conf_ctx){
3532 				/*transform the graph to connect it to the conference filter */
3533 				mute = stream->dir==SalStreamRecvOnly;
3534 				linphone_conference_on_call_stream_starting(lc->conf_ctx, call, mute);
3535 			}
3536 			call->current_params->in_conference=call->params->in_conference;
3537 			call->current_params->low_bandwidth=call->params->low_bandwidth;
3538 
3539 			/* start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */
3540 			if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP) &&
3541 				(call->params->media_encryption == LinphoneMediaEncryptionZRTP || remote_stream->haveZrtpHash==1) ){
3542 				audio_stream_start_zrtp(call->audiostream);
3543 				if (remote_stream->haveZrtpHash == 1) {
3544 					int retval;
3545 					if ((retval = ms_zrtp_setPeerHelloHash(call->audiostream->ms.sessions.zrtp_context, (uint8_t *)remote_stream->zrtphash, strlen((const char *)(remote_stream->zrtphash)))) != 0) {
3546 						ms_error("Zrtp hash mismatch 0x%x", retval);
3547 					}
3548 				}
3549 			}
3550 		}else ms_warning("No audio stream accepted ?");
3551 	}
3552 	linphone_call_set_on_hold_file(call, file_to_play);
3553 }
3554 
3555 #ifdef VIDEO_ENABLED
3556 static RtpSession * create_video_rtp_io_session(LinphoneCall *call) {
3557 	PayloadType *pt;
3558 	LinphoneCore *lc = call->core;
3559 	const char *local_ip = lp_config_get_string(lc->config, "video", "rtp_local_addr", "127.0.0.1");
3560 	const char *remote_ip = lp_config_get_string(lc->config, "video", "rtp_remote_addr", "127.0.0.1");
3561 	int local_port = lp_config_get_int(lc->config, "video", "rtp_local_port", 19076);
3562 	int remote_port = lp_config_get_int(lc->config, "video", "rtp_remote_port", 19078);
3563 	int ptnum = lp_config_get_int(lc->config, "video", "rtp_ptnum", 0);
3564 	const char *rtpmap = lp_config_get_string(lc->config, "video", "rtp_map", "vp8/90000/1");
3565 	int symmetric = lp_config_get_int(lc->config, "video", "rtp_symmetric", 0);
3566 	int jittcomp = lp_config_get_int(lc->config, "video", "rtp_jittcomp", 0); /* 0 means no jitter buffer*/
3567 	RtpSession *rtp_session = NULL;
3568 	pt = rtp_profile_get_payload_from_rtpmap(call->video_profile, rtpmap);
3569 	if (pt != NULL) {
3570 		call->rtp_io_video_profile = rtp_profile_new("RTP IO video profile");
3571 		rtp_profile_set_payload(call->rtp_io_video_profile, ptnum, payload_type_clone(pt));
3572 		rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1, ms_factory_get_mtu(lc->factory));
3573 		rtp_session_set_profile(rtp_session, call->rtp_io_video_profile);
3574 		rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1);
3575 		rtp_session_enable_rtcp(rtp_session, FALSE);
3576 		rtp_session_set_payload_type(rtp_session, ptnum);
3577 		rtp_session_set_symmetric_rtp(rtp_session, (bool_t)symmetric);
3578 		rtp_session_set_jitter_compensation(rtp_session, jittcomp);
3579 		rtp_session_enable_jitter_buffer(rtp_session, jittcomp>0);
3580 	}
3581 	return rtp_session;
3582 }
3583 #endif
3584 
3585 static void linphone_call_start_video_stream(LinphoneCall *call, LinphoneCallState next_state){
3586 #ifdef VIDEO_ENABLED
3587 	LinphoneCore *lc=call->core;
3588 	int used_pt=-1;
3589 	const SalStreamDescription *vstream;
3590 	MSFilter* source = NULL;
3591 	bool_t reused_preview = FALSE;
3592 	bool_t use_rtp_io = lp_config_get_int(lc->config, "video", "rtp_io", FALSE);
3593 	MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER;
3594 
3595 	/* shutdown preview */
3596 	if (lc->previewstream!=NULL) {
3597 		if( lc->video_conf.reuse_preview_source == FALSE) video_preview_stop(lc->previewstream);
3598 		else source = video_preview_stop_reuse_source(lc->previewstream);
3599 		lc->previewstream=NULL;
3600 	}
3601 
3602 	vstream = sal_media_description_find_best_stream(call->resultdesc, SalVideo);
3603 	if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->rtp_port!=0) {
3604 		const char *rtp_addr=vstream->rtp_addr[0]!='\0' ? vstream->rtp_addr : call->resultdesc->addr;
3605 		const char *rtcp_addr=vstream->rtcp_addr[0]!='\0' ? vstream->rtcp_addr : call->resultdesc->addr;
3606 		const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,vstream->proto,SalVideo);
3607 		bool_t is_multicast=ms_is_multicast(rtp_addr);
3608 		call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt);
3609 
3610 		if (used_pt!=-1){
3611 			MediaStreamDir dir= MediaStreamSendRecv;
3612 			bool_t is_inactive=FALSE;
3613 			MSWebCam *cam;
3614 
3615 			call->current_params->video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
3616 			call->current_params->has_video=TRUE;
3617 
3618 			rtp_session_enable_rtcp_mux(call->videostream->ms.sessions.rtp_session, vstream->rtcp_mux);
3619 			if (lc->video_conf.preview_vsize.width!=0)
3620 				video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize);
3621 			video_stream_set_fps(call->videostream,linphone_core_get_preferred_framerate(lc));
3622 			if (lp_config_get_int(lc->config, "video", "nowebcam_uses_normal_fps", 0))
3623 				call->videostream->staticimage_webcam_fps_optimization = FALSE;
3624 			video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
3625 			video_stream_enable_self_view(call->videostream,lc->video_conf.selfview);
3626 			if (call->video_window_id != NULL)
3627 				video_stream_set_native_window_id(call->videostream, call->video_window_id);
3628 			else if (lc->video_window_id != NULL)
3629 				video_stream_set_native_window_id(call->videostream, lc->video_window_id);
3630 			if (lc->preview_window_id != NULL)
3631 				video_stream_set_native_preview_window_id(call->videostream, lc->preview_window_id);
3632 			video_stream_use_preview_video_window (call->videostream,lc->use_preview_window);
3633 
3634 			if (is_multicast){
3635 				if (vstream->multicast_role == SalMulticastReceiver)
3636 					dir=MediaStreamRecvOnly;
3637 				else
3638 					dir=MediaStreamSendOnly;
3639 			} else if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
3640 				dir=MediaStreamSendOnly;
3641 			}else if (vstream->dir==SalStreamRecvOnly && lc->video_conf.display ){
3642 				dir=MediaStreamRecvOnly;
3643 			}else if (vstream->dir==SalStreamSendRecv){
3644 				if (lc->video_conf.display && lc->video_conf.capture)
3645 					dir=MediaStreamSendRecv;
3646 				else if (lc->video_conf.display)
3647 					dir=MediaStreamRecvOnly;
3648 				else
3649 					dir=MediaStreamSendOnly;
3650 			}else{
3651 				ms_warning("video stream is inactive.");
3652 				/*either inactive or incompatible with local capabilities*/
3653 				is_inactive=TRUE;
3654 			}
3655 			cam = linphone_call_get_video_device(call);
3656 			if (!is_inactive){
3657 				/* get remote stream description to check for zrtp-hash presence */
3658 				SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
3659 				const SalStreamDescription *remote_stream = sal_media_description_find_best_stream(remote_desc, SalVideo);
3660 
3661 				if (sal_stream_description_has_srtp(vstream) == TRUE) {
3662 					int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag);
3663 					if (crypto_idx >= 0) {
3664 						ms_media_stream_sessions_set_srtp_recv_key_b64(&call->videostream->ms.sessions, vstream->crypto[0].algo,vstream->crypto[0].master_key);
3665 						ms_media_stream_sessions_set_srtp_send_key_b64(&call->videostream->ms.sessions, vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
3666 					}
3667 				}
3668 				configure_rtp_session_for_rtcp_fb(call, vstream);
3669 				configure_rtp_session_for_rtcp_xr(lc, call, SalVideo);
3670 				configure_adaptive_rate_control(call, (MediaStream*)call->videostream, call->current_params->video_codec, TRUE);
3671 
3672 				call->log->video_enabled = TRUE;
3673 				video_stream_set_direction (call->videostream, dir);
3674 				ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
3675 				video_stream_set_device_rotation(call->videostream, lc->device_rotation);
3676 				video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 1));
3677 				if (is_multicast)
3678 					rtp_session_set_multicast_ttl(call->videostream->ms.sessions.rtp_session,vstream->ttl);
3679 
3680 				video_stream_use_video_preset(call->videostream, lp_config_get_string(lc->config, "video", "preset", NULL));
3681 				if (lc->video_conf.reuse_preview_source && source) {
3682 					ms_message("video_stream_start_with_source kept: %p", source);
3683 					video_stream_start_with_source(call->videostream,
3684 												   call->video_profile, rtp_addr, vstream->rtp_port,
3685 												   rtcp_addr,
3686 												   linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
3687 												   used_pt, -1, cam, source);
3688 					reused_preview = TRUE;
3689 				} else {
3690 					bool_t ok = TRUE;
3691 					if (use_rtp_io) {
3692 						io.input.type = io.output.type = MSResourceRtp;
3693 						io.input.session = io.output.session = create_video_rtp_io_session(call);
3694 						if (io.input.session == NULL) {
3695 							ok = FALSE;
3696 							ms_warning("Cannot create video RTP IO session");
3697 						}
3698 					} else {
3699 						io.input.type = MSResourceCamera;
3700 						io.input.camera = cam;
3701 						io.output.type = MSResourceDefault;
3702 					}
3703 					if (ok) {
3704 						video_stream_start_from_io(call->videostream,
3705 							call->video_profile, rtp_addr, vstream->rtp_port,
3706 							rtcp_addr,
3707 							(linphone_core_rtcp_enabled(lc) && !is_multicast)  ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
3708 							used_pt, &io);
3709 					}
3710 				}
3711 				ms_media_stream_sessions_set_encryption_mandatory(&call->videostream->ms.sessions,
3712 					linphone_call_encryption_mandatory(call));
3713 				_linphone_call_set_next_video_frame_decoded_trigger(call);
3714 
3715 				/* start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */
3716 				if (call->params->media_encryption==LinphoneMediaEncryptionZRTP || remote_stream->haveZrtpHash==1) {
3717 					/*audio stream is already encrypted and video stream is active*/
3718 					if (media_stream_secured((MediaStream *)call->audiostream) && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
3719 						video_stream_start_zrtp(call->videostream);
3720 						if (remote_stream->haveZrtpHash == 1) {
3721 							int retval;
3722 							if ((retval = ms_zrtp_setPeerHelloHash(call->videostream->ms.sessions.zrtp_context, (uint8_t *)remote_stream->zrtphash, strlen((const char *)(remote_stream->zrtphash)))) != 0) {
3723 								ms_error("video stream ZRTP hash mismatch 0x%x", retval);
3724 							}
3725 						}
3726 					}
3727 				}
3728 			}
3729 		}else ms_warning("No video stream accepted.");
3730 	}else{
3731 		ms_message("No valid video stream defined.");
3732 	}
3733 	if( reused_preview == FALSE && source != NULL ){
3734 		/* destroy not-reused source filter */
3735 		ms_warning("Video preview (%p) not reused: destroying it.", source);
3736 		ms_filter_destroy(source);
3737 	}
3738 
3739 #endif
3740 }
3741 
3742 static void real_time_text_character_received(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) {
3743 	if (id == MS_RTT_4103_RECEIVED_CHAR) {
3744 		LinphoneCall *call = (LinphoneCall *)userdata;
3745 		RealtimeTextReceivedCharacter *data = (RealtimeTextReceivedCharacter *)arg;
3746 		LinphoneChatRoom * chat_room = linphone_call_get_chat_room(call);
3747 		linphone_core_real_time_text_received(call->core, chat_room, data->character, call);
3748 	}
3749 }
3750 
3751 static void linphone_call_start_text_stream(LinphoneCall *call) {
3752 	LinphoneCore *lc = call->core;
3753 	int used_pt = -1;
3754 	const SalStreamDescription *tstream;
3755 
3756 	tstream = sal_media_description_find_best_stream(call->resultdesc, SalText);
3757 	if (tstream != NULL && tstream->dir != SalStreamInactive && tstream->rtp_port != 0) {
3758 		const char *rtp_addr = tstream->rtp_addr[0] != '\0' ? tstream->rtp_addr : call->resultdesc->addr;
3759 		const char *rtcp_addr = tstream->rtcp_addr[0] != '\0' ? tstream->rtcp_addr : call->resultdesc->addr;
3760 		const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, tstream->proto, SalText);
3761 		bool_t is_multicast = ms_is_multicast(rtp_addr);
3762 		call->text_profile = make_profile(call, call->resultdesc, tstream, &used_pt);
3763 
3764 		if (used_pt != -1) {
3765 			call->current_params->text_codec = rtp_profile_get_payload(call->text_profile, used_pt);
3766 			call->current_params->realtimetext_enabled = TRUE;
3767 
3768 			if (sal_stream_description_has_srtp(tstream) == TRUE) {
3769 				int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, tstream->crypto_local_tag);
3770 				if (crypto_idx >= 0) {
3771 					ms_media_stream_sessions_set_srtp_recv_key_b64(&call->textstream->ms.sessions, tstream->crypto[0].algo, tstream->crypto[0].master_key);
3772 					ms_media_stream_sessions_set_srtp_send_key_b64(&call->textstream->ms.sessions, tstream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key);
3773 				}
3774 			}
3775 
3776 			configure_rtp_session_for_rtcp_fb(call, tstream);
3777 			configure_rtp_session_for_rtcp_xr(lc, call, SalText);
3778 			rtp_session_enable_rtcp_mux(call->textstream->ms.sessions.rtp_session, tstream->rtcp_mux);
3779 
3780 			if (is_multicast) rtp_session_set_multicast_ttl(call->textstream->ms.sessions.rtp_session,tstream->ttl);
3781 
3782 			text_stream_start(call->textstream, call->text_profile, rtp_addr, tstream->rtp_port, rtcp_addr, (linphone_core_rtcp_enabled(lc) && !is_multicast)  ? (tstream->rtcp_port ? tstream->rtcp_port : tstream->rtp_port + 1) : 0, used_pt);
3783 			ms_filter_add_notify_callback(call->textstream->rttsink, real_time_text_character_received, call, FALSE);
3784 
3785 			ms_media_stream_sessions_set_encryption_mandatory(&call->textstream->ms.sessions,
3786 				linphone_call_encryption_mandatory(call));
3787 		} else ms_warning("No text stream accepted.");
3788 	} else {
3789 		ms_message("No valid text stream defined.");
3790 	}
3791 }
3792 
3793 void linphone_call_set_symmetric_rtp(LinphoneCall *call, bool_t val){
3794 	int i;
3795 	for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
3796 		MSMediaStreamSessions *mss = &call->sessions[i];
3797 		if (mss->rtp_session){
3798 			rtp_session_set_symmetric_rtp(mss->rtp_session, val);
3799 		}
3800 	}
3801 }
3802 
3803 void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState next_state){
3804 	LinphoneCore *lc=call->core;
3805 	bool_t video_will_be_used = FALSE;
3806 #ifdef VIDEO_ENABLED
3807 	const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo);
3808 #endif
3809 
3810 	switch (next_state){
3811 		case LinphoneCallIncomingEarlyMedia:
3812 			if (linphone_core_get_remote_ringback_tone(lc)){
3813 				call->playing_ringbacktone = TRUE;
3814 			}
3815 			BCTBX_NO_BREAK;
3816 		case LinphoneCallOutgoingEarlyMedia:
3817 			if (!call->params->real_early_media){
3818 				call->all_muted = TRUE;
3819 			}
3820 		break;
3821 		default:
3822 			call->playing_ringbacktone = FALSE;
3823 			call->all_muted = FALSE;
3824 		break;
3825 	}
3826 
3827 	call->current_params->audio_codec = NULL;
3828 	call->current_params->video_codec = NULL;
3829 	call->current_params->text_codec = NULL;
3830 
3831 	if ((call->audiostream == NULL) && (call->videostream == NULL)) {
3832 		ms_fatal("start_media_stream() called without prior init !");
3833 		return;
3834 	}
3835 
3836 	if (call->ice_session != NULL){
3837 		/*if there is an ICE session when we are about to start streams, then ICE will conduct the media path checking and authentication properly.
3838 		 * Symmetric RTP must be turned off*/
3839 		linphone_call_set_symmetric_rtp(call, FALSE);
3840 	}
3841 
3842 	call->nb_media_starts++;
3843 #if defined(VIDEO_ENABLED)
3844 	if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){
3845 		/*when video is used, do not make adaptive rate control on audio, it is stupid.*/
3846 		video_will_be_used = TRUE;
3847 	}
3848 #endif
3849 	ms_message("linphone_call_start_media_streams() call=[%p] local upload_bandwidth=[%i] kbit/s; local download_bandwidth=[%i] kbit/s",
3850 		   call, linphone_core_get_upload_bandwidth(lc),linphone_core_get_download_bandwidth(lc));
3851 
3852 	call->current_params->has_audio = FALSE;
3853 	if (call->audiostream!=NULL) {
3854 		linphone_call_start_audio_stream(call, next_state, video_will_be_used);
3855 	} else {
3856 		ms_warning("linphone_call_start_media_streams(): no audio stream!");
3857 	}
3858 	call->current_params->has_video=FALSE;
3859 	if (call->videostream!=NULL) {
3860 		if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream);
3861 		linphone_call_start_video_stream(call, next_state);
3862 	}
3863 	/*the onhold file is to be played once both audio and video are ready.*/
3864 	if (call->onhold_file && !call->params->in_conference && call->audiostream){
3865 		MSFilter *player = audio_stream_open_remote_play(call->audiostream, call->onhold_file);
3866 		if (player){
3867 			int pause_time=500;
3868 			ms_filter_call_method(player, MS_PLAYER_SET_LOOP, &pause_time);
3869 			ms_filter_call_method_noarg(player, MS_PLAYER_START);
3870 		}
3871 	}
3872 
3873 	call->up_bw=linphone_core_get_upload_bandwidth(lc);
3874 
3875 	if (call->params->realtimetext_enabled) {
3876 		linphone_call_start_text_stream(call);
3877 	}
3878 
3879 	set_dtls_fingerprint_on_all_streams(call);
3880 
3881 	if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed)) {
3882 		if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
3883 			call->current_params->update_call_when_ice_completed = FALSE;
3884 			ms_message("Disabling update call when ice completed on call [%p]",call);
3885 		}
3886 		ice_session_start_connectivity_checks(call->ice_session);
3887 	} else {
3888 		/*should not start dtls until ice is completed*/
3889 		start_dtls_on_all_streams(call);
3890 	}
3891 
3892 }
3893 
3894 void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
3895 	if(call->audiostream && call->audiostream->ms.state==MSStreamPreparing) audio_stream_unprepare_sound(call->audiostream);
3896 #ifdef VIDEO_ENABLED
3897 	if (call->videostream && call->videostream->ms.state==MSStreamPreparing) {
3898 		video_stream_unprepare_video(call->videostream);
3899 	}
3900 #endif
3901 	if (call->textstream && call->textstream->ms.state == MSStreamPreparing) {
3902 		text_stream_unprepare_text(call->textstream);
3903 	}
3904 }
3905 
3906 static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDescription *local_st_desc, SalStreamDescription *old_stream, SalStreamDescription *new_stream, MediaStream *ms){
3907 	int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
3908 	if (crypto_idx >= 0) {
3909 		if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED)
3910 			ms_media_stream_sessions_set_srtp_send_key_b64(&ms->sessions, new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
3911 		if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){
3912 			ms_media_stream_sessions_set_srtp_recv_key_b64(&ms->sessions, new_stream->crypto[0].algo,new_stream->crypto[0].master_key);
3913 		}
3914 		return TRUE;
3915 	} else {
3916 		ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
3917 	}
3918 	return FALSE;
3919 }
3920 
3921 void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
3922 	SalStreamDescription *old_stream;
3923 	SalStreamDescription *new_stream;
3924 	const SalStreamDescription *local_st_desc;
3925 
3926 	local_st_desc = sal_media_description_find_secure_stream_of_type(call->localdesc, SalAudio);
3927 	old_stream = sal_media_description_find_secure_stream_of_type(old_md, SalAudio);
3928 	new_stream = sal_media_description_find_secure_stream_of_type(new_md, SalAudio);
3929 	if (call->audiostream && local_st_desc && old_stream && new_stream &&
3930 		update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->audiostream->ms)){
3931 	}
3932 
3933 	local_st_desc = sal_media_description_find_secure_stream_of_type(call->localdesc, SalText);
3934 	old_stream = sal_media_description_find_secure_stream_of_type(old_md, SalText);
3935 	new_stream = sal_media_description_find_secure_stream_of_type(new_md, SalText);
3936 	if (call->textstream && local_st_desc && old_stream && new_stream &&
3937 		update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->textstream->ms)){
3938 	}
3939 
3940 	start_dtls_on_all_streams(call);
3941 
3942 #ifdef VIDEO_ENABLED
3943 	local_st_desc = sal_media_description_find_secure_stream_of_type(call->localdesc, SalVideo);
3944 	old_stream = sal_media_description_find_secure_stream_of_type(old_md, SalVideo);
3945 	new_stream = sal_media_description_find_secure_stream_of_type(new_md, SalVideo);
3946 	if (call->videostream && local_st_desc && old_stream && new_stream &&
3947 		update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->videostream->ms)){
3948 	}
3949 #endif
3950 }
3951 
3952 void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call) {
3953 	SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
3954 	if (remote_desc) {
3955 		call->remote_session_id = remote_desc->session_id;
3956 		call->remote_session_ver = remote_desc->session_ver;
3957 	}
3958 }
3959 
3960 void linphone_call_delete_ice_session(LinphoneCall *call){
3961 	if (call->ice_session != NULL) {
3962 		ice_session_destroy(call->ice_session);
3963 		call->ice_session = NULL;
3964 		if (call->audiostream != NULL) call->audiostream->ms.ice_check_list = NULL;
3965 		if (call->videostream != NULL) call->videostream->ms.ice_check_list = NULL;
3966 		if (call->textstream != NULL) call->textstream->ms.ice_check_list = NULL;
3967 		call->audio_stats->ice_state = LinphoneIceStateNotActivated;
3968 		call->video_stats->ice_state = LinphoneIceStateNotActivated;
3969 		call->text_stats->ice_state = LinphoneIceStateNotActivated;
3970 	}
3971 }
3972 
3973 void linphone_call_delete_upnp_session(LinphoneCall *call){
3974 #ifdef BUILD_UPNP
3975 	if(call->upnp_session!=NULL) {
3976 		linphone_upnp_session_destroy(call->upnp_session);
3977 		call->upnp_session=NULL;
3978 	}
3979 #endif //BUILD_UPNP
3980 }
3981 
3982 static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){
3983 	float quality=media_stream_get_average_quality_rating(st);
3984 	if (quality>=0){
3985 		if (log->quality!=-1){
3986 			log->quality*=quality/5.0f;
3987 		}else log->quality=quality;
3988 	}
3989 }
3990 
3991 static void update_rtp_stats(LinphoneCall *call, int stream_index) {
3992 	if (call->sessions[stream_index].rtp_session) {
3993 		const rtp_stats_t *stats = rtp_session_get_stats(call->sessions[stream_index].rtp_session);
3994 		LinphoneCallStats *call_stats = NULL;
3995 		if (stream_index == call->main_audio_stream_index) {
3996 			call_stats = call->audio_stats;
3997 		} else if (stream_index == call->main_video_stream_index) {
3998 			call_stats = call->video_stats;
3999 		} else {
4000 			call_stats = call->text_stats;
4001 		}
4002 		if (call_stats) memcpy(&(call_stats->rtp_stats), stats, sizeof(*stats));
4003 	}
4004 }
4005 
4006 static void linphone_call_stop_audio_stream(LinphoneCall *call) {
4007 	LinphoneCore *lc = call->core;
4008 	if (call->audiostream!=NULL) {
4009 		linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_AUDIO);
4010 		media_stream_reclaim_sessions(&call->audiostream->ms,&call->sessions[call->main_audio_stream_index]);
4011 
4012 		if (call->audiostream->ec){
4013 			char *state_str=NULL;
4014 			ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str);
4015 			if (state_str){
4016 				ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str));
4017 				lp_config_write_relative_file(call->core->config, EC_STATE_STORE, state_str);
4018 			}
4019 		}
4020 		audio_stream_get_local_rtp_stats(call->audiostream,&call->log->local_stats);
4021 		linphone_call_log_fill_stats (call->log,(MediaStream*)call->audiostream);
4022 		if (call->endpoint){
4023 			linphone_conference_on_call_stream_stopping(lc->conf_ctx, call);
4024 		}
4025 		ms_bandwidth_controller_remove_stream(lc->bw_controller, (MediaStream*)call->audiostream);
4026 		audio_stream_stop(call->audiostream);
4027 		update_rtp_stats(call, call->main_audio_stream_index);
4028 		call->audiostream=NULL;
4029 		linphone_call_handle_stream_events(call, call->main_audio_stream_index);
4030 		rtp_session_unregister_event_queue(call->sessions[call->main_audio_stream_index].rtp_session, call->audiostream_app_evq);
4031 		ortp_ev_queue_flush(call->audiostream_app_evq);
4032 		ortp_ev_queue_destroy(call->audiostream_app_evq);
4033 		call->audiostream_app_evq=NULL;
4034 
4035 		call->current_params->audio_codec = NULL;
4036 	}
4037 }
4038 
4039 static void linphone_call_stop_video_stream(LinphoneCall *call) {
4040 #ifdef VIDEO_ENABLED
4041 	if (call->videostream!=NULL){
4042 		linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_VIDEO);
4043 		media_stream_reclaim_sessions(&call->videostream->ms,&call->sessions[call->main_video_stream_index]);
4044 		linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream);
4045 		ms_bandwidth_controller_remove_stream(call->core->bw_controller, (MediaStream*)call->videostream);
4046 		video_stream_stop(call->videostream);
4047 		update_rtp_stats(call, call->main_video_stream_index);
4048 		call->videostream=NULL;
4049 		linphone_call_handle_stream_events(call, call->main_video_stream_index);
4050 		rtp_session_unregister_event_queue(call->sessions[call->main_video_stream_index].rtp_session, call->videostream_app_evq);
4051 		ortp_ev_queue_flush(call->videostream_app_evq);
4052 		ortp_ev_queue_destroy(call->videostream_app_evq);
4053 		call->videostream_app_evq=NULL;
4054 		call->current_params->video_codec = NULL;
4055 	}
4056 #endif
4057 }
4058 
4059 static void unset_rtp_profile(LinphoneCall *call, int i){
4060 	if (call->sessions[i].rtp_session)
4061 		rtp_session_set_profile(call->sessions[i].rtp_session,&av_profile);
4062 }
4063 
4064 static void linphone_call_stop_text_stream(LinphoneCall *call) {
4065 	if (call->textstream != NULL) {
4066 		linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_TEXT);
4067 		media_stream_reclaim_sessions(&call->textstream->ms, &call->sessions[call->main_text_stream_index]);
4068 		linphone_call_log_fill_stats(call->log, (MediaStream*)call->textstream);
4069 		text_stream_stop(call->textstream);
4070 		update_rtp_stats(call, call->main_text_stream_index);
4071 		call->textstream = NULL;
4072 		linphone_call_handle_stream_events(call, call->main_text_stream_index);
4073 		rtp_session_unregister_event_queue(call->sessions[call->main_text_stream_index].rtp_session, call->textstream_app_evq);
4074 		ortp_ev_queue_flush(call->textstream_app_evq);
4075 		ortp_ev_queue_destroy(call->textstream_app_evq);
4076 		call->textstream_app_evq = NULL;
4077 		call->current_params->text_codec = NULL;
4078 	}
4079 }
4080 
4081 void linphone_call_stop_media_streams(LinphoneCall *call){
4082 	if (call->audiostream || call->videostream || call->textstream) {
4083 		if (call->audiostream && call->videostream)
4084 			audio_stream_unlink_video(call->audiostream, call->videostream);
4085 		linphone_call_stop_audio_stream(call);
4086 		linphone_call_stop_video_stream(call);
4087 		linphone_call_stop_text_stream(call);
4088 
4089 		if (call->core->msevq != NULL) {
4090 			ms_event_queue_skip(call->core->msevq);
4091 		}
4092 	}
4093 
4094 	if (call->audio_profile){
4095 		rtp_profile_destroy(call->audio_profile);
4096 		call->audio_profile=NULL;
4097 		unset_rtp_profile(call,call->main_audio_stream_index);
4098 	}
4099 	if (call->video_profile){
4100 		rtp_profile_destroy(call->video_profile);
4101 		call->video_profile=NULL;
4102 		unset_rtp_profile(call,call->main_video_stream_index);
4103 	}
4104 	if (call->text_profile){
4105 		rtp_profile_destroy(call->text_profile);
4106 		call->text_profile=NULL;
4107 		unset_rtp_profile(call,call->main_text_stream_index);
4108 	}
4109 	if (call->rtp_io_audio_profile) {
4110 		rtp_profile_destroy(call->rtp_io_audio_profile);
4111 		call->rtp_io_audio_profile = NULL;
4112 	}
4113 	if (call->rtp_io_video_profile) {
4114 		rtp_profile_destroy(call->rtp_io_video_profile);
4115 		call->rtp_io_video_profile = NULL;
4116 	}
4117 
4118 	linphone_core_soundcard_hint_check(call->core);
4119 }
4120 
4121 void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t enable) {
4122 	if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){
4123 		bool_t bypass_mode = !enable;
4124 		ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_SET_BYPASS_MODE,&bypass_mode);
4125 	}
4126 }
4127 
4128 bool_t linphone_call_echo_cancellation_enabled(LinphoneCall *call) {
4129 	if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){
4130 		bool_t val;
4131 		ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_BYPASS_MODE,&val);
4132 		return !val;
4133 	} else {
4134 		return linphone_core_echo_cancellation_enabled(call->core);
4135 	}
4136 }
4137 
4138 void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val){
4139 	if (call!=NULL && call->audiostream!=NULL ) {
4140 		if (val) {
4141 		const char *type=lp_config_get_string(call->core->config,"sound","el_type","mic");
4142 		if (strcasecmp(type,"mic")==0)
4143 			audio_stream_enable_echo_limiter(call->audiostream,ELControlMic);
4144 		else if (strcasecmp(type,"full")==0)
4145 			audio_stream_enable_echo_limiter(call->audiostream,ELControlFull);
4146 		} else {
4147 			audio_stream_enable_echo_limiter(call->audiostream,ELInactive);
4148 		}
4149 	}
4150 }
4151 
4152 bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call){
4153 	if (call!=NULL && call->audiostream!=NULL ){
4154 		return call->audiostream->el_type !=ELInactive ;
4155 	} else {
4156 		return linphone_core_echo_limiter_enabled(call->core);
4157 	}
4158 }
4159 
4160 float linphone_call_get_play_volume(LinphoneCall *call){
4161 	AudioStream *st=call->audiostream;
4162 	if (st && st->volrecv){
4163 		float vol=0;
4164 		ms_filter_call_method(st->volrecv,MS_VOLUME_GET,&vol);
4165 		return vol;
4166 
4167 	}
4168 	return LINPHONE_VOLUME_DB_LOWEST;
4169 }
4170 
4171 float linphone_call_get_record_volume(LinphoneCall *call){
4172 	AudioStream *st=call->audiostream;
4173 	if (st && st->volsend && !call->audio_muted && call->state==LinphoneCallStreamsRunning){
4174 		float vol=0;
4175 		ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol);
4176 		return vol;
4177 
4178 	}
4179 	return LINPHONE_VOLUME_DB_LOWEST;
4180 }
4181 
4182 float linphone_call_get_speaker_volume_gain(const LinphoneCall *call) {
4183 	if(call->audiostream) return audio_stream_get_sound_card_output_gain(call->audiostream);
4184 	else {
4185 		ms_error("Could not get playback volume: no audio stream");
4186 		return -1.0f;
4187 	}
4188 }
4189 
4190 void linphone_call_set_speaker_volume_gain(LinphoneCall *call, float volume) {
4191 	if(call->audiostream) audio_stream_set_sound_card_output_gain(call->audiostream, volume);
4192 	else ms_error("Could not set playback volume: no audio stream");
4193 }
4194 
4195 float linphone_call_get_microphone_volume_gain(const LinphoneCall *call) {
4196 	if(call->audiostream) return audio_stream_get_sound_card_input_gain(call->audiostream);
4197 	else {
4198 		ms_error("Could not get record volume: no audio stream");
4199 		return -1.0f;
4200 	}
4201 }
4202 
4203 void linphone_call_set_microphone_volume_gain(LinphoneCall *call, float volume) {
4204 	if(call->audiostream) audio_stream_set_sound_card_input_gain(call->audiostream, volume);
4205 	else ms_error("Could not set record volume: no audio stream");
4206 }
4207 
4208 static float agregate_ratings(float audio_rating, float video_rating){
4209 	float result;
4210 	if (audio_rating<0 && video_rating<0) result=-1;
4211 	else if (audio_rating<0) result=video_rating*5.0f;
4212 	else if (video_rating<0) result=audio_rating*5.0f;
4213 	else result=audio_rating*video_rating*5.0f;
4214 	return result;
4215 }
4216 
4217 float linphone_call_get_current_quality(LinphoneCall *call){
4218 	float audio_rating=-1.f;
4219 	float video_rating=-1.f;
4220 
4221 	if (call->audiostream){
4222 		audio_rating=media_stream_get_quality_rating((MediaStream*)call->audiostream)/5.0f;
4223 	}
4224 	if (call->videostream){
4225 		video_rating=media_stream_get_quality_rating((MediaStream*)call->videostream)/5.0f;
4226 	}
4227 	return agregate_ratings(audio_rating, video_rating);
4228 }
4229 
4230 float linphone_call_get_average_quality(LinphoneCall *call){
4231 	float audio_rating=-1.f;
4232 	float video_rating=-1.f;
4233 
4234 	if (call->audiostream){
4235 		audio_rating = media_stream_get_average_quality_rating((MediaStream*)call->audiostream)/5.0f;
4236 	}
4237 	if (call->videostream){
4238 		video_rating = media_stream_get_average_quality_rating((MediaStream*)call->videostream)/5.0f;
4239 	}
4240 	return agregate_ratings(audio_rating, video_rating);
4241 }
4242 
4243 static void update_local_stats(LinphoneCallStats *stats, MediaStream *stream) {
4244 	PayloadType *pt;
4245 	RtpSession *session = stream->sessions.rtp_session;
4246 	const MSQualityIndicator *qi = media_stream_get_quality_indicator(stream);
4247 	if (qi) {
4248 		stats->local_late_rate=ms_quality_indicator_get_local_late_rate(qi);
4249 		stats->local_loss_rate=ms_quality_indicator_get_local_loss_rate(qi);
4250 	}
4251 	media_stream_get_local_rtp_stats(stream, &stats->rtp_stats);
4252 	pt = rtp_profile_get_payload(rtp_session_get_profile(session), rtp_session_get_send_payload_type(session));
4253 	stats->clockrate = pt ? pt->clock_rate : 8000;
4254 }
4255 
4256 static MediaStream *linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type){
4257 	switch(type){
4258 		case LinphoneStreamTypeAudio:
4259 			return &call->audiostream->ms;
4260 		case LinphoneStreamTypeVideo:
4261 			return &call->videostream->ms;
4262 		case LinphoneStreamTypeText:
4263 			return &call->textstream->ms;
4264 		case LinphoneStreamTypeUnknown:
4265 			break;
4266 	}
4267 	return NULL;
4268 }
4269 
4270 static void _linphone_call_stats_clone(LinphoneCallStats *dst, const LinphoneCallStats *src) {
4271 	/*
4272 	 * Save the belle_sip_object_t part, copy the entire structure and restore the belle_sip_object_t part
4273 	 */
4274 	belle_sip_object_t tmp = dst->base;
4275 	memcpy(dst, src, sizeof(LinphoneCallStats));
4276 	dst->base = tmp;
4277 
4278 	dst->received_rtcp = NULL;
4279 	dst->sent_rtcp = NULL;
4280 }
4281 
4282 LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type){
4283 	if ((int)type >=0 && type<=LinphoneStreamTypeText){
4284 		LinphoneCallStats *stats = NULL;
4285 		LinphoneCallStats *stats_copy = linphone_call_stats_new();
4286 		if (type == LinphoneStreamTypeAudio) {
4287 			stats = call->audio_stats;
4288 		} else if (type == LinphoneStreamTypeVideo) {
4289 			stats = call->video_stats;
4290 		} else if (type == LinphoneStreamTypeText) {
4291 			stats = call->text_stats;
4292 		}
4293 		MediaStream *ms = linphone_call_get_stream(call, type);
4294 		if (ms && stats) update_local_stats(stats, ms);
4295 		_linphone_call_stats_clone(stats_copy, stats);
4296 		return stats_copy;
4297 	}
4298 	ms_error("Invalid stream type %i", (int)type);
4299 	return NULL;
4300 }
4301 
4302 LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) {
4303 	return linphone_call_get_stats(call, LinphoneStreamTypeAudio);
4304 }
4305 
4306 LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) {
4307 	return linphone_call_get_stats(call, LinphoneStreamTypeVideo);
4308 }
4309 
4310 LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call) {
4311 	return linphone_call_get_stats(call, LinphoneStreamTypeText);
4312 }
4313 
4314 static bool_t ice_in_progress(LinphoneCallStats *stats){
4315 	return stats->ice_state==LinphoneIceStateInProgress;
4316 }
4317 
4318 bool_t linphone_call_media_in_progress(LinphoneCall *call){
4319 	bool_t ret=FALSE;
4320 	if (ice_in_progress(call->audio_stats) || ice_in_progress(call->video_stats) || ice_in_progress(call->text_stats))
4321 		ret=TRUE;
4322 	/*TODO: could check zrtp state, upnp state*/
4323 	return ret;
4324 }
4325 
4326 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallStats);
4327 
4328 BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallStats, belle_sip_object_t,
4329 	NULL, // destroy
4330 	_linphone_call_stats_clone, // clone
4331 	NULL, // marshal
4332 	TRUE
4333 );
4334 
4335 LinphoneCallStats *linphone_call_stats_new() {
4336 	LinphoneCallStats *stats = belle_sip_object_new(LinphoneCallStats);
4337 	return stats;
4338 }
4339 
4340 LinphoneCallStats* linphone_call_stats_ref(LinphoneCallStats* stats) {
4341 	return (LinphoneCallStats*) belle_sip_object_ref(stats);
4342 }
4343 
4344 void linphone_call_stats_unref(LinphoneCallStats* stats) {
4345 	belle_sip_object_unref(stats);
4346 }
4347 
4348 void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats) {
4349 	return stats->user_data;
4350 }
4351 
4352 void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data) {
4353 	stats->user_data = data;
4354 }
4355 
4356 LinphoneStreamType linphone_call_stats_get_type(const LinphoneCallStats *stats) {
4357 	return stats->type;
4358 }
4359 
4360 float linphone_call_stats_get_sender_loss_rate(const LinphoneCallStats *stats) {
4361 	const report_block_t *srb = NULL;
4362 
4363 	if (!stats || !stats->sent_rtcp)
4364 		return 0.0;
4365 	/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
4366 	if (stats->sent_rtcp->b_cont != NULL)
4367 		msgpullup(stats->sent_rtcp, -1);
4368 
4369 	do{
4370 		if (rtcp_is_SR(stats->sent_rtcp))
4371 			srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
4372 		else if (rtcp_is_RR(stats->sent_rtcp))
4373 			srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
4374 		if (srb) break;
4375 	}while (rtcp_next_packet(stats->sent_rtcp));
4376 	rtcp_rewind(stats->sent_rtcp);
4377 	if (!srb)
4378 		return 0.0;
4379 	return 100.0f * report_block_get_fraction_lost(srb) / 256.0f;
4380 }
4381 
4382 float linphone_call_stats_get_receiver_loss_rate(const LinphoneCallStats *stats) {
4383 	const report_block_t *rrb = NULL;
4384 
4385 	if (!stats || !stats->received_rtcp)
4386 		return 0.0;
4387 	/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
4388 	if (stats->received_rtcp->b_cont != NULL)
4389 		msgpullup(stats->received_rtcp, -1);
4390 
4391 	do{
4392 		if (rtcp_is_RR(stats->received_rtcp))
4393 			rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
4394 		else if (rtcp_is_SR(stats->received_rtcp))
4395 			rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
4396 		if (rrb) break;
4397 	}while (rtcp_next_packet(stats->received_rtcp));
4398 	rtcp_rewind(stats->received_rtcp);
4399 	if (!rrb)
4400 		return 0.0;
4401 	return 100.0f * report_block_get_fraction_lost(rrb) / 256.0f;
4402 }
4403 
4404 float linphone_call_stats_get_local_loss_rate(const LinphoneCallStats *stats) {
4405 	return stats->local_loss_rate;
4406 }
4407 
4408 float linphone_call_stats_get_local_late_rate(const LinphoneCallStats *stats) {
4409 	return stats->local_late_rate;
4410 }
4411 
4412 float linphone_call_stats_get_sender_interarrival_jitter(const LinphoneCallStats *stats) {
4413 	const report_block_t *srb = NULL;
4414 
4415 	if (!stats || !stats->sent_rtcp)
4416 		return 0.0;
4417 	/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
4418 	if (stats->sent_rtcp->b_cont != NULL)
4419 		msgpullup(stats->sent_rtcp, -1);
4420 	if (rtcp_is_SR(stats->sent_rtcp))
4421 		srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
4422 	else if (rtcp_is_RR(stats->sent_rtcp))
4423 		srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
4424 	if (!srb)
4425 		return 0.0;
4426 	if (stats->clockrate == 0)
4427 		return 0.0;
4428 	return (float)report_block_get_interarrival_jitter(srb) / (float)stats->clockrate;
4429 }
4430 
4431 float linphone_call_stats_get_receiver_interarrival_jitter(const LinphoneCallStats *stats) {
4432 	const report_block_t *rrb = NULL;
4433 
4434 	if (!stats || !stats->received_rtcp)
4435 		return 0.0;
4436 	/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
4437 	if (stats->received_rtcp->b_cont != NULL)
4438 		msgpullup(stats->received_rtcp, -1);
4439 	if (rtcp_is_SR(stats->received_rtcp))
4440 		rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
4441 	else if (rtcp_is_RR(stats->received_rtcp))
4442 		rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
4443 	if (!rrb)
4444 		return 0.0;
4445 	if (stats->clockrate == 0)
4446 		return 0.0;
4447 	return (float)report_block_get_interarrival_jitter(rrb) / (float)stats->clockrate;
4448 }
4449 
4450 const rtp_stats_t *linphone_call_stats_get_rtp_stats(const LinphoneCallStats *stats) {
4451 	return &stats->rtp_stats;
4452 }
4453 
4454 uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCallStats *stats) {
4455 	return linphone_call_stats_get_rtp_stats(stats)->outoftime;
4456 }
4457 
4458 float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats) {
4459 	return stats->download_bandwidth;
4460 }
4461 
4462 float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats) {
4463 	return stats->upload_bandwidth;
4464 }
4465 
4466 LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats) {
4467 	return stats->ice_state;
4468 }
4469 
4470 LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats) {
4471 	return stats->upnp_state;
4472 }
4473 
4474 LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remote(const LinphoneCallStats *stats) {
4475 	return (LinphoneAddressFamily)stats->rtp_remote_family;
4476 }
4477 
4478 float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *stats) {
4479 	return stats->jitter_stats.jitter_buffer_size_ms;
4480 }
4481 
4482 float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats) {
4483 	return stats->round_trip_delay;
4484 }
4485 
4486 void linphone_call_start_recording(LinphoneCall *call){
4487 	if (!call->params->record_file){
4488 		ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file().");
4489 		return;
4490 	}
4491 	if (call->audiostream && !call->params->in_conference){
4492 		audio_stream_mixed_record_start(call->audiostream);
4493 	}
4494 	call->record_active=TRUE;
4495 }
4496 
4497 void linphone_call_stop_recording(LinphoneCall *call){
4498 	if (call->audiostream && !call->params->in_conference){
4499 		audio_stream_mixed_record_stop(call->audiostream);
4500 	}
4501 	call->record_active=FALSE;
4502 }
4503 
4504 static void report_bandwidth_for_stream(LinphoneCall *call, MediaStream *ms, LinphoneStreamType type){
4505 	bool_t active = ms ?  (media_stream_get_state(ms) == MSStreamStarted) : FALSE;
4506 	LinphoneCallStats *stats = NULL;
4507 	if (type == LinphoneStreamTypeAudio) {
4508 		stats = call->audio_stats;
4509 	} else if (type == LinphoneStreamTypeVideo) {
4510 		stats = call->video_stats;
4511 	} else if (type == LinphoneStreamTypeText) {
4512 		stats = call->text_stats;
4513 	} else {
4514 		return;
4515 	}
4516 
4517 	stats->download_bandwidth=(active) ? (float)(media_stream_get_down_bw(ms)*1e-3) : 0.f;
4518 	stats->upload_bandwidth=(active) ? (float)(media_stream_get_up_bw(ms)*1e-3) : 0.f;
4519 	stats->rtcp_download_bandwidth=(active) ? (float)(media_stream_get_rtcp_down_bw(ms)*1e-3) : 0.f;
4520 	stats->rtcp_upload_bandwidth=(active) ? (float)(media_stream_get_rtcp_up_bw(ms)*1e-3) : 0.f;
4521 	stats->rtp_remote_family=(active)
4522 		? (ortp_stream_is_ipv6(&ms->sessions.rtp_session->rtp.gs) ? LinphoneAddressFamilyInet6 : LinphoneAddressFamilyInet) : LinphoneAddressFamilyUnspec;
4523 
4524 	if (call->core->send_call_stats_periodical_updates){
4525 		if (active) update_local_stats(stats, ms);
4526 		stats->updated |= LINPHONE_CALL_STATS_PERIODICAL_UPDATE;
4527 		linphone_call_notify_stats_updated(call, stats);
4528 		stats->updated=0;
4529 	}
4530 }
4531 
4532 static void report_bandwidth(LinphoneCall *call, MediaStream *as, MediaStream *vs, MediaStream *ts){
4533 	report_bandwidth_for_stream(call, as, LinphoneStreamTypeAudio);
4534 	report_bandwidth_for_stream(call, vs, LinphoneStreamTypeVideo);
4535 	report_bandwidth_for_stream(call, ts, LinphoneStreamTypeText);
4536 
4537 	ms_message(	"Bandwidth usage for call [%p]:\n"
4538 				"\tRTP  audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec\n"
4539 				"\tRTCP audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec",
4540 				call,
4541 				call->audio_stats->download_bandwidth,
4542 				call->audio_stats->upload_bandwidth,
4543 				call->video_stats->download_bandwidth,
4544 				call->video_stats->upload_bandwidth,
4545 				call->text_stats->download_bandwidth,
4546 				call->text_stats->upload_bandwidth,
4547 				call->audio_stats->rtcp_download_bandwidth,
4548 				call->audio_stats->rtcp_upload_bandwidth,
4549 				call->video_stats->rtcp_download_bandwidth,
4550 				call->video_stats->rtcp_upload_bandwidth,
4551 				call->text_stats->rtcp_download_bandwidth,
4552 				call->text_stats->rtcp_upload_bandwidth
4553 	);
4554 }
4555 
4556 static void linphone_call_lost(LinphoneCall *call){
4557 	LinphoneCore *lc = call->core;
4558 	char *temp = NULL;
4559 	char *from = NULL;
4560 
4561 	from = linphone_call_get_remote_address_as_string(call);
4562 	temp = ms_strdup_printf("Media connectivity with %s is lost, call is going to be closed.", from ? from : "?");
4563 	if (from) ms_free(from);
4564 	ms_message("LinphoneCall [%p]: %s", call, temp);
4565 	linphone_core_notify_display_warning(lc, temp);
4566 	call->non_op_error = TRUE;
4567 	linphone_error_info_set(call->ei,NULL, LinphoneReasonIOError, 503, "Media lost", NULL);
4568 	linphone_call_terminate(call);
4569 	linphone_core_play_named_tone(lc, LinphoneToneCallLost);
4570 	ms_free(temp);
4571 }
4572 
4573 static void linphone_call_on_ice_gathering_finished(LinphoneCall *call){
4574 	int ping_time;
4575 	const SalMediaDescription *rmd = sal_call_get_remote_media_description(call->op);
4576 	if (rmd){
4577 		linphone_call_clear_unused_ice_candidates(call, rmd);
4578 	}
4579 	ice_session_compute_candidates_foundations(call->ice_session);
4580 	ice_session_eliminate_redundant_candidates(call->ice_session);
4581 	ice_session_choose_default_candidates(call->ice_session);
4582 	ping_time = ice_session_average_gathering_round_trip_time(call->ice_session);
4583 	if (ping_time >=0) {
4584 		call->ping_time=ping_time;
4585 	}
4586 }
4587 
4588 static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
4589 	OrtpEventType evt=ortp_event_get_type(ev);
4590 	OrtpEventData *evd=ortp_event_get_data(ev);
4591 
4592 	if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
4593 		switch (ice_session_state(call->ice_session)) {
4594 			case IS_Completed:
4595 			case IS_Failed:
4596 				/* At least one ICE session has succeeded, so perform a call update. */
4597 				if (ice_session_has_completed_check_list(call->ice_session) == TRUE) {
4598 					const LinphoneCallParams *current_param =  linphone_call_get_current_params(call);
4599 					if (ice_session_role(call->ice_session) == IR_Controlling && current_param->update_call_when_ice_completed ) {
4600 						LinphoneCallParams *params = linphone_core_create_call_params(call->core, call);
4601 						params->internal_call_update = TRUE;
4602 						linphone_call_update(call, params);
4603 						linphone_call_params_unref(params);
4604 					}
4605 					start_dtls_on_all_streams(call);
4606 				}
4607 				break;
4608 			default:
4609 				break;
4610 		}
4611 		linphone_call_update_ice_state_in_call_stats(call);
4612 	} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
4613 		if (evd->info.ice_processing_successful==FALSE) {
4614 			ms_warning("No STUN answer from [%s], continuing without STUN",linphone_core_get_stun_server(call->core));
4615 		}
4616 		linphone_call_on_ice_gathering_finished(call);
4617 		switch (call->state) {
4618 			case LinphoneCallUpdating:
4619 				linphone_call_start_update(call);
4620 				break;
4621 			case LinphoneCallUpdatedByRemote:
4622 				linphone_call_start_accept_update(call, call->prevstate,linphone_call_state_to_string(call->prevstate));
4623 				break;
4624 			case LinphoneCallOutgoingInit:
4625 				linphone_call_stop_media_streams_for_ice_gathering(call);
4626 				linphone_call_proceed_with_invite_if_ready(call, NULL);
4627 				break;
4628 			case LinphoneCallIdle:
4629 				linphone_call_stop_media_streams_for_ice_gathering(call);
4630 				linphone_call_update_local_media_description_from_ice_or_upnp(call);
4631 				sal_call_set_local_media_description(call->op,call->localdesc);
4632 				linphone_core_notify_incoming_call(call->core, call);
4633 				break;
4634 			default:
4635 				break;
4636 		}
4637 	} else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
4638 		if (call->state==LinphoneCallUpdatedByRemote){
4639 			linphone_call_start_accept_update(call, call->prevstate, linphone_call_state_to_string(call->prevstate));
4640 			linphone_call_update_ice_state_in_call_stats(call);
4641 		}
4642 	} else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
4643 		ice_session_restart(call->ice_session, IR_Controlling);
4644 		linphone_call_update(call, call->current_params);
4645 	}
4646 }
4647 
4648 /*do not change the prototype of this function, it is also used internally in linphone-daemon.*/
4649 void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){
4650 	OrtpEventType evt=ortp_event_get_type(ev);
4651 	OrtpEventData *evd=ortp_event_get_data(ev);
4652 
4653 	if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
4654 		stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session);
4655 		if(stats->received_rtcp != NULL)
4656 			freemsg(stats->received_rtcp);
4657 		stats->received_rtcp = evd->packet;
4658 		stats->rtcp_received_via_mux = evd->info.socket_type == OrtpRTPSocket;
4659 		evd->packet = NULL;
4660 		stats->updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE;
4661 		update_local_stats(stats,ms);
4662 	} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
4663 		memcpy(&stats->jitter_stats, rtp_session_get_jitter_stats(ms->sessions.rtp_session), sizeof(jitter_stats_t));
4664 		if (stats->sent_rtcp != NULL)
4665 			freemsg(stats->sent_rtcp);
4666 		stats->sent_rtcp = evd->packet;
4667 		evd->packet = NULL;
4668 		stats->updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE;
4669 		update_local_stats(stats,ms);
4670 	}
4671 }
4672 
4673 void linphone_call_stats_uninit(LinphoneCallStats *stats){
4674 	if (stats->received_rtcp) {
4675 		freemsg(stats->received_rtcp);
4676 		stats->received_rtcp=NULL;
4677 	}
4678 	if (stats->sent_rtcp){
4679 		freemsg(stats->sent_rtcp);
4680 		stats->sent_rtcp=NULL;
4681 	}
4682 }
4683 
4684 void linphone_call_notify_stats_updated_with_stream_index(LinphoneCall *call, int stream_index){
4685 	LinphoneCallStats *stats = NULL;
4686 	if (stream_index == call->main_audio_stream_index) {
4687 		stats = call->audio_stats;
4688 	} else if (stream_index == call->main_video_stream_index) {
4689 		stats = call->video_stats;
4690 	} else {
4691 		stats = call->text_stats;
4692 	}
4693 	if (stats->updated){
4694 		switch(stats->updated) {
4695 			case LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE:
4696 			case LINPHONE_CALL_STATS_SENT_RTCP_UPDATE:
4697 				linphone_reporting_on_rtcp_update(call, stream_index == call->main_audio_stream_index ? SalAudio : stream_index == call->main_video_stream_index ? SalVideo : SalText);
4698 				break;
4699 			default:
4700 				break;
4701 		}
4702 		linphone_call_notify_stats_updated(call, stats);
4703 		stats->updated = 0;
4704 	}
4705 }
4706 
4707 static MediaStream * linphone_call_get_media_stream(LinphoneCall *call, int stream_index){
4708 	if (stream_index == call->main_audio_stream_index)
4709 		return (MediaStream*)call->audiostream;
4710 	if (stream_index == call->main_video_stream_index)
4711 		return (MediaStream*)call->videostream;
4712 	if (stream_index == call->main_text_stream_index)
4713 		return (MediaStream*)call->textstream;
4714 	ms_error("linphone_call_get_media_stream(): no stream index %i", stream_index);
4715 	return NULL;
4716 }
4717 
4718 static OrtpEvQueue *linphone_call_get_event_queue(LinphoneCall *call, int stream_index){
4719 	if (stream_index == call->main_audio_stream_index)
4720 		return call->audiostream_app_evq;
4721 	if (stream_index == call->main_video_stream_index)
4722 		return call->videostream_app_evq;
4723 	if (stream_index == call->main_text_stream_index)
4724 		return call->textstream_app_evq;
4725 	ms_error("linphone_call_get_event_queue(): no stream index %i", stream_index);
4726 	return NULL;
4727 }
4728 
4729 void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){
4730 	MediaStream *ms = stream_index == call->main_audio_stream_index ? (MediaStream *)call->audiostream : (stream_index == call->main_video_stream_index ? (MediaStream *)call->videostream : (MediaStream *)call->textstream);
4731 	OrtpEvQueue *evq;
4732 	OrtpEvent *ev;
4733 
4734 	if (ms){
4735 		/* Ensure there is no dangling ICE check list. */
4736 		if (call->ice_session == NULL) {
4737 			media_stream_set_ice_check_list(ms, NULL);
4738 		}
4739 
4740 		switch(ms->type){
4741 			case MSAudio:
4742 				audio_stream_iterate((AudioStream*)ms);
4743 			break;
4744 			case MSVideo:
4745 	#ifdef VIDEO_ENABLED
4746 				video_stream_iterate((VideoStream*)ms);
4747 	#endif
4748 			break;
4749 			case MSText:
4750 				text_stream_iterate((TextStream*)ms);
4751 			break;
4752 			default:
4753 				ms_error("linphone_call_handle_stream_events(): unsupported stream type.");
4754 				return;
4755 			break;
4756 		}
4757 	}
4758 	/*yes the event queue has to be taken at each iteration, because ice events may perform operations re-creating the streams*/
4759 	while((evq = linphone_call_get_event_queue(call, stream_index)) != NULL && NULL != (ev=ortp_ev_queue_get(evq))){
4760 		OrtpEventType evt=ortp_event_get_type(ev);
4761 		OrtpEventData *evd=ortp_event_get_data(ev);
4762 		int stats_index;
4763 		LinphoneCallStats *stats = NULL;
4764 
4765 		if (stream_index == call->main_audio_stream_index) {
4766 			stats_index = LINPHONE_CALL_STATS_AUDIO;
4767 			stats = call->audio_stats;
4768 		} else if (stream_index == call->main_video_stream_index) {
4769 			stats_index = LINPHONE_CALL_STATS_VIDEO;
4770 			stats = call->video_stats;
4771 		} else {
4772 			stats_index = LINPHONE_CALL_STATS_TEXT;
4773 			stats = call->text_stats;
4774 		}
4775 
4776 		/*and yes the MediaStream must be taken at each iteration, because it may have changed due to the handling of events
4777 		 * in this loop*/
4778 		ms = linphone_call_get_media_stream(call, stream_index);
4779 
4780 		if (ms) linphone_call_stats_fill(stats,ms,ev);
4781 		linphone_call_notify_stats_updated_with_stream_index(call,stats_index);
4782 
4783 		if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
4784 			if (stream_index == call->main_audio_stream_index)
4785 				linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
4786 			else if (stream_index == call->main_video_stream_index) {
4787 				propagate_encryption_changed(call);
4788 			}
4789 		} else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
4790 			if (stream_index == call->main_audio_stream_index)
4791 				linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_info.sas, evd->info.zrtp_info.verified);
4792 		} else if (evt == ORTP_EVENT_DTLS_ENCRYPTION_CHANGED) {
4793 			if (stream_index == call->main_audio_stream_index)
4794 				linphone_call_audiostream_encryption_changed(call, evd->info.dtls_stream_encrypted);
4795 			else if (stream_index == call->main_video_stream_index)
4796 				propagate_encryption_changed(call);
4797 		}else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
4798 			|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
4799 			if (ms) handle_ice_events(call, ev);
4800 		} else if (evt==ORTP_EVENT_TELEPHONE_EVENT){
4801 			linphone_core_dtmf_received(call,evd->info.telephone_event);
4802 		} else if (evt == ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE) {
4803 			ms_message("Video bandwidth estimation is %i kbit/s", (int)evd->info.video_bandwidth_available / 1000);
4804 			//TODO
4805 		}
4806 		ortp_event_destroy(ev);
4807 	}
4808 }
4809 
4810 void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){
4811 	int disconnect_timeout = linphone_core_get_nortp_timeout(call->core);
4812 	bool_t disconnected=FALSE;
4813 
4814 	switch (call->state) {
4815 	case LinphoneCallStreamsRunning:
4816 	case LinphoneCallOutgoingEarlyMedia:
4817 	case LinphoneCallIncomingEarlyMedia:
4818 	case LinphoneCallPausedByRemote:
4819 	case LinphoneCallPaused:
4820 		if (one_second_elapsed){
4821 			float audio_load=0, video_load=0, text_load=0;
4822 			if (call->audiostream != NULL) {
4823 				if (call->audiostream->ms.sessions.ticker)
4824 					audio_load = ms_ticker_get_average_load(call->audiostream->ms.sessions.ticker);
4825 			}
4826 			if (call->videostream != NULL) {
4827 				if (call->videostream->ms.sessions.ticker)
4828 					video_load = ms_ticker_get_average_load(call->videostream->ms.sessions.ticker);
4829 			}
4830 			if (call->textstream != NULL) {
4831 				if (call->textstream->ms.sessions.ticker)
4832 					text_load = ms_ticker_get_average_load(call->textstream->ms.sessions.ticker);
4833 			}
4834 			report_bandwidth(call, (MediaStream*)call->audiostream, (MediaStream*)call->videostream,  (MediaStream*)call->textstream);
4835 			ms_message("Thread processing load: audio=%f\tvideo=%f\ttext=%f", audio_load, video_load, text_load);
4836 		}
4837 		break;
4838 	default:
4839 		/*no stats for other states*/
4840 		break;
4841 	}
4842 
4843 #ifdef BUILD_UPNP
4844 	linphone_upnp_call_process(call);
4845 #endif //BUILD_UPNP
4846 
4847 	linphone_call_handle_stream_events(call, call->main_audio_stream_index);
4848 	linphone_call_handle_stream_events(call, call->main_video_stream_index);
4849 	linphone_call_handle_stream_events(call, call->main_text_stream_index);
4850 	if ((call->state == LinphoneCallStreamsRunning ||
4851 		call->state == LinphoneCallPausedByRemote) && one_second_elapsed && call->audiostream!=NULL
4852 		&& call->audiostream->ms.state==MSStreamStarted && disconnect_timeout>0 ) {
4853 		disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
4854 	}
4855 	if (disconnected) linphone_call_lost(call);
4856 }
4857 
4858 void linphone_call_log_completed(LinphoneCall *call){
4859 	LinphoneCore *lc=call->core;
4860 
4861 	call->log->duration= _linphone_call_compute_duration(call); /*store duration since connected*/
4862 	call->log->error_info = linphone_error_info_ref((LinphoneErrorInfo*)linphone_call_get_error_info(call));
4863 
4864 	if (call->log->status==LinphoneCallMissed){
4865 		char *info;
4866 		lc->missed_calls++;
4867 		info=ortp_strdup_printf(ngettext("You have missed %i call.",
4868 										 "You have missed %i calls.", lc->missed_calls),
4869 								lc->missed_calls);
4870 		linphone_core_notify_display_status(lc,info);
4871 		ms_free(info);
4872 	}
4873 	linphone_core_report_call_log(lc, call->log);
4874 }
4875 
4876 LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call) {
4877 	return call->transfer_state;
4878 }
4879 
4880 void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state) {
4881 	if (state != call->transfer_state) {
4882 		ms_message("Transfer state for call [%p] changed  from [%s] to [%s]",call
4883 						,linphone_call_state_to_string(call->transfer_state)
4884 						,linphone_call_state_to_string(state));
4885 		call->transfer_state = state;
4886 		linphone_call_notify_transfer_state_changed(call, state);
4887 	}
4888 }
4889 
4890 bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
4891 	return call->params->in_conference;
4892 }
4893 
4894 LinphoneConference *linphone_call_get_conference(const LinphoneCall *call) {
4895 	return call->conf_ref;
4896 }
4897 
4898 void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) {
4899 	VideoStream* vstream = call->videostream;
4900 	if (vstream && vstream->output) {
4901 		float zoom[3];
4902 		float halfsize;
4903 
4904 		if (zoom_factor < 1)
4905 			zoom_factor = 1;
4906 		halfsize = 0.5f * 1.0f / zoom_factor;
4907 
4908 		if ((*cx - halfsize) < 0)
4909 			*cx = 0 + halfsize;
4910 		if ((*cx + halfsize) > 1)
4911 			*cx = 1 - halfsize;
4912 		if ((*cy - halfsize) < 0)
4913 			*cy = 0 + halfsize;
4914 		if ((*cy + halfsize) > 1)
4915 			*cy = 1 - halfsize;
4916 
4917 		zoom[0] = zoom_factor;
4918 		zoom[1] = *cx;
4919 		zoom[2] = *cy;
4920 		ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
4921 	}else ms_warning("Could not apply zoom: video output wasn't activated.");
4922 }
4923 
4924 static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){
4925 	LinphoneAddress *ctt=NULL;
4926 	LinphoneAddress *ret=NULL;
4927 	//const char *localip=call->localip;
4928 
4929 	/* first use user's supplied ip address if asked*/
4930 	if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
4931 		ctt=linphone_core_get_primary_contact_parsed(lc);
4932 		linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc));
4933 		ret=ctt;
4934 	} else if (call->op && sal_op_get_contact_address(call->op)!=NULL){
4935 		/* if already choosed, don't change it */
4936 		return NULL;
4937 	} else if (call->ping_op && sal_op_get_contact_address(call->ping_op)) {
4938 		/* if the ping OPTIONS request succeeded use the contact guessed from the
4939 		 received, rport*/
4940 		ms_message("Contact has been fixed using OPTIONS"/* to %s",guessed*/);
4941 		ret=linphone_address_clone(sal_op_get_contact_address(call->ping_op));;
4942 	} else 	if (dest_proxy && dest_proxy->op && sal_op_get_contact_address(dest_proxy->op)){
4943 	/*if using a proxy, use the contact address as guessed with the REGISTERs*/
4944 		ms_message("Contact has been fixed using proxy" /*to %s",fixed_contact*/);
4945 		ret=linphone_address_clone(sal_op_get_contact_address(dest_proxy->op));
4946 	} else {
4947 		ctt=linphone_core_get_primary_contact_parsed(lc);
4948 		if (ctt!=NULL){
4949 			/*otherwise use supplied localip*/
4950 			linphone_address_set_domain(ctt,NULL/*localip*/);
4951 			linphone_address_set_port(ctt,-1/*linphone_core_get_sip_port(lc)*/);
4952 			ms_message("Contact has not been fixed stack will do"/* to %s",ret*/);
4953 			ret=ctt;
4954 		}
4955 	}
4956 	return ret;
4957 }
4958 
4959 void linphone_call_set_contact_op(LinphoneCall* call) {
4960 	LinphoneAddress *contact;
4961 	contact=get_fixed_contact(call->core,call,call->dest_proxy);
4962 	if (contact){
4963 		SalTransport tport=sal_address_get_transport((SalAddress*)contact);
4964 		sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/
4965 		sal_address_set_transport((SalAddress*)contact,tport);
4966 		sal_op_set_contact_address(call->op, contact);
4967 		linphone_address_unref(contact);
4968 	}
4969 }
4970 
4971 LinphonePlayer *linphone_call_get_player(LinphoneCall *call){
4972 	if (call->player==NULL)
4973 		call->player=linphone_call_build_player(call);
4974 	return call->player;
4975 }
4976 
4977 
4978 void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params){
4979 	if ( call->state == LinphoneCallOutgoingInit || call->state == LinphoneCallIncomingReceived){
4980 		_linphone_call_set_new_params(call, params);
4981 	}
4982 	else {
4983 		ms_error("linphone_call_set_params() invalid state %s to call this function", linphone_call_state_to_string(call->state));
4984 	}
4985 }
4986 
4987 
4988 void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){
4989 	LinphoneCallParams *cp=NULL;
4990 	if (params) cp=linphone_call_params_copy(params);
4991 	if (call->params) linphone_call_params_unref(call->params);
4992 	call->params=cp;
4993 }
4994 
4995 const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call){
4996 	return call->params;
4997 }
4998 
4999 
5000 static int send_dtmf_handler(void *data, unsigned int revents){
5001 	LinphoneCall *call = (LinphoneCall*)data;
5002 	/*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/
5003 	if (linphone_core_get_use_rfc2833_for_dtmf(call->core)!=0 || linphone_core_get_use_info_for_dtmf(call->core)==0)
5004 	{
5005 		/* In Band DTMF */
5006 		if (call->audiostream!=NULL){
5007 			audio_stream_send_dtmf(call->audiostream,*call->dtmf_sequence);
5008 		}
5009 		else
5010 		{
5011 			ms_error("Cannot send RFC2833 DTMF when we are not in communication.");
5012 			return FALSE;
5013 		}
5014 	}
5015 	if (linphone_core_get_use_info_for_dtmf(call->core)!=0){
5016 		/* Out of Band DTMF (use INFO method) */
5017 		sal_call_send_dtmf(call->op,*call->dtmf_sequence);
5018 	}
5019 
5020 	/*this check is needed because linphone_call_send_dtmf does not set the timer since its a single character*/
5021 	if (call->dtmfs_timer!=NULL) {
5022 		memmove(call->dtmf_sequence, call->dtmf_sequence+1, strlen(call->dtmf_sequence));
5023 	}
5024 	/* continue only if the dtmf sequence is not empty*/
5025 	if (call->dtmf_sequence!=NULL&&*call->dtmf_sequence!='\0') {
5026 		return TRUE;
5027 	} else {
5028 		linphone_call_cancel_dtmfs(call);
5029 		return FALSE;
5030 	}
5031 }
5032 
5033 LinphoneStatus linphone_call_send_dtmf(LinphoneCall *call, char dtmf) {
5034 	if (call==NULL){
5035 		ms_warning("linphone_call_send_dtmf(): invalid call, canceling DTMF.");
5036 		return -1;
5037 	}
5038 	call->dtmf_sequence = &dtmf;
5039 	send_dtmf_handler(call,0);
5040 	call->dtmf_sequence = NULL;
5041 	return 0;
5042 }
5043 
5044 LinphoneStatus linphone_call_send_dtmfs(LinphoneCall *call,const char *dtmfs) {
5045 	if (call==NULL){
5046 		ms_warning("linphone_call_send_dtmfs(): invalid call, canceling DTMF sequence.");
5047 		return -1;
5048 	}
5049 	if (call->dtmfs_timer!=NULL){
5050 		ms_warning("linphone_call_send_dtmfs(): a DTMF sequence is already in place, canceling DTMF sequence.");
5051 		return -2;
5052 	}
5053 	if (dtmfs != NULL) {
5054 		int delay_ms = lp_config_get_int(call->core->config,"net","dtmf_delay_ms",200);
5055 		call->dtmf_sequence = ms_strdup(dtmfs);
5056 		call->dtmfs_timer = sal_create_timer(call->core->sal, send_dtmf_handler, call, delay_ms, "DTMF sequence timer");
5057 	}
5058 	return 0;
5059 }
5060 
5061 void linphone_call_cancel_dtmfs(LinphoneCall *call) {
5062 	/*nothing to do*/
5063 	if (!call || !call->dtmfs_timer) return;
5064 
5065 	sal_cancel_timer(call->core->sal, call->dtmfs_timer);
5066 	belle_sip_object_unref(call->dtmfs_timer);
5067 	call->dtmfs_timer = NULL;
5068 	if (call->dtmf_sequence != NULL) {
5069 		ms_free(call->dtmf_sequence);
5070 		call->dtmf_sequence = NULL;
5071 	}
5072 }
5073 
5074 void * linphone_call_get_native_video_window_id(const LinphoneCall *call) {
5075 	if (call->video_window_id) {
5076 		/* The video id was previously set by the app. */
5077 		return call->video_window_id;
5078 	}
5079 #ifdef VIDEO_ENABLED
5080 	else if (call->videostream) {
5081 		/* It was not set but we want to get the one automatically created by mediastreamer2 (desktop versions only). */
5082 		return video_stream_get_native_window_id(call->videostream);
5083 	}
5084 #endif
5085 	return 0;
5086 }
5087 
5088 void linphone_call_set_native_video_window_id(LinphoneCall *call, void *id) {
5089 	call->video_window_id = id;
5090 #ifdef VIDEO_ENABLED
5091 	if (call->videostream) {
5092 		video_stream_set_native_window_id(call->videostream, id);
5093 	}
5094 #endif
5095 }
5096 
5097 MSWebCam *linphone_call_get_video_device(const LinphoneCall *call) {
5098 	LinphoneCallState state = linphone_call_get_state(call);
5099 	bool_t paused = (state == LinphoneCallPausing) || (state == LinphoneCallPaused);
5100 	if (paused || call->all_muted || (call->camera_enabled == FALSE))
5101 		return get_nowebcam_device(call->core->factory);
5102 	else
5103 		return call->core->video_conf.device;
5104 }
5105 
5106 void linphone_call_set_audio_route(LinphoneCall *call, LinphoneAudioRoute route) {
5107 	if (call != NULL && call->audiostream != NULL){
5108 		audio_stream_set_audio_route(call->audiostream, (MSAudioRoute) route);
5109 	}
5110 }
5111 
5112 LinphoneChatRoom * linphone_call_get_chat_room(LinphoneCall *call) {
5113 	if (!call->chat_room){
5114 		if (call->state != LinphoneCallReleased && call->state != LinphoneCallEnd){
5115 			call->chat_room = _linphone_core_create_chat_room_from_call(call);
5116 		}
5117 	}
5118 	return call->chat_room;
5119 }
5120 
5121 int linphone_call_get_stream_count(LinphoneCall *call) {
5122 	// Revisit when multiple media streams will be implemented
5123 #ifdef VIDEO_ENABLED
5124 	if (linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) {
5125 		return 3;
5126 	}
5127 	return 2;
5128 #else
5129 	if (linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) {
5130 		return 2;
5131 	}
5132 	return 1;
5133 #endif
5134 }
5135 
5136 MSFormatType linphone_call_get_stream_type(LinphoneCall *call, int stream_index) {
5137 	// Revisit when multiple media streams will be implemented
5138 	if (stream_index == call->main_video_stream_index) {
5139 		return MSVideo;
5140 	} else if (stream_index == call->main_text_stream_index) {
5141 		return MSText;
5142 	} else if (stream_index == call->main_audio_stream_index){
5143 		return MSAudio;
5144 	}
5145 	return MSUnknownMedia;
5146 }
5147 
5148 RtpTransport* linphone_call_get_meta_rtp_transport(LinphoneCall *call, int stream_index) {
5149 	RtpTransport *meta_rtp;
5150 	RtpTransport *meta_rtcp;
5151 
5152 	if (!call || stream_index < 0 || stream_index >= linphone_call_get_stream_count(call)) {
5153 		return NULL;
5154 	}
5155 
5156 	rtp_session_get_transports(call->sessions[stream_index].rtp_session, &meta_rtp, &meta_rtcp);
5157 	return meta_rtp;
5158 }
5159 
5160 RtpTransport* linphone_call_get_meta_rtcp_transport(LinphoneCall *call, int stream_index) {
5161 	RtpTransport *meta_rtp;
5162 	RtpTransport *meta_rtcp;
5163 
5164 	if (!call || stream_index < 0 || stream_index >= linphone_call_get_stream_count(call)) {
5165 		return NULL;
5166 	}
5167 
5168 	rtp_session_get_transports(call->sessions[stream_index].rtp_session, &meta_rtp, &meta_rtcp);
5169 	return meta_rtcp;
5170 }
5171 
5172 LinphoneStatus linphone_call_pause(LinphoneCall *call) {
5173 	int err = _linphone_call_pause(call);
5174 	if (err == 0) call->paused_by_app = TRUE;
5175 	return err;
5176 }
5177 
5178 /* Internal version that does not play tone indication*/
5179 int _linphone_call_pause(LinphoneCall *call) {
5180 	LinphoneCore *lc;
5181 	const char *subject = NULL;
5182 
5183 	if ((call->state != LinphoneCallStreamsRunning) && (call->state != LinphoneCallPausedByRemote)) {
5184 		ms_warning("Cannot pause this call, it is not active.");
5185 		return -1;
5186 	}
5187 	if (sal_media_description_has_dir(call->resultdesc, SalStreamSendRecv)) {
5188 		subject = "Call on hold";
5189 	} else if (sal_media_description_has_dir(call->resultdesc, SalStreamRecvOnly)) {
5190 		subject = "Call on hold for me too";
5191 	} else {
5192 		ms_error("No reason to pause this call, it is already paused or inactive.");
5193 		return -1;
5194 	}
5195 
5196 	lc = linphone_call_get_core(call);
5197 	call->broken = FALSE;
5198 	linphone_call_set_state(call, LinphoneCallPausing, "Pausing call");
5199 	linphone_call_make_local_media_description(call);
5200 #ifdef BUILD_UPNP
5201 	if (call->upnp_session != NULL) {
5202 		linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
5203 	}
5204 #endif // BUILD_UPNP
5205 	sal_call_set_local_media_description(call->op, call->localdesc);
5206 	if (sal_call_update(call->op, subject, FALSE) != 0) {
5207 		linphone_core_notify_display_warning(lc, _("Could not pause the call"));
5208 	}
5209 	lc->current_call = NULL;
5210 	linphone_core_notify_display_status(lc, _("Pausing the current call..."));
5211 	if (call->audiostream || call->videostream || call->textstream)
5212 		linphone_call_stop_media_streams(call);
5213 	call->paused_by_app = FALSE;
5214 	return 0;
5215 }
5216 
5217 LinphoneStatus linphone_call_resume(LinphoneCall *call) {
5218 	LinphoneCore *lc;
5219 	const char *subject = "Call resuming";
5220 	char *remote_address;
5221 	char *display_status;
5222 
5223 	if (call->state != LinphoneCallPaused) {
5224 		ms_warning("we cannot resume a call that has not been established and paused before");
5225 		return -1;
5226 	}
5227 	lc = linphone_call_get_core(call);
5228 	if (call->params->in_conference == FALSE) {
5229 		if (linphone_core_sound_resources_locked(lc)) {
5230 			ms_warning("Cannot resume call %p because another call is locking the sound resources.", call);
5231 			return -1;
5232 		}
5233 		linphone_core_preempt_sound_resources(lc);
5234 		ms_message("Resuming call %p", call);
5235 	}
5236 
5237 	call->was_automatically_paused = FALSE;
5238 	call->broken = FALSE;
5239 
5240 	/* Stop playing music immediately. If remote side is a conference it
5241 	 prevents the participants to hear it while the 200OK comes back. */
5242 	if (call->audiostream) audio_stream_play(call->audiostream, NULL);
5243 
5244 	linphone_call_make_local_media_description(call);
5245 #ifdef BUILD_UPNP
5246 	if (call->upnp_session != NULL) {
5247 		linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
5248 	}
5249 #endif // BUILD_UPNP
5250 	if (!lc->sip_conf.sdp_200_ack) {
5251 		sal_call_set_local_media_description(call->op, call->localdesc);
5252 	} else {
5253 		sal_call_set_local_media_description(call->op, NULL);
5254 	}
5255 	sal_media_description_set_dir(call->localdesc, SalStreamSendRecv);
5256 	if (call->params->in_conference && !call->current_params->in_conference) subject = "Conference";
5257 	if (sal_call_update(call->op, subject, FALSE) != 0) {
5258 		return -1;
5259 	}
5260 	linphone_call_set_state(call, LinphoneCallResuming,"Resuming");
5261 	if (call->params->in_conference == FALSE)
5262 		lc->current_call = call;
5263 	remote_address = linphone_call_get_remote_address_as_string(call);
5264 	display_status = ms_strdup_printf("Resuming the call with with %s", remote_address);
5265 	ms_free(remote_address);
5266 	linphone_core_notify_display_status(lc, display_status);
5267 	ms_free(display_status);
5268 
5269 	if (lc->sip_conf.sdp_200_ack) {
5270 		/* We are NOT offering, set local media description after sending the call so that we are ready to
5271 		 process the remote offer when it will arrive. */
5272 		sal_call_set_local_media_description(call->op, call->localdesc);
5273 	}
5274 	return 0;
5275 }
5276 
5277 static void terminate_call(LinphoneCall *call) {
5278 	LinphoneCore *lc = linphone_call_get_core(call);
5279 	const bctbx_list_t *calls = linphone_core_get_calls(lc);
5280 	bool_t stop_ringing = TRUE;
5281 
5282 	if ((call->state == LinphoneCallIncomingReceived) && (linphone_error_info_get_reason(call->ei) != LinphoneReasonNotAnswered)){
5283 		linphone_error_info_set_reason(call->ei, LinphoneReasonDeclined);
5284 		call->non_op_error = TRUE;
5285 	}
5286 
5287 	/* Stop ringing */
5288 	bool_t ring_during_early_media = linphone_core_get_ring_during_incoming_early_media(lc);
5289 	while(calls) {
5290 		if (((LinphoneCall *)calls->data)->state == LinphoneCallIncomingReceived || (ring_during_early_media && ((LinphoneCall *)calls->data)->state == LinphoneCallIncomingEarlyMedia)) {
5291 			stop_ringing = FALSE;
5292 			break;
5293 		}
5294 		calls = calls->next;
5295 	}
5296 	if(stop_ringing) {
5297 		linphone_core_stop_ringing(lc);
5298 	}
5299 	linphone_call_stop_media_streams(call);
5300 
5301 #ifdef BUILD_UPNP
5302 	linphone_call_delete_upnp_session(call);
5303 #endif // BUILD_UPNP
5304 
5305 	linphone_core_notify_display_status(lc, _("Call ended") );
5306 	linphone_call_set_state(call, LinphoneCallEnd, "Call terminated");
5307 }
5308 
5309 LinphoneStatus linphone_call_terminate(LinphoneCall *call) {
5310 	return linphone_call_terminate_with_error_info(call, NULL);
5311 }
5312 
5313 
5314 LinphoneStatus linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneErrorInfo *ei){
5315 	SalErrorInfo sei={0};
5316 	LinphoneErrorInfo* p_ei = (LinphoneErrorInfo*) ei;
5317 
5318 	ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state));
5319 	switch (call->state) {
5320 		case LinphoneCallReleased:
5321 		case LinphoneCallEnd:
5322 		case LinphoneCallError:
5323 			ms_warning("No need to terminate a call [%p] in state [%s]", call, linphone_call_state_to_string(call->state));
5324 			return -1;
5325 		case LinphoneCallIncomingReceived:
5326 		case LinphoneCallIncomingEarlyMedia:
5327 			return linphone_call_decline_with_error_info(call, p_ei);
5328 		case LinphoneCallOutgoingInit:
5329 			/* In state OutgoingInit, op has to be destroyed */
5330 			sal_op_release(call->op);
5331 			call->op = NULL;
5332 			break;
5333 		default:
5334 
5335 			if (ei == NULL){
5336 				sal_call_terminate(call->op);
5337 			}
5338 			else{
5339 				linphone_error_info_to_sal(ei, &sei);
5340 				sal_call_terminate_with_error(call->op, &sei);
5341 				sal_error_info_reset(&sei);
5342 			}
5343 			break;
5344 	}
5345 
5346 	terminate_call(call);
5347 	return 0;
5348 
5349 }
5350 
5351 LinphoneStatus linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) {
5352 	char *real_url = NULL;
5353 	LinphoneCore *lc;
5354 	LinphoneAddress *real_parsed_url;
5355 	SalErrorInfo sei = {0};
5356 
5357 	if (call->state != LinphoneCallIncomingReceived) {
5358 		ms_error("Bad state for call redirection.");
5359 		return -1;
5360 	}
5361 
5362 	lc = linphone_call_get_core(call);
5363 	real_parsed_url = linphone_core_interpret_url(lc, redirect_uri);
5364 	if (!real_parsed_url) {
5365 		/* Bad url */
5366 		ms_error("Bad redirect URI: %s", redirect_uri ? redirect_uri : "NULL");
5367 		return -1;
5368 	}
5369 
5370 	real_url = linphone_address_as_string(real_parsed_url);
5371 	sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL);
5372 	sal_call_decline_with_error_info(call->op, &sei, real_url);
5373 	ms_free(real_url);
5374 	linphone_error_info_set(call->ei, NULL, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL);
5375 	call->non_op_error = TRUE;
5376 	terminate_call(call);
5377 	linphone_address_unref(real_parsed_url);
5378 	sal_error_info_reset(&sei);
5379 	return 0;
5380 }
5381 
5382 LinphoneStatus linphone_call_decline(LinphoneCall * call, LinphoneReason reason) {
5383 	LinphoneStatus status;
5384 	LinphoneErrorInfo *ei = linphone_error_info_new();
5385 	linphone_error_info_set(ei, "SIP", reason,linphone_reason_to_error_code(reason), NULL, NULL);
5386 	status = linphone_call_decline_with_error_info(call, ei);
5387 	linphone_error_info_unref(ei);
5388 	return status;
5389 }
5390 
5391 
5392 LinphoneStatus linphone_call_decline_with_error_info(LinphoneCall * call, const LinphoneErrorInfo *ei) {
5393 	SalErrorInfo sei = {0};
5394 	SalErrorInfo sub_sei = {0};
5395 
5396 	sei.sub_sei = &sub_sei;
5397 
5398 	if ((call->state != LinphoneCallIncomingReceived) && (call->state != LinphoneCallIncomingEarlyMedia)) {
5399 		ms_error("Cannot decline a call that is in state %s", linphone_call_state_to_string(call->state));
5400 		return -1;
5401 	}
5402 	if (ei) {
5403 		linphone_error_info_to_sal(ei, &sei);
5404 		sal_call_decline_with_error_info(call->op, &sei , NULL);
5405 	}else{
5406 		sal_call_decline(call->op, SalReasonDeclined, NULL);
5407 	}
5408 	sal_error_info_reset(&sei);
5409 	sal_error_info_reset(&sub_sei);
5410 	terminate_call(call);
5411 	return 0;
5412 }
5413 
5414 LinphoneStatus linphone_call_accept(LinphoneCall *call) {
5415 	return linphone_call_accept_with_params(call, NULL);
5416 }
5417 
5418 LinphoneStatus linphone_call_accept_with_params(LinphoneCall *call, const LinphoneCallParams *params) {
5419 	LinphoneCore *lc;
5420 	SalOp *replaced;
5421 	SalMediaDescription *new_md;
5422 	bool_t was_ringing = FALSE;
5423 	bctbx_list_t *iterator, *copy;
5424 
5425 	switch (call->state) {
5426 		case LinphoneCallIncomingReceived:
5427 		case LinphoneCallIncomingEarlyMedia:
5428 			break;
5429 		default:
5430 			ms_error("linphone_core_accept_call_with_params() call [%p] is in state [%s], operation not permitted.",
5431 				call, linphone_call_state_to_string(call->state));
5432 			return -1;
5433 	}
5434 
5435 	lc = linphone_call_get_core(call);
5436 	for (iterator = copy = bctbx_list_copy(linphone_core_get_calls(lc)); iterator != NULL; iterator = bctbx_list_next(iterator)) {
5437 		LinphoneCall *a_call = (LinphoneCall *)bctbx_list_get_data(iterator);
5438 		if (a_call == call) continue;
5439 		switch (a_call->state) {
5440 			case LinphoneCallOutgoingInit:
5441 			case LinphoneCallOutgoingProgress:
5442 			case LinphoneCallOutgoingRinging:
5443 			case LinphoneCallOutgoingEarlyMedia:
5444 				ms_message("Already existing call [%p] in state [%s], canceling it before accepting new call [%p]",
5445 					a_call, linphone_call_state_to_string(a_call->state), call);
5446 				linphone_call_terminate(a_call);
5447 				break;
5448 			default:
5449 				break; /* Nothing to do */
5450 		}
5451 	}
5452 	bctbx_list_free(copy);
5453 
5454 	/* Check if this call is supposed to replace an already running one */
5455 	replaced = sal_call_get_replaces(call->op);
5456 	if (replaced) {
5457 		LinphoneCall *rc = (LinphoneCall *)sal_op_get_user_pointer(replaced);
5458 		if (rc) {
5459 			ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.", call, rc);
5460 			linphone_call_terminate(rc);
5461 		}
5462 	}
5463 
5464 	if (lc->current_call != call) {
5465 		linphone_core_preempt_sound_resources(lc);
5466 	}
5467 
5468 	/* Stop ringing */
5469 	if (linphone_ringtoneplayer_is_started(lc->ringtoneplayer)) {
5470 		ms_message("Stop ringing");
5471 		linphone_core_stop_ringing(lc);
5472 		was_ringing = TRUE;
5473 	}
5474 	if (call->ringing_beep) {
5475 		linphone_core_stop_dtmf(lc);
5476 		call->ringing_beep = FALSE;
5477 	}
5478 
5479 	/* Try to be best-effort in giving real local or routable contact address */
5480 	linphone_call_set_contact_op(call);
5481 	if (params) {
5482 		_linphone_call_set_new_params(call, params);
5483 		linphone_call_prepare_ice(call, TRUE);
5484 		linphone_call_make_local_media_description(call);
5485 		sal_call_set_local_media_description(call->op, call->localdesc);
5486 		sal_op_set_sent_custom_header(call->op, params->custom_headers);
5487 	}
5488 
5489 	/* Give a chance a set card prefered sampling frequency */
5490 	if (call->localdesc->streams[0].max_rate > 0) {
5491 		ms_message("Configuring prefered card sampling rate to [%i]", call->localdesc->streams[0].max_rate);
5492 		if (lc->sound_conf.play_sndcard)
5493 			ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate);
5494 		if (lc->sound_conf.capt_sndcard)
5495 			ms_snd_card_set_preferred_sample_rate(lc->sound_conf.capt_sndcard, call->localdesc->streams[0].max_rate);
5496 	}
5497 
5498 	if (!was_ringing && (call->audiostream->ms.state == MSStreamInitialized) && !lc->use_files) {
5499 		audio_stream_prepare_sound(call->audiostream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard);
5500 	}
5501 
5502 	linphone_call_update_remote_session_id_and_ver(call);
5503 
5504 	sal_call_accept(call->op);
5505 	linphone_core_notify_display_status(lc, _("Connected."));
5506 	lc->current_call = call;
5507 	linphone_call_set_state(call, LinphoneCallConnected, "Connected");
5508 	new_md = sal_call_get_final_media_description(call->op);
5509 	linphone_call_stop_ice_for_inactive_streams(call, new_md);
5510 	if (new_md) {
5511 		linphone_call_update_streams(call, new_md, LinphoneCallStreamsRunning);
5512 		linphone_call_set_state(call, LinphoneCallStreamsRunning, "Connected (streams running)");
5513 	} else {
5514 		call->expect_media_in_ack = TRUE;
5515 	}
5516 
5517 	ms_message("Call answered");
5518 	return 0;
5519 }
5520 
5521 LinphoneStatus linphone_call_accept_early_media(LinphoneCall* call) {
5522 	return linphone_call_accept_early_media_with_params(call, NULL);
5523 }
5524 
5525 LinphoneStatus linphone_call_accept_early_media_with_params(LinphoneCall *call, const LinphoneCallParams *params) {
5526 	SalMediaDescription* md;
5527 
5528 	if (call->state != LinphoneCallIncomingReceived) {
5529 		ms_error("Bad state %s for linphone_core_accept_early_media_with_params()", linphone_call_state_to_string(call->state));
5530 		return -1;
5531 	}
5532 
5533 	/* Try to be best-effort in giving real local or routable contact address for 100Rel case */
5534 	linphone_call_set_contact_op(call);
5535 
5536 	/* If parameters are passed, update the media description */
5537 	if (params) {
5538 		_linphone_call_set_new_params(call, params);
5539 		linphone_call_make_local_media_description(call);
5540 		sal_call_set_local_media_description(call->op, call->localdesc);
5541 		sal_op_set_sent_custom_header(call->op, params->custom_headers);
5542 	}
5543 
5544 	sal_call_notify_ringing(call->op, TRUE);
5545 
5546 	linphone_call_set_state(call, LinphoneCallIncomingEarlyMedia, "Incoming call early media");
5547 	md = sal_call_get_final_media_description(call->op);
5548 	if (md) linphone_call_update_streams(call, md, call->state);
5549 	return 0;
5550 }
5551 
5552 LinphoneStatus linphone_call_update(LinphoneCall *call, const LinphoneCallParams *params) {
5553 	int err = 0;
5554 	LinphoneCallState nextstate;
5555 	LinphoneCallState initial_state = call->state;
5556 	const LinphoneCallParams *current_params;
5557 
5558 #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
5559 	bool_t has_video = FALSE;
5560 #endif
5561 
5562 	switch (initial_state) {
5563 		case LinphoneCallIncomingReceived:
5564 		case LinphoneCallIncomingEarlyMedia:
5565 		case LinphoneCallOutgoingRinging:
5566 		case LinphoneCallOutgoingEarlyMedia:
5567 			nextstate = LinphoneCallEarlyUpdating;
5568 			break;
5569 		case LinphoneCallStreamsRunning:
5570 		case LinphoneCallPausedByRemote:
5571 		case LinphoneCallUpdatedByRemote:
5572 			nextstate = LinphoneCallUpdating;
5573 			break;
5574 		case LinphoneCallPaused:
5575 			nextstate = LinphoneCallPausing;
5576 			break;
5577 		case LinphoneCallOutgoingProgress:
5578 		case LinphoneCallPausing:
5579 		case LinphoneCallResuming:
5580 		case LinphoneCallUpdating:
5581 			nextstate = initial_state;
5582 			break;
5583 		default:
5584 			ms_error("linphone_call_update() is not allowed in [%s] state", linphone_call_state_to_string(call->state));
5585 			return -1;
5586 	}
5587 
5588 	current_params = linphone_call_get_current_params(call);
5589 	if ((current_params != NULL) && (current_params == params)) {
5590 		ms_warning("linphone_call_update() is given the current params of the call, this probably not what you intend to do!");
5591 	}
5592 
5593 	linphone_call_check_ice_session(call, IR_Controlling, TRUE);
5594 
5595 	if (params != NULL) {
5596 		call->broken = FALSE;
5597 		linphone_call_set_state(call, nextstate, "Updating call");
5598 #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
5599 		has_video = call->params->has_video;
5600 
5601 		/* Video removal */
5602 		if ((call->videostream != NULL) && !params->has_video) {
5603 			if (call->upnp_session != NULL) {
5604 				if (linphone_call_update_upnp(call) < 0) {
5605 					/* uPnP port mappings failed, proceed with the call anyway. */
5606 					linphone_call_delete_upnp_session(call);
5607 				}
5608 			}
5609 		}
5610 #endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */
5611 		_linphone_call_set_new_params(call, params);
5612 		err = linphone_call_prepare_ice(call, FALSE);
5613 		if (err == 1) {
5614 			ms_message("Defer call update to gather ICE candidates");
5615 			return 0;
5616 		}
5617 
5618 #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
5619 		/* Video adding */
5620 		if (!has_video && call->params->has_video) {
5621 			if(call->upnp_session != NULL) {
5622 				ms_message("Defer call update to add uPnP port mappings");
5623 				video_stream_prepare_video(call->videostream);
5624 				if (linphone_call_update_upnp(call) < 0) {
5625 					/* uPnP port mappings failed, proceed with the call anyway. */
5626 					linphone_call_delete_upnp_session(call);
5627 				} else {
5628 					return err;
5629 				}
5630 			}
5631 		}
5632 #endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */
5633 		if ((err = linphone_call_start_update(call)) && (call->state != initial_state)) {
5634 			/* Restore initial state */
5635 			linphone_call_set_state(call, initial_state, "Restore initial state");
5636 		}
5637 	} else {
5638 #ifdef VIDEO_ENABLED
5639 		LinphoneCore *lc = linphone_call_get_core(call);
5640 		if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) {
5641 			video_stream_set_sent_video_size(call->videostream, linphone_core_get_preferred_video_size(lc));
5642 			video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc));
5643 			if (call->camera_enabled && (call->videostream->cam != lc->video_conf.device)) {
5644 				video_stream_change_camera(call->videostream, lc->video_conf.device);
5645 			} else {
5646 				video_stream_update_video_params(call->videostream);
5647 			}
5648 		}
5649 #endif
5650 	}
5651 
5652 	return err;
5653 }
5654 
5655 int linphone_call_start_update(LinphoneCall *call) {
5656 	const char *subject;
5657 	int err;
5658 	bool_t no_user_consent = call->params->no_user_consent;
5659 	LinphoneCore *lc = linphone_call_get_core(call);
5660 
5661 	linphone_call_fill_media_multicast_addr(call);
5662 
5663 	if (!no_user_consent) linphone_call_make_local_media_description(call);
5664 #ifdef BUILD_UPNP
5665 	if (call->upnp_session != NULL) {
5666 		linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
5667 	}
5668 #endif // BUILD_UPNP
5669 	if (call->params->in_conference) {
5670 		subject = "Conference";
5671 	} else if (call->params->internal_call_update) {
5672 		subject = "ICE processing concluded";
5673 	} else if (no_user_consent) {
5674 		subject = "Refreshing";
5675 	} else {
5676 		subject = "Media change";
5677 	}
5678 	linphone_core_notify_display_status(lc, _("Modifying call parameters..."));
5679 	if (!lc->sip_conf.sdp_200_ack) {
5680 		sal_call_set_local_media_description(call->op, call->localdesc);
5681 	} else {
5682 		sal_call_set_local_media_description(call->op, NULL);
5683 	}
5684 	if (call->dest_proxy && call->dest_proxy->op) {
5685 		/* Give a chance to update the contact address if connectivity has changed */
5686 		sal_op_set_contact_address(call->op, sal_op_get_contact_address(call->dest_proxy->op));
5687 	} else {
5688 		sal_op_set_contact_address(call->op, NULL);
5689 	}
5690 	err = sal_call_update(call->op, subject, no_user_consent);
5691 	if (lc->sip_conf.sdp_200_ack) {
5692 		/* We are NOT offering, set local media description after sending the call so that we are ready to
5693 		   process the remote offer when it will arrive. */
5694 		sal_call_set_local_media_description(call->op, call->localdesc);
5695 	}
5696 	return err;
5697 }
5698 
5699 LinphoneStatus linphone_call_defer_update(LinphoneCall *call) {
5700 	if (call->state != LinphoneCallUpdatedByRemote) {
5701 		ms_error("linphone_call_defer_update() not done in state LinphoneCallUpdatedByRemote");
5702 		return -1;
5703 	}
5704 
5705 	if (call->expect_media_in_ack) {
5706 		ms_error("linphone_call_defer_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
5707 		return -1;
5708 	}
5709 
5710 	call->defer_update=TRUE;
5711 	return 0;
5712 }
5713 
5714 int linphone_call_start_accept_update(LinphoneCall *call, LinphoneCallState next_state, const char *state_info) {
5715 	SalMediaDescription *md;
5716 
5717 	if ((call->ice_session != NULL) && (ice_session_nb_losing_pairs(call->ice_session) > 0)) {
5718 		/* Defer the sending of the answer until there are no losing pairs left */
5719 		return 0;
5720 	}
5721 
5722 	linphone_call_make_local_media_description(call);
5723 	linphone_call_update_remote_session_id_and_ver(call);
5724 	sal_call_set_local_media_description(call->op, call->localdesc);
5725 	sal_call_accept(call->op);
5726 	md = sal_call_get_final_media_description(call->op);
5727 	linphone_call_stop_ice_for_inactive_streams(call, md);
5728 	if (md && !sal_media_description_empty(md)) {
5729 		linphone_call_update_streams(call, md, next_state);
5730 	}
5731 	linphone_call_set_state(call, next_state, state_info);
5732 	return 0;
5733 }
5734 
5735 int _linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info) {
5736 	SalMediaDescription *remote_desc;
5737 	bool_t keep_sdp_version;
5738 	LinphoneCore *lc = linphone_call_get_core(call);
5739 #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
5740 	bool_t old_has_video = call->params->has_video;
5741 #endif
5742 
5743 	remote_desc = sal_call_get_remote_media_description(call->op);
5744 	keep_sdp_version = lp_config_get_int(lc->config, "sip", "keep_sdp_version", 0);
5745 	if (keep_sdp_version && (remote_desc->session_id == call->remote_session_id) && (remote_desc->session_ver == call->remote_session_ver)) {
5746 		/* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */
5747 		ms_warning("SDP version has not changed, send same SDP as before.");
5748 		sal_call_accept(call->op);
5749 		linphone_call_set_state(call, next_state, state_info);
5750 		return 0;
5751 	}
5752 	if (params == NULL) {
5753 		if (!sal_call_is_offerer(call->op)) {
5754 			/* Reset call param for multicast because this param is only relevant when offering */
5755 			linphone_call_params_enable_audio_multicast(call->params, FALSE);
5756 			linphone_call_params_enable_video_multicast(call->params, FALSE);
5757 		}
5758 	} else {
5759 		_linphone_call_set_new_params(call, params);
5760 	}
5761 
5762 	if (call->params->has_video && !linphone_core_video_enabled(lc)) {
5763 		ms_warning("Requested video but video support is globally disabled. Refusing video.");
5764 		call->params->has_video = FALSE;
5765 	}
5766 	if (call->current_params->in_conference) {
5767 		ms_warning("Video isn't supported in conference");
5768 		call->params->has_video = FALSE;
5769 	}
5770 	/* Update multicast params according to call params */
5771 	linphone_call_fill_media_multicast_addr(call);
5772 
5773 	linphone_call_check_ice_session(call, IR_Controlled, TRUE);
5774 	linphone_call_init_media_streams(call); /* So that video stream is initialized if necessary */
5775 	if (linphone_call_prepare_ice(call, TRUE) == 1) {
5776 		return 0; /* Deferred until completion of ICE gathering */
5777 	}
5778 
5779 #ifdef BUILD_UPNP
5780 	if (call->upnp_session != NULL) {
5781 		linphone_call_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
5782 #ifdef VIDEO_ENABLED
5783 		if ((call->params->has_video) && (call->params->has_video != old_has_video)) {
5784 			video_stream_prepare_video(call->videostream);
5785 			if (linphone_call_update_upnp(call) < 0) {
5786 				/* uPnP update failed, proceed with the call anyway. */
5787 				linphone_call_delete_upnp_session(call);
5788 			} else return 0;
5789 		}
5790 #endif // VIDEO_ENABLED
5791 	}
5792 #endif // BUILD_UPNP
5793 
5794 	linphone_call_start_accept_update(call, next_state, state_info);
5795 	return 0;
5796 }
5797 
5798 LinphoneStatus linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params) {
5799 	if (call->state != LinphoneCallUpdatedByRemote) {
5800 		ms_error("linphone_call_accept_update(): invalid state %s to call this function.", linphone_call_state_to_string(call->state));
5801 		return -1;
5802 	}
5803 	if (call->expect_media_in_ack) {
5804 		ms_error("linphone_call_accept_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
5805 		return -1;
5806 	}
5807 	return _linphone_call_accept_update(call, params, call->prevstate, linphone_call_state_to_string(call->prevstate));
5808 }
5809 
5810 LinphoneStatus linphone_call_transfer(LinphoneCall *call, const char *refer_to) {
5811 	char *real_url = NULL;
5812 	LinphoneCore *lc = linphone_call_get_core(call);
5813 	LinphoneAddress *real_parsed_url = linphone_core_interpret_url(lc, refer_to);
5814 
5815 	if (!real_parsed_url) {
5816 		/* bad url */
5817 		return -1;
5818 	}
5819 	//lc->call = NULL; // Do not do that you will lose the call afterward...
5820 	real_url = linphone_address_as_string(real_parsed_url);
5821 	sal_call_refer(call->op, real_url);
5822 	ms_free(real_url);
5823 	linphone_address_unref(real_parsed_url);
5824 	linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
5825 	return 0;
5826 }
5827 
5828 LinphoneStatus linphone_call_transfer_to_another(LinphoneCall *call, LinphoneCall *dest) {
5829 	int result = sal_call_refer_with_replaces (call->op, dest->op);
5830 	linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
5831 	return result;
5832 }
5833 
5834 int linphone_call_abort(LinphoneCall *call, const char *error) {
5835 	LinphoneCore *lc = linphone_call_get_core(call);
5836 
5837 	sal_call_terminate(call->op);
5838 
5839 	/* Stop ringing */
5840 	linphone_core_stop_ringing(lc);
5841 	linphone_call_stop_media_streams(call);
5842 
5843 #ifdef BUILD_UPNP
5844 	linphone_call_delete_upnp_session(call);
5845 #endif // BUILD_UPNP
5846 
5847 	linphone_core_notify_display_status(lc, _("Call aborted"));
5848 	linphone_call_set_state(call, LinphoneCallError, error);
5849 	return 0;
5850 }
5851 
5852 int linphone_call_proceed_with_invite_if_ready(LinphoneCall *call, LinphoneProxyConfig *dest_proxy) {
5853 	bool_t ice_ready = FALSE;
5854 	bool_t upnp_ready = FALSE;
5855 	bool_t ping_ready = FALSE;
5856 
5857 	if (call->ice_session != NULL) {
5858 		if (ice_session_candidates_gathered(call->ice_session)) ice_ready = TRUE;
5859 	} else {
5860 		ice_ready = TRUE;
5861 	}
5862 #ifdef BUILD_UPNP
5863 	if (call->upnp_session != NULL) {
5864 		if (linphone_upnp_session_get_state(call->upnp_session) == LinphoneUpnpStateOk) upnp_ready = TRUE;
5865 	} else {
5866 		upnp_ready = TRUE;
5867 	}
5868 #else
5869 	upnp_ready=TRUE;
5870 #endif // BUILD_UPNP
5871 	if (call->ping_op != NULL) {
5872 		if (call->ping_replied == TRUE) ping_ready = TRUE;
5873 	} else {
5874 		ping_ready = TRUE;
5875 	}
5876 
5877 	if ((ice_ready == TRUE) && (upnp_ready == TRUE) && (ping_ready == TRUE)) {
5878 		return linphone_call_start_invite(call, NULL);
5879 	}
5880 	return 0;
5881 }
5882 
5883 int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destination /* = NULL if to be taken from the call log */) {
5884 	int err;
5885 	char *real_url, *barmsg;
5886 	char *from;
5887 	LinphoneCore *lc = linphone_call_get_core(call);
5888 
5889 	/* Try to be best-effort in giving real local or routable contact address */
5890 	linphone_call_set_contact_op(call);
5891 
5892 	linphone_core_stop_dtmf_stream(lc);
5893 	linphone_call_make_local_media_description(call);
5894 
5895 	if (lc->ringstream == NULL) {
5896 		if (lc->sound_conf.play_sndcard && lc->sound_conf.capt_sndcard) {
5897 			/* Give a chance a set card prefered sampling frequency */
5898 			if (call->localdesc->streams[0].max_rate > 0) {
5899 				ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate);
5900 			}
5901 			if (!lc->use_files) {
5902 				audio_stream_prepare_sound(call->audiostream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard);
5903 			}
5904 		}
5905 	}
5906 	real_url = linphone_address_as_string(destination ? destination : call->log->to);
5907 	from = linphone_address_as_string(call->log->from);
5908 
5909 	if (!lc->sip_conf.sdp_200_ack) {
5910 		/* We are offering, set local media description before sending the call */
5911 		sal_call_set_local_media_description(call->op, call->localdesc);
5912 	}
5913 
5914 	barmsg = ms_strdup_printf("%s %s", _("Contacting"), real_url);
5915 	linphone_core_notify_display_status(lc, barmsg);
5916 	ms_free(barmsg);
5917 
5918 	linphone_call_ref(call); /* Take a ref because sal_call() may destroy the call if no SIP transport is available */
5919 	err = sal_call(call->op, from, real_url);
5920 
5921 	if (err < 0) {
5922 		if ((call->state != LinphoneCallError) && (call->state != LinphoneCallReleased)) {
5923 			/* sal_call() may invoke call_failure() and call_released() SAL callbacks synchronously,
5924 			   in which case there is no need to perform a state change here. */
5925 			linphone_core_notify_display_status(lc, _("Could not call"));
5926 			linphone_call_stop_media_streams(call);
5927 			linphone_call_set_state(call, LinphoneCallError, "Call failed");
5928 		}
5929 		goto end;
5930 	}
5931 	if (lc->sip_conf.sdp_200_ack) {
5932 		/* We are NOT offering, set local media description after sending the call so that we are ready to
5933 		   process the remote offer when it will arrive. */
5934 		sal_call_set_local_media_description(call->op, call->localdesc);
5935 	}
5936 	call->log->call_id = ms_strdup(sal_op_get_call_id(call->op)); /* Must be known at that time */
5937 	linphone_call_set_state(call, LinphoneCallOutgoingProgress, "Outgoing call in progress");
5938 
5939 end:
5940 	linphone_call_unref(call); /* Revert the ref taken before calling sal_call() */
5941 	ms_free(real_url);
5942 	ms_free(from);
5943 	return err;
5944 }
5945 
5946 int linphone_call_restart_invite(LinphoneCall *call) {
5947 	linphone_call_create_op(call);
5948 	linphone_call_stop_media_streams(call);
5949 	ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]);
5950 	ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]);
5951 	ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
5952 	linphone_call_init_media_streams(call);
5953 	return linphone_call_start_invite(call, NULL);
5954 }
5955 
5956 void linphone_call_set_broken(LinphoneCall *call){
5957 	switch(call->state){
5958 		/*for all the early states, we prefer to drop the call*/
5959 		case LinphoneCallOutgoingInit:
5960 		case LinphoneCallOutgoingProgress:
5961 		case LinphoneCallOutgoingRinging:
5962 		case LinphoneCallOutgoingEarlyMedia:
5963 		case LinphoneCallIncomingReceived:
5964 		case LinphoneCallIncomingEarlyMedia:
5965 			/*during the early states, the SAL layer reports the failure from the dialog or transaction layer,
5966 			 * hence, there is nothing special to do*/
5967 		//break;
5968 		case LinphoneCallStreamsRunning:
5969 		case LinphoneCallUpdating:
5970 		case LinphoneCallPausing:
5971 		case LinphoneCallResuming:
5972 		case LinphoneCallPaused:
5973 		case LinphoneCallPausedByRemote:
5974 		case LinphoneCallUpdatedByRemote:
5975 			/*during these states, the dialog is established. A failure of a transaction is not expected to close it.
5976 			 * Instead we have to repair the dialog by sending a reINVITE*/
5977 			call->broken = TRUE;
5978 			call->need_localip_refresh = TRUE;
5979 		break;
5980 		default:
5981 			ms_error("linphone_call_set_broken() unimplemented case.");
5982 		break;
5983 	}
5984 }
5985 
5986 static void linphone_call_repair_by_invite_with_replaces(LinphoneCall *call) {
5987 	const char *call_id = sal_op_get_call_id(call->op);
5988 	const char *from_tag = sal_call_get_local_tag(call->op);
5989 	const char *to_tag = sal_call_get_remote_tag(call->op);
5990 	sal_op_kill_dialog(call->op);
5991 	linphone_call_create_op(call);
5992 	sal_call_set_replaces(call->op, call_id, from_tag, to_tag);
5993 	linphone_call_start_invite(call, NULL);
5994 }
5995 
5996 void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call) {
5997 	LinphoneCallParams *params;
5998 	ms_message("LinphoneCall[%p] is going to be updated (reINVITE) in order to recover from lost connectivity", call);
5999 	if (call->ice_session){
6000 		ice_session_reset(call->ice_session, IR_Controlling);
6001 	}
6002 	params = linphone_core_create_call_params(call->core, call);
6003 	linphone_call_update(call, params);
6004 	linphone_call_params_unref(params);
6005 }
6006 
6007 void linphone_call_repair_if_broken(LinphoneCall *call){
6008 	SalErrorInfo sei = {0};
6009 	if (!call->broken) return;
6010 	if (!call->core->media_network_reachable) return;
6011 
6012 	/*Make sure that the proxy from which we received this call, or to which we routed this call is registered first*/
6013 	if (call->dest_proxy){
6014 		/*in all other cases, ie no proxy config, or a proxy config for which no registration was requested, we can start the
6015 		 * call repair immediately.*/
6016 		if (linphone_proxy_config_register_enabled(call->dest_proxy)
6017 			&& linphone_proxy_config_get_state(call->dest_proxy) != LinphoneRegistrationOk) return;
6018 	}
6019 
6020 	switch (call->state){
6021 		case LinphoneCallUpdating:
6022 		case LinphoneCallPausing:
6023 			if (sal_call_dialog_request_pending(call->op)) {
6024 				/* Need to cancel first re-INVITE as described in section 5.5 of RFC 6141 */
6025 				sal_call_cancel_invite(call->op);
6026 				call->reinvite_on_cancel_response_requested = TRUE;
6027 			}
6028 			break;
6029 		case LinphoneCallStreamsRunning:
6030 		case LinphoneCallPaused:
6031 		case LinphoneCallPausedByRemote:
6032 			if (!sal_call_dialog_request_pending(call->op)) {
6033 				linphone_call_reinvite_to_recover_from_connection_loss(call);
6034 			}
6035 			break;
6036 		case LinphoneCallUpdatedByRemote:
6037 			if (sal_call_dialog_request_pending(call->op)) {
6038 				sal_error_info_set(&sei, SalReasonServiceUnavailable,"SIP", 0, NULL, NULL);
6039 				sal_call_decline_with_error_info(call->op, &sei,NULL);
6040 			}
6041 			linphone_call_reinvite_to_recover_from_connection_loss(call);
6042 			break;
6043 		case LinphoneCallOutgoingInit:
6044 		case LinphoneCallOutgoingProgress:
6045 			sal_call_cancel_invite(call->op);
6046 			call->reinvite_on_cancel_response_requested = TRUE;
6047 			break;
6048 		case LinphoneCallOutgoingEarlyMedia:
6049 		case LinphoneCallOutgoingRinging:
6050 			linphone_call_repair_by_invite_with_replaces(call);
6051 			break;
6052 		case LinphoneCallIncomingEarlyMedia:
6053 		case LinphoneCallIncomingReceived:
6054 			/* Keep the call broken until a forked INVITE is received from the server. */
6055 			break;
6056 		default:
6057 			ms_warning("linphone_call_repair_if_broken(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
6058 			call->broken = FALSE;
6059 		break;
6060 	}
6061 	sal_error_info_reset(&sei);
6062 }
6063 
6064 void linphone_call_refresh_sockets(LinphoneCall *call){
6065 	int i;
6066 	for (i=0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
6067 		MSMediaStreamSessions *mss = &call->sessions[i];
6068 		if (mss->rtp_session){
6069 			rtp_session_refresh_sockets(mss->rtp_session);
6070 		}
6071 	}
6072 }
6073 
6074 void linphone_call_replace_op(LinphoneCall *call, SalOp *op) {
6075 	SalOp *oldop = call->op;
6076 	LinphoneCallState oldstate = linphone_call_get_state(call);
6077 	call->op = op;
6078 	sal_op_set_user_pointer(call->op, call);
6079 	sal_call_set_local_media_description(call->op, call->localdesc);
6080 	switch (linphone_call_get_state(call)) {
6081 		case LinphoneCallIncomingEarlyMedia:
6082 		case LinphoneCallIncomingReceived:
6083 			sal_call_notify_ringing(call->op, (linphone_call_get_state(call) == LinphoneCallIncomingEarlyMedia) ? TRUE : FALSE);
6084 			break;
6085 		case LinphoneCallConnected:
6086 		case LinphoneCallStreamsRunning:
6087 			sal_call_accept(call->op);
6088 			break;
6089 		default:
6090 			ms_warning("linphone_call_replace_op(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
6091 			break;
6092 	}
6093 	switch (oldstate) {
6094 		case LinphoneCallIncomingEarlyMedia:
6095 		case LinphoneCallIncomingReceived:
6096 			sal_op_set_user_pointer(oldop, NULL); /* To make the call does not get terminated by terminating this op. */
6097 			/* Do not terminate a forked INVITE */
6098 			if (sal_call_get_replaces(op)) {
6099 				sal_call_terminate(oldop);
6100 			} else {
6101 				sal_op_kill_dialog(oldop);
6102 			}
6103 			break;
6104 		case LinphoneCallConnected:
6105 		case LinphoneCallStreamsRunning:
6106 			sal_call_terminate(oldop);
6107 			sal_op_kill_dialog(oldop);
6108 			break;
6109 		default:
6110 			break;
6111 	}
6112 	sal_op_release(oldop);
6113 }
6114 
6115 void linphone_call_ogl_render(const LinphoneCall *call) {
6116 	#ifdef VIDEO_ENABLED
6117 
6118 	VideoStream *stream = call->videostream;
6119 	if (stream && stream->output && ms_filter_get_id(stream->output) == MS_OGL_ID)
6120 		ms_filter_call_method(stream->output, MS_OGL_RENDER, NULL);
6121 
6122 	#endif
6123 }
6124 
6125 void linphone_call_add_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs) {
6126 	call->callbacks = bctbx_list_append(call->callbacks, linphone_call_cbs_ref(cbs));
6127 }
6128 
6129 void linphone_call_remove_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs) {
6130 	call->callbacks = bctbx_list_remove(call->callbacks, cbs);
6131 	linphone_call_cbs_unref(cbs);
6132 }
6133 
6134 LinphoneCallCbs *linphone_call_get_current_callbacks(const LinphoneCall *call) {
6135 	return call->current_cbs;
6136 }
6137 
6138 #define NOTIFY_IF_EXIST(function_name, ...) \
6139 	bctbx_list_t* iterator; \
6140 	for (iterator = call->callbacks; iterator != NULL; iterator = bctbx_list_next(iterator)) { \
6141 		call->current_cbs = (LinphoneCallCbs *)bctbx_list_get_data(iterator); \
6142 		if (call->current_cbs->function_name != NULL) { \
6143 			call->current_cbs->function_name(__VA_ARGS__); \
6144 		} \
6145 	}
6146 
6147 void linphone_call_notify_state_changed(LinphoneCall *call, LinphoneCallState cstate, const char *message) {
6148 	NOTIFY_IF_EXIST(state_changed_cb, call, cstate, message)
6149 	linphone_core_notify_call_state_changed(linphone_call_get_core(call), call, cstate, message);
6150 }
6151 
6152 void linphone_call_notify_dtmf_received(LinphoneCall *call, int dtmf) {
6153 	NOTIFY_IF_EXIST(dtmf_received_cb, call, dtmf)
6154 	linphone_core_notify_dtmf_received(linphone_call_get_core(call), call, dtmf);
6155 }
6156 
6157 void linphone_call_notify_encryption_changed(LinphoneCall *call, bool_t on, const char *authentication_token) {
6158 	NOTIFY_IF_EXIST(encryption_changed_cb, call, on, authentication_token)
6159 	linphone_core_notify_call_encryption_changed(linphone_call_get_core(call), call, on, authentication_token);
6160 }
6161 
6162 void linphone_call_notify_transfer_state_changed(LinphoneCall *call, LinphoneCallState cstate) {
6163 	NOTIFY_IF_EXIST(transfer_state_changed_cb, call, cstate)
6164 	linphone_core_notify_transfer_state_changed(linphone_call_get_core(call), call, cstate);
6165 }
6166 
6167 void linphone_call_notify_stats_updated(LinphoneCall *call, const LinphoneCallStats *stats) {
6168 	NOTIFY_IF_EXIST(stats_updated_cb, call, stats)
6169 	linphone_core_notify_call_stats_updated(linphone_call_get_core(call), call, stats);
6170 }
6171 
6172 void linphone_call_notify_info_message_received(LinphoneCall *call, const LinphoneInfoMessage *msg) {
6173 	NOTIFY_IF_EXIST(info_message_received_cb, call, msg)
6174 	linphone_core_notify_info_received(linphone_call_get_core(call), call, msg);
6175 }
6176 
6177 void linphone_call_notify_ack_processing(LinphoneCall *call, void *msg, bool_t is_received) {
6178 	NOTIFY_IF_EXIST(ack_processing, call, msg, is_received)
6179 }
6180 
6181