From bfbc5e69b7cacf5ca57798767ffd3efa9c3c99c9 Mon Sep 17 00:00:00 2001 From: Tristan Matthews <tristan.matthews@savoirfairelinux.com> Date: Tue, 26 Aug 2014 15:33:22 -0400 Subject: [PATCH] config: port to yamlcpp Change-Id: I927e7ef2a61240d6d8b5f3eda94f4ce88dc0a240 --- daemon/configure.ac | 2 +- daemon/src/Makefile.am | 2 +- daemon/src/account.cpp | 2 +- daemon/src/account.h | 4 +- daemon/src/config/Makefile.am | 13 +- daemon/src/config/serializable.h | 10 +- daemon/src/config/sfl_config.cpp | 324 --------- daemon/src/config/sfl_config.h | 199 ------ daemon/src/config/yamlemitter.cpp | 213 ------ daemon/src/config/yamlemitter.h | 126 ---- daemon/src/config/yamlnode.cpp | 167 ----- daemon/src/config/yamlnode.h | 179 ----- daemon/src/config/yamlparser.cpp | 396 +---------- daemon/src/config/yamlparser.h | 118 +--- daemon/src/global.h | 7 - daemon/src/history/historynamecache.cpp | 10 - daemon/src/history/historynamecache.h | 5 +- daemon/src/iax/iaxaccount.cpp | 74 +-- daemon/src/iax/iaxaccount.h | 10 +- daemon/src/iax/iaxvoiplink.cpp | 4 +- daemon/src/managerimpl.cpp | 149 ++--- daemon/src/managerimpl.h | 40 +- daemon/src/preferences.cpp | 367 ++++------- daemon/src/preferences.h | 34 +- daemon/src/sip/sipaccount.cpp | 617 ++++++------------ daemon/src/sip/sipaccount.h | 11 +- daemon/src/sip/sipaccountbase.h | 2 - .../video/v4l2/video_device_monitor_impl.cpp | 2 - daemon/src/video/video_device_monitor.cpp | 67 +- daemon/src/video/video_device_monitor.h | 11 +- daemon/test/configurationtest.cpp | 141 +--- daemon/test/configurationtest.h | 6 +- daemon/test/sflphoned-sample.yml | 4 +- 33 files changed, 545 insertions(+), 2771 deletions(-) delete mode 100644 daemon/src/config/sfl_config.cpp delete mode 100644 daemon/src/config/sfl_config.h delete mode 100644 daemon/src/config/yamlemitter.cpp delete mode 100644 daemon/src/config/yamlemitter.h delete mode 100644 daemon/src/config/yamlnode.cpp delete mode 100644 daemon/src/config/yamlnode.h diff --git a/daemon/configure.ac b/daemon/configure.ac index 56746b3599..bd8dc2c211 100644 --- a/daemon/configure.ac +++ b/daemon/configure.ac @@ -164,7 +164,7 @@ esac dnl Check for pjproject PKG_CHECK_MODULES(PJPROJECT, libpjproject,, AC_MSG_ERROR([Missing pjproject files])) -PKG_CHECK_MODULES(YAML, [yaml-0.1],, AC_MSG_ERROR([Unable to find yaml])) +PKG_CHECK_MODULES([YAMLCPP], [yaml-cpp],, AC_MSG_ERROR([yaml-cpp not found])) if test "xSANDROID" = "xyes"; then dnl Check for OpenSL diff --git a/daemon/src/Makefile.am b/daemon/src/Makefile.am index 7c0ed10ea3..893bdcece0 100644 --- a/daemon/src/Makefile.am +++ b/daemon/src/Makefile.am @@ -56,7 +56,7 @@ libsflphone_la_LDFLAGS = \ @PULSEAUDIO_LIBS@ \ @SAMPLERATE_LIBS@ \ @SNDFILE_LIBS@ \ - @YAML_LIBS@ \ + @YAMLCPP_LIBS@ \ $(TLS_LIB) \ $(IAX_LIB) \ $(IM_LIB) diff --git a/daemon/src/account.cpp b/daemon/src/account.cpp index a362390022..cf7b71fefc 100644 --- a/daemon/src/account.cpp +++ b/daemon/src/account.cpp @@ -359,7 +359,7 @@ void Account::parseBool(const std::map<std::string, std::string> &details, const char *key, bool &b) { find_iter(); - b = iter->second == Conf::TRUE_STR; + b = iter->second == TRUE_STR; } #undef find_iter diff --git a/daemon/src/account.h b/daemon/src/account.h index b7e64dff79..2923cc6da1 100644 --- a/daemon/src/account.h +++ b/daemon/src/account.h @@ -34,7 +34,6 @@ #define ACCOUNT_H #include "noncopyable.h" -#include "config/sfl_config.h" #include "config/serializable.h" #include "registration_states.h" @@ -64,6 +63,9 @@ class VoipLinkException : public std::runtime_error { class Account : public Serializable { public: + constexpr static const char *TRUE_STR = "true"; + constexpr static const char *FALSE_STR = "false"; + Account(const std::string& accountID); /** diff --git a/daemon/src/config/Makefile.am b/daemon/src/config/Makefile.am index a790afe67d..a9af69eb4f 100644 --- a/daemon/src/config/Makefile.am +++ b/daemon/src/config/Makefile.am @@ -1,16 +1,5 @@ noinst_LTLIBRARIES = libconfig.la -libconfig_la_SOURCES = \ - sfl_config.cpp \ - yamlemitter.cpp \ - yamlparser.cpp \ - yamlnode.cpp - -noinst_HEADERS = \ - sfl_config.h \ - serializable.h \ - yamlemitter.h \ - yamlparser.h \ - yamlnode.h +libconfig_la_SOURCES = serializable.h yamlparser.h yamlparser.cpp libconfig_la_CXXFLAGS = -I $(top_srcdir)/src diff --git a/daemon/src/config/serializable.h b/daemon/src/config/serializable.h index 8d5c41b4f3..9f8ca02492 100644 --- a/daemon/src/config/serializable.h +++ b/daemon/src/config/serializable.h @@ -31,17 +31,17 @@ #ifndef SERIALIZABLE_H__ #define SERIALIZABLE_H__ -namespace Conf { - class YamlEmitter; - class YamlNode; +namespace YAML { + class Emitter; + class Node; } class Serializable { public: virtual ~Serializable() {}; - virtual void serialize(Conf::YamlEmitter &emitter) = 0; - virtual void unserialize(const Conf::YamlNode &map) = 0; + virtual void serialize(YAML::Emitter &out) = 0; + virtual void unserialize(const YAML::Node &node) = 0; }; #endif diff --git a/daemon/src/config/sfl_config.cpp b/daemon/src/config/sfl_config.cpp deleted file mode 100644 index 99130fca5c..0000000000 --- a/daemon/src/config/sfl_config.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> - * Author: Yan Morin <yan.morin@savoirfairelinux.com> - * - * 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 3 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. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#include "sfl_config.h" -#include "logger.h" -#include <fstream> -#include <cstdlib> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <iostream> -#include <string.h> -#include "yamlparser.h" - -namespace Conf { - -void ConfigTree::addDefaultValue(const std::pair<std::string, std::string>& token, std::string section) -{ - defaultValueMap_.insert(token); - - if (not section.empty()) - addConfigTreeItem(section, ConfigTreeItem(token.first, token.second, token.second, "string")); -} - -std::string ConfigTree::getDefaultValue(const std::string& key) const -{ - std::map<std::string, std::string>::const_iterator it; - it = defaultValueMap_.find(key); - - if (it == defaultValueMap_.end()) - return ""; - - return it->second; -} - -/** - * Create the section only if it doesn't exists - */ -void -ConfigTree::createSection(const std::string& section) -{ - // if we doesn't find the item, create it - if (sections_.find(section) == sections_.end()) - sections_[section] = ItemMap(); -} - -/** - * Remove the section only if it exists - */ -void -ConfigTree::removeSection(const std::string& section) -{ - // if we doesn't find the item, create it - SectionMap::iterator iter = sections_.find(section); - - if (iter != sections_.end()) - sections_.erase(iter); -} - -/** Retrieve the sections as an array */ -std::list<std::string> -ConfigTree::getSections() const -{ - std::list<std::string> sections; - - for (const auto &item : sections_) - sections.push_back(item.first); - - return sections; -} - -/** - * Add the config item only if it exists.. - * If the section doesn't exists, create it - */ -void -ConfigTree::addConfigTreeItem(const std::string& section, const ConfigTreeItem &item) -{ - // if we doesn't find the item, create it - SectionMap::iterator iter = sections_.find(section); - - if (iter == sections_.end()) { - sections_[section] = ItemMap(); - iter = sections_.find(section); - } - - // be prudent here - if (iter != sections_.end()) { - std::string name(item.getName()); - - if (iter->second.find(name) == iter->second.end()) - iter->second[name] = item; - } -} - -std::string -ConfigTree::getConfigTreeItemValue(const std::string& section, const std::string& itemName) const -{ - const ConfigTreeItem* item = getConfigTreeItem(section, itemName); - - if (item) - return item->getValue(); - - return getDefaultValue(itemName); -} - -/** - * Return a ConfigTreeItem or NULL if not found - */ -const ConfigTreeItem* -ConfigTree::getConfigTreeItem(const std::string& section, const std::string& itemName) const -{ - SectionMap::const_iterator iter = sections_.find(section); - - if (iter == sections_.end()) - return NULL; - - ItemMap::const_iterator iterItem = iter->second.find(itemName); - - if (iterItem == iter->second.end()) - return NULL; - - return & (iterItem->second); -} - -/** - * Set the configItem if found, if not, *CREATE IT* - * - * @todo Élimier les 45,000 classes qui servent à rien pour Conf. - * The true/false logic is useless here. - */ -void ConfigTree::setConfigTreeItem(const std::string& section, - const std::string& itemName, - const std::string& value) -{ - SectionMap::iterator iter = sections_.find(section); - - if (iter == sections_.end()) { - // Not found, create section - sections_[section] = ItemMap(); - iter = sections_.find(section); - } - - ItemMap::iterator iterItem = iter->second.find(itemName); - - if (iterItem == iter->second.end()) { - // If not found, search in our default list to find - // something that would fit. - std::string defaultValue = getDefaultValue(itemName); - addConfigTreeItem(section, ConfigTreeItem(itemName, value, defaultValue)); - return; - } - - // Use default value if the value is empty. - if (value.empty()) { - iterItem->second.setValue(getDefaultValue(itemName)); - return; - } - - iterItem->second.setValue(value); - return; -} - -// Create the tree from an existing ini file -// false = error -// true = OK -bool -ConfigTree::populateFromFile(const std::string& fileName) -{ - DEBUG("Populate from file %s", fileName.c_str()); - - if (fileName.empty()) - return false; - - std::fstream file; - - file.open(fileName.data(), std::fstream::in); - - if (!file.is_open()) { - file.open(fileName.data(), std::fstream::out); - - if (!file.is_open()) - return false; - - file.close(); - - return false; - } - - // get length of file: - file.seekg(0, std::ios::end); - - int length = file.tellg(); - - file.seekg(0, std::ios::beg); - - if (length == 0) { - file.close(); - return false; // should load config - } - - std::string line; - std::string section; - std::string key; - std::string val; - std::string::size_type pos; - - while (!file.eof()) { - // Read the file line by line - std::getline(file, line); - - if (!line.empty()) { - if (line[0] == '[') { - // If the line is a section - pos = line.find(']'); - section = line.substr(1, pos - 1); - } else if (line[0] != '#') { - // If the line is "key=value" and doesn't begin with '#'(comments) - - pos = line.find('='); - key = line.substr(0, pos); - val = line.substr(pos + 1, line.length() - pos); - - if (key.length() > 0 && val.length() > 0) - setConfigTreeItem(section, key, val); - } - } - } - - file.close(); - - if (chmod(fileName.c_str(), S_IRUSR | S_IWUSR)) - DEBUG("Failed to set permission on configuration file because: %m"); - - return true; -} - -std::list<std::string> -ConfigTreeIterator::begin() const -{ - std::list<std::string> tk; - iter_ = tree_->sections_.begin(); - - if (iter_ != tree_->sections_.end()) { - iterItem_ = iter_->second.begin(); - - if (iterItem_ != iter_->second.end()) { - tk.push_back(iter_->first); - tk.push_back(iterItem_->first); - tk.push_back(iterItem_->second.getType()); - tk.push_back(iterItem_->second.getValue()); - tk.push_back(iterItem_->second.getDefaultValue()); - } - } - - return tk; -} - -std::list<std::string> -ConfigTreeIterator::next() -{ - std::list<std::string> tk; - // we return tk empty if we are at the end of the list... - - if (iter_ == tree_->sections_.end()) - return tk; - - if (iterItem_ != iter_->second.end()) - iterItem_++; - - if (iterItem_ == iter_->second.end()) { - // if we increment, and we are at the end of a section - iter_++; - - if (iter_ != tree_->sections_.end()) { - iterItem_ = iter_->second.begin(); - - if (iterItem_ != iter_->second.end()) { - tk.push_back(iter_->first); - tk.push_back(iterItem_->first); - tk.push_back(iterItem_->second.getType()); - tk.push_back(iterItem_->second.getValue()); - tk.push_back(iterItem_->second.getDefaultValue()); - } - } - } else { - tk.push_back(iter_->first); - tk.push_back(iterItem_->first); - tk.push_back(iterItem_->second.getType()); - tk.push_back(iterItem_->second.getValue()); - tk.push_back(iterItem_->second.getDefaultValue()); - } - - return tk; -} -} // end namespace ConfigTree diff --git a/daemon/src/config/sfl_config.h b/daemon/src/config/sfl_config.h deleted file mode 100644 index 02f8999174..0000000000 --- a/daemon/src/config/sfl_config.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> - * Author: Yan Morin <yan.morin@savoirfairelinux.com> - * - * 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 3 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. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#ifndef CONF_CONFIG_H__ -#define CONF_CONFIG_H__ - -#include <map> -#include <string> -#include <list> -#include "noncopyable.h" - -/** - * @file config.h - * @brief Configuration namespace for ConfigTree object (like .ini files) - */ - -namespace Conf { -static const char * const TRUE_STR = "true"; -static const char * const FALSE_STR = "false"; - -class ConfigTreeItem { - - public: - ConfigTreeItem() : name_(""), value_(""), defaultValue_(""), type_("string") {} - - // defaultvalue = value - ConfigTreeItem(const std::string& name, const std::string& value, const std::string& type) : - name_(name), value_(value), - defaultValue_(value), type_(type) {} - - ConfigTreeItem(const std::string& name, const std::string& value, const std::string& defaultValue, const std::string& type) : - name_(name), value_(value), - defaultValue_(defaultValue), type_(type) {} - - void setValue(const std::string& value) { - value_ = value; - } - - std::string getName() const { - return name_; - } - - std::string getValue() const { - return value_; - } - - std::string getDefaultValue() const { - return defaultValue_; - } - - std::string getType() const { - return type_; - } - - private: - std::string name_; - std::string value_; - std::string defaultValue_; - std::string type_; -}; - - - -typedef std::map<std::string, ConfigTreeItem> ItemMap; -typedef std::map<std::string, ItemMap> SectionMap; - -class ConfigTreeItemException { -}; - -class ConfigTree; - -class ConfigTreeIterator { - - public: - std::list<std::string> begin() const; - - const std::list<std::string> & end() const { - return endToken_; - } - - std::list<std::string> next(); - - private: - friend class ConfigTree; - ConfigTreeIterator(ConfigTree *configTree) : tree_(configTree), endToken_(), iter_(), iterItem_() {} - - NON_COPYABLE(ConfigTreeIterator); - - ConfigTree* tree_; - std::list<std::string> endToken_; - mutable SectionMap::iterator iter_; - mutable ItemMap::iterator iterItem_; -}; - -class ConfigTree { - public: - ConfigTree() : sections_(), defaultValueMap_() {} - /** - * Add a default value for a given key. - * It looks in a map of default values when - * the value for a given key cannot be found. - * - * @param section the section under which the given key/value pair - should go under. Note that this has no effect - when searching for a default value later on. Only - one possible value is actually supported as a default - value for a given key. - @param token A default key/value pair. - */ - void addDefaultValue(const std::pair<std::string, std::string>& token, std::string section = ""); - - void createSection(const std::string& section); - void removeSection(const std::string& section); - /** - * Return an array of strings, listing the sections of the config file - * - * This will be mainly used to filter which sections are an - * "Account" definition. - * - * @return array Strings of the sections - */ - std::list<std::string> getSections() const; - - void addConfigTreeItem(const std::string& section, const ConfigTreeItem &item); - /** - * Set a configuration value. - * - * @param section Write to this [section] of the .ini file - * @param itemName The itemName= in the .ini file - * @param value The value to assign to that itemName - */ - void setConfigTreeItem(const std::string& section, const std::string& itemName, const std::string& value); - - /** - * Get a value. - * - * If the key cannot be found in the actual file representation in - * memory, it check for a default value in the default value map. If it's - * not found there, it will return an empty string. - * - * @param section The name of the [section] in the .ini file. - * @param itemName The name of the item= in the .ini file. - * @return The value of the corresponding item. The default value if the section exists - * but the item doesn't. - */ - std::string getConfigTreeItemValue(const std::string& section, const std::string& itemName) const; - - /** - * Load data (and fill ConfigTree) from disk - */ - bool populateFromFile(const std::string& fileName); - - private: - std::string getDefaultValue(const std::string& key) const; - const ConfigTreeItem* getConfigTreeItem(const std::string& section, const std::string& itemName) const; - - /** - * List of sections. Each sections has an ItemList as child - */ - SectionMap sections_; - - std::map<std::string, std::string> defaultValueMap_; - - friend class ConfigTreeIterator; - - NON_COPYABLE(ConfigTree); -}; - -} // end namespace ConfigTree - -#endif // __CONFIG_CONFIG_H__ diff --git a/daemon/src/config/yamlemitter.cpp b/daemon/src/config/yamlemitter.cpp deleted file mode 100644 index 5ffc1d2e19..0000000000 --- a/daemon/src/config/yamlemitter.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> - * - * 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 3 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. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#include "yamlemitter.h" -#include "yamlnode.h" -#include <cstdio> -#include "logger.h" - -namespace Conf { - -YamlEmitter::YamlEmitter(const char *file) : filename_(file), fd_(0), - emitter_(), events_(), buffer_(), document_(), topLevelMapping_(0), - isFirstAccount_(true), accountSequence_(0) -{ - open(); -} - -YamlEmitter::~YamlEmitter() -{ - close(); -} - -void YamlEmitter::open() -{ - fd_ = fopen(filename_.c_str(), "w"); - - if (!fd_) - throw YamlEmitterException("Could not open file descriptor"); - - if (!yaml_emitter_initialize(&emitter_)) - throw YamlEmitterException("Could not initialize emitter"); - - // Allows unescaped unicode characters - yaml_emitter_set_unicode(&emitter_, 1); - - yaml_emitter_set_output_file(&emitter_, fd_); - - if (yaml_document_initialize(&document_, NULL, NULL, NULL, 0, 0) == 0) - throw YamlEmitterException("Could not initialize yaml document while saving configuration"); - - // Init the main configuration mapping - if ((topLevelMapping_ = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not create top level mapping"); -} - -void YamlEmitter::close() -{ - yaml_emitter_delete(&emitter_); - - // Refererence: - // http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9 - if (!fd_) { - ERROR("File descriptor not valid"); - return; - } - - if (fclose(fd_)) - ERROR("Error closing file descriptor"); -} - -void YamlEmitter::serializeData() -{ - // Document object is destroyed once its content is emitted - if (yaml_emitter_dump(&emitter_, &document_) == 0) - throw YamlEmitterException("Error while emitting configuration yaml document"); -} - -void YamlEmitter::serializeAccount(MappingNode *map) -{ - if (map->getType() != MAPPING) - throw YamlEmitterException("Node type is not a mapping while writing account"); - - if (isFirstAccount_) { - int accountid; - - // accountSequence_ need to be static outside this scope since reused each time an account is written - if ((accountid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) "accounts", -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add preference scalar to document"); - - if ((accountSequence_ = yaml_document_add_sequence(&document_, NULL, YAML_BLOCK_SEQUENCE_STYLE)) == 0) - throw YamlEmitterException("Could not add sequence to document"); - - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, accountid, accountSequence_) == 0) - throw YamlEmitterException("Could not add mapping pair to top level mapping"); - - isFirstAccount_ = false; - } - - int accountMapping; - if ((accountMapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add account mapping to document"); - - if (yaml_document_append_sequence_item(&document_, accountSequence_, accountMapping) == 0) - throw YamlEmitterException("Could not append account mapping to sequence"); - - addMappingItems(accountMapping, map->getMapping()); -} - -void YamlEmitter::serializePreference(MappingNode *map, const char *preference_str) -{ - if (map->getType() != MAPPING) - throw YamlEmitterException("Node type is not a mapping while writing preferences"); - - int preferenceid; - if ((preferenceid = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) preference_str, -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - int preferenceMapping; - if ((preferenceMapping = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add mapping to document"); - - if (yaml_document_append_mapping_pair(&document_, topLevelMapping_, preferenceid, preferenceMapping) == 0) - throw YamlEmitterException("Could not add mapping pair to top leve mapping"); - - addMappingItems(preferenceMapping, map->getMapping()); -} - -void YamlEmitter::addMappingItems(int mappingID, YamlNodeMap &iMap) -{ - for (const auto &i : iMap) - addMappingItem(mappingID, i.first, i.second); -} - -void YamlEmitter::addMappingItem(int mappingid, const std::string &key, YamlNode *node) -{ - if (node->getType() == SCALAR) { - ScalarNode *sclr = static_cast<ScalarNode *>(node); - - int temp1; - if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - int temp2; - if ((temp2 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) sclr->getValue().c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - if (yaml_document_append_mapping_pair(&document_, mappingid, temp1, temp2) == 0) - throw YamlEmitterException("Could not append mapping pair to mapping"); - - } else if (node->getType() == MAPPING) { - MappingNode *map = static_cast<MappingNode *>(node); - - int temp1; - if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - int temp2; - if ((temp2 = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - if (yaml_document_append_mapping_pair(&document_, mappingid, temp1, temp2) == 0) - throw YamlEmitterException("Could not add mapping pair to mapping"); - - addMappingItems(temp2, map->getMapping()); - - } else if (node->getType() == SEQUENCE) { - SequenceNode *seqnode = static_cast<SequenceNode *>(node); - - int temp1; - if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - int temp2; - if ((temp2 = yaml_document_add_sequence(&document_, NULL, YAML_BLOCK_SEQUENCE_STYLE)) == 0) - throw YamlEmitterException("Could not add scalar to document"); - - if (yaml_document_append_mapping_pair(&document_, mappingid, temp1, temp2) == 0) - throw YamlEmitterException("Could not append mapping pair to mapping"); - - Sequence *seq = seqnode->getSequence(); - for (const auto &it : *seq) { - YamlNode *yamlNode = it; - int id; - if ((id = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0) - throw YamlEmitterException("Could not add account mapping to document"); - - if (yaml_document_append_sequence_item(&document_, temp2, id) == 0) - throw YamlEmitterException("Could not append account mapping to sequence"); - - MappingNode *mapnode = static_cast<MappingNode*>(yamlNode); - addMappingItems(id, mapnode->getMapping()); - } - } else - throw YamlEmitterException("Unknown node type while adding mapping node"); -} -} diff --git a/daemon/src/config/yamlemitter.h b/daemon/src/config/yamlemitter.h deleted file mode 100644 index bd2c1a31b4..0000000000 --- a/daemon/src/config/yamlemitter.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> - * - * 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 3 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. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#ifndef YAMLEMITTER_H_ -#define YAMLEMITTER_H_ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <yaml.h> -#include <stdexcept> -#include <string> -#include <map> - -#include "yamlnode.h" -#include "noncopyable.h" - -namespace Conf { - -#define EMITTER_BUFFERSIZE 65536 -#define EMITTER_MAXEVENT 1024 - - -class YamlEmitterException : public std::runtime_error { - public: - YamlEmitterException(const char *err) : std::runtime_error(err) {} -}; - -class YamlEmitter { - - public: - - YamlEmitter(const char *file); - ~YamlEmitter(); - - void open(); - - void close(); - - void serializeAccount(MappingNode *map); - - void serializePreference(MappingNode *map, const char *preference_str); - - void writeAudio(); - - void writeHooks(); - - void writeVoiplink(); - - void serializeData(); - - private: - - NON_COPYABLE(YamlEmitter); - void addMappingItems(int mappingid, YamlNodeMap &iMap); - void addMappingItem(int mappingid, const std::string &key, YamlNode *node); - - std::string filename_; - - FILE *fd_; - - /** - * The parser structure. - */ - yaml_emitter_t emitter_; - - /** - * The event structure array. - */ - yaml_event_t events_[EMITTER_MAXEVENT]; - - unsigned char buffer_[EMITTER_BUFFERSIZE]; - - /** - * Main document for this serialization - */ - yaml_document_t document_; - - /** - * Reference id to the top levell mapping when creating - */ - int topLevelMapping_; - - /** - * We need to add the account sequence if this is the first account to be - */ - bool isFirstAccount_; - - /** - * Reference to the account sequence - */ - int accountSequence_; - - friend class ConfigurationTest; -}; -} - -#endif // YAMLEMITTER_H__ diff --git a/daemon/src/config/yamlnode.cpp b/daemon/src/config/yamlnode.cpp deleted file mode 100644 index ada00d4a49..0000000000 --- a/daemon/src/config/yamlnode.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> - * - * 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 3 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. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#include "yamlnode.h" -#include <cstdlib> -#include "logger.h" - -namespace Conf { - -void YamlDocument::addNode(YamlNode *node) -{ - Sequence::iterator it = doc_.end(); - doc_.insert(it, node); -} - -YamlNode *YamlDocument::popNode() -{ - YamlNode *node = doc_.front(); - - //removed element's destructor is called - doc_.pop_front(); - - return node; -} - -void YamlDocument::deleteChildNodes() -{ - for (auto &it : doc_) { - YamlNode *yamlNode = static_cast<YamlNode *>(it); - - yamlNode->deleteChildNodes(); - delete yamlNode; - yamlNode = NULL; - } -} - -void MappingNode::addNode(YamlNode *node) -{ - setKeyValue(tmpKey_, node); -} - - -void MappingNode::setKeyValue(const std::string &key, YamlNode *value) -{ - map_[key] = value; -} - -void MappingNode::removeKeyValue(const std::string &key) -{ - YamlNodeMap::iterator it = map_.find(key); - map_.erase(it); -} - -YamlNode *MappingNode::getValue(const std::string &key) const -{ - YamlNodeMap::const_iterator it = map_.find(key); - - if (it != map_.end()) - return it->second; - else - return NULL; -} - -void MappingNode::getValue(const std::string &key, bool *b) const -{ - ScalarNode *node = static_cast<ScalarNode*>(getValue(key)); - if (!node) - return; - - const std::string &v = node->getValue(); - *b = v == "true"; -} - -void MappingNode::getValue(const std::string &key, int *i) const -{ - ScalarNode *node = static_cast<ScalarNode*>(getValue(key)); - if (!node) { - ERROR("node %s not found", key.c_str()); - return; - } - - *i = std::atoi(node->getValue().c_str()); -} - -void MappingNode::getValue(const std::string &key, double *d) const -{ - ScalarNode *node = static_cast<ScalarNode*>(getValue(key)); - if (!node) { - ERROR("node %s not found", key.c_str()); - return; - } - - *d = std::atof(node->getValue().c_str()); -} - -void MappingNode::getValue(const std::string &key, std::string *v) const -{ - ScalarNode *node = static_cast<ScalarNode*>(getValue(key)); - - if (!node) { - ERROR("node %s not found", key.c_str()); - return; - } - - *v = node->getValue(); -} - - -void MappingNode::deleteChildNodes() -{ - for (auto &it : map_) { - YamlNode *yamlNode = static_cast<YamlNode *>(it.second); - - if (!yamlNode) - continue; - - yamlNode->deleteChildNodes(); - delete yamlNode; - yamlNode = NULL; - } -} - -void SequenceNode::addNode(YamlNode *node) -{ - Sequence::iterator it = seq_.end(); - seq_.insert(it, node); -} - -void SequenceNode::deleteChildNodes() -{ - for (auto &it : seq_) { - YamlNode *yamlNode = static_cast<YamlNode *>(it); - - yamlNode->deleteChildNodes(); - delete yamlNode; - yamlNode = NULL; - } -} - -} diff --git a/daemon/src/config/yamlnode.h b/daemon/src/config/yamlnode.h deleted file mode 100644 index 684cbc033e..0000000000 --- a/daemon/src/config/yamlnode.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. - * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> - * - * 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 3 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. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#ifndef __YAMLNODE_H__ -#define __YAMLNODE_H__ - -#include <string> -#include <list> -#include <map> -#include <stdexcept> - -#include "noncopyable.h" -#include "global.h" - -namespace Conf { - -class YamlNode; - -typedef std::list<YamlNode *> Sequence; -typedef std::map<std::string, YamlNode*> YamlNodeMap; - -enum NodeType { DOCUMENT, SCALAR, MAPPING, SEQUENCE }; - -class YamlNode { - public: - YamlNode(NodeType t, YamlNode *top = NULL) : type_(t), topNode_(top) {} - - virtual ~YamlNode() {} - - NodeType getType() const { return type_; } - - YamlNode *getTopNode() { return topNode_; } - - virtual void deleteChildNodes() = 0; - - virtual void addNode(YamlNode *node) = 0; - - virtual YamlNode *getValue(const std::string &key) const = 0; - virtual void getValue(const std::string &key UNUSED, bool *b) const = 0; - virtual void getValue(const std::string &key UNUSED, int *i) const = 0; - virtual void getValue(const std::string &key UNUSED, double *d) const = 0; - virtual void getValue(const std::string &key UNUSED, std::string *s) const = 0; - - private: - NON_COPYABLE(YamlNode); - NodeType type_; - YamlNode *topNode_; -}; - - -class YamlDocument : public YamlNode { - public: - YamlDocument(YamlNode* top = NULL) : YamlNode(DOCUMENT, top), doc_() {} - - virtual void addNode(YamlNode *node); - - YamlNode *popNode(); - - Sequence *getSequence() { return &doc_; } - - virtual void deleteChildNodes(); - - virtual YamlNode *getValue(const std::string &key UNUSED) const { return NULL; } - virtual void getValue(const std::string &key UNUSED, bool *b) const { *b = false; } - virtual void getValue(const std::string &key UNUSED, int *i) const { *i = 0; } - virtual void getValue(const std::string &key UNUSED, double *d) const { *d = 0.0; } - virtual void getValue(const std::string &key UNUSED, std::string *s) const { *s = ""; } - - private: - Sequence doc_; -}; - -class SequenceNode : public YamlNode { - public: - SequenceNode(YamlNode *top) : YamlNode(SEQUENCE, top), seq_() {} - - Sequence *getSequence() { - return &seq_; - } - - virtual void addNode(YamlNode *node); - - virtual void deleteChildNodes(); - - virtual YamlNode *getValue(const std::string &key UNUSED) const { return NULL; } - virtual void getValue(const std::string &key UNUSED, bool *b) const { *b = false; } - virtual void getValue(const std::string &key UNUSED, int *i) const { *i = 0; } - virtual void getValue(const std::string &key UNUSED, double *d) const { *d = 0.0; } - virtual void getValue(const std::string &key UNUSED, std::string *s) const { *s = ""; } - - - private: - Sequence seq_; -}; - - -class MappingNode : public YamlNode { - public: - MappingNode(YamlNode *top) : - YamlNode(MAPPING, top), map_(), tmpKey_() {} - - YamlNodeMap &getMapping() { return map_; } - - virtual void addNode(YamlNode *node); - - void setTmpKey(std::string key) { tmpKey_ = key; } - - void setKeyValue(const std::string &key, YamlNode *value); - - void removeKeyValue(const std::string &key); - - YamlNode *getValue(const std::string &key) const; - void getValue(const std::string &key, bool *b) const; - void getValue(const std::string &key, int *i) const; - void getValue(const std::string &key, double *d) const; - void getValue(const std::string &key, std::string *s) const; - - virtual void deleteChildNodes(); - - private: - YamlNodeMap map_; - std::string tmpKey_; -}; - -class ScalarNode : public YamlNode { - public: - ScalarNode(const std::string &s, YamlNode *top = NULL) : YamlNode(SCALAR, top), str_(s) {} - /* This avoids const char * arguments calling the constructor, see #20793 */ - ScalarNode(const char *s, YamlNode *top = NULL) : YamlNode(SCALAR, top), str_(s) {} - ScalarNode(bool b, YamlNode *top = NULL) : YamlNode(SCALAR, top), str_(b ? "true" : "false") {} - - virtual void addNode(YamlNode *node UNUSED) {} - - const std::string &getValue() const { return str_; } - void setValue(const std::string &s) { str_ = s; } - - virtual YamlNode *getValue(const std::string &key UNUSED) const { return NULL; } - virtual void getValue(const std::string &key UNUSED, bool *b) const { *b = false; } - virtual void getValue(const std::string &key UNUSED, int *i) const { *i = 0; } - virtual void getValue(const std::string &key UNUSED, double *d) const { *d = 0.0; } - virtual void getValue(const std::string &key UNUSED, std::string *s) const { *s = ""; } - - virtual void deleteChildNodes() {} - - private: - std::string str_; -}; - -} - -#endif - diff --git a/daemon/src/config/yamlparser.cpp b/daemon/src/config/yamlparser.cpp index 04907e71a6..4d66f380b6 100644 --- a/daemon/src/config/yamlparser.cpp +++ b/daemon/src/config/yamlparser.cpp @@ -28,394 +28,24 @@ * as that of the covered work. */ -#include <cstdio> -#include <assert.h> +#include <yaml-cpp/yaml.h> -#include "yamlparser.h" +namespace yaml_utils { -#include "../global.h" -#include "sfl_config.h" -#include "yamlnode.h" -#include "logger.h" - -namespace Conf { - -YamlParser::YamlParser(FILE *fd) : fd_(fd) - , parser_() - , events_() - , eventNumber_(0) - , doc_(NULL) - , eventIndex_(0) - , accountSequence_(NULL) - , preferenceNode_(NULL) - , audioNode_(NULL) -#ifdef SFL_VIDEO - , videoNode_(NULL) -#endif - , hooksNode_(NULL) - , voiplinkNode_(NULL) - , shortcutNode_(NULL) -{ - if (!fd_) - throw YamlParserException("Could not open file descriptor"); - - if (!yaml_parser_initialize(&parser_)) - throw YamlParserException("Could not initialize"); - - yaml_parser_set_input_file(&parser_, fd_); -} - -#define CHECK_AND_RETURN(x) \ - if (!x) { \ - ERROR("%s", __PRETTY_FUNCTION__); \ - throw YamlParserException("Invalid node"); \ - } \ - return x - -SequenceNode * -YamlParser::getAccountSequence() -{ - CHECK_AND_RETURN(accountSequence_); -} - -MappingNode * -YamlParser::getPreferenceNode() -{ - CHECK_AND_RETURN(preferenceNode_); -} - -MappingNode * -YamlParser::getAudioNode() -{ - CHECK_AND_RETURN(audioNode_); -} - -#ifdef SFL_VIDEO -MappingNode * -YamlParser::getVideoNode() +// FIXME: Maybe think of something more clever, this is due to yaml-cpp's poor +// handling of empty values for nested collections. +std::vector<std::map<std::string, std::string>> +parseVectorMap(const YAML::Node &node, const std::initializer_list<std::string> &keys) { - CHECK_AND_RETURN(videoNode_); -} -#endif - -MappingNode * -YamlParser::getHookNode() -{ - CHECK_AND_RETURN(hooksNode_); -} - -MappingNode * -YamlParser::getVoipPreferenceNode() -{ - CHECK_AND_RETURN(voiplinkNode_); -} - -MappingNode * -YamlParser::getShortcutNode() -{ - CHECK_AND_RETURN(shortcutNode_); -} - -#undef CHECK_AND_RETURN - -YamlParser::~YamlParser() -{ - if (fd_) - yaml_parser_delete(&parser_); - - for (int i = 0; i < eventNumber_; ++i) - yaml_event_delete(&events_[i]); - - doc_.deleteChildNodes(); -} - -void YamlParser::serializeEvents() -{ - bool done = false; - yaml_event_t event, copiedEvent; - - while (not done) { - if (!yaml_parser_parse(&parser_, &event)) - throw YamlParserException("Error while parsing"); - - done = (event.type == YAML_STREAM_END_EVENT); - - copyEvent(&copiedEvent, &event); - - events_.push_back(copiedEvent); - - ++eventNumber_; - - yaml_event_delete(&event); - } -} - - -void YamlParser::copyEvent(yaml_event_t *event_to, yaml_event_t *event_from) -{ - switch (event_from->type) { - case YAML_STREAM_START_EVENT: { - if (yaml_stream_start_event_initialize(event_to, - event_from->data.stream_start.encoding) == 0) - throw YamlParserException("Error stream start event"); - - break; - } - - case YAML_STREAM_END_EVENT: { - if (yaml_stream_end_event_initialize(event_to) == 0) - throw YamlParserException("Error stream end event"); - - break; - } - - case YAML_DOCUMENT_START_EVENT: { - if (yaml_document_start_event_initialize(event_to, - event_from->data.document_start.version_directive, - event_from->data.document_start.tag_directives.start, - event_from->data.document_start.tag_directives.end, - event_from->data.document_start.implicit) == 0) - throw YamlParserException("Error document start event"); - - break; - } - - case YAML_DOCUMENT_END_EVENT: { - if (yaml_document_end_event_initialize(event_to, - event_from->data.document_end.implicit) == 0) - throw YamlParserException("Error document end event"); - - break; - } - case YAML_ALIAS_EVENT: { - if (yaml_alias_event_initialize(event_to, - event_from->data.alias.anchor) == 0) - throw YamlParserException("Error alias event initialize"); - - break; - } - case YAML_SCALAR_EVENT: { - if (yaml_scalar_event_initialize(event_to, - event_from->data.scalar.anchor, - event_from->data.scalar.tag, - event_from->data.scalar.value, - event_from->data.scalar.length, - event_from->data.scalar.plain_implicit, - event_from->data.scalar.quoted_implicit, - event_from->data.scalar.style) == 0) - throw YamlParserException("Error scalar event initialize"); - - break; - } - case YAML_SEQUENCE_START_EVENT: { - if (yaml_sequence_start_event_initialize(event_to, - event_from->data.sequence_start.anchor, - event_from->data.sequence_start.tag, - event_from->data.sequence_start.implicit, - event_from->data.sequence_start.style) == 0) - throw YamlParserException("Error sequence start event"); - - break; - } - case YAML_SEQUENCE_END_EVENT: { - if (yaml_sequence_end_event_initialize(event_to) == 0) - throw YamlParserException("Error sequence end event"); - - break; - } - case YAML_MAPPING_START_EVENT: { - if (yaml_mapping_start_event_initialize(event_to, - event_from->data.mapping_start.anchor, - event_from->data.mapping_start.tag, - event_from->data.mapping_start.implicit, - event_from->data.mapping_start.style) == 0) - throw YamlParserException("Error mapping start event"); - break; - } - case YAML_MAPPING_END_EVENT: { - if (yaml_mapping_end_event_initialize(event_to) == 0) - throw YamlParserException("Error mapping end event"); - - break; - } - default: - break; - } -} - - -void YamlParser::composeEvents() -{ - if (eventNumber_ == 0) - throw YamlParserException("No event available"); - - if (events_[0].type != YAML_STREAM_START_EVENT) - throw YamlParserException("Parsing does not start with stream start"); - - eventIndex_ = 0; - - processStream(); -} - -void YamlParser::processStream() -{ - for (; (eventIndex_ < eventNumber_) and (events_[eventIndex_].type != YAML_STREAM_END_EVENT); ++eventIndex_) - if (events_[eventIndex_].type == YAML_DOCUMENT_START_EVENT) - processDocument(); - - if (events_[eventIndex_].type != YAML_STREAM_END_EVENT) - throw YamlParserException("Did not found end of stream"); -} - -void YamlParser::processDocument() -{ - assert(eventNumber_ > 0); - - for (; (eventIndex_ < eventNumber_) and (events_[eventIndex_].type != YAML_DOCUMENT_END_EVENT); ++eventIndex_) { - switch (events_[eventIndex_].type) { - case YAML_SCALAR_EVENT: - processScalar(&doc_); - break; - case YAML_SEQUENCE_START_EVENT: - processSequence(&doc_); - break; - case YAML_MAPPING_START_EVENT: - processMapping(&doc_); - break; - default: - break; - } - } - - if (events_[eventIndex_].type != YAML_DOCUMENT_END_EVENT) - throw YamlParserException("Did not found end of document"); -} - - -void YamlParser::processScalar(YamlNode *topNode) -{ - if (!topNode) - throw YamlParserException("No container for scalar"); - - ScalarNode *sclr = new ScalarNode(std::string((const char*) events_[eventIndex_].data.scalar.value), topNode); - - topNode->addNode(sclr); -} - - -void YamlParser::processSequence(YamlNode *topNode) -{ - if (!topNode) - throw YamlParserException("No container for sequence"); - - SequenceNode *seq = new SequenceNode(topNode); - - topNode->addNode(seq); - - ++eventIndex_; - - for (; (eventIndex_ < eventNumber_) and (events_[eventIndex_].type != YAML_SEQUENCE_END_EVENT); ++eventIndex_) { - switch (events_[eventIndex_].type) { - case YAML_SCALAR_EVENT: - processScalar(seq); - break; - case YAML_SEQUENCE_START_EVENT: - processSequence(seq); - break; - case YAML_MAPPING_START_EVENT: - processMapping(seq); - break; - default: - break; - } - } - - if (events_[eventIndex_].type != YAML_SEQUENCE_END_EVENT) - throw YamlParserException("Did not found end of sequence"); - -} - -void YamlParser::processMapping(YamlNode *topNode) -{ - if (!topNode) - throw YamlParserException("No container for mapping"); - - MappingNode *map = new MappingNode(topNode); - - topNode->addNode(map); - - ++eventIndex_; - - while ((eventIndex_ < eventNumber_) && (events_[eventIndex_].type != YAML_MAPPING_END_EVENT)) { - - if (events_[eventIndex_].type != YAML_SCALAR_EVENT) - throw YamlParserException("Mapping not followed by a key"); - - map->setTmpKey(std::string((const char *)events_[eventIndex_].data.scalar.value)); - std::string tmpstring((const char *)events_[eventIndex_].data.scalar.value); - ++eventIndex_; - - switch (events_[eventIndex_].type) { - case YAML_SCALAR_EVENT: - processScalar(map); - break; - case YAML_SEQUENCE_START_EVENT: - processSequence(map); - break; - case YAML_MAPPING_START_EVENT: - processMapping(map); - break; - default: - break; - } - - ++eventIndex_; - } - - if (events_[eventIndex_].type != YAML_MAPPING_END_EVENT) - throw YamlParserException("Did not found end of mapping"); -} - -void YamlParser::constructNativeData() -{ - Sequence *seq = doc_.getSequence(); - - for (const auto &item : *seq) { - YamlNode *yamlNode = static_cast<YamlNode *>(item); - if (yamlNode == NULL) { - ERROR("Could not retrieve yaml node from document sequence"); - continue; - } - - NodeType nodeType = yamlNode->getType(); - switch (nodeType) { - case MAPPING: { - MappingNode *map = static_cast<MappingNode *>(yamlNode); - mainNativeDataMapping(map); - break; - } - case SCALAR: - case SEQUENCE: - default: - throw YamlParserException("Unknown type in configuration file, expect a mapping"); - break; + std::vector<std::map<std::string, std::string>> result; + for (const auto &n : node) { + std::map<std::string, std::string> t; + for (const auto &k : keys) { + t[k] = n[k].as<std::string>(""); } + result.push_back(t); } + return result; } -void YamlParser::mainNativeDataMapping(MappingNode *map) -{ - std::map<std::string, YamlNode*> &mapping = map->getMapping(); - - accountSequence_ = static_cast<SequenceNode*>(mapping["accounts"]); - audioNode_ = static_cast<MappingNode *>(mapping["audio"]); -#ifdef SFL_VIDEO - videoNode_ = static_cast<MappingNode *>(mapping["video"]); -#endif - hooksNode_ = static_cast<MappingNode *>(mapping["hooks"]); - preferenceNode_ = static_cast<MappingNode *>(mapping["preferences"]); - voiplinkNode_ = static_cast<MappingNode *>(mapping["voipPreferences"]); - shortcutNode_ = static_cast<MappingNode *>(mapping["shortcuts"]); } -} - diff --git a/daemon/src/config/yamlparser.h b/daemon/src/config/yamlparser.h index b0f03ae9cf..3c7c0fa96c 100644 --- a/daemon/src/config/yamlparser.h +++ b/daemon/src/config/yamlparser.h @@ -31,113 +31,19 @@ #ifndef __YAMLPARSER_H__ #define __YAMLPARSER_H__ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "yamlnode.h" -#include <yaml.h> -#include <cstdio> -#include <stdexcept> -#include <string> -#include <vector> -#include "noncopyable.h" - -namespace Conf { - -#define PARSER_BUFFERSIZE 65536 - -typedef std::vector<yaml_event_t> YamlEventVector; - -class YamlParserException : public std::runtime_error { - public: - YamlParserException(const char *err) : std::runtime_error(err) {} -}; - - -class YamlParser { - - public: - - YamlParser(FILE *fd); - - ~YamlParser(); - - void serializeEvents(); - - void composeEvents(); - - void constructNativeData(); - - SequenceNode *getAccountSequence(); - - MappingNode *getPreferenceNode(); - - MappingNode *getAudioNode(); - -#ifdef SFL_VIDEO - MappingNode *getVideoNode(); -#endif - MappingNode *getHookNode(); - - MappingNode *getVoipPreferenceNode(); - - MappingNode *getShortcutNode(); - - private: - NON_COPYABLE(YamlParser); - - /** - * Copy yaml parser event in event_to according to their type. - */ - void copyEvent(yaml_event_t *event_to, yaml_event_t *event_from); - - void processStream(); - - void processDocument(); - - void processScalar(YamlNode *topNode); - - void processSequence(YamlNode *topNode); - - void processMapping(YamlNode *topNode); - - void mainNativeDataMapping(MappingNode *map); - - /** - * Configuration file descriptor - */ - FILE *fd_; - - /** - * The parser structure. - */ - yaml_parser_t parser_; - - /** - * The event structure array. - */ - YamlEventVector events_; - - /** - * Number of event actually parsed - */ - int eventNumber_; - - YamlDocument doc_; - - int eventIndex_; +#include <yaml-cpp/yaml.h> + +namespace yaml_utils { +// set T to the value stored at key, or leaves T unchanged +// if no value is stored. +template <typename T> +void parseValue(const YAML::Node &node, const char *key, T &value) +{ + value = node[key].as<T>(value); +} - SequenceNode *accountSequence_; - MappingNode *preferenceNode_; - MappingNode *audioNode_; -#ifdef SFL_VIDEO - MappingNode *videoNode_; -#endif - MappingNode *hooksNode_; - MappingNode *voiplinkNode_; - MappingNode *shortcutNode_; -}; +std::vector<std::map<std::string, std::string>> +parseVectorMap(const YAML::Node &node, const std::initializer_list<std::string> &keys); } #endif diff --git a/daemon/src/global.h b/daemon/src/global.h index 03d61fa762..c713714321 100644 --- a/daemon/src/global.h +++ b/daemon/src/global.h @@ -55,13 +55,6 @@ const char * const ZRTP_ZID_FILENAME = "sfl.zid"; #define PCM_DSNOOP "plug:dsnoop" /** Alsa plugin for microphone sharing */ #define PCM_DMIX_DSNOOP "dmix/dsnoop" /** Audio profile using Alsa dmix/dsnoop */ -#define RINGTONE_ENABLED TRUE_STR /** Custom ringtone enable or not */ -#define DISPLAY_DIALPAD TRUE_STR /** Display dialpad or not */ -#define DISPLAY_VOLUME_CONTROLS TRUE_STR /** Display the volume controls or not */ -#define START_HIDDEN TRUE_STR /** SFlphone starts hidden at start-up or not */ -#define WINDOW_POPUP TRUE_STR /** Popup mode */ -#define NOTIFY_ALL TRUE_STR /** Desktop notification level 0: never notify */ - // Error codes for error handling #define NO_ERROR 0x0000 /** No error - Everything alright */ #define ALSA_CAPTURE_DEVICE 0x0001 /** Error while opening capture device */ diff --git a/daemon/src/history/historynamecache.cpp b/daemon/src/history/historynamecache.cpp index 8e2b20d928..db320a25e8 100644 --- a/daemon/src/history/historynamecache.cpp +++ b/daemon/src/history/historynamecache.cpp @@ -56,16 +56,6 @@ HistoryNameCache& HistoryNameCache::getInstance() return instance_; } -void HistoryNameCache::serialize(Conf::YamlEmitter &emitter UNUSED) -{ - //TODO -} - -void HistoryNameCache::unserialize(const Conf::YamlNode &map UNUSED) -{ - //TODO -} - std::string HistoryNameCache::getNameFromHistory(const std::string &number, const std::string &accountid) { return hNameCache_[accountid][number]; diff --git a/daemon/src/history/historynamecache.h b/daemon/src/history/historynamecache.h index dccc88aa7d..431e181981 100644 --- a/daemon/src/history/historynamecache.h +++ b/daemon/src/history/historynamecache.h @@ -31,14 +31,11 @@ #ifndef HISTORYNAMECACHE_H_ #define HISTORYNAMECACHE_H_ -#include "config/serializable.h" #include <iostream> #include <map> -class HistoryNameCache : public Serializable { +class HistoryNameCache { public: - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); static HistoryNameCache& getInstance(); std::string getNameFromHistory(const std::string &number, const std::string &accountid); private: diff --git a/daemon/src/iax/iaxaccount.cpp b/daemon/src/iax/iaxaccount.cpp index 2e076bef3d..fe2c883eb8 100644 --- a/daemon/src/iax/iaxaccount.cpp +++ b/daemon/src/iax/iaxaccount.cpp @@ -42,69 +42,49 @@ #include "iaxcall.h" #include "logger.h" #include "manager.h" -#include "config/yamlnode.h" -#include "config/yamlemitter.h" #include "call_factory.h" +#include "config/yamlparser.h" +#include <yaml-cpp/yaml.h> + constexpr const char * const IAXAccount::ACCOUNT_TYPE; IAXAccount::IAXAccount(const std::string& accountID) : Account(accountID), link_(new IAXVoIPLink(*this)) {} -void IAXAccount::serialize(Conf::YamlEmitter &emitter) +void IAXAccount::serialize(YAML::Emitter &out) { - Conf::MappingNode accountmap(NULL); - - Conf::ScalarNode id(accountID_); - Conf::ScalarNode username(username_); - Conf::ScalarNode password(password_); - Conf::ScalarNode alias(alias_); - Conf::ScalarNode hostname(hostname_); - Conf::ScalarNode enable(enabled_); - Conf::ScalarNode type(ACCOUNT_TYPE); - Conf::ScalarNode mailbox(mailBox_); - - Conf::ScalarNode codecs(audioCodecStr_); - Conf::ScalarNode displayName(displayName_); - - accountmap.setKeyValue(ALIAS_KEY, &alias); - accountmap.setKeyValue(TYPE_KEY, &type); - accountmap.setKeyValue(ID_KEY, &id); - accountmap.setKeyValue(USERNAME_KEY, &username); - accountmap.setKeyValue(PASSWORD_KEY, &password); - accountmap.setKeyValue(HOSTNAME_KEY, &hostname); - accountmap.setKeyValue(ACCOUNT_ENABLE_KEY, &enable); - accountmap.setKeyValue(MAILBOX_KEY, &mailbox); - - accountmap.setKeyValue(DISPLAY_NAME_KEY, &displayName); - accountmap.setKeyValue(AUDIO_CODECS_KEY, &codecs); - - Conf::ScalarNode userAgent(userAgent_); - accountmap.setKeyValue(USER_AGENT_KEY, &userAgent); - - try { - emitter.serializeAccount(&accountmap); - } catch (const Conf::YamlEmitterException &e) { - ERROR("ConfigTree: %s", e.what()); - } + 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_; + 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 Conf::YamlNode &map) +void IAXAccount::unserialize(const YAML::Node &node) { - map.getValue(ALIAS_KEY, &alias_); - map.getValue(USERNAME_KEY, &username_); - map.getValue(PASSWORD_KEY, &password_); - map.getValue(HOSTNAME_KEY, &hostname_); - map.getValue(ACCOUNT_ENABLE_KEY, &enabled_); - map.getValue(MAILBOX_KEY, &mailBox_); - map.getValue(AUDIO_CODECS_KEY, &audioCodecStr_); + using namespace yaml_utils; + parseValue(node, ALIAS_KEY, alias_); + parseValue(node, USERNAME_KEY, username_); + 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_)); - map.getValue(DISPLAY_NAME_KEY, &displayName_); + parseValue(node, DISPLAY_NAME_KEY, displayName_); - map.getValue(USER_AGENT_KEY, &userAgent_); + parseValue(node, USER_AGENT_KEY, userAgent_); } void IAXAccount::setAccountDetails(const std::map<std::string, std::string> &details) diff --git a/daemon/src/iax/iaxaccount.h b/daemon/src/iax/iaxaccount.h index 2f84692199..7577f6bde5 100644 --- a/daemon/src/iax/iaxaccount.h +++ b/daemon/src/iax/iaxaccount.h @@ -37,6 +37,11 @@ #include "iaxvoiplink.h" #include "sfl_types.h" // enable_if_base_of +namespace YAML { + class Emitter; + class Node; +} + class IAXCall; /** @@ -53,9 +58,6 @@ class IAXAccount : public Account { return ACCOUNT_TYPE; } - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); - std::map<std::string, std::string> getAccountDetails() const; void setNextRefreshStamp(int value) { @@ -124,6 +126,8 @@ 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); /** diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index 1ca6d675dd..351a52b0c8 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -314,8 +314,8 @@ IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall& call) case IAX_EVENT_URL: - if (Manager::instance().getConfigString("Hooks", "Hooks.iax2_enabled") == "1") - UrlHook::runAction(Manager::instance().getConfigString("Hooks", "Hooks.url_command"), (char*) event->data); + if (Manager::instance().hookPreference.getIax2Enabled()) + UrlHook::runAction(Manager::instance().hookPreference.getUrlCommand(), (char*) event->data); break; } diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 1b09b8e04f..672a6e43ab 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -55,7 +55,6 @@ #include "numbercleaner.h" #include "config/yamlparser.h" -#include "config/yamlemitter.h" #if HAVE_ALSA #include "audio/alsa/alsalayer.h" @@ -126,7 +125,6 @@ ManagerImpl::ManagerImpl() : preferences(), voipPreferences(), hookPreference(), audioPreference(), shortcutPreferences(), hasTriedToRegister_(false), audioCodecFactory(), client_(), - config_(), currentCallMutex_(), dtmfKey_(), dtmfBuf_(0, AudioFormat::MONO()), toneMutex_(), telephoneTone_(), audiofile_(), audioLayerMutex_(), waitingCalls_(), waitingCallsMutex_(), path_(), @@ -145,29 +143,17 @@ ManagerImpl::parseConfiguration() { bool result = true; - FILE *file = fopen(path_.c_str(), "rb"); - try { - if (file) { - Conf::YamlParser parser(file); - parser.serializeEvents(); - parser.composeEvents(); - parser.constructNativeData(); - const int error_count = loadAccountMap(parser); - fclose(file); - - if (error_count > 0) { - WARN("Errors while parsing %s", path_.c_str()); - result = false; - } - } else { - WARN("Config file not found: creating default account map"); - loadDefaultAccountMap(); + YAML::Node parsedFile = YAML::LoadFile(path_); + const int error_count = loadAccountMap(parsedFile); + + if (error_count > 0) { + WARN("Errors while parsing %s", path_.c_str()); + result = false; } - } catch (const Conf::YamlParserException &e) { - // we only want to close the local file here and then rethrow the exception - fclose(file); - throw; + } catch (const YAML::BadFile &e) { + WARN("Could not open config file: creating default account map"); + loadDefaultAccountMap(); } return result; @@ -189,7 +175,7 @@ ManagerImpl::init(const std::string &config_file) try { no_errors = parseConfiguration(); - } catch (const Conf::YamlParserException &e) { + } catch (const YAML::Exception &e) { ERROR("%s", e.what()); no_errors = false; } @@ -206,7 +192,7 @@ ManagerImpl::init(const std::string &config_file) removeAccounts(); restore_backup(path_); parseConfiguration(); - } catch (const Conf::YamlParserException &e) { + } catch (const YAML::Exception &e) { ERROR("%s", e.what()); WARN("Restoring backup failed, creating default account map"); loadDefaultAccountMap(); @@ -1329,25 +1315,33 @@ ManagerImpl::saveConfig() } try { - Conf::YamlEmitter emitter(path_.c_str()); + YAML::Emitter out; + + // FIXME maybe move this into accountFactory? + out << YAML::BeginMap << YAML::Key << "accounts" << YAML::BeginSeq; - for (const auto& account : accountFactory_.getAllAccounts()) - account->serialize(emitter); + for (const auto& account : accountFactory_.getAllAccounts()) { + account->serialize(out); + } + out << YAML::EndSeq; // FIXME: this is a hack until we get rid of accountOrder preferences.verifyAccountOrder(getAccountList()); - preferences.serialize(emitter); - voipPreferences.serialize(emitter); - hookPreference.serialize(emitter); - audioPreference.serialize(emitter); + preferences.serialize(out); + voipPreferences.serialize(out); + hookPreference.serialize(out); + audioPreference.serialize(out); #ifdef SFL_VIDEO - getVideoManager()->getVideoDeviceMonitor().serialize(emitter); + getVideoManager()->getVideoDeviceMonitor().serialize(out); #endif - shortcutPreferences.serialize(emitter); + shortcutPreferences.serialize(out); - emitter.serializeData(); - } catch (const Conf::YamlEmitterException &e) { - ERROR("ConfigTree: %s", e.what()); + std::ofstream fout(path_); + fout << out.c_str(); + } catch (const YAML::Exception &e) { + ERROR("%s", e.what()); + } catch (const std::runtime_error &e) { + ERROR("%s", e.what()); } } @@ -2276,32 +2270,6 @@ ManagerImpl::audioFormatUsed(AudioFormat format) dtmfKey_.reset(new DTMF(format.sample_rate)); } -//THREAD=Main -std::string -ManagerImpl::getConfigString(const std::string& section, - const std::string& name) const -{ - return config_.getConfigTreeItemValue(section, name); -} - -//THREAD=Main -void -ManagerImpl::setConfig(const std::string& section, const std::string& name, - const std::string& value) -{ - config_.setConfigTreeItem(section, name, value); -} - -//THREAD=Main -void -ManagerImpl::setConfig(const std::string& section, const std::string& name, - int value) -{ - std::ostringstream valueStream; - valueStream << value; - config_.setConfigTreeItem(section, name, valueStream.str()); -} - void ManagerImpl::setAccountsOrder(const std::string& order) { @@ -2466,7 +2434,6 @@ void ManagerImpl::removeAccount(const std::string& accountID) } preferences.removeAccount(accountID); - config_.removeSection(accountID); saveConfig(); @@ -2504,23 +2471,18 @@ ManagerImpl::loadAccountOrder() const } void -ManagerImpl::loadAccount(const Conf::YamlNode *item, int &errorCount, +ManagerImpl::loadAccount(const YAML::Node &node, int &errorCount, const std::string &accountOrder) { - if (!item) { - ERROR("Could not load account"); - ++errorCount; - return; - } - + using namespace yaml_utils; std::string accountType; - item->getValue("type", &accountType); + parseValue(node, "type", accountType); std::string accountid; - item->getValue("id", &accountid); + parseValue(node, "id", accountid); std::string accountAlias; - item->getValue("alias", &accountAlias); + parseValue(node, "alias", accountAlias); const auto inAccountOrder = [&](const std::string & id) { return accountOrder.find(id + "/") != std::string::npos; }; @@ -2536,7 +2498,7 @@ ManagerImpl::loadAccount(const Conf::YamlNode *item, int &errorCount, else a = accountFactory_.getIP2IPAccount(); if (a) { - a->unserialize(*item); + a->unserialize(node); } else { ERROR("Failed to create account type \"%s\"", accountType.c_str()); ++errorCount; @@ -2549,39 +2511,38 @@ ManagerImpl::loadAccount(const Conf::YamlNode *item, int &errorCount, } int -ManagerImpl::loadAccountMap(Conf::YamlParser &parser) +ManagerImpl::loadAccountMap(const YAML::Node &node) { using namespace Conf; accountFactory_.initIP2IPAccount(); - // load saved preferences for IP2IP account from configuration file - Sequence *seq = parser.getAccountSequence()->getSequence(); - // build preferences - preferences.unserialize(*parser.getPreferenceNode()); - voipPreferences.unserialize(*parser.getVoipPreferenceNode()); - hookPreference.unserialize(*parser.getHookNode()); - audioPreference.unserialize(*parser.getAudioNode()); - shortcutPreferences.unserialize(*parser.getShortcutNode()); + preferences.unserialize(node); + voipPreferences.unserialize(node); + hookPreference.unserialize(node); + audioPreference.unserialize(node); + shortcutPreferences.unserialize(node); int errorCount = 0; -#ifdef SFL_VIDEO - VideoManager *controls(getVideoManager()); try { - MappingNode *videoNode = parser.getVideoNode(); - if (videoNode) - controls->getVideoDeviceMonitor().unserialize(*videoNode); - } catch (const YamlParserException &e) { - ERROR("No video node in config file"); +#ifdef SFL_VIDEO + VideoManager *controls(getVideoManager()); + controls->getVideoDeviceMonitor().unserialize(node); +#endif + } catch (const YAML::Exception &e) { + ERROR("%s: No video node in config file", e.what()); ++errorCount; } -#endif const std::string accountOrder = preferences.getAccountOrder(); - for (auto &s : *seq) - loadAccount(s, errorCount, accountOrder); + // load saved preferences for IP2IP account from configuration file + const auto &accountList = node["accounts"]; + + for (auto &a : accountList) { + loadAccount(a, errorCount, accountOrder); + } return errorCount; } diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index 412e4d0c85..f9f023d836 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -48,8 +48,6 @@ #include "client/client.h" -#include "config/sfl_config.h" - #include "conference.h" #include "account_factory.h" @@ -654,37 +652,6 @@ class ManagerImpl { */ void audioFormatUsed(AudioFormat format); - /** - * Change a specific value in the configuration tree. - * This value will then be saved in the user config file sflphonedrc - * @param section The section name - * @param name The parameter name - * @param value The new string value - * @return bool true on success - * false otherwise - */ - void setConfig(const std::string& section, const std::string& name, const std::string& value); - - /** - * Change a specific value in the configuration tree. - * This value will then be saved in the user config file sflphonedrc - * @param section The section name - * @param name The parameter name - * @param value The new int value - * @return bool true on success - * false otherwise - */ - void setConfig(const std::string& section, const std::string& name, int value); - - /** - * Get a string from the configuration tree - * Throw an Conf::ConfigTreeItemException if not found - * @param section The section name to look in - * @param name The parameter name - * @return sdt::string The string value - */ - std::string getConfigString(const std::string& section, const std::string& name) const; - /** * Handle audio sounds heard by a caller while they wait for their * connection to a called party to be completed. @@ -803,9 +770,6 @@ class ManagerImpl { Client client_; - /** The configuration tree. It contains accounts parameters, general user settings ,audio settings, ... */ - Conf::ConfigTree config_; - /** Current Call ID */ std::shared_ptr<Call> currentCall_ = nullptr; @@ -868,7 +832,7 @@ class ManagerImpl { /** * Load the account map from configuration */ - int loadAccountMap(Conf::YamlParser &parser); + int loadAccountMap(const YAML::Node &node); /** * Instance of the MainBuffer for the whole application @@ -1022,7 +986,7 @@ class ManagerImpl { void loadDefaultAccountMap(); - void loadAccount(const Conf::YamlNode *item, int &errorCount, + void loadAccount(const YAML::Node &item, int &errorCount, const std::string &accountOrder); }; diff --git a/daemon/src/preferences.cpp b/daemon/src/preferences.cpp index 4a08cad242..819dd15c4a 100644 --- a/daemon/src/preferences.cpp +++ b/daemon/src/preferences.cpp @@ -48,8 +48,9 @@ #include "audio/pulseaudio/pulselayer.h" #endif #endif /* HAVE_OPENSL */ -#include "config/yamlemitter.h" -#include "config/yamlnode.h" + +#include <yaml-cpp/yaml.h> +#include "config/yamlparser.h" #include "hooks/urlhook.h" #include "sip/sip_utils.h" #include <sstream> @@ -57,6 +58,7 @@ #include "global.h" #include "fileutils.h" +constexpr const char * const Preferences::CONFIG_LABEL; const char * const Preferences::DFT_ZONE = "North America"; const char * const Preferences::REGISTRATION_EXPIRE_KEY = "registrationexpire"; @@ -71,6 +73,7 @@ static const char * const SEARCH_BAR_DISPLAY_KEY = "searchBarDisplay"; static const char * const MD5_HASH_KEY = "md5Hash"; // voip preferences +constexpr const char * const VoipPreference::CONFIG_LABEL; static const char * const PLAY_DTMF_KEY = "playDtmf"; static const char * const PLAY_TONES_KEY = "playTones"; static const char * const PULSE_LENGTH_KEY = "pulseLength"; @@ -78,6 +81,7 @@ static const char * const SYMMETRIC_RTP_KEY = "symmetric"; static const char * const ZID_FILE_KEY = "zidFile"; // hooks preferences +constexpr const char * const HookPreference::CONFIG_LABEL; static const char * const IAX2_ENABLED_KEY = "iax2Enabled"; static const char * const NUMBER_ADD_PREFIX_KEY = "numberAddPrefix"; static const char * const NUMBER_ENABLED_KEY = "numberEnabled"; @@ -86,6 +90,7 @@ static const char * const URL_COMMAND_KEY = "urlCommand"; static const char * const URL_SIP_FIELD_KEY = "urlSipField"; // audio preferences +constexpr const char * const AudioPreference::CONFIG_LABEL; #if HAVE_ALSA static const char * const ALSAMAP_KEY = "alsa"; #endif @@ -110,6 +115,7 @@ static const char * const CAPTURE_MUTED_KEY = "captureMuted"; static const char * const PLAYBACK_MUTED_KEY = "playbackMuted"; // shortcut preferences +constexpr const char * const ShortcutPreferences::CONFIG_LABEL; static const char * const HANGUP_SHORT_KEY = "hangUp"; static const char * const PICKUP_SHORT_KEY = "pickUp"; static const char * const POPUP_SHORT_KEY = "popupWindow"; @@ -177,49 +183,34 @@ void Preferences::removeAccount(const std::string &oldAccountID) accountOrder_.erase(start, oldAccountID.length() + 1); } -void Preferences::serialize(Conf::YamlEmitter &emiter) +void Preferences::serialize(YAML::Emitter &out) { - Conf::MappingNode preferencemap(NULL); - - Conf::ScalarNode order(accountOrder_); - std::stringstream histlimitstr; - histlimitstr << historyLimit_; - Conf::ScalarNode historyLimit(histlimitstr.str()); - std::stringstream histmaxstr; - histmaxstr << historyMaxCalls_; - Conf::ScalarNode historyMaxCalls(histmaxstr.str()); - Conf::ScalarNode zoneToneChoice(zoneToneChoice_); - std::stringstream expirestr; - expirestr << registrationExpire_; - Conf::ScalarNode registrationExpire(expirestr.str()); - std::stringstream portstr; - portstr << portNum_; - Conf::ScalarNode portNum(portstr.str()); - Conf::ScalarNode searchBarDisplay(searchBarDisplay_); - Conf::ScalarNode md5Hash(md5Hash_); - - preferencemap.setKeyValue(ORDER_KEY, &order); - preferencemap.setKeyValue(HISTORY_LIMIT_KEY, &historyLimit); - preferencemap.setKeyValue(HISTORY_MAX_CALLS_KEY, &historyMaxCalls); - preferencemap.setKeyValue(ZONE_TONE_CHOICE_KEY, &zoneToneChoice); - preferencemap.setKeyValue(REGISTRATION_EXPIRE_KEY, ®istrationExpire); - preferencemap.setKeyValue(PORT_NUM_KEY, &portNum); - preferencemap.setKeyValue(SEARCH_BAR_DISPLAY_KEY, &searchBarDisplay); - preferencemap.setKeyValue(MD5_HASH_KEY, &md5Hash); - - emiter.serializePreference(&preferencemap, "preferences"); + out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; + + out << YAML::Key << HISTORY_LIMIT_KEY << YAML::Value << historyLimit_; + out << YAML::Key << HISTORY_MAX_CALLS_KEY << YAML::Value << historyMaxCalls_; + out << YAML::Key << MD5_HASH_KEY << YAML::Value << md5Hash_; + out << YAML::Key << ORDER_KEY << YAML::Value << accountOrder_; + out << YAML::Key << PORT_NUM_KEY << YAML::Value << portNum_; + out << YAML::Key << REGISTRATION_EXPIRE_KEY << YAML::Value << registrationExpire_; + out << YAML::Key << SEARCH_BAR_DISPLAY_KEY << YAML::Value << searchBarDisplay_; + out << YAML::Key << ZONE_TONE_CHOICE_KEY << YAML::Value << zoneToneChoice_; + out << YAML::EndMap; } -void Preferences::unserialize(const Conf::YamlNode &map) +void Preferences::unserialize(const YAML::Node &in) { - map.getValue(ORDER_KEY, &accountOrder_); - map.getValue(HISTORY_LIMIT_KEY, &historyLimit_); - map.getValue(HISTORY_MAX_CALLS_KEY, &historyMaxCalls_); - map.getValue(ZONE_TONE_CHOICE_KEY, &zoneToneChoice_); - map.getValue(REGISTRATION_EXPIRE_KEY, ®istrationExpire_); - map.getValue(PORT_NUM_KEY, &portNum_); - map.getValue(SEARCH_BAR_DISPLAY_KEY, &searchBarDisplay_); - map.getValue(MD5_HASH_KEY, &md5Hash_); + using namespace yaml_utils; + const auto &node = in[CONFIG_LABEL]; + + parseValue(node, ORDER_KEY, accountOrder_); + parseValue(node, HISTORY_LIMIT_KEY, historyLimit_); + parseValue(node, HISTORY_MAX_CALLS_KEY, historyMaxCalls_); + parseValue(node, ZONE_TONE_CHOICE_KEY, zoneToneChoice_); + parseValue(node, REGISTRATION_EXPIRE_KEY, registrationExpire_); + parseValue(node, PORT_NUM_KEY, portNum_); + parseValue(node, SEARCH_BAR_DISPLAY_KEY, searchBarDisplay_); + parseValue(node, MD5_HASH_KEY, md5Hash_); } VoipPreference::VoipPreference() : @@ -230,34 +221,26 @@ VoipPreference::VoipPreference() : , zidFile_(ZRTP_ZIDFILE) {} -void VoipPreference::serialize(Conf::YamlEmitter &emitter) +void VoipPreference::serialize(YAML::Emitter &out) { - Conf::MappingNode preferencemap(NULL); - - Conf::ScalarNode playDtmf(playDtmf_); - Conf::ScalarNode playTones(playTones_); - std::stringstream pulselengthstr; - pulselengthstr << pulseLength_; - Conf::ScalarNode pulseLength(pulselengthstr.str()); - Conf::ScalarNode symmetricRtp(symmetricRtp_); - Conf::ScalarNode zidFile(zidFile_.c_str()); - - preferencemap.setKeyValue(PLAY_DTMF_KEY, &playDtmf); - preferencemap.setKeyValue(PLAY_TONES_KEY, &playTones); - preferencemap.setKeyValue(PULSE_LENGTH_KEY, &pulseLength); - preferencemap.setKeyValue(SYMMETRIC_RTP_KEY, &symmetricRtp); - preferencemap.setKeyValue(ZID_FILE_KEY, &zidFile); - - emitter.serializePreference(&preferencemap, "voipPreferences"); + out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; + out << YAML::Key << PLAY_DTMF_KEY << YAML::Value << playDtmf_; + out << YAML::Key << PLAY_TONES_KEY << YAML::Value << playTones_; + out << YAML::Key << PULSE_LENGTH_KEY << YAML::Value << pulseLength_; + out << YAML::Key << SYMMETRIC_RTP_KEY << YAML::Value << symmetricRtp_; + out << YAML::Key << ZID_FILE_KEY << YAML::Value << zidFile_; + out << YAML::EndMap; } -void VoipPreference::unserialize(const Conf::YamlNode &map) +void VoipPreference::unserialize(const YAML::Node &in) { - map.getValue(PLAY_DTMF_KEY, &playDtmf_); - map.getValue(PLAY_TONES_KEY, &playTones_); - map.getValue(PULSE_LENGTH_KEY, &pulseLength_); - map.getValue(SYMMETRIC_RTP_KEY, &symmetricRtp_); - map.getValue(ZID_FILE_KEY, &zidFile_); + using namespace yaml_utils; + const auto &node = in[CONFIG_LABEL]; + parseValue(node, PLAY_DTMF_KEY, playDtmf_); + parseValue(node, PLAY_TONES_KEY, playTones_); + parseValue(node, PULSE_LENGTH_KEY, pulseLength_); + parseValue(node, SYMMETRIC_RTP_KEY, symmetricRtp_); + parseValue(node, ZID_FILE_KEY, zidFile_); } HookPreference::HookPreference() : @@ -291,35 +274,27 @@ std::map<std::string, std::string> HookPreference::toMap() const return settings; } -void HookPreference::serialize(Conf::YamlEmitter &emitter) +void HookPreference::serialize(YAML::Emitter &out) { - Conf::MappingNode preferencemap(NULL); - - Conf::ScalarNode iax2Enabled(iax2Enabled_); - Conf::ScalarNode numberAddPrefix(numberAddPrefix_); - Conf::ScalarNode numberEnabled(numberEnabled_); - Conf::ScalarNode sipEnabled(sipEnabled_); - Conf::ScalarNode urlCommand(urlCommand_); - Conf::ScalarNode urlSipField(urlSipField_); - - preferencemap.setKeyValue(IAX2_ENABLED_KEY, &iax2Enabled); - preferencemap.setKeyValue(NUMBER_ADD_PREFIX_KEY, &numberAddPrefix); - preferencemap.setKeyValue(NUMBER_ENABLED_KEY, &numberEnabled); - preferencemap.setKeyValue(SIP_ENABLED_KEY, &sipEnabled); - preferencemap.setKeyValue(URL_COMMAND_KEY, &urlCommand); - preferencemap.setKeyValue(URL_SIP_FIELD_KEY, &urlSipField); - - emitter.serializePreference(&preferencemap, "hooks"); + out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; + out << YAML::Key << IAX2_ENABLED_KEY << YAML::Value << iax2Enabled_; + out << YAML::Key << NUMBER_ADD_PREFIX_KEY << YAML::Value << numberAddPrefix_; + out << YAML::Key << SIP_ENABLED_KEY << YAML::Value << sipEnabled_; + out << YAML::Key << URL_COMMAND_KEY << YAML::Value << urlCommand_; + out << YAML::Key << URL_SIP_FIELD_KEY << YAML::Value << urlSipField_; + out << YAML::EndMap; } -void HookPreference::unserialize(const Conf::YamlNode &map) +void HookPreference::unserialize(const YAML::Node &in) { - map.getValue(IAX2_ENABLED_KEY, &iax2Enabled_); - map.getValue(NUMBER_ADD_PREFIX_KEY, &numberAddPrefix_); - map.getValue(NUMBER_ENABLED_KEY, &numberEnabled_); - map.getValue(SIP_ENABLED_KEY, &sipEnabled_); - map.getValue(URL_COMMAND_KEY, &urlCommand_); - map.getValue(URL_SIP_FIELD_KEY, &urlSipField_); + using namespace yaml_utils; + const auto &node = in[CONFIG_LABEL]; + + parseValue(node, IAX2_ENABLED_KEY, iax2Enabled_); + parseValue(node, NUMBER_ADD_PREFIX_KEY, numberAddPrefix_); + parseValue(node, SIP_ENABLED_KEY, sipEnabled_); + parseValue(node, URL_COMMAND_KEY, urlCommand_); + parseValue(node, URL_SIP_FIELD_KEY, urlSipField_); } void HookPreference::runHook(pjsip_msg *msg) @@ -414,74 +389,39 @@ AudioLayer* AudioPreference::createAudioLayer() #endif // __ANDROID__ } -void AudioPreference::serialize(Conf::YamlEmitter &emitter) +void AudioPreference::serialize(YAML::Emitter &out) { - // alsa preference - std::stringstream instr; - instr << alsaCardin_; - Conf::ScalarNode cardin(instr.str()); - std::stringstream outstr; - outstr << alsaCardout_; - Conf::ScalarNode cardout(outstr.str()); - std::stringstream ringstr; - ringstr << alsaCardring_; - Conf::ScalarNode cardring(ringstr.str()); - Conf::ScalarNode plugin(alsaPlugin_); - - std::stringstream ratestr; - ratestr << alsaSmplrate_; - Conf::ScalarNode alsaSmplrate(ratestr.str()); - - //pulseaudio preference - Conf::ScalarNode pulseDevicePlayback(pulseDevicePlayback_); - Conf::ScalarNode pulseDeviceRecord(pulseDeviceRecord_); - Conf::ScalarNode pulseDeviceRingtone(pulseDeviceRingtone_); - - // general preference - Conf::ScalarNode audioapi(audioApi_); - Conf::ScalarNode recordpath(recordpath_); //: /home/msavard/Bureau - Conf::ScalarNode alwaysRecording(alwaysRecording_); - std::ostringstream micstr; - micstr << volumemic_; - Conf::ScalarNode volumemic(micstr.str()); //: 100 - std::ostringstream spkrstr; - spkrstr << volumespkr_; - Conf::ScalarNode volumespkr(spkrstr.str()); //: 100 - Conf::ScalarNode denoise(denoise_); - Conf::ScalarNode agc(agcEnabled_); - Conf::ScalarNode captureMuted(captureMuted_); - Conf::ScalarNode playbackMuted(playbackMuted_); - - Conf::MappingNode preferencemap(NULL); - preferencemap.setKeyValue(AUDIO_API_KEY, &audioapi); - preferencemap.setKeyValue(RECORDPATH_KEY, &recordpath); - preferencemap.setKeyValue(ALWAYS_RECORDING_KEY, &alwaysRecording); - preferencemap.setKeyValue(VOLUMEMIC_KEY, &volumemic); - preferencemap.setKeyValue(VOLUMESPKR_KEY, &volumespkr); - preferencemap.setKeyValue(CAPTURE_MUTED_KEY, &captureMuted); - preferencemap.setKeyValue(PLAYBACK_MUTED_KEY, &playbackMuted); - - Conf::MappingNode alsapreferencemap(NULL); -#if HAVE_ALSA - preferencemap.setKeyValue(ALSAMAP_KEY, &alsapreferencemap); - alsapreferencemap.setKeyValue(CARDIN_KEY, &cardin); - alsapreferencemap.setKeyValue(CARDOUT_KEY, &cardout); - alsapreferencemap.setKeyValue(CARDRING_KEY, &cardring); - alsapreferencemap.setKeyValue(PLUGIN_KEY, &plugin); - alsapreferencemap.setKeyValue(SMPLRATE_KEY, &alsaSmplrate); -#endif - -#if HAVE_PULSE - Conf::MappingNode pulsepreferencemap(NULL); - preferencemap.setKeyValue(PULSEMAP_KEY, &pulsepreferencemap); - pulsepreferencemap.setKeyValue(DEVICE_PLAYBACK_KEY, &pulseDevicePlayback); - pulsepreferencemap.setKeyValue(DEVICE_RECORD_KEY, &pulseDeviceRecord); - pulsepreferencemap.setKeyValue(DEVICE_RINGTONE_KEY, &pulseDeviceRingtone); -#endif - - preferencemap.setKeyValue(NOISE_REDUCE_KEY, &denoise); - preferencemap.setKeyValue(AGC_KEY, &agc); - emitter.serializePreference(&preferencemap, "audio"); + out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; + // alsa submap + out << YAML::Key << ALSAMAP_KEY << YAML::Value << YAML::BeginMap; + out << YAML::Key << CARDIN_KEY << YAML::Value << alsaCardin_; + out << YAML::Key << CARDOUT_KEY << YAML::Value << alsaCardout_; + out << YAML::Key << CARDRING_KEY << YAML::Value << alsaCardring_; + out << YAML::Key << PLUGIN_KEY << YAML::Value << alsaPlugin_; + out << YAML::Key << SMPLRATE_KEY << YAML::Value << alsaSmplrate_; + out << YAML::EndMap; + + // common options + out << YAML::Key << ALWAYS_RECORDING_KEY << YAML::Value << alwaysRecording_; + out << YAML::Key << AUDIO_API_KEY << YAML::Value << audioApi_; + out << YAML::Key << AGC_KEY << YAML::Value << agcEnabled_; + out << YAML::Key << CAPTURE_MUTED_KEY << YAML::Value << captureMuted_; + out << YAML::Key << NOISE_REDUCE_KEY << YAML::Value << denoise_; + out << YAML::Key << PLAYBACK_MUTED_KEY << YAML::Value << playbackMuted_; + + // pulse submap + out << YAML::Key << PULSEMAP_KEY << YAML::Value << YAML::BeginMap; + out << YAML::Key << DEVICE_PLAYBACK_KEY << YAML::Value << pulseDevicePlayback_; + out << YAML::Key << DEVICE_RECORD_KEY << YAML::Value << pulseDeviceRecord_; + out << YAML::Key << DEVICE_RINGTONE_KEY << YAML::Value << pulseDeviceRingtone_; + out << YAML::Key << YAML::EndMap; + + // more common options! + out << YAML::Key << RECORDPATH_KEY << YAML::Value << recordpath_; + out << YAML::Key << VOLUMEMIC_KEY << YAML::Value << volumemic_; + out << YAML::Key << VOLUMESPKR_KEY << YAML::Value << volumespkr_; + + out << YAML::EndMap; } bool @@ -497,50 +437,38 @@ AudioPreference::setRecordPath(const std::string &r) } } -void AudioPreference::unserialize(const Conf::YamlNode &map) +void AudioPreference::unserialize(const YAML::Node &in) { - map.getValue(AUDIO_API_KEY, &audioApi_); - std::string tmpRecordPath; - map.getValue(RECORDPATH_KEY, &tmpRecordPath); - - if (not setRecordPath(tmpRecordPath)) - setRecordPath(fileutils::get_home_dir()); - - map.getValue(ALWAYS_RECORDING_KEY, &alwaysRecording_); - map.getValue(VOLUMEMIC_KEY, &volumemic_); - - const auto clamp = [] (double min, double max, double val) { - return std::min(max, std::max(min, val)); - }; - - volumemic_ = clamp(-1.0, 1.0, volumemic_); - map.getValue(VOLUMESPKR_KEY, &volumespkr_); - volumespkr_ = clamp(-1.0, 1.0, volumespkr_); - map.getValue(NOISE_REDUCE_KEY, &denoise_); - map.getValue(AGC_KEY, &agcEnabled_); - map.getValue(CAPTURE_MUTED_KEY, &captureMuted_); - map.getValue(PLAYBACK_MUTED_KEY, &playbackMuted_); - - Conf::MappingNode *alsamap = (Conf::MappingNode *) map.getValue("alsa"); - - if (alsamap) { - alsamap->getValue(CARDIN_KEY, &alsaCardin_); - alsamap->getValue(CARDOUT_KEY, &alsaCardout_); - alsamap->getValue(CARDRING_KEY, &alsaCardring_); - alsamap->getValue(SMPLRATE_KEY, &alsaSmplrate_); - alsamap->getValue(PLUGIN_KEY, &alsaPlugin_); - } - -#if HAVE_PULSE - Conf::MappingNode *pulsemap = (Conf::MappingNode *)(map.getValue("pulse")); - - if (pulsemap) { - pulsemap->getValue(DEVICE_PLAYBACK_KEY, &pulseDevicePlayback_); - pulsemap->getValue(DEVICE_RECORD_KEY, &pulseDeviceRecord_); - pulsemap->getValue(DEVICE_RINGTONE_KEY, &pulseDeviceRingtone_); - } - -#endif + using namespace yaml_utils; + const auto &node = in[CONFIG_LABEL]; + + // alsa submap + const auto &alsa = node[ALSAMAP_KEY]; + + parseValue(alsa, CARDIN_KEY, alsaCardin_); + parseValue(alsa, CARDOUT_KEY, alsaCardout_); + parseValue(alsa, CARDRING_KEY, alsaCardring_); + parseValue(alsa, PLUGIN_KEY, alsaPlugin_); + parseValue(alsa, SMPLRATE_KEY, alsaSmplrate_); + + // common options + parseValue(node, ALWAYS_RECORDING_KEY, alwaysRecording_); + parseValue(node, AUDIO_API_KEY, audioApi_); + parseValue(node, AGC_KEY, agcEnabled_); + parseValue(node, CAPTURE_MUTED_KEY, captureMuted_); + parseValue(node, NOISE_REDUCE_KEY, denoise_); + parseValue(node, PLAYBACK_MUTED_KEY, playbackMuted_); + + // pulse submap + const auto &pulse = node[PULSEMAP_KEY]; + parseValue(pulse, DEVICE_PLAYBACK_KEY, pulseDevicePlayback_); + parseValue(pulse, DEVICE_RECORD_KEY, pulseDeviceRecord_); + parseValue(pulse, DEVICE_RINGTONE_KEY, pulseDeviceRingtone_); + + // more common options! + parseValue(node, RECORDPATH_KEY, recordpath_); + parseValue(node, VOLUMEMIC_KEY, volumemic_); + parseValue(node, VOLUMESPKR_KEY, volumespkr_); } ShortcutPreferences::ShortcutPreferences() : hangup_(), pickup_(), popup_(), @@ -569,31 +497,26 @@ void ShortcutPreferences::setShortcuts(std::map<std::string, std::string> map) } -void ShortcutPreferences::serialize(Conf::YamlEmitter &emitter) +void ShortcutPreferences::serialize(YAML::Emitter &out) { - Conf::MappingNode preferencemap(NULL); - - Conf::ScalarNode hangup(hangup_); - Conf::ScalarNode pickup(pickup_); - Conf::ScalarNode popup(popup_); - Conf::ScalarNode toggleHold(toggleHold_); - Conf::ScalarNode togglePickupHangup(togglePickupHangup_); - - preferencemap.setKeyValue(HANGUP_SHORT_KEY, &hangup); - preferencemap.setKeyValue(PICKUP_SHORT_KEY, &pickup); - preferencemap.setKeyValue(POPUP_SHORT_KEY, &popup); - preferencemap.setKeyValue(TOGGLE_HOLD_SHORT_KEY, &toggleHold); - preferencemap.setKeyValue(TOGGLE_PICKUP_HANGUP_SHORT_KEY, &togglePickupHangup); - - emitter.serializePreference(&preferencemap, "shortcuts"); + out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; + out << YAML::Key << HANGUP_SHORT_KEY << YAML::Value << hangup_; + out << YAML::Key << PICKUP_SHORT_KEY << YAML::Value << pickup_; + out << YAML::Key << POPUP_SHORT_KEY << YAML::Value << popup_; + out << YAML::Key << TOGGLE_HOLD_SHORT_KEY << YAML::Value << toggleHold_; + out << YAML::Key << TOGGLE_PICKUP_HANGUP_SHORT_KEY << YAML::Value << togglePickupHangup_; + out << YAML::EndMap; } -void ShortcutPreferences::unserialize(const Conf::YamlNode &map) +void ShortcutPreferences::unserialize(const YAML::Node &in) { - map.getValue(HANGUP_SHORT_KEY, &hangup_); - map.getValue(PICKUP_SHORT_KEY, &pickup_); - map.getValue(POPUP_SHORT_KEY, &popup_); - map.getValue(TOGGLE_HOLD_SHORT_KEY, &toggleHold_); - map.getValue(TOGGLE_PICKUP_HANGUP_SHORT_KEY, &togglePickupHangup_); + using namespace yaml_utils; + const auto &node = in[CONFIG_LABEL]; + + parseValue(node, HANGUP_SHORT_KEY, hangup_); + parseValue(node, PICKUP_SHORT_KEY, pickup_); + parseValue(node, POPUP_SHORT_KEY, popup_); + parseValue(node, TOGGLE_HOLD_SHORT_KEY, toggleHold_); + parseValue(node, TOGGLE_PICKUP_HANGUP_SHORT_KEY, togglePickupHangup_); } diff --git a/daemon/src/preferences.h b/daemon/src/preferences.h index a134e44f67..6651159585 100644 --- a/daemon/src/preferences.h +++ b/daemon/src/preferences.h @@ -38,6 +38,11 @@ class AudioLayer; +namespace YAML { + class Emitter; + class Node; +} + class Preferences : public Serializable { public: static const char * const DFT_ZONE; @@ -45,8 +50,8 @@ class Preferences : public Serializable { Preferences(); - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); + void serialize(YAML::Emitter &out); + void unserialize(const YAML::Node &in); std::string getAccountOrder() const { return accountOrder_; @@ -126,14 +131,15 @@ class Preferences : public Serializable { int portNum_; bool searchBarDisplay_; bool md5Hash_; + constexpr static const char * const CONFIG_LABEL = "preferences"; }; class VoipPreference : public Serializable { public: VoipPreference(); - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); + void serialize(YAML::Emitter &out); + void unserialize(const YAML::Node &in); bool getPlayDtmf() const { return playDtmf_; @@ -174,12 +180,12 @@ class VoipPreference : public Serializable { } private: - bool playDtmf_; bool playTones_; int pulseLength_; bool symmetricRtp_; std::string zidFile_; + constexpr static const char * const CONFIG_LABEL = "voipPreferences"; }; struct pjsip_msg; @@ -189,8 +195,8 @@ class HookPreference : public Serializable { HookPreference(); HookPreference(const std::map<std::string, std::string> &settings); - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); + void serialize(YAML::Emitter &out); + void unserialize(const YAML::Node &in); std::string getNumberAddPrefix() const { if (numberEnabled_) @@ -199,6 +205,9 @@ class HookPreference : public Serializable { return ""; } + bool getIax2Enabled() const { return iax2Enabled_; } + const std::string & getUrlCommand() const { return urlCommand_; } + std::map<std::string, std::string> toMap() const; void runHook(pjsip_msg *msg); @@ -209,6 +218,7 @@ class HookPreference : public Serializable { bool sipEnabled_; std::string urlCommand_; std::string urlSipField_; + constexpr static const char * const CONFIG_LABEL = "hooks"; }; class AudioPreference : public Serializable { @@ -225,8 +235,8 @@ class AudioPreference : public Serializable { audioApi_ = api; } - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); + void serialize(YAML::Emitter &out); + void unserialize(const YAML::Node &in); // alsa preference int getAlsaCardin() const { @@ -378,13 +388,14 @@ class AudioPreference : public Serializable { bool agcEnabled_; bool captureMuted_; bool playbackMuted_; + constexpr static const char * const CONFIG_LABEL = "audio"; }; class ShortcutPreferences : public Serializable { public: ShortcutPreferences(); - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); + void serialize(YAML::Emitter &out); + void unserialize(const YAML::Node &in); void setShortcuts(std::map<std::string, std::string> shortcuts); std::map<std::string, std::string> getShortcuts() const; @@ -435,6 +446,7 @@ class ShortcutPreferences : public Serializable { std::string popup_; std::string toggleHold_; std::string togglePickupHangup_; + constexpr static const char * const CONFIG_LABEL = "shortcuts"; }; #endif diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index 79356641c6..784a8978d4 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -50,9 +50,10 @@ #include "client/configurationmanager.h" #endif +#include <yaml-cpp/yaml.h> + #include "account_schema.h" -#include "config/yamlnode.h" -#include "config/yamlemitter.h" +#include "config/yamlparser.h" #include "logger.h" #include "manager.h" @@ -155,25 +156,6 @@ SIPAccount::~SIPAccount() #endif } -static std::array<std::unique_ptr<Conf::ScalarNode>, 2> -serializeRange(Conf::MappingNode &accountMap, const char *minKey, const char *maxKey, const std::pair<uint16_t, uint16_t> &range) -{ - using namespace Conf; - std::array<std::unique_ptr<ScalarNode>, 2> result; - - std::ostringstream os; - os << range.first; - result[0].reset(new ScalarNode(os.str())); - os.str(""); - accountMap.setKeyValue(minKey, result[0].get()); - - os << range.second; - ScalarNode portMax(os.str()); - result[1].reset(new ScalarNode(os.str())); - accountMap.setKeyValue(maxKey, result[1].get()); - return result; -} - static void updateRange(int min, int max, std::pair<uint16_t, uint16_t> &range) { @@ -184,12 +166,12 @@ updateRange(int min, int max, std::pair<uint16_t, uint16_t> &range) } static void -unserializeRange(const Conf::YamlNode &mapNode, const char *minKey, const char *maxKey, std::pair<uint16_t, uint16_t> &range) +unserializeRange(const YAML::Node &node, const char *minKey, const char *maxKey, std::pair<uint16_t, uint16_t> &range) { int tmpMin = 0; int tmpMax = 0; - mapNode.getValue(minKey, &tmpMin); - mapNode.getValue(maxKey, &tmpMax); + yaml_utils::parseValue(node, minKey, tmpMin); + yaml_utils::parseValue(node, maxKey, tmpMax); updateRange(tmpMin, tmpMax, range); } @@ -372,210 +354,94 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call) return true; } -void SIPAccount::serialize(Conf::YamlEmitter &emitter) +void SIPAccount::serialize(YAML::Emitter &out) { using namespace Conf; - MappingNode accountmap(nullptr); - MappingNode srtpmap(nullptr); - MappingNode zrtpmap(nullptr); - MappingNode tlsmap(nullptr); - - ScalarNode id(Account::accountID_); - ScalarNode username(Account::username_); - ScalarNode alias(Account::alias_); - ScalarNode hostname(Account::hostname_); - ScalarNode enable(enabled_); - ScalarNode autoAnswer(autoAnswerEnabled_); - ScalarNode type(ACCOUNT_TYPE); - std::stringstream registrationExpireStr; - registrationExpireStr << registrationExpire_; - ScalarNode expire(registrationExpireStr.str()); - ScalarNode interface(interface_); - std::stringstream portstr; - portstr << localPort_; - ScalarNode port(portstr.str()); - ScalarNode serviceRoute(serviceRoute_); - ScalarNode keepAliveEnabled(keepAliveEnabled_); - -#ifdef SFL_PRESENCE - std::string pres(presence_ and presence_->isEnabled() ? Conf::TRUE_STR : Conf::FALSE_STR); - ScalarNode presenceEnabled(pres); - std::string presPub(presence_ and presence_->isSupported(PRESENCE_FUNCTION_PUBLISH) ? Conf::TRUE_STR : Conf::FALSE_STR); - ScalarNode presencePublish(presPub); - std::string presSub(presence_ and presence_->isSupported(PRESENCE_FUNCTION_SUBSCRIBE) ? Conf::TRUE_STR : Conf::FALSE_STR); - ScalarNode presenceSubscribe(presSub); -#endif - - ScalarNode mailbox(mailBox_); - ScalarNode publishAddr(publishedIpAddress_); - std::stringstream publicportstr; - publicportstr << publishedPort_; - - ScalarNode publishPort(publicportstr.str()); - - ScalarNode sameasLocal(publishedSameasLocal_); - ScalarNode audioCodecs(audioCodecStr_); -#ifdef SFL_VIDEO - SequenceNode videoCodecs(nullptr); - accountmap.setKeyValue(VIDEO_CODECS_KEY, &videoCodecs); - for (auto &codec : videoCodecList_) { - MappingNode *mapNode = new MappingNode(nullptr); - mapNode->setKeyValue(VIDEO_CODEC_NAME, new ScalarNode(codec[VIDEO_CODEC_NAME])); - mapNode->setKeyValue(VIDEO_CODEC_BITRATE, new ScalarNode(codec[VIDEO_CODEC_BITRATE])); - mapNode->setKeyValue(VIDEO_CODEC_ENABLED, new ScalarNode(codec[VIDEO_CODEC_ENABLED])); - mapNode->setKeyValue(VIDEO_CODEC_PARAMETERS, new ScalarNode(codec[VIDEO_CODEC_PARAMETERS])); - videoCodecs.addNode(mapNode); - } - -#endif - - ScalarNode ringtonePath(ringtonePath_); - ScalarNode ringtoneEnabled(ringtoneEnabled_); - ScalarNode videoEnabled(videoEnabled_); - ScalarNode stunServer(stunServer_); - ScalarNode stunEnabled(stunEnabled_); - ScalarNode displayName(displayName_); - ScalarNode dtmfType(dtmfType_); - - std::stringstream countstr; - countstr << 0; - ScalarNode count(countstr.str()); + out << YAML::BeginMap; + out << YAML::Key << ALIAS_KEY << YAML::Value << alias_; + out << YAML::Key << AUDIO_CODECS_KEY << YAML::Value << audioCodecStr_; + 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 << ACCOUNT_AUTOANSWER_KEY << YAML::Value << autoAnswerEnabled_; + // each credential is a map, and we can have multiple credentials + out << YAML::Key << CRED_KEY << YAML::Value << credentials_; + + out << YAML::Key << DISPLAY_NAME_KEY << YAML::Value << displayName_; + out << YAML::Key << DTMF_TYPE_KEY << YAML::Value << dtmfType_; + out << YAML::Key << ACCOUNT_ENABLE_KEY << YAML::Value << enabled_; + out << YAML::Key << HAS_CUSTOM_USER_AGENT_KEY << YAML::Value << hasCustomUserAgent_; + out << YAML::Key << HOSTNAME_KEY << YAML::Value << hostname_; + out << YAML::Key << ID_KEY << YAML::Value << accountID_; + out << YAML::Key << INTERFACE_KEY << YAML::Value << interface_; + out << YAML::Key << KEEP_ALIVE_ENABLED << YAML::Value << keepAliveEnabled_; + out << YAML::Key << MAILBOX_KEY << YAML::Value << mailBox_; + out << YAML::Key << PORT_KEY << YAML::Value << localPort_; - ScalarNode srtpenabled(srtpEnabled_); - ScalarNode keyExchange(srtpKeyExchange_); - ScalarNode rtpFallback(srtpFallback_); - - ScalarNode displaySas(zrtpDisplaySas_); - ScalarNode displaySasOnce(zrtpDisplaySasOnce_); - ScalarNode helloHashEnabled(zrtpHelloHash_); - ScalarNode notSuppWarning(zrtpNotSuppWarning_); - - portstr.str(""); - portstr << tlsListenerPort_; - ScalarNode tlsport(portstr.str()); - ScalarNode certificate(tlsCertificateFile_); - ScalarNode calist(tlsCaListFile_); - ScalarNode ciphersNode(tlsCiphers_); - ScalarNode tlsenabled(tlsEnable_); - ScalarNode tlsmethod(tlsMethod_); - ScalarNode timeout(tlsNegotiationTimeoutSec_); - ScalarNode tlspassword(tlsPassword_); - ScalarNode privatekey(tlsPrivateKeyFile_); - ScalarNode requirecertif(tlsRequireClientCertificate_); - ScalarNode server(tlsServerName_); - ScalarNode verifyclient(tlsVerifyServer_); - ScalarNode verifyserver(tlsVerifyClient_); - - accountmap.setKeyValue(ALIAS_KEY, &alias); - accountmap.setKeyValue(TYPE_KEY, &type); - accountmap.setKeyValue(ID_KEY, &id); - accountmap.setKeyValue(USERNAME_KEY, &username); - accountmap.setKeyValue(HOSTNAME_KEY, &hostname); - accountmap.setKeyValue(ACCOUNT_ENABLE_KEY, &enable); - accountmap.setKeyValue(ACCOUNT_AUTOANSWER_KEY, &autoAnswer); - accountmap.setKeyValue(MAILBOX_KEY, &mailbox); - accountmap.setKeyValue(Preferences::REGISTRATION_EXPIRE_KEY, &expire); - accountmap.setKeyValue(INTERFACE_KEY, &interface); - accountmap.setKeyValue(PORT_KEY, &port); - accountmap.setKeyValue(STUN_SERVER_KEY, &stunServer); - accountmap.setKeyValue(STUN_ENABLED_KEY, &stunEnabled); - accountmap.setKeyValue(PUBLISH_ADDR_KEY, &publishAddr); - accountmap.setKeyValue(PUBLISH_PORT_KEY, &publishPort); - accountmap.setKeyValue(SAME_AS_LOCAL_KEY, &sameasLocal); - accountmap.setKeyValue(SERVICE_ROUTE_KEY, &serviceRoute); - accountmap.setKeyValue(DTMF_TYPE_KEY, &dtmfType); - accountmap.setKeyValue(DISPLAY_NAME_KEY, &displayName); - accountmap.setKeyValue(AUDIO_CODECS_KEY, &audioCodecs); - accountmap.setKeyValue(RINGTONE_PATH_KEY, &ringtonePath); - accountmap.setKeyValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled); - accountmap.setKeyValue(VIDEO_ENABLED_KEY, &videoEnabled); - accountmap.setKeyValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled); #ifdef SFL_PRESENCE - accountmap.setKeyValue(PRESENCE_ENABLED_KEY, &presenceEnabled); - accountmap.setKeyValue(PRESENCE_PUBLISH_SUPPORTED_KEY, &presencePublish); - accountmap.setKeyValue(PRESENCE_SUBSCRIBE_SUPPORTED_KEY, &presenceSubscribe); + out << YAML::Key << PRESENCE_MODULE_ENABLED_KEY << YAML::Value << (presence_ and presence_->isEnabled()); + out << YAML::Key << PRESENCE_PUBLISH_SUPPORTED_KEY << YAML::Value << (presence_ and presence_->isSupported(PRESENCE_FUNCTION_PUBLISH)); + out << YAML::Key << PRESENCE_SUBSCRIBE_SUPPORTED_KEY << YAML::Value << (presence_ and presence_->isSupported(PRESENCE_FUNCTION_SUBSCRIBE)); +#else + out << YAML::Key << PRESENCE_MODULE_ENABLED_KEY << YAML::Value << false; + out << YAML::Key << PRESENCE_PUBLISH_SUPPORTED_KEY << YAML::Value << false; + out << YAML::Key << PRESENCE_SUBSCRIBE_SUPPORTED_KEY << YAML::Value << false; #endif - accountmap.setKeyValue(SRTP_KEY, &srtpmap); - srtpmap.setKeyValue(SRTP_ENABLE_KEY, &srtpenabled); - srtpmap.setKeyValue(KEY_EXCHANGE_KEY, &keyExchange); - srtpmap.setKeyValue(RTP_FALLBACK_KEY, &rtpFallback); - - accountmap.setKeyValue(ZRTP_KEY, &zrtpmap); - zrtpmap.setKeyValue(DISPLAY_SAS_KEY, &displaySas); - zrtpmap.setKeyValue(DISPLAY_SAS_ONCE_KEY, &displaySasOnce); - zrtpmap.setKeyValue(HELLO_HASH_ENABLED_KEY, &helloHashEnabled); - zrtpmap.setKeyValue(NOT_SUPP_WARNING_KEY, ¬SuppWarning); - - SequenceNode credentialseq(nullptr); - accountmap.setKeyValue(CRED_KEY, &credentialseq); - - for (const auto &it : credentials_) { - std::map<std::string, std::string> cred = it; - MappingNode *map = new MappingNode(nullptr); - map->setKeyValue(CONFIG_ACCOUNT_USERNAME, new ScalarNode(cred[CONFIG_ACCOUNT_USERNAME])); - map->setKeyValue(CONFIG_ACCOUNT_PASSWORD, new ScalarNode(cred[CONFIG_ACCOUNT_PASSWORD])); - map->setKeyValue(CONFIG_ACCOUNT_REALM, new ScalarNode(cred[CONFIG_ACCOUNT_REALM])); - credentialseq.addNode(map); - } - - accountmap.setKeyValue(TLS_KEY, &tlsmap); - tlsmap.setKeyValue(TLS_PORT_KEY, &tlsport); - tlsmap.setKeyValue(CERTIFICATE_KEY, &certificate); - tlsmap.setKeyValue(CALIST_KEY, &calist); - tlsmap.setKeyValue(CIPHERS_KEY, &ciphersNode); - tlsmap.setKeyValue(TLS_ENABLE_KEY, &tlsenabled); - tlsmap.setKeyValue(METHOD_KEY, &tlsmethod); - tlsmap.setKeyValue(TIMEOUT_KEY, &timeout); - tlsmap.setKeyValue(TLS_PASSWORD_KEY, &tlspassword); - tlsmap.setKeyValue(PRIVATE_KEY_KEY, &privatekey); - tlsmap.setKeyValue(REQUIRE_CERTIF_KEY, &requirecertif); - tlsmap.setKeyValue(SERVER_KEY, &server); - tlsmap.setKeyValue(VERIFY_CLIENT_KEY, &verifyclient); - tlsmap.setKeyValue(VERIFY_SERVER_KEY, &verifyserver); - - ScalarNode userAgent(userAgent_); - accountmap.setKeyValue(USER_AGENT_KEY, &userAgent); - - ScalarNode hasCustomUserAgent(hasCustomUserAgent_); - accountmap.setKeyValue(HAS_CUSTOM_USER_AGENT_KEY, &hasCustomUserAgent); - - auto audioPortNodes(serializeRange(accountmap, AUDIO_PORT_MIN_KEY, AUDIO_PORT_MAX_KEY, audioPortRange_)); -#ifdef SFL_VIDEO - auto videoPortNodes(serializeRange(accountmap, VIDEO_PORT_MIN_KEY, VIDEO_PORT_MAX_KEY, videoPortRange_)); -#endif - - try { - emitter.serializeAccount(&accountmap); - } catch (const YamlEmitterException &e) { - ERROR("%s", e.what()); - } - - // Cleanup - Sequence *credSeq = credentialseq.getSequence(); - - for (const auto &seqit : *credSeq) { - MappingNode *node = static_cast<MappingNode*>(seqit); - delete node->getValue(CONFIG_ACCOUNT_USERNAME); - delete node->getValue(CONFIG_ACCOUNT_PASSWORD); - delete node->getValue(CONFIG_ACCOUNT_REALM); - delete node; - } - -#ifdef SFL_VIDEO - Sequence *videoCodecSeq = videoCodecs.getSequence(); - - for (auto &i : *videoCodecSeq) { - MappingNode *node = static_cast<MappingNode*>(i); - delete node->getValue(VIDEO_CODEC_NAME); - delete node->getValue(VIDEO_CODEC_BITRATE); - delete node->getValue(VIDEO_CODEC_ENABLED); - delete node->getValue(VIDEO_CODEC_PARAMETERS); - delete node; - } - -#endif + out << YAML::Key << PUBLISH_ADDR_KEY << YAML::Value << publishedIpAddress_; + out << YAML::Key << PUBLISH_PORT_KEY << YAML::Value << publishedPort_; + out << YAML::Key << Preferences::REGISTRATION_EXPIRE_KEY << YAML::Value << registrationExpire_; + out << YAML::Key << RINGTONE_ENABLED_KEY << YAML::Value << ringtoneEnabled_; + out << YAML::Key << RINGTONE_PATH_KEY << YAML::Value << ringtonePath_; + out << YAML::Key << SAME_AS_LOCAL_KEY << YAML::Value << publishedSameasLocal_; + out << YAML::Key << SERVICE_ROUTE_KEY << YAML::Value << serviceRoute_; + + // 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 << STUN_ENABLED_KEY << YAML::Value << stunEnabled_; + out << YAML::Key << STUN_SERVER_KEY << YAML::Value << stunServer_; + + // tls submap + out << YAML::Key << TLS_KEY << YAML::Value << YAML::BeginMap; + out << YAML::Key << CALIST_KEY << YAML::Value << tlsCaListFile_; + out << YAML::Key << CERTIFICATE_KEY << YAML::Value << tlsCertificateFile_; + out << YAML::Key << CIPHERS_KEY << YAML::Value << tlsCiphers_; + out << YAML::Key << TLS_ENABLE_KEY << YAML::Value << tlsEnable_; + out << YAML::Key << METHOD_KEY << YAML::Value << tlsMethod_; + out << YAML::Key << TLS_PASSWORD_KEY << YAML::Value << tlsPassword_; + out << YAML::Key << PRIVATE_KEY_KEY << YAML::Value << tlsPrivateKeyFile_; + out << YAML::Key << REQUIRE_CERTIF_KEY << YAML::Value << tlsRequireClientCertificate_; + out << YAML::Key << SERVER_KEY << YAML::Value << tlsServerName_; + out << YAML::Key << TIMEOUT_KEY << YAML::Value << tlsNegotiationTimeoutSec_; + out << YAML::Key << TLS_PORT_KEY << YAML::Value << tlsListenerPort_; + out << YAML::Key << VERIFY_CLIENT_KEY << YAML::Value << tlsVerifyClient_; + out << YAML::Key << VERIFY_SERVER_KEY << YAML::Value << tlsVerifyServer_; + out << YAML::EndMap; + + 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::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; + + // zrtp submap + out << YAML::Key << ZRTP_KEY << YAML::Value << YAML::BeginMap; + out << YAML::Key << DISPLAY_SAS_KEY << YAML::Value << zrtpDisplaySas_; + out << YAML::Key << DISPLAY_SAS_ONCE_KEY << YAML::Value << zrtpDisplaySasOnce_; + out << YAML::Key << HELLO_HASH_ENABLED_KEY << YAML::Value << zrtpHelloHash_; + out << YAML::Key << NOT_SUPP_WARNING_KEY << YAML::Value << zrtpNotSuppWarning_; + out << YAML::EndMap; + + out << YAML::EndMap; } void SIPAccount::usePublishedAddressPortInVIA() @@ -597,205 +463,136 @@ validate(std::string &member, const std::string ¶m, const T& valid) ERROR("Invalid parameter \"%s\"", param.c_str()); } -void SIPAccount::unserialize(const Conf::YamlNode &mapNode) +void SIPAccount::unserialize(const YAML::Node &node) { using namespace Conf; - using std::vector; - using std::map; - using std::string; + using namespace yaml_utils; + parseValue(node, ALIAS_KEY, alias_); + parseValue(node, USERNAME_KEY, username_); - mapNode.getValue(ALIAS_KEY, &alias_); - mapNode.getValue(USERNAME_KEY, &username_); + if (not isIP2IP()) parseValue(node, HOSTNAME_KEY, hostname_); - if (not isIP2IP()) mapNode.getValue(HOSTNAME_KEY, &hostname_); + parseValue(node, ACCOUNT_ENABLE_KEY, enabled_); + parseValue(node, ACCOUNT_AUTOANSWER_KEY, autoAnswerEnabled_); - mapNode.getValue(ACCOUNT_ENABLE_KEY, &enabled_); - mapNode.getValue(ACCOUNT_AUTOANSWER_KEY, &autoAnswerEnabled_); + if (not isIP2IP()) parseValue(node, MAILBOX_KEY, mailBox_); - if (not isIP2IP()) mapNode.getValue(MAILBOX_KEY, &mailBox_); - - mapNode.getValue(AUDIO_CODECS_KEY, &audioCodecStr_); + parseValue(node, AUDIO_CODECS_KEY, audioCodecStr_); // Update codec list which one is used for SDP offer setActiveAudioCodecs(split_string(audioCodecStr_)); -#ifdef SFL_VIDEO - YamlNode *videoCodecsNode(mapNode.getValue(VIDEO_CODECS_KEY)); - - if (videoCodecsNode and videoCodecsNode->getType() == SEQUENCE) { - SequenceNode *videoCodecs = static_cast<SequenceNode *>(videoCodecsNode); - Sequence *seq = videoCodecs->getSequence(); - - if (seq->empty()) { - // Video codecs are an empty list - WARN("Loading default video codecs"); - videoCodecList_ = libav_utils::getDefaultCodecs(); - } else { - vector<map<string, string> > videoCodecDetails; - - for (const auto &it : *seq) { - MappingNode *codec = static_cast<MappingNode *>(it); - map<string, string> codecMap; - codec->getValue(VIDEO_CODEC_NAME, &codecMap[VIDEO_CODEC_NAME]); - codec->getValue(VIDEO_CODEC_BITRATE, &codecMap[VIDEO_CODEC_BITRATE]); - codec->getValue(VIDEO_CODEC_ENABLED, &codecMap[VIDEO_CODEC_ENABLED]); - codec->getValue(VIDEO_CODEC_PARAMETERS, &codecMap[VIDEO_CODEC_PARAMETERS]); - videoCodecDetails.push_back(codecMap); - } + const auto &vCodecNode = node[VIDEO_CODECS_KEY]; + auto tmp = parseVectorMap(vCodecNode, {VIDEO_CODEC_BITRATE, + VIDEO_CODEC_ENABLED, VIDEO_CODEC_NAME, VIDEO_CODEC_PARAMETERS}); - // these must be validated - setVideoCodecs(videoCodecDetails); - } - } else { - // either this is an older config file which had videoCodecs as a scalar node, - // or it had no video codecs at all +#ifdef SFL_VIDEO + if (tmp.empty()) { + // Video codecs are an empty list WARN("Loading default video codecs"); - videoCodecList_ = libav_utils::getDefaultCodecs(); + tmp = libav_utils::getDefaultCodecs(); } - #endif + // validate it + setVideoCodecs(tmp); - mapNode.getValue(RINGTONE_PATH_KEY, &ringtonePath_); - mapNode.getValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled_); - mapNode.getValue(VIDEO_ENABLED_KEY, &videoEnabled_); + parseValue(node, RINGTONE_PATH_KEY, ringtonePath_); + parseValue(node, RINGTONE_ENABLED_KEY, ringtoneEnabled_); + parseValue(node, VIDEO_ENABLED_KEY, videoEnabled_); - if (not isIP2IP()) mapNode.getValue(Preferences::REGISTRATION_EXPIRE_KEY, ®istrationExpire_); + if (not isIP2IP()) parseValue(node, Preferences::REGISTRATION_EXPIRE_KEY, registrationExpire_); - mapNode.getValue(INTERFACE_KEY, &interface_); + parseValue(node, INTERFACE_KEY, interface_); int port = DEFAULT_SIP_PORT; - mapNode.getValue(PORT_KEY, &port); + parseValue(node, PORT_KEY, port); localPort_ = port; - mapNode.getValue(PUBLISH_ADDR_KEY, &publishedIpAddress_); - mapNode.getValue(PUBLISH_PORT_KEY, &port); + parseValue(node, PUBLISH_ADDR_KEY, publishedIpAddress_); + parseValue(node, PUBLISH_PORT_KEY, port); publishedPort_ = port; - mapNode.getValue(SAME_AS_LOCAL_KEY, &publishedSameasLocal_); + parseValue(node, SAME_AS_LOCAL_KEY, publishedSameasLocal_); if (not publishedSameasLocal_) usePublishedAddressPortInVIA(); - if (not isIP2IP()) mapNode.getValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled_); + if (not isIP2IP()) parseValue(node, KEEP_ALIVE_ENABLED, keepAliveEnabled_); + bool presEnabled = false; + parseValue(node, PRESENCE_ENABLED_KEY, presEnabled); + enablePresence(presEnabled); + bool publishSupported = false; + parseValue(node, PRESENCE_PUBLISH_SUPPORTED_KEY, publishSupported); + bool subscribeSupported = false; + parseValue(node, PRESENCE_SUBSCRIBE_SUPPORTED_KEY, subscribeSupported); #ifdef SFL_PRESENCE - std::string pres; - mapNode.getValue(PRESENCE_ENABLED_KEY, &pres); - enablePresence(pres == Conf::TRUE_STR); - mapNode.getValue(PRESENCE_PUBLISH_SUPPORTED_KEY, &pres); - if (presence_) - presence_->support(PRESENCE_FUNCTION_PUBLISH, pres == Conf::TRUE_STR); - mapNode.getValue(PRESENCE_SUBSCRIBE_SUPPORTED_KEY, &pres); - if (presence_) - presence_->support(PRESENCE_FUNCTION_SUBSCRIBE, pres == Conf::TRUE_STR); + if (presence_) { + presence_->support(PRESENCE_FUNCTION_PUBLISH, publishSupported); + presence_->support(PRESENCE_FUNCTION_SUBSCRIBE, subscribeSupported); + } #endif - std::string dtmfType; - mapNode.getValue(DTMF_TYPE_KEY, &dtmfType); - dtmfType_ = dtmfType; + parseValue(node, DTMF_TYPE_KEY, dtmfType_); - if (not isIP2IP()) mapNode.getValue(SERVICE_ROUTE_KEY, &serviceRoute_); + if (not isIP2IP()) parseValue(node, SERVICE_ROUTE_KEY, serviceRoute_); // stun enabled - if (not isIP2IP()) mapNode.getValue(STUN_ENABLED_KEY, &stunEnabled_); + if (not isIP2IP()) parseValue(node, STUN_ENABLED_KEY, stunEnabled_); - if (not isIP2IP()) mapNode.getValue(STUN_SERVER_KEY, &stunServer_); + if (not isIP2IP()) parseValue(node, STUN_SERVER_KEY, stunServer_); // Init stun server name with default server name stunServerName_ = pj_str((char*) stunServer_.data()); - mapNode.getValue(DISPLAY_NAME_KEY, &displayName_); - - std::vector<std::map<std::string, std::string> > creds; - - YamlNode *credNode = mapNode.getValue(CRED_KEY); - - /* We check if the credential key is a sequence - * because it was a mapping in a previous version of - * the configuration file. - */ - if (credNode && credNode->getType() == SEQUENCE) { - SequenceNode *credSeq = static_cast<SequenceNode *>(credNode); - Sequence *seq = credSeq->getSequence(); - - for (const auto &it : *seq) { - MappingNode *cred = static_cast<MappingNode *>(it); - std::string user; - std::string pass; - std::string realm; - cred->getValue(CONFIG_ACCOUNT_USERNAME, &user); - cred->getValue(CONFIG_ACCOUNT_PASSWORD, &pass); - cred->getValue(CONFIG_ACCOUNT_REALM, &realm); - std::map<std::string, std::string> credentialMap; - credentialMap[CONFIG_ACCOUNT_USERNAME] = user; - credentialMap[CONFIG_ACCOUNT_PASSWORD] = pass; - credentialMap[CONFIG_ACCOUNT_REALM] = realm; - creds.push_back(credentialMap); - } - } - - if (creds.empty()) { - // migration from old file format - std::map<std::string, std::string> credmap; - std::string password; - - if (not isIP2IP()) mapNode.getValue(PASSWORD_KEY, &password); - - credmap[CONFIG_ACCOUNT_USERNAME] = username_; - credmap[CONFIG_ACCOUNT_PASSWORD] = password; - credmap[CONFIG_ACCOUNT_REALM] = "*"; - creds.push_back(credmap); - } + parseValue(node, DISPLAY_NAME_KEY, displayName_); + const auto &credsNode = node[CRED_KEY]; + const auto creds = parseVectorMap(credsNode, {CONFIG_ACCOUNT_PASSWORD, + CONFIG_ACCOUNT_REALM, CONFIG_ACCOUNT_USERNAME}); setCredentials(creds); // get srtp submap - MappingNode *srtpMap = static_cast<MappingNode *>(mapNode.getValue(SRTP_KEY)); + const auto &srtpMap = node[SRTP_KEY]; - if (srtpMap) { - srtpMap->getValue(SRTP_ENABLE_KEY, &srtpEnabled_); - std::string tmp; - srtpMap->getValue(KEY_EXCHANGE_KEY, &tmp); - validate(srtpKeyExchange_, tmp, VALID_SRTP_KEY_EXCHANGES); - srtpMap->getValue(RTP_FALLBACK_KEY, &srtpFallback_); - } + 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_); // get zrtp submap - MappingNode *zrtpMap = static_cast<MappingNode *>(mapNode.getValue(ZRTP_KEY)); + const auto &zrtpMap = node[ZRTP_KEY]; - if (zrtpMap) { - zrtpMap->getValue(DISPLAY_SAS_KEY, &zrtpDisplaySas_); - zrtpMap->getValue(DISPLAY_SAS_ONCE_KEY, &zrtpDisplaySasOnce_); - zrtpMap->getValue(HELLO_HASH_ENABLED_KEY, &zrtpHelloHash_); - zrtpMap->getValue(NOT_SUPP_WARNING_KEY, &zrtpNotSuppWarning_); - } + parseValue(zrtpMap, DISPLAY_SAS_KEY, zrtpDisplaySas_); + parseValue(zrtpMap, DISPLAY_SAS_ONCE_KEY, zrtpDisplaySasOnce_); + parseValue(zrtpMap, HELLO_HASH_ENABLED_KEY, zrtpHelloHash_); + parseValue(zrtpMap, NOT_SUPP_WARNING_KEY, zrtpNotSuppWarning_); // get tls submap - MappingNode *tlsMap = static_cast<MappingNode *>(mapNode.getValue(TLS_KEY)); - - if (tlsMap) { - tlsMap->getValue(TLS_ENABLE_KEY, &tlsEnable_); - std::string tlsPort; - tlsMap->getValue(TLS_PORT_KEY, &tlsPort); - tlsListenerPort_ = atoi(tlsPort.c_str()); - tlsMap->getValue(CERTIFICATE_KEY, &tlsCertificateFile_); - tlsMap->getValue(CALIST_KEY, &tlsCaListFile_); - tlsMap->getValue(CIPHERS_KEY, &tlsCiphers_); - - std::string tmp(tlsMethod_); - tlsMap->getValue(METHOD_KEY, &tmp); - validate(tlsMethod_, tmp, VALID_TLS_METHODS); - - tlsMap->getValue(TLS_PASSWORD_KEY, &tlsPassword_); - tlsMap->getValue(PRIVATE_KEY_KEY, &tlsPrivateKeyFile_); - tlsMap->getValue(REQUIRE_CERTIF_KEY, &tlsRequireClientCertificate_); - tlsMap->getValue(SERVER_KEY, &tlsServerName_); - tlsMap->getValue(VERIFY_CLIENT_KEY, &tlsVerifyClient_); - tlsMap->getValue(VERIFY_SERVER_KEY, &tlsVerifyServer_); - // FIXME - tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutSec_); - } - mapNode.getValue(USER_AGENT_KEY, &userAgent_); - mapNode.getValue(HAS_CUSTOM_USER_AGENT_KEY, &userAgent_); - - unserializeRange(mapNode, AUDIO_PORT_MIN_KEY, AUDIO_PORT_MAX_KEY, audioPortRange_); + const auto &tlsMap = node[TLS_KEY]; + + parseValue(tlsMap, TLS_ENABLE_KEY, tlsEnable_); + parseValue(tlsMap, TLS_PORT_KEY, tlsListenerPort_); + parseValue(tlsMap, CERTIFICATE_KEY, tlsCertificateFile_); + parseValue(tlsMap, CALIST_KEY, tlsCaListFile_); + parseValue(tlsMap, CIPHERS_KEY, tlsCiphers_); + + std::string tmpMethod(tlsMethod_); + parseValue(tlsMap, METHOD_KEY, tmpMethod); + validate(tlsMethod_, tmpMethod, VALID_TLS_METHODS); + + parseValue(tlsMap, TLS_PASSWORD_KEY, tlsPassword_); + parseValue(tlsMap, PRIVATE_KEY_KEY, tlsPrivateKeyFile_); + parseValue(tlsMap, REQUIRE_CERTIF_KEY, tlsRequireClientCertificate_); + parseValue(tlsMap, SERVER_KEY, tlsServerName_); + parseValue(tlsMap, VERIFY_CLIENT_KEY, tlsVerifyClient_); + parseValue(tlsMap, VERIFY_SERVER_KEY, tlsVerifyServer_); + // FIXME + parseValue(tlsMap, TIMEOUT_KEY, tlsNegotiationTimeoutSec_); + + parseValue(node, USER_AGENT_KEY, userAgent_); + parseValue(node, HAS_CUSTOM_USER_AGENT_KEY, hasCustomUserAgent_); + + unserializeRange(node, AUDIO_PORT_MIN_KEY, AUDIO_PORT_MAX_KEY, audioPortRange_); #ifdef SFL_VIDEO - unserializeRange(mapNode, VIDEO_PORT_MIN_KEY, VIDEO_PORT_MAX_KEY, videoPortRange_); + unserializeRange(node, VIDEO_PORT_MIN_KEY, VIDEO_PORT_MAX_KEY, videoPortRange_); #endif } @@ -940,8 +737,8 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const // note: The IP2IP profile will always have IP2IP as an alias a[CONFIG_ACCOUNT_ALIAS] = alias_; - a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_ACCOUNT_AUTOANSWER] = autoAnswerEnabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_ACCOUNT_ENABLE] = enabled_ ? TRUE_STR : FALSE_STR; + a[CONFIG_ACCOUNT_AUTOANSWER] = autoAnswerEnabled_ ? TRUE_STR : FALSE_STR; a[CONFIG_ACCOUNT_TYPE] = ACCOUNT_TYPE; a[CONFIG_ACCOUNT_HOSTNAME] = hostname_; a[CONFIG_ACCOUNT_USERNAME] = username_; @@ -959,15 +756,15 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const } a[CONFIG_RINGTONE_PATH] = ringtonePath_; - a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_VIDEO_ENABLED] = videoEnabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_RINGTONE_ENABLED] = ringtoneEnabled_ ? TRUE_STR : FALSE_STR; + a[CONFIG_VIDEO_ENABLED] = videoEnabled_ ? TRUE_STR : FALSE_STR; a[CONFIG_ACCOUNT_MAILBOX] = mailBox_; #ifdef SFL_PRESENCE - a[CONFIG_PRESENCE_ENABLED] = presence_ and presence_->isEnabled()? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_PRESENCE_PUBLISH_SUPPORTED] = presence_ and presence_->isSupported(PRESENCE_FUNCTION_PUBLISH)? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_PRESENCE_SUBSCRIBE_SUPPORTED] = presence_ and presence_->isSupported(PRESENCE_FUNCTION_SUBSCRIBE)? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_PRESENCE_ENABLED] = presence_ and presence_->isEnabled()? TRUE_STR : FALSE_STR; + a[CONFIG_PRESENCE_PUBLISH_SUPPORTED] = presence_ and presence_->isSupported(PRESENCE_FUNCTION_PUBLISH)? TRUE_STR : FALSE_STR; + a[CONFIG_PRESENCE_SUBSCRIBE_SUPPORTED] = presence_ and presence_->isSupported(PRESENCE_FUNCTION_SUBSCRIBE)? TRUE_STR : FALSE_STR; // initialize status values - a[CONFIG_PRESENCE_STATUS] = presence_ and presence_->isOnline()? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_PRESENCE_STATUS] = presence_ and presence_->isOnline()? TRUE_STR : FALSE_STR; a[CONFIG_PRESENCE_NOTE] = presence_ ? presence_->getNote() : " "; #endif @@ -993,7 +790,7 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const // Add sip specific details a[CONFIG_ACCOUNT_ROUTESET] = serviceRoute_; a[CONFIG_ACCOUNT_USERAGENT] = hasCustomUserAgent_ ? userAgent_ : DEFAULT_USER_AGENT; - a[CONFIG_ACCOUNT_HAS_CUSTOM_USERAGENT] = hasCustomUserAgent_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_ACCOUNT_HAS_CUSTOM_USERAGENT] = hasCustomUserAgent_ ? TRUE_STR : FALSE_STR; addRangeToDetails(a, CONFIG_ACCOUNT_AUDIO_PORT_MIN, CONFIG_ACCOUNT_AUDIO_PORT_MAX, audioPortRange_); #ifdef SFL_VIDEO @@ -1004,7 +801,7 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const registrationExpireStr << registrationExpire_; a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = registrationExpireStr.str(); a[CONFIG_LOCAL_INTERFACE] = interface_; - a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? TRUE_STR : FALSE_STR; a[CONFIG_PUBLISHED_ADDRESS] = publishedIpAddress_; std::stringstream localport; @@ -1013,25 +810,25 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const std::stringstream publishedport; publishedport << publishedPort_; a[CONFIG_PUBLISHED_PORT] = publishedport.str(); - a[CONFIG_STUN_ENABLE] = stunEnabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_STUN_ENABLE] = stunEnabled_ ? TRUE_STR : FALSE_STR; a[CONFIG_STUN_SERVER] = stunServer_; a[CONFIG_ACCOUNT_DTMF_TYPE] = dtmfType_; - a[CONFIG_KEEP_ALIVE_ENABLED] = keepAliveEnabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_KEEP_ALIVE_ENABLED] = keepAliveEnabled_ ? TRUE_STR : FALSE_STR; a[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_; - a[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? TRUE_STR : FALSE_STR; + a[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? TRUE_STR : FALSE_STR; - a[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? TRUE_STR : FALSE_STR; + a[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? TRUE_STR : FALSE_STR; + a[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? TRUE_STR : FALSE_STR; + a[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? TRUE_STR : FALSE_STR; // TLS listener is unique and parameters are modified through IP2IP_PROFILE std::stringstream tlslistenerport; tlslistenerport << tlsListenerPort_; a[CONFIG_TLS_LISTENER_PORT] = tlslistenerport.str(); - a[CONFIG_TLS_ENABLE] = tlsEnable_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_TLS_ENABLE] = tlsEnable_ ? TRUE_STR : FALSE_STR; a[CONFIG_TLS_CA_LIST_FILE] = tlsCaListFile_; a[CONFIG_TLS_CERTIFICATE_FILE] = tlsCertificateFile_; a[CONFIG_TLS_PRIVATE_KEY_FILE] = tlsPrivateKeyFile_; @@ -1039,9 +836,9 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const a[CONFIG_TLS_METHOD] = tlsMethod_; a[CONFIG_TLS_CIPHERS] = tlsCiphers_; a[CONFIG_TLS_SERVER_NAME] = tlsServerName_; - a[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? Conf::TRUE_STR : Conf::FALSE_STR; - a[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? Conf::TRUE_STR : Conf::FALSE_STR; + a[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? TRUE_STR : FALSE_STR; + a[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? TRUE_STR : FALSE_STR; + a[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? TRUE_STR : FALSE_STR; a[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_; return a; @@ -1874,12 +1671,12 @@ std::map<std::string, std::string> SIPAccount::getIp2IpDetails() const assert(isIP2IP()); std::map<std::string, std::string> ip2ipAccountDetails; ip2ipAccountDetails[CONFIG_SRTP_KEY_EXCHANGE] = srtpKeyExchange_; - ip2ipAccountDetails[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? Conf::TRUE_STR : Conf::FALSE_STR; - ip2ipAccountDetails[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? Conf::TRUE_STR : Conf::FALSE_STR; - ip2ipAccountDetails[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? Conf::TRUE_STR : Conf::FALSE_STR; - ip2ipAccountDetails[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? Conf::TRUE_STR : Conf::FALSE_STR; - ip2ipAccountDetails[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? Conf::TRUE_STR : Conf::FALSE_STR; - ip2ipAccountDetails[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? Conf::TRUE_STR : Conf::FALSE_STR; + ip2ipAccountDetails[CONFIG_SRTP_ENABLE] = srtpEnabled_ ? TRUE_STR : FALSE_STR; + ip2ipAccountDetails[CONFIG_SRTP_RTP_FALLBACK] = srtpFallback_ ? TRUE_STR : FALSE_STR; + ip2ipAccountDetails[CONFIG_ZRTP_DISPLAY_SAS] = zrtpDisplaySas_ ? TRUE_STR : FALSE_STR; + ip2ipAccountDetails[CONFIG_ZRTP_HELLO_HASH] = zrtpHelloHash_ ? TRUE_STR : FALSE_STR; + ip2ipAccountDetails[CONFIG_ZRTP_NOT_SUPP_WARNING] = zrtpNotSuppWarning_ ? TRUE_STR : FALSE_STR; + ip2ipAccountDetails[CONFIG_ZRTP_DISPLAY_SAS_ONCE] = zrtpDisplaySasOnce_ ? TRUE_STR : FALSE_STR; ip2ipAccountDetails[CONFIG_LOCAL_INTERFACE] = interface_; std::stringstream portstr; portstr << localPort_; @@ -1900,7 +1697,7 @@ std::map<std::string, std::string> SIPAccount::getTlsSettings() const std::stringstream portstr; portstr << tlsListenerPort_; tlsSettings[CONFIG_TLS_LISTENER_PORT] = portstr.str(); - tlsSettings[CONFIG_TLS_ENABLE] = tlsEnable_ ? Conf::TRUE_STR : Conf::FALSE_STR; + tlsSettings[CONFIG_TLS_ENABLE] = tlsEnable_ ? TRUE_STR : FALSE_STR; tlsSettings[CONFIG_TLS_CA_LIST_FILE] = tlsCaListFile_; tlsSettings[CONFIG_TLS_CERTIFICATE_FILE] = tlsCertificateFile_; tlsSettings[CONFIG_TLS_PRIVATE_KEY_FILE] = tlsPrivateKeyFile_; @@ -1908,9 +1705,9 @@ std::map<std::string, std::string> SIPAccount::getTlsSettings() const tlsSettings[CONFIG_TLS_METHOD] = tlsMethod_; tlsSettings[CONFIG_TLS_CIPHERS] = tlsCiphers_; tlsSettings[CONFIG_TLS_SERVER_NAME] = tlsServerName_; - tlsSettings[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? Conf::TRUE_STR : Conf::FALSE_STR; - tlsSettings[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? Conf::TRUE_STR : Conf::FALSE_STR; - tlsSettings[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? Conf::TRUE_STR : Conf::FALSE_STR; + tlsSettings[CONFIG_TLS_VERIFY_SERVER] = tlsVerifyServer_ ? TRUE_STR : FALSE_STR; + tlsSettings[CONFIG_TLS_VERIFY_CLIENT] = tlsVerifyClient_ ? TRUE_STR : FALSE_STR; + tlsSettings[CONFIG_TLS_REQUIRE_CLIENT_CERTIFICATE] = tlsRequireClientCertificate_ ? TRUE_STR : FALSE_STR; tlsSettings[CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC] = tlsNegotiationTimeoutSec_; return tlsSettings; @@ -1931,7 +1728,7 @@ set_opt(const std::map<std::string, std::string> &details, const char *key, bool std::map<std::string, std::string>::const_iterator it = details.find(key); if (it != details.end()) - val = it->second == Conf::TRUE_STR; + val = it->second == Account::TRUE_STR; } static void @@ -1984,7 +1781,7 @@ SIPAccount::enablePresence(const bool& enabled) DEBUG("Presence enabled for %s : %s.", accountID_.c_str(), - enabled? Conf::TRUE_STR : Conf::FALSE_STR); + enabled? TRUE_STR : FALSE_STR); presence_->enable(enabled); } @@ -2006,7 +1803,7 @@ SIPAccount::supportPresence(int function, bool enabled) DEBUG("Presence support for %s (%s: %s).", accountID_.c_str(), function == PRESENCE_FUNCTION_PUBLISH ? "publish" : "subscribe", - enabled ? Conf::TRUE_STR : Conf::FALSE_STR); + enabled ? TRUE_STR : FALSE_STR); presence_->support(function, enabled); // force presence to disable when nothing is supported diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h index f5d8fa88d8..0486fbf2cd 100644 --- a/daemon/src/sip/sipaccount.h +++ b/daemon/src/sip/sipaccount.h @@ -57,6 +57,11 @@ namespace Conf { const char *const KEEP_ALIVE_ENABLED = "keepAlive"; } +namespace YAML { + class Node; + class Emitter; +} + class SIPPresence; class SIPCall; @@ -100,15 +105,15 @@ class SIPAccount : public SIPAccountBase { /** * Serialize internal state of this account for configuration - * @param YamlEmitter the configuration engine which generate the configuration file + * @param out Emitter to which state will be saved */ - virtual void serialize(Conf::YamlEmitter &emitter); + void serialize(YAML::Emitter &out); /** * Populate the internal state for this account based on info stored in the configuration file * @param The configuration node for this account */ - virtual void unserialize(const Conf::YamlNode &map); + virtual void unserialize(const YAML::Node &node); /** * Return an map containing the internal state of this account. Client application can use this method to manage diff --git a/daemon/src/sip/sipaccountbase.h b/daemon/src/sip/sipaccountbase.h index 649af8c921..7eabf8c093 100644 --- a/daemon/src/sip/sipaccountbase.h +++ b/daemon/src/sip/sipaccountbase.h @@ -53,8 +53,6 @@ typedef std::vector<pj_ssl_cipher> CipherArray; namespace Conf { - class YamlEmitter; - class MappingNode; // SIP specific configuration keys const char *const INTERFACE_KEY = "interface"; const char *const PORT_KEY = "port"; diff --git a/daemon/src/video/v4l2/video_device_monitor_impl.cpp b/daemon/src/video/v4l2/video_device_monitor_impl.cpp index a9c30d56cc..1216be0be3 100644 --- a/daemon/src/video/v4l2/video_device_monitor_impl.cpp +++ b/daemon/src/video/v4l2/video_device_monitor_impl.cpp @@ -45,8 +45,6 @@ #include <vector> #include "../video_device_monitor.h" -#include "config/yamlemitter.h" -#include "config/yamlnode.h" #include "logger.h" #include "noncopyable.h" diff --git a/daemon/src/video/video_device_monitor.cpp b/daemon/src/video/video_device_monitor.cpp index ee0bfb0eaa..181bea8591 100644 --- a/daemon/src/video/video_device_monitor.cpp +++ b/daemon/src/video/video_device_monitor.cpp @@ -33,15 +33,18 @@ #include <cassert> #include <sstream> +#include <yaml-cpp/yaml.h> + #include "manager.h" #include "client/videomanager.h" -#include "config/yamlemitter.h" -#include "config/yamlnode.h" +#include "config/yamlparser.h" #include "logger.h" #include "video_device_monitor.h" namespace sfl_video { +constexpr const char * const VideoDeviceMonitor::CONFIG_LABEL; + using std::map; using std::string; using std::stringstream;; @@ -270,65 +273,25 @@ VideoDeviceMonitor::overwritePreferences(VideoSettings settings) } void -VideoDeviceMonitor::serialize(Conf::YamlEmitter &emitter) +VideoDeviceMonitor::serialize(YAML::Emitter &out) { - using namespace Conf; - - // Put the default in first position - auto def = findPreferencesByName(defaultDevice_); - if (def != preferences_.end()) - std::iter_swap(preferences_.begin(), def); - - MappingNode devices(nullptr); - SequenceNode sequence(nullptr); - - for (auto& pref : preferences_) { - MappingNode *node = new MappingNode(nullptr); - - node->setKeyValue("name", new ScalarNode(pref["name"])); - node->setKeyValue("channel", new ScalarNode(pref["channel"])); - node->setKeyValue("size", new ScalarNode(pref["size"])); - node->setKeyValue("rate", new ScalarNode(pref["rate"])); - - sequence.addNode(node); - } - - devices.setKeyValue("devices", &sequence); - - /* store the device list under the "video" YAML section */ - emitter.serializePreference(&devices, "video"); + out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; + out << YAML::Key << "devices" << YAML::Value << preferences_; + out << YAML::EndMap; } void -VideoDeviceMonitor::unserialize(const Conf::YamlNode &node) +VideoDeviceMonitor::unserialize(const YAML::Node &in) { using namespace Conf; + const auto &node = in[CONFIG_LABEL]; /* load the device list from the "video" YAML section */ - YamlNode *devicesNode(node.getValue("devices")); - - if (!devicesNode || devicesNode->getType() != SEQUENCE) { - ERROR("No 'devices' sequence node! Old config?"); - return; - } - - SequenceNode *seqNode = static_cast<SequenceNode *>(devicesNode); - Sequence *seq = seqNode->getSequence(); - - if (seq->empty()) { - WARN("Empty video device list"); - return; - } - - for (const auto &iter : *seq) { - MappingNode *devnode = static_cast<MappingNode *>(iter); - VideoSettings pref; - - devnode->getValue("name", &pref["name"]); - devnode->getValue("channel", &pref["channel"]); - devnode->getValue("size", &pref["size"]); - devnode->getValue("rate", &pref["rate"]); + auto tmp = preferences_; + yaml_utils::parseValue(node, "devices", tmp); + for (const auto &iter : tmp) { + VideoSettings pref = iter; overwritePreferences(pref); // Restore the device preferences if present diff --git a/daemon/src/video/video_device_monitor.h b/daemon/src/video/video_device_monitor.h index cd4e98db7c..eac3854b71 100644 --- a/daemon/src/video/video_device_monitor.h +++ b/daemon/src/video/video_device_monitor.h @@ -41,8 +41,9 @@ #include "video_device.h" -namespace Conf { - class SequenceNode; +namespace YAML { + class Emitter; + class Node; } namespace sfl_video { @@ -70,8 +71,8 @@ class VideoDeviceMonitor : public Serializable /* * Interface to load from/store to the (YAML) configuration file. */ - virtual void serialize(Conf::YamlEmitter &emitter); - virtual void unserialize(const Conf::YamlNode &map); + void serialize(YAML::Emitter &out); + virtual void unserialize(const YAML::Node &in); private: NON_COPYABLE(VideoDeviceMonitor); @@ -97,6 +98,8 @@ class VideoDeviceMonitor : public Serializable std::vector<VideoDevice>::const_iterator findDeviceByNode(const std::string& node) const; std::unique_ptr<VideoDeviceMonitorImpl> monitorImpl_; + + constexpr static const char *CONFIG_LABEL = "video"; }; } // namespace sfl_video diff --git a/daemon/test/configurationtest.cpp b/daemon/test/configurationtest.cpp index b8594a15b7..ef08d9c2fd 100644 --- a/daemon/test/configurationtest.cpp +++ b/daemon/test/configurationtest.cpp @@ -29,145 +29,14 @@ */ #include "configurationtest.h" -#include "manager.h" -#include "config/yamlemitter.h" +#include "fileutils.h" #include "config/yamlparser.h" -#include "account.h" -#include "account_schema.h" -#include "logger.h" -#include "audio/alsa/alsalayer.h" -#include "audio/pulseaudio/pulselayer.h" -#include "sip/sipaccount.h" -#include "test_utils.h" -void ConfigurationTest::testYamlEmitter() +void ConfigurationTest::testNodeParse() { - using namespace Conf; - MappingNode accountmap(NULL); - MappingNode credentialmap(NULL); - MappingNode srtpmap(NULL); - MappingNode zrtpmap(NULL); - MappingNode tlsmap(NULL); - - ScalarNode id("Account:1278432417"); - ScalarNode username("181"); - ScalarNode password("pass181"); - ScalarNode alias("sfl-181"); - ScalarNode hostname("192.168.50.3"); - ScalarNode enable(true); - ScalarNode type("SIP"); - ScalarNode expire("3600"); - ScalarNode interface("default"); - ScalarNode port("5060"); - ScalarNode mailbox("97"); - ScalarNode publishAddr("192.168.50.182"); - ScalarNode publishPort("5060"); - ScalarNode sameasLocal(true); - ScalarNode codecs("0/9/110/111/112/"); - ScalarNode stunServer(""); - ScalarNode stunEnabled(false); - ScalarNode displayName("Alexandre Savard"); - ScalarNode dtmfType("sipinfo"); - - ScalarNode count("0"); - - ScalarNode srtpenabled(false); - ScalarNode keyExchange("sdes"); - ScalarNode rtpFallback(false); - - ScalarNode displaySas(false); - ScalarNode displaySasOnce(false); - ScalarNode helloHashEnabled(false); - ScalarNode notSuppWarning(false); - - ScalarNode tlsport(""); - ScalarNode certificate(""); - ScalarNode calist(""); - ScalarNode ciphers(""); - ScalarNode tlsenabled(false); - ScalarNode tlsmethod("TLSV1"); - ScalarNode timeout("0"); - ScalarNode tlspassword(""); - ScalarNode privatekey(""); - ScalarNode requirecertif(true); - ScalarNode server(""); - ScalarNode verifyclient(true); - ScalarNode verifyserver(true); - - accountmap.setKeyValue(Account::ALIAS_KEY, &alias); - accountmap.setKeyValue(Account::TYPE_KEY, &type); - accountmap.setKeyValue(Account::ID_KEY, &id); - accountmap.setKeyValue(Account::USERNAME_KEY, &username); - accountmap.setKeyValue(Account::PASSWORD_KEY, &password); - accountmap.setKeyValue(Account::HOSTNAME_KEY, &hostname); - accountmap.setKeyValue(Account::ACCOUNT_ENABLE_KEY, &enable); - accountmap.setKeyValue(Account::MAILBOX_KEY, &mailbox); - accountmap.setKeyValue(Preferences::REGISTRATION_EXPIRE_KEY, &expire); - accountmap.setKeyValue(INTERFACE_KEY, &interface); - accountmap.setKeyValue(PORT_KEY, &port); - accountmap.setKeyValue(PUBLISH_ADDR_KEY, &publishAddr); - accountmap.setKeyValue(PUBLISH_PORT_KEY, &publishPort); - accountmap.setKeyValue(SAME_AS_LOCAL_KEY, &sameasLocal); - accountmap.setKeyValue(DTMF_TYPE_KEY, &dtmfType); - accountmap.setKeyValue(Account::DISPLAY_NAME_KEY, &displayName); - - accountmap.setKeyValue(SRTP_KEY, &srtpmap); - srtpmap.setKeyValue(SRTP_ENABLE_KEY, &srtpenabled); - srtpmap.setKeyValue(KEY_EXCHANGE_KEY, &keyExchange); - srtpmap.setKeyValue(RTP_FALLBACK_KEY, &rtpFallback); - - accountmap.setKeyValue(ZRTP_KEY, &zrtpmap); - zrtpmap.setKeyValue(DISPLAY_SAS_KEY, &displaySas); - zrtpmap.setKeyValue(DISPLAY_SAS_ONCE_KEY, &displaySasOnce); - zrtpmap.setKeyValue(HELLO_HASH_ENABLED_KEY, &helloHashEnabled); - zrtpmap.setKeyValue(NOT_SUPP_WARNING_KEY, ¬SuppWarning); - - accountmap.setKeyValue(CRED_KEY, &credentialmap); - SequenceNode credentialseq(NULL); - accountmap.setKeyValue(CRED_KEY, &credentialseq); - - MappingNode credmap1(NULL); - MappingNode credmap2(NULL); - ScalarNode user1("user"); - ScalarNode pass1("pass"); - ScalarNode realm1("*"); - ScalarNode user2("john"); - ScalarNode pass2("doe"); - ScalarNode realm2("fbi"); - credmap1.setKeyValue(CONFIG_ACCOUNT_USERNAME, &user1); - credmap1.setKeyValue(CONFIG_ACCOUNT_PASSWORD, &pass1); - credmap1.setKeyValue(CONFIG_ACCOUNT_REALM, &realm1); - credmap2.setKeyValue(CONFIG_ACCOUNT_USERNAME, &user2); - credmap2.setKeyValue(CONFIG_ACCOUNT_PASSWORD, &pass2); - credmap2.setKeyValue(CONFIG_ACCOUNT_REALM, &realm2); - credentialseq.addNode(&credmap1); - credentialseq.addNode(&credmap2); - - accountmap.setKeyValue(TLS_KEY, &tlsmap); - tlsmap.setKeyValue(TLS_PORT_KEY, &tlsport); - tlsmap.setKeyValue(CERTIFICATE_KEY, &certificate); - tlsmap.setKeyValue(CALIST_KEY, &calist); - tlsmap.setKeyValue(CIPHERS_KEY, &ciphers); - tlsmap.setKeyValue(TLS_ENABLE_KEY, &tlsenabled); - tlsmap.setKeyValue(METHOD_KEY, &tlsmethod); - tlsmap.setKeyValue(TIMEOUT_KEY, &timeout); - tlsmap.setKeyValue(TLS_PASSWORD_KEY, &tlspassword); - tlsmap.setKeyValue(PRIVATE_KEY_KEY, &privatekey); - tlsmap.setKeyValue(REQUIRE_CERTIF_KEY, &requirecertif); - tlsmap.setKeyValue(SERVER_KEY, &server); - tlsmap.setKeyValue(VERIFY_CLIENT_KEY, &verifyclient); - tlsmap.setKeyValue(VERIFY_SERVER_KEY, &verifyserver); - - try { - YamlEmitter emitter("/tmp/ymlEmiter.txt"); - - emitter.serializeAccount(&accountmap); - emitter.serializeAccount(&accountmap); - emitter.serializeData(); - - } catch (const YamlEmitterException &e) { - ERROR("ConfigTree: %s", e.what()); - } + YAML::Node node = YAML::Load("[{a: 0, b: 1, c: 2}, {a: 0, b: 1, c: 2}]"); + auto result = yaml_utils::parseVectorMap(node, {"a", "b", "c"}); + CPPUNIT_ASSERT(result[1]["b"] == "1"); } void ConfigurationTest::test_expand_path(void){ diff --git a/daemon/test/configurationtest.h b/daemon/test/configurationtest.h index 85de32f5e0..7d63b54168 100644 --- a/daemon/test/configurationtest.h +++ b/daemon/test/configurationtest.h @@ -43,21 +43,19 @@ #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> -#include "fileutils.h" - class ConfigurationTest: public CppUnit::TestFixture { /* * Use cppunit library macros to add unit test the factory */ CPPUNIT_TEST_SUITE(ConfigurationTest); - CPPUNIT_TEST(testYamlEmitter); + CPPUNIT_TEST(testNodeParse); CPPUNIT_TEST(test_expand_path); CPPUNIT_TEST_SUITE_END(); public: - void testYamlEmitter(); + void testNodeParse(); void test_expand_path(); }; /* Register our test module */ diff --git a/daemon/test/sflphoned-sample.yml b/daemon/test/sflphoned-sample.yml index 8a15217a14..b3ac98eb42 100644 --- a/daemon/test/sflphoned-sample.yml +++ b/daemon/test/sflphoned-sample.yml @@ -182,8 +182,8 @@ audio: deviceRecord: alsa_input.pci-0000_00_1b.0.analog-stereo deviceRingtone: alsa_output.pci-0000_00_1b.0.analog-stereo recordPath: ~ - volumeMic: 100 - volumeSpkr: 100 + volumeMic: 1.0 + volumeSpkr: 1.0 video: devices: - channel: Camera 1 -- GitLab