Commit b2b1c01a authored by Nicolas Michon's avatar Nicolas Michon

Change the way linphone specs are managed

parent 8b91bfa5
......@@ -1371,7 +1371,8 @@ static void sip_config_read(LinphoneCore *lc) {
lc->sal->useNoInitialRoute(!!lp_config_get_int(lc->config,"sip","use_no_initial_route",0));
lc->sal->useRport(!!lp_config_get_int(lc->config,"sip","use_rport",1));
lc->sal->setContactLinphoneSpecs(lp_config_get_string(lc->config, "sip", "linphone_specs", ""));
linphone_core_set_linphone_specs(lc, lp_config_get_string(lc->config, "sip", "linphone_specs", ""));
if (!lp_config_get_int(lc->config,"sip","ipv6_migration_done",FALSE) && lp_config_has_entry(lc->config,"sip","use_ipv6")) {
lp_config_clean_entry(lc->config,"sip","use_ipv6");
......@@ -7638,12 +7639,3 @@ bool_t linphone_core_has_crappy_opengl(LinphoneCore *lc) {
if (sound_description->flags & DEVICE_HAS_CRAPPY_OPENGL) return TRUE;
return FALSE;
}
const char *linphone_core_get_linphone_specs (const LinphoneCore *core) {
return lp_config_get_string(linphone_core_get_config(core), "sip", "linphone_specs", NULL);
}
void linphone_core_set_linphone_specs (LinphoneCore *core, const char *specs) {
lp_config_set_string(linphone_core_get_config(core), "sip", "linphone_specs", specs);
core->sal->setContactLinphoneSpecs(L_C_TO_STRING(specs));
}
......@@ -155,7 +155,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cf
ms_error("Cannot create default nat policy with ref [%s] for proxy config [%p]",nat_policy_ref,cfg);
}
}
cfg->conference_factory_uri = conference_factory_uri ? ms_strdup(conference_factory_uri) : NULL;
linphone_proxy_config_set_conference_factory_uri(cfg, conference_factory_uri ? ms_strdup(conference_factory_uri) : NULL);
}
LinphoneProxyConfig *linphone_proxy_config_new() {
......@@ -1584,8 +1584,10 @@ void linphone_proxy_config_set_conference_factory_uri(LinphoneProxyConfig *cfg,
bctbx_free(cfg->conference_factory_uri);
cfg->conference_factory_uri = nullptr;
}
if (uri)
if (uri) {
cfg->conference_factory_uri = bctbx_strdup(uri);
linphone_core_add_linphone_spec(cfg->lc, "groupchat");
}
}
const char * linphone_proxy_config_get_conference_factory_uri(const LinphoneProxyConfig *cfg) {
......
......@@ -5181,30 +5181,63 @@ LINPHONE_PUBLIC bool_t linphone_core_is_content_type_supported(const LinphoneCor
*/
LINPHONE_PUBLIC void linphone_core_add_content_type_support(LinphoneCore *lc, const char *content_type);
/**
* Remove support for the specified content type.
* It is the application responsibility to handle it correctly afterwards.
* @param[in] lc LinphoneCore object
* @param[in] content_type The content type to remove support for
*/
LINPHONE_PUBLIC void linphone_core_remove_content_type_support(LinphoneCore *lc, const char *content_type);
/**
* Get the linphone specs value telling what functionalities the linphone client supports.
* @param[in] core #LinphoneCore object
* @return The linphone specs telling what functionalities the linphone client supports
* @ingroup initializing
* @deprecated Use linphone_core_get_linphone_specs_list instead. Deprecated since 2019-02-07
*/
LINPHONE_PUBLIC const char *linphone_core_get_linphone_specs (const LinphoneCore *core);
LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_linphone_specs (const LinphoneCore *core);
/**
* Set the linphone specs value telling what functionalities the linphone client supports.
* @param[in] core #LinphoneCore object
* @param[in] specs The linphone specs to set
* @ingroup initializing
* @deprecated Use linphone_core_set_linphone_specs_list or linphone_core_add_linphone_spec instead. Deprecated since 2019-02-07
*/
LINPHONE_PUBLIC void linphone_core_set_linphone_specs (LinphoneCore *core, const char *specs);
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_linphone_specs (LinphoneCore *core, const char *specs);
/**
* Remove support for the specified content type.
* It is the application responsibility to handle it correctly afterwards.
* @param[in] lc LinphoneCore object
* @param[in] content_type The content type to remove support for
* Set the linphone specs list value telling what functionalities the linphone client supports.
* @param[in] core #LinphoneCore object
* @param[in] specs \bctbx_list{char *} The list of string specs to set
* @ingroup initializing
*/
LINPHONE_PUBLIC void linphone_core_remove_content_type_support(LinphoneCore *lc, const char *content_type);
LINPHONE_PUBLIC void linphone_core_set_linphone_specs_list (LinphoneCore *core, const bctbx_list_t *specs);
/**
* Add the given linphone specs to the list of functionalities the linphone client supports.
* @param[in] core #LinphoneCore object
* @param[in] spec The spec to add
* @ingroup initializing
*/
LINPHONE_PUBLIC void linphone_core_add_linphone_spec (LinphoneCore *core, const char *spec);
/**
* Remove the given linphone specs from the list of functionalities the linphone client supports.
* @param[in] core #LinphoneCore object
* @param[in] spec The spec to remove
* @ingroup initializing
*/
LINPHONE_PUBLIC void linphone_core_remove_linphone_spec (LinphoneCore *core, const char *spec);
/**
* Get the list of linphone specs string values representing what functionalities the linphone client supports
* @param[in] core #LinphoneCore object
* @return \bctbx_list{char *} a list of supported specs. The list must be freed with bctbx_list_free() after usage
* @ingroup initializing
*/
LINPHONE_PUBLIC const bctbx_list_t *linphone_core_get_linphone_specs_list (LinphoneCore *core);
/**
* @addtogroup chatroom
......
......@@ -110,10 +110,15 @@ namespace Utils {
template<typename S, typename T>
inline std::string join (const std::vector<T>& elems, const S& delim) {
std::stringstream ss;
auto e = elems.begin();
ss << *e++;
for (; e != elems.end(); ++e)
ss << delim << *e;
for (auto e = elems.begin(); e != elems.end();) {
if (e != elems.end()) {
ss << *e;
}
if (++e != elems.end()) {
ss << delim;
}
}
return ss.str();
}
LINPHONE_PUBLIC std::string trim (const std::string &str);
......@@ -124,6 +129,21 @@ namespace Utils {
return object;
}
template<class Container>
inline std::vector<typename Container::value_type> toVector(const Container &l) {
std::vector<typename Container::value_type> v;
v.reserve(l.size());
std::copy(std::begin(l), std::end(l), std::back_inserter(v));
return v;
}
template<class Container>
inline std::list<typename Container::value_type> toList(const Container &l) {
std::list<typename Container::value_type> v;
std::copy(std::begin(l), std::end(l), std::back_inserter(v));
return v;
}
LINPHONE_PUBLIC std::tm getTimeTAsTm (time_t t);
LINPHONE_PUBLIC time_t getTmAsTimeT (const std::tm &t);
......
......@@ -18,7 +18,7 @@
*/
#include "linphone/wrapper_utils.h"
#include "linphone/utils/utils.h"
#include "c-wrapper/c-wrapper.h"
#include "core/core.h"
......@@ -83,3 +83,29 @@ void linphone_core_delete_local_encryption_db (const LinphoneCore *lc) {
if (encryptionEngine)
encryptionEngine->cleanDb();
}
//Deprecated
const char *linphone_core_get_linphone_specs (const LinphoneCore *lc) {
return lp_config_get_string(linphone_core_get_config(lc), "sip", "linphone_specs", NULL);
}
//Deprecated
void linphone_core_set_linphone_specs (LinphoneCore *lc, const char *specs) {
L_GET_CPP_PTR_FROM_C_OBJECT(lc)->setSpecs(Utils::cStringToCppString(specs));
}
void linphone_core_set_linphone_specs_list (LinphoneCore *lc, const bctbx_list_t *specs) {
L_GET_CPP_PTR_FROM_C_OBJECT(lc)->setSpecsList(L_GET_CPP_LIST_FROM_C_LIST(specs, const char *, string));
}
void linphone_core_add_linphone_spec (LinphoneCore *lc, const char *spec) {
L_GET_CPP_PTR_FROM_C_OBJECT(lc)->addSpec(Utils::cStringToCppString(spec));
}
void linphone_core_remove_linphone_spec (LinphoneCore *lc, const char *spec) {
L_GET_CPP_PTR_FROM_C_OBJECT(lc)->removeSpec(Utils::cStringToCppString(spec));
}
const bctbx_list_t *linphone_core_get_linphone_specs_list (LinphoneCore *lc) {
return L_GET_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getSpecsList());
}
......@@ -533,25 +533,32 @@ public:
// ---------------------------------------------------------------------------
template<typename T>
static inline bctbx_list_t *getCListFromCppList (const std::list<T *> &cppList) {
static inline bctbx_list_t *getCListFromCppList (const std::list<T> &cppList) {
bctbx_list_t *result = nullptr;
for (const auto &value : cppList)
result = bctbx_list_append(result, value);
return result;
}
template<typename T>
static inline std::list<T *> getCppListFromCList (const bctbx_list_t *cList) {
std::list<T> result;
//Specialization for string lists
static inline bctbx_list_t *getCListFromCppList (const std::list<std::string> &cppList) {
bctbx_list_t *result = nullptr;
for (const auto &value : cppList)
result = bctbx_list_append(result, static_cast<void *>(bctbx_strdup(value.c_str())));
return result;
}
template<typename CType, typename CppType>
static inline std::list<CppType> getCppListFromCList (const bctbx_list_t *cList) {
std::list<CppType> result;
for (auto it = cList; it; it = bctbx_list_next(it))
result.push_back(static_cast<T>(bctbx_list_get_data(it)));
result.push_back(CppType(static_cast<CType>(bctbx_list_get_data(it))));
return result;
}
// ---------------------------------------------------------------------------
// Resolved list conversions.
// ---------------------------------------------------------------------------
template<
typename CppType,
typename = typename std::enable_if<IsDefinedBaseCppObject<CppType>::value, CppType>::type
......@@ -855,8 +862,8 @@ LINPHONE_END_NAMESPACE
// Transforms cpp list and c list.
#define L_GET_C_LIST_FROM_CPP_LIST(CPP_LIST) \
LinphonePrivate::Wrapper::getCListFromCppList(CPP_LIST)
#define L_GET_CPP_LIST_FROM_C_LIST(C_LIST, TYPE) \
LinphonePrivate::Wrapper::getCppListFromCList<TYPE>(C_LIST)
#define L_GET_CPP_LIST_FROM_C_LIST(C_LIST, CTYPE, CPPTYPE) \
LinphonePrivate::Wrapper::getCppListFromCList<CTYPE, CPPTYPE>(C_LIST)
// Transforms cpp list and c list and convert cpp object to c object.
#define L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(CPP_LIST) \
......
......@@ -26,6 +26,8 @@
#include "core/core-p.h"
#include "c-wrapper/c-wrapper.h"
#include "linphone/utils/algorithm.h"
// =============================================================================
using namespace std;
......@@ -55,7 +57,7 @@ public:
void sendChatMessage (const shared_ptr<ChatMessage> &chatMessage) override {
L_Q();
ProxyChatRoomPrivate::sendChatMessage(chatMessage);
const char *specs = linphone_core_get_linphone_specs(chatMessage->getCore()->getCCore());
const list<string> &specs = chatMessage->getCore()->getSpecsList();
time_t currentRealTime = ms_time(nullptr);
LinphoneAddress *lAddr = linphone_address_new(
chatMessage->getChatRoom()->getConferenceId().getLocalAddress().asString().c_str()
......@@ -68,7 +70,7 @@ public:
if (!conferenceFactoryUri
|| (chatRoom->getCapabilities() & ChatRoom::Capabilities::Conference)
|| clientGroupChatRoom
|| !specs || !strstr(specs, "groupchat")
|| findIf(specs, [] (const string &spec) { return spec.find("groupchat") != string::npos;}) == specs.cend()
|| ((currentRealTime - migrationRealTime) <
linphone_config_get_int(linphone_core_get_config(chatMessage->getCore()->getCCore()),
"misc", "basic_to_client_group_chat_room_migration_timer", 86400) // Try migration every 24 hours
......
......@@ -99,6 +99,8 @@ private:
std::unique_ptr<EncryptionEngine> imee;
std::list<std::string> specs;
// Ugly cache to deal with C code.
std::unordered_map<const AbstractChatRoom *, std::shared_ptr<const AbstractChatRoom>> noCreatedClientGroupChatRooms;
......
......@@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <algorithm>
#include <mediastreamer2/mscommon.h>
#include <xercesc/util/PlatformUtils.hpp>
......@@ -32,6 +33,9 @@
#include "core/core-p.h"
#include "logger/logger.h"
#include "paths/paths.h"
#include "linphone/utils/utils.h"
#include "linphone/utils/algorithm.h"
#include "linphone/lpconfig.h"
// TODO: Remove me later.
#include "c-wrapper/c-wrapper.h"
......@@ -220,6 +224,7 @@ void Core::enableLimeX3dh (bool enable) {
if (!enable) {
if (d->imee != nullptr)
d->imee.release();
removeSpec("lime");
return;
}
......@@ -243,6 +248,7 @@ void Core::enableLimeX3dh (bool enable) {
LimeX3dhEncryptionEngine *engine = new LimeX3dhEncryptionEngine(dbAccess, serverUrl, prov, getSharedFromThis());
setEncryptionEngine(engine);
d->registerListener(engine);
addSpec("lime");
}
#else
lWarning() << "Lime X3DH support is not available";
......@@ -283,6 +289,56 @@ bool Core::limeX3dhAvailable() const {
#endif
}
// -----------------------------------------------------------------------------
// Specs.
// -----------------------------------------------------------------------------
void Core::setSpecsList (const std::list<std::string> &specsList) {
L_D();
d->specs = specsList;
d->specs.unique();
const string tmpSpecs = getSpecs();
LinphoneConfig *lpconfig = linphone_core_get_config(getCCore());
linphone_config_set_string(lpconfig, "sip", "linphone_specs", tmpSpecs.c_str());
getCCore()->sal->setContactLinphoneSpecs(tmpSpecs);
//lInfo() << "DEBUG SETTING LINPHONE SPECS LIST::::: [" << tmpSpecs << "]" << d->specs.size() << std::endl;
}
void Core::addSpec (const std::string &spec) {
L_D();
d->specs.push_back(spec);
setSpecsList(d->specs);
}
void Core::removeSpec(const std::string &pSpec) {
L_D();
d->specs.remove_if([&pSpec](const std::string &spec) { return spec.compare(pSpec) == 0; });
setSpecsList(d->specs);
}
const std::list<std::string> &Core::getSpecsList () const {
L_D();
return d->specs;
}
//Deprecated
void Core::setSpecs (const std::string &pSpecs) {
L_D();
if (pSpecs.empty()) {
d->specs.clear();
setSpecsList(d->specs);
} else {
//Assume a list of coma-separated values
setSpecsList(Utils::toList(Utils::split(pSpecs, ",")));
}
}
//Initial use of the public API of this function has been deprecated, but will still be kept as utility function for setSpecsList()
std::string Core::getSpecs() const {
L_D();
return Utils::join(Utils::toVector(d->specs), ",");
}
// -----------------------------------------------------------------------------
// Misc.
// -----------------------------------------------------------------------------
......
......@@ -146,6 +146,17 @@ public:
bool limeX3dhEnabled () const;
bool limeX3dhAvailable () const;
// ---------------------------------------------------------------------------
// Specs.
// ---------------------------------------------------------------------------
void setSpecsList(const std::list<std::string> &specsList);
void addSpec (const std::string &spec);
void removeSpec (const std::string &spec);
const std::list<std::string> &getSpecsList () const;
void setSpecs (const std::string &specs);
std::string getSpecs() const;
// ---------------------------------------------------------------------------
// Misc.
// ---------------------------------------------------------------------------
......
......@@ -664,7 +664,7 @@ int SalOp::sendRequestAndCreateRefresher (belle_sip_request_t *request, int expi
belle_sip_refresher_stop(mRefresher);
belle_sip_object_unref(mRefresher);
}
//As stated a few lines below, "we should remove our context from the transaction", including op
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(mPendingClientTransaction), nullptr);
mRefresher = belle_sip_client_transaction_create_refresher(mPendingClientTransaction);
......@@ -721,7 +721,7 @@ belle_sip_header_contact_t *SalOp::createContact () {
}
}
if (!mRoot->mLinphoneSpecs.empty()
&& !belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contactHeader), "+org.linphone.specs")
&& !belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contactHeader), "+org.linphone.specs")
) {
stringstream ss;
ss << "\"" << mRoot->mLinphoneSpecs << "\"";
......
......@@ -182,7 +182,6 @@ public:
void setContactLinphoneSpecs (const std::string &value) { mLinphoneSpecs = value; }
// ---------------------------------------------------------------------------
// Network parameters
// ---------------------------------------------------------------------------
......
......@@ -185,7 +185,6 @@ void configure_core_for_conference (LinphoneCore *core, const char* username, co
LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(core);
linphone_proxy_config_set_conference_factory_uri(proxy, factoryUri);
bctbx_free(factoryUri);
linphone_core_set_linphone_specs(core, linphone_core_lime_x3dh_available(core) ? "groupchat,lime" : "groupchat");
}
void _configure_core_for_conference (LinphoneCoreManager *lcm, LinphoneAddress *factoryAddr) {
......@@ -545,7 +544,7 @@ static void group_chat_room_add_participant (void) {
coresManagerList = bctbx_list_append(coresManagerList, laure);
coresManagerList = bctbx_list_append(coresManagerList, chloe);
bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
linphone_core_set_linphone_specs(chloe->lc, ""); // Disable group chat for Chloe
linphone_core_remove_linphone_spec(chloe->lc, "groupchat");
start_core_for_conference(coresManagerList);
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(marie->lc)));
......@@ -2294,7 +2293,7 @@ static void group_chat_room_fallback_to_basic_chat_room (void) {
coresManagerList = bctbx_list_append(coresManagerList, marie);
coresManagerList = bctbx_list_append(coresManagerList, pauline);
bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
linphone_core_set_linphone_specs(pauline->lc, NULL);
linphone_core_remove_linphone_spec(pauline->lc, "groupchat");
start_core_for_conference(coresManagerList);
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc)));
stats initialMarieStats = marie->stat;
......@@ -2349,8 +2348,8 @@ static void group_chat_room_creation_fails_if_invited_participants_dont_support_
coresManagerList = bctbx_list_append(coresManagerList, pauline);
coresManagerList = bctbx_list_append(coresManagerList, laure);
bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
linphone_core_set_linphone_specs(pauline->lc, NULL);
linphone_core_set_linphone_specs(laure->lc, NULL);
linphone_core_remove_linphone_spec(pauline->lc, "groupchat");
linphone_core_remove_linphone_spec(laure->lc, "groupchat");
start_core_for_conference(coresManagerList);
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc)));
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc)));
......@@ -2390,7 +2389,7 @@ static void group_chat_room_creation_successful_if_at_least_one_invited_particip
coresManagerList = bctbx_list_append(coresManagerList, pauline);
coresManagerList = bctbx_list_append(coresManagerList, laure);
bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
linphone_core_set_linphone_specs(laure->lc, NULL);
linphone_core_remove_linphone_spec(laure->lc, "groupchat");
start_core_for_conference(coresManagerList);
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc)));
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc)));
......@@ -2536,7 +2535,7 @@ static void group_chat_room_migrate_from_basic_to_client_fail (void) {
coresManagerList = bctbx_list_append(coresManagerList, marie);
coresManagerList = bctbx_list_append(coresManagerList, pauline);
bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
linphone_core_set_linphone_specs(pauline->lc, NULL);
linphone_core_remove_linphone_spec(pauline->lc, "groupchat");
start_core_for_conference(coresManagerList);
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc)));
stats initialMarieStats = marie->stat;
......@@ -2632,7 +2631,7 @@ static void group_chat_room_migrate_from_basic_to_client_fail (void) {
tmpCoresManagerList = bctbx_list_append(NULL, pauline);
tmpCoresList = init_core_for_conference(tmpCoresManagerList);
lp_config_set_int(linphone_core_get_config(pauline->lc), "misc", "enable_basic_to_client_group_chat_room_migration", 1);
linphone_core_set_linphone_specs(pauline->lc, "groupchat");
linphone_core_add_linphone_spec(pauline->lc, "groupchat");
bctbx_list_free(tmpCoresManagerList);
coresList = bctbx_list_concat(coresList, tmpCoresList);
linphone_core_manager_start(pauline, TRUE);
......
......@@ -1866,9 +1866,9 @@ static void notify_friend_capabilities(void) {
LinphoneCoreManager *chloe2 = linphone_core_manager_create("chloe_rc");
LinphoneCoreManager *chloe3 = linphone_core_manager_create("chloe_rc");
linphone_core_set_linphone_specs(pauline->lc, "groupchat/1.1");
linphone_core_set_linphone_specs(pauline2->lc, "lime");
linphone_core_set_linphone_specs(laure->lc, "groupchat/2.0");
linphone_core_add_linphone_spec(pauline->lc, "groupchat/1.1");
linphone_core_add_linphone_spec(pauline2->lc, "lime");
linphone_core_add_linphone_spec(laure->lc, "groupchat/2.0");
linphone_core_set_linphone_specs(chloe->lc, "groupchat/2.1, lime/1.5");
linphone_core_set_linphone_specs(chloe3->lc, "groupchat/2.1, lime/1.7");
......
......@@ -10,6 +10,7 @@ allow_message_in_unsafe_chatroom=0
unsafe_if_sas_refused=1
x3dh_server_url=http://x3dh.example.org:8082/flexisip-account-manager/x3dh-25519.php
[sip]
sip_port=-1
sip_tcp_port=-1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment