linphonecore.c 240 KB
Newer Older
aymeric's avatar
aymeric committed
1 2 3
/*
linphone
Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)
Simon Morlat's avatar
Simon Morlat committed
4
Copyright (C) 2010  Belledonne Communications SARL
aymeric's avatar
aymeric committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

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

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

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "linphonecore.h"
smorlat's avatar
smorlat committed
22
#include "sipsetup.h"
aymeric's avatar
aymeric committed
23 24
#include "lpconfig.h"
#include "private.h"
25
#include "quality_reporting.h"
26

Yann Diorcet's avatar
Yann Diorcet committed
27
#include <math.h>
28 29
#include <sys/types.h>
#include <sys/stat.h>
30
#include <ortp/telephonyevents.h>
31
#include <mediastreamer2/zrtp.h>
johan's avatar
johan committed
32
#include <mediastreamer2/dtls_srtp.h>
aymeric's avatar
aymeric committed
33
#include "mediastreamer2/mediastream.h"
34
#include "mediastreamer2/mseventqueue.h"
smorlat's avatar
smorlat committed
35
#include "mediastreamer2/msvolume.h"
36
#include "mediastreamer2/msequalizer.h"
37
#include "mediastreamer2/dtmfgen.h"
aymeric's avatar
aymeric committed
38

39
#ifdef INET6
aymeric's avatar
aymeric committed
40
#ifndef WIN32
41
#include <netdb.h>
aymeric's avatar
aymeric committed
42 43 44
#endif
#endif

45
#ifdef HAVE_CONFIG_H
46
#include "config.h"
47 48 49
#ifndef ANDROID /*on Android LIBLINPHONE version is passed from root Makefile*/
	#include "liblinphone_gitversion.h"
#endif
Ghislain MARY's avatar
Ghislain MARY committed
50 51 52
#else
#ifndef LIBLINPHONE_GIT_VERSION
#define LIBLINPHONE_GIT_VERSION "unknown"
53 54 55
#endif
#endif

56 57 58
#ifdef __APPLE__
#include "TargetConditionals.h"
#endif
59

60
#ifdef HAVE_ZLIB
Ghislain MARY's avatar
Ghislain MARY committed
61
#define COMPRESSED_LOG_COLLECTION_EXTENSION "gz"
62 63 64 65 66 67 68 69
#ifdef WIN32
#include <fcntl.h>
#include <io.h>
#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
#define SET_BINARY_MODE(file)
#endif
#include <zlib.h>
70
#else
Ghislain MARY's avatar
Ghislain MARY committed
71
#define COMPRESSED_LOG_COLLECTION_EXTENSION "txt"
72
#endif
Ghislain MARY's avatar
Ghislain MARY committed
73 74 75 76
#define LOG_COLLECTION_DEFAULT_PATH "."
#define LOG_COLLECTION_DEFAULT_PREFIX "linphone"
#define LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE (10 * 1024 * 1024)

77

smorlat's avatar
smorlat committed
78
/*#define UNSTANDART_GSM_11K 1*/
aymeric's avatar
aymeric committed
79

80 81
#define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem"

82 83 84 85 86 87 88
static const char *liblinphone_version=
#ifdef LIBLINPHONE_GIT_VERSION
	LIBLINPHONE_GIT_VERSION
#else
	LIBLINPHONE_VERSION
#endif
;
89
static OrtpLogFunc liblinphone_log_func = NULL;
Ghislain MARY's avatar
Ghislain MARY committed
90
static LinphoneLogCollectionState liblinphone_log_collection_state = LinphoneLogCollectionDisabled;
91
static char * liblinphone_log_collection_path = NULL;
Ghislain MARY's avatar
Ghislain MARY committed
92 93
static char * liblinphone_log_collection_prefix = NULL;
static int liblinphone_log_collection_max_file_size = LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE;
94
static ortp_mutex_t liblinphone_log_collection_mutex;
95
static bool_t liblinphone_serialize_logs = FALSE;
96
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
Simon Morlat's avatar
Simon Morlat committed
97 98
static void linphone_core_run_hooks(LinphoneCore *lc);
static void linphone_core_free_hooks(LinphoneCore *lc);
aymeric's avatar
aymeric committed
99 100

#include "enum.h"
101
#include "contact_providers_priv.h"
102

103

104
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
aymeric's avatar
aymeric committed
105 106
static void toggle_video_preview(LinphoneCore *lc, bool_t val);

107
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
108
#define SOUNDS_PREFIX
109 110
#else
#define SOUNDS_PREFIX "Assets/Sounds/"
111
#endif
aymeric's avatar
aymeric committed
112
/* relative path where is stored local ring*/
113
#define LOCAL_RING SOUNDS_PREFIX "rings/oldphone.wav"
aymeric's avatar
aymeric committed
114
/* same for remote ring (ringback)*/
115 116
#define REMOTE_RING SOUNDS_PREFIX "ringback.wav"
#define HOLD_MUSIC SOUNDS_PREFIX "rings/toy-mono.wav"
117

aymeric's avatar
aymeric committed
118

Simon Morlat's avatar
Simon Morlat committed
119
extern SalCallbacks linphone_sal_callbacks;
aymeric's avatar
aymeric committed
120 121 122 123 124 125 126 127 128 129 130 131

void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud)
{
  obj->_func=func;
  obj->_user_data=ud;
}

int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){
	if (obj->_func!=NULL) obj->_func(lc,obj->_user_data);
	return 0;
}

132

