diff --git a/CMakeLists.txt b/CMakeLists.txt index 69be3d8d8..9ee2ecc62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,6 @@ option(ENABLE_JAVADOC "Add a target to generate documentation for Java API" NO) option(ENABLE_LDAP "Enable LDAP support." NO) 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) @@ -255,7 +254,6 @@ if(MSVC) include_directories(${MSVC_INCLUDE_DIR}) endif() -add_definitions("-DLINPHONE_EXPORTS") set(LINPHONE_CPPFLAGS ${BELCARD_CPPFLAGS} ${BELLESIP_CPPFLAGS} ${MEDIASTREAMER2_CPPFLAGS} ${BCTOOLBOX_CPPFLAGS} ${BELR_CPPFLAGS}) if(ENABLE_STATIC) list(APPEND LINPHONE_CPPFLAGS "-DLINPHONE_STATIC") diff --git a/build/rpm/liblinphone.spec.cmake b/build/rpm/liblinphone.spec.cmake index b0f030334..f2512146c 100755 --- a/build/rpm/liblinphone.spec.cmake +++ b/build/rpm/liblinphone.spec.cmake @@ -31,6 +31,9 @@ Requires: %{pkg_prefix}ortp Requires: %{pkg_prefix}mediastreamer Requires: %{pkg_prefix}belle-sip Requires: %{pkg_prefix}belr +%if @ENABLE_VCARD@ +Requires: %{pkg_prefix}belcard +%endif %if @ENABLE_SOCI_STORAGE@ Requires: %{pkg_prefix}soci %endif @@ -83,7 +86,7 @@ rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc AUTHORS ChangeLog COPYING NEWS README.md TODO -%if @ENABLE_DAEMON@ || @ENABLE_CONSOLE_UI@ +%if @ENABLE_DAEMON@ || @ENABLE_CONSOLE_UI@ || @ENABLE_TOOLS@ %{_bindir}/* %endif %{_libdir}/*.so.* diff --git a/cmake/FindSoci.cmake b/cmake/FindSoci.cmake index e930f93a9..a2257ad05 100644 --- a/cmake/FindSoci.cmake +++ b/cmake/FindSoci.cmake @@ -25,6 +25,7 @@ # SET(_SOCI_ALL_PLUGINS mysql sqlite3) SET(_SOCI_REQUIRED_VARS SOCI_INCLUDE_DIRS SOCI_LIBRARIES) +SET(_SOCI_VERSION "_4_0") # ### FIRST STEP: Find the soci headers. @@ -37,7 +38,7 @@ MARK_AS_ADVANCED(SOCI_INCLUDE_DIRS) ### SECOND STEP: Find the soci core library. Respect LIB_SUFFIX # FIND_LIBRARY(SOCI_LIBRARIES - NAMES soci_core + NAMES soci_core soci_core${_SOCI_VERSION} PATH_SUFFIXES lib lib64) MARK_AS_ADVANCED(SOCI_LIBRARIES) @@ -54,7 +55,7 @@ IF(SOCI_INCLUDE_DIRS AND SOCI_LIBRARIES) FIND_LIBRARY( SOCI_${plugin}_PLUGIN - NAMES soci_${plugin} + NAMES soci_${plugin} soci_${plugin}${_SOCI_VERSION} PATH_SUFFIXES lib lib64) MARK_AS_ADVANCED(SOCI_${plugin}_PLUGIN) @@ -88,4 +89,3 @@ ENDIF() # include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Soci DEFAULT_MSG ${_SOCI_REQUIRED_VARS}) - diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 7e46275bf..be6515224 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -97,6 +97,7 @@ set(LINPHONE_SOURCE_FILES_CXX conference.cc tester_utils.cpp ) + if(ENABLE_JAVA_WRAPPER) list(APPEND LINPHONE_SOURCE_FILES_CXX ${LINPHONE_JNI_SOURCES}) set_source_files_properties(${LINPHONE_JNI_SOURCES} PROPERTIES GENERATED TRUE) @@ -140,8 +141,8 @@ bc_git_version(liblinphone ${PROJECT_VERSION}) add_definitions( -DUSE_BELLESIP - -DLIBLINPHONE_EXPORTS -DBCTBX_LOG_DOMAIN="liblinphone" + -DLINPHONE_EXPORTS ) set_source_files_properties(${LINPHONE_SOURCE_FILES_C} PROPERTIES LANGUAGE CXX) diff --git a/coreapi/authentication.c b/coreapi/authentication.c index 5ae67f4d2..2832b8c46 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -61,7 +61,7 @@ LinphoneAuthInfo *linphone_auth_info_new_for_algorithm(const char *username, con if (!algorithm) obj->algorithm = ms_strdup("MD5"); - if(algorithm && strcmp(algorithm, "MD5") && strcmp(algorithm, "SHA-256")){ + if(algorithm && strcasecmp(algorithm, "MD5") && strcasecmp(algorithm, "SHA-256")){ ms_error("Given algorithm %s is not correct.", algorithm); return NULL; } @@ -258,12 +258,12 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in } if (!obj->ha1 && obj->realm && obj->passwd && (obj->username || obj->userid) && store_ha1_passwd) { /* Default algorithm is MD5 if it's NULL */ - if((obj->algorithm==NULL)||(!(strcmp(obj->algorithm, "MD5")))){ + if((obj->algorithm==NULL)||(!(strcasecmp(obj->algorithm, "MD5")))){ obj->ha1 = reinterpret_cast(ms_malloc(33)); sal_auth_compute_ha1(obj->userid ? obj->userid : obj->username, obj->realm, obj->passwd, obj->ha1); } /* If algorithm is SHA-256, calcul ha1 by sha256*/ - if((obj->algorithm)&&(!(strcmp(obj->algorithm, "SHA-256")))){ + if((obj->algorithm)&&(!(strcasecmp(obj->algorithm, "SHA-256")))){ obj->ha1 = reinterpret_cast(ms_malloc(65)); sal_auth_compute_ha1_for_algorithm(obj->userid ? obj->userid : obj->username, obj->realm, obj->passwd, obj->ha1,65, obj->algorithm); } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index eaa118ae1..87bc3ab80 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -515,11 +515,11 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) { * exit. The default algorithm is MD5 if it's NULL. */ if (sai->algorithm && ai->algorithm) { - if (strcmp(ai->algorithm, sai->algorithm)) + if (strcasecmp(ai->algorithm, sai->algorithm)) return TRUE; } else if ( - (ai->algorithm && strcmp(ai->algorithm, "MD5")) || - (sai->algorithm && strcmp(sai->algorithm, "MD5")) + (ai->algorithm && strcasecmp(ai->algorithm, "MD5")) || + (sai->algorithm && strcasecmp(sai->algorithm, "MD5")) ) return TRUE; diff --git a/coreapi/lime.c b/coreapi/lime.c index b19eae8be..beb03b00a 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -60,7 +60,7 @@ int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys) { /* Note: retrieved potentially expired keys, just to be able to send a different status to caller(no keys found is not expired key found) */ /* if we do not have self uri in associatedKeys, just retrieve any available key matching peer URI */ if (associatedKeys->selfURI == NULL) { - stmt = sqlite3_mprintf("SELECT zu.zuid, zu.zid as peerZID, l.sndkey, l.sndSId, l.sndIndex, l.valid FROM ziduri as zu LEFT JOIN zrtp as z ON z.zuid=zu.zuid LEFT JOIN lime as l ON z.zuid=l.zuid WHERE zu.peeruri=? AND z.pvs=?;"); + stmt = sqlite3_mprintf("SELECT zu.zuid, zu.zid as peerZID, l.sndkey, l.sndSId, l.sndIndex, l.valid FROM ziduri as zu INNER JOIN zrtp as z ON z.zuid=zu.zuid INNER JOIN lime as l ON z.zuid=l.zuid WHERE zu.peeruri=? AND z.pvs=?;"); ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL); sqlite3_free(stmt); if (ret != SQLITE_OK) { @@ -69,7 +69,7 @@ int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys) { sqlite3_bind_text(sqlStmt, 1, associatedKeys->peerURI,-1, SQLITE_TRANSIENT); sqlite3_bind_blob(sqlStmt, 2, pvsOne, 1, SQLITE_TRANSIENT); } else { /* we have a self URI, so include it in the query */ - stmt = sqlite3_mprintf("SELECT zu.zuid, zu.zid as peerZID, l.sndkey, l.sndSId, l.sndIndex, l.valid FROM ziduri as zu LEFT JOIN zrtp as z ON z.zuid=zu.zuid LEFT JOIN lime as l ON z.zuid=l.zuid WHERE zu.selfuri=? AND zu.peeruri=? AND z.pvs=?;"); + stmt = sqlite3_mprintf("SELECT zu.zuid, zu.zid as peerZID, l.sndkey, l.sndSId, l.sndIndex, l.valid FROM ziduri as zu INNER JOIN zrtp as z ON z.zuid=zu.zuid INNER JOIN lime as l ON z.zuid=l.zuid WHERE zu.selfuri=? AND zu.peeruri=? AND z.pvs=?;"); ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL); sqlite3_free(stmt); if (ret != SQLITE_OK) { @@ -186,17 +186,17 @@ int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const cha if (db == NULL) { /* there is no cache return error */ + ms_error("[LIME] Get Cached Rcv Key by Zid : no cache found"); return LIME_INVALID_CACHE; } /* query the DB: join ziduri, lime and zrtp tables : */ /* retrieve zuid(for easier key update in cache), rcvKey, rcvSId, rcvIndex where self/peer uris and peer zid are matching constraint(unique row) and pvs is raised */ - /* Note: retrieved potentially expired keys, just to be able to send a different status to caller(no keys found is not expired key found) */ - /* if we do not have self uri in associatedKeys, just retrieve any available key matching peer URI */ - stmt = sqlite3_mprintf("SELECT zu.zuid, l.rcvkey, l.rcvSId, l.rcvIndex FROM ziduri as zu LEFT JOIN zrtp as z ON z.zuid=zu.zuid LEFT JOIN lime as l ON z.zuid=l.zuid WHERE zu.selfuri=? AND zu.peeruri=? AND zu.zid=? AND z.pvs=? LIMIT 1;"); + stmt = sqlite3_mprintf("SELECT zu.zuid, l.rcvkey, l.rcvSId, l.rcvIndex FROM ziduri as zu INNER JOIN zrtp as z ON z.zuid=zu.zuid INNER JOIN lime as l ON z.zuid=l.zuid WHERE zu.selfuri=? AND zu.peeruri=? AND zu.zid=? AND z.pvs=? LIMIT 1;"); ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL); sqlite3_free(stmt); if (ret != SQLITE_OK) { + ms_error("[LIME] Get Cached Rcv Key by Zid can't prepare statement to retrieve key"); return LIME_INVALID_CACHE; } sqlite3_bind_text(sqlStmt, 1, selfURI,-1, SQLITE_TRANSIENT); @@ -214,20 +214,22 @@ int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const cha if (length==32) { /* rcvKey */ memcpy(associatedKey->key, sqlite3_column_blob(sqlStmt, 1), (size_t)length); } else { /* something wrong */ + ms_error("[LIME] Get Cached Rcv Key by Zid fetched a rcvKey with wrong length"); sqlite3_finalize(sqlStmt); - return LIME_NO_VALID_KEY_FOUND_FOR_PEER; + return LIME_INVALID_CACHE; } length = sqlite3_column_bytes(sqlStmt, 2); if (length==32) { /* rcvSId */ memcpy(associatedKey->sessionId, sqlite3_column_blob(sqlStmt, 2), (size_t)length); } else { /* something wrong */ + ms_error("[LIME] Get Cached Rcv Key by Zid fetched a rcvSid with wrong length"); sqlite3_finalize(sqlStmt); - return LIME_NO_VALID_KEY_FOUND_FOR_PEER; + return LIME_INVALID_CACHE; } length = sqlite3_column_bytes(sqlStmt, 3); - if (length==4) { /* rcvKey */ + if (length==4) { /* rcvIndex */ uint8_t *sessionId = (uint8_t *)sqlite3_column_blob(sqlStmt, 3); associatedKey->sessionIndex = ((uint32_t)(sessionId[0]))<<24 | ((uint32_t)(sessionId[1]))<<16 | @@ -235,7 +237,8 @@ int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const cha ((uint32_t)(sessionId[3])); } else { /* something wrong */ sqlite3_finalize(sqlStmt); - return LIME_NO_VALID_KEY_FOUND_FOR_PEER; + ms_error("[LIME] Get Cached Rcv Key by Zid fetched a rcvIndex with wrong length"); + return LIME_INVALID_CACHE; } sqlite3_finalize(sqlStmt); @@ -244,6 +247,7 @@ int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const cha /* something is wrong with the cache? */ if (ret!=SQLITE_DONE) { + ms_error("[LIME] Get Cached Rcv Key by Zid : request gone bad"); return LIME_INVALID_CACHE; } @@ -635,14 +639,15 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se if (peerZidHex != NULL) { /* Convert it from hexa string to bytes string and set the result in the associatedKey structure */ bctbx_str_to_uint8(associatedKey.peerZID, (const uint8_t *)peerZidHex, (uint16_t)strlen(peerZidHex)); - linphone_free_xml_text_content(peerZidHex); /* Get the matching key from cache */ retval = lime_getCachedRcvKeyByZid(cachedb, &associatedKey, selfURI, peerURI); if (retval != 0) { - ms_error("[LIME] Couldn't get cache rcv key by ZID"); + ms_error("[LIME] Couldn't get cache rcv key by ZID. Returns %04x. PeerZid %s peerURI %s selfURI %s", retval, peerZidHex, peerURI, selfURI); + linphone_free_xml_text_content(peerZidHex); goto error; } + linphone_free_xml_text_content(peerZidHex); /* Retrieve the portion of message which is encrypted with our key(seek for a pzid matching our) */ msg_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/doc/msg"); @@ -770,8 +775,9 @@ bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) { if (zrtp_cache_db != NULL) { bool_t res; limeURIKeys_t associatedKeys; - char *peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - + char *peer = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(linphone_chat_room_get_peer_address(cr)) + , linphone_address_get_username(linphone_chat_room_get_peer_address(cr)) + , linphone_address_get_domain(linphone_chat_room_get_peer_address(cr))); /* retrieve keys associated to the peer URI */ associatedKeys.peerURI = bctbx_strdup(peer); associatedKeys.selfURI = NULL; /* TODO : there is no sender associated to chatroom so check for any local URI available, shall we add sender to chatroom? */ @@ -813,10 +819,15 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn errcode = 500; return errcode; } - peerUri = linphone_address_as_string_uri_only(linphone_chat_message_get_from_address(msg)); - selfUri = linphone_address_as_string_uri_only(linphone_chat_message_get_to_address(msg)); + peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(linphone_chat_message_get_from_address(msg)) + , linphone_address_get_username(linphone_chat_message_get_from_address(msg)) + , linphone_address_get_domain(linphone_chat_message_get_from_address(msg))); + selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(linphone_chat_message_get_to_address(msg)) + , linphone_address_get_username(linphone_chat_message_get_to_address(msg)) + , linphone_address_get_domain(linphone_chat_message_get_to_address(msg))); + retval = lime_decryptMultipartMessage(zrtp_cache_db, (uint8_t *)linphone_chat_message_get_text(msg), selfUri, peerUri, &decrypted_body, &decrypted_content_type, - bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0"))); + bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0"))); ms_free(peerUri); ms_free(selfUri); if (retval != 0) { @@ -876,8 +887,12 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn } else { int retval; uint8_t *crypted_body = NULL; - char *selfUri = linphone_address_as_string_uri_only(linphone_chat_message_get_from_address(msg)); - char *peerUri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(room)); + char *peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(linphone_chat_room_get_peer_address(room)) + , linphone_address_get_username(linphone_chat_room_get_peer_address(room)) + , linphone_address_get_domain(linphone_chat_room_get_peer_address(room))); + char *selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(linphone_chat_message_get_from_address(msg)) + , linphone_address_get_username(linphone_chat_message_get_from_address(msg)) + , linphone_address_get_domain(linphone_chat_message_get_from_address(msg))); retval = lime_createMultipartMessage(zrtp_cache_db, linphone_chat_message_get_content_type(msg), (uint8_t *)linphone_chat_message_get_text(msg), selfUri, peerUri, &crypted_body); if (retval != 0) { /* fail to encrypt */ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index e5337abd6..9135cf934 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -19,9 +19,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/api/c-content.h" +#include "linphone/core_utils.h" #include "linphone/core.h" -#include "linphone/lpconfig.h" #include "linphone/logging.h" +#include "linphone/lpconfig.h" #include "linphone/sipsetup.h" #include "private.h" @@ -41,8 +42,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include -#include -#include +#include "bctoolbox/defs.h" +#include "bctoolbox/regex.h" +#include "belr/grammarbuilder.h" #include "mediastreamer2/dtmfgen.h" #include "mediastreamer2/mediastream.h" @@ -53,6 +55,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msogl.h" #include "mediastreamer2/msvolume.h" #include "mediastreamer2/msqrcodereader.h" + #include "bctoolbox/charconv.h" #include "chat/chat-room/client-group-chat-room-p.h" @@ -69,6 +72,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "address/address-p.h" #include "c-wrapper/c-wrapper.h" + #ifdef INET6 #ifndef _WIN32 #include @@ -1282,33 +1286,57 @@ static void sound_config_read(LinphoneCore *lc) _linphone_core_set_tone(lc,LinphoneReasonBusy,LinphoneToneBusy,NULL); } +static int _linphone_core_tls_postcheck_callback(void *data, const bctbx_x509_certificate_t *peer_cert){ + LinphoneCore *lc = (LinphoneCore *) data; + const char *tls_certificate_subject_regexp = lp_config_get_string(lc->config,"sip","tls_certificate_subject_regexp", NULL); + int ret = 0; + if (tls_certificate_subject_regexp){ + ret = -1; + /*the purpose of this handling is to a peer certificate for which there is no single subject matching the regexp given + * in the "tls_certificate_subject_regexp" property. + */ + bctbx_list_t *subjects = bctbx_x509_certificate_get_subjects(peer_cert); + bctbx_list_t *elem; + for(elem = subjects; elem != NULL; elem = elem->next){ + const char *subject = (const char *)elem->data; + ms_message("_linphone_core_tls_postcheck_callback: subject=%s", subject); + if (bctbx_is_matching_regex(subject, tls_certificate_subject_regexp)){ + ret = 0; + ms_message("_linphone_core_tls_postcheck_callback(): successful by matching '%s'", subject); + break; + } + } + bctbx_list_free_with_data(subjects, bctbx_free); + } + if (ret == -1){ + ms_message("_linphone_core_tls_postcheck_callback(): postcheck failed, nothing matched."); + } + return ret; +} + static void certificates_config_read(LinphoneCore *lc) { LinphoneFactory *factory = linphone_factory_get(); const char *data_dir = linphone_factory_get_data_resources_dir(factory); char *root_ca_path = bctbx_strdup_printf("%s/rootca.pem", data_dir); const char *rootca = lp_config_get_string(lc->config,"sip","root_ca", NULL); - // If rootca is not existing anymore, we reset it to the default value - if (rootca == NULL || ((bctbx_file_exist(rootca) != 0) && (!bctbx_directory_exists(rootca)))) { -#ifdef __linux - #ifdef __ANDROID__ - const char *possible_rootca = "/system/etc/security/cacerts"; - #else - const char *possible_rootca = "/etc/ssl/certs"; - #endif - if (bctbx_directory_exists(possible_rootca)) { - rootca = possible_rootca; - } else -#endif - { - if (bctbx_file_exist(root_ca_path) == 0) { - rootca = root_ca_path; - } - } + + // If rootca is not existing anymore, we try data_resources_dir/rootca.pem else default from belle-sip + if (rootca == NULL || ((bctbx_file_exist(rootca) != 0 && !bctbx_directory_exists(rootca)))) { + //Check root_ca_path + if ((bctbx_file_exist(root_ca_path) == 0) || bctbx_directory_exists(root_ca_path)) + rootca = root_ca_path; + else + rootca = NULL; } - linphone_core_set_root_ca(lc,rootca); + + if (rootca) + linphone_core_set_root_ca(lc,rootca); + /*else use default value from belle-sip*/ linphone_core_verify_server_certificates(lc, !!lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE)); linphone_core_verify_server_cn(lc, !!lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE)); bctbx_free(root_ca_path); + + lc->sal->setTlsPostcheckCallback(_linphone_core_tls_postcheck_callback, lc); } static void sip_config_read(LinphoneCore *lc) { @@ -2282,7 +2310,7 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig lc->factory = ms_factory_new_with_voip_and_directories(msplugins_dir, image_resources_dir); lc->sal->setFactory(lc->factory); - belr::GrammarLoader::get().addPath(getPlatformHelpers(lc)->getDataPath()); + belr::GrammarLoader::get().addPath(std::string(linphone_factory_get_top_resources_dir(lfactory)).append("/belr/grammars")); linphone_task_list_init(&lc->hooks); @@ -7381,6 +7409,7 @@ void linphone_core_check_for_update(LinphoneCore *lc, const char *current_versio int err; bool_t is_desktop = FALSE; const char *platform = NULL; + const char *mobilePlatform = NULL; const char *version_check_url_root = lp_config_get_string(lc->config, "misc", "version_check_url_root", NULL); if (version_check_url_root != NULL) { @@ -7396,9 +7425,14 @@ void linphone_core_check_for_update(LinphoneCore *lc, const char *current_versio if (strcmp(tag, "win32") == 0) platform = "windows"; else if (strcmp(tag, "apple") == 0) platform = "macosx"; else if (strcmp(tag, "linux") == 0) platform = "linux"; + else if (strcmp(tag, "ios") == 0) mobilePlatform = "ios"; + else if (strcmp(tag, "android") == 0) mobilePlatform = "android"; else if (strcmp(tag, "desktop") == 0) is_desktop = TRUE; } - if ((is_desktop == FALSE) || (platform == NULL)) { + if (!is_desktop) { + platform = mobilePlatform; + } + if (platform == NULL) { ms_warning("Update checking is not supported on this platform"); return; } diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 9162e5c4f..5da325464 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -1530,6 +1530,9 @@ public: jcontent, jbytes, size); + if (jbytes) { + env->DeleteLocalRef(jbytes); + } if (jcontent) { env->DeleteLocalRef(jcontent); } @@ -6204,7 +6207,7 @@ static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent * jbyteArray jdata = NULL; jint jsize = 0; const char *tmp; - void *data; + const uint8_t *data; contentClass = (jclass)env->FindClass("org/linphone/core/LinphoneContentImpl"); ctor = env->GetMethodID(contentClass,"", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V"); @@ -6226,6 +6229,9 @@ static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent * env->DeleteLocalRef(contentClass); env->DeleteLocalRef(jtype); env->DeleteLocalRef(jsubtype); + if (jdata) { + env->DeleteLocalRef(jdata); + } if (jencoding) { env->DeleteLocalRef(jencoding); } @@ -6252,6 +6258,7 @@ static jobject create_java_linphone_buffer(JNIEnv *env, const LinphoneBuffer *bu } jobject jobj = env->NewObject(bufferClass, ctor, jdata, jsize); + if (jdata) env->DeleteLocalRef(jdata); env->DeleteLocalRef(bufferClass); return jobj; } diff --git a/coreapi/private_functions.h b/coreapi/private_functions.h index 0f706c415..c27c0ae8e 100644 --- a/coreapi/private_functions.h +++ b/coreapi/private_functions.h @@ -54,17 +54,28 @@ void linphone_call_notify_next_video_frame_decoded(LinphoneCall *call); LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LinphonePrivate::SalCallOp *op); -LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress * to); +LINPHONE_PUBLIC LinphoneCallLog *linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress * to); LinphonePlayer *linphone_call_build_player(LinphoneCall*call); LinphonePrivate::SalCallOp *linphone_call_get_op(const LinphoneCall *call); -LinphoneProxyConfig * linphone_call_get_dest_proxy(const LinphoneCall *call); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC LinphoneProxyConfig *linphone_call_get_dest_proxy(const LinphoneCall *call); + LINPHONE_PUBLIC MediaStream * linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type); -LinphoneCallLog * linphone_call_get_log(const LinphoneCall *call); -IceSession * linphone_call_get_ice_session(const LinphoneCall *call); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC LinphoneCallLog * linphone_call_get_log(const LinphoneCall *call); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC IceSession *linphone_call_get_ice_session(const LinphoneCall *call); + bool_t linphone_call_get_audio_muted(const LinphoneCall *call); void linphone_call_set_audio_muted(LinphoneCall *call, bool_t value); -bool_t linphone_call_get_all_muted(const LinphoneCall *call); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC bool_t linphone_call_get_all_muted(const LinphoneCall *call); + void _linphone_call_set_conf_ref (LinphoneCall *call, LinphoneConference *ref); MSAudioEndpoint *_linphone_call_get_endpoint (const LinphoneCall *call); void _linphone_call_set_endpoint (LinphoneCall *call, MSAudioEndpoint *endpoint); @@ -95,7 +106,10 @@ SalCustomSdpAttribute * linphone_call_params_get_custom_sdp_attributes(const Lin SalCustomSdpAttribute * linphone_call_params_get_custom_sdp_media_attributes(const LinphoneCallParams *params, LinphoneStreamType type); LinphoneCall * linphone_call_params_get_referer(const LinphoneCallParams *params); void linphone_call_params_set_referer(LinphoneCallParams *params, LinphoneCall *referer); -bool_t linphone_call_params_get_update_call_when_ice_completed(const LinphoneCallParams *params); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC bool_t linphone_call_params_get_update_call_when_ice_completed(const LinphoneCallParams *params); + void linphone_call_params_set_update_call_when_ice_completed(LinphoneCallParams *params, bool_t value); void linphone_call_params_set_sent_vsize(LinphoneCallParams *params, MSVideoSize vsize); void linphone_call_params_set_recv_vsize(LinphoneCallParams *params, MSVideoSize vsize); @@ -107,7 +121,9 @@ void linphone_call_params_set_used_audio_codec(LinphoneCallParams *params, OrtpP void linphone_call_params_set_used_video_codec(LinphoneCallParams *params, OrtpPayloadType *codec); void linphone_call_params_set_used_text_codec(LinphoneCallParams *params, OrtpPayloadType *codec); bool_t linphone_call_params_get_no_user_consent(const LinphoneCallParams *params); -void linphone_call_params_set_no_user_consent(LinphoneCallParams *params, bool_t value); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC void linphone_call_params_set_no_user_consent(LinphoneCallParams *params, bool_t value); void linphone_auth_info_write_config(LinphoneConfig *config, LinphoneAuthInfo *obj, int pos); LinphoneAuthInfo * linphone_auth_info_new_from_config_file(LpConfig *config, int pos); @@ -222,7 +238,10 @@ void _linphone_call_stats_set_type (LinphoneCallStats *stats, LinphoneStreamType void _linphone_call_stats_set_received_rtcp (LinphoneCallStats *stats, mblk_t *m); mblk_t *_linphone_call_stats_get_sent_rtcp (const LinphoneCallStats *stats); void _linphone_call_stats_set_sent_rtcp (LinphoneCallStats *stats, mblk_t *m); -int _linphone_call_stats_get_updated (const LinphoneCallStats *stats); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC int _linphone_call_stats_get_updated (const LinphoneCallStats *stats); + void _linphone_call_stats_set_updated (LinphoneCallStats *stats, int updated); void _linphone_call_stats_set_rtp_stats (LinphoneCallStats *stats, const rtp_stats_t *rtpStats); void _linphone_call_stats_set_download_bandwidth (LinphoneCallStats *stats, float bandwidth); @@ -230,7 +249,10 @@ void _linphone_call_stats_set_upload_bandwidth (LinphoneCallStats *stats, float void _linphone_call_stats_set_rtcp_download_bandwidth (LinphoneCallStats *stats, float bandwidth); void _linphone_call_stats_set_rtcp_upload_bandwidth (LinphoneCallStats *stats, float bandwidth); void _linphone_call_stats_set_ip_family_of_remote (LinphoneCallStats *stats, LinphoneAddressFamily family); -bool_t _linphone_call_stats_rtcp_received_via_mux (const LinphoneCallStats *stats); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC bool_t _linphone_call_stats_rtcp_received_via_mux (const LinphoneCallStats *stats); + bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md); void linphone_core_send_initial_subscribes(LinphoneCore *lc); @@ -325,7 +347,8 @@ LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc); void linphone_tunnel_configure(LinphoneTunnel *tunnel); void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler); -int linphone_core_get_calls_nb(const LinphoneCore *lc); +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC int linphone_core_get_calls_nb(const LinphoneCore *lc); void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); void linphone_call_update_biggest_desc(LinphoneCall *call, SalMediaDescription *md); diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 5e79f3298..3b4d5d06c 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -21,6 +21,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #ifndef _WIN32 #include #endif + +#include + #include #include #include @@ -82,6 +85,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "commands/play.h" #include "private.h" + using namespace std; #define INT_TO_VOIDPTR(i) ((void*)(intptr_t)(i)) @@ -134,6 +138,7 @@ EventResponse::EventResponse(Daemon *daemon, LinphoneCall *call, LinphoneCallSta setBody(ostr.str().c_str()); bctbx_free(fromStr); + } DtmfResponse::DtmfResponse(Daemon *daemon, LinphoneCall *call, int dtmf) { @@ -532,6 +537,10 @@ bool Daemon::pullEvent() { void Daemon::callStateChanged(LinphoneCall *call, LinphoneCallState state, const char *msg) { mEventQueue.push(new EventResponse(this, call, state)); + + if (state == LinphoneCallIncomingReceived && mAutoAnswer){ + linphone_call_accept(call); + } } void Daemon::callStatsUpdated(LinphoneCall *call, const LinphoneCallStats *stats) { @@ -791,7 +800,8 @@ static void printHelp() { "\t--disable-stats-events Do not automatically raise RTP statistics events." << endl << "\t--enable-lsd Use the linphone sound daemon." << endl << "\t-C Enable video capture." << endl << - "\t-D Enable video display." << endl; + "\t-D Enable video display." << endl << + "\t--auto-answer Automatically answer incoming calls."<quit(); + the_app = NULL; + } +} + int main(int argc, char *argv[]) { const char *config_path = NULL; const char *factory_config_path = NULL; @@ -908,6 +931,7 @@ int main(int argc, char *argv[]) { bool display_video = false; bool stats_enabled = true; bool lsd_enabled = false; + bool auto_answer = false; int i; for (i = 1; i < argc; ++i) { @@ -956,15 +980,21 @@ int main(int argc, char *argv[]) { display_video = true; }else if (strcmp(argv[i],"--disable-stats-events")==0){ stats_enabled = false; - } else if (strcmp(argv[i], "--enable-lsd") == 0) { + }else if (strcmp(argv[i], "--enable-lsd") == 0) { lsd_enabled = true; + }else if (strcmp(argv[i], "--auto-answer") == 0) { + auto_answer = true; } else{ fprintf(stderr, "Unrecognized option : %s", argv[i]); } } Daemon app(config_path, factory_config_path, log_file, pipe_name, display_video, capture_video); + + the_app = &app; + signal(SIGINT, sighandler); app.enableStatsEvents(stats_enabled); app.enableLSD(lsd_enabled); + app.enableAutoAnswer(auto_answer); return app.run(); } diff --git a/daemon/daemon.h b/daemon/daemon.h index 79ae20c1e..195ff1317 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -235,6 +235,7 @@ public: void dumpCommandsHelpHtml(); void enableStatsEvents(bool enabled); void enableLSD(bool enabled); + void enableAutoAnswer(bool enabled); void callPlayingComplete(int id); void setAutoVideo( bool enabled ){ mAutoVideo = enabled; } inline bool autoVideo(){ return mAutoVideo; } @@ -265,6 +266,7 @@ private: std::string mHistfile; bool mRunning; bool mUseStatsEvents; + bool mAutoAnswer; FILE *mLogFile; bool mAutoVideo; int mCallIds; diff --git a/include/linphone/api/c-call.h b/include/linphone/api/c-call.h index c90b0a0b3..e1010580b 100644 --- a/include/linphone/api/c-call.h +++ b/include/linphone/api/c-call.h @@ -258,7 +258,13 @@ LINPHONE_PUBLIC void linphone_call_set_authentication_token_verified (LinphoneCa **/ LINPHONE_PUBLIC void linphone_call_send_vfu_request (LinphoneCall *call); -LINPHONE_PUBLIC void linphone_call_set_next_video_frame_decoded_callback (LinphoneCall *call, LinphoneCallCbFunc cb, void *ud); +/** + * Request the callback passed to linphone_call_cbs_set_next_video_frame_decoded() to be called the next time the video decoder properly decodes a video frame. + * @param call the #LinphoneCall +**/ +LINPHONE_PUBLIC void linphone_call_request_notify_next_video_frame_decoded(LinphoneCall *call); + +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_call_set_next_video_frame_decoded_callback (LinphoneCall *call, LinphoneCallCbFunc cb, void *ud); /** * Returns the current transfer state, if a transfer has been initiated from this call. diff --git a/include/linphone/core.h b/include/linphone/core.h index 027709570..d06a2081e 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -4372,14 +4372,14 @@ LINPHONE_PUBLIC LinphoneConference *linphone_core_get_conference(LinphoneCore *l * @param[in] lc A #LinphoneCore object * @param[in] enable A boolean value telling whether to enable or disable the conference server feature */ -void linphone_core_enable_conference_server (LinphoneCore *lc, bool_t enable); +LINPHONE_PUBLIC void linphone_core_enable_conference_server (LinphoneCore *lc, bool_t enable); /** * Tells whether the conference server feature is enabled. * @param[in] lc A #LinphoneCore object * @return A boolean value telling whether the conference server feature is enabled or not */ -bool_t linphone_core_conference_server_enabled (const LinphoneCore *lc); +LINPHONE_PUBLIC bool_t linphone_core_conference_server_enabled (const LinphoneCore *lc); /** * @} @@ -5031,7 +5031,7 @@ LINPHONE_PUBLIC void linphone_core_add_content_type_support(LinphoneCore *lc, co * @return The linphone specs telling what functionalities the linphone client supports * @ingroup initializing */ -const char *linphone_core_get_linphone_specs (const LinphoneCore *core); +LINPHONE_PUBLIC const char *linphone_core_get_linphone_specs (const LinphoneCore *core); /** * Set the linphone specs value telling what functionalities the linphone client supports. @@ -5039,7 +5039,7 @@ const char *linphone_core_get_linphone_specs (const LinphoneCore *core); * @param[in] specs The linphone specs to set * @ingroup initializing */ -void linphone_core_set_linphone_specs (LinphoneCore *core, const char *specs); +LINPHONE_PUBLIC void linphone_core_set_linphone_specs (LinphoneCore *core, const char *specs); /** * Remove support for the specified content type. diff --git a/include/linphone/core_utils.h b/include/linphone/core_utils.h index aaac2e5ab..18d0f8807 100644 --- a/include/linphone/core_utils.h +++ b/include/linphone/core_utils.h @@ -122,9 +122,9 @@ LINPHONE_PUBLIC void linphone_core_stop_dtmf_stream(LinphoneCore* lc); typedef bool_t (*LinphoneCoreIterateHook)(void *data); -void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); +LINPHONE_PUBLIC void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); -void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); +LINPHONE_PUBLIC void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); #ifdef __cplusplus } diff --git a/include/linphone/proxy_config.h b/include/linphone/proxy_config.h index 5242a71e1..1b1d6c54f 100644 --- a/include/linphone/proxy_config.h +++ b/include/linphone/proxy_config.h @@ -276,7 +276,7 @@ LINPHONE_PUBLIC const char *linphone_proxy_config_get_route(const LinphoneProxyC * Gets the list of the routes set for this proxy config. * @param[in] cfg #LinphoneProxyConfig object. * @return \bctbx_list{const char *} the list of routes. - */ + */ LINPHONE_PUBLIC const bctbx_list_t* linphone_proxy_config_get_routes(const LinphoneProxyConfig *cfg); /** @@ -609,14 +609,14 @@ LINPHONE_PUBLIC void linphone_proxy_config_set_nat_policy(LinphoneProxyConfig *c * @param[in] cfg A #LinphoneProxyConfig object * @param[in] uri The uri of the conference factory */ -void linphone_proxy_config_set_conference_factory_uri(LinphoneProxyConfig *cfg, const char *uri); +LINPHONE_PUBLIC void linphone_proxy_config_set_conference_factory_uri(LinphoneProxyConfig *cfg, const char *uri); /** * Get the conference factory uri. * @param[in] cfg A #LinphoneProxyConfig object * @return The uri of the conference factory */ -const char * linphone_proxy_config_get_conference_factory_uri(const LinphoneProxyConfig *cfg); +LINPHONE_PUBLIC const char * linphone_proxy_config_get_conference_factory_uri(const LinphoneProxyConfig *cfg); /** * Indicates whether to add to the contact parameters the push notification information. diff --git a/include/linphone/utils/general.h b/include/linphone/utils/general.h index 829d4bda5..87f4a4808 100644 --- a/include/linphone/utils/general.h +++ b/include/linphone/utils/general.h @@ -53,9 +53,9 @@ LINPHONE_BEGIN_NAMESPACE #define LINPHONE_PUBLIC #else #ifdef LINPHONE_EXPORTS - #define LINPHONE_PUBLIC __declspec(dllexport) + #define LINPHONE_PUBLIC __declspec(dllexport) #else - #define LINPHONE_PUBLIC __declspec(dllimport) + #define LINPHONE_PUBLIC __declspec(dllimport) #endif #endif #else diff --git a/include/linphone/utils/static-string.h b/include/linphone/utils/static-string.h index bbc421e06..44f31a847 100644 --- a/include/linphone/utils/static-string.h +++ b/include/linphone/utils/static-string.h @@ -120,7 +120,7 @@ namespace Private { raw{ char('0' + Value / pow10(N - Index - 2) % 10)..., '\0' } {} template::type* = nullptr> - constexpr StaticIntStringHelper(const IndexSequence &) : + constexpr StaticIntStringHelper (const IndexSequence &) : raw{ '-', char('0' + abs(Value) / pow10(N - Index - 3) % 10)..., '\0' } {} }; }; diff --git a/include/linphone/utils/utils.h b/include/linphone/utils/utils.h index c93058006..b4675af0c 100644 --- a/include/linphone/utils/utils.h +++ b/include/linphone/utils/utils.h @@ -35,32 +35,32 @@ LINPHONE_BEGIN_NAMESPACE namespace Utils { template - LINPHONE_PUBLIC constexpr T *getPtr (std::shared_ptr &object) { + constexpr T *getPtr (std::shared_ptr &object) { return object.get(); } template - LINPHONE_PUBLIC constexpr T *getPtr (const std::shared_ptr &object) { + constexpr T *getPtr (const std::shared_ptr &object) { return object.get(); } template - LINPHONE_PUBLIC constexpr T *getPtr (std::unique_ptr &object) { + constexpr T *getPtr (std::unique_ptr &object) { return object.get(); } template - LINPHONE_PUBLIC constexpr T *getPtr (const std::unique_ptr &object) { + constexpr T *getPtr (const std::unique_ptr &object) { return object.get(); } template - LINPHONE_PUBLIC constexpr T *getPtr (T *object) { + constexpr T *getPtr (T *object) { return object; } template - LINPHONE_PUBLIC constexpr T *getPtr (T &object) { + constexpr T *getPtr (T &object) { return &object; } @@ -108,7 +108,7 @@ namespace Utils { } template - LINPHONE_PUBLIC std::string join (const std::vector& elems, const S& delim) { + inline std::string join (const std::vector& elems, const S& delim) { std::stringstream ss; auto e = elems.begin(); ss << *e++; @@ -119,7 +119,7 @@ namespace Utils { LINPHONE_PUBLIC std::string trim (const std::string &str); template - LINPHONE_PUBLIC const T &getEmptyConstRefObject () { + inline const T &getEmptyConstRefObject () { static const T object{}; return object; } @@ -129,7 +129,7 @@ namespace Utils { LINPHONE_PUBLIC std::string localeToUtf8 (const std::string &str); LINPHONE_PUBLIC std::string utf8ToLocale (const std::string &str); - LINPHONE_PUBLIC std::string convertString (const std::string &str, const std::string &from, const std::string &to); + LINPHONE_PUBLIC std::string convertAnyToUtf8 (const std::string &str, const std::string &encoding); } LINPHONE_END_NAMESPACE diff --git a/java/impl/org/linphone/core/tools/AndroidPlatformHelper.java b/java/impl/org/linphone/core/tools/AndroidPlatformHelper.java deleted file mode 100644 index b601a2972..000000000 --- a/java/impl/org/linphone/core/tools/AndroidPlatformHelper.java +++ /dev/null @@ -1,201 +0,0 @@ -/* -AndroidPlatformHelper.java -Copyright (C) 2017 Belledonne Communications, Grenoble, France - -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. -*/ - - -package org.linphone.core.tools; - -import org.linphone.core.Core; -import org.linphone.mediastream.Log; -import org.linphone.mediastream.MediastreamerAndroidContext; -import org.linphone.mediastream.Version; - -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.MulticastLock; -import android.net.wifi.WifiManager.WifiLock; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkInfo; -import android.os.PowerManager; -import android.os.PowerManager.WakeLock; -import android.os.Build; - -import java.net.InetAddress; -import java.util.List; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * This class is instanciated directly by the linphone library in order to access specific features only accessible in java. -**/ - -public class AndroidPlatformHelper { - private Context mContext; - private WifiManager.WifiLock mWifiLock; - private WifiManager.MulticastLock mMcastLock; - private ConnectivityManager mConnectivityManager; - private PowerManager mPowerManager; - private WakeLock mWakeLock; - private String mLinphoneRootCaFile; - private String mRingSoundFile; - private String mRingbackSoundFile; - private String mPauseSoundFile; - private String mErrorToneFile; - private String mGrammarCpimFile; - private String mGrammarVcardFile ; - private String mUserCertificatePath; - - public AndroidPlatformHelper(Object ctx_obj) { - mContext = (Context) ctx_obj; - MediastreamerAndroidContext.setContext(mContext); - - WifiManager wifiMgr = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - mConnectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - - mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidPlatformHelper"); - mWakeLock.setReferenceCounted(true); - mMcastLock = wifiMgr.createMulticastLock("AndroidPlatformHelper"); - mMcastLock.setReferenceCounted(true); - mWifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "AndroidPlatformHelper"); - mWifiLock.setReferenceCounted(true); - - String basePath = mContext.getFilesDir().getAbsolutePath(); - mLinphoneRootCaFile = basePath + "/rootca.pem"; - mRingSoundFile = basePath + "/ringtone.mkv"; - mRingbackSoundFile = basePath + "/ringback.wav"; - mPauseSoundFile = basePath + "/hold.mkv"; - mErrorToneFile = basePath + "/error.wav"; - mGrammarCpimFile = basePath + "/cpim_grammar"; - mGrammarVcardFile = basePath + "/vcard_gramamr"; - mUserCertificatePath = basePath; - - copyAssetsFromPackage(); - } - - public void initCore(long ptrLc) { - Core lc = Factory.instance().getCore(ptrLc); - if (lc == null) return; - lc.setRingback(mRingbackSoundFile); - lc.setRootCa(mLinphoneRootCaFile); - lc.setPlayFile(mPauseSoundFile); - lc.setUserCertificatesPath(mUserCertificatePath); - } - - public Object getPowerManager() { - return mPowerManager; - } - - public String[] getDnsServers() { - if (mConnectivityManager == null || Build.VERSION.SDK_INT < Version.API23_MARSHMALLOW_60) - return null; - - if (mConnectivityManager.getActiveNetwork() == null - || mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()) == null) - return null; - - int i = 0; - List inetServers = null; - inetServers = mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()).getDnsServers(); - - String[] servers = new String[inetServers.size()]; - - for (InetAddress address : inetServers) { - servers[i++] = address.getHostAddress(); - } - Log.i("getDnsServers() returning"); - return servers; - } - - public String getDataPath() { - return mContext.getFilesDir().getAbsolutePath(); - } - - public String getConfigPath() { - return mContext.getFilesDir().getAbsolutePath(); - } - - public String getCachePath() { - return mContext.getCacheDir().getAbsolutePath(); - } - - public void acquireWifiLock() { - Log.i("acquireWifiLock()"); - mWifiLock.acquire(); - } - - public void releaseWifiLock() { - Log.i("releaseWifiLock()"); - mWifiLock.release(); - } - - public void acquireMcastLock() { - Log.i("acquireMcastLock()"); - mMcastLock.acquire(); - } - - public void releaseMcastLock() { - Log.i("releaseMcastLock()"); - mMcastLock.release(); - } - - public void acquireCpuLock() { - Log.i("acquireCpuLock()"); - mWakeLock.acquire(); - } - - public void releaseCpuLock(){ - Log.i("releaseCpuLock()"); - mWakeLock.release(); - } - - private void copyAssetsFromPackage() throws IOException { - copyIfNotExist(mContext.getResources().getIdentifier("org.linphone:raw/notes_of_the_optimistic", null, null), mRingSoundFile); - copyIfNotExist(mContext.getResources().getIdentifier("org.linphone:raw/ringback", null, null), mRingbackSoundFile); - copyIfNotExist(mContext.getResources().getIdentifier("org.linphone:raw/hold", null, null), mPauseSoundFile); - copyIfNotExist(mContext.getResources().getIdentifier("org.linphone:raw/incoming_chat", null, null), mErrorToneFile); - copyIfNotExist(mContext.getResources().getIdentifier("org.linphone:raw/cpim_grammar", null, null), mGrammarCpimFile); - copyIfNotExist(mContext.getResources().getIdentifier("org.linphone:raw/vcard_grammar", null, null), mGrammarVcardFile); - copyFromPackage(R.raw.rootca, new File(mLinphoneRootCaFile).getName()); - } - - public void copyIfNotExist(int ressourceId, String target) throws IOException { - File lFileToCopy = new File(target); - if (!lFileToCopy.exists()) { - copyFromPackage(ressourceId,lFileToCopy.getName()); - } - } - - public void copyFromPackage(int ressourceId, String target) throws IOException{ - FileOutputStream lOutputStream = mServiceContext.openFileOutput (target, 0); - InputStream lInputStream = mR.openRawResource(ressourceId); - int readByte; - byte[] buff = new byte[8048]; - while (( readByte = lInputStream.read(buff)) != -1) { - lOutputStream.write(buff,0, readByte); - } - lOutputStream.flush(); - lOutputStream.close(); - lInputStream.close(); - } -}; - - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d05cfd3a9..aeb45a7bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -210,6 +210,7 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES search/magic-search.h search/search-result.h utils/background-task.h + utils/general-internal.h utils/payload-type-handler.h variant/variant.h xml/conference-info.h @@ -371,7 +372,7 @@ set(LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${SOCI_INCLUDE_DIRS} ${SOCI_MYSQL_INCLUDES} ) -set(LINPHONE_CXX_OBJECTS_DEFINITIONS "-DLIBLINPHONE_EXPORTS") +set(LINPHONE_CXX_OBJECTS_DEFINITIONS "-DLINPHONE_EXPORTS") set(LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${BELR_INCLUDE_DIRS}) set(LINPHONE_PRIVATE_HEADER_FILES) @@ -401,7 +402,8 @@ if(ENABLE_STATIC) ) endif() if(ENABLE_SHARED) - add_library(linphone SHARED "../share/cpim_grammar" ${LINPHONE_HEADER_FILES} + set(LINPHONE_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../share/cpim_grammar") #keep it relative to current dir to allow CMakeList inclusion + add_library(linphone SHARED ${LINPHONE_RESOURCES} ${LINPHONE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_SOURCE_FILES} ${LINPHONE_OBJC_SOURCE_FILES} $ ) @@ -417,7 +419,7 @@ if(ENABLE_SHARED) FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER org.linphone.linphone MACOSX_FRAMEWORK_INFO_PLIST Info.plist.in - RESOURCE "../share/cpim_grammar" + RESOURCE ${LINPHONE_RESOURCES} ) endif() if(BELCARD_FOUND) @@ -436,8 +438,12 @@ if(ENABLE_SHARED) if(APPLE) target_link_libraries(linphone PRIVATE "-framework Foundation" "-framework AVFoundation") endif() - if(WIN32 AND CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - set_target_properties(linphone PROPERTIES PREFIX "lib") + if(WIN32) + # Export Xerces and Soci symbols. + list(APPEND LINPHONE_CXX_OBJECTS_DEFINITIONS "-DDLL_EXPORT" "-DSOCI_DLL") + if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + set_target_properties(linphone PROPERTIES PREFIX "lib") + endif() elseif(ANDROID) target_link_libraries(linphone PUBLIC "log" ${SUPPORT_LIBRARIES} ${CPUFEATURES_LIBRARIES}) endif() @@ -457,6 +463,8 @@ if(ENABLE_SHARED) PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) endif() +target_compile_definitions(linphone PRIVATE ${LINPHONE_CXX_OBJECTS_DEFINITIONS}) + if(ICONV_FOUND) if(APPLE) # Prevent conflict between the system iconv.h header and the one from macports. diff --git a/src/c-wrapper/api/c-call.cpp b/src/c-wrapper/api/c-call.cpp index ffb4b8e30..724c38066 100644 --- a/src/c-wrapper/api/c-call.cpp +++ b/src/c-wrapper/api/c-call.cpp @@ -364,6 +364,10 @@ void linphone_call_set_next_video_frame_decoded_callback (LinphoneCall *call, Li L_GET_CPP_PTR_FROM_C_OBJECT(call)->setNextVideoFrameDecodedCallback(cb, ud); } +void linphone_call_request_notify_next_video_frame_decoded(LinphoneCall *call){ + L_GET_CPP_PTR_FROM_C_OBJECT(call)->requestNotifyNextVideoFrameDecoded(); +} + LinphoneCallState linphone_call_get_transfer_state (LinphoneCall *call) { return static_cast(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getTransferState()); } diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index 18f996048..0832910e4 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -236,9 +236,7 @@ LinphoneChatMessage *linphone_chat_room_get_last_message_in_history(LinphoneChat if (!cppPtr) return nullptr; - LinphoneChatMessage *object = L_INIT(ChatMessage); - L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); - return object; + return linphone_chat_message_ref(L_GET_C_BACK_PTR(cppPtr)); } LinphoneChatMessage *linphone_chat_room_find_message (LinphoneChatRoom *cr, const char *message_id) { diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 29ccb9c16..6dbbd81ec 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -32,10 +32,12 @@ using namespace std; static void _linphone_content_constructor (LinphoneContent *content); static void _linphone_content_destructor (LinphoneContent *content); +static void _linphone_content_c_clone (LinphoneContent *dest, const LinphoneContent *src); L_DECLARE_C_CLONABLE_OBJECT_IMPL_WITH_XTORS(Content, _linphone_content_constructor, _linphone_content_destructor, + _linphone_content_c_clone, void *cryptoContext; // Used to encrypt file for RCS file transfer. @@ -57,6 +59,12 @@ static void _linphone_content_destructor (LinphoneContent *content) { content->cache.~Cache(); } +static void _linphone_content_c_clone (LinphoneContent *dest, const LinphoneContent *src) { + new(&dest->cache) LinphoneContent::Cache(); + dest->size = src->size; + dest->cache = src->cache; +} + // ============================================================================= // Reference and user data handling functions. // ============================================================================= diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index f34c4ee5f..77cd79a01 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -33,6 +33,7 @@ #include "mediastreamer2/mediastream.h" #include "ortp/rtpsession.h" #include "belle-sip/belle-sip.h" +#include "bctoolbox/crypto.h" #ifndef LINPHONE_PUBLIC #if defined(_MSC_VER) @@ -94,10 +95,10 @@ extern "C" { const char* sal_transport_to_string(SalTransport transport); SalTransport sal_transport_parse(const char*); /* Address manipulation API*/ -SalAddress * sal_address_new(const char *uri); +LINPHONE_PUBLIC SalAddress * sal_address_new(const char *uri); SalAddress * sal_address_clone(const SalAddress *addr); SalAddress * sal_address_ref(SalAddress *addr); -void sal_address_unref(SalAddress *addr); +LINPHONE_PUBLIC void sal_address_unref(SalAddress *addr); const char *sal_address_get_scheme(const SalAddress *addr); const char *sal_address_get_display_name(const SalAddress* addr); const char *sal_address_get_display_name_unquoted(const SalAddress *addr); @@ -119,7 +120,7 @@ void sal_address_clean(SalAddress *addr); char *sal_address_as_string(const SalAddress *u); char *sal_address_as_string_uri_only(const SalAddress *u); void sal_address_destroy(SalAddress *u); -void sal_address_set_param(SalAddress *u,const char* name,const char* value); +LINPHONE_PUBLIC void sal_address_set_param(SalAddress *u,const char* name,const char* value); void sal_address_set_transport(SalAddress* addr,SalTransport transport); void sal_address_set_transport_name(SalAddress* addr,const char* transport); void sal_address_set_method_param(SalAddress *addr, const char *method); diff --git a/src/c-wrapper/internal/c-tools.h b/src/c-wrapper/internal/c-tools.h index 492cbaccf..e2520dcc3 100644 --- a/src/c-wrapper/internal/c-tools.h +++ b/src/c-wrapper/internal/c-tools.h @@ -612,6 +612,7 @@ LINPHONE_END_NAMESPACE #undef L_INTERNAL_WRAPPER_CONSTEXPR #define L_INTERNAL_C_NO_XTOR(C_OBJECT) +#define L_INTERNAL_C_NO_CLONE_C(C_DEST_OBJECT, C_SRC_OBJECT) #define L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, ...) \ static_assert(LinphonePrivate::CTypeMetaInfo::defined, "Type is not defined."); \ @@ -669,7 +670,7 @@ LINPHONE_END_NAMESPACE __VA_ARGS__ \ }; \ -#define L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR) \ +#define L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, CLONE_C) \ BELLE_SIP_DECLARE_VPTR_NO_EXPORT(Linphone ## C_TYPE); \ Linphone ## C_TYPE *_linphone_ ## C_TYPE ## _init () { \ Linphone ## C_TYPE *object = belle_sip_object_new(Linphone ## C_TYPE); \ @@ -683,6 +684,7 @@ LINPHONE_END_NAMESPACE static void _linphone_ ## C_TYPE ## _clone (Linphone ## C_TYPE *dest, const Linphone ## C_TYPE *src) { \ L_ASSERT(src->cppPtr); \ dest->cppPtr = new L_CPP_TYPE_OF_C_TYPE(C_TYPE)(*src->cppPtr); \ + CLONE_C(dest, src); \ } \ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(Linphone ## C_TYPE); \ BELLE_SIP_INSTANCIATE_VPTR( \ @@ -760,15 +762,15 @@ LINPHONE_END_NAMESPACE L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, __VA_ARGS__) \ L_INTERNAL_DECLARE_C_OBJECT_FUNCTIONS(C_TYPE, L_INTERNAL_C_NO_XTOR, L_INTERNAL_C_NO_XTOR) -// Declare clonable wrapped C object with constructor/destructor. -#define L_DECLARE_C_CLONABLE_OBJECT_IMPL_WITH_XTORS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, ...) \ +// Declare clonable wrapped C object with constructor/destructor and clone_c. +#define L_DECLARE_C_CLONABLE_OBJECT_IMPL_WITH_XTORS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, CLONE_C, ...) \ L_INTERNAL_DECLARE_C_CLONABLE_OBJECT(C_TYPE, __VA_ARGS__) \ - L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR) + L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, CLONE_C) // Declare clonable wrapped C object. #define L_DECLARE_C_CLONABLE_OBJECT_IMPL(C_TYPE, ...) \ L_INTERNAL_DECLARE_C_CLONABLE_OBJECT(C_TYPE, __VA_ARGS__) \ - L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, L_INTERNAL_C_NO_XTOR, L_INTERNAL_C_NO_XTOR) + L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, L_INTERNAL_C_NO_XTOR, L_INTERNAL_C_NO_XTOR, L_INTERNAL_C_NO_CLONE_C) // ----------------------------------------------------------------------------- // Helpers. diff --git a/src/call/call-p.h b/src/call/call-p.h index 488df87aa..d75942501 100644 --- a/src/call/call-p.h +++ b/src/call/call-p.h @@ -67,7 +67,7 @@ public: void stopMediaStreams (); private: - void resetFirstVideoFrameDecoded (); + void requestNotifyNextVideoFrameDecoded (); void startRemoteRing (); void terminateBecauseOfLostMedia (); diff --git a/src/call/call.cpp b/src/call/call.cpp index a16d08482..e7d0348f2 100644 --- a/src/call/call.cpp +++ b/src/call/call.cpp @@ -148,12 +148,6 @@ void CallPrivate::stopMediaStreams () { // ----------------------------------------------------------------------------- -void CallPrivate::resetFirstVideoFrameDecoded () { -#ifdef VIDEO_ENABLED - if (nextVideoFrameDecoded._func) - static_pointer_cast(getActiveSession())->resetFirstVideoFrameDecoded(); -#endif // ifdef VIDEO_ENABLED -} void CallPrivate::startRemoteRing () { L_Q(); @@ -170,6 +164,7 @@ void CallPrivate::startRemoteRing () { if (as) audio_stream_unprepare_sound(as); if (lc->sound_conf.remote_ring) { + ms_snd_card_set_stream_type(ringCard, MS_SND_CARD_STREAM_VOICE); lc->ringstream = ring_start(lc->factory, lc->sound_conf.remote_ring, 2000, ringCard); } } @@ -350,9 +345,9 @@ void CallPrivate::onIncomingCallSessionTimeoutCheck (const shared_ptr q->getCore()->getCCore()->sip_conf.inc_timeout) { lInfo() << "Incoming call timeout (" << q->getCore()->getCCore()->sip_conf.inc_timeout << ")"; - LinphoneReason declineReason = (q->getCore()->getCurrentCall() != q->getSharedFromThis()) - ? LinphoneReasonBusy : LinphoneReasonDeclined; - getActiveSession()->declineNotAnswered(declineReason); + auto config = linphone_core_get_config(q->getCore()->getCCore()); + int statusCode = linphone_config_get_int(config, "sip", "inc_timeout_status_code", 486); + getActiveSession()->declineNotAnswered(linphone_error_code_to_reason(statusCode)); } } @@ -419,7 +414,16 @@ void CallPrivate::onFirstVideoFrameDecoded (const shared_ptr &sessi } void CallPrivate::onResetFirstVideoFrameDecoded (const shared_ptr &session) { - resetFirstVideoFrameDecoded(); + /*we are called here by the MediaSession when the stream start to know whether there is the deprecated nextVideoFrameDecoded callback set, + * so that we can request the notification of the next frame decoded.*/ +#ifdef VIDEO_ENABLED + if (nextVideoFrameDecoded._func) + requestNotifyNextVideoFrameDecoded(); +#endif // ifdef VIDEO_ENABLED +} + +void CallPrivate::requestNotifyNextVideoFrameDecoded(){ + static_pointer_cast(getActiveSession())->requestNotifyNextVideoFrameDecoded(); } void CallPrivate::onPlayErrorTone (const shared_ptr &session, LinphoneReason reason) { @@ -924,7 +928,12 @@ void Call::setNextVideoFrameDecodedCallback (LinphoneCallCbFunc cb, void *user_d L_D(); d->nextVideoFrameDecoded._func = cb; d->nextVideoFrameDecoded._user_data = user_data; - d->resetFirstVideoFrameDecoded(); + d->requestNotifyNextVideoFrameDecoded(); +} + +void Call::requestNotifyNextVideoFrameDecoded (){ + L_D(); + d->requestNotifyNextVideoFrameDecoded(); } void Call::setParams (const MediaSessionParams *msp) { diff --git a/src/call/call.h b/src/call/call.h index 7566d9420..49315d9f9 100644 --- a/src/call/call.h +++ b/src/call/call.h @@ -123,6 +123,7 @@ public: void setMicrophoneVolumeGain (float value); void setNativeVideoWindowId (void *id); void setNextVideoFrameDecodedCallback (LinphoneCallCbFunc cb, void *user_data); + void requestNotifyNextVideoFrameDecoded(); void setParams (const MediaSessionParams *msp); void setSpeakerVolumeGain (float value); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index ff2a48399..3017bd233 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -457,7 +457,7 @@ static void forceUtf8Content (Content &content) { charset = charset.substr(begin, end - begin); if (Utils::stringToLower(charset) != "utf-8") { - string utf8Body = Utils::convertString(content.getBodyAsUtf8String(), charset, "UTF-8"); + string utf8Body = Utils::convertAnyToUtf8(content.getBodyAsUtf8String(), charset); if (!utf8Body.empty()) { // TODO: use move operator if possible in the future! content.setBodyFromUtf8(utf8Body); diff --git a/src/chat/chat-room/basic-chat-room-p.h b/src/chat/chat-room/basic-chat-room-p.h index c281f940d..28d810955 100644 --- a/src/chat/chat-room/basic-chat-room-p.h +++ b/src/chat/chat-room/basic-chat-room-p.h @@ -30,6 +30,7 @@ LINPHONE_BEGIN_NAMESPACE class BasicChatRoomPrivate : public ChatRoomPrivate { private: std::string subject; + std::shared_ptr me; std::list> participants; bool cpimAllowed = false; bool multipartAllowed = false; diff --git a/src/chat/chat-room/basic-chat-room.cpp b/src/chat/chat-room/basic-chat-room.cpp index 5951f482d..16d6185ce 100644 --- a/src/chat/chat-room/basic-chat-room.cpp +++ b/src/chat/chat-room/basic-chat-room.cpp @@ -40,6 +40,7 @@ BasicChatRoom::BasicChatRoom ( const ChatRoomId &chatRoomId ) : ChatRoom(p, core, chatRoomId) { L_D(); + d->me = make_shared(getLocalAddress()); d->participants.push_back(make_shared(getPeerAddress())); } @@ -102,8 +103,8 @@ shared_ptr BasicChatRoom::findParticipant (const IdentityAddress &) } shared_ptr BasicChatRoom::getMe () const { - lError() << "getMe() is not allowed on a BasicChatRoom"; - return nullptr; + L_D(); + return d->me; } int BasicChatRoom::getParticipantCount () const { diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index aaecdf469..75f91c676 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -168,7 +168,7 @@ bool ChatRoomPrivate::sendDisplayNotification (const shared_ptr &me LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(q->getCore()->getCCore()); if (linphone_im_notif_policy_get_send_imdn_displayed(policy)) { imdnHandler->notifyDisplay(message); - return true; + return imdnHandler->aggregationEnabled(); } return false; } diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index ca4aa3b4d..8fc7fe259 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -58,14 +58,20 @@ Cpim::Message::HeaderList Cpim::Message::getMessageHeaders (const string &ns) co return d->messageHeaders.at(ns); } -void Cpim::Message::addMessageHeader (const Header &messageHeader, const string &ns) { +bool Cpim::Message::addMessageHeader (const Header &messageHeader, const string &ns) { L_D(); + auto header = Parser::getInstance()->cloneHeader(messageHeader); + if (header == nullptr) + return false; + if (d->messageHeaders.find(ns) == d->messageHeaders.end()) d->messageHeaders[ns] = make_shared(); auto list = d->messageHeaders.at(ns); - list->push_back(Parser::getInstance()->cloneHeader(messageHeader)); + list->push_back(header); + + return true; } void Cpim::Message::removeMessageHeader (const Header &messageHeader, const string &ns) { @@ -99,9 +105,16 @@ Cpim::Message::HeaderList Cpim::Message::getContentHeaders () const { return d->contentHeaders; } -void Cpim::Message::addContentHeader (const Header &contentHeader) { +bool Cpim::Message::addContentHeader (const Header &contentHeader) { L_D(); - d->contentHeaders->push_back(Parser::getInstance()->cloneHeader(contentHeader)); + + auto header = Parser::getInstance()->cloneHeader(contentHeader); + if (header == nullptr) + return false; + + d->contentHeaders->push_back(header); + + return true; } void Cpim::Message::removeContentHeader (const Header &contentHeader) { diff --git a/src/chat/cpim/message/cpim-message.h b/src/chat/cpim/message/cpim-message.h index 19e91a43a..ff2a26e30 100644 --- a/src/chat/cpim/message/cpim-message.h +++ b/src/chat/cpim/message/cpim-message.h @@ -37,12 +37,12 @@ namespace Cpim { typedef std::shared_ptr>> HeaderList; HeaderList getMessageHeaders (const std::string &ns = "") const; - void addMessageHeader (const Header &messageHeader, const std::string &ns = ""); + bool addMessageHeader (const Header &messageHeader, const std::string &ns = ""); void removeMessageHeader (const Header &messageHeader, const std::string &ns = ""); std::shared_ptr getMessageHeader (const std::string &name, const std::string &ns = "") const; HeaderList getContentHeaders () const; - void addContentHeader (const Header &contentHeader); + bool addContentHeader (const Header &contentHeader); void removeContentHeader (const Header &contentHeader); std::shared_ptr getContentHeader (const std::string &name) const; diff --git a/src/chat/cpim/parser/cpim-parser.cpp b/src/chat/cpim/parser/cpim-parser.cpp index 23fa0a360..83dd037ce 100644 --- a/src/chat/cpim/parser/cpim-parser.cpp +++ b/src/chat/cpim/parser/cpim-parser.cpp @@ -29,10 +29,6 @@ #include "object/object-p.h" #include "cpim-parser.h" -#ifdef __APPLE__ -#include -#include -#endif #define CPIM_GRAMMAR "cpim_grammar" @@ -339,7 +335,7 @@ namespace Cpim { if (mTime.tm_mon < 1 || mTime.tm_mon > 12) return false; - if (mTime.tm_mday < 1 || (mTime.tm_mon == 2 && isLeapYear ? mTime.tm_mday > 29 : mTime.tm_mday > daysInMonth[mTime.tm_mon - 1])) + if (mTime.tm_mday < 1 || (mTime.tm_mon == 2 && isLeapYear ? mTime.tm_mday > 29 : mTime.tm_mday > daysInMonth[mTime.tm_mon])) return false; // Check time. @@ -583,18 +579,7 @@ public: Cpim::Parser::Parser () : Singleton(*new ParserPrivate) { L_D(); - #if TARGET_OS_IPHONE - CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR("org.linphone.linphone")); - CFURLRef grammarUrl = CFBundleCopyResourceURL(bundle, CFSTR(CPIM_GRAMMAR), nullptr, nullptr); - CFStringRef grammarPath = CFURLCopyFileSystemPath(grammarUrl, kCFURLPOSIXPathStyle); - CFStringEncoding encodingMethod = CFStringGetSystemEncoding(); - const char *path = CFStringGetCStringPtr(grammarPath, encodingMethod); - CFRelease(grammarUrl); - CFRelease(grammarPath); - #else - const char *path = CPIM_GRAMMAR; - #endif - d->grammar = belr::GrammarLoader::get().load(path); + d->grammar = belr::GrammarLoader::get().load(CPIM_GRAMMAR); if (!d->grammar) lFatal() << "Unable to load CPIM grammar."; } diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index d4853bf2d..0e40e6dc1 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -98,7 +98,7 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptrgetContentType().asString()) ); cpimMessage.addContentHeader( - Cpim::GenericHeader("Content-Length", to_string(contentBody.size())) + Cpim::GenericHeader("Content-Length", Utils::toString(contentBody.size())) ); cpimMessage.setContent(contentBody); diff --git a/src/chat/notification/imdn.cpp b/src/chat/notification/imdn.cpp index 8afe38a6b..41f189857 100644 --- a/src/chat/notification/imdn.cpp +++ b/src/chat/notification/imdn.cpp @@ -204,13 +204,11 @@ int Imdn::timerExpired (void *data, unsigned int revents) { bool Imdn::aggregationEnabled () const { auto config = linphone_core_get_config(chatRoom->getCore()->getCCore()); - bool aggregateImdn = linphone_config_get_bool(config, "misc", "aggregate_imdn", TRUE); - return (chatRoom->canHandleCpim() && aggregateImdn); + return (chatRoom->canHandleCpim() && linphone_config_get_bool(config, "misc", "aggregate_imdn", TRUE)); } void Imdn::send () { - bool networkReachable = linphone_core_is_network_reachable(chatRoom->getCore()->getCCore()); - if (!networkReachable) + if (!linphone_core_is_network_reachable(chatRoom->getCore()->getCCore())) return; if (!deliveredMessages.empty() || !displayedMessages.empty()) { diff --git a/src/chat/notification/imdn.h b/src/chat/notification/imdn.h index 58755fdd8..fd765b040 100644 --- a/src/chat/notification/imdn.h +++ b/src/chat/notification/imdn.h @@ -69,13 +69,14 @@ public: void onGlobalStateChanged (LinphoneGlobalState state) override; void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; + bool aggregationEnabled () const; + static std::string createXml (const std::string &id, time_t time, Imdn::Type imdnType, LinphoneReason reason); static void parse (const std::shared_ptr &chatMessage); private: static int timerExpired (void *data, unsigned int revents); - bool aggregationEnabled () const; void send (); void startTimer (); void stopTimer (); diff --git a/src/conference/handlers/local-conference-event-handler-p.h b/src/conference/handlers/local-conference-event-handler-p.h index a4ad08b2a..2c79157b8 100644 --- a/src/conference/handlers/local-conference-event-handler-p.h +++ b/src/conference/handlers/local-conference-event-handler-p.h @@ -32,7 +32,7 @@ LINPHONE_BEGIN_NAMESPACE class Participant; class ParticipantDevice; -class LocalConferenceEventHandlerPrivate : public ObjectPrivate { +class LINPHONE_INTERNAL_PUBLIC LocalConferenceEventHandlerPrivate : public ObjectPrivate { public: void notifyFullState (const std::string ¬ify, const std::shared_ptr &device); void notifyAllExcept (const std::string ¬ify, const std::shared_ptr &exceptParticipant); diff --git a/src/conference/handlers/remote-conference-event-handler.h b/src/conference/handlers/remote-conference-event-handler.h index 550ffeff1..f1d13db6e 100644 --- a/src/conference/handlers/remote-conference-event-handler.h +++ b/src/conference/handlers/remote-conference-event-handler.h @@ -30,8 +30,9 @@ class ChatRoomId; class RemoteConference; class RemoteConferenceEventHandlerPrivate; -class RemoteConferenceEventHandler : public Object { +class LINPHONE_PUBLIC RemoteConferenceEventHandler : public Object { friend class ClientGroupChatRoom; + public: RemoteConferenceEventHandler (RemoteConference *remoteConference); ~RemoteConferenceEventHandler (); diff --git a/src/conference/handlers/remote-conference-list-event-handler.cpp b/src/conference/handlers/remote-conference-list-event-handler.cpp index 1c77a4636..0ea5f22c3 100644 --- a/src/conference/handlers/remote-conference-list-event-handler.cpp +++ b/src/conference/handlers/remote-conference-list-event-handler.cpp @@ -17,7 +17,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/api/c-api.h" #include "linphone/core.h" #include "linphone/event.h" #include "linphone/proxy_config.h" diff --git a/src/conference/local-conference.h b/src/conference/local-conference.h index d926ecf54..31942e241 100644 --- a/src/conference/local-conference.h +++ b/src/conference/local-conference.h @@ -28,7 +28,7 @@ LINPHONE_BEGIN_NAMESPACE class LocalConferencePrivate; -class LocalConference : public Conference { +class LINPHONE_PUBLIC LocalConference : public Conference { friend class ServerGroupChatRoomPrivate; public: diff --git a/src/conference/params/call-session-params.h b/src/conference/params/call-session-params.h index 687b77b17..986c53216 100644 --- a/src/conference/params/call-session-params.h +++ b/src/conference/params/call-session-params.h @@ -33,7 +33,7 @@ LINPHONE_BEGIN_NAMESPACE class CallSessionParamsPrivate; class Core; -class CallSessionParams : public ClonableObject { +class LINPHONE_PUBLIC CallSessionParams : public ClonableObject { friend class CallSession; friend class CallSessionPrivate; friend class ClientGroupChatRoom; diff --git a/src/conference/participant.cpp b/src/conference/participant.cpp index f72094c7f..3d3c4e472 100644 --- a/src/conference/participant.cpp +++ b/src/conference/participant.cpp @@ -111,10 +111,4 @@ bool Participant::isAdmin () const { return d->isAdmin; } -// ============================================================================= - -ostream & operator<< (ostream &strm, const shared_ptr &participant) { - return strm << "'" << participant->getAddress().asString() << "'"; -} - LINPHONE_END_NAMESPACE diff --git a/src/conference/participant.h b/src/conference/participant.h index f1d9f1040..5d59188f4 100644 --- a/src/conference/participant.h +++ b/src/conference/participant.h @@ -23,8 +23,8 @@ #include #include "address/identity-address.h" -#include "object/object.h" #include "conference/params/call-session-params.h" +#include "object/object.h" // ============================================================================= @@ -34,6 +34,7 @@ class ClientGroupChatRoom; class ParticipantPrivate; class Participant : public Object { + // TODO: Remove... It's ugly. friend class Call; friend class CallPrivate; friend class ClientGroupChatRoom; @@ -67,7 +68,10 @@ private: L_DISABLE_COPY(Participant); }; -std::ostream & operator<< (std::ostream &strm, const std::shared_ptr &participant); +inline std::ostream &operator<< (std::ostream &os, const Participant &participant) { + return os << participant.getAddress().asString(); + return os; +} LINPHONE_END_NAMESPACE diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index 8e0b1025e..04c7107d5 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -1122,7 +1122,7 @@ void MediaSessionPrivate::discoverMtu (const Address &remoteAddr) { string MediaSessionPrivate::getBindIpForStream (int streamIndex) { L_Q(); - string bindIp = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", (af == AF_INET6) ? "::0" : "0.0.0.0"); + string bindIp = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", ""); PortConfig *pc = &mediaPorts[streamIndex]; if (!pc->multicastIp.empty()){ if (direction == LinphoneCallOutgoing) { @@ -2367,7 +2367,7 @@ void MediaSessionPrivate::initializeAudioStream () { if (remoteDesc) streamDesc = sal_media_description_find_best_stream(remoteDesc, SalAudio); - audioStream = audio_stream_new2(q->getCore()->getCCore()->factory, getBindIpForStream(mainAudioStreamIndex).c_str(), + audioStream = audio_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainAudioStreamIndex)), (multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainAudioStreamIndex].rtpPort, (multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainAudioStreamIndex].rtcpPort); if (multicastRole == SalMulticastReceiver) @@ -2381,8 +2381,14 @@ void MediaSessionPrivate::initializeAudioStream () { /* Initialize zrtp even if we didn't explicitely set it, just in case peer offers it */ if (linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP)) { - char *peerUri = linphone_address_as_string_uri_only((direction == LinphoneCallIncoming) ? log->from : log->to); - char *selfUri = linphone_address_as_string_uri_only((direction == LinphoneCallIncoming) ? log->to : log->from); + LinphoneAddress *peerAddr = (direction == LinphoneCallIncoming) ? log->from : log->to; + LinphoneAddress *selfAddr = (direction == LinphoneCallIncoming) ? log->to : log->from; + char *peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(peerAddr) + , linphone_address_get_username(peerAddr) + , linphone_address_get_domain(peerAddr)); + char *selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(selfAddr) + , linphone_address_get_username(selfAddr) + , linphone_address_get_domain(selfAddr)); MSZrtpParams params; memset(¶ms, 0, sizeof(MSZrtpParams)); /* media encryption of current params will be set later when zrtp is activated */ @@ -2473,7 +2479,7 @@ void MediaSessionPrivate::initializeTextStream () { if (remoteDesc) streamDesc = sal_media_description_find_best_stream(remoteDesc, SalText); - textStream = text_stream_new2(q->getCore()->getCCore()->factory, getBindIpForStream(mainTextStreamIndex).c_str(), + textStream = text_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainTextStreamIndex)), (multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainTextStreamIndex].rtpPort, (multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainTextStreamIndex].rtcpPort); if (multicastRole == SalMulticastReceiver) @@ -2517,7 +2523,7 @@ void MediaSessionPrivate::initializeVideoStream () { if (remoteDesc) streamDesc = sal_media_description_find_best_stream(remoteDesc, SalVideo); - videoStream = video_stream_new2(q->getCore()->getCCore()->factory, getBindIpForStream(mainVideoStreamIndex).c_str(), + videoStream = video_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainVideoStreamIndex)), (multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainVideoStreamIndex].rtpPort, (multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainVideoStreamIndex].rtcpPort); if (multicastRole == SalMulticastReceiver) @@ -3729,7 +3735,7 @@ void MediaSessionPrivate::accept (const MediaSessionParams *msp, bool wasRinging L_Q(); if (msp) { setParams(new MediaSessionParams(*msp)); - iceAgent->prepare(localDesc, true); + iceAgent->prepare(localDesc, true, false /*we don't allow gathering now, it must have been done before*/); makeLocalMediaDescription(); op->setLocalMediaDescription(localDesc); } @@ -4234,10 +4240,6 @@ void MediaSession::sendVfuRequest () { L_D(); MediaSessionParams *curParams = getCurrentParams(); - if (d->videoStream && d->videoStream->ms.decoder) { - ms_filter_call_method_noarg(d->videoStream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); - } - if ((curParams->avpfEnabled() || curParams->getPrivate()->implicitRtcpFbEnabled()) && d->videoStream && media_stream_get_state(&d->videoStream->ms) == MSStreamStarted) { // || sal_media_description_has_implicit_avpf((const SalMediaDescription *)call->resultdesc) lInfo() << "Request Full Intra Request on CallSession [" << this << "]"; @@ -4369,7 +4371,7 @@ LinphoneStatus MediaSession::update (const MediaSessionParams *msp, const string // ----------------------------------------------------------------------------- -void MediaSession::resetFirstVideoFrameDecoded () { +void MediaSession::requestNotifyNextVideoFrameDecoded () { L_D(); if (d->videoStream && d->videoStream->ms.decoder) ms_filter_call_method_noarg(d->videoStream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); diff --git a/src/conference/session/media-session.h b/src/conference/session/media-session.h index 18fc76d2a..8236c4f8a 100644 --- a/src/conference/session/media-session.h +++ b/src/conference/session/media-session.h @@ -63,7 +63,7 @@ public: void terminateBecauseOfLostMedia (); LinphoneStatus update (const MediaSessionParams *msp, const std::string &subject = ""); - void resetFirstVideoFrameDecoded (); + void requestNotifyNextVideoFrameDecoded (); LinphoneStatus takePreviewSnapshot (const std::string& file); LinphoneStatus takeVideoSnapshot (const std::string& file); void zoomVideo (float zoomFactor, float *cx, float *cy); diff --git a/src/content/content-manager.h b/src/content/content-manager.h index d44c9c3ad..deeb62f57 100644 --- a/src/content/content-manager.h +++ b/src/content/content-manager.h @@ -33,9 +33,10 @@ class Content; namespace { constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; } + namespace ContentManager { - std::list multipartToContentList (const Content &content); - Content contentListToMultipart (const std::list &contents, const std::string &boundary = MultipartBoundary); + LINPHONE_PUBLIC std::list multipartToContentList (const Content &content); + LINPHONE_PUBLIC Content contentListToMultipart (const std::list &contents, const std::string &boundary = MultipartBoundary); } LINPHONE_END_NAMESPACE diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp index 5924cdf5b..519ae2db3 100644 --- a/src/content/header/header.cpp +++ b/src/content/header/header.cpp @@ -45,7 +45,7 @@ Header::Header (const string &name, const string &value) : ClonableObject(*new H setValue(value); return; } - + string parsedValue = value.substr(0, posParam); string params = value.substr(posParam + 1); string token; @@ -167,7 +167,7 @@ string Header::asString () const { stringstream asString; if (!getName().empty()) { asString << getName() << ":"; - } + } asString << getValue(); for (const auto ¶m : getParameters()) { asString << param.asString(); @@ -175,9 +175,9 @@ string Header::asString () const { return asString.str(); } -ostream &operator<<(ostream& stream, const Header& header) { - stream << header.asString(); - return stream; +ostream &operator<< (ostream &os, const Header& header) { + os << header.asString(); + return os; } -LINPHONE_END_NAMESPACE \ No newline at end of file +LINPHONE_END_NAMESPACE diff --git a/src/content/header/header.h b/src/content/header/header.h index 583572523..e0541538a 100644 --- a/src/content/header/header.h +++ b/src/content/header/header.h @@ -60,7 +60,8 @@ public: const HeaderParam &getParameter (const std::string ¶mName) const; std::string asString () const; - friend std::ostream &operator<<(std::ostream&, const Header&); + + LINPHONE_PUBLIC friend std::ostream &operator<< (std::ostream &os, const Header &header); protected: explicit Header (HeaderPrivate &p); diff --git a/src/core/paths/paths-windows.cpp b/src/core/paths/paths-windows.cpp index 827db3500..65b6ba26c 100644 --- a/src/core/paths/paths-windows.cpp +++ b/src/core/paths/paths-windows.cpp @@ -21,6 +21,9 @@ #include #include +#pragma comment(lib, "comsuppw.lib") +#pragma comment(lib, "kernel32.lib") + #include "core/platform-helpers/platform-helpers.h" #include "paths-windows.h" @@ -41,7 +44,7 @@ static string getPath (const GUID &id) { CoTaskMemFree(path); } - return strPath; + return strPath.append("/linphone/"); } diff --git a/src/core/platform-helpers/android-platform-helpers.cpp b/src/core/platform-helpers/android-platform-helpers.cpp index fe27646cb..ca28fe20f 100644 --- a/src/core/platform-helpers/android-platform-helpers.cpp +++ b/src/core/platform-helpers/android-platform-helpers.cpp @@ -109,6 +109,8 @@ AndroidPlatformHelpers::AndroidPlatformHelpers (LinphoneCore *lc, void *systemCo jobject pm = env->CallObjectMethod(mJavaHelper, mGetPowerManagerId); belle_sip_wake_lock_init(env, pm); + linphone_factory_set_top_resources_dir(linphone_factory_get() , getDataPath().append("share").c_str()); + lInfo() << "AndroidPlatformHelpers is fully initialised."; } diff --git a/src/core/platform-helpers/ios-platform-helpers.cpp b/src/core/platform-helpers/ios-platform-helpers.cpp index 6e9ed2f5b..57d14b21f 100644 --- a/src/core/platform-helpers/ios-platform-helpers.cpp +++ b/src/core/platform-helpers/ios-platform-helpers.cpp @@ -20,9 +20,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef __APPLE__ #include "TargetConditionals.h" #endif - #if TARGET_OS_IPHONE +#include + +#include + #include "linphone/utils/general.h" #include "linphone/utils/utils.h" @@ -56,6 +59,7 @@ public: private: void bgTaskTimeout (); static void sBgTaskTimeout (void *data); + static std::string directoryForResource (CFStringRef framework, CFStringRef resource); long int mCpuLockTaskId; int mCpuLockCount; @@ -66,7 +70,20 @@ private: IosPlatformHelpers::IosPlatformHelpers (LinphoneCore *lc, void *system_context) : PlatformHelpers(lc) { mCpuLockCount = 0; mCpuLockTaskId = 0; - lInfo() << "IosPlatformHelpers is fully initialised"; + + std::string cpimPath = directoryForResource(CFSTR("org.linphone.linphone"), CFSTR("cpim_grammar")); + std::string vcardPath = directoryForResource(CFSTR("org.linphone.belcard"), CFSTR("vcard_grammar")); + if (!cpimPath.empty()) + belr::GrammarLoader::get().addPath(cpimPath); + else + lError() << "IosPlatformHelpers did not find cpim grammar resource directory..."; + + if (!vcardPath.empty()) + belr::GrammarLoader::get().addPath(vcardPath); + else + lError() << "IosPlatformHelpers did not find vcard grammar resource directory..."; + + lInfo() << "IosPlatformHelpers is fully initialised."; } // ----------------------------------------------------------------------------- @@ -108,6 +125,19 @@ void IosPlatformHelpers::releaseCpuLock () { mCpuLockTaskId = 0; } +std::string IosPlatformHelpers::directoryForResource (CFStringRef framework, CFStringRef resource) { + CFBundleRef bundle = CFBundleGetBundleWithIdentifier(framework); + CFURLRef grammarUrl = CFBundleCopyResourceURL(bundle, resource, nullptr, nullptr); + CFURLRef grammarUrlDirectory = CFURLCreateCopyDeletingLastPathComponent(nullptr, grammarUrl); + CFStringRef grammarPath = CFURLCopyFileSystemPath(grammarUrlDirectory, kCFURLPOSIXPathStyle); + CFStringEncoding encodingMethod = CFStringGetSystemEncoding(); + std::string path(CFStringGetCStringPtr(grammarPath, encodingMethod)); + CFRelease(grammarUrl); + CFRelease(grammarPath); + CFRelease(grammarUrlDirectory); + return path; +} + // ----------------------------------------------------------------------------- PlatformHelpers *createIosPlatformHelpers (LinphoneCore *lc, void *system_context) { diff --git a/src/db/abstract/abstract-db.h b/src/db/abstract/abstract-db.h index a6b401dd8..ff367f764 100644 --- a/src/db/abstract/abstract-db.h +++ b/src/db/abstract/abstract-db.h @@ -21,6 +21,7 @@ #define _L_ABSTRACT_DB_H_ #include "object/object.h" +#include "utils/general-internal.h" // ============================================================================= @@ -28,7 +29,7 @@ LINPHONE_BEGIN_NAMESPACE class AbstractDbPrivate; -class AbstractDb : public Object { +class LINPHONE_INTERNAL_PUBLIC AbstractDb : public Object { public: enum Backend { Mysql, diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index f96a6e14d..19405c72e 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -138,16 +138,14 @@ struct SqlEventFilterBuilder {}; template struct SqlEventFilterBuilder { - static constexpr Private::StaticString<1 + getIntLength(int(Type)) + sums((1 + getIntLength(int(List)))...)> get () { - return StaticIntString() + "," + SqlEventFilterBuilder::get(); - } + static constexpr auto get () L_AUTO_RETURN( + StaticIntString() + "," + SqlEventFilterBuilder::get() + ); }; template struct SqlEventFilterBuilder { - static constexpr Private::StaticString<1 + getIntLength(int(Type))> get () { - return StaticIntString(); - } + static constexpr auto get () L_AUTO_RETURN(StaticIntString()); }; // ----------------------------------------------------------------------------- @@ -155,27 +153,35 @@ struct SqlEventFilterBuilder { // ----------------------------------------------------------------------------- namespace { - constexpr auto ConferenceCallFilter = SqlEventFilterBuilder< - EventLog::Type::ConferenceCallStart, - EventLog::Type::ConferenceCallEnd - >::get(); + #ifdef _WIN32 + // TODO: Find a workaround to deal with StaticString concatenation!!! + constexpr char ConferenceCallFilter[] = "3,4"; + constexpr char ConferenceChatMessageFilter[] = "5"; + constexpr char ConferenceInfoNoDeviceFilter[] = "1,2,6,7,8,9,12"; + constexpr char ConferenceInfoFilter[] = "1,2,6,7,8,9,10,11,12"; + #else + constexpr auto ConferenceCallFilter = SqlEventFilterBuilder< + EventLog::Type::ConferenceCallStart, + EventLog::Type::ConferenceCallEnd + >::get(); - constexpr auto ConferenceChatMessageFilter = SqlEventFilterBuilder::get(); + constexpr auto ConferenceChatMessageFilter = SqlEventFilterBuilder::get(); - constexpr auto ConferenceInfoNoDeviceFilter = SqlEventFilterBuilder< - EventLog::Type::ConferenceCreated, - EventLog::Type::ConferenceTerminated, - EventLog::Type::ConferenceParticipantAdded, - EventLog::Type::ConferenceParticipantRemoved, - EventLog::Type::ConferenceParticipantSetAdmin, - EventLog::Type::ConferenceParticipantUnsetAdmin, - EventLog::Type::ConferenceSubjectChanged - >::get(); + constexpr auto ConferenceInfoNoDeviceFilter = SqlEventFilterBuilder< + EventLog::Type::ConferenceCreated, + EventLog::Type::ConferenceTerminated, + EventLog::Type::ConferenceParticipantAdded, + EventLog::Type::ConferenceParticipantRemoved, + EventLog::Type::ConferenceParticipantSetAdmin, + EventLog::Type::ConferenceParticipantUnsetAdmin, + EventLog::Type::ConferenceSubjectChanged + >::get(); - constexpr auto ConferenceInfoFilter = ConferenceInfoNoDeviceFilter + "," + SqlEventFilterBuilder< - EventLog::Type::ConferenceParticipantDeviceAdded, - EventLog::Type::ConferenceParticipantDeviceRemoved - >::get(); + constexpr auto ConferenceInfoFilter = ConferenceInfoNoDeviceFilter + "," + SqlEventFilterBuilder< + EventLog::Type::ConferenceParticipantDeviceAdded, + EventLog::Type::ConferenceParticipantDeviceRemoved + >::get(); + #endif // ifdef _WIN32 constexpr EnumToSql EventFilterToSql[] = { { MainDb::ConferenceCallFilter, ConferenceCallFilter }, @@ -356,8 +362,6 @@ long long MainDbPrivate::insertChatRoom (const shared_ptr &cha soci::use(lastUpdateTime), soci::use(capabilities), soci::use(subject), soci::use(flags), soci::use(notifyId); id = dbSession.getLastInsertId(); - if (!chatRoom->canHandleParticipants()) - return id; // Do not add 'me' when creating a server-group-chat-room. if (chatRoomId.getLocalAddress() != chatRoomId.getPeerAddress()) { @@ -613,7 +617,7 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( chatRoom, ChatMessage::Direction(row.get(8)) )); - chatMessage->setIsSecured(bool(row.get(9))); + chatMessage->setIsSecured(!!row.get(9)); ChatMessagePrivate *dChatMessage = chatMessage->getPrivate(); ChatMessage::State messageState = ChatMessage::State(row.get(7)); @@ -627,8 +631,8 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( dChatMessage->setTime(MainDbPrivate::getTmAsTimeT(row.get(5))); dChatMessage->setImdnMessageId(row.get(6)); - dChatMessage->setPositiveDeliveryNotificationRequired(bool(row.get(14))); - dChatMessage->setDisplayNotificationRequired(bool(row.get(15))); + dChatMessage->setPositiveDeliveryNotificationRequired(!!row.get(14)); + dChatMessage->setDisplayNotificationRequired(!!row.get(15)); dChatMessage->markContentsAsNotLoaded(); dChatMessage->setIsReadOnly(true); @@ -1078,7 +1082,7 @@ void MainDbPrivate::updateSchema () { static inline bool checkLegacyTableExists (soci::session &session, const string &name) { session << "SELECT name FROM sqlite_master WHERE type='table' AND name = :name", soci::use(name); - return session.got_data() > 0; + return session.got_data(); } static inline bool checkLegacyFriendsTableExists (soci::session &session) { diff --git a/src/db/main-db.h b/src/db/main-db.h index 53d471dbc..b43f4a7ae 100644 --- a/src/db/main-db.h +++ b/src/db/main-db.h @@ -42,7 +42,7 @@ class MainDbKey; class MainDbPrivate; class ParticipantDevice; -class MainDb : public AbstractDb, public CoreAccessor { +class LINPHONE_INTERNAL_PUBLIC MainDb : public AbstractDb, public CoreAccessor { template friend class DbTransaction; diff --git a/src/db/session/db-session.cpp b/src/db/session/db-session.cpp index b78ae04e7..d96031f7a 100644 --- a/src/db/session/db-session.cpp +++ b/src/db/session/db-session.cpp @@ -225,10 +225,10 @@ bool DbSession::checkTableExists (const string &table) const { switch (d->backend) { case DbSessionPrivate::Backend::Mysql: *session << "SHOW TABLES LIKE :table", soci::use(table); - return session->got_data() > 0; + return session->got_data(); case DbSessionPrivate::Backend::Sqlite3: *session << "SELECT name FROM sqlite_master WHERE type='table' AND name=:table", soci::use(table); - return session->got_data() > 0; + return session->got_data(); case DbSessionPrivate::Backend::None: return false; } diff --git a/src/nat/ice-agent.cpp b/src/nat/ice-agent.cpp index 727781482..b296f066a 100644 --- a/src/nat/ice-agent.cpp +++ b/src/nat/ice-agent.cpp @@ -127,7 +127,7 @@ bool IceAgent::isControlling () const { return ice_session_role(iceSession) == IR_Controlling; } -bool IceAgent::prepare (const SalMediaDescription *localDesc, bool incomingOffer) { +bool IceAgent::prepare (const SalMediaDescription *localDesc, bool incomingOffer, bool allowGathering) { if (!iceSession) return false; @@ -147,10 +147,11 @@ bool IceAgent::prepare (const SalMediaDescription *localDesc, bool incomingOffer prepareIceForStream(mediaSession.getPrivate()->getMediaStream(LinphoneStreamTypeText), true); // Start ICE gathering. - if (incomingOffer) + if (incomingOffer){ // This may delete the ice session. updateFromRemoteMediaDescription(localDesc, remoteDesc, true); - if (iceSession && !ice_session_candidates_gathered(iceSession)) { + } + if (iceSession && allowGathering && !ice_session_candidates_gathered(iceSession)) { mediaSession.getPrivate()->prepareStreamsForIceGathering(hasVideo); int err = gatherIceCandidates(); if (err == 0) { @@ -607,7 +608,6 @@ int IceAgent::gatherIceCandidates () { if (mediaSession.getPrivate()->getAf() == AF_INET6) { if (linphone_core_get_local_ip_for(AF_INET6, nullptr, localAddr) < 0) { lError() << "Fail to get local IPv6"; - return -1; } else addLocalIceCandidates(AF_INET6, localAddr, audioCl, videoCl, textCl); } diff --git a/src/nat/ice-agent.h b/src/nat/ice-agent.h index cb688f0af..f98f2a02e 100644 --- a/src/nat/ice-agent.h +++ b/src/nat/ice-agent.h @@ -57,7 +57,7 @@ public: } bool isControlling () const; - bool prepare (const SalMediaDescription *localDesc, bool incomingOffer); + bool prepare (const SalMediaDescription *localDesc, bool incomingOffer, bool allowGathering = true); void prepareIceForStream (MediaStream *ms, bool createChecklist); void resetSession (IceRole role); void restartSession (IceRole role); diff --git a/src/object/base-object-p.h b/src/object/base-object-p.h index 9c5120a15..ee1099e3a 100644 --- a/src/object/base-object-p.h +++ b/src/object/base-object-p.h @@ -23,12 +23,13 @@ #include "linphone/utils/general.h" #include "object-head-p.h" +#include "utils/general-internal.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE -class BaseObjectPrivate { +class LINPHONE_INTERNAL_PUBLIC BaseObjectPrivate { L_OBJECT_PRIVATE; public: diff --git a/src/object/object-p.h b/src/object/object-p.h index 122ce8d34..2b2d0d351 100644 --- a/src/object/object-p.h +++ b/src/object/object-p.h @@ -27,7 +27,14 @@ LINPHONE_BEGIN_NAMESPACE -class ObjectPrivate : public BaseObjectPrivate { +#ifdef _WIN32 + // TODO: Avoid this error. + // Disable C4251 triggered by std::recursive_mutex. + #pragma warning(push) + #pragma warning(disable: 4251) +#endif // ifdef _WIN32 + +class LINPHONE_INTERNAL_PUBLIC ObjectPrivate : public BaseObjectPrivate { protected: inline const Object::Lock &getLock () const { return lock; @@ -39,6 +46,10 @@ private: L_DECLARE_PUBLIC(Object); }; +#ifdef _WIN32 + #pragma warning(pop) +#endif // ifdef _WIN32 + LINPHONE_END_NAMESPACE #endif // ifndef _L_OBJECT_P_H_ diff --git a/src/sal/call-op.cpp b/src/sal/call-op.cpp index 910031635..d92e4b9ec 100644 --- a/src/sal/call-op.cpp +++ b/src/sal/call-op.cpp @@ -1521,8 +1521,8 @@ void SalCallOp::processNotify(const belle_sip_request_event_t *event, belle_sip_ mRoot->mCallbacks.notify_refer(this,status); } }else{ - ms_error("Notify without sipfrag, trashing"); - resp = createResponseFromRequest(req,501); + ms_error("Notify without sipfrag or not for 'refer' event package, rejecting"); + resp = createResponseFromRequest(req, 489); belle_sip_server_transaction_send_response(server_transaction,resp); } } diff --git a/src/sal/op.cpp b/src/sal/op.cpp index 219ffb568..b8df469df 100644 --- a/src/sal/op.cpp +++ b/src/sal/op.cpp @@ -457,13 +457,19 @@ int SalOp::getAddressFamily() const { if (mRefresher) { - belle_sip_response_t *resp = belle_sip_transaction_get_response(tr); - belle_sip_header_via_t *via = resp ?belle_sip_message_get_header_by_type(resp,belle_sip_header_via_t):NULL; + belle_sip_message_t *msg = belle_sip_transaction_get_response(tr) ? (belle_sip_message_t*) belle_sip_transaction_get_response(tr) : (belle_sip_message_t*) belle_sip_transaction_get_request(tr); + belle_sip_header_via_t *via = msg ? belle_sip_message_get_header_by_type(msg,belle_sip_header_via_t):NULL; + const char *host; if (!via){ ms_error("Unable to determine IP version from signaling operation, no via header found."); return AF_UNSPEC; } - return (strchr(belle_sip_header_via_get_host(via),':') != NULL) ? AF_INET6 : AF_INET; + host = belle_sip_header_via_get_host(via); + if (!host){ + ms_error("Unable to determine IP version from signaling operation, no via header is not yet completed."); + return AF_UNSPEC; + } + return (strchr(host,':') != NULL) ? AF_INET6 : AF_INET; } else { belle_sip_request_t *req = belle_sip_transaction_get_request(tr); contact=(belle_sip_header_address_t*)belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t); diff --git a/src/sal/sal.cpp b/src/sal/sal.cpp index ac3db4c15..193588ca4 100644 --- a/src/sal/sal.cpp +++ b/src/sal/sal.cpp @@ -226,12 +226,12 @@ void Sal::processRequestEventCb (void *ud, const belle_sip_request_event_t *even /*It is worth noting that proxies can (and will) remove this header field*/ op->setPrivacyFromMessage((belle_sip_message_t*)req); - + if (strcmp("ACK",method) != 0){ /*The ACK custom header is processed specifically later on*/ op->assignRecvHeaders((belle_sip_message_t*)req); } - + if (op->mCallbacks && op->mCallbacks->process_request_event) { op->mCallbacks->process_request_event(op,event); } else { @@ -469,6 +469,7 @@ void Sal::setTlsProperties(){ if (!mRootCaData.empty()) belle_tls_crypto_config_set_root_ca_data(crypto_config, mRootCaData.c_str()); if (mSslConfig != NULL) belle_tls_crypto_config_set_ssl_config(crypto_config, mSslConfig); + if (mTlsPostcheckCb) belle_tls_crypto_config_set_postcheck_callback(crypto_config, mTlsPostcheckCb, mTlsPostcheckCbData); belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config); belle_sip_object_unref(crypto_config); } @@ -707,6 +708,11 @@ void Sal::setSslConfig(void *ssl_config) { setTlsProperties(); } +void Sal::setTlsPostcheckCallback(int (*cb)(void *, const bctbx_x509_certificate_t *), void *data){ + mTlsPostcheckCb = cb; + mTlsPostcheckCbData = data; +} + int Sal::createUuid(char *uuid, size_t len) { if (generateUuid(uuid, len) == 0) { setUuid(uuid); @@ -911,147 +917,151 @@ LINPHONE_END_NAMESPACE using namespace LinphonePrivate; +// NOTE: This is ugly but it's not possible to export simply this set of functions in tester_utils... +// Because tester_utils and private files are ill-thought. +// A workaround is to use LINPHONE_PUBLIC here. + extern "C" { -Sal *linphone_core_get_sal(const LinphoneCore *lc) { +LINPHONE_PUBLIC Sal *linphone_core_get_sal(const LinphoneCore *lc) { return lc->sal; } -SalOp *linphone_proxy_config_get_sal_op(const LinphoneProxyConfig *cfg) { +LINPHONE_PUBLIC SalOp *linphone_proxy_config_get_sal_op(const LinphoneProxyConfig *cfg) { return cfg->op; } -SalOp *linphone_call_get_op_as_sal_op(const LinphoneCall *call) { +LINPHONE_PUBLIC SalOp *linphone_call_get_op_as_sal_op(const LinphoneCall *call) { return linphone_call_get_op(call); } -Sal *sal_init(MSFactory *factory) { +LINPHONE_PUBLIC Sal *sal_init(MSFactory *factory) { return new Sal(factory); } -void sal_uninit(Sal* sal) { +LINPHONE_PUBLIC void sal_uninit(Sal* sal) { delete sal; } -int sal_create_uuid(Sal *ctx, char *uuid, size_t len) { +LINPHONE_PUBLIC int sal_create_uuid(Sal *ctx, char *uuid, size_t len) { return ctx->createUuid(uuid, len); } -void sal_set_uuid(Sal *ctx, const char *uuid) { +LINPHONE_PUBLIC void sal_set_uuid(Sal *ctx, const char *uuid) { ctx->setUuid(L_C_TO_STRING(uuid)); } -void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handling_method) { +LINPHONE_PUBLIC void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handling_method) { h->setDefaultSdpHandling(handling_method); } -void sal_set_send_error(Sal *sal,int value) { +LINPHONE_PUBLIC void sal_set_send_error(Sal *sal,int value) { sal->setSendError(value); } -void sal_set_recv_error(Sal *sal,int value) { +LINPHONE_PUBLIC void sal_set_recv_error(Sal *sal,int value) { sal->setRecvError(value); } -void sal_enable_pending_trans_checking(Sal *sal, bool value) { +LINPHONE_PUBLIC void sal_enable_pending_trans_checking(Sal *sal, bool value) { sal->enablePendingTransactionChecking(value); } -void sal_enable_unconditional_answer(Sal *sal,int value) { +LINPHONE_PUBLIC void sal_enable_unconditional_answer(Sal *sal,int value) { sal->enableUnconditionalAnswer(value); } -void sal_set_dns_timeout(Sal* sal,int timeout) { +LINPHONE_PUBLIC void sal_set_dns_timeout(Sal* sal,int timeout) { sal->setDnsTimeout(timeout); } -void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) { +LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) { sal->setDnsUserHostsFile(hosts_file); } -void *sal_get_stack_impl(Sal *sal) { +LINPHONE_PUBLIC void *sal_get_stack_impl(Sal *sal) { return sal->getStackImpl(); } -void sal_set_refresher_retry_after(Sal *sal,int value) { +LINPHONE_PUBLIC void sal_set_refresher_retry_after(Sal *sal,int value) { sal->setRefresherRetryAfter(value); } -int sal_get_refresher_retry_after(const Sal *sal) { +LINPHONE_PUBLIC int sal_get_refresher_retry_after(const Sal *sal) { return sal->getRefresherRetryAfter(); } -void sal_set_transport_timeout(Sal* sal,int timeout) { +LINPHONE_PUBLIC void sal_set_transport_timeout(Sal* sal,int timeout) { sal->setTransportTimeout(timeout); } -void sal_enable_test_features(Sal*ctx, bool enabled) { +LINPHONE_PUBLIC void sal_enable_test_features(Sal*ctx, bool enabled) { ctx->enableTestFeatures(enabled); } -int sal_transport_available(Sal *ctx, SalTransport t) { +LINPHONE_PUBLIC int sal_transport_available(Sal *ctx, SalTransport t) { return ctx->isTransportAvailable(t); } -const SalErrorInfo *sal_op_get_error_info(const SalOp *op) { +LINPHONE_PUBLIC const SalErrorInfo *sal_op_get_error_info(const SalOp *op) { return op->getErrorInfo(); } -bool sal_call_dialog_request_pending(const SalOp *op) { +LINPHONE_PUBLIC bool sal_call_dialog_request_pending(const SalOp *op) { auto callOp = dynamic_cast(op); return callOp->dialogRequestPending(); } -void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) { +LINPHONE_PUBLIC void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) { auto callOp = dynamic_cast(h); callOp->setSdpHandling(handling); } -SalMediaDescription * sal_call_get_final_media_description(SalOp *h) { +LINPHONE_PUBLIC SalMediaDescription * sal_call_get_final_media_description(SalOp *h) { auto callOp = dynamic_cast(h); return callOp->getFinalMediaDescription(); } -belle_sip_resolver_context_t *sal_resolve_a(Sal *sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) { +LINPHONE_PUBLIC belle_sip_resolver_context_t *sal_resolve_a(Sal *sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) { return sal->resolveA(name, port, family, cb, data); } -Sal *sal_op_get_sal(SalOp *op) { +LINPHONE_PUBLIC Sal *sal_op_get_sal(SalOp *op) { return op->getSal(); } -SalOp *sal_create_refer_op(Sal *sal) { +LINPHONE_PUBLIC SalOp *sal_create_refer_op(Sal *sal) { return new SalReferOp(sal); } -void sal_release_op(SalOp *op) { +LINPHONE_PUBLIC void sal_release_op(SalOp *op) { op->release(); } -void sal_op_set_from(SalOp *sal_refer_op, const char* from) { +LINPHONE_PUBLIC void sal_op_set_from(SalOp *sal_refer_op, const char* from) { auto referOp = dynamic_cast(sal_refer_op); referOp->setFrom(from); } -void sal_op_set_to(SalOp *sal_refer_op, const char* to) { +LINPHONE_PUBLIC void sal_op_set_to(SalOp *sal_refer_op, const char* to) { auto referOp = dynamic_cast(sal_refer_op); referOp->setTo(to); } -void sal_op_send_refer(SalOp *sal_refer_op, SalAddress* refer_to) { +LINPHONE_PUBLIC void sal_op_send_refer(SalOp *sal_refer_op, SalAddress* refer_to) { auto referOp = dynamic_cast(sal_refer_op); referOp->sendRefer(refer_to); } -void sal_set_user_pointer(Sal *sal, void *user_pointer) { +LINPHONE_PUBLIC void sal_set_user_pointer(Sal *sal, void *user_pointer) { sal->setUserPointer(user_pointer); } -void *sal_get_user_pointer(Sal *sal) { +LINPHONE_PUBLIC void *sal_get_user_pointer(Sal *sal) { return sal->getUserPointer(); } -void sal_set_call_refer_callback(Sal *sal, void (*OnReferCb)(SalOp *op, const SalAddress *referto)) { +LINPHONE_PUBLIC void sal_set_call_refer_callback(Sal *sal, void (*OnReferCb)(SalOp *op, const SalAddress *referto)) { struct Sal::Callbacks cbs = {NULL}; cbs.refer_received = OnReferCb; sal->setCallbacks(&cbs); diff --git a/src/sal/sal.h b/src/sal/sal.h index 082929f1b..1de178d5f 100644 --- a/src/sal/sal.h +++ b/src/sal/sal.h @@ -224,7 +224,7 @@ public: void verifyServerCertificates (bool value); void verifyServerCn (bool value); - + void setTlsPostcheckCallback(int (*cb)(void *, const bctbx_x509_certificate_t *), void *data); // --------------------------------------------------------------------------- // DNS resolution @@ -317,6 +317,8 @@ private: void *mSslConfig = nullptr; std::vector mSupportedContentTypes; std::string mLinphoneSpecs; + belle_tls_crypto_config_postcheck_callback_t mTlsPostcheckCb; + void *mTlsPostcheckCbData; // Cache values mutable std::string mDnsUserHostsFile; diff --git a/src/search/magic-search.cpp b/src/search/magic-search.cpp index 3d9c6adf4..b88b35aa2 100644 --- a/src/search/magic-search.cpp +++ b/src/search/magic-search.cpp @@ -121,7 +121,7 @@ list MagicSearch::getContactListFromFilter(const string &filter, c list returnList; LinphoneProxyConfig *proxy = nullptr; - if (filter.empty()) return getAllFriends(); + if (filter.empty()) return getFriends(withDomain); if (getSearchCache() != nullptr) { resultList = continueSearch(filter, withDomain); @@ -148,10 +148,14 @@ list MagicSearch::getContactListFromFilter(const string &filter, c if (proxy) { const char *domain = linphone_proxy_config_get_domain(proxy); if (domain) { - string filterAddress = "sip:" + filter + "@" + domain; + string strTmp = filter; + transform(strTmp.begin(), strTmp.end(), strTmp.begin(), [](unsigned char c){ return tolower(c); }); + string filterAddress = "sip:" + strTmp + "@" + domain; LinphoneAddress *lastResult = linphone_core_create_address(this->getCore()->getCCore(), filterAddress.c_str()); - if (lastResult) returnList.push_back(SearchResult(0, lastResult, "", nullptr)); - linphone_address_unref(lastResult); + if (lastResult) { + returnList.push_back(SearchResult(0, lastResult, "", nullptr)); + linphone_address_unref(lastResult); + } } } @@ -173,27 +177,112 @@ void MagicSearch::setSearchCache(list *cache) { d->mCacheResult = cache; } -list MagicSearch::getAllFriends() { +static bool findAddress(const list &list, const LinphoneAddress *addr) { + bool returnValue = false; + char *charAddr = linphone_address_as_string_uri_only(addr); + string sAddr = charAddr; + for (auto r : list) { + if (r.getAddress()) { + char *charTmp = linphone_address_as_string_uri_only(r.getAddress()); + string tmp = charTmp; + if (sAddr == tmp){ + returnValue = true; + if (charTmp) bctbx_free(charTmp); + break; + } + if (charTmp) bctbx_free(charTmp); + } + } + if (charAddr) bctbx_free(charAddr); + return returnValue; +} + +list MagicSearch::getAddressFromCallLog(const string &filter, const string &withDomain, const list ¤tList) { + list resultList; + const bctbx_list_t *callLog = linphone_core_get_call_logs(this->getCore()->getCCore()); + + // For all call log or when we reach the search limit + for (const bctbx_list_t *f = callLog ; f != nullptr ; f = bctbx_list_next(f)) { + LinphoneCallLog *log = reinterpret_cast(f->data); + const LinphoneAddress *addr = (linphone_call_log_get_dir(log) == LinphoneCallDir::LinphoneCallIncoming) ? + linphone_call_log_get_from_address(log) : linphone_call_log_get_to_address(log); + if (addr) { + if (filter.empty()) { + if (findAddress(currentList, addr)) continue; + resultList.push_back(SearchResult(0, addr, "", nullptr)); + } else { + unsigned int weight = searchInAddress(addr, filter, withDomain); + if (weight > getMinWeight()) { + if (findAddress(currentList, addr)) continue; + resultList.push_back(SearchResult(weight, addr, "", nullptr)); + } + } + } + } + + return resultList; +} + +list MagicSearch::getFriends(const string &withDomain) { list returnList; + list clResults; LinphoneFriendList *list = linphone_core_get_default_friend_list(this->getCore()->getCCore()); for (bctbx_list_t *f = list->friends ; f != nullptr ; f = bctbx_list_next(f)) { + LinphoneAddress *phoneAddress = nullptr; const LinphoneFriend *lFriend = reinterpret_cast(f->data); - const LinphoneAddress* lAddress = linphone_friend_get_address(lFriend); + const LinphoneAddress *lAddress = linphone_friend_get_address(lFriend); bctbx_list_t *lPhoneNumbers = linphone_friend_get_phone_numbers(lFriend); string lPhoneNumber = (lPhoneNumbers != nullptr) ? static_cast(lPhoneNumbers->data) : ""; + const LinphonePresenceModel *presence = linphone_friend_get_presence_model(lFriend); + if (lPhoneNumbers) bctbx_list_free(lPhoneNumbers); + + if (presence && !lAddress) { + char *contact = linphone_presence_model_get_contact(presence); + if (contact) { + phoneAddress = linphone_core_create_address(this->getCore()->getCCore(), contact); + bctbx_free(contact); + } + } + + if (!withDomain.empty()) { + if (!lAddress && !phoneAddress) + continue; + if (withDomain != "*" && + withDomain != ((lAddress) ? linphone_address_get_domain(lAddress) : "") && + withDomain != ((phoneAddress) ? linphone_address_get_domain(phoneAddress) : "")) + continue; + } + + if (phoneAddress) linphone_address_unref(phoneAddress); returnList.push_back(SearchResult(1, lAddress, lPhoneNumber, lFriend)); } + clResults = getAddressFromCallLog("", withDomain, clResults); + addResultsToResultsList(clResults, returnList); + returnList.sort([](const SearchResult& lsr, const SearchResult& rsr){ unsigned int cpt = 0; - string name1 = linphone_friend_get_name(lsr.getFriend()); - string name2 = linphone_friend_get_name(rsr.getFriend()); - int char1 = tolower(name1.at(cpt)); - int char2 = tolower(name2.at(cpt)); + string name1 = ""; + string name2 = ""; + if (lsr.getFriend()) { + name1 = linphone_friend_get_name(lsr.getFriend()); + } else if (lsr.getAddress()){ + name1 = linphone_address_get_display_name(lsr.getAddress()) ? + linphone_address_get_display_name(lsr.getAddress()) : linphone_address_get_username(lsr.getAddress()); + } + + if (rsr.getFriend()) { + name2 = linphone_friend_get_name(rsr.getFriend()); + } else if (rsr.getAddress()){ + name2 = linphone_address_get_display_name(rsr.getAddress()) ? + linphone_address_get_display_name(rsr.getAddress()) : linphone_address_get_username(rsr.getAddress()); + } while (name1.size() > cpt && name2.size() > cpt) { + int char1 = tolower(name1.at(cpt)); + int char2 = tolower(name2.at(cpt)); if (char1 < char2) { return true; } else if (char1 > char2) { @@ -204,34 +293,24 @@ list MagicSearch::getAllFriends() { return name1.size() < name2.size(); }); - return returnList; + return *uniqueItemsList(returnList); } list *MagicSearch::beginNewSearch(const string &filter, const string &withDomain) { + list clResults; list *resultList = new list(); LinphoneFriendList *fList = linphone_core_get_default_friend_list(this->getCore()->getCCore()); - const bctbx_list_t *callLog = linphone_core_get_call_logs(this->getCore()->getCCore()); // For all friends or when we reach the search limit for (bctbx_list_t *f = fList->friends ; f != nullptr ; f = bctbx_list_next(f)) { - list results = searchInFriend(reinterpret_cast(f->data), filter, withDomain); - addResultsToResultsList(results, *resultList); + list fResults = searchInFriend(reinterpret_cast(f->data), filter, withDomain); + addResultsToResultsList(fResults, *resultList); } - // For all call log or when we reach the search limit - for (const bctbx_list_t *f = callLog ; f != nullptr ; f = bctbx_list_next(f)) { - LinphoneCallLog *log = reinterpret_cast(f->data); - const LinphoneAddress *addr = (linphone_call_log_get_dir(log) == LinphoneCallDir::LinphoneCallIncoming) ? - linphone_call_log_get_from_address(log) : linphone_call_log_get_to_address(log); - if (addr) { - unsigned int weight = searchInAddress(addr, filter, withDomain); - if (weight > getMinWeight()) { - resultList->push_back(SearchResult(weight, addr, "", nullptr)); - } - } - } + clResults = getAddressFromCallLog(filter, withDomain, *resultList); + addResultsToResultsList(clResults, *resultList); - return resultList; + return uniqueItemsList(*resultList); } list *MagicSearch::continueSearch(const string &filter, const string &withDomain) { @@ -252,7 +331,7 @@ list *MagicSearch::continueSearch(const string &filter, const stri } } - return resultList; + return uniqueItemsList(*resultList); } list MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const string &filter, const string &withDomain) { @@ -290,22 +369,40 @@ list MagicSearch::searchInFriend(const LinphoneFriend *lFriend, co bctbx_list_t *begin, *phoneNumbers = linphone_friend_get_phone_numbers(lFriend); begin = phoneNumbers; while (phoneNumbers && phoneNumbers->data) { + bool domainOk = (withDomain.empty()); string number = static_cast(phoneNumbers->data); const LinphonePresenceModel *presence = linphone_friend_get_presence_model_for_uri_or_tel(lFriend, number.c_str()); phoneNumber = number; if (proxy) { char * buff = linphone_proxy_config_normalize_phone_number(proxy, phoneNumber.c_str()); - phoneNumber = buff; - bctbx_free(buff); + if (buff) { + phoneNumber = buff; + bctbx_free(buff); + } } unsigned int weightNumber = getWeight(phoneNumber.c_str(), filter); if (presence) { char *contact = linphone_presence_model_get_contact(presence); - weightNumber += getWeight(contact, filter) * 2; - bctbx_free(contact); + if (contact) { + if (!domainOk) { + LinphoneAddress *tmpAdd = linphone_core_create_address(this->getCore()->getCCore(), contact); + if (tmpAdd) { + string tmpDomain = linphone_address_get_domain(tmpAdd); + domainOk = (tmpDomain == withDomain) || withDomain == "*"; + linphone_address_unref(tmpAdd); + } + } + weightNumber += getWeight(contact, filter) * 2; + bctbx_free(contact); + } } - if (weightNumber > getMinWeight()) { - friendResult.push_back(SearchResult(weight + weightNumber, linphone_friend_get_address(lFriend), phoneNumber, lFriend)); + if ((weightNumber + weight) > getMinWeight()) { + if (!domainOk && linphone_friend_get_address(lFriend)) { + string tmpDomain = linphone_address_get_domain(linphone_friend_get_address(lFriend)); + domainOk = (tmpDomain == withDomain) || withDomain == "*"; + } + if (domainOk) + friendResult.push_back(SearchResult(weight + weightNumber, linphone_friend_get_address(lFriend), phoneNumber, lFriend)); } phoneNumbers = phoneNumbers->next; } @@ -371,7 +468,7 @@ unsigned int MagicSearch::getWeight(const string &stringWords, const string &fil } bool MagicSearch::checkDomain(const LinphoneFriend *lFriend, const LinphoneAddress *lAddress, const string &withDomain) const { - bool onlySipUri = !withDomain.empty() && withDomain.compare("*") != 0; + bool onlyOneDomain = !withDomain.empty() && withDomain != "*"; const LinphonePresenceModel *presenceModel = lFriend ? linphone_friend_get_presence_model(lFriend) : nullptr; char *contactPresence = presenceModel ? linphone_presence_model_get_contact(presenceModel) : nullptr; @@ -382,12 +479,12 @@ bool MagicSearch::checkDomain(const LinphoneFriend *lFriend, const LinphoneAddre } bool soFarSoGood = + !onlyOneDomain || ( // If we don't want Sip URI only or Address or Presence model - (!onlySipUri || lAddress || presenceModel) && + (lAddress || presenceModel) && // And If we don't want Sip URI only or Address match or Address presence match - (!onlySipUri || - (lAddress && withDomain.compare(linphone_address_get_domain(lAddress)) == 0) || - (addrPresence && withDomain.compare(linphone_address_get_domain(addrPresence)) == 0) + ((lAddress && withDomain == linphone_address_get_domain(lAddress)) || + (addrPresence && withDomain == linphone_address_get_domain(addrPresence))) ); if (addrPresence) linphone_address_unref(addrPresence); @@ -397,10 +494,45 @@ bool MagicSearch::checkDomain(const LinphoneFriend *lFriend, const LinphoneAddre void MagicSearch::addResultsToResultsList(std::list &results, std::list &srL) { if (results.size() > 0) { - for (auto r : results) { - srL.push_back(r); - } + srL.merge(results); } } +static string getAddressFromSearchResult(const SearchResult &sr, const shared_ptr lc) { + string sAddress = ""; + if (!sr.getAddress() && sr.getFriend()) { + const LinphonePresenceModel *presenceModel = linphone_friend_get_presence_model(sr.getFriend()); + char *contactPresence = presenceModel ? linphone_presence_model_get_contact(presenceModel) : nullptr; + + LinphoneAddress *addrPresence = nullptr; + if (contactPresence) { + addrPresence = linphone_core_create_address(lc->getCCore(), contactPresence); + if (addrPresence) { + char *tmp = linphone_address_as_string_uri_only(addrPresence); + sAddress = tmp; + if (tmp) bctbx_free(tmp); + linphone_address_unref(addrPresence); + } + bctbx_free(contactPresence); + } + } else { + char *tmp = linphone_address_as_string_uri_only(sr.getAddress()); + sAddress = tmp; + if (tmp) bctbx_free(tmp); + } + + return sAddress; +} + +list *MagicSearch::uniqueItemsList(list &list) { + auto lc = this->getCore(); + list.unique([lc](const SearchResult& lsr, const SearchResult& rsr){ + string left = getAddressFromSearchResult(lsr, lc); + string right = getAddressFromSearchResult(rsr, lc); + + return (!left.empty() || !right.empty()) && left == right; + }); + return &list; +} + LINPHONE_END_NAMESPACE diff --git a/src/search/magic-search.h b/src/search/magic-search.h index ac6a30e30..13348bac0 100644 --- a/src/search/magic-search.h +++ b/src/search/magic-search.h @@ -140,12 +140,23 @@ private: **/ void setSearchCache(std::list *cache); + /** + * Get all address from call log + * @param[in] filter word we search + * @param[in] withDomain domain which we want to search only + * @param[in] currentList current list where we will check if address already exist + * @return all address from call log which match in a SearchResult list + * @private + **/ + std::list getAddressFromCallLog(const std::string &filter, const std::string &withDomain, const std::list ¤tList); + /** * Get all friends as SearchResult + * @param[in] withDomain domain which we want to search only * @return all friends in a SearchResult list * @private **/ - std::list getAllFriends(); + std::list getFriends(const std::string &withDomain); /** * Begin the search from friend list @@ -202,6 +213,8 @@ private: void addResultsToResultsList(std::list &results, std::list &srL); + std::list *uniqueItemsList(std::list &list); + L_DECLARE_PRIVATE(MagicSearch); }; diff --git a/src/utils/general-internal.h b/src/utils/general-internal.h new file mode 100644 index 000000000..c2e765339 --- /dev/null +++ b/src/utils/general-internal.h @@ -0,0 +1,51 @@ +/* + * general-internal.h + * Copyright (C) 2010-2018 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. + */ + +#ifndef _L_GENERAL_INTERNAL_H_ +#define _L_GENERAL_INTERNAL_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- +// Export. +// ----------------------------------------------------------------------------- + +#ifndef LINPHONE_INTERNAL_PUBLIC + #if defined(_MSC_VER) + #ifdef LINPHONE_STATIC + #define LINPHONE_INTERNAL_PUBLIC + #else + #ifdef LINPHONE_EXPORTS + #define LINPHONE_INTERNAL_PUBLIC __declspec(dllexport) + #else + #define LINPHONE_INTERNAL_PUBLIC __declspec(dllimport) + #endif + #endif + #else + #define LINPHONE_INTERNAL_PUBLIC + #endif +#endif + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_GENERAL_INTERNAL_H_ diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index b05174a63..14de24c8d 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -243,8 +243,8 @@ string Utils::utf8ToLocale (const string &str) { return localeStr; } -string Utils::convertString (const string &str, const string &from, const string &to) { - char *cStr = bctbx_convert_from_to(str.c_str(), from.c_str(), to.c_str()); +string Utils::convertAnyToUtf8 (const string &str, const string &encoding) { + char *cStr = bctbx_convert_any_to_utf8(str.c_str(), encoding.c_str()); string convertedStr = cStringToCppString(cStr); bctbx_free(cStr); return convertedStr; diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index a3342c863..b8fe58a54 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -370,13 +370,13 @@ static inline bool getValueAsBool (const VariantPrivate &p, bool *soFarSoGood) { case Variant::Char: case Variant::Double: case Variant::Float: - return static_cast(getAssumedNumber(p)); + return!!getAssumedNumber(p); case Variant::UnsignedInt: case Variant::UnsignedShort: case Variant::UnsignedLong: case Variant::UnsignedLongLong: - return static_cast(getAssumedUnsignedNumber(p)); + return !!getAssumedUnsignedNumber(p); case Variant::Bool: return p.value.b; @@ -385,7 +385,7 @@ static inline bool getValueAsBool (const VariantPrivate &p, bool *soFarSoGood) { return Utils::stob(*p.value.str); case Variant::Generic: - return static_cast(p.value.g); + return !!p.value.g; default: *soFarSoGood = false; diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 68cd7fe1b..9a4e257a7 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -20,7 +20,7 @@ # ############################################################################ -set(OTHER_LIBS_FOR_TESTER ${BCTOOLBOX_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${BELLESIP_LIBRARIES} ${XML2_LIBRARIES} ${XSD_LIBRARIES}) +set(OTHER_LIBS_FOR_TESTER ${BCTOOLBOX_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${BELLESIP_LIBRARIES} ${XML2_LIBRARIES} ${XSD_LIBRARIES} ${BELR_LIBRARIES}) if(INTL_FOUND) list(APPEND OTHER_LIBS_FOR_TESTER ${INTL_LIBRARIES}) endif() @@ -71,6 +71,8 @@ set(CERTIFICATE_CLIENT_FILES certificates/client/key.pem certificates/client/cert2.pem certificates/client/key2.pem + certificates/client/cert3.pem + certificates/client/key3.pem certificates/client/cert2-signed-by-other-ca.pem ) @@ -262,6 +264,7 @@ if(ANDROID OR IOS) set_target_properties(linphonetester PROPERTIES FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER com.belledonne-communications.linphonetester + PUBLIC_HEADER "${HEADER_FILES}" ) endif() install(TARGETS linphonetester @@ -316,6 +319,7 @@ if (NOT ANDROID AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") endif() set_target_properties(liblinphone_tester PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set_target_properties(liblinphone_tester PROPERTIES LINKER_LANGUAGE CXX) + set_target_properties(liblinphone_tester PROPERTIES C_STANDARD 99) target_include_directories(liblinphone_tester PUBLIC ${BCTOOLBOX_TESTER_INCLUDE_DIRS}) target_link_libraries(liblinphone_tester ${LINPHONE_LIBS_FOR_TOOLS} ${OTHER_LIBS_FOR_TESTER}) diff --git a/tester/call_multicast_tester.c b/tester/call_multicast_tester.c index 249c2adfb..f6182aa18 100644 --- a/tester/call_multicast_tester.c +++ b/tester/call_multicast_tester.c @@ -55,7 +55,7 @@ static void call_multicast_base(bool_t video) { BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(marie),70,int,"%d"); if (video) { /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(linphone_core_get_current_call(marie->lc)); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_get_current_call(marie->lc)); linphone_call_send_vfu_request(linphone_core_get_current_call(marie->lc)); BC_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1)); } @@ -149,7 +149,7 @@ static void early_media_with_multicast_base(bool_t video) { /* send a 183 to initiate the early media */ if (video) { /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(linphone_core_get_current_call(pauline->lc)); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_get_current_call(pauline->lc)); } linphone_call_accept_early_media(linphone_core_get_current_call(pauline->lc)); @@ -160,7 +160,7 @@ static void early_media_with_multicast_base(bool_t video) { /* send a 183 to initiate the early media */ if (video) { /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(linphone_core_get_current_call(pauline2->lc)); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_get_current_call(pauline2->lc)); } linphone_call_accept_early_media(linphone_core_get_current_call(pauline2->lc)); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index a6287f1fe..3a97089de 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -186,11 +186,15 @@ static void linphone_call_next_video_frame_decoded_cb(LinphoneCall *call) { counters->number_of_IframeDecoded++; } -void linphone_call_set_first_video_frame_decoded_cb(LinphoneCall *call) { - LinphoneCallCbs *call_cbs = linphone_factory_create_call_cbs(linphone_factory_get()); - linphone_call_cbs_set_next_video_frame_decoded(call_cbs, linphone_call_next_video_frame_decoded_cb); - linphone_call_add_callbacks(call, call_cbs); - linphone_call_cbs_unref(call_cbs); +void liblinphone_tester_set_next_video_frame_decoded_cb(LinphoneCall *call) { + if (belle_sip_object_data_get(BELLE_SIP_OBJECT(call), "next_video_frame_decoded_set") == NULL){ + LinphoneCallCbs *call_cbs = linphone_factory_create_call_cbs(linphone_factory_get()); + linphone_call_cbs_set_next_video_frame_decoded(call_cbs, linphone_call_next_video_frame_decoded_cb); + linphone_call_add_callbacks(call, call_cbs); + linphone_call_cbs_unref(call_cbs); + belle_sip_object_data_set(BELLE_SIP_OBJECT(call), "next_video_frame_decoded_set", (void*)1, NULL); + } + linphone_call_request_notify_next_video_frame_decoded(call); } #define reset_call_stats(var, value) \ @@ -1492,7 +1496,11 @@ static void call_declined_base(bool_t use_timeout) { BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallEnd,1, int, "%d"); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallEnd,1, int, "%d"); BC_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined, int, "%d"); - BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallDeclined, int, "%d"); + if (use_timeout){ + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallMissed, int, "%d"); + }else{ + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallDeclined, int, "%d"); + } BC_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined, int, "%d"); BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(out_call)),LinphoneCallDeclined, int, "%d"); linphone_call_unref(in_call); @@ -3180,7 +3188,7 @@ static void early_media_call_with_ringing_base(bool_t network_change){ end_call(pauline, marie); ended_time=ms_get_cur_time_ms(); - BC_ASSERT_LOWER( labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1000, long, "%ld"); + BC_ASSERT_LOWER( labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1500, long, "%ld"); } bctbx_list_free(lcs); } @@ -3668,6 +3676,7 @@ void check_media_direction(LinphoneCoreManager* mgr, LinphoneCall *call, bctbx_l linphone_call_cbs_set_next_video_frame_decoded(call_cbs, linphone_call_next_video_frame_decoded_cb); linphone_call_add_callbacks(call, call_cbs); linphone_call_cbs_unref(call_cbs); + linphone_call_request_notify_next_video_frame_decoded(call); linphone_call_send_vfu_request(call); } switch (video_dir) { @@ -4145,7 +4154,7 @@ void early_media_without_sdp_in_200_base( bool_t use_video, bool_t use_ice ){ end_call(pauline, marie); ended_time=ms_get_cur_time_ms(); - BC_ASSERT_LOWER(labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1000, long, "%ld"); + BC_ASSERT_LOWER(labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1500, long, "%ld"); } bctbx_list_free(lcs); linphone_core_manager_destroy(marie); @@ -5826,18 +5835,23 @@ static void call_with_ice_and_rtcp_mux_without_reinvite(void){ static void call_with_zrtp_configured_calling_base(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) { if (ms_zrtp_available()) { - bool_t call_ok; linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionZRTP); - BC_ASSERT_TRUE((call_ok=call(pauline,marie))); + if (BC_ASSERT_TRUE(call(pauline,marie))){ - liblinphone_tester_check_rtcp(marie,pauline); + liblinphone_tester_check_rtcp(marie,pauline); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - end_call(pauline, marie); + LinphoneCall *call = linphone_core_get_current_call(marie->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + + call = linphone_core_get_current_call(pauline->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + end_call(pauline, marie); + } } else { ms_warning("Test skipped, ZRTP not available"); } @@ -5846,18 +5860,23 @@ static void call_with_zrtp_configured_calling_base(LinphoneCoreManager *marie, L static void call_with_zrtp_configured_callee_base(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) { if (ms_zrtp_available()) { - bool_t call_ok; linphone_core_set_media_encryption(marie->lc, LinphoneMediaEncryptionZRTP); - BC_ASSERT_TRUE((call_ok=call(pauline,marie))); + if (BC_ASSERT_TRUE(call(pauline,marie))){ - liblinphone_tester_check_rtcp(marie,pauline); + liblinphone_tester_check_rtcp(marie,pauline); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - end_call(pauline, marie); + LinphoneCall *call = linphone_core_get_current_call(marie->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + + call = linphone_core_get_current_call(pauline->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + end_call(pauline, marie); + } } else { ms_warning("Test skipped, ZRTP not available"); } diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index d96b7b1a3..c0d64e100 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -276,7 +276,7 @@ bool_t request_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bo } if (video_added) { - linphone_call_set_first_video_frame_decoded_cb(call_obj); + liblinphone_tester_set_next_video_frame_decoded_cb(call_obj); /*send vfu*/ linphone_call_send_vfu_request(call_obj); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_IframeDecoded,initial_callee_stat.number_of_IframeDecoded+1)); @@ -600,7 +600,7 @@ void video_call_base_2(LinphoneCoreManager* caller,LinphoneCoreManager* callee, BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(caller_call))); /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(callee_call); + liblinphone_tester_set_next_video_frame_decoded_cb(callee_call); linphone_call_send_vfu_request(callee_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_IframeDecoded,1)); } else { @@ -623,8 +623,8 @@ static void check_fir(LinphoneCoreManager* caller,LinphoneCoreManager* callee ){ /*check video path is established in both directions. Indeed, FIR are ignored until the first RTP packet is received, because SSRC is not known.*/ - linphone_call_set_first_video_frame_decoded_cb(callee_call); - linphone_call_set_first_video_frame_decoded_cb(caller_call); + liblinphone_tester_set_next_video_frame_decoded_cb(callee_call); + liblinphone_tester_set_next_video_frame_decoded_cb(caller_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_IframeDecoded,1)); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_IframeDecoded,1)); @@ -640,7 +640,7 @@ static void check_fir(LinphoneCoreManager* caller,LinphoneCoreManager* callee ){ ms_message("check_fir: [%p] received %d FIR ",&caller_call ,caller_vstream->ms_video_stat.counter_rcvd_fir); ms_message("check_fir: [%p] stat number of iframe decoded %d ",&callee_call, callee->stat.number_of_IframeDecoded); - linphone_call_set_first_video_frame_decoded_cb(caller_call); + liblinphone_tester_set_next_video_frame_decoded_cb(caller_call); linphone_call_send_vfu_request(caller_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_IframeDecoded,1)); @@ -669,6 +669,12 @@ void video_call_base_3(LinphoneCoreManager* caller,LinphoneCoreManager* callee, linphone_core_set_video_policy(callee->lc,&callee_policy); linphone_core_set_video_policy(caller->lc,&caller_policy); } + + linphone_core_set_preferred_video_size_by_name(caller->lc, "QVGA"); + linphone_core_set_preferred_video_size_by_name(callee->lc, "QVGA"); + + linphone_core_set_video_device(caller->lc, "Mire: Mire (synthetic moving picture)"); + linphone_core_set_video_device(callee->lc, "Mire: Mire (synthetic moving picture)"); linphone_core_enable_video_display(callee->lc, callee_video_enabled); linphone_core_enable_video_capture(callee->lc, callee_video_enabled); @@ -879,8 +885,8 @@ static void video_call_established_by_reinvite_with_implicit_avpf(void) { BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(callee_call))); BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(caller_call))); - linphone_call_set_first_video_frame_decoded_cb(caller_call); - linphone_call_set_first_video_frame_decoded_cb(callee_call); + liblinphone_tester_set_next_video_frame_decoded_cb(caller_call); + liblinphone_tester_set_next_video_frame_decoded_cb(callee_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_IframeDecoded,1)); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_IframeDecoded,1)); @@ -1329,7 +1335,7 @@ static void accept_call_in_send_only_base(LinphoneCoreManager* pauline, Linphone /*The send-only client shall set rtp symmetric in absence of media relay for this test.*/ lp_config_set_int(linphone_core_get_config(marie->lc),"rtp","symmetric",1); - linphone_call_set_first_video_frame_decoded_cb(linphone_core_invite_address(pauline->lc,marie->identity)); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_invite_address(pauline->lc,marie->identity)); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallIncomingReceived,1,DEFAULT_WAIT_FOR)); @@ -1420,8 +1426,6 @@ static void video_early_media_call(void) { LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); LinphoneCall *pauline_to_marie; - linphone_core_set_video_device(pauline->lc, "Mire: Mire (synthetic moving picture)"); - video_call_base_3(pauline, marie, TRUE, LinphoneMediaEncryptionNone, TRUE, TRUE); BC_ASSERT_PTR_NOT_NULL(pauline_to_marie = linphone_core_get_current_call(pauline->lc)); @@ -2167,13 +2171,23 @@ static void video_call_expected_fps_for_specified_bandwidth(int bandwidth, int f if (BC_ASSERT_TRUE(call(marie, pauline))){ LinphoneCall *call = linphone_core_get_current_call(marie->lc); - - /*wait for the first TMMBR*/ - BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.last_tmmbr_value_received, 1, 10000)); - VideoStream *vstream = (VideoStream *)linphone_call_get_stream(call, LinphoneStreamTypeVideo); + int count; + /*wait some time until the target fps is reached. Indeed the bandwidth measurement may take several iterations to converge + to a value big enough to allow mediastreamer2 to switch to the high fps profile*/ + + for (count = 0 ; count < 3; count++){ + /*wait for at least the first TMMBR to arrive*/ + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.last_tmmbr_value_received, 1, 10000)); + + if ((int)vstream->configured_fps == fps){ + break; + }else{ + /*target fps not reached yet, wait more time*/ + wait_for_until(marie->lc, pauline->lc, NULL, 0, 2000); + } + } BC_ASSERT_EQUAL((int)vstream->configured_fps, fps, int, "%d"); - end_call(marie, pauline); } } else { diff --git a/tester/certificates/client/cert3.pem b/tester/certificates/client/cert3.pem new file mode 100644 index 000000000..1bffa265d --- /dev/null +++ b/tester/certificates/client/cert3.pem @@ -0,0 +1,78 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 19 (0x13) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=FR, ST=Some-State, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=Jehan Monnier/emailAddress=jehan.monnier@belledonne-communications.com + Validity + Not Before: Apr 3 13:55:30 2018 GMT + Not After : Mar 31 13:55:30 2028 GMT + Subject: C=FR, ST=Some-State, L=Grenoble, O=Internet Widgits Pty Ltd, CN=sip:gandalf@sip.example.org + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c4:b0:07:de:24:1a:46:3c:63:2c:f2:a6:9a:ba: + fd:3d:e4:f0:1e:96:6c:74:f7:ad:cf:b3:3c:51:31: + 45:11:af:0a:ca:ba:f2:cc:ef:82:05:28:c3:5d:6c: + bf:65:47:27:ec:37:37:f3:ab:42:52:83:a0:e9:4f: + ef:99:cd:07:04:ee:bb:87:6d:40:a6:dd:2f:b5:79: + 1b:f1:c1:3a:22:75:29:e3:9e:64:67:ae:bf:93:36: + a9:3a:0a:00:bc:4e:b6:ab:db:83:01:7f:35:5e:52: + 2c:bc:21:52:d7:76:0b:48:1d:d7:09:90:be:1b:7c: + 98:3f:a2:70:78:48:99:95:eb:5d:95:07:ca:6f:f7: + 43:f0:c5:0d:3d:60:95:ef:6d:53:8f:7f:6c:95:2d: + 51:b5:3c:84:3a:56:57:b2:2d:d8:6e:36:fe:66:3f: + e5:80:89:6d:98:e0:67:f6:ed:65:ab:dc:ad:fb:04: + 90:2f:30:60:30:8b:9f:a1:a0:9b:b9:54:6b:ae:83: + 41:38:18:60:a3:fe:32:ef:38:46:bc:44:0b:e1:ca: + 4c:41:7e:e2:9c:35:36:eb:f7:54:83:67:c8:9f:83: + 68:00:c3:58:ee:54:be:d6:05:d1:97:c8:e1:47:c0: + 25:eb:55:a6:a0:1b:c6:86:35:ba:f5:7a:63:75:79: + 7d:d7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 47:91:DE:5F:F9:8A:85:B5:0F:68:02:38:5D:67:3F:ED:C6:3C:F2:66 + X509v3 Authority Key Identifier: + keyid:06:5F:5D:C7:16:AF:62:F8:2D:6E:71:03:88:A0:D6:1D:2B:04:7F:BA + + X509v3 Subject Alternative Name: + URI:sip:gandalf@sip.linphone.org, URI:sip:gandalf@sip.example.org + Signature Algorithm: sha1WithRSAEncryption + 38:eb:34:2f:d3:fe:c6:8f:3f:8b:a3:4c:73:2c:84:75:1e:f0: + c0:41:6a:78:63:ad:81:99:ac:cf:9a:27:28:4f:19:3c:81:7f: + dd:81:31:f4:f3:6a:ee:6d:13:fd:99:3f:96:75:94:1f:44:e6: + 9c:1e:d8:9e:34:4d:e6:c9:1c:51:59:e2:6a:96:fc:84:95:d3: + a3:0f:d7:38:db:89:2d:df:67:58:32:88:83:e8:76:7f:5c:28: + 08:3c:75:c0:e1:ae:68:78:0c:4d:9b:71:57:ee:76:99:80:69: + 73:7f:fd:fe:ec:e5:f1:f8:92:e4:1a:c1:8e:9e:70:3e:e3:de: + 1c:2f +-----BEGIN CERTIFICATE----- +MIID9zCCA2CgAwIBAgIBEzANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx +EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK +DBlCZWxsZWRvbm5lIENvbW11bmljYXRpb25zMQwwCgYDVQQLDANMQUIxFjAUBgNV +BAMMDUplaGFuIE1vbm5pZXIxOjA4BgkqhkiG9w0BCQEWK2plaGFuLm1vbm5pZXJA +YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTgwNDAzMTM1NTMwWhcN +MjgwMzMxMTM1NTMwWjB+MQswCQYDVQQGEwJGUjETMBEGA1UECAwKU29tZS1TdGF0 +ZTERMA8GA1UEBwwIR3Jlbm9ibGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg +UHR5IEx0ZDEkMCIGA1UEAwwbc2lwOmdhbmRhbGZAc2lwLmV4YW1wbGUub3JnMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLAH3iQaRjxjLPKmmrr9PeTw +HpZsdPetz7M8UTFFEa8KyrryzO+CBSjDXWy/ZUcn7Dc386tCUoOg6U/vmc0HBO67 +h21Apt0vtXkb8cE6InUp455kZ66/kzapOgoAvE62q9uDAX81XlIsvCFS13YLSB3X +CZC+G3yYP6JweEiZletdlQfKb/dD8MUNPWCV721Tj39slS1RtTyEOlZXsi3Ybjb+ +Zj/lgIltmOBn9u1lq9yt+wSQLzBgMIufoaCbuVRrroNBOBhgo/4y7zhGvEQL4cpM +QX7inDU26/dUg2fIn4NoAMNY7lS+1gXRl8jhR8Al61WmoBvGhjW69XpjdXl91wID +AQABo4HCMIG/MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2Vu +ZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRHkd5f+YqFtQ9oAjhdZz/txjzy +ZjAfBgNVHSMEGDAWgBQGX13HFq9i+C1ucQOIoNYdKwR/ujBEBgNVHREEPTA7hhxz +aXA6Z2FuZGFsZkBzaXAubGlucGhvbmUub3JnhhtzaXA6Z2FuZGFsZkBzaXAuZXhh +bXBsZS5vcmcwDQYJKoZIhvcNAQEFBQADgYEAOOs0L9P+xo8/i6NMcyyEdR7wwEFq +eGOtgZmsz5onKE8ZPIF/3YEx9PNq7m0T/Zk/lnWUH0TmnB7YnjRN5skcUVniapb8 +hJXTow/XONuJLd9nWDKIg+h2f1woCDx1wOGuaHgMTZtxV+52mYBpc3/9/uzl8fiS +5BrBjp5wPuPeHC8= +-----END CERTIFICATE----- diff --git a/tester/certificates/client/key3.pem b/tester/certificates/client/key3.pem new file mode 100644 index 000000000..144fdee61 --- /dev/null +++ b/tester/certificates/client/key3.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEsAfeJBpGPGMs +8qaauv095PAelmx0963PszxRMUURrwrKuvLM74IFKMNdbL9lRyfsNzfzq0JSg6Dp +T++ZzQcE7ruHbUCm3S+1eRvxwToidSnjnmRnrr+TNqk6CgC8Trar24MBfzVeUiy8 +IVLXdgtIHdcJkL4bfJg/onB4SJmV612VB8pv90PwxQ09YJXvbVOPf2yVLVG1PIQ6 +VleyLdhuNv5mP+WAiW2Y4Gf27WWr3K37BJAvMGAwi5+hoJu5VGuug0E4GGCj/jLv +OEa8RAvhykxBfuKcNTbr91SDZ8ifg2gAw1juVL7WBdGXyOFHwCXrVaagG8aGNbr1 +emN1eX3XAgMBAAECggEAMFb/KAaBep+e1E4yyjaIxOx+Y1YfA8RXsINhoKbWTdlS +cq7tu5ZlwzTYhx6SD6ckVbbghn+hxjvZkV33CjrMrdaqukcMq7YS4qwIRStzSUK4 +b9ve22ikZt75Sm1o7t79oFFL6lNEX5Ecs4QRIyk87pV+4zfysTi3BnS65aUaMjD/ +K+zpK3pBqWcb5dUCjCUMHKw99XC+HjtKFiVWS7CXUQoF1kzTiSNtnz+yX/RBkHYZ +eVM/Gex1WtgCqt9P5zPaFstvxQO8osXZsOrSK2oRZjpiaD5FyyVOBLhTVF1cKHTS +oI89g5SO0GXq+hbfVgx90clnIyLSB83bB5czUJKYIQKBgQDn7vF5pYtF1uxZsRdk +zoDxENfKCghHq7QYULez5mzC8p8COvzXUBq9VKc1zFWhK1R6c+Nl+IXJwf59uO83 +L97cRvminEA3g/CkJet0CoHCHAZ0Z5XrZwuPAX3kjiz3XrThveAJGqO6R239kib2 +V7zXG0aQNP/1VeR1XfPm0e2+ZwKBgQDZGNKTOGI3OnbKlDPTIXhfWixSTR3EU+zE +9Udoeuut0GGZRe/aveciiBGQIrMUpIVPRYJEyP2o3R43z/ZwRjNwDUDA+s0evQ8n +2LFlpNVlN1xdcZrMv7j3hvFGbr362ZPPz7FC6H7FgeHjDq2sHGgjwJMucO0qnNuA +iNoOuLe/EQKBgA+C5HVtQ9483Hu3I0hjoy38IWJqv1kDu7ywkUifzYBQN6Avj79a +pR8qbTBk5QktW64A2CF2uIPgzINd/emj8vSqboGYj5bm5Q4lVxTgqwLvWuMoFlez +AYvj3qaNd6ZnmBNM3pHdTTvlEQ8XWjG5dnCwa0yzrraasvfCe9BhE9RbAoGAdkTu +muNxpjLEenIolZG7WP7v/FokqEssRtR09XdZo5RNR0nxdFJWc9p67vHoa4uBUIFG +iaCRiAgGKVOzJtEnvpiJuVgonOFUO1nysrQMyRpSyFlWgsrDwp2SHdPAzcLwopq8 +L/4m6gRrAd6CQKwtE6UayYcdvUQ81JY5bSG2gHECgYEAg2KU1y5lwws4rjo0HD5f +xeR5JnAVUZ5g2T99SzA1VnNy2klCVF7DorviPiZOlJBvLp0n25tGArRAHqiFSfbH +dUPWhOXiLTozP9Gb0ODAK4k1EtgISNbec1FdhTA+YBOk4CvVCvLFWr2h9yNCzNpd +TCuUz4z2lSsg1YRHT4lJJr8= +-----END PRIVATE KEY----- diff --git a/tester/certificates/client/openssl-altname.cnf b/tester/certificates/client/openssl-altname.cnf new file mode 100644 index 000000000..f97c844d7 --- /dev/null +++ b/tester/certificates/client/openssl-altname.cnf @@ -0,0 +1,360 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# This variant is used for generating client certificate with subjectAltName.uri. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = . # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several ctificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extentions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 3650 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extentions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +# req_extensions = v3_req # The extensions to add to a certificate request +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = FR +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = France + +localityName = Locality Name (eg, city) +localityName_default = Grenoble + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Belledonne Communications + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = LAB +#organizationalUnitName_default = + +0.commonName = Common Name (e.g. server FQDN or YOUR name) +0.commonName_max = 64 +0.commonName_default = sip2.linphone.org + +1.commonName = Common Name (e.g. server FQDN or YOUR name) +1.commonName_max = 64 +1.commonName_default = *.wildcard1.linphone.org + +emailAddress = Email Address +emailAddress_max = 64 +emailAddress_default = jehan.monnier@belledonne-communications.com + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +subjectAltName=URI:sip:gandalf@sip.linphone.org, URI:sip:gandalf@sip.example.org + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo + +#################################################################### +[ tsa ] + +default_tsa = tsa_config1 # the default TSA section + +[ tsa_config1 ] + +# These are used by the TSA reply generation only. +dir = . # TSA root directory +serial = $dir/tsaserial # The current serial number (mandatory) +crypto_device = builtin # OpenSSL engine to use for signing +signer_cert = $dir/tsacert.pem # The TSA signing certificate + # (optional) +certs = $dir/cacert.pem # Certificate chain to include in reply + # (optional) +signer_key = $dir/private/tsakey.pem # The TSA private key (optional) + +default_policy = tsa_policy1 # Policy if request did not specify it + # (optional) +other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) +digests = md5, sha1 # Acceptable message digests (mandatory) +accuracy = secs:1, millisecs:500, microsecs:100 # (optional) +clock_precision_digits = 0 # number of digits after dot. (optional) +ordering = yes # Is ordering defined for timestamps? + # (optional, default: no) +tsa_name = yes # Must the TSA name be included in the reply? + # (optional, default: no) +ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) diff --git a/tester/conference-event-tester.cpp b/tester/conference-event-tester.cpp index ecde1d4ab..42b341d4a 100644 --- a/tester/conference-event-tester.cpp +++ b/tester/conference-event-tester.cpp @@ -492,9 +492,10 @@ void ConferenceEventTester::onFirstNotifyReceived (const IdentityAddress &addr) void ConferenceEventTester::onParticipantAdded (const shared_ptr &event, bool isFullState) { (void)isFullState; // unused const IdentityAddress addr = event->getParticipantAddress(); - participants.insert(pair(addr.asString(), FALSE)); - participantDevices.insert(pair(addr.asString(), 0)); + participants.insert({ addr.asString(), false }); + participantDevices.insert({ addr.asString(), 0 }); } + void ConferenceEventTester::onParticipantRemoved (const shared_ptr &event, bool isFullState) { (void)isFullState; // unused const IdentityAddress addr = event->getParticipantAddress(); diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index ec1f8338a..cb8007551 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -23,7 +23,7 @@ #include "content/content-type.h" #include "content/content.h" #include "core/core.h" - +#include "belr/grammarbuilder.h" // TODO: Remove me later. #include "private.h" @@ -151,6 +151,7 @@ static void parse_message_with_generic_header_parameters () { } static void build_message () { + Cpim::Message message; // Set message headers. @@ -160,7 +161,7 @@ static void build_message () { // 976686000 is 2000-12-13T13:40:00-08:00 Cpim::DateTimeHeader dateTimeHeader(976686000); - BC_ASSERT_EQUAL(dateTimeHeader.getTime(), 976686000, int, "%d"); + BC_ASSERT_EQUAL((int)dateTimeHeader.getTime(), 976686000, int, "%d"); Cpim::SubjectHeader subjectHeader("the weather will be fine today"); @@ -174,22 +175,29 @@ static void build_message () { Cpim::GenericHeader wackyMessageHeader("MyFeatures.WackyMessageOption", "Use-silly-font"); - message.addMessageHeader(fromHeader); - message.addMessageHeader(toHeader); - message.addMessageHeader(dateTimeHeader); - message.addMessageHeader(subjectHeader); - message.addMessageHeader(subjectWithLanguageHeader); - message.addMessageHeader(nsHeader); - message.addMessageHeader(requireHeader); - message.addMessageHeader(vitalMessageHeader); - message.addMessageHeader(wackyMessageHeader); + if (!BC_ASSERT_TRUE(message.addMessageHeader(fromHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(toHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectWithLanguageHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(nsHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(requireHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(vitalMessageHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(wackyMessageHeader))) return; // Set Content headers. Cpim::GenericHeader contentTypeHeader("Content-Type", "text/xml; charset=utf-8"); - message.addContentHeader(contentTypeHeader); + if (!BC_ASSERT_TRUE(message.addContentHeader(contentTypeHeader))) return; Cpim::GenericHeader contentIdHeader("Content-ID", "<1234567890@foo.com>"); - message.addContentHeader(contentIdHeader); + if (!BC_ASSERT_TRUE(message.addContentHeader(contentIdHeader))) return; + + // Add a wrong message header and a wrong content header + Cpim::FromHeader wrongFromHeader("", ""); + if (!BC_ASSERT_FALSE(message.addMessageHeader(wrongFromHeader))) return; + + Cpim::GenericHeader wrongContentHeader("", ""); + if (!BC_ASSERT_FALSE(message.addContentHeader(wrongContentHeader))) return; const string content = "" "Here is the text of my message." @@ -310,7 +318,12 @@ test_t cpim_tests[] = { TEST_NO_TAG("CPIM chat message modifier with multipart body", cpim_chat_message_modifier_with_multipart_body) }; +static int suite_begin(void) { + //Supposed to be done by platform helper, but in this case, we don't have it" + belr::GrammarLoader::get().addPath(std::string(bc_tester_get_resource_dir_prefix()).append("/share/belr/grammars")); + return 0; +} test_suite_t cpim_test_suite = { - "Cpim", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + "Cpim", suite_begin, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, sizeof(cpim_tests) / sizeof(cpim_tests[0]), cpim_tests }; diff --git a/tester/flexisip/README b/tester/flexisip/README index b2799db77..c4dce60b8 100644 --- a/tester/flexisip/README +++ b/tester/flexisip/README @@ -1,3 +1,5 @@ flexisip.conf : is the configuration of the flexisip running on sip2.linphone.org. It has lots of IP addresses hardcoded because this machine is running multiple instances on different IP addresses. flexisip-generic.conf : is the same configuration without any IP address hardcoded and relative paths. It can be run on any machine from the "tester" directory of linphone. +Make sure that any changes performed on one of these two files is also made on the other. + diff --git a/tester/flexisip/flexisip-generic.conf b/tester/flexisip/flexisip-generic.conf index 2795738cd..a25e61166 100644 --- a/tester/flexisip/flexisip-generic.conf +++ b/tester/flexisip/flexisip-generic.conf @@ -115,6 +115,9 @@ filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains ' # Default value: auth-domains= sip.example.org auth.example.org auth1.example.org auth2.example.org +#regexp for test "TLS authentication - client rejected due to unmatched certificate subject" of Flexisip test suite. +tls-client-certificate-required-subject=galadrielle|sip:sip.example.org + # List of whitespace separated IP which will not be challenged. diff --git a/tester/flexisip/flexisip.conf b/tester/flexisip/flexisip.conf index 78f4cba57..e5b800fe2 100644 --- a/tester/flexisip/flexisip.conf +++ b/tester/flexisip/flexisip.conf @@ -115,6 +115,8 @@ filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains ' # Default value: auth-domains= sip.example.org auth.example.org auth1.example.org auth2.example.org +#regexp for test "TLS authentication - client rejected due to unmatched certificate subject" of Flexisip test suite. +tls-client-certificate-required-subject=galadrielle|sip:sip.example.org # List of whitespace separated IP which will not be challenged. @@ -264,7 +266,7 @@ max-contacts-by-aor=15 # Maximum expire time for a REGISTER, in seconds. # Default value: 86400 -max-expires=60 +max-expires=600 # Minimum expire time for a REGISTER, in seconds. # Default value: 60 diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index c98380d85..bc85fd026 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -210,19 +210,19 @@ static void message_forking_with_unreachable_recipients_with_gruu(void) { LinphoneCoreManager *marie = ms_new0(LinphoneCoreManager, 1); LinphoneCoreManager *pauline = ms_new0(LinphoneCoreManager, 1); LinphoneCoreManager *marie2 = ms_new0(LinphoneCoreManager, 1); - + linphone_core_manager_init(marie, "marie_rc", NULL); linphone_core_manager_init(pauline, transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", NULL); linphone_core_manager_init(marie2, "marie_rc", NULL); - + linphone_core_add_supported_tag(marie->lc,"gruu"); linphone_core_add_supported_tag(pauline->lc,"gruu"); linphone_core_add_supported_tag(marie2->lc,"gruu"); - + linphone_core_manager_start(marie,TRUE); linphone_core_manager_start(pauline,TRUE); linphone_core_manager_start(marie2,TRUE); - + bctbx_list_t* lcs=bctbx_list_append(NULL,marie->lc); LinphoneProxyConfig *marie_proxy_config = linphone_core_get_default_proxy_config(marie->lc); @@ -562,7 +562,7 @@ static void call_forking_with_push_notification_double_contact(void){ LinphoneCoreManager* pauline = linphone_core_manager_new2( transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc",FALSE); int dummy=0; - + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "unregister_previous_contact", 1); lp_config_set_int(linphone_core_get_config(pauline->lc), "sip", "unregister_previous_contact", 1); linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); @@ -598,9 +598,9 @@ static void call_forking_with_push_notification_double_contact(void){ BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallConnected,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,1000)); - + liblinphone_tester_check_rtcp(pauline,marie); - + linphone_call_terminate(linphone_core_get_current_call(pauline->lc)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,5000)); @@ -1342,14 +1342,28 @@ static void tls_authentication_requested_bad(LinphoneCore *lc, LinphoneAuthInfo } } -static void tls_client_auth_try_register(const char *identity, bool_t with_good_cert, bool_t must_work){ +static void tls_authentication_provide_altname_cert(LinphoneCore *lc, LinphoneAuthInfo *auth_info, LinphoneAuthMethod method){ + if (method == LinphoneAuthTls){ + + char *cert = bc_tester_res("certificates/client/cert3.pem"); + char *key = bc_tester_res("certificates/client/key3.pem"); + + linphone_auth_info_set_tls_cert_path(auth_info, cert); + linphone_auth_info_set_tls_key_path(auth_info, key); + linphone_core_add_auth_info(lc, auth_info); + bc_free(cert); + bc_free(key); + } +} + +static void tls_client_auth_try_register(const char *identity, LinphoneCoreAuthenticationRequestedCb cb, bool_t good_cert, bool_t must_work){ LinphoneCoreManager *lcm; LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); LinphoneProxyConfig *cfg; lcm = linphone_core_manager_new(NULL); - linphone_core_cbs_set_authentication_requested(cbs, with_good_cert ? tls_authentication_requested_good : tls_authentication_requested_bad); + linphone_core_cbs_set_authentication_requested(cbs, cb); linphone_core_add_callbacks(lcm->lc, cbs); linphone_core_cbs_unref(cbs); cfg = linphone_core_create_proxy_config(lcm->lc); @@ -1368,7 +1382,8 @@ static void tls_client_auth_try_register(const char *identity, bool_t with_good_ /*we should expect at least 2 "auth_requested": one for the TLS certificate, another one because the server rejects the REGISTER with 401, with eventually MD5 + SHA256 challenge*/ /*If the certificate isn't recognized at all, the connection will not happen and no SIP response will be received from server.*/ - if (with_good_cert) BC_ASSERT_GREATER(lcm->stat.number_of_auth_info_requested,2, int, "%d"); + if (good_cert) BC_ASSERT_GREATER(lcm->stat.number_of_auth_info_requested,2, int, "%d"); + else BC_ASSERT_EQUAL(lcm->stat.number_of_auth_info_requested,1, int, "%d"); } @@ -1380,9 +1395,9 @@ void tls_client_auth_bad_certificate_cn(void) { if (transport_supported(LinphoneTransportTls)) { /*first register to the proxy with galadrielle's identity, and authenticate by supplying galadrielle's certificate. * It must work.*/ - tls_client_auth_try_register("sip:galadrielle@sip.example.org", TRUE, TRUE); + tls_client_auth_try_register("sip:galadrielle@sip.example.org", tls_authentication_requested_good, TRUE, TRUE); /*now do the same thing, but trying to register as "Arwen". It must fail.*/ - tls_client_auth_try_register("sip:arwen@sip.example.org", TRUE, FALSE); + tls_client_auth_try_register("sip:arwen@sip.example.org", tls_authentication_requested_good, TRUE, FALSE); } } @@ -1390,7 +1405,18 @@ void tls_client_auth_bad_certificate(void) { if (transport_supported(LinphoneTransportTls)) { /*first register to the proxy with galadrielle's identity, and authenticate by supplying galadrielle's certificate. * It must work.*/ - tls_client_auth_try_register("sip:galadrielle@sip.example.org", FALSE, FALSE); + tls_client_auth_try_register("sip:galadrielle@sip.example.org", tls_authentication_requested_bad, FALSE, FALSE); + } +} + +/* + * This test verifies that the flexisip certificate postcheck works. + * Here, the certificate presented for gandalf is valid and matches the SIP from. However we've set the regexp in flexisip.conf to only accept + * certificates with subjects containing either galadrielle or sip:sip.example.org. + */ +static void tls_client_rejected_due_to_unmatched_subject(void){ + if (transport_supported(LinphoneTransportTls)) { + tls_client_auth_try_register("sip:gandalf@sip.example.org", tls_authentication_provide_altname_cert, TRUE, FALSE); } } @@ -1493,6 +1519,11 @@ void test_removing_old_tport(void) { linphone_core_manager_destroy(marie2); bctbx_list_free(lcs); } +#if 0 +/* SM: I comment this test out. It doesn't unregister participants properly, which confuses subsequent tests. + * The storage of REFER request by flexisip in late forking is no longer required in group chat "release" version. + * It is not essential to keep testing this feature. + */ static const char* get_laure_rc(void) { if (liblinphone_tester_ipv6_available()) { @@ -1509,6 +1540,7 @@ static void on_refer_received(SalOp *op, const SalAddress *refer_to) { } + void resend_refer_other_devices(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -1564,6 +1596,8 @@ void resend_refer_other_devices(void) { bctbx_list_free(lcs); } +#endif + void sequential_forking(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -1594,7 +1628,7 @@ void sequential_forking(void) { BC_ASSERT_EQUAL(marie2->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); LinphoneCall *call = linphone_core_get_current_call(marie->lc); - if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; /*marie accepts the call on its second device*/ linphone_call_accept(call); @@ -1610,6 +1644,7 @@ void sequential_forking(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); +end: linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(marie2); @@ -1650,16 +1685,17 @@ void sequential_forking_with_timeout_for_highest_priority(void) { linphone_core_invite_address(pauline->lc,marie->identity); + /*second and third devices should have received the call*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,13000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallIncomingReceived,1,3000)); /*pauline should hear ringback*/ BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); /*first device should receive nothing since it is disconnected*/ BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); - /*second and third devices should have received the call*/ - BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,3000)); - BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallIncomingReceived,1,3000)); + LinphoneCall *call = linphone_core_get_current_call(marie3->lc); - if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; /*marie accepts the call on her third device*/ linphone_call_accept(call); @@ -1678,6 +1714,7 @@ void sequential_forking_with_timeout_for_highest_priority(void) { /*first device should have received nothing*/ BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallEnd, 0, int, "%d"); +end: linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(marie2); @@ -1708,10 +1745,10 @@ void sequential_forking_with_no_response_for_highest_priority(void) { linphone_core_invite_address(pauline->lc,marie->identity); - /*pauline should hear ringback*/ - BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); /*first device should receive the call*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,3000)); + /*pauline should hear ringback*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); /*second device should have not received the call yet*/ BC_ASSERT_EQUAL(marie2->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); @@ -1722,7 +1759,7 @@ void sequential_forking_with_no_response_for_highest_priority(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived, 1, 3000)); LinphoneCall *call = linphone_core_get_current_call(marie2->lc); - if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; /*marie accepts the call on her second device*/ linphone_call_accept(call); @@ -1738,6 +1775,7 @@ void sequential_forking_with_no_response_for_highest_priority(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000)); +end: linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(marie2); @@ -1770,12 +1808,12 @@ void sequential_forking_with_insertion_of_higher_priority(void) { linphone_core_invite_address(pauline->lc,marie->identity); + /*second device should have received the call*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,13000)); /*pauline should hear ringback*/ BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); /*first device should receive nothing since it is disconnected*/ BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); - /*second device should have received the call*/ - BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,3000)); /*we create a new device*/ LinphoneCoreManager* marie3 = linphone_core_manager_new("marie_rc"); @@ -1786,7 +1824,7 @@ void sequential_forking_with_insertion_of_higher_priority(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallIncomingReceived,1,3000)); LinphoneCall *call = linphone_core_get_current_call(marie3->lc); - if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; /*marie accepts the call on her third device*/ linphone_call_accept(call); @@ -1805,6 +1843,7 @@ void sequential_forking_with_insertion_of_higher_priority(void) { /*first device should have received nothing*/ BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallEnd, 0, int, "%d"); +end: linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(marie2); @@ -1852,16 +1891,16 @@ void sequential_forking_with_fallback_route(void) { /*marie invites pauline2 on the other server*/ linphone_core_invite_address(marie->lc,pauline2->identity); + /*the call should be routed to the first server with pauline account*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallIncomingReceived,1,13000)); + /*marie should hear ringback*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); /*pauline2 should receive nothing since it is disconnected*/ BC_ASSERT_EQUAL(pauline2->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); - /*the call should be routed to the first server with pauline account*/ - BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallIncomingReceived,1,3000)); - LinphoneCall *call = linphone_core_get_current_call(pauline->lc); - if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; /*pauline accepts the call*/ linphone_call_accept(call); @@ -1877,6 +1916,7 @@ void sequential_forking_with_fallback_route(void) { /*first device should have received nothing*/ BC_ASSERT_EQUAL(pauline2->stat.number_of_LinphoneCallEnd, 0, int, "%d"); +end: linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(pauline2); linphone_core_manager_destroy(marie); @@ -1921,9 +1961,10 @@ test_t flexisip_tests[] = { TEST_ONE_TAG("Redis Publish/subscribe", redis_publish_subscribe, "Skip"), TEST_NO_TAG("TLS authentication - client rejected due to CN mismatch", tls_client_auth_bad_certificate_cn), TEST_NO_TAG("TLS authentication - client rejected due to unrecognized certificate chain", tls_client_auth_bad_certificate), + TEST_NO_TAG("TLS authentication - client rejected due to unmatched certificate subject", tls_client_rejected_due_to_unmatched_subject), TEST_NO_TAG("Transcoder", transcoder_tester), TEST_NO_TAG("Removing old tport on flexisip for the same client", test_removing_old_tport), - TEST_NO_TAG("Resend of REFER with other devices", resend_refer_other_devices), + /*TEST_NO_TAG("Resend of REFER with other devices", resend_refer_other_devices),*/ TEST_NO_TAG("Sequential forking", sequential_forking), TEST_NO_TAG("Sequential forking with timeout for highest priority", sequential_forking_with_timeout_for_highest_priority), TEST_NO_TAG("Sequential forking with no response from highest priority", sequential_forking_with_no_response_for_highest_priority), diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c index f4f43d466..12a5a6ad6 100644 --- a/tester/group_chat_tester.c +++ b/tester/group_chat_tester.c @@ -3361,7 +3361,7 @@ static void imdn_sent_from_db_state (void) { BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatReceivedChloeMessage), 2, int, "%d"); for (bctbx_list_t *item = participantsThatReceivedChloeMessage; item; item = bctbx_list_next(item)) { LinphoneParticipantImdnState *state = (LinphoneParticipantImdnState *)bctbx_list_get_data(item); - BC_ASSERT_GREATER(linphone_participant_imdn_state_get_state_change_time(state), initialTime, int, "%d"); + BC_ASSERT_GREATER((int)linphone_participant_imdn_state_get_state_change_time(state), (int)initialTime, int, "%d"); BC_ASSERT_EQUAL(linphone_participant_imdn_state_get_state(state), LinphoneChatMessageStateDeliveredToUser, int, "%d"); BC_ASSERT_PTR_NOT_NULL(linphone_participant_imdn_state_get_participant(state)); } diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 76123ca2c..cac05db7d 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -39,6 +39,12 @@ extern "C" { #endif +#ifdef __ANDROID__ +extern jobject system_context; +#else +extern void *system_context; +#endif + extern test_suite_t account_creator_test_suite; extern test_suite_t call_test_suite; @@ -411,7 +417,7 @@ void account_manager_destroy(void); LinphoneAddress *account_manager_get_identity_with_modified_identity(const LinphoneAddress *modified_identity); LinphoneCore *configure_lc_from(LinphoneCoreCbs *cbs, const char *path, const char *file, void *user_data); -void linphone_call_set_first_video_frame_decoded_cb(LinphoneCall *call); +void liblinphone_tester_set_next_video_frame_decoded_cb(LinphoneCall *call); void call_paused_resumed_base(bool_t multicast,bool_t with_losses); void simple_call_base(bool_t enable_multicast_recv_side); void call_base_with_configfile(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy,bool_t enable_tunnel, const char *marie_rc, const char *pauline_rc); diff --git a/tester/message_tester.c b/tester/message_tester.c index 096873f43..d9cead082 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -315,14 +315,15 @@ static void text_message_within_call_dialog(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); lp_config_set_int(linphone_core_get_config(pauline->lc),"sip","chat_use_call_dialogs",1); - BC_ASSERT_TRUE(call(marie,pauline)); - linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bla bla bla bla"); + if (BC_ASSERT_TRUE(call(marie,pauline))){ + linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bla bla bla bla"); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); - // when using call dialogs, we will never receive delivered status - BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,0,int,"%d"); + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); + // when using call dialogs, we will never receive delivered status + BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,0,int,"%d"); - end_call(marie, pauline); + end_call(marie, pauline); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -551,8 +552,10 @@ end: bc_free(receive_filepath); } -void transfer_message_base(bool_t upload_error, bool_t download_error, bool_t use_file_body_handler_in_upload, - bool_t use_file_body_handler_in_download, bool_t download_from_history, bool_t enable_imdn) { +void transfer_message_base( + bool_t upload_error, bool_t download_error, bool_t use_file_body_handler_in_upload, + bool_t use_file_body_handler_in_download, bool_t download_from_history, bool_t enable_imdn +) { if (transport_supported(LinphoneTransportTls)) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); @@ -825,44 +828,45 @@ void info_message_base(bool_t with_content) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - BC_ASSERT_TRUE(call(pauline,marie)); + if (BC_ASSERT_TRUE(call(pauline,marie))){ - info=linphone_core_create_info_message(marie->lc); - linphone_info_message_add_header(info,"Weather","still bad"); - if (with_content) { - LinphoneContent* content = linphone_core_create_content(marie->lc); - linphone_content_set_type(content, "application"); - linphone_content_set_subtype(content, "somexml"); - linphone_content_set_buffer(content, (const uint8_t *)info_content, strlen(info_content)); - linphone_info_message_set_content(info, content); - linphone_content_unref(content); - } - linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info); - linphone_info_message_unref(info); - - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1)); - - BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_info_message); - hvalue=linphone_info_message_get_header(pauline->stat.last_received_info_message, "Weather"); - content=linphone_info_message_get_content(pauline->stat.last_received_info_message); - - BC_ASSERT_PTR_NOT_NULL(hvalue); - if (hvalue) - BC_ASSERT_STRING_EQUAL(hvalue, "still bad"); - - if (with_content){ - BC_ASSERT_PTR_NOT_NULL(content); - if (content) { - BC_ASSERT_PTR_NOT_NULL(linphone_content_get_buffer(content)); - BC_ASSERT_PTR_NOT_NULL(linphone_content_get_type(content)); - BC_ASSERT_PTR_NOT_NULL(linphone_content_get_subtype(content)); - if (linphone_content_get_type(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content),"application"); - if (linphone_content_get_subtype(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content),"somexml"); - if (linphone_content_get_buffer(content))BC_ASSERT_STRING_EQUAL(linphone_content_get_string_buffer(content),info_content); - BC_ASSERT_EQUAL((int)linphone_content_get_size(content),(int)strlen(info_content), int, "%d"); + info=linphone_core_create_info_message(marie->lc); + linphone_info_message_add_header(info,"Weather","still bad"); + if (with_content) { + LinphoneContent* content = linphone_core_create_content(marie->lc); + linphone_content_set_type(content, "application"); + linphone_content_set_subtype(content, "somexml"); + linphone_content_set_buffer(content, (const uint8_t *)info_content, strlen(info_content)); + linphone_info_message_set_content(info, content); + linphone_content_unref(content); } + linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info); + linphone_info_message_unref(info); + + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1)); + + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_info_message); + hvalue=linphone_info_message_get_header(pauline->stat.last_received_info_message, "Weather"); + content=linphone_info_message_get_content(pauline->stat.last_received_info_message); + + BC_ASSERT_PTR_NOT_NULL(hvalue); + if (hvalue) + BC_ASSERT_STRING_EQUAL(hvalue, "still bad"); + + if (with_content){ + BC_ASSERT_PTR_NOT_NULL(content); + if (content) { + BC_ASSERT_PTR_NOT_NULL(linphone_content_get_buffer(content)); + BC_ASSERT_PTR_NOT_NULL(linphone_content_get_type(content)); + BC_ASSERT_PTR_NOT_NULL(linphone_content_get_subtype(content)); + if (linphone_content_get_type(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content),"application"); + if (linphone_content_get_subtype(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content),"somexml"); + if (linphone_content_get_buffer(content))BC_ASSERT_STRING_EQUAL(linphone_content_get_string_buffer(content),info_content); + BC_ASSERT_EQUAL((int)linphone_content_get_size(content),(int)strlen(info_content), int, "%d"); + } + } + end_call(marie, pauline); } - end_call(marie, pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -1501,7 +1505,7 @@ static void lime_cache_migration(void) { if ((xmlCacheFD = fopen(xmlCache_filepath, "w") ) == NULL) { BC_ASSERT_PTR_NOT_NULL(xmlCacheFD); ms_error("Unable to create temporary XML ZID cache file to test cache migration"); - return; + goto end2; } fprintf(xmlCacheFD, "%s", xmlCacheMigration); fclose(xmlCacheFD); @@ -1515,9 +1519,11 @@ static void lime_cache_migration(void) { linphone_proxy_config_done(cfg); + BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 2, 5000)); + if (!linphone_core_lime_available(marie->lc)) { ms_warning("Lime not available, skiping"); - return; + goto end1; } /* make sure lime is enabled */ @@ -1541,8 +1547,12 @@ static void lime_cache_migration(void) { /* TODO */ /* free memory */ + + end1: linphone_core_manager_destroy(marie); + end2: remove(xmlCache_filepath); + bc_free(xmlCache_filepath); } } @@ -1746,8 +1756,11 @@ static void file_transfer_io_error_after_destroying_chatroom(void) { file_transfer_io_error_base("https://www.linphone.org:444/lft.php", TRUE); } -static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, bool_t mess_with_marie_payload_number, bool_t mess_with_pauline_payload_number, - bool_t ice_enabled, bool_t sql_storage, bool_t do_not_store_rtt_messages_in_sql_storage) { +static void real_time_text( + bool_t audio_stream_enabled, bool_t srtp_enabled, bool_t mess_with_marie_payload_number, + bool_t mess_with_pauline_payload_number, bool_t ice_enabled, bool_t sql_storage, + bool_t do_not_store_rtt_messages_in_sql_storage +) { LinphoneChatRoom *pauline_chat_room; LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); @@ -1905,96 +1918,97 @@ static void real_time_text_conversation(void) { LinphoneCall *pauline_call, *marie_call; linphone_call_params_enable_realtime_text(marie_params,TRUE); - BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params)); - pauline_call=linphone_core_get_current_call(pauline->lc); - marie_call=linphone_core_get_current_call(marie->lc); - BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call))); + if (BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params))){ + pauline_call=linphone_core_get_current_call(pauline->lc); + marie_call=linphone_core_get_current_call(marie->lc); + BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call))); - pauline_chat_room = linphone_call_get_chat_room(pauline_call); - BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); - marie_chat_room = linphone_call_get_chat_room(marie_call); - BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); - if (pauline_chat_room && marie_chat_room) { - const char* message1_1 = "Lorem"; - const char* message1_2 = "Ipsum"; - const char* message2_1 = "Be lle Com"; - const char* message2_2 = "eB ell moC"; - size_t i; - LinphoneChatMessage* pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); - LinphoneChatMessage* marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); + pauline_chat_room = linphone_call_get_chat_room(pauline_call); + BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); + marie_chat_room = linphone_call_get_chat_room(marie_call); + BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); + if (pauline_chat_room && marie_chat_room) { + const char* message1_1 = "Lorem"; + const char* message1_2 = "Ipsum"; + const char* message2_1 = "Be lle Com"; + const char* message2_2 = "eB ell moC"; + size_t i; + LinphoneChatMessage* pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); + LinphoneChatMessage* marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); - for (i = 0; i < strlen(message1_1); i++) { - linphone_chat_message_put_char(pauline_rtt_message, message1_1[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message1_1[i], char, "%c"); + for (i = 0; i < strlen(message1_1); i++) { + linphone_chat_message_put_char(pauline_rtt_message, message1_1[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message1_1[i], char, "%c"); - linphone_chat_message_put_char(marie_rtt_message, message1_2[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message1_2[i], char, "%c"); - } - - /*Commit the message, triggers a NEW LINE in T.140 */ - linphone_chat_message_send(pauline_rtt_message); - linphone_chat_message_send(marie_rtt_message); - - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = marie->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_1); + linphone_chat_message_put_char(marie_rtt_message, message1_2[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message1_2[i], char, "%c"); } - } - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_2); + + /*Commit the message, triggers a NEW LINE in T.140 */ + linphone_chat_message_send(pauline_rtt_message); + linphone_chat_message_send(marie_rtt_message); + + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = marie->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_1); + } } - } - - linphone_chat_message_unref(pauline_rtt_message); - linphone_chat_message_unref(marie_rtt_message); - reset_counters(&pauline->stat); - reset_counters(&marie->stat); - pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); - marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); - - for (i = 0; i < strlen(message2_1); i++) { - linphone_chat_message_put_char(pauline_rtt_message, message2_1[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message2_1[i], char, "%c"); - - linphone_chat_message_put_char(marie_rtt_message, message2_2[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message2_2[i], char, "%c"); - } - - /*Commit the message, triggers a NEW LINE in T.140 */ - linphone_chat_message_send(pauline_rtt_message); - linphone_chat_message_send(marie_rtt_message); - - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = marie->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_1); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_2); + } } - } - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_2); + + linphone_chat_message_unref(pauline_rtt_message); + linphone_chat_message_unref(marie_rtt_message); + reset_counters(&pauline->stat); + reset_counters(&marie->stat); + pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); + marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); + + for (i = 0; i < strlen(message2_1); i++) { + linphone_chat_message_put_char(pauline_rtt_message, message2_1[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message2_1[i], char, "%c"); + + linphone_chat_message_put_char(marie_rtt_message, message2_2[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message2_2[i], char, "%c"); } + + /*Commit the message, triggers a NEW LINE in T.140 */ + linphone_chat_message_send(pauline_rtt_message); + linphone_chat_message_send(marie_rtt_message); + + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = marie->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_1); + } + } + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_2); + } + } + linphone_chat_message_unref(pauline_rtt_message); + linphone_chat_message_unref(marie_rtt_message); } - linphone_chat_message_unref(pauline_rtt_message); - linphone_chat_message_unref(marie_rtt_message); + end_call(marie, pauline); } - end_call(marie, pauline); linphone_call_params_unref(marie_params); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/offeranswer_tester.c b/tester/offeranswer_tester.c index 5a70a42ba..2df43bbdf 100644 --- a/tester/offeranswer_tester.c +++ b/tester/offeranswer_tester.c @@ -35,7 +35,7 @@ static int get_codec_position(const MSList *l, const char *mime_type, int rate){ /*check basic things about codecs at startup: order and enablement*/ static void start_with_no_config(void){ - LinphoneCore *lc=linphone_factory_create_core(linphone_factory_get(), NULL, NULL, NULL); + LinphoneCore *lc=linphone_factory_create_core_2(linphone_factory_get(), NULL, NULL, NULL, NULL, system_context); const MSList *codecs=linphone_core_get_audio_codecs(lc); int opus_codec_pos; int speex_codec_pos=get_codec_position(codecs, "speex", 8000); diff --git a/tester/register_tester.c b/tester/register_tester.c index e69ec1937..9865b5845 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -999,6 +999,36 @@ static void tls_certificate_failure(void){ } } +static void tls_certificate_subject_check(void){ + if (transport_supported(LinphoneTransportTls)) { + LinphoneCoreManager* lcm; + LinphoneCore *lc; + char *rootcapath = bc_tester_res("certificates/cn/cafile.pem"); + lcm=linphone_core_manager_new2("pauline_alt_rc",FALSE); + lc=lcm->lc; + linphone_core_set_root_ca(lc, rootcapath); + /*let's search for a subject that is not in the certificate, it should fail*/ + lp_config_set_string(linphone_core_get_config(lc), "sip", "tls_certificate_subject_regexp", "cotcotcot.org"); + linphone_core_set_network_reachable(lc,TRUE); + BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&lcm->stat.number_of_LinphoneRegistrationFailed,1)); + + /*let's search for a subject (in subjectAltNames and CN) that exist in the certificate, it should pass*/ + lp_config_set_string(linphone_core_get_config(lc), "sip", "tls_certificate_subject_regexp", "altname.linphone.org"); + linphone_core_refresh_registers(lcm->lc); + BC_ASSERT_TRUE(wait_for(lc,lc,&lcm->stat.number_of_LinphoneRegistrationOk,1)); + linphone_core_set_network_reachable(lc,FALSE); + + /*let's search for a subject (in subjectAltNames and CN) that exist in the certificate, it should pass*/ + lp_config_set_string(linphone_core_get_config(lc), "sip", "tls_certificate_subject_regexp", "Jehan Monnier"); + linphone_core_set_network_reachable(lc,TRUE); + BC_ASSERT_TRUE(wait_for(lc,lc,&lcm->stat.number_of_LinphoneRegistrationOk,2)); + + BC_ASSERT_EQUAL(lcm->stat.number_of_LinphoneRegistrationFailed,1, int, "%d"); + linphone_core_manager_destroy(lcm); + bc_free(rootcapath); + } +} + char *read_file(const char *path) { long numbytes = 0; size_t readbytes; @@ -1331,6 +1361,7 @@ test_t register_tests[] = { TEST_NO_TAG("TLS register with alt. name certificate", tls_alt_name_register), TEST_NO_TAG("TLS register with wildcard certificate", tls_wildcard_register), TEST_NO_TAG("TLS certificate not verified",tls_certificate_failure), + TEST_NO_TAG("TLS certificate subjects check",tls_certificate_subject_check), TEST_NO_TAG("TLS certificate given by string instead of file",tls_certificate_data), TEST_NO_TAG("TLS with non tls server",tls_with_non_tls_server), TEST_NO_TAG("Simple authenticated register", simple_authenticated_register), diff --git a/tester/setup_tester.c b/tester/setup_tester.c index abf5f3fe9..590a3c41b 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -68,7 +68,7 @@ static void _check_friend_result_list(LinphoneCore *lc, const bctbx_list_t *resu } const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, index); const LinphoneFriend *lf = linphone_search_result_get_friend(sr); - if (lf) { + if (lf || linphone_search_result_get_address(sr)) { const LinphoneAddress *la = (linphone_search_result_get_address(sr)) ? linphone_search_result_get_address(sr) : linphone_friend_get_address(lf); if (la) { @@ -121,8 +121,8 @@ static void linphone_version_test(void){ static void core_init_test(void) { LinphoneCore* lc; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); - + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); + /* until we have good certificates on our test server... */ linphone_core_verify_server_certificates(lc,FALSE); if (BC_ASSERT_PTR_NOT_NULL(lc)) { @@ -131,14 +131,24 @@ static void core_init_test(void) { } static void linphone_address_test(void) { + LinphoneAddress *address; + linphone_address_unref(create_linphone_address(NULL)); BC_ASSERT_PTR_NULL(linphone_address_new("sip:@sip.linphone.org")); + + address = linphone_address_new("sip:90.110.127.31"); + if (!BC_ASSERT_PTR_NOT_NULL(address)) return; + linphone_address_unref(address); + + address = linphone_address_new("sip:[::ffff:90.110.127.31]"); + if (!BC_ASSERT_PTR_NOT_NULL(address)) return; + linphone_address_unref(address); } static void core_sip_transport_test(void) { LinphoneCore* lc; LCSipTransports tr; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); if (!BC_ASSERT_PTR_NOT_NULL(lc)) return; linphone_core_get_sip_transports(lc,&tr); BC_ASSERT_EQUAL(tr.udp_port,5060, int, "%d"); /*default config*/ @@ -167,7 +177,7 @@ static void linphone_interpret_url_test(void) { LinphoneAddress* address; LinphoneProxyConfig *proxy_config; char *tmp; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); if (!BC_ASSERT_PTR_NOT_NULL( lc )) return; proxy_config =linphone_core_create_proxy_config(lc); @@ -360,7 +370,7 @@ void linphone_proxy_config_is_server_config_changed_test(void) { static void chat_room_test(void) { LinphoneCore* lc; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); if (!BC_ASSERT_PTR_NOT_NULL(lc)) return; BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room_from_uri(lc,"sip:toto@titi.com")); linphone_core_unref(lc); @@ -493,21 +503,25 @@ static void search_friend_in_alphabetical_order(void) { const char *name2SipUri = {"sip:stephanie@sip.example.org"}; const char *name3SipUri = {"sip:alber@sip.example.org"}; const char *name4SipUri = {"sip:gauthier@sip.example.org"}; + const char *name5SipUri = {"sip:gal@sip.example.org"}; LinphoneFriend *friend1 = linphone_core_create_friend(manager->lc); LinphoneFriend *friend2 = linphone_core_create_friend(manager->lc); LinphoneFriend *friend3 = linphone_core_create_friend(manager->lc); LinphoneFriend *friend4 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend5 = linphone_core_create_friend(manager->lc); LinphoneVcard *vcard1 = linphone_factory_create_vcard(linphone_factory_get()); LinphoneVcard *vcard2 = linphone_factory_create_vcard(linphone_factory_get()); LinphoneVcard *vcard3 = linphone_factory_create_vcard(linphone_factory_get()); LinphoneVcard *vcard4 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard5 = linphone_factory_create_vcard(linphone_factory_get()); const char *name1 = {"STEPHANIE delarue"}; const char *name2 = {"alias delarue"}; const char *name3 = {"Alber josh"}; const char *name4 = {"gauthier wei"}; + const char *name5 = {"gal tcho"}; linphone_vcard_set_full_name(vcard1, name1); // STEPHANIE delarue linphone_vcard_set_url(vcard1, name1SipUri); //sip:toto@sip.example.org @@ -533,16 +547,23 @@ static void search_friend_in_alphabetical_order(void) { linphone_friend_set_vcard(friend4, vcard4); linphone_core_add_friend(manager->lc, friend4); + linphone_vcard_set_full_name(vcard5, name5); // gal tcho + linphone_vcard_set_url(vcard5, name5SipUri); //sip:gal@sip.example.org + linphone_vcard_add_sip_address(vcard5, name5SipUri); + linphone_friend_set_vcard(friend5, vcard5); + linphone_core_add_friend(manager->lc, friend5); + magicSearch = linphone_magic_search_new(manager->lc); resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", ""); if (BC_ASSERT_PTR_NOT_NULL(resultList)) { - BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d"); + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d"); _check_friend_result_list(manager->lc, resultList, 0, name3SipUri, NULL);//"sip:stephanie@sip.example.org" _check_friend_result_list(manager->lc, resultList, 1, name2SipUri, NULL);//"sip:alber@sip.example.org" - _check_friend_result_list(manager->lc, resultList, 2, name4SipUri, NULL);//"sip:gauthier@sip.example.org" - _check_friend_result_list(manager->lc, resultList, 3, name1SipUri, NULL);//"sip:toto@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, name5SipUri, NULL);//"sip:gal@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, name4SipUri, NULL);//"sip:gauthier@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 4, name1SipUri, NULL);//"sip:toto@sip.example.org" bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); } @@ -552,16 +573,19 @@ static void search_friend_in_alphabetical_order(void) { linphone_friend_list_remove_friend(lfl, friend2); linphone_friend_list_remove_friend(lfl, friend3); linphone_friend_list_remove_friend(lfl, friend4); + linphone_friend_list_remove_friend(lfl, friend5); if (friend1) linphone_friend_unref(friend1); if (friend2) linphone_friend_unref(friend2); if (friend3) linphone_friend_unref(friend3); if (friend4) linphone_friend_unref(friend4); + if (friend5) linphone_friend_unref(friend5); if (vcard1) linphone_vcard_unref(vcard1); if (vcard2) linphone_vcard_unref(vcard2); if (vcard3) linphone_vcard_unref(vcard3); if (vcard4) linphone_vcard_unref(vcard4); + if (vcard5) linphone_vcard_unref(vcard5); linphone_magic_search_unref(magicSearch); linphone_core_manager_destroy(manager); @@ -591,6 +615,56 @@ static void search_friend_without_filter(void) { linphone_core_manager_destroy(manager); } +static void search_friend_with_domain_without_filter(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("marie_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *chloeName = "chloe zaya"; + const char *chloeSipUri = "sip:ch@sip.test.org"; + const char *chloePhoneNumber = "0633556644"; + LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc); + LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc); + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(manager->lc); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_set_dial_prefix(proxy, "33"); + linphone_proxy_config_done(proxy); + linphone_core_set_default_proxy(manager->lc, proxy); + + linphone_presence_model_set_contact(chloePresence, chloeSipUri); + linphone_friend_set_name(chloeFriend, chloeName); + linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber); + linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence); + linphone_friend_list_add_friend(lfl, chloeFriend); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "sip.test.org"); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[4], NULL);//"sip:hello@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 3, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 4, sFriends[9], NULL);//"sip:loic@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(lfl, chloeSipUri); + linphone_friend_list_remove_friend(lfl, fr); + + if (chloeFriend) linphone_friend_unref(chloeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + static void search_friend_all_domains(void) { LinphoneMagicSearch *magicSearch = NULL; bctbx_list_t *resultList = NULL; @@ -727,15 +801,24 @@ static void search_friend_with_phone_number(void) { bctbx_list_t *resultList = NULL; LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + LinphoneFriend *stephanieFriend = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanieVcard = linphone_factory_create_vcard(linphone_factory_get()); + const char* stephanieName = {"stephanie de monaco"}; const char* mariePhoneNumber = {"0633556644"}; + const char* stephaniePhoneNumber = {"0633889977"}; _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + linphone_vcard_set_full_name(stephanieVcard, stephanieName); // stephanie de monaco + linphone_vcard_add_phone_number(stephanieVcard, stephaniePhoneNumber); + linphone_friend_set_vcard(stephanieFriend, stephanieVcard); + linphone_core_add_friend(manager->lc, stephanieFriend); + linphone_friend_add_phone_number(linphone_friend_list_find_friend_by_uri(lfl, sFriends[5]), mariePhoneNumber); magicSearch = linphone_magic_search_new(manager->lc); - resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", ""); + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", "*"); if (BC_ASSERT_PTR_NOT_NULL(resultList)) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 3, int, "%d"); @@ -791,8 +874,16 @@ static void search_friend_with_phone_number(void) { bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); } + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "55667", "sip.test.org"); + + BC_ASSERT_PTR_NULL(resultList); + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + linphone_friend_list_remove_friend(lfl, stephanieFriend); + if (stephanieFriend) linphone_friend_unref(stephanieFriend); + if (stephanieVcard) linphone_vcard_unref(stephanieVcard); + linphone_magic_search_unref(magicSearch); linphone_core_manager_destroy(manager); } @@ -802,7 +893,8 @@ static void search_friend_with_presence(void) { bctbx_list_t *resultList = NULL; LinphoneCoreManager* manager = linphone_core_manager_create("marie_rc"); LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); - const char *chloeSipUri = "sip:chloe@sip.example.org"; + const char *chloeName = "chloe zaya"; + const char *chloeSipUri = "sip:ch@sip.example.org"; const char *chloePhoneNumber = "0633556644"; LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc); LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc); @@ -815,6 +907,7 @@ static void search_friend_with_presence(void) { _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); linphone_presence_model_set_contact(chloePresence, chloeSipUri); + linphone_friend_set_name(chloeFriend, chloeName); linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber); linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence); linphone_friend_list_add_friend(lfl, chloeFriend); @@ -824,11 +917,11 @@ static void search_friend_with_presence(void) { resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", ""); if (BC_ASSERT_PTR_NOT_NULL(resultList)) { - // 3 + last address from filter "sip:33@sip.example.org" BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d"); - _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+111223344@sip.example.org" - _check_friend_result_list(manager->lc, resultList, 1, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org" - _check_friend_result_list(manager->lc, resultList, 2, sFriends[10], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[10], NULL);//"sip:+111223344@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, "sip:33@sip.example.org", NULL);//"sip:33@sip.example.org" bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); } @@ -837,9 +930,9 @@ static void search_friend_with_presence(void) { resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "chloe", ""); if (BC_ASSERT_PTR_NOT_NULL(resultList)) { - // 1 + last address from filter "sip:chloe@sip.example.org" BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); - _check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, "sip:chloe@sip.example.org", NULL);//"sip:chloe@sip.example.org" bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); } @@ -909,6 +1002,70 @@ static void search_friend_in_call_log(void) { linphone_core_manager_destroy(manager); } +static void search_friend_in_call_log_already_exist(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("marie_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *ronanSipUri = {"sip:ronan@sip.example.org"}; + const char *chloeName = "chloe zaya"; + const char *chloeSipUri = "sip:chloe@sip.example.org"; + const char *chloePhoneNumber = "0633556644"; + LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc); + LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc); + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(manager->lc); + LinphoneAddress *ronanAddress = linphone_address_new(ronanSipUri); + LinphoneAddress *chloeAddress = linphone_address_new(chloeSipUri); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_set_dial_prefix(proxy, "33"); + linphone_proxy_config_done(proxy); + linphone_core_set_default_proxy(manager->lc, proxy); + + linphone_presence_model_set_contact(chloePresence, chloeSipUri); + linphone_friend_set_name(chloeFriend, chloeName); + linphone_friend_set_address(chloeFriend, chloeAddress); + linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber); + linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence); + linphone_friend_list_add_friend(lfl, chloeFriend); + + _create_call_log(manager->lc, ronanAddress, chloeAddress); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "ch", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, NULL);//"sip:chloe@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[1], NULL);//"sip:charette@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, "sip:pauline@sip.example.org", NULL);//In the linphonerc "sip:pauline@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 4,"sip:ch@sip.example.org", NULL);//"sip:ch@sip.example.org" + const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, 0); + if (BC_ASSERT_PTR_NOT_NULL(sr)) { + const LinphoneFriend *lf = linphone_search_result_get_friend(sr); + BC_ASSERT_PTR_NOT_NULL(lf); + } + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(lfl, chloeSipUri); + linphone_friend_list_remove_friend(lfl, fr); + + if (chloeFriend) linphone_friend_unref(chloeFriend); + + if (chloeAddress) linphone_address_unref(chloeAddress); + if (ronanAddress) linphone_address_unref(ronanAddress); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + static void search_friend_last_item_is_filter(void) { LinphoneMagicSearch *magicSearch = NULL; bctbx_list_t *resultList = NULL; @@ -1105,6 +1262,82 @@ static void search_friend_with_multiple_sip_address(void) { linphone_core_manager_destroy(manager); } +static void search_friend_with_same_address(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *stephanieSipUri = {"sip:stephanie@sip.example.org"}; + LinphoneFriend *stephanieFriend1 = linphone_core_create_friend(manager->lc); + LinphoneFriend *stephanieFriend2 = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanieVcard1 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *stephanieVcard2 = linphone_factory_create_vcard(linphone_factory_get()); + const char *stephanieName = {"stephanie delarue"}; + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + linphone_vcard_set_full_name(stephanieVcard1, stephanieName); // stephanie delarue + linphone_vcard_set_url(stephanieVcard1, stephanieSipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(stephanieVcard1, stephanieSipUri); + linphone_friend_set_vcard(stephanieFriend1, stephanieVcard1); + linphone_core_add_friend(manager->lc, stephanieFriend1); + + linphone_vcard_set_full_name(stephanieVcard2, stephanieName); // stephanie delarue + linphone_vcard_set_url(stephanieVcard2, stephanieSipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(stephanieVcard2, stephanieSipUri); + linphone_friend_set_vcard(stephanieFriend2, stephanieVcard2); + linphone_core_add_friend(manager->lc, stephanieFriend2); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "stephanie", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri, NULL);//"sip:stephanie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "delarue", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri, NULL);//"sip:stephanie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), S_SIZE_FRIEND+1, int, "%d"); + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "*"); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), S_SIZE_FRIEND+1, int, "%d"); + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + linphone_friend_list_remove_friend(lfl, stephanieFriend1); + linphone_friend_list_remove_friend(lfl, stephanieFriend2); + if (stephanieFriend1) linphone_friend_unref(stephanieFriend1); + if (stephanieFriend2) linphone_friend_unref(stephanieFriend2); + if (stephanieVcard1) linphone_vcard_unref(stephanieVcard1); + if (stephanieVcard2) linphone_vcard_unref(stephanieVcard2); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + static void search_friend_large_database(void) { char *dbPath = bc_tester_res("db/friends.db"); char *searchedFriend = "6295103032641994169"; @@ -1120,9 +1353,11 @@ static void search_friend_large_database(void) { liblinphone_tester_clock_start(&start); bctbx_list_t *resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, subBuff, ""); if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + long long time; ms_get_cur_time(¤t); - ms_message("Searching time: %lld ms", - ((current.tv_sec - start.tv_sec) * 1000LL) + ((current.tv_nsec - start.tv_nsec) / 1000000LL)); + time = ((current.tv_sec - start.tv_sec) * 1000LL) + ((current.tv_nsec - start.tv_nsec) / 1000000LL); + ms_message("Searching time: %lld ms", time); + BC_ASSERT_LOWER(time, 10000, long long, "%lld"); ms_message("List size: %zu", bctbx_list_size(resultList)); bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); } @@ -1151,7 +1386,8 @@ test_t setup_tests[] = { TEST_NO_TAG("Codec setup", codec_setup), TEST_NO_TAG("Custom tones setup", custom_tones_setup), TEST_ONE_TAG("Return friend list in alphabetical order", search_friend_in_alphabetical_order, "MagicSearch"), - TEST_ONE_TAG("Search friend without filter", search_friend_without_filter, "MagicSearch"), + TEST_ONE_TAG("Search friend without filter and domain", search_friend_without_filter, "MagicSearch"), + TEST_ONE_TAG("Search friend with domain and without filter", search_friend_with_domain_without_filter, "MagicSearch"), TEST_ONE_TAG("Search friend from all domains", search_friend_all_domains, "MagicSearch"), TEST_ONE_TAG("Search friend from one domain", search_friend_one_domain, "MagicSearch"), TEST_ONE_TAG("Multiple looking for friends with the same cache", search_friend_research_estate, "MagicSearch"), @@ -1159,10 +1395,12 @@ test_t setup_tests[] = { TEST_ONE_TAG("Search friend with phone number", search_friend_with_phone_number, "MagicSearch"), TEST_ONE_TAG("Search friend and find it with its presence", search_friend_with_presence, "MagicSearch"), TEST_ONE_TAG("Search friend in call log", search_friend_in_call_log, "MagicSearch"), + TEST_ONE_TAG("Search friend in call log but don't add address which already exist", search_friend_in_call_log_already_exist, "MagicSearch"), TEST_ONE_TAG("Search friend last item is the filter", search_friend_last_item_is_filter, "MagicSearch"), TEST_ONE_TAG("Search friend with name", search_friend_with_name, "MagicSearch"), TEST_ONE_TAG("Search friend with uppercase name", search_friend_with_name_with_uppercase, "MagicSearch"), TEST_ONE_TAG("Search friend with multiple sip address", search_friend_with_multiple_sip_address, "MagicSearch"), + TEST_ONE_TAG("Search friend with same address", search_friend_with_same_address, "MagicSearch"), TEST_ONE_TAG("Search friend in large friends database", search_friend_large_database, "MagicSearch") }; diff --git a/tester/tester.c b/tester/tester.c index 53b408d3c..5f6729c37 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -29,7 +29,12 @@ #define unlink _unlink #endif +#ifdef __ANDROID__ extern jobject system_context; +#else +void *system_context=0; +#endif + static int liblinphone_tester_keep_accounts_flag = 0; static bool_t liblinphone_tester_keep_record_files = FALSE; static bool_t liblinphone_tester_leak_detector_disabled = FALSE; diff --git a/tester/vcard_tester.c b/tester/vcard_tester.c index 84cfcd62f..23a897c13 100644 --- a/tester/vcard_tester.c +++ b/tester/vcard_tester.c @@ -265,7 +265,7 @@ static void friends_sqlite_storage(void) { cbs = linphone_factory_create_core_cbs(linphone_factory_get()); linphone_core_cbs_set_friend_list_created(cbs, friend_list_created_cb); linphone_core_cbs_set_friend_list_removed(cbs, friend_list_removed_cb); - lc = linphone_factory_create_core(linphone_factory_get(), cbs, NULL, NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(), cbs, NULL, NULL, NULL, system_context); linphone_core_cbs_unref(cbs); friends = linphone_friend_list_get_friends(linphone_core_get_default_friend_list(lc)); lfl = linphone_core_create_friend_list(lc); @@ -358,7 +358,7 @@ end: } static void friends_sqlite_store_lot_of_friends(void) { - LinphoneCore* lc = linphone_factory_create_core(linphone_factory_get(), NULL, NULL, NULL); + LinphoneCore* lc = linphone_factory_create_core_2(linphone_factory_get(), NULL, NULL, NULL, NULL, system_context); sqlite3 *db; int i; char* errmsg = NULL; @@ -428,7 +428,7 @@ static void friends_sqlite_store_lot_of_friends(void) { } static void friends_sqlite_find_friend_in_lot_of_friends(void) { - LinphoneCore* lc = linphone_factory_create_core(linphone_factory_get(), NULL, NULL, NULL); + LinphoneCore* lc = linphone_factory_create_core_2(linphone_factory_get(), NULL, NULL, NULL, NULL, system_context); sqlite3 *db; int i; char* errmsg = NULL; diff --git a/tools/generator.cc b/tools/generator.cc deleted file mode 100644 index de8528a9e..000000000 --- a/tools/generator.cc +++ /dev/null @@ -1,454 +0,0 @@ -/* -linphone -Copyright (C) 2013 Belledonne Communications SARL -Simon Morlat (simon.morlat@linphone.org) - -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. -*/ - - -#include - -#include "generator.hh" - -#ifdef _WIN32 -#include - -#define strncasecmp _strnicmp -#endif - - -string to_lower(const string &str){ - string res=str; - for(string::iterator it=res.begin();it!=res.end();++it){ - *it=tolower(*it); - } - return res; -} - -CplusplusGenerator::CplusplusGenerator(){ -} - -void CplusplusGenerator::generate(Project *proj){ - list classes=proj->getClasses(); - mCurProj=proj; -#ifndef _WIN32 - mkdir(proj->getName().c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH); -#else - _mkdir(proj->getName().c_str()); -#endif - for_each(classes.begin(),classes.end(),bind1st(mem_fun(&CplusplusGenerator::writeClass),this)); -} - -void CplusplusGenerator::writeEnumMember(ConstField *cf, bool isLast){ - writeTabs(1); - mOutfile<getName()<<"="<getValue(); - if (!isLast) mOutfile<<","; - if (!cf->getHelp().empty()) mOutfile<<"\t/**< "<getHelp()<<" */"; - mOutfile<getName()<<"/"<getName()<<".hh"; - mOutfile.open(filename.str().c_str()); - if (!mOutfile.is_open()){ - cerr<<"Could not write into "< methods=klass->getMethods(); - list constFields=klass->getConstFields(); - mCurClass=klass; - mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<"<getName().empty()) - mOutfile<<"namespace "<getName()<<"{"<getType()==Type::Enum){ - mOutfile<<"enum "<getName()<<"{"<::iterator cfit,next; - for (cfit=constFields.begin();cfit!=constFields.end();){ - ConstField *cf=*cfit; - writeEnumMember(cf,++cfit==constFields.end()); - } - }else{ - mOutfile<<"class "<getName()<<"{"<getName().empty()) - mOutfile<<"} //end of namespace "<getName()<getType(); - - if (type->getBasicType()==Type::Class){ - if (arg->isConst()){ - mOutfile<<"const "; - } - mOutfile<getName(); - if (arg->isPointer()) - mOutfile<<"*"; - }else if (type->getBasicType()==Type::Integer){ - mOutfile<<"int"; - }else if (type->getBasicType()==Type::Enum){ - mOutfile<getName(); - }else if (type->getBasicType()==Type::String){ - if (!isReturn) - mOutfile<<"const std::string &"; - else - mOutfile<<"std::string"; - }else if (type->getBasicType()==Type::Void){ - mOutfile<<"void"; - }else if (type->getBasicType()==Type::Boolean){ - mOutfile<<"bool"; - } - if (!isReturn && !arg->getName().empty()) - mOutfile<<" "<getName(); -} - -void CplusplusGenerator::writeTabs(int ntabs){ - int i; - for(i=0;i100 && comment[i]==' ')){ - mOutfile<isCallback()) return; - - Argument *retarg=method->getReturnArg(); - const list &args=method->getArgs(); - list::const_iterator it; - - writeTabs(1); - mOutfile<<"/**"<getHelp(),1); - mOutfile<getName()<<"("; - - for(it=args.begin();it!=args.end();++it){ - if (it!=args.begin()) mOutfile<<", "; - writeArgument(*it); - } - mOutfile<<")"; - if (method->isConst()) mOutfile<<"const"; - mOutfile<<";"< classes=proj->getClasses(); - mCurProj=proj; -#ifndef _WIN32 - remove(to_lower(proj->getName()).c_str()); - mkdir(to_lower(proj->getName()).c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH); -#else - _mkdir(to_lower(proj->getName()).c_str()); -#endif - ostringstream filename; - - /*write a file for the namespace*/ - filename<getName())<<"/"<getName())<<".js"; - mOutfile.open(filename.str().c_str()); - if (!mOutfile.is_open()){ - cerr<<"Could not write into "<getName()<getName()<<" = {};"<getName(); - if (strncasecmp(enum_name.c_str(),mCurProj->getName().c_str(),mCurProj->getName().size())==0){ - //since enum is part of the namespace, drop the namespace part of the enum if any. - enum_name.erase(0,mCurProj->getName().size()); - } - return enum_name; -} - -void JavascriptGenerator::writeEnum(Class *klass){ - if (klass->getType()!=Type::Enum) return; - - ostringstream filename; - list members=klass->getConstFields(); - list::iterator it; - string enum_name=getEnumName(klass); - - filename<getName())<<"/"<getName()<<" = "<getName()<<" || {};"<getHelp(),0); - mOutfile<getName()<<"."<getHelp().empty()){ - writeTabs(1); - mOutfile<<"/**"<getHelp(),1); - mOutfile<getName().substr(prefix_size,string::npos)<<" : "<getValue(); - if (++it!=members.end()) mOutfile<<","; - mOutfile<getName() << ".get" << enum_name << "Text = function(value) {" << endl; - mOutfile << "\tswitch (value) {" << endl; - for (it = members.begin(); it != members.end(); it++) { - ConstField *cf = *it; - mOutfile << "\tcase " << mCurProj->getName() << "." << enum_name << "." << cf->getName().substr(prefix_size, string::npos) << ":" << endl; - mOutfile << "\t\treturn \"" << cf->getName().substr(prefix_size, string::npos) << "\";" << endl; - } - mOutfile << "\tdefault:" << endl; - mOutfile << "\t\treturn \"?\";" << endl; - mOutfile << "\t}" << endl; - mOutfile << "};" << endl; - - mOutfile.close(); -} - -void JavascriptGenerator::writeClass(Class *klass){ - ostringstream filename; - - if (klass->getType()==Type::Enum) { - return; - } - const list &methods=klass->getMethods(); - if (methods.empty()) return;//skip empty classes - - filename<getName())<<"/"<getName())<<".js"; - mOutfile.open(filename.str().c_str()); - if (!mOutfile.is_open()){ - cerr<<"Could not write into "<getName().empty()) - // mOutfile<<"namespace "<getName()<<"{"<getHelp()<getName()< properties=klass->getProperties(); - for_each(properties.begin(),properties.end(),bind1st(mem_fun(&JavascriptGenerator::writeProperty),this)); - mOutfile<getName().empty()) - // mOutfile<<"} //end of namespace "<getName()<getBasicType()){ - case Type::Float: - case Type::Integer: - mOutfile<<"number"; - break; - case Type::String: - mOutfile<<"string"; - break; - case Type::Boolean: - mOutfile<<"boolean"; - break; - case Type::Class: - mOutfile<<"external:"<getName(); - break; - case Type::Enum: - mOutfile<getName()<<"."<getClass(type->getName())); - break; - case Type::Void: - mOutfile<<"void"; - break; - case Type::Callback: - break; - case Type::Array: - mOutfile<<"Array."; - break; - } -} - -void JavascriptGenerator::writeArgument(Argument *arg, ArgKind kind){ - switch(kind){ - case Normal: - mOutfile<<" * @param {"; - writeType(arg->getType()); - mOutfile<<"} "<getName()<<" - "<getHelp()<getType()); - mOutfile<<"} "<getHelp()<getType()); - mOutfile<<"} "<getName()<<" - "<getHelp()<100 && comment[i]==' ')){ - mOutfile<getName()=="userData" || prop->getName()=="userPointer") return; - mOutfile<<"/**"<getHelp(),0); - mOutfile<getType()); - mOutfile<<"} external:"<getName()<<"#"<getName()<getAttribute()==Property::ReadOnly) - mOutfile<<" * @readonly"<getReturnArg(); - const list &args=method->getArgs(); - list::const_iterator it; - - if (method->isCallback()) return; - if (method->getPropertyBehaviour()!=Method::None) return; - if (method->getName()=="ref" || method->getName()=="unref") return; - - mOutfile<<"/**"<getHelp(),0); - mOutfile<getName()<<"#"<getName()< &args=event->getArgs(); - list::const_iterator it; - - if (!event->isCallback()) return; - mOutfile<<"/**"<getHelp()),0); - mOutfile<getName()<<"#"<getName()< - -#include "software-desc.hh" - -class OutputGenerator{ -public: - virtual void generate(Project *proj)=0; -}; - -class CplusplusGenerator : public OutputGenerator{ -public: - CplusplusGenerator(); - virtual void generate(Project *proj); -private: - void writeClass(Class *klass); - void writeArgument(Argument *arg, bool isReturn=false); - void writeTabs(int ntabs); - void writeHelpComment(const std::string &comment, int ntabs); - void writeMethod(Method *method); - void writeEnumMember(ConstField *cf, bool isLast); - ofstream mOutfile; - Project *mCurProj; - Class *mCurClass; -}; - -class JavascriptGenerator : public OutputGenerator{ -public: - JavascriptGenerator(); - virtual void generate(Project *proj); -private: - void writeClass(Class *klass); - void writeEnum(Class *klass); - void writeType(Type *type); - enum ArgKind { Normal, Return, PropertyArg}; - void writeArgument(Argument *arg, ArgKind kind=Normal); - void writeTabs(int ntabs); - void writeHelpComment(const std::string &comment, int ntabs); - void writeProperty(Property *prop); - void writeMethod(Method *method); - void writeEvent(Method *event); - string getEventHelp(const string &ref); - string getEnumName(Class *klass); - ofstream mOutfile; - Project *mCurProj; - Class *mCurClass; -}; - -string to_lower(const string &str); - -#endif diff --git a/tools/genwrappers.cc b/tools/genwrappers.cc deleted file mode 100644 index d55f3dc6f..000000000 --- a/tools/genwrappers.cc +++ /dev/null @@ -1,482 +0,0 @@ -/* -linphone -Copyright (C) 2013 Belledonne Communications SARL -Simon Morlat (simon.morlat@linphone.org) - -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. -*/ - -#include "software-desc.hh" -#include "generator.hh" - -#include -#include -#include -#include -#include -#include - - - -static bool isSpace(const char *str){ - for(;*str!='\0';++str){ - if (!isspace(*str)) return false; - } - return true; -} - -//Convenient class for examining node recursively -class XmlNode{ -public: - XmlNode(const xmlNode *node=NULL) : mNode(node){ - } - XmlNode getChild(const string &name)const{ - if (mNode==NULL) return XmlNode(); - xmlNode *it; - for(it=mNode->children;it!=NULL;it=it->next){ - if (xmlStrcmp(it->name,(const xmlChar*)name.c_str())==0) - return XmlNode(it); - } - return XmlNode(); - } - XmlNode getChildRecursive(const string &name)const{ - if (mNode==NULL) return XmlNode(); - xmlNode *it; - //find in direct children - for(it=mNode->children;it!=NULL;it=it->next){ - if (xmlStrcmp(it->name,(const xmlChar*)name.c_str())==0) - return XmlNode(it); - } - //recurse into children - for(it=mNode->children;it!=NULL;it=it->next){ - XmlNode res=XmlNode(it).getChildRecursive(name); - if (!res.isNull()) return res; - } - return XmlNode(); - } - list getChildren(const string &name)const{ - xmlNode *it; - list nodes; - - if (mNode==NULL) return nodes; - for(it=mNode->children;it!=NULL;it=it->next){ - if (xmlStrcmp(it->name,(const xmlChar*)name.c_str())==0) - nodes.push_back(XmlNode(it)); - } - if (nodes.empty()) cerr<<"getChildren() no "<content; - if (!isSpace(text)) return string(text); - } - return ""; - } - string getProp(const string &propname)const{ - if (mNode==NULL) return ""; - xmlChar *value; - value=xmlGetProp((xmlNode*)mNode,(const xmlChar*)propname.c_str()); - if (value) return string((const char*)value); - return ""; - } - bool isNull()const{ - return mNode==NULL; - } -private: - const xmlNode *mNode; -}; - -static Argument *parseArgument(XmlNode node, bool isReturn){ - string name=node.getChild("declname").getText(); - Type *type=NULL; - string typecontent=node.getChild("type").getText(); - bool isConst=false; - bool isPointer=false; - - //find documented type if any - string tname=node.getChild("type").getChild("ref").getText(); - if (!tname.empty()){ - type=Type::getType(tname); - }else type=Type::getType(typecontent); - - //find const attribute if any - if (typecontent.find("const")!=string::npos) - isConst=true; - - if (typecontent.find("*")!=string::npos) - isPointer=true; - - if (type==NULL) { - return NULL; - } - //cout<<"Parsed argument "<getBasicType()<<" "<getName()<0) - useUpper=true; - }else{ - if (useUpper) - *w++=toupper(p); - else - *w++=p; - useUpper=false; - } - } - *w++='\0'; - string ret(tmp); - delete[] tmp; - return ret; -} - -static string extractMethodName(const string &c_name, const std::string& class_name){ - string prefix=classNameToPrefix(class_name); - if (c_name.find(prefix)==0){ - return makeMethodName(c_name.substr(prefix.size(),string::npos)); - } - return ""; -} - -static string getHelpBody(XmlNode myNode){ - ostringstream result; - XmlNode brief=myNode.getChild("briefdescription"); - XmlNode detailed=myNode.getChild("detaileddescription"); - - result< args; - string help; - XmlNode funcnode(node); - XmlNode parameterlist; - list params; - list paramsHelp; - list::iterator it,helpit; - - name=funcnode.getChild("name").getText(); - params=funcnode.getChildren("param"); - parameterlist=funcnode.getChild("detaileddescription").getChildRecursive("parameterlist"); - if (parameterlist.isNull()) cerr<<"parameterlist not found"<setHelp(item.getChild("parameterdescription").getChild("para").getText()); - }else cerr<<"Undocumented parameter "<getName()<<" in function "<getType()->getBasicType()!=Type::Class) return; - className=first_arg->getType()->getName(); - methodName=extractMethodName(name,className); - if (!methodName.empty() && methodName!="destroy"){ - //cout<<"Found "<isConst(),false); - method->setHelp(help); - proj->getClass(className)->addMethod(method); - delete first_arg; - } -} - -static string findCommon(const string &c1, const string & c2){ - size_t i; - ostringstream res; - for(i=0;i params=node.getChildRecursive("parameterlist").getChildren("parameteritem"); - list::iterator it=params.begin(); - string rettype=node.getChild("type").getText(); - argsstring=argsstring.substr(argsstring.find('(')+1,string::npos); - bool cont=true; - list args; - Type *firstArgType=NULL; - - rettype=rettype.substr(0,rettype.find('(')); - Argument *retarg=new Argument(Type::getType(rettype),"",false,rettype.find('*')!=string::npos); - - do{ - size_t comma=argsstring.find(','); - size_t end=argsstring.find(')'); - if (comma!=string::npos && commasetHelp((*it).getChild("parameterdescription").getChild("para").getText()); - ++it; - } - args.push_back(argobj); - }while(cont); - - if (firstArgType->getBasicType()!=Type::Class) return; - Class *klass=proj->getClass(firstArgType->getName()); - Method *callback=new Method("", retarg, extractCallbackName(name,klass->getName()), args, false, false, true); - //cout<<"Found callback "<getName()<<" with "<setHelp(node.getChild("detaileddescription").getChild("para").getText()); - klass->addMethod(callback); - - -} - -static void parseEnum(Project *proj, XmlNode node){ - string name=node.getChild("name").getText(); - if (name[0]=='_') name.erase(0,1); - Class *klass=proj->getClass(name); - klass->setHelp(node.getChild("detaileddescription").getChild("para").getText()); - list enumValues=node.getChildren("enumvalue"); - list::iterator it; - int value = 0; - for (it=enumValues.begin();it!=enumValues.end();++it){ - string initializer = (*it).getChild("initializer").getText(); - if ((initializer.length() > 1) && (initializer.at(0) == '=')) { - std::stringstream ss; - if ((initializer.length() > 2) && (initializer.at(1) == '0')) { - if ((initializer.length() > 3) && (initializer.at(2) == 'x')) { - ss << std::hex << initializer.substr(3); - } else { - ss << std::oct << initializer.substr(2); - } - } else { - ss << std::dec << initializer.substr(1); - } - ss >> value; - } - ConstField *cf=new ConstField(Type::getType("int"),(*it).getChild("name").getText(),value); - cf->setHelp((*it).getChild("detaileddescription").getChild("para").getText()); - klass->addConstField(cf); - value++; - } - -} - -static void parseTypedef(Project *proj, xmlNode *node){ - XmlNode tdef(node); - string typecontent=tdef.getChild("type").getText(); - string name=tdef.getChild("name").getText(); - if (typecontent.find("enum")==0){ - Type::addType(Type::Enum,name); - }else if (typecontent.find("(*")!=string::npos){ - parseCallback(proj,node); - }else - proj->getClass(name)->setHelp(getHelpBody(node)); -} - -static void parseMemberDef(Project *proj, xmlNode *node){ - XmlNode member(node); - string brief; - string detailed; - string kind; - - if (member.getChild("briefdescription").getText().empty() && - member.getChild("detaileddescription").getChild("para").getText().empty()) - return; - if (member.getProp("id").find("group__")!=0) - return; - if (member.getChild("detaileddescription").getChildRecursive("xreftitle").getText()=="Deprecated") - return; - - kind=member.getProp("kind"); - if (kind=="function"){ - parseFunction(proj,node); - }else if (kind=="typedef"){ - parseTypedef(proj,node); - }else if (kind=="enum"){ - parseEnum(proj,node); - } -} - -static void inspectNode(Project *proj, xmlNode *a_node){ - xmlNode *cur_node; - - for (cur_node = a_node; cur_node != NULL ; cur_node = cur_node->next) { - if (cur_node->type == XML_ELEMENT_NODE) { - //printf("node type: Element, name: %s\n", cur_node->name); - if (strcmp((const char*)cur_node->name,"memberdef")==0 ){ - //cout<<"Found memberdef"<children) inspectNode(proj,cur_node->children); - } -} - -static int parse_file(Project *proj, const char *filename){ - xmlDoc *doc = NULL; - xmlNode *root_element = NULL; - - - /*parse the file and get the DOM */ - doc = xmlReadFile(filename, NULL, XML_PARSE_RECOVER); - - if (doc == NULL) { - cerr<<"xmlReadFile failed."< files; - list::iterator it; - - LIBXML_TEST_VERSION - - for(i=1;i file1 file2...\nParses xml files generated by doxygen to output wrappers in a specified language.\n",argv[0]); - return -1; - }else if (strcmp(argv[i],"--output")==0){ - i++; - if (strcmp(argv[i],"c++")==0){ - gen=new CplusplusGenerator(); - }else if (strcmp(argv[i],"javascript")==0){ - gen=new JavascriptGenerator(); - } - }else if (strcmp(argv[i],"--project")==0){ - i++; - projectName=argv[i]; - }else{ - files.push_back(argv[i]); - } - } - - if (gen==NULL) { - cerr<<"No output generator selected !"<analyse(); - gen->generate(proj); - return 0; -} diff --git a/tools/software-desc.cc b/tools/software-desc.cc deleted file mode 100644 index 7cf96ac48..000000000 --- a/tools/software-desc.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* -linphone -Copyright (C) 2013 Belledonne Communications SARL -Simon Morlat (simon.morlat@linphone.org) - -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. -*/ - -#include "software-desc.hh" - -Type Type::sStringType(Type::String); -Type Type::sIntegerType(Type::Integer); -Type Type::sVoidType(Type::Void); -Type Type::sBooleanType(Type::Boolean); -Type Type::sFloatType(Type::Float); -Type Type::sArrayType(Type::Array); - -std::map Type::mTypes; -const char *Type::sBasicTypeNames[]={ - "Void", - "Boolean", - "Integer", - "Float", - "String", - "Enum", - "Class", - "Callback", - "Array", - "undef", - "undef" -}; diff --git a/tools/software-desc.hh b/tools/software-desc.hh deleted file mode 100644 index c20b22425..000000000 --- a/tools/software-desc.hh +++ /dev/null @@ -1,470 +0,0 @@ -/* -linphone -Copyright (C) 2013 Belledonne Communications SARL -Simon Morlat (simon.morlat@linphone.org) - -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. -*/ - -#ifndef software_desc_hh -#define software_desc_hh - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - - -class Type{ -public: - enum BasicType{ - Void, - Boolean, - Integer, - Float, - String, - Enum, - Class, - Callback, - Array - }; - static const char *sBasicTypeNames[]; - static Type* addType(BasicType bt, const std::string &name){ - Type* ret; - if ((ret=mTypes[name])==0){ - //cout<<"Adding new "<mBasic=bt; - } - return ret; - } - static Type *getType(const std::std::string &tname){ - if (tname.find("(")!=std::string::npos) return NULL; //arrives when parsing function pointer declared inside function prototype - if (strstr(tname.c_str(),"char")!=0 && strchr(tname.c_str(),'*')!=0){ - return &sStringType; - }else if (tname.find("int")!=std::string::npos){ - return &sIntegerType; - }else if (tname.find("size_t")!=std::string::npos){ - return &sIntegerType; - }else if (tname.find("float")!=std::string::npos){ - return &sFloatType; - }else if (tname.find("bool_t")!=std::string::npos){ - return &sBooleanType; - }else if (tname.find("void")!=std::string::npos){ - return &sVoidType; - }else if (tname.find("enum")!=std::string::npos){ - return addType(Enum,tname.c_str()+strlen("enum ")); - }else if (tname.find("MSList")!=std::string::npos){ - return &sArrayType; - }else{/*an object?*/ - - std::string tmp=tname; - size_t pos; - - /*really ugly and slow*/ - - pos=tmp.find('*'); - if (pos!=std::string::npos) - tmp.erase(pos,1); - - pos=tmp.find("const"); - if (pos!=std::string::npos) - tmp.erase(pos,strlen("const")); - - while ((pos=tmp.find(' '))!=std::string::npos){ - tmp.erase(pos,1); - } - return addType(Class,tmp); - } - std::cerr<<"Unhandled type name"< mTypes; -}; - - - -class Argument{ -public: - Argument(Type *type, const std::string &argname, bool isConst, bool isPointer) : mType(type), mName(argname), mConst(isConst), mPointer(isPointer){ - if (!isPointer) mConst=false; - } - Type *getType()const{ - return mType; - } - bool isConst()const{ - return mConst; - } - const std::string &getName()const{ - return mName; - } - bool isPointer()const{ - return mPointer; - } - const std::string &getHelp()const{ - return mHelp; - } - void setHelp(const std::string &help){ - mHelp=help; - } -private: - - Type *mType; - std::string mName; - std::string mHelp; - bool mConst; - bool mPointer; -}; - -class Method{ -public: - enum PropertyBehaviour{ - None, - Read, - Write - }; - Method(const std::string &uid, Argument* return_arg, const std::string &name, const list &args, bool isConst, bool isStatic, bool isCallback=false){ - mUid=uid; - mReturn=return_arg; - mName=name; - mArgs=args; - mConst=isConst; - mStatic=isStatic; - mIsCallback=isCallback; - analyseProperties(); - } - void setHelp(const std::string &help){ - mHelp=help; - } - Argument *getReturnArg()const{ - return mReturn; - } - const string &getName()const{ - return mName; - } - const list &getArgs()const { - return mArgs; - } - bool isConst()const{ - return mConst; - } - bool isStatic()const{ - return mStatic; - } - bool isCallback()const{ - return mIsCallback; - } - const string &getHelp(){ - return mHelp; - } - PropertyBehaviour getPropertyBehaviour()const{ - return mPropertyBehaviour; - } - const string &getPropertyName()const{ - return mPropertyName; - } -private: - void analyseProperties(){ - size_t enabled_pos; - mPropertyBehaviour=None; - - if (mName.find("get")==0 && mArgs.size()==0){ - mPropertyName=mName.substr(3,string::npos); - if (!mPropertyName.empty()){ - mPropertyName[0]=tolower(mPropertyName[0]); - mPropertyBehaviour=Read; - } - }else if (mName.find("is")==0 && mArgs.size()==0){ - mPropertyName=mName.substr(2,string::npos); - if (!mPropertyName.empty()){ - mPropertyName[0]=tolower(mPropertyName[0]); - mPropertyBehaviour=Read; - } - }else if (mName.find("enable")==0 && mArgs.size()==1){ - mPropertyName=mName.substr(6,string::npos); - if (!mPropertyName.empty()){ - mPropertyName[0]=tolower(mPropertyName[0]); - mPropertyName+="Enabled"; - mPropertyBehaviour=Write; - } - }else if (mName.find("set")==0 && mArgs.size()==1){ - mPropertyName=mName.substr(3,string::npos); - if (!mPropertyName.empty()){ - mPropertyName[0]=tolower(mPropertyName[0]); - mPropertyBehaviour=Write; - } - }else if ((enabled_pos=mName.rfind("Enabled"))!=string::npos && mArgs.size()==0){ - size_t goodpos=mName.size()-7; - if (enabled_pos==goodpos){ - mPropertyName=mName.substr(0,goodpos); - if (!mPropertyName.empty()){ - mPropertyName+="Enabled"; - mPropertyBehaviour=Read; - } - } - } - if (mPropertyBehaviour==None) { - mPropertyName=""; - if (mName.find("create")==0) { - mName="new"+mName.substr(6,string::npos); - } - } - } - string mUid; - Argument *mReturn; - string mName; - list mArgs; - string mHelp; - string mPropertyName; /*if it can be a property*/ - PropertyBehaviour mPropertyBehaviour; - bool mConst; - bool mStatic; - bool mIsCallback; -}; - -class Property{ -public: - enum Attribute{ - ReadOnly, - ReadWrite - }; - Property(Attribute attr, const string &name, Type *type, const string &help) : mAttr(attr), mName(name), mType(type), mHelp(help){ - } - const string &getName()const{ - return mName; - } - const string &getHelp()const{ - return mHelp; - } - void setHelp(const string &help){ - mHelp=help; - } - Attribute getAttribute()const{ - return mAttr; - } - void setAttribute(Attribute attr){ - mAttr=attr; - } - Type* getType()const{ - return mType; - } -private: - Attribute mAttr; - string mName; - Type *mType; - string mHelp; -}; - -class ConstField{ -public: - ConstField(Type *type, const string &name, int value) : mType(type), mName(name), mValue(value){ - } - void setHelp(const string & help){ - mHelp=help; - } - const string &getHelp()const{ - return mHelp; - } - const string & getName()const{ - return mName; - } - Type *getType()const{ - return mType; - } - int getValue()const{ - return mValue; - } - static string getCommonPrefix(list fields){ - if (fields.size()<2) return ""; - list::iterator it; - string prefix=fields.front()->getName(); - int prefixsize; - - for (prefixsize=prefix.size();prefixsize>0;prefixsize--){ - bool isMatching=true; - prefix=prefix.substr(0,prefixsize); - - for(it=fields.begin();it!=fields.end();++it){ - ConstField *cf=*it; - if (prefix != cf->getName().substr(0,prefixsize)){ - isMatching=false; - break; - } - } - if (isMatching){ - //cout<<"enum prefix: "< -struct name_matcher{ - name_matcher(const string &name) : mName(name){} - bool operator()(_type *cf){ - return cf->getName()==mName; - } - string mName; -}; - -/*actually a class or an enum*/ -class Class{ -public: - Class(const std::string &name): mName(name){ - } - Type::BasicType getType(){ - return Type::getType(mName)->getBasicType(); - } - void addMethod(Method *method){ - if (mMethods.find(method->getName())==mMethods.end()) - mMethods.insert(make_pair(method->getName(),method)); - } - void addConstField(ConstField *field){ - list::iterator it=find_if(mConstFields.begin(),mConstFields.end(),name_matcher(field->getName())); - if (it==mConstFields.end()) - mConstFields.push_back(field); - } - void setHelp(const std::string &help){ - mHelp=help; - } - list getMethods()const{ - list ret; - map::const_iterator it; - for(it=mMethods.begin();it!=mMethods.end();++it){ - ret.push_back((*it).second); - } - return ret; - } - const list &getConstFields()const{ - return mConstFields; - } - const string &getName()const{ - return mName; - } - const string &getHelp()const{ - return mHelp; - } - list getProperties(){ - list ret; - map::const_iterator it; - for(it=mProperties.begin();it!=mProperties.end();++it){ - ret.push_back((*it).second); - } - return ret; - } - void computeProperties(){ - map::const_iterator it; - Property *prop; - for (it=mMethods.begin();it!=mMethods.end();++it){ - Method *m=(*it).second; - if (m->getPropertyBehaviour()==Method::Read){ - prop=mProperties[m->getPropertyName()]; - if (prop==NULL){ - prop=new Property(Property::ReadOnly,m->getPropertyName(),m->getReturnArg()->getType(), m->getHelp()); - mProperties[m->getPropertyName()]=prop; - } - }else if (m->getPropertyBehaviour()==Method::Write){ - prop=mProperties[m->getPropertyName()]; - if (prop==NULL){ - prop=new Property(Property::ReadWrite,m->getPropertyName(),m->getArgs().front()->getType(), m->getHelp()); - mProperties[m->getPropertyName()]=prop; - }else{ - prop->setHelp(m->getHelp()); - prop->setAttribute(Property::ReadWrite); - } - } - } - } -private: - map mMethods; - map mProperties; - list mConstFields; - string mName; - string mHelp; -}; - -class Project{ -public: - Project(const string &name="wrapper") : mName(name){ - } - Class *getClass(const std::string &name){ - Class *ret; - if ((ret=mClasses[name])==NULL){ - ret=mClasses[name]=new Class(name); - } - return ret; - } - list getClasses()const{ - list ret; - map::const_iterator it; - for(it=mClasses.begin();it!=mClasses.end();++it){ - ret.push_back((*it).second); - } - return ret; - } - const string &getName()const{ - return mName; - } - void analyse(){ - list classes=getClasses(); - for_each(classes.begin(),classes.end(),mem_fun(&Class::computeProperties)); - } - void addCallback(Method *callback){ - list::iterator it=find_if(mCallbacks.begin(),mCallbacks.end(),name_matcher(callback->getName())); - if (it==mCallbacks.end()) - mCallbacks.push_back(callback); - } - const list &getCallbacks()const{ - return mCallbacks; - } -private: - map mClasses; - list mCallbacks; - string mName; -}; - -#endif diff --git a/wrappers/java/classes/tools/AndroidPlatformHelper.java b/wrappers/java/classes/tools/AndroidPlatformHelper.java index 34ba1445a..ab7c50d47 100644 --- a/wrappers/java/classes/tools/AndroidPlatformHelper.java +++ b/wrappers/java/classes/tools/AndroidPlatformHelper.java @@ -20,8 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. package org.linphone.core.tools; -import org.linphone.core.Core; -import org.linphone.core.Factory; import org.linphone.mediastream.Log; import org.linphone.mediastream.MediastreamerAndroidContext; import org.linphone.mediastream.Version; @@ -84,26 +82,19 @@ public class AndroidPlatformHelper { mWifiLock.setReferenceCounted(true); String basePath = mContext.getFilesDir().getAbsolutePath(); - mLinphoneRootCaFile = basePath + "/rootca.pem"; - mRingSoundFile = basePath + "/ringtone.mkv"; - mRingbackSoundFile = basePath + "/ringback.wav"; - mPauseSoundFile = basePath + "/hold.mkv"; - mErrorToneFile = basePath + "/error.wav"; - mGrammarCpimFile = basePath + "/cpim_grammar"; - mGrammarVcardFile = basePath + "/vcard_grammar"; + //make sur to follow same path as unix version of the sdk + mLinphoneRootCaFile = basePath + "/share/linphone/rootca.pem"; + mRingSoundFile = basePath + "/share/sounds/linphone/rings/notes_of_the_optimistic.mkv"; + mRingbackSoundFile = basePath + "/share/sounds/linphone/ringback.wav"; + mPauseSoundFile = basePath + "/share/sounds/linphone/rings/dont_wait_too_long.mkv"; + mErrorToneFile = basePath + "/share/sounds/linphone/incoming_chat.wav"; + mGrammarCpimFile = basePath + "/share/belr/grammars/cpim_grammar"; + mGrammarVcardFile = basePath + "/share/belr/grammars/vcard_grammar"; mUserCertificatePath = basePath; copyAssetsFromPackage(); } - public void initCore(long ptrLc) { - Core lc = Factory.instance().getCore(ptrLc); - if (lc == null) return; - lc.setRingback(mRingbackSoundFile); - lc.setRootCa(mLinphoneRootCaFile); - lc.setPlayFile(mPauseSoundFile); - lc.setUserCertificatesPath(mUserCertificatePath); - } public Object getPowerManager() { return mPowerManager; @@ -184,58 +175,44 @@ public class AndroidPlatformHelper { return resId; } - private void copyAssetsFromPackage() { - try { - copyEvenIfExists(getResourceIdentifierFromName("cpim_grammar"), mGrammarCpimFile); - } catch (Exception e) { - Log.e(e, "AndroidPlatformHelper: Cannot copy \"cpim_grammar\" from package."); - } - - try { - copyEvenIfExists(getResourceIdentifierFromName("vcard_grammar"), mGrammarVcardFile); - } catch (Exception e) { - Log.e(e, "AndroidPlatformHelper: Cannot copy \"vcard_grammar\" from package."); - } - - try { - copyEvenIfExists(getResourceIdentifierFromName("notes_of_the_optimistic"), mRingSoundFile); - } catch (Exception e) { - Log.e(e, "AndroidPlatformHelper: Cannot copy \"notes_of_the_optimistic\" from package."); - } - - try { - copyEvenIfExists(getResourceIdentifierFromName("ringback"), mRingbackSoundFile); - } catch (Exception e) { - Log.e(e, "AndroidPlatformHelper: Cannot copy \"ringback\" from package."); - } - - try { - copyEvenIfExists(getResourceIdentifierFromName("hold"), mPauseSoundFile); - } catch (Exception e) { - Log.e(e, "AndroidPlatformHelper: Cannot copy \"hold\" from package."); - } - - try { - copyEvenIfExists(getResourceIdentifierFromName("incoming_chat"), mErrorToneFile); - } catch (Exception e) { - Log.e(e, "AndroidPlatformHelper: Cannot copy \"incoming_chat\" from package."); - } - - try { - copyEvenIfExists(getResourceIdentifierFromName("rootca"), mLinphoneRootCaFile); - } catch (Exception e) { - Log.e(e, "AndroidPlatformHelper: Cannot copy \"rootca\" from package."); - } + private void copyAssetsFromPackage() throws IOException { + Log.i("Starting copy from assets to application files directory"); + copyAssetsFromPackage(mContext, "org.linphone.core","."); + Log.i("Copy from assets done"); + Log.i("Starting copy from legacy resources to application files directory"); + /*legacy code for 3.X*/ + copyEvenIfExists(getResourceIdentifierFromName("cpim_grammar"), mGrammarCpimFile); + copyEvenIfExists(getResourceIdentifierFromName("vcard_grammar"), mGrammarVcardFile); + copyEvenIfExists(getResourceIdentifierFromName("rootca"), mLinphoneRootCaFile); + copyEvenIfExists(getResourceIdentifierFromName("notes_of_the_optimistic"), mRingSoundFile); + copyEvenIfExists(getResourceIdentifierFromName("ringback"), mRingbackSoundFile); + copyEvenIfExists(getResourceIdentifierFromName("hold"), mPauseSoundFile); + copyEvenIfExists(getResourceIdentifierFromName("incoming_chat"), mErrorToneFile); + Log.i("Copy from legacy resources done"); } public void copyEvenIfExists(int ressourceId, String target) throws IOException { File lFileToCopy = new File(target); - copyFromPackage(ressourceId, lFileToCopy.getName()); + copyFromPackage(ressourceId, lFileToCopy); } - public void copyFromPackage(int ressourceId, String target) throws IOException{ - FileOutputStream lOutputStream = mContext.openFileOutput (target, 0); + public void copyIfNotExist(int ressourceId, String target) throws IOException { + File lFileToCopy = new File(target); + if (!lFileToCopy.exists()) { + copyFromPackage(ressourceId, lFileToCopy); + } + } + + public void copyFromPackage(int ressourceId, File target) throws IOException { + if (ressourceId == 0) { + Log.i("Resource identifier null for target ["+target.getName()+"]"); + return; + } + if (!target.getParentFile().exists()) + target.getParentFile().mkdirs(); + InputStream lInputStream = mResources.openRawResource(ressourceId); + FileOutputStream lOutputStream = new FileOutputStream(target); int readByte; byte[] buff = new byte[8048]; while (( readByte = lInputStream.read(buff)) != -1) { @@ -245,6 +222,34 @@ public class AndroidPlatformHelper { lOutputStream.close(); lInputStream.close(); } + + public static void copyAssetsFromPackage(Context ctx,String fromPath, String toPath) throws IOException { + new File(ctx.getFilesDir().getPath()+"/"+toPath).mkdir(); + + for (String f :ctx.getAssets().list(fromPath)) { + String current_name = fromPath+"/"+f; + String current_dest = toPath+"/"+f; + InputStream lInputStream; + try { + lInputStream = ctx.getAssets().open(current_name); + } catch (IOException e) { + //probably a dir + copyAssetsFromPackage(ctx,current_name,current_dest); + continue; + } + FileOutputStream lOutputStream = new FileOutputStream(new File(ctx.getFilesDir().getPath()+"/"+current_dest));//ctx.openFileOutput (fromPath+"/"+f, 0); + + + int readByte; + byte[] buff = new byte[8048]; + while (( readByte = lInputStream.read(buff)) != -1) { + lOutputStream.write(buff,0, readByte); + } + lOutputStream.flush(); + lOutputStream.close(); + lInputStream.close(); + } + } }; diff --git a/wrappers/java/classes/tools/Lpc2Xml.java b/wrappers/java/classes/tools/Lpc2Xml.java deleted file mode 100644 index 04bc6c5a2..000000000 --- a/wrappers/java/classes/tools/Lpc2Xml.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.linphone.core.tools; - -import org.linphone.core.Config; -import org.linphone.mediastream.Log; - -public class Lpc2Xml { - - private enum LogLevel { - DEBUG, - MESSAGE, - WARNING, - ERROR, - } - - private static boolean mAvailable; - - private long internalPtr = 0; - - private native void init(); - private native void destroy(); - - public Lpc2Xml() { - init(); - } - - public void finalize() { - destroy(); - } - - public native int setLpc(Config lpc); - - public native int convertFile(String file); - public native int convertString(StringBuffer content); - - public void printLog(int level, String message) { - if(level > 0 && level < LogLevel.values().length) { - switch(LogLevel.values()[level]) { - case DEBUG: - Log.d(message); - break; - case MESSAGE: - Log.i(message); - break; - case WARNING: - Log.w(message); - break; - case ERROR: - Log.e(message); - break; - } - } - } - - static boolean isAvailable() { - return mAvailable; - } - - // Load library - static { - try { - System.loadLibrary("xml2"); - //System.loadLibrary("lpc2xml"); - mAvailable = true; - } catch (Throwable e) { - mAvailable = false; - } - } -} diff --git a/wrappers/java/classes/tools/Xml2Lpc.java b/wrappers/java/classes/tools/Xml2Lpc.java deleted file mode 100644 index b805750ec..000000000 --- a/wrappers/java/classes/tools/Xml2Lpc.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.linphone.core.tools; - -import org.linphone.core.Config; -import org.linphone.mediastream.Log; - -public class Xml2Lpc { - - private enum LogLevel { - DEBUG, - MESSAGE, - WARNING, - ERROR - } - - private static boolean mAvailable; - - private long internalPtr = 0; - - private native void init(); - private native void destroy(); - - public Xml2Lpc() { - init(); - } - - public void finalize() { - destroy(); - } - - public native int setXmlFile(String filename); - public native int setXmlString(String content); - - public native int setXsdFile(String filename); - public native int setXsdString(String content); - - public native int validate(); - public native int convert(Config config); - - public void printLog(int level, String message) { - if(level > 0 && level < LogLevel.values().length) { - switch(LogLevel.values()[level]) { - case DEBUG: - Log.d(message); - break; - case MESSAGE: - Log.i(message); - break; - case WARNING: - Log.w(message); - break; - case ERROR: - Log.e(message); - break; - } - } - } - - public static boolean isAvailable() { - return mAvailable; - } - - // Load library - static { - try { - new Xml2Lpc(); - //System.loadLibrary("xml2"); - //System.loadLibrary("xml2lpc"); - mAvailable = true; - } catch (Throwable e) { - mAvailable = false; - } - } -} diff --git a/wrappers/java/jni.mustache b/wrappers/java/jni.mustache index e226d5c68..549669a6f 100644 --- a/wrappers/java/jni.mustache +++ b/wrappers/java/jni.mustache @@ -283,9 +283,8 @@ static inline void handle_possible_java_exception(JNIEnv *env, jobject listener) {{#callbacks}} static {{return}} {{callbackName}}({{params}}) { - JNIEnv *env = 0; - jint jvmResult = jvm->AttachCurrentThread(&env,NULL); - if (jvmResult != 0) { + JNIEnv *env = ms_get_jni_env(); + if (!env) { ms_error("cannot attach VM"); return{{returnIfFail}}; } diff --git a/wrappers/java/migration.sh b/wrappers/java/migration.sh old mode 100644 new mode 100755 index 86dd25bc2..98e4286ff --- a/wrappers/java/migration.sh +++ b/wrappers/java/migration.sh @@ -49,8 +49,8 @@ s/TransportType.LinphoneTransportUdp/TransportType.Udp/g; \ s/TransportType.LinphoneTransportTcp/TransportType.Tcp/g; \ s/TransportType.LinphoneTransportTls/TransportType.Tls/g; \ s/TransportType.LinphoneTransportDtls/TransportType.Dtls/g; \ -s/AddressFamily.INET_6.getInt()/AddressFamily.Inet6.toInt()/g; \ -s/AddressFamily.INET.getInt()/AddressFamily.Inet.toInt()/g; \ +s/AddressFamily.INET_6.getInt()/AddressFamily.Inet6/g; \ +s/AddressFamily.INET.getInt()/AddressFamily.Inet/g; \ s/LpConfig/Config/g; \ s/LinphoneCoreException/CoreException/g; \ s/LinphoneCoreFactory/Factory/g; \ @@ -148,6 +148,9 @@ s/getFriendLists()/getFriendsLists()/g; \ s/getFriendList(/getFriendsLists(/g; \ s/getIdentity(/getIdentityAddress(/g; \ s/isTunnelAvailable()/tunnelAvailable()/g; \ +s/tunnelSetMode(/getTunnel().setMode(/g; \ +s/tunnelAddServer(/getTunnel().addServer(/g; \ +s/tunnelCleanServers(/getTunnel().cleanServers(/g; \ s/setZrtpSecretsCache(/setZrtpSecretsFile(/g; \ s/setRootCA(/setRootCa(/g; \ s/isInComingInvitePending()/isIncomingInvitePending()/g; \ @@ -167,7 +170,7 @@ s/isIncall()/inCall()/g; \ s/setVideoEnabled(/enableVideo(/g; \ s/setAudioBandwidth(/setAudioBandwidthLimit(/g; \ s/isAuthenticationTokenVerified()/getAuthenticationTokenVerified()/g; \ -s/isMicMuted()/!micEnabled()/g; \ +s/\(\s*\)\([a-zA-Z()\.]*\)isMicMuted()/\1!\2micEnabled()/g; \ s/isLowBandwidthEnabled()/lowBandwidthEnabled()/g; \ s/muteMic(/enableMic(!/g; \ s/getRate()/getClockRate()/g; \ @@ -229,16 +232,17 @@ s/getIncomingTimeout/getIncTimeout/g; \ s/setIncomingTimeout/setIncTimeout/g; \ s/migrateCallLogs()/migrateLogsFromRcToDb()/g; \ s/setRLSUri/setRlsUri/g; \ -s/hasCrappyOpenGL(/hasCrappyOpenGl(/g; \ +s/hasCrappyOpenGL(/hasCrappyOpengl(/g; \ s/needsEchoCalibration(/isEchoCancellerCalibrationRequired(/g; \ s/getCountryCode()/getCountryCallingCode()/g; \ s/isEchoCancellationEnabled()/echoCancellationEnabled()/g; \ s/startEchoCalibration(/startEchoCancellerCalibration(/g; \ s/.isRegistered()/.getState() == RegistrationState.Ok/g; \ -s/isInConference()/(getConference() != null)/g; \ +s/\(\s*\)\([a-zA-Z()\.]*\)isInConference()/\1\2getConference() != null/g; \ s/getAudioStats()/getStats(StreamType.Audio)/g; \ s/getVideoStats()/getStats(StreamType.Video)/g; \ s/getVcardToString()/getVcard().asVcard4String()/g; \ +s/getVideoAutoAcceptPolicy(/getVideoActivationPolicy().getAutomaticallyAccept(/g; \ s/getVideoAutoInitiatePolicy()/getVideoActivationPolicy().getAutomaticallyInitiate()/g; \ s/setFamilyName(/getVcard().setFamilyName(/g; \ s/setGivenName(/getVcard().setGivenName(/g; \ @@ -247,9 +251,9 @@ s/getFamilyName()/getVcard().getFamilyName()/g; \ s/getGivenName()/getVcard().getGivenName()/g; \ s/\.getOrganization()/\.getVcard().getOrganization()/g; \ s/enableAvpf(/setAvpfMode(AVPFMode.Enabled)/g; \ -s/transports.udp = /transports.setUdpPort(/g; \ -s/transports.tcp = /transports.setTcpPort(/g; \ -s/transports.tls = /transports.setTlsPort(/g; \ +s/transports.udp\s*=\s*\([a-zA-Z0-9_]*\)/transports.setUdpPort(\1)/g; \ +s/transports.tcp\s*=\s*\([a-zA-Z0-9_]*\)/transports.setTcpPort(\1)/g; \ +s/transports.tls\s*=\s*\([a-zA-Z0-9_]*\)/transports.setTlsPort(\1)/g; \ s/transports.udp/transports.getUdpPort()/g; \ s/transports.tcp/transports.getTcpPort()/g; \ s/transports.tls/transports.getTlsPort()/g; \ @@ -271,7 +275,10 @@ s/linkPhoneNumberWithAccount()/linkAccount()/g; \ s/zoomVideo(/zoom(/g; \ s/mLc.setCpuCount(/\/\/mLc.setCpuCount(/g; \ s/new XmlRpcRequestImpl(/xmlRpcSession.createRequest(/g; \ -s/new XmlRpcSessionImpl(LinphoneManager.getLcIfManagerNotDestroyedOrNull(), /LinphoneManager.getLcIfManagerNotDestroyedOrNull().createXmlRpcSession(/g;" {} \; +s/new XmlRpcSessionImpl(LinphoneManager.getLcIfManagerNotDestroyedOrNull(), /LinphoneManager.getLcIfManagerNotDestroyedOrNull().createXmlRpcSession(/g; \ +s/FriendImpl/Friend/g; \ +s/PresenceActivityType/PresenceActivity.Type/g; \ +s/org\.linphone\.core\.VideoSize/org.linphone.core.VideoDefinition/g;" {} \; # 2nd pass find ./src/android/org/linphone/ -type f -exec sed -i -e "s/Address\.TransportType/TransportType/g; \ @@ -286,47 +293,80 @@ s/Core\.LimeState/LimeState/g; \ s/Core\.LogCollectionState/LogCollectionState/g; \ s/Core\.MediaEncryption/MediaEncryption/g; \ s/Core\.RegistrationState/RegistrationState/g; \ +s/Core\.TunnelMode/Tunnel.Mode/g; \ s/Core\.VersionUpdateCheckResult/VersionUpdateCheckResult/g; \ s/Event\.PublishState/PublishState/g; \ s/Friend\.SubscribePolicy/SubscribePolicy/g; \ s/XmlRpcRequest\.ArgType/XmlRpcArgType/g; \ -s/XmlRpcRequest\.Status/XmlRpcStatus/g;" {} \; +s/XmlRpcRequest\.Status/XmlRpcStatus/g; \ +s/org\.linphone\.core\.PresenceActivity\.Type/org.linphone.core.PresenceActivity/g;" {} \; -# TODO -#Tunnel, TunnelConfig -#AccountCreator.updatePassword => What to do ? -# Manual changes required +# Manual changes required: +# # Some callbacks no longer exist, their name will be "removed", remove them -# Above sed commands will create erros in syntax you need to manually fix: -# # !micEnabled() -# # (getConference() != null) -# # (AVPFMode.Enabled) -# # (port; +# +# This script may create build errors in your application, especially if you defined methods that have the same name as methods +# of the linphone SDK. For example, with the Linphone application we get errors for the enableAVPF(int n, boolean enabled) method of +# LinphonePreferences that is wrongly replaced into setAVPFMode(AVPFMode.Enabled)int n, boolean enabled). +# +# You may need to import some classes, eg. AccountCreatorListener, AVPFMode, Call, ChatMessageListener, ConfiguringState, LimeState, +# MediaEncryption, RegistrationState, StreamType, VideoDefinition, XmlRpcArgType... +# +# If you are using the LinphoneContact class, some getVcard() method may have been wrongly introduced by this script that you will need +# to delete. +# # Some methods that used to take or return String or LinphoneAddress now take the other -# createAddress, addAddress, addFriend, acceptCall, acceptCallWithParams no longer throws a CoreException +# +# createAddress, addAddress, addFriend, acceptCall, acceptCallWithParams no longer throw a CoreException +# # AccountCreator's Status.Ok must be renamed in Status.RequestOk +# # VideoDevices were int, now are String +# # XmlRpcSessionImpl => XmlRpcSession +# # getFriendsLists() returned Friend[], now is a FriendList[] +# # No need anymore to cast to a Impl class to be able to use setUserData or getUserData +# # findFriend now takes an Address instead of a String +# # createOpenH264DownloadHelper() now takes a Context +# # Factory.createCore(this, mConfigFile, mLinphoneFactoryConfigFile, null, c) => createCore(this, mConfigFile, mLinphoneFactoryConfigFile) +# # startEchoTester and stopEchoTester now return void +# # createProxyConfig no longer takes any parameter +# # setPrimaryContact only takes one String argument -# AdaptiveRateAlgorithm was an enum, now is nothing +# +# AdaptiveRateAlgorithm was an enum, now is replaced by a String in the methods that were using it +# # createAddress(userName,domain,null); no longer exists +# # Buffer.setContent now takes the size as second parameter +# # ChatMessageListener onFileTransferSend now returns the Buffer instead of having it as part of his arguments +# # Core.startEchoCancellerCalibration no longer takes a parameter +# # XmlRpcSession.createRequest takes first the return arg type and then the name of the method, until now it was the other way around -# ProxyConfig.normalizePhoneNumber returns null if it fails instead of the value given as parameter in the previous version ! +# +# ProxyConfig.normalizePhoneNumber returns null if it fails instead of the value given as parameter in the previous version! +# +# ChatMessage.getStorageId() no longer exists +# +# ChatRoom.getHistory() no needs an integer parameter corresponding to the number of messages to get (use 0 to get the full history) +# +# Factory.createContent() no longer takes arguments. Use the Content methods to fill the content. +# +# AccountCreator.updatePassword() no longer exist. Use setPassword() and updateAccount() instead. # # Factory #Factory.createAccountCreator() => Core.createAccountCreator() -#Factory.createPresenceModel() => Core.createPresenceModel() +#Factory.createPresenceModel() => Core.createPresenceModel() & PresenceModel.setActivity() #Factory.instance().enableLogCollection(isDebugEnabled); now takes a LogCollectionState # # Core @@ -336,6 +376,7 @@ s/XmlRpcRequest\.Status/XmlRpcStatus/g;" {} \; #Core.getFriendsLists() => now returns a FriendList[] instead of a Friend[] #Core.enableSpeaker / isSpeakerEnabled() => mAudioManager.setSpeakerphoneOn(speakerOn); #Core.enableVideo(true, true) => Core.enableVideoCapture(bool) & Core.enableVideoDisplay(bool) +#Core.setVideoPolicy(initiate, accept) => Core.getVideoActivationPolicy().setAutomaticallyInitiate(initiate) & Core.getVideoActivationPolicy().setAutomaticallyAccept(accept) # # Other #CallParams.getJitterBufferSize() => CallStatsImpl.getJitterBufferSizeMs()