call_tester.c 189 KB
Newer Older
jehan's avatar
jehan committed
1
/*
2 3
	liblinphone_tester - liblinphone test suite
	Copyright (C) 2013  Belledonne Communications SARL
jehan's avatar
jehan committed
4

5 6 7 8
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.
jehan's avatar
jehan committed
9

10 11 12 13
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
jehan's avatar
jehan committed
14

15 16
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
jehan's avatar
jehan committed
17
*/
Ghislain MARY's avatar
Ghislain MARY committed
18

Simon Morlat's avatar
Simon Morlat committed
19

Ghislain MARY's avatar
Ghislain MARY committed
20
#include <sys/types.h>
21
#include <sys/stat.h>
jehan's avatar
jehan committed
22
#include "linphonecore.h"
23
#include "lpconfig.h"
jehan's avatar
jehan committed
24 25
#include "private.h"
#include "liblinphone_tester.h"
Simon Morlat's avatar
Simon Morlat committed
26
#include "mediastreamer2/msutils.h"
jehan's avatar
jehan committed
27
#include "belle-sip/sipstack.h"
Simon Morlat's avatar
Simon Morlat committed
28

Ghislain MARY's avatar
Ghislain MARY committed
29
#ifdef _WIN32
Simon Morlat's avatar
Simon Morlat committed
30
#define unlink _unlink
Ghislain MARY's avatar
Ghislain MARY committed
31 32 33
#ifndef F_OK
#define F_OK 00 /*visual studio does not define F_OK*/
#endif
Simon Morlat's avatar
Simon Morlat committed
34
#endif
jehan's avatar
jehan committed
35

36
static void srtp_call(void);
Simon Morlat's avatar
Simon Morlat committed
37
static char *create_filepath(const char *dir, const char *filename, const char *ext);
jehan's avatar
jehan committed
38

39 40 41 42 43 44 45
// prototype definition for call_recording()
#ifdef ANDROID
#ifdef HAVE_OPENH264
extern void libmsopenh264_init(void);
#endif
#endif

jehan's avatar
jehan committed
46 47 48
void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){
	char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to);
	char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from);
49
	stats* counters;
jehan's avatar
jehan committed
50 51 52 53
	ms_message(" %s call from [%s] to [%s], new state is [%s]"	,linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing"
																,from
																,to
																,linphone_call_state_to_string(cstate));
jehan's avatar
jehan committed
54 55
	ms_free(to);
	ms_free(from);
56
	counters = get_stats(lc);
jehan's avatar
jehan committed
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
	switch (cstate) {
	case LinphoneCallIncomingReceived:counters->number_of_LinphoneCallIncomingReceived++;break;
	case LinphoneCallOutgoingInit :counters->number_of_LinphoneCallOutgoingInit++;break;
	case LinphoneCallOutgoingProgress :counters->number_of_LinphoneCallOutgoingProgress++;break;
	case LinphoneCallOutgoingRinging :counters->number_of_LinphoneCallOutgoingRinging++;break;
	case LinphoneCallOutgoingEarlyMedia :counters->number_of_LinphoneCallOutgoingEarlyMedia++;break;
	case LinphoneCallConnected :counters->number_of_LinphoneCallConnected++;break;
	case LinphoneCallStreamsRunning :counters->number_of_LinphoneCallStreamsRunning++;break;
	case LinphoneCallPausing :counters->number_of_LinphoneCallPausing++;break;
	case LinphoneCallPaused :counters->number_of_LinphoneCallPaused++;break;
	case LinphoneCallResuming :counters->number_of_LinphoneCallResuming++;break;
	case LinphoneCallRefered :counters->number_of_LinphoneCallRefered++;break;
	case LinphoneCallError :counters->number_of_LinphoneCallError++;break;
	case LinphoneCallEnd :counters->number_of_LinphoneCallEnd++;break;
	case LinphoneCallPausedByRemote :counters->number_of_LinphoneCallPausedByRemote++;break;
	case LinphoneCallUpdatedByRemote :counters->number_of_LinphoneCallUpdatedByRemote++;break;
	case LinphoneCallIncomingEarlyMedia :counters->number_of_LinphoneCallIncomingEarlyMedia++;break;
	case LinphoneCallUpdating :counters->number_of_LinphoneCallUpdating++;break;
	case LinphoneCallReleased :counters->number_of_LinphoneCallReleased++;break;
76 77
	case LinphoneCallEarlyUpdating: counters->number_of_LinphoneCallEarlyUpdating++;break;
	case LinphoneCallEarlyUpdatedByRemote: counters->number_of_LinphoneCallEarlyUpdatedByRemote++;break;
jehan's avatar
jehan committed
78
	default:
79
		BC_FAIL("unexpected event");break;
jehan's avatar
jehan committed
80 81
	}
}
82 83 84

