diff --git a/MSVC/ring-daemon.vcxproj b/MSVC/ring-daemon.vcxproj
index b7d4ae207b6c7a840eb7513c08d5fcbc7c3b8dab..beffd2867a548150d213c255acb6bf173219ed55 100644
--- a/MSVC/ring-daemon.vcxproj
+++ b/MSVC/ring-daemon.vcxproj
@@ -501,7 +501,7 @@
       <SDLCheck>
       </SDLCheck>
       <AdditionalIncludeDirectories>$(ProjectDir)..\contrib\build\FFmpegInterop\ffmpeg\Build\Windows10\x64\include;$(ProjectDir);$(ProjectDir)..\;$(ProjectDir)..\src;$(ProjectDir)..\src\client;$(ProjectDir)..\src\config;$(ProjectDir)..\src\dring;$(ProjectDir)..\src\hooks;$(ProjectDir)..\src\iax;$(ProjectDir)..\src\im;$(ProjectDir)..\src\media;$(ProjectDir)..\src\ringdht;$(ProjectDir)..\src\security;$(ProjectDir)..\src\sip;$(ProjectDir)..\src\upnp;$(ProjectDir)..\src\ringdht\eth;$(ProjectDir)..\contrib\build;$(ProjectDir)..\contrib\build\include;$(ProjectDir)..\contrib\build\pjproject\pjlib\include;$(ProjectDir)..\contrib\build\pjproject\pjnath\include;$(ProjectDir)..\contrib\build\pjproject\pjlib-util\include;$(ProjectDir)..\contrib\build\pjproject\pjsip\include;$(ProjectDir)..\contrib\build\pjproject\third_party\speex\include;$(ProjectDir)..\contrib\build\pjproject\third_party;$(ProjectDir)..\contrib\build\pjproject\pjmedia\include;$(ProjectDir)..\contrib\build\boost;$(ProjectDir)..\contrib\build\cryptopp;$(ProjectDir)..\contrib\build\restbed\source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>BOOST_SYSTEM_NO_DEPRECATED;PJ_OS_HAS_CHECK_STACK=1;STATIC_GETOPT;_USE_MATH_DEFINES;PCRE_STATIC;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;HAVE_CONFIG_H;WIN32_LEAN_AND_MEAN;RING_UWP;WIN32_NATIVE;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>BOOST_SYSTEM_NO_DEPRECATED;PJ_OS_HAS_CHECK_STACK=1;STATIC_GETOPT;_USE_MATH_DEFINES;PCRE_STATIC;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;HAVE_CONFIG_H;WIN32_LEAN_AND_MEAN;RING_UWP;WIN32_NATIVE;_MBCS;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <DisableSpecificWarnings>4996;4503;4180;4244;4267;</DisableSpecificWarnings>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <BasicRuntimeChecks>Default</BasicRuntimeChecks>
@@ -527,7 +527,7 @@
       </Command>
     </PreBuildEvent>
     <Lib>
-      <AdditionalDependencies>ws2_32.lib;iphlpapi.lib;advapi32.lib;avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;libsamplerate.lib;libgnutls.lib;lib_json.lib;opendht.lib;Argon2Ref.lib;pcre.lib;yaml-cpp.lib;portaudio-UWP.lib;libupnp.lib;pjsip-core-x86_64-x64-vc14-Release.lib;pjsip-simple-x86_64-x64-vc14-Release.lib;pjsua2-lib-x86_64-x64-vc14-Release.lib;pjsua-lib-x86_64-x64-vc14-Release.lib;pjsip-ua-x86_64-x64-vc14-Release.lib;pjmedia-codec-x86_64-x64-vc14-Release.lib;pjmedia-x86_64-x64-vc14-Release.lib;pjlib-util-x86_64-x64-vc14-Release.lib;libspeex-x86_64-x64-vc14-Release.lib;pjlib-x86_64-x64-vc14-Release.lib;pjnath-x86_64-x64-vc14-Release.lib;restbed.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;iphlpapi.lib;advapi32.lib;avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;libsamplerate.lib;libgnutls.lib;lib_json.lib;opendht.lib;Argon2Ref.lib;pcre.lib;yaml-cpp.lib;portaudio-UWP.lib;libupnp.lib;pjsip-core-x86_64-x64-vc14-Release.lib;pjsip-simple-x86_64-x64-vc14-Release.lib;pjsua2-lib-x86_64-x64-vc14-Release.lib;pjsua-lib-x86_64-x64-vc14-Release.lib;pjsip-ua-x86_64-x64-vc14-Release.lib;pjmedia-codec-x86_64-x64-vc14-Release.lib;pjmedia-x86_64-x64-vc14-Release.lib;pjlib-util-x86_64-x64-vc14-Release.lib;libspeex-x86_64-x64-vc14-Release.lib;pjlib-x86_64-x64-vc14-Release.lib;pjnath-x86_64-x64-vc14-Release.lib;restbed.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(ProjectDir)..\contrib\build\FFmpegInterop\ffmpeg\Build\Windows10\x64\bin;$(ProjectDir)..\contrib\build\lib\x64;$(ProjectDir)..\contrib\build\boost\stage\lib;$(ProjectDir)..\contrib\build\pjproject\pjsip\lib;$(ProjectDir)..\contrib\build\pjproject\pjmedia\lib;$(ProjectDir)..\contrib\build\pjproject\pjlib-util\lib;$(ProjectDir)..\contrib\build\pjproject\third_party\lib;$(ProjectDir)..\contrib\build\pjproject\pjlib\lib;$(ProjectDir)..\contrib\build\pjproject\pjnath\lib;$(ProjectDir)..\contrib\build\libnatpmp\msvc\x64\Release;$(ProjectDir)..\contrib\build\restbed\build\Release;$(ProjectDir)..\contrib\build\restbed\dependency\openssl\out32dll</AdditionalLibraryDirectories>
       <AdditionalOptions>/ignore:4006 /ignore:4221 %(AdditionalOptions)</AdditionalOptions>
       <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