133 134 135 136 137 138 139 140 141 142 143 144
/**
 * Returns TRUE if the LinphoneCall asked to autoanswer
 *
**/
bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){
	//return TRUE if the unique(for the moment) incoming call asked to be autoanswered
	if(call)
		return sal_call_autoanswer_asked(call->op);
	else
		return FALSE;
}

145 146
int linphone_core_get_current_call_duration(const LinphoneCore *lc){
	LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc);
147 148
	if (call)  return linphone_call_get_duration(call);
	return -1;
149 150 151 152
}

const LinphoneAddress *linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc){
	LinphoneCall *call=linphone_core_get_current_call(lc);
Simon Morlat's avatar
Simon Morlat committed
153
	if (call==NULL) return NULL;
154
	return linphone_call_get_remote_address(call);
smorlat's avatar
smorlat committed
155 156
}

jehan's avatar
jehan committed
157 158
static void linphone_core_log_collection_handler(OrtpLogLevel level, const char *fmt, va_list args);

159
void linphone_core_set_log_handler(OrtpLogFunc logfunc) {
160 161 162 163 164
	if (ortp_logv_out == linphone_core_log_collection_handler) {
		ms_message("There is already a log collection handler, keep it");
		liblinphone_log_func = logfunc;
	} else
		ortp_set_log_handler(logfunc);
165 166 167 168 169 170 171 172 173
}

void linphone_core_set_log_file(FILE *file) {
	if (file == NULL) file = stdout;
	ortp_set_log_file(file);
}

void linphone_core_set_log_level(OrtpLogLevel loglevel) {
	ortp_set_log_level_mask(loglevel);
174 175 176 177 178
	if (loglevel == 0) {
		sal_disable_logs();
	} else {
		sal_enable_logs();
	}
179 180
}

181 182 183 184 185 186 187
static void linphone_core_log_collection_handler(OrtpLogLevel level, const char *fmt, va_list args) {
	const char *lname="undef";
	char *msg;
	char *log_filename1;
	char *log_filename2;
	FILE *log_file;
	struct timeval tp;
188
	struct tm *lt;
189 190 191 192
	time_t tt;
	struct stat statbuf;

	if (liblinphone_log_func != NULL) {
193
#ifndef WIN32
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
194 195 196 197
		va_list args_copy;
		va_copy(args_copy, args);
		liblinphone_log_func(level, fmt, args_copy);
		va_end(args_copy);
198 199 200 201 202
#else
		/* This works on 32 bits, luckily. */
		/* TODO: va_copy is available in Visual Studio 2013. */
		liblinphone_log_func(level, fmt, args);
#endif
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	}

	ortp_gettimeofday(&tp, NULL);
	tt = (time_t)tp.tv_sec;
	lt = localtime((const time_t*)&tt);
	switch(level){
		case ORTP_DEBUG:
			lname = "DEBUG";
			break;
		case ORTP_MESSAGE:
			lname = "MESSAGE";
			break;
		case ORTP_WARNING:
			lname = "WARNING";
			break;
		case ORTP_ERROR:
			lname = "ERROR";
			break;
		case ORTP_FATAL:
			lname = "FATAL";
			break;
		default:
			ortp_fatal("Bad level !");
	}
	msg = ortp_strdup_vprintf(fmt, args);

Ghislain MARY's avatar
Ghislain MARY committed
229 230 231 232 233 234
	log_filename1 = ortp_strdup_printf("%s/%s1.log",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
	log_filename2 = ortp_strdup_printf("%s/%s2.log",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
235
	ortp_mutex_lock(&liblinphone_log_collection_mutex);
236 237
	log_file = fopen(log_filename1, "a");
	fstat(fileno(log_file), &statbuf);
Ghislain MARY's avatar
Ghislain MARY committed
238
	if (statbuf.st_size > liblinphone_log_collection_max_file_size) {
239 240 241
		fclose(log_file);
		log_file = fopen(log_filename2, "a");
		fstat(fileno(log_file), &statbuf);
Ghislain MARY's avatar
Ghislain MARY committed
242
		if (statbuf.st_size > liblinphone_log_collection_max_file_size) {
243 244 245 246 247 248 249 250 251 252
			fclose(log_file);
			unlink(log_filename1);
			rename(log_filename2, log_filename1);
			log_file = fopen(log_filename2, "a");
		}
	}
	fprintf(log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i %s %s\n",
		1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, (int)(tp.tv_usec / 1000), lname, msg);
	fflush(log_file);
	fclose(log_file);
253
	ortp_mutex_unlock(&liblinphone_log_collection_mutex);
254 255 256 257 258 259

	ortp_free(log_filename1);
	ortp_free(log_filename2);
	ortp_free(msg);
}

Ghislain MARY's avatar
Ghislain MARY committed
260 261 262 263 264 265 266
const char * linphone_core_get_log_collection_path(void) {
	if (liblinphone_log_collection_path != NULL) {
		return liblinphone_log_collection_path;
	}
	return LOG_COLLECTION_DEFAULT_PATH;
}

267
void linphone_core_set_log_collection_path(const char *path) {
268 269 270 271 272 273 274
	if (liblinphone_log_collection_path != NULL) {
		ms_free(liblinphone_log_collection_path);
		liblinphone_log_collection_path = NULL;
	}
	if (path != NULL) {
		liblinphone_log_collection_path = ms_strdup(path);
	}
275 276
}

Ghislain MARY's avatar
Ghislain MARY committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
const char * linphone_core_get_log_collection_prefix(void) {
	if (liblinphone_log_collection_prefix != NULL) {
		return liblinphone_log_collection_prefix;
	}
	return LOG_COLLECTION_DEFAULT_PREFIX;
}

void linphone_core_set_log_collection_prefix(const char *prefix) {
	if (liblinphone_log_collection_prefix != NULL) {
		ms_free(liblinphone_log_collection_prefix);
		liblinphone_log_collection_prefix = NULL;
	}
	if (prefix != NULL) {
		liblinphone_log_collection_prefix = ms_strdup(prefix);
	}
}

int linphone_core_get_log_collection_max_file_size(void) {
	return liblinphone_log_collection_max_file_size;
}

void linphone_core_set_log_collection_max_file_size(int size) {
	liblinphone_log_collection_max_file_size = size;
}

302 303 304 305 306 307 308 309
const char *linphone_core_get_log_collection_upload_server_url(LinphoneCore *core) {
	return lp_config_get_string(core->config, "misc", "log_collection_upload_server_url", NULL);
}

void linphone_core_set_log_collection_upload_server_url(LinphoneCore *core, const char *server_url) {
	lp_config_set_string(core->config, "misc", "log_collection_upload_server_url", server_url);
}

Ghislain MARY's avatar
Ghislain MARY committed
310 311 312 313
LinphoneLogCollectionState linphone_core_log_collection_enabled(void) {
	return liblinphone_log_collection_state;
}

314
void linphone_core_enable_log_collection(LinphoneLogCollectionState state) {
315 316
	if (liblinphone_log_collection_state == state) return;

317 318 319 320 321
	/* at first call of this function, set liblinphone_log_func to the current
	 * ortp log function */
	if( liblinphone_log_func == NULL ){
		liblinphone_log_func = ortp_logv_out;
	}
Ghislain MARY's avatar
Ghislain MARY committed
322 323
	liblinphone_log_collection_state = state;
	if (state != LinphoneLogCollectionDisabled) {
324
		ortp_mutex_init(&liblinphone_log_collection_mutex, NULL);
325 326 327 328 329
		if (state == LinphoneLogCollectionEnabledWithoutPreviousLogHandler) {
			liblinphone_log_func = NULL;
		} else {
			liblinphone_log_func = ortp_logv_out;
		}
330 331 332 333 334 335
		ortp_set_log_handler(linphone_core_log_collection_handler);
	} else {
		ortp_set_log_handler(liblinphone_log_func);
	}
}

jehan's avatar
jehan committed
336
static void clean_log_collection_upload_context(LinphoneCore *lc) {
Ghislain MARY's avatar
Ghislain MARY committed
337 338 339 340
	char *filename = ms_strdup_printf("%s/%s_log.%s",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
		COMPRESSED_LOG_COLLECTION_EXTENSION);
341
	unlink(filename);
342
	ms_free(filename);
jehan's avatar
jehan committed
343 344 345 346
	if (lc && lc->log_collection_upload_information) {
		ms_free(lc->log_collection_upload_information);
		lc->log_collection_upload_information=NULL;
	}
347 348
}

349 350 351 352
static void process_io_error_upload_log_collection(void *data, const belle_sip_io_error_event_t *event) {
	LinphoneCore *core = (LinphoneCore *)data;
	ms_error("I/O Error during log collection upload to %s", linphone_core_get_log_collection_upload_server_url(core));
	linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateNotDelivered, "I/O Error");
jehan's avatar
jehan committed
353
	clean_log_collection_upload_context(core);
354 355 356 357 358 359
}

static void process_auth_requested_upload_log_collection(void *data, belle_sip_auth_event_t *event) {
	LinphoneCore *core = (LinphoneCore *)data;
	ms_error("Error during log collection upload: auth requested to connect %s", linphone_core_get_log_collection_upload_server_url(core));
	linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateNotDelivered, "Auth requested");
jehan's avatar
jehan committed
360
	clean_log_collection_upload_context(core);
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
}

/**
 * Callback called when posting a log collection file to server (following rcs5.1 recommendation)
 *
 * @param[in] bh The body handler
 * @param[in] msg The belle sip message
 * @param[in] data The user data associated with the handler, contains the LinphoneCore object
 * @param[in] offset The current position in the input buffer
 * @param[in] buffer The ouput buffer where to copy the data to be uploaded
 * @param[in,out] size The size in byte of the data requested, as output it will contain the effective copied size
 *
 */
static int log_collection_upload_on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, uint8_t *buffer, size_t *size) {
	LinphoneCore *core = (LinphoneCore *)data;

	/* If we've not reach the end of file yet, fill the buffer with more data */
378
	if (offset < linphone_content_get_size(core->log_collection_upload_information)) {
Ghislain MARY's avatar
Ghislain MARY committed
379 380 381 382
		char *log_filename = ms_strdup_printf("%s/%s_log.%s",
			liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
			liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
			COMPRESSED_LOG_COLLECTION_EXTENSION);
383 384 385
#ifdef HAVE_ZLIB
		FILE *log_file = fopen(log_filename, "rb");
#else
386
		FILE *log_file = fopen(log_filename, "r");
387
#endif
388 389 390
		fseek(log_file, offset, SEEK_SET);
		*size = fread(buffer, 1, *size, log_file);
		fclose(log_file);
391
		ms_free(log_filename);
392 393 394 395 396 397 398 399 400 401 402
	}

	return BELLE_SIP_CONTINUE;
}

