message_tester.c 74.7 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

20

jehan's avatar
jehan committed
21 22 23
#include "linphonecore.h"
#include "private.h"
#include "liblinphone_tester.h"
24
#include "lime.h"
jehan's avatar
jehan committed
25

26 27 28 29 30
#ifdef MSG_STORAGE_ENABLED
#include <sqlite3.h>
#endif


Simon Morlat's avatar
Simon Morlat committed
31
static char* message_external_body_url=NULL;
Ghislain MARY's avatar
Ghislain MARY committed
32

33
void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *msg) {
34
	stats* counters = get_stats(lc);
35 36
	counters->number_of_LinphoneMessageReceivedLegacy++;
}
Ghislain MARY's avatar
Ghislain MARY committed
37

38 39
void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* msg) {
	char* from=linphone_address_as_string(linphone_chat_message_get_from(msg));
40
	stats* counters;
41 42
	const char *text=linphone_chat_message_get_text(msg);
	const char *external_body_url=linphone_chat_message_get_external_body_url(msg);
Ghislain MARY's avatar
Ghislain MARY committed
43 44 45
	ms_message("Message from [%s]  is [%s] , external URL [%s]",from?from:""
																,text?text:""
																,external_body_url?external_body_url:"");
jehan's avatar
jehan committed
46
	ms_free(from);
47
	counters = get_stats(lc);
jehan's avatar
jehan committed
48
	counters->number_of_LinphoneMessageReceived++;
jehan's avatar
jehan committed
49
	if (counters->last_received_chat_message) linphone_chat_message_unref(counters->last_received_chat_message);
50 51
	counters->last_received_chat_message=linphone_chat_message_ref(msg);
	if (linphone_chat_message_get_file_transfer_information(msg)) {
52
		counters->number_of_LinphoneMessageReceivedWithFile++;
53
	} else if (linphone_chat_message_get_external_body_url(msg)) {
54
		counters->number_of_LinphoneMessageExtBodyReceived++;
jehan's avatar
jehan committed
55
		if (message_external_body_url) {
56
			BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_external_body_url(msg),message_external_body_url);
jehan's avatar
jehan committed
57 58
			message_external_body_url=NULL;
		}
59
	}
jehan's avatar
jehan committed
60 61
}

62 63 64
/**
 * function invoked when a file transfer is received.
 * */
65
void file_transfer_received(LinphoneChatMessage *msg, const LinphoneContent* content, const LinphoneBuffer *buffer){
66
	FILE* file=NULL;
67
	char *receive_file = bc_tester_file("receive_file.dump");
68
	LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg);
69
	LinphoneCore *lc = linphone_chat_room_get_core(cr);
70
	if (!linphone_chat_message_get_user_data(msg)) {
71
		/*first chunk, creating file*/
72
		file = fopen(receive_file,"wb");
73
		linphone_chat_message_set_user_data(msg,(void*)file); /*store fd for next chunks*/
74
	}
75
	ms_free(receive_file);
76
	file = (FILE*)linphone_chat_message_get_user_data(msg);
77

78 79
	if (linphone_buffer_is_empty(buffer)) { /* tranfer complete */
		stats* counters = get_stats(lc);
80
		counters->number_of_LinphoneFileTransferDownloadSuccessful++;
81 82 83 84
		fclose(file);
	} else { /* store content on a file*/
		if (fwrite(linphone_buffer_get_content(buffer),linphone_buffer_get_size(buffer),1,file)==-1){
			ms_error("file_transfer_received(): write() failed: %s",strerror(errno));
85
		}
86 87 88 89 90 91
	}
}

/*
 * function called when the file transfer is initiated. file content should be feed into object LinphoneContent
 * */
92
LinphoneBuffer * tester_file_transfer_send(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t size){
93 94 95 96
	LinphoneBuffer *lb;
	size_t file_size;
	size_t size_to_send;
	uint8_t *buf;
97
	FILE *file_to_send = linphone_chat_message_get_user_data(msg);
98 99
	fseek(file_to_send, 0, SEEK_END);
	file_size = ftell(file_to_send);
100
	fseek(file_to_send, (long)offset, SEEK_SET);
101 102
	size_to_send = MIN(size, file_size - offset);
	buf = ms_malloc(size_to_send);
Simon Morlat's avatar
Simon Morlat committed
103
	if (fread(buf, size_to_send, 1, file_to_send)!=size_to_send){
104 105
		// reaching end of file, close it
		fclose(file_to_send);
Simon Morlat's avatar
Simon Morlat committed
106
	}
107 108 109 110 111
	lb = linphone_buffer_new_from_data(buf, size_to_send);
	ms_free(buf);
	return lb;
}

112 113 114
/**
 * function invoked to report file transfer progress.
 * */
115 116
void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) {
	LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg);
117
	LinphoneCore *lc = linphone_chat_room_get_core(cr);
118 119 120
	const LinphoneAddress* from_address = linphone_chat_message_get_from(msg);
	const LinphoneAddress* to_address = linphone_chat_message_get_to(msg);
	char *address = linphone_chat_message_is_outgoing(msg)?linphone_address_as_string(to_address):linphone_address_as_string(from_address);
