call_tester.c 195 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
		}
183
		wait_for_until(caller->lc,callee->lc,&dummy,1,20); /*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
	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)
247
			&& retry++ < 100) {
jehan's avatar
jehan committed
248 249
			linphone_core_iterate(caller_mgr->lc);
			linphone_core_iterate(callee_mgr->lc);
250
			ms_usleep(20000);
jehan's avatar
jehan committed
251 252 253
	}


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
	LinphoneProxyConfig* marie_cfg;
366 367

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

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

373 374 375
	/* with the account manager, we might lose the identity */
	marie_cfg = linphone_core_get_default_proxy_config(marie->lc);
	{
376
		LinphoneAddress* marie_addr = linphone_address_clone(linphone_proxy_config_get_identity_address(marie_cfg));
377 378 379
		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
380

381 382 383
		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
384

385
		ms_free(marie_tmp_id);
386
		linphone_address_destroy(marie_addr);
387
	}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
388

389
	linphone_core_enable_audio_multicast(pauline->lc,enable_multicast_recv_side);
jehan's avatar
jehan committed
390

391 392 393 394 395 396 397 398 399 400 401 402
	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");
403 404
			}
		}
405
	}
406 407


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

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

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

jehan's avatar
jehan committed
424 425 426 427 428 429 430 431 432 433
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");
434
	pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
jehan's avatar
jehan committed
435

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

	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);

447 448
	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
449 450 451 452

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

	linphone_core_terminate_all_calls(marie->lc);
453 454
	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
455 456 457 458 459

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);

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

Simon Morlat's avatar
Simon Morlat committed
466 467 468 469 470
static void direct_call_over_ipv6(){
	LinphoneCoreManager* marie;
	LinphoneCoreManager* pauline;

	if (liblinphone_tester_ipv6_available()){
jehan's avatar
jehan committed
471 472
		LCSipTransports pauline_transports;
		LinphoneAddress* pauline_dest = linphone_address_new("sip:[::1];transport=tcp");
Simon Morlat's avatar
Simon Morlat committed
473
		marie = linphone_core_manager_new( "marie_rc");
474
		pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
jehan's avatar
jehan committed
475

Simon Morlat's avatar
Simon Morlat committed
476 477 478
		linphone_core_enable_ipv6(marie->lc,TRUE);
		linphone_core_enable_ipv6(pauline->lc,TRUE);
		linphone_core_set_default_proxy_config(marie->lc,NULL);
479 480
		/*wait for register in v6 mode, however sip2.linphone.org has an ipv6 address but doesn't listen to it*/
#if 0
481 482
		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));
483
#endif
484

jehan's avatar
jehan committed
485 486 487
		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);
488

489 490
		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
491
		linphone_core_accept_call(pauline->lc,linphone_core_get_current_call(pauline->lc));
492 493
		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));
494

Simon Morlat's avatar
Simon Morlat committed
495 496 497 498
		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
499
		linphone_address_destroy(pauline_dest);
Simon Morlat's avatar
Simon Morlat committed
500 501 502
	}else ms_warning("Test skipped, no ipv6 available");
}

503 504
static void call_outbound_with_multiple_proxy() {
	LinphoneCoreManager* marie   = linphone_core_manager_new2( "marie_rc", FALSE);
505
	LinphoneCoreManager* pauline = linphone_core_manager_new2( "pauline_tcp_rc", FALSE);
506 507 508 509 510 511 512

	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);

513 514
	BC_ASSERT_FATAL(lpc != NULL);
	BC_ASSERT_FATAL(registered_lpc != NULL);
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529

	// 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);

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

532 533
	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));
534 535

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

538 539
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
540 541
}

542
#if 0 /* TODO: activate test when the implementation is ready */
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
543 544
static void multiple_answers_call() {
	/* Scenario is this: pauline calls marie, which is registered 2 times.
545
	   Both linphones answer at the same time, and only one should get the
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
546 547 548 549
	   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" );
550

Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
551
	LinphoneCall* call1, *call2;
552

Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
553 554 555
	MSList* lcs = ms_list_append(NULL,pauline->lc);
	lcs = ms_list_append(lcs,marie1->lc);
	lcs = ms_list_append(lcs,marie2->lc);
556 557


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

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

562 563 564
	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));
565

Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
566 567 568
	// 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);
569

570 571
	BC_ASSERT_PTR_NOT_NULL_FATAL(call1);
	BC_ASSERT_PTR_NOT_NULL_FATAL(call2);
572

573 574
	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");
575

576 577 578
	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) );
579 580


Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
581 582 583
	linphone_core_manager_destroy(pauline);
	linphone_core_manager_destroy(marie1);
	linphone_core_manager_destroy(marie2);
584 585 586
}
#endif

587
static void multiple_answers_call_with_media_relay(void) {
588

589
	/* Scenario is this: pauline calls marie, which is registered 2 times.
590
	 *   Both linphones answer at the same time, and only one should get the
591
	 *   call running, the other should be terminated */
592
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc" );
593 594
	LinphoneCoreManager* marie1  = linphone_core_manager_new( "marie_rc" );
	LinphoneCoreManager* marie2  = linphone_core_manager_new( "marie_rc" );
595

596
	LinphoneCall* call1, *call2;
597

598 599 600
	MSList* lcs = ms_list_append(NULL,pauline->lc);
	lcs = ms_list_append(lcs,marie1->lc);
	lcs = ms_list_append(lcs,marie2->lc);
601

602 603 604
	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);