void call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *lstats) {
	stats* counters = get_stats(lc);
85
	counters->number_of_LinphoneCallStatsUpdated++;
86
	if (lstats->updated & LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) {
87
		counters->number_of_rtcp_received++;
88 89
	}
	if (lstats->updated & LINPHONE_CALL_STATS_SENT_RTCP_UPDATE ) {
90 91
		counters->number_of_rtcp_sent++;
	}
92 93 94 95 96 97 98 99 100 101 102 103
	if (lstats->updated & LINPHONE_CALL_STATS_PERIODICAL_UPDATE ) {
		int tab_size = sizeof (counters->audio_download_bandwidth)/sizeof(int);
		int index =  (counters->current_bandwidth_index++) % tab_size;

		counters->current_audio_download_bandwidth = counters->audio_download_bandwidth + index;
		counters->current_audio_upload_bandwidth = counters->audio_upload_bandwidth +index;

		counters->audio_download_bandwidth[index] = linphone_call_get_audio_stats(call)->download_bandwidth;
		counters->audio_upload_bandwidth[index] = linphone_call_get_audio_stats(call)->upload_bandwidth;
		counters->video_download_bandwidth[index] = linphone_call_get_video_stats(call)->download_bandwidth;
		counters->video_upload_bandwidth[index] = linphone_call_get_video_stats(call)->upload_bandwidth;
	}
104

105 106
}

jehan's avatar
jehan committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) {
	char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to);
	char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from);
	stats* counters;
	ms_message(" %s call from [%s] to [%s], is now [%s]",linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing"
														,from
														,to
														,(on?"encrypted":"unencrypted"));
	ms_free(to);
	ms_free(from);
	counters = get_stats(lc);
	if (on)
		counters->number_of_LinphoneCallEncryptedOn++;
	else
		counters->number_of_LinphoneCallEncryptedOff++;
}
johan's avatar
johan committed
123

jehan's avatar
jehan committed
124 125 126
void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) {
	char* to=linphone_address_as_string(linphone_call_get_call_log(transfered)->to);
	char* from=linphone_address_as_string(linphone_call_get_call_log(transfered)->from);
127
	stats* counters;
jehan's avatar
jehan committed
128 129 130 131
	ms_message("Transferred call from [%s] to [%s], new state is [%s]",from,to,linphone_call_state_to_string(new_call_state));
	ms_free(to);
	ms_free(from);

132
	counters = get_stats(lc);
jehan's avatar
jehan committed
133
	switch (new_call_state) {
jehan's avatar
jehan committed
134
	case LinphoneCallOutgoingInit :counters->number_of_LinphoneTransferCallOutgoingInit++;break;
135 136 137 138 139
	case LinphoneCallOutgoingProgress :counters->number_of_LinphoneTransferCallOutgoingProgress++;break;
	case LinphoneCallOutgoingRinging :counters->number_of_LinphoneTransferCallOutgoingRinging++;break;
	case LinphoneCallOutgoingEarlyMedia :counters->number_of_LinphoneTransferCallOutgoingEarlyMedia++;break;
	case LinphoneCallConnected :counters->number_of_LinphoneTransferCallConnected++;break;
	case LinphoneCallStreamsRunning :counters->number_of_LinphoneTransferCallStreamsRunning++;break;
140
	case LinphoneCallError :counters->number_of_LinphoneTransferCallError++;break;
jehan's avatar
jehan committed
141
	default:
142
		BC_FAIL("unexpected event");break;
jehan's avatar
jehan committed
143 144
	}
}
Ghislain MARY's avatar
Ghislain MARY committed
145

jehan's avatar
jehan committed
146 147

void linphone_call_cb(LinphoneCall *call,void * user_data) {
jehan's avatar
jehan committed
148 149
	char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to);
	char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from);
150
	stats* counters;
jehan's avatar
jehan committed
151 152 153 154
	LinphoneCore* lc=(LinphoneCore*)user_data;
	ms_message("call from [%s] to [%s] receive iFrame",from,to);
	ms_free(to);
	ms_free(from);
155
	counters = (stats*)get_stats(lc);
jehan's avatar
jehan committed
156 157
	counters->number_of_IframeDecoded++;
}
Simon Morlat's avatar
Simon Morlat committed
158