121
	stats* counters = get_stats(lc);
François Grisez's avatar
François Grisez committed
122 123
	int progress = (int)((offset * 100)/total);
	ms_message(" File transfer  [%d%%] %s of type [%s/%s] %s [%s] \n", progress
124
																	,(linphone_chat_message_is_outgoing(msg)?"sent":"received")
125 126
																	, linphone_content_get_type(content)
																	, linphone_content_get_subtype(content)
127
																	,(linphone_chat_message_is_outgoing(msg)?"to":"from")
128
																	, address);
johan's avatar
johan committed
129
	counters->progress_of_LinphoneFileTransfer = progress;
130 131 132
	free(address);
}

133 134 135 136 137 138 139 140 141
void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
	stats *counters = get_stats(lc);
	if (room->remote_is_composing == LinphoneIsComposingActive) {
		counters->number_of_LinphoneIsComposingActiveReceived++;
	} else {
		counters->number_of_LinphoneIsComposingIdleReceived++;
	}
}

Simon Morlat's avatar
Simon Morlat committed
142
void liblinphone_tester_chat_message_state_change(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) {
143 144 145 146 147 148
	liblinphone_tester_chat_message_msg_state_changed(msg, state);
}

void liblinphone_tester_chat_message_msg_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
	LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg);
	LinphoneCore *lc = linphone_chat_room_get_core(cr);
149
	stats* counters = get_stats(lc);
150
	switch (state) {
Simon Morlat's avatar
Simon Morlat committed
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
		case LinphoneChatMessageStateIdle:
			return;
		case LinphoneChatMessageStateDelivered:
			counters->number_of_LinphoneMessageDelivered++;
			return;
		case LinphoneChatMessageStateNotDelivered:
			counters->number_of_LinphoneMessageNotDelivered++;
			return;
		case LinphoneChatMessageStateInProgress:
			counters->number_of_LinphoneMessageInProgress++;
			return;
		case LinphoneChatMessageStateFileTransferError:
			counters->number_of_LinphoneMessageNotDelivered++;
			return;
		case LinphoneChatMessageStateFileTransferDone:
			counters->number_of_LinphoneMessageFileTransferDone++;
			return;
168
	}
169
	ms_error("Unexpected state [%s] for msg [%p]",linphone_chat_message_state_to_string(state), msg);
170
}
jehan's avatar
jehan committed
171

172 173 174 175 176
void compare_files(const char *path1, const char *path2) {
	size_t size1;
	size_t size2;
	uint8_t *buf1;
	uint8_t *buf2;
jehan's avatar
jehan committed
177

178 179 180 181
	buf1 = (uint8_t*)ms_load_path_content(path1, &size1);
	buf2 = (uint8_t*)ms_load_path_content(path2, &size2);
	BC_ASSERT_PTR_NOT_NULL(buf1);
	BC_ASSERT_PTR_NOT_NULL(buf2);
182
	BC_ASSERT_EQUAL((uint8_t)size1, (uint8_t)size2, uint8_t, "%u");
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
	BC_ASSERT_EQUAL(memcmp(buf1, buf2, size1), 0, int, "%d");
	ms_free(buf1);
	ms_free(buf2);
}

LinphoneChatMessage* create_message_from_nowebcam(LinphoneChatRoom *chat_room) {
	FILE *file_to_send = NULL;
	LinphoneChatMessageCbs *cbs;
	LinphoneContent* content;
	LinphoneChatMessage* msg;
	size_t file_size;
	char *send_filepath = bc_tester_res("images/nowebcamCIF.jpg");
	file_to_send = fopen(send_filepath, "rb");
	fseek(file_to_send, 0, SEEK_END);
	file_size = ftell(file_to_send);
	fseek(file_to_send, 0, SEEK_SET);

	content = linphone_core_create_content(chat_room->lc);
	belle_sip_object_set_name(&content->base, "nowebcam content");
	linphone_content_set_type(content,"image");
	linphone_content_set_subtype(content,"jpeg");
	linphone_content_set_size(content,file_size); /*total size to be transfered*/
	linphone_content_set_name(content,"nowebcamCIF.jpg");


	msg = linphone_chat_room_create_file_transfer_message(chat_room, content);
	cbs = linphone_chat_message_get_callbacks(msg);
	linphone_chat_message_cbs_set_file_transfer_send(cbs, tester_file_transfer_send);
	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
212
	linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
213 214 215 216 217 218 219 220 221 222 223 224 225 226
	linphone_chat_message_set_user_data(msg, file_to_send);

	linphone_content_unref(content);
	ms_free(send_filepath);
	return msg;
}

void text_message_base(LinphoneCoreManager* marie, LinphoneCoreManager* pauline) {
	LinphoneChatMessage* msg = linphone_chat_room_create_message(linphone_core_get_chat_room(pauline->lc,marie->identity),"Bli bli bli \n blu");
	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
	linphone_chat_room_send_chat_message(msg->chat_room,msg);

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1));
227
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
jehan's avatar
jehan committed
228

229
	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
230 231 232 233 234 235 236 237 238 239
}

/****************************** Tests starting below ******************************/

static void text_message(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");

	linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc,marie->identity), "hello");
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,1));
jehan's avatar
jehan committed
240 241 242 243 244

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

