mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
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:
commit
f893132414
102 changed files with 1971 additions and 2514 deletions
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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.*
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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' } {}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public:
|
|||
void stopMediaStreams ();
|
||||
|
||||
private:
|
||||
void resetFirstVideoFrameDecoded ();
|
||||
void requestNotifyNextVideoFrameDecoded ();
|
||||
void startRemoteRing ();
|
||||
void terminateBecauseOfLostMedia ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
class Participant;
|
||||
class ParticipantDevice;
|
||||
|
||||
class LocalConferenceEventHandlerPrivate : public ObjectPrivate {
|
||||
class LINPHONE_INTERNAL_PUBLIC LocalConferenceEventHandlerPrivate : public ObjectPrivate {
|
||||
public:
|
||||
void notifyFullState (const std::string ¬ify, const std::shared_ptr<ParticipantDevice> &device);
|
||||
void notifyAllExcept (const std::string ¬ify, const std::shared_ptr<Participant> &exceptParticipant);
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ LINPHONE_BEGIN_NAMESPACE
|
|||
|
||||
class LocalConferencePrivate;
|
||||
|
||||
class LocalConference : public Conference {
|
||||
class LINPHONE_PUBLIC LocalConference : public Conference {
|
||||
friend class ServerGroupChatRoomPrivate;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1122,7 +1122,7 @@ void MediaSessionPrivate::discoverMtu (const Address &remoteAddr) {
|
|||
|
||||
string MediaSessionPrivate::getBindIpForStream (int streamIndex) {
|
||||
L_Q();
|
||||
string bindIp = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", (af == AF_INET6) ? "::0" : "0.0.0.0");
|
||||
string bindIp = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", "");
|
||||
PortConfig *pc = &mediaPorts[streamIndex];
|
||||
if (!pc->multicastIp.empty()){
|
||||
if (direction == LinphoneCallOutgoing) {
|
||||
|
|
@ -2367,7 +2367,7 @@ void MediaSessionPrivate::initializeAudioStream () {
|
|||
if (remoteDesc)
|
||||
streamDesc = sal_media_description_find_best_stream(remoteDesc, SalAudio);
|
||||
|
||||
audioStream = audio_stream_new2(q->getCore()->getCCore()->factory, getBindIpForStream(mainAudioStreamIndex).c_str(),
|
||||
audioStream = audio_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainAudioStreamIndex)),
|
||||
(multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainAudioStreamIndex].rtpPort,
|
||||
(multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainAudioStreamIndex].rtcpPort);
|
||||
if (multicastRole == SalMulticastReceiver)
|
||||
|
|
@ -2381,8 +2381,14 @@ void MediaSessionPrivate::initializeAudioStream () {
|
|||
|
||||
/* Initialize zrtp even if we didn't explicitely set it, just in case peer offers it */
|
||||
if (linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP)) {
|
||||
char *peerUri = linphone_address_as_string_uri_only((direction == LinphoneCallIncoming) ? log->from : log->to);
|
||||
char *selfUri = linphone_address_as_string_uri_only((direction == LinphoneCallIncoming) ? log->to : log->from);
|
||||
LinphoneAddress *peerAddr = (direction == LinphoneCallIncoming) ? log->from : log->to;
|
||||
LinphoneAddress *selfAddr = (direction == LinphoneCallIncoming) ? log->to : log->from;
|
||||
char *peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(peerAddr)
|
||||
, linphone_address_get_username(peerAddr)
|
||||
, linphone_address_get_domain(peerAddr));
|
||||
char *selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(selfAddr)
|
||||
, linphone_address_get_username(selfAddr)
|
||||
, linphone_address_get_domain(selfAddr));
|
||||
MSZrtpParams params;
|
||||
memset(¶ms, 0, sizeof(MSZrtpParams));
|
||||
/* media encryption of current params will be set later when zrtp is activated */
|
||||
|
|
@ -2473,7 +2479,7 @@ void MediaSessionPrivate::initializeTextStream () {
|
|||
if (remoteDesc)
|
||||
streamDesc = sal_media_description_find_best_stream(remoteDesc, SalText);
|
||||
|
||||
textStream = text_stream_new2(q->getCore()->getCCore()->factory, getBindIpForStream(mainTextStreamIndex).c_str(),
|
||||
textStream = text_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainTextStreamIndex)),
|
||||
(multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainTextStreamIndex].rtpPort,
|
||||
(multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainTextStreamIndex].rtcpPort);
|
||||
if (multicastRole == SalMulticastReceiver)
|
||||
|
|
@ -2517,7 +2523,7 @@ void MediaSessionPrivate::initializeVideoStream () {
|
|||
if (remoteDesc)
|
||||
streamDesc = sal_media_description_find_best_stream(remoteDesc, SalVideo);
|
||||
|
||||
videoStream = video_stream_new2(q->getCore()->getCCore()->factory, getBindIpForStream(mainVideoStreamIndex).c_str(),
|
||||
videoStream = video_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainVideoStreamIndex)),
|
||||
(multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainVideoStreamIndex].rtpPort,
|
||||
(multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainVideoStreamIndex].rtcpPort);
|
||||
if (multicastRole == SalMulticastReceiver)
|
||||
|
|
@ -3729,7 +3735,7 @@ void MediaSessionPrivate::accept (const MediaSessionParams *msp, bool wasRinging
|
|||
L_Q();
|
||||
if (msp) {
|
||||
setParams(new MediaSessionParams(*msp));
|
||||
iceAgent->prepare(localDesc, true);
|
||||
iceAgent->prepare(localDesc, true, false /*we don't allow gathering now, it must have been done before*/);
|
||||
makeLocalMediaDescription();
|
||||
op->setLocalMediaDescription(localDesc);
|
||||
}
|
||||
|
|
@ -4234,10 +4240,6 @@ void MediaSession::sendVfuRequest () {
|
|||
L_D();
|
||||
MediaSessionParams *curParams = getCurrentParams();
|
||||
|
||||
if (d->videoStream && d->videoStream->ms.decoder) {
|
||||
ms_filter_call_method_noarg(d->videoStream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION);
|
||||
}
|
||||
|
||||
if ((curParams->avpfEnabled() || curParams->getPrivate()->implicitRtcpFbEnabled())
|
||||
&& d->videoStream && media_stream_get_state(&d->videoStream->ms) == MSStreamStarted) { // || sal_media_description_has_implicit_avpf((const SalMediaDescription *)call->resultdesc)
|
||||
lInfo() << "Request Full Intra Request on CallSession [" << this << "]";
|
||||
|
|
@ -4369,7 +4371,7 @@ LinphoneStatus MediaSession::update (const MediaSessionParams *msp, const string
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void MediaSession::resetFirstVideoFrameDecoded () {
|
||||
void MediaSession::requestNotifyNextVideoFrameDecoded () {
|
||||
L_D();
|
||||
if (d->videoStream && d->videoStream->ms.decoder)
|
||||
ms_filter_call_method_noarg(d->videoStream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ Header::Header (const string &name, const string &value) : ClonableObject(*new H
|
|||
setValue(value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
string parsedValue = value.substr(0, posParam);
|
||||
string params = value.substr(posParam + 1);
|
||||
string token;
|
||||
|
|
@ -167,7 +167,7 @@ string Header::asString () const {
|
|||
stringstream asString;
|
||||
if (!getName().empty()) {
|
||||
asString << getName() << ":";
|
||||
}
|
||||
}
|
||||
asString << getValue();
|
||||
for (const auto ¶m : getParameters()) {
|
||||
asString << param.asString();
|
||||
|
|
@ -175,9 +175,9 @@ string Header::asString () const {
|
|||
return asString.str();
|
||||
}
|
||||
|
||||
ostream &operator<<(ostream& stream, const Header& header) {
|
||||
stream << header.asString();
|
||||
return stream;
|
||||
ostream &operator<< (ostream &os, const Header& header) {
|
||||
os << header.asString();
|
||||
return os;
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ public:
|
|||
const HeaderParam &getParameter (const std::string ¶mName) const;
|
||||
|
||||
std::string asString () const;
|
||||
friend std::ostream &operator<<(std::ostream&, const Header&);
|
||||
|
||||
LINPHONE_PUBLIC friend std::ostream &operator<< (std::ostream &os, const Header &header);
|
||||
|
||||
protected:
|
||||
explicit Header (HeaderPrivate &p);
|
||||
|
|
|
|||
|
|
@ -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/");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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> ¤tList) {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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> ¤tList);
|
||||
|
||||
/**
|
||||
* Get all friends as SearchResult
|
||||
* @param[in] withDomain domain which we want to search only
|
||||
* @return all friends in a SearchResult list
|
||||
* @private
|
||||
**/
|
||||
std::list<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);
|
||||
};
|
||||
|
||||
|
|
|
|||
51
src/utils/general-internal.h
Normal file
51
src/utils/general-internal.h
Normal 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_
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
78
tester/certificates/client/cert3.pem
Normal file
78
tester/certificates/client/cert3.pem
Normal 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-----
|
||||
28
tester/certificates/client/key3.pem
Normal file
28
tester/certificates/client/key3.pem
Normal 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-----
|
||||
360
tester/certificates/client/openssl-altname.cnf
Normal file
360
tester/certificates/client/openssl-altname.cnf
Normal 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)
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static void _check_friend_result_list(LinphoneCore *lc, const bctbx_list_t *resu
|
|||
}
|
||||
const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, index);
|
||||
const LinphoneFriend *lf = linphone_search_result_get_friend(sr);
|
||||
if (lf) {
|
||||
if (lf || linphone_search_result_get_address(sr)) {
|
||||
const LinphoneAddress *la = (linphone_search_result_get_address(sr)) ?
|
||||
linphone_search_result_get_address(sr) : linphone_friend_get_address(lf);
|
||||
if (la) {
|
||||
|
|
@ -121,8 +121,8 @@ static void linphone_version_test(void){
|
|||
|
||||
static void core_init_test(void) {
|
||||
LinphoneCore* lc;
|
||||
lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL);
|
||||
|
||||
lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context);
|
||||
|
||||
/* until we have good certificates on our test server... */
|
||||
linphone_core_verify_server_certificates(lc,FALSE);
|
||||
if (BC_ASSERT_PTR_NOT_NULL(lc)) {
|
||||
|
|
@ -131,14 +131,24 @@ static void core_init_test(void) {
|
|||
}
|
||||
|
||||
static void linphone_address_test(void) {
|
||||
LinphoneAddress *address;
|
||||
|
||||
linphone_address_unref(create_linphone_address(NULL));
|
||||
BC_ASSERT_PTR_NULL(linphone_address_new("sip:@sip.linphone.org"));
|
||||
|
||||
address = linphone_address_new("sip:90.110.127.31");
|
||||
if (!BC_ASSERT_PTR_NOT_NULL(address)) return;
|
||||
linphone_address_unref(address);
|
||||
|
||||
address = linphone_address_new("sip:[::ffff:90.110.127.31]");
|
||||
if (!BC_ASSERT_PTR_NOT_NULL(address)) return;
|
||||
linphone_address_unref(address);
|
||||
}
|
||||
|
||||
static void core_sip_transport_test(void) {
|
||||
LinphoneCore* lc;
|
||||
LCSipTransports tr;
|
||||
lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL);
|
||||
lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context);
|
||||
if (!BC_ASSERT_PTR_NOT_NULL(lc)) return;
|
||||
linphone_core_get_sip_transports(lc,&tr);
|
||||
BC_ASSERT_EQUAL(tr.udp_port,5060, int, "%d"); /*default config*/
|
||||
|
|
@ -167,7 +177,7 @@ static void linphone_interpret_url_test(void) {
|
|||
LinphoneAddress* address;
|
||||
LinphoneProxyConfig *proxy_config;
|
||||
char *tmp;
|
||||
lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL);
|
||||
lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context);
|
||||
if (!BC_ASSERT_PTR_NOT_NULL( lc )) return;
|
||||
|
||||
proxy_config =linphone_core_create_proxy_config(lc);
|
||||
|
|
@ -360,7 +370,7 @@ void linphone_proxy_config_is_server_config_changed_test(void) {
|
|||
|
||||
static void chat_room_test(void) {
|
||||
LinphoneCore* lc;
|
||||
lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL);
|
||||
lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context);
|
||||
if (!BC_ASSERT_PTR_NOT_NULL(lc)) return;
|
||||
BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room_from_uri(lc,"sip:toto@titi.com"));
|
||||
linphone_core_unref(lc);
|
||||
|
|
@ -493,21 +503,25 @@ static void search_friend_in_alphabetical_order(void) {
|
|||
const char *name2SipUri = {"sip:stephanie@sip.example.org"};
|
||||
const char *name3SipUri = {"sip:alber@sip.example.org"};
|
||||
const char *name4SipUri = {"sip:gauthier@sip.example.org"};
|
||||
const char *name5SipUri = {"sip:gal@sip.example.org"};
|
||||
|
||||
LinphoneFriend *friend1 = linphone_core_create_friend(manager->lc);
|
||||
LinphoneFriend *friend2 = linphone_core_create_friend(manager->lc);
|
||||
LinphoneFriend *friend3 = linphone_core_create_friend(manager->lc);
|
||||
LinphoneFriend *friend4 = linphone_core_create_friend(manager->lc);
|
||||
LinphoneFriend *friend5 = linphone_core_create_friend(manager->lc);
|
||||
|
||||
LinphoneVcard *vcard1 = linphone_factory_create_vcard(linphone_factory_get());
|
||||
LinphoneVcard *vcard2 = linphone_factory_create_vcard(linphone_factory_get());
|
||||
LinphoneVcard *vcard3 = linphone_factory_create_vcard(linphone_factory_get());
|
||||
LinphoneVcard *vcard4 = linphone_factory_create_vcard(linphone_factory_get());
|
||||
LinphoneVcard *vcard5 = linphone_factory_create_vcard(linphone_factory_get());
|
||||
|
||||
const char *name1 = {"STEPHANIE delarue"};
|
||||
const char *name2 = {"alias delarue"};
|
||||
const char *name3 = {"Alber josh"};
|
||||
const char *name4 = {"gauthier wei"};
|
||||
const char *name5 = {"gal tcho"};
|
||||
|
||||
linphone_vcard_set_full_name(vcard1, name1); // STEPHANIE delarue
|
||||
linphone_vcard_set_url(vcard1, name1SipUri); //sip:toto@sip.example.org
|
||||
|
|
@ -533,16 +547,23 @@ static void search_friend_in_alphabetical_order(void) {
|
|||
linphone_friend_set_vcard(friend4, vcard4);
|
||||
linphone_core_add_friend(manager->lc, friend4);
|
||||
|
||||
linphone_vcard_set_full_name(vcard5, name5); // gal tcho
|
||||
linphone_vcard_set_url(vcard5, name5SipUri); //sip:gal@sip.example.org
|
||||
linphone_vcard_add_sip_address(vcard5, name5SipUri);
|
||||
linphone_friend_set_vcard(friend5, vcard5);
|
||||
linphone_core_add_friend(manager->lc, friend5);
|
||||
|
||||
magicSearch = linphone_magic_search_new(manager->lc);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d");
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d");
|
||||
_check_friend_result_list(manager->lc, resultList, 0, name3SipUri, NULL);//"sip:stephanie@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 1, name2SipUri, NULL);//"sip:alber@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 2, name4SipUri, NULL);//"sip:gauthier@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 3, name1SipUri, NULL);//"sip:toto@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 2, name5SipUri, NULL);//"sip:gal@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 3, name4SipUri, NULL);//"sip:gauthier@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 4, name1SipUri, NULL);//"sip:toto@sip.example.org"
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
|
|
@ -552,16 +573,19 @@ static void search_friend_in_alphabetical_order(void) {
|
|||
linphone_friend_list_remove_friend(lfl, friend2);
|
||||
linphone_friend_list_remove_friend(lfl, friend3);
|
||||
linphone_friend_list_remove_friend(lfl, friend4);
|
||||
linphone_friend_list_remove_friend(lfl, friend5);
|
||||
|
||||
if (friend1) linphone_friend_unref(friend1);
|
||||
if (friend2) linphone_friend_unref(friend2);
|
||||
if (friend3) linphone_friend_unref(friend3);
|
||||
if (friend4) linphone_friend_unref(friend4);
|
||||
if (friend5) linphone_friend_unref(friend5);
|
||||
|
||||
if (vcard1) linphone_vcard_unref(vcard1);
|
||||
if (vcard2) linphone_vcard_unref(vcard2);
|
||||
if (vcard3) linphone_vcard_unref(vcard3);
|
||||
if (vcard4) linphone_vcard_unref(vcard4);
|
||||
if (vcard5) linphone_vcard_unref(vcard5);
|
||||
|
||||
linphone_magic_search_unref(magicSearch);
|
||||
linphone_core_manager_destroy(manager);
|
||||
|
|
@ -591,6 +615,56 @@ static void search_friend_without_filter(void) {
|
|||
linphone_core_manager_destroy(manager);
|
||||
}
|
||||
|
||||
static void search_friend_with_domain_without_filter(void) {
|
||||
LinphoneMagicSearch *magicSearch = NULL;
|
||||
bctbx_list_t *resultList = NULL;
|
||||
LinphoneCoreManager* manager = linphone_core_manager_new2("marie_rc", FALSE);
|
||||
LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc);
|
||||
const char *chloeName = "chloe zaya";
|
||||
const char *chloeSipUri = "sip:ch@sip.test.org";
|
||||
const char *chloePhoneNumber = "0633556644";
|
||||
LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc);
|
||||
LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc);
|
||||
LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(manager->lc);
|
||||
|
||||
linphone_proxy_config_edit(proxy);
|
||||
linphone_proxy_config_set_dial_prefix(proxy, "33");
|
||||
linphone_proxy_config_done(proxy);
|
||||
linphone_core_set_default_proxy(manager->lc, proxy);
|
||||
|
||||
linphone_presence_model_set_contact(chloePresence, chloeSipUri);
|
||||
linphone_friend_set_name(chloeFriend, chloeName);
|
||||
linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber);
|
||||
linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence);
|
||||
linphone_friend_list_add_friend(lfl, chloeFriend);
|
||||
|
||||
_create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend);
|
||||
|
||||
magicSearch = linphone_magic_search_new(manager->lc);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "sip.test.org");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d");
|
||||
_check_friend_result_list(manager->lc, resultList, 0, sFriends[0], NULL);//"sip:charu@sip.test.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 1, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.test.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 2, sFriends[4], NULL);//"sip:hello@sip.test.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 3, sFriends[8], NULL);//"sip:laure@sip.test.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 4, sFriends[9], NULL);//"sip:loic@sip.test.org"
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
_remove_friends_from_list(lfl, sFriends, sSizeFriend);
|
||||
|
||||
LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(lfl, chloeSipUri);
|
||||
linphone_friend_list_remove_friend(lfl, fr);
|
||||
|
||||
if (chloeFriend) linphone_friend_unref(chloeFriend);
|
||||
|
||||
linphone_magic_search_unref(magicSearch);
|
||||
linphone_core_manager_destroy(manager);
|
||||
}
|
||||
|
||||
static void search_friend_all_domains(void) {
|
||||
LinphoneMagicSearch *magicSearch = NULL;
|
||||
bctbx_list_t *resultList = NULL;
|
||||
|
|
@ -727,15 +801,24 @@ static void search_friend_with_phone_number(void) {
|
|||
bctbx_list_t *resultList = NULL;
|
||||
LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE);
|
||||
LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc);
|
||||
LinphoneFriend *stephanieFriend = linphone_core_create_friend(manager->lc);
|
||||
LinphoneVcard *stephanieVcard = linphone_factory_create_vcard(linphone_factory_get());
|
||||
const char* stephanieName = {"stephanie de monaco"};
|
||||
const char* mariePhoneNumber = {"0633556644"};
|
||||
const char* stephaniePhoneNumber = {"0633889977"};
|
||||
|
||||
_create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend);
|
||||
|
||||
linphone_vcard_set_full_name(stephanieVcard, stephanieName); // stephanie de monaco
|
||||
linphone_vcard_add_phone_number(stephanieVcard, stephaniePhoneNumber);
|
||||
linphone_friend_set_vcard(stephanieFriend, stephanieVcard);
|
||||
linphone_core_add_friend(manager->lc, stephanieFriend);
|
||||
|
||||
linphone_friend_add_phone_number(linphone_friend_list_find_friend_by_uri(lfl, sFriends[5]), mariePhoneNumber);
|
||||
|
||||
magicSearch = linphone_magic_search_new(manager->lc);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", "");
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", "*");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 3, int, "%d");
|
||||
|
|
@ -791,8 +874,16 @@ static void search_friend_with_phone_number(void) {
|
|||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "55667", "sip.test.org");
|
||||
|
||||
BC_ASSERT_PTR_NULL(resultList);
|
||||
|
||||
_remove_friends_from_list(lfl, sFriends, sSizeFriend);
|
||||
|
||||
linphone_friend_list_remove_friend(lfl, stephanieFriend);
|
||||
if (stephanieFriend) linphone_friend_unref(stephanieFriend);
|
||||
if (stephanieVcard) linphone_vcard_unref(stephanieVcard);
|
||||
|
||||
linphone_magic_search_unref(magicSearch);
|
||||
linphone_core_manager_destroy(manager);
|
||||
}
|
||||
|
|
@ -802,7 +893,8 @@ static void search_friend_with_presence(void) {
|
|||
bctbx_list_t *resultList = NULL;
|
||||
LinphoneCoreManager* manager = linphone_core_manager_create("marie_rc");
|
||||
LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc);
|
||||
const char *chloeSipUri = "sip:chloe@sip.example.org";
|
||||
const char *chloeName = "chloe zaya";
|
||||
const char *chloeSipUri = "sip:ch@sip.example.org";
|
||||
const char *chloePhoneNumber = "0633556644";
|
||||
LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc);
|
||||
LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc);
|
||||
|
|
@ -815,6 +907,7 @@ static void search_friend_with_presence(void) {
|
|||
|
||||
_create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend);
|
||||
linphone_presence_model_set_contact(chloePresence, chloeSipUri);
|
||||
linphone_friend_set_name(chloeFriend, chloeName);
|
||||
linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber);
|
||||
linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence);
|
||||
linphone_friend_list_add_friend(lfl, chloeFriend);
|
||||
|
|
@ -824,11 +917,11 @@ static void search_friend_with_presence(void) {
|
|||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", "");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
// 3 + last address from filter "sip:33@sip.example.org"
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d");
|
||||
_check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+111223344@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 1, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 2, sFriends[10], NULL);//"sip:+33655667788@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 1, sFriends[10], NULL);//"sip:+111223344@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 2, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 3, "sip:33@sip.example.org", NULL);//"sip:33@sip.example.org"
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
|
|
@ -837,9 +930,9 @@ static void search_friend_with_presence(void) {
|
|||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "chloe", "");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
// 1 + last address from filter "sip:chloe@sip.example.org"
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d");
|
||||
_check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 1, "sip:chloe@sip.example.org", NULL);//"sip:chloe@sip.example.org"
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
|
|
@ -909,6 +1002,70 @@ static void search_friend_in_call_log(void) {
|
|||
linphone_core_manager_destroy(manager);
|
||||
}
|
||||
|
||||
static void search_friend_in_call_log_already_exist(void) {
|
||||
LinphoneMagicSearch *magicSearch = NULL;
|
||||
bctbx_list_t *resultList = NULL;
|
||||
LinphoneCoreManager* manager = linphone_core_manager_new2("marie_rc", FALSE);
|
||||
LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc);
|
||||
const char *ronanSipUri = {"sip:ronan@sip.example.org"};
|
||||
const char *chloeName = "chloe zaya";
|
||||
const char *chloeSipUri = "sip:chloe@sip.example.org";
|
||||
const char *chloePhoneNumber = "0633556644";
|
||||
LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc);
|
||||
LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc);
|
||||
LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(manager->lc);
|
||||
LinphoneAddress *ronanAddress = linphone_address_new(ronanSipUri);
|
||||
LinphoneAddress *chloeAddress = linphone_address_new(chloeSipUri);
|
||||
|
||||
linphone_proxy_config_edit(proxy);
|
||||
linphone_proxy_config_set_dial_prefix(proxy, "33");
|
||||
linphone_proxy_config_done(proxy);
|
||||
linphone_core_set_default_proxy(manager->lc, proxy);
|
||||
|
||||
linphone_presence_model_set_contact(chloePresence, chloeSipUri);
|
||||
linphone_friend_set_name(chloeFriend, chloeName);
|
||||
linphone_friend_set_address(chloeFriend, chloeAddress);
|
||||
linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber);
|
||||
linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence);
|
||||
linphone_friend_list_add_friend(lfl, chloeFriend);
|
||||
|
||||
_create_call_log(manager->lc, ronanAddress, chloeAddress);
|
||||
|
||||
_create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend);
|
||||
|
||||
magicSearch = linphone_magic_search_new(manager->lc);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "ch", "");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d");
|
||||
_check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, NULL);//"sip:chloe@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 1, sFriends[0], NULL);//"sip:charu@sip.test.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 2, sFriends[1], NULL);//"sip:charette@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 3, "sip:pauline@sip.example.org", NULL);//In the linphonerc "sip:pauline@sip.example.org"
|
||||
_check_friend_result_list(manager->lc, resultList, 4,"sip:ch@sip.example.org", NULL);//"sip:ch@sip.example.org"
|
||||
const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, 0);
|
||||
if (BC_ASSERT_PTR_NOT_NULL(sr)) {
|
||||
const LinphoneFriend *lf = linphone_search_result_get_friend(sr);
|
||||
BC_ASSERT_PTR_NOT_NULL(lf);
|
||||
}
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
_remove_friends_from_list(lfl, sFriends, sSizeFriend);
|
||||
|
||||
LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(lfl, chloeSipUri);
|
||||
linphone_friend_list_remove_friend(lfl, fr);
|
||||
|
||||
if (chloeFriend) linphone_friend_unref(chloeFriend);
|
||||
|
||||
if (chloeAddress) linphone_address_unref(chloeAddress);
|
||||
if (ronanAddress) linphone_address_unref(ronanAddress);
|
||||
|
||||
linphone_magic_search_unref(magicSearch);
|
||||
linphone_core_manager_destroy(manager);
|
||||
}
|
||||
|
||||
static void search_friend_last_item_is_filter(void) {
|
||||
LinphoneMagicSearch *magicSearch = NULL;
|
||||
bctbx_list_t *resultList = NULL;
|
||||
|
|
@ -1105,6 +1262,82 @@ static void search_friend_with_multiple_sip_address(void) {
|
|||
linphone_core_manager_destroy(manager);
|
||||
}
|
||||
|
||||
static void search_friend_with_same_address(void) {
|
||||
LinphoneMagicSearch *magicSearch = NULL;
|
||||
bctbx_list_t *resultList = NULL;
|
||||
LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE);
|
||||
LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc);
|
||||
const char *stephanieSipUri = {"sip:stephanie@sip.example.org"};
|
||||
LinphoneFriend *stephanieFriend1 = linphone_core_create_friend(manager->lc);
|
||||
LinphoneFriend *stephanieFriend2 = linphone_core_create_friend(manager->lc);
|
||||
LinphoneVcard *stephanieVcard1 = linphone_factory_create_vcard(linphone_factory_get());
|
||||
LinphoneVcard *stephanieVcard2 = linphone_factory_create_vcard(linphone_factory_get());
|
||||
const char *stephanieName = {"stephanie delarue"};
|
||||
|
||||
_create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend);
|
||||
|
||||
linphone_vcard_set_full_name(stephanieVcard1, stephanieName); // stephanie delarue
|
||||
linphone_vcard_set_url(stephanieVcard1, stephanieSipUri); //sip:stephanie@sip.example.org
|
||||
linphone_vcard_add_sip_address(stephanieVcard1, stephanieSipUri);
|
||||
linphone_friend_set_vcard(stephanieFriend1, stephanieVcard1);
|
||||
linphone_core_add_friend(manager->lc, stephanieFriend1);
|
||||
|
||||
linphone_vcard_set_full_name(stephanieVcard2, stephanieName); // stephanie delarue
|
||||
linphone_vcard_set_url(stephanieVcard2, stephanieSipUri); //sip:stephanie@sip.example.org
|
||||
linphone_vcard_add_sip_address(stephanieVcard2, stephanieSipUri);
|
||||
linphone_friend_set_vcard(stephanieFriend2, stephanieVcard2);
|
||||
linphone_core_add_friend(manager->lc, stephanieFriend2);
|
||||
|
||||
magicSearch = linphone_magic_search_new(manager->lc);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "stephanie", "");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d");
|
||||
_check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri, NULL);//"sip:stephanie@sip.example.org"
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
linphone_magic_search_reset_search_cache(magicSearch);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "delarue", "");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d");
|
||||
_check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri, NULL);//"sip:stephanie@sip.example.org"
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
linphone_magic_search_reset_search_cache(magicSearch);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), S_SIZE_FRIEND+1, int, "%d");
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
linphone_magic_search_reset_search_cache(magicSearch);
|
||||
|
||||
resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "*");
|
||||
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
BC_ASSERT_EQUAL(bctbx_list_size(resultList), S_SIZE_FRIEND+1, int, "%d");
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
||||
_remove_friends_from_list(lfl, sFriends, sSizeFriend);
|
||||
linphone_friend_list_remove_friend(lfl, stephanieFriend1);
|
||||
linphone_friend_list_remove_friend(lfl, stephanieFriend2);
|
||||
if (stephanieFriend1) linphone_friend_unref(stephanieFriend1);
|
||||
if (stephanieFriend2) linphone_friend_unref(stephanieFriend2);
|
||||
if (stephanieVcard1) linphone_vcard_unref(stephanieVcard1);
|
||||
if (stephanieVcard2) linphone_vcard_unref(stephanieVcard2);
|
||||
|
||||
linphone_magic_search_unref(magicSearch);
|
||||
linphone_core_manager_destroy(manager);
|
||||
}
|
||||
|
||||
static void search_friend_large_database(void) {
|
||||
char *dbPath = bc_tester_res("db/friends.db");
|
||||
char *searchedFriend = "6295103032641994169";
|
||||
|
|
@ -1120,9 +1353,11 @@ static void search_friend_large_database(void) {
|
|||
liblinphone_tester_clock_start(&start);
|
||||
bctbx_list_t *resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, subBuff, "");
|
||||
if (BC_ASSERT_PTR_NOT_NULL(resultList)) {
|
||||
long long time;
|
||||
ms_get_cur_time(¤t);
|
||||
ms_message("Searching time: %lld ms",
|
||||
((current.tv_sec - start.tv_sec) * 1000LL) + ((current.tv_nsec - start.tv_nsec) / 1000000LL));
|
||||
time = ((current.tv_sec - start.tv_sec) * 1000LL) + ((current.tv_nsec - start.tv_nsec) / 1000000LL);
|
||||
ms_message("Searching time: %lld ms", time);
|
||||
BC_ASSERT_LOWER(time, 10000, long long, "%lld");
|
||||
ms_message("List size: %zu", bctbx_list_size(resultList));
|
||||
bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref);
|
||||
}
|
||||
|
|
@ -1151,7 +1386,8 @@ test_t setup_tests[] = {
|
|||
TEST_NO_TAG("Codec setup", codec_setup),
|
||||
TEST_NO_TAG("Custom tones setup", custom_tones_setup),
|
||||
TEST_ONE_TAG("Return friend list in alphabetical order", search_friend_in_alphabetical_order, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend without filter", search_friend_without_filter, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend without filter and domain", search_friend_without_filter, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend with domain and without filter", search_friend_with_domain_without_filter, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend from all domains", search_friend_all_domains, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend from one domain", search_friend_one_domain, "MagicSearch"),
|
||||
TEST_ONE_TAG("Multiple looking for friends with the same cache", search_friend_research_estate, "MagicSearch"),
|
||||
|
|
@ -1159,10 +1395,12 @@ test_t setup_tests[] = {
|
|||
TEST_ONE_TAG("Search friend with phone number", search_friend_with_phone_number, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend and find it with its presence", search_friend_with_presence, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend in call log", search_friend_in_call_log, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend in call log but don't add address which already exist", search_friend_in_call_log_already_exist, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend last item is the filter", search_friend_last_item_is_filter, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend with name", search_friend_with_name, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend with uppercase name", search_friend_with_name_with_uppercase, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend with multiple sip address", search_friend_with_multiple_sip_address, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend with same address", search_friend_with_same_address, "MagicSearch"),
|
||||
TEST_ONE_TAG("Search friend in large friends database", search_friend_large_database, "MagicSearch")
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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"
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
Loading…
Add table
Reference in a new issue