Commit 6506e686 authored by Paul Cartier's avatar Paul Cartier
Browse files

Add Shared Core for iOS platform

- Add Shared Core logic in shared-core-helpers and constructors in factory
- Add high level functions to get the message or the new chat room from a push notification
- Allow wrappers to use linphone logger
- Add core option to send imdn without being registered
- Improve linphone_core_stop()
- Move the paths functions to the same place for all platforms and add paths for iOS shared file system
- Add shared core tests and modify LinphoneCoreManager to create shared cores
parent 9eb4be0d
......@@ -207,7 +207,7 @@ static void call_received(SalCallOp *h) {
sal_address_unref(altAddr);
LinphoneErrorInfo *ei = linphone_error_info_new();
linphone_error_info_set(ei, nullptr, LinphoneReasonMovedPermanently, 302, "Moved permanently", nullptr);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei, L_STRING_TO_C(h->getCallId()));
h->release();
sal_error_info_reset(&sei);
return;
......@@ -223,7 +223,7 @@ static void call_received(SalCallOp *h) {
h->decline(SalReasonBusy);
LinphoneErrorInfo *ei = linphone_error_info_new();
linphone_error_info_set(ei, nullptr, LinphoneReasonBusy, 486, "Busy - too many calls", nullptr);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei, L_STRING_TO_C(h->getCallId()));
h->release();
return;
}
......@@ -243,7 +243,7 @@ static void call_received(SalCallOp *h) {
h->decline(SalReasonBusy);
LinphoneErrorInfo *ei = linphone_error_info_new();
linphone_error_info_set(ei, nullptr, LinphoneReasonBusy, 486, "Busy - duplicated call", nullptr);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei, L_STRING_TO_C(h->getCallId()));
h->release();
linphone_address_unref(fromAddressToSearchIfMe);
ms_free(addr);
......@@ -263,7 +263,7 @@ static void call_rejected(SalCallOp *h){
LinphoneCore *lc = reinterpret_cast<LinphoneCore *>(h->getSal()->getUserPointer());
LinphoneErrorInfo *ei = linphone_error_info_new();
linphone_error_info_from_sal_op(ei, h);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_new(h->getFrom().c_str()), linphone_address_new(h->getTo().c_str()), ei);
linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_new(h->getFrom().c_str()), linphone_address_new(h->getTo().c_str()), ei, L_STRING_TO_C(h->getCallId()));
}
static void call_ringing(SalOp *h) {
......
......@@ -22,6 +22,7 @@
#include "c-wrapper/c-wrapper.h"
#include "address/address-p.h"
#include "core/paths/paths.h"
// TODO: From coreapi. Remove me later.
#include "private.h"
......@@ -171,6 +172,25 @@ static LinphoneCore *_linphone_factory_create_core (
return lc;
}
static LinphoneCore *_linphone_factory_create_shared_core (
const LinphoneFactory *factory,
LinphoneCoreCbs *cbs,
const char *config_filename,
const char *factory_config_path,
void *user_data,
void *system_context,
bool_t automatically_start,
const char *app_group_id,
bool_t main_core
) {
bctbx_init_logger(FALSE);
LpConfig *config = linphone_config_new_for_shared_core(app_group_id, config_filename, factory_config_path);
LinphoneCore *lc = _linphone_core_new_shared_with_config(cbs, config, user_data, system_context, automatically_start, app_group_id, main_core);
lp_config_unref(config);
bctbx_uninit_logger();
return lc;
}
LinphoneCore *linphone_factory_create_core (
const LinphoneFactory *factory,
LinphoneCoreCbs *cbs,
......@@ -200,6 +220,17 @@ LinphoneCore *linphone_factory_create_core_3 (
return _linphone_factory_create_core(factory, NULL, config_path, factory_config_path, NULL, system_context, FALSE);
}
LinphoneCore *linphone_factory_create_shared_core (
const LinphoneFactory *factory,
const char *config_filename,
const char *factory_config_path,
void *system_context,
const char *app_group_id,
bool_t main_core
) {
return _linphone_factory_create_shared_core(factory, NULL, factory_config_path, factory_config_path, NULL, system_context, FALSE, app_group_id, main_core);
}
LinphoneCore *linphone_factory_create_core_with_config (
const LinphoneFactory *factory,
LinphoneCoreCbs *cbs,
......@@ -226,6 +257,16 @@ LinphoneCore *linphone_factory_create_core_with_config_3 (
return _linphone_core_new_with_config(NULL, config, NULL, system_context, FALSE);
}
LinphoneCore *linphone_factory_create_shared_core_with_config (
const LinphoneFactory *factory,
LinphoneConfig *config,
void *system_context,
const char *app_group_id,
bool_t main_core
) {
return _linphone_core_new_shared_with_config(NULL, config, NULL, system_context, FALSE, app_group_id, main_core);
}
LinphoneCoreCbs *linphone_factory_create_core_cbs(const LinphoneFactory *factory) {
return _linphone_core_cbs_new();
}
......@@ -518,3 +559,18 @@ bool_t linphone_factory_is_imdn_available(LinphoneFactory *factory) {
return FALSE;
#endif
}
const char *linphone_factory_get_config_dir(LinphoneFactory *factory, void *context) {
std::string path = LinphonePrivate::Paths::getPath(LinphonePrivate::Paths::Config, context);
return ms_strdup(path.c_str());
}
const char *linphone_factory_get_data_dir(LinphoneFactory *factory, void *context) {
std::string path = LinphonePrivate::Paths::getPath(LinphonePrivate::Paths::Data, context);
return ms_strdup(path.c_str());
}
const char *linphone_factory_get_download_dir(LinphoneFactory *factory, void *context) {
std::string path = LinphonePrivate::Paths::getPath(LinphonePrivate::Paths::Download, context);
return ms_strdup(path.c_str());
}
......@@ -92,6 +92,10 @@
#include "TargetConditionals.h"
#endif
#ifdef __ANDROID__
#include "android/api-level.h"
#endif
#include "c-wrapper/c-wrapper.h"
#include "call/call-p.h"
#include "conference/params/media-session-params-p.h"
......@@ -639,6 +643,17 @@ static void _close_log_collection_file(void) {
}
}
#if (!__ANDROID__ && !__APPLE__) || (__ANDROID__ && __ANDROID_API__ < 21)
static const char* getprogname() {
#if defined(__GLIBC__)
return program_invocation_short_name;
#else
//not known yet on windows
return"";
#endif
}
#endif
static void linphone_core_log_collection_handler(const char *domain, OrtpLogLevel level, const char *fmt, va_list args) {
const char *lname="undef";
char *msg;
......@@ -686,8 +701,8 @@ static void linphone_core_log_collection_handler(const char *domain, OrtpLogLeve
}
if (liblinphone_log_collection_file) {
ortp_mutex_lock(&liblinphone_log_collection_mutex);
ret = fprintf(liblinphone_log_collection_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i [%s] %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), domain, lname, msg);
ret = fprintf(liblinphone_log_collection_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i [%s/%s] %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), getprogname(), domain, lname, msg);
fflush(liblinphone_log_collection_file);
if (ret > 0) {
liblinphone_log_collection_file_size += (size_t)ret;
......@@ -2611,6 +2626,11 @@ LinphoneStatus linphone_core_start (LinphoneCore *lc) {
bctbx_uninit_logger();
}
if (!getPlatformHelpers(lc)->getSharedCoreHelpers()->canCoreStart()) {
bctbx_warning("Core [%p] can't start", lc);
return -1;
}
linphone_core_set_state(lc, LinphoneGlobalStartup, "Starting up");
L_GET_PRIVATE_FROM_C_OBJECT(lc)->init();
......@@ -2659,6 +2679,17 @@ LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpCon
return core;
}
LinphoneCore *_linphone_core_new_shared_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context, bool_t automatically_start, const char *app_group_id, bool_t main_core) {
bctbx_message("[SHARED] Creating %s Shared Core", main_core ? "Main" : "Executor");
linphone_config_set_string(config, "shared_core", "app_group_id", app_group_id);
LinphoneCore *core = _linphone_core_new_with_config(cbs, config, userdata, system_context, automatically_start);
core->is_main_core = main_core;
// allow ios app extension to mark msg as read without being registered
core->send_imdn_if_unregistered = !main_core;
getPlatformHelpers(core)->getSharedCoreHelpers()->registerSharedCoreMsgCallback();
return core;
}
static LinphoneCore *_linphone_core_new_with_config_and_start (
const LinphoneCoreVTable *vtable,
LinphoneConfig *config,
......@@ -3670,8 +3701,12 @@ void linphone_core_iterate(LinphoneCore *lc){
ortp_logv_flush();
}
if (lc->state == LinphoneGlobalShutdown && lc->async_stop) {
if (L_GET_PRIVATE_FROM_C_OBJECT(lc)->asyncStopDone()) {
/* When doing asynchronous core stop, the core goes to LinphoneGlobalShutdown state
Then linphone_core_iterate() needs to be called until synchronous tasks are done
Then the stop is finished and the status is changed to LinphoneGlobalOff */
if (lc->state == LinphoneGlobalShutdown) {
if (L_GET_PRIVATE_FROM_C_OBJECT(lc)->isShutdownDone()) {
_linphone_core_stop_async_end(lc);
}
}
......@@ -6119,29 +6154,36 @@ void sip_config_uninit(LinphoneCore *lc)
lp_config_set_int(lc->config,"sip","register_only_when_upnp_is_ok",config->register_only_when_upnp_is_ok);
if (lc->sip_network_state.global_state) {
for(elem=config->proxies;elem!=NULL;elem=bctbx_list_next(elem)){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
_linphone_proxy_config_unpublish(cfg); /* to unpublish without changing the stored flag enable_publish */
bool_t need_to_unregister = FALSE;
for (elem = config->proxies; elem != NULL; elem = bctbx_list_next(elem)) {
LinphoneProxyConfig *cfg = (LinphoneProxyConfig *)(elem->data);
_linphone_proxy_config_unpublish(cfg); /* to unpublish without changing the stored flag enable_publish */
/* Do not unregister when push notifications are allowed, otherwise this clears tokens from the SIP server.*/
if (!linphone_proxy_config_is_push_notification_allowed(cfg)){
if (!linphone_proxy_config_is_push_notification_allowed(cfg)) {
_linphone_proxy_config_unregister(cfg); /* to unregister without changing the stored flag enable_register */
need_to_unregister = TRUE;
}
}
ms_message("Unregistration started.");
for (i=0;i<20&&still_registered;i++){
still_registered=FALSE;
lc->sal->iterate();
for(elem=config->proxies;elem!=NULL;elem=bctbx_list_next(elem)){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
LinphoneRegistrationState state = linphone_proxy_config_get_state(cfg);
still_registered = (state==LinphoneRegistrationOk||state==LinphoneRegistrationProgress);
if (need_to_unregister) {
ms_message("Unregistration started.");
for (i = 0; i < 20 && still_registered; i++) {
still_registered = FALSE;
lc->sal->iterate();
for (elem = config->proxies; elem != NULL; elem = bctbx_list_next(elem)) {
LinphoneProxyConfig *cfg = (LinphoneProxyConfig *)(elem->data);
if (!linphone_proxy_config_is_push_notification_allowed(cfg)) {
LinphoneRegistrationState state = linphone_proxy_config_get_state(cfg);
still_registered = (state == LinphoneRegistrationOk || state == LinphoneRegistrationProgress);
}
}
ms_usleep(100000);
}
ms_usleep(100000);
if (i >= 20) ms_warning("Cannot complete unregistration, giving up");
}
if (i>=20) ms_warning("Cannot complete unregistration, giving up");
}
elem = config->proxies;
......@@ -6352,9 +6394,13 @@ LinphoneXmlRpcSession * linphone_core_create_xml_rpc_session(LinphoneCore *lc, c
* Called by linphone_core_stop_async() to begin the async stop process and change the state to "Shutdown"
*/
static void _linphone_core_stop_async_start(LinphoneCore *lc) {
if (linphone_core_get_global_state(lc) == LinphoneGlobalOff) {
ms_message("Core [%p] is already stopped", lc);
return;
}
linphone_task_list_free(&lc->hooks);
lc->video_conf.show_local = FALSE;
lc->async_stop = TRUE;
L_GET_PRIVATE_FROM_C_OBJECT(lc)->shutdown();
......@@ -6379,7 +6425,7 @@ static void _linphone_core_stop_async_start(LinphoneCore *lc) {
* and change the state to "Off"
*/
static void _linphone_core_stop_async_end(LinphoneCore *lc) {
L_GET_PRIVATE_FROM_C_OBJECT(lc)->stop();
L_GET_PRIVATE_FROM_C_OBJECT(lc)->uninit();
lc->chat_rooms = bctbx_list_free_with_data(lc->chat_rooms, (bctbx_list_free_func)linphone_chat_room_unref);
......@@ -6458,126 +6504,44 @@ static void _linphone_core_stop_async_end(LinphoneCore *lc) {
ms_factory_destroy(lc->factory);
lc->factory = NULL;
#if TARGET_OS_IPHONE
bool_t is_shared_core = getPlatformHelpers(lc)->getSharedCoreHelpers()->isCoreShared();
#endif
if (lc->platform_helper) delete getPlatformHelpers(lc);
lc->platform_helper = NULL;
#if TARGET_OS_IPHONE
/* this will unlock the other Linphone Shared Core that are waiting to start (if any).
We need to unlock them at the very end of the stopping process otherwise two Cores will
process at the same time until this one is finally stopped */
if (is_shared_core) LinphonePrivate::uninitSharedCore(lc);
#endif
linphone_core_set_state(lc, LinphoneGlobalOff, "Off");
}
static void _linphone_core_stop(LinphoneCore *lc) {
bctbx_list_t *elem = NULL;
int i=0;
bool_t wait_until_unsubscribe = FALSE;
linphone_task_list_free(&lc->hooks);
lc->video_conf.show_local = FALSE;
lc->async_stop = FALSE;
linphone_core_set_state(lc, LinphoneGlobalShutdown, "Shutdown");
L_GET_PRIVATE_FROM_C_OBJECT(lc)->uninit();
for (elem = lc->friends_lists; elem != NULL; elem = bctbx_list_next(elem)) {
LinphoneFriendList *list = (LinphoneFriendList *)elem->data;
linphone_friend_list_enable_subscriptions(list,FALSE);
if (list->event)
wait_until_unsubscribe = TRUE;
}
/*give a chance to unsubscribe, might be optimized*/
for (i=0; wait_until_unsubscribe && i<50; i++) {
linphone_core_iterate(lc);
ms_usleep(10000);
}
lc->chat_rooms = bctbx_list_free_with_data(lc->chat_rooms, (bctbx_list_free_func)linphone_chat_room_unref);
getPlatformHelpers(lc)->onLinphoneCoreStop();
#ifdef VIDEO_ENABLED
if (lc->previewstream!=NULL){
video_preview_stop(lc->previewstream);
lc->previewstream=NULL;
if (linphone_core_get_global_state(lc) == LinphoneGlobalOff) {
ms_message("Core [%p] is already stopped", lc);
return;
}
#endif
lc->msevq=NULL;
/* save all config */
friends_config_uninit(lc);
sip_config_uninit(lc);
net_config_uninit(lc);
rtp_config_uninit(lc);
linphone_core_stop_ringing(lc);
linphone_core_stop_dtmf_stream(lc);
sound_config_uninit(lc);
video_config_uninit(lc);
codecs_config_uninit(lc);
sip_setup_unregister_all();
if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config);
_linphone_core_stop_async_start(lc);
bctbx_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref);
lc->call_logs=bctbx_list_free(lc->call_logs);
bool_t is_off = FALSE;
uint64_t start_time = ms_get_cur_time_ms();
if(lc->zrtp_secrets_cache != NULL) {
ms_free(lc->zrtp_secrets_cache);
lc->zrtp_secrets_cache = NULL;
while (!is_off && ms_get_cur_time_ms() - start_time < 1000) {
linphone_core_iterate(lc);
ms_usleep(50000);
is_off = (linphone_core_get_global_state(lc) == LinphoneGlobalOff);
}
if(lc->user_certificates_path != NULL) {
ms_free(lc->user_certificates_path);
lc->user_certificates_path = NULL;
}
if(lc->play_file!=NULL){
ms_free(lc->play_file);
lc->play_file = NULL;
}
if(lc->rec_file!=NULL){
ms_free(lc->rec_file);
lc->rec_file = NULL;
}
if (lc->logs_db_file) {
ms_free(lc->logs_db_file);
lc->logs_db_file = NULL;
}
if (lc->friends_db_file) {
ms_free(lc->friends_db_file);
lc->friends_db_file = NULL;
}
if (lc->tls_key){
ms_free(lc->tls_key);
lc->tls_key = NULL;
}
if (lc->tls_cert){
ms_free(lc->tls_cert);
lc->tls_cert = NULL;
}
if (lc->ringtoneplayer) {
linphone_ringtoneplayer_destroy(lc->ringtoneplayer);
lc->ringtoneplayer = NULL;
}
if (lc->im_encryption_engine) {
linphone_im_encryption_engine_unref(lc->im_encryption_engine);
lc->im_encryption_engine = NULL;
}
if (lc->default_ac_service) {
linphone_account_creator_service_unref(lc->default_ac_service);
lc->default_ac_service = NULL;
/* linphone_core_iterate() can call _linphone_core_stop_async_end()
if all asynchronous tasks are done so we don't need to call it twice */
if (!is_off) {
_linphone_core_stop_async_end(lc);
}
linphone_core_free_payload_types(lc);
if (lc->supported_formats) ms_free((void *)lc->supported_formats);
lc->supported_formats = NULL;
linphone_core_call_log_storage_close(lc);
linphone_core_friends_storage_close(lc);
linphone_core_zrtp_cache_close(lc);
ms_bandwidth_controller_destroy(lc->bw_controller);
lc->bw_controller = NULL;
ms_factory_destroy(lc->factory);
lc->factory = NULL;
if (lc->platform_helper) delete getPlatformHelpers(lc);
lc->platform_helper = NULL;
linphone_core_set_state(lc, LinphoneGlobalOff, "Off");
}
void linphone_core_stop(LinphoneCore *lc) {
......
......@@ -35,6 +35,7 @@ struct _LinphoneLoggingService {
LinphoneLoggingServiceCbs *cbs; // Deprecated, use a list of Cbs instead
bctbx_list_t *callbacks;
bctbx_log_handler_t *log_handler;
char *domain;
};
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneLoggingService);
......@@ -241,6 +242,10 @@ void linphone_logging_service_set_log_level(LinphoneLoggingService *log_service,
for (domain=_linphone_logging_service_log_domains; *domain; domain++) {
bctbx_set_log_level(*domain, _linphone_log_level_to_bctbx_log_level(loglevel));
}
if (log_service->domain) {
bctbx_set_log_level(log_service->domain, _linphone_log_level_to_bctbx_log_level(loglevel));
}
}
void linphone_logging_service_set_log_level_mask(LinphoneLoggingService *log_service, unsigned int mask) {
......@@ -248,6 +253,10 @@ void linphone_logging_service_set_log_level_mask(LinphoneLoggingService *log_ser
for (domain=_linphone_logging_service_log_domains; *domain; domain++) {
bctbx_set_log_level_mask(*domain, (int)_linphone_log_mask_to_bctbx_log_mask(mask));
}
if (log_service->domain) {
bctbx_set_log_level_mask(log_service->domain, (int)_linphone_log_mask_to_bctbx_log_mask(mask));
}
}
unsigned int linphone_logging_service_get_log_level_mask(const LinphoneLoggingService *log_service) {
......@@ -259,6 +268,47 @@ void linphone_logging_service_set_log_file(const LinphoneLoggingService *service
bctbx_add_log_handler(log_handler);
}
void linphone_logging_service_set_domain(LinphoneLoggingService *log_service, const char *domain) {
log_service->domain = bctbx_strdup(domain);
}
const char *linphone_logging_service_get_domain(LinphoneLoggingService *log_service) {
return log_service->domain;
}
void _linphone_logging_service_print(LinphoneLoggingService *log_service, const char *msg, _LinphoneLogLevel log_level, int dummy, ...) {
if (log_service->domain) {
va_list empty_va_list;
va_start(empty_va_list, dummy);
bctbx_logv(log_service->domain, _linphone_log_level_to_bctbx_log_level(log_level), msg, empty_va_list);
va_end(empty_va_list);
}
}
void linphone_logging_service_debug(LinphoneLoggingService *log_service, const char *msg) {
_linphone_logging_service_print(log_service, msg, LinphoneLogLevelDebug, 0);
}
void linphone_logging_service_trace(LinphoneLoggingService *log_service, const char *msg) {
_linphone_logging_service_print(log_service, msg, LinphoneLogLevelTrace, 0);
}
void linphone_logging_service_message(LinphoneLoggingService *log_service, const char *msg) {
_linphone_logging_service_print(log_service, msg, LinphoneLogLevelMessage, 0);
}
void linphone_logging_service_warning(LinphoneLoggingService *log_service, const char *msg) {
_linphone_logging_service_print(log_service, msg, LinphoneLogLevelWarning, 0);
}
void linphone_logging_service_error(LinphoneLoggingService *log_service, const char *msg) {
_linphone_logging_service_print(log_service, msg, LinphoneLogLevelError, 0);
}
void linphone_logging_service_fatal(LinphoneLoggingService *log_service, const char *msg) {
_linphone_logging_service_print(log_service, msg, LinphoneLogLevelFatal, 0);
}
BELLE_SIP_INSTANCIATE_VPTR(LinphoneLoggingService, belle_sip_object_t,
_linphone_logging_service_uninit, // uninit
NULL, // clone
......
......@@ -72,6 +72,7 @@
#include "lpc2xml.h"
#include "c-wrapper/c-wrapper.h"
#include "core/paths/paths.h"
typedef struct _LpItem{
char *key;
......@@ -474,7 +475,7 @@ fail:
LpConfig *linphone_config_new_with_factory(const char *config_filename, const char *factory_config_filename) {
LpConfig *lpconfig=belle_sip_object_new(LinphoneConfig);
if (factory_config_filename)
if (factory_config_filename && strcmp(factory_config_filename, "") != 0)
lpconfig->factory_filename = bctbx_strdup(factory_config_filename);
if (_linphone_config_init_from_files(lpconfig, config_filename, factory_config_filename) == 0) {
return lpconfig;
......@@ -484,6 +485,13 @@ LpConfig *linphone_config_new_with_factory(const char *config_filename, const ch
}
}
LpConfig *linphone_config_new_for_shared_core(const char *app_group_id, const char* config_filename, const char *factory_path) {
std::string path = LinphonePrivate::Paths::getPath(LinphonePrivate::Paths::Config, static_cast<void *>(strdup(app_group_id)));
path = path + "/" + config_filename;
const char* full_path = ms_strdup(path.c_str());
return linphone_config_new_with_factory(full_path, factory_path);
}
LinphoneStatus linphone_config_read_file(LpConfig *lpconfig, const char *filename){
char* path = lp_realpath(filename, NULL);
bctbx_vfs_file_t* pFile = bctbx_file_open(lpconfig->g_bctbx_vfs, path, "r");
......@@ -939,6 +947,13 @@ LinphoneStatus linphone_config_sync(LpConfig *lpconfig){
return 0;
}
void linphone_config_reload(LinphoneConfig *lpconfig) {
bctbx_list_for_each(lpconfig->sections, (void (*)(void*)) lp_section_destroy);
bctbx_list_free(lpconfig->sections);
lpconfig->sections = NULL;
linphone_config_read_file(lpconfig, lpconfig->filename);
}
int linphone_config_has_section(const LpConfig *lpconfig, const char *section){
if (linphone_config_find_section(lpconfig,section)!=NULL) return 1;
return 0;
......
......@@ -933,9 +933,10 @@ void linphone_core_report_call_log(LinphoneCore *lc, LinphoneCallLog *call_log){
linphone_core_notify_call_log_updated(lc,call_log);
}
void linphone_core_report_early_failed_call(LinphoneCore *lc, LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to, LinphoneErrorInfo *ei){
void linphone_core_report_early_failed_call(LinphoneCore *lc, LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to, LinphoneErrorInfo *ei, const char *cid){
LinphoneCallLog *l = linphone_call_log_new(dir, from, to);
l->error_info = ei;
l->call_id = cid? bctbx_strdup(cid) : NULL;
l->status = LinphoneCallEarlyAborted;
linphone_core_report_call_log(lc, l);
linphone_call_log_unref(l);
......
......@@ -406,6 +406,7 @@ int linphone_core_get_edge_bw(LinphoneCore *lc);
int linphone_core_get_edge_ptime(LinphoneCore *lc);
LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context, bool_t automatically_start);
LinphoneCore *_linphone_core_new_shared_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context, bool_t automatically_start, const char *app_group_id, bool_t main_core);
int linphone_upnp_init(LinphoneCore *lc);
void linphone_upnp_destroy(LinphoneCore *lc);
......@@ -609,7 +610,7 @@ int linphone_core_get_default_proxy_config_index(LinphoneCore *lc);
char *linphone_presence_model_to_xml(LinphonePresenceModel *model) ;
void linphone_core_report_call_log(LinphoneCore *lc, LinphoneCallLog *call_log);
void linphone_core_report_early_failed_call(LinphoneCore *lc, LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to, LinphoneErrorInfo *ei);
void linphone_core_report_early_failed_call(LinphoneCore *lc, LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to, LinphoneErrorInfo *ei, const char *cid);
LinphoneVideoDefinition * linphone_video_definition_new(unsigned int width, unsigned int height, const char *name);
......