245
static void text_message_within_call_dialog(void) {
246
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
247
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
248 249
	lp_config_set_int(pauline->lc->config,"sip","chat_use_call_dialogs",1);

250
	BC_ASSERT_TRUE(call(marie,pauline));
251
	linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bla bla bla bla");
252

253
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
254 255
	// when using call dialogs, we will never receive delivered status
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,0,int,"%d");
256

Simon Morlat's avatar
Simon Morlat committed
257
	end_call(marie, pauline);
258 259 260 261
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

262 263
static LinphoneAuthInfo* text_message_with_credential_from_auth_cb_auth_info;
static void text_message_with_credential_from_auth_cb_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) {
264
	ms_message("text_message_with_credential_from_auth_callback:Auth info requested  for user id [%s] at realm [%s]\n"
265 266 267 268
						,username
						,realm);
	linphone_core_add_auth_info(lc,text_message_with_credential_from_auth_cb_auth_info); /*add stored authentication info to LinphoneCore*/
}
269
static void text_message_with_credential_from_auth_callback(void) {
270
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
271
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
272
	LinphoneCoreVTable* vtable = linphone_core_v_table_new();
273 274

	/*to force cb to be called*/
275
	text_message_with_credential_from_auth_cb_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(pauline->lc)->data));
jehan's avatar
jehan committed
276
	linphone_core_clear_all_auth_info(pauline->lc);
277
	vtable->auth_info_requested=text_message_with_credential_from_auth_cb_auth_info_requested;
jehan's avatar
jehan committed
278
	linphone_core_add_listener(pauline->lc, vtable);
279

280
	text_message_base(marie, pauline);
281 282 283 284 285

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

jehan's avatar
jehan committed
286
static void text_message_with_privacy(void) {
Simon Morlat's avatar
Simon Morlat committed
287
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
288
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
289
	linphone_proxy_config_set_privacy(linphone_core_get_default_proxy_config(pauline->lc),LinphonePrivacyId);
290

291
	text_message_base(marie, pauline);
292
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1, int, "%d");
jehan's avatar
jehan committed
293

294 295 296
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
jehan's avatar
jehan committed
297

298
static void text_message_compatibility_mode(void) {
Simon Morlat's avatar
Simon Morlat committed
299
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
300
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
301 302 303
	LinphoneProxyConfig* proxy = linphone_core_get_default_proxy_config(marie->lc);
	LinphoneAddress* proxy_address=linphone_address_new(linphone_proxy_config_get_server_addr(proxy));
	char route[256];
304
	char*tmp;
305 306
	/*only keep tcp*/
	LCSipTransports transport = {0,-1,0,0};
307 308 309
	linphone_address_clean(proxy_address);
	tmp=linphone_address_as_string_uri_only(proxy_address);
	linphone_proxy_config_set_server_addr(proxy,tmp);
310 311
	sprintf(route,"sip:%s",test_route);
	linphone_proxy_config_set_route(proxy,route);
312 313 314 315
	ms_free(tmp);
	linphone_address_destroy(proxy_address);
	linphone_core_set_sip_transports(marie->lc,&transport);
	marie->stat.number_of_LinphoneRegistrationOk=0;
316
	BC_ASSERT_TRUE (wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationOk,1));
317

318 319
	text_message_base(marie, pauline);

320 321 322
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
323

Ghislain MARY's avatar
Ghislain MARY committed
324
static void text_message_with_ack(void) {
325 326
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
327 328 329 330 331 332 333 334 335 336 337 338

	text_message_base(marie, pauline);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void text_message_with_send_error(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");

	LinphoneChatRoom* chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity);
339 340
	LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu");
	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
341 342 343 344

	/*simulate a network error*/
	sal_set_send_error(marie->lc->sal, -1);
	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
345
	linphone_chat_room_send_chat_message(chat_room,msg);
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

	/* check transient msg list: the msg should be in it, and should be the only one */
	BC_ASSERT_EQUAL(ms_list_size(chat_room->transient_messages), 1, int, "%d");
	BC_ASSERT_PTR_EQUAL(ms_list_nth_data(chat_room->transient_messages,0), msg);

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1));
	/*BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageInProgress,1, int, "%d");*/
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d");

	/* the msg should have been discarded from transient list after an error */
	BC_ASSERT_EQUAL(ms_list_size(chat_room->transient_messages), 0, int, "%d");

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

	/*give a chance to register again to allow linphone_core_manager_destroy to properly unregister*/
	linphone_core_refresh_registers(marie->lc);
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationOk,marie->stat.number_of_LinphoneRegistrationOk + 1));

364 365
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
366
}
Ghislain MARY's avatar
Ghislain MARY committed
367 368

