Commit 4fd4f8f0 authored by Adrien Béraud's avatar Adrien Béraud

Config: factor code in *Account superclasses

Refs #53127

Change-Id: I3266a4e8ee366ec2ee534df9f1406af908b99620
parent 763369bf
......@@ -46,6 +46,10 @@
#include "manager.h"
#include "client/configurationmanager.h"
#include "account_schema.h"
#include "config/yamlparser.h"
#include <yaml-cpp/yaml.h>
const char * const Account::AUDIO_CODECS_KEY = "audioCodecs"; // 0/9/110/111/112/
const char * const Account::VIDEO_CODECS_KEY = "videoCodecs";
......@@ -160,6 +164,92 @@ void Account::loadDefaultCodecs()
#endif
}
void Account::serialize(YAML::Emitter &out)
{
using namespace Conf;
out << YAML::Key << ID_KEY << YAML::Value << accountID_;
out << YAML::Key << ALIAS_KEY << YAML::Value << alias_;
out << YAML::Key << ACCOUNT_ENABLE_KEY << YAML::Value << enabled_;
out << YAML::Key << TYPE_KEY << YAML::Value << getAccountType();
out << YAML::Key << AUDIO_CODECS_KEY << YAML::Value << audioCodecStr_;
out << YAML::Key << MAILBOX_KEY << YAML::Value << mailBox_;
out << YAML::Key << ACCOUNT_AUTOANSWER_KEY << YAML::Value << autoAnswerEnabled_;
out << YAML::Key << RINGTONE_ENABLED_KEY << YAML::Value << ringtoneEnabled_;
out << YAML::Key << RINGTONE_PATH_KEY << YAML::Value << ringtonePath_;
out << YAML::Key << HAS_CUSTOM_USER_AGENT_KEY << YAML::Value << hasCustomUserAgent_;
out << YAML::Key << USER_AGENT_KEY << YAML::Value << userAgent_;
out << YAML::Key << USERNAME_KEY << YAML::Value << username_;
out << YAML::Key << DISPLAY_NAME_KEY << YAML::Value << displayName_;
out << YAML::Key << HOSTNAME_KEY << YAML::Value << hostname_;
}
void Account::unserialize(const YAML::Node &node)
{
using namespace yaml_utils;
parseValue(node, ALIAS_KEY, alias_);
parseValue(node, ACCOUNT_ENABLE_KEY, enabled_);
parseValue(node, USERNAME_KEY, username_);
parseValue(node, ACCOUNT_AUTOANSWER_KEY, autoAnswerEnabled_);
//parseValue(node, PASSWORD_KEY, password_);
parseValue(node, MAILBOX_KEY, mailBox_);
parseValue(node, AUDIO_CODECS_KEY, audioCodecStr_);
// Update codec list which one is used for SDP offer
setActiveAudioCodecs(split_string(audioCodecStr_));
parseValue(node, DISPLAY_NAME_KEY, displayName_);
parseValue(node, HOSTNAME_KEY, hostname_);
parseValue(node, HAS_CUSTOM_USER_AGENT_KEY, hasCustomUserAgent_);
parseValue(node, USER_AGENT_KEY, userAgent_);
parseValue(node, RINGTONE_PATH_KEY, ringtonePath_);
parseValue(node, RINGTONE_ENABLED_KEY, ringtoneEnabled_);
}
void Account::setAccountDetails(const std::map<std::string, std::string> &details)
{
// Account setting common to SIP and IAX
parseString(details, CONFIG_ACCOUNT_ALIAS, alias_);
parseBool(details, CONFIG_ACCOUNT_ENABLE, enabled_);
parseString(details, CONFIG_ACCOUNT_USERNAME, username_);
parseString(details, CONFIG_ACCOUNT_HOSTNAME, hostname_);
parseString(details, CONFIG_ACCOUNT_MAILBOX, mailBox_);
parseString(details, CONFIG_ACCOUNT_USERAGENT, userAgent_);
parseBool(details, CONFIG_ACCOUNT_AUTOANSWER, autoAnswerEnabled_);
parseBool(details, CONFIG_RINGTONE_ENABLED, ringtoneEnabled_);
parseString(details, CONFIG_RINGTONE_PATH, ringtonePath_);
parseBool(details, CONFIG_ACCOUNT_HAS_CUSTOM_USERAGENT, hasCustomUserAgent_);
if (hasCustomUserAgent_)
parseString(details, CONFIG_ACCOUNT_USERAGENT, userAgent_);
else
userAgent_ = DEFAULT_USER_AGENT;
}
std::map<std::string, std::string> Account::getAccountDetails() const
{
std::map<std::string, std::string> a;
a[CONFIG_ACCOUNT_ALIAS] = alias_;
a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? "true" : "false";
a[CONFIG_ACCOUNT_TYPE] = getAccountType();
a[CONFIG_ACCOUNT_HOSTNAME] = hostname_;
a[CONFIG_ACCOUNT_USERNAME] = username_;
a[CONFIG_ACCOUNT_MAILBOX] = mailBox_;
RegistrationState state(registrationState_);
a[CONFIG_ACCOUNT_REGISTRATION_STATUS] = mapStateNumberToString(state);
a[CONFIG_ACCOUNT_USERAGENT] = hasCustomUserAgent_ ? userAgent_ : DEFAULT_USER_AGENT;
a[CONFIG_ACCOUNT_HAS_CUSTOM_USERAGENT] = hasCustomUserAgent_ ? TRUE_STR : FALSE_STR;
a[CONFIG_ACCOUNT_AUTOANSWER] = autoAnswerEnabled_ ? TRUE_STR : FALSE_STR;
a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? TRUE_STR : FALSE_STR;
a[CONFIG_RINGTONE_PATH] = ringtonePath_;
return a;
}
#ifdef SFL_VIDEO
static bool
isPositiveInteger(const string &s)
......
......@@ -53,6 +53,11 @@ class VoipLinkException : public std::runtime_error {
std::runtime_error("VoipLinkException occured: " + str) {}
};
namespace YAML {
class Emitter;
class Node;
}
/**
* @file account.h
* @brief Interface to protocol account (SIPAccount, IAXAccount)
......@@ -79,15 +84,18 @@ class Account : public Serializable {
*/
void freeAccount();
virtual void setAccountDetails(const std::map<std::string, std::string> &details) = 0;
virtual void setAccountDetails(const std::map<std::string, std::string> &details);
virtual std::map<std::string, std::string> getAccountDetails() const = 0;
virtual std::map<std::string, std::string> getAccountDetails() const;
/**
* Load the settings for this account.
*/
virtual void loadConfig() = 0;
virtual void serialize(YAML::Emitter &out);
virtual void unserialize(const YAML::Node &node);
/**
* Get the account ID
* @return constant account id
......
......@@ -58,64 +58,29 @@ void IAXAccount::serialize(YAML::Emitter &out)
using namespace Conf;
out << YAML::BeginMap;
out << YAML::Key << ALIAS_KEY << YAML::Value << alias_;
out << YAML::Key << AUDIO_CODECS_KEY << YAML::Value << audioCodecStr_;
out << YAML::Key << ACCOUNT_ENABLE_KEY << YAML::Value << enabled_;
out << YAML::Key << MAILBOX_KEY << YAML::Value << mailBox_;
Account::serialize(out);
out << YAML::Key << PASSWORD_KEY << YAML::Value << password_;
out << YAML::Key << TYPE_KEY << YAML::Value << ACCOUNT_TYPE;
out << YAML::Key << USER_AGENT_KEY << YAML::Value << userAgent_;
out << YAML::Key << USERNAME_KEY << YAML::Value << username_;
out << YAML::EndMap;
}
void IAXAccount::unserialize(const YAML::Node &node)
{
using namespace yaml_utils;
parseValue(node, ALIAS_KEY, alias_);
parseValue(node, USERNAME_KEY, username_);
Account::unserialize(node);
parseValue(node, PASSWORD_KEY, password_);
parseValue(node, HOSTNAME_KEY, hostname_);
parseValue(node, ACCOUNT_ENABLE_KEY, enabled_);
parseValue(node, MAILBOX_KEY, mailBox_);
parseValue(node, AUDIO_CODECS_KEY, audioCodecStr_);
// Update codec list which one is used for SDP offer
setActiveAudioCodecs(split_string(audioCodecStr_));
parseValue(node, DISPLAY_NAME_KEY, displayName_);
parseValue(node, USER_AGENT_KEY, userAgent_);
}
void IAXAccount::setAccountDetails(const std::map<std::string, std::string> &details)
{
// Account setting common to SIP and IAX
parseString(details, CONFIG_ACCOUNT_ALIAS, alias_);
parseString(details, CONFIG_ACCOUNT_USERNAME, username_);
parseString(details, CONFIG_ACCOUNT_HOSTNAME, hostname_);
Account::setAccountDetails(details);
parseString(details, CONFIG_ACCOUNT_PASSWORD, password_);
parseBool(details, CONFIG_ACCOUNT_ENABLE, enabled_);
parseString(details, CONFIG_ACCOUNT_MAILBOX, mailBox_);
parseString(details, CONFIG_ACCOUNT_USERAGENT, userAgent_);
}
std::map<std::string, std::string> IAXAccount::getAccountDetails() const
{
std::map<std::string, std::string> a;
a[CONFIG_ACCOUNT_ALIAS] = alias_;
a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? "true" : "false";
a[CONFIG_ACCOUNT_TYPE] = ACCOUNT_TYPE;
a[CONFIG_ACCOUNT_HOSTNAME] = hostname_;
a[CONFIG_ACCOUNT_USERNAME] = username_;
std::map<std::string, std::string> a = Account::getAccountDetails();
a[CONFIG_ACCOUNT_PASSWORD] = password_;
a[CONFIG_ACCOUNT_MAILBOX] = mailBox_;
RegistrationState state(registrationState_);
a[CONFIG_ACCOUNT_REGISTRATION_STATUS] = mapStateNumberToString(state);
a[CONFIG_ACCOUNT_USERAGENT] = userAgent_;
return a;
}
......
......@@ -54,6 +54,9 @@ class IAXAccount : public Account {
IAXAccount(const std::string& accountID);
virtual void serialize(YAML::Emitter &out);
virtual void unserialize(const YAML::Node &node);
const char* getAccountType() const {
return ACCOUNT_TYPE;
}
......@@ -126,8 +129,7 @@ class IAXAccount : public Account {
newIncomingCall(const std::string& id);
private:
void serialize(YAML::Emitter &out);
void unserialize(const YAML::Node &node);
void setAccountDetails(const std::map<std::string, std::string> &details);
/**
......
This diff is collapsed.
......@@ -107,7 +107,7 @@ class SIPAccount : public SIPAccountBase {
* Serialize internal state of this account for configuration
* @param out Emitter to which state will be saved
*/
void serialize(YAML::Emitter &out);
virtual void serialize(YAML::Emitter &out);
/**
* Populate the internal state for this account based on info stored in the configuration file
......
......@@ -32,12 +32,210 @@
#include "sipaccountbase.h"
#include "sipvoiplink.h"
#ifdef SFL_VIDEO
#include "video/libav_utils.h"
#endif
#include "account_schema.h"
#include <yaml-cpp/yaml.h>
#include "config/yamlparser.h"
bool SIPAccountBase::portsInUse_[HALF_MAX_PORT];
static const char *const VALID_SRTP_KEY_EXCHANGES[] = {"", "sdes", "zrtp"};
SIPAccountBase::SIPAccountBase(const std::string& accountID)
: Account(accountID), link_(getSIPVoIPLink())
{}
template <typename T>
static void
validate(std::string &member, const std::string &param, const T& valid)
{
const auto begin = std::begin(valid);
const auto end = std::end(valid);
if (find(begin, end, param) != end)
member = param;
else
ERROR("Invalid parameter \"%s\"", param.c_str());
}
static void
updateRange(int min, int max, std::pair<uint16_t, uint16_t> &range)
{
if (min > 0 and (max > min) and max <= MAX_PORT - 2) {
range.first = min;
range.second = max;
}
}
static void
unserializeRange(const YAML::Node &node, const char *minKey, const char *maxKey, std::pair<uint16_t, uint16_t> &range)
{
int tmpMin = 0;
int tmpMax = 0;
yaml_utils::parseValue(node, minKey, tmpMin);
yaml_utils::parseValue(node, maxKey, tmpMax);
updateRange(tmpMin, tmpMax, range);
}
template <typename T>
static void
parseInt(const std::map<std::string, std::string> &details, const char *key, T &i)
{
const auto iter = details.find(key);
if (iter == details.end()) {
ERROR("Couldn't find key %s", key);
return;
}
i = atoi(iter->second.c_str());
}
void SIPAccountBase::serialize(YAML::Emitter &out)
{
using namespace Conf;
Account::serialize(out);
out << YAML::Key << AUDIO_PORT_MAX_KEY << YAML::Value << audioPortRange_.second;
out << YAML::Key << AUDIO_PORT_MIN_KEY << YAML::Value << audioPortRange_.first;
out << YAML::Key << DTMF_TYPE_KEY << YAML::Value << dtmfType_;
out << YAML::Key << INTERFACE_KEY << YAML::Value << interface_;
out << YAML::Key << PORT_KEY << YAML::Value << localPort_;
out << YAML::Key << PUBLISH_ADDR_KEY << YAML::Value << publishedIpAddress_;
out << YAML::Key << PUBLISH_PORT_KEY << YAML::Value << publishedPort_;
out << YAML::Key << SAME_AS_LOCAL_KEY << YAML::Value << publishedSameasLocal_;
// srtp submap
out << YAML::Key << SRTP_KEY << YAML::Value << YAML::BeginMap;
out << YAML::Key << SRTP_ENABLE_KEY << YAML::Value << srtpEnabled_;
out << YAML::Key << KEY_EXCHANGE_KEY << YAML::Value << srtpKeyExchange_;
out << YAML::Key << RTP_FALLBACK_KEY << YAML::Value << srtpFallback_;
out << YAML::EndMap;
out << YAML::Key << VIDEO_CODECS_KEY << YAML::Value << videoCodecList_;
out << YAML::Key << VIDEO_ENABLED_KEY << YAML::Value << videoEnabled_;
out << YAML::Key << VIDEO_PORT_MAX_KEY << YAML::Value << videoPortRange_.second;
out << YAML::Key << VIDEO_PORT_MIN_KEY << YAML::Value << videoPortRange_.first;
}
void SIPAccountBase::unserialize(const YAML::Node &node)
{
using namespace Conf;
using namespace yaml_utils;
Account::unserialize(node);
parseValue(node, VIDEO_ENABLED_KEY, videoEnabled_);
const auto &vCodecNode = node[VIDEO_CODECS_KEY];
auto tmp = parseVectorMap(vCodecNode, {VIDEO_CODEC_BITRATE, VIDEO_CODEC_ENABLED, VIDEO_CODEC_NAME, VIDEO_CODEC_PARAMETERS});
#ifdef SFL_VIDEO
if (tmp.empty()) {
// Video codecs are an empty list
WARN("Loading default video codecs");
tmp = libav_utils::getDefaultCodecs();
}
#endif
// validate it
setVideoCodecs(tmp);
parseValue(node, INTERFACE_KEY, interface_);
int port = DEFAULT_SIP_PORT;
parseValue(node, PORT_KEY, port);
localPort_ = port;
parseValue(node, PUBLISH_ADDR_KEY, publishedIpAddress_);
parseValue(node, PUBLISH_PORT_KEY, port);
publishedPort_ = port;
parseValue(node, SAME_AS_LOCAL_KEY, publishedSameasLocal_);
parseValue(node, DTMF_TYPE_KEY, dtmfType_);
// get srtp submap
const auto &srtpMap = node[SRTP_KEY];
parseValue(srtpMap, SRTP_ENABLE_KEY, srtpEnabled_);
std::string tmpKey;
parseValue(srtpMap, KEY_EXCHANGE_KEY, tmpKey);
validate(srtpKeyExchange_, tmpKey, VALID_SRTP_KEY_EXCHANGES);
parseValue(srtpMap, RTP_FALLBACK_KEY, srtpFallback_);
unserializeRange(node, AUDIO_PORT_MIN_KEY, AUDIO_PORT_MAX_KEY, audioPortRange_);
#ifdef SFL_VIDEO
unserializeRange(node, VIDEO_PORT_MIN_KEY, VIDEO_PORT_MAX_KEY, videoPortRange_);
#endif
}
void SIPAccountBase::setAccountDetails(const std::map<std::string, std::string> &details)
{
Account::setAccountDetails(details);
parseBool(details, CONFIG_VIDEO_ENABLED, videoEnabled_);
// general sip settings
parseString(details, CONFIG_LOCAL_INTERFACE, interface_);
parseBool(details, CONFIG_PUBLISHED_SAMEAS_LOCAL, publishedSameasLocal_);
parseString(details, CONFIG_PUBLISHED_ADDRESS, publishedIpAddress_);
parseInt(details, CONFIG_LOCAL_PORT, localPort_);
parseInt(details, CONFIG_PUBLISHED_PORT, publishedPort_);
parseString(details, CONFIG_ACCOUNT_DTMF_TYPE, dtmfType_);
int tmpMin = -1;
parseInt(details, CONFIG_ACCOUNT_AUDIO_PORT_MIN, tmpMin);
int tmpMax = -1;
parseInt(details, CONFIG_ACCOUNT_AUDIO_PORT_MAX, tmpMax);
updateRange(tmpMin, tmpMax, audioPortRange_);
#ifdef SFL_VIDEO
tmpMin = -1;
parseInt(details, CONFIG_ACCOUNT_VIDEO_PORT_MIN, tmpMin);
tmpMax = -1;
parseInt(details, CONFIG_ACCOUNT_VIDEO_PORT_MAX, tmpMax);
updateRange(tmpMin, tmpMax, videoPortRange_);
#endif
// srtp settings
parseBool(details, CONFIG_SRTP_ENABLE, srtpEnabled_);
parseBool(details, CONFIG_SRTP_RTP_FALLBACK, srtpFallback_);
auto iter = details.find(CONFIG_SRTP_KEY_EXCHANGE);
if (iter != details.end())
validate(srtpKeyExchange_, iter->second, VALID_SRTP_KEY_EXCHANGES);
}
std::map<std::string, std::string>
SIPAccountBase::getAccountDetails() const
{
std::map<std::string, std::string> a = Account::getAccountDetails();
// note: The IP2IP profile will always have IP2IP as an alias
a[CONFIG_VIDEO_ENABLED] = videoEnabled_ ? TRUE_STR : FALSE_STR;
a[CONFIG_ACCOUNT_REGISTRATION_STATUS] = isIP2IP() ? "READY" : mapStateNumberToString(registrationState_);
// Add sip specific details
addRangeToDetails(a, CONFIG_ACCOUNT_AUDIO_PORT_MIN, CONFIG_ACCOUNT_AUDIO_PORT_MAX, audioPortRange_);
#ifdef SFL_VIDEO
addRangeToDetails(a, CONFIG_ACCOUNT_VIDEO_PORT_MIN, CONFIG_ACCOUNT_VIDEO_PORT_MAX, videoPortRange_);
#endif
a[CONFIG_LOCAL_INTERFACE] = interface_;
a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? TRUE_STR : FALSE_STR;
a[CONFIG_PUBLISHED_ADDRESS] = publishedIpAddress_;
std::stringstream localport;
localport << localPort_;
a[CONFIG_LOCAL_PORT] = localport.str();
std::stringstream publishedport;
publishedport << publishedPort_;
a[CONFIG_PUBLISHED_PORT] = publishedport.str();
a[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_;
a[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? TRUE_STR : FALSE_STR;
a[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? TRUE_STR : FALSE_STR;
return a;
}
void
SIPAccountBase::setTransport(pjsip_transport* transport, pjsip_tpfactory* lis)
......
......@@ -131,6 +131,7 @@ public:
virtual ~SIPAccountBase() = default;
/**
* Create incoming SIPCall.
* @param[in] id The ID of the call
......@@ -286,6 +287,13 @@ public:
protected:
virtual void serialize(YAML::Emitter &out);
virtual void unserialize(const YAML::Node &node);
virtual void setAccountDetails(const std::map<std::string, std::string> &details);
virtual std::map<std::string, std::string> getAccountDetails() const;
/**
* Voice over IP Link contains a listener thread and calls
*/
......
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