1 /*
2 	liblinphone_tester - liblinphone test suite
3 	Copyright (C) 2013  Belledonne Communications SARL
4 
5 	This program is free software: you can redistribute it and/or modify
6 	it under the terms of the GNU General Public License as published by
7 	the Free Software Foundation, either version 2 of the License, or
8 	(at your option) any later version.
9 
10 	This program is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 
20 
21 #include "linphone/core.h"
22 #include "private.h"
23 #include "liblinphone_tester.h"
24 #include "lime.h"
25 #include "bctoolbox/crypto.h"
26 
27 #ifdef SQLITE_STORAGE_ENABLED
28 #include <sqlite3.h>
29 #endif
30 
31 #if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
32 #pragma GCC diagnostic push
33 #endif
34 #ifdef _MSC_VER
35 #pragma warning(disable : 4996)
36 #endif
37 
38 
39 static char* message_external_body_url=NULL;
40 
41 /* sql cache creation string, contains 3 string to be inserted : selfuri/selfuri/peeruri */
42 static const char *marie_zid_sqlcache = "BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS ziduri (zuid          INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,zid		BLOB NOT NULL DEFAULT '000000000000',selfuri	 TEXT NOT NULL DEFAULT 'unset',peeruri	 TEXT NOT NULL DEFAULT 'unset'); INSERT INTO `ziduri` (zuid,zid,selfuri,peeruri) VALUES (1,X'4ddc8042bee500ad0366bf93','%s','self'), (2,X'bcb4028bf55e1b7ac4c4edee','%s','%s'); CREATE TABLE IF NOT EXISTS zrtp (zuid		INTEGER NOT NULL DEFAULT 0 UNIQUE,rs1		BLOB DEFAULT NULL,rs2		BLOB DEFAULT NULL,aux		BLOB DEFAULT NULL,pbx		BLOB DEFAULT NULL,pvs		BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `zrtp` (zuid,rs1,rs2,aux,pbx,pvs) VALUES (2,X'f0e0ad4d3d4217ba4048d1553e5ab26fae0b386cdac603f29a66d5f4258e14ef',NULL,NULL,NULL,X'01'); CREATE TABLE IF NOT EXISTS lime (zuid		INTEGER NOT NULL DEFAULT 0 UNIQUE,sndKey		BLOB DEFAULT NULL,rcvKey		BLOB DEFAULT NULL,sndSId		BLOB DEFAULT NULL,rcvSId		BLOB DEFAULT NULL,sndIndex	BLOB DEFAULT NULL,rcvIndex	BLOB DEFAULT NULL,valid		BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `lime` (zuid,sndKey,rcvKey,sndSId,rcvSId,sndIndex,rcvIndex,valid) VALUES (2,X'97c75a5a92a041b415296beec268efc3373ef4aa8b3d5f301ac7522a7fb4e332',x'3b74b709b961e5ebccb1db6b850ea8c1f490546d6adee2f66b5def7093cead3d',X'e2ebca22ad33071bc37631393bf25fc0a9badeea7bf6dcbcb5d480be7ff8c5ea',X'a2086d195344ec2997bf3de7441d261041cda5d90ed0a0411ab2032e5860ea48',X'33376935',X'7ce32d86',X'0000000000000000'); COMMIT;";
43 
44 static const char *pauline_zid_sqlcache = "BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS ziduri (zuid          INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,zid		BLOB NOT NULL DEFAULT '000000000000',selfuri	 TEXT NOT NULL DEFAULT 'unset',peeruri	 TEXT NOT NULL DEFAULT 'unset'); INSERT INTO `ziduri` (zuid,zid,selfuri,peeruri) VALUES (1,X'bcb4028bf55e1b7ac4c4edee','%s','self'), (2,X'4ddc8042bee500ad0366bf93','%s','%s'); CREATE TABLE IF NOT EXISTS zrtp (zuid		INTEGER NOT NULL DEFAULT 0 UNIQUE,rs1		BLOB DEFAULT NULL,rs2		BLOB DEFAULT NULL,aux		BLOB DEFAULT NULL,pbx		BLOB DEFAULT NULL,pvs		BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `zrtp` (zuid,rs1,rs2,aux,pbx,pvs) VALUES (2,X'f0e0ad4d3d4217ba4048d1553e5ab26fae0b386cdac603f29a66d5f4258e14ef',NULL,NULL,NULL,X'01'); CREATE TABLE IF NOT EXISTS lime (zuid		INTEGER NOT NULL DEFAULT 0 UNIQUE,sndKey		BLOB DEFAULT NULL,rcvKey		BLOB DEFAULT NULL,sndSId		BLOB DEFAULT NULL,rcvSId		BLOB DEFAULT NULL,sndIndex	BLOB DEFAULT NULL,rcvIndex	BLOB DEFAULT NULL,valid		BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `lime` (zuid,rcvKey,sndKey,rcvSId,sndSId,rcvIndex,sndIndex,valid) VALUES (2,X'97c75a5a92a041b415296beec268efc3373ef4aa8b3d5f301ac7522a7fb4e332',x'3b74b709b961e5ebccb1db6b850ea8c1f490546d6adee2f66b5def7093cead3d',X'e2ebca22ad33071bc37631393bf25fc0a9badeea7bf6dcbcb5d480be7ff8c5ea',X'a2086d195344ec2997bf3de7441d261041cda5d90ed0a0411ab2032e5860ea48',X'33376935',X'7ce32d86',X'0000000000000000'); COMMIT;";
45 
46 static const char *xmlCacheMigration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>00112233445566778899aabb</selfZID><peer><ZID>99887766554433221100ffee</ZID><rs1>c4274f13a2b6fa05c15ec93158f930e7264b0a893393376dbc80c6eb1cccdc5a</rs1><uri>sip:bob@sip.linphone.org</uri><sndKey>219d9e445d10d4ed64083c7ccbb83a23bc17a97df0af5de4261f3fe026b05b0b</sndKey><rcvKey>747e72a5cc996413cb9fa6e3d18d8b370436e274cd6ba4efc1a4580340af57ca</rcvKey><sndSId>df2bf38e719fa89e17332cf8d5e774ee70d347baa74d16dee01f306c54789869</sndSId><rcvSId>928ce78b0bfc30427a02b1b668b2b3b0496d5664d7e89b75ed292ee97e3fc850</rcvSId><sndIndex>496bcc89</sndIndex><rcvIndex>59337abe</rcvIndex><rs2>5dda11f388384b349d210612f30824268a3753a7afa52ef6df5866dca76315c4</rs2><uri>sip:bob2@sip.linphone.org</uri></peer><peer><ZID>ffeeddccbbaa987654321012</ZID><rs1>858b495dfad483af3c088f26d68c4beebc638bd44feae45aea726a771727235e</rs1><uri>sip:bob@sip.linphone.org</uri><sndKey>b6aac945057bc4466bfe9a23771c6a1b3b8d72ec3e7d8f30ed63cbc5a9479a25</sndKey><rcvKey>bea5ac3225edd0545b816f061a8190370e3ee5160e75404846a34d1580e0c263</rcvKey><sndSId>17ce70fdf12e500294bcb5f2ffef53096761bb1c912b21e972ae03a5a9f05c47</sndSId><rcvSId>7e13a20e15a517700f0be0921f74b96d4b4a0c539d5e14d5cdd8706441874ac0</rcvSId><sndIndex>75e18caa</sndIndex><rcvIndex>2cfbbf06</rcvIndex><rs2>1533dee20c8116dc2c282cae9adfea689b87bc4c6a4e18a846f12e3e7fea3959</rs2></peer><peer><ZID>0987654321fedcba5a5a5a5a</ZID><rs1>cb6ecc87d1dd87b23f225eec53a26fc541384917623e0c46abab8c0350c6929e</rs1><sndKey>92bb03988e8f0ccfefa37a55fd7c5893bea3bfbb27312f49dd9b10d0e3c15fc7</sndKey><rcvKey>2315705a5830b98f68458fcd49623144cb34a667512c4d44686aee125bb8b622</rcvKey><sndSId>94c56eea0dd829379263b6da3f6ac0a95388090f168a3568736ca0bd9f8d595f</sndSId><rcvSId>c319ae0d41183fec90afc412d42253c5b456580f7a463c111c7293623b8631f4</rcvSId><uri>sip:bob@sip.linphone.org</uri><sndIndex>2c46ddcc</sndIndex><rcvIndex>15f5779e</rcvIndex><valid>0000000058f095bf</valid><pvs>01</pvs></peer></cache>";
47 
text_message_received(LinphoneCore * lc,LinphoneChatRoom * room,const LinphoneAddress * from_address,const char * msg)48 void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *msg) {
49 	stats* counters = get_stats(lc);
50 	counters->number_of_LinphoneMessageReceivedLegacy++;
51 }
52 
message_received(LinphoneCore * lc,LinphoneChatRoom * room,LinphoneChatMessage * msg)53 void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* msg) {
54 	char* from=linphone_address_as_string(linphone_chat_message_get_from(msg));
55 	stats* counters;
56 	const char *text=linphone_chat_message_get_text(msg);
57 	const char *external_body_url=linphone_chat_message_get_external_body_url(msg);
58 	ms_message("Message from [%s]  is [%s] , external URL [%s]",from?from:""
59 																,text?text:""
60 																,external_body_url?external_body_url:"");
61 	ms_free(from);
62 	counters = get_stats(lc);
63 	counters->number_of_LinphoneMessageReceived++;
64 	if (counters->last_received_chat_message) linphone_chat_message_unref(counters->last_received_chat_message);
65 	counters->last_received_chat_message=linphone_chat_message_ref(msg);
66 	if (linphone_chat_message_get_file_transfer_information(msg)) {
67 		counters->number_of_LinphoneMessageReceivedWithFile++;
68 	} else if (linphone_chat_message_get_external_body_url(msg)) {
69 		counters->number_of_LinphoneMessageExtBodyReceived++;
70 		if (message_external_body_url) {
71 			BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_external_body_url(msg),message_external_body_url);
72 			message_external_body_url=NULL;
73 		}
74 	}
75 }
76 
77 /**
78  * function invoked when a file transfer is received.
79  * */
file_transfer_received(LinphoneChatMessage * msg,const LinphoneContent * content,const LinphoneBuffer * buffer)80 void file_transfer_received(LinphoneChatMessage *msg, const LinphoneContent* content, const LinphoneBuffer *buffer){
81 	FILE* file=NULL;
82 	char *receive_file = NULL;
83 
84 	// If a file path is set, we should NOT call the on_recv callback !
85 	BC_ASSERT_PTR_NULL(msg->file_transfer_filepath);
86 
87 	receive_file = bc_tester_file("receive_file.dump");
88 	if (!linphone_chat_message_get_user_data(msg)) {
89 		/*first chunk, creating file*/
90 		file = fopen(receive_file,"wb");
91 		linphone_chat_message_set_user_data(msg,(void*)file); /*store fd for next chunks*/
92 	}
93 	bc_free(receive_file);
94 	file = (FILE*)linphone_chat_message_get_user_data(msg);
95 	BC_ASSERT_PTR_NOT_NULL(file);
96 	if (linphone_buffer_is_empty(buffer)) { /* tranfer complete */
97 		linphone_chat_message_set_user_data(msg, NULL);
98 		fclose(file);
99 	} else { /* store content on a file*/
100 		if (fwrite(linphone_buffer_get_content(buffer),linphone_buffer_get_size(buffer),1,file)==0){
101 			ms_error("file_transfer_received(): write() failed: %s",strerror(errno));
102 		}
103 	}
104 }
105 
106 /*
107  * function called when the file transfer is initiated. file content should be feed into object LinphoneContent
108  * */
tester_file_transfer_send(LinphoneChatMessage * msg,const LinphoneContent * content,size_t offset,size_t size)109 LinphoneBuffer * tester_file_transfer_send(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t size){
110 	LinphoneBuffer *lb;
111 	size_t file_size;
112 	size_t size_to_send;
113 	uint8_t *buf;
114 	FILE *file_to_send = linphone_chat_message_get_user_data(msg);
115 
116 	// If a file path is set, we should NOT call the on_send callback !
117 	BC_ASSERT_PTR_NULL(msg->file_transfer_filepath);
118 
119 	BC_ASSERT_PTR_NOT_NULL(file_to_send);
120 	if (file_to_send == NULL){
121 		return NULL;
122 	}
123 	fseek(file_to_send, 0, SEEK_END);
124 	file_size = ftell(file_to_send);
125 	fseek(file_to_send, (long)offset, SEEK_SET);
126 	size_to_send = MIN(size, file_size - offset);
127 	buf = ms_malloc(size_to_send);
128 	if (fread(buf, sizeof(uint8_t), size_to_send, file_to_send) != size_to_send){
129 		// reaching end of file, close it
130 		fclose(file_to_send);
131 		linphone_chat_message_set_user_data(msg, NULL);
132 	}
133 	lb = linphone_buffer_new_from_data(buf, size_to_send);
134 	ms_free(buf);
135 	return lb;
136 }
137 
138 /**
139  * function invoked to report file transfer progress.
140  * */
file_transfer_progress_indication(LinphoneChatMessage * msg,const LinphoneContent * content,size_t offset,size_t total)141 void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) {
142 	LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg);
143 	LinphoneCore *lc = linphone_chat_room_get_core(cr);
144 	const LinphoneAddress* from_address = linphone_chat_message_get_from(msg);
145 	const LinphoneAddress* to_address = linphone_chat_message_get_to(msg);
146 	char *address = linphone_chat_message_is_outgoing(msg)?linphone_address_as_string(to_address):linphone_address_as_string(from_address);
147 	stats* counters = get_stats(lc);
148 	int progress = (int)((offset * 100)/total);
149 	ms_message(" File transfer  [%d%%] %s of type [%s/%s] %s [%s] \n", progress
150 																	,(linphone_chat_message_is_outgoing(msg)?"sent":"received")
151 																	, linphone_content_get_type(content)
152 																	, linphone_content_get_subtype(content)
153 																	,(linphone_chat_message_is_outgoing(msg)?"to":"from")
154 																	, address);
155 	counters->progress_of_LinphoneFileTransfer = progress;
156 	if (progress == 100) {
157 		counters->number_of_LinphoneFileTransferDownloadSuccessful++;
158 	}
159 	free(address);
160 }
161 
is_composing_received(LinphoneCore * lc,LinphoneChatRoom * room)162 void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
163 	stats *counters = get_stats(lc);
164 	if (room->remote_is_composing == LinphoneIsComposingActive) {
165 		counters->number_of_LinphoneIsComposingActiveReceived++;
166 	} else {
167 		counters->number_of_LinphoneIsComposingIdleReceived++;
168 	}
169 }
170 
liblinphone_tester_chat_message_state_change(LinphoneChatMessage * msg,LinphoneChatMessageState state,void * ud)171 void liblinphone_tester_chat_message_state_change(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) {
172 	liblinphone_tester_chat_message_msg_state_changed(msg, state);
173 }
174 
liblinphone_tester_chat_message_msg_state_changed(LinphoneChatMessage * msg,LinphoneChatMessageState state)175 void liblinphone_tester_chat_message_msg_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
176 	LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg);
177 	LinphoneCore *lc = linphone_chat_room_get_core(cr);
178 	stats* counters = get_stats(lc);
179 	switch (state) {
180 		case LinphoneChatMessageStateIdle:
181 			return;
182 		case LinphoneChatMessageStateDelivered:
183 			counters->number_of_LinphoneMessageDelivered++;
184 			return;
185 		case LinphoneChatMessageStateNotDelivered:
186 			counters->number_of_LinphoneMessageNotDelivered++;
187 			return;
188 		case LinphoneChatMessageStateInProgress:
189 			counters->number_of_LinphoneMessageInProgress++;
190 			return;
191 		case LinphoneChatMessageStateFileTransferError:
192 			counters->number_of_LinphoneMessageNotDelivered++;
193 			return;
194 		case LinphoneChatMessageStateFileTransferDone:
195 			counters->number_of_LinphoneMessageFileTransferDone++;
196 			return;
197 		case LinphoneChatMessageStateDeliveredToUser:
198 			counters->number_of_LinphoneMessageDeliveredToUser++;
199 			return;
200 		case LinphoneChatMessageStateDisplayed:
201 			counters->number_of_LinphoneMessageDisplayed++;
202 			return;
203 	}
204 	ms_error("Unexpected state [%s] for msg [%p]",linphone_chat_message_state_to_string(state), msg);
205 }
206 
compare_files(const char * path1,const char * path2)207 void compare_files(const char *path1, const char *path2) {
208 	size_t size1;
209 	size_t size2;
210 	uint8_t *buf1;
211 	uint8_t *buf2;
212 
213 	buf1 = (uint8_t*)ms_load_path_content(path1, &size1);
214 	buf2 = (uint8_t*)ms_load_path_content(path2, &size2);
215 	BC_ASSERT_PTR_NOT_NULL(buf1);
216 	BC_ASSERT_PTR_NOT_NULL(buf2);
217 	if (buf1 && buf2){
218 		BC_ASSERT_EQUAL(memcmp(buf1, buf2, size1), 0, int, "%d");
219 	}
220 	BC_ASSERT_EQUAL((uint8_t)size2, (uint8_t)size1, uint8_t, "%u");
221 
222 	if (buf1) ms_free(buf1);
223 	if (buf2) ms_free(buf2);
224 }
225 
create_message_from_sintel_trailer(LinphoneChatRoom * chat_room)226 LinphoneChatMessage* create_message_from_sintel_trailer(LinphoneChatRoom *chat_room) {
227 	FILE *file_to_send = NULL;
228 	LinphoneChatMessageCbs *cbs;
229 	LinphoneContent* content;
230 	LinphoneChatMessage* msg;
231 	char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv");
232 	size_t file_size;
233 	file_to_send = fopen(send_filepath, "rb");
234 	fseek(file_to_send, 0, SEEK_END);
235 	file_size = ftell(file_to_send);
236 	fseek(file_to_send, 0, SEEK_SET);
237 
238 	content = linphone_core_create_content(chat_room->lc);
239 	belle_sip_object_set_name(&content->base, "sintel trailer content");
240 	linphone_content_set_type(content,"video");
241 	linphone_content_set_subtype(content,"mkv");
242 	linphone_content_set_size(content,file_size); /*total size to be transfered*/
243 	linphone_content_set_name(content,"sintel_trailer_opus_h264.mkv");
244 
245 	msg = linphone_chat_room_create_file_transfer_message(chat_room, content);
246 	cbs = linphone_chat_message_get_callbacks(msg);
247 	linphone_chat_message_cbs_set_file_transfer_send(cbs, tester_file_transfer_send);
248 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
249 	linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
250 	linphone_chat_message_set_user_data(msg, file_to_send);
251 	BC_ASSERT_PTR_NOT_NULL(linphone_chat_message_get_user_data(msg));
252 
253 	linphone_content_unref(content);
254 	bc_free(send_filepath);
255 	return msg;
256 }
257 
create_file_transfer_message_from_sintel_trailer(LinphoneChatRoom * chat_room)258 LinphoneChatMessage* create_file_transfer_message_from_sintel_trailer(LinphoneChatRoom *chat_room) {
259 	LinphoneChatMessageCbs *cbs;
260 	LinphoneContent* content;
261 	LinphoneChatMessage* msg;
262 	char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv");
263 
264 	content = linphone_core_create_content(chat_room->lc);
265 	belle_sip_object_set_name(&content->base, "sintel trailer content");
266 	linphone_content_set_type(content,"video");
267 	linphone_content_set_subtype(content,"mkv");
268 	linphone_content_set_name(content,"sintel_trailer_opus_h264.mkv");
269 
270 	msg = linphone_chat_room_create_file_transfer_message(chat_room, content);
271 	linphone_chat_message_set_file_transfer_filepath(msg, send_filepath);
272 	cbs = linphone_chat_message_get_callbacks(msg);
273 	linphone_chat_message_cbs_set_file_transfer_send(cbs, tester_file_transfer_send);
274 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
275 	linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
276 
277 	linphone_content_unref(content);
278 	bc_free(send_filepath);
279 	return msg;
280 }
281 
text_message_base(LinphoneCoreManager * marie,LinphoneCoreManager * pauline)282 void text_message_base(LinphoneCoreManager* marie, LinphoneCoreManager* pauline) {
283 	LinphoneChatMessage* msg = linphone_chat_room_create_message(linphone_core_get_chat_room(pauline->lc,marie->identity),"Bli bli bli \n blu");
284 	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
285 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
286 	linphone_chat_room_send_chat_message(msg->chat_room,msg);
287 
288 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1));
289 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
290 	BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message);
291 	if (marie->stat.last_received_chat_message != NULL) {
292 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(marie->stat.last_received_chat_message), "text/plain");
293 	}
294 
295 	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
296 }
297 
298 /****************************** Tests starting below ******************************/
299 
text_message(void)300 static void text_message(void) {
301 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
302 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
303 
304 	linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc,marie->identity), "hello");
305 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,1));
306 
307 	linphone_core_manager_destroy(marie);
308 	linphone_core_manager_destroy(pauline);
309 }
310 
text_message_within_call_dialog(void)311 static void text_message_within_call_dialog(void) {
312 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
313 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
314 	lp_config_set_int(pauline->lc->config,"sip","chat_use_call_dialogs",1);
315 
316 	BC_ASSERT_TRUE(call(marie,pauline));
317 	linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bla bla bla bla");
318 
319 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
320 	// when using call dialogs, we will never receive delivered status
321 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,0,int,"%d");
322 
323 	end_call(marie, pauline);
324 	linphone_core_manager_destroy(marie);
325 	linphone_core_manager_destroy(pauline);
326 }
327 
328 static LinphoneAuthInfo* text_message_with_credential_from_auth_cb_auth_info;
text_message_with_credential_from_auth_cb_auth_info_requested(LinphoneCore * lc,const char * realm,const char * username,const char * domain)329 static void text_message_with_credential_from_auth_cb_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) {
330 	ms_message("text_message_with_credential_from_auth_callback:Auth info requested  for user id [%s] at realm [%s]\n"
331 						,username
332 						,realm);
333 	linphone_core_add_auth_info(lc,text_message_with_credential_from_auth_cb_auth_info); /*add stored authentication info to LinphoneCore*/
334 }
text_message_with_credential_from_auth_callback(void)335 static void text_message_with_credential_from_auth_callback(void) {
336 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
337 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
338 	LinphoneCoreVTable* vtable = linphone_core_v_table_new();
339 
340 	/*to force cb to be called*/
341 	text_message_with_credential_from_auth_cb_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(pauline->lc)->data));
342 	linphone_core_clear_all_auth_info(pauline->lc);
343 	vtable->auth_info_requested=text_message_with_credential_from_auth_cb_auth_info_requested;
344 	linphone_core_add_listener(pauline->lc, vtable);
345 
346 	text_message_base(marie, pauline);
347 
348 	linphone_core_manager_destroy(marie);
349 	linphone_core_manager_destroy(pauline);
350 	linphone_auth_info_destroy(text_message_with_credential_from_auth_cb_auth_info);
351 	text_message_with_credential_from_auth_cb_auth_info = NULL;
352 }
353 
text_message_with_privacy(void)354 static void text_message_with_privacy(void) {
355 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
356 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
357 	linphone_proxy_config_set_privacy(linphone_core_get_default_proxy_config(pauline->lc),LinphonePrivacyId);
358 
359 	text_message_base(marie, pauline);
360 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1, int, "%d");
361 
362 	linphone_core_manager_destroy(marie);
363 	linphone_core_manager_destroy(pauline);
364 }
365 
text_message_compatibility_mode(void)366 static void text_message_compatibility_mode(void) {
367 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
368 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
369 	LinphoneProxyConfig* proxy = linphone_core_get_default_proxy_config(marie->lc);
370 	LinphoneAddress* proxy_address=linphone_address_new(linphone_proxy_config_get_server_addr(proxy));
371 	char route[256];
372 	char*tmp;
373 	/*only keep tcp*/
374 	LCSipTransports transport = {0,-1,0,0};
375 	linphone_address_clean(proxy_address);
376 	tmp=linphone_address_as_string_uri_only(proxy_address);
377 	linphone_proxy_config_set_server_addr(proxy,tmp);
378 	sprintf(route,"sip:%s",test_route);
379 	linphone_proxy_config_set_route(proxy,route);
380 	ms_free(tmp);
381 	linphone_address_unref(proxy_address);
382 	linphone_core_set_sip_transports(marie->lc,&transport);
383 	marie->stat.number_of_LinphoneRegistrationOk=0;
384 	BC_ASSERT_TRUE (wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationOk,1));
385 
386 	text_message_base(marie, pauline);
387 
388 	linphone_core_manager_destroy(marie);
389 	linphone_core_manager_destroy(pauline);
390 }
391 
text_message_with_ack(void)392 static void text_message_with_ack(void) {
393 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
394 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
395 
396 	text_message_base(marie, pauline);
397 
398 	linphone_core_manager_destroy(marie);
399 	linphone_core_manager_destroy(pauline);
400 }
401 
text_message_with_send_error(void)402 static void text_message_with_send_error(void) {
403 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
404 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
405 	LinphoneChatRoom* chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity);
406 	LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu");
407 	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
408 
409 	/*simulate a network error*/
410 	sal_set_send_error(marie->lc->sal, -1);
411 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
412 	linphone_chat_room_send_chat_message(chat_room,msg);
413 
414 	/* check transient msg list: the msg should be in it, and should be the only one */
415 	BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u");
416 	BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg);
417 
418 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1));
419 	/*BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageInProgress,1, int, "%d");*/
420 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d");
421 
422 	/* the msg should have been discarded from transient list after an error */
423 	BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u");
424 
425 	sal_set_send_error(marie->lc->sal, 0);
426 
427 	/*give a chance to register again to allow linphone_core_manager_destroy to properly unregister*/
428 	linphone_core_refresh_registers(marie->lc);
429 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationOk,marie->stat.number_of_LinphoneRegistrationOk + 1));
430 
431 	linphone_core_manager_destroy(marie);
432 	linphone_core_manager_destroy(pauline);
433 }
434 
text_message_with_external_body(void)435 static void text_message_with_external_body(void) {
436 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
437 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
438 	LinphoneChatRoom* chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
439 	LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu");
440 	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
441 
442 	message_external_body_url="http://www.linphone.org";
443 	linphone_chat_message_set_external_body_url(msg,message_external_body_url);
444 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
445 	linphone_chat_room_send_chat_message(chat_room,msg);
446 
447 	/* check transient msg list: the msg should be in it, and should be the only one */
448 	BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u");
449 	BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg);
450 
451 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
452 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1));
453 
454 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1, int, "%d");
455 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1, int, "%d");
456 
457 	BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u");
458 
459 	linphone_core_manager_destroy(marie);
460 	linphone_core_manager_destroy(pauline);
461 }
462 
transfer_message_base2(LinphoneCoreManager * marie,LinphoneCoreManager * pauline,bool_t upload_error,bool_t download_error,bool_t use_file_body_handler_in_upload,bool_t use_file_body_handler_in_download,bool_t download_from_history)463 void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pauline, bool_t upload_error, bool_t download_error,
464 							bool_t use_file_body_handler_in_upload, bool_t use_file_body_handler_in_download, bool_t download_from_history) {
465 	char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv");
466 	char *receive_filepath = bc_tester_file("receive_file.dump");
467 	LinphoneChatRoom* chat_room;
468 	LinphoneChatMessage* msg;
469 	LinphoneChatMessageCbs *cbs;
470 	bctbx_list_t *msg_list = NULL;
471 
472 	/* Remove any previously downloaded file */
473 	remove(receive_filepath);
474 
475 	/* Globally configure an http file transfer server. */
476 	linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
477 
478 	/* create a chatroom on pauline's side */
479 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
480 
481 	/* create a file transfer msg */
482 	if (use_file_body_handler_in_upload) {
483 		msg = create_file_transfer_message_from_sintel_trailer(chat_room);
484 	} else {
485 		msg = create_message_from_sintel_trailer(chat_room);
486 	}
487 
488 	linphone_chat_room_send_chat_message(chat_room,msg);
489 
490 	if (upload_error) {
491 		int chat_room_size = 0;
492 		bctbx_list_t *history;
493 
494 		/*wait for file to be 25% uploaded and simulate a network error*/
495 		BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer,25, 60000));
496 		/* Check that the message is already in the chat room history during file upload */
497 		chat_room_size = linphone_chat_room_get_history_size(chat_room);
498 		BC_ASSERT_EQUAL(chat_room_size, 1, int, "%d");
499 		if (chat_room_size == 1) {
500 			history = linphone_chat_room_get_history(chat_room, 0);
501 			LinphoneChatMessage *sent_msg = (LinphoneChatMessage *)bctbx_list_get_data(history);
502 			BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateInProgress, int, "%d");
503 			bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref);
504 		}
505 		sal_set_send_error(pauline->lc->sal, -1);
506 
507 		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));
508 
509 		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");
510 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");
511 
512 		sal_set_send_error(pauline->lc->sal, 0);
513 
514 		linphone_core_refresh_registers(pauline->lc); /*to make sure registration is back in registered and so it can be later unregistered*/
515 		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneRegistrationOk,pauline->stat.number_of_LinphoneRegistrationOk+1));
516 
517 		/* Check that the message is in the chat room history even if the file upload failed */
518 		chat_room_size = linphone_chat_room_get_history_size(chat_room);
519 		BC_ASSERT_EQUAL(chat_room_size, 1, int, "%d");
520 		if (chat_room_size == 1) {
521 			history = linphone_chat_room_get_history(chat_room, 0);
522 			LinphoneChatMessage *sent_msg = (LinphoneChatMessage *)bctbx_list_get_data(history);
523 			BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateNotDelivered, int, "%d");
524 			bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref);
525 		}
526 	} else {
527 		BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000));
528 		if (marie->stat.last_received_chat_message) {
529 			LinphoneChatMessage *recv_msg;
530 			if (download_from_history) {
531 				LinphoneChatRoom *marie_room = linphone_core_get_chat_room(marie->lc, pauline->identity);
532 				msg_list = linphone_chat_room_get_history(marie_room,1);
533 				BC_ASSERT_PTR_NOT_NULL(msg_list);
534 				if (!msg_list)  goto end;
535 				recv_msg = (LinphoneChatMessage *)msg_list->data;
536 			} else {
537 				recv_msg = marie->stat.last_received_chat_message;
538 			}
539 			cbs = linphone_chat_message_get_callbacks(recv_msg);
540 			linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
541 			linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
542 			linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
543 			if (use_file_body_handler_in_download) {
544 				linphone_chat_message_set_file_transfer_filepath(recv_msg, receive_filepath);
545 			}
546 			linphone_chat_message_download_file(recv_msg);
547 
548 			if (download_error) {
549 				/* wait for file to be 50% downloaded */
550 				BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
551 				/* and simulate network error */
552 				belle_http_provider_set_recv_error(marie->lc->http_provider, -1);
553 				BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneMessageNotDelivered,1, 10000));
554 				belle_http_provider_set_recv_error(marie->lc->http_provider, 0);
555 			} else {
556 				/* wait for a long time in case the DNS SRV resolution takes times - it should be immediate though */
557 				if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1,55000))) {
558 					compare_files(send_filepath, receive_filepath);
559 				}
560 			}
561 		}
562 		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); //sent twice because of file transfer
563 		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
564 	}
565 end:
566 	bctbx_list_free_with_data(msg_list, (bctbx_list_free_func)linphone_chat_message_unref);
567 	remove(receive_filepath);
568 	bc_free(send_filepath);
569 	bc_free(receive_filepath);
570 }
571 
transfer_message_base(bool_t upload_error,bool_t download_error,bool_t use_file_body_handler_in_upload,bool_t use_file_body_handler_in_download,bool_t download_from_history)572 void transfer_message_base(bool_t upload_error, bool_t download_error, bool_t use_file_body_handler_in_upload,
573 						   bool_t use_file_body_handler_in_download, bool_t download_from_history) {
574 	if (transport_supported(LinphoneTransportTls)) {
575 		LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
576 		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
577 		transfer_message_base2(marie,pauline,upload_error,download_error, use_file_body_handler_in_upload, use_file_body_handler_in_download, download_from_history);
578 		linphone_core_manager_destroy(pauline);
579 		linphone_core_manager_destroy(marie);
580 	}
581 }
transfer_message(void)582 static void transfer_message(void) {
583 	transfer_message_base(FALSE, FALSE, FALSE, FALSE, FALSE);
584 }
585 
transfer_message_2(void)586 static void transfer_message_2(void) {
587 	transfer_message_base(FALSE, FALSE, TRUE, FALSE, FALSE);
588 }
589 
transfer_message_3(void)590 static void transfer_message_3(void) {
591 	transfer_message_base(FALSE, FALSE, FALSE, TRUE, FALSE);
592 }
593 
transfer_message_4(void)594 static void transfer_message_4(void) {
595 	transfer_message_base(FALSE, FALSE, TRUE, TRUE, FALSE);
596 }
597 
transfer_message_from_history(void)598 static void transfer_message_from_history(void) {
599 	transfer_message_base(FALSE, FALSE, TRUE, TRUE, TRUE);
600 }
601 
transfer_message_with_upload_io_error(void)602 static void transfer_message_with_upload_io_error(void) {
603 	transfer_message_base(TRUE, FALSE, FALSE, FALSE, FALSE);
604 }
605 
transfer_message_with_download_io_error(void)606 static void transfer_message_with_download_io_error(void) {
607 	transfer_message_base(FALSE, TRUE, FALSE, FALSE, FALSE);
608 }
609 
transfer_message_upload_cancelled(void)610 static void transfer_message_upload_cancelled(void) {
611 	if (transport_supported(LinphoneTransportTls)) {
612 		LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
613 		LinphoneChatRoom* chat_room;
614 		LinphoneChatMessage* msg;
615 		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
616 
617 		/* Globally configure an http file transfer server. */
618 		linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
619 
620 		/* create a chatroom on pauline's side */
621 		chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
622 
623 		msg = create_message_from_sintel_trailer(chat_room);
624 		linphone_chat_room_send_chat_message(chat_room,msg);
625 
626 		/*wait for file to be 25% uploaded and cancel the transfer */
627 		BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 25, 60000));
628 		linphone_chat_message_cancel_file_transfer(msg);
629 
630 		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));
631 
632 		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");
633 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");
634 
635 		linphone_core_manager_destroy(pauline);
636 		linphone_core_manager_destroy(marie);
637 	}
638 }
639 
transfer_message_download_cancelled(void)640 static void transfer_message_download_cancelled(void) {
641 	LinphoneChatRoom* chat_room;
642 	LinphoneChatMessage* msg;
643 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
644 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
645 
646 	/* Globally configure an http file transfer server. */
647 	linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
648 
649 	/* create a chatroom on pauline's side */
650 	chat_room = linphone_core_get_chat_room(pauline->lc,marie->identity);
651 	msg = create_message_from_sintel_trailer(chat_room);
652 	linphone_chat_room_send_chat_message(chat_room,msg);
653 
654 	/* wait for marie to receive pauline's msg */
655 	BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000));
656 
657 	if (marie->stat.last_received_chat_message ) { /* get last msg and use it to download file */
658 		LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(marie->stat.last_received_chat_message);
659 		linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
660 		linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change, marie->lc);
661 		/* wait for file to be 50% downloaded */
662 		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
663 		/* and cancel the transfer */
664 		linphone_chat_message_cancel_file_transfer(marie->stat.last_received_chat_message);
665 	}
666 
667 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d");
668 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
669 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d");
670 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d");
671 
672 	linphone_core_manager_destroy(marie);
673 	linphone_core_manager_destroy(pauline);
674 }
675 
file_transfer_using_external_body_url(void)676 static void file_transfer_using_external_body_url(void) {
677 	if (transport_supported(LinphoneTransportTls)) {
678 		LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
679 		LinphoneChatRoom *chat_room;
680 		LinphoneChatMessage *msg;
681 		LinphoneChatMessageCbs *cbs;
682 		LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc");
683 
684 		/* make sure lime is disabled */
685 		linphone_core_enable_lime(marie->lc, LinphoneLimeDisabled);
686 		linphone_core_enable_lime(pauline->lc, LinphoneLimeDisabled);
687 
688 		/* create a chatroom on pauline's side */
689 		chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
690 
691 		msg = linphone_chat_room_create_message(chat_room, NULL);
692 
693 		cbs = linphone_chat_message_get_callbacks(msg);
694 		linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
695 
696 		linphone_chat_message_set_external_body_url(msg, "https://www.linphone.org:444//tmp/54ec58280ace9_c30709218df8eaba61d1.jpg");
697 		linphone_chat_room_send_chat_message(chat_room, msg);
698 
699 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
700 		if (marie->stat.last_received_chat_message) {
701 			linphone_chat_message_download_file(marie->stat.last_received_chat_message);
702 		}
703 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageExtBodyReceived, 1));
704 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageInProgress, 1));
705 		linphone_core_manager_destroy(pauline);
706 		linphone_core_manager_destroy(marie);
707 	}
708 }
709 
file_transfer_2_messages_simultaneously(void)710 static void file_transfer_2_messages_simultaneously(void) {
711 	if (transport_supported(LinphoneTransportTls)) {
712 		LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
713 		LinphoneChatRoom* pauline_room;
714 		LinphoneChatMessage* msg;
715 		LinphoneChatMessage* msg2;
716 		LinphoneChatMessageCbs *cbs;
717 		char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv");
718 		char *receive_filepath = bc_tester_file("receive_file.dump");
719 		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
720 
721 		/* Remove any previously downloaded file */
722 		remove(receive_filepath);
723 
724 		/* Globally configure an http file transfer server. */
725 		linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
726 
727 		/* create a chatroom on pauline's side */
728 		pauline_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
729 		msg = create_message_from_sintel_trailer(pauline_room);
730 		msg2 = create_message_from_sintel_trailer(pauline_room);
731 
732 		cbs = linphone_chat_message_get_callbacks(msg2);
733 		linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
734 
735 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)), 0, unsigned int, "%u");
736 		if (bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)) == 0) {
737 			linphone_chat_room_send_chat_message(pauline_room,msg);
738 			linphone_chat_room_send_chat_message(pauline_room,msg2);
739 			if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000))) {
740 				msg = linphone_chat_message_clone(marie->stat.last_received_chat_message);
741 				BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,2, 60000));
742 				msg2 = marie->stat.last_received_chat_message;
743 				BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)), 1, unsigned int, "%u");
744 				if (bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)) != 1) {
745 					char * buf = ms_strdup_printf("Found %d rooms instead of 1: ", bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)));
746 					const bctbx_list_t *it = linphone_core_get_chat_rooms(marie->lc);
747 					while (it) {
748 						const LinphoneAddress * peer = linphone_chat_room_get_peer_address(it->data);
749 						buf = ms_strcat_printf("%s, ", linphone_address_get_username(peer));
750 						it = it->next;
751 					}
752 					ms_error("%s", buf);
753 				}
754 
755 				cbs = linphone_chat_message_get_callbacks(msg);
756 				linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
757 				linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
758 				linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
759 				linphone_chat_message_download_file(msg);
760 
761 				cbs = linphone_chat_message_get_callbacks(msg2);
762 				linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
763 				linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
764 				linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
765 				linphone_chat_message_download_file(msg2);
766 
767 				BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,2,50000));
768 
769 				BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,4, int, "%d");
770 				BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,2, int, "%d");
771 				compare_files(send_filepath, receive_filepath);
772 
773 				linphone_chat_message_unref(msg);
774 			}
775 		}
776 		linphone_core_manager_destroy(pauline);
777 		remove(receive_filepath);
778 		bc_free(send_filepath);
779 		bc_free(receive_filepath);
780 		linphone_core_manager_destroy(marie);
781 	}
782 }
783 
text_message_denied(void)784 static void text_message_denied(void) {
785 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
786 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
787 	LinphoneChatRoom* chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity);
788 	LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu");
789 	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
790 
791 	/*pauline doesn't want to be disturbed*/
792 	linphone_core_disable_chat(pauline->lc,LinphoneReasonDoNotDisturb);
793 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
794 	linphone_chat_room_send_chat_message(chat_room,msg);
795 
796 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1));
797 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d");
798 	linphone_core_manager_destroy(marie);
799 	linphone_core_manager_destroy(pauline);
800 }
801 
802 static const char *info_content="<somexml>blabla</somexml>";
803 
info_message_received(LinphoneCore * lc,LinphoneCall * call,const LinphoneInfoMessage * msg)804 void info_message_received(LinphoneCore *lc, LinphoneCall* call, const LinphoneInfoMessage *msg){
805 	stats* counters = get_stats(lc);
806 
807 	if (counters->last_received_info_message) {
808 		linphone_info_message_unref(counters->last_received_info_message);
809 	}
810 	counters->last_received_info_message=linphone_info_message_copy(msg);
811 	counters->number_of_inforeceived++;
812 }
813 
info_message_base(bool_t with_content)814 void info_message_base(bool_t with_content) {
815 	LinphoneInfoMessage *info;
816 	const LinphoneContent *content;
817 	const char *hvalue;
818 
819 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
820 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
821 
822 	BC_ASSERT_TRUE(call(pauline,marie));
823 
824 	info=linphone_core_create_info_message(marie->lc);
825 	linphone_info_message_add_header(info,"Weather","still bad");
826 	if (with_content) {
827 		LinphoneContent* ct=linphone_core_create_content(marie->lc);
828 		linphone_content_set_type(ct,"application");
829 		linphone_content_set_subtype(ct,"somexml");
830 		linphone_content_set_buffer(ct,info_content,strlen(info_content));
831 		linphone_info_message_set_content(info,ct);
832 		linphone_content_unref(ct);
833 	}
834 	linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info);
835 	linphone_info_message_unref(info);
836 
837 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1));
838 
839 	BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_info_message);
840 	hvalue=linphone_info_message_get_header(pauline->stat.last_received_info_message, "Weather");
841 	content=linphone_info_message_get_content(pauline->stat.last_received_info_message);
842 
843 	BC_ASSERT_PTR_NOT_NULL(hvalue);
844 	if (hvalue)
845 		BC_ASSERT_STRING_EQUAL(hvalue, "still bad");
846 
847 	if (with_content){
848 		BC_ASSERT_PTR_NOT_NULL(content);
849 		if (content) {
850 			BC_ASSERT_PTR_NOT_NULL(linphone_content_get_buffer(content));
851 			BC_ASSERT_PTR_NOT_NULL(linphone_content_get_type(content));
852 			BC_ASSERT_PTR_NOT_NULL(linphone_content_get_subtype(content));
853 			if (linphone_content_get_type(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content),"application");
854 			if (linphone_content_get_subtype(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content),"somexml");
855 			if (linphone_content_get_buffer(content))BC_ASSERT_STRING_EQUAL((const char*)linphone_content_get_buffer(content),info_content);
856 			BC_ASSERT_EQUAL((int)linphone_content_get_size(content),(int)strlen(info_content), int, "%d");
857 		}
858 	}
859 	end_call(marie, pauline);
860 	linphone_core_manager_destroy(marie);
861 	linphone_core_manager_destroy(pauline);
862 }
863 
info_message(void)864 static void info_message(void){
865 	info_message_base(FALSE);
866 }
867 
info_message_with_body(void)868 static void info_message_with_body(void){
869 	info_message_base(TRUE);
870 }
871 
enable_lime_for_message_test(LinphoneCoreManager * marie,LinphoneCoreManager * pauline)872 static int enable_lime_for_message_test(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) {
873 #ifdef SQLITE_STORAGE_ENABLED
874 	char* filepath = NULL;
875 	char* stmt = NULL;
876 	char* errmsg=NULL;
877 	int ret = 0;
878 	char* paulineUri = NULL;
879 	char* marieUri = NULL;
880 
881 	if (!linphone_core_lime_available(marie->lc) || !linphone_core_lime_available(pauline->lc)) {
882 		ms_warning("Lime not available, skiping");
883 		return -1;
884 	}
885 	/* make sure lime is enabled */
886 	linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory);
887 	linphone_core_enable_lime(pauline->lc, LinphoneLimeMandatory);
888 
889 	/* make sure to not trigger the cache migration function */
890 	lp_config_set_int(marie->lc->config, "sip", "zrtp_cache_migration_done", TRUE);
891 	lp_config_set_int(pauline->lc->config, "sip", "zrtp_cache_migration_done", TRUE);
892 
893 	/* create temporary cache files: setting the database_path will create and initialise the files */
894 	remove(bc_tester_file("tmpZIDCacheMarie.sqlite"));
895 	remove(bc_tester_file("tmpZIDCachePauline.sqlite"));
896 	filepath = bc_tester_file("tmpZIDCacheMarie.sqlite");
897 	linphone_core_set_zrtp_secrets_file(marie->lc, filepath);
898 	bc_free(filepath);
899 	filepath = bc_tester_file("tmpZIDCachePauline.sqlite");
900 	linphone_core_set_zrtp_secrets_file(pauline->lc, filepath);
901 	bc_free(filepath);
902 
903 	/* caches are empty, populate them */
904 	paulineUri =  linphone_address_as_string_uri_only(pauline->identity);
905 	marieUri = linphone_address_as_string_uri_only(marie->identity);
906 
907 	stmt = sqlite3_mprintf(marie_zid_sqlcache, marieUri, marieUri, paulineUri);
908 	ret = sqlite3_exec(linphone_core_get_zrtp_cache_db(marie->lc),stmt,NULL,NULL,&errmsg);
909 	sqlite3_free(stmt);
910 	if (ret != SQLITE_OK) {
911 		ms_warning("Lime can't populate marie's sqlite cache: %s", errmsg);
912 		sqlite3_free(errmsg);
913 		return -1;
914 	}
915 	stmt = sqlite3_mprintf(pauline_zid_sqlcache, paulineUri, paulineUri, marieUri);
916 	ret = sqlite3_exec(linphone_core_get_zrtp_cache_db(pauline->lc),stmt,NULL,NULL,&errmsg);
917 	sqlite3_free(stmt);
918 	if (ret != SQLITE_OK) {
919 		ms_warning("Lime can't populate pauline's sqlite cache: %s", errmsg);
920 		sqlite3_free(errmsg);
921 		return -1;
922 	}
923 
924 
925 	return 0;
926 #else /* SQLITE_STORAGE_ENABLED */
927 	return -1; /* cannot enable lime without SQLITE_STORAGE */
928 #endif /* SQLITE_STORAGE_ENABLED */
929 }
930 
_is_composing_notification(bool_t lime_enabled)931 static void _is_composing_notification(bool_t lime_enabled) {
932 	LinphoneChatRoom* chat_room;
933 	int dummy = 0;
934 
935 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
936 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
937 
938 	if (lime_enabled) {
939 		if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
940 	}
941 
942 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
943 	linphone_core_get_chat_room(marie->lc, pauline->identity); /*make marie create the chatroom with pauline, which is necessary for receiving the is-composing*/
944 	linphone_chat_room_compose(chat_room);
945 	wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /*just to sleep while iterating*/
946 	linphone_chat_room_send_message(chat_room, "Composing a msg");
947 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 1));
948 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingIdleReceived, 2));
949 
950 end:
951 	linphone_core_manager_destroy(marie);
952 	linphone_core_manager_destroy(pauline);
953 	remove("tmpZIDCacheMarie.sqlite");
954 	remove("tmpZIDCachePauline.sqlite");
955 }
956 
is_composing_notification(void)957 static void is_composing_notification(void) {
958 	_is_composing_notification(FALSE);
959 }
960 
961 #ifdef SQLITE_STORAGE_ENABLED
is_composing_notification_with_lime(void)962 static void is_composing_notification_with_lime(void) {
963 	_is_composing_notification(TRUE);
964 }
965 #endif
966 
_imdn_notifications(bool_t with_lime)967 static void _imdn_notifications(bool_t with_lime) {
968 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
969 	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
970 	LinphoneChatRoom *pauline_chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
971 	LinphoneChatRoom *marie_chat_room;
972 	LinphoneChatMessage *sent_cm;
973 	LinphoneChatMessage *received_cm;
974 	LinphoneChatMessageCbs *cbs;
975 	bctbx_list_t *history;
976 
977 	if (with_lime) {
978 		if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
979 	}
980 
981 	linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc));
982 	linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc));
983 	sent_cm = linphone_chat_room_create_message(pauline_chat_room, "Tell me if you get my message");
984 	linphone_chat_message_ref(sent_cm);
985 	cbs = linphone_chat_message_get_callbacks(sent_cm);
986 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
987 	linphone_chat_room_send_chat_message(pauline_chat_room, sent_cm);
988 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
989 	marie_chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity);
990 	history = linphone_chat_room_get_history(marie_chat_room, 1);
991 	BC_ASSERT_EQUAL((int)bctbx_list_size(history), 1, int, "%d");
992 	received_cm = (LinphoneChatMessage *)bctbx_list_nth_data(history, 0);
993 	BC_ASSERT_PTR_NOT_NULL(received_cm);
994 	if (received_cm != NULL) {
995 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1));
996 		linphone_chat_room_mark_as_read(marie_chat_room); /* This sends the display notification */
997 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDisplayed, 1));
998 		bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref);
999 	}
1000 
1001 	linphone_chat_message_unref(sent_cm);
1002 
1003 end:
1004 	linphone_core_manager_destroy(marie);
1005 	linphone_core_manager_destroy(pauline);
1006 	remove("tmpZIDCacheMarie.sqlite");
1007 	remove("tmpZIDCachePauline.sqlite");
1008 }
1009 
_im_notification_policy(bool_t with_lime)1010 static void _im_notification_policy(bool_t with_lime) {
1011 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1012 	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
1013 	LinphoneImNotifPolicy *marie_policy = linphone_core_get_im_notif_policy(marie->lc);
1014 	LinphoneImNotifPolicy *pauline_policy = linphone_core_get_im_notif_policy(pauline->lc);
1015 	LinphoneChatRoom *pauline_chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
1016 	LinphoneChatRoom *marie_chat_room;
1017 	LinphoneChatMessage *msg1;
1018 	LinphoneChatMessage *msg2;
1019 	LinphoneChatMessage *msg3;
1020 	LinphoneChatMessage *msg4;
1021 	LinphoneChatMessageCbs *cbs;
1022 	int dummy = 0;
1023 
1024 	if (with_lime) {
1025 		if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
1026 	}
1027 
1028 	linphone_im_notif_policy_enable_all(marie_policy);
1029 	linphone_im_notif_policy_clear(pauline_policy);
1030 	marie_chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity); /* Make marie create the chatroom with pauline, which is necessary for receiving the is-composing */
1031 
1032 	/* Test is_composing sending */
1033 	linphone_chat_room_compose(pauline_chat_room);
1034 	wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */
1035 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneIsComposingActiveReceived, 0, int, "%d");
1036 	linphone_im_notif_policy_set_send_is_composing(pauline_policy, TRUE);
1037 	linphone_chat_room_compose(pauline_chat_room);
1038 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 1));
1039 
1040 	/* Test is_composing receiving */
1041 	linphone_chat_room_compose(marie_chat_room);
1042 	wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */
1043 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneIsComposingActiveReceived, 0, int, "%d");
1044 	linphone_im_notif_policy_set_recv_is_composing(pauline_policy, TRUE);
1045 	linphone_chat_room_compose(marie_chat_room);
1046 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, 1));
1047 
1048 	/* Test imdn delivered */
1049 	msg1 = linphone_chat_room_create_message(pauline_chat_room, "Happy new year!");
1050 	linphone_chat_message_ref(msg1);
1051 	cbs = linphone_chat_message_get_callbacks(msg1);
1052 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
1053 	linphone_chat_room_send_chat_message(pauline_chat_room, msg1);
1054 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
1055 	wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */
1056 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDeliveredToUser, 0, int, "%d");
1057 	linphone_im_notif_policy_set_recv_imdn_delivered(pauline_policy, TRUE);
1058 	msg2 = linphone_chat_room_create_message(pauline_chat_room, "I said: Happy new year!");
1059 	linphone_chat_message_ref(msg2);
1060 	cbs = linphone_chat_message_get_callbacks(msg2);
1061 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
1062 	linphone_chat_room_send_chat_message(pauline_chat_room, msg2);
1063 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2));
1064 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1));
1065 	msg3 = linphone_chat_room_create_message(marie_chat_room, "Thank you! Happy easter to you!");
1066 	linphone_chat_message_ref(msg3);
1067 	cbs = linphone_chat_message_get_callbacks(msg3);
1068 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
1069 	linphone_chat_room_send_chat_message(marie_chat_room, msg3);
1070 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1));
1071 	wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */
1072 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageDeliveredToUser, 0, int, "%d");
1073 	linphone_im_notif_policy_set_send_imdn_delivered(pauline_policy, TRUE);
1074 	msg4 = linphone_chat_room_create_message(marie_chat_room, "Yeah, yeah, I heard that...");
1075 	linphone_chat_message_ref(msg4);
1076 	cbs = linphone_chat_message_get_callbacks(msg4);
1077 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
1078 	linphone_chat_room_send_chat_message(marie_chat_room, msg4);
1079 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 2));
1080 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageDeliveredToUser, 1));
1081 
1082 	/* Test imdn displayed */
1083 	linphone_im_notif_policy_set_send_imdn_displayed(pauline_policy, TRUE);
1084 	linphone_chat_room_mark_as_read(pauline_chat_room);
1085 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageDisplayed, 2));
1086 	linphone_im_notif_policy_set_recv_imdn_displayed(pauline_policy, TRUE);
1087 	linphone_chat_room_mark_as_read(marie_chat_room);
1088 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDisplayed, 2));
1089 
1090 	linphone_chat_message_unref(msg1);
1091 	linphone_chat_message_unref(msg2);
1092 	linphone_chat_message_unref(msg3);
1093 	linphone_chat_message_unref(msg4);
1094 
1095 end:
1096 	linphone_core_manager_destroy(marie);
1097 	linphone_core_manager_destroy(pauline);
1098 	remove("tmpZIDCacheMarie.sqlite");
1099 	remove("tmpZIDCachePauline.sqlite");
1100 }
1101 
imdn_notifications(void)1102 static void imdn_notifications(void) {
1103 	_imdn_notifications(FALSE);
1104 }
1105 
im_notification_policy(void)1106 static void im_notification_policy(void) {
1107 	_im_notification_policy(FALSE);
1108 }
1109 
1110 #ifdef SQLITE_STORAGE_ENABLED
imdn_notifications_with_lime(void)1111 static void imdn_notifications_with_lime(void) {
1112 	_imdn_notifications(TRUE);
1113 }
1114 
im_notification_policy_with_lime(void)1115 static void im_notification_policy_with_lime(void) {
1116 	_im_notification_policy(TRUE);
1117 }
1118 #endif
1119 
_im_error_delivery_notification(bool_t online)1120 static void _im_error_delivery_notification(bool_t online) {
1121 	LinphoneChatRoom *chat_room;
1122 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1123 	LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_tcp_rc");
1124 	LinphoneChatMessage *msg;
1125 	LinphoneChatMessageCbs *cbs;
1126 	int dummy = 0;
1127 	void *zrtp_cache_db_holder=NULL;
1128 
1129 	if (!linphone_core_lime_available(marie->lc)) {
1130 		ms_warning("Lime not available, skiping");
1131 		goto end;
1132 	}
1133 
1134 	/* Make sure lime is enabled */
1135 	if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
1136 
1137 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
1138 
1139 	linphone_chat_room_send_message(chat_room, "Bla bla bla bla");
1140 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
1141 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceivedLegacy, 1));
1142 	BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message);
1143 	if (marie->stat.last_received_chat_message) {
1144 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla bla bla");
1145 	}
1146 
1147 	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc, pauline->identity));
1148 
1149 	/* Temporary disabling receiver cache and enable all IM notifications */
1150 	zrtp_cache_db_holder = marie->lc->zrtp_cache_db;
1151 	marie->lc->zrtp_cache_db = NULL;
1152 	linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc));
1153 	linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc));
1154 
1155 	msg = linphone_chat_room_create_message(chat_room, "Happy new year!");
1156 	linphone_chat_message_ref(msg);
1157 	cbs = linphone_chat_message_get_callbacks(msg);
1158 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
1159 	linphone_chat_room_send_chat_message(chat_room, msg);
1160 	if (!online) {
1161 		linphone_core_set_network_reachable(marie->lc, FALSE);
1162 		BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDelivered, 1, 60000));
1163 		linphone_core_set_network_reachable(marie->lc, TRUE);
1164 		BC_ASSERT_TRUE (wait_for(marie->lc, marie->lc, &marie->stat.number_of_LinphoneRegistrationOk, 2));
1165 		wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */
1166 	}
1167 	wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */
1168 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceived, 1, int, "%d"); /* Check the new message is not considered as received */
1169 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageNotDelivered, 1));
1170 
1171 	/* Restore the ZID cache of the receiver and resend the chat message */
1172 	marie->lc->zrtp_cache_db = zrtp_cache_db_holder;
1173 	linphone_chat_message_ref(msg);
1174 	linphone_chat_message_resend(msg);
1175 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2)); /* Check the new message is now received */
1176 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1));
1177 	linphone_chat_message_unref(msg);
1178 
1179 end:
1180 	linphone_core_manager_destroy(marie);
1181 	linphone_core_manager_destroy(pauline);
1182 	remove("tmpZIDCacheMarie.sqlite");
1183 	remove("tmpZIDCachePauline.sqlite");
1184 }
1185 
im_error_delivery_notification_online(void)1186 static void im_error_delivery_notification_online(void) {
1187 	_im_error_delivery_notification(TRUE);
1188 }
1189 
im_error_delivery_notification_offline(void)1190 static void im_error_delivery_notification_offline(void) {
1191 	_im_error_delivery_notification(FALSE);
1192 }
1193 
1194 #ifdef SQLITE_STORAGE_ENABLED
lime_text_message(void)1195 static void lime_text_message(void) {
1196 	LinphoneChatRoom* chat_room;
1197 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1198 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
1199 
1200 	if (!linphone_core_lime_available(marie->lc)) {
1201 		ms_warning("Lime not available, skiping");
1202 		goto end;
1203 	}
1204 
1205 	if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
1206 
1207 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
1208 
1209 	linphone_chat_room_send_message(chat_room,"Bla bla bla bla");
1210 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
1211 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,1));
1212 	BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message);
1213 	if (marie->stat.last_received_chat_message) {
1214 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla bla bla");
1215 	}
1216 
1217 	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
1218 end:
1219 	remove("tmpZIDCacheMarie.sqlite");
1220 	remove("tmpZIDCachePauline.sqlite");
1221 	linphone_core_manager_destroy(marie);
1222 	linphone_core_manager_destroy(pauline);
1223 }
1224 
lime_text_message_to_non_lime(bool_t sender_policy_mandatory,bool_t lime_key_available)1225 static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t lime_key_available) {
1226 	LinphoneChatRoom* chat_room;
1227 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1228 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
1229 
1230 	if (!linphone_core_lime_available(marie->lc)) {
1231 		ms_warning("Lime not available, skiping");
1232 		goto end;
1233 	}
1234 	/* make sure lime is enabled */
1235 	linphone_core_enable_lime(marie->lc, LinphoneLimeDisabled);
1236 	linphone_core_enable_lime(pauline->lc, sender_policy_mandatory ? LinphoneLimeMandatory : LinphoneLimePreferred);
1237 
1238 	if (lime_key_available) {
1239 		/* enable lime for both parts */
1240 		if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
1241 		/* but then disable marie */
1242 		sqlite3_close(marie->lc->zrtp_cache_db);
1243 		marie->lc->zrtp_cache_db = NULL;
1244 	}
1245 
1246 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
1247 
1248 	linphone_chat_room_send_message(chat_room,"Bla bla bla bla");
1249 	//since we cannot decrypt message, we should not receive any message
1250 	if (sender_policy_mandatory || lime_key_available) {
1251 		int chat_room_size = 0;
1252 		BC_ASSERT_FALSE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
1253 		BC_ASSERT_FALSE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));
1254 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy, 0, int, "%d");
1255 		chat_room_size = linphone_chat_room_get_history_size(chat_room);
1256 		BC_ASSERT_EQUAL(chat_room_size, 1, int, "%d");
1257 		if (chat_room_size == 1) {
1258 			bctbx_list_t *history = linphone_chat_room_get_history(chat_room, 0);
1259 			LinphoneChatMessage *sent_msg = (LinphoneChatMessage *)bctbx_list_get_data(history);
1260 			if (lime_key_available) {
1261 				BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateDelivered, int, "%d");
1262 			} else {
1263 				BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateNotDelivered, int, "%d");
1264 			}
1265 			bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref);
1266 		}
1267 	} else {
1268 		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
1269 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy, 1, int, "%d");
1270 	}
1271 
1272 	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
1273 end:
1274 	remove("tmpZIDCachePauline.sqlite");
1275 	linphone_core_manager_destroy(marie);
1276 	linphone_core_manager_destroy(pauline);
1277 }
1278 
lime_text_message_to_non_lime_mandatory_policy(void)1279 static void lime_text_message_to_non_lime_mandatory_policy(void) {
1280 	lime_text_message_to_non_lime(TRUE, TRUE);
1281 }
1282 
lime_text_message_to_non_lime_preferred_policy(void)1283 static void lime_text_message_to_non_lime_preferred_policy(void) {
1284 	lime_text_message_to_non_lime(FALSE, TRUE);
1285 }
1286 
lime_text_message_to_non_lime_preferred_policy_2(void)1287 static void lime_text_message_to_non_lime_preferred_policy_2(void) {
1288 	lime_text_message_to_non_lime(FALSE, FALSE);
1289 }
1290 
lime_text_message_without_cache(void)1291 static void lime_text_message_without_cache(void) {
1292 	lime_text_message_to_non_lime(TRUE, FALSE);
1293 }
1294 
lime_multiple_messages_while_network_unreachable(void)1295 static void lime_multiple_messages_while_network_unreachable(void) {
1296 	LinphoneChatRoom* chat_room;
1297 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1298 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
1299 
1300 	if (!linphone_core_lime_available(marie->lc)) {
1301 		ms_warning("Lime not available, skiping");
1302 		goto end;
1303 	}
1304 
1305 	if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
1306 
1307 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
1308 
1309 	linphone_core_set_network_reachable(pauline->lc, FALSE);
1310 	linphone_chat_room_send_message(chat_room,"Bla bla 1");
1311 	linphone_chat_room_send_message(chat_room,"Bla bla 2");
1312 	linphone_core_set_network_reachable(pauline->lc, TRUE);
1313 
1314 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,2));
1315 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,2));
1316 	BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message);
1317 	if (marie->stat.last_received_chat_message) {
1318 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla 2");
1319 	}
1320 
1321 	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
1322 end:
1323 	remove("tmpZIDCacheMarie.sqlite");
1324 	remove("tmpZIDCachePauline.sqlite");
1325 	linphone_core_manager_destroy(marie);
1326 	linphone_core_manager_destroy(pauline);
1327 }
1328 
lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_stored_msg,bool_t use_file_body_handler_in_upload,bool_t use_file_body_handler_in_download)1329 void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_stored_msg, bool_t use_file_body_handler_in_upload, bool_t use_file_body_handler_in_download) {
1330 	LinphoneCoreManager *marie, *pauline;
1331 	LinphoneChatMessage *msg;
1332 	LinphoneChatMessageCbs *cbs;
1333 	char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv");
1334 	char *receive_filepath = bc_tester_file("receive_file.dump");
1335 	MSList * msg_list = NULL;
1336 
1337 	/* Remove any previously downloaded file */
1338 	remove(receive_filepath);
1339 
1340 	marie = linphone_core_manager_new( "marie_rc");
1341 	pauline = linphone_core_manager_new( "pauline_tcp_rc");
1342 
1343 	if (!linphone_core_lime_available(marie->lc)) {
1344 		ms_warning("Lime not available, skiping");
1345 		goto end;
1346 	}
1347 	/* make sure lime is enabled */
1348 	enable_lime_for_message_test(marie, pauline);
1349 
1350 	if (!encrypt_file) {
1351 		LpConfig *pauline_lp = linphone_core_get_config(pauline->lc);
1352 		lp_config_set_int(pauline_lp, "sip", "lime_for_file_sharing", 0);
1353 	}
1354 	/* Globally configure an http file transfer server. */
1355 	linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php");
1356 
1357 	/* create a file transfer msg */
1358 	if (use_file_body_handler_in_upload) {
1359 		msg = create_file_transfer_message_from_sintel_trailer(linphone_core_get_chat_room(pauline->lc, marie->identity));
1360 	} else {
1361 		msg = create_message_from_sintel_trailer(linphone_core_get_chat_room(pauline->lc, marie->identity));
1362 	}
1363 
1364 	linphone_chat_room_send_chat_message(msg->chat_room, msg);
1365 	BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000));
1366 	if (marie->stat.last_received_chat_message ) {
1367 		LinphoneChatMessage *recv_msg;
1368 		const LinphoneContent* content;
1369 		if (download_file_from_stored_msg) {
1370 			LinphoneChatRoom *marie_room = linphone_core_get_chat_room(marie->lc, pauline->identity);
1371 			msg_list = linphone_chat_room_get_history(marie_room,1);
1372 			BC_ASSERT_PTR_NOT_NULL(msg_list);
1373 			if (!msg_list)  goto end;
1374 			recv_msg = (LinphoneChatMessage *)msg_list->data;
1375 		} else {
1376 			recv_msg = marie->stat.last_received_chat_message;
1377 		}
1378 		cbs = linphone_chat_message_get_callbacks(recv_msg);
1379 		linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
1380 		linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received);
1381 		linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
1382 		content = linphone_chat_message_get_file_transfer_information(recv_msg);
1383 		if (!content) goto end;
1384 		if (encrypt_file)
1385 			BC_ASSERT_PTR_NOT_NULL(linphone_content_get_key(content));
1386 		else
1387 			BC_ASSERT_PTR_NULL(linphone_content_get_key(content));
1388 
1389 		if (use_file_body_handler_in_download) {
1390 			linphone_chat_message_set_file_transfer_filepath(recv_msg, receive_filepath);
1391 		}
1392 		linphone_chat_message_download_file(recv_msg);
1393 
1394 		if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1,55000))) {
1395 			compare_files(send_filepath, receive_filepath);
1396 		}
1397 		bctbx_list_free_with_data(msg_list, (bctbx_list_free_func)linphone_chat_message_unref);
1398 	}
1399 
1400 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); // file transfer
1401 	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
1402 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1, int, "%d");
1403 end:
1404 	remove("tmpZIDCacheMarie.sqlite");
1405 	remove("tmpZIDCachePauline.sqlite");
1406 	remove(receive_filepath);
1407 	bc_free(send_filepath);
1408 	bc_free(receive_filepath);
1409 	linphone_core_manager_destroy(marie);
1410 	linphone_core_manager_destroy(pauline);
1411 }
1412 
lime_transfer_message(void)1413 static  void lime_transfer_message(void) {
1414 	lime_transfer_message_base(TRUE, FALSE, FALSE, FALSE);
1415 }
1416 
lime_transfer_message_2(void)1417 static  void lime_transfer_message_2(void) {
1418 	lime_transfer_message_base(TRUE, FALSE, TRUE, FALSE);
1419 }
1420 
lime_transfer_message_3(void)1421 static  void lime_transfer_message_3(void) {
1422 	lime_transfer_message_base(TRUE, FALSE, FALSE, TRUE);
1423 }
1424 
lime_transfer_message_4(void)1425 static  void lime_transfer_message_4(void) {
1426 	lime_transfer_message_base(TRUE, FALSE, TRUE, TRUE);
1427 }
1428 
lime_transfer_message_from_history(void)1429 static  void lime_transfer_message_from_history(void) {
1430 	lime_transfer_message_base(TRUE, TRUE, FALSE, FALSE);
1431 }
1432 
lime_transfer_message_without_encryption(void)1433 static  void lime_transfer_message_without_encryption(void) {
1434 	lime_transfer_message_base(FALSE, FALSE, FALSE, FALSE);
1435 }
1436 
lime_transfer_message_without_encryption_2(void)1437 static  void lime_transfer_message_without_encryption_2(void) {
1438 	lime_transfer_message_base(FALSE, FALSE, TRUE, FALSE);
1439 }
1440 
lime_cache_migration(void)1441 static void lime_cache_migration(void) {
1442 	if (lime_is_available()) {
1443 		char *xmlCache_filepath = bc_tester_file("tmp_zidCacheMigration");
1444 		FILE *xmlCacheFD = NULL;
1445 		/* create the temporary cache xml file, it will be turned to sqlite */
1446 		if ((xmlCacheFD = fopen(xmlCache_filepath, "w") ) == NULL) {
1447 			BC_ASSERT_PTR_NOT_NULL(xmlCacheFD);
1448 			ms_error("Unable to create temporary XML ZID cache file to test cache migration");
1449 			return;
1450 		}
1451 		fprintf(xmlCacheFD, "%s", xmlCacheMigration);
1452 		fclose(xmlCacheFD);
1453 
1454 		LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1455 
1456 		if (!linphone_core_lime_available(marie->lc)) {
1457 			ms_warning("Lime not available, skiping");
1458 			return;
1459 		}
1460 
1461 		/* make sure lime is enabled */
1462 		linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory);
1463 
1464 		/* make sure to trigger the cache migration function */
1465 		lp_config_set_int(marie->lc->config, "sip", "zrtp_cache_migration_done", FALSE);
1466 
1467 		/* set the cache path, it will trigger the migration function */
1468 		linphone_core_set_zrtp_secrets_file(marie->lc, xmlCache_filepath);
1469 
1470 		/* perform checks on the new cache, simple check is ok as deeper ones are performed in the bzrtp migration tester */
1471 		/* TODO */
1472 
1473 		/* free memory */
1474 		linphone_core_manager_destroy(marie);
1475 		remove(xmlCache_filepath);
1476 	}
1477 }
1478 
lime_unit(void)1479 static void lime_unit(void) {
1480 	if (lime_is_available()) {
1481 		LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1482 		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
1483 
1484 		BC_ASSERT_EQUAL(enable_lime_for_message_test(marie, pauline), 0, int, "%d");
1485 
1486 		linphone_core_manager_destroy(marie);
1487 		linphone_core_manager_destroy(pauline);
1488 		/* TODO: perform more elaborate testing */
1489 	}
1490 }
1491 
1492 /*
1493  * Copy file "from" to file "to".
1494  * Destination file is truncated if existing.
1495  * Return 0 on success, positive value on error.
1496  */
message_tester_copy_file(const char * from,const char * to)1497 int message_tester_copy_file(const char *from, const char *to)
1498 {
1499 	FILE *in, *out;
1500 	char buf[256];
1501 	size_t n;
1502 
1503 	/* Open "from" file for reading */
1504 	in=fopen(from, "rb");
1505 	if ( in == NULL )
1506 	{
1507 		ms_error("Can't open %s for reading: %s\n",from,strerror(errno));
1508 		return 1;
1509 	}
1510 
1511 	/* Open "to" file for writing (will truncate existing files) */
1512 	out=fopen(to, "wb");
1513 	if ( out == NULL )
1514 	{
1515 		ms_error("Can't open %s for writing: %s\n",to,strerror(errno));
1516 		fclose(in);
1517 		return 2;
1518 	}
1519 
1520 	/* Copy data from "in" to "out" */
1521 	while ( (n=fread(buf, sizeof(char), sizeof(buf), in)) > 0 )
1522 	{
1523 		if ( ! fwrite(buf, 1, n, out) )
1524 		{
1525 			ms_error("Could not write in %s: %s\n",to,strerror(errno));
1526 			fclose(in);
1527 			fclose(out);
1528 			return 3;
1529 		}
1530 	}
1531 
1532 	fclose(in);
1533 	fclose(out);
1534 
1535 	return 0;
1536 }
1537 
check_no_strange_time(void * data,int argc,char ** argv,char ** cNames)1538 int check_no_strange_time(void* data,int argc, char** argv,char** cNames) {
1539 	BC_ASSERT_EQUAL(argc, 1, int, "%d");
1540 	BC_ASSERT_STRING_EQUAL(cNames[0], "COUNT(*)"); // count of non updated messages should be 0
1541 	BC_ASSERT_STRING_EQUAL(argv[0], "0"); // count of non updated messages should be 0
1542 	return 0;
1543 }
1544 
history_message_count_helper(LinphoneChatRoom * chatroom,int x,int y,unsigned int expected)1545 void history_message_count_helper(LinphoneChatRoom* chatroom, int x, int y, unsigned int expected ){
1546 	bctbx_list_t* messages = linphone_chat_room_get_history_range(chatroom, x, y);
1547 	BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), expected, unsigned int, "%u");
1548 	bctbx_list_free_with_data(messages, (void (*)(void *))linphone_chat_message_unref);
1549 }
1550 
database_migration(void)1551 static void database_migration(void) {
1552 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1553 	char *src_db = bc_tester_res("messages.db");
1554 	char *tmp_db  = bc_tester_file("tmp.db");
1555 	const bctbx_list_t* chatrooms;
1556 	LinphoneChatRoom *cr;
1557 
1558 	BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d");
1559 
1560 	// enable to test the performances of the migration step
1561 	//linphone_core_message_storage_set_debug(marie->lc, TRUE);
1562 
1563 	// the messages.db has 10000 dummy messages with the very first DB scheme.
1564 	// This will test the migration procedure
1565 	linphone_core_set_chat_database_path(marie->lc, tmp_db);
1566 	BC_ASSERT_PTR_NOT_NULL(marie->lc->db);
1567 	if (!marie->lc->db) goto end;
1568 
1569 	chatrooms = linphone_core_get_chat_rooms(marie->lc);
1570 	BC_ASSERT(bctbx_list_size(chatrooms) > 0);
1571 
1572 	// check that all messages have been migrated to the UTC time storage
1573 	BC_ASSERT(sqlite3_exec(marie->lc->db, "SELECT COUNT(*) FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK);
1574 
1575 	// check that the read messages (field read=1) has been migrated to the LinphoneChatMessageStateDisplayed state
1576 	cr = linphone_core_get_chat_room_from_uri(marie->lc, "sip:Marielle@sip.linphone.org");
1577 	BC_ASSERT_EQUAL(linphone_chat_room_get_unread_messages_count(cr), 8, int, "%i");
1578 
1579 end:
1580 	linphone_core_manager_destroy(marie);
1581 	remove(tmp_db);
1582 	bc_free(src_db);
1583 	bc_free(tmp_db);
1584 }
1585 
history_range(void)1586 static void history_range(void){
1587 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1588 	LinphoneAddress *jehan_addr = linphone_address_new("<sip:Jehan@sip.linphone.org>");
1589 	LinphoneChatRoom *chatroom;
1590 	char *src_db = bc_tester_res("messages.db");
1591 	char *tmp_db  = bc_tester_file("tmp.db");
1592 
1593 	BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d");
1594 
1595 	linphone_core_set_chat_database_path(marie->lc, tmp_db);
1596 	BC_ASSERT_PTR_NOT_NULL(marie->lc->db);
1597 	if (!marie->lc->db) goto end;
1598 
1599 	chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr);
1600 	BC_ASSERT_PTR_NOT_NULL(chatroom);
1601 	if (chatroom){
1602 		// We have 20 tests to perform to fully qualify the function, here they are:
1603 		history_message_count_helper(chatroom, 0, 0, 1);
1604 		history_message_count_helper(chatroom, -1, 0, 1);
1605 		history_message_count_helper(chatroom, 0, -1, 1270);
1606 		history_message_count_helper(chatroom, 1, 3, 3);
1607 		history_message_count_helper(chatroom, 3, 1, 1270-3);
1608 		history_message_count_helper(chatroom, 10, 10, 1);
1609 		history_message_count_helper(chatroom, -1, -1, 1270);
1610 		history_message_count_helper(chatroom, -1, -2, 1270);
1611 		history_message_count_helper(chatroom, -2, -1, 1270);
1612 		history_message_count_helper(chatroom, 3, -1, 1270-3);
1613 		history_message_count_helper(chatroom, 1, -3, 1270-1);
1614 		history_message_count_helper(chatroom, 2, -2, 1270-2);
1615 		history_message_count_helper(chatroom, 2, 0, 1270-2);
1616 		history_message_count_helper(chatroom, 0, 2, 3);
1617 		history_message_count_helper(chatroom, -1, 3, 4);
1618 		history_message_count_helper(chatroom, -2, 2, 3);
1619 		history_message_count_helper(chatroom, -3, 1, 2);
1620 	}
1621 
1622 end:
1623 	linphone_core_manager_destroy(marie);
1624 	linphone_address_unref(jehan_addr);
1625 	remove(tmp_db);
1626 	bc_free(src_db);
1627 	bc_free(tmp_db);
1628 }
1629 
history_count(void)1630 static void history_count(void) {
1631 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1632 	LinphoneAddress *jehan_addr = linphone_address_new("<sip:Jehan@sip.linphone.org>");
1633 	LinphoneChatRoom *chatroom;
1634 	bctbx_list_t *messages;
1635 	char *src_db = bc_tester_res("messages.db");
1636 	char *tmp_db  = bc_tester_file("tmp.db");
1637 
1638 	BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d");
1639 
1640 	linphone_core_set_chat_database_path(marie->lc, tmp_db);
1641 	BC_ASSERT_PTR_NOT_NULL(marie->lc->db);
1642 	if (!marie->lc->db) goto end;
1643 
1644 	chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr);
1645 	BC_ASSERT_PTR_NOT_NULL(chatroom);
1646 	if (chatroom){
1647 		messages=linphone_chat_room_get_history(chatroom,10);
1648 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 10, unsigned int, "%u");
1649 		bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
1650 
1651 		messages=linphone_chat_room_get_history(chatroom,1);
1652 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1, unsigned int, "%u");
1653 		bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
1654 
1655 		messages=linphone_chat_room_get_history(chatroom,0);
1656 		BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(chatroom), 1270, int, "%d");
1657 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1270, unsigned int, "%u");
1658 
1659 		/*check the second most recent msg*/
1660 		BC_ASSERT_PTR_NOT_NULL(messages);
1661 		if (messages){
1662 			BC_ASSERT_PTR_NOT_NULL(messages->next->data);
1663 			if (messages->next->data){
1664 				BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->next->data), "Fore and aft follow each other.");
1665 			}
1666 		}
1667 
1668 		bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
1669 
1670 		/*test offset+limit: retrieve the 42th latest msg only and check its content*/
1671 		messages=linphone_chat_room_get_history_range(chatroom, 42, 42);
1672 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1, unsigned int, "%u");
1673 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->data), "If you open yourself to the Tao is intangible and evasive, yet prefers to keep us at the mercy of the kingdom, then all of the streams of hundreds of valleys because of its limitless possibilities.");
1674 		bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
1675 
1676 		/*test offset without limit*/
1677 		messages = linphone_chat_room_get_history_range(chatroom, 1265, -1);
1678 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1270-1265, unsigned int, "%u");
1679 		bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
1680 
1681 		/*test limit without offset*/
1682 		messages = linphone_chat_room_get_history_range(chatroom, 0, 5);
1683 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 6, unsigned int, "%u");
1684 		bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
1685 
1686 		/*test invalid start*/
1687 		messages = linphone_chat_room_get_history_range(chatroom, 1265, 1260);
1688 		BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1270-1265, unsigned int, "%u");
1689 		bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
1690 	}
1691 
1692 end:
1693 	linphone_core_manager_destroy(marie);
1694 	linphone_address_unref(jehan_addr);
1695 	remove(tmp_db);
1696 	bc_free(src_db);
1697 	bc_free(tmp_db);
1698 }
1699 
1700 
crash_during_file_transfer(void)1701 void crash_during_file_transfer(void) {
1702 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1703 	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
1704 	char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv");
1705 	char *initial_db  = bc_tester_file("initial.db");
1706 	char *saved_db  = bc_tester_file("saved.db");
1707 	LinphoneChatRoom *chat_room;
1708 	LinphoneChatMessage *msg;
1709 	int chat_room_size = 0;
1710 	bctbx_list_t *msg_list = NULL;
1711 
1712 	/* Remove any previous files */
1713 	remove(initial_db);
1714 	remove(saved_db);
1715 
1716 	/* Globally configure an http file transfer server. */
1717 	linphone_core_set_file_transfer_server(pauline->lc, "https://www.linphone.org:444/lft.php");
1718 	linphone_core_set_chat_database_path(pauline->lc, initial_db);
1719 
1720 	/* Create a chatroom and a file transfer message on pauline's side */
1721 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
1722 	msg = create_file_transfer_message_from_sintel_trailer(chat_room);
1723 	linphone_chat_room_send_chat_message(chat_room, msg);
1724 
1725 	/* Wait for 25% of the file to be uploaded and crash by stopping the iteration, saving the chat database and destroying the core */
1726 	BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.progress_of_LinphoneFileTransfer, 25, 60000));
1727 	BC_ASSERT_EQUAL(message_tester_copy_file(initial_db, saved_db), 0, int, "%d");
1728 	linphone_chat_message_unref(msg);
1729 	linphone_core_manager_destroy(pauline);
1730 
1731 	/* Create a new core and check that the message stored in the saved database is in the not delivered state */
1732 	pauline = linphone_core_manager_new("pauline_tcp_rc");
1733 	linphone_core_set_chat_database_path(pauline->lc, saved_db);
1734 	BC_ASSERT_TRUE(wait_for(pauline->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1));
1735 
1736 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
1737 	chat_room_size = linphone_chat_room_get_history_size(chat_room);
1738 	BC_ASSERT_EQUAL(chat_room_size, 1, int, "%d");
1739 	if (chat_room_size == 1) {
1740 		msg_list = linphone_chat_room_get_history(chat_room, 0);
1741 		LinphoneChatMessage *sent_msg = (LinphoneChatMessage *)bctbx_list_get_data(msg_list);
1742 		BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateNotDelivered, int, "%d");
1743 	}
1744 
1745 	bctbx_list_free_with_data(msg_list, (bctbx_list_free_func)linphone_chat_message_unref);
1746 	bc_free(send_filepath);
1747 	bc_free(initial_db);
1748 	bc_free(saved_db);
1749 
1750 	linphone_core_manager_destroy(pauline);
1751 	linphone_core_manager_destroy(marie);
1752 }
1753 
1754 #endif /* SQLITE_STORAGE_ENABLED */
1755 
text_status_after_destroying_chat_room(void)1756 static void text_status_after_destroying_chat_room(void) {
1757 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1758 	LinphoneChatRoom *chatroom = linphone_core_get_chat_room_from_uri(marie->lc, "<sip:Jehan@sip.linphone.org>");
1759 	LinphoneChatMessage *msg = linphone_chat_room_create_message(chatroom, "hello");
1760 	linphone_chat_room_send_chat_message(chatroom, msg);
1761 	linphone_core_delete_chat_room(marie->lc, chatroom);
1762 	//since message is orphan, we do not expect to be notified of state change
1763 	BC_ASSERT_FALSE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 1000));
1764 	linphone_core_manager_destroy(marie);
1765 }
1766 
1767 
file_transfer_not_sent_if_invalid_url(void)1768 static void file_transfer_not_sent_if_invalid_url(void) {
1769 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1770 	LinphoneChatRoom *chatroom = linphone_core_get_chat_room_from_uri(marie->lc, "<sip:Jehan@sip.linphone.org>");
1771 	LinphoneChatMessage *msg = create_message_from_sintel_trailer(chatroom);
1772 	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
1773 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
1774 	linphone_core_set_file_transfer_server(marie->lc, "INVALID URL");
1775 	linphone_chat_room_send_chat_message(chatroom, msg);
1776 	BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 1000));
1777 	linphone_core_manager_destroy(marie);
1778 }
1779 
file_transfer_io_error_base(char * server_url,bool_t destroy_room)1780 void file_transfer_io_error_base(char *server_url, bool_t destroy_room) {
1781 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
1782 	LinphoneChatRoom *chatroom = linphone_core_get_chat_room_from_uri(marie->lc, "<sip:Jehan@sip.linphone.org>");
1783 	LinphoneChatMessage *msg = create_message_from_sintel_trailer(chatroom);
1784 	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
1785 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
1786 	linphone_core_set_file_transfer_server(marie->lc, server_url);
1787 	linphone_chat_room_send_chat_message(chatroom, msg);
1788 	BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageInProgress, 1, 1000));
1789 	if (destroy_room) {
1790 		//since message is orphan, we do not expect to be notified of state change
1791 		linphone_core_delete_chat_room(marie->lc, chatroom);
1792 		BC_ASSERT_FALSE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 1000));
1793 	} else {
1794 		BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 3000));
1795 	}
1796 	linphone_core_manager_destroy(marie);
1797 }
1798 
file_transfer_not_sent_if_host_not_found(void)1799 static void file_transfer_not_sent_if_host_not_found(void) {
1800 	file_transfer_io_error_base("https://not-existing-url.com", FALSE);
1801 }
1802 
file_transfer_not_sent_if_url_moved_permanently(void)1803 static void file_transfer_not_sent_if_url_moved_permanently(void) {
1804 	file_transfer_io_error_base("http://linphone.org/toto.php", FALSE);
1805 }
1806 
file_transfer_io_error_after_destroying_chatroom(void)1807 static void file_transfer_io_error_after_destroying_chatroom(void) {
1808 	file_transfer_io_error_base("https://www.linphone.org:444/lft.php", TRUE);
1809 }
1810 
real_time_text(bool_t audio_stream_enabled,bool_t srtp_enabled,bool_t mess_with_marie_payload_number,bool_t mess_with_pauline_payload_number,bool_t ice_enabled,bool_t sql_storage,bool_t do_not_store_rtt_messages_in_sql_storage)1811 static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, bool_t mess_with_marie_payload_number, bool_t mess_with_pauline_payload_number,
1812 						   bool_t ice_enabled, bool_t sql_storage, bool_t do_not_store_rtt_messages_in_sql_storage) {
1813 	LinphoneChatRoom *pauline_chat_room;
1814 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1815 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
1816 	LinphoneCallParams *marie_params = NULL;
1817 	LinphoneCall *pauline_call, *marie_call;
1818 	char *marie_db  = bc_tester_file("marie.db");
1819 	char *pauline_db  = bc_tester_file("pauline.db");
1820 
1821 	if (sql_storage) {
1822 		linphone_core_set_chat_database_path(marie->lc, marie_db);
1823 		linphone_core_set_chat_database_path(pauline->lc, pauline_db);
1824 #ifdef SQLITE_STORAGE_ENABLED
1825 		BC_ASSERT_PTR_NOT_NULL(marie->lc->db);
1826 		BC_ASSERT_PTR_NOT_NULL(pauline->lc->db);
1827 #endif
1828 
1829 		if (do_not_store_rtt_messages_in_sql_storage) {
1830 			lp_config_set_int(marie->lc->config, "misc", "store_rtt_messages", 0);
1831 			lp_config_set_int(pauline->lc->config, "misc", "store_rtt_messages", 0);
1832 		}
1833 	}
1834 
1835 	if (mess_with_marie_payload_number) {
1836 		bctbx_list_t *elem;
1837 		for (elem = marie->lc->codecs_conf.text_codecs; elem != NULL; elem = elem->next) {
1838 			PayloadType *pt = (PayloadType*)elem->data;
1839 			if (strcasecmp(pt->mime_type, payload_type_t140.mime_type) == 0) {
1840 				payload_type_set_number(pt, 99);
1841 				break;
1842 			}
1843 		}
1844 	} else if (mess_with_pauline_payload_number) {
1845 		bctbx_list_t *elem;
1846 		for (elem = pauline->lc->codecs_conf.text_codecs; elem != NULL; elem = elem->next) {
1847 			PayloadType *pt = (PayloadType*)elem->data;
1848 			if (strcasecmp(pt->mime_type, payload_type_t140.mime_type) == 0) {
1849 				payload_type_set_number(pt, 99);
1850 				break;
1851 			}
1852 		}
1853 	}
1854 
1855 	if (ice_enabled) {
1856 		linphone_core_set_firewall_policy(marie->lc, LinphonePolicyUseIce);
1857 		linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce);
1858 	}
1859 
1860 	if (srtp_enabled) {
1861 		if (!ms_srtp_supported()) {
1862 			ms_warning("test skipped, missing srtp support");
1863 			goto srtp_end;
1864 		}
1865 		BC_ASSERT_TRUE(linphone_core_media_encryption_supported(marie->lc, LinphoneMediaEncryptionSRTP));
1866 		linphone_core_set_media_encryption(marie->lc, LinphoneMediaEncryptionSRTP);
1867 		linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionSRTP);
1868 		linphone_core_set_media_encryption_mandatory(marie->lc, TRUE);
1869 		linphone_core_set_media_encryption_mandatory(pauline->lc, TRUE);
1870 	}
1871 
1872 	marie_params = linphone_core_create_call_params(marie->lc, NULL);
1873 	linphone_call_params_enable_realtime_text(marie_params,TRUE);
1874 	if (!audio_stream_enabled) {
1875 		linphone_call_params_enable_audio(marie_params,FALSE);
1876 		linphone_core_set_nortp_timeout(marie->lc, 5);
1877 		linphone_core_set_nortp_timeout(pauline->lc, 5);
1878 	}
1879 
1880 	BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params));
1881 	pauline_call = linphone_core_get_current_call(pauline->lc);
1882 	marie_call = linphone_core_get_current_call(marie->lc);
1883 	if (pauline_call) {
1884 		BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call)));
1885 		if (audio_stream_enabled) {
1886 			BC_ASSERT_TRUE(linphone_call_params_audio_enabled(linphone_call_get_current_params(pauline_call)));
1887 		}
1888 
1889 		pauline_chat_room = linphone_call_get_chat_room(pauline_call);
1890 		BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
1891 		if (pauline_chat_room) {
1892 			const char* message = "Be l3l";
1893 			size_t i;
1894 			LinphoneChatMessage* rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL);
1895 			LinphoneChatRoom *marie_chat_room = linphone_call_get_chat_room(marie_call);
1896 
1897 			for (i = 0; i < strlen(message); i++) {
1898 				BC_ASSERT_FALSE(linphone_chat_message_put_char(rtt_message, message[i]));
1899 				BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000));
1900 				BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], char, "%c");
1901 			}
1902 			linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message);
1903 			BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
1904 
1905 			if (sql_storage) {
1906 				bctbx_list_t *marie_messages = linphone_chat_room_get_history(marie_chat_room, 0);
1907 				bctbx_list_t *pauline_messages = linphone_chat_room_get_history(pauline_chat_room, 0);
1908 				LinphoneChatMessage *marie_msg = NULL;
1909 				LinphoneChatMessage *pauline_msg = NULL;
1910 				if (do_not_store_rtt_messages_in_sql_storage) {
1911 					BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(marie_messages), 0, unsigned int , "%u");
1912 					BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(pauline_messages), 0, unsigned int , "%u");
1913 				} else {
1914 					BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(marie_messages), 1, unsigned int , "%u");
1915 					BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(pauline_messages), 1, unsigned int , "%u");
1916 					if (!marie_messages || !pauline_messages) {
1917 						goto end;
1918 					}
1919 					marie_msg = (LinphoneChatMessage *)marie_messages->data;
1920 					pauline_msg = (LinphoneChatMessage *)pauline_messages->data;
1921 					BC_ASSERT_STRING_EQUAL(marie_msg->message, message);
1922 					BC_ASSERT_STRING_EQUAL(pauline_msg->message, message);
1923 					bctbx_list_free_with_data(marie_messages, (void (*)(void *))linphone_chat_message_unref);
1924 					bctbx_list_free_with_data(pauline_messages, (void (*)(void *))linphone_chat_message_unref);
1925 				}
1926 			}
1927 		}
1928 
1929 		if (!audio_stream_enabled) {
1930 			int dummy = 0;
1931 			wait_for_until(pauline->lc, marie->lc, &dummy, 1, 7000); /* Wait to see if call is dropped after the nortp_timeout */
1932 			BC_ASSERT_FALSE(marie->stat.number_of_LinphoneCallEnd > 0);
1933 			BC_ASSERT_FALSE(pauline->stat.number_of_LinphoneCallEnd > 0);
1934 		}
1935 
1936 		if (ice_enabled) {
1937 			BC_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
1938 		}
1939 
1940 end:
1941 		end_call(marie, pauline);
1942 	}
1943 	linphone_call_params_unref(marie_params);
1944 srtp_end:
1945 	linphone_core_manager_destroy(marie);
1946 	linphone_core_manager_destroy(pauline);
1947 	remove(marie_db);
1948 	bc_free(marie_db);
1949 	remove(pauline_db);
1950 	bc_free(pauline_db);
1951 }
1952 
real_time_text_message(void)1953 static void real_time_text_message(void) {
1954 	real_time_text(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
1955 }
1956 
real_time_text_sql_storage(void)1957 static void real_time_text_sql_storage(void) {
1958 	real_time_text(TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE);
1959 }
1960 
real_time_text_sql_storage_rtt_disabled(void)1961 static void real_time_text_sql_storage_rtt_disabled(void) {
1962 	real_time_text(TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
1963 }
1964 
real_time_text_conversation(void)1965 static void real_time_text_conversation(void) {
1966 	LinphoneChatRoom *pauline_chat_room, *marie_chat_room;
1967 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
1968 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
1969 	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
1970 	LinphoneCall *pauline_call, *marie_call;
1971 	linphone_call_params_enable_realtime_text(marie_params,TRUE);
1972 
1973 	BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params));
1974 	pauline_call=linphone_core_get_current_call(pauline->lc);
1975 	marie_call=linphone_core_get_current_call(marie->lc);
1976 	BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call)));
1977 
1978 	pauline_chat_room = linphone_call_get_chat_room(pauline_call);
1979 	BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
1980 	marie_chat_room = linphone_call_get_chat_room(marie_call);
1981 	BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
1982 	if (pauline_chat_room && marie_chat_room) {
1983 		const char* message1_1 = "Lorem";
1984 		const char* message1_2 = "Ipsum";
1985 		const char* message2_1 = "Be lle Com";
1986 		const char* message2_2 = "eB ell moC";
1987 		size_t i;
1988 		LinphoneChatMessage* pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL);
1989 		LinphoneChatMessage* marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL);
1990 
1991 		for (i = 0; i < strlen(message1_1); i++) {
1992 			linphone_chat_message_put_char(pauline_rtt_message, message1_1[i]);
1993 			BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000));
1994 			BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message1_1[i], char, "%c");
1995 
1996 			linphone_chat_message_put_char(marie_rtt_message, message1_2[i]);
1997 			BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000));
1998 			BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message1_2[i], char, "%c");
1999 		}
2000 
2001 		/*Commit the message, triggers a NEW LINE in T.140 */
2002 		linphone_chat_room_send_chat_message(pauline_chat_room, pauline_rtt_message);
2003 		linphone_chat_room_send_chat_message(marie_chat_room, marie_rtt_message);
2004 
2005 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
2006 		{
2007 			LinphoneChatMessage * msg = marie->stat.last_received_chat_message;
2008 			BC_ASSERT_PTR_NOT_NULL(msg);
2009 			if (msg) {
2010 				BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_1);
2011 			}
2012 		}
2013 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1));
2014 		{
2015 			LinphoneChatMessage * msg = pauline->stat.last_received_chat_message;
2016 			BC_ASSERT_PTR_NOT_NULL(msg);
2017 			if (msg) {
2018 				BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_2);
2019 			}
2020 		}
2021 
2022 		reset_counters(&pauline->stat);
2023 		reset_counters(&marie->stat);
2024 		pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL);
2025 		marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL);
2026 
2027 		for (i = 0; i < strlen(message2_1); i++) {
2028 			linphone_chat_message_put_char(pauline_rtt_message, message2_1[i]);
2029 			BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000));
2030 			BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message2_1[i], char, "%c");
2031 
2032 			linphone_chat_message_put_char(marie_rtt_message, message2_2[i]);
2033 			BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000));
2034 			BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message2_2[i], char, "%c");
2035 		}
2036 
2037 		/*Commit the message, triggers a NEW LINE in T.140 */
2038 		linphone_chat_room_send_chat_message(pauline_chat_room, pauline_rtt_message);
2039 		linphone_chat_room_send_chat_message(marie_chat_room, marie_rtt_message);
2040 
2041 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
2042 		{
2043 			LinphoneChatMessage * msg = marie->stat.last_received_chat_message;
2044 			BC_ASSERT_PTR_NOT_NULL(msg);
2045 			if (msg) {
2046 				BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_1);
2047 			}
2048 		}
2049 		BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1));
2050 		{
2051 			LinphoneChatMessage * msg = pauline->stat.last_received_chat_message;
2052 			BC_ASSERT_PTR_NOT_NULL(msg);
2053 			if (msg) {
2054 				BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_2);
2055 			}
2056 		}
2057 	}
2058 	end_call(marie, pauline);
2059 	linphone_call_params_unref(marie_params);
2060 	linphone_core_manager_destroy(marie);
2061 	linphone_core_manager_destroy(pauline);
2062 }
2063 
real_time_text_without_audio(void)2064 static void real_time_text_without_audio(void) {
2065 	real_time_text(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
2066 }
2067 
real_time_text_srtp(void)2068 static void real_time_text_srtp(void) {
2069 	real_time_text(TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE);
2070 }
2071 
real_time_text_ice(void)2072 static void real_time_text_ice(void) {
2073 	real_time_text(TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
2074 }
2075 
real_time_text_message_compat(bool_t end_with_crlf,bool_t end_with_lf)2076 static void real_time_text_message_compat(bool_t end_with_crlf, bool_t end_with_lf) {
2077 	LinphoneChatRoom *pauline_chat_room;
2078 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
2079 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
2080 	LinphoneCallParams *marie_params = NULL;
2081 	LinphoneCall *pauline_call, *marie_call;
2082 
2083 	marie_params = linphone_core_create_call_params(marie->lc, NULL);
2084 	linphone_call_params_enable_realtime_text(marie_params,TRUE);
2085 
2086 	BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params));
2087 	pauline_call=linphone_core_get_current_call(pauline->lc);
2088 	marie_call=linphone_core_get_current_call(marie->lc);
2089 	if (pauline_call) {
2090 		BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call)));
2091 
2092 		pauline_chat_room = linphone_call_get_chat_room(pauline_call);
2093 		BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
2094 		if (pauline_chat_room) {
2095 			const char* message = "Be l3l";
2096 			size_t i;
2097 			LinphoneChatMessage* rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL);
2098 			LinphoneChatRoom *marie_chat_room = linphone_call_get_chat_room(marie_call);
2099 			uint32_t crlf = 0x0D0A;
2100 			uint32_t lf = 0x0A;
2101 
2102 			for (i = 0; i < strlen(message); i++) {
2103 				linphone_chat_message_put_char(rtt_message, message[i]);
2104 				BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000));
2105 				BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], char, "%c");
2106 			}
2107 
2108 			if (end_with_crlf) {
2109 				linphone_chat_message_put_char(rtt_message, crlf);
2110 			} else if (end_with_lf) {
2111 				linphone_chat_message_put_char(rtt_message, lf);
2112 			}
2113 			BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)strlen(message), 1000));
2114 			BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
2115 			linphone_chat_message_unref(rtt_message);
2116 		}
2117 		end_call(marie, pauline);
2118 	}
2119 	linphone_call_params_unref(marie_params);
2120 	linphone_core_manager_destroy(marie);
2121 	linphone_core_manager_destroy(pauline);
2122 }
2123 
real_time_text_message_compat_crlf(void)2124 static void real_time_text_message_compat_crlf(void) {
2125 	real_time_text_message_compat(TRUE, FALSE);
2126 }
2127 
real_time_text_message_compat_lf(void)2128 static void real_time_text_message_compat_lf(void) {
2129 	real_time_text_message_compat(FALSE, TRUE);
2130 }
2131 
real_time_text_message_accented_chars(void)2132 static void real_time_text_message_accented_chars(void) {
2133 	LinphoneChatRoom *pauline_chat_room;
2134 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
2135 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
2136 	LinphoneCallParams *marie_params = NULL;
2137 	LinphoneCall *pauline_call, *marie_call;
2138 
2139 	marie_params = linphone_core_create_call_params(marie->lc, NULL);
2140 	linphone_call_params_enable_realtime_text(marie_params,TRUE);
2141 
2142 	BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params));
2143 	pauline_call=linphone_core_get_current_call(pauline->lc);
2144 	marie_call=linphone_core_get_current_call(marie->lc);
2145 	if (pauline_call) {
2146 		BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call)));
2147 
2148 		pauline_chat_room = linphone_call_get_chat_room(pauline_call);
2149 		BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
2150 		if (pauline_chat_room) {
2151 			LinphoneChatMessage* rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL);
2152 			LinphoneChatRoom *marie_chat_room = linphone_call_get_chat_room(marie_call);
2153 			int i;
2154 			uint32_t message[8];
2155 			int message_len = 8;
2156 
2157 			message[0] = 0xE3; // ã
2158 			message[1] = 0xE6; // æ
2159 			message[2] = 0xE7; // ç
2160 			message[3] = 0xE9; // é
2161 			message[4] = 0xEE; // î
2162 			message[5] = 0xF8; // ø
2163 			message[6] = 0xF9; // ù
2164 			message[7] = 0xFF; // ÿ
2165 			for (i = 0; i < message_len; i++) {
2166 				linphone_chat_message_put_char(rtt_message, message[i]);
2167 				BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, i+1, 1000));
2168 				BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], unsigned long, "%lu");
2169 			}
2170 
2171 			linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message);
2172 			BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
2173 			BC_ASSERT_EQUAL(strcmp(marie->stat.last_received_chat_message->message, "ãæçéîøùÿ"), 0, int, "%i");
2174 		}
2175 		end_call(marie, pauline);
2176 	}
2177 	linphone_call_params_unref(marie_params);
2178 	linphone_core_manager_destroy(marie);
2179 	linphone_core_manager_destroy(pauline);
2180 }
2181 
real_time_text_message_different_text_codecs_payload_numbers_sender_side(void)2182 static void real_time_text_message_different_text_codecs_payload_numbers_sender_side(void) {
2183 	real_time_text(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE);
2184 }
2185 
real_time_text_message_different_text_codecs_payload_numbers_receiver_side(void)2186 static void real_time_text_message_different_text_codecs_payload_numbers_receiver_side(void) {
2187 	real_time_text(FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE);
2188 }
2189 
real_time_text_copy_paste(void)2190 static void real_time_text_copy_paste(void) {
2191 	LinphoneChatRoom *pauline_chat_room;
2192 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
2193 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
2194 	LinphoneCallParams *marie_params = NULL;
2195 	LinphoneCall *pauline_call, *marie_call;
2196 
2197 	marie_params = linphone_core_create_call_params(marie->lc, NULL);
2198 	linphone_call_params_enable_realtime_text(marie_params,TRUE);
2199 
2200 	BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params));
2201 	pauline_call = linphone_core_get_current_call(pauline->lc);
2202 	marie_call = linphone_core_get_current_call(marie->lc);
2203 	if (pauline_call) {
2204 		BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call)));
2205 
2206 		pauline_chat_room = linphone_call_get_chat_room(pauline_call);
2207 		BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
2208 		if (pauline_chat_room) {
2209 			const char* message = "Be l3l";
2210 			size_t i;
2211 			LinphoneChatMessage* rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL);
2212 			LinphoneChatRoom *marie_chat_room = linphone_call_get_chat_room(marie_call);
2213 
2214 			for (i = 1; i <= strlen(message); i++) {
2215 				linphone_chat_message_put_char(rtt_message, message[i-1]);
2216 				if (i % 4 == 0) {
2217 					int j;
2218 					BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i, 1000));
2219 					for (j = 4; j > 0; j--) {
2220 						BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i-j], char, "%c");
2221 					}
2222 				}
2223 			}
2224 			linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message);
2225 			BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
2226 		}
2227 
2228 		end_call(marie, pauline);
2229 	}
2230 	linphone_call_params_unref(marie_params);
2231 	linphone_core_manager_destroy(marie);
2232 	linphone_core_manager_destroy(pauline);
2233 }
2234 
file_transfer_with_http_proxy(void)2235 void file_transfer_with_http_proxy(void) {
2236 	if (transport_supported(LinphoneTransportTls)) {
2237 		LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
2238 		LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
2239 		linphone_core_set_http_proxy_host(marie->lc, "sip.linphone.org");
2240 		transfer_message_base2(marie,pauline,FALSE,FALSE,FALSE,FALSE,FALSE);
2241 		linphone_core_manager_destroy(pauline);
2242 		linphone_core_manager_destroy(marie);
2243 	}
2244 }
2245 
chat_message_custom_headers(void)2246 void chat_message_custom_headers(void) {
2247 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
2248 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
2249 	LinphoneChatRoom* chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
2250 	LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room, "Lorem Ipsum");
2251 	LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg);
2252 
2253 	linphone_chat_message_add_custom_header(msg, "Test1", "Value1");
2254 	linphone_chat_message_add_custom_header(msg, "Test2", "Value2");
2255 	linphone_chat_message_remove_custom_header(msg, "Test1");
2256 
2257 	linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed);
2258 	linphone_chat_room_send_chat_message(chat_room,msg);
2259 
2260 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
2261 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1));
2262 
2263 	if (marie->stat.last_received_chat_message) {
2264 		const char *header = linphone_chat_message_get_custom_header(marie->stat.last_received_chat_message, "Test2");
2265 		BC_ASSERT_STRING_EQUAL(header, "Value2");
2266 		header = linphone_chat_message_get_custom_header(marie->stat.last_received_chat_message, "Test1");
2267 		BC_ASSERT_PTR_NULL(header);
2268 		BC_ASSERT_STRING_EQUAL(marie->stat.last_received_chat_message->message, "Lorem Ipsum");
2269 	}
2270 
2271 	linphone_core_manager_destroy(marie);
2272 	linphone_core_manager_destroy(pauline);
2273 }
2274 
_text_message_with_custom_content_type(bool_t with_lime)2275 void _text_message_with_custom_content_type(bool_t with_lime) {
2276 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
2277 	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
2278 	LinphoneChatRoom *chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
2279 	LinphoneChatMessage *msg;
2280 	LinphoneChatMessageCbs *cbs;
2281 	bctbx_vfs_t *vfs = bctbx_vfs_get_default();
2282 	char *send_filepath;
2283 	bctbx_vfs_file_t *file_to_send;
2284 	size_t file_size;
2285 	char *buf;
2286 
2287 	if (with_lime) {
2288 		if (enable_lime_for_message_test(marie, pauline) < 0) goto end;
2289 	}
2290 
2291 	send_filepath = bc_tester_res("images/linphone.svg");
2292 	file_to_send = bctbx_file_open(vfs, send_filepath, "r");
2293 	file_size = (size_t)bctbx_file_size(file_to_send);
2294 	buf = bctbx_malloc(file_size + 1);
2295 	bctbx_file_read(file_to_send, buf, file_size, 0);
2296 	buf[file_size] = '\0';
2297 	bctbx_file_close(file_to_send);
2298 	bc_free(send_filepath);
2299 	msg = linphone_chat_room_create_message(chat_room, buf);
2300 	linphone_chat_message_set_content_type(msg, "image/svg+xml");
2301 
2302 	linphone_core_add_content_type_support(marie->lc, "image/svg+xml");
2303 	linphone_core_add_content_type_support(pauline->lc, "image/svg+xml");
2304 	cbs = linphone_chat_message_get_callbacks(msg);
2305 	linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed);
2306 	linphone_chat_room_send_chat_message(chat_room, msg);
2307 
2308 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
2309 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDelivered, 1));
2310 
2311 	if (marie->stat.last_received_chat_message) {
2312 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(marie->stat.last_received_chat_message), "image/svg+xml");
2313 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), buf);
2314 	}
2315 
2316 	bctbx_free(buf);
2317 
2318 end:
2319 	linphone_core_manager_destroy(marie);
2320 	linphone_core_manager_destroy(pauline);
2321 	remove("tmpZIDCacheMarie.sqlite");
2322 	remove("tmpZIDCachePauline.sqlite");
2323 }
2324 
text_message_with_custom_content_type(void)2325 void text_message_with_custom_content_type(void) {
2326 	_text_message_with_custom_content_type(FALSE);
2327 }
2328 
text_message_with_custom_content_type_and_lime(void)2329 void text_message_with_custom_content_type_and_lime(void) {
2330 	_text_message_with_custom_content_type(TRUE);
2331 }
2332 
2333 
im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine * engine,LinphoneChatRoom * room,LinphoneChatMessage * msg)2334 static int im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
2335 	if (linphone_chat_message_get_content_type(msg)) {
2336 		if (strcmp(linphone_chat_message_get_content_type(msg), "cipher/b64") == 0) {
2337 			size_t b64Size = 0;
2338 			unsigned char *output;
2339 			bctbx_base64_decode(NULL, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg)));
2340 			output = (unsigned char *)ms_malloc(b64Size+1),
2341 			bctbx_base64_decode(output, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg)));
2342 			output[b64Size] = '\0';
2343 			linphone_chat_message_set_text(msg, (char *)output);
2344 			ms_free(output);
2345 			linphone_chat_message_set_content_type(msg, "text/plain");
2346 			return 0;
2347 		} else if (strcmp(linphone_chat_message_get_content_type(msg), "text/plain") == 0) {
2348 			return -1; // Not encrypted, nothing to do
2349 		} else {
2350 			return 488; // Not acceptable
2351 		}
2352 	}
2353 	return 500;
2354 }
2355 
im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEngine * engine,LinphoneChatRoom * room,LinphoneChatMessage * msg)2356 static int im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
2357 	if (strcmp(linphone_chat_message_get_content_type(msg),"text/plain") == 0) {
2358 		size_t b64Size = 0;
2359 		unsigned char *output;
2360 		bctbx_base64_encode(NULL, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg)));
2361 		output = (unsigned char *)ms_malloc0(b64Size+1),
2362 		bctbx_base64_encode(output, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg)));
2363 		output[b64Size] = '\0';
2364 		linphone_chat_message_set_text(msg,(const char*)output);
2365 		ms_free(output);
2366 		linphone_chat_message_set_content_type(msg, "cipher/b64");
2367 		return 0;
2368 	}
2369 	return -1;
2370 }
2371 
im_encryption_engine_b64(void)2372 void im_encryption_engine_b64(void) {
2373 	LinphoneChatMessage *chat_msg = NULL;
2374 	LinphoneChatRoom* chat_room = NULL;
2375 	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
2376 	LinphoneImEncryptionEngine *marie_imee = linphone_im_encryption_engine_new();
2377 	LinphoneImEncryptionEngineCbs *marie_cbs = linphone_im_encryption_engine_get_callbacks(marie_imee);
2378 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
2379 	LinphoneImEncryptionEngine *pauline_imee = linphone_im_encryption_engine_new();
2380 	LinphoneImEncryptionEngineCbs *pauline_cbs = linphone_im_encryption_engine_get_callbacks(pauline_imee);
2381 
2382 	linphone_im_encryption_engine_cbs_set_process_incoming_message(marie_cbs, im_encryption_engine_process_incoming_message_cb);
2383 	linphone_im_encryption_engine_cbs_set_process_outgoing_message(marie_cbs, im_encryption_engine_process_outgoing_message_cb);
2384 	linphone_im_encryption_engine_cbs_set_process_incoming_message(pauline_cbs, im_encryption_engine_process_incoming_message_cb);
2385 	linphone_im_encryption_engine_cbs_set_process_outgoing_message(pauline_cbs, im_encryption_engine_process_outgoing_message_cb);
2386 
2387 	linphone_core_set_im_encryption_engine(marie->lc, marie_imee);
2388 	linphone_core_set_im_encryption_engine(pauline->lc, pauline_imee);
2389 
2390 	chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity);
2391 	chat_msg = linphone_chat_room_create_message(chat_room, "Bla bla bla bla");
2392 	linphone_chat_room_send_chat_message(chat_room, chat_msg);
2393 	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1));
2394 	BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message);
2395 	if (marie->stat.last_received_chat_message) {
2396 		BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla bla bla");
2397 	}
2398 	BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity));
2399 
2400 	linphone_im_encryption_engine_unref(marie_imee);
2401 	linphone_im_encryption_engine_unref(pauline_imee);
2402 	linphone_core_manager_destroy(marie);
2403 	linphone_core_manager_destroy(pauline);
2404 }
2405 
2406 test_t message_tests[] = {
2407 	TEST_NO_TAG("Text message", text_message),
2408 	TEST_NO_TAG("Text message within call dialog", text_message_within_call_dialog),
2409 	TEST_NO_TAG("Text message with credentials from auth callback", text_message_with_credential_from_auth_callback),
2410 	TEST_NO_TAG("Text message with privacy", text_message_with_privacy),
2411 	TEST_NO_TAG("Text message compatibility mode", text_message_compatibility_mode),
2412 	TEST_NO_TAG("Text message with ack", text_message_with_ack),
2413 	TEST_NO_TAG("Text message with send error", text_message_with_send_error),
2414 	TEST_NO_TAG("Text message with external body", text_message_with_external_body),
2415 	TEST_NO_TAG("Transfer message", transfer_message),
2416 	TEST_NO_TAG("Transfer message 2", transfer_message_2),
2417 	TEST_NO_TAG("Transfer message 3", transfer_message_3),
2418 	TEST_NO_TAG("Transfer message 4", transfer_message_4),
2419 	TEST_NO_TAG("Transfer message from history", transfer_message_from_history),
2420 	TEST_NO_TAG("Transfer message with http proxy", file_transfer_with_http_proxy),
2421 	TEST_NO_TAG("Transfer message with upload io error", transfer_message_with_upload_io_error),
2422 	TEST_NO_TAG("Transfer message with download io error", transfer_message_with_download_io_error),
2423 	TEST_NO_TAG("Transfer message upload cancelled", transfer_message_upload_cancelled),
2424 	TEST_NO_TAG("Transfer message download cancelled", transfer_message_download_cancelled),
2425 	TEST_ONE_TAG("Transfer message using external body url", file_transfer_using_external_body_url, "LeaksMemory"),
2426 	TEST_NO_TAG("Transfer 2 messages simultaneously", file_transfer_2_messages_simultaneously),
2427 	TEST_NO_TAG("Text message denied", text_message_denied),
2428 	TEST_NO_TAG("Info message", info_message),
2429 	TEST_NO_TAG("Info message with body", info_message_with_body),
2430 	TEST_NO_TAG("IsComposing notification", is_composing_notification),
2431 	TEST_NO_TAG("IMDN notifications", imdn_notifications),
2432 	TEST_NO_TAG("IM notification policy", im_notification_policy),
2433 #ifdef SQLITE_STORAGE_ENABLED
2434 	TEST_ONE_TAG("IsComposing notification lime", is_composing_notification_with_lime, "LIME"),
2435 	TEST_ONE_TAG("IMDN notifications with lime", imdn_notifications_with_lime, "LIME"),
2436 	TEST_ONE_TAG("IM notification policy with lime", im_notification_policy_with_lime, "LIME"),
2437 	TEST_ONE_TAG("IM error delivery notification online", im_error_delivery_notification_online, "LIME"),
2438 	TEST_ONE_TAG("IM error delivery notification offline", im_error_delivery_notification_offline, "LIME"),
2439 	TEST_ONE_TAG("Lime text message", lime_text_message, "LIME"),
2440 	TEST_ONE_TAG("Lime text message to non lime", lime_text_message_to_non_lime_mandatory_policy, "LIME"),
2441 	TEST_ONE_TAG("Lime text message to non lime with preferred policy", lime_text_message_to_non_lime_preferred_policy, "LIME"),
2442 	TEST_ONE_TAG("Lime text message to non lime with preferred policy 2", lime_text_message_to_non_lime_preferred_policy_2, "LIME"),
2443 	TEST_ONE_TAG("Lime text message without cache", lime_text_message_without_cache, "LIME"),
2444 	TEST_ONE_TAG("Lime multiple messages while network wasn't reachable", lime_multiple_messages_while_network_unreachable, "LIME"),
2445 	TEST_ONE_TAG("Lime transfer message", lime_transfer_message, "LIME"),
2446 	TEST_ONE_TAG("Lime transfer message 2", lime_transfer_message_2, "LIME"),
2447 	TEST_ONE_TAG("Lime transfer message 3", lime_transfer_message_3, "LIME"),
2448 	TEST_ONE_TAG("Lime transfer message 4", lime_transfer_message_4, "LIME"),
2449 	TEST_ONE_TAG("Lime transfer message from history", lime_transfer_message_from_history, "LIME"),
2450 	TEST_ONE_TAG("Lime transfer message without encryption", lime_transfer_message_without_encryption, "LIME"),
2451 	TEST_ONE_TAG("Lime transfer message without encryption 2", lime_transfer_message_without_encryption_2, "LIME"),
2452 	TEST_ONE_TAG("Lime cache migration", lime_cache_migration, "LIME"),
2453 	TEST_ONE_TAG("Lime unitary", lime_unit, "LIME"),
2454 	TEST_NO_TAG("Database migration", database_migration),
2455 	TEST_NO_TAG("History range", history_range),
2456 	TEST_NO_TAG("History count", history_count),
2457 	TEST_NO_TAG("Crash during file transfer", crash_during_file_transfer),
2458 #endif
2459 	TEST_NO_TAG("Text status after destroying chat room", text_status_after_destroying_chat_room),
2460 	TEST_NO_TAG("Transfer not sent if invalid url", file_transfer_not_sent_if_invalid_url),
2461 	TEST_NO_TAG("Transfer not sent if host not found", file_transfer_not_sent_if_host_not_found),
2462 	TEST_NO_TAG("Transfer not sent if url moved permanently", file_transfer_not_sent_if_url_moved_permanently),
2463 	TEST_ONE_TAG("Transfer io error after destroying chatroom", file_transfer_io_error_after_destroying_chatroom, "LeaksMemory"),
2464 	TEST_ONE_TAG("Real Time Text message", real_time_text_message, "RTT"),
2465 	TEST_ONE_TAG("Real Time Text SQL storage", real_time_text_sql_storage, "RTT"),
2466 	TEST_ONE_TAG("Real Time Text SQL storage with RTT messages not stored", real_time_text_sql_storage_rtt_disabled, "RTT"),
2467 	TEST_ONE_TAG("Real Time Text conversation", real_time_text_conversation, "RTT"),
2468 	TEST_ONE_TAG("Real Time Text without audio", real_time_text_without_audio, "RTT"),
2469 	TEST_ONE_TAG("Real Time Text with srtp", real_time_text_srtp, "RTT"),
2470 	TEST_ONE_TAG("Real Time Text with ice", real_time_text_ice, "RTT"),
2471 	TEST_ONE_TAG("Real Time Text message compatibility crlf", real_time_text_message_compat_crlf, "RTT"),
2472 	TEST_ONE_TAG("Real Time Text message compatibility lf", real_time_text_message_compat_lf, "RTT"),
2473 	TEST_ONE_TAG("Real Time Text message with accented characters", real_time_text_message_accented_chars, "RTT"),
2474 	TEST_ONE_TAG("Real Time Text offer answer with different payload numbers (sender side)", real_time_text_message_different_text_codecs_payload_numbers_sender_side, "RTT"),
2475 	TEST_ONE_TAG("Real Time Text offer answer with different payload numbers (receiver side)", real_time_text_message_different_text_codecs_payload_numbers_receiver_side, "RTT"),
2476 	TEST_ONE_TAG("Real Time Text copy paste", real_time_text_copy_paste, "RTT"),
2477 	TEST_NO_TAG("IM Encryption Engine custom headers", chat_message_custom_headers),
2478 	TEST_NO_TAG("Text message with custom content-type", text_message_with_custom_content_type),
2479 #ifdef SQLITE_STORAGE_ENABLED
2480 	TEST_ONE_TAG("Text message with custom content-type and lime", text_message_with_custom_content_type_and_lime, "LIME"),
2481 #endif
2482 	TEST_NO_TAG("IM Encryption Engine b64", im_encryption_engine_b64)
2483 };
2484 
2485 test_suite_t message_test_suite = {
2486 	"Message",
2487 	NULL,
2488 	NULL,
2489 	liblinphone_tester_before_each,
2490 	liblinphone_tester_after_each,
2491 	sizeof(message_tests) / sizeof(message_tests[0]), message_tests
2492 };
2493 
2494 #if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
2495 #pragma GCC diagnostic pop
2496 #endif
2497