/**
 * Callback called during upload of a log collection to server.
 * It is just forwarding the call and some parameters to the vtable defined callback.
 */
static void log_collection_upload_on_progress(belle_sip_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, size_t total) {
	LinphoneCore *core = (LinphoneCore *)data;
403
	linphone_core_notify_log_collection_upload_progress_indication(core, offset, total);
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
}

/**
 * Callback function called when we have a response from server during the upload of the log collection to the server (rcs5.1 recommandation)
 * Note: The first post is empty and the server shall reply a 204 (No content) message, this will trigger a new post request to the server
 * to upload the file. The server response to this second post is processed by this same function
 *
 * @param[in] data The user-defined pointer associated with the request, it contains the LinphoneCore object
 * @param[in] event The response from server
 */
static void process_response_from_post_file_log_collection(void *data, const belle_http_response_event_t *event) {
	LinphoneCore *core = (LinphoneCore *)data;

	/* Check the answer code */
	if (event->response) {
		int code = belle_http_response_get_status_code(event->response);
		if (code == 204) { /* This is the reply to the first post to the server - an empty file */
			/* Start uploading the file */
			belle_http_request_listener_callbacks_t cbs = { 0 };
			belle_http_request_listener_t *l;
			belle_generic_uri_t *uri;
			belle_http_request_t *req;
			belle_sip_multipart_body_handler_t *bh;
			char* ua;
			char *first_part_header;
			belle_sip_user_body_handler_t *first_part_bh;

			linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateInProgress, NULL);

			/* Temporary storage for the Content-disposition header value */
434
			first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", linphone_content_get_name(core->log_collection_upload_information));
435 436

			/* Create a user body handler to take care of the file and add the content disposition and content-type headers */
437
			first_part_bh = belle_sip_user_body_handler_new(linphone_content_get_size(core->log_collection_upload_information), NULL, NULL, log_collection_upload_on_send_body, core);
438 439
			belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, belle_sip_header_create("Content-disposition", first_part_header));
			belle_sip_free(first_part_header);
440 441
			belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh,
				(belle_sip_header_t *)belle_sip_header_content_type_create(linphone_content_get_type(core->log_collection_upload_information), linphone_content_get_subtype(core->log_collection_upload_information)));
442 443 444 445 446

			/* Insert it in a multipart body handler which will manage the boundaries of multipart message */
			bh = belle_sip_multipart_body_handler_new(log_collection_upload_on_progress, core, (belle_sip_body_handler_t *)first_part_bh);
			ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
			uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core));
447
			req = belle_http_request_create("POST", uri, belle_sip_header_create("User-Agent", ua), NULL);
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
			ms_free(ua);
			belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(bh));
			cbs.process_response = process_response_from_post_file_log_collection;
			cbs.process_io_error = process_io_error_upload_log_collection;
			cbs.process_auth_requested = process_auth_requested_upload_log_collection;
			l = belle_http_request_listener_create_from_callbacks(&cbs, core);
			belle_http_provider_send_request(core->http_provider, req, l);
		}
		if (code == 200) { /* The file has been uploaded correctly, get the server reply */
			xmlDocPtr xmlMessageBody;
			xmlNodePtr cur;
			xmlChar *file_url = NULL;
			const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
			xmlMessageBody = xmlParseDoc((const xmlChar *)body);
			cur = xmlDocGetRootElement(xmlMessageBody);
			if (cur != NULL) {
				cur = cur->xmlChildrenNode;
				while (cur != NULL) {
					if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { /* we found a file info node, check it has a type="file" attribute */
						xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type");
						if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */
							cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */
							while (cur != NULL) {
								if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) {
									file_url = 	xmlGetProp(cur, (const xmlChar *)"url");
								}
								cur=cur->next;
							}
							xmlFree(typeAttribute);
							break;
						}
						xmlFree(typeAttribute);
					}
					cur = cur->next;
				}
			}
			if (file_url != NULL) {
				linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateDelivered, (const char *)file_url);
			}
jehan's avatar
jehan committed
487
			clean_log_collection_upload_context(core);
488 489 490 491
		}
	}
}

492
#ifdef HAVE_ZLIB
493 494 495
#define COMPRESS_FILE_PTR gzFile
#define COMPRESS_OPEN gzopen
#define COMPRESS_CLOSE gzclose
496
#else
497 498 499 500
#define COMPRESS_FILE_PTR FILE*
#define COMPRESS_OPEN fopen
#define COMPRESS_CLOSE fclose
#endif
501 502 503 504

/**
 * If zlib is not available the two log files are simply concatenated.
 */
505
static int compress_file(FILE *input_file, COMPRESS_FILE_PTR output_file) {
506
	char buffer[131072]; /* 128kB */
507
	int bytes;
508

Simon Morlat's avatar
Simon Morlat committed
509
	while ((bytes = fread(buffer, 1, sizeof(buffer), input_file)) > 0) {
510 511 512 513 514 515 516
		if (bytes < 0) return bytes;
#ifdef HAVE_ZLIB
		bytes = gzwrite(output_file, buffer, bytes);
#else
		bytes = fwrite(buffer, 1, bytes, output_file);
#endif
		if (bytes < 0) return bytes;
517
	}
518
	return 0;
519 520
}

