From 4dd1932decf86bcfbe1355966f1dac037777b892 Mon Sep 17 00:00:00 2001 From: atraczyk <andreastraczyk@gmail.com> Date: Mon, 14 Nov 2016 10:12:17 -0500 Subject: [PATCH] cherry-pick commits: from: dae99566886348b420ab5a0f43cb3a6c8f548a22 to: d1682f6aebb391f5763238bfaaea227555972fe0 Change-Id: I1cb799a778bc6f80b385d8cb40c5ddf3ed1d2c3a --- .gitignore | 5 +- Makefile.am | 2 +- README | 2 +- bin/dbus/Makefile.am | 2 +- bin/restcpp/Makefile.am | 2 +- configure.ac | 6 +- doc/dbus-api/Makefile.am | 2 +- globals.mak => globals.mk | 1 + src/Makefile.am | 4 +- src/call.cpp | 2 + src/client/Makefile.am | 2 +- src/client/configurationmanager.cpp | 8 +- src/ice_transport.cpp | 95 ++-- src/ice_transport.h | 5 +- src/im/Makefile.am | 2 +- src/manager.cpp | 21 +- src/manager.h | 9 + src/media/Makefile.am | 2 +- src/media/audio/Makefile.am | 2 +- src/media/audio/alsa/Makefile.am | 2 +- src/media/audio/coreaudio/Makefile.am | 2 +- src/media/audio/jack/Makefile.am | 2 +- src/media/audio/opensl/Makefile.am | 2 +- src/media/audio/portaudio/Makefile.am | 2 +- src/media/audio/pulseaudio/Makefile.am | 2 +- src/media/audio/sound/Makefile.am | 2 +- src/media/media_decoder.cpp | 5 +- src/media/media_decoder.h | 1 + src/media/media_device.h | 1 - src/media/video/Makefile.am | 2 +- src/media/video/androidvideo/Makefile.am | 2 +- src/media/video/osxvideo/Makefile.am | 2 +- src/media/video/test/Makefile.am | 2 +- .../video/uwpvideo/video_device_impl.cpp | 19 +- src/media/video/v4l2/Makefile.am | 2 +- src/media/video/v4l2/vaapi.cpp | 2 +- src/media/video/video_base.cpp | 10 +- src/media/video/video_base.h | 1 - src/media/video/video_device.h | 4 - src/media/video/video_device_monitor.cpp | 2 - src/media/video/video_receive_thread.cpp | 8 +- src/media/video/video_receive_thread.h | 3 +- src/media/video/video_rtp_session.cpp | 8 +- src/media/video/winvideo/Makefile.am | 2 +- src/preferences.cpp | 29 ++ src/preferences.h | 20 + src/ringdht/Makefile.am | 2 +- src/ringdht/eth/libdevcore/Makefile.am | 2 +- src/ringdht/eth/libdevcrypto/Makefile.am | 2 +- src/ringdht/namedirectory.cpp | 445 +++++++++++------- src/ringdht/namedirectory.h | 26 +- src/ringdht/ringaccount.cpp | 38 +- src/ringdht/ringaccount.h | 1 + src/security/Makefile.am | 2 +- src/sip/Makefile.am | 2 +- src/sip/sipcall.cpp | 4 +- src/upnp/Makefile.am | 2 +- 57 files changed, 503 insertions(+), 336 deletions(-) rename globals.mak => globals.mk (96%) diff --git a/.gitignore b/.gitignore index 4b390e5f50..f4a3e4a0f6 100644 --- a/.gitignore +++ b/.gitignore @@ -69,9 +69,10 @@ config_auto.h # Ignore temp files *~ -# Cscope/Ctags files +# Cscope/Ctags/Etags files cscope.* tags +TAGS TAGS.LST ID @@ -112,4 +113,4 @@ __pycache__ contrib/* !contrib/bootstrap !contrib/src -!contrib/tarballs \ No newline at end of file +!contrib/tarballs diff --git a/Makefile.am b/Makefile.am index 11fccbf362..d8952086b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -include globals.mak +include globals.mk # Makefile.am diff --git a/README b/README index bf138a7727..f06c971b37 100644 --- a/README +++ b/README @@ -79,7 +79,7 @@ make install Done ! More details available here: -https://tuleap.ring.cx/wiki/index.php?pagename=How%20To%20Build%20Ring&group_id=101 +https://tuleap.ring.cx/plugins/mediawiki/wiki/ring/index.php/Build_Instructions How to compile on OSX diff --git a/bin/dbus/Makefile.am b/bin/dbus/Makefile.am index fda17a225b..99eec615bf 100644 --- a/bin/dbus/Makefile.am +++ b/bin/dbus/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libclient_dbus.la diff --git a/bin/restcpp/Makefile.am b/bin/restcpp/Makefile.am index 2f5e1e5c2e..57401c1fa1 100644 --- a/bin/restcpp/Makefile.am +++ b/bin/restcpp/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libclient_rest.la diff --git a/configure.ac b/configure.ac index e83b479cf3..6455f8a21a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Ring - configure.ac for automake 1.9 and autoconf 2.59 dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([Ring],[2.3.0],[ring@lists.savoirfairelinux.net],[ring]) +AC_INIT([Ring],[3.0.0],[ring@lists.savoirfairelinux.net],[ring]) AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2016]]) AC_REVISION([$Revision$]) @@ -396,6 +396,10 @@ AC_DEFINE_UNQUOTED([HAVE_RINGNS], `if test "x$enable_ringns" != "xno"; then echo # Rest C++ with restbed AC_ARG_WITH([restcpp], AS_HELP_STRING([--with-restcpp], [enable rest support with C++])) +AC_ARG_ENABLE([restbed_old_api], AS_HELP_STRING([--enable-restbed-old-api], [Use the old restbed API])) +AS_IF([test "x$enable_restbed_old_api" = "xyes"], [ + AC_DEFINE([RESTBED_OLD_API], [], [Defined if you use the old restbed API]) +]) AS_IF([test "x$enable_ringns" != "xno" || test "x$with_restcpp" = "xyes"], AC_CHECK_LIB(restbed, exit,, AC_MSG_ERROR([Missing restbed files]))); diff --git a/doc/dbus-api/Makefile.am b/doc/dbus-api/Makefile.am index b7064e5dd9..b7f84139e1 100644 --- a/doc/dbus-api/Makefile.am +++ b/doc/dbus-api/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk XSLTPROC=xsltproc --xinclude --nonet PYTHON=python diff --git a/globals.mak b/globals.mk similarity index 96% rename from globals.mak rename to globals.mk index a467a69a63..218680204e 100644 --- a/globals.mak +++ b/globals.mk @@ -34,6 +34,7 @@ AM_CPPFLAGS = \ -DENABLE_TRACE \ -DRING_REVISION=\"$(RING_REVISION)\" \ -DRING_DIRTY_REPO=\"$(RING_DIRTY_REPO)\" \ + -DPJSIP_MAX_PKT_LEN=8000 \ $(SPEEXCODEC) \ $(GSMCODEC) \ $(OPUSCODEC) diff --git a/src/Makefile.am b/src/Makefile.am index 1c36d1799b..3a85be6565 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -include ../globals.mak +include ../globals.mk RING_VIDEO_LIBS= @@ -124,7 +124,7 @@ libring_la_SOURCES = \ noncopyable.h \ utf8_utils.h \ ring_types.h \ - intrin.h \ + compiler_intrinsics.h \ array_size.h \ account_schema.h \ registration_states.h \ diff --git a/src/call.cpp b/src/call.cpp index aac915369a..9e93391e77 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -465,6 +465,8 @@ Call::merge(std::shared_ptr<Call> scall) std::lock_guard<std::recursive_mutex> lk2 (call.callMutex_, std::adopt_lock); auto pendingInMessages = std::move(call.pendingInMessages_); iceTransport_ = std::move(call.iceTransport_); + if (peerNumber_.empty()) + peerNumber_ = std::move(call.peerNumber_); peerDisplayName_ = std::move(call.peerDisplayName_); localAddr_ = call.localAddr_; localAudioPort_ = call.localAudioPort_; diff --git a/src/client/Makefile.am b/src/client/Makefile.am index cb26ade38f..fd4e3a32f0 100644 --- a/src/client/Makefile.am +++ b/src/client/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libclient.la diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp index 97132fec0a..eb7b0e04d7 100644 --- a/src/client/configurationmanager.cpp +++ b/src/client/configurationmanager.cpp @@ -838,9 +838,13 @@ bool lookupName(const std::string& account, const std::string& nameserver, const { #if HAVE_RINGNS if (account.empty()) { - ring::NameDirectory::instance(nameserver).lookupName(name, [name](const std::string& result, ring::NameDirectory::Response response) { + auto cb = [name](const std::string& result, ring::NameDirectory::Response response) { ring::emitSignal<DRing::ConfigurationSignal::RegisteredNameFound>("", (int)response, result, name); - }); + }; + if (nameserver.empty()) + ring::NameDirectory::lookupUri(name, "", cb); + else + ring::NameDirectory::instance(nameserver).lookupName(name, cb); return true; } else if (auto acc = ring::Manager::instance().getAccount<RingAccount>(account)) { acc->lookupName(name); diff --git a/src/ice_transport.cpp b/src/ice_transport.cpp index a0128fd9ca..00c538c32b 100644 --- a/src/ice_transport.cpp +++ b/src/ice_transport.cpp @@ -26,8 +26,10 @@ #include "upnp/upnp_control.h" #include <pjlib.h> +#include <msgpack.hpp> #include <utility> +#include <tuple> #include <algorithm> #include <sstream> #include <chrono> @@ -438,56 +440,48 @@ IceTransport::start(const Attribute& rem_attrs, return true; } -std::string -IceTransport::unpackLine(std::vector<uint8_t>::const_iterator& begin, - std::vector<uint8_t>::const_iterator& end) -{ - if (std::distance(begin, end) <= 0) - return {}; - - // Search for EOL - std::vector<uint8_t>::const_iterator line_end(begin); - while (line_end != end && *line_end != NEW_LINE && *line_end) - ++line_end; - - if (std::distance(begin, line_end) <= 0) - return {}; - - std::string str(begin, line_end); - - // Consume the new line character - if (std::distance(line_end, end) > 0) - ++line_end; - - begin = line_end; - return str; -} - bool IceTransport::start(const std::vector<uint8_t>& rem_data) { - auto begin = rem_data.cbegin(); - auto end = rem_data.cend(); - auto rem_ufrag = unpackLine(begin, end); - auto rem_pwd = unpackLine(begin, end); - if (rem_pwd.empty() or rem_pwd.empty()) { - RING_ERR("ICE remote attributes parsing error"); - return false; - } + std::string rem_ufrag; + std::string rem_pwd; std::vector<IceCandidate> rem_candidates; + + auto data = reinterpret_cast<const char*>(rem_data.data()); + auto size = rem_data.size(); + try { - while (true) { - IceCandidate candidate; - const auto line = unpackLine(begin, end); - if (line.empty()) - break; - if (getCandidateFromSDP(line, candidate)) - rem_candidates.push_back(candidate); + std::size_t offset = 0; + auto result = msgpack::unpack(data, size, offset); + auto version = result.get().as<uint8_t>(); + RING_DBG("[ice:%p] rx msg v%u", this, version); + if (version == 1) { + result = msgpack::unpack(data, size, offset); + std::tie(rem_ufrag, rem_pwd) = result.get().as<std::pair<std::string, std::string>>(); + result = msgpack::unpack(data, size, offset); + auto comp_cnt = result.get().as<uint8_t>(); + while (comp_cnt-- > 0) { + result = msgpack::unpack(data, size, offset); + IceCandidate cand; + for (const auto& line : result.get().as<std::vector<std::string>>()) { + if (getCandidateFromSDP(line, cand)) + rem_candidates.emplace_back(std::move(cand)); + } + } + } else { + RING_ERR("[ice:%p] invalid msg version", this); + return false; } - } catch (std::exception& e) { - RING_ERR("ICE remote candidates parsing error"); + } catch (const msgpack::unpack_error& e) { + RING_ERR("[ice:%p] remote msg unpack error: %s", this, e.what()); return false; } + + if (rem_pwd.empty() or rem_pwd.empty() or rem_candidates.empty()) { + RING_ERR("[ice:%p] invalid remote attributes", this); + return false; + } + return start({rem_ufrag, rem_pwd}, rem_candidates); } @@ -736,19 +730,20 @@ IceTransport::selectUPnPIceCandidates() } std::vector<uint8_t> -IceTransport::getLocalAttributesAndCandidates() const +IceTransport::packIceMsg() const { + static constexpr uint8_t ICE_MSG_VERSION = 1; + if (not isInitialized()) return {}; std::stringstream ss; - ss << local_ufrag_ << NEW_LINE; - ss << local_pwd_ << NEW_LINE; - for (unsigned i=0; i<component_count_; i++) { - const auto& candidates = getLocalCandidates(i); - for (const auto& c : candidates) - ss << c << NEW_LINE; - } + msgpack::pack(ss, ICE_MSG_VERSION); + msgpack::pack(ss, std::make_pair(local_ufrag_, local_pwd_)); + msgpack::pack(ss, static_cast<uint8_t>(component_count_)); + for (unsigned i=0; i<component_count_; i++) + msgpack::pack(ss, getLocalCandidates(i)); + auto str(ss.str()); return std::vector<uint8_t>(str.begin(), str.end()); } diff --git a/src/ice_transport.h b/src/ice_transport.h index 1b635c2c42..622c155742 100644 --- a/src/ice_transport.h +++ b/src/ice_transport.h @@ -190,7 +190,7 @@ class IceTransport { /** * Returns serialized ICE attributes and candidates. */ - std::vector<uint8_t> getLocalAttributesAndCandidates() const; + std::vector<uint8_t> packIceMsg() const; bool getCandidateFromSDP(const std::string& line, IceCandidate& cand); @@ -228,9 +228,6 @@ class IceTransport { pj_ice_strans_op op, pj_status_t status); - static std::string unpackLine(std::vector<uint8_t>::const_iterator& begin, - std::vector<uint8_t>::const_iterator& end); - struct IceSTransDeleter { void operator ()(pj_ice_strans* ptr) { pj_ice_strans_stop_ice(ptr); diff --git a/src/im/Makefile.am b/src/im/Makefile.am index 58cf15885a..848864b692 100644 --- a/src/im/Makefile.am +++ b/src/im/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libim.la diff --git a/src/manager.cpp b/src/manager.cpp index daac4659fb..6eeaf1e6f1 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -248,8 +248,9 @@ Manager::setAutoAnswer(bool enable) Manager::Manager() : pluginManager_(new PluginManager) , preferences(), voipPreferences(), - hookPreference(), audioPreference(), shortcutPreferences(), - hasTriedToRegister_(false) + hookPreference(), audioPreference(), shortcutPreferences() + , videoPreferences() + , hasTriedToRegister_(false) , toneCtrl_(preferences) , currentCallMutex_(), dtmfKey_(), dtmfBuf_(0, AudioFormat::MONO()) , audioLayerMutex_() @@ -1556,7 +1557,7 @@ Manager::saveConfig() hookPreference.serialize(out); audioPreference.serialize(out); #ifdef RING_VIDEO - getVideoDeviceMonitor().serialize(out); + videoPreferences.serialize(out); #endif shortcutPreferences.serialize(out); @@ -2662,7 +2663,7 @@ Manager::loadAccountMap(const YAML::Node &node) int errorCount = 0; try { #ifdef RING_VIDEO - getVideoDeviceMonitor().unserialize(node); + videoPreferences.unserialize(node); #endif } catch (const YAML::Exception &e) { RING_ERR("%s: No video node in config file", e.what()); @@ -2942,6 +2943,18 @@ Manager::getSinkClient(const std::string& id) return sink; return nullptr; } + +bool +Manager::getDecodingAccelerated() const +{ + return videoPreferences.getDecodingAccelerated(); +} + +void +Manager::setDecodingAccelerated(bool isAccelerated) +{ + videoPreferences.setDecodingAccelerated(isAccelerated); +} #endif // RING_VIDEO } // namespace ring diff --git a/src/manager.h b/src/manager.h index 2734334847..f472115883 100644 --- a/src/manager.h +++ b/src/manager.h @@ -117,6 +117,11 @@ class Manager { */ ShortcutPreferences shortcutPreferences; + /** + * Video preferences + */ + VideoPreferences videoPreferences; + // Manager should not be accessed until initialized. // FIXME this is an evil hack! static std::atomic_bool initialized; @@ -1013,6 +1018,10 @@ class Manager { std::shared_ptr<video::SinkClient> getSinkClient(const std::string& id); VideoManager& getVideoManager() const { return *videoManager_; } + + bool getDecodingAccelerated() const; + + void setDecodingAccelerated(bool isAccelerated); #endif // RING_VIDEO std::atomic<unsigned> dhtLogLevel {0}; // default = disable diff --git a/src/media/Makefile.am b/src/media/Makefile.am index bee4635ad2..c216e36c44 100644 --- a/src/media/Makefile.am +++ b/src/media/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libmedia.la diff --git a/src/media/audio/Makefile.am b/src/media/audio/Makefile.am index b26233d9b0..66161b3184 100644 --- a/src/media/audio/Makefile.am +++ b/src/media/audio/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libaudio.la diff --git a/src/media/audio/alsa/Makefile.am b/src/media/audio/alsa/Makefile.am index ce6f2ad100..39c9bcdaa9 100644 --- a/src/media/audio/alsa/Makefile.am +++ b/src/media/audio/alsa/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk if BUILD_ALSA diff --git a/src/media/audio/coreaudio/Makefile.am b/src/media/audio/coreaudio/Makefile.am index be060ee961..c30686629c 100644 --- a/src/media/audio/coreaudio/Makefile.am +++ b/src/media/audio/coreaudio/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk if HAVE_OSX noinst_LTLIBRARIES = libcoreaudiolayer.la diff --git a/src/media/audio/jack/Makefile.am b/src/media/audio/jack/Makefile.am index 54d900f26c..846dda9485 100644 --- a/src/media/audio/jack/Makefile.am +++ b/src/media/audio/jack/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk if BUILD_JACK noinst_LTLIBRARIES = libjacklayer.la diff --git a/src/media/audio/opensl/Makefile.am b/src/media/audio/opensl/Makefile.am index 782af06548..b5c3ec0cf5 100644 --- a/src/media/audio/opensl/Makefile.am +++ b/src/media/audio/opensl/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk if BUILD_OPENSL diff --git a/src/media/audio/portaudio/Makefile.am b/src/media/audio/portaudio/Makefile.am index a8fed9adfe..4313987ed0 100644 --- a/src/media/audio/portaudio/Makefile.am +++ b/src/media/audio/portaudio/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk if BUILD_PORTAUDIO diff --git a/src/media/audio/pulseaudio/Makefile.am b/src/media/audio/pulseaudio/Makefile.am index 36aed1ff2b..faa11ff40a 100644 --- a/src/media/audio/pulseaudio/Makefile.am +++ b/src/media/audio/pulseaudio/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk if BUILD_PULSE diff --git a/src/media/audio/sound/Makefile.am b/src/media/audio/sound/Makefile.am index f2ba42881f..5997ce2684 100644 --- a/src/media/audio/sound/Makefile.am +++ b/src/media/audio/sound/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libsound.la diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp index 959e41aca7..378fcdfec4 100644 --- a/src/media/media_decoder.cpp +++ b/src/media/media_decoder.cpp @@ -26,6 +26,7 @@ #include "audio/audiobuffer.h" #include "audio/ringbuffer.h" #include "audio/resampler.h" +#include "manager.h" #if defined(RING_VIDEO) && defined(RING_ACCEL) #include "video/accel.h" @@ -96,7 +97,9 @@ int MediaDecoder::openInput(const DeviceParams& params) RING_DBG("Trying to open device %s with format %s, pixel format %s, size %dx%d, rate %lf", params.input.c_str(), params.format.c_str(), params.pixel_format.c_str(), params.width, params.height, params.framerate.real()); - enableAccel_ = (params.enableAccel != "0"); + // if there was a fallback to software decoding, do not enable accel + // it has been disabled already by the video_receive_thread + enableAccel_ &= Manager::instance().getDecodingAccelerated(); int ret = avformat_open_input( &inputCtx_, diff --git a/src/media/media_decoder.h b/src/media/media_decoder.h index 1388688283..72531eebae 100644 --- a/src/media/media_decoder.h +++ b/src/media/media_decoder.h @@ -94,6 +94,7 @@ class MediaDecoder { int getPixelFormat() const; void setOptions(const std::map<std::string, std::string>& options); + void enableAccel(const bool enableAccel) { enableAccel_ = enableAccel; } private: NON_COPYABLE(MediaDecoder); diff --git a/src/media/media_device.h b/src/media/media_device.h index abf4826e03..9fb6859434 100644 --- a/src/media/media_device.h +++ b/src/media/media_device.h @@ -45,7 +45,6 @@ struct DeviceParams { std::string sdp_flags {}; unsigned offset_x {}; unsigned offset_y {}; - std::string enableAccel {}; }; } diff --git a/src/media/video/Makefile.am b/src/media/video/Makefile.am index 80e8469480..d95ddea7da 100644 --- a/src/media/video/Makefile.am +++ b/src/media/video/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk SUBDIRS= test diff --git a/src/media/video/androidvideo/Makefile.am b/src/media/video/androidvideo/Makefile.am index 0393a07d60..f651fc05d6 100644 --- a/src/media/video/androidvideo/Makefile.am +++ b/src/media/video/androidvideo/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libandroidvideo.la diff --git a/src/media/video/osxvideo/Makefile.am b/src/media/video/osxvideo/Makefile.am index 5da22cf4f7..f471e28a58 100644 --- a/src/media/video/osxvideo/Makefile.am +++ b/src/media/video/osxvideo/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libosxvideo.la diff --git a/src/media/video/test/Makefile.am b/src/media/video/test/Makefile.am index 96be9b522d..f4f44aa903 100644 --- a/src/media/video/test/Makefile.am +++ b/src/media/video/test/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk TESTS=test_shm test_video_input test_video_rtp check_PROGRAMS=test_video_rtp test_video_input test_shm diff --git a/src/media/video/uwpvideo/video_device_impl.cpp b/src/media/video/uwpvideo/video_device_impl.cpp index 1ae628f82e..ef7aeda35e 100644 --- a/src/media/video/uwpvideo/video_device_impl.cpp +++ b/src/media/video/uwpvideo/video_device_impl.cpp @@ -45,26 +45,11 @@ typedef struct { } uwp_fmt; // have all formats map to bgra -static const std::array<uwp_fmt, 19> uwp_formats { +static const std::array<uwp_fmt, 4> uwp_formats { uwp_fmt { "MJPG", VIDEO_PIXFMT_BGRA }, uwp_fmt { "RGB24", VIDEO_PIXFMT_BGRA }, uwp_fmt { "NV12", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "YUY2", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{30323449-0000-0010-8000-00AA00389B71}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{56555949-0000-0010-8000-00AA00389B71}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{e436eb78-524f-11ce-9f53-0020af0ba7701}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{e436eb7d-524f-11ce-9f53-0020af0ba7701}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{e436eb7e-524f-11ce-9f53-0020af0ba770}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{e436eb79-524f-11ce-9f53-0020af0ba770}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{e436eb7c-524f-11ce-9f53-0020af0ba770}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{e436eb7b-524f-11ce-9f53-0020af0ba770}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{e436eb7a-524f-11ce-9f53-0020af0ba770}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{59565955-0000-0010-8000-00AA00389B71}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{1d4a45f2-e5f6-4b44-8388-f0ae5c0e0c37}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{32595559-0000-0010-8000-00AA00389B71}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{31313259-0000-0010-8000-00AA00389B71}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{39555659-0000-0010-8000-00AA00389B71}", VIDEO_PIXFMT_BGRA }, - uwp_fmt { "{55595659-0000-0010-8000-00AA00389B71}", VIDEO_PIXFMT_BGRA } + uwp_fmt { "YUY2", VIDEO_PIXFMT_BGRA } }; class VideoDeviceImpl { diff --git a/src/media/video/v4l2/Makefile.am b/src/media/video/v4l2/Makefile.am index 99339d3050..cd3cf3dd8e 100644 --- a/src/media/video/v4l2/Makefile.am +++ b/src/media/video/v4l2/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libv4l2.la diff --git a/src/media/video/v4l2/vaapi.cpp b/src/media/video/v4l2/vaapi.cpp index 003d1d5cab..e18d5a2d48 100644 --- a/src/media/video/v4l2/vaapi.cpp +++ b/src/media/video/v4l2/vaapi.cpp @@ -154,7 +154,7 @@ VaapiAccel::open(AVCodecContext* codecCtx, std::string deviceName) return false; } - deviceBufferRef_.reset(av_buffer_ref(hardwareDeviceCtx)); + deviceBufferRef_.reset(hardwareDeviceCtx); auto device = reinterpret_cast<AVHWDeviceContext*>(deviceBufferRef_->data); vaConfig_ = VA_INVALID_ID; diff --git a/src/media/video/video_base.cpp b/src/media/video/video_base.cpp index 2faae31e32..4a88996fd3 100644 --- a/src/media/video/video_base.cpp +++ b/src/media/video/video_base.cpp @@ -82,7 +82,6 @@ VideoSettings::VideoSettings(const std::map<std::string, std::string>& settings) channel = extractString(settings, "channel"); video_size = extractString(settings, "size"); framerate = extractString(settings, "rate"); - enableAccel = extractString(settings, "enableAccel"); } std::map<std::string, std::string> @@ -92,8 +91,7 @@ VideoSettings::to_map() const {"name", name}, {"size", video_size}, {"channel", channel}, - {"rate", framerate}, - {"enableAccel", enableAccel} + {"rate", framerate} }; } @@ -108,7 +106,6 @@ convert<ring::video::VideoSettings>::encode(const ring::video::VideoSettings& rh node["video_size"] = rhs.video_size; node["channel"] = rhs.channel; node["framerate"] = rhs.framerate; - node["enableAccel"] = rhs.enableAccel; return node; } @@ -122,11 +119,6 @@ convert<ring::video::VideoSettings>::decode(const Node& node, ring::video::Video rhs.video_size = node["video_size"].as<std::string>(); rhs.channel = node["channel"].as<std::string>(); rhs.framerate = node["framerate"].as<std::string>(); - // optional setting that may or may not be there - try { - rhs.enableAccel = node["enableAccel"].as<std::string>(); - } catch (...) {} - return true; } diff --git a/src/media/video/video_base.h b/src/media/video/video_base.h index 0d6fe68c1f..16a9fb2c71 100644 --- a/src/media/video/video_base.h +++ b/src/media/video/video_base.h @@ -160,7 +160,6 @@ struct VideoSettings std::string channel {}; std::string video_size {}; std::string framerate {}; - std::string enableAccel {}; }; }} // namespace ring::video diff --git a/src/media/video/video_device.h b/src/media/video/video_device.h index b4e9f69119..504501f810 100644 --- a/src/media/video/video_device.h +++ b/src/media/video/video_device.h @@ -128,8 +128,6 @@ public: settings.framerate.c_str()); } - settings.enableAccel = "1"; - return settings; } @@ -143,7 +141,6 @@ public: settings.channel = params.channel_name; settings.video_size = sizeToString(params.width, params.height); settings.framerate = ring::to_string(params.framerate.real()); - settings.enableAccel = params.enableAccel; return settings; } @@ -162,7 +159,6 @@ public: params.width = size.first; params.height = size.second; params.framerate = rateFromString(settings.channel, size, settings.framerate); - params.enableAccel = settings.enableAccel; setDeviceParams(params); } diff --git a/src/media/video/video_device_monitor.cpp b/src/media/video/video_device_monitor.cpp index d5465fc982..384b40556f 100644 --- a/src/media/video/video_device_monitor.cpp +++ b/src/media/video/video_device_monitor.cpp @@ -292,9 +292,7 @@ VideoDeviceMonitor::overwritePreferences(VideoSettings settings) void VideoDeviceMonitor::serialize(YAML::Emitter &out) { - out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; out << YAML::Key << "devices" << YAML::Value << preferences_; - out << YAML::EndMap; } void diff --git a/src/media/video/video_receive_thread.cpp b/src/media/video/video_receive_thread.cpp index fa34ac64fb..73e7880125 100644 --- a/src/media/video/video_receive_thread.cpp +++ b/src/media/video/video_receive_thread.cpp @@ -41,14 +41,15 @@ using std::string; VideoReceiveThread::VideoReceiveThread(const std::string& id, const std::string &sdp, - const DeviceParams& args) : + const bool isReset) : VideoGenerator::VideoGenerator() - , args_(args) + , args_() , dstWidth_(0) , dstHeight_(0) , id_(id) , stream_(sdp) , restartDecoder_(false) + , isReset_(isReset) , sdpContext_(stream_.str().size(), false, &readFunction, 0, 0, this) , sink_ {Manager::instance().createSinkClient(id)} , requestKeyFrameCallback_(0) @@ -74,6 +75,9 @@ bool VideoReceiveThread::setup() { videoDecoder_.reset(new MediaDecoder()); + // disable accel if there was a fallback to software decoding + videoDecoder_->enableAccel(!isReset_); + dstWidth_ = args_.width; dstHeight_ = args_.height; diff --git a/src/media/video/video_receive_thread.h b/src/media/video/video_receive_thread.h index 57d1032de8..773acd1516 100644 --- a/src/media/video/video_receive_thread.h +++ b/src/media/video/video_receive_thread.h @@ -47,7 +47,7 @@ class SinkClient; class VideoReceiveThread : public VideoGenerator { public: - VideoReceiveThread(const std::string &id, const std::string &sdp, const DeviceParams& args); + VideoReceiveThread(const std::string &id, const std::string &sdp, const bool isReset); ~VideoReceiveThread(); void startLoop(); @@ -79,6 +79,7 @@ private: std::unique_ptr<MediaIOHandle> demuxContext_; std::shared_ptr<SinkClient> sink_; std::atomic_bool restartDecoder_; + bool isReset_; void (*requestKeyFrameCallback_)(const std::string &); void openDecoder(); bool decodeFrame(); diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index 077dff5363..72b7f97e1c 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -129,13 +129,13 @@ VideoRtpSession::restartSender() void VideoRtpSession::startReceiver() { if (receive_.enabled and not receive_.holding) { - DeviceParams receiverArgs = {}; + bool isReset = false; if (receiveThread_) { RING_WARN("Restarting video receiver"); - receiverArgs.enableAccel = "0"; // most likely cause of this restart + isReset = true; } receiveThread_.reset( - new VideoReceiveThread(callID_, receive_.receiving_sdp, receiverArgs) + new VideoReceiveThread(callID_, receive_.receiving_sdp, isReset) ); /* ebail: keyframe requests can lead to timeout if they are not answered. * we decided so to disable them for the moment @@ -160,7 +160,7 @@ VideoRtpSession::restartReceiver() if (not socketPair_) return; - startReceiver(); // disable accel + startReceiver(); } void VideoRtpSession::start(std::unique_ptr<IceSocket> rtp_sock, diff --git a/src/media/video/winvideo/Makefile.am b/src/media/video/winvideo/Makefile.am index 9e45320d6c..3451b694ce 100644 --- a/src/media/video/winvideo/Makefile.am +++ b/src/media/video/winvideo/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libwinvideo.la diff --git a/src/preferences.cpp b/src/preferences.cpp index d55ffd9ea7..0f2efb892b 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -45,6 +45,8 @@ #endif #endif /* HAVE_OPENSL */ +#include "client/videomanager.h" + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #include <yaml-cpp/yaml.h> @@ -122,6 +124,10 @@ static const char * const POPUP_SHORT_KEY = "popupWindow"; static const char * const TOGGLE_HOLD_SHORT_KEY = "toggleHold"; static const char * const TOGGLE_PICKUP_HANGUP_SHORT_KEY = "togglePickupHangup"; +// video preferences +constexpr const char * const VideoPreferences::CONFIG_LABEL; +static const char * const DECODING_ACCELERATED_KEY = "decodingAccelerated"; + static const char * const DFT_PULSE_LENGTH_STR = "250"; /** Default DTMF lenght */ static const char * const ALSA_DFT_CARD = "0"; /** Default sound card index */ @@ -537,4 +543,27 @@ void ShortcutPreferences::unserialize(const YAML::Node &in) parseValue(node, TOGGLE_PICKUP_HANGUP_SHORT_KEY, togglePickupHangup_); } +VideoPreferences::VideoPreferences() + : decodingAccelerated_(false) +{ +} + +void VideoPreferences::serialize(YAML::Emitter &out) +{ + out << YAML::Key << CONFIG_LABEL << YAML::Value << YAML::BeginMap; + out << YAML::Key << DECODING_ACCELERATED_KEY << YAML::Value << decodingAccelerated_; + getVideoDeviceMonitor().serialize(out); + out << YAML::EndMap; +} + +void VideoPreferences::unserialize(const YAML::Node &in) +{ + const auto &node = in[CONFIG_LABEL]; + // value may or may not be present + try { + parseValue(node, DECODING_ACCELERATED_KEY, decodingAccelerated_); + } catch (...) { decodingAccelerated_ = false; } // experimental, so disabled by default + getVideoDeviceMonitor().unserialize(in); +} + } // namespace ring diff --git a/src/preferences.h b/src/preferences.h index 1a8edbb86b..27716a4fd1 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -439,6 +439,26 @@ class ShortcutPreferences : public Serializable { constexpr static const char * const CONFIG_LABEL = "shortcuts"; }; +class VideoPreferences : public Serializable { + public: + VideoPreferences(); + + void serialize(YAML::Emitter &out); + void unserialize(const YAML::Node &in); + + bool getDecodingAccelerated() const { + return decodingAccelerated_; + } + + void setDecodingAccelerated(bool decodingAccelerated) { + decodingAccelerated_ = decodingAccelerated; + } + + private: + bool decodingAccelerated_; + constexpr static const char* const CONFIG_LABEL = "video"; +}; + } // namespace ring #endif diff --git a/src/ringdht/Makefile.am b/src/ringdht/Makefile.am index ecbc496385..0fc76be20b 100644 --- a/src/ringdht/Makefile.am +++ b/src/ringdht/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk SUBDIRS = eth/libdevcore eth/libdevcrypto diff --git a/src/ringdht/eth/libdevcore/Makefile.am b/src/ringdht/eth/libdevcore/Makefile.am index 24aebec25b..4c54d4eb7b 100644 --- a/src/ringdht/eth/libdevcore/Makefile.am +++ b/src/ringdht/eth/libdevcore/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libdevcore.la libdevcore_la_CPPFLAGS = @CPPFLAGS@ -DBOOST_SYSTEM_NO_DEPRECATED diff --git a/src/ringdht/eth/libdevcrypto/Makefile.am b/src/ringdht/eth/libdevcrypto/Makefile.am index b94f7ce16c..791c9e12c5 100644 --- a/src/ringdht/eth/libdevcrypto/Makefile.am +++ b/src/ringdht/eth/libdevcrypto/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk AM_CPPFLAGS += -I../ noinst_LTLIBRARIES = libdevcrypto.la diff --git a/src/ringdht/namedirectory.cpp b/src/ringdht/namedirectory.cpp index 0f6994948d..ec1bb6bc08 100644 --- a/src/ringdht/namedirectory.cpp +++ b/src/ringdht/namedirectory.cpp @@ -20,7 +20,9 @@ #include "logger.h" #include "string_utils.h" #include "thread_pool.h" +#include "fileutils.h" +#include <msgpack.hpp> #include <json/json.h> #include <restbed> @@ -28,154 +30,203 @@ #include <ciso646> #include <sstream> #include <regex> +#include <fstream> namespace ring { constexpr const char* const QUERY_NAME {"/name/"}; constexpr const char* const QUERY_ADDR {"/addr/"}; -const std::regex NAME_VALIDATOR {"^[a-z0-9-_]{3,32}$"}; -const std::regex URI_VALIDATOR {"^(:?[a-zA-Z]+://)?([a-zA-Z0-9\\-._~%!$&'()*+,;=:\\[\\]]+)"}; +constexpr const char* const HTTP_PROTO {"http://"}; + +/** Parser for Ring URIs. ( protocol ) ( username ) ( hostname ) */ +const std::regex URI_VALIDATOR {"^([a-zA-Z]+:(?://)?)?(?:([a-z0-9-_]{1,64})@)?([a-zA-Z0-9\\-._~%!$&'()*+,;=:\\[\\]]+)"}; +const std::regex NAME_VALIDATOR {"^[a-zA-Z0-9-_]{3,32}$"}; constexpr size_t MAX_RESPONSE_SIZE {1024 * 1024}; -std::string hostFromUri(const std::string& uri) +void toLower(std::string& string) +{ + std::transform(string.begin(), string.end(), string.begin(), ::tolower); +} + +void +NameDirectory::lookupUri(const std::string& uri, const std::string& default_server, LookupCallback cb) { std::smatch pieces_match; - if (std::regex_search(uri, pieces_match, URI_VALIDATOR)) - if (pieces_match.size() == 3) - return pieces_match[2].str(); - return uri; + if (std::regex_match(uri, pieces_match, URI_VALIDATOR)) { + if (pieces_match.size() == 4) { + if (pieces_match[2].length() == 0) + instance(default_server).lookupName(pieces_match[3], cb); + else + instance(pieces_match[3].str()).lookupName(pieces_match[2], cb); + return; + } + } + RING_ERR("Can't parse URI: %s", uri.c_str()); + cb("", Response::invalidName); } -NameDirectory::NameDirectory(const std::string& s) : serverUri_(s), serverHost_(hostFromUri(s)) +NameDirectory::NameDirectory(const std::string& s) + : serverHost_(s), + cachePath_(fileutils::get_cache_dir()+DIR_SEPARATOR_STR+"namecache"+DIR_SEPARATOR_STR+serverHost_) {} +void +NameDirectory::load() +{ + loadCache(); +} + NameDirectory& NameDirectory::instance(const std::string& server) { - const std::string& s = server.empty() ? DEFAULT_SERVER_URI : server; + const std::string& s = server.empty() ? DEFAULT_SERVER_HOST : server; static std::map<std::string, NameDirectory> instances {}; - auto it = instances.emplace(s, NameDirectory{s}); - return it.first->second; + auto r = instances.emplace(s, NameDirectory{s}); + if (r.second) + r.first->second.load(); + return r.first->second; +} + +size_t getContentLength(restbed::Response& reply) +{ + size_t length = 0; +#ifndef RESTBED_OLD_API + length = +#endif + reply.get_header("Content-Length", length); + return length; } void NameDirectory::lookupAddress(const std::string& addr, LookupCallback cb) { - auto cacheRes = nameCache_.find(addr); - if (cacheRes != nameCache_.end()) { - cb(cacheRes->second, Response::found); - return; - } + try { + auto cacheRes = nameCache_.find(addr); + if (cacheRes != nameCache_.end()) { + cb(cacheRes->second, Response::found); + return; + } - restbed::Uri uri(serverUri_ + QUERY_ADDR + addr); - auto req = std::make_shared<restbed::Request>(uri); - req->set_header("Accept", "*/*"); - req->set_header("Host", serverHost_); + restbed::Uri uri(HTTP_PROTO + serverHost_ + QUERY_ADDR + addr); + auto req = std::make_shared<restbed::Request>(uri); + req->set_header("Accept", "*/*"); + req->set_header("Host", serverHost_); - RING_DBG("Address lookup for %s: %s", addr.c_str(), uri.to_string().c_str()); + RING_DBG("Address lookup for %s: %s", addr.c_str(), uri.to_string().c_str()); - auto ret = restbed::Http::async(req, [this,cb,addr](const std::shared_ptr<restbed::Request>, - const std::shared_ptr<restbed::Response> reply) { - if (reply->get_status_code() == 200) { - size_t length = 0; - length = reply->get_header("Content-Length", length); - if (length > MAX_RESPONSE_SIZE) { - cb("", Response::error); - return; - } - restbed::Http::fetch(length, reply); - std::string body; - reply->get_body(body); - - Json::Value json; - Json::Reader reader; - if (!reader.parse(body, json)) { - RING_ERR("Address lookup for %s: can't parse server response: %s", addr.c_str(), body.c_str()); - cb("", Response::error); - return; - } - auto name = json["name"].asString(); - if (not name.empty()) { - RING_DBG("Found name for %s: %s", addr.c_str(), name.c_str()); - addrCache_.emplace(name, addr); - nameCache_.emplace(addr, name); - cb(name, Response::found); + auto ret = restbed::Http::async(req, [this,cb,addr](const std::shared_ptr<restbed::Request>, + const std::shared_ptr<restbed::Response> reply) { + if (reply->get_status_code() == 200) { + size_t length = getContentLength(*reply); + if (length > MAX_RESPONSE_SIZE) { + cb("", Response::error); + return; + } + restbed::Http::fetch(length, reply); + std::string body; + reply->get_body(body); + + Json::Value json; + Json::Reader reader; + if (!reader.parse(body, json)) { + RING_ERR("Address lookup for %s: can't parse server response: %s", addr.c_str(), body.c_str()); + cb("", Response::error); + return; + } + auto name = json["name"].asString(); + if (not name.empty()) { + RING_DBG("Found name for %s: %s", addr.c_str(), name.c_str()); + addrCache_.emplace(name, addr); + nameCache_.emplace(addr, name); + cb(name, Response::found); + saveCache(); + } else { + cb("", Response::notFound); + } } else { - cb("", Response::notFound); + cb("", Response::error); } - } else { - cb("", Response::error); - } - }).share(); + }).share(); - // avoid blocking on future destruction - ThreadPool::instance().run([ret](){ ret.get(); }); + // avoid blocking on future destruction + ThreadPool::instance().run([ret](){ ret.get(); }); + } catch (const std::exception& e) { + RING_ERR("Error when performing address lookup: %s", e.what()); + cb("", Response::error); + } } static const std::string HEX_PREFIX {"0x"}; -void NameDirectory::lookupName(const std::string& name, LookupCallback cb) +void NameDirectory::lookupName(const std::string& n, LookupCallback cb) { - if (not validateName(name)) { - cb(name, Response::invalidName); - return; - } - - auto cacheRes = addrCache_.find(name); - if (cacheRes != addrCache_.end()) { - cb(cacheRes->second, Response::found); - return; - } - - restbed::Uri uri(serverUri_ + QUERY_NAME + name); - auto request = std::make_shared<restbed::Request>(std::move(uri)); - request->set_header("Accept", "*/*"); - request->set_header("Host", serverHost_); + try { + std::string name {n}; + if (not validateName(name)) { + cb(name, Response::invalidName); + return; + } + toLower(name); - RING_DBG("Name lookup for %s: %s", name.c_str(), uri.to_string().c_str()); + auto cacheRes = addrCache_.find(name); + if (cacheRes != addrCache_.end()) { + cb(cacheRes->second, Response::found); + return; + } - auto ret = restbed::Http::async(request, [this,cb,name](const std::shared_ptr<restbed::Request>, - const std::shared_ptr<restbed::Response> reply) { - auto code = reply->get_status_code(); - if (code != 200) - RING_DBG("Name lookup for %s: got reply code %d", name.c_str(), code); - if (code >= 200 && code < 300) { - size_t length = 0; - length = reply->get_header("Content-Length", length); - if (length > MAX_RESPONSE_SIZE) { - cb("", Response::error); - return; - } - restbed::Http::fetch(length, reply); - std::string body; - reply->get_body(body); - - Json::Value json; - Json::Reader reader; - if (!reader.parse(body, json)) { - RING_ERR("Name lookup for %s: can't parse server response: %s", name.c_str(), body.c_str()); - cb("", Response::error); - return; - } - auto addr = json["addr"].asString(); - if (!addr.compare(0, HEX_PREFIX.size(), HEX_PREFIX)) - addr = addr.substr(HEX_PREFIX.size()); - if (not addr.empty()) { - RING_DBG("Found address for %s: %s", name.c_str(), addr.c_str()); - addrCache_.emplace(name, addr); - nameCache_.emplace(addr, name); - cb(addr, Response::found); - } else { + restbed::Uri uri(HTTP_PROTO + serverHost_ + QUERY_NAME + name); + auto request = std::make_shared<restbed::Request>(std::move(uri)); + request->set_header("Accept", "*/*"); + request->set_header("Host", serverHost_); + + RING_DBG("Name lookup for %s: %s", name.c_str(), uri.to_string().c_str()); + + auto ret = restbed::Http::async(request, [this,cb,name](const std::shared_ptr<restbed::Request>, + const std::shared_ptr<restbed::Response> reply) { + auto code = reply->get_status_code(); + if (code != 200) + RING_DBG("Name lookup for %s: got reply code %d", name.c_str(), code); + if (code >= 200 && code < 300) { + size_t length = getContentLength(*reply); + if (length > MAX_RESPONSE_SIZE) { + cb("", Response::error); + return; + } + restbed::Http::fetch(length, reply); + std::string body; + reply->get_body(body); + + Json::Value json; + Json::Reader reader; + if (!reader.parse(body, json)) { + RING_ERR("Name lookup for %s: can't parse server response: %s", name.c_str(), body.c_str()); + cb("", Response::error); + return; + } + auto addr = json["addr"].asString(); + if (!addr.compare(0, HEX_PREFIX.size(), HEX_PREFIX)) + addr = addr.substr(HEX_PREFIX.size()); + if (not addr.empty()) { + RING_DBG("Found address for %s: %s", name.c_str(), addr.c_str()); + addrCache_.emplace(name, addr); + nameCache_.emplace(addr, name); + cb(addr, Response::found); + saveCache(); + } else { + cb("", Response::notFound); + } + } else if (code >= 400 && code < 500) { cb("", Response::notFound); + } else { + cb("", Response::error); } - } else if (code >= 400 && code < 500) { - cb("", Response::notFound); - } else { - cb("", Response::error); - } - }).share(); + }).share(); - // avoid blocking on future destruction - ThreadPool::instance().run([ret](){ ret.get(); }); + // avoid blocking on future destruction + ThreadPool::instance().run([ret](){ ret.get(); }); + } catch (const std::exception& e) { + RING_ERR("Error when performing name lookup: %s", e.what()); + cb("", Response::error); + } } bool NameDirectory::validateName(const std::string& name) const @@ -183,79 +234,123 @@ bool NameDirectory::validateName(const std::string& name) const return std::regex_match(name, NAME_VALIDATOR); } -void NameDirectory::registerName(const std::string& addr, const std::string& name, const std::string& owner, RegistrationCallback cb) +void NameDirectory::registerName(const std::string& addr, const std::string& n, const std::string& owner, RegistrationCallback cb) { - if (not validateName(name)) { - cb(RegistrationResponse::invalidName); - return; - } + try { + std::string name {n}; + if (not validateName(name)) { + cb(RegistrationResponse::invalidName); + return; + } + toLower(name); + + auto cacheRes = addrCache_.find(name); + if (cacheRes != addrCache_.end()) { + if (cacheRes->second == addr) + cb(RegistrationResponse::success); + else + cb(RegistrationResponse::alreadyTaken); + return; + } - auto cacheRes = addrCache_.find(name); - if (cacheRes != addrCache_.end()) { - if (cacheRes->second == addr) - cb(RegistrationResponse::success); - else - cb(RegistrationResponse::alreadyTaken); - return; - } + auto request = std::make_shared<restbed::Request>(restbed::Uri(HTTP_PROTO + serverHost_ + QUERY_NAME + name)); + request->set_header("Accept", "*/*"); + request->set_header("Host", serverHost_); + request->set_header("Content-Type", "application/json"); + request->set_method("POST"); + std::string body; + { + std::stringstream ss; + ss << "{\"addr\":\"" << addr << "\",\"owner\":\"" << owner << "\"}"; + body = ss.str(); + } + request->set_body(body); + request->set_header("Content-Length", ring::to_string(body.size())); + + auto params = std::make_shared<restbed::Settings>(); + params->set_connection_timeout(std::chrono::seconds(120)); + + RING_WARN("registerName: sending request %s %s", addr.c_str(), name.c_str()); + auto ret = restbed::Http::async(request, + [this,cb,addr,name](const std::shared_ptr<restbed::Request>, + const std::shared_ptr<restbed::Response> reply) + { + auto code = reply->get_status_code(); + RING_DBG("Got reply for registration of %s -> %s: code %d", name.c_str(), addr.c_str(), code); + if (code >= 200 && code < 300) { + size_t length = getContentLength(*reply); + if (length > MAX_RESPONSE_SIZE) { + cb(RegistrationResponse::error); + return; + } + restbed::Http::fetch(length, reply); + std::string body; + reply->get_body(body); + + Json::Value json; + Json::Reader reader; + if (!reader.parse(body, json)) { + cb(RegistrationResponse::error); + return; + } + auto success = json["success"].asBool(); + RING_DBG("Got reply for registration of %s -> %s: %s", name.c_str(), addr.c_str(), success ? "success" : "failure"); + if (success) { + addrCache_.emplace(name, addr); + nameCache_.emplace(addr, name); + } + cb(success ? RegistrationResponse::success : RegistrationResponse::error); + } else if (code >= 400 && code < 500) { + cb(RegistrationResponse::alreadyTaken); + } else { + cb(RegistrationResponse::error); + } + }, params).share(); - auto request = std::make_shared<restbed::Request>(restbed::Uri(serverUri_ + QUERY_NAME + name)); - request->set_header("Accept", "*/*"); - request->set_header("Host", serverHost_); - request->set_header("Content-Type", "application/json"); - request->set_method("POST"); - std::string body; - { - std::stringstream ss; - ss << "{\"addr\":\"" << addr << "\",\"owner\":\"" << owner << "\"}"; - body = ss.str(); + // avoid blocking on future destruction + ThreadPool::instance().run([ret](){ ret.get(); }); + } catch (const std::exception& e) { + RING_ERR("Error when performing name registration: %s", e.what()); + cb(RegistrationResponse::error); } - request->set_body(body); - request->set_header("Content-Length", ring::to_string(body.size())); +} - auto params = std::make_shared<restbed::Settings>(); - params->set_connection_timeout(std::chrono::seconds(60)); +void +NameDirectory::saveCache() +{ + fileutils::recursive_mkdir(fileutils::get_cache_dir()+DIR_SEPARATOR_STR+"namecache"); + std::ofstream file(cachePath_, std::ios::trunc); + msgpack::pack(file, nameCache_); + RING_DBG("Saved %lu name-address mappings", (long unsigned)nameCache_.size()); +} - RING_WARN("registerName: sending request %s %s", addr.c_str(), name.c_str()); - auto ret = restbed::Http::async(request, - [this,cb,addr,name](const std::shared_ptr<restbed::Request>, - const std::shared_ptr<restbed::Response> reply) - { - auto code = reply->get_status_code(); - RING_DBG("Got reply for registration of %s -> %s: code %d", name.c_str(), addr.c_str(), code); - if (code >= 200 && code < 300) { - size_t length = 0; - length = reply->get_header("Content-Length", length); - if (length > MAX_RESPONSE_SIZE) { - cb(RegistrationResponse::error); - return; - } - restbed::Http::fetch(length, reply); - std::string body; - reply->get_body(body); +void +NameDirectory::loadCache() +{ + msgpack::unpacker pac; - Json::Value json; - Json::Reader reader; - if (!reader.parse(body, json)) { - cb(RegistrationResponse::error); - return; - } - auto success = json["success"].asBool(); - RING_DBG("Got reply for registration of %s -> %s: %s", name.c_str(), addr.c_str(), success ? "success" : "failure"); - if (success) { - addrCache_.emplace(name, addr); - nameCache_.emplace(addr, name); - } - cb(success ? RegistrationResponse::success : RegistrationResponse::error); - } else if (code >= 400 && code < 500) { - cb(RegistrationResponse::alreadyTaken); - } else { - cb(RegistrationResponse::error); + // read file + { + std::ifstream file(cachePath_); + if (!file.is_open()) { + RING_DBG("Could not load %s", cachePath_.c_str()); + return; + } + std::string line; + while (std::getline(file, line)) { + pac.reserve_buffer(line.size()); + memcpy(pac.buffer(), line.data(), line.size()); + pac.buffer_consumed(line.size()); } - }, params).share(); + } - // avoid blocking on future destruction - ThreadPool::instance().run([ret](){ ret.get(); }); + // load values + msgpack::object_handle oh; + if (pac.next(oh)) + oh.get().convert(nameCache_); + for (const auto& m : nameCache_) + addrCache_.emplace(m.second, m.first); + RING_DBG("Loaded %lu name-address mappings", (long unsigned)nameCache_.size()); } } diff --git a/src/ringdht/namedirectory.h b/src/ringdht/namedirectory.h index e8acc6f2a4..7528bef1a0 100644 --- a/src/ringdht/namedirectory.h +++ b/src/ringdht/namedirectory.h @@ -26,36 +26,44 @@ namespace ring { class NameDirectory { public: + enum class Response : int { found = 0, invalidName, notFound, error }; + enum class RegistrationResponse : int { success = 0, invalidName, alreadyTaken, error }; + + using LookupCallback = std::function<void(const std::string& result, Response response)>; + using RegistrationCallback = std::function<void(RegistrationResponse response)>; + NameDirectory() {} NameDirectory(const std::string& s); + void load(); static NameDirectory& instance(const std::string& server); - static NameDirectory& instance() { return instance(DEFAULT_SERVER_URI); } + static NameDirectory& instance() { return instance(DEFAULT_SERVER_HOST); } - enum class Response : int { found = 0, invalidName, notFound, error }; - enum class RegistrationResponse : int { success = 0, invalidName, alreadyTaken, error }; + static void lookupUri(const std::string& uri, const std::string& default_server, LookupCallback cb); - using LookupCallback = std::function<void(const std::string& result, Response response)>; void lookupAddress(const std::string& addr, LookupCallback cb); void lookupName(const std::string& name, LookupCallback cb); - using RegistrationCallback = std::function<void(RegistrationResponse response)>; void registerName(const std::string& addr, const std::string& name, const std::string& owner, RegistrationCallback cb); const std::string& getServer() const { - return serverUri_; + return serverHost_; } private: - constexpr static const char* const DEFAULT_SERVER_URI = "http://5.196.89.112:3000"; + constexpr static const char* const DEFAULT_SERVER_HOST = "ns.ring.cx"; + + const std::string serverHost_ {DEFAULT_SERVER_HOST}; + const std::string cachePath_; - const std::string serverUri_ {DEFAULT_SERVER_URI}; - const std::string serverHost_ {}; std::map<std::string, std::string> nameCache_; std::map<std::string, std::string> addrCache_; + bool validateName(const std::string& name) const; + void saveCache(); + void loadCache(); }; } diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp index 8147c514a7..e39cc54906 100644 --- a/src/ringdht/ringaccount.cpp +++ b/src/ringdht/ringaccount.cpp @@ -237,7 +237,7 @@ RingAccount::newOutgoingSIPCall(const std::string& toUrl) } catch (...) { #if HAVE_RINGNS std::weak_ptr<RingAccount> wthis_ = std::static_pointer_cast<RingAccount>(shared_from_this()); - nameDir_.get().lookupName(sufix, [wthis_,call](const std::string& result, NameDirectory::Response response) mutable { + NameDirectory::lookupUri(sufix, nameServer_, [wthis_,call](const std::string& result, NameDirectory::Response response) mutable { runOnMainThread([=]() mutable { if (auto sthis = wthis_.lock()) { try { @@ -269,6 +269,7 @@ RingAccount::startOutgoingCall(std::shared_ptr<SIPCall>& call, const std::string const auto toH = dht::InfoHash(toUri); + call->setPeerNumber(toUri + "@ring.dht"); call->setState(Call::ConnectionState::TRYING); std::weak_ptr<SIPCall> wCall = call; @@ -325,7 +326,7 @@ RingAccount::startOutgoingCall(std::shared_ptr<SIPCall>& call, const std::string const dht::Value::Id callvid = udist(sthis->rand_); const dht::Value::Id vid = udist(sthis->rand_); const auto callkey = dht::InfoHash::get("callto:" + dev.dev.toString()); - dht::Value val { dht::IceCandidates(callvid, ice->getLocalAttributesAndCandidates()) }; + dht::Value val { dht::IceCandidates(callvid, ice->packIceMsg()) }; val.id = vid; sthis->dht_.putEncrypted( @@ -528,7 +529,7 @@ void RingAccount::serialize(YAML::Emitter &out) out << YAML::Key << Conf::DHT_ALLOW_PEERS_FROM_TRUSTED << YAML::Value << allowPeersFromTrusted_; #if HAVE_RINGNS - out << YAML::Key << DRing::Account::ConfProperties::RingNS::URI << YAML::Value << nameDir_.get().getServer(); + out << YAML::Key << DRing::Account::ConfProperties::RingNS::URI << YAML::Value << nameServer_; #endif out << YAML::Key << DRing::Account::ConfProperties::ARCHIVE_PATH << YAML::Value << archivePath_; @@ -571,9 +572,12 @@ void RingAccount::unserialize(const YAML::Node &node) dhtPortUsed_ = dhtPort_; #if HAVE_RINGNS - std::string ringns_server; - parseValue(node, DRing::Account::ConfProperties::RingNS::URI, ringns_server); - nameDir_ = NameDirectory::instance(ringns_server); + try { + parseValue(node, DRing::Account::ConfProperties::RingNS::URI, nameServer_); + } catch (const std::exception& e) { + RING_WARN("can't read name server: %s", e.what()); + } + nameDir_ = NameDirectory::instance(nameServer_); #endif parseValue(node, Conf::DHT_PUBLIC_IN_CALLS, dhtPublicInCalls_); @@ -1122,6 +1126,10 @@ RingAccount::loadAccount(const std::string& archive_password, const std::string& // no receipt or archive, creating new account if (archive_password.empty()) { RING_WARN("Password needed to create archive"); + if (identity_.first) { + ringAccountId_ = identity_.first->getPublicKey().getId().toString(); + username_ = RING_URI_PREFIX+ringAccountId_; + } setRegistrationState(RegistrationState::ERROR_NEED_MIGRATION); } else { if (archive_pin.empty()) { @@ -1169,9 +1177,9 @@ RingAccount::setAccountDetails(const std::map<std::string, std::string> &details parseString(details, DRing::Account::ConfProperties::ARCHIVE_PATH, archivePath_); #if HAVE_RINGNS - std::string ringns_server; - parseString(details, DRing::Account::ConfProperties::RingNS::URI, ringns_server); - nameDir_ = NameDirectory::instance(ringns_server); + //std::string ringns_server; + parseString(details, DRing::Account::ConfProperties::RingNS::URI, nameServer_); + nameDir_ = NameDirectory::instance(nameServer_); #endif loadAccount(archive_password, archive_pin); @@ -1206,7 +1214,7 @@ RingAccount::getAccountDetails() const //a.emplace(DRing::Account::ConfProperties::ETH::KEY_FILE, ethPath_); a.emplace(DRing::Account::ConfProperties::RingNS::ACCOUNT, ethAccount_); #if HAVE_RINGNS - a.emplace(DRing::Account::ConfProperties::RingNS::URI, nameDir_.get().getServer()); + a.emplace(DRing::Account::ConfProperties::RingNS::URI, nameDir_.get().getServer()); #endif return a; @@ -1229,7 +1237,7 @@ void RingAccount::lookupName(const std::string& name) { auto acc = getAccountID(); - nameDir_.get().lookupName(name, [acc,name](const std::string& result, NameDirectory::Response response) { + NameDirectory::lookupUri(name, nameServer_, [acc,name](const std::string& result, NameDirectory::Response response) { emitSignal<DRing::ConfigurationSignal::RegisteredNameFound>(acc, (int)response, result, name); }); } @@ -1850,13 +1858,14 @@ RingAccount::replyToIncomingIceMsg(std::shared_ptr<SIPCall> call, std::shared_ptr<dht::crypto::Certificate> peer_cert) { const auto vid = udist(rand_); - dht::Value val { dht::IceCandidates(peer_ice_msg.id, ice->getLocalAttributesAndCandidates()) }; + dht::Value val { dht::IceCandidates(peer_ice_msg.id, ice->packIceMsg()) }; val.id = vid; + auto from = (peer_cert ? (peer_cert->issuer ? peer_cert->issuer->getId() : peer_cert->getId()) : peer_ice_msg.from).toString(); + std::weak_ptr<SIPCall> wcall = call; #if HAVE_RINGNS - auto from_acc_id = peer_cert ? (peer_cert->issuer ? peer_cert->issuer->getId().toString() : peer_cert->getId().toString()) : peer_ice_msg.from.toString(); - nameDir_.get().lookupAddress(from_acc_id, [wcall](const std::string& result, const NameDirectory::Response& response){ + nameDir_.get().lookupAddress(from, [wcall](const std::string& result, const NameDirectory::Response& response){ if (response == NameDirectory::Response::found) if (auto call = wcall.lock()) call->setPeerRegistredName(result); @@ -1886,7 +1895,6 @@ RingAccount::replyToIncomingIceMsg(std::shared_ptr<SIPCall> call, return; } - auto from = peer_ice_msg.from.toString(); call->setPeerNumber(from); call->initRecFilename(from); diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h index 1839fdec87..487fa8080a 100644 --- a/src/ringdht/ringaccount.h +++ b/src/ringdht/ringaccount.h @@ -350,6 +350,7 @@ class RingAccount : public SIPAccountBase { #if HAVE_RINGNS std::reference_wrapper<NameDirectory> nameDir_; + std::string nameServer_; std::string registeredName_; #endif diff --git a/src/security/Makefile.am b/src/security/Makefile.am index 8321a993b0..87ae2f1826 100644 --- a/src/security/Makefile.am +++ b/src/security/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libsecurity.la libsecurity_la_CXXFLAGS = @CXXFLAGS@ -I$(top_srcdir)/src diff --git a/src/sip/Makefile.am b/src/sip/Makefile.am index 71f7b272b3..ded7512cf5 100644 --- a/src/sip/Makefile.am +++ b/src/sip/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libsiplink.la libsiplink_la_CXXFLAGS = @CXXFLAGS@ -I$(top_srcdir)/src diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index 5ff8403627..6c62d60698 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -671,7 +671,9 @@ SIPCall::sendTextMessage(const std::map<std::string, std::string>& messages, c->sendTextMessage(messages, from); } else { if (inv) { - im::sendSipMessage(inv.get(), messages); + try { + im::sendSipMessage(inv.get(), messages); + } catch (...) {} } else { pendingOutMessages_.emplace_back(messages, from); RING_ERR("[call:%s] sendTextMessage: no invite session for this call", getCallId().c_str()); diff --git a/src/upnp/Makefile.am b/src/upnp/Makefile.am index 353152f5ba..60a07466cb 100644 --- a/src/upnp/Makefile.am +++ b/src/upnp/Makefile.am @@ -1,4 +1,4 @@ -include $(top_srcdir)/globals.mak +include $(top_srcdir)/globals.mk noinst_LTLIBRARIES = libupnpcontrol.la -- GitLab