static void text_message_with_external_body(void) {
Simon Morlat's avatar
Simon Morlat committed
369
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
370
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
Simon Morlat's avatar
Simon Morlat committed
371
	LinphoneChatRoom* chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
372 373
	LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu");
	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
Simon Morlat's avatar
Simon Morlat committed
374

375 376
	message_external_body_url="http://www.linphone.org";
	linphone_chat_message_set_external_body_url(msg,message_external_body_url);
377

378
	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
379
	linphone_chat_room_send_chat_message(chat_room,msg);
380

381
	/* check transient msg list: the msg should be in it, and should be the only one */
382
	BC_ASSERT_EQUAL(ms_list_size(chat_room->transient_messages), 1, int, "%d");
383
	BC_ASSERT_PTR_EQUAL(ms_list_nth_data(chat_room->transient_messages,0), msg);
384

385 386
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1));
387

388 389
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1, int, "%d");
390

391
	BC_ASSERT_EQUAL(ms_list_size(chat_room->transient_messages), 0, int, "%d");
392

jehan's avatar
jehan committed
393 394 395 396
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

397 398 399 400 401 402
void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pauline, bool_t upload_error, bool_t download_error) {
	char *send_filepath = bc_tester_res("images/nowebcamCIF.jpg");
	char *receive_filepath = bc_tester_file("receive_file.dump");
	LinphoneChatRoom* chat_room;
	LinphoneChatMessage* msg;
	LinphoneChatMessageCbs *cbs;
403

404 405
	/* Globally configure an http file transfer server. */
	linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
406

407 408 409 410 411
	/* create a chatroom on pauline's side */
	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
	/* create a file transfer msg */
	msg = create_message_from_nowebcam(chat_room);
	linphone_chat_room_send_chat_message(chat_room,msg);
412

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
	if (upload_error) {
		/*wait for file to be 25% uploaded and simulate a network error*/
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer,25));
		sal_set_send_error(pauline->lc->sal, -1);

		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));

		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");

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

		linphone_core_refresh_registers(pauline->lc); /*to make sure registration is back in registered and so it can be later unregistered*/
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneRegistrationOk,pauline->stat.number_of_LinphoneRegistrationOk+1));
	} else {
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));
		if (marie->stat.last_received_chat_message ) {
			cbs = linphone_chat_message_get_callbacks(marie->stat.last_received_chat_message);
			linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
			linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
			linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
			linphone_chat_message_download_file(marie->stat.last_received_chat_message);

			if (download_error) {
				/* wait for file to be 50% downloaded */
				BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
				/* and simulate network error */
				belle_http_provider_set_recv_error(marie->lc->http_provider, -1);
				BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneMessageNotDelivered,1, 10000));
				belle_http_provider_set_recv_error(marie->lc->http_provider, 0);
			} else {
				BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1));
				compare_files(send_filepath, receive_filepath);
446 447
			}
		}
448 449 450 451 452 453 454 455 456 457 458 459
		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); //sent twice because of file transfer
		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
	}
	ms_free(send_filepath);
	ms_free(receive_filepath);
}

void transfer_message_base(bool_t upload_error, bool_t download_error) {
	if (transport_supported(LinphoneTransportTls)) {
		LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
		transfer_message_base2(marie,pauline,upload_error,download_error);
460
		linphone_core_manager_destroy(pauline);
461
		linphone_core_manager_destroy(marie);
462
	}
463
}
464
static void transfer_message(void) {
465 466 467 468 469 470 471 472 473 474 475 476
	transfer_message_base(FALSE, FALSE);
}

static void transfer_message_with_upload_io_error(void) {
	transfer_message_base(TRUE, FALSE);
}

static void transfer_message_with_download_io_error(void) {
	transfer_message_base(FALSE, TRUE);
}

static void transfer_message_upload_cancelled(void) {
477 478
	if (transport_supported(LinphoneTransportTls)) {
		LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
479
		LinphoneChatRoom* chat_room;
480
		LinphoneChatMessage* msg;
481
		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
johan's avatar
johan committed
482

483 484
		/* Globally configure an http file transfer server. */
		linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
johan's avatar
johan committed
485

486
		/* create a chatroom on pauline's side */
Simon Morlat's avatar
Simon Morlat committed
487
		chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
488 489

		msg = create_message_from_nowebcam(chat_room);
490
		linphone_chat_room_send_chat_message(chat_room,msg);
johan's avatar
johan committed
491

492 493 494 495 496 497 498 499
		/*wait for file to be 50% uploaded and cancel the transfer */
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 50));
		linphone_chat_message_cancel_file_transfer(msg);

		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));

		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");
johan's avatar
johan committed
500

501
		linphone_core_manager_destroy(pauline);
502
		linphone_core_manager_destroy(marie);
503
	}
johan's avatar
johan committed
504 505
}

