...
 
Commits (35)
......@@ -20,7 +20,7 @@
#
############################################################################
cmake_minimum_required(VERSION 3.11) # we need CMake 3.11 for defining 'package_source' target as custom target
cmake_minimum_required(VERSION 3.1)
project(linphone VERSION 4.3.0 LANGUAGES C CXX)
......@@ -66,6 +66,7 @@ option(ENABLE_UPDATE_CHECK "Enable update check." NO)
option(ENABLE_VCARD "Turn on compilation of vcard4 support." YES)
option(ENABLE_VIDEO "Build with video support." YES)
option(ENABLE_ASSETS "Package sound assets." YES)
option(ENABLE_PACKAGE_SOURCE "Create 'package_source' target for source archive making (CMake >= 3.11)" OFF)
cmake_dependent_option(ENABLE_NOTIFY "Enable libnotify support." YES "ENABLE_GTK_UI;NOT APPLE" NO)
cmake_dependent_option(ENABLE_ASSISTANT "Turn on assistant compiling." YES "ENABLE_GTK_UI" NO)
......@@ -134,7 +135,7 @@ find_package(XML2 REQUIRED)
if (ENABLE_DB_STORAGE)
#APPLE platform does not use dlopen for soci backend
if (APPLE)
if (APPLE OR ANDROID)
find_package(Soci REQUIRED COMPONENTS sqlite3)
else()
find_package(Soci REQUIRED)
......@@ -417,4 +418,7 @@ install(FILES
DESTINATION ${CONFIG_PACKAGE_LOCATION}
)
add_subdirectory(build)
if (ENABLE_PACKAGE_SOURCE)
add_subdirectory(build)
endif()
......@@ -20,6 +20,8 @@
#
############################################################################
cmake_minimum_required(VERSION 3.11) # we need CMake 3.11 for defining 'package_source' target as custom target
if(NOT CPACK_PACKAGE_NAME)
set(CPACK_PACKAGE_NAME "liblinphone")
endif()
......
......@@ -23,11 +23,7 @@
#
### Global Configuration Section
#
if(ANDROID)
SET(_SOCI_ALL_PLUGINS sqlite3)
else()
SET(_SOCI_ALL_PLUGINS mysql sqlite3)
endif()
SET(_SOCI_REQUIRED_VARS SOCI_INCLUDE_DIRS SOCI_LIBRARIES)
SET(_SOCI_VERSION "_4_0")
......@@ -67,10 +63,6 @@ IF(SOCI_INCLUDE_DIRS AND SOCI_LIBRARIES)
IF(SOCI_${plugin}_PLUGIN)
MESSAGE(STATUS " * Plugin ${plugin} found ${SOCI_${plugin}_PLUGIN}.")
SET(SOCI_${plugin}_FOUND True)
if(IOS OR ANDROID)
list(APPEND SOCI_LIBRARIES ${SOCI_${plugin}_PLUGIN})
endif()
ELSE()
MESSAGE(STATUS " * Plugin ${plugin} not found.")
SET(SOCI_${plugin}_FOUND False)
......
......@@ -23,6 +23,12 @@
if(ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRAPPER OR ENABLE_SWIFT_WRAPPER)
find_package(Doxygen REQUIRED)
if(DOXYGEN_FOUND)
if (DOXYGEN_VERSION VERSION_EQUAL "1.8.17" OR DOXYGEN_VERSION VERSION_GREATER "1.8.17")
message(FATAL_ERROR
"Your version of Doxygen (${DOXYGEN_VERSION}) is known to malfunction with some of our "
"macro definitions, which causes errors while wrapprers generation. Please install an "
"older version of Doxygen (< 1.8.17) or disable documentation and wrapper generation.")
endif()
set(top_srcdir "${PROJECT_SOURCE_DIR}")
set(DOXYGEN_INPUT "")
foreach (HEADER_FILE ${LINPHONE_HEADER_FILES})
......
......@@ -1255,6 +1255,11 @@ static void sound_config_read(LinphoneCore *lc) {
devid=lp_config_get_string(lc->config,"sound","media_dev_id",NULL);
linphone_core_set_media_device(lc,devid);
tmp=lp_config_get_int(lc->config, "sound", "enable_dummy_audio", 0);
if (!!tmp) {
ms_snd_card_manager_add_card(ms_factory_get_snd_card_manager(lc->factory), ms_dummy_audio_snd_card_new());
}
/*
tmp=lp_config_get_int(lc->config,"sound","play_lev",80);
linphone_core_set_play_level(lc,tmp);
......@@ -1421,7 +1426,11 @@ static void sip_config_read(LinphoneCore *lc) {
int ipv6_default = TRUE;
if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
lc->sal->useSessionTimers(200);
// usage of compatibility
lc->sal->useSessionTimers(600);
lp_config_set_int(lc->config, "sip", "session_expires_value",600);
} else {
lc->sal->useSessionTimers(lp_config_get_int(lc->config,"sip","session_expires_value",0));
}
lc->sal->useNoInitialRoute(!!lp_config_get_int(lc->config,"sip","use_no_initial_route",0));
......@@ -1485,7 +1494,8 @@ static void sip_config_read(LinphoneCore *lc) {
tmp=lp_config_get_int(lc->config,"sip", "lime", LinphoneLimeDisabled);
LinphoneLimeState limeState = static_cast<LinphoneLimeState>(tmp);
if (limeState != LinphoneLimeDisabled && linphone_core_lime_x3dh_enabled(lc)) {
bctbx_fatal("You can't have both LIME and LIME X3DH enabled at the same time !\nConflicting settings are [sip] lime and [lime] lime_server_url");
bctbx_warning("You can't have both LIME and LIME X3DH enabled at the same time ! LIME will be disabled.\nConflicting settings are [sip] lime(!=LinphoneLimeDisabled) and [lime] lime_server_url.");
limeState = LinphoneLimeDisabled;
}
linphone_core_enable_lime(lc, limeState);
......@@ -4602,6 +4612,11 @@ void linphone_core_reload_sound_devices(LinphoneCore *lc){
capture_copy = ms_strdup(capture);
}
ms_snd_card_manager_reload(ms_factory_get_snd_card_manager(lc->factory));
int tmp=lp_config_get_int(lc->config, "sound", "enable_dummy_audio", 0);
if (!!tmp) {
ms_snd_card_manager_add_card(ms_factory_get_snd_card_manager(lc->factory), ms_dummy_audio_snd_card_new());
}
build_sound_devices_table(lc);
if (ringer_copy != NULL) {
linphone_core_set_ringer_device(lc, ringer_copy);
......@@ -5713,7 +5728,9 @@ int linphone_core_get_device_rotation(LinphoneCore *lc ) {
}
void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation) {
if (rotation!=lc->device_rotation) ms_message("%s : rotation=%d\n", __FUNCTION__, rotation);
if (rotation == lc->device_rotation) return;
ms_message("%s : rotation=%d\n", __FUNCTION__, rotation);
lc->device_rotation = rotation;
#ifdef VIDEO_ENABLED
{
......@@ -7242,6 +7259,15 @@ bool_t linphone_core_sdp_200_ack_enabled(const LinphoneCore *lc) {
return lc->sip_conf.sdp_200_ack!=0;
}
void linphone_core_set_session_expires_value(const LinphoneCore *lc, int expires) {
lc->sal->useSessionTimers(expires);
lp_config_set_int(lc->config,"sip","session_expires_value",expires);
}
int linphone_core_get_session_expires_value(const LinphoneCore *lc) {
return lp_config_get_int(lc->config,"sip","session_expires_value",0);
}
void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url) {
lp_config_set_string(core->config, "misc", "file_transfer_server_url", server_url);
}
......
......@@ -1485,7 +1485,7 @@ public:
handle_possible_java_exception(env, lcData->listener);
}
static void fileTransferProgressIndication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) {
static void fileTransferProgressIndication(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, size_t offset, size_t total) {
JNIEnv *env = 0;
jobject jmsg;
size_t progress = (offset * 100) / total;
......@@ -1514,7 +1514,7 @@ public:
handle_possible_java_exception(env, lcData->listener);
}
static void fileTransferSend(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) {
static void fileTransferSend(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, char* buff, size_t* size) {
JNIEnv *env = 0;
jobject jmsg;
size_t asking = *size;
......@@ -1548,7 +1548,7 @@ public:
handle_possible_java_exception(env, lcData->listener);
}
static void fileTransferRecv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) {
static void fileTransferRecv(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, const char* buff, size_t size) {
JNIEnv *env = 0;
jobject jmsg;
jint result = jvm->AttachCurrentThread(&env,NULL);
......@@ -4820,7 +4820,7 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS
env->DeleteLocalRef(listener);
}
static void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) {
static void file_transfer_progress_indication(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t total) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
......@@ -4845,7 +4845,7 @@ static void file_transfer_progress_indication(LinphoneChatMessage *msg, const Li
env->DeleteLocalRef(listener);
}
static void file_transfer_recv(LinphoneChatMessage *msg, const LinphoneContent* content, const LinphoneBuffer *buffer) {
static void file_transfer_recv(LinphoneChatMessage *msg, LinphoneContent* content, const LinphoneBuffer *buffer) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
......@@ -4875,7 +4875,7 @@ static void file_transfer_recv(LinphoneChatMessage *msg, const LinphoneContent*
env->DeleteLocalRef(listener);
}
static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t size) {
static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t size) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
LinphoneBuffer *buffer = NULL;
......
......@@ -103,7 +103,17 @@ static void _local_player_close(LinphonePlayer *obj) {
static void _local_player_eof_callback(void *user_data) {
LinphonePlayer *obj = (LinphonePlayer *)user_data;
LinphonePlayerCbs *cbs = linphone_player_get_callbacks(obj);
LinphonePlayerCbsEofReachedCb cb = linphone_player_cbs_get_eof_reached(cbs);
if (cb) cb(obj);
bctbx_list_t *callbacksCopy = bctbx_list_copy(linphone_player_get_callbacks_list(obj));
for (bctbx_list_t *it = callbacksCopy; it; it = bctbx_list_next(it)) {
linphone_player_set_current_callbacks(obj, reinterpret_cast<LinphonePlayerCbs *>(bctbx_list_get_data(it)));
LinphonePlayerCbsEofReachedCb cb = linphone_player_cbs_get_eof_reached(linphone_player_get_current_callbacks(obj));
if (cb) cb(obj);
}
linphone_player_set_current_callbacks(obj, NULL);
bctbx_list_free(callbacksCopy);
}
......@@ -422,7 +422,7 @@ LpConfig * linphone_config_new_from_buffer(const char *buffer){
static int _linphone_config_init_from_files(LinphoneConfig *lpconfig, const char *config_filename, const char *factory_config_filename) {
lpconfig->g_bctbx_vfs = bctbx_vfs_get_default();
if (config_filename!=NULL){
if (config_filename != NULL && config_filename[0] != '\0'){
if(ortp_file_exist(config_filename) == 0) {
lpconfig->filename=lp_realpath(config_filename, NULL);
if(lpconfig->filename == NULL) {
......
......@@ -333,9 +333,9 @@ void _linphone_chat_room_clear_callbacks (LinphoneChatRoom *cr);
void _linphone_chat_message_notify_msg_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageState state);
void _linphone_chat_message_notify_participant_imdn_state_changed(LinphoneChatMessage* msg, const LinphoneParticipantImdnState *state);
void _linphone_chat_message_notify_file_transfer_recv(LinphoneChatMessage *msg, const LinphoneContent* content, const LinphoneBuffer *buffer);
void _linphone_chat_message_notify_file_transfer_send(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t size);
void _linphone_chat_message_notify_file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total);
void _linphone_chat_message_notify_file_transfer_recv(LinphoneChatMessage *msg, LinphoneContent* content, const LinphoneBuffer *buffer);
void _linphone_chat_message_notify_file_transfer_send(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t size);
void _linphone_chat_message_notify_file_transfer_progress_indication(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t total);
void _linphone_chat_message_clear_callbacks (LinphoneChatMessage *msg);
......@@ -535,9 +535,9 @@ void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *r
void linphone_core_notify_message_sent(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message);
void linphone_core_notify_message_received_unable_decrypt(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message);
void linphone_core_notify_chat_room_read(LinphoneCore *lc, LinphoneChatRoom *room);
void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size);
void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size);
void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total);
void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, const char* buff, size_t size);
void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, char* buff, size_t* size);
void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, size_t offset, size_t total);
void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room);
void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf);
/*
......
......@@ -111,8 +111,6 @@ struct _LinphoneProxyConfig
bool_t commit;
bool_t reg_sendregister;
/* Used to completely disable registration on a dependent proxy config. (Won't be enabled back even if it's 'master' proxy config state goes to LinphoneRegistrationOk) */
bool_t reg_dependent_disabled;
bool_t publish;
bool_t dial_escape_plus;
......
......@@ -177,7 +177,6 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cf
}
}
cfg->depends_on = depends_on ? ms_strdup(depends_on) : NULL;
cfg->reg_dependent_disabled = cfg->depends_on && !cfg->reg_sendregister;
if (idkey) {
cfg->idkey = ms_strdup(idkey);
} else {
......@@ -267,6 +266,10 @@ void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){
linphone_event_unref(cfg->presence_publish_event);
cfg->presence_publish_event=NULL;
}
if (cfg->dependency){
linphone_proxy_config_unref(cfg->dependency);
cfg->dependency = NULL;
}
}
void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){
......@@ -444,36 +447,49 @@ LinphoneStatus linphone_proxy_config_set_routes(LinphoneProxyConfig *cfg, const
return 0;
}
static void _linphone_core_resolve_proxy_config_dependencies(LinphoneCore *lc){
LinphoneProxyConfig *cfg;
const bctbx_list_t *elem;
for(elem = lc->sip_conf.proxies; elem != NULL; elem = elem->next){
cfg = (LinphoneProxyConfig*)elem->data;
if (cfg->dependency != NULL && cfg->depends_on != NULL) {
LinphoneProxyConfig *master_cfg = linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on);
if (master_cfg != NULL && master_cfg != cfg->dependency) {
ms_error("LinphoneProxyConfig has a dependency but idkeys do not match: [%s] != [%s], breaking dependency now.", cfg->depends_on, cfg->dependency->idkey);
linphone_proxy_config_unref(cfg->dependency);
cfg->dependency = NULL;
return;
}else if (master_cfg == NULL){
ms_warning("LinphoneProxyConfig [%p] depends on proxy config [%p], which is not currently in the list.", cfg, cfg->dependency);
}
}
if (cfg->depends_on != NULL && cfg->dependency == NULL) {
LinphoneProxyConfig *dependency = linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on);
if (dependency == NULL) {
ms_warning("LinphoneProxyConfig marked as dependent but no proxy configuration found for idkey [%s]", cfg->depends_on);
return;
} else {
ms_message("LinphoneProxyConfig [%p] now depends on master LinphoneProxyConfig [%p]", cfg, dependency);
cfg->dependency = linphone_proxy_config_ref(dependency);
}
}
}
}
bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *cfg){
if (cfg->reg_proxy==NULL)
return FALSE;
if (cfg->identity_address==NULL)
return FALSE;
if (cfg->dependency != NULL && cfg->depends_on != NULL) {
if (linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on) != cfg->dependency) {
ms_warning("LinphoneProxyConfig as a dependency but idkeys do not match: [%s] != [%s]", cfg->depends_on, cfg->dependency->idkey);
return FALSE;
}
}
if (cfg->depends_on != NULL && cfg->dependency == NULL) {
LinphoneProxyConfig *dependency = linphone_core_get_proxy_config_by_idkey(lc, cfg->depends_on);
if (dependency == NULL) {
ms_warning("LinphoneProxyConfig marked as dependent but no proxy configuration found for idkey [%s]", cfg->depends_on);
return FALSE;
} else {
cfg->dependency = linphone_proxy_config_ref(dependency);
}
}
_linphone_core_resolve_proxy_config_dependencies(lc);
return TRUE;
}
void linphone_proxy_config_enableregister(LinphoneProxyConfig *cfg, bool_t val){
if (val != cfg->reg_sendregister) cfg->register_changed = TRUE;
cfg->reg_sendregister = val;
if (cfg->dependency && !val) {
cfg->reg_dependent_disabled = TRUE;
}
}
void linphone_proxy_config_set_expires(LinphoneProxyConfig *cfg, int val){
......@@ -1174,15 +1190,8 @@ void linphone_core_remove_dependent_proxy_config(LinphoneCore *lc, LinphoneProxy
if (tmp != cfg && tmp->dependency == cfg) {
ms_message("Updating dependent proxy config [%p] caused by removal of 'master' proxy config idkey[%s]", tmp, cfg->idkey);
linphone_proxy_config_set_dependency(tmp, NULL);
linphone_proxy_config_edit(tmp);
//Only re-enable register if proxy wasn't explicitely disabled
linphone_proxy_config_enable_register(tmp, tmp->reg_dependent_disabled != TRUE);
tmp->reg_dependent_disabled = FALSE;
linphone_proxy_config_done(tmp);
//Force update on dependent if master wasn't registered
if (cfg->state != LinphoneRegistrationOk) {
linphone_proxy_config_update(tmp);
}
cfg->commit = TRUE;
linphone_proxy_config_update(tmp);
}
}
}
......@@ -1421,8 +1430,6 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc
CONFIGURE_STRING_VALUE(cfg, config, key, conference_factory_uri, "conference_factory_uri");
cfg->reg_dependent_disabled = cfg->depends_on && !cfg->reg_sendregister;
return cfg;
}
......@@ -1467,7 +1474,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){
return FALSE;
}
if (cfg->dependency) {
return linphone_proxy_config_get_state(cfg->dependency) == LinphoneRegistrationOk && !cfg->reg_dependent_disabled;
return linphone_proxy_config_get_state(cfg->dependency) == LinphoneRegistrationOk;
}
return TRUE;
}
......@@ -1519,8 +1526,13 @@ void _linphone_update_dependent_proxy_config(LinphoneProxyConfig *cfg, LinphoneR
for (;it;it = it->next) {
LinphoneProxyConfig *tmp = reinterpret_cast<LinphoneProxyConfig *>(it->data);
ms_message("_linphone_update_dependent_proxy_config(): %p is registered, checking for [%p] ->dependency=%p", cfg, tmp, tmp->dependency);
if (tmp != cfg && tmp->dependency == cfg) {
if (tmp->reg_dependent_disabled) continue;
if (!tmp->reg_sendregister) {
ms_message("Dependant proxy config [%p] has registration disabled, so it will not register.", tmp);
continue;
}
linphone_proxy_config_edit(tmp);
if (state == LinphoneRegistrationOk) {
// Force dependent proxy config to re-register
......
......@@ -188,17 +188,17 @@ void linphone_core_notify_message_received_unable_decrypt(LinphoneCore *lc, Linp
#else
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) {
void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, const char* buff, size_t size) {
NOTIFY_IF_EXIST(file_transfer_recv, lc,message,content,buff,size);
cleanup_dead_vtable_refs(lc);
}
void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) {
void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, char* buff, size_t* size) {
NOTIFY_IF_EXIST(file_transfer_send, lc,message,content,buff,size);
cleanup_dead_vtable_refs(lc);
}
void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) {
void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, size_t offset, size_t total) {
NOTIFY_IF_EXIST(file_transfer_progress_indication, lc,message,content,offset,total);
cleanup_dead_vtable_refs(lc);
}
......
......@@ -141,12 +141,33 @@ set(LINPHONE_HEADER_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}" PARENT_SCOPE)
# ------------------------------------------------------------------------------
if (APPLE AND ENABLE_SHARED)
#cmake 3.10 seems not able to handle subdirectories for PUBLIC_HEADER. May be reworked in the future.
#cmake 3.10 seems not able to handle subdirectories for PUBLIC_HEADER. May be reworked in the future.
set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_PREFIX}/Frameworks/linphone.framework/Headers")
install(FILES ${ROOT_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
install(FILES ${C_API_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}/api"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
install(FILES ${ENUMS_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}/enums"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
install(FILES ${UTILS_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}/utils"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
else()
set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone")
# Use this when we want to split OS X Frameworks and unix-style package components
# set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone")
endif()
# In all case, we want to get an unix-style package components as the OS X Frameworks is not fully support
set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone")
install(FILES ${ROOT_HEADER_FILES}
DESTINATION "${DEST_ROOT_DIRECTORY}"
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
......
......@@ -148,7 +148,7 @@ typedef void (*LinphoneChatMessageCbsParticipantImdnStateChangedCb)(LinphoneChat
* @param content #LinphoneContent incoming content information
* @param buffer #LinphoneBuffer holding the received data. Empty buffer means end of file.
*/
typedef void (*LinphoneChatMessageCbsFileTransferRecvCb)(LinphoneChatMessage *msg, const LinphoneContent* content, const LinphoneBuffer *buffer);
typedef void (*LinphoneChatMessageCbsFileTransferRecvCb)(LinphoneChatMessage *msg, LinphoneContent* content, const LinphoneBuffer *buffer);
/**
* File transfer send callback prototype. This function is called by the core when an outgoing file transfer is started. This function is called until size is set to 0.
......@@ -158,7 +158,7 @@ typedef void (*LinphoneChatMessageCbsFileTransferRecvCb)(LinphoneChatMessage *ms
* @param size the number of bytes expected by the framework
* @return A #LinphoneBuffer object holding the data written by the application. An empty buffer means end of file.
*/
typedef LinphoneBuffer * (*LinphoneChatMessageCbsFileTransferSendCb)(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t size);
typedef LinphoneBuffer * (*LinphoneChatMessageCbsFileTransferSendCb)(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t size);
/**
* File transfer progress indication callback prototype.
......@@ -167,7 +167,7 @@ typedef LinphoneBuffer * (*LinphoneChatMessageCbsFileTransferSendCb)(LinphoneCha
* @param offset The number of bytes sent/received since the beginning of the transfer.
* @param total The total number of bytes to be sent/received.
*/
typedef void (*LinphoneChatMessageCbsFileTransferProgressIndicationCb)(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total);
typedef void (*LinphoneChatMessageCbsFileTransferProgressIndicationCb)(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t total);
/**
* Is composing notification callback prototype.
......
......@@ -230,7 +230,7 @@ typedef void (*LinphoneCoreCbsMessageReceivedUnableDecryptCb)(LinphoneCore *lc,
* @param buff pointer to the received data
* @param size number of bytes to be read from buff. 0 means end of file.
*/
typedef void (*LinphoneCoreFileTransferRecvCb)(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size);
typedef void (*LinphoneCoreFileTransferRecvCb)(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, const char* buff, size_t size);
/**
* File transfer send callback prototype. This function is called by the core upon an outgoing file transfer is started. This function is called until size is set to 0.
......@@ -241,7 +241,7 @@ typedef void (*LinphoneCoreFileTransferRecvCb)(LinphoneCore *lc, LinphoneChatMes
* @param size as input value, it represents the number of bytes expected by the framework. As output value, it means the number of bytes wrote by the application in the buffer. 0 means end of file.
*
*/
typedef void (*LinphoneCoreFileTransferSendCb)(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size);
typedef void (*LinphoneCoreFileTransferSendCb)(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, char* buff, size_t* size);
/**
* File transfer progress indication callback prototype.
......@@ -251,7 +251,7 @@ typedef void (*LinphoneCoreFileTransferSendCb)(LinphoneCore *lc, LinphoneChatMes
* @param offset The number of bytes sent/received since the beginning of the transfer.
* @param total The total number of bytes to be sent/received.
*/
typedef void (*LinphoneCoreFileTransferProgressIndicationCb)(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total);
typedef void (*LinphoneCoreFileTransferProgressIndicationCb)(LinphoneCore *lc, LinphoneChatMessage *message, LinphoneContent* content, size_t offset, size_t total);
/**
* Is composing notification callback prototype.
......
......@@ -4228,6 +4228,21 @@ LINPHONE_PUBLIC int linphone_core_get_mtu(const LinphoneCore *lc);
**/
LINPHONE_PUBLIC void linphone_core_set_mtu(LinphoneCore *lc, int mtu);
/**
* Sets the session expires value, 0 by default, which means session expires disabled.
* @param[in] lc #LinphoneCore object
* @param[in] expire The session expires value
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_core_set_session_expires_value(const LinphoneCore *lc, int expires);
/**
* Returns the session expires value, 0 by default, which means session expires disabled.
* @param[in] lc #LinphoneCore object
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_core_get_session_expires_value(const LinphoneCore *lc);
/**
* This method is called by the application to notify the linphone core library when network is reachable.
* Calling this method with true trigger linphone to initiate a registration process for all proxies.
......
......@@ -115,6 +115,18 @@ LINPHONE_PUBLIC void linphone_chat_message_resend_2(LinphoneChatMessage *msg);
*/
LINPHONE_PUBLIC void *linphone_vcard_get_belcard(LinphoneVcard *vcard);
/**
* Allow multipart on a basic chat room
* @donotwrap
*/
LINPHONE_PUBLIC void linphone_chat_room_allow_multipart(LinphoneChatRoom *room);
/**
* Allow cpim on a basic chat room
* @donotwrap
*/
LINPHONE_PUBLIC void linphone_chat_room_allow_cpim(LinphoneChatRoom *room);
/**
* @}
*/
......
......@@ -55,12 +55,13 @@ if(ZLIB_FOUND)
endif()
if (ENABLE_DB_STORAGE)
if (SOCI_FOUND)
list(APPEND INTERFACE_LIBS soci)
list(APPEND LINK_LIBS ${SOCI_LIBRARIES})
if(APPLE)
#take care of the order for static link
if(APPLE OR ANDROID)
list(APPEND INTERFACE_LIBS ${SOCI_sqlite3_PLUGIN})
list(APPEND LINK_LIBS ${SOCI_sqlite3_PLUGIN})
endif()
endif()
list(APPEND INTERFACE_LIBS soci)
list(APPEND LINK_LIBS ${SOCI_LIBRARIES})
endif()
endif()
if(SQLITE3_FOUND)
......
......@@ -59,7 +59,7 @@ AuthInfo::AuthInfo(LpConfig *config, string key){
domain = lp_config_get_string(config, key.c_str(), "domain", "");
tls_cert_path = lp_config_get_string(config, key.c_str(), "client_cert_chain", "");
tls_key_path = lp_config_get_string(config, key.c_str(), "client_cert_key", "");
algo = lp_config_get_string(config, key.c_str(), "algorithm", "MD5");
algo = lp_config_get_string(config, key.c_str(), "algorithm", "");
setTlsCertPath(tls_cert_path);
setTlsKeyPath(tls_key_path);
......
......@@ -156,15 +156,15 @@ void _linphone_chat_message_notify_participant_imdn_state_changed(LinphoneChatMe
NOTIFY_IF_EXIST(ParticipantImdnStateChanged, participant_imdn_state_changed, msg, state)
}
void _linphone_chat_message_notify_file_transfer_recv(LinphoneChatMessage *msg, const LinphoneContent* content, const LinphoneBuffer *buffer) {
void _linphone_chat_message_notify_file_transfer_recv(LinphoneChatMessage *msg, LinphoneContent* content, const LinphoneBuffer *buffer) {
NOTIFY_IF_EXIST(FileTransferRecv, file_transfer_recv, msg, content, buffer)
}
void _linphone_chat_message_notify_file_transfer_send(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t size) {
void _linphone_chat_message_notify_file_transfer_send(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t size) {
NOTIFY_IF_EXIST(FileTransferSend, file_transfer_send, msg, content, offset, size)
}
void _linphone_chat_message_notify_file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) {
void _linphone_chat_message_notify_file_transfer_progress_indication(LinphoneChatMessage *msg, LinphoneContent* content, size_t offset, size_t total) {
NOTIFY_IF_EXIST(FileTransferProgressIndication, file_transfer_progress_indication, msg, content, offset, total)
}
......@@ -305,17 +305,15 @@ LinphoneStatus linphone_chat_message_put_char (LinphoneChatMessage *msg, uint32_
void linphone_chat_message_add_file_content (LinphoneChatMessage *msg, LinphoneContent *c_content) {
LinphonePrivate::FileContent *fileContent = new LinphonePrivate::FileContent();
LinphonePrivate::ContentType contentType;
contentType.setType(L_C_TO_STRING(linphone_content_get_type(c_content)));
contentType.setSubType(L_C_TO_STRING(linphone_content_get_subtype(c_content)));
fileContent->setContentType(contentType);
LinphonePrivate::Content *content = L_GET_CPP_PTR_FROM_C_OBJECT(c_content);
fileContent->setContentType(content->getContentType());
fileContent->setFileSize(linphone_content_get_size(c_content));
fileContent->setFileName(linphone_content_get_name(c_content));
fileContent->setFilePath(linphone_content_get_file_path(c_content));
if (linphone_content_get_size(c_content) > 0) {
fileContent->setBody(linphone_content_get_string_buffer(c_content));
}
fileContent->setFileName(L_C_TO_STRING(linphone_content_get_name(c_content)));
fileContent->setFilePath(L_C_TO_STRING(linphone_content_get_file_path(c_content)));
fileContent->setBody(content->getBody());
fileContent->setUserData(content->getUserData());
L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(fileContent);
lInfo() << "File content [" << fileContent << "] added into message [" << msg << "]";
}
void linphone_chat_message_add_text_content (LinphoneChatMessage *msg, const char *text) {
......
......@@ -81,6 +81,14 @@ static list<LinphonePrivate::IdentityAddress> _get_identity_address_list_from_ad
}
*/
void linphone_chat_room_allow_multipart(LinphoneChatRoom *room) {
L_GET_CPP_PTR_FROM_C_OBJECT(room)->allowMultipart(true);
}
void linphone_chat_room_allow_cpim(LinphoneChatRoom *room) {
L_GET_CPP_PTR_FROM_C_OBJECT(room)->allowCpim(true);
}
// =============================================================================
// Public functions.
// =============================================================================
......
......@@ -85,11 +85,11 @@ void linphone_content_unref (LinphoneContent *content) {
}
void *linphone_content_get_user_data (const LinphoneContent *content) {
return L_GET_USER_DATA_FROM_C_OBJECT(content);
return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getUserData().getValue<void *>();
}
void linphone_content_set_user_data (LinphoneContent *content, void *user_data) {
return L_SET_USER_DATA_FROM_C_OBJECT(content, user_data);
return L_GET_CPP_PTR_FROM_C_OBJECT(content)->setUserData(user_data);
}
// =============================================================================
......@@ -300,6 +300,32 @@ void linphone_content_set_key (LinphoneContent *content, const char *key, const
}
}
const char *linphone_content_get_authTag (const LinphoneContent *content) {
const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content);
if (c->isFileTransfer()) {
const LinphonePrivate::FileTransferContent *ftc = static_cast<const LinphonePrivate::FileTransferContent *>(c);
return ftc->getFileAuthTag().data();
}
return nullptr;
}
size_t linphone_content_get_authTag_size (const LinphoneContent *content) {
const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content);
if (c->isFileTransfer()) {
const LinphonePrivate::FileTransferContent *ftc = static_cast<const LinphonePrivate::FileTransferContent *>(c);
return ftc->getFileAuthTagSize();
}
return 0;
}
void linphone_content_set_authTag (LinphoneContent *content, const char *tag, const size_t tagLength) {
LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content);
if (c->isFileTransfer()) {
LinphonePrivate::FileTransferContent *ftc = static_cast<LinphonePrivate::FileTransferContent *>(c);
ftc->setFileAuthTag(tag, tagLength);
}
}
const char *linphone_content_get_file_path (const LinphoneContent *content) {
const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content);
if (c->isFile())
......
......@@ -32,6 +32,8 @@
LINPHONE_BEGIN_NAMESPACE
#define ERROR_FILE_TRANFER_AUTHENTICATION_FAILED -0x1001
class AbstractChatRoom;
class ChatMessage;
......@@ -62,7 +64,8 @@ public:
virtual void generateFileTransferKey (
const std::shared_ptr<AbstractChatRoom> &ChatRoom,
const std::shared_ptr<ChatMessage> &message
const std::shared_ptr<ChatMessage> &message,
FileTransferContent *fileTransferContent
) {}
virtual int downloadingFile (
......@@ -70,7 +73,8 @@ public:
size_t offset,
const uint8_t *buffer,
size_t size,
uint8_t *decryptedBuffer
uint8_t *decryptedBuffer,
FileTransferContent *fileTransferContent
) { return 0; }
virtual int uploadingFile (
......@@ -78,7 +82,8 @@ public:
size_t offset,
const uint8_t *buffer,
size_t *size,
uint8_t *encryptedBuffer
uint8_t *encryptedBuffer,
FileTransferContent *fileTransferContent
) { return 0; }
virtual void mutualAuthentication (
......
......@@ -100,7 +100,7 @@ bool LegacyEncryptionEngine::isEncryptionEnabledForFileTransfer (const shared_pt
return false;
}
void LegacyEncryptionEngine::generateFileTransferKey (const shared_ptr<AbstractChatRoom> &chatRoom, const shared_ptr<ChatMessage> &message) {
void LegacyEncryptionEngine::generateFileTransferKey (const shared_ptr<AbstractChatRoom> &chatRoom, const shared_ptr<ChatMessage> &message, FileTransferContent *fileTransferContent) {
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb =
......@@ -110,7 +110,7 @@ void LegacyEncryptionEngine::generateFileTransferKey (const shared_ptr<AbstractC
}
}
int LegacyEncryptionEngine::downloadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decryptedBuffer) {
int LegacyEncryptionEngine::downloadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decryptedBuffer, FileTransferContent *fileTransferContent) {
shared_ptr<AbstractChatRoom> chatRoom = message->getChatRoom();
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
......@@ -121,7 +121,7 @@ int LegacyEncryptionEngine::downloadingFile (const shared_ptr<ChatMessage> &mess
return -1;
}
int LegacyEncryptionEngine::uploadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encryptedBuffer) {
int LegacyEncryptionEngine::uploadingFile (const shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encryptedBuffer, FileTransferContent *fileTransferContent) {
shared_ptr<AbstractChatRoom> chatRoom = message->getChatRoom();
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore());
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
......
......@@ -33,9 +33,9 @@ public:
ChatMessageModifier::Result processIncomingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) override;
ChatMessageModifier::Result processOutgoingMessage (const std::shared_ptr<ChatMessage> &message, int &errorCode) override;
bool isEncryptionEnabledForFileTransfer (const std::shared_ptr<AbstractChatRoom> &ChatRoom) override;
void generateFileTransferKey (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message) override;
int downloadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) override;
int uploadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer) override;
void generateFileTransferKey (const std::shared_ptr<AbstractChatRoom> &ChatRoom, const std::shared_ptr<ChatMessage> &message, FileTransferContent *fileTransferContent) override;
int downloadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer, FileTransferContent *fileTransferContent) override;
int uploadingFile (const std::shared_ptr<ChatMessage> &message, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer, FileTransferContent *fileTransferContent) override;
};
LINPHONE_END_NAMESPACE
......
......@@ -447,22 +447,18 @@ bool LimeX3dhEncryptionEngine::isEncryptionEnabledForFileTransfer (const shared_
return (chatRoom->getCapabilities() & ChatRoom::Capabilities::Encrypted);
}
#define FILE_TRANSFER_AUTH_TAG_SIZE 16
#define FILE_TRANSFER_KEY_SIZE 32
void LimeX3dhEncryptionEngine::generateFileTransferKey (
const shared_ptr<AbstractChatRoom> &chatRoom,
const shared_ptr<ChatMessage> &message
const shared_ptr<ChatMessage> &message,
FileTransferContent *fileTransferContent
) {
#define FILE_TRANSFER_KEY_SIZE 32
char keyBuffer [FILE_TRANSFER_KEY_SIZE];// temporary storage of generated key: 192 bits of key + 64 bits of initial vector
// generate a random 192 bits key + 64 bits of initial vector and store it into the file_transfer_information->key field of the msg
sal_get_random_bytes((unsigned char *)keyBuffer, FILE_TRANSFER_KEY_SIZE);
for (Content *content : message->getContents()) {
if (content->isFileTransfer()) {
FileTransferContent *fileTransferContent = static_cast<FileTransferContent *>(content);
fileTransferContent->setFileKey(keyBuffer, FILE_TRANSFER_KEY_SIZE);
return;
}
}
fileTransferContent->setFileKey(keyBuffer, FILE_TRANSFER_KEY_SIZE);
}
int LimeX3dhEncryptionEngine::downloadingFile (
......@@ -470,20 +466,37 @@ int LimeX3dhEncryptionEngine::downloadingFile (
size_t offset,
const uint8_t *buffer,
size_t size,
uint8_t *decrypted_buffer
uint8_t *decrypted_buffer,
FileTransferContent *fileTransferContent
) {
const Content *content = message->getPrivate()->getFileTransferContent();
if (!content)
if (fileTransferContent == nullptr)
return -1;
const FileTransferContent *fileTransferContent = static_cast<const FileTransferContent *>(content);
Content *content = static_cast<Content *>(fileTransferContent);
const char *fileKey = fileTransferContent->getFileKey().data();
if (!fileKey)
return -1;
if (!buffer || size == 0)
return bctbx_aes_gcm_decryptFile(linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)), NULL, 0, NULL, NULL);
if (!buffer) {
// get the authentication tag
char authTag[FILE_TRANSFER_AUTH_TAG_SIZE]; // store the authentication tag generated at the end of decryption
int ret = bctbx_aes_gcm_decryptFile(linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)), NULL, FILE_TRANSFER_AUTH_TAG_SIZE, authTag, NULL);
if (ret<0) return ret;
// compare auth tag if we have one
const size_t fileAuthTagSize = fileTransferContent->getFileAuthTagSize();
if (fileAuthTagSize == FILE_TRANSFER_AUTH_TAG_SIZE) {
const char *fileAuthTag = fileTransferContent->getFileAuthTag().data();
if (memcmp(authTag, fileAuthTag, FILE_TRANSFER_AUTH_TAG_SIZE) != 0) {
lError()<<"download encrypted file : authentication failure";
return ERROR_FILE_TRANFER_AUTHENTICATION_FAILED;
} else {
return ret;
}
} else {
lWarning()<<"download encrypted file : no authentication Tag";
return 0;
}
}
return bctbx_aes_gcm_decryptFile(
linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)),
......@@ -492,8 +505,6 @@ int LimeX3dhEncryptionEngine::downloadingFile (
(char *)decrypted_buffer,
(char *)buffer
);
return 0;
}
int LimeX3dhEncryptionEngine::uploadingFile (
......@@ -501,20 +512,24 @@ int LimeX3dhEncryptionEngine::uploadingFile (
size_t offset,
const uint8_t *buffer,
size_t *size,
uint8_t *encrypted_buffer
uint8_t *encrypted_buffer,
FileTransferContent *fileTransferContent
) {
const Content *content = message->getPrivate()->getFileTransferContent();
if (!content)
if (fileTransferContent == nullptr)
return -1;
const FileTransferContent *fileTransferContent = dynamic_cast<const FileTransferContent *>(content);
Content *content = static_cast<Content *>(fileTransferContent);
const char *fileKey = fileTransferContent->getFileKey().data();
if (!fileKey)
return -1;
if (!buffer || *size == 0)
return bctbx_aes_gcm_encryptFile(linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)), NULL, 0, NULL, NULL);
/* This is the final call, get an auth tag and insert it in the fileTransferContent*/
if (!buffer || *size == 0) {
char authTag[FILE_TRANSFER_AUTH_TAG_SIZE]; // store the authentication tag generated at the end of encryption, size is fixed at 16 bytes
int ret = bctbx_aes_gcm_encryptFile(linphone_content_get_cryptoContext_address(L_GET_C_BACK_PTR(content)), NULL, FILE_TRANSFER_AUTH_TAG_SIZE, NULL, authTag);
fileTransferContent->setFileAuthTag(authTag, 16);
return ret;
}
size_t file_size = fileTransferContent->getFileSize();
if (file_size == 0) {
......
......@@ -93,7 +93,8 @@ public:
void generateFileTransferKey (
const std::shared_ptr<AbstractChatRoom> &ChatRoom,
const std::shared_ptr<ChatMessage> &message
const std::shared_ptr<ChatMessage> &message,
FileTransferContent *fileTransferContent
) override;
int downloadingFile (
......@@ -101,7 +102,8 @@ public:
size_t offset,
const uint8_t *buffer,
size_t size,
uint8_t *decrypted_buffer
uint8_t *decrypted_buffer,
FileTransferContent *fileTransferContent
) override;
int uploadingFile (
......@@ -109,7 +111,8 @@ public:
size_t offset,
const uint8_t *buffer,
size_t *size,
uint8_t *encrypted_buffer
uint8_t *encrypted_buffer,
FileTransferContent *fileTransferContent
) override;
void mutualAuthentication (
......
......@@ -78,6 +78,7 @@ private:
std::weak_ptr<ChatMessage> chatMessage;
FileContent* currentFileContentToTransfer = nullptr;
FileTransferContent *currentFileTransferContent = nullptr;
belle_http_request_t *httpRequest = nullptr;
belle_http_request_listener_t *httpListener = nullptr;
......
......@@ -589,7 +589,7 @@ void MediaSessionPrivate::setRemoteParams (MediaSessionParams *msp) {
}
MediaStream *MediaSessionPrivate::getMediaStream (LinphoneStreamType type) const {
return getMediaStream(int(type));
return getMediaStream(getStreamIndex(type));
}
int MediaSessionPrivate::getRtcpPort (LinphoneStreamType type) const {
......@@ -615,7 +615,14 @@ LinphoneCallStats * MediaSessionPrivate::getStats (LinphoneStreamType type) cons
}
int MediaSessionPrivate::getStreamIndex (LinphoneStreamType type) const {
return getStreamIndex(getMediaStream(type));
switch (type) {
case LinphoneStreamTypeAudio: return mainAudioStreamIndex;
case LinphoneStreamTypeVideo: return mainVideoStreamIndex;
case LinphoneStreamTypeText: return mainTextStreamIndex;
case LinphoneStreamTypeUnknown: break;
}
lError() << __func__ << "(LinphoneStreamType): invalid stream type [" << type << "]";
return -1;
}
int MediaSessionPrivate::getStreamIndex (MediaStream *ms) const {
......
......@@ -235,4 +235,12 @@ list<Header>::const_iterator Content::findHeader (const string &headerName) cons
});
}
void Content::setUserData(const Variant &userData) {
setProperty("LinphonePrivate::Content::userData", userData);
}
Variant Content::getUserData() const {
return getProperty("LinphonePrivate::Content::userData");
}
LINPHONE_END_NAMESPACE
......@@ -90,6 +90,9 @@ public:
void removeHeader (const std::string &headerName);
std::list<Header>::const_iterator findHeader (const std::string &headerName) const;
void setUserData(const Variant &userData);
Variant getUserData() const;
protected:
explicit Content (ContentPrivate &p);
......
......@@ -39,6 +39,7 @@ public:
FileContent *fileContent = nullptr;
size_t fileSize = 0;
std::vector<char> fileKey;
std::vector<char> fileAuthTag;
};
// -----------------------------------------------------------------------------
......@@ -56,6 +57,7 @@ FileTransferContent::FileTransferContent (const FileTransferContent &other) : Co
d->fileContent = other.getFileContent();
d->fileSize = other.getFileSize();
d->fileKey = other.getFileKey();
d->fileAuthTag = other.getFileAuthTag();
}
FileTransferContent::FileTransferContent (FileTransferContent &&other) : Content(*new FileTransferContentPrivate) {
......@@ -67,6 +69,7 @@ FileTransferContent::FileTransferContent (FileTransferContent &&other) : Content
d->fileContent = move(other.getPrivate()->fileContent);
d->fileSize = move(other.getPrivate()->fileSize);
d->fileKey = move(other.getPrivate()->fileKey);
d->fileAuthTag = move(other.getPrivate()->fileAuthTag);
}
FileTransferContent &FileTransferContent::operator= (const FileTransferContent &other) {
......@@ -79,6 +82,7 @@ FileTransferContent &FileTransferContent::operator= (const FileTransferContent &
d->fileContent = other.getFileContent();
d->fileSize = other.getFileSize();
d->fileKey = other.getFileKey();
d->fileAuthTag = other.getFileAuthTag();
}
return *this;
......@@ -93,6 +97,7 @@ FileTransferContent &FileTransferContent::operator= (FileTransferContent &&other
d->fileContent = move(other.getPrivate()->fileContent);
d->fileSize = move(other.getPrivate()->fileSize);
d->fileKey = move(other.getPrivate()->fileKey);
d->fileAuthTag = move(other.getPrivate()->fileAuthTag);
return *this;
}
......@@ -171,6 +176,21 @@ size_t FileTransferContent::getFileKeySize() const {
return d->fileKey.size();
}
void FileTransferContent::setFileAuthTag (const char *tag, size_t size) {
L_D();
d->fileAuthTag = vector<char>(tag, tag + size);
}
const vector<char> &FileTransferContent::getFileAuthTag () const {
L_D();
return d->fileAuthTag;
}
size_t FileTransferContent::getFileAuthTagSize() const {
L_D();
return d->fileAuthTag.size();
}
bool FileTransferContent::isFile () const {
return false;
}
......
......@@ -65,6 +65,10 @@ public:
const std::vector<char> &getFileKey () const;
size_t getFileKeySize() const;
void setFileAuthTag (const char *authTag, size_t size);
const std::vector<char> &getFileAuthTag () const;
size_t getFileAuthTagSize() const;
bool isFile () const override;
bool isFileTransfer () const override;
......
......@@ -396,7 +396,10 @@ void IosPlatformHelpers::networkChangeCallback() {
reachable = isReachable(flags);
if (flags != mCurrentFlags || reachable != isNetworkReachable()) {
changed = true;
if (mCurrentFlags == 0) {
if (mCurrentFlags == 0
||
/*check if moving from Wifi to cellular*/
(mCurrentFlags & kSCNetworkReachabilityFlagsIsWWAN) != (flags & kSCNetworkReachabilityFlagsIsWWAN)) {
//Force reinit after network down
force = true;
}
......
......@@ -205,7 +205,7 @@ const list<shared_ptr<DialPlan>> DialPlan::DialPlans = {
DialPlan::create("Portugal", "PT", "351", 9, "00"),
DialPlan::create("Puerto Rico", "PR", "1", 10, "011"),
DialPlan::create("Qatar", "QA", "974", 8, "00"),
DialPlan::create("Runion Island", "RE", "262", 9, "011"),
DialPlan::create("Reunion Island", "RE", "262", 9, "011"),
DialPlan::create("Romania", "RO", "40", 9, "00"),
DialPlan::create("Russian Federation", "RU", "7", 10, "8"),
DialPlan::create("Rwanda", "RW", "250", 9, "00"),
......
......@@ -24,6 +24,8 @@
#include <bctoolbox/defs.h>
#include <belle-sip/provider.h>
#include "linphone/utils/utils.h"
using namespace std;
LINPHONE_BEGIN_NAMESPACE
......@@ -162,7 +164,8 @@ int SalCallOp::setSdpFromDesc (belle_sip_message_t *msg, const SalMediaDescripti
void SalCallOp::fillInvite (belle_sip_request_t *invite) {
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite), BELLE_SIP_HEADER(createAllow(mRoot->mEnableSipUpdate)));
if (mRoot->mSessionExpires != 0) {
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite), belle_sip_header_create("Session-expires", "600;refresher=uas"));
string sessionExpires = Utils::toString(mRoot->mSessionExpires) + ";refresher=uas";
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite), belle_sip_header_create("Session-expires", sessionExpires.c_str()));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite), belle_sip_header_create("Supported", "timer"));
}
mSdpOffering = (mLocalBody.getContentType() == ContentType::Sdp);
......@@ -980,8 +983,9 @@ int SalCallOp::accept () {
}
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response), BELLE_SIP_HEADER(createAllow(mRoot->mEnableSipUpdate)));
if (mRoot->mSessionExpires != 0) {
string sessionExpires = Utils::toString(mRoot->mSessionExpires) + ";refresher=uac";
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response), belle_sip_header_create("Supported", "timer"));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response), belle_sip_header_create( "Session-expires", "600;refresher=uac"));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response), belle_sip_header_create( "Session-expires", sessionExpires.c_str()));
}
auto contactHeader = createContact();
......@@ -1371,14 +1375,17 @@ void SalCallOp::sendVfuRequest () {
}
}
int SalCallOp::sendNotifyForRefer (int code, const string &reason) {
int SalCallOp::sendNotifyForRefer (int code, const string &reason, const std::string & subscription_state, const std::string &subscription_state_reason) {
auto notifyRequest = belle_sip_dialog_create_queued_request(mDialog, "NOTIFY");
char *sipfrag = belle_sip_strdup_printf("SIP/2.0 %i %s\r\n", code, reason.c_str());
size_t contentLength = strlen(sipfrag);
belle_sip_header_subscription_state_t *subsription_state_header = belle_sip_header_subscription_state_create(subscription_state.c_str(), -1);
if (!subscription_state_reason.empty()) {
belle_sip_header_subscription_state_set_reason(subsription_state_header, subscription_state_reason.c_str());
}
belle_sip_message_add_header(
BELLE_SIP_MESSAGE(notifyRequest),
BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE, -1))
BELLE_SIP_HEADER(subsription_state_header)
);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notifyRequest), belle_sip_header_create("Event", "refer"));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notifyRequest), BELLE_SIP_HEADER(belle_sip_header_content_type_create("message", "sipfrag")));
......@@ -1408,7 +1415,7 @@ int SalCallOp::notifyReferState (SalCallOp *newCallOp) {
sendNotifyForRefer(100, "Trying");
break;
case BELLE_SIP_DIALOG_CONFIRMED:
sendNotifyForRefer(200, "Ok");
sendNotifyForRefer(200, "Ok", "terminated", "reason=noresource");
break;
case BELLE_SIP_DIALOG_TERMINATED:
case BELLE_SIP_DIALOG_NULL:
......
......@@ -85,7 +85,7 @@ private:
void fillInvite (belle_sip_request_t *invite);
void cancellingInvite (const SalErrorInfo *info);
int referTo (belle_sip_header_refer_to_t *referToHeader, belle_sip_header_referred_by_t *referredByHeader);
int sendNotifyForRefer (int code, const std::string &reason);
int sendNotifyForRefer (int code, const std::string &reason,const std::string & subscription_state = BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE, const std::string & subscription_reason = "");
void notifyLastResponse (SalCallOp *newCallOp);
void processRefer (const belle_sip_request_event_t *event, belle_sip_server_transaction_t *serverTransaction);
void processNotify (const belle_sip_request_event_t *event, belle_sip_server_transaction_t *serverTransaction);
......
......@@ -77,8 +77,6 @@ SalOp::~SalOp () {
sal_address_unref(mContactAddress);
if (mRemoteContactAddress)
sal_address_unref(mRemoteContactAddress);
if (mServiceRoute)
sal_address_unref(mServiceRoute);
for (auto &addr : mRouteAddresses)
sal_address_unref(addr);
......@@ -370,6 +368,9 @@ int SalOp::processRedirect () {
belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(redirectUri), "transport");
belle_sip_header_to_t *toHeader = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_to_t);
belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(toHeader), redirectUri);
/* remove previously used authorization headers. */
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request), BELLE_SIP_AUTHORIZATION);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request), BELLE_SIP_PROXY_AUTHORIZATION);
sendRequest(request);
return 0;
}
......
......@@ -154,7 +154,7 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana
linphone_call_unref(c2);
}
void simple_call_base(bool_t enable_multicast_recv_side, bool_t disable_soundcard) {
void simple_call_base_2(bool_t enable_multicast_recv_side, bool_t disable_soundcard, bool_t use_session_expires) {
LinphoneCoreManager* marie;
LinphoneCoreManager* pauline;
const LinphoneAddress *from;
......@@ -165,7 +165,11 @@ void simple_call_base(bool_t enable_multicast_recv_side, bool_t disable_soundcar
ms_snd_card_manager_bypass_soundcard_detection(TRUE);
}
marie = linphone_core_manager_new( "marie_rc");
marie = linphone_core_manager_new("marie_rc");
if (use_session_expires) {
linphone_core_set_session_expires_value(marie->lc, 300);
}
pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
/* with the account manager, we might lose the identity */
......@@ -200,6 +204,15 @@ void simple_call_base(bool_t enable_multicast_recv_side, bool_t disable_soundcar
BC_ASSERT_STRING_EQUAL(dname, "Super Marie");
}
}
if (use_session_expires) {
const LinphoneCallParams *marie_remote_params=linphone_call_get_remote_params(pauline_call);
const char *value=linphone_call_params_get_custom_header(marie_remote_params,"Session-Expires");
BC_ASSERT_PTR_NOT_NULL(value);
if (value) {
BC_ASSERT_TRUE(strcmp(value, "300;refresher=uas")==0);
}
}
}
liblinphone_tester_check_rtcp(marie,pauline);
......@@ -212,6 +225,11 @@ void simple_call_base(bool_t enable_multicast_recv_side, bool_t disable_soundcar
}
}
void simple_call_base(bool_t enable_multicast_recv_side, bool_t disable_soundcard) {
simple_call_base_2(enable_multicast_recv_side, disable_soundcard, FALSE);
}
static void simple_call(void) {
simple_call_base(FALSE, FALSE);
}
......@@ -220,6 +238,10 @@ static void simple_call_without_soundcard(void) {
simple_call_base(FALSE, TRUE);
}
static void simple_call_with_session_expires(void) {
simple_call_base_2(FALSE, FALSE, TRUE);
}
/*This test is added to reproduce a crash when a call is failed synchronously*/
static void simple_call_with_no_sip_transport(void){
LinphoneCoreManager* marie;
......@@ -4985,6 +5007,45 @@ end:
linphone_core_manager_destroy(marie);
}
static void simple_call_with_dummy_audio(void) {
LinphoneCoreManager* marie;
LinphoneCoreManager* pauline;
LinphoneCall *pauline_call;
LinphoneCall *marie_call;
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_tcp_rc");
MSFactory *marie_factory = linphone_core_get_ms_factory(marie->lc);
MSSndCardManager *marie_sndcard_manager = ms_factory_get_snd_card_manager(marie_factory);
ms_snd_card_manager_add_card(marie_sndcard_manager, ms_dummy_audio_snd_card_new());
BC_ASSERT_TRUE(call(marie,pauline));
pauline_call=linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
wait_for_until(pauline->lc, marie->lc, NULL, 0, 2000);
// set DUMMY_AUDIO_SOUND_CARD
marie_call = linphone_core_get_current_call(marie->lc);
linphone_core_set_capture_device(marie->lc, DUMMY_AUDIO_SOUNDCARD);
linphone_core_set_playback_device(marie->lc, DUMMY_AUDIO_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_capture_device(marie->lc), DUMMY_AUDIO_SOUNDCARD);
BC_ASSERT_STRING_EQUAL(linphone_core_get_playback_device(marie->lc), DUMMY_AUDIO_SOUNDCARD);
if (BC_ASSERT_PTR_NOT_NULL(marie_call))
linphone_call_update(marie_call, NULL);
wait_for_until(pauline->lc, marie->lc, NULL, 0, 2000);
AudioStream *stream = (AudioStream *)linphone_call_get_stream(marie_call, LinphoneStreamTypeAudio);
BC_ASSERT_STRING_EQUAL(stream->soundread->desc->name, "MSVoidSource");
BC_ASSERT_STRING_EQUAL(stream->soundwrite->desc->name, "MSVoidSink");
wait_for_until(pauline->lc, marie->lc, NULL, 0, 2000);
end_call(marie,pauline);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
test_t call_tests[] = {
TEST_NO_TAG("Early declined call", early_declined_call),
TEST_NO_TAG("Call declined", call_declined),
......@@ -4998,6 +5059,7 @@ test_t call_tests[] = {
TEST_NO_TAG("Cancelled ringing call", cancelled_ringing_call),
TEST_NO_TAG("Call busy when calling self", call_busy_when_calling_self),
TEST_NO_TAG("Simple call", simple_call),
TEST_NO_TAG("Simple call with session expires", simple_call_with_session_expires),