diff --git a/bin/jni/configurationmanager.i b/bin/jni/configurationmanager.i
index 043bffc2686a8a1683abb6013827df2d7db7451f..871c64ee8ec2d9bc7efa73fa48ecba14489a746e 100644
--- a/bin/jni/configurationmanager.i
+++ b/bin/jni/configurationmanager.i
@@ -194,6 +194,11 @@ int exportAccounts(std::vector<std::string> accountIDs, std::string toDir, std::
 int importAccounts(std::string archivePath, std::string password);
 
 void connectivityChanged();
+
+void enableProxyClient(const std::string& accountID, bool enable);
+void setPushNotificationToken(const std::string& pushDeviceToken);
+void pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data);
+
 }
 
 class ConfigurationCallback {
diff --git a/configure.ac b/configure.ac
index f3e1062caecc60dc98cad0840b9fbb62c47bf416..9e9dbc2b5879965ee9ea1f80805fb0f4f851eb71 100644
--- a/configure.ac
+++ b/configure.ac
@@ -223,6 +223,8 @@ AS_IF([test -n "${CONTRIB_DIR}"], [
   AC_MSG_RESULT([${CONTRIB_DIR}])
   export PATH=${CONTRIB_DIR}/bin:$PATH
   CPPFLAGS="${CPPFLAGS} -I${CONTRIB_DIR}/include"
+  CPPFLAGS+=" -DOPENDHT_PROXY_CLIENT=true -DOPENDHT_PUSH_NOTIFICATIONS=true -DOPENDHT_PROXY_SERVER=true"
+
   CFLAGS="${CFLAGS} -DPJ_AUTOCONF=1 "
   CXXFLAGS="${CXXFLAGS} -DPJ_AUTOCONF=1 "
   AS_IF([test "${HAVE_WIN64}" = "1"],[
@@ -230,8 +232,12 @@ AS_IF([test -n "${CONTRIB_DIR}"], [
       CXXFLAGS+=" -DPJ_WIN64=1"
   ])
   CFLAGS+=" -I${CONTRIB_DIR}/include"
+  CFLAGS+=" -DOPENDHT_PROXY_CLIENT=true -DOPENDHT_PUSH_NOTIFICATIONS=true -DOPENDHT_PROXY_SERVER=true"
   CXXFLAGS+=" -I${CONTRIB_DIR}/include"
+  CXXFLAGS+=" -DOPENDHT_PROXY_CLIENT=true -DOPENDHT_PUSH_NOTIFICATIONS=true -DOPENDHT_PROXY_SERVER=true"
+
   OBJCFLAGS="${OBJCFLAGS} -I${CONTRIB_DIR}/include"
+  OBJCFLAGS+=" -DOPENDHT_PROXY_CLIENT=true -DOPENDHT_PUSH_NOTIFICATIONS=true -DOPENDHT_PROXY_SERVER=true"
   AS_IF([test "${SYS}" = "mingw32"],[
         PKG_CONFIG_PATH_CUSTOM="${CONTRIB_DIR}/lib/pkgconfig:${CONTRIB_DIR}/lib64/pkgconfig"
         AC_SUBST(PKG_CONFIG_PATH_CUSTOM)
@@ -243,6 +249,10 @@ AS_IF([test -n "${CONTRIB_DIR}"], [
   AS_IF([test "${SYS}" = "darwin"], [
     export LD_LIBRARY_PATH="${CONTRIB_DIR}/lib:$LD_LIBRARY_PATH"
     export DYLD_LIBRARY_PATH="${CONTRIB_DIR}/lib:$DYLD_LIBRARY_PATH"
+  ], [
+      PKG_CHECK_MODULES([Jsoncpp], [jsoncpp >= 1.6.5])
+      CPPFLAGS="${CPPFLAGS} ${Jsoncpp_CFLAGS}"
+      LDFLAGS="${LDFLAGS} ${Jsoncpp_LIBS}"
   ])
 ], [
   AS_IF([test -n "${with_contrib}" && test "${with_contrib}" != "no"], [
@@ -413,7 +423,7 @@ AS_IF([test "x$enable_restbed_old_api" = "xyes"], [
 ])
 
 AS_IF([test "x$enable_ringns" != "xno" || test "x$with_restcpp" = "xyes"],
-  AC_CHECK_LIB(restbed, exit,, AC_MSG_ERROR([Missing restbed files])));
+AC_CHECK_LIB(restbed, exit,, AC_MSG_ERROR([Missing restbed files])));
 
 AS_IF([test "x$with_restcpp" = "xyes"], [
     AS_AC_EXPAND(SBINDIR, $sbindir)
diff --git a/contrib/build_all_uwp.bat b/contrib/build_all_uwp.bat
index 803964cac3cc7954e9786572c17e3857e011abb6..80203fe31146c1e7e7e4b999a6f74f07115050f7 100644
--- a/contrib/build_all_uwp.bat
+++ b/contrib/build_all_uwp.bat
@@ -70,20 +70,11 @@ set MSYS2_BIN="C:\msys64\usr\bin\bash.exe"
 call BuildFFmpeg.bat win10 x64
 cd ..\..
 
-rem * build openssl UWP *
-cd build\restbed\dependency\openssl
-call perl Configure no-asm no-hw no-dso VC-WINUNIVERSAL
-call ms\do_winuniversal
-call ms\setVSvars universal10.0x64
-call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
-call nmake -f ms\ntdll.mak
-set PATH=restbed\dependency\openssl\out32dll;%PATH%
-
 rem * build restbed w/asio *
-cd ..\..
+cd build\restbed
 mkdir build
 cd build
-cmake -G "Visual Studio 14 2015 Win64" ..
+cmake -DBUILD_SSL=OFF -G "Visual Studio 14 2015 Win64" ..
 cmake --build . --target ALL_BUILD --config Release
 cd ..\..
 
diff --git a/contrib/src/opendht/SHA512SUMS b/contrib/src/opendht/SHA512SUMS
index cc4f242bf6acbdde7b8941e3cb8c11e38fdd18c8..3de588ce3222f59e7aeca6829c5971a907a70f48 100644
--- a/contrib/src/opendht/SHA512SUMS
+++ b/contrib/src/opendht/SHA512SUMS
@@ -1 +1 @@
-eb2ffc2662cd981a552ae19109260a2d675de748906f5e1037b85fe123cfbd2b4a714ef1428444f69828d5cd2405f7cb70cd53ad36c71b298d9930c49fca16ba  opendht-1.5.0.tar.gz
+ef677a72dfbd59dfa604165ab3be547e1bd52ff2862a86bfed54c7f931d26a8374b30a20ad818ff45fa377bad662d8b9dc9e1db9108cda6422b9c4a8ec90dc4d  opendht-4d4ba2be96ae237f21e65acdc3eab24d7d5d0e00.tar.gz
diff --git a/contrib/src/opendht/fetch_and_patch.bat b/contrib/src/opendht/fetch_and_patch.bat
index 0678217de4906de347c2aa2fdd60a4eecf6586be..dfdc7795ea4d4115cf8af52ca7f6b4866981e53b 100644
--- a/contrib/src/opendht/fetch_and_patch.bat
+++ b/contrib/src/opendht/fetch_and_patch.bat
@@ -1,6 +1,6 @@
 set BUILD=%SRC%..\build
 
-set OPENDHT_VERSION=1.5.0
+set OPENDHT_VERSION=4d4ba2be96ae237f21e65acdc3eab24d7d5d0e00
 set OPENDHT_URL=https://github.com/savoirfairelinux/opendht/archive/%OPENDHT_VERSION%.tar.gz
 
 mkdir %BUILD%
@@ -18,5 +18,6 @@ rename %BUILD%\opendht-%OPENDHT_VERSION% opendht
 cd %BUILD%\opendht
 
 git apply --reject --whitespace=fix %SRC%\opendht\opendht-uwp.patch
+git apply --reject --whitespace=fix %SRC%\opendht\opendht-proxy-uwp.patch
 
 cd %SRC%
diff --git a/contrib/src/opendht/opendht-proxy-uwp.patch b/contrib/src/opendht/opendht-proxy-uwp.patch
new file mode 100644
index 0000000000000000000000000000000000000000..285d2e0608c01123ddffb0e4cc7ee6406eaf6dd1
--- /dev/null
+++ b/contrib/src/opendht/opendht-proxy-uwp.patch
@@ -0,0 +1,194 @@
+--- a/MSVC/opendht.vcxproj
++++ b/MSVC/opendht.vcxproj
+@@ -19,11 +19,14 @@
+     </ProjectConfiguration>
+   </ItemGroup>
+   <ItemGroup>
++    <ClCompile Include="..\src\base64.cpp" />
+     <ClCompile Include="..\src\callbacks.cpp" />
+     <ClCompile Include="..\src\crypto.cpp" />
+     <ClCompile Include="..\src\default_types.cpp" />
+     <ClCompile Include="..\src\dht.cpp" />
+     <ClCompile Include="..\src\dhtrunner.cpp" />
++    <ClCompile Include="..\src\dht_proxy_client.cpp" />
++    <ClCompile Include="..\src\dht_proxy_server.cpp" />
+     <ClCompile Include="..\src\indexation\pht.cpp" />
+     <ClCompile Include="..\src\infohash.cpp" />
+     <ClCompile Include="..\src\log.cpp" />
+@@ -36,32 +39,13 @@
+     <ClCompile Include="..\src\value.cpp" />
+   </ItemGroup>
+   <ItemGroup>
+-    <ClInclude Include="..\include\opendht.h" />
+-    <ClInclude Include="..\include\opendht\callbacks.h" />
+-    <ClInclude Include="..\include\opendht\crypto.h" />
+     <ClInclude Include="..\include\opendht\def.h" />
+-    <ClInclude Include="..\include\opendht\default_types.h" />
+-    <ClInclude Include="..\include\opendht\dht.h" />
+-    <ClInclude Include="..\include\opendht\dhtrunner.h" />
+-    <ClInclude Include="..\include\opendht\indexation\pht.h" />
+-    <ClInclude Include="..\include\opendht\infohash.h" />
+-    <ClInclude Include="..\include\opendht\log.h" />
+-    <ClInclude Include="..\include\opendht\log_enable.h" />
+-    <ClInclude Include="..\include\opendht\network_engine.h" />
+-    <ClInclude Include="..\include\opendht\node.h" />
+-    <ClInclude Include="..\include\opendht\node_cache.h" />
+-    <ClInclude Include="..\include\opendht\rate_limiter.h" />
+-    <ClInclude Include="..\include\opendht\request.h" />
+-    <ClInclude Include="..\include\opendht\rng.h" />
+-    <ClInclude Include="..\include\opendht\routing_table.h" />
+-    <ClInclude Include="..\include\opendht\scheduler.h" />
+-    <ClInclude Include="..\include\opendht\securedht.h" />
+     <ClInclude Include="..\include\opendht\sockaddr.h" />
+-    <ClInclude Include="..\include\opendht\utils.h" />
+-    <ClInclude Include="..\include\opendht\value.h" />
+-    <ClInclude Include="..\src\net.h" />
++    <ClInclude Include="..\src\base64.h" />
+     <ClInclude Include="..\src\listener.h" />
++    <ClInclude Include="..\src\net.h" />
+     <ClInclude Include="..\src\parsed_message.h" />
++    <ClInclude Include="..\src\request.h" />
+     <ClInclude Include="..\src\search.h" />
+     <ClInclude Include="..\src\storage.h" />
+   </ItemGroup>
+@@ -215,8 +199,8 @@ copy ..\include\opendht.h $(OutDir)\include\</Command>
+       <FunctionLevelLinking>true</FunctionLevelLinking>
+       <IntrinsicFunctions>true</IntrinsicFunctions>
+       <SDLCheck>true</SDLCheck>
+-      <AdditionalIncludeDirectories>$(ProjectDir)contrib\build\include;$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)contrib\build\msgpack-c\include;$(ProjectDir)contrib\build\argon2\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include</AdditionalIncludeDirectories>
+-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++      <AdditionalIncludeDirectories>$(ProjectDir)contrib\build\include;$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)contrib\build\msgpack-c\include;$(ProjectDir)contrib\build\argon2\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\restbed\source</AdditionalIncludeDirectories>
++      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+       <DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
+       <AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
+       <ProgramDataBaseFileName>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDataBaseFileName>
+diff --git a/MSVC/opendht.vcxproj.filters b/MSVC/opendht.vcxproj.filters
+index 9d275f8..885baa0 100644
+--- a/MSVC/opendht.vcxproj.filters
++++ b/MSVC/opendht.vcxproj.filters
+@@ -31,9 +31,6 @@
+     <ClCompile Include="..\src\node_cache.cpp">
+       <Filter>Source Files</Filter>
+     </ClCompile>
+-    <ClCompile Include="..\src\indexation\pht.cpp">
+-      <Filter>Source Files</Filter>
+-    </ClCompile>
+     <ClCompile Include="..\src\routing_table.cpp">
+       <Filter>Source Files</Filter>
+     </ClCompile>
+@@ -46,79 +43,38 @@
+     <ClCompile Include="..\src\value.cpp">
+       <Filter>Source Files</Filter>
+     </ClCompile>
++    <ClCompile Include="..\src\base64.cpp">
++      <Filter>Source Files</Filter>
++    </ClCompile>
++    <ClCompile Include="..\src\dht_proxy_client.cpp">
++      <Filter>Source Files</Filter>
++    </ClCompile>
++    <ClCompile Include="..\src\dht_proxy_server.cpp">
++      <Filter>Source Files</Filter>
++    </ClCompile>
++    <ClCompile Include="..\src\indexation\pht.cpp">
++      <Filter>Source Files\indexation</Filter>
++    </ClCompile>
+   </ItemGroup>
+   <ItemGroup>
+-    <ClInclude Include="..\include\opendht\callbacks.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\crypto.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\default_types.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\dht.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\dhtrunner.h">
+-      <Filter>Header Files</Filter>
++    <ClInclude Include="..\include\opendht\def.h" />
++    <ClInclude Include="..\include\opendht\sockaddr.h" />
++    <ClInclude Include="..\src\net.h" />
++    <ClInclude Include="..\src\parsed_message.h" />
++    <ClInclude Include="..\src\base64.h">
++      <Filter>Source Files</Filter>
+     </ClInclude>
+-    <ClInclude Include="..\include\opendht\infohash.h">
+-      <Filter>Header Files</Filter>
++    <ClInclude Include="..\src\request.h">
++      <Filter>Source Files</Filter>
+     </ClInclude>
+     <ClInclude Include="..\src\listener.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\log.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\log_enable.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\network_engine.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\node.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\node_cache.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\indexation\pht.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\rate_limiter.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\request.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\rng.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\routing_table.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\scheduler.h">
+-      <Filter>Header Files</Filter>
++      <Filter>Source Files</Filter>
+     </ClInclude>
+     <ClInclude Include="..\src\search.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\securedht.h">
+-      <Filter>Header Files</Filter>
++      <Filter>Source Files</Filter>
+     </ClInclude>
+     <ClInclude Include="..\src\storage.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\utils.h">
+-      <Filter>Header Files</Filter>
+-    </ClInclude>
+-    <ClInclude Include="..\include\opendht\value.h">
+-      <Filter>Header Files</Filter>
++      <Filter>Source Files</Filter>
+     </ClInclude>
+   </ItemGroup>
+   <ItemGroup>
+@@ -128,5 +84,8 @@
+     <Filter Include="Header Files">
+       <UniqueIdentifier>{d1ab5bfe-3ab1-45ee-9324-b4b071887668}</UniqueIdentifier>
+     </Filter>
++    <Filter Include="Source Files\indexation">
++      <UniqueIdentifier>{4f930bd8-2e82-4b16-8db5-8c8dfff25a18}</UniqueIdentifier>
++    </Filter>
+   </ItemGroup>
+ </Project>
+\ No newline at end of file
+-- 
+2.10.2.windows.1
+
diff --git a/contrib/src/opendht/rules.mak b/contrib/src/opendht/rules.mak
index b7fbe8ec832d1f1e7cc5377bddc4bec3ef2b33a3..eace582492d37593393474519316a7d7508b1cd9 100644
--- a/contrib/src/opendht/rules.mak
+++ b/contrib/src/opendht/rules.mak
@@ -1,5 +1,5 @@
 # OPENDHT
-OPENDHT_VERSION := 1.5.0
+OPENDHT_VERSION := 4d4ba2be96ae237f21e65acdc3eab24d7d5d0e00
 OPENDHT_URL := https://github.com/savoirfairelinux/opendht/archive/$(OPENDHT_VERSION).tar.gz
 
 PKGS += opendht
@@ -14,6 +14,12 @@ endif
 ifneq ($(call need_pkg,"libargon2"),)
 DEPS_opendht += argon2
 endif
+ifneq ($(call need_pkg,"restbed"),)
+DEPS_opendht += restbed
+endif
+ifneq ($(call need_pkg,"jsoncpp"),)
+DEPS_opendht += jsoncpp
+endif
 ifneq ($(call need_pkg,"gnutls >= 3.3.0"),)
 DEPS_opendht += gnutls
 endif
@@ -30,6 +36,6 @@ opendht: opendht-$(OPENDHT_VERSION).tar.gz
 
 .opendht: opendht .sum-opendht
 	mkdir -p $</m4 && $(RECONF)
-	cd $< && $(HOSTVARS) ./configure --disable-tools --disable-python --disable-doc $(HOSTCONF)
+	cd $< && $(HOSTVARS) ./configure --disable-tools --disable-python --disable-doc --enable-proxy-server --enable-proxy-client --enable-push-notifications $(HOSTCONF)
 	cd $< && $(MAKE) install
 	touch $@
diff --git a/contrib/src/restbed/SHA512SUMS b/contrib/src/restbed/SHA512SUMS
index 765ea6a0fedf0715989e9b9d678d878154dce10e..6db3ed127a87153279d0374c95126b5dc944191f 100644
--- a/contrib/src/restbed/SHA512SUMS
+++ b/contrib/src/restbed/SHA512SUMS
@@ -1 +1 @@
-81fbc7c90b6690ba9926c7990495bf114d4b4511785cf8ad7d526a119104e6eea0d0945c7e73e94ff7005b996b96ec4ecb067e192da04afa20e854c1f982549d  restbed-4.6.tar.gz
\ No newline at end of file
+26fa79c08cf9414bb26a0a6d3573e71d4df0facfe1a0d86a5935bdf5203f7d1fb633fa99802bc2c9104eed7ab67e9cef3e1679ca4a12b982bfd49d7f5a1c088c  restbed-df867a858dddc4cf6ca8642da02720bd65ba239a.tar.gz
diff --git a/contrib/src/restbed/async_read_until-uwp.patch b/contrib/src/restbed/async_read_until-uwp.patch
new file mode 100644
index 0000000000000000000000000000000000000000..78cf7ee20677ab522371213182ecde5a786ea9c9
--- /dev/null
+++ b/contrib/src/restbed/async_read_until-uwp.patch
@@ -0,0 +1,88 @@
+--- a/source/corvusoft/restbed/detail/socket_impl.cpp
++++ b/source/corvusoft/restbed/detail/socket_impl.cpp
+@@ -418,20 +418,40 @@ namespace restbed
+             m_timer->async_wait( bind( &SocketImpl::connection_timeout_handler, this, shared_from_this( ), _1 ) );
+             
+             size_t size = 0;
++            auto finished = std::make_shared<bool>(false);
++            auto sharedError = std::make_shared<error_code>();
++            auto sharedSize = std::make_shared<size_t>(0);
+ #ifdef BUILD_SSL
+             
+             if ( m_socket not_eq nullptr )
+             {
+ #endif
+                 size = asio::read( *m_socket, *data, asio::transfer_at_least( length ), error );
++                asio::async_read(*m_socket, *data, asio::transfer_at_least(length),
++                    [this, finished, sharedSize, sharedError](const error_code & error, size_t size) {
++                    *sharedError = error;
++                    *sharedSize = size;
++                    *finished = true;
++                });
+ #ifdef BUILD_SSL
+             }
+             else
+             {
+                 size = asio::read( *m_ssl_socket, *data, asio::transfer_at_least( length ), error );
++                asio::async_read(*m_ssl_socket, *data, asio::transfer_at_least(length),
++                    [this, finished, sharedSize, sharedError](const error_code & error, size_t size) {
++                    *sharedError = error;
++                    *sharedSize = size;
++                    *finished = true;
++                });
+             }
+             
+ #endif
++            auto& io_service = m_socket->get_io_service();
++            while (!*finished)
++                io_service.run_one();
++            error = *sharedError;
++            size = *sharedSize;
+             m_timer->cancel( );
+             
+             if ( error )
+@@ -549,21 +569,40 @@ namespace restbed
+             m_timer->async_wait( bind( &SocketImpl::connection_timeout_handler, this, shared_from_this( ), _1 ) );
+             
+             size_t length = 0;
+-            
++            auto finished = std::make_shared<bool>(false);
++            auto sharedError = std::make_shared<error_code>();
++            auto sharedLength = std::make_shared<size_t>(0);
+ #ifdef BUILD_SSL
+             
+             if ( m_socket not_eq nullptr )
+             {
+ #endif
+                 length = asio::read_until( *m_socket, *data, delimiter, error );
++                asio::async_read_until(*m_socket, *data, delimiter,
++                    [this, finished, sharedLength, sharedError](const error_code & error, size_t length) {
++                    *sharedError = error;
++                    *sharedLength = length;
++                    *finished = true;
++                });
+ #ifdef BUILD_SSL
+             }
+             else
+             {
+                 length = asio::read_until( *m_ssl_socket, *data, delimiter, error );
++                asio::async_read_until(*m_ssl_socket, *data, delimiter,
++                    [this, finished, sharedLength, sharedError](const error_code & error, size_t length) {
++                    *sharedError = error;
++                    *sharedLength = length;
++                    *finished = true;
++        });
+             }
+             
+ #endif
++            auto& io_service = m_socket->get_io_service();
++            while (!*finished)
++                io_service.run_one();
++            error = *sharedError;
++            length = *sharedLength;
+             m_timer->cancel( );
+             
+             if ( error )
+-- 
+2.10.2.windows.1
+
diff --git a/contrib/src/restbed/async_read_until.patch b/contrib/src/restbed/async_read_until.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9dd0760cee30d1661f6884d4aff00ffcba556d49
--- /dev/null
+++ b/contrib/src/restbed/async_read_until.patch
@@ -0,0 +1,123 @@
+From 09b542eea3fb3038d02ff056d41dea16bfe889bd Mon Sep 17 00:00:00 2001
+From: AmarOk <contact@enconn.fr>
+Date: Tue, 5 Dec 2017 10:45:53 -0600
+Subject: [PATCH]socket_impl: replace read_until by async_read_until
+
+---
+ source/corvusoft/restbed/detail/socket_impl.cpp | 62 +++++++++++++++++++------
+ 1 file changed, 49 insertions(+), 13 deletions(-)
+
+diff --git a/source/corvusoft/restbed/detail/socket_impl.cpp b/source/corvusoft/restbed/detail/socket_impl.cpp
+index 90e8b04..379f1c7 100644
+--- a/source/corvusoft/restbed/detail/socket_impl.cpp
++++ b/source/corvusoft/restbed/detail/socket_impl.cpp
+@@ -417,28 +417,47 @@ namespace restbed
+             m_timer->expires_from_now( m_timeout );
+             m_timer->async_wait( bind( &SocketImpl::connection_timeout_handler, this, shared_from_this( ), _1 ) );
+             
++
+             size_t size = 0;
++            auto finished = std::make_shared<bool>(false);
++            auto sharedError = std::make_shared<error_code>();
++            auto sharedSize = std::make_shared<size_t>(0);
++
+ #ifdef BUILD_SSL
+-            
++
+             if ( m_socket not_eq nullptr )
+             {
+ #endif
+-                size = asio::read( *m_socket, *data, asio::transfer_at_least( length ), error );
++                asio::async_read( *m_socket, *data, asio::transfer_at_least( length ),
++                    [ this, finished, sharedSize, sharedError ]( const error_code & error, size_t size ) {
++                        *sharedError = error;
++                        *sharedSize = size;
++                        *finished = true;
++                });
+ #ifdef BUILD_SSL
+             }
+             else
+             {
+-                size = asio::read( *m_ssl_socket, *data, asio::transfer_at_least( length ), error );
++                asio::async_read( *m_ssl_socket, *data, asio::transfer_at_least( length ),
++                    [ this, finished, sharedSize, sharedError ]( const error_code & error, size_t size ) {
++                        *sharedError = error;
++                        *sharedSize = size;
++                        *finished = true;
++                });
+             }
+-            
+ #endif
++            auto& io_service = m_socket->get_io_service( );
++            while (!*finished)
++                io_service.run_one();
++            error = *sharedError;
++            size = *sharedSize;
+             m_timer->cancel( );
+-            
++
+             if ( error )
+             {
+                 m_is_open = false;
+             }
+-            
++
+             return size;
+         }
+         
+@@ -549,28 +568,45 @@ namespace restbed
+             m_timer->async_wait( bind( &SocketImpl::connection_timeout_handler, this, shared_from_this( ), _1 ) );
+             
+             size_t length = 0;
+-            
++            auto finished = std::make_shared<bool>(false);
++            auto sharedError = std::make_shared<error_code>();
++            auto sharedLength = std::make_shared<size_t>(0);
++
+ #ifdef BUILD_SSL
+-            
++
+             if ( m_socket not_eq nullptr )
+             {
+ #endif
+-                length = asio::read_until( *m_socket, *data, delimiter, error );
++                asio::async_read_until( *m_socket, *data, delimiter,
++                    [ this, finished, sharedLength, sharedError ]( const error_code & error, size_t length ) {
++                        *sharedError = error;
++                        *sharedLength = length;
++                        *finished = true;
++                });
+ #ifdef BUILD_SSL
+             }
+             else
+             {
+-                length = asio::read_until( *m_ssl_socket, *data, delimiter, error );
++                asio::async_read_until( *m_ssl_socket, *data, delimiter,
++                    [ this, finished, sharedLength, sharedError ]( const error_code & error, size_t length ) {
++                        *sharedError = error;
++                        *sharedLength = length;
++                        *finished = true;
++                });
+             }
+-            
+ #endif
++            auto& io_service = m_socket->get_io_service( );
++            while (!*finished)
++                io_service.run_one();
++            error = *sharedError;
++            length = *sharedLength;
+             m_timer->cancel( );
+-            
++
+             if ( error )
+             {
+                 m_is_open = false;
+             }
+-            
++
+             return length;
+         }
+         
+-- 
+2.14.3
+
diff --git a/contrib/src/restbed/cmake-uwp.patch b/contrib/src/restbed/cmake-uwp.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d272c155724efb9a4d01460433cb31aba75222c3
--- /dev/null
+++ b/contrib/src/restbed/cmake-uwp.patch
@@ -0,0 +1,20 @@
+--- a/cmake/configuration.cmake
++++ b/cmake/configuration.cmake
+@@ -37,13 +37,7 @@ elseif( ${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC )
+     if ( ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 19.00.23026.0 )
+         message( WARNING "\nMSVC compiler version < 19.00.23026.0" )
+     endif ( )
+-    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT /std:c++latest /D_WIN32_WINNT=0x0601 /W4 /wd4068 /wd4702 /wd4996" )
+-
+-    foreach ( flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO )
+-       if ( ${flag_var} MATCHES "/MD" )
+-          string( REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}" )
+-       endif ( ${flag_var} MATCHES "/MD" )
+-    endforeach ( )
++    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MD /std:c++latest /D_WIN32_WINNT=0x0601 /W4 /wd4068 /wd4702 /wd4996" )
+ else ( )
+     message( FATAL_ERROR "Compiler not supported.")
+ endif ( )
+-- 
+2.10.2.windows.1
+
diff --git a/contrib/src/restbed/fetch_and_patch.bat b/contrib/src/restbed/fetch_and_patch.bat
index 799687830501f23446606fdaa2eac1634bb3329b..95729d6464bcf7982a9c5ab4e85832041b4f1dfb 100644
--- a/contrib/src/restbed/fetch_and_patch.bat
+++ b/contrib/src/restbed/fetch_and_patch.bat
@@ -1,66 +1,72 @@
-set BUILD=%SRC%..\build
-
-set RESTBED_VERSION=34187502642144ab9f749ab40f5cdbd8cb17a54a
-set RESTBED_URL=https://github.com/Corvusoft/restbed/archive/%RESTBED_VERSION%.tar.gz
-
-mkdir %BUILD%
-
-if %USE_CACHE%==1 (
-    copy %CACHE_DIR%\%RESTBED_VERSION%.tar.gz %cd%
-) else (
-    wget %RESTBED_URL%
-)
-
-7z -y x %RESTBED_VERSION%.tar.gz && 7z -y x %RESTBED_VERSION%.tar -o%BUILD%
-del %RESTBED_VERSION%.tar && del %RESTBED_VERSION%.tar.gz && del %BUILD%\pax_global_header
-rename %BUILD%\restbed-%RESTBED_VERSION% restbed
-
-rmdir /s /q %BUILD%\restbed\dependency
-mkdir %BUILD%\restbed\dependency
-cd %BUILD%\restbed\dependency
-
-set ASIO_VERSION=276846097ab5073b67e772dbdfa12596224a54a5
-set ASIO_URL=https://github.com/Corvusoft/asio-dependency/archive/%ASIO_VERSION%.tar.gz
-
-if %USE_CACHE%==1 (
-    copy %CACHE_DIR%\%ASIO_VERSION%.tar.gz %cd%
-) else (
-    wget %ASIO_URL%
-)
-
-7z -y x %ASIO_VERSION%.tar.gz && 7z -y x %ASIO_VERSION%.tar
-del %ASIO_VERSION%.tar && del %ASIO_VERSION%.tar.gz && del pax_global_header
-rename asio-dependency-%ASIO_VERSION% asio
-
-cd asio
-git apply --reject --whitespace=fix %SRC%\restbed\asio-uwp.patch
-
-cd ..
-
-set CATCH_VERSION=35f510545d55a831372d3113747bf1314ff4f2ef
-set CATCH_URL=https://github.com/Corvusoft/catch-dependency/archive/%CATCH_VERSION%.tar.gz
-
-if %USE_CACHE%==1 (
-    copy %CACHE_DIR%\%CATCH_VERSION%.tar.gz %cd%
-) else (
-    wget %CATCH_URL%
-)
-
-7z -y x %CATCH_VERSION%.tar.gz && 7z -y x %CATCH_VERSION%.tar
-del %CATCH_VERSION%.tar && del %CATCH_VERSION%.tar.gz && del pax_global_header
-rename catch-dependency-%CATCH_VERSION% catch
-
-set OPENSSL_VERSION=c7ba244789ce9f9b6675ff88e61dd5d5e5cac53e
-set OPENSSL_URL=https://github.com/Microsoft/openssl/archive/%OPENSSL_VERSION%.tar.gz
-
-if %USE_CACHE%==1 (
-    copy %CACHE_DIR%\%OPENSSL_VERSION%.tar.gz %cd%
-) else (
-    wget %OPENSSL_URL%
-)
-
-7z -y x %OPENSSL_VERSION%.tar.gz && 7z -y x %OPENSSL_VERSION%.tar
-del %OPENSSL_VERSION%.tar && del %OPENSSL_VERSION%.tar.gz && del pax_global_header
-rename openssl-%OPENSSL_VERSION% openssl
-
+set BUILD=%SRC%..\build
+
+set RESTBED_VERSION=df867a858dddc4cf6ca8642da02720bd65ba239a
+set RESTBED_URL=https://github.com/Corvusoft/restbed/archive/%RESTBED_VERSION%.tar.gz
+
+mkdir %BUILD%
+
+if %USE_CACHE%==1 (
+    copy %CACHE_DIR%\%RESTBED_VERSION%.tar.gz %cd%
+) else (
+    wget %RESTBED_URL%
+)
+
+7z -y x %RESTBED_VERSION%.tar.gz && 7z -y x %RESTBED_VERSION%.tar -o%BUILD%
+del %RESTBED_VERSION%.tar && del %RESTBED_VERSION%.tar.gz && del %BUILD%\pax_global_header
+rename %BUILD%\restbed-%RESTBED_VERSION% restbed
+
+cd %BUILD%\restbed
+git apply --reject --whitespace=fix %SRC%\restbed\async_read_until-uwp.patch
+git apply --reject --whitespace=fix %SRC%\restbed\cmake-uwp.patch
+
+cd ..
+
+rmdir /s /q %BUILD%\restbed\dependency
+mkdir %BUILD%\restbed\dependency
+cd %BUILD%\restbed\dependency
+
+set ASIO_VERSION=276846097ab5073b67e772dbdfa12596224a54a5
+set ASIO_URL=https://github.com/Corvusoft/asio-dependency/archive/%ASIO_VERSION%.tar.gz
+
+if %USE_CACHE%==1 (
+    copy %CACHE_DIR%\%ASIO_VERSION%.tar.gz %cd%
+) else (
+    wget %ASIO_URL%
+)
+
+7z -y x %ASIO_VERSION%.tar.gz && 7z -y x %ASIO_VERSION%.tar
+del %ASIO_VERSION%.tar && del %ASIO_VERSION%.tar.gz && del pax_global_header
+rename asio-dependency-%ASIO_VERSION% asio
+
+cd asio
+git apply --reject --whitespace=fix %SRC%\restbed\asio-uwp.patch
+
+cd ..
+
+set CATCH_VERSION=35f510545d55a831372d3113747bf1314ff4f2ef
+set CATCH_URL=https://github.com/Corvusoft/catch-dependency/archive/%CATCH_VERSION%.tar.gz
+
+if %USE_CACHE%==1 (
+    copy %CACHE_DIR%\%CATCH_VERSION%.tar.gz %cd%
+) else (
+    wget %CATCH_URL%
+)
+
+7z -y x %CATCH_VERSION%.tar.gz && 7z -y x %CATCH_VERSION%.tar
+del %CATCH_VERSION%.tar && del %CATCH_VERSION%.tar.gz && del pax_global_header
+rename catch-dependency-%CATCH_VERSION% catch
+
+set KASHMIR_VERSION=2f3913f49c4ac7f9bff9224db5178f6f8f0ff3ee
+set KASHMIR_URL=https://github.com/corvusoft/kashmir-dependency/archive/%KASHMIR_VERSION%.tar.gz
+
+if %USE_CACHE%==1 (
+    copy %CACHE_DIR%\%KASHMIR_VERSION%.tar.gz %cd%
+) else (
+    wget %KASHMIR_URL%
+)
+
+7z -y x %KASHMIR_VERSION%.tar.gz && 7z -y x %KASHMIR_VERSION%.tar
+del %KASHMIR_VERSION%.tar && del %KASHMIR_VERSION%.tar.gz && del pax_global_header
+rename kashmir-dependency-%KASHMIR_VERSION% kashmir
+
 cd %SRC%
\ No newline at end of file
diff --git a/contrib/src/restbed/rules.mak b/contrib/src/restbed/rules.mak
index ac48aea3f6562e505e8fb0ecd4765ffe6b8d20a9..adf2c033a468d9f5264e8b3e2c9e60a30e43d5cd 100644
--- a/contrib/src/restbed/rules.mak
+++ b/contrib/src/restbed/rules.mak
@@ -19,8 +19,8 @@
 #  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 #
 
-RESTBED_VERSION := 4.6
-RESTBED_URL := https://github.com/Corvusoft/restbed/archive/$(RESTBED_VERSION).tar.gz
+RESTBED_VERSION := df867a858dddc4cf6ca8642da02720bd65ba239a
+RESTBED_URL := https://github.com/corvusoft//restbed/archive/$(RESTBED_VERSION).tar.gz
 
 PKGS += restbed
 
@@ -49,7 +49,7 @@ restbed: restbed-$(RESTBED_VERSION).tar.gz kashmir.tar.gz .sum-restbed
 	mv kashmir-dependency-master $(UNPACK_DIR)/dependency/kashmir
 	$(APPLY) $(SRC)/restbed/findkashmir.patch
 	$(APPLY) $(SRC)/restbed/strand.patch
-	$(APPLY) $(SRC)/restbed/locale-fix.patch
+	$(APPLY) $(SRC)/restbed/async_read_until.patch
 	$(MOVE)
 
 .restbed: restbed toolchain.cmake
diff --git a/contrib/src/restbed/strand.patch b/contrib/src/restbed/strand.patch
index 1ef4c55c35c4fb1ea18e526aff0d671a2a6a5006..84ed5ff90898b1880f809a8ead2b0571735a90b9 100644
--- a/contrib/src/restbed/strand.patch
+++ b/contrib/src/restbed/strand.patch
@@ -1,8 +1,24 @@
---- a/source/corvusoft/restbed/detail/socket_impl.hpp	2016-09-28 12:01:30.415787179 -0400
---- a/source/corvusoft/restbed/detail/socket_impl.hpp	2016-09-28 12:01:33.329120391 -0400
-@@ -23,3 +23,3 @@
+From a330edb28151830aeaf08a71e42cb6618c25ef2f Mon Sep 17 00:00:00 2001
+From: Sébastien Blin <sebastiem.blin@savoirfairelinux.fr>
+Date: Tue, 5 Dec 2017 10:31:21 -0600
+Subject: [PATCH]update strand header for asio
+
+---
+ source/corvusoft/restbed/detail/socket_impl.hpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/source/corvusoft/restbed/detail/socket_impl.hpp b/source/corvusoft/restbed/detail/socket_impl.hpp
+index b10c3f7..02df572 100644
+--- a/source/corvusoft/restbed/detail/socket_impl.hpp
++++ b/source/corvusoft/restbed/detail/socket_impl.hpp
+@@ -23,7 +23,7 @@
+ #include <asio/streambuf.hpp>
+ #include <asio/steady_timer.hpp>
  #include <asio/io_service.hpp>
 -#include <asio/io_service_strand.hpp>
 +#include <asio/strand.hpp>
- 
 
+ #ifdef BUILD_SSL
+     #include <asio/ssl.hpp>
+--
+2.14.3
diff --git a/m4/dolt.m4 b/m4/dolt.m4
index 326b6a8251b4d4611d7d3ae38dab8d3123cbe6f1..78b3cff537b9d709858a8930b1f7c012fff88aa9 100644
--- a/m4/dolt.m4
+++ b/m4/dolt.m4
@@ -164,10 +164,14 @@ for arg in "$[]@"; do
         *) args@<:@${#args[@]}@:>@="$arg" ;;
     esac
 done
+
+dnl enable opendht proxy
+dhtproxy_variables="-DOPENDHT_PROXY_CLIENT=true -DOPENDHT_PROXY_SERVER=true -DOPENDHT_PUSH_NOTIFICATIONS=true"
+
 if $modeok && $tagok ; then
-    . ${top_builddir_slash}doltcompile "${args@<:@@@:>@}"
+    . ${top_builddir_slash}doltcompile "${args@<:@@@:>@}" ${dhtproxy_variables}
 else
-    exec ${top_builddir_slash}libtool "$[]@"
+    exec ${top_builddir_slash}libtool "$[]@" $(proxydht_variables) ${dhtproxy_variables}
 fi
 __DOLTLIBTOOL__EOF__
 
diff --git a/src/account.cpp b/src/account.cpp
index d4b0b31ab22c09a1ea2b01738612dc26206689d7..51c1f284086c98d8fc2e6c0d898bcf03b0700306 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -41,6 +41,7 @@ using random_device = dht::crypto::random_device;
 
 #include "client/ring_signal.h"
 #include "account_schema.h"
+#include "dring/account_const.h"
 #include "string_utils.h"
 #include "fileutils.h"
 #include "config/yamlparser.h"
@@ -84,6 +85,9 @@ const char * const Account::USER_AGENT_KEY                = "useragent";
 const char * const Account::HAS_CUSTOM_USER_AGENT_KEY     = "hasCustomUserAgent";
 const char * const Account::PRESENCE_MODULE_ENABLED_KEY   = "presenceModuleEnabled";
 const char * const Account::UPNP_ENABLED_KEY              = "upnpEnabled";
+const char * const Account::PROXY_ENABLED_KEY             = "proxyEnabled";
+const char * const Account::PROXY_SERVER_KEY              = "proxyServer";
+const char * const Account::PROXY_PUSH_TOKEN_KEY          = "proxyPushToken";
 
 Account::Account(const std::string &accountID)
     : accountID_(accountID)
@@ -100,6 +104,9 @@ Account::Account(const std::string &accountID)
     , displayName_("")
     , userAgent_(DEFAULT_USER_AGENT)
     , hasCustomUserAgent_(false)
+    , proxyEnabled_(false)
+    , proxyServer_("")
+    , deviceKey_("")
     , mailBox_()
 {
     random_device rdev;
@@ -227,6 +234,9 @@ Account::serialize(YAML::Emitter& out)
     out << YAML::Key << DISPLAY_NAME_KEY << YAML::Value << displayName_;
     out << YAML::Key << HOSTNAME_KEY << YAML::Value << hostname_;
     out << YAML::Key << UPNP_ENABLED_KEY << YAML::Value << bool(upnp_);
+    out << YAML::Key << PROXY_ENABLED_KEY << YAML::Value << proxyEnabled_;
+    out << YAML::Key << PROXY_SERVER_KEY << YAML::Value << proxyServer_;
+    out << YAML::Key << PROXY_PUSH_TOKEN_KEY << YAML::Value << deviceKey_;
 }
 
 void
@@ -257,6 +267,10 @@ Account::unserialize(const YAML::Node& node)
     bool enabled;
     parseValue(node, UPNP_ENABLED_KEY, enabled);
     enableUpnp(enabled);
+
+    parseValue(node, PROXY_ENABLED_KEY, proxyEnabled_);
+    parseValue(node, PROXY_SERVER_KEY, proxyServer_);
+    parseValue(node, PROXY_PUSH_TOKEN_KEY, deviceKey_);
 }
 
 void
@@ -281,6 +295,9 @@ Account::setAccountDetails(const std::map<std::string, std::string> &details)
     bool enabled;
     parseBool(details, Conf::CONFIG_UPNP_ENABLED, enabled);
     enableUpnp(enabled);
+    parseBool(details, DRing::Account::ConfProperties::PROXY_ENABLED, proxyEnabled_);
+    parseString(details, DRing::Account::ConfProperties::PROXY_SERVER, proxyServer_);
+    parseString(details, DRing::Account::ConfProperties::PROXY_PUSH_TOKEN, deviceKey_);
 }
 
 std::map<std::string, std::string>
@@ -301,6 +318,9 @@ Account::getAccountDetails() const
         {Conf::CONFIG_RINGTONE_ENABLED,     ringtoneEnabled_ ? TRUE_STR : FALSE_STR},
         {Conf::CONFIG_RINGTONE_PATH,        ringtonePath_},
         {Conf::CONFIG_UPNP_ENABLED,         upnp_ ? TRUE_STR : FALSE_STR},
+        {DRing::Account::ConfProperties::PROXY_ENABLED,        proxyEnabled_ ? TRUE_STR : FALSE_STR},
+        {DRing::Account::ConfProperties::PROXY_SERVER,         proxyServer_},
+        {DRing::Account::ConfProperties::PROXY_PUSH_TOKEN,     deviceKey_},
     };
 }
 
diff --git a/src/account.h b/src/account.h
index 965f6b877dee7889e8a8e77f60041d6874d61fea..dac434907a5abf671b6eae62366335c29fed7335 100644
--- a/src/account.h
+++ b/src/account.h
@@ -365,6 +365,9 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
         static const char * const DEFAULT_USER_AGENT;
         static const char * const PRESENCE_MODULE_ENABLED_KEY;
         static const char * const UPNP_ENABLED_KEY;
+        static const char * const PROXY_ENABLED_KEY;
+        static const char * const PROXY_SERVER_KEY;
+        static const char * const PROXY_PUSH_TOKEN_KEY;
 
         static std::string mapStateNumberToString(RegistrationState state);
 
@@ -469,6 +472,13 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
         std::unique_ptr<ring::upnp::Controller> upnp_;
         mutable std::mutex upnp_mtx {};
 
+        /**
+         * Proxy
+         */
+        bool proxyEnabled_;
+        std::string proxyServer_;
+        std::string deviceKey_;
+
         /**
          * private account codec searching functions
          */
diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp
index 9db4f051d7bd3121fa16343a496d82e848561722..0020ce4440d2904f06009959f5b57df4bafbe262 100644
--- a/src/client/configurationmanager.cpp
+++ b/src/client/configurationmanager.cpp
@@ -923,4 +923,26 @@ bool registerName(const std::string& account, const std::string& password, const
     return false;
 }
 
+void enableProxyClient(const std::string& accountID, bool enable)
+{
+    if (auto account = ring::Manager::instance().getAccount<ring::RingAccount>(accountID))
+        account->enableProxyClient(enable);
+}
+
+void setPushNotificationToken(const std::string& token)
+{
+    for (const auto &account : ring::Manager::instance().getAllAccounts<RingAccount>())
+        account->setPushNotificationToken(token);
+}
+
+void pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data)
+{
+    try {
+        if (auto account = ring::Manager::instance().getAccount<ring::RingAccount>(data.at("to")))
+            account->pushNotificationReceived(from, data);
+    } catch (const std::exception& e) {
+        RING_ERR("Error processing push notification: %s", e.what());
+    }
+}
+
 } // namespace DRing
diff --git a/src/dring/account_const.h b/src/dring/account_const.h
index 38325a01b63ecfd02f8f825c2c8e90078fd16c0a..1dbb87cba1bf18c12ee62ae97bb93cba54d2d3b5 100644
--- a/src/dring/account_const.h
+++ b/src/dring/account_const.h
@@ -135,6 +135,9 @@ constexpr static const char ARCHIVE_PATH            [] = "Account.archivePath";
 constexpr static const char ARCHIVE_PIN             [] = "Account.archivePIN";
 constexpr static const char RING_DEVICE_ID          [] = "Account.deviceID";
 constexpr static const char RING_DEVICE_NAME        [] = "Account.deviceName";
+constexpr static const char PROXY_ENABLED           [] = "Account.proxyEnabled";
+constexpr static const char PROXY_SERVER            [] = "Account.proxyServer";
+constexpr static const char PROXY_PUSH_TOKEN        [] = "Account.proxyPushToken";
 
 namespace Audio {
 
diff --git a/src/dring/configurationmanager_interface.h b/src/dring/configurationmanager_interface.h
index 372e0dff8ef48d0455c8adad4d7050fa7b4ad0c1..3021b74e3915c7947daf9cf8e42e2da0c1754136 100644
--- a/src/dring/configurationmanager_interface.h
+++ b/src/dring/configurationmanager_interface.h
@@ -181,6 +181,25 @@ int importAccounts(std::string archivePath, std::string password);
  */
 void connectivityChanged();
 
+/* Dht proxy */
+
+/**
+ * Start or stop to use the proxy for account
+ */
+void enableProxyClient(const std::string& accountID, bool enable);
+
+/**
+ * Set the device push notification token (for all accounts).
+ * If set, proxy clients will use push notifications.
+ * Set to empty to disable push notifications.
+ */
+void setPushNotificationToken(const std::string& pushDeviceToken);
+
+/**
+ * To be called by clients with relevent data when a push notification is received.
+ */
+void pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data);
+
 struct AudioSignal {
         struct DeviceEvent {
                 constexpr static const char* name = "audioDeviceEvent";
diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index cca347c314648bee4307f48e3cfdff451924f260..c928a23f3b3a1cc076b3e289ca99d5fa7d4755f5 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -1854,7 +1854,6 @@ RingAccount::doRegister()
         }}.detach();
     } else
         doRegister_();
-
 }
 
 
@@ -2042,7 +2041,18 @@ RingAccount::doRegister_()
             setRegistrationState(state);
         });
 
