complex_sip_case_tester.c 14 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
	liblinphone_tester - liblinphone test suite
	Copyright (C) 2015  Belledonne Communications SARL

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

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


20
#include "linphone/core.h"
jehan's avatar
jehan committed
21
#include "liblinphone_tester.h"
22
#include "linphone/lpconfig.h"
jehan's avatar
jehan committed
23

Simon Morlat's avatar
Simon Morlat committed
24

Ghislain MARY's avatar
Ghislain MARY committed
25
#if HAVE_SIPP
26 27
void check_rtcp(LinphoneCall *call) {
	MSTimeSpec ts;
28
	LinphoneCallStats *audio_stats, *video_stats;
29

30 31
	linphone_call_ref(call);
	liblinphone_tester_clock_start(&ts);
32

33
	do {
34 35 36
		audio_stats = linphone_call_get_audio_stats(call);
		video_stats = linphone_call_get_video_stats(call);
		if (linphone_call_stats_get_round_trip_delay(audio_stats) > 0.0 && (!linphone_call_log_video_enabled(linphone_call_get_call_log(call)) || linphone_call_stats_get_round_trip_delay(video_stats) > 0.0)) {
37 38
			break;
		}
39 40
		linphone_call_stats_unref(audio_stats);
		if (video_stats) linphone_call_stats_unref(video_stats);
41
		wait_for_until(linphone_call_get_core(call), NULL, NULL, 0, 20); /*just to sleep while iterating*/
42
	} while (!liblinphone_tester_clock_elapsed(&ts, 15000));
43

44 45
	audio_stats = linphone_call_get_audio_stats(call);
	BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(audio_stats), 0.0, float, "%f");
46
	if (linphone_call_log_video_enabled(linphone_call_get_call_log(call))) {
47 48 49
		video_stats = linphone_call_get_video_stats(call);
		BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(video_stats), 0.0, float, "%f");
		linphone_call_stats_unref(video_stats);
50
	}
51
	linphone_call_stats_unref(audio_stats);
52

53 54
	linphone_call_unref(call);
}
jehan's avatar
jehan committed
55

56
FILE *sip_start(const char *senario, const char* dest_username, const char *passwd, LinphoneAddress* dest_addres) {
jehan's avatar
jehan committed
57 58 59
	char *dest;
	char *command;
	FILE *file;
60

jehan's avatar
jehan committed
61 62 63 64
	if (linphone_address_get_port(dest_addres)>0)
		dest = ms_strdup_printf("%s:%i",linphone_address_get_domain(dest_addres),linphone_address_get_port(dest_addres));
	else
		dest = ms_strdup_printf("%s",linphone_address_get_domain(dest_addres));
65
	//until errors logs are handled correctly and stop breaks output, they will be DISABLED
66 67 68 69
	command = ms_strdup_printf(SIPP_COMMAND" -sf %s -s %s %s -trace_err -trace_msg -rtp_echo -m 1 -d 1000 -ap %s 2>/dev/null",senario
								,dest_username
								,dest
								,(passwd?passwd:"none"));
70

71
	ms_message("Starting sipp command [%s]",command);
jehan's avatar
jehan committed
72 73 74 75 76
	file = popen(command, "r");
	ms_free(command);
	ms_free(dest);
	return file;
}
77

78

79 80 81 82 83
static FILE *sip_start_recv(const char *senario) {
	char *command;
	FILE *file;

	//until errors logs are handled correctly and stop breaks output, they will be DISABLED
84
	command = ms_strdup_printf(SIPP_COMMAND" -sf %s -trace_err -trace_msg -rtp_echo -m 1 -d 1000 2>/dev/null",senario);
85

86
	ms_message("Starting sipp command [%s]",command);
87 88 89 90
	file = popen(command, "r");
	ms_free(command);
	return file;
}
91

Ghislain MARY's avatar
Ghislain MARY committed
92
static void dest_server_server_resolved(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl) {
jehan's avatar
jehan committed
93
	*(struct addrinfo **)data =ai_list;
Simon Morlat's avatar
Simon Morlat committed
94 95
}