Simon Morlat's avatar
Simon Morlat committed
159
void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee) {
160 161
	LinphoneCall *c1,*c2;
	int dummy=0;
Simon Morlat's avatar
Simon Morlat committed
162
	MSTimeSpec ts;
163 164 165

	c1=linphone_core_get_current_call(caller->lc);
	c2=linphone_core_get_current_call(callee->lc);
166

167 168
	BC_ASSERT_PTR_NOT_NULL(c1);
	BC_ASSERT_PTR_NOT_NULL(c2);
169

Simon Morlat's avatar
Simon Morlat committed
170
	if (!c1 || !c2) return;
jehan's avatar
jehan committed
171 172
	linphone_call_ref(c1);
	linphone_call_ref(c2);
173

Simon Morlat's avatar
Simon Morlat committed
174 175
	liblinphone_tester_clock_start(&ts);
	do {
176 177
		if (linphone_call_get_audio_stats(c1)->round_trip_delay >0.0
				&& linphone_call_get_audio_stats(c2)->round_trip_delay >0.0
jehan's avatar
jehan committed
178 179
				&& (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || linphone_call_get_video_stats(c1)->round_trip_delay>0.0)
				&& (!linphone_call_log_video_enabled(linphone_call_get_call_log(c2))  || linphone_call_get_video_stats(c2)->round_trip_delay>0.0)) {
180
			break;
jehan's avatar
jehan committed
181

182
		}
jehan's avatar
jehan committed
183
		wait_for_until(caller->lc,callee->lc,&dummy,1,500); /*just to sleep while iterating*/
Simon Morlat's avatar
Simon Morlat committed
184
	}while (!liblinphone_tester_clock_elapsed(&ts,12000));
185 186
	BC_ASSERT_TRUE(linphone_call_get_audio_stats(c1)->round_trip_delay>0.0);
	BC_ASSERT_TRUE(linphone_call_get_audio_stats(c2)->round_trip_delay>0.0);
187
	if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) {
188
		BC_ASSERT_TRUE(linphone_call_get_video_stats(c1)->round_trip_delay>0.0);
189 190
	}
	if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) {
191
		BC_ASSERT_TRUE(linphone_call_get_video_stats(c2)->round_trip_delay>0.0);
192
	}
jehan's avatar
jehan committed
193 194
	linphone_call_unref(c1);
	linphone_call_unref(c2);
195 196
}

197 198 199 200 201 202 203 204
static void setup_sdp_handling(const LinphoneCallTestParams* params, LinphoneCoreManager* mgr ){
	if( params->sdp_removal ){
		sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateRemove);
	} else if( params->sdp_simulate_error ){
		sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateError);
	}
}

205
bool_t call_with_params2(LinphoneCoreManager* caller_mgr
206
						,LinphoneCoreManager* callee_mgr
207 208 209
						, const LinphoneCallTestParams *caller_test_params
						, const LinphoneCallTestParams *callee_test_params
						, bool_t build_callee_params) {
jehan's avatar
jehan committed
210
	int retry=0;
jehan's avatar
jehan committed
211 212
	stats initial_caller=caller_mgr->stat;
	stats initial_callee=callee_mgr->stat;
jehan's avatar
jehan committed
213
	bool_t result=FALSE;
214 215
	LinphoneCallParams *caller_params = caller_test_params->base;
	LinphoneCallParams *callee_params = callee_test_params->base;
216
	bool_t did_receive_call;
217
	LinphoneCall *callee_call=NULL;
218

219 220
	setup_sdp_handling(caller_test_params, caller_mgr);
	setup_sdp_handling(callee_test_params, callee_mgr);
221

222
	if (!caller_params){
223
		BC_ASSERT_PTR_NOT_NULL(linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity));
Simon Morlat's avatar
Simon Morlat committed
224
	}else{
225
		BC_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params));
Simon Morlat's avatar
Simon Morlat committed
226
	}
jehan's avatar
jehan committed
227

228
	did_receive_call = wait_for(callee_mgr->lc
229 230 231
				,caller_mgr->lc
				,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived
				,initial_callee.number_of_LinphoneCallIncomingReceived+1);
232
	BC_ASSERT_EQUAL(did_receive_call, !callee_test_params->sdp_simulate_error, int, "%d");
233

234 235
	sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal);
	sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal);
236

237
	if (!did_receive_call) return 0;
238 239


240
	if (linphone_core_get_calls_nb(callee_mgr->lc)<=1)
241 242
		BC_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc));
	BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1, int, "%d");
jehan's avatar
jehan committed
243

jehan's avatar
jehan committed
244

jehan's avatar
jehan committed
245 246 247
	while (caller_mgr->stat.number_of_LinphoneCallOutgoingRinging!=(initial_caller.number_of_LinphoneCallOutgoingRinging + 1)
			&& caller_mgr->stat.number_of_LinphoneCallOutgoingEarlyMedia!=(initial_caller.number_of_LinphoneCallOutgoingEarlyMedia +1)
			&& retry++ <20) {
jehan's avatar
jehan committed
248 249 250 251 252 253
			linphone_core_iterate(caller_mgr->lc);
			linphone_core_iterate(callee_mgr->lc);
			ms_usleep(100000);
	}