-        dht_.run((in_port_t)dhtPortUsed_, identity_, false);
+        dht::DhtRunner::Config config {};
+        config.dht_config.node_config.network = 0;
+        config.dht_config.id = identity_;
+        config.proxy_server = proxyEnabled_ ? proxyServer_ : std::string();
+        config.push_node_id = getAccountID();
+        config.threaded = false;
+        RING_WARN("[Account %s] using proxy server %s", getAccountID().c_str(), config.proxy_server.c_str());
+
+        if (not deviceKey_.empty())
+            dht_.setPushNotificationToken(deviceKey_);
+
+        dht_.run((in_port_t)dhtPortUsed_, config);
 
         dht_.setLocalCertificateStore([](const dht::InfoHash& pk_id) {
             std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
@@ -2455,7 +2465,7 @@ RingAccount::doUnregister(std::function<void(bool)> released_cb)
         return;
     }
 
-    RING_WARN("[Account %s] unregistering account", getAccountID().c_str());
+    RING_WARN("[Account %s] unregistering account %p", getAccountID().c_str(), this);
     {
         std::lock_guard<std::mutex> lock(callsMutex_);
         pendingCalls_.clear();
@@ -3344,4 +3354,28 @@ RingAccount::requestPeerConnection(const std::string& peer_id,
     dhtPeerConnector_->requestConnection(peer_id, connect_cb);
 }
 
+void
+RingAccount::enableProxyClient(bool enable)
+{
+    RING_WARN("[Account %s] DHT proxy client: %s", getAccountID().c_str(), enable ? "enable" : "disable");
+    dht_.enableProxy(enable);
+}
+
+void RingAccount::setPushNotificationToken(const std::string& token)
+{
+    RING_WARN("[Account %s] setPushNotificationToken: %s", getAccountID().c_str(), token.c_str());
+    deviceKey_ = token;
+    dht_.setPushNotificationToken(deviceKey_);
+}
+
+/**
+ * To be called by clients with relevent data when a push notification is received.
+ */
+void RingAccount::pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data)
+{
+    RING_WARN("[Account %s] pushNotificationReceived: %s", getAccountID().c_str(), from.c_str());
+    dht_.pushNotificationReceived(data);
+}
+
+
 } // namespace ring
diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h
index b704f6e54297d07640e4063b387a4884434d169b..86e7991a8845666db9c7f701505729f9ec15ddb2 100644
--- a/src/ringdht/ringaccount.h
+++ b/src/ringdht/ringaccount.h
@@ -349,6 +349,20 @@ class RingAccount : public SIPAccountBase {
          */
         static bool foundPeerDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, dht::InfoHash& account_id);
 
+        /**
+         * Start or stop to use the proxy client
+         * @param address of the proxy
+         * @param deviceKey the device key for push notifications (empty to not use it)
+         */
+        void enableProxyClient(bool enable);
+
+        void setPushNotificationToken(const std::string& pushDeviceToken = "");
+
+        /**
+         * To be called by clients with relevent data when a push notification is received.
+         */
+        void pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data);
+
     private:
         NON_COPYABLE(RingAccount);