96
LinphoneAddress * linphone_core_manager_resolve(LinphoneCoreManager *mgr, const LinphoneAddress *source) {
jehan's avatar
jehan committed
97 98 99
	struct addrinfo *addrinfo = NULL;
	char ipstring [INET6_ADDRSTRLEN];
	int err;
100 101 102
	int port = linphone_address_get_port(source);
	LinphoneAddress * dest;
	
103
	sal_resolve_a(linphone_core_get_sal(mgr->lc)
104 105 106
	 ,linphone_address_get_domain(source)
	 ,linphone_address_get_port(source)
	 ,AF_INET
Ghislain MARY's avatar
Ghislain MARY committed
107
	 ,dest_server_server_resolved
108 109 110 111 112
	 ,&addrinfo);
	
	 dest=linphone_address_new(NULL);
	 
	 wait_for(mgr->lc, mgr->lc, (int*)&addrinfo, 1);
113
	 err=bctbx_getnameinfo((struct sockaddr*)addrinfo->ai_addr,addrinfo->ai_addrlen,ipstring,INET6_ADDRSTRLEN,NULL,0,NI_NUMERICHOST);
Simon Morlat's avatar
Simon Morlat committed
114 115 116
	 if (err !=0 ){
		 ms_error("linphone_core_manager_resolve(): getnameinfo error %s", gai_strerror(err));
	 }
117 118 119 120 121 122 123 124 125 126
	 linphone_address_set_domain(dest, ipstring);
	 if (port > 0)
		linphone_address_set_port(dest, port);
	
	return dest;
}


static void sip_update_within_icoming_reinvite_with_no_sdp(void) {
	LinphoneCoreManager *mgr;
jehan's avatar
jehan committed
127
	char *identity_char;
jehan's avatar
jehan committed
128 129
	char *scen;
	FILE * sipp_out;
130

jehan's avatar
jehan committed
131 132 133 134 135 136 137
	/*currently we use direct connection because sipp do not properly set ACK request uri*/
	mgr= linphone_core_manager_new2( "empty_rc", FALSE);
	mgr->identity= linphone_core_get_primary_contact_parsed(mgr->lc);
	linphone_address_set_username(mgr->identity,"marie");
	identity_char=linphone_address_as_string(mgr->identity);
	linphone_core_set_primary_contact(mgr->lc,identity_char);
	linphone_core_iterate(mgr->lc);
jehan's avatar
jehan committed
138
	scen = bc_tester_res("sipp/sip_update_within_icoming_reinvite_with_no_sdp.xml");
139
	sipp_out = sip_start(scen, linphone_address_get_username(mgr->identity),NULL, mgr->identity);
jehan's avatar
jehan committed
140 141

	if (sipp_out) {
jehan's avatar
jehan committed
142
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallIncomingReceived, 1));
143 144 145 146 147
		if (linphone_core_get_current_call(mgr->lc)) {
			linphone_call_accept(linphone_core_get_current_call(mgr->lc));
			BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 2));
			BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1));
		}
jehan's avatar
jehan committed
148
		pclose(sipp_out);
jehan's avatar
jehan committed
149
	}
jehan's avatar
jehan committed
150
	linphone_core_manager_destroy(mgr);
jehan's avatar
jehan committed
151 152
}

153
static void call_with_audio_mline_before_video_in_sdp(void) {
154 155 156 157 158
	LinphoneCoreManager *mgr;
	char *identity_char;
	char *scen;
	FILE * sipp_out;
	LinphoneCall *call = NULL;
159

160 161 162 163 164 165
	/*currently we use direct connection because sipp do not properly set ACK request uri*/
	mgr= linphone_core_manager_new2( "empty_rc", FALSE);
	mgr->identity = linphone_core_get_primary_contact_parsed(mgr->lc);
	linphone_address_set_username(mgr->identity,"marie");
	identity_char = linphone_address_as_string(mgr->identity);
	linphone_core_set_primary_contact(mgr->lc,identity_char);
166

167
	linphone_core_iterate(mgr->lc);
168

169
	scen = bc_tester_res("sipp/call_with_audio_mline_before_video_in_sdp.xml");
170

171
	sipp_out = sip_start(scen, linphone_address_get_username(mgr->identity), NULL,  mgr->identity);
172 173 174

	if (sipp_out) {
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallIncomingReceived, 1));
175
		call = linphone_core_get_current_call(mgr->lc);
176 177
		BC_ASSERT_PTR_NOT_NULL(call);
		if (call) {
178
			linphone_call_accept(call);
179
			BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1));
180
#if 0
181 182 183
			BC_ASSERT_EQUAL(call->main_audio_stream_index, 0, int, "%d");
			BC_ASSERT_EQUAL(call->main_video_stream_index, 1, int, "%d");
			BC_ASSERT_TRUE(call->main_text_stream_index > 1);
184
#endif
185 186 187 188
			BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call)));

			check_rtcp(call);
		}