254
	BC_ASSERT_TRUE((caller_mgr->stat.number_of_LinphoneCallOutgoingRinging==initial_caller.number_of_LinphoneCallOutgoingRinging+1)
Simon Morlat's avatar
Simon Morlat committed
255
							||(caller_mgr->stat.number_of_LinphoneCallOutgoingEarlyMedia==initial_caller.number_of_LinphoneCallOutgoingEarlyMedia+1));
jehan's avatar
jehan committed
256

jehan's avatar
jehan committed
257

258
	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call_remote_address(callee_mgr->lc));
259 260
	callee_call=linphone_core_get_call_by_remote_address2(callee_mgr->lc,caller_mgr->identity);

261
	if(!linphone_core_get_current_call(caller_mgr->lc) || !linphone_core_get_current_call(callee_mgr->lc) || !linphone_core_get_current_call_remote_address(callee_mgr->lc)) {
jehan's avatar
jehan committed
262
		return 0;
263
	} else if (caller_mgr->identity){
jehan's avatar
jehan committed
264 265
		LinphoneAddress* callee_from=linphone_address_clone(caller_mgr->identity);
		linphone_address_set_port(callee_from,0); /*remove port because port is never present in from header*/
266

jehan's avatar
jehan committed
267
		if (linphone_call_params_get_privacy(linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc))) == LinphonePrivacyNone) {
268 269
			/*don't check in case of p asserted id*/
			if (!lp_config_get_int(callee_mgr->lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0))
270
				BC_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(callee_call)));
jehan's avatar
jehan committed
271
		} else {
272
			BC_ASSERT_FALSE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(linphone_core_get_current_call(callee_mgr->lc))));
jehan's avatar
jehan committed
273 274
		}
		linphone_address_destroy(callee_from);
jehan's avatar
jehan committed
275
	}
276 277


278
	if (callee_params){
279
		linphone_core_accept_call_with_params(callee_mgr->lc,callee_call,callee_params);
280
	}else if (build_callee_params){
281
		LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,callee_call);
282
		ms_message("Created default call params with video=%i", linphone_call_params_video_enabled(default_params));
283
		linphone_core_accept_call_with_params(callee_mgr->lc,callee_call,default_params);
284 285
		linphone_call_params_destroy(default_params);
	}else{
286
		linphone_core_accept_call(callee_mgr->lc,callee_call);
287
	}
jehan's avatar
jehan committed
288

289 290
	BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1));
	BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1));
jehan's avatar
jehan committed
291
	/*just to sleep*/
jehan's avatar
jehan committed
292
	result = wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1)
jehan's avatar
jehan committed
293
			&&
jehan's avatar
jehan committed
294
			wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1);
jehan's avatar
jehan committed
295

jehan's avatar
jehan committed
296
	if (linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionNone
jehan's avatar
jehan committed
297
		|| linphone_core_get_media_encryption(callee_mgr->lc) != LinphoneMediaEncryptionNone) {
johan's avatar
johan committed
298
		/*wait for encryption to be on, in case of zrtp or dtls, it can take a few seconds*/
jehan's avatar
jehan committed
299 300
		if (	(linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionZRTP)
				|| (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionDTLS))
jehan's avatar
jehan committed
301
			wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_caller.number_of_LinphoneCallEncryptedOn+1);
jehan's avatar
jehan committed
302 303 304
		if ((linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionZRTP)
			|| (linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionDTLS)
			|| (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionDTLS) /*also take care of caller policy*/ )
jehan's avatar
jehan committed
305 306
			wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_callee.number_of_LinphoneCallEncryptedOn+1);
		{
307
			const LinphoneCallParams* call_param = linphone_call_get_current_params(callee_call);
308
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc), int, "%d");
Simon Morlat's avatar
Simon Morlat committed
309
			call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc));
310
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc), int, "%d");
311

jehan's avatar
jehan committed
312
		}
jehan's avatar
jehan committed
313
	}
jehan's avatar
jehan committed
314 315 316 317 318 319 320 321
	/*wait ice re-invite*/
	if (linphone_core_get_firewall_policy(caller_mgr->lc) == LinphonePolicyUseIce
			&& linphone_core_get_firewall_policy(callee_mgr->lc) == LinphonePolicyUseIce
			&& !linphone_core_sdp_200_ack_enabled(caller_mgr->lc)) { /*ice does not work with sdp less invite*/
		BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+2));
		BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+2));

	}
jehan's avatar
jehan committed
322
	return result;
jehan's avatar
jehan committed
323
}
324 325 326

bool_t call_with_params(LinphoneCoreManager* caller_mgr
						,LinphoneCoreManager* callee_mgr
327 328 329 330 331 332 333 334 335 336 337 338 339
						,const LinphoneCallParams *caller_params
						,const LinphoneCallParams *callee_params){
	LinphoneCallTestParams caller_test_params = {0}, callee_test_params =  {0};
	caller_test_params.base = (LinphoneCallParams*)caller_params;
	callee_test_params.base = (LinphoneCallParams*)caller_params;
	return call_with_params2(caller_mgr,callee_mgr,&caller_test_params,&callee_test_params,FALSE);
}