521
static int prepare_log_collection_file_to_upload(const char *filename) {
522 523 524
	char *input_filename = NULL;
	char *output_filename = NULL;
	FILE *input_file = NULL;
525 526
	COMPRESS_FILE_PTR output_file = NULL;
	int ret = 0;
527

528
	ortp_mutex_lock(&liblinphone_log_collection_mutex);
Ghislain MARY's avatar
Ghislain MARY committed
529 530
	output_filename = ms_strdup_printf("%s/%s",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename);
531
	output_file = COMPRESS_OPEN(output_filename, "w");
532
	if (output_file == NULL) goto error;
Ghislain MARY's avatar
Ghislain MARY committed
533 534 535
	input_filename = ms_strdup_printf("%s/%s1.log",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
536 537 538 539 540
	input_file = fopen(input_filename, "r");
	if (input_file == NULL) goto error;
	ret = compress_file(input_file, output_file);
	if (ret < 0) goto error;
	fclose(input_file);
541
	ms_free(input_filename);
Ghislain MARY's avatar
Ghislain MARY committed
542 543 544
	input_filename = ms_strdup_printf("%s/%s2.log",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
545 546 547 548 549
	input_file = fopen(input_filename, "r");
	if (input_file != NULL) {
		ret = compress_file(input_file, output_file);
		if (ret < 0) goto error;
	}
550

551 552
error:
	if (input_file != NULL) fclose(input_file);
553
	if (output_file != NULL) COMPRESS_CLOSE(output_file);
554 555
	if (input_filename != NULL) ms_free(input_filename);
	if (output_filename != NULL) ms_free(output_filename);
556
	ortp_mutex_unlock(&liblinphone_log_collection_mutex);
557 558 559 560 561
	return ret;
}

static size_t get_size_of_file_to_upload(const char *filename) {
	struct stat statbuf;
Ghislain MARY's avatar
Ghislain MARY committed
562 563
	char *output_filename = ms_strdup_printf("%s/%s",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename);
564 565 566
	FILE *output_file = fopen(output_filename, "rb");
	fstat(fileno(output_file), &statbuf);
	fclose(output_file);
567
	ms_free(output_filename);
568
	return statbuf.st_size;
569 570
}

571
void linphone_core_upload_log_collection(LinphoneCore *core) {
Ghislain MARY's avatar
Ghislain MARY committed
572
	if ((core->log_collection_upload_information == NULL) && (linphone_core_get_log_collection_upload_server_url(core) != NULL) && (liblinphone_log_collection_state != LinphoneLogCollectionDisabled)) {
573 574 575 576 577
		/* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */
		belle_http_request_listener_callbacks_t cbs = { 0 };
		belle_http_request_listener_t *l;
		belle_generic_uri_t *uri;
		belle_http_request_t *req;
578
		char *name;
579 580 581

		core->log_collection_upload_information = (LinphoneContent *)malloc(sizeof(LinphoneContent));
		memset(core->log_collection_upload_information, 0, sizeof(LinphoneContent));
582
#ifdef HAVE_ZLIB
583 584
		linphone_content_set_type(core->log_collection_upload_information, "application");
		linphone_content_set_subtype(core->log_collection_upload_information, "gzip");
585
#else
586 587
		linphone_content_set_type(core->log_collection_upload_information, "text");
		linphone_content_set_subtype(core->log_collection_upload_information,"plain");
588
#endif
589
		name = ms_strdup_printf("%s_log.%s",
Ghislain MARY's avatar
Ghislain MARY committed
590 591
			liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
			COMPRESSED_LOG_COLLECTION_EXTENSION);
592 593 594
		linphone_content_set_name(core->log_collection_upload_information, name);
		if (prepare_log_collection_file_to_upload(name) < 0) return;
		linphone_content_set_size(core->log_collection_upload_information, get_size_of_file_to_upload(name));
595 596 597 598 599 600 601
		uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core));
		req = belle_http_request_create("POST", uri, NULL, NULL, NULL);
		cbs.process_response = process_response_from_post_file_log_collection;
		cbs.process_io_error = process_io_error_upload_log_collection;
		cbs.process_auth_requested = process_auth_requested_upload_log_collection;
		l = belle_http_request_listener_create_from_callbacks(&cbs, core);
		belle_http_provider_send_request(core->http_provider, req, l);
602
		ms_free(name);
603 604 605
	}
}

606
char * linphone_core_compress_log_collection() {
Ghislain MARY's avatar
Ghislain MARY committed
607 608 609 610 611 612 613 614 615 616 617 618 619 620
	char *filename = NULL;
	if (liblinphone_log_collection_state == LinphoneLogCollectionDisabled) return NULL;
	filename = ms_strdup_printf("%s_log.%s",
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
		COMPRESSED_LOG_COLLECTION_EXTENSION);
	if (prepare_log_collection_file_to_upload(filename) < 0) {
		ms_free(filename);
		return NULL;
	}
	ms_free(filename);
	return ms_strdup_printf("%s/%s_log.%s",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
		COMPRESSED_LOG_COLLECTION_EXTENSION);
621 622
}

