diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index d63a2ecc4b44e2e71ab1a6e7a724835467c5c09d..70e47aa76c6a7599491d935cf94a4f2e1392f9ac 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -1719,7 +1719,7 @@ RingAccount::doRegister_()
             dht_.put(h, announce_, dht::DoneCallback{}, {}, true);
             dht_.listen<DeviceAnnouncement>(h, [shared](DeviceAnnouncement&& dev) {
                 shared->findCertificate(dev.dev, [shared](const std::shared_ptr<dht::crypto::Certificate> crt) {
-                    shared->foundAccountDevice(crt);
+                    shared->foundKnownDevice(crt);
                 });
                 return true;
             });
@@ -1739,16 +1739,44 @@ RingAccount::doRegister_()
                 if (msg.from == this_.dht_.getId())
                     return true;
 
+                RING_WARN("ICE candidate from %s.", msg.from.toString().c_str());
+
+                // quick check in case we already explicilty banned this public key
+                auto trustStatus = this_.trust_.getCertificateStatus(msg.from.toString());
+                if (trustStatus == tls::TrustStore::PermissionStatus::BANNED) {
+                    RING_WARN("Discarding incoming DHT call request from banned peer %s", msg.from.toString().c_str());
+                    return true;
+                }
+
                 auto res = this_.treatedCalls_.insert(msg.id);
                 this_.saveTreatedCalls();
                 if (!res.second)
                     return true;
 
-                RING_WARN("ICE candidate from %s.", msg.from.toString().c_str());
+                this_.findCertificate( msg.from,
+                    [shared, msg, trustStatus](const std::shared_ptr<dht::crypto::Certificate> cert) mutable {
+                    auto& this_ = *shared;
+                    if (not this_.dhtPublicInCalls_ and trustStatus != tls::TrustStore::PermissionStatus::ALLOWED) {
+                        if (!cert or cert->getId() != msg.from) {
+                            RING_WARN("Can't find certificate of %s for incoming call.",
+                                      msg.from.toString().c_str());
+                            return;
+                        }
+
+                        tls::CertificateStore::instance().pinCertificate(cert);
 
-                this_.onPeerMessage(msg.from, [shared, msg](const std::shared_ptr<dht::crypto::Certificate>& cert,
-                                                            const dht::InfoHash& /*account*/) mutable
-                {
+                        auto& this_ = *shared;
+                        if (!this_.trust_.isAllowed(*cert)) {
+                            RING_WARN("Discarding incoming DHT call from untrusted peer %s.",
+                                      msg.from.toString().c_str());
+                            return;
+                        }
+                    } else if (not this_.dhtPublicInCalls_
+                               or trustStatus == tls::TrustStore::PermissionStatus::BANNED) {
+                        return;
+                    }
+
+                    // Peer certificate trusted... go ahead
                     shared->incomingCall(std::move(msg), cert);
                 });
                 return true;
@@ -1799,7 +1827,7 @@ RingAccount::doRegister_()
                         RING_WARN("Can't find certificate for device %s", sync.from.toString().c_str());
                         return;
                     }
-                    if (not shared->foundAccountDevice(cert))
+                    if (not shared->foundKnownDevice(cert))
                         return;
                     shared->onReceiveDeviceSync(std::move(sync));
                 });
@@ -1817,15 +1845,43 @@ RingAccount::doRegister_()
                 if (!res.second)
                     return true;
                 this_.saveTreatedMessages();