bool_t call_with_test_params(LinphoneCoreManager* caller_mgr
				,LinphoneCoreManager* callee_mgr
				,const LinphoneCallTestParams *caller_test_params
				,const LinphoneCallTestParams *callee_test_params){
	return call_with_params2(caller_mgr,callee_mgr,caller_test_params,callee_test_params,FALSE);
340 341
}

342 343 344
bool_t call_with_caller_params(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr, const LinphoneCallParams *params) {
	return call_with_params(caller_mgr,callee_mgr,params,NULL);
}
345

Simon Morlat's avatar
Simon Morlat committed
346
bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr){
347
	return call_with_params(caller_mgr,callee_mgr,NULL,NULL);
Simon Morlat's avatar
Simon Morlat committed
348 349
}

350
void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){
Simon Morlat's avatar
Simon Morlat committed
351
	linphone_core_terminate_all_calls(m1->lc);
352 353 354 355
	BC_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m1->stat.number_of_LinphoneCallEnd,1));
	BC_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m2->stat.number_of_LinphoneCallEnd,1));
	BC_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m1->stat.number_of_LinphoneCallReleased,1));
	BC_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m2->stat.number_of_LinphoneCallReleased,1));
Simon Morlat's avatar
Simon Morlat committed
356 357
}

jehan's avatar
jehan committed
358
void simple_call_base(bool_t enable_multicast_recv_side) {
359
	int begin;
Simon Morlat's avatar
Simon Morlat committed
360
	int leaked_objects;
361 362
	LinphoneCoreManager* marie;
	LinphoneCoreManager* pauline;
363 364
	const LinphoneAddress *from;
	LinphoneCall *pauline_call;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
365 366
	LinphoneProxyConfig* marie_cfg;
	const char* marie_id = NULL;
367 368

	belle_sip_object_enable_leak_detector(TRUE);
369
begin=belle_sip_object_get_object_count();
370

371 372
marie = linphone_core_manager_new( "marie_rc");
	pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
373

374 375 376 377 378 379 380 381
	/* with the account manager, we might lose the identity */
	marie_cfg = linphone_core_get_default_proxy_config(marie->lc);
	marie_id = linphone_proxy_config_get_identity(marie_cfg);
	{
		LinphoneAddress* marie_addr = linphone_address_new(marie_id);
		char* marie_tmp_id = NULL;
		linphone_address_set_display_name(marie_addr, "Super Marie");
		marie_tmp_id = linphone_address_as_string(marie_addr);
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
382

383 384 385
		linphone_proxy_config_edit(marie_cfg);
		linphone_proxy_config_set_identity(marie_cfg,marie_tmp_id);
		linphone_proxy_config_done(marie_cfg);
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
386

387 388 389
		ms_free(marie_tmp_id);
		linphone_address_unref(marie_addr);
	}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
390

391
	linphone_core_enable_audio_multicast(pauline->lc,enable_multicast_recv_side);
jehan's avatar
jehan committed
392

393 394 395 396 397 398 399 400 401 402 403 404
	BC_ASSERT_TRUE(call(marie,pauline));
	pauline_call=linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(pauline_call);
	/*check that display name is correctly propagated in From */
	if (pauline_call){
		from=linphone_call_get_remote_address(linphone_core_get_current_call(pauline->lc));
		BC_ASSERT_PTR_NOT_NULL(from);
		if (from){
			const char *dname=linphone_address_get_display_name(from);
			BC_ASSERT_PTR_NOT_NULL(dname);
			if (dname){
				BC_ASSERT_STRING_EQUAL(dname, "Super Marie");
405 406
			}
		}
407
	}
408 409


410 411 412
	liblinphone_tester_check_rtcp(marie,pauline);
	end_call(marie,pauline);
	linphone_core_manager_destroy(pauline);
413
	linphone_core_manager_destroy(marie);
Simon Morlat's avatar
Simon Morlat committed
414 415

	leaked_objects=belle_sip_object_get_object_count()-begin;
416
	BC_ASSERT_EQUAL(leaked_objects, 0, int, "%d");
Simon Morlat's avatar
Simon Morlat committed
417 418 419
	if (leaked_objects>0){
		belle_sip_object_dump_active_objects();
	}
jehan's avatar
jehan committed
420
}
421

jehan's avatar
jehan committed
422 423 424
static void simple_call() {
	simple_call_base(FALSE);
}
425