623
void linphone_core_reset_log_collection() {
624 625
	char *filename;
	ortp_mutex_lock(&liblinphone_log_collection_mutex);
jehan's avatar
jehan committed
626
	clean_log_collection_upload_context(NULL);
Ghislain MARY's avatar
Ghislain MARY committed
627 628 629
	filename = ms_strdup_printf("%s/%s1.log",
			liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
			liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
630 631
	unlink(filename);
	ms_free(filename);
Ghislain MARY's avatar
Ghislain MARY committed
632 633 634
	filename = ms_strdup_printf("%s/%s2.log",
		liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
		liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
635 636 637 638 639
	unlink(filename);
	ms_free(filename);
	ortp_mutex_unlock(&liblinphone_log_collection_mutex);
}

640 641 642 643
/**
 * Enable logs in supplied FILE*.
 *
 * @ingroup misc
644
 * @deprecated Use #linphone_core_set_log_file and #linphone_core_set_log_level instead.
645 646
 *
 * @param file a C FILE* where to fprintf logs. If null stdout is used.
647
 *
648
**/
aymeric's avatar
aymeric committed
649 650 651 652
void linphone_core_enable_logs(FILE *file){
	if (file==NULL) file=stdout;
	ortp_set_log_file(file);
	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
jehan's avatar
jehan committed
653
	sal_enable_logs();
aymeric's avatar
aymeric committed
654 655
}

656 657 658 659
/**
 * Enable logs through the user's supplied log callback.
 *
 * @ingroup misc
660
 * @deprecated Use #linphone_core_set_log_handler and #linphone_core_set_log_level instead.
661 662 663
 *
 * @param logfunc The address of a OrtpLogFunc callback whose protoype is
 *            	  typedef void (*OrtpLogFunc)(OrtpLogLevel lev, const char *fmt, va_list args);
664
 *
665
**/
aymeric's avatar
aymeric committed
666 667
void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
668
	linphone_core_set_log_handler(logfunc);
jehan's avatar
jehan committed
669
	sal_enable_logs();
aymeric's avatar
aymeric committed
670 671
}

672 673 674 675
/**
 * Entirely disable logging.
 *
 * @ingroup misc
676
 * @deprecated Use #linphone_core_set_log_level instead.
677
**/
678
void linphone_core_disable_logs(void){
aymeric's avatar
aymeric committed
679
	ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL);
jehan's avatar
jehan committed
680
	sal_disable_logs();
aymeric's avatar
aymeric committed
681 682
}

683 684 685 686
void linphone_core_serialize_logs(void) {
	liblinphone_serialize_logs = TRUE;
}

aymeric's avatar
aymeric committed
687

688
static void net_config_read (LinphoneCore *lc)
aymeric's avatar
aymeric committed
689 690 691 692 693
{
	int tmp;
	const char *tmpstr;
	LpConfig *config=lc->config;

694
	lc->net_conf.nat_address_ip = NULL;
aymeric's avatar
aymeric committed
695 696 697 698 699 700 701 702 703 704
	tmp=lp_config_get_int(config,"net","download_bw",0);
	linphone_core_set_download_bandwidth(lc,tmp);
	tmp=lp_config_get_int(config,"net","upload_bw",0);
	linphone_core_set_upload_bandwidth(lc,tmp);
	linphone_core_set_stun_server(lc,lp_config_get_string(config,"net","stun_server",NULL));
	tmpstr=lp_config_get_string(lc->config,"net","nat_address",NULL);
	if (tmpstr!=NULL && (strlen(tmpstr)<1)) tmpstr=NULL;
	linphone_core_set_nat_address(lc,tmpstr);
	tmp=lp_config_get_int(lc->config,"net","nat_sdp_only",0);
	lc->net_conf.nat_sdp_only=tmp;
705
	tmp=lp_config_get_int(lc->config,"net","mtu",1300);
aymeric's avatar
aymeric committed
706
	linphone_core_set_mtu(lc,tmp);
707 708 709 710 711
	tmp=lp_config_get_int(lc->config,"net","download_ptime",-1);
	if (tmp !=-1 && linphone_core_get_download_ptime(lc) !=0) {
		/*legacy parameter*/
		linphone_core_set_download_ptime(lc,tmp);
	}
712 713
	tmp = lp_config_get_int(lc->config, "net", "dns_srv_enabled", 1);
	linphone_core_enable_dns_srv(lc, tmp);
714 715 716

	/* This is to filter out unsupported firewall policies */
	linphone_core_set_firewall_policy(lc, linphone_core_get_firewall_policy(lc));
aymeric's avatar
aymeric committed
717 718
}

719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
static void build_sound_devices_table(LinphoneCore *lc){
	const char **devices;
	const char **old;
	int ndev;
	int i;
	const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get());
	ndev=ms_list_size(elem);
	devices=ms_malloc((ndev+1)*sizeof(const char *));
	for (i=0;elem!=NULL;elem=elem->next,i++){
		devices[i]=ms_snd_card_get_string_id((MSSndCard *)elem->data);
	}
	devices[ndev]=NULL;
	old=lc->sound_conf.cards;
	lc->sound_conf.cards=devices;
	if (old!=NULL) ms_free(old);
}
aymeric's avatar
aymeric committed
735

736
static void sound_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
737
{
738
	int tmp;
aymeric's avatar
aymeric committed
739 740
	const char *tmpbuf;
	const char *devid;
741
#ifdef __linux
aymeric's avatar
aymeric committed
742 743 744
	/*alsadev let the user use custom alsa device within linphone*/
	devid=lp_config_get_string(lc->config,"sound","alsadev",NULL);
	if (devid){
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
		MSSndCard* card;
		const char* delim=",";
		size_t l=strlen(devid);
		char* d=malloc(l+1);
		char* i;
		memcpy(d,devid,l+1);
		for (l=0,i=strpbrk(d+l,delim);i;i=strpbrk(d+l,delim)){
			char s=*i;
			*i='\0';
			card=ms_alsa_card_new_custom(d+l,d+l);
			ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card);
			*i=s;
			l=i-d+1;
		}
		if(d[l]!='\0') {
			card=ms_alsa_card_new_custom(d+l,d+l);
			ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card);
		}
		free(d);