-                this_.onPeerMessage(v.from, [shared, v, inboxDeviceKey](const std::shared_ptr<dht::crypto::Certificate>&,
-                                                                        const dht::InfoHash& peer_account)
-                {
+
+                // quick check in case we already explicilty banned this public key
+                auto trustStatus = this_.trust_.getCertificateStatus(v.from.toString());
+                if (trustStatus == tls::TrustStore::PermissionStatus::BANNED) {
+                    RING_WARN("Discarding incoming DHT message from banned peer %s", v.from.toString().c_str());
+                    return true;
+                }
+
+                this_.findCertificate( v.from,
+                    [shared, v, trustStatus, inboxDeviceKey](const std::shared_ptr<dht::crypto::Certificate> cert) mutable {
+                    auto& this_ = *shared;
+                    if (not this_.dhtPublicInCalls_ and trustStatus != tls::TrustStore::PermissionStatus::ALLOWED) {
+                        if (!cert or cert->getId() != v.from) {
+                            RING_WARN("Can't find certificate of %s for incoming message.", v.from.toString().c_str());
+                            return;
+                        }
+
+                        tls::CertificateStore::instance().pinCertificate(cert);
+
+                        auto& this_ = *shared;
+                        if (!this_.trust_.isAllowed(*cert)) {
+                            RING_WARN("Discarding incoming DHT message from untrusted peer %s.", v.from.toString().c_str());
+                            return;
+                        }
+                    } else if (not this_.dhtPublicInCalls_ or trustStatus == tls::TrustStore::PermissionStatus::BANNED) {
+                        RING_WARN("Discarding incoming DHT message from untrusted or banned peer %s.", v.from.toString().c_str());
+                        return;
+                    }
+
+                    auto from_acc_id = cert ? (cert->issuer ? cert->issuer->getId().toString() : cert->getId().toString()) : v.from.toString();
+
                     auto now = system_clock::to_time_t(system_clock::now());
                     std::map<std::string, std::string> payloads = {{"text/plain",
                                                                     utf8_make_valid(v.msg)}};
-                    shared->onTextMessage(peer_account.toString(), payloads);
+                    shared->onTextMessage(from_acc_id, payloads);
                     RING_DBG("Sending message confirmation %" PRIu64, v.id);
-                    shared->dht_.putEncrypted(inboxDeviceKey,
+                    this_.dht_.putEncrypted(inboxDeviceKey,
                               v.from,
                               dht::ImMessage(v.id, std::string(), now));
                 });
@@ -1839,52 +1895,12 @@ RingAccount::doRegister_()
     }
 }
 
-
-void
-RingAccount::onPeerMessage(const dht::InfoHash& peer_device, std::function<void(const std::shared_ptr<dht::crypto::Certificate>& crt, const dht::InfoHash& peer_account)> cb)
-{
-    // quick check in case we already explicilty banned this public key
-    auto trustStatus = trust_.getCertificateStatus(peer_device.toString());
-    if (trustStatus == tls::TrustStore::PermissionStatus::BANNED) {
-        RING_WARN("Discarding message from banned peer %s", peer_device.toString().c_str());
-        return;
-    }
-
-    auto shared = std::static_pointer_cast<RingAccount>(shared_from_this());
-    findCertificate(peer_device,
-        [shared, peer_device, trustStatus, cb](const std::shared_ptr<dht::crypto::Certificate>& cert) {
-        auto& this_ = *shared;
-
-        dht::InfoHash peer_account_id;
-        if (not this_.foundPeerDevice(cert, peer_account_id)) {
-            RING_WARN("Discarding message from invalid peer certificate %s.", peer_device.toString().c_str());
-            return;
-        }
-
-        if (not this_.dhtPublicInCalls_ and trustStatus != tls::TrustStore::PermissionStatus::ALLOWED) {
-            if (!cert or cert->getId() != peer_device) {
-                RING_WARN("Can't find certificate of %s for incoming message.", peer_device.toString().c_str());
-                return;
-            }
-
-            auto& this_ = *shared;
-            if (!this_.trust_.isAllowed(*cert)) {
-                RING_WARN("Discarding message from untrusted peer %s.", peer_device.toString().c_str());
-                return;
-            }
-        } else if (not this_.dhtPublicInCalls_ or trustStatus == tls::TrustStore::PermissionStatus::BANNED) {
-            RING_WARN("Discarding message from untrusted or banned peer %s.", peer_device.toString().c_str());
-            return;
-        }
-
-        cb(cert, peer_account_id);
-    });
-}
-
 void
 RingAccount::incomingCall(dht::IceCandidates&& msg, std::shared_ptr<dht::crypto::Certificate> from_cert)
 {
-    RING_WARN("ICE incoming from DHT peer %s", msg.from.toString().c_str());
+    auto from = msg.from.toString();
+    RING_WARN("ICE incoming from DHT peer %s\n%s", from.c_str(),
+              std::string(msg.ice_data.cbegin(), msg.ice_data.cend()).c_str());
     auto call = Manager::instance().callFactory.newCall<SIPCall, RingAccount>(*this, Manager::instance().getNewCallID(), Call::CallType::INCOMING);
     auto ice = createIceTransport(("sip:"+call->getCallId()).c_str(), ICE_COMPONENTS, false, getIceOptions());
 
@@ -1915,7 +1931,7 @@ RingAccount::incomingCall(dht::IceCandidates&& msg, std::shared_ptr<dht::crypto:
 }
 
 bool
-RingAccount::foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, const std::string& name)
+RingAccount::foundKnownDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, const std::string& name)
 {
     if (not crt)
         return false;
@@ -1951,36 +1967,6 @@ RingAccount::foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>&
     return true;
 }
 
