diff --git a/bin/dbus/configurationmanager-introspec.xml b/bin/dbus/configurationmanager-introspec.xml index d06a812a1afbeec61c2d7d5f56792312bc0b2233..66a28150523ae6b875fa922010f5629478a7b8ad 100644 --- a/bin/dbus/configurationmanager-introspec.xml +++ b/bin/dbus/configurationmanager-introspec.xml @@ -158,6 +158,25 @@ </arg> </method> + <method name="testAccountICEInitialization" tp:name-for-bindings="testAccountICEInitialization"> + <tp:docstring> + Test initializing an ICE transport with the current account configuration. + </tp:docstring> + <arg type="s" name="accountID" direction="in"> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="result" direction="out" tp:type="String_String_Map"> + <tp:docstring> + A string map. + Available attributes: + <ul> + <li>STATUS: 0 for success, non-0 for error</li> + <li>MESSAGE: message explaining the status</li> + </ul> + </tp:docstring> + </arg> + </method> + <method name="setAccountsOrder" tp:name-for-bindings="setAccountsOrder"> <tp:docstring> Update the accounts order. diff --git a/bin/dbus/dbusconfigurationmanager.cpp b/bin/dbus/dbusconfigurationmanager.cpp index bb3cfa37820dd19718c47db1b7084acb04472c1a..6cd07444fa99da787768ac6db715219a194e0c1e 100644 --- a/bin/dbus/dbusconfigurationmanager.cpp +++ b/bin/dbus/dbusconfigurationmanager.cpp @@ -49,6 +49,13 @@ DBusConfigurationManager::setAccountDetails(const std::string& accountID, const DRing::setAccountDetails(accountID, details); } +auto +DBusConfigurationManager::testAccountICEInitialization(const std::string& accountID) -> decltype(DRing::testAccountICEInitialization(accountID)) +{ + return DRing::testAccountICEInitialization(accountID); +} + + void DBusConfigurationManager::setAccountActive(const std::string& accountID, const bool& active) { diff --git a/bin/dbus/dbusconfigurationmanager.h b/bin/dbus/dbusconfigurationmanager.h index a3c8c08b3dff52067046658aed2ccc0aecdb41fa..a0ee7bcf5ee76cc24a2085b518da02014815d09d 100644 --- a/bin/dbus/dbusconfigurationmanager.h +++ b/bin/dbus/dbusconfigurationmanager.h @@ -59,6 +59,7 @@ class DBusConfigurationManager : std::map<std::string, std::string> getAccountDetails(const std::string& accountID); std::map<std::string, std::string> getVolatileAccountDetails(const std::string& accountID); void setAccountDetails(const std::string& accountID, const std::map<std::string, std::string>& details); + std::map<std::string, std::string> testAccountICEInitialization(const std::string& accountID); void setAccountActive(const std::string& accountID, const bool& active); std::map<std::string, std::string> getAccountTemplate(const std::string& accountType); std::string addAccount(const std::map<std::string, std::string>& details); diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp index 52b5da537fb28fdf8a1793e40d2a729899747e5d..005d06ec901b72e4d74d848e2991571e43791ca8 100644 --- a/src/client/configurationmanager.cpp +++ b/src/client/configurationmanager.cpp @@ -90,6 +90,12 @@ getVolatileAccountDetails(const std::string& accountID) return ring::Manager::instance().getVolatileAccountDetails(accountID); } +std::map<std::string, std::string> +testAccountICEInitialization(const std::string& accountID) +{ + return ring::Manager::instance().testAccountICEInitialization(accountID); +} + std::map<std::string, std::string> getTlsDefaultSettings() { diff --git a/src/dring/account_const.h b/src/dring/account_const.h index 3e3bd5daa0c790f24820cc1438e372c22c2578f9..614a2a923eb3150843003d65a83ded718cacb233 100644 --- a/src/dring/account_const.h +++ b/src/dring/account_const.h @@ -66,6 +66,11 @@ enum class MessageStates : int { FAILURE }; //DRing::Account::MessageStates +enum class testAccountICEInitializationStatus : int { + SUCCESS = 0, + FAILURE = 1 +}; //DRING:Account::testAccountICEInitializationResults + namespace VolatileProperties { constexpr static const char ACTIVE [] = "Account.active"; diff --git a/src/dring/configurationmanager_interface.h b/src/dring/configurationmanager_interface.h index de7aa4f093400d7a94737d14ced47cb89edcadf0..241d864bfd7dd04a249b452957690741cbc3db72 100644 --- a/src/dring/configurationmanager_interface.h +++ b/src/dring/configurationmanager_interface.h @@ -41,6 +41,7 @@ void registerConfHandlers(const std::map<std::string, std::shared_ptr<CallbackWr std::map<std::string, std::string> getAccountDetails(const std::string& accountID); std::map<std::string, std::string> getVolatileAccountDetails(const std::string& accountID); void setAccountDetails(const std::string& accountID, const std::map<std::string, std::string>& details); +std::map<std::string, std::string> testAccountICEInitialization(const std::string& accountID); void setAccountActive(const std::string& accountID, bool active); std::map<std::string, std::string> getAccountTemplate(const std::string& accountType); std::string addAccount(const std::map<std::string, std::string>& details); diff --git a/src/ice_transport.cpp b/src/ice_transport.cpp index 3f009185af0216492d3de6ddb1cdd51f4d8a380e..f768cd92252db320a2a3de70913b436b5efa24c3 100644 --- a/src/ice_transport.cpp +++ b/src/ice_transport.cpp @@ -236,7 +236,8 @@ IceTransport::handleEvents(unsigned max_msec) if (n_events < 0) { const auto err = pj_get_os_error(); // Kept as debug as some errors are "normal" in regular context - RING_DBG("IceIOQueue: error %d - %s", err, sip_utils::sip_strerror(err).c_str()); + last_errmsg_ = sip_utils::sip_strerror(err); + RING_DBG("IceIOQueue: error %d - %s", err, last_errmsg_.c_str()); std::this_thread::sleep_for(std::chrono::milliseconds(PJ_TIME_VAL_MSEC(timeout))); return; } @@ -255,10 +256,13 @@ IceTransport::onComplete(pj_ice_strans* ice_st, pj_ice_strans_op op, op == PJ_ICE_STRANS_OP_NEGOTIATION ? "negotiation" : "unknown_op"; const bool done = status == PJ_SUCCESS; - if (done) + if (done) { RING_DBG("ICE %s success", opname); - else - RING_ERR("ICE %s failed: %s", opname, sip_utils::sip_strerror(status).c_str()); + } + else { + last_errmsg_ = sip_utils::sip_strerror(status); + RING_ERR("ICE %s failed: %s", opname, last_errmsg_.c_str()); + } { std::lock_guard<std::mutex> lk(iceMutex_); @@ -292,6 +296,12 @@ IceTransport::getUFragPwd() local_pwd_.assign(local_pwd.ptr, local_pwd.slen); } +std::string +IceTransport::getLastErrMsg() const +{ + return last_errmsg_; +} + void IceTransport::getDefaultCanditates() { @@ -322,7 +332,8 @@ IceTransport::setInitiatorSession() if (isInitialized()) { auto status = pj_ice_strans_change_role(icest_.get(), PJ_ICE_SESS_ROLE_CONTROLLING); if (status != PJ_SUCCESS) { - RING_ERR("ICE role change failed: %s", sip_utils::sip_strerror(status).c_str()); + last_errmsg_ = sip_utils::sip_strerror(status); + RING_ERR("ICE role change failed: %s", last_errmsg_.c_str()); return false; } return true; @@ -338,7 +349,8 @@ IceTransport::setSlaveSession() if (isInitialized()) { auto status = pj_ice_strans_change_role(icest_.get(), PJ_ICE_SESS_ROLE_CONTROLLED); if (status != PJ_SUCCESS) { - RING_ERR("ICE role change failed: %s", sip_utils::sip_strerror(status).c_str()); + last_errmsg_ = sip_utils::sip_strerror(status); + RING_ERR("ICE role change failed: %s", last_errmsg_.c_str()); return false; } return true; @@ -377,7 +389,8 @@ IceTransport::start(const Attribute& rem_attrs, rem_candidates.size(), rem_candidates.data()); if (status != PJ_SUCCESS) { - RING_ERR("ICE start failed: %s", sip_utils::sip_strerror(status).c_str()); + last_errmsg_ = sip_utils::sip_strerror(status); + RING_ERR("ICE start failed: %s", last_errmsg_.c_str()); return false; } return true; @@ -442,7 +455,8 @@ IceTransport::stop() if (isStarted()) { auto status = pj_ice_strans_stop_ice(icest_.get()); if (status != PJ_SUCCESS) { - RING_ERR("ICE stop failed: %s", sip_utils::sip_strerror(status).c_str()); + last_errmsg_ = sip_utils::sip_strerror(status); + RING_ERR("ICE stop failed: %s", last_errmsg_.c_str()); return false; } } @@ -618,8 +632,9 @@ IceTransport::addReflectiveCandidate(int comp_id, const IpAddr& base, const IpAd NULL); if (ret != PJ_SUCCESS) { + last_errmsg_ = sip_utils::sip_strerror(ret); RING_ERR("pj_ice_sess_add_cand failed with error %d: %s", ret, - sip_utils::sip_strerror(ret).c_str()); + last_errmsg_.c_str()); RING_ERR("failed to add candidate for comp_id=%d : %s : %s", comp_id, base.toString().c_str(), addr.toString().c_str()); } else { @@ -803,7 +818,8 @@ IceTransport::send(int comp_id, const unsigned char* buf, size_t len) if (status == PJ_EBUSY) { errno = EAGAIN; } else { - RING_ERR("ice send failed: %s", sip_utils::sip_strerror(status).c_str()); + last_errmsg_ = sip_utils::sip_strerror(status); + RING_ERR("ice send failed: %s", last_errmsg_.c_str()); errno = EIO; } return -1; diff --git a/src/ice_transport.h b/src/ice_transport.h index 09497f2bf6ec4a5e004f8d6c1c0e73981d4325eb..a6cff0eaebd23d26af32311ec194409d6c516189 100644 --- a/src/ice_transport.h +++ b/src/ice_transport.h @@ -152,6 +152,8 @@ class IceTransport { IpAddr getRemoteAddress(unsigned comp_id) const; + std::string getLastErrMsg() const; + IpAddr getDefaultLocalAddress() const { return getLocalAddress(0); } @@ -248,6 +250,7 @@ class IceTransport { std::condition_variable iceCV_ {}; mutable std::mutex iceMutex_ {}; pj_ice_strans_cfg config_; + std::string last_errmsg_; struct Packet { Packet(void *pkt, pj_size_t size); diff --git a/src/manager.cpp b/src/manager.cpp index f459c24bd241c2dad0fcf8503a2c029d57279476..c3a9642449cb7978772a678d80065dbc42f0e8a6 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -93,6 +93,8 @@ using random_device = std::random_device; namespace ring { +static constexpr int ICE_INIT_TIMEOUT {10}; + std::atomic_bool Manager::initialized = {false}; static void @@ -2426,6 +2428,33 @@ Manager::setAccountDetails(const std::string& accountID, }); } +std::map <std::string, std::string> +Manager::testAccountICEInitialization(const std::string& accountID) +{ + const auto account = getAccount(accountID); + const auto transportOptions = account->getIceOptions(); + + auto& iceTransportFactory = Manager::instance().getIceTransportFactory(); + std::shared_ptr<IceTransport> ice = iceTransportFactory.createTransport( + accountID.c_str(), 4, true, account->getIceOptions() + ); + + std::map<std::string, std::string> result; + + if (ice->waitForInitialization(ICE_INIT_TIMEOUT) <= 0) + { + result["STATUS"] = std::to_string((int) DRing::Account::testAccountICEInitializationStatus::FAILURE); + result["MESSAGE"] = ice->getLastErrMsg(); + } + else + { + result["STATUS"] = std::to_string((int) DRing::Account::testAccountICEInitializationStatus::SUCCESS); + result["MESSAGE"] = ""; + } + + return result; +} + std::string Manager::getNewAccountId() { diff --git a/src/manager.h b/src/manager.h index 23c0ebe7fa0c04f26871892c26ae55e62e36db49..a3dde6c34f8a07412b838319e1ac1b4b5497c304 100644 --- a/src/manager.h +++ b/src/manager.h @@ -497,6 +497,8 @@ class Manager { void setAccountActive(const std::string& accountID, bool active); + std::map<std::string, std::string> testAccountICEInitialization(const std::string& accountID); + /** * Return a new random accountid that is not present in the list * @return A brand new accountid