jehan's avatar
jehan committed
426 427 428 429 430 431 432 433 434 435
static void call_with_timeouted_bye(void) {
	int begin;
	int leaked_objects;
	LinphoneCoreManager* marie;
	LinphoneCoreManager* pauline;
	belle_sip_timer_config_t timer_config;
	belle_sip_object_enable_leak_detector(TRUE);
	begin=belle_sip_object_get_object_count();

	marie = linphone_core_manager_new( "marie_rc");
436
	pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
jehan's avatar
jehan committed
437

438
	BC_ASSERT_TRUE(call(marie,pauline));
jehan's avatar
jehan committed
439 440 441 442 443 444 445 446 447 448

	sal_set_send_error(pauline->lc->sal,1500); /*to trash the message without generating error*/
	timer_config.T1=50; /*to have timer F = 3s*/
	timer_config.T2=4000;
	timer_config.T3=0;
	timer_config.T4=5000;

	belle_sip_stack_set_timer_config(sal_get_belle_sip_stack(pauline->lc->sal),&timer_config);
	linphone_core_terminate_all_calls(pauline->lc);

449 450
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
	BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1,timer_config.T1*84));
jehan's avatar
jehan committed
451 452 453 454

	sal_set_send_error(pauline->lc->sal,0);

	linphone_core_terminate_all_calls(marie->lc);
455 456
	BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1,5000));
	BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallReleased,1,5000));
jehan's avatar
jehan committed
457 458 459 460 461

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);

	leaked_objects=belle_sip_object_get_object_count()-begin;
462
	BC_ASSERT_EQUAL(leaked_objects, 0, int, "%d");
jehan's avatar
jehan committed
463 464 465 466 467
	if (leaked_objects>0){
		belle_sip_object_dump_active_objects();
	}
}

468 469 470 471
static void phone_number_normalization(void){
	LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc");
	LinphoneProxyConfig *cfg = linphone_core_create_proxy_config(marie->lc);
	char result[128];
472

473 474
	linphone_proxy_config_set_dial_prefix(cfg, "33");
	linphone_proxy_config_normalize_number(cfg, "0952636505", result, sizeof(result));
475
	BC_ASSERT_STRING_EQUAL(result, "+33952636505");
476
	linphone_proxy_config_normalize_number(cfg, "09 52 63 65 05", result, sizeof(result));
477
	BC_ASSERT_STRING_EQUAL(result, "+33952636505");
478
	linphone_proxy_config_normalize_number(cfg, "09-52-63-65-05", result, sizeof(result));
479
	BC_ASSERT_STRING_EQUAL(result, "+33952636505");
480
	linphone_proxy_config_normalize_number(cfg, "+31952636505", result, sizeof(result));
481
	BC_ASSERT_STRING_EQUAL(result, "+31952636505");
482
	linphone_proxy_config_normalize_number(cfg, "0033952636505", result, sizeof(result));
483
	BC_ASSERT_STRING_EQUAL(result, "+33952636505");
484
	linphone_proxy_config_normalize_number(cfg, "0033952636505", result, sizeof(result));
485
	BC_ASSERT_STRING_EQUAL(result, "+33952636505");
486
	linphone_proxy_config_normalize_number(cfg, "toto", result, sizeof(result));
487
	BC_ASSERT_STRING_EQUAL(result, "toto");
488

489 490
	linphone_proxy_config_set_dial_escape_plus(cfg, TRUE);
	linphone_proxy_config_normalize_number(cfg, "0033952636505", result, sizeof(result));
491
	BC_ASSERT_STRING_EQUAL(result, "0033952636505");
492
	linphone_proxy_config_normalize_number(cfg, "0952636505", result, sizeof(result));
493
	BC_ASSERT_STRING_EQUAL(result, "0033952636505");
494
	linphone_proxy_config_normalize_number(cfg, "+34952636505", result, sizeof(result));
495
	BC_ASSERT_STRING_EQUAL(result, "0034952636505");
496

497 498 499
	linphone_proxy_config_unref(cfg);
	linphone_core_manager_destroy(marie);
}
jehan's avatar
jehan committed
500

Simon Morlat's avatar
Simon Morlat committed
501 502 503 504 505
static void direct_call_over_ipv6(){
	LinphoneCoreManager* marie;
	LinphoneCoreManager* pauline;

	if (liblinphone_tester_ipv6_available()){
jehan's avatar
jehan committed
506 507
		LCSipTransports pauline_transports;
		LinphoneAddress* pauline_dest = linphone_address_new("sip:[::1];transport=tcp");
Simon Morlat's avatar
Simon Morlat committed
508
		marie = linphone_core_manager_new( "marie_rc");
509
		pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
jehan's avatar
jehan committed
510

Simon Morlat's avatar
Simon Morlat committed
511 512 513
		linphone_core_enable_ipv6(marie->lc,TRUE);
		linphone_core_enable_ipv6(pauline->lc,TRUE);
		linphone_core_set_default_proxy_config(marie->lc,NULL);
514 515
		/*wait for register in v6 mode, however sip2.linphone.org has an ipv6 address but doesn't listen to it*/
#if 0
516 517
		BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 2, 2000));
		BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 2, 2000));