-bool
-RingAccount::foundPeerDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, dht::InfoHash& account_id)
-{
-    if (not crt)
-        return false;
-
-    auto top_issuer = crt;
-    while (top_issuer->issuer)
-        top_issuer = top_issuer->issuer;
-
-    // Device certificate can't be self-signed
-    if (top_issuer == crt) {
-        RING_WARN("[Account %s] Found invalid peer device: %s", getAccountID().c_str(), crt->getId().toString().c_str());
-        return false;
-    }
-
-    // Check peer certificate chain
-    // Trust store with top issuer as the only CA
-    tls::TrustStore peer_trust;
-    peer_trust.setCertificateStatus(top_issuer, tls::TrustStore::PermissionStatus::ALLOWED, false);
-
-    if (not peer_trust.isAllowed(*crt)) {
-        RING_WARN("[Account %s] Found invalid peer device: %s", getAccountID().c_str(), crt->getId().toString().c_str());
-        return false;
-    }
-
-    account_id = crt->issuer->getId();
-    return true;
-}
-
 void
 RingAccount::replyToIncomingIceMsg(std::shared_ptr<SIPCall> call,
                                   std::shared_ptr<IceTransport> ice,
@@ -2539,7 +2525,7 @@ RingAccount::onReceiveDeviceSync(DeviceSync&& sync)
         findCertificate(d.first, [shared,d](const std::shared_ptr<dht::crypto::Certificate> crt) {
             if (not crt)
                 return;
-            shared->foundAccountDevice(crt, d.second);
+            shared->foundKnownDevice(crt, d.second);
         });
     }
     it->second.last_sync = sync_date;
diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h
index 37390e139a62979ffa0fac0d6206a642907eac20..6eb828d15784de6695b7048fa59a7b31c749fd76 100644
--- a/src/ringdht/ringaccount.h
+++ b/src/ringdht/ringaccount.h
@@ -343,26 +343,7 @@ class RingAccount : public SIPAccountBase {
          */
         bool SIPStartCall(const std::shared_ptr<SIPCall>& call, IpAddr target);
 
-        /**
-         * Inform that a potential account device have been found.
-         * Returns true if the device have been validated to be part of this account
-         */
-        bool foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, const std::string& name = {});
-
-        /**
-         * Inform that a potential peer device have been found.
-         * Returns true only if the device certificate is a valid Ring device certificate.
-         * In that case (true is returned) the account_id parameter is set to the peer account ID.
-         */
-        bool foundPeerDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, dht::InfoHash& account_id);
-
-        /**
-         * Check that a peer is authorised to talk to us.
-         * If everything is in order, calls the callback with the
-         * peer certificate chain (down to the peer device certificate),
-         * and the peer account id.
-         */
-        void onPeerMessage(const dht::InfoHash& peer_device, std::function<void(const std::shared_ptr<dht::crypto::Certificate>& crt, const dht::InfoHash& account_id)>);
+        bool foundKnownDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, const std::string& name = {});
 
         /**
          * Maps require port via UPnP