189

190 191 192 193 194 195
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1));
		pclose(sipp_out);
	}
	linphone_core_manager_destroy(mgr);
}

196
static void call_with_video_mline_before_audio_in_sdp(void) {
197 198 199 200 201
	LinphoneCoreManager *mgr;
	char *identity_char;
	char *scen;
	FILE * sipp_out;
	LinphoneCall *call = NULL;
202

203 204
	/*currently we use direct connection because sipp do not properly set ACK request uri*/
	mgr= linphone_core_manager_new2( "empty_rc", FALSE);
205
	mgr->identity = linphone_core_get_primary_contact_parsed(mgr->lc);
206
	linphone_address_set_username(mgr->identity,"marie");
207
	identity_char = linphone_address_as_string(mgr->identity);
208
	linphone_core_set_primary_contact(mgr->lc,identity_char);
209

210
	linphone_core_iterate(mgr->lc);
211

212
	scen = bc_tester_res("sipp/call_with_video_mline_before_audio_in_sdp.xml");
213

214
	sipp_out = sip_start(scen, linphone_address_get_username(mgr->identity), NULL, mgr->identity);
215 216 217

	if (sipp_out) {
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallIncomingReceived, 1));
218
		call = linphone_core_get_current_call(mgr->lc);
219 220
		BC_ASSERT_PTR_NOT_NULL(call);
		if (call) {
221
			linphone_call_accept(call);
222
			BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1));
223
#if 0
224 225 226
			BC_ASSERT_EQUAL(call->main_audio_stream_index, 1, int, "%d");
			BC_ASSERT_EQUAL(call->main_video_stream_index, 0, int, "%d");
			BC_ASSERT_TRUE(call->main_text_stream_index > 1);
227
#endif
228 229 230 231
			BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call)));

			check_rtcp(call);
		}
232

233 234 235 236 237 238
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1));
		pclose(sipp_out);
	}
	linphone_core_manager_destroy(mgr);
}

239
static void call_with_multiple_audio_mline_in_sdp(void) {
240 241 242 243 244
	LinphoneCoreManager *mgr;
	char *identity_char;
	char *scen;
	FILE * sipp_out;
	LinphoneCall *call = NULL;
245

246 247 248 249 250 251
	/*currently we use direct connection because sipp do not properly set ACK request uri*/
	mgr= linphone_core_manager_new2( "empty_rc", FALSE);
	mgr->identity = linphone_core_get_primary_contact_parsed(mgr->lc);
	linphone_address_set_username(mgr->identity,"marie");
	identity_char = linphone_address_as_string(mgr->identity);
	linphone_core_set_primary_contact(mgr->lc,identity_char);
252

253
	linphone_core_iterate(mgr->lc);
254

255
	scen = bc_tester_res("sipp/call_with_multiple_audio_mline_in_sdp.xml");
256

257
	sipp_out = sip_start(scen, linphone_address_get_username(mgr->identity), NULL, mgr->identity);
258 259 260

	if (sipp_out) {
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallIncomingReceived, 1));
261
		call = linphone_core_get_current_call(mgr->lc);
262 263
		BC_ASSERT_PTR_NOT_NULL(call);
		if (call) {
264
			linphone_call_accept(call);
265
			BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1));
266
#if 0
267 268 269
			BC_ASSERT_EQUAL(call->main_audio_stream_index, 0, int, "%d");
			BC_ASSERT_EQUAL(call->main_video_stream_index, 2, int, "%d");
			BC_ASSERT_TRUE(call->main_text_stream_index > 2);
270
#endif
271 272 273 274
			BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call)));

			check_rtcp(call);
		}
275

276 277 278 279 280 281
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1));
		pclose(sipp_out);
	}
	linphone_core_manager_destroy(mgr);
}

282
static void call_with_multiple_video_mline_in_sdp(void) {
283 284 285 286 287
	LinphoneCoreManager *mgr;
	char *identity_char;
	char *scen;
	FILE * sipp_out;
	LinphoneCall *call = NULL;
288

289 290 291 292 293 294
	/*currently we use direct connection because sipp do not properly set ACK request uri*/
	mgr= linphone_core_manager_new2( "empty_rc", FALSE);
	mgr->identity = linphone_core_get_primary_contact_parsed(mgr->lc);
	linphone_address_set_username(mgr->identity,"marie");
	identity_char = linphone_address_as_string(mgr->identity);
	linphone_core_set_primary_contact(mgr->lc,identity_char);
295

296
	linphone_core_iterate(mgr->lc);
297

298
	scen = bc_tester_res("sipp/call_with_multiple_video_mline_in_sdp.xml");
299

300
	sipp_out = sip_start(scen, linphone_address_get_username(mgr->identity), NULL, mgr->identity);
301 302 303

	if (sipp_out) {
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallIncomingReceived, 1));
304
		call = linphone_core_get_current_call(mgr->lc);