605

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

608
	BC_ASSERT_PTR_NOT_NULL( linphone_core_invite_address(pauline->lc, marie1->identity ) );
609

610 611 612
	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));
613

614 615 616
	// 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);
617

618 619
	BC_ASSERT_PTR_NOT_NULL_FATAL(call1);
	BC_ASSERT_PTR_NOT_NULL_FATAL(call2);
620

621 622
	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");
623

624 625 626
	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) );
627 628


629 630 631
	linphone_core_manager_destroy(pauline);
	linphone_core_manager_destroy(marie1);
	linphone_core_manager_destroy(marie2);
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
632 633
}

634
static void call_with_specified_codec_bitrate(void) {
635
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
636
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
637 638
	const LinphoneCallStats *pauline_stats,*marie_stats;
	bool_t call_ok;
639
	const char * codec = "opus";
640
	int rate = 48000;
641
	int min_bw=24;
642
	int max_bw=50;
643

644 645
#ifdef __arm__
	if (ms_get_cpu_count() <2) { /*2 opus codec channel + resampler is too much for a single core*/
646
#ifndef ANDROID
647
		codec = "speex";
648 649 650
		rate = 8000;
		min_bw=20;
		max_bw=35;
651
#else
652
		BC_PASS("Test requires at least a dual core");
653 654
		goto end;
#endif
655 656 657 658
	}
#endif

	if (linphone_core_find_payload_type(marie->lc,codec,rate,-1)==NULL){
659
		BC_PASS("opus codec not supported, test skipped.");
660 661
		goto end;
	}
662

663 664
	disable_all_audio_codecs_except_one(marie->lc,codec,rate);
	disable_all_audio_codecs_except_one(pauline->lc,codec,rate);
665

666
	linphone_core_set_payload_type_bitrate(marie->lc,
667
		linphone_core_find_payload_type(marie->lc,codec,rate,-1),
668
		max_bw);
669
	linphone_core_set_payload_type_bitrate(pauline->lc,
670
		linphone_core_find_payload_type(pauline->lc,codec,rate,-1),
671
		min_bw);
672

673
	BC_ASSERT_TRUE((call_ok=call(pauline,marie)));
674 675
	if (!call_ok) goto end;
	liblinphone_tester_check_rtcp(marie,pauline);
676 677 678
	/*wait a bit that bitstreams are stabilized*/
	wait_for_until(marie->lc, pauline->lc, NULL, 0, 2000);
	
679 680
	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));
681 682 683 684
	
	BC_ASSERT_LOWER(marie_stats->download_bandwidth, min_bw+5+min_bw*.1, int, "%i");
	BC_ASSERT_GREATER(marie_stats->download_bandwidth, 10, int, "%i"); /*check that at least something is received */
	BC_ASSERT_GREATER(pauline_stats->download_bandwidth, (max_bw-5-max_bw*.1), int, "%i");
685 686 687 688 689 690

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

691
static void simple_call_compatibility_mode(void) {
692
	char route[256];
693
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
694
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
695 696 697 698 699 700

	LinphoneCore* lc_marie=marie->lc;
	LinphoneCore* lc_pauline=pauline->lc;
	stats* stat_marie=&marie->stat;
	stats* stat_pauline=&pauline->stat;
	LinphoneProxyConfig* proxy;
701
	const LinphoneAddress* identity;
702 703 704 705 706
	LinphoneAddress* proxy_address;
	char*tmp;
	LCSipTransports transport;

	linphone_core_get_default_proxy(lc_marie,&proxy);
707
	BC_ASSERT_PTR_NOT_NULL (proxy);
708
	identity = linphone_proxy_config_get_identity_address(proxy);
709 710 711 712 713 714


	proxy_address=linphone_address_new(linphone_proxy_config_get_addr(proxy));
	linphone_address_clean(proxy_address);
	tmp=linphone_address_as_string_uri_only(proxy_address);
	linphone_proxy_config_set_server_addr(proxy,tmp);
715 716
	sprintf(route,"sip:%s",test_route);
	linphone_proxy_config_set_route(proxy,route);
717 718 719 720 721 722 723 724 725 726
	ms_free(tmp);
	linphone_address_destroy(proxy_address);
	linphone_core_get_sip_transports(lc_marie,&transport);
	transport.udp_port=0;
	transport.tls_port=0;
	transport.dtls_port=0;
	/*only keep tcp*/
	linphone_core_set_sip_transports(lc_marie,&transport);
	stat_marie->number_of_LinphoneRegistrationOk=0;

727
	BC_ASSERT_TRUE (wait_for(lc_marie,lc_marie,&stat_marie->number_of_LinphoneRegistrationOk,1));
728

729
	linphone_core_invite_address(lc_marie,pauline->identity);
730

731 732 733 734
	BC_ASSERT_TRUE (wait_for(lc_pauline,lc_marie,&stat_pauline->number_of_LinphoneCallIncomingReceived,1));
	BC_ASSERT_TRUE(linphone_core_inc_invite_pending(lc_pauline));
	BC_ASSERT_EQUAL(stat_marie->number_of_LinphoneCallOutgoingProgress,1,</