518
#endif
519

jehan's avatar
jehan committed
520 521 522
		linphone_core_get_sip_transports_used(pauline->lc,&pauline_transports);
		linphone_address_set_port(pauline_dest,pauline_transports.tcp_port);
		linphone_core_invite_address(marie->lc,pauline_dest);
523

524 525
		BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallOutgoingRinging,1));
		BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallIncomingReceived,1));
Simon Morlat's avatar
Simon Morlat committed
526
		linphone_core_accept_call(pauline->lc,linphone_core_get_current_call(pauline->lc));
527 528
		BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,1));
		BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,1));
529

Simon Morlat's avatar
Simon Morlat committed
530 531 532 533
		liblinphone_tester_check_rtcp(marie,pauline);
		end_call(marie,pauline);
		linphone_core_manager_destroy(marie);
		linphone_core_manager_destroy(pauline);
jehan's avatar
jehan committed
534
		linphone_address_destroy(pauline_dest);
Simon Morlat's avatar
Simon Morlat committed
535 536 537
	}else ms_warning("Test skipped, no ipv6 available");
}

538 539
static void call_outbound_with_multiple_proxy() {
	LinphoneCoreManager* marie   = linphone_core_manager_new2( "marie_rc", FALSE);
540
	LinphoneCoreManager* pauline = linphone_core_manager_new2( "pauline_tcp_rc", FALSE);
541 542 543 544 545 546 547

	LinphoneProxyConfig* lpc = NULL;
	LinphoneProxyConfig* registered_lpc = linphone_proxy_config_new();

	linphone_core_get_default_proxy(marie->lc, &lpc);
	linphone_core_set_default_proxy(marie->lc,NULL);

548 549
	BC_ASSERT_FATAL(lpc != NULL);
	BC_ASSERT_FATAL(registered_lpc != NULL);
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564

	// create new LPC that will successfully register
	linphone_proxy_config_set_identity(registered_lpc, linphone_proxy_config_get_identity(lpc));
	linphone_proxy_config_set_server_addr(registered_lpc, linphone_proxy_config_get_addr(lpc));
	linphone_proxy_config_set_route(registered_lpc, linphone_proxy_config_get_route(lpc));
	linphone_proxy_config_enable_register(registered_lpc, TRUE);

	linphone_core_add_proxy_config(marie->lc, registered_lpc);

	// set first LPC to unreacheable proxy addr
	linphone_proxy_config_edit(lpc);
	linphone_proxy_config_set_server_addr(lpc,"12.13.14.15:5223;transport=udp");
	linphone_proxy_config_set_route(lpc, "12.13.14.15:5223;transport=udp;lr");
	linphone_proxy_config_done(lpc);

565
	BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 1, 2000));
566

567 568
	BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationProgress, 2, 200));
	BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 1, 2000));
569 570

	// calling marie should go through the second proxy config
571
	BC_ASSERT_TRUE(call(marie, pauline));
572

573 574
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
575 576
}

577
#if 0 /* TODO: activate test when the implementation is ready */
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
578 579
static void multiple_answers_call() {
	/* Scenario is this: pauline calls marie, which is registered 2 times.
580
	   Both linphones answer at the same time, and only one should get the
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
581 582 583 584
	   call running, the other should be terminated */
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc" );
	LinphoneCoreManager* marie1  = linphone_core_manager_new( "marie_rc" );
	LinphoneCoreManager* marie2  = linphone_core_manager_new( "marie_rc" );
585

Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
586
	LinphoneCall* call1, *call2;
587

Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
588 589 590
	MSList* lcs = ms_list_append(NULL,pauline->lc);
	lcs = ms_list_append(lcs,marie1->lc);
	lcs = ms_list_append(lcs,marie2->lc);
591 592


593
	BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 1, 2000));
594

595
	BC_ASSERT_PTR_NOT_NULL( linphone_core_invite_address(pauline->lc, marie1->identity ) );
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
596

597 598 599
	BC_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneCallIncomingReceived, 1, 2000));
	BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived, 1, 2000));
	BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingProgress, 1, 2000));
600

Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
601 602 603
	// marie 1 and 2 answer at the same time
	call1 = linphone_core_get_current_call(marie1->lc);
	call2 = linphone_core_get_current_call(marie2->lc);
604

605 606
	BC_ASSERT_PTR_NOT_NULL_FATAL(call1);
	BC_ASSERT_PTR_NOT_NULL_FATAL(call2);
607

608 609
	BC_ASSERT_EQUAL( linphone_core_accept_call(marie1->lc, call1), 0, int, "%d");
	BC_ASSERT_EQUAL( linphone_core_accept_call(marie2->lc, call2), 0, int, "%d");
610

