blob: 5a6b4b93ff6ac356e0e61bc126cbe120b3a0f52d [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013-2020, Regents of the University of California
* Yingdi Yu
*
* BSD license, See the LICENSE file for more information
*
* Author: Yingdi Yu <yingdi@cs.ucla.edu>
* Qiuhan Ding <qiuhanding@cs.ucla.edu>
*/
#include "contact-manager.hpp"
#include <QStringList>
#include <QFile>
#ifndef Q_MOC_RUN
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>
#include <ndn-cxx/security/transform/buffer-source.hpp>
#include <ndn-cxx/security/transform/digest-filter.hpp>
#include <ndn-cxx/security/transform/stream-sink.hpp>
#include <ndn-cxx/security/validator.hpp>
#include <ndn-cxx/security/validator-null.hpp>
#include <ndn-cxx/security/verification-helpers.hpp>
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/tokenizer.hpp>
#endif
namespace fs = boost::filesystem;
namespace chronochat {
using std::string;
using std::map;
using std::vector;
using ndn::Face;
using ndn::OBufferStream;
using ndn::security::Certificate;
ContactManager::ContactManager(Face& face,
QObject* parent)
: QObject(parent)
, m_face(face)
{
initializeSecurity();
}
ContactManager::~ContactManager()
{
}
void
ContactManager::initializeSecurity()
{
m_validator = make_shared<ndn::security::ValidatorConfig>(m_face);
m_validator->load("security/validation-contact-manager.conf");
}
void
ContactManager::fetchCollectEndorse(const Name& identity)
{
Name interestName = identity;
interestName.append("DNS").append("ENDORSED");
Interest interest(interestName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setCanBePrefix(true);
interest.setMustBeFresh(true);
ndn::security::DataValidationSuccessCallback onValidated =
bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
ndn::security::DataValidationFailureCallback onValidationFailed =
bind(&ContactManager::onDnsCollectEndorseValidationFailed, this, _1, _2, identity);
TimeoutNotify timeoutNotify =
bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, _1, identity);
sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}
void
ContactManager::fetchEndorseCertificateInternal(const Name& identity, size_t certIndex)
{
auto endorseCollection = m_bufferedContacts[identity].m_endorseCollection;
if (certIndex >= endorseCollection->getCollectionEntries().size())
return prepareEndorseInfo(identity);
Name interestName(endorseCollection->getCollectionEntries()[certIndex].certName);
Interest interest(interestName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setCanBePrefix(true);
interest.setMustBeFresh(false);
m_face.expressInterest(interest,
bind(&ContactManager::onEndorseCertificateInternal,
this, _1, _2, identity, certIndex,
endorseCollection->getCollectionEntries()[certIndex].hash),
bind(&ContactManager::onEndorseCertificateInternalTimeout,
this, _1, identity, certIndex),
bind(&ContactManager::onEndorseCertificateInternalTimeout,
this, _1, identity, certIndex));
}
void
ContactManager::prepareEndorseInfo(const Name& identity)
{
const Profile& profile = m_bufferedContacts[identity].m_selfEndorseCert->getProfile();
shared_ptr<EndorseInfo> endorseInfo = make_shared<EndorseInfo>();
m_bufferedContacts[identity].m_endorseInfo = endorseInfo;
map<string, size_t> endorseCount;
for (auto pIt = profile.begin(); pIt != profile.end(); pIt++)
endorseCount[pIt->first] = 0;
size_t endorseCertCount = 0;
auto cIt = m_bufferedContacts[identity].m_endorseCertList.cbegin();
auto cEnd = m_bufferedContacts[identity].m_endorseCertList.cend();
for (; cIt != cEnd; cIt++, endorseCertCount++) {
shared_ptr<Contact> contact = getContact((*cIt)->getSigner());
if (!static_cast<bool>(contact))
continue;
if (!contact->isIntroducer() ||
!contact->canBeTrustedFor(profile.getIdentityName()))
continue;
if (!(*cIt)->isValid())
continue;
if (!ndn::security::verifySignature(**cIt, contact->getPublicKey().data(), contact->getPublicKey().size()))
continue;
const Profile& tmpProfile = (*cIt)->getProfile();
const auto& endorseList = (*cIt)->getEndorseList();
for (auto eIt = endorseList.begin(); eIt != endorseList.end(); eIt++)
if (tmpProfile.get(*eIt) == profile.get(*eIt))
endorseCount[*eIt] += 1;
}
for (auto pIt = profile.begin(); pIt != profile.end(); pIt++) {
std::stringstream ss;
ss << endorseCount[pIt->first] << "/" << endorseCertCount;
endorseInfo->addEndorsement(pIt->first, pIt->second, ss.str());
}
emit contactEndorseInfoReady (*endorseInfo);
}
void
ContactManager::onDnsSelfEndorseCertValidated(const Data& data,
const Name& identity)
{
try {
Data plainData;
plainData.wireDecode(data.getContent().blockFromValue());
shared_ptr<EndorseCertificate> selfEndorseCertificate =
make_shared<EndorseCertificate>(boost::cref(plainData));
if (ndn::security::verifySignature(plainData, *selfEndorseCertificate)) {
m_bufferedContacts[identity].m_selfEndorseCert = selfEndorseCertificate;
fetchCollectEndorse(identity);
}
else
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": verification failed"));
}
catch (const Block::Error& e) {
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": block error " + e.what()));
}
catch (const EndorseCertificate::Error& e) {
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": cert error " + e.what()));
}
catch (const Data::Error& e) {
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": data error " + e.what()));
}
}
void
ContactManager::onDnsSelfEndorseCertValidationFailed(const Data& data,
const ndn::security::ValidationError& error,
const Name& identity)
{
// If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
// but let's stay with failure for now.
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}
void
ContactManager::onDnsSelfEndorseCertTimeoutNotify(const Interest& interest,
const Name& identity)
{
// If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
// but let's stay with failure for now.
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}
void
ContactManager::onDnsCollectEndorseValidated(const Data& data,
const Name& identity)
{
try {
shared_ptr<EndorseCollection> endorseCollection =
make_shared<EndorseCollection>(data.getContent().blockFromValue());
m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
fetchEndorseCertificateInternal(identity, 0);
}
catch (const std::runtime_error&) {
prepareEndorseInfo(identity);
}
}
void
ContactManager::onDnsCollectEndorseValidationFailed(const Data& data,
const ndn::security::ValidationError& error,
const Name& identity)
{
prepareEndorseInfo(identity);
}
void
ContactManager::onDnsCollectEndorseTimeoutNotify(const Interest& interest, const Name& identity)
{
prepareEndorseInfo(identity);
}
void
ContactManager::onEndorseCertificateInternal(const Interest&, const Data& data,
const Name& identity, size_t certIndex, string hash)
{
std::ostringstream ss;
{
using namespace ndn::security::transform;
bufferSource(data.wireEncode().wire(), data.wireEncode().size())
>> digestFilter(ndn::DigestAlgorithm::SHA256)
>> streamSink(ss);
}
if (ss.str() == hash) {
auto endorseCertificate = make_shared<EndorseCertificate>(data);
m_bufferedContacts[identity].m_endorseCertList.push_back(std::move(endorseCertificate));
}
fetchEndorseCertificateInternal(identity, certIndex+1);
}
void
ContactManager::onEndorseCertificateInternalTimeout(const Interest& interest,
const Name& identity,
size_t certIndex)
{
fetchEndorseCertificateInternal(identity, certIndex+1);
}
void
ContactManager::collectEndorsement()
{
{
boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
m_collectCount = m_contactList.size();
for (auto it = m_contactList.begin(); it != m_contactList.end(); it++) {
Name interestName = (*it)->getNameSpace();
interestName.append("DNS").append(m_identity.wireEncode()).append("ENDORSEE");
Interest interest(interestName);
interest.setMustBeFresh(true);
interest.setCanBePrefix(true);
interest.setInterestLifetime(time::milliseconds(1000));
ndn::security::DataValidationSuccessCallback onValidated =
bind(&ContactManager::onDnsEndorseeValidated, this, _1);
ndn::security::DataValidationFailureCallback onValidationFailed =
bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1, _2);
TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);
sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}
}
}
void
ContactManager::onDnsEndorseeValidated(const Data& data)
{
Data endorseData;
endorseData.wireDecode(data.getContent().blockFromValue());
EndorseCertificate endorseCertificate(endorseData);
m_contactStorage->updateCollectEndorse(endorseCertificate);
decreaseCollectStatus();
}
void
ContactManager::onDnsEndorseeValidationFailed(const Data& data,
const ndn::security::ValidationError& error)
{
decreaseCollectStatus();
}
void
ContactManager::onDnsEndorseeTimeoutNotify(const Interest& interest)
{
decreaseCollectStatus();
}
void
ContactManager::decreaseCollectStatus()
{
size_t count;
{
boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
m_collectCount--;
count = m_collectCount;
}
if(count == 0)
publishCollectEndorsedDataInDNS();
}
void
ContactManager::publishCollectEndorsedDataInDNS()
{
Name dnsName = m_identity;
dnsName.append("DNS").append("ENDORSED").appendVersion();
shared_ptr<Data> data = make_shared<Data>();
data->setName(dnsName);
data->setFreshnessPeriod(time::milliseconds(1000));
EndorseCollection endorseCollection;
m_contactStorage->getCollectEndorse(endorseCollection);
data->setContent(endorseCollection.wireEncode());
m_keyChain.sign(*data, ndn::security::signingByIdentity(m_identity));
m_contactStorage->updateDnsOthersEndorse(*data);
m_face.put(*data);
}
void
ContactManager::onIdentityCertValidated(const Data& data)
{
shared_ptr<Certificate> cert = make_shared<Certificate>(boost::cref(data));
m_bufferedIdCerts[cert->getName()] = cert;
decreaseIdCertCount();
}
void
ContactManager::onIdentityCertValidationFailed(const Data& data,
const ndn::security::ValidationError& error)
{
decreaseIdCertCount();
}
void
ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
{
decreaseIdCertCount();
}
void
ContactManager::decreaseIdCertCount()
{
size_t count;
{
boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
m_idCertCount--;
count = m_idCertCount;
}
if (count == 0) {
QStringList certNameList;
QStringList nameList;
for (auto it = m_bufferedIdCerts.begin(); it != m_bufferedIdCerts.end(); it++) {
certNameList << QString::fromStdString(it->second->getName().toUri());
Profile profile(*(it->second));
nameList << QString::fromStdString(profile.get("name"));
}
emit idCertNameListReady(certNameList);
emit nameListReady(nameList);
}
}
shared_ptr<EndorseCertificate>
ContactManager::getSignedSelfEndorseCertificate(const Profile& profile)
{
auto signCert = m_keyChain.getPib().getIdentity(m_identity)
.getDefaultKey().getDefaultCertificate();
vector<string> endorseList;
for (auto it = profile.begin(); it != profile.end(); it++)
endorseList.push_back(it->first);
shared_ptr<EndorseCertificate> selfEndorseCertificate =
make_shared<EndorseCertificate>(boost::cref(signCert),
boost::cref(profile),
boost::cref(endorseList));
m_keyChain.sign(*selfEndorseCertificate,
ndn::security::signingByIdentity(m_identity).setSignatureInfo(
selfEndorseCertificate->getSignatureInfo()));
return selfEndorseCertificate;
}
void
ContactManager::publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate)
{
Name dnsName = m_identity;
dnsName.append("DNS").append("PROFILE").appendVersion();
shared_ptr<Data> data = make_shared<Data>();
data->setName(dnsName);
data->setContent(selfEndorseCertificate.wireEncode());
data->setFreshnessPeriod(time::milliseconds(1000));
m_keyChain.sign(*data, ndn::security::signingByIdentity(m_identity));
m_contactStorage->updateDnsSelfProfileData(*data);
m_face.put(*data);
}
shared_ptr<EndorseCertificate>
ContactManager::generateEndorseCertificate(const Name& identity)
{
auto signCert = m_keyChain.getPib().getIdentity(m_identity)
.getDefaultKey().getDefaultCertificate();
shared_ptr<Contact> contact = getContact(identity);
if (!static_cast<bool>(contact))
return shared_ptr<EndorseCertificate>();
Name signerKeyName = m_identity;
vector<string> endorseList;
m_contactStorage->getEndorseList(identity, endorseList);
shared_ptr<EndorseCertificate> cert =
shared_ptr<EndorseCertificate>(new EndorseCertificate(contact->getPublicKeyName(),
contact->getPublicKey(),
contact->getNotBefore(),
contact->getNotAfter(),
signCert.getKeyId(),
signerKeyName,
contact->getProfile(),
endorseList));
m_keyChain.sign(*cert,
ndn::security::signingByIdentity(m_identity)
.setSignatureInfo(cert->getSignatureInfo()));
return cert;
}
void
ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate)
{
Name endorsee = endorseCertificate.getKeyName().getPrefix(-4);
Name dnsName = m_identity;
dnsName.append("DNS")
.append(endorsee.wireEncode())
.append("ENDORSEE")
.appendVersion();
shared_ptr<Data> data = make_shared<Data>();
data->setName(dnsName);
data->setContent(endorseCertificate.wireEncode());
data->setFreshnessPeriod(time::milliseconds(1000));
m_keyChain.sign(*data, ndn::security::signingByIdentity(m_identity));
m_contactStorage->updateDnsEndorseOthers(*data, dnsName.get(-3).toUri());
m_face.put(*data);
}
void
ContactManager::sendInterest(const Interest& interest,
const ndn::security::DataValidationSuccessCallback& onValidated,
const ndn::security::DataValidationFailureCallback& onValidationFailed,
const TimeoutNotify& timeoutNotify,
int retry /* = 1 */)
{
m_face.expressInterest(interest,
bind(&ContactManager::onTargetData,
this, _1, _2, onValidated, onValidationFailed),
bind(&ContactManager::onTargetTimeout,
this, _1, retry, onValidated, onValidationFailed, timeoutNotify),
bind(&ContactManager::onTargetTimeout,
this, _1, retry, onValidated, onValidationFailed, timeoutNotify));
}
void
ContactManager::onTargetData(const Interest& interest,
const Data& data,
const ndn::security::DataValidationSuccessCallback& onValidated,
const ndn::security::DataValidationFailureCallback& onValidationFailed)
{
m_validator->validate(data, onValidated, onValidationFailed);
}
void
ContactManager::onTargetTimeout(const Interest& interest,
int retry,
const ndn::security::DataValidationSuccessCallback& onValidated,
const ndn::security::DataValidationFailureCallback& onValidationFailed,
const TimeoutNotify& timeoutNotify)
{
if (retry > 0)
sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
else
timeoutNotify(interest);
}
void
ContactManager::onDnsInterest(const Name& prefix, const Interest& interest)
{
const Name& interestName = interest.getName();
shared_ptr<Data> data;
if (interestName.size() <= prefix.size())
return;
if (interestName.size() == (prefix.size()+1)) {
data = m_contactStorage->getDnsData("N/A", interestName.get(prefix.size()).toUri());
if (static_cast<bool>(data))
m_face.put(*data);
return;
}
if (interestName.size() == (prefix.size()+2)) {
data = m_contactStorage->getDnsData(interestName.get(prefix.size()).toUri(),
interestName.get(prefix.size()+1).toUri());
if (static_cast<bool>(data))
m_face.put(*data);
return;
}
}
void
ContactManager::onDnsRegisterFailed(const Name& prefix, const std::string& failInfo)
{
emit warning(QString(failInfo.c_str()));
}
void
ContactManager::onKeyInterest(const Name& prefix, const Interest& interest)
{
const Name& interestName = interest.getName();
shared_ptr<Certificate> data;
try {
ndn::security::Certificate cert = m_keyChain.getPib()
.getIdentity(m_identity)
.getDefaultKey()
.getDefaultCertificate();
if (cert.getKeyName() == interestName)
return m_face.put(cert);
} catch (const ndn::security::Pib::Error&) {}
data = m_contactStorage->getSelfEndorseCertificate();
if (static_cast<bool>(data) && data->getKeyName().equals(interestName))
return m_face.put(*data);
data = m_contactStorage->getCollectEndorseByName(interestName);
if (static_cast<bool>(data))
return m_face.put(*data);
}
// public slots
void
ContactManager::onIdentityUpdated(const QString& identity)
{
m_identity = Name(identity.toStdString());
m_contactStorage = make_shared<ContactStorage>(m_identity);
m_dnsListenerHandle = m_face.setInterestFilter(
Name(m_identity).append("DNS"),
bind(&ContactManager::onDnsInterest, this, _1, _2),
bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));
m_keyListenerHandle = m_face.setInterestFilter(
Name(m_identity).append("KEY"),
bind(&ContactManager::onKeyInterest, this, _1, _2),
bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));
m_profileCertListenerHandle = m_face.setInterestFilter(
Name(m_identity).append("PROFILE-CERT"),
bind(&ContactManager::onKeyInterest, this, _1, _2),
bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));
m_contactList.clear();
m_contactStorage->getAllContacts(m_contactList);
m_bufferedContacts.clear();
onWaitForContactList();
collectEndorsement();
}
void
ContactManager::onFetchContactInfo(const QString& identity)
{
// try to fetch self-endorse-certificate via DNS PROFILE first.
Name identityName(identity.toStdString());
Name interestName;
interestName.append(identityName).append("DNS").append("PROFILE");
Interest interest(interestName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setCanBePrefix(true);
interest.setMustBeFresh(true);
ndn::security::DataValidationSuccessCallback onValidated =
bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
ndn::security::DataValidationFailureCallback onValidationFailed =
bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, _2, identityName);
TimeoutNotify timeoutNotify =
bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, _1, identityName);
sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}
void
ContactManager::onAddFetchedContact(const QString& identity)
{
Name identityName(identity.toStdString());
auto it = m_bufferedContacts.find(identityName);
if (it != m_bufferedContacts.end()) {
Contact contact(*(it->second.m_selfEndorseCert));
try {
m_contactStorage->addContact(contact);
m_bufferedContacts.erase(identityName);
m_contactList.clear();
m_contactStorage->getAllContacts(m_contactList);
onWaitForContactList();
}
catch (const ContactStorage::Error& e) {
emit warning(QString::fromStdString(e.what()));
}
}
else
emit warning(QString("Failure: no information of %1").arg(identity));
}
void
ContactManager::onUpdateProfile()
{
// Get current profile;
shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile();
if (!static_cast<bool>(newProfile))
return;
shared_ptr<EndorseCertificate> newEndorseCertificate =
getSignedSelfEndorseCertificate(*newProfile);
m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate);
publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
}
void
ContactManager::onRefreshBrowseContact()
{
return;
#if 0
// The following no longer works as we don't serve such a list anymore
vector<string> bufferedIdCertNames;
try {
using namespace boost::asio::ip;
tcp::iostream request_stream;
request_stream.expires_from_now(std::chrono::milliseconds(5000));
request_stream.connect("ndncert.named-data.net","80");
if (!request_stream) {
emit warning(QString::fromStdString("Fail to fetch certificate directory! #1"));
return;
}
request_stream << "GET /cert/list/ HTTP/1.0\r\n";
request_stream << "Host: ndncert.named-data.net\r\n\r\n";
request_stream.flush();
string line1;
std::getline(request_stream,line1);
if (!request_stream) {
emit warning(QString::fromStdString("Fail to fetch certificate directory! #2"));
return;
}
std::stringstream response_stream(line1);
string http_version;
response_stream >> http_version;
size_t status_code;
response_stream >> status_code;
string status_message;
std::getline(response_stream,status_message);
if (!response_stream ||
http_version.substr(0,5) != "HTTP/") {
emit warning(QString::fromStdString("Fail to fetch certificate directory! #3"));
return;
}
if (status_code!=200) {
emit warning(QString::fromStdString("Fail to fetch certificate directory! #4"));
return;
}
vector<string> headers;
string header;
while (std::getline(request_stream, header) && header != "\r")
headers.push_back(header);
std::istreambuf_iterator<char> stream_iter (request_stream);
std::istreambuf_iterator<char> end_of_stream;
typedef boost::tokenizer< boost::escaped_list_separator<char>,
std::istreambuf_iterator<char> > tokenizer_t;
tokenizer_t certItems (stream_iter,
end_of_stream,
boost::escaped_list_separator<char>('\\', '\n', '"'));
for (tokenizer_t::iterator it = certItems.begin(); it != certItems.end (); it++)
if (!it->empty())
bufferedIdCertNames.push_back(*it);
}
catch (const std::exception& e) {
emit warning(QString::fromStdString("Fail to fetch certificate directory! #N"));
}
{
boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
m_idCertCount = bufferedIdCertNames.size();
}
m_bufferedIdCerts.clear();
for (auto it = bufferedIdCertNames.begin(); it != bufferedIdCertNames.end(); it++) {
Name certName(*it);
Interest interest(certName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setMustBeFresh(true);
interest.setCanBePrefix(true);
ndn::security::DataValidationSuccessCallback onValidated =
bind(&ContactManager::onIdentityCertValidated, this, _1);
ndn::security::DataValidationFailureCallback onValidationFailed =
bind(&ContactManager::onIdentityCertValidationFailed, this, _1, _2);
TimeoutNotify timeoutNotify =
bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);
sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}
#endif
}
void
ContactManager::onFetchIdCert(const QString& qCertName)
{
Name certName(qCertName.toStdString());
if (m_bufferedIdCerts.find(certName) != m_bufferedIdCerts.end())
emit idCertReady(*m_bufferedIdCerts[certName]);
}
void
ContactManager::onAddFetchedContactIdCert(const QString& qCertName)
{
Name certName(qCertName.toStdString());
Name identity = certName.getPrefix(-1);
auto it = m_bufferedIdCerts.find(certName);
if (it != m_bufferedIdCerts.end()) {
Contact contact(*it->second);
try {
m_contactStorage->addContact(contact);
m_bufferedIdCerts.erase(certName);
m_contactList.clear();
m_contactStorage->getAllContacts(m_contactList);
onWaitForContactList();
}
catch (const ContactStorage::Error& e) {
emit warning(QString::fromStdString(e.what()));
}
}
else
emit warning(QString("Failure: no information of %1")
.arg(QString::fromStdString(identity.toUri())));
}
void
ContactManager::onWaitForContactList()
{
QStringList aliasList;
QStringList idList;
for (auto it = m_contactList.begin(); it != m_contactList.end(); it++) {
aliasList << QString((*it)->getAlias().c_str());
idList << QString((*it)->getNameSpace().toUri().c_str());
}
emit contactAliasListReady(aliasList);
emit contactIdListReady(idList);
}
void
ContactManager::onWaitForContactInfo(const QString& identity)
{
for (auto it = m_contactList.begin(); it != m_contactList.end(); it++)
if ((*it)->getNameSpace().toUri() == identity.toStdString())
emit contactInfoReady(QString((*it)->getNameSpace().toUri().c_str()),
QString((*it)->getName().c_str()),
QString((*it)->getInstitution().c_str()),
(*it)->isIntroducer());
}
void
ContactManager::onRemoveContact(const QString& identity)
{
m_contactStorage->removeContact(Name(identity.toStdString()));
m_contactList.clear();
m_contactStorage->getAllContacts(m_contactList);
onWaitForContactList();
}
void
ContactManager::onUpdateAlias(const QString& identity, const QString& alias)
{
m_contactStorage->updateAlias(Name(identity.toStdString()), alias.toStdString());
m_contactList.clear();
m_contactStorage->getAllContacts(m_contactList);
onWaitForContactList();
}
void
ContactManager::onUpdateIsIntroducer(const QString& identity, bool isIntroducer)
{
m_contactStorage->updateIsIntroducer(Name(identity.toStdString()), isIntroducer);
}
void
ContactManager::onUpdateEndorseCertificate(const QString& identity)
{
Name identityName(identity.toStdString());
shared_ptr<Certificate> newEndorseCertificate = generateEndorseCertificate(identityName);
if (!static_cast<bool>(newEndorseCertificate))
return;
m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identityName);
publishEndorseCertificateInDNS(*newEndorseCertificate);
}
} // namespace chronochat
#if WAF
#include "contact-manager.moc"
#endif