506 507 508 509 510
static void transfer_message_download_cancelled(void) {
	LinphoneChatRoom* chat_room;
	LinphoneChatMessage* msg;
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
511

512 513
	/* Globally configure an http file transfer server. */
	linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
514

515 516 517
	/* create a chatroom on pauline's side */
	chat_room = linphone_core_get_chat_room(pauline->lc,marie->identity);
	msg = create_message_from_nowebcam(chat_room);
518
	linphone_chat_room_send_message2(chat_room,msg,NULL,pauline->lc);
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576

	/* wait for marie to receive pauline's msg */
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));


	if (marie->stat.last_received_chat_message ) { /* get last msg and use it to download file */
		LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(marie->stat.last_received_chat_message);
		linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
		linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc);
		/* wait for file to be 50% downloaded */
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
		/* and cancel the transfer */
		linphone_chat_message_cancel_file_transfer(marie->stat.last_received_chat_message);
	}

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d");
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void file_transfer_using_external_body_url(void) {
	if (transport_supported(LinphoneTransportTls)) {
		LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
		LinphoneChatMessageCbs *cbs;
		LinphoneChatRoom *chat_room;
		LinphoneChatMessage *msg;
		LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc");

		/* make sure lime is disabled */
		linphone_core_enable_lime(marie->lc, FALSE);
		linphone_core_enable_lime(pauline->lc, FALSE);

		/* create a chatroom on pauline's side */
		chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);

		msg = linphone_chat_room_create_message(chat_room, NULL);

		cbs = linphone_chat_message_get_callbacks(msg);
		linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);

		linphone_chat_message_set_external_body_url(msg, "https://www.linphone.org:444//tmp/54ec58280ace9_c30709218df8eaba61d1.jpg");
		linphone_chat_room_send_chat_message(chat_room, msg);

		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
		if (marie->stat.last_received_chat_message) {
			linphone_chat_message_download_file(marie->stat.last_received_chat_message);
		}
		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageExtBodyReceived, 1));
		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageInProgress, 1));
		linphone_core_manager_destroy(pauline);
		linphone_core_manager_destroy(marie);
	}
}

577
static void file_transfer_2_messages_simultaneously(void) {
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
	if (transport_supported(LinphoneTransportTls)) {
		LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
		LinphoneChatRoom* pauline_room;
		LinphoneChatMessage* msg;
		LinphoneChatMessage* msg2;
		LinphoneChatMessageCbs *cbs;
		char *send_filepath = bc_tester_res("images/nowebcamCIF.jpg");
		char *receive_filepath = bc_tester_file("receive_file.dump");
		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");

		/* Globally configure an http file transfer server. */
		linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");

		/* create a chatroom on pauline's side */
		pauline_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
		msg = create_message_from_nowebcam(pauline_room);
		msg2 = create_message_from_nowebcam(pauline_room);

		cbs = linphone_chat_message_get_callbacks(msg2);
		linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);

		BC_ASSERT_EQUAL(ms_list_size(linphone_core_get_chat_rooms(marie->lc)), 0, int, "%d");
		linphone_chat_room_send_chat_message(pauline_room,msg);
		linphone_chat_room_send_chat_message(pauline_room,msg2);
		if (BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1))) {
			msg = linphone_chat_message_clone(marie->stat.last_received_chat_message);
			BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,2));
			msg2 = marie->stat.last_received_chat_message;
			BC_ASSERT_EQUAL(ms_list_size(linphone_core_get_chat_rooms(marie->lc)), 1, int, "%d");
			if (ms_list_size(linphone_core_get_chat_rooms(marie->lc)) != 1) {
				char * buf = ms_strdup_printf("Found %d rooms instead of 1: ", ms_list_size(linphone_core_get_chat_rooms(marie->lc)));
				const MSList *it = linphone_core_get_chat_rooms(marie->lc);
				while (it) {
					const LinphoneAddress * peer = linphone_chat_room_get_peer_address(it->data);
					buf = ms_strcat_printf("%s, ", linphone_address_get_username(peer));
					it = it->next;
				}
				ms_error("%s", buf);
			}

			cbs = linphone_chat_message_get_callbacks(msg);
			linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
			linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
			linphone_chat_message_download_file(msg);

			cbs = linphone_chat_message_get_callbacks(msg2);
			linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
			linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
			linphone_chat_message_download_file(msg2);

			BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,2));

			BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,4, int, "%d");
			BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,2, int, "%d");
			compare_files(send_filepath, receive_filepath);

			linphone_chat_message_unref(msg);
		}
		linphone_core_manager_destroy(pauline);
		ms_free(send_filepath);
		ms_free(receive_filepath);
		linphone_core_manager_destroy(marie);
	}
}

static void text_message_denied(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
	LinphoneChatRoom* chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity);
	LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu");
	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);

	/*pauline doesn't want to be disturbed*/
	linphone_core_disable_chat(pauline->lc,LinphoneReasonDoNotDisturb);
	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
	linphone_chat_room_send_chat_message(chat_room,msg);

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1));
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d");
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static const char *info_content="<somexml>blabla</somexml>";

void info_message_received(LinphoneCore *lc, LinphoneCall* call, const LinphoneInfoMessage *msg){
	stats* counters = get_stats(lc);

	if (counters->last_received_info_message) {
		linphone_info_message_destroy(counters->last_received_info_message);
	}
	counters->last_received_info_message=linphone_info_message_copy(msg);
	counters->number_of_inforeceived++;
}

