diff --git a/CMakeLists.txt b/CMakeLists.txt index 508d4ef57..24d225847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,34 +38,43 @@ include(CMakeDependentOption) option(ENABLE_SHARED "Build shared library." YES) option(ENABLE_STATIC "Build static library." YES) + option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES) -option(ENABLE_DATE "Use build date in internal version number." NO) +option(ENABLE_CSHARP_WRAPPER "Build the C# wrapper for Liblinphone." OFF) +option(ENABLE_CXX_WRAPPER "Build the C++ wrapper for Liblinphone." YES) option(ENABLE_DAEMON "Enable the linphone daemon interface." YES) +option(ENABLE_DATE "Use build date in internal version number." NO) +option(ENABLE_DEBUG_LOGS "Turn on or off debug level logs." NO) option(ENABLE_DOC "Enable documentation generation with Doxygen." YES) -option(ENABLE_JAVADOC "Add a target to generate documentation for Java API" NO) option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." NO) +option(ENABLE_JAVADOC "Add a target to generate documentation for Java API" NO) option(ENABLE_LDAP "Enable LDAP support." NO) -option(ENABLE_SQLITE_STORAGE "Turn on compilation sqlite storage, for messages, contacts, history" YES) -cmake_dependent_option(ENABLE_LIME "Enable Instant Messaging Encryption." YES "ENABLE_SQLITE_STORAGE" NO) -cmake_dependent_option(ENABLE_NOTIFY "Enable libnotify support." YES "ENABLE_GTK_UI;NOT APPLE" NO) +option(ENABLE_NLS "Build with internationalisation support" YES) option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO) +option(ENABLE_ROOTCA_DOWNLOAD "Download rootca.pem at build time." YES) +option(ENABLE_SOCI_STORAGE "Turn on compilation soci storage, for messages, contacts, history" YES) +option(ENABLE_SQLITE_STORAGE "Turn on compilation sqlite storage, for messages, contacts, history" YES) option(ENABLE_STRICT "Build with strict compile options." YES) option(ENABLE_TOOLS "Turn on or off compilation of tools." YES) option(ENABLE_TUNNEL "Turn on compilation of tunnel support." NO) option(ENABLE_TUTORIALS "Enable compilation of tutorials." YES) option(ENABLE_UNIT_TESTS "Enable compilation of unit tests." YES) option(ENABLE_UPDATE_CHECK "Enable update check." NO) -option(ENABLE_VIDEO "Build with video support." YES) -cmake_dependent_option(ENABLE_ASSISTANT "Turn on assistant compiling." YES "ENABLE_GTK_UI" NO) -option(ENABLE_DEBUG_LOGS "Turn on or off debug level logs." NO) -option(ENABLE_NLS "Build with internationalisation support" YES) option(ENABLE_VCARD "Turn on compilation of vcard4 support." YES) -option(ENABLE_ROOTCA_DOWNLOAD "Download rootca.pem at build time." YES) -option(ENABLE_CXX_WRAPPER "Build the C++ wrapper for Liblinphone." YES) -option(ENABLE_CSHARP_WRAPPER "Build the C# wrapper for Liblinphone." OFF) +option(ENABLE_VIDEO "Build with video support." YES) + +cmake_dependent_option(ENABLE_LIME "Enable Instant Messaging Encryption." YES "ENABLE_SQLITE_STORAGE" NO) +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) set(CMAKE_CXX_STANDARD 11) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") +endif() + +set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") +set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG") if(ENABLE_STATIC) set(LINPHONE_LIBS_FOR_TOOLS linphone-static) @@ -125,7 +134,7 @@ else() endif() find_package(XML2 REQUIRED) find_package(LibXsd REQUIRED) -find_package(Soci REQUIRED) +find_package(Soci) find_package(Zlib) if(ENABLE_TUNNEL) if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS) @@ -258,7 +267,7 @@ if(LINPHONE_CPPFLAGS) endif() if(ENABLE_DEBUG_LOGS) - add_definitions("-DDEBUG") + add_definitions("-DDEBUG_LOGS") endif() set(STRICT_OPTIONS_CPP ) diff --git a/cmake/FindSoci.cmake b/cmake/FindSoci.cmake new file mode 100644 index 000000000..91c4e376d --- /dev/null +++ b/cmake/FindSoci.cmake @@ -0,0 +1,87 @@ +############################################################################### +# CMake module to search for SOCI library +# +# WARNING: This module is experimental work in progress. +# +# This module defines: +# SOCI_INCLUDE_DIRS = include dirs to be used when using the soci library +# SOCI_LIBRARIES = full path to the soci library +# SOCI_VERSION = the soci version found (not yet. soci does not provide that info.) +# SOCI_FOUND = true if soci was found +# +# For each component you specify in find_package(), the following variables are set. +# +# SOCI_${COMPONENT}_PLUGIN = full path to the soci plugin +# SOCI_${COMPONENT}_FOUND +# +# Copyright (c) 2011 Michael Jansen +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +############################################################################### +# +### Global Configuration Section +# +SET(_SOCI_ALL_PLUGINS mysql sqlite3) +SET(_SOCI_REQUIRED_VARS SOCI_INCLUDE_DIRS SOCI_LIBRARIES) + +# +### FIRST STEP: Find the soci headers. +# +FIND_PATH(SOCI_INCLUDE_DIRS soci/soci.h + DOC "Soci (http://soci.sourceforge.net) include directory") +MARK_AS_ADVANCED(SOCI_INCLUDE_DIRS) + +# +### SECOND STEP: Find the soci core library. Respect LIB_SUFFIX +# +FIND_LIBRARY(SOCI_LIBRARIES + NAMES soci_core + PATH_SUFFIXES lib lib64) +MARK_AS_ADVANCED(SOCI_LIBRARIES) + +GET_FILENAME_COMPONENT(SOCI_LIBRARY_DIR ${SOCI_LIBRARIES} PATH) +MARK_AS_ADVANCED(SOCI_LIBRARY_DIR) + +# +### THIRD STEP: Find all installed plugins if the library was found +# +IF(SOCI_INCLUDE_DIRS AND SOCI_LIBRARIES) + + MESSAGE(STATUS "Soci found: Looking for plugins") + FOREACH(plugin IN LISTS _SOCI_ALL_PLUGINS) + + FIND_LIBRARY( + SOCI_${plugin}_PLUGIN + NAMES soci_${plugin} + PATH_SUFFIXES lib lib64) + MARK_AS_ADVANCED(SOCI_${plugin}_PLUGIN) + + IF(SOCI_${plugin}_PLUGIN) + MESSAGE(STATUS " * Plugin ${plugin} found ${SOCI_${plugin}_PLUGIN}.") + SET(SOCI_${plugin}_FOUND True) + ELSE() + MESSAGE(STATUS " * Plugin ${plugin} not found.") + SET(SOCI_${plugin}_FOUND False) + ENDIF() + + ENDFOREACH() + + # + ### FOURTH CHECK: Check if the required components were all found + # + FOREACH(component ${Soci_FIND_COMPONENTS}) + IF(NOT SOCI_${component}_FOUND) + MESSAGE(SEND_ERROR "Required component ${component} not found. It seems that Soci was built without support of ${component}, consider rebuilding it.") + ENDIF() + ENDFOREACH() + +ENDIF() + +# +### ADHERE TO STANDARDS +# +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Soci DEFAULT_MSG ${_SOCI_REQUIRED_VARS}) + diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 453f35935..88c78b589 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -159,7 +159,6 @@ set(LIBS ${XML2_LIBRARIES} ${BELR_LIBRARIES} ${LIBXSD_LIBRARIES} - ${SOCI_LIBRARY} ) if(WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") list(APPEND LIBS "Ws2_32") @@ -170,6 +169,9 @@ endif() if(ZLIB_FOUND) list(APPEND LIBS ${ZLIB_LIBRARIES}) endif() +if(SOCI_FOUND) + list(APPEND LIBS ${SOCI_LIBRARIES}) +endif() if(SQLITE3_FOUND) list(APPEND LIBS ${SQLITE3_LIBRARIES}) endif() diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index c6803481b..4aa2c1fb8 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -59,31 +59,6 @@ void sal_op_set_privacy_from_message(SalOp* op,belle_sip_message_t* msg) { } static void set_tls_properties(Sal *ctx); -void _belle_sip_log(const char *domain, belle_sip_log_level lev, const char *fmt, va_list args) { - OrtpLogLevel ortp_level; - switch(lev) { - case BELLE_SIP_LOG_FATAL: - ortp_level=ORTP_FATAL; - break; - case BELLE_SIP_LOG_ERROR: - ortp_level=ORTP_ERROR; - break; - case BELLE_SIP_LOG_WARNING: - ortp_level=ORTP_WARNING; - break; - case BELLE_SIP_LOG_MESSAGE: - ortp_level=ORTP_MESSAGE; - break; - case BELLE_SIP_LOG_DEBUG: - default: - ortp_level=ORTP_DEBUG; - break; - } - if (ortp_log_level_enabled("belle-sip", ortp_level)){ - ortp_logv("belle-sip", ortp_level,fmt,args); - } -} - void sal_enable_log(){ sal_set_log_level(ORTP_MESSAGE); } @@ -93,24 +68,31 @@ void sal_disable_log() { } void sal_set_log_level(OrtpLogLevel level) { - belle_sip_log_level belle_sip_level; + belle_sip_log_level belle_sip_level = BELLE_SIP_LOG_MESSAGE; if ((level&ORTP_FATAL) != 0) { belle_sip_level = BELLE_SIP_LOG_FATAL; - } else if ((level&ORTP_ERROR) != 0) { + } + if ((level&ORTP_ERROR) != 0) { belle_sip_level = BELLE_SIP_LOG_ERROR; - } else if ((level&ORTP_WARNING) != 0) { + } + if ((level&ORTP_WARNING) != 0) { belle_sip_level = BELLE_SIP_LOG_WARNING; - } else if ((level&ORTP_MESSAGE) != 0) { - belle_sip_level = BELLE_SIP_LOG_MESSAGE; - } else if (((level&ORTP_DEBUG) != 0) || ((level&ORTP_TRACE) != 0)) { - belle_sip_level = BELLE_SIP_LOG_DEBUG; - } else { - //well, this should never occurs but... + } + if ((level&ORTP_MESSAGE) != 0) { belle_sip_level = BELLE_SIP_LOG_MESSAGE; } + if (((level&ORTP_DEBUG) != 0) || ((level&ORTP_TRACE) != 0)) { + belle_sip_level = BELLE_SIP_LOG_DEBUG; + } + belle_sip_set_log_level(belle_sip_level); } +static BctbxLogFunc _belle_sip_log_handler = bctbx_logv_out; +void sal_set_log_handler(BctbxLogFunc log_handler) { + _belle_sip_log_handler = log_handler; + belle_sip_set_log_handler(log_handler); +} void sal_add_pending_auth(Sal *sal, SalOp *op){ if (bctbx_list_find(sal->pending_auths,op)==NULL){ sal->pending_auths=bctbx_list_append(sal->pending_auths,op); @@ -505,7 +487,7 @@ Sal * sal_init(MSFactory *factory){ sal->auto_contacts=TRUE; sal->factory = factory; /*first create the stack, which initializes the belle-sip object's pool for this thread*/ - belle_sip_set_log_handler(_belle_sip_log); + belle_sip_set_log_handler(_belle_sip_log_handler); //printf by default sal->stack = belle_sip_stack_new(NULL); sal->user_agent=belle_sip_header_user_agent_new(); diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index 1d0ccbb3e..3526152e0 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -48,8 +48,17 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher if (service_route_address) belle_sip_object_unref(service_route_address); sal_remove_pending_auth(op->base.root,op); /*just in case*/ + if (contact) { - sal_op_set_contact_address(op,(SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ + const char *gruu; + belle_sip_parameters_t* p = (BELLE_SIP_PARAMETERS(contact)); + if((gruu = belle_sip_parameters_get_parameter(p, "pub-gruu"))) { + char *unquoted = belle_sip_unquote_strdup(gruu); + sal_op_set_contact_address(op, (SalAddress*)belle_sip_header_address_parse(unquoted)); + belle_sip_parameters_remove_parameter(p, "pub-gruu"); + } else { + sal_op_set_contact_address(op, (SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ + } } op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0); } else if (status_code>=400) { diff --git a/coreapi/dial_plan.c b/coreapi/dial_plan.c index 85c652fe8..327521377 100644 --- a/coreapi/dial_plan.c +++ b/coreapi/dial_plan.c @@ -60,7 +60,7 @@ static LinphoneDialPlan const dial_plans[]={ {"Burkina Faso" ,"BF" , "226" , 8 , "00" }, {"Burundi" ,"BI" , "257" , 8 , "011" }, {"Cambodia" ,"KH" , "855" , 9 , "00" }, - {"Cameroon" ,"CM" , "237" , 8 , "00" }, + {"Cameroon" ,"CM" , "237" , 9 , "00" }, {"Canada" ,"CA" , "1" , 10 , "011" }, {"Cape Verde" ,"CV" , "238" , 7 , "00" }, {"Cayman Islands" ,"KY" , "1" , 10 , "011" }, @@ -168,7 +168,7 @@ static LinphoneDialPlan const dial_plans[]={ {"Montserrat" ,"MS" , "664" , 10 , "011" }, {"Morocco" ,"MA" , "212" , 9 , "00" }, {"Mozambique" ,"MZ" , "258" , 9 , "00" }, - {"Myanmar" ,"MM" , "95" , 8 , "00" }, + {"Myanmar" ,"MM" , "95" , 10 , "00" }, {"Namibia" ,"NA" , "264" , 9 , "00" }, {"Nauru" ,"NR" , "674" , 7 , "00" }, {"Nepal" ,"NP" , "43" , 10 , "00" }, diff --git a/coreapi/help/examples/C/CMakeLists.txt b/coreapi/help/examples/C/CMakeLists.txt index af59a648a..84a5b38d5 100644 --- a/coreapi/help/examples/C/CMakeLists.txt +++ b/coreapi/help/examples/C/CMakeLists.txt @@ -29,7 +29,7 @@ if (ENABLE_TOOLS) string(REPLACE ".c" "" EXECUTABLE_NAME ${EXECUTABLE}) bc_apply_compile_flags(${EXECUTABLE} STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(${EXECUTABLE_NAME} ${USE_BUNDLE} ${EXECUTABLE}) - target_link_libraries(${EXECUTABLE_NAME} ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES}) + target_link_libraries(${EXECUTABLE_NAME} ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") if (NOT IOS) install(TARGETS ${EXECUTABLE_NAME} diff --git a/coreapi/help/examples/C/buddy_status.c b/coreapi/help/examples/C/buddy_status.c index 905162214..98149b951 100644 --- a/coreapi/help/examples/C/buddy_status.c +++ b/coreapi/help/examples/C/buddy_status.c @@ -107,8 +107,8 @@ int main(int argc, char *argv[]){ password=argv[3]; } signal(SIGINT,stop); -//#define DEBUG -#ifdef DEBUG +//#define DEBUG_LOGS +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif /* diff --git a/coreapi/help/examples/C/chatroom.c b/coreapi/help/examples/C/chatroom.c index 52a71faab..ad21d3399 100644 --- a/coreapi/help/examples/C/chatroom.c +++ b/coreapi/help/examples/C/chatroom.c @@ -59,8 +59,8 @@ int main(int argc, char *argv[]){ } signal(SIGINT,stop); -//#define DEBUG -#ifdef DEBUG +//#define DEBUG_LOGS +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif /* diff --git a/coreapi/help/examples/C/filetransfer.c b/coreapi/help/examples/C/filetransfer.c index e461aafa2..485c0a662 100644 --- a/coreapi/help/examples/C/filetransfer.c +++ b/coreapi/help/examples/C/filetransfer.c @@ -133,8 +133,8 @@ int main(int argc, char *argv[]){ big_file[sizeof(big_file)-1]=*"E"; signal(SIGINT,stop); -//#define DEBUG -#ifdef DEBUG +//#define DEBUG_LOGS +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif vtable.message_received=message_received; diff --git a/coreapi/help/examples/C/helloworld.c b/coreapi/help/examples/C/helloworld.c index 19f433eab..8da3b227f 100644 --- a/coreapi/help/examples/C/helloworld.c +++ b/coreapi/help/examples/C/helloworld.c @@ -79,7 +79,7 @@ int main(int argc, char *argv[]){ signal(SIGINT,stop); -#ifdef DEBUG +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif /* diff --git a/coreapi/help/examples/C/notify.c b/coreapi/help/examples/C/notify.c index 8ebbc3e82..9f20cdb1c 100644 --- a/coreapi/help/examples/C/notify.c +++ b/coreapi/help/examples/C/notify.c @@ -34,7 +34,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ -#define DEBUG 1 +#define DEBUG_LOGS 1 #include "linphone/core.h" @@ -102,7 +102,7 @@ int main(int argc, char *argv[]){ signal(SIGINT,stop); -#ifdef DEBUG +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif /* diff --git a/coreapi/help/examples/C/realtimetext_receiver.c b/coreapi/help/examples/C/realtimetext_receiver.c index 9d8acf5dc..3915749a8 100644 --- a/coreapi/help/examples/C/realtimetext_receiver.c +++ b/coreapi/help/examples/C/realtimetext_receiver.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]){ signal(SIGINT,stop); -#ifdef DEBUG +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif /* diff --git a/coreapi/help/examples/C/realtimetext_sender.c b/coreapi/help/examples/C/realtimetext_sender.c index d765a6768..340ad7de2 100644 --- a/coreapi/help/examples/C/realtimetext_sender.c +++ b/coreapi/help/examples/C/realtimetext_sender.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]){ signal(SIGINT,stop); -#ifdef DEBUG +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif diff --git a/coreapi/help/examples/C/registration.c b/coreapi/help/examples/C/registration.c index 318723323..66667bc05 100644 --- a/coreapi/help/examples/C/registration.c +++ b/coreapi/help/examples/C/registration.c @@ -76,7 +76,7 @@ int main(int argc, char *argv[]){ signal(SIGINT,stop); -#ifdef DEBUG +#ifdef DEBUG_LOGS linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif /* diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 4471af2f1..c455c68e2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -4983,13 +4983,7 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , void linphone_call_set_contact_op(LinphoneCall* call) { LinphoneAddress *contact; contact=get_fixed_contact(call->core,call,call->dest_proxy); - if (contact){ - SalTransport tport=sal_address_get_transport((SalAddress*)contact); - sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/ - sal_address_set_transport((SalAddress*)contact,tport); - sal_op_set_contact_address(call->op, contact); - linphone_address_unref(contact); - } + sal_op_set_and_clean_contact_address(call->op, (SalAddress *)contact); } LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 01f4b5983..a89923637 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -469,7 +469,9 @@ void linphone_core_set_log_handler(OrtpLogFunc logfunc) { void linphone_core_set_log_file(FILE *file) { if (file == NULL) file = stdout; - ortp_set_log_file(file); + bctbx_set_log_file(file); /*gather everythings*/ + sal_set_log_handler(NULL); /*disable default log handler*/ + ortp_set_log_handler(NULL); /*disable default log handler*/ } void linphone_core_set_log_level(OrtpLogLevel loglevel) { @@ -498,15 +500,13 @@ void linphone_core_set_log_level(OrtpLogLevel loglevel) { } void linphone_core_set_log_level_mask(unsigned int loglevel) { - ortp_set_log_level_mask(NULL, loglevel); - bctbx_set_log_level_mask(NULL, loglevel); - if (loglevel == 0) { - sal_disable_log(); - } else { - sal_enable_log(); - } + //we only have 2 domain for now ortp and belle-sip + bctbx_set_log_level_mask(ORTP_LOG_DOMAIN, loglevel); + sal_set_log_level((OrtpLogLevel)loglevel); +} +unsigned int linphone_core_get_log_level_mask(void) { + return bctbx_get_log_level_mask(ORTP_LOG_DOMAIN); } - static int _open_log_collection_file_with_idx(int idx) { struct stat statbuf; char *log_filename; @@ -1388,7 +1388,7 @@ static void sip_config_read(LinphoneCore *lc) { sal_enable_sip_update_method(lc->sal,lp_config_get_int(lc->config,"sip","sip_update",1)); lc->sip_conf.vfu_with_info=lp_config_get_int(lc->config,"sip","vfu_with_info",1); linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000)); - sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound")); + sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound, gruu")); lc->sip_conf.save_auth_info = lp_config_get_int(lc->config, "sip", "save_auth_info", 1); linphone_core_create_im_notif_policy(lc); } @@ -3512,14 +3512,9 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy)); if (with_contact && proxy && proxy->op){ const SalAddress *contact; - if ((contact=sal_op_get_contact_address(proxy->op))){ - SalTransport tport=sal_address_get_transport((SalAddress*)contact); - SalAddress *new_contact=sal_address_clone(contact); - sal_address_clean(new_contact); /* clean out contact_params that come from proxy config*/ - sal_address_set_transport(new_contact,tport); - sal_op_set_contact_address(op,new_contact); - sal_address_destroy(new_contact); - } + contact=sal_op_get_contact_address(proxy->op); + SalAddress *new_contact = contact ? sal_address_clone(contact) : NULL; + sal_op_set_and_clean_contact_address(proxy->op, new_contact); } sal_op_cnx_ip_to_0000_if_sendonly_enable(op,lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0)); /*also set in linphone_call_new_incoming*/ } diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 5f730ca0c..c6f063c54 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -4284,6 +4284,15 @@ extern "C" jobject Java_org_linphone_core_LinphoneFriendImpl_getCore(JNIEnv* en return NULL; } +extern "C" jstring Java_org_linphone_core_LinphoneFriendImpl_getVcardToString(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + LinphoneFriend *lf = (LinphoneFriend*)ptr; + LinphoneVcard *lvc = linphone_friend_get_vcard(lf); + const char* vcard = linphone_vcard_as_vcard4_string(lvc); + return vcard ? env->NewStringUTF(vcard) : NULL; +} + extern "C" jobject Java_org_linphone_core_LinphoneFriendListImpl_getCore(JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -7846,6 +7855,21 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallImpl_setListener(JNIEn linphone_call_set_next_video_frame_decoded_callback(call, _next_video_frame_decoded_callback, listener); } +extern "C" void Java_org_linphone_core_LinphoneCallImpl_setVideoWindowId(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jobject obj) { + jobject oldWindow = (jobject) linphone_call_get_native_video_window_id((LinphoneCall*)lc); + if (obj != NULL) { + obj = env->NewGlobalRef(obj); + ms_message("Java_org_linphone_core_LinphoneCallImpl_setVideoWindowId(): NewGlobalRef(%p)",obj); + }else ms_message("Java_org_linphone_core_LinphoneCallImpl_setVideoWindowId(): setting to NULL"); + linphone_call_set_native_video_window_id((LinphoneCall*)lc,(void *)obj); + if (oldWindow != NULL) { + ms_message("Java_org_linphone_core_LinphoneCallImpl_setVideoWindowId(): DeleteGlobalRef(%p)",oldWindow); + env->DeleteGlobalRef(oldWindow); + } +} /* * returns the java TunnelConfig associated with a C LinphoneTunnelConfig. diff --git a/coreapi/sal.c b/coreapi/sal.c index b52557aad..3870e59e3 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -517,6 +517,20 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress *address){ if (((SalOpBase*)op)->contact_address) sal_address_destroy(((SalOpBase*)op)->contact_address); ((SalOpBase*)op)->contact_address=address?sal_address_clone(address):NULL; } + +void sal_op_set_and_clean_contact_address(SalOp *op, SalAddress *contact) { + if (contact){ + SalTransport tport = sal_address_get_transport((SalAddress*)contact); + const char* gruu = bctbx_strdup(sal_address_get_uri_param(contact, "gr")); + sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/ + sal_address_set_transport((SalAddress*)contact,tport); + if(gruu) + sal_address_set_uri_param(contact, "gr", gruu); + sal_op_set_contact_address(op, contact); + sal_address_unref(contact); + } +} + const SalAddress* sal_op_get_contact_address(const SalOp *op) { return ((SalOpBase*)op)->contact_address; } diff --git a/coreapi/video_definition.c b/coreapi/video_definition.c index 57329d154..d193d0363 100644 --- a/coreapi/video_definition.c +++ b/coreapi/video_definition.c @@ -101,8 +101,9 @@ void linphone_video_definition_set_name(LinphoneVideoDefinition *vdef, const cha } bool_t linphone_video_definition_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2) { - return (((vdef1->width == vdef2->width) && (vdef1->height == vdef2->height)) - || ((vdef1->width == vdef2->height) && (vdef1->height == vdef2->width))); + return ((vdef1 != NULL && vdef2 != NULL) + && (((vdef1->width == vdef2->width) && (vdef1->height == vdef2->height)) + || ((vdef1->width == vdef2->height) && (vdef1->height == vdef2->width)))); } bool_t linphone_video_definition_strict_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2) { diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 1975363c2..61178d119 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -119,7 +119,7 @@ target_link_libraries(linphone-daemon ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER set_target_properties(linphone-daemon PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") add_executable(linphone-daemon-pipetest ${DAEMON_PIPETEST_SOURCE_FILES}) -target_link_libraries(linphone-daemon-pipetest ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES}) +target_link_libraries(linphone-daemon-pipetest ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) set_target_properties(linphone-daemon-pipetest PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set(INSTALL_TARGETS linphone-daemon linphone-daemon-pipetest) diff --git a/include/linphone/core.h b/include/linphone/core.h index 6fc0bb029..01483b3c9 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -803,6 +803,14 @@ LINPHONE_PUBLIC void linphone_core_set_log_level(OrtpLogLevel loglevel); */ LINPHONE_PUBLIC void linphone_core_set_log_level_mask(unsigned int loglevel); +/** + * Get defined log level mask. + * + * @return The loglevel parameter is a bitmask parameter. Therefore to enable only warning and error + * messages, use ORTP_WARNING | ORTP_ERROR. To disable logs, simply set loglevel to 0. + */ +LINPHONE_PUBLIC unsigned int linphone_core_get_log_level_mask(void); + /** * Enable logs in supplied FILE*. * @param file a C FILE* where to fprintf logs. If null stdout is used. diff --git a/include/sal/sal.h b/include/sal/sal.h index f41c09336..0aa5073ae 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -148,6 +148,8 @@ const char *sal_address_get_header(const SalAddress *addr, const char *name); LINPHONE_PUBLIC Sal * sal_init(MSFactory *factory); LINPHONE_PUBLIC void sal_uninit(Sal* sal); + +void sal_set_log_handler(BctbxLogFunc log_handler); void sal_set_user_pointer(Sal *sal, void *user_data); void *sal_get_user_pointer(const Sal *sal); @@ -672,6 +674,7 @@ SalOp * sal_op_new(Sal *sal); /*generic SalOp API, working for all operations */ Sal *sal_op_get_sal(const SalOp *op); void sal_op_set_contact_address(SalOp *op, const SalAddress* address); +void sal_op_set_and_clean_contact_address(SalOp *op, SalAddress* address); void sal_op_set_route(SalOp *op, const char *route); void sal_op_set_route_address(SalOp *op, const SalAddress* address); void sal_op_add_route_address(SalOp *op, const SalAddress* address); diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java index 8cb43e796..332a76b57 100644 --- a/java/common/org/linphone/core/LinphoneCall.java +++ b/java/common/org/linphone/core/LinphoneCall.java @@ -20,6 +20,8 @@ package org.linphone.core; import java.util.Vector; +import org.linphone.mediastream.video.AndroidVideoWindowImpl; + /** * Object representing a call. Calls are created using {@link LinphoneCore#invite(LinphoneAddress)} or passed to the application by listener {@link LinphoneCoreListener#callState} * @@ -404,6 +406,13 @@ public interface LinphoneCall { */ void setListener(LinphoneCall.LinphoneCallListener listener); + /** + * Set the native video window id where the video is to be displayed. + * On Android, it must be of type {@link AndroidVideoWindowImpl} + * @param w window of type {@link AndroidVideoWindowImpl} + */ + void setVideoWindow(Object w); + /** * Indicates if remote party requested automatic answering to be performed. * This is an indication - the application remains responsible for answering the call. diff --git a/java/common/org/linphone/core/LinphoneFriend.java b/java/common/org/linphone/core/LinphoneFriend.java index a9c2d9979..07b582979 100644 --- a/java/common/org/linphone/core/LinphoneFriend.java +++ b/java/common/org/linphone/core/LinphoneFriend.java @@ -165,6 +165,12 @@ public interface LinphoneFriend { * @return The reference key of the friend. **/ String getRefKey(); + +/** + * return a the string value of the vcard corresponding to the given friend + */ + String getVcardToString(); + /** * Set a name for this friend * @param name diff --git a/java/impl/org/linphone/core/LinphoneCallImpl.java b/java/impl/org/linphone/core/LinphoneCallImpl.java index f1338c423..70c0b01dc 100644 --- a/java/impl/org/linphone/core/LinphoneCallImpl.java +++ b/java/impl/org/linphone/core/LinphoneCallImpl.java @@ -45,6 +45,7 @@ class LinphoneCallImpl implements LinphoneCall { private native float getAverageQuality(long nativePtr); private native boolean mediaInProgress(long nativePtr); private native void setListener(long ptr, LinphoneCallListener listener); + private native void setVideoWindowId(long nativePtr, Object wid); native private long getDiversionAddress(long nativePtr); native private Object getStats(long nativePtr, int stream_type); native private LinphoneCore getCore(long nativePtr); @@ -295,6 +296,11 @@ class LinphoneCallImpl implements LinphoneCall { setListener(nativePtr, listener); } } + + @Override + public synchronized void setVideoWindow(Object w) { + setVideoWindowId(nativePtr, w); + } public LinphoneAddress getDiversionAddress() { long lNativePtr = getDiversionAddress(nativePtr); diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 2d5ed151c..671fb1fcc 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -195,7 +195,7 @@ class LinphoneCoreImpl implements LinphoneCore { private native Object createFriend(long nativePtr); private native Object createFriendWithAddress(long nativePtr, String address); private native int getIncomingTimeout(long nativePtr); - + LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata) throws IOException { mListener = listener; String user = userConfig == null ? null : userConfig.getCanonicalPath(); diff --git a/java/impl/org/linphone/core/LinphoneFriendImpl.java b/java/impl/org/linphone/core/LinphoneFriendImpl.java index 6aa92bda6..1aa3c4f26 100644 --- a/java/impl/org/linphone/core/LinphoneFriendImpl.java +++ b/java/impl/org/linphone/core/LinphoneFriendImpl.java @@ -40,6 +40,7 @@ public class LinphoneFriendImpl implements LinphoneFriend, Serializable { private native Object getCore(long ptr); private native void setRefKey(long nativePtr, String key); private native String getRefKey(long nativePtr); + private native String getVcardToString(long nativePtr); private Object userdData; public Object getUserData() { @@ -141,6 +142,12 @@ public class LinphoneFriendImpl implements LinphoneFriend, Serializable { public String getRefKey(){ return getRefKey(nativePtr); } + + + public synchronized String getVcardToString() { + return getVcardToString(nativePtr); + } + private native void setName(long nativePtr, String name); @Override diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 07259d697..4b064d20e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,8 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES conference/conference-listener.h conference/local-conference-event-handler.h conference/remote-conference-event-handler.h + content/content.h + core/core.h cpim/cpim.h cpim/header/cpim-core-headers.h cpim/header/cpim-generic-header.h @@ -32,9 +34,23 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES cpim/message/cpim-message.h cpim/parser/cpim-grammar.h cpim/parser/cpim-parser.h + db/abstract/abstract-db-p.h + db/abstract/abstract-db.h + db/events-db.h + db/provider/db-session-p.h + db/provider/db-session-provider.h + db/provider/db-session.h + enums.h + event/call-event.h + event/conference-event-p.h + event/conference-event.h + event/conference-participant-event.h + event/event.h + event/message-event.h logger/logger.h - object/clonable-object.h + message/message.h object/clonable-object-p.h + object/clonable-object.h object/object-p.h object/object.h object/singleton.h @@ -47,15 +63,28 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES set(LINPHONE_CXX_OBJECTS_SOURCE_FILES conference/local-conference-event-handler.cpp conference/remote-conference-event-handler.cpp + content/content.cpp + core/core.cpp cpim/header/cpim-core-headers.cpp cpim/header/cpim-generic-header.cpp cpim/header/cpim-header.cpp cpim/message/cpim-message.cpp cpim/parser/cpim-grammar.cpp cpim/parser/cpim-parser.cpp + db/abstract/abstract-db.cpp + db/events-db.cpp + db/provider/db-session-provider.cpp + db/provider/db-session.cpp + event/call-event.cpp + event/conference-event.cpp + event/conference-participant-event.cpp + event/event.cpp + event/message-event.cpp logger/logger.cpp + message/message.cpp object/clonable-object.cpp object/object.cpp + utils/general.cpp utils/utils.cpp xml/conference-info.cpp xml/xml.cpp @@ -64,7 +93,14 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES ADD_XSD_WRAPPERS(xml/xml "XML XSD - xml.xsd") ADD_XSD_WRAPPERS(xml/conference-info "Conference info XSD - conference-info.xsd") -set(LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${BELR_INCLUDE_DIRS} ${SOCI_INCLUDE_DIRS} ${SOCI_MYSQL_INCLUDES} ${LIBXSD_INCLUDE_DIRS}) +set(LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${BELR_INCLUDE_DIRS} ${LIBXSD_INCLUDE_DIRS}) +set(LINPHONE_CXX_OBJECTS_DEFINITIONS "-DLIBLINPHONE_EXPORTS") +set(LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${BELR_INCLUDE_DIRS}) + +if(SOCI_FOUND) + list(APPEND LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${SOCI_INCLUDE_DIRS} ${SOCI_MYSQL_INCLUDES}) + add_definitions(-DSOCI_ENABLED) +endif() set(LINPHONE_PRIVATE_HEADER_FILES) foreach(header ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES}) @@ -77,12 +113,12 @@ bc_apply_compile_flags(LINPHONE_CXX_OBJECTS_SOURCE_FILES STRICT_OPTIONS_CPP STRI if(ENABLE_STATIC) add_library(linphone-cxx-objects-static OBJECT ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_SOURCE_FILES}) target_compile_definitions(linphone-cxx-objects-static PRIVATE ${LINPHONE_CXX_OBJECTS_DEFINITIONS}) - target_include_directories(linphone-cxx-objects-static PRIVATE ${LINPHONE_CXX_OBJECTS_INCLUDE_DIRS} ${LINPHONE_INCLUDE_DIRS}) + target_include_directories(linphone-cxx-objects-static SYSTEM PRIVATE ${LINPHONE_CXX_OBJECTS_INCLUDE_DIRS} ${LINPHONE_INCLUDE_DIRS}) endif() if(ENABLE_SHARED) add_library(linphone-cxx-objects OBJECT ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_SOURCE_FILES}) target_compile_definitions(linphone-cxx-objects PRIVATE ${LINPHONE_CXX_OBJECTS_DEFINITIONS}) - target_include_directories(linphone-cxx-objects PRIVATE ${LINPHONE_CXX_OBJECTS_INCLUDE_DIRS} ${LINPHONE_INCLUDE_DIRS}) + target_include_directories(linphone-cxx-objects SYSTEM PRIVATE ${LINPHONE_CXX_OBJECTS_INCLUDE_DIRS} ${LINPHONE_INCLUDE_DIRS}) target_compile_options(linphone-cxx-objects PRIVATE "-fPIC") endif() diff --git a/src/content/content.cpp b/src/content/content.cpp new file mode 100644 index 000000000..2003b1613 --- /dev/null +++ b/src/content/content.cpp @@ -0,0 +1,37 @@ +/* + * content.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "object/object-p.h" + +#include "content.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ContentPrivate : public ObjectPrivate { +private: + + L_DECLARE_PUBLIC(Content); +}; + +// ----------------------------------------------------------------------------- + +Content::Content (ContentPrivate &p) : Object(p) {} + +LINPHONE_END_NAMESPACE diff --git a/src/content/content.h b/src/content/content.h new file mode 100644 index 000000000..fa59de1e7 --- /dev/null +++ b/src/content/content.h @@ -0,0 +1,45 @@ +/* + * content.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _CONTENT_H_ +#define _CONTENT_H_ + +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ContentPrivate; + +class LINPHONE_PUBLIC Content : public Object { + friend class Core; + +public: + // Nothing for the moment. + +private: + Content (ContentPrivate &p); + + L_DECLARE_PRIVATE(Content); + L_DISABLE_COPY(Content); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _CONTENT_H_ diff --git a/src/core/core.cpp b/src/core/core.cpp new file mode 100644 index 000000000..2d4e9696e --- /dev/null +++ b/src/core/core.cpp @@ -0,0 +1,36 @@ +/* + * core.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "object/object-p.h" + +#include "core.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CorePrivate : public ObjectPrivate { +public: + // TODO. +}; + +// ----------------------------------------------------------------------------- + +Core::Core (CorePrivate &p) : Object(p) {} + +LINPHONE_END_NAMESPACE diff --git a/src/core/core.h b/src/core/core.h new file mode 100644 index 000000000..1d4874c31 --- /dev/null +++ b/src/core/core.h @@ -0,0 +1,43 @@ +/* + * core.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _CORE_H_ +#define _CORE_H_ + +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CorePrivate; + +class LINPHONE_PUBLIC Core : public Object { +public: + // Nothing for the moment. + +private: + Core (CorePrivate &p); + + L_DECLARE_PRIVATE(Core); + L_DISABLE_COPY(Core); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _CORE_H_ diff --git a/src/cpim/parser/cpim-parser.cpp b/src/cpim/parser/cpim-parser.cpp index c57a15ab2..724f4bf68 100644 --- a/src/cpim/parser/cpim-parser.cpp +++ b/src/cpim/parser/cpim-parser.cpp @@ -279,7 +279,7 @@ shared_ptr Cpim::Parser::cloneHeader (const Header &header) { class EmptyObject {}; -inline bool headerIsValid (const shared_ptr &grammar, const string &input) { +static bool headerIsValid (const shared_ptr &grammar, const string &input) { belr::Parser > parser(grammar); parser.setHandler( "Header", belr::make_fn(make_shared ) @@ -307,7 +307,7 @@ bool Cpim::Parser::headerParameterIsValid (const string &headerParameter) const // ----------------------------------------------------------------------------- -inline bool coreHeaderIsValid ( +static bool coreHeaderIsValid ( const shared_ptr &grammar, const string &headerName, const string &headerValue, diff --git a/src/db/abstract/abstract-db-p.h b/src/db/abstract/abstract-db-p.h new file mode 100644 index 000000000..51dbd2ffe --- /dev/null +++ b/src/db/abstract/abstract-db-p.h @@ -0,0 +1,42 @@ +/* + * abstract-db-p.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _ABSTRACT_DB_P_H_ +#define _ABSTRACT_DB_P_H_ + +#include "abstract-db.h" +#include "db/provider/db-session.h" +#include "object/object-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class AbstractDbPrivate : public ObjectPrivate { +public: + DbSession dbSession; + +private: + AbstractDb::Backend backend; + + L_DECLARE_PUBLIC(AbstractDb); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _ABSTRACT_DB_P_H_ diff --git a/src/db/abstract/abstract-db.cpp b/src/db/abstract/abstract-db.cpp new file mode 100644 index 000000000..81df3a33f --- /dev/null +++ b/src/db/abstract/abstract-db.cpp @@ -0,0 +1,75 @@ +/* + * abstract-db.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "abstract-db-p.h" +#include "db/provider/db-session-provider.h" + +#include "abstract-db.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +AbstractDb::AbstractDb (AbstractDbPrivate &p) : Object(*new AbstractDbPrivate) {} + +bool AbstractDb::connect (Backend backend, const string ¶meters) { + L_D(AbstractDb); + + d->dbSession = DbSessionProvider::getInstance()->getSession( + (backend == Mysql ? "mysql://" : "sqlite3://") + parameters + ); + + if (d->dbSession) + init(); + return d->dbSession; +} + +bool AbstractDb::isConnected () const { + L_D(const AbstractDb); + return d->dbSession; +} + +AbstractDb::Backend AbstractDb::getBackend () const { + L_D(const AbstractDb); + return d->backend; +} + +// ----------------------------------------------------------------------------- + +void AbstractDb::init () { + // Nothing. +} + +// ----------------------------------------------------------------------------- + +string AbstractDb::primaryKeyAutoIncrementStr (const string &type) const { + L_D(const AbstractDb); + + switch (d->backend) { + case Mysql: + return type + "UNSIGNED PRIMARY KEY AUTO_INCREMENT"; + case Sqlite3: + return " INTEGER PRIMARY KEY AUTOINCREMENT"; + } + + return ""; +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/abstract/abstract-db.h b/src/db/abstract/abstract-db.h new file mode 100644 index 000000000..3eac6971f --- /dev/null +++ b/src/db/abstract/abstract-db.h @@ -0,0 +1,62 @@ +/* + * abstract-db.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _ABSTRACT_DB_H_ +#define _ABSTRACT_DB_H_ + +#include + +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class AbstractDbPrivate; + +class LINPHONE_PUBLIC AbstractDb : public Object { +public: + enum Backend { + Mysql, + Sqlite3 + }; + + virtual ~AbstractDb () = default; + + bool connect (Backend backend, const std::string ¶meters); + bool disconnect (); + + bool isConnected () const; + + Backend getBackend () const; + +protected: + explicit AbstractDb (AbstractDbPrivate &p); + + virtual void init (); + + std::string primaryKeyAutoIncrementStr (const std::string &type = "INT") const; + +private: + L_DECLARE_PRIVATE(AbstractDb); + L_DISABLE_COPY(AbstractDb); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _ABSTRACT_DB_H_ diff --git a/src/db/events-db.cpp b/src/db/events-db.cpp new file mode 100644 index 000000000..d6c90fb29 --- /dev/null +++ b/src/db/events-db.cpp @@ -0,0 +1,411 @@ +/* + * events-db.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include + +#ifdef SOCI_ENABLED + #include +#endif // ifdef SOCI_ENABLED + +#include "abstract/abstract-db-p.h" +#include "event/call-event.h" +#include "event/event.h" +#include "event/message-event.h" +#include "logger/logger.h" +#include "message/message.h" + +#include "events-db.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class EventsDbPrivate : public AbstractDbPrivate {}; + +// ----------------------------------------------------------------------------- + +EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} + +// ----------------------------------------------------------------------------- +// Soci backend. +// ----------------------------------------------------------------------------- + +#ifdef SOCI_ENABLED + + template + struct EnumToSql { + T first; + const char *second; + }; + + template + static constexpr const char *mapEnumToSql (const EnumToSql enumToSql[], size_t n, T key) { + return n == 0 ? "" : ( + enumToSql[n - 1].first == key ? enumToSql[n - 1].second : mapEnumToSql(enumToSql, n - 1, key) + ); + } + +// ----------------------------------------------------------------------------- + + static constexpr EnumToSql eventFilterToSql[] = { + { EventsDb::MessageFilter, "1" }, + { EventsDb::CallFilter, "2" }, + { EventsDb::ConferenceFilter, "3" } + }; + + static constexpr const char *mapEventFilterToSql (EventsDb::Filter filter) { + return mapEnumToSql( + eventFilterToSql, sizeof eventFilterToSql / sizeof eventFilterToSql[0], filter + ); + } + + static constexpr EnumToSql messageStateToSql[] = { + { Message::Idle, "1" }, + { Message::InProgress, "2" }, + { Message::Delivered, "3" }, + { Message::NotDelivered, "4" }, + { Message::FileTransferError, "5" }, + { Message::FileTransferDone, "6" }, + { Message::DeliveredToUser, "7" }, + { Message::Displayed, "8" } + }; + + static constexpr const char *mapMessageStateToSql (Message::State state) { + return mapEnumToSql( + messageStateToSql, sizeof messageStateToSql / sizeof messageStateToSql[0], state + ); + } + + static constexpr const char *mapMessageDirectionToSql (Message::Direction direction) { + return direction == Message::Direction::Incoming ? "1" : "2"; + } + +// ----------------------------------------------------------------------------- + + static string buildSqlEventFilter (const list &filters, EventsDb::FilterMask mask) { + L_ASSERT( + find_if(filters.cbegin(), filters.cend(), [](const EventsDb::Filter &filter) { + return filter == EventsDb::NoFilter; + }) == filters.cend() + ); + + if (mask == EventsDb::NoFilter) + return ""; + + bool isStart = true; + string sql; + for (const auto &filter : filters) { + if (!(mask & filter)) + continue; + + if (isStart) { + isStart = false; + sql += " WHERE "; + } else + sql += " OR "; + sql += " event_type_id = "; + sql += mapEventFilterToSql(filter); + } + + return sql; + } + +// ----------------------------------------------------------------------------- + + void EventsDb::init () { + L_D(EventsDb); + soci::session *session = d->dbSession.getBackendSession(); + + *session << + "CREATE TABLE IF NOT EXISTS sip_address (" + " id" + primaryKeyAutoIncrementStr() + "," + " value VARCHAR(255) NOT NULL" + ")"; + + *session << + "CREATE TABLE IF NOT EXISTS event_type (" + " id" + primaryKeyAutoIncrementStr("TINYINT") + "," + " value VARCHAR(255) NOT NULL" + ")"; + + *session << + "CREATE TABLE IF NOT EXISTS event (" + " id" + primaryKeyAutoIncrementStr() + "," + " event_type_id TINYINT UNSIGNED NOT NULL," + " timestamp TIMESTAMP NOT NULL," + " FOREIGN KEY (event_type_id)" + " REFERENCES event_type(id)" + " ON DELETE CASCADE" + ")"; + + *session << + "CREATE TABLE IF NOT EXISTS message_state (" + " id" + primaryKeyAutoIncrementStr("TINYINT") + "," + " state VARCHAR(255) NOT NULL" + ")"; + + *session << + "CREATE TABLE IF NOT EXISTS message_direction (" + " id" + primaryKeyAutoIncrementStr("TINYINT") + "," + " direction VARCHAR(255) NOT NULL" + ")"; + + *session << + "CREATE TABLE IF NOT EXISTS dialog (" + " id" + primaryKeyAutoIncrementStr() + "," + " local_sip_address_id INT UNSIGNED NOT NULL," // Sip address used to communicate. + " remote_sip_address_id INT UNSIGNED NOT NULL," // Server (for conference) or user sip address. + " creation_timestamp TIMESTAMP NOT NULL," // Dialog creation date. + " last_update_timestamp TIMESTAMP NOT NULL," // Last event timestamp (call, message...). + " FOREIGN KEY (local_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (remote_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ")"; + + *session << + "CREATE TABLE IF NOT EXISTS message_event (" + " id" + primaryKeyAutoIncrementStr() + "," + " dialog_id INT UNSIGNED NOT NULL," + " state_id TINYINT UNSIGNED NOT NULL," + " direction_id TINYINT UNSIGNED NOT NULL," + " imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3 + " content_type VARCHAR(255) NOT NULL," + " is_secured BOOLEAN NOT NULL," + " app_data VARCHAR(2048)," + " FOREIGN KEY (dialog_id)" + " REFERENCES dialog(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (state_id)" + " REFERENCES message_state(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (direction_id)" + " REFERENCES message_direction(id)" + " ON DELETE CASCADE" + ")"; + + { + string query = getBackend() == Mysql + ? "INSERT INTO event_type (id, value)" + : "INSERT OR IGNORE INTO event_type (id, value)"; + query += "VALUES" + "(1, \"Message\")," + "(2, \"Call\")," + "(3, \"Conference\")"; + if (getBackend() == Mysql) + query += "ON DUPLICATE KEY UPDATE value = VALUES(value)"; + + *session << query; + } + + { + string query = getBackend() == Mysql + ? "INSERT INTO message_direction (id, value)" + : "INSERT OR IGNORE INTO message_direction (id, value)"; + query += "VALUES" + "(1, \"Incoming\")," + "(2, \"Outgoing\")"; + if (getBackend() == Mysql) + query += "ON DUPLICATE KEY UPDATE value = VALUES(value)"; + + *session << query; + } + + { + string query = getBackend() == Mysql + ? "INSERT INTO message_state (id, value)" + : "INSERT OR IGNORE INTO message_state (id, value)"; + query += "VALUES" + "(1, \"Idle\")," + "(2, \"InProgress\")," + "(3, \"Delivered\")," + "(4, \"NotDelivered\")," + "(5, \"FileTransferError\")," + "(6, \"FileTransferDone\")," + "(7, \"DeliveredToUser\")," + "(8, \"Displayed\")"; + if (getBackend() == Mysql) + query += "ON DUPLICATE KEY UPDATE value = VALUES(value)"; + + *session << query; + } + } + + bool EventsDb::addEvent (const Event &event) { + // TODO. + switch (event.getType()) { + case Event::None: + return false; + case Event::MessageEvent: + case Event::CallStartEvent: + case Event::CallEndEvent: + case Event::ConferenceCreatedEvent: + case Event::ConferenceDestroyedEvent: + case Event::ConferenceParticipantAddedEvent: + case Event::ConferenceParticipantRemovedEvent: + case Event::ConferenceParticipantSetAdminEvent: + case Event::ConferenceParticipantUnsetAdminEvent: + break; + } + + return true; + } + + bool EventsDb::deleteEvent (const Event &event) { + // TODO. + (void)event; + return true; + } + + void EventsDb::cleanEvents (FilterMask mask) { + // TODO. + (void)mask; + } + + int EventsDb::getEventsCount (FilterMask mask) const { + L_D(const EventsDb); + + string query = "SELECT COUNT(*) FROM event" + + buildSqlEventFilter({ MessageFilter, CallFilter, ConferenceFilter }, mask); + int count = 0; + + L_BEGIN_LOG_EXCEPTION + + soci::session *session = d->dbSession.getBackendSession(); + *session << query, soci::into(count); + + L_END_LOG_EXCEPTION + + return count; + } + + int EventsDb::getMessagesCount (const string &remoteAddress) const { + L_D(const EventsDb); + + string query = "SELECT COUNT(*) FROM message_event"; + if (!remoteAddress.empty()) + query += " WHERE dialog_id = (" + " SELECT id FROM dialog WHERE remote_sip_address_id =(" + " SELECT id FROM sip_address WHERE value = :remote_address" + " )" + " )"; + int count = 0; + + L_BEGIN_LOG_EXCEPTION + + soci::session *session = d->dbSession.getBackendSession(); + *session << query, soci::use(remoteAddress), soci::into(count); + + L_END_LOG_EXCEPTION + + return count; + } + + int EventsDb::getUnreadMessagesCount (const string &remoteAddress) const { + L_D(const EventsDb); + + string query = "SELECT COUNT(*) FROM message_event"; + if (!remoteAddress.empty()) + query += " WHERE dialog_id = (" + " SELECT id FROM dialog WHERE remote_sip_address_id = (" + " SELECT id FROM sip_address WHERE value = :remote_address" + " )" + " )" + " AND direction_id = " + string(mapMessageDirectionToSql(Message::Incoming)) + + " AND state_id = " + string(mapMessageStateToSql(Message::Displayed)); + int count = 0; + + L_BEGIN_LOG_EXCEPTION + + soci::session *session = d->dbSession.getBackendSession(); + *session << query, soci::use(remoteAddress), soci::into(count); + + L_END_LOG_EXCEPTION + + return count; + } + + list EventsDb::getHistory (const string &remoteAddress, int nLast, FilterMask mask) const { + // TODO. + (void)remoteAddress; + (void)nLast; + (void)mask; + return list(); + } + + list EventsDb::getHistory (const string &remoteAddress, int begin, int end, FilterMask mask) const { + // TODO. + (void)remoteAddress; + (void)begin; + (void)end; + (void)mask; + return list(); + } + + void EventsDb::cleanHistory (const string &remoteAddress) { + // TODO. + (void)remoteAddress; + } + +// ----------------------------------------------------------------------------- +// No backend. +// ----------------------------------------------------------------------------- + +#else + + void EventsDb::init () {} + + bool EventsDb::addEvent (const Event &) { + return false; + } + + bool EventsDb::deleteEvent (const Event &) { + return false; + } + + void EventsDb::cleanEvents (FilterMask) {} + + int EventsDb::getEventsCount (FilterMask) const { + return 0; + } + + int EventsDb::getMessagesCount (const string &) const { + return 0; + } + + int EventsDb::getUnreadMessagesCount (const string &) const { + return 0; + } + + list EventsDb::getHistory (const string &, int, FilterMask) const { + return list(); + } + + list EventsDb::getHistory (const string &, int, int, FilterMask) const { + return list(); + } + + void EventsDb::cleanHistory (const string &) {} + +#endif // ifdef SOCI_ENABLED + +LINPHONE_END_NAMESPACE diff --git a/src/db/events-db.h b/src/db/events-db.h new file mode 100644 index 000000000..d6013ed2e --- /dev/null +++ b/src/db/events-db.h @@ -0,0 +1,69 @@ +/* + * events-db.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _EVENTS_DB_H_ +#define _EVENTS_DB_H_ + +#include + +#include "abstract/abstract-db.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Event; +class EventsDbPrivate; + +class LINPHONE_PUBLIC EventsDb : public AbstractDb { +public: + enum Filter { + NoFilter = 0x0, + MessageFilter = 0x1, + CallFilter = 0x2, + ConferenceFilter = 0x4 + }; + + typedef int FilterMask; + + EventsDb (); + + // Generic. + bool addEvent (const Event &event); + bool deleteEvent (const Event &event); + void cleanEvents (FilterMask mask = NoFilter); + int getEventsCount (FilterMask mask = NoFilter) const; + + // Messages, calls and conferences. + int getMessagesCount (const std::string &remoteAddress = "") const; + int getUnreadMessagesCount (const std::string &remoteAddress = "") const; + std::list getHistory (const std::string &remoteAddress, int nLast, FilterMask mask = NoFilter) const; + std::list getHistory (const std::string &remoteAddress, int begin, int end, FilterMask mask = NoFilter) const; + void cleanHistory (const std::string &remoteAddress = ""); + +protected: + void init () override; + +private: + L_DECLARE_PRIVATE(EventsDb); + L_DISABLE_COPY(EventsDb); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _EVENTS_DB_H_ diff --git a/src/db/provider/db-session-p.h b/src/db/provider/db-session-p.h new file mode 100644 index 000000000..de9e9b5da --- /dev/null +++ b/src/db/provider/db-session-p.h @@ -0,0 +1,47 @@ +/* + * db-session-p.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _DB_SESSION_P_H_ +#define _DB_SESSION_P_H_ + +#include + +#include "db-session.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class DbSessionPrivate : public ClonableObjectPrivate { + friend class DbSessionProvider; + +private: + bool isValid = false; + + DbSession::Type type = DbSession::None; + std::shared_ptr backendSession; + + L_DECLARE_PUBLIC(DbSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _DB_SESSION_P_H_ diff --git a/src/db/provider/db-session-provider.cpp b/src/db/provider/db-session-provider.cpp new file mode 100644 index 000000000..35dc9c82c --- /dev/null +++ b/src/db/provider/db-session-provider.cpp @@ -0,0 +1,83 @@ +/* + * db-session-provider.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include + +#ifdef SOCI_ENABLED + #include +#endif // ifdef SOCI_ENABLED + +#include "db-session-p.h" +#include "object/object-p.h" + +#include "db-session-provider.h" + +#define CLEAN_COUNTER_MAX 1000 + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionProviderPrivate : public ObjectPrivate { +public: + typedef pair, DbSessionPrivate *> InternalSession; + unordered_map sessions; + int cleanCounter = 0; +}; + +DbSessionProvider::DbSessionProvider () : Singleton(*new DbSessionProviderPrivate) {} + +DbSession DbSessionProvider::getSession (const string &uri) { + L_D(DbSessionProvider); + + #ifdef SOCI_ENABLED + DbSession session(DbSession::Soci); + try { + shared_ptr backendSession = d->sessions[uri].first.lock(); + ++d->cleanCounter; + if (!backendSession) { // Create new session. + backendSession = make_shared(uri); + DbSessionPrivate *p = session.getPrivate(); + p->backendSession = backendSession; + p->isValid = true; + d->sessions[uri] = make_pair(backendSession, p); + } else // Share session. + session.setRef(*d->sessions[uri].second); + } catch (const exception &) {} + #else + DbSession session(DbSession::None); + #endif // ifdef SOCI_ENABLED + + // Remove invalid weak ptrs. + if (d->cleanCounter >= CLEAN_COUNTER_MAX) { + d->cleanCounter = 0; + + for (auto it = d->sessions.begin(), itEnd = d->sessions.end(); it != itEnd;) { + if (it->second.first.expired()) + it = d->sessions.erase(it); + else + ++it; + } + } + + return session; +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/provider/db-session-provider.h b/src/db/provider/db-session-provider.h new file mode 100644 index 000000000..50542d5eb --- /dev/null +++ b/src/db/provider/db-session-provider.h @@ -0,0 +1,48 @@ +/* + * db-session-provider.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _DB_SESSION_PROVIDER_H_ +#define _DB_SESSION_PROVIDER_H_ + +#include + +#include "db-session.h" +#include "object/singleton.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionProviderPrivate; + +class DbSessionProvider : public Singleton { + friend class Singleton; + +public: + DbSession getSession (const std::string &uri); + +private: + DbSessionProvider (); + + L_DECLARE_PRIVATE(DbSessionProvider); + L_DISABLE_COPY(DbSessionProvider); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _DB_SESSION_PROVIDER_H_ diff --git a/src/db/provider/db-session.cpp b/src/db/provider/db-session.cpp new file mode 100644 index 000000000..f074804b3 --- /dev/null +++ b/src/db/provider/db-session.cpp @@ -0,0 +1,51 @@ +/* + * db-session.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "db-session-p.h" + +#include "db-session.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +DbSession::DbSession (Type type) : ClonableObject(*new DbSessionPrivate) { + L_D(DbSession); + d->type = type; +} + +L_USE_DEFAULT_SHARE_IMPL(DbSession, ClonableObject); + +DbSession::operator bool () const { + L_D(const DbSession); + return d->isValid; +} + +DbSession::Type DbSession::getBackendType () const { + L_D(const DbSession); + return d->type; +} + +void *DbSession::getBackendSession () const { + L_D(const DbSession); + return d->backendSession.get(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/provider/db-session.h b/src/db/provider/db-session.h new file mode 100644 index 000000000..ac8a0582e --- /dev/null +++ b/src/db/provider/db-session.h @@ -0,0 +1,92 @@ +/* + * db-session.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _DB_SESSION_H_ +#define _DB_SESSION_H_ + +#include + +#include "object/clonable-object.h" + +// ============================================================================= + +#ifdef SOCI_ENABLED + namespace soci { + class session; + } +#endif // ifdef SOCI_ENABLED + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionPrivate; + +class DbSession : public ClonableObject { + friend class DbSessionProvider; + +public: + enum Type { + None, + Soci + }; + + DbSession (Type type = None); + DbSession (const DbSession &src); + + DbSession &operator= (const DbSession &src); + + operator bool () const; + + Type getBackendType () const; + + template + T *getBackendSession () const; + +private: + void *getBackendSession () const; + + L_DECLARE_PRIVATE(DbSession); +}; + +// ----------------------------------------------------------------------------- + +template +struct TypeOfDbSession { + static const DbSession::Type type = DbSession::None; +}; + +#ifdef SOCI_ENABLED + + template<> + struct TypeOfDbSession<::soci::session> { + static const DbSession::Type type = DbSession::Soci; + }; + +#endif // ifdef SOCI_ENABLED + +template +T *DbSession::getBackendSession () const { + typedef TypeOfDbSession Type; + static_assert(Type::type != DbSession::None, "Unable to get backend session, invalid type."); + if (getBackendType() != Type::type) + return nullptr; + return static_cast(getBackendSession()); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _DB_SESSION_H_ diff --git a/src/enums.h b/src/enums.h new file mode 100644 index 000000000..78f0d1ed5 --- /dev/null +++ b/src/enums.h @@ -0,0 +1,32 @@ +/* + * enums.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _ENUMS_H_ +#define _ENUMS_H_ + +#include "utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +// Nothing. for the moment. + +LINPHONE_END_NAMESPACE + +#endif // ifndef _ENUMS_H_ diff --git a/src/event/call-event.cpp b/src/event/call-event.cpp new file mode 100644 index 000000000..f6eee2b1e --- /dev/null +++ b/src/event/call-event.cpp @@ -0,0 +1,60 @@ +/* + * call-event.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "event-p.h" + +#include "call-event.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class CallEventPrivate : public EventPrivate { +public: + shared_ptr call; +}; + +// ----------------------------------------------------------------------------- + +CallEvent::CallEvent (Type type, const shared_ptr &call) : Event(*new CallEventPrivate, type) { + L_D(CallEvent); + L_ASSERT(call); + L_ASSERT(type == CallStartEvent || type == CallEndEvent); + d->call = call; +} + +CallEvent::CallEvent (const CallEvent &src) : CallEvent(src.getType(), src.getCall()) {} + +CallEvent &CallEvent::operator= (const CallEvent &src) { + L_D(CallEvent); + if (this != &src) { + Event::operator=(src); + d->call = src.getPrivate()->call; + } + + return *this; +} + +shared_ptr CallEvent::getCall () const { + L_D(const CallEvent); + return d->call; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event/call-event.h b/src/event/call-event.h new file mode 100644 index 000000000..e56d25dfc --- /dev/null +++ b/src/event/call-event.h @@ -0,0 +1,48 @@ +/* + * call-event.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _CALL_EVENT_H_ +#define _CALL_EVENT_H_ + +#include + +#include "event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Call; +class CallEventPrivate; + +class LINPHONE_PUBLIC CallEvent : public Event { +public: + CallEvent (Type type, const std::shared_ptr &message); + CallEvent (const CallEvent &src); + + CallEvent &operator= (const CallEvent &src); + + std::shared_ptr getCall () const; + +private: + L_DECLARE_PRIVATE(CallEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _CALL_EVENT_H_ diff --git a/src/event/conference-event-p.h b/src/event/conference-event-p.h new file mode 100644 index 000000000..d4fcd9b65 --- /dev/null +++ b/src/event/conference-event-p.h @@ -0,0 +1,39 @@ +/* + * conference-event-p.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _CONFERENCE_EVENT_P_H_ +#define _CONFERENCE_EVENT_P_H_ + +#include "conference-event.h" + +#include "event-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceEventPrivate : public EventPrivate { +private: + std::shared_ptr
address; + + L_DECLARE_PUBLIC(ConferenceEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _CONFERENCE_EVENT_P_H_ diff --git a/src/event/conference-event.cpp b/src/event/conference-event.cpp new file mode 100644 index 000000000..a75d22657 --- /dev/null +++ b/src/event/conference-event.cpp @@ -0,0 +1,61 @@ +/* + * conference-event.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "conference-event-p.h" + +#include "conference-event.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +ConferenceEvent::ConferenceEvent (Type type, const shared_ptr
&address) : + Event(*new ConferenceEventPrivate, type) { + L_D(ConferenceEvent); + L_ASSERT(type == ConferenceCreatedEvent || type == ConferenceDestroyedEvent); + L_ASSERT(address); + d->address = address; +} + +ConferenceEvent::ConferenceEvent (const ConferenceEvent &src) : ConferenceEvent(src.getType(), src.getAddress()) {} + +ConferenceEvent::ConferenceEvent (ConferenceEventPrivate &p, Type type, const shared_ptr
&address) : + Event(p, type) { + L_D(ConferenceEvent); + L_ASSERT(address); + d->address = address; +} + +ConferenceEvent &ConferenceEvent::operator= (const ConferenceEvent &src) { + L_D(ConferenceEvent); + if (this != &src) { + Event::operator=(src); + d->address = src.getPrivate()->address; + } + + return *this; +} + +shared_ptr
ConferenceEvent::getAddress () const { + // TODO. + return nullptr; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event/conference-event.h b/src/event/conference-event.h new file mode 100644 index 000000000..5a499b215 --- /dev/null +++ b/src/event/conference-event.h @@ -0,0 +1,52 @@ +/* + * conference-event.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _CONFERENCE_EVENT_H_ +#define _CONFERENCE_EVENT_H_ + +#include + +#include "event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Address; +class ConferenceEventPrivate; + +class LINPHONE_PUBLIC ConferenceEvent : public Event { +public: + ConferenceEvent (Type type, const std::shared_ptr
&address); + ConferenceEvent (const ConferenceEvent &src); + virtual ~ConferenceEvent () = default; + + ConferenceEvent &operator= (const ConferenceEvent &src); + + std::shared_ptr
getAddress () const; + +protected: + ConferenceEvent (ConferenceEventPrivate &p, Type type, const std::shared_ptr
&address); + +private: + L_DECLARE_PRIVATE(ConferenceEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _CONFERENCE_EVENT_H_ diff --git a/src/event/conference-participant-event.cpp b/src/event/conference-participant-event.cpp new file mode 100644 index 000000000..5cb0a1ce7 --- /dev/null +++ b/src/event/conference-participant-event.cpp @@ -0,0 +1,70 @@ +/* + * conference-participant-event.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "conference-event-p.h" + +#include "conference-participant-event.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceParticipantEventPrivate : public ConferenceEventPrivate { +public: + shared_ptr
participantAddress; +}; + +// ----------------------------------------------------------------------------- + +ConferenceParticipantEvent::ConferenceParticipantEvent ( + Type type, + const shared_ptr
&conferenceAddress, + const shared_ptr
&participantAddress +) : ConferenceEvent(*new ConferenceParticipantEventPrivate, type, conferenceAddress) { + L_D(ConferenceParticipantEvent); + L_ASSERT( + type == ConferenceParticipantAddedEvent || + type == ConferenceParticipantRemovedEvent || + type == ConferenceParticipantSetAdminEvent || + type == ConferenceParticipantUnsetAdminEvent + ); + L_ASSERT(participantAddress); + d->participantAddress = participantAddress; +} + +ConferenceParticipantEvent::ConferenceParticipantEvent (const ConferenceParticipantEvent &src) : + ConferenceParticipantEvent(src.getType(), src.getAddress(), src.getParticipantAddress()) {} + +ConferenceParticipantEvent &ConferenceParticipantEvent::operator= (const ConferenceParticipantEvent &src) { + L_D(ConferenceParticipantEvent); + if (this != &src) { + ConferenceEvent::operator=(src); + d->participantAddress = src.getPrivate()->participantAddress; + } + + return *this; +} + +shared_ptr
ConferenceParticipantEvent::getParticipantAddress () const { + // TODO. + return nullptr; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event/conference-participant-event.h b/src/event/conference-participant-event.h new file mode 100644 index 000000000..9b65f1002 --- /dev/null +++ b/src/event/conference-participant-event.h @@ -0,0 +1,49 @@ +/* + * conference-participant-event.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _CONFERENCE_PARTICIPANT_EVENT_H_ +#define _CONFERENCE_PARTICIPANT_EVENT_H_ + +#include "conference-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceParticipantEventPrivate; + +class LINPHONE_PUBLIC ConferenceParticipantEvent : public ConferenceEvent { +public: + ConferenceParticipantEvent ( + Type type, + const std::shared_ptr
&conferenceAddress, + const std::shared_ptr
&participantAddress + ); + ConferenceParticipantEvent (const ConferenceParticipantEvent &src); + + ConferenceParticipantEvent &operator= (const ConferenceParticipantEvent &src); + + std::shared_ptr
getParticipantAddress () const; + +private: + L_DECLARE_PRIVATE(ConferenceParticipantEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _CONFERENCE_PARTICIPANT_EVENT_H_ diff --git a/src/event/event-p.h b/src/event/event-p.h new file mode 100644 index 000000000..0499716fd --- /dev/null +++ b/src/event/event-p.h @@ -0,0 +1,38 @@ +/* + * event-p.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _EVENT_P_H_ +#define _EVENT_P_H_ + +#include "event.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class EventPrivate : public ClonableObjectPrivate { +private: + Event::Type type = Event::None; + + L_DECLARE_PUBLIC(Event); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _EVENT_P_H_ diff --git a/src/event/event.cpp b/src/event/event.cpp new file mode 100644 index 000000000..824240425 --- /dev/null +++ b/src/event/event.cpp @@ -0,0 +1,50 @@ +/* + * event.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "event-p.h" + +#include "event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +Event::Event () : ClonableObject(*new EventPrivate) {} + +Event::Event (const Event &) : ClonableObject(*new EventPrivate) {} + +Event::Event (EventPrivate &p, Type type) : ClonableObject(*new EventPrivate) { + L_D(Event); + d->type = type; +} + +Event &Event::operator= (const Event &src) { + L_D(Event); + if (this != &src) + d->type = src.getPrivate()->type; + return *this; +} + +Event::Type Event::getType () const { + L_D(const Event); + return d->type; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event/event.h b/src/event/event.h new file mode 100644 index 000000000..ebd530a4b --- /dev/null +++ b/src/event/event.h @@ -0,0 +1,66 @@ +/* + * event.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _EVENT_H_ +#define _EVENT_H_ + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class EventPrivate; + +class LINPHONE_PUBLIC Event : public ClonableObject { +public: + enum Type { + None, + // MessageEvent. + MessageEvent, + // CallEvent. + CallStartEvent, + CallEndEvent, + // ConferenceEvent. + ConferenceCreatedEvent, + ConferenceDestroyedEvent, + // ConferenceParticipantEvent. + ConferenceParticipantAddedEvent, + ConferenceParticipantRemovedEvent, + ConferenceParticipantSetAdminEvent, + ConferenceParticipantUnsetAdminEvent + }; + + Event (); + Event (const Event &src); + virtual ~Event () = default; + + Event &operator= (const Event &src); + + Type getType () const; + +protected: + Event (EventPrivate &p, Type type); + +private: + L_DECLARE_PRIVATE(Event); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _EVENT_H_ diff --git a/src/event/message-event.cpp b/src/event/message-event.cpp new file mode 100644 index 000000000..49e74f3b7 --- /dev/null +++ b/src/event/message-event.cpp @@ -0,0 +1,59 @@ +/* + * message-event.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "event-p.h" + +#include "message-event.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class MessageEventPrivate : public EventPrivate { +public: + shared_ptr message; +}; + +// ----------------------------------------------------------------------------- + +MessageEvent::MessageEvent (const shared_ptr &message) : Event(*new MessageEventPrivate, Event::MessageEvent) { + L_D(MessageEvent); + L_ASSERT(message); + d->message = message; +} + +MessageEvent::MessageEvent (const MessageEvent &src) : MessageEvent(src.getMessage()) {} + +MessageEvent &MessageEvent::operator= (const MessageEvent &src) { + L_D(MessageEvent); + if (this != &src) { + Event::operator=(src); + d->message = src.getPrivate()->message; + } + + return *this; +} + +shared_ptr MessageEvent::getMessage () const { + L_D(const MessageEvent); + return d->message; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event/message-event.h b/src/event/message-event.h new file mode 100644 index 000000000..9edff75a9 --- /dev/null +++ b/src/event/message-event.h @@ -0,0 +1,48 @@ +/* + * message-event.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _MESSAGE_EVENT_H_ +#define _MESSAGE_EVENT_H_ + +#include + +#include "event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Message; +class MessageEventPrivate; + +class LINPHONE_PUBLIC MessageEvent : public Event { +public: + MessageEvent (const std::shared_ptr &message); + MessageEvent (const MessageEvent &src); + + MessageEvent &operator= (const MessageEvent &src); + + std::shared_ptr getMessage () const; + +private: + L_DECLARE_PRIVATE(MessageEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _MESSAGE_EVENT_H_ diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index 340cf4a4f..7ca01589d 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -49,7 +49,9 @@ Logger::~Logger () { switch (d->level) { case Debug: - ms_debug("%s", str.c_str()); + #if DEBUG_LOGS + ms_debug("%s", str.c_str()); + #endif // if DEBUG_LOGS break; case Info: ms_message("%s", str.c_str()); diff --git a/src/logger/logger.h b/src/logger/logger.h index c3c209c1e..2314a9ea9 100644 --- a/src/logger/logger.h +++ b/src/logger/logger.h @@ -57,4 +57,10 @@ LINPHONE_END_NAMESPACE #define lError() LINPHONE_NAMESPACE::Logger(Logger::Error).getOutput() #define lFatal() LINPHONE_NAMESPACE::Logger(Logger::Fatal).getOutput() +#define L_BEGIN_LOG_EXCEPTION try { + #define L_END_LOG_EXCEPTION \ +} catch (const exception &e) { \ + lWarning() << "Error: " << e.what(); \ +} + #endif // ifndef _LOGGER_H_ diff --git a/src/message/message.cpp b/src/message/message.cpp new file mode 100644 index 000000000..a4e907426 --- /dev/null +++ b/src/message/message.cpp @@ -0,0 +1,188 @@ +/* + * message.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include + +#include "db/events-db.h" +#include "object/object-p.h" + +#include "message.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +using namespace std; + +class MessagePrivate : public ObjectPrivate { +private: + weak_ptr chatRoom; + Message::Direction direction = Message::Incoming; + // LinphoneAddress *from; + // LinphoneAddress *to; + shared_ptr errorInfo; + string contentType; + string text; + bool isSecured = false; + time_t time = 0; + string id; + string appData; + list > contents; + unordered_map customHeaders; + Message::State state = Message::Idle; + shared_ptr eventsDb; + + L_DECLARE_PUBLIC(Message); +}; + +// ----------------------------------------------------------------------------- + +Message::Message (MessagePrivate &p) : Object(p) {} + +shared_ptr Message::getChatRoom () const { + L_D(const Message); + shared_ptr chatRoom = d->chatRoom.lock(); + if (!chatRoom) { + // TODO. + } + return chatRoom; +} + +Message::Direction Message::getDirection () const { + L_D(const Message); + return d->direction; +} + +shared_ptr Message::getFromAddress () const { + // TODO. + return nullptr; +} + +shared_ptr Message::getToAddress () const { + // TODO. + return nullptr; +} + +shared_ptr Message::getLocalAddress () const { + // TODO. + return nullptr; +} + +shared_ptr Message::getRemoteAddress () const { + // TODO. + return nullptr; +} + +Message::State Message::getState () const { + L_D(const Message); + return d->state; +} + +shared_ptr Message::getErrorInfo () const { + L_D(const Message); + return d->errorInfo; +} + +string Message::getContentType () const { + L_D(const Message); + return d->contentType; +} + +string Message::getText () const { + L_D(const Message); + return d->text; +} + +void Message::setText (const string &text) { + L_D(Message); + d->text = text; +} + +void Message::send () const { + // TODO. +} + +bool Message::containsReadableText () const { + // TODO: Check content type. + return true; +} + +bool Message::isSecured () const { + L_D(const Message); + return d->isSecured; +} + +time_t Message::getTime () const { + L_D(const Message); + return d->time; +} + +string Message::getId () const { + L_D(const Message); + return d->id; +} + +string Message::getAppdata () const { + L_D(const Message); + return d->appData; +} + +void Message::setAppdata (const string &appData) { + L_D(Message); + d->appData = appData; +} + +list > Message::getContents () const { + L_D(const Message); + list > contents; + for (const auto &content : d->contents) + contents.push_back(content); + return contents; +} + +void Message::addContent (const shared_ptr &content) { + L_D(Message); + d->contents.push_back(content); +} + +void Message::removeContent (const shared_ptr &content) { + L_D(Message); + d->contents.remove(const_pointer_cast(content)); +} + +string Message::getCustomHeaderValue (const string &headerName) const { + L_D(const Message); + try { + return d->customHeaders.at(headerName); + } catch (const exception &) { + // Key doesn't exist. + } + return ""; +} + +void Message::addCustomHeader (const string &headerName, const string &headerValue) { + L_D(Message); + d->customHeaders[headerName] = headerValue; +} + +void Message::removeCustomHeader (const string &headerName) { + L_D(Message); + d->customHeaders.erase(headerName); +} + +LINPHONE_END_NAMESPACE diff --git a/src/message/message.h b/src/message/message.h new file mode 100644 index 000000000..61754010b --- /dev/null +++ b/src/message/message.h @@ -0,0 +1,107 @@ +/* + * message.h + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#ifndef _MESSAGE_H_ +#define _MESSAGE_H_ + +#include +#include +#include + +#include "enums.h" +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Address; +class ChatRoom; +class Content; +class ErrorInfo; +class MessagePrivate; + +class LINPHONE_PUBLIC Message : public Object { + friend class ChatRoom; + +public: + enum Direction { + Incoming, + Outgoing + }; + + enum State { + Idle, + InProgress, + Delivered, + NotDelivered, + FileTransferError, + FileTransferDone, + DeliveredToUser, + Displayed + }; + + std::shared_ptr getChatRoom () const; + + Direction getDirection () const; + + std::shared_ptr getFromAddress () const; + std::shared_ptr getToAddress () const; + std::shared_ptr getLocalAddress () const; + std::shared_ptr getRemoteAddress () const; + + State getState () const; + + std::shared_ptr getErrorInfo () const; + + std::string getContentType () const; + + std::string getText () const; + void setText (const std::string &text); + + void send () const; + + bool containsReadableText () const; + + bool isSecured () const; + + time_t getTime () const; + + std::string getId () const; + + std::string getAppdata () const; + void setAppdata (const std::string &appData); + + std::list > getContents () const; + void addContent (const std::shared_ptr &content); + void removeContent (const std::shared_ptr &content); + + std::string getCustomHeaderValue (const std::string &headerName) const; + void addCustomHeader (const std::string &headerName, const std::string &headerValue); + void removeCustomHeader (const std::string &headerName); + +private: + Message (MessagePrivate &p); + + L_DECLARE_PRIVATE(Message); + L_DISABLE_COPY(Message); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _MESSAGE_H_ diff --git a/src/object/clonable-object-p.h b/src/object/clonable-object-p.h index 94c3b4491..8c099be7b 100644 --- a/src/object/clonable-object-p.h +++ b/src/object/clonable-object-p.h @@ -19,22 +19,27 @@ #ifndef _CLONABLE_OBJECT_P_H_ #define _CLONABLE_OBJECT_P_H_ +#include + #include "utils/general.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE -class ClonableObject; - class ClonableObjectPrivate { public: virtual ~ClonableObjectPrivate () = default; protected: - ClonableObject *mPublic = nullptr; + std::unordered_map *mPublic = nullptr; private: + void ref (); + void unref (); + + int nRefs = 0; + L_DECLARE_PUBLIC(ClonableObject); }; diff --git a/src/object/clonable-object.cpp b/src/object/clonable-object.cpp index 5b21b09b3..1eb46a512 100644 --- a/src/object/clonable-object.cpp +++ b/src/object/clonable-object.cpp @@ -20,16 +20,66 @@ #include "clonable-object.h" -LINPHONE_BEGIN_NAMESPACE - // ============================================================================= -ClonableObject::~ClonableObject () { - delete mPrivate; +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// TODO: Use atomic counter? + +void ClonableObjectPrivate::ref () { + ++nRefs; } +void ClonableObjectPrivate::unref () { + if (--nRefs == 0) { + delete mPublic; + delete this; + } +} + +// ----------------------------------------------------------------------------- + ClonableObject::ClonableObject (ClonableObjectPrivate &p) : mPrivate(&p) { - mPrivate->mPublic = this; + // Q-pointer must be empty. It's a constructor that takes a new private data. + L_ASSERT(!mPrivate->mPublic); + + mPrivate->mPublic = new remove_pointermPublic)>::type; + (*mPrivate->mPublic)[mPrivate] = this; + mPrivate->ref(); +} + +ClonableObject::ClonableObject (const ClonableObjectPrivate &p) { + // Cannot access to Q-pointer. It's a copy constructor from private data. + L_ASSERT(!mPrivate); + + setRef(p); +} + +ClonableObject::~ClonableObject () { + mPrivate->mPublic->erase(mPrivate); + mPrivate->unref(); +} + +void ClonableObject::setRef (const ClonableObjectPrivate &p) { + // Q-pointer must exist if private data is defined. + L_ASSERT(!mPrivate || mPrivate->mPublic); + + // Nothing, same reference. + if (&p == mPrivate) + return; + + // Unref previous private data. + if (mPrivate) { + mPrivate->mPublic->erase(mPrivate); + mPrivate->unref(); + } + + // Add and reference new private data. + mPrivate = const_cast(&p); + (*mPrivate->mPublic)[mPrivate] = this; + mPrivate->ref(); } LINPHONE_END_NAMESPACE diff --git a/src/object/clonable-object.h b/src/object/clonable-object.h index bda4392e1..490c5bc71 100644 --- a/src/object/clonable-object.h +++ b/src/object/clonable-object.h @@ -25,19 +25,28 @@ LINPHONE_BEGIN_NAMESPACE -class ClonableObjectPrivate; - class LINPHONE_PUBLIC ClonableObject { public: virtual ~ClonableObject (); protected: + // Use a new ClonableObjectPrivate without owner. explicit ClonableObject (ClonableObjectPrivate &p); + // If you want share an existing ClonableObjectPrivate, call this function. + explicit ClonableObject (const ClonableObjectPrivate &p); + + // Change the ClonableObjectPrivate, it can be shared. + void setRef (const ClonableObjectPrivate &p); + ClonableObjectPrivate *mPrivate = nullptr; private: L_DECLARE_PRIVATE(ClonableObject); + + // Yeah, it's a `ClonableObject` that cannot be copied. + // Only inherited classes must implement copy. + L_DISABLE_COPY(ClonableObject); }; LINPHONE_END_NAMESPACE diff --git a/src/object/object-p.h b/src/object/object-p.h index 83d7612fc..ca9111eac 100644 --- a/src/object/object-p.h +++ b/src/object/object-p.h @@ -25,8 +25,6 @@ LINPHONE_BEGIN_NAMESPACE -class Object; - class ObjectPrivate { public: virtual ~ObjectPrivate () = default; diff --git a/src/object/object.h b/src/object/object.h index 54ed08d28..d3cc22808 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -25,8 +25,6 @@ LINPHONE_BEGIN_NAMESPACE -class ObjectPrivate; - class LINPHONE_PUBLIC Object { public: virtual ~Object (); diff --git a/src/utils/general.cpp b/src/utils/general.cpp new file mode 100644 index 000000000..9ed357c03 --- /dev/null +++ b/src/utils/general.cpp @@ -0,0 +1,31 @@ +/* + * general.cpp + * Copyright (C) 2017 Belledonne Communications SARL + * + * 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 3 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, see . + */ + +#include "logger/logger.h" + +#include "general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +void l_assert (const char *condition, const char *file, int line) { + lFatal() << "ASSERT: " << condition << " in " << file << " line " << line << "."; +} + +LINPHONE_END_NAMESPACE diff --git a/src/utils/general.h b/src/utils/general.h index 17a911eb6..243c7a7ca 100644 --- a/src/utils/general.h +++ b/src/utils/general.h @@ -16,11 +16,19 @@ * along with this program. If not, see . */ -// ============================================================================= - #ifndef _GENERAL_H_ #define _GENERAL_H_ +// ============================================================================= + +#define LINPHONE_NAMESPACE LinphonePrivate +#define LINPHONE_BEGIN_NAMESPACE namespace LINPHONE_NAMESPACE { +#define LINPHONE_END_NAMESPACE } + +// ----------------------------------------------------------------------------- + +LINPHONE_BEGIN_NAMESPACE + #ifndef LINPHONE_PUBLIC #if defined(_MSC_VER) #ifdef LINPHONE_STATIC @@ -39,11 +47,13 @@ // ----------------------------------------------------------------------------- -#define LINPHONE_NAMESPACE LinphonePrivate -#define LINPHONE_BEGIN_NAMESPACE namespace LINPHONE_NAMESPACE { -#define LINPHONE_END_NAMESPACE } +void l_assert (const char *condition, const char *file, int line); -// ----------------------------------------------------------------------------- +#ifdef DEBUG + #define L_ASSERT(CONDITION) static_cast(false && (CONDITION)) +#else + #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast(0) : l_assert(#CONDITION, __FILE__, __LINE__)) +#endif #define L_DECLARE_PRIVATE(CLASS) \ inline CLASS ## Private * getPrivate() { \ @@ -54,12 +64,41 @@ } \ friend class CLASS ## Private; +class ClonableObject; +class ClonableObjectPrivate; +class Object; +class ObjectPrivate; + +template +inline ClonableObject *getPublicHelper (T *object, ClonableObjectPrivate *context) { + auto it = object->find(context); + L_ASSERT(it != object->end()); + return it->second; +} + +template +inline const ClonableObject *getPublicHelper (const T *object, const ClonableObjectPrivate *context) { + auto it = object->find(context); + L_ASSERT(it != object->cend()); + return it->second; +} + +template +inline Object *getPublicHelper (T *object, ObjectPrivate *) { + return object; +} + +template +inline const Object *getPublicHelper (const T *object, const ObjectPrivate *) { + return object; +} + #define L_DECLARE_PUBLIC(CLASS) \ - inline CLASS * getPublic() { \ - return static_cast(mPublic); \ + inline CLASS * getPublic () { \ + return static_cast(getPublicHelper(mPublic, this)); \ } \ - inline const CLASS *getPublic() const { \ - return static_cast(mPublic); \ + inline const CLASS *getPublic () const { \ + return static_cast(getPublicHelper(mPublic, this)); \ } \ friend class CLASS; @@ -70,4 +109,14 @@ #define L_D(CLASS) CLASS ## Private * const d = getPrivate(); #define L_Q(CLASS) CLASS * const q = getPublic(); +#define L_USE_DEFAULT_SHARE_IMPL(CLASS, PARENT_CLASS) \ + CLASS::CLASS (const CLASS &src) : PARENT_CLASS(*src.getPrivate()) {} \ + CLASS &CLASS::operator= (const CLASS &src) { \ + if (this != &src) \ + setRef(*src.getPrivate()); \ + return *this; \ + } + +LINPHONE_END_NAMESPACE + #endif // ifndef _GENERAL_H_ diff --git a/src/utils/utils.h b/src/utils/utils.h index 3e5ca768d..e64dc4e7e 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -29,15 +29,15 @@ LINPHONE_BEGIN_NAMESPACE namespace Utils { - bool iequals (const std::string &a, const std::string &b); + LINPHONE_PUBLIC bool iequals (const std::string &a, const std::string &b); - std::vector split (const std::string &str, const std::string &delimiter); + LINPHONE_PUBLIC std::vector split (const std::string &str, const std::string &delimiter); - inline std::vector split (const std::string &str, char delimiter) { + LINPHONE_PUBLIC inline std::vector split (const std::string &str, char delimiter) { return split(str, std::string(1, delimiter)); } - int stoi (const std::string &str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10); } LINPHONE_END_NAMESPACE diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 4e101551d..6e2105d10 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -205,7 +205,7 @@ if(APPLE) endif() bc_apply_compile_flags(SOURCE_FILES_C STRICT_OPTIONS_CPP STRICT_OPTIONS_C) -bc_apply_compile_flags(SOURCE_FILES_C_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX) +bc_apply_compile_flags(SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX) bc_apply_compile_flags(SOURCE_FILES_OBJC STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC) if(MSVC) diff --git a/tester/accountmanager.c b/tester/accountmanager.c index 385717ed2..26ebd3f75 100644 --- a/tester/accountmanager.c +++ b/tester/accountmanager.c @@ -259,7 +259,7 @@ static LinphoneAddress *account_manager_check_account(AccountManager *m, Linphon void linphone_core_manager_check_accounts(LinphoneCoreManager *m){ const bctbx_list_t *it; AccountManager *am=account_manager_get(); - int logmask = ortp_get_log_level_mask(NULL); + int logmask = linphone_core_get_log_level_mask(); if (!liblinphonetester_show_account_manager_logs) linphone_core_set_log_level_mask(ORTP_ERROR|ORTP_FATAL); for(it=linphone_core_get_proxy_config_list(m->lc);it!=NULL;it=it->next){ diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 383722743..089ac77d6 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -6158,6 +6158,101 @@ static void recreate_zrtpdb_when_corrupted(void) { #endif /* SQLITE_STORAGE_ENABLED */ } +static void simple_call_with_gruu(void) { + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + const LinphoneAddress *addr; + LinphoneCall *marie_call = NULL; + LinphoneCall *pauline_call = NULL; + LinphoneProxyConfig* pauline_cfg; + + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new("pauline_tcp_rc"); + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); + + pauline_cfg = linphone_core_get_default_proxy_config(pauline->lc); + addr = linphone_proxy_config_get_contact(pauline_cfg); + BC_ASSERT_PTR_NOT_NULL(addr); + BC_ASSERT_PTR_NOT_NULL(strstr(linphone_address_as_string_uri_only(addr), "gr")); + + marie_call = linphone_core_invite_address(marie->lc, addr); + BC_ASSERT_PTR_NOT_NULL(marie_call); + if(!marie_call) goto end; + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1)); + pauline_call = linphone_core_get_current_call(pauline->lc); + BC_ASSERT_PTR_NOT_NULL(pauline_call); + if(!pauline_call) goto end; + linphone_call_accept(pauline_call); + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); + + linphone_call_terminate(pauline_call); + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); + +end: + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); +} + +static void simple_call_with_gruu_only_one_device_ring(void) { + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + LinphoneCoreManager* pauline2; + const LinphoneAddress *pauline_addr; + const LinphoneAddress *pauline_addr2; + LinphoneCall *marie_call = NULL; + LinphoneCall *pauline_call = NULL; + LinphoneProxyConfig* pauline_cfg; + LinphoneProxyConfig* pauline_cfg2; + + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + pauline2 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline2->stat.number_of_LinphoneRegistrationOk, 1)); + + pauline_cfg = linphone_core_get_default_proxy_config(pauline->lc); + pauline_addr = linphone_proxy_config_get_contact(pauline_cfg); + BC_ASSERT_PTR_NOT_NULL(pauline_addr); + BC_ASSERT_PTR_NOT_NULL(strstr(linphone_address_as_string_uri_only(pauline_addr), "gr")); + pauline_cfg2 = linphone_core_get_default_proxy_config(pauline2->lc); + pauline_addr2 = linphone_proxy_config_get_contact(pauline_cfg2); + BC_ASSERT_PTR_NOT_NULL(pauline_addr2); + BC_ASSERT_PTR_NOT_NULL(strstr(linphone_address_as_string_uri_only(pauline_addr2), "gr")); + BC_ASSERT_NOT_EQUAL(linphone_address_as_string_uri_only(pauline_addr), linphone_address_as_string_uri_only(pauline_addr2), char*, "%s"); // Not same GRUU + + marie_call = linphone_core_invite_address(marie->lc, pauline_addr); + BC_ASSERT_PTR_NOT_NULL(marie_call); + if(!marie_call) goto end; + BC_ASSERT_FALSE(wait_for(marie->lc, pauline2->lc, &pauline2->stat.number_of_LinphoneCallIncomingReceived, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1)); + pauline_call = linphone_core_get_current_call(pauline->lc); + BC_ASSERT_PTR_NOT_NULL(pauline_call); + if(!pauline_call) goto end; + + linphone_call_accept(pauline_call); + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); + + linphone_call_terminate(pauline_call); + + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); + +end: + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(pauline2); + 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), @@ -6309,7 +6404,9 @@ test_t call_tests[] = { TEST_NO_TAG("Call cancelled with reason", cancel_call_with_error), TEST_NO_TAG("Call accepted, other ringing device receive CANCEL with reason", cancel_other_device_after_accept), TEST_NO_TAG("Call declined, other ringing device receive CANCEL with reason", cancel_other_device_after_decline), - TEST_NO_TAG("Recreate ZRTP db file when corrupted", recreate_zrtpdb_when_corrupted) + TEST_NO_TAG("Recreate ZRTP db file when corrupted", recreate_zrtpdb_when_corrupted), + TEST_NO_TAG("Simple call with GRUU", simple_call_with_gruu), + TEST_NO_TAG("Simple call with GRUU only one device ring", simple_call_with_gruu_only_one_device_ring) }; test_suite_t call_test_suite = {"Single Call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/flexisip/userdb.conf b/tester/flexisip/userdb.conf index 6ac364764..c990afc35 100644 --- a/tester/flexisip/userdb.conf +++ b/tester/flexisip/userdb.conf @@ -1,8 +1,7 @@ -liblinphone_tester@sip.example.org secret liblinphone_tester +33123456789 +liblinphone_tester@sip.example.org secret liblinphone_tester@auth.example.org secret liblinphone_tester@auth1.example.org secret tester@sip.example.org secret - pauline@sip.example.org secret marie@sip.example.org secret laure@sip.example.org secret diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 3626150a4..7421a20d0 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -167,9 +167,7 @@ static void log_handler(int lev, const char *fmt, va_list args) { #endif va_end(cap); #endif - if (log_file){ - ortp_logv_out(ORTP_LOG_DOMAIN, lev, fmt, args); - } + bctbx_logv(ORTP_LOG_DOMAIN, lev, fmt, args); } void liblinphone_tester_init(void(*ftester_printf)(int level, const char *fmt, va_list args)) { @@ -195,8 +193,7 @@ int liblinphone_tester_set_log_file(const char *filename) { return -1; } ms_message("Redirecting traces to file [%s]", filename); - bctbx_set_log_file(log_file); - ortp_set_log_file(log_file); + linphone_core_set_log_file(log_file); return 0; } diff --git a/tester/proxy_config_tester.c b/tester/proxy_config_tester.c index 27c4063f0..c11f352db 100644 --- a/tester/proxy_config_tester.c +++ b/tester/proxy_config_tester.c @@ -132,6 +132,14 @@ static void phone_normalization_with_proxy(void) { BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "+5217227718184"), "+5217227718184"); /*this is a mobile phone number */ BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "+528127718184"), "+528127718184"); /*this is a landline phone number from Monterrey*/ + // Phone normalization for myanmar dial plans + linphone_proxy_config_set_dial_prefix(proxy, "95"); + BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "9965066691"), "+959965066691"); + + // Phone normalization for cameroon dial plans + linphone_proxy_config_set_dial_prefix(proxy, "237"); + BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "674788175"), "+237674788175"); + linphone_proxy_config_unref(proxy); } diff --git a/tester/register_tester.c b/tester/register_tester.c index 6989c8b1c..c994e8931 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -684,6 +684,11 @@ static void proxy_transport_change(void){ linphone_core_manager_destroy(lcm); } +/* + * On ios, some firewal require to disable flow label (livebox with default firewall level). + * sudo sysctl net.inet6.ip6.auto_flowlabel=0 + * It might be possible to found a sockopt for such purpose. + */ static void proxy_transport_change_with_wrong_port(void) { LinphoneCoreManager* lcm = create_lcm(); stats* counters = &lcm->stat; @@ -1180,6 +1185,16 @@ static void tls_auth_info_client_cert_cb_2(void) { } } +static void register_get_gruu(void) { + LinphoneCoreManager *marie=linphone_core_manager_new("marie_rc"); + LinphoneProxyConfig *cfg=linphone_core_get_default_proxy_config(marie->lc); + if(cfg) { + const LinphoneAddress *addr = linphone_proxy_config_get_contact(cfg); + BC_ASSERT_PTR_NOT_NULL(addr); + BC_ASSERT_PTR_NOT_NULL(strstr(linphone_address_as_string_uri_only(addr), "gr")); + } + linphone_core_manager_destroy(marie); +} test_t register_tests[] = { TEST_NO_TAG("Simple register", simple_register), @@ -1226,6 +1241,7 @@ test_t register_tests[] = { TEST_NO_TAG("AuthInfo TLS client certificate authentication using API 2", tls_auth_info_client_cert_api_path), TEST_NO_TAG("AuthInfo TLS client certificate authentication in callback", tls_auth_info_client_cert_cb), TEST_NO_TAG("AuthInfo TLS client certificate authentication in callback 2", tls_auth_info_client_cert_cb_2), + TEST_NO_TAG("Register get GRUU", register_get_gruu) }; test_suite_t register_test_suite = {"Register", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/tester.c b/tester/tester.c index 38a620a28..4e1b5c7f8 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -461,7 +461,7 @@ void linphone_core_manager_stop(LinphoneCoreManager *mgr){ } void linphone_core_manager_uninit(LinphoneCoreManager *mgr) { - int old_log_level = ortp_get_log_level_mask(NULL); + int old_log_level = linphone_core_get_log_level_mask(); linphone_core_set_log_level(ORTP_ERROR); if (mgr->phone_alias) { ms_free(mgr->phone_alias); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index f26b5491f..fdc797c02 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -33,7 +33,7 @@ endif() set(LP_AUTO_ANSWER_SOURCE_FILES auto_answer.c) bc_apply_compile_flags(LP_AUTO_ANSWER_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(lp-auto-answer ${USE_BUNDLE} ${LP_AUTO_ANSWER_SOURCE_FILES}) -target_link_libraries(lp-auto-answer ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_LIBRARIES}) +target_link_libraries(lp-auto-answer ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) set_target_properties(lp-auto-answer PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set(LP_SENDMSG_SOURCE_FILES lpsendmsg.c) @@ -57,7 +57,7 @@ set_target_properties(xml2lpc_test PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set(LP_TEST_ECC_SOURCE_FILES test_ecc.c) bc_apply_compile_flags(LP_TEST_ECC_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(lp-test-ecc ${USE_BUNDLE} ${LP_TEST_ECC_SOURCE_FILES}) -target_link_libraries(lp-test-ecc ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES}) +target_link_libraries(lp-test-ecc ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) set_target_properties(lp-test-ecc PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") if (NOT IOS) diff --git a/wrappers/csharp/genwrapper.py b/wrappers/csharp/genwrapper.py index 84dd66dd9..2bf303cf6 100644 --- a/wrappers/csharp/genwrapper.py +++ b/wrappers/csharp/genwrapper.py @@ -1,17 +1,17 @@ #!/usr/bin/python # Copyright (C) 2017 Belledonne Communications SARL -# +# # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -58,7 +58,7 @@ class CsharpTranslator(object): def translate_method_name(self, name, recursive=False, topAncestor=None): translatedName = name.to_camel_case(lower=True) - + if name.prev is None or not recursive or name.prev is topAncestor: return translatedName @@ -129,7 +129,7 @@ class CsharpTranslator(object): return False if dllImport else True elif type(_type) is AbsApi.EnumType: return False if dllImport else True - + def translate_type(self, _type, isArg, dllImport=True): if type(_type) is AbsApi.EnumType: if dllImport and isArg: @@ -156,10 +156,10 @@ class CsharpTranslator(object): raise AbsApi.Error('translation of bctbx_list_t of enums') else: raise AbsApi.Error('translation of bctbx_list_t of unknow type !') - + def translate_argument(self, arg, dllImport=True): return '{0} {1}'.format(self.translate_type(arg.type, True, dllImport), self.translate_argument_name(arg.name)) - + def throws_exception(self, return_type): if type(return_type) is AbsApi.BaseType: if return_type.name == 'status': @@ -178,7 +178,7 @@ class CsharpTranslator(object): if arg is not method.args[0] or not static: methodElems['params'] += ', ' methodElems['params'] += self.translate_argument(arg) - + methodDict = {} methodDict['prototype'] = "static extern {return} {name}({params});".format(**methodElems) @@ -235,7 +235,7 @@ class CsharpTranslator(object): methodDict['impl']['args'] += self.translate_argument(arg, False) return methodDict - + ########################################################################################################################################### def translate_property_getter(self, prop, name, static=False): @@ -311,7 +311,7 @@ class CsharpTranslator(object): methodDict['setter_c_name'] = methodDictSet['setter_c_name'] return methodDict - + def translate_property(self, prop): res = [] name = prop.name.to_camel_case() @@ -323,7 +323,7 @@ class CsharpTranslator(object): elif prop.setter is not None: res.append(self.translate_property_setter(prop.setter, name)) return res - + ########################################################################################################################################### def translate_listener(self, _class, method): @@ -350,7 +350,7 @@ class CsharpTranslator(object): listenerDict['delegate']['interfaceClassName'] = listenedClass.name.to_camel_case() listenerDict['delegate']['isSimpleListener'] = not listenedClass.multilistener listenerDict['delegate']['isMultiListener'] = listenedClass.multilistener - + listenerDict['delegate']['params_public'] = "" listenerDict['delegate']['params_private'] = "" listenerDict['delegate']['params'] = "" @@ -378,7 +378,7 @@ class CsharpTranslator(object): else: listenerDict['delegate']['first_param'] = argName listenerDict['delegate']['params'] = 'thiz' - + listenerDict['delegate']['params_public'] += normalType + " " + argName listenerDict['delegate']['params_private'] += dllImportType + " " + argName @@ -434,7 +434,7 @@ class CsharpTranslator(object): methodDict['is_generic'] = True return methodDict - + ########################################################################################################################################### def translate_enum(self, enum): @@ -470,6 +470,8 @@ class CsharpTranslator(object): classDict = {} classDict['className'] = _class.name.to_camel_case() classDict['isLinphoneFactory'] = _class.name.to_camel_case() == "Factory" + classDict['isLinphoneCall'] = _class.name.to_camel_case() == "Call" + classDict['isLinphoneCore'] = _class.name.to_camel_case() == "Core" classDict['doc'] = self.docTranslator.translate(_class.briefDescription) classDict['dllImports'] = [] @@ -482,12 +484,12 @@ class CsharpTranslator(object): else: classDict['dllImports'].append(self.generate_add_for_listener_callbacks(_class, listenerName)) classDict['dllImports'].append(self.generate_remove_for_listener_callbacks(_class, listenerName)) - + for method in _class.classMethods: try: if 'get' in method.name.to_word_list(): methodDict = self.translate_property_getter(method, method.name.to_camel_case(), True) - #The following doesn't work because there a at least one method that has both getter and setter, + #The following doesn't work because there a at least one method that has both getter and setter, #and because it doesn't do both of them at once, property is declared twice #elif 'set' in method.name.to_word_list(): # methodDict = self.translate_property_setter(method, method.name.to_camel_case(), True) @@ -521,7 +523,7 @@ class CsharpTranslator(object): interfaceDict['methods'] = [] for method in interface.methods: interfaceDict['methods'].append(self.translate_listener(interface, method)) - + return interfaceDict ########################################################################################################################################### @@ -549,7 +551,7 @@ class WrapperImpl(object): self.enums = enums self.interfaces = interfaces self.classes = classes - + ########################################################################################################################################### def render(renderer, item, path): @@ -569,21 +571,29 @@ def main(): argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.') argparser.add_argument('-n --name', type=str, help='the name of the genarated source file', dest='outputfile', default='LinphoneWrapper.cs') args = argparser.parse_args() - + entries = os.listdir(args.outputdir) - + project = CApi.Project() project.initFromDir(args.xmldir) project.check() - + parser = AbsApi.CParser(project) - parser.functionBl = ['linphone_vcard_get_belcard', 'linphone_core_get_current_vtable'] + parser.functionBl = \ + ['linphone_vcard_get_belcard',\ + 'linphone_core_get_current_vtable',\ + 'linphone_call_set_native_video_window_id',\ + 'linphone_call_get_native_video_window_id',\ + 'linphone_core_get_native_preview_window_id',\ + 'linphone_core_set_native_preview_window_id',\ + 'linphone_core_set_native_video_window_id',\ + 'linphone_core_get_native_video_window_id'] parser.classBl += 'LinphoneCoreVTable' parser.methodBl.remove('getCurrentCallbacks') parser.parse_all() translator = CsharpTranslator() renderer = pystache.Renderer() - + enums = [] for item in parser.enumsIndex.items(): if item[1] is not None: @@ -610,4 +620,4 @@ def main(): render(renderer, wrapper, args.outputdir + "/" + args.outputfile) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/wrappers/csharp/wrapper_impl.mustache b/wrappers/csharp/wrapper_impl.mustache index f99438889..f66c504fe 100644 --- a/wrappers/csharp/wrapper_impl.mustache +++ b/wrappers/csharp/wrapper_impl.mustache @@ -376,6 +376,62 @@ namespace Linphone return fromNativePtr(coreCbsPtr, false); } {{/isLinphoneFactory}} + {{#isLinphoneCall}} + [DllImport(LinphoneWrapper.LIB_NAME)] + static extern IntPtr linphone_call_get_native_video_window_id(IntPtr thiz); + [DllImport(LinphoneWrapper.LIB_NAME)] + static extern void linphone_call_set_native_video_window_id(IntPtr thiz, IntPtr id); + + /// Get the native window handle of the video window, casted as an unsigned long. + public string NativeVideoWindowId + { + get + { + return Marshal.PtrToStringUni(linphone_call_get_native_video_window_id(nativePtr)); + } + set + { + linphone_call_set_native_video_window_id(nativePtr, Marshal.StringToHGlobalUni(value)); + } + } + {{/isLinphoneCall}} + {{#isLinphoneCore}} + [DllImport(LinphoneWrapper.LIB_NAME)] + static extern IntPtr linphone_core_get_native_video_window_id(IntPtr thiz); + [DllImport(LinphoneWrapper.LIB_NAME)] + static extern void linphone_core_set_native_video_window_id(IntPtr thiz, IntPtr id); + + /// Get the native window handle of the video window. + public string NativeVideoWindowId + { + get + { + return Marshal.PtrToStringUni(linphone_core_get_native_video_window_id(nativePtr)); + } + set + { + linphone_core_set_native_video_window_id(nativePtr, Marshal.StringToHGlobalUni(value)); + } + } + + [DllImport(LinphoneWrapper.LIB_NAME)] + static extern IntPtr linphone_core_get_native_preview_window_id(IntPtr thiz); + [DllImport(LinphoneWrapper.LIB_NAME)] + static extern void linphone_core_set_native_preview_window_id(IntPtr thiz, IntPtr id); + + /// Get the native window handle of the video preview window. + public string NativePreviewWindowId + { + get + { + return Marshal.PtrToStringUni(linphone_core_get_native_preview_window_id(nativePtr)); + } + set + { + linphone_core_set_native_preview_window_id(nativePtr, Marshal.StringToHGlobalUni(value)); + } + } + {{/isLinphoneCore}} {{#dllImports}} [DllImport(LinphoneWrapper.LIB_NAME)] {{{prototype}}} @@ -400,7 +456,7 @@ namespace Linphone return Marshal.PtrToStringAnsi(stringPtr); {{/is_string}} {{#is_bool}} - return {{getter_c_name}}({{getter_nativePtr}}) == 1; + return {{getter_c_name}}({{getter_nativePtr}}) != 0; {{/is_bool}} {{#is_class}} IntPtr ptr = {{getter_c_name}}({{getter_nativePtr}}); @@ -476,12 +532,12 @@ namespace Linphone return fromNativePtr<{{type}}>(ptr, {{takeRef}}); {{/is_class}} {{#is_enum}} - {{#exception}}int exception_result = {{/exception}}{{return}}{{c_name}}({{nativePtr}}{{c_args}}); + {{#exception}}int exception_result = {{/exception}}{{return}}{{c_name}}({{nativePtr}}{{{c_args}}}); {{#exception}}if (exception_result != 0) throw new LinphoneException("{{name}} returned value " + exception_result);{{/exception}} {{/is_enum}} {{#is_generic}} - {{#exception}}int exception_result = {{/exception}}{{return}}{{c_name}}({{nativePtr}}{{c_args}}); - {{#exception}}if (exception_result != 0) throw new LinphoneException("{{name}} returned value " + exception_result);{{/exception}} + {{#exception}}int exception_result = {{/exception}}{{return}}{{c_name}}({{nativePtr}}{{{c_args}}}); + {{#exception}}if (exception_result != 0) throw new LinphoneException("{{name}} returned value" + exception_result);{{/exception}} {{/is_generic}} {{#is_string_list}} return MarshalStringArray({{c_name}}({{nativePtr}}{{c_args}}));