aymeric's avatar
aymeric committed
764
	}
Simon Morlat's avatar
Simon Morlat committed
765
	tmp=lp_config_get_int(lc->config,"sound","alsa_forced_rate",-1);
766
	if (tmp>0) ms_alsa_card_set_forced_sample_rate(tmp);
aymeric's avatar
aymeric committed
767 768
#endif
	/* retrieve all sound devices */
769 770
	build_sound_devices_table(lc);

aymeric's avatar
aymeric committed
771 772
	devid=lp_config_get_string(lc->config,"sound","playback_dev_id",NULL);
	linphone_core_set_playback_device(lc,devid);
773

aymeric's avatar
aymeric committed
774 775
	devid=lp_config_get_string(lc->config,"sound","ringer_dev_id",NULL);
	linphone_core_set_ringer_device(lc,devid);
776

aymeric's avatar
aymeric committed
777 778
	devid=lp_config_get_string(lc->config,"sound","capture_dev_id",NULL);
	linphone_core_set_capture_device(lc,devid);
779

aymeric's avatar
aymeric committed
780 781 782 783 784 785 786 787 788 789
/*
	tmp=lp_config_get_int(lc->config,"sound","play_lev",80);
	linphone_core_set_play_level(lc,tmp);
	tmp=lp_config_get_int(lc->config,"sound","ring_lev",80);
	linphone_core_set_ring_level(lc,tmp);
	tmp=lp_config_get_int(lc->config,"sound","rec_lev",80);
	linphone_core_set_rec_level(lc,tmp);
	tmpbuf=lp_config_get_string(lc->config,"sound","source","m");
	linphone_core_set_sound_source(lc,tmpbuf[0]);
*/
790

aymeric's avatar
aymeric committed
791 792
	tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	tmpbuf=lp_config_get_string(lc->config,"sound","local_ring",tmpbuf);
Jehan Monnier's avatar
Jehan Monnier committed
793
	if (ortp_file_exist(tmpbuf)==-1) {
794
		ms_warning("%s does not exist",tmpbuf);
aymeric's avatar
aymeric committed
795 796 797 798 799 800 801
		tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	}
	if (strstr(tmpbuf,".wav")==NULL){
		/* it currently uses old sound files, so replace them */
		tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	}
	linphone_core_set_ring(lc,tmpbuf);
802

803
	tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
804
	tmpbuf=lp_config_get_string(lc->config,"sound","remote_ring",tmpbuf);
Jehan Monnier's avatar
Jehan Monnier committed
805
	if (ortp_file_exist(tmpbuf)==-1){
806
		tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
807 808 809
	}
	if (strstr(tmpbuf,".wav")==NULL){
		/* it currently uses old sound files, so replace them */
810
		tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
811
	}
812
	linphone_core_set_ringback(lc,tmpbuf);
813 814

	linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC));
aymeric's avatar
aymeric committed
815
	lc->sound_conf.latency=0;
816
#ifndef __ios
Simon Morlat's avatar
Simon Morlat committed
817
	tmp=TRUE;
818
#else
Simon Morlat's avatar
Simon Morlat committed
819
	tmp=FALSE; /* on iOS we have builtin echo cancellation.*/
820
#endif
Simon Morlat's avatar
Simon Morlat committed
821
	tmp=lp_config_get_int(lc->config,"sound","echocancellation",tmp);
822
	linphone_core_enable_echo_cancellation(lc,tmp);
smorlat's avatar
smorlat committed
823 824
	linphone_core_enable_echo_limiter(lc,
		lp_config_get_int(lc->config,"sound","echolimiter",0));
825 826
	linphone_core_enable_agc(lc,
		lp_config_get_int(lc->config,"sound","agc",0));
827

Yann Diorcet's avatar
Yann Diorcet committed
828 829
	linphone_core_set_playback_gain_db (lc,lp_config_get_float(lc->config,"sound","playback_gain_db",0));
	linphone_core_set_mic_gain_db (lc,lp_config_get_float(lc->config,"sound","mic_gain_db",0));
830 831

	linphone_core_set_remote_ringback_tone (lc,lp_config_get_string(lc->config,"sound","ringback_tone",NULL));
832 833 834

	/*just parse requested stream feature once at start to print out eventual errors*/
	linphone_core_get_audio_features(lc);
835

836
	_linphone_core_set_tone(lc,LinphoneReasonBusy,LinphoneToneBusy,NULL);
aymeric's avatar
aymeric committed
837 838
}

839 840
static void certificates_config_read(LinphoneCore *lc)
{
841
	const char *rootca;
842
#ifdef __linux
843
	rootca=lp_config_get_string(lc->config,"sip","root_ca", "/etc/ssl/certs");
844
#else
845
	rootca=lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE);
846
#endif
847
	linphone_core_set_root_ca(lc,rootca);
848
	linphone_core_verify_server_certificates(lc,lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE));
849
	linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE));
850 851
}

852
static void sip_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
853 854 855
{
	char *contact;
	const char *tmpstr;
856
	LCSipTransports tr;
aymeric's avatar
aymeric committed
857 858
	int i,tmp;
	int ipv6;
859 860 861 862

	if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
		sal_use_session_timers(lc->sal,200);
	}
aymeric's avatar
aymeric committed
863