611 612 613
	BC_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1, 2000) );
	BC_ASSERT_TRUE( wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallStreamsRunning, 1, 2000) );
	BC_ASSERT_TRUE( wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallEnd, 1, 2000) );
614 615


Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
616 617 618
	linphone_core_manager_destroy(pauline);
	linphone_core_manager_destroy(marie1);
	linphone_core_manager_destroy(marie2);
619 620 621
}
#endif

622
static void multiple_answers_call_with_media_relay(void) {
623

624
	/* Scenario is this: pauline calls marie, which is registered 2 times.
625
	 *   Both linphones answer at the same time, and only one should get the
626
	 *   call running, the other should be terminated */
627
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc" );
628 629
	LinphoneCoreManager* marie1  = linphone_core_manager_new( "marie_rc" );
	LinphoneCoreManager* marie2  = linphone_core_manager_new( "marie_rc" );
630

631
	LinphoneCall* call1, *call2;
632

633 634 635
	MSList* lcs = ms_list_append(NULL,pauline->lc);
	lcs = ms_list_append(lcs,marie1->lc);
	lcs = ms_list_append(lcs,marie2->lc);
636

637 638 639
	linphone_core_set_user_agent(pauline->lc, "Natted Linphone", NULL);
	linphone_core_set_user_agent(marie1->lc, "Natted Linphone", NULL);
	linphone_core_set_user_agent(marie2->lc, "Natted Linphone", NULL);
640

641
	BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 1, 2000));
642

643
	BC_ASSERT_PTR_NOT_NULL( linphone_core_invite_address(pauline->lc, marie1->identity ) );
644

645 646 647
	BC_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneCallIncomingReceived, 1, 2000));
	BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived, 1, 2000));
	BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingProgress, 1, 2000));
648

649 650 651
	// marie 1 and 2 answer at the same time
	call1 = linphone_core_get_current_call(marie1->lc);
	call2 = linphone_core_get_current_call(marie2->lc);
652

653 654
	BC_ASSERT_PTR_NOT_NULL_FATAL(call1);
	BC_ASSERT_PTR_NOT_NULL_FATAL(call2);
655

656 657
	BC_ASSERT_EQUAL( linphone_core_accept_call(marie1->lc, call1), 0, int, "%d");
	BC_ASSERT_EQUAL( linphone_core_accept_call(marie2->lc, call2), 0, int, "%d");
658

659 660 661
	BC_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1, 2000) );
	BC_ASSERT_TRUE( wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallStreamsRunning, 1, 2000) );
	BC_ASSERT_TRUE( wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallEnd, 1, 2000) );
662 663


664 665 666
	linphone_core_manager_destroy(pauline);
	linphone_core_manager_destroy(marie1);
	linphone_core_manager_destroy(marie2);
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
667 668
}

669
static void call_with_specified_codec_bitrate(void) {
670
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
671
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
672 673
	const LinphoneCallStats *pauline_stats,*marie_stats;
	bool_t call_ok;
674 675
	char * codec = "opus";
	int rate = 48000;
676 677 678
	int min_bw=24;
	int max_bw=40;

679 680
#ifdef __arm__
	if (ms_get_cpu_count() <2) { /*2 opus codec channel + resampler is too much for a single core*/
681
#ifndef ANDROID
682
		codec = "speex";
683 684 685
		rate = 8000;
		min_bw=20;
		max_bw=35;
686
#else
687
		BC_PASS("Test requires at least a dual core");
688 689
		goto end;
#endif
690 691 692 693
	}
#endif

	if (linphone_core_find_payload_type(marie->lc,codec,rate,-1)==NULL){
694 695 696
		ms_warning("opus codec not supported, test skipped.");
		goto end;
	}
697

698 699
	disable_all_audio_codecs_except_one(marie->lc,codec,rate);
	disable_all_audio_codecs_except_one(pauline->lc,codec,rate);
700

701
	linphone_core_set_payload_type_bitrate(marie->lc,
702
		linphone_core_find_payload_type(marie->lc,codec,rate,-1),
703
		max_bw);
704
	linphone_core_set_payload_type_bitrate(pauline->lc,
705
		linphone_core_find_payload_type(pauline->lc,codec,rate,-1),
706
		min_bw);
707

708
	BC_ASSERT_TRUE((call_ok=call(pauline,marie)));
709 710 711 712
	if (!call_ok) goto end;
	liblinphone_tester_check_rtcp(marie,pauline);
	marie_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc));
	pauline_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc));
713 714
	BC_ASSERT_TRUE(marie_stats->download_bandwidth<(min_bw+5+min_bw*.1));
	BC_ASSERT_TRUE(pauline_stats->download_bandwidth>(max_bw-5-max_bw*.1));
715 716 717 718 719 720

end:
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

721
static void simple_call_compatibility_mode(void) {
722
	char route[256];
723
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
724
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
725 726 727 728 729 730 731