305 306
		BC_ASSERT_PTR_NOT_NULL(call);
		if (call) {
307
			linphone_call_accept(call);
308
			BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1));
309
#if 0
310 311 312
			BC_ASSERT_EQUAL(call->main_audio_stream_index, 0, int, "%d");
			BC_ASSERT_EQUAL(call->main_video_stream_index, 1, int, "%d");
			BC_ASSERT_TRUE(call->main_text_stream_index > 3);
313
#endif
314 315 316 317
			BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call)));

			check_rtcp(call);
		}
318

319 320 321 322 323 324
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1));
		pclose(sipp_out);
	}
	linphone_core_manager_destroy(mgr);
}

325

326
static void call_invite_200ok_without_contact_header(void) {
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
	LinphoneCoreManager *mgr;
	char *identity_char;
	char *scen;
	FILE * sipp_out;
	LinphoneCall *call = NULL;

	/*currently we use direct connection because sipp do not properly set ACK request uri*/
	mgr= linphone_core_manager_new2("empty_rc", FALSE);
	mgr->identity = linphone_core_get_primary_contact_parsed(mgr->lc);
	linphone_address_set_username(mgr->identity,"marie");
	identity_char = linphone_address_as_string(mgr->identity);
	linphone_core_set_primary_contact(mgr->lc,identity_char);

	linphone_core_iterate(mgr->lc);

	scen = bc_tester_res("sipp/call_invite_200ok_without_contact_header.xml");

	sipp_out = sip_start_recv(scen);

	if (sipp_out) {
		call = linphone_core_invite(mgr->lc, "sipp@127.0.0.1");
		BC_ASSERT_PTR_NOT_NULL(call);
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallOutgoingInit, 1));
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallOutgoingProgress, 1));
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallOutgoingRinging, 1));
352 353 354 355
		/*assert that the call never gets connected nor terminated*/
		BC_ASSERT_FALSE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallConnected, 1));
		BC_ASSERT_EQUAL(mgr->stat.number_of_LinphoneCallEnd, 0, int, "%d");
		BC_ASSERT_EQUAL(mgr->stat.number_of_LinphoneCallError, 0, int, "%d");
356
		linphone_call_terminate(call);
357 358
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1));
		BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallReleased, 1));
359 360 361 362
		pclose(sipp_out);
	}
	linphone_core_manager_destroy(mgr);
}
363

364

jehan's avatar
jehan committed
365
static test_t tests[] = {
366 367 368 369 370 371
	TEST_NO_TAG("SIP UPDATE within incoming reinvite without sdp", sip_update_within_icoming_reinvite_with_no_sdp),
	TEST_NO_TAG("Call with audio mline before video in sdp", call_with_audio_mline_before_video_in_sdp),
	TEST_NO_TAG("Call with video mline before audio in sdp", call_with_video_mline_before_audio_in_sdp),
	TEST_NO_TAG("Call with multiple audio mline in sdp", call_with_multiple_audio_mline_in_sdp),
	TEST_NO_TAG("Call with multiple video mline in sdp", call_with_multiple_video_mline_in_sdp),
	TEST_NO_TAG("Call invite 200ok without contact header", call_invite_200ok_without_contact_header)
jehan's avatar
jehan committed
372
};
Ghislain MARY's avatar
Ghislain MARY committed
373
#endif
jehan's avatar
jehan committed
374

jehan's avatar
jehan committed
375
test_suite_t complex_sip_call_test_suite = {
376
	"Complex SIP Case",
Sylvain Berfini's avatar
Sylvain Berfini committed
377 378 379
	NULL,
	NULL,
	liblinphone_tester_before_each,
380
	liblinphone_tester_after_each,
Ghislain MARY's avatar
Ghislain MARY committed
381
#if HAVE_SIPP
jehan's avatar
jehan committed
382 383
	sizeof(tests) / sizeof(tests[0]),
	tests
Ghislain MARY's avatar
Ghislain MARY committed
384 385 386 387
#else
	0,
	NULL
#endif
jehan's avatar
jehan committed
388
};