864
	sal_use_no_initial_route(lc->sal,lp_config_get_int(lc->config,"sip","use_no_initial_route",0));
865 866
	sal_use_rport(lc->sal,lp_config_get_int(lc->config,"sip","use_rport",1));

aymeric's avatar
aymeric committed
867 868 869 870 871
	ipv6=lp_config_get_int(lc->config,"sip","use_ipv6",-1);
	if (ipv6==-1){
		ipv6=0;
	}
	linphone_core_enable_ipv6(lc,ipv6);
872
	memset(&tr,0,sizeof(tr));
873

874 875 876 877
	tr.udp_port=lp_config_get_int(lc->config,"sip","sip_port",5060);
	tr.tcp_port=lp_config_get_int(lc->config,"sip","sip_tcp_port",5060);
	/*we are not listening inbound connection for tls, port has no meaning*/
	tr.tls_port=lp_config_get_int(lc->config,"sip","sip_tls_port",LC_SIP_TRANSPORT_RANDOM);
878

879
	certificates_config_read(lc);
880 881
	/*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/
	sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc));
882
	/*start listening on ports*/
883
	linphone_core_set_sip_transports(lc,&tr);
884

aymeric's avatar
aymeric committed
885 886
	tmpstr=lp_config_get_string(lc->config,"sip","contact",NULL);
	if (tmpstr==NULL || linphone_core_set_primary_contact(lc,tmpstr)==-1) {
smorlat's avatar
smorlat committed
887 888
		const char *hostname=NULL;
		const char *username=NULL;
889
#ifdef HAVE_GETENV
smorlat's avatar
smorlat committed
890 891
		hostname=getenv("HOST");
		username=getenv("USER");
aymeric's avatar
aymeric committed
892
		if (hostname==NULL) hostname=getenv("HOSTNAME");
893
#endif /*HAVE_GETENV*/
aymeric's avatar
aymeric committed
894 895 896 897 898 899 900 901 902 903 904 905
		if (hostname==NULL)
			hostname="unknown-host";
		if (username==NULL){
			username="toto";
		}
		contact=ortp_strdup_printf("sip:%s@%s",username,hostname);
		linphone_core_set_primary_contact(lc,contact);
		ms_free(contact);
	}

	tmp=lp_config_get_int(lc->config,"sip","guess_hostname",1);
	linphone_core_set_guess_hostname(lc,tmp);
906

Simon Morlat's avatar
Simon Morlat committed
907 908
	tmp=lp_config_get_int(lc->config,"sip","lime",FALSE);
	linphone_core_enable_lime(lc,tmp);
909

910
	tmp=lp_config_get_int(lc->config,"sip","inc_timeout",30);
aymeric's avatar
aymeric committed
911 912
	linphone_core_set_inc_timeout(lc,tmp);

Yann Diorcet's avatar
Yann Diorcet committed
913 914
	tmp=lp_config_get_int(lc->config,"sip","in_call_timeout",0);
	linphone_core_set_in_call_timeout(lc,tmp);
915

916 917
	tmp=lp_config_get_int(lc->config,"sip","delayed_timeout",4);
	linphone_core_set_delayed_timeout(lc,tmp);
Yann Diorcet's avatar
Yann Diorcet committed
918

aymeric's avatar
aymeric committed
919 920
	/* get proxies config */
	for(i=0;; i++){
jehan's avatar
jehan committed
921
		LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc,i);
aymeric's avatar
aymeric committed
922 923
		if (cfg!=NULL){
			linphone_core_add_proxy_config(lc,cfg);
Simon Morlat's avatar
Simon Morlat committed
924
			linphone_proxy_config_unref(cfg);
aymeric's avatar
aymeric committed
925 926 927 928 929 930 931
		}else{
			break;
		}
	}
	/* get the default proxy */
	tmp=lp_config_get_int(lc->config,"sip","default_proxy",-1);
	linphone_core_set_default_proxy_index(lc,tmp);
932

aymeric's avatar
aymeric committed
933 934 935 936 937
	/* read authentication information */
	for(i=0;; i++){
		LinphoneAuthInfo *ai=linphone_auth_info_new_from_config_file(lc->config,i);
		if (ai!=NULL){
			linphone_core_add_auth_info(lc,ai);
Simon Morlat's avatar
Simon Morlat committed
938
			linphone_auth_info_destroy(ai);
aymeric's avatar
aymeric committed
939 940 941 942
		}else{
			break;
		}
	}
943 944
	/*this is to filter out unsupported encryption schemes*/
	linphone_core_set_media_encryption(lc,linphone_core_get_media_encryption(lc));
945

946
	/*for tuning or test*/
aymeric's avatar
aymeric committed
947
	lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
948
	lc->sip_conf.register_only_when_network_is_up=
949
		lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1);
950 951
	lc->sip_conf.register_only_when_upnp_is_ok=
		lp_config_get_int(lc->config,"sip","register_only_when_upnp_is_ok",1);
952
	lc->sip_conf.ping_with_options=lp_config_get_int(lc->config,"sip","ping_with_options",0);
jehan's avatar
jehan committed
953
	lc->sip_conf.auto_net_state_mon=lp_config_get_int(lc->config,"sip","auto_net_state_mon",1);
954
	lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000);
955 956
	lc->sip_conf.tcp_tls_keepalive=lp_config_get_int(lc->config,"sip","tcp_tls_keepalive",0);
	linphone_core_enable_keep_alive(lc, (lc->sip_conf.keepalive_period > 0));