Merge branch 'dev_refactor_cpp_qrcode' of gitlab.linphone.org:BC/public/linphone into dev_refactor_cpp

Add QRCode API
This commit is contained in:
Erwan Croze 2018-06-15 10:40:24 +02:00
commit f893132414
102 changed files with 1971 additions and 2514 deletions

View file

@ -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")

View file

@ -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.*

View file

@ -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})

View file

@ -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)

View file

@ -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<char *>(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<char *>(ms_malloc(65));
sal_auth_compute_ha1_for_algorithm(obj->userid ? obj->userid : obj->username, obj->realm, obj->passwd, obj->ha1,65, obj->algorithm);
}

View file

@ -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;

View file

@ -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 */

View file

@ -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 <ortp/telephonyevents.h>
#include <mediastreamer2/zrtp.h>
#include <mediastreamer2/dtls_srtp.h>
#include <bctoolbox/defs.h>
#include <belr/grammarbuilder.h>
#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 <netdb.h>
@ -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;
}

View file

@ -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,"<init>", "(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;
}

View file

@ -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);

View file

@ -21,6 +21,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef _WIN32
#include <sys/ioctl.h>
#endif
#include <signal.h>
#include <iostream>
#include <iomanip>
#include <sstream>
@ -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."<<endl;
}
void Daemon::startThread() {
@ -862,6 +872,10 @@ void Daemon::enableStatsEvents(bool enabled){
mUseStatsEvents=enabled;
}
void Daemon::enableAutoAnswer(bool enabled){
mAutoAnswer = enabled;
}
void Daemon::enableLSD(bool enabled) {
if (mLSD) linphone_sound_daemon_destroy(mLSD);
linphone_core_use_sound_daemon(mLc, NULL);
@ -899,6 +913,15 @@ Daemon::~Daemon() {
#endif
}
static Daemon *the_app = NULL;
static void sighandler(int signum){
if (the_app){
the_app->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();
}

View file

@ -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;

View file

@ -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.

View file

@ -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.

View file

@ -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
}

View file

@ -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.

View file

@ -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

View file

@ -120,7 +120,7 @@ namespace Private {
raw{ char('0' + Value / pow10(N - Index - 2) % 10)..., '\0' } {}
template<std::size_t... Index, typename Int = int, typename std::enable_if<IsNeg::value, Int>::type* = nullptr>
constexpr StaticIntStringHelper(const IndexSequence<Index...> &) :
constexpr StaticIntStringHelper (const IndexSequence<Index...> &) :
raw{ '-', char('0' + abs(Value) / pow10(N - Index - 3) % 10)..., '\0' } {}
};
};

View file

@ -35,32 +35,32 @@ LINPHONE_BEGIN_NAMESPACE
namespace Utils {
template<typename T>
LINPHONE_PUBLIC constexpr T *getPtr (std::shared_ptr<T> &object) {
constexpr T *getPtr (std::shared_ptr<T> &object) {
return object.get();
}
template<typename T>
LINPHONE_PUBLIC constexpr T *getPtr (const std::shared_ptr<T> &object) {
constexpr T *getPtr (const std::shared_ptr<T> &object) {
return object.get();
}
template<typename T>
LINPHONE_PUBLIC constexpr T *getPtr (std::unique_ptr<T> &object) {
constexpr T *getPtr (std::unique_ptr<T> &object) {
return object.get();
}
template<typename T>
LINPHONE_PUBLIC constexpr T *getPtr (const std::unique_ptr<T> &object) {
constexpr T *getPtr (const std::unique_ptr<T> &object) {
return object.get();
}
template<typename T>
LINPHONE_PUBLIC constexpr T *getPtr (T *object) {
constexpr T *getPtr (T *object) {
return object;
}
template<typename T>
LINPHONE_PUBLIC constexpr T *getPtr (T &object) {
constexpr T *getPtr (T &object) {
return &object;
}
@ -108,7 +108,7 @@ namespace Utils {
}
template<typename S, typename T>
LINPHONE_PUBLIC std::string join (const std::vector<T>& elems, const S& delim) {
inline std::string join (const std::vector<T>& 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<typename T>
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

View file

@ -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<InetAddress> 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();
}
};

View file

@ -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}
$<TARGET_OBJECTS:linphone-coreapi>
)
@ -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.

View file

@ -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<LinphoneCallState>(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getTransferState());
}

View file

@ -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) {

View file

@ -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.
// =============================================================================

View file

@ -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);

View file

@ -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<Linphone ## C_TYPE>::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.

View file

@ -67,7 +67,7 @@ public:
void stopMediaStreams ();
private:
void resetFirstVideoFrameDecoded ();
void requestNotifyNextVideoFrameDecoded ();
void startRemoteRing ();
void terminateBecauseOfLostMedia ();

View file

@ -148,12 +148,6 @@ void CallPrivate::stopMediaStreams () {
// -----------------------------------------------------------------------------
void CallPrivate::resetFirstVideoFrameDecoded () {
#ifdef VIDEO_ENABLED
if (nextVideoFrameDecoded._func)
static_pointer_cast<MediaSession>(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<CallSessio
lInfo() << "Incoming call ringing for " << elapsed << " seconds";
if (elapsed > 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<CallSession> &sessi
}
void CallPrivate::onResetFirstVideoFrameDecoded (const shared_ptr<CallSession> &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<MediaSession>(getActiveSession())->requestNotifyNextVideoFrameDecoded();
}
void CallPrivate::onPlayErrorTone (const shared_ptr<CallSession> &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) {

View file

@ -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);

View file

@ -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);

View file

@ -30,6 +30,7 @@ LINPHONE_BEGIN_NAMESPACE
class BasicChatRoomPrivate : public ChatRoomPrivate {
private:
std::string subject;
std::shared_ptr<Participant> me;
std::list<std::shared_ptr<Participant>> participants;
bool cpimAllowed = false;
bool multipartAllowed = false;

View file

@ -40,6 +40,7 @@ BasicChatRoom::BasicChatRoom (
const ChatRoomId &chatRoomId
) : ChatRoom(p, core, chatRoomId) {
L_D();
d->me = make_shared<Participant>(getLocalAddress());
d->participants.push_back(make_shared<Participant>(getPeerAddress()));
}
@ -102,8 +103,8 @@ shared_ptr<Participant> BasicChatRoom::findParticipant (const IdentityAddress &)
}
shared_ptr<Participant> BasicChatRoom::getMe () const {
lError() << "getMe() is not allowed on a BasicChatRoom";
return nullptr;
L_D();
return d->me;
}
int BasicChatRoom::getParticipantCount () const {

View file

@ -168,7 +168,7 @@ bool ChatRoomPrivate::sendDisplayNotification (const shared_ptr<ChatMessage> &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;
}

View file

@ -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<Cpim::MessagePrivate::PrivHeaderList>();
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) {

View file

@ -37,12 +37,12 @@ namespace Cpim {
typedef std::shared_ptr<std::list<std::shared_ptr<const Cpim::Header>>> 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<const Cpim::Header> 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<const Cpim::Header> getContentHeader (const std::string &name) const;

View file

@ -29,10 +29,6 @@
#include "object/object-p.h"
#include "cpim-parser.h"
#ifdef __APPLE__
#include <TargetConditionals.h>
#include <CoreFoundation/CoreFoundation.h>
#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.";
}

View file

@ -98,7 +98,7 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptr<Ch
Cpim::GenericHeader("Content-Type", content->getContentType().asString())
);
cpimMessage.addContentHeader(
Cpim::GenericHeader("Content-Length", to_string(contentBody.size()))
Cpim::GenericHeader("Content-Length", Utils::toString(contentBody.size()))
);
cpimMessage.setContent(contentBody);

View file

@ -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()) {

View file

@ -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> &chatMessage);
private:
static int timerExpired (void *data, unsigned int revents);
bool aggregationEnabled () const;
void send ();
void startTimer ();
void stopTimer ();

View file

@ -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 &notify, const std::shared_ptr<ParticipantDevice> &device);
void notifyAllExcept (const std::string &notify, const std::shared_ptr<Participant> &exceptParticipant);

View file

@ -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 ();

View file

@ -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"

View file

@ -28,7 +28,7 @@ LINPHONE_BEGIN_NAMESPACE
class LocalConferencePrivate;
class LocalConference : public Conference {
class LINPHONE_PUBLIC LocalConference : public Conference {
friend class ServerGroupChatRoomPrivate;
public:

View file

@ -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;

View file

@ -111,10 +111,4 @@ bool Participant::isAdmin () const {
return d->isAdmin;
}
// =============================================================================
ostream & operator<< (ostream &strm, const shared_ptr<Participant> &participant) {
return strm << "'" << participant->getAddress().asString() << "'";
}
LINPHONE_END_NAMESPACE

View file

@ -23,8 +23,8 @@
#include <list>
#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> &participant);
inline std::ostream &operator<< (std::ostream &os, const Participant &participant) {
return os << participant.getAddress().asString();
return os;
}
LINPHONE_END_NAMESPACE

View file

@ -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(&params, 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);

View file

@ -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);

View file

@ -33,9 +33,10 @@ class Content;
namespace {
constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449";
}
namespace ContentManager {
std::list<Content> multipartToContentList (const Content &content);
Content contentListToMultipart (const std::list<Content *> &contents, const std::string &boundary = MultipartBoundary);
LINPHONE_PUBLIC std::list<Content> multipartToContentList (const Content &content);
LINPHONE_PUBLIC Content contentListToMultipart (const std::list<Content *> &contents, const std::string &boundary = MultipartBoundary);
}
LINPHONE_END_NAMESPACE

View file

@ -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 &param : 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
LINPHONE_END_NAMESPACE

View file

@ -60,7 +60,8 @@ public:
const HeaderParam &getParameter (const std::string &paramName) 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);

View file

@ -21,6 +21,9 @@
#include <comutil.h>
#include <ShlObj_core.h>
#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/");
}

View file

@ -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.";
}

View file

@ -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 <CoreFoundation/CoreFoundation.h>
#include <belr/grammarbuilder.h>
#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) {

View file

@ -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,

View file

@ -138,16 +138,14 @@ struct SqlEventFilterBuilder {};
template<EventLog::Type Type, EventLog::Type... List>
struct SqlEventFilterBuilder<Type, List...> {
static constexpr Private::StaticString<1 + getIntLength(int(Type)) + sums((1 + getIntLength(int(List)))...)> get () {
return StaticIntString<int(Type)>() + "," + SqlEventFilterBuilder<List...>::get();
}
static constexpr auto get () L_AUTO_RETURN(
StaticIntString<int(Type)>() + "," + SqlEventFilterBuilder<List...>::get()
);
};
template<EventLog::Type Type>
struct SqlEventFilterBuilder<Type> {
static constexpr Private::StaticString<1 + getIntLength(int(Type))> get () {
return StaticIntString<int(Type)>();
}
static constexpr auto get () L_AUTO_RETURN(StaticIntString<int(Type)>());
};
// -----------------------------------------------------------------------------
@ -155,27 +153,35 @@ struct SqlEventFilterBuilder<Type> {
// -----------------------------------------------------------------------------
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<EventLog::Type::ConferenceChatMessage>::get();
constexpr auto ConferenceChatMessageFilter = SqlEventFilterBuilder<EventLog::Type::ConferenceChatMessage>::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<MainDb::Filter> EventFilterToSql[] = {
{ MainDb::ConferenceCallFilter, ConferenceCallFilter },
@ -356,8 +362,6 @@ long long MainDbPrivate::insertChatRoom (const shared_ptr<AbstractChatRoom> &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<EventLog> MainDbPrivate::selectConferenceChatMessageEvent (
chatRoom,
ChatMessage::Direction(row.get<int>(8))
));
chatMessage->setIsSecured(bool(row.get<int>(9)));
chatMessage->setIsSecured(!!row.get<int>(9));
ChatMessagePrivate *dChatMessage = chatMessage->getPrivate();
ChatMessage::State messageState = ChatMessage::State(row.get<int>(7));
@ -627,8 +631,8 @@ shared_ptr<EventLog> MainDbPrivate::selectConferenceChatMessageEvent (
dChatMessage->setTime(MainDbPrivate::getTmAsTimeT(row.get<tm>(5)));
dChatMessage->setImdnMessageId(row.get<string>(6));
dChatMessage->setPositiveDeliveryNotificationRequired(bool(row.get<int>(14)));
dChatMessage->setDisplayNotificationRequired(bool(row.get<int>(15)));
dChatMessage->setPositiveDeliveryNotificationRequired(!!row.get<int>(14));
dChatMessage->setDisplayNotificationRequired(!!row.get<int>(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) {

View file

@ -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<typename Function>
friend class DbTransaction;

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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:

View file

@ -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_

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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<const SalCallOp *>(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<SalCallOp *>(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<SalCallOp *>(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<SalReferOp *>(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<SalReferOp *>(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<SalReferOp *>(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);

View file

@ -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<std::string> mSupportedContentTypes;
std::string mLinphoneSpecs;
belle_tls_crypto_config_postcheck_callback_t mTlsPostcheckCb;
void *mTlsPostcheckCbData;
// Cache values
mutable std::string mDnsUserHostsFile;

View file

@ -121,7 +121,7 @@ list<SearchResult> MagicSearch::getContactListFromFilter(const string &filter, c
list<SearchResult> 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<SearchResult> 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<SearchResult> *cache) {
d->mCacheResult = cache;
}
list<SearchResult> MagicSearch::getAllFriends() {
static bool findAddress(const list<SearchResult> &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<SearchResult> MagicSearch::getAddressFromCallLog(const string &filter, const string &withDomain, const list<SearchResult> &currentList) {
list<SearchResult> 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<LinphoneCallLog*>(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<SearchResult> MagicSearch::getFriends(const string &withDomain) {
list<SearchResult> returnList;
list<SearchResult> 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<LinphoneFriend*>(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<const char*>(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<SearchResult> MagicSearch::getAllFriends() {
return name1.size() < name2.size();
});
return returnList;
return *uniqueItemsList(returnList);
}
list<SearchResult> *MagicSearch::beginNewSearch(const string &filter, const string &withDomain) {
list<SearchResult> clResults;
list<SearchResult> *resultList = new list<SearchResult>();
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<SearchResult> results = searchInFriend(reinterpret_cast<LinphoneFriend*>(f->data), filter, withDomain);
addResultsToResultsList(results, *resultList);
list<SearchResult> fResults = searchInFriend(reinterpret_cast<LinphoneFriend*>(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<LinphoneCallLog*>(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<SearchResult> *MagicSearch::continueSearch(const string &filter, const string &withDomain) {
@ -252,7 +331,7 @@ list<SearchResult> *MagicSearch::continueSearch(const string &filter, const stri
}
}
return resultList;
return uniqueItemsList(*resultList);
}
list<SearchResult> MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const string &filter, const string &withDomain) {
@ -290,22 +369,40 @@ list<SearchResult> 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<const char*>(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<SearchResult> &results, std::list<SearchResult> &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<Core> 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<SearchResult> *MagicSearch::uniqueItemsList(list<SearchResult> &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

View file

@ -140,12 +140,23 @@ private:
**/
void setSearchCache(std::list<SearchResult> *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<SearchResult> getAddressFromCallLog(const std::string &filter, const std::string &withDomain, const std::list<SearchResult> &currentList);
/**
* 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<SearchResult> getAllFriends();
std::list<SearchResult> getFriends(const std::string &withDomain);
/**
* Begin the search from friend list
@ -202,6 +213,8 @@ private:
void addResultsToResultsList(std::list<SearchResult> &results, std::list<SearchResult> &srL);
std::list<SearchResult> *uniqueItemsList(std::list<SearchResult> &list);
L_DECLARE_PRIVATE(MagicSearch);
};

View file

@ -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_

View file

@ -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;

View file

@ -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<bool>(getAssumedNumber(p));
return!!getAssumedNumber(p);
case Variant::UnsignedInt:
case Variant::UnsignedShort:
case Variant::UnsignedLong:
case Variant::UnsignedLongLong:
return static_cast<bool>(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<bool>(p.value.g);
return !!p.value.g;
default:
*soFarSoGood = false;

View file

@ -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})

View file

@ -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));

View file

@ -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");
}

View file

@ -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 {

View file

@ -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-----

View file

@ -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-----

View file

@ -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)

View file

@ -492,9 +492,10 @@ void ConferenceEventTester::onFirstNotifyReceived (const IdentityAddress &addr)
void ConferenceEventTester::onParticipantAdded (const shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) {
(void)isFullState; // unused
const IdentityAddress addr = event->getParticipantAddress();
participants.insert(pair<string, bool>(addr.asString(), FALSE));
participantDevices.insert(pair<string, int>(addr.asString(), 0));
participants.insert({ addr.asString(), false });
participantDevices.insert({ addr.asString(), 0 });
}
void ConferenceEventTester::onParticipantRemoved (const shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) {
(void)isFullState; // unused
const IdentityAddress addr = event->getParticipantAddress();

View file

@ -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 = "<body>"
"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
};

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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),

View file

@ -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));
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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),

View file

@ -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(&current);
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")
};

View file

@ -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;

View file

@ -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;

View file

@ -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 <sstream>
#include "generator.hh"
#ifdef _WIN32
#include <direct.h>
#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<Class*> 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<<cf->getName()<<"="<<cf->getValue();
if (!isLast) mOutfile<<",";
if (!cf->getHelp().empty()) mOutfile<<"\t/**< "<<cf->getHelp()<<" */";
mOutfile<<endl;
}
void CplusplusGenerator::writeClass(Class *klass){
ostringstream filename;
filename<<mCurProj->getName()<<"/"<<klass->getName()<<".hh";
mOutfile.open(filename.str().c_str());
if (!mOutfile.is_open()){
cerr<<"Could not write into "<<filename.str()<<endl;
return;
}
list<Method*> methods=klass->getMethods();
list<ConstField*> constFields=klass->getConstFields();
mCurClass=klass;
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
mOutfile<<endl;
mOutfile<<"#include <string>"<<endl;
mOutfile<<endl;
if (!mCurProj->getName().empty())
mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
if (klass->getType()==Type::Enum){
mOutfile<<"enum "<<klass->getName()<<"{"<<endl;
list<ConstField*>::iterator cfit,next;
for (cfit=constFields.begin();cfit!=constFields.end();){
ConstField *cf=*cfit;
writeEnumMember(cf,++cfit==constFields.end());
}
}else{
mOutfile<<"class "<<klass->getName()<<"{"<<endl;
mOutfile<<"public:"<<endl;
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&CplusplusGenerator::writeMethod),this));
}
mOutfile<<"};"<<endl<<endl;
if (!mCurProj->getName().empty())
mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
mOutfile<<endl;
mOutfile.close();
}
void CplusplusGenerator::writeArgument(Argument *arg, bool isReturn){
Type *type=arg->getType();
if (type->getBasicType()==Type::Class){
if (arg->isConst()){
mOutfile<<"const ";
}
mOutfile<<type->getName();
if (arg->isPointer())
mOutfile<<"*";
}else if (type->getBasicType()==Type::Integer){
mOutfile<<"int";
}else if (type->getBasicType()==Type::Enum){
mOutfile<<type->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<<" "<<arg->getName();
}
void CplusplusGenerator::writeTabs(int ntabs){
int i;
for(i=0;i<ntabs;++i)
mOutfile<<"\t";
}
void CplusplusGenerator::writeHelpComment(const std::string &comment, int ntabs){
size_t i;
int curindex=0;
writeTabs(ntabs);
mOutfile<<" * ";
for(i=0;i<comment.size();i++,curindex++){
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
mOutfile<<endl;
writeTabs(ntabs);
mOutfile<<" * ";
curindex=0;
}else mOutfile<<comment[i];
}
}
void CplusplusGenerator::writeMethod(Method *method){
if (method->isCallback()) return;
Argument *retarg=method->getReturnArg();
const list<Argument*> &args=method->getArgs();
list<Argument*>::const_iterator it;
writeTabs(1);
mOutfile<<"/**"<<endl;
writeHelpComment(method->getHelp(),1);
mOutfile<<endl;
writeTabs(1);
mOutfile<<"**/"<<endl;
writeTabs(1);
writeArgument(retarg,true);
mOutfile<<" "<<method->getName()<<"(";
for(it=args.begin();it!=args.end();++it){
if (it!=args.begin()) mOutfile<<", ";
writeArgument(*it);
}
mOutfile<<")";
if (method->isConst()) mOutfile<<"const";
mOutfile<<";"<<endl;
mOutfile<<endl;
}
JavascriptGenerator::JavascriptGenerator(){
}
void JavascriptGenerator::generate(Project *proj){
list<Class*> 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<<to_lower(mCurProj->getName())<<"/"<<to_lower(mCurProj->getName())<<".js";
mOutfile.open(filename.str().c_str());
if (!mOutfile.is_open()){
cerr<<"Could not write into "<<filename.str()<<endl;
return;
}
mOutfile<<"/**"<<endl;
mOutfile<<" * Namespace for non-external variables and objects."<<endl;
mOutfile<<" * @namespace "<<mCurProj->getName()<<endl;
mOutfile<<"**/"<<endl;
mOutfile<<"var "<<proj->getName()<<" = {};"<<endl;
mOutfile.close();
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&JavascriptGenerator::writeEnum),this));
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&JavascriptGenerator::writeClass),this));
}
string JavascriptGenerator::getEnumName(Class *klass){
string enum_name=klass->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<ConstField*> members=klass->getConstFields();
list<ConstField*>::iterator it;
string enum_name=getEnumName(klass);
filename<<to_lower(mCurProj->getName())<<"/"<<to_lower(enum_name)<<".js";
mOutfile.open(filename.str().c_str());
if (!mOutfile.is_open()){
cerr<<"Could not write into "<<filename.str()<<endl;
return;
}
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl<<endl;
mOutfile<<"var "<<mCurProj->getName()<<" = "<<mCurProj->getName()<<" || {};"<<endl;
mOutfile<<"/**"<<endl;
writeHelpComment(klass->getHelp(),0);
mOutfile<<endl;
mOutfile<<" * "<<"@readonly"<<endl;
mOutfile<<" * "<<"@enum {number}"<<endl;
mOutfile<<"**/"<<endl;
mOutfile<<mCurProj->getName()<<"."<<enum_name<<" = {"<<endl;
string prefix=ConstField::getCommonPrefix(members);
size_t prefix_size=prefix.size();
for(it=members.begin();it!=members.end();){
ConstField *cf=(*it);
if (!cf->getHelp().empty()){
writeTabs(1);
mOutfile<<"/**"<<endl;
writeHelpComment(cf->getHelp(),1);
mOutfile<<endl;
writeTabs(1);
mOutfile<<"*/"<<endl;
}
writeTabs(1);
mOutfile<<cf->getName().substr(prefix_size,string::npos)<<" : "<<cf->getValue();
if (++it!=members.end()) mOutfile<<",";
mOutfile<<endl;
}
mOutfile<<"};"<<endl;
mOutfile << "/**" << endl;
mOutfile << " * Get the name of a value of the " << enum_name << " enum as a string." << endl;
mOutfile << " * @function linphone#get" << enum_name << "Text" << endl;
mOutfile << " * @param { number } value - One of the values of the " << enum_name << " enum." << endl;
mOutfile << "**/" << endl;
mOutfile << mCurProj->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<Method*> &methods=klass->getMethods();
if (methods.empty()) return;//skip empty classes
filename<<to_lower(mCurProj->getName())<<"/"<<to_lower(klass->getName())<<".js";
mOutfile.open(filename.str().c_str());
if (!mOutfile.is_open()){
cerr<<"Could not write into "<<filename.str()<<endl;
return;
}
mCurClass=klass;
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
mOutfile<<endl;
//if (!mCurProj->getName().empty())
// mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
mOutfile<<"/**"<<endl;
mOutfile<<" * "<<klass->getHelp()<<endl;
mOutfile<<" * @external "<<klass->getName()<<endl;
mOutfile<<"**/"<<endl;
list<Property*> properties=klass->getProperties();
for_each(properties.begin(),properties.end(),bind1st(mem_fun(&JavascriptGenerator::writeProperty),this));
mOutfile<<endl;
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&JavascriptGenerator::writeMethod),this));
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&JavascriptGenerator::writeEvent),this));
//if (!mCurProj->getName().empty())
// mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
mOutfile<<endl;
mOutfile.close();
}
void JavascriptGenerator::writeType(Type *type){
switch(type->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:"<<type->getName();
break;
case Type::Enum:
mOutfile<<mCurProj->getName()<<"."<<getEnumName(mCurProj->getClass(type->getName()));
break;
case Type::Void:
mOutfile<<"void";
break;
case Type::Callback:
break;
case Type::Array:
mOutfile<<"Array.<Object>";
break;
}
}
void JavascriptGenerator::writeArgument(Argument *arg, ArgKind kind){
switch(kind){
case Normal:
mOutfile<<" * @param {";
writeType(arg->getType());
mOutfile<<"} "<<arg->getName()<<" - "<<arg->getHelp()<<endl;
break;
case Return:
mOutfile<<" * @returns {";
writeType(arg->getType());
mOutfile<<"} "<<arg->getHelp()<<endl;
break;
case PropertyArg:
mOutfile<<" * @property {";
writeType(arg->getType());
mOutfile<<"} "<<arg->getName()<<" - "<<arg->getHelp()<<endl;
break;
}
}
void JavascriptGenerator::writeTabs(int ntabs){
int i;
for(i=0;i<ntabs;++i)
mOutfile<<"\t";
}
void JavascriptGenerator::writeHelpComment(const std::string &comment, int ntabs){
size_t i;
int curindex=0;
writeTabs(ntabs);
mOutfile<<" * ";
for(i=0;i<comment.size();i++,curindex++){
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
mOutfile<<endl;
writeTabs(ntabs);
mOutfile<<" * ";
curindex=0;
}else mOutfile<<comment[i];
}
}
void JavascriptGenerator::writeProperty(Property *prop){
if (prop->getName()=="userData" || prop->getName()=="userPointer") return;
mOutfile<<"/**"<<endl;
writeHelpComment(prop->getHelp(),0);
mOutfile<<endl;
mOutfile<<" * @member {";
writeType(prop->getType());
mOutfile<<"} external:"<<mCurClass->getName()<<"#"<<prop->getName()<<endl;
if (prop->getAttribute()==Property::ReadOnly)
mOutfile<<" * @readonly"<<endl;
mOutfile<<"**/"<<endl;
}
void JavascriptGenerator::writeMethod(Method *method){
Argument *retarg=method->getReturnArg();
const list<Argument*> &args=method->getArgs();
list<Argument*>::const_iterator it;
if (method->isCallback()) return;
if (method->getPropertyBehaviour()!=Method::None) return;
if (method->getName()=="ref" || method->getName()=="unref") return;
mOutfile<<"/**"<<endl;
writeHelpComment(method->getHelp(),0);
mOutfile<<endl;
mOutfile<<" * @function external:"<<mCurClass->getName()<<"#"<<method->getName()<<endl;
for(it=args.begin();it!=args.end();++it){
writeArgument(*it);
}
writeArgument(retarg,Return);
mOutfile<<"**/"<<endl;
mOutfile<<endl;
}
string JavascriptGenerator::getEventHelp(const string &help){
size_t i=help.find("Callback");
if (i==string::npos){
i=help.find("callback");
if (i==string::npos) return help;
}
string res(help);
res.replace(i,8,"event");
return res;
}
void JavascriptGenerator::writeEvent(Method* event){
const list<Argument*> &args=event->getArgs();
list<Argument*>::const_iterator it;
if (!event->isCallback()) return;
mOutfile<<"/**"<<endl;
writeHelpComment(getEventHelp(event->getHelp()),0);
mOutfile<<endl;
mOutfile<<" * @event external:"<<mCurClass->getName()<<"#"<<event->getName()<<endl;
mOutfile<<" * @type {object}"<<endl;
for(it=args.begin();it!=args.end();++it){
writeArgument(*it,PropertyArg);
}
mOutfile<<"**/"<<endl;
mOutfile<<endl;
}

View file

@ -1,73 +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 generator_hh
#define generator_hh
#include <fstream>
#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

View file

@ -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 <libxml/parser.h>
#include <libxml/tree.h>
#include <string.h>
#include <cstdio>
#include <iostream>
#include <sstream>
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<XmlNode> getChildren(const string &name)const{
xmlNode *it;
list<XmlNode> 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 "<<name<<" found"<<endl;
return nodes;
}
string getText()const{
if (mNode==NULL) return "";
XmlNode node=getChild("text");
if (!node.isNull()) {
const char *text=(const char*)node.mNode->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 "<<name<<" with type "<<type->getBasicType()<<" "<<type->getName()<<endl;
return new Argument(type,!isReturn ? name : "",isConst,isPointer);
}
static string classNameToPrefix(const std::string &classname){
char *tmp = new char[classname.size()*2];
char *w=tmp;
size_t i;
for(i=0;i<classname.size();i++){
char p=classname[i];
if (isupper(p)){
if (i!=0){
*w++='_';
}
*w++=tolower(p);
}else *w++=p;
}
*w++='\0';
string ret(tmp);
delete[] tmp;
return ret;
}
static string makeMethodName(const string & suffix){
char *tmp = new char[suffix.size()];
char *w=tmp;
size_t i;
bool useUpper=false;
for(i=0;i<suffix.size();i++){
char p=suffix[i];
if (p=='_'){
if (i>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<<brief.getText();
result<<detailed.getChild("para").getText();
//cout<<"getHelpBody():"<<result.str();
return result.str();
}
static void parseFunction(Project *proj, xmlNode *node){
string name;
Argument *first_arg=NULL;
string className;
string methodName;
Argument *retarg=NULL;
list<Argument*> args;
string help;
XmlNode funcnode(node);
XmlNode parameterlist;
list<XmlNode> params;
list<XmlNode> paramsHelp;
list<XmlNode>::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"<<endl;
paramsHelp=parameterlist.getChildren("parameteritem");
for (it=params.begin(),helpit=paramsHelp.begin();it!=params.end();++it){
Argument *a=parseArgument(*it,false);
if (a){
//add argument help
if (!args.empty()){
if (helpit!=paramsHelp.end()){
XmlNode item=*helpit;
a->setHelp(item.getChild("parameterdescription").getChild("para").getText());
}else cerr<<"Undocumented parameter "<<a->getName()<<" in function "<<name<<endl;
}
args.push_back(a);
if (helpit!=paramsHelp.end()) ++helpit;
}
else return;
}
help=getHelpBody(funcnode);
retarg=parseArgument(funcnode,true);
if (!retarg){
cerr<<"Could not parse return argument of function "<<name<<endl;
return;
}
if (!args.empty()) first_arg=args.front();
if (!first_arg){
cerr<<"Could not determine first argument of "<<name<<endl;
return;
}
if (first_arg->getType()->getBasicType()!=Type::Class) return;
className=first_arg->getType()->getName();
methodName=extractMethodName(name,className);
if (!methodName.empty() && methodName!="destroy"){
//cout<<"Found "<<className<<"."<<methodName<<"()"<<endl;
args.pop_front();
Method *method=new Method("",retarg,methodName,args,first_arg->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<c1.size() && i<c2.size();++i){
if (tolower(c1[i])==tolower(c2[i]))
res<<(char)c1[i];
else break;
}
return res.str();
}
static string extractCallbackName(const string &c_name, const string & classname){
string prefix=findCommon(c_name,classname);
string res=c_name.substr(prefix.size(),string::npos);
res[0]=tolower(res[0]);
size_t pos=res.find("Cb");
if (pos!=string::npos) res=res.substr(0,pos);
return res;
}
static void parseCallback(Project *proj, XmlNode node){
string argsstring=node.getChild("argsstring").getText();
string name=node.getChild("name").getText();
list<XmlNode> params=node.getChildRecursive("parameterlist").getChildren("parameteritem");
list<XmlNode>::iterator it=params.begin();
string rettype=node.getChild("type").getText();
argsstring=argsstring.substr(argsstring.find('(')+1,string::npos);
bool cont=true;
list<Argument*> 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 && comma<end) end=comma;
else cont=false;
string arg=argsstring.substr(0,end);
bool isConst=false;
bool isPointer=false;
size_t endtype=arg.find('*');
if (endtype==string::npos) endtype=arg.rfind(' ');
else isPointer=true;
string typestring=arg.substr(0,endtype+1);
Type *type=Type::getType(typestring);
if (type==NULL) return;
if (firstArgType==NULL) firstArgType=type;
//find const attribute if any
if (typestring.find("const")!=string::npos)
isConst=true;
string argname=arg.substr(endtype+1,end);
argsstring=argsstring.substr(end+1,string::npos);
Argument *argobj=new Argument(type,makeMethodName(argname),isConst,isPointer);
if (it!=params.end()){
argobj->setHelp((*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 "<<callback->getName()<<" with "<<args.size()<<" arguments."<<endl;
callback->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<XmlNode> enumValues=node.getChildren("enumvalue");
list<XmlNode>::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"<<endl;
parseMemberDef(proj,cur_node);
}
}
if (cur_node->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."<<endl;
return -1;
}
/*Get the root element node */
root_element = xmlDocGetRootElement(doc);
inspectNode(proj,root_element);
/*free the document */
xmlFreeDoc(doc);
return 0;
}
int main(int argc, char *argv[]){
int i;
string projectName="wrapper";
OutputGenerator *gen=NULL;
list<string> files;
list<string>::iterator it;
LIBXML_TEST_VERSION
for(i=1;i<argc;i++){
if (strcmp(argv[i],"--help")==0){
fprintf(stderr,"%s: [--help] --output (c++, javascript) --project <project name> 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 !"<<endl;
return -1;
}
Project *proj=new Project(projectName);
for(it=files.begin();it!=files.end();it++){
if (parse_file(proj,(*it).c_str())==-1){
cerr<<"Parsing aborted."<<endl;
return -1;
}
}
proj->analyse();
gen->generate(proj);
return 0;
}

View file

@ -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<string,Type*> Type::mTypes;
const char *Type::sBasicTypeNames[]={
"Void",
"Boolean",
"Integer",
"Float",
"String",
"Enum",
"Class",
"Callback",
"Array",
"undef",
"undef"
};

View file

@ -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 <functional>
#include <iostream>
#include <list>
#include <map>
#include <algorithm>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstring>
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 "<<sBasicTypeNames[(int)bt]<<" type '"<<name<<"'"<<endl;
ret=mTypes[name]=new Type(bt,name);
}else if (bt!=Class){
ret->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"<<tname<<std::endl;
return NULL;
}
const std::string &getName()const{
return mName;
}
BasicType getBasicType()const{
return mBasic;
}
private:
BasicType mBasic;
std::string mName;
Type(BasicType basic, const std::string &tname="") : mBasic(basic), mName(tname){
}
static Type sStringType;
static Type sIntegerType;
static Type sVoidType;
static Type sBooleanType;
static Type sFloatType;
static Type sArrayType;
static std::map<std::string,Type*> 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<Argument*> &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<Argument*> &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<Argument*> 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<ConstField *> fields){
if (fields.size()<2) return "";
list<ConstField*>::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: "<<prefix<<endl;
return prefix;
}
}
return "";
}
private:
Type *mType;
string mName;
int mValue;
string mHelp;
};
template <typename _type>
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<ConstField*>::iterator it=find_if(mConstFields.begin(),mConstFields.end(),name_matcher<ConstField>(field->getName()));
if (it==mConstFields.end())
mConstFields.push_back(field);
}
void setHelp(const std::string &help){
mHelp=help;
}
list<Method*> getMethods()const{
list<Method*> ret;
map<string,Method*>::const_iterator it;
for(it=mMethods.begin();it!=mMethods.end();++it){
ret.push_back((*it).second);
}
return ret;
}
const list<ConstField*> &getConstFields()const{
return mConstFields;
}
const string &getName()const{
return mName;
}
const string &getHelp()const{
return mHelp;
}
list<Property*> getProperties(){
list<Property*> ret;
map<string,Property*>::const_iterator it;
for(it=mProperties.begin();it!=mProperties.end();++it){
ret.push_back((*it).second);
}
return ret;
}
void computeProperties(){
map<string,Method*>::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<string,Method*> mMethods;
map<string,Property*> mProperties;
list<ConstField*> 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<Class*> getClasses()const{
list<Class*> ret;
map<string,Class*>::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<Class*> classes=getClasses();
for_each(classes.begin(),classes.end(),mem_fun(&Class::computeProperties));
}
void addCallback(Method *callback){
list<Method*>::iterator it=find_if(mCallbacks.begin(),mCallbacks.end(),name_matcher<Method>(callback->getName()));
if (it==mCallbacks.end())
mCallbacks.push_back(callback);
}
const list<Method*> &getCallbacks()const{
return mCallbacks;
}
private:
map<string,Class*> mClasses;
list<Method*> mCallbacks;
string mName;
};
#endif

View file

@ -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();
}
}
};

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

Some files were not shown because too many files have changed in this diff Show more