void info_message_base(bool_t with_content) {
	LinphoneInfoMessage *info;
	const LinphoneContent *content;
	const char *hvalue;

	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");

	BC_ASSERT_TRUE(call(pauline,marie));

	info=linphone_core_create_info_message(marie->lc);
	linphone_info_message_add_header(info,"Weather","still bad");
	if (with_content) {
		LinphoneContent* ct=linphone_core_create_content(marie->lc);
		linphone_content_set_type(ct,"application");
		linphone_content_set_subtype(ct,"somexml");
		linphone_content_set_buffer(ct,info_content,strlen(info_content));
		linphone_info_message_set_content(info,ct);
		linphone_content_unref(ct);
	}
	linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info);
	linphone_info_message_destroy(info);

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1));

	BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_info_message);
	hvalue=linphone_info_message_get_header(pauline->stat.last_received_info_message, "Weather");
	content=linphone_info_message_get_content(pauline->stat.last_received_info_message);

	BC_ASSERT_PTR_NOT_NULL(hvalue);
	if (hvalue)
		BC_ASSERT_STRING_EQUAL(hvalue, "still bad");

	if (with_content){
		BC_ASSERT_PTR_NOT_NULL(content);
		if (content) {
			BC_ASSERT_PTR_NOT_NULL(linphone_content_get_buffer(content));
			BC_ASSERT_PTR_NOT_NULL(linphone_content_get_type(content));
			BC_ASSERT_PTR_NOT_NULL(linphone_content_get_subtype(content));
			if (linphone_content_get_type(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content),"application");
			if (linphone_content_get_subtype(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content),"somexml");
			if (linphone_content_get_buffer(content))BC_ASSERT_STRING_EQUAL((const char*)linphone_content_get_buffer(content),info_content);
715
			BC_ASSERT_EQUAL((int)linphone_content_get_size(content),(int)strlen(info_content), int, "%d");
716 717 718 719 720 721 722
		}
	}
	end_call(marie, pauline);
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

723
static void info_message(void){
724 725 726
	info_message_base(FALSE);
}

727
static void info_message_with_body(void){
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
	info_message_base(TRUE);
}

static void is_composing_notification(void) {
	LinphoneChatRoom* chat_room;
	int dummy = 0;

	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
	linphone_core_get_chat_room(marie->lc, pauline->identity); /*make marie create the chatroom with pauline, which is necessary for receiving the is-composing*/
	linphone_chat_room_compose(chat_room);
	wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /*just to sleep while iterating*/
	linphone_chat_room_send_message(chat_room, "Composing a msg");
	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 1));
	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingIdleReceived, 2));
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}


#ifdef HAVE_LIME

static FILE* fopen_from_write_dir(const char * name, const char * mode) {
	char *filepath = bc_tester_file(name);
	FILE * file = fopen(filepath,mode);
	ms_free(filepath);
	return file;
}

758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
static void lime_text_message(void) {
	FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD;
	LinphoneChatRoom* chat_room;
	char* filepath;
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");

	/* make sure lime is enabled */
	linphone_core_enable_lime(marie->lc, 1);
	linphone_core_enable_lime(pauline->lc, 1);

	/* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */
	ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "w");
	ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w");
	fprintf(ZIDCacheMarieFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>ef7692d0792a67491ae2d44e</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</sndKey><rcvKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</rcvKey><sndSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>00000078</sndIndex><rcvIndex>000001cf</rcvIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a9176</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000000f</sndIndex><rcvIndex>00000000</rcvIndex></peer></cache>", linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity));
	fprintf(ZIDCachePaulineFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>005dbe0399643d953a2202dd</selfZID><peer><ZID>ef7692d0792a67491ae2d44e</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><rcvKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</rcvKey><sndKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</sndKey><rcvSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvIndex>00000078</rcvIndex><sndIndex>000001cf</sndIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000002e</sndIndex><rcvIndex>00000000</rcvIndex><pvs>01</pvs></peer></cache>", linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity));
	fclose(ZIDCacheMarieFD);
	fclose(ZIDCachePaulineFD);

	filepath = bc_tester_file("tmpZIDCacheMarie.xml");
	linphone_core_set_zrtp_secrets_file(marie->lc, filepath);
	ms_free(filepath);

	filepath = bc_tester_file("tmpZIDCachePauline.xml");
	linphone_core_set_zrtp_secrets_file(pauline->lc, filepath);
	ms_free(filepath);

	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);

	linphone_chat_room_send_message(chat_room,"Bla bla bla bla");
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,1));

	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
	/* TODO : check the msg arrived correctly deciphered */

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

798 799 800
void lime_transfer_message_base(bool_t encrypt_file) {
	FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD;
	LinphoneCoreManager *marie, *pauline;
801
	LinphoneChatMessage *msg;
802
	LinphoneChatMessageCbs *cbs;
Simon Morlat's avatar
Simon Morlat committed
803
	char *pauline_id, *marie_id;
804
	char *filepath;
805

806
	marie = linphone_core_manager_new( "marie_rc");
807
	pauline = linphone_core_manager_new( "pauline_tcp_rc");
johan's avatar
johan committed
808 809

	/* make sure lime is enabled */
Simon Morlat's avatar
Simon Morlat committed
810 811
	linphone_core_enable_lime(marie->lc, 1);
	linphone_core_enable_lime(pauline->lc, 1);
jehan's avatar
jehan committed
812 813 814 815
	if (!encrypt_file) {
		LpConfig *pauline_lp = linphone_core_get_config(pauline->lc);
		lp_config_set_int(pauline_lp,"sip","lime_for_file_sharing",0);
	}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
816

817
	/* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */
jehan's avatar
jehan committed
818 819
	ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "wb");
	ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "wb");
Simon Morlat's avatar
Simon Morlat committed
820 821
	pauline_id = linphone_address_as_string_uri_only(pauline->identity);
	marie_id = linphone_address_as_string_uri_only(marie->identity);
Simon Morlat's avatar
Simon Morlat committed
822
	fprintf(ZIDCacheMarieFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>ef7692d0792a67491ae2d44e</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</sndKey><rcvKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</rcvKey><sndSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>00000078</sndIndex><rcvIndex>000001cf</rcvIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778csal_set_uuid(lc->sal, account->instance_id);bdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a9176</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000000f</sndIndex><rcvIndex>00000000</rcvIndex></peer></cache>", pauline_id, pauline_id);
Simon Morlat's avatar
Simon Morlat committed
823
	fprintf(ZIDCachePaulineFD, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>005dbe0399643d953a2202dd</selfZID><peer><ZID>ef7692d0792a67491ae2d44e</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><rcvKey>08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d</rcvKey><sndKey>60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a</sndKey><rcvSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndSId>bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvIndex>00000078</rcvIndex><sndIndex>000001cf</sndIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>%s</uri><sndKey>81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>0000002e</sndIndex><rcvIndex>00000000</rcvIndex><pvs>01</pvs></peer></cache>", marie_id, marie_id);
824 825
	fclose(ZIDCacheMarieFD);
	fclose(ZIDCachePaulineFD);
Simon Morlat's avatar
Simon Morlat committed
826 827
	ms_free(marie_id);
	ms_free(pauline_id);
828

829
	filepath = bc_tester_file("tmpZIDCacheMarie.xml");
830 831 832
	linphone_core_set_zrtp_secrets_file(marie->lc, filepath);
	ms_free(filepath);

833
	filepath = bc_tester_file("tmpZIDCachePauline.xml");
834 835
	linphone_core_set_zrtp_secrets_file(pauline->lc, filepath);
	ms_free(filepath);
johan's avatar
johan committed
836 837 838 839

	/* Globally configure an http file transfer server. */
	linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");

840
	/* create a file transfer msg */
841
	msg = create_message_from_nowebcam(linphone_core_get_chat_room(pauline->lc, marie->identity));
842

843
	linphone_chat_room_send_chat_message(msg->chat_room, msg);
844
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1));
845
	if (marie->stat.last_received_chat_message ) {
846 847 848 849
		cbs = linphone_chat_message_get_callbacks(marie->stat.last_received_chat_message);
		linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
		linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
		linphone_chat_message_download_file(marie->stat.last_received_chat_message);
jehan's avatar
jehan committed
850
	}
851
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1));
johan's avatar
johan committed
852

853 854
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); // file transfer
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
855
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1, int, "%d");
johan's avatar
johan committed
856 857
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
johan's avatar
johan committed
858
}
859

860
static  void lime_transfer_message(void) {
861
	lime_transfer_message_base(TRUE);
862 863
}

864
static  void lime_transfer_message_without_encryption(void) {
865
	lime_transfer_message_base(FALSE);
866 867
}

868 869 870 871 872 873 874 875 876
static void printHex(char *title, uint8_t *data, uint32_t length) {
	int i;
	char debug_string_buffer[2048];
	char *debug_string = debug_string_buffer;
	sprintf (debug_string, "%s : ", title);
	debug_string += strlen(title)+3;
	for (i=0; i<length; i++) {
		sprintf (debug_string, "0x%02x, ", data[i]);
		debug_string+=6;
877
	}
878 879
	*debug_string = '\0';
	ms_message("%s", debug_string_buffer);
880 881
}

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
static void lime_unit(void) {
	const char* PLAIN_TEXT_TEST_MESSAGE = "Ceci est un fabuleux msg de test à encrypter";
	int retval;
	size_t size;
	uint8_t *cacheBufferString;
	xmlDocPtr cacheBufferAlice;
	xmlDocPtr cacheBufferBob;
	uint8_t *multipartMessage = NULL;
	uint8_t *decryptedMessage = NULL;
	xmlChar *xmlStringOutput;
	int xmlStringLength;
	limeURIKeys_t associatedKeys;
	int i;
	limeKey_t associatedKey;
	uint8_t targetZID[12] = {0x00, 0x5d, 0xbe, 0x03, 0x99, 0x64, 0x3d, 0x95, 0x3a, 0x22, 0x02, 0xdd};
	uint8_t senderZID[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0};
	uint8_t encryptedMessage[1024];
	uint8_t plainMessage[1024];
	uint8_t receiverZID[12];
	xmlDocPtr cacheBuffer;
	FILE *CACHE;
903

904 905
	/**** Low level tests using on cache file to extract keys, encrypt/decrypt ****/
	/**** use functions that are not directly used by external entities ****/
906

907 908 909 910 911 912 913 914 915 916 917
	/* create and load cache file */
	CACHE = fopen_from_write_dir("ZIDCache.xml", "wb");
	fprintf (CACHE, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>ef7692d0792a67491ae2d44e</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>pipo1@pipo.com</uri><sndKey>963c57bb28e62068d2df23e8f9b771932d3c57bb28e62068d2df23e8f9b77193</sndKey><rcvKey>05d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>02ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>00000069</sndIndex><rcvIndex>000001e8</rcvIndex><pvs>01</pvs></peer><peer><ZID>1234567889643d953a2202ee</ZID><rs1>9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899</rs2><uri>pipo1@pipo.com</uri><sndKey>123456789012345678901234567890123456765431262068d2df23e8f9b77193</sndKey><rcvKey>25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193</rcvKey><sndSId>f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193</sndSId><rcvSId>22ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193</rcvSId><sndIndex>00000001</sndIndex><rcvIndex>00000000</rcvIndex><pvs>01</pvs></peer></cache>");
	fclose(CACHE);
	CACHE = fopen_from_write_dir("ZIDCache.xml", "rb+");
	cacheBufferString = (uint8_t*) ms_load_file_content(CACHE, &size);
	*(cacheBufferString+size) = '\0';
	fclose(CACHE);
	/* parse it to an xmlDoc */
	cacheBuffer = xmlParseDoc(cacheBufferString);
	ms_free(cacheBufferString);
jehan's avatar
jehan committed
918

919 920 921 922 923 924 925 926
	/* get data from cache : sender */
	associatedKeys.peerURI = (uint8_t *)malloc(15);
	memcpy(associatedKeys.peerURI, "pipo1@pipo.com", 15);
	associatedKeys.associatedZIDNumber  = 0;
	retval = lime_getCachedSndKeysByURI(cacheBuffer, &associatedKeys);
	BC_ASSERT_EQUAL_FATAL(retval, 0, int, "%d");
	BC_ASSERT_EQUAL_FATAL(associatedKeys.associatedZIDNumber, 2, int, "%d"); /* there are 2 keys associated to pipo1@pipo.com address in the cache above*/
	ms_message("Get cached key by URI, for sender, return %d keys", associatedKeys.associatedZIDNumber);
927

928 929 930 931 932 933
	for (i=0; i<associatedKeys.associatedZIDNumber; i++) {
		printHex("ZID", associatedKeys.peerKeys[i]->peerZID, 12);
		printHex("key", associatedKeys.peerKeys[i]->key, 32);
		printHex("sessionID", associatedKeys.peerKeys[i]->sessionId, 32);
		ms_message("session index %d\n", associatedKeys.peerKeys[i]->sessionIndex);
	}
934

935 936 937 938 939 940 941 942
	/* get data from cache : receiver */
	memcpy(associatedKey.peerZID, targetZID, 12);
	retval = lime_getCachedRcvKeyByZid(cacheBuffer, &associatedKey);
	BC_ASSERT_EQUAL_FATAL(retval, 0, int, "%d");
	printHex("Got receiver key for ZID", targetZID, 12);
	printHex("Key", associatedKey.key, 32);
	printHex("sessionID", associatedKey.sessionId, 32);
	ms_message("session index %d\n", associatedKey.sessionIndex);
Simon Morlat's avatar
Simon Morlat committed
943

944 945 946 947 948 949 950 951 952 953
	/* encrypt/decrypt a msg */
	lime_encryptMessage(associatedKeys.peerKeys[0], (uint8_t *)PLAIN_TEXT_TEST_MESSAGE, strlen(PLAIN_TEXT_TEST_MESSAGE), senderZID, encryptedMessage);
	printHex("Ciphered", encryptedMessage, strlen((char *)encryptedMessage));
	/* invert sender and receiverZID to decrypt/authenticate */
	memcpy(receiverZID, associatedKeys.peerKeys[0]->peerZID, 12);
	memcpy(associatedKeys.peerKeys[0]->peerZID, senderZID, 12);
	retval = lime_decryptMessage(associatedKeys.peerKeys[0], encryptedMessage, strlen(PLAIN_TEXT_TEST_MESSAGE)+16, receiverZID, plainMessage);
	BC_ASSERT_EQUAL_FATAL(retval, 0, int, "%d");
	BC_ASSERT_STRING_EQUAL((char *)plainMessage, (char *)PLAIN_TEXT_TEST_MESSAGE);
	ms_message("Decrypt and auth returned %d\nPlain text is %s\n", retval, plainMessage);
Simon Morlat's avatar
Simon Morlat committed
954

955 956 957 958 959 960
	/* update receiver data */
	associatedKey.sessionIndex++;
	associatedKey.key[0]++;
	associatedKey.sessionId[0]++;
	retval = lime_setCachedKey(cacheBuffer, &associatedKey, LIME_RECEIVER);
	BC_ASSERT_EQUAL_FATAL(retval, 0, int, "%d");
Simon Morlat's avatar
Simon Morlat committed
961

962 963 964 965 966 967
	/* update sender data */
	associatedKeys.peerKeys[0]->sessionIndex++;
	associatedKeys.peerKeys[0]->key[0]++;
	associatedKeys.peerKeys[0]->sessionId[0]++;
	retval = lime_setCachedKey(cacheBuffer, associatedKeys.peerKeys[0], LIME_SENDER);
	BC_ASSERT_EQUAL_FATAL(retval, 0, int, "%d");