blob: 811130e887071ace8259a2a298c4dcad749367e6 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013-2016, 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>
*/
#if __clang__
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
#include "contact-manager.hpp"
#include <QStringList>
#include <QFile>
#ifndef Q_MOC_RUN
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include <ndn-cxx/util/crypto.hpp>
#include <ndn-cxx/security/sec-rule-relative.hpp>
#include <ndn-cxx/security/validator-regex.hpp>
#include "cryptopp.hpp"
#include <boost/asio.hpp>
#include <boost/tokenizer.hpp>
#include <boost/filesystem.hpp>
#include "logging.h"
#endif
namespace fs = boost::filesystem;
// INIT_LOGGER("chronochat.ContactManager");
namespace chronochat {
using std::string;
using std::map;
using std::vector;
using ndn::Face;
using ndn::OBufferStream;
using ndn::IdentityCertificate;
using ndn::Validator;
using ndn::ValidatorRegex;
using ndn::SecRuleRelative;
using ndn::OnDataValidated;
using ndn::OnDataValidationFailed;
using ndn::OnInterestValidated;
using ndn::OnInterestValidationFailed;
ContactManager::ContactManager(Face& face,
QObject* parent)
: QObject(parent)
, m_face(face)
, m_dnsListenerId(0)
{
initializeSecurity();
}
ContactManager::~ContactManager()
{
}
// private methods
shared_ptr<IdentityCertificate>
ContactManager::loadTrustAnchor()
{
shared_ptr<IdentityCertificate> anchor;
QFile anchorFile(":/security/anchor.cert");
if (!anchorFile.open(QIODevice::ReadOnly)) {
emit warning(QString("Cannot load trust anchor!"));
return anchor;
}
qint64 fileSize = anchorFile.size();
char* buf = new char[fileSize];
anchorFile.read(buf, fileSize);
try {
using namespace CryptoPP;
OBufferStream os;
StringSource(reinterpret_cast<const uint8_t*>(buf), fileSize, true,
new Base64Decoder(new FileSink(os)));
anchor = make_shared<IdentityCertificate>();
anchor->wireDecode(Block(os.buf()));
}
catch (CryptoPP::Exception& e) {
emit warning(QString("Cannot load trust anchor!"));
}
catch (IdentityCertificate::Error& e) {
emit warning(QString("Cannot load trust anchor!"));
}
catch(Block::Error& e) {
emit warning(QString("Cannot load trust anchor!"));
}
delete [] buf;
return anchor;
}
void
ContactManager::initializeSecurity()
{
shared_ptr<IdentityCertificate> anchor = loadTrustAnchor();
shared_ptr<ValidatorRegex> validator = make_shared<ValidatorRegex>(boost::ref(m_face));
validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><ENDORSED>",
"^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
"==", "\\1", "\\1\\2", true));
validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><><ENDORSEE>",
"^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
"==", "\\1", "\\1\\2", true));
validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
"^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
"==", "\\1", "\\1\\2", true));
validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
"^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$",
"==", "\\1", "\\1\\2", true));
validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
"^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
">", "\\1\\2", "\\1", true));
validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
"^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
"==", "\\1", "\\1\\2", true));
validator->addDataVerificationRule(make_shared<SecRuleRelative>("^(<>*)$",
"^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
">", "\\1", "\\1\\2", true));
validator->addTrustAnchor(anchor);
m_validator = validator;
}
void
ContactManager::fetchCollectEndorse(const Name& identity)
{
Name interestName = identity;
interestName.append("DNS").append("ENDORSED");
Interest interest(interestName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setMustBeFresh(true);
OnDataValidated onValidated =
bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
OnDataValidationFailed 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)
{
shared_ptr<EndorseCollection> endorseCollection =
m_bufferedContacts[identity].m_endorseCollection;
if(certIndex >= endorseCollection->getCollectionEntries().size())
prepareEndorseInfo(identity);
Name interestName(endorseCollection->getCollectionEntries()[certIndex].certName);
Interest interest(interestName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setMustBeFresh(true);
m_face.expressInterest(interest,
bind(&ContactManager::onEndorseCertificateInternal,
this, _1, _2, identity, certIndex,
endorseCollection->getCollectionEntries()[certIndex].hash),
bind(&ContactManager::onEndorseCertificateInternalTimeout,
this, _1, identity, certIndex));
}
void
ContactManager::prepareEndorseInfo(const Name& identity)
{
// _LOG_DEBUG("prepareEndorseInfo");
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 (Profile::const_iterator pIt = profile.begin(); pIt != profile.end(); pIt++) {
// _LOG_DEBUG("prepareEndorseInfo: profile[" << pIt->first << "]: " << pIt->second);
endorseCount[pIt->first] = 0;
}
size_t endorseCertCount = 0;
vector<shared_ptr<EndorseCertificate> >::const_iterator cIt =
m_bufferedContacts[identity].m_endorseCertList.begin();
vector<shared_ptr<EndorseCertificate> >::const_iterator cEnd =
m_bufferedContacts[identity].m_endorseCertList.end();
for (; cIt != cEnd; cIt++, endorseCertCount++) {
shared_ptr<Contact> contact = getContact((*cIt)->getSigner().getPrefix(-1));
if (!static_cast<bool>(contact))
continue;
if (!contact->isIntroducer() ||
!contact->canBeTrustedFor(profile.getIdentityName()))
continue;
if (!Validator::verifySignature(**cIt, contact->getPublicKey()))
continue;
const Profile& tmpProfile = (*cIt)->getProfile();
if (tmpProfile != profile)
continue;
const vector<string>& endorseList = (*cIt)->getEndorseList();
for (vector<string>::const_iterator eIt = endorseList.begin(); eIt != endorseList.end(); eIt++)
endorseCount[*eIt] += 1;
}
for (Profile::const_iterator 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 shared_ptr<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 (Validator::verifySignature(plainData, selfEndorseCertificate->getPublicKeyInfo())) {
m_bufferedContacts[identity].m_selfEndorseCert = selfEndorseCertificate;
fetchCollectEndorse(identity);
}
else
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}
catch(Block::Error& e) {
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}
catch(EndorseCertificate::Error& e) {
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}
catch(Data::Error& e) {
emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}
}
void
ContactManager::onDnsSelfEndorseCertValidationFailed(const shared_ptr<const Data>& data,
const string& failInfo,
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 shared_ptr<const Data>& data,
const Name& identity)
{
try {
shared_ptr<EndorseCollection> endorseCollection =
make_shared<EndorseCollection>(data->getContent());
m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
fetchEndorseCertificateInternal(identity, 0);
}
catch (tlv::Error) {
prepareEndorseInfo(identity);
}
}
void
ContactManager::onDnsCollectEndorseValidationFailed(const shared_ptr<const Data>& data,
const string& failInfo,
const Name& identity)
{
prepareEndorseInfo(identity);
}
void
ContactManager::onDnsCollectEndorseTimeoutNotify(const Interest& interest, const Name& identity)
{
// _LOG_DEBUG("onDnsCollectEndorseTimeoutNotify: " << interest.getName());
prepareEndorseInfo(identity);
}
void
ContactManager::onEndorseCertificateInternal(const Interest& interest, Data& data,
const Name& identity, size_t certIndex,
string hash)
{
std::stringstream ss;
{
using namespace CryptoPP;
SHA256 hash;
StringSource(data.wireEncode().wire(), data.wireEncode().size(), true,
new HashFilter(hash, new FileSink(ss)));
}
if (ss.str() == hash) {
shared_ptr<EndorseCertificate> endorseCertificate =
make_shared<EndorseCertificate>(boost::cref(data));
m_bufferedContacts[identity].m_endorseCertList.push_back(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 (ContactList::iterator 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.setInterestLifetime(time::milliseconds(1000));
OnDataValidated onValidated = bind(&ContactManager::onDnsEndorseeValidated, this, _1);
OnDataValidationFailed onValidationFailed =
bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1, _2);
TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);
sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}
}
}
void
ContactManager::onDnsEndorseeValidated(const shared_ptr<const Data>& data)
{
Data endorseData;
endorseData.wireDecode(data->getContent().blockFromValue());
EndorseCertificate endorseCertificate(endorseData);
m_contactStorage->updateCollectEndorse(endorseCertificate);
decreaseCollectStatus();
}
void
ContactManager::onDnsEndorseeValidationFailed(const shared_ptr<const Data>& data,
const string& failInfo)
{
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);
EndorseCollection endorseCollection;
m_contactStorage->getCollectEndorse(endorseCollection);
data->setContent(endorseCollection.wireEncode());
m_keyChain.signByIdentity(*data, m_identity);
m_contactStorage->updateDnsOthersEndorse(*data);
m_face.put(*data);
}
void
ContactManager::onIdentityCertValidated(const shared_ptr<const Data>& data)
{
shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(boost::cref(*data));
m_bufferedIdCerts[cert->getName()] = cert;
decreaseIdCertCount();
}
void
ContactManager::onIdentityCertValidationFailed(const shared_ptr<const Data>& data,
const string& failInfo)
{
// _LOG_DEBUG("ContactManager::onIdentityCertValidationFailed " << data->getName());
decreaseIdCertCount();
}
void
ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
{
// _LOG_DEBUG("ContactManager::onIdentityCertTimeoutNotify: " << interest.getName());
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(BufferedIdCerts::const_iterator 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)
{
Name certificateName = m_keyChain.getDefaultCertificateNameForIdentity(m_identity);
shared_ptr<IdentityCertificate> signingCert = m_keyChain.getCertificate(certificateName);
vector<string> endorseList;
for (Profile::const_iterator it = profile.begin(); it != profile.end(); it++)
endorseList.push_back(it->first);
shared_ptr<EndorseCertificate> selfEndorseCertificate =
make_shared<EndorseCertificate>(boost::cref(*signingCert),
boost::cref(profile),
boost::cref(endorseList));
m_keyChain.sign(*selfEndorseCertificate, certificateName);
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.signByIdentity(*data, m_identity);
m_contactStorage->updateDnsSelfProfileData(*data);
m_face.put(*data);
}
shared_ptr<EndorseCertificate>
ContactManager::generateEndorseCertificate(const Name& identity)
{
shared_ptr<Contact> contact = getContact(identity);
if (!static_cast<bool>(contact))
return shared_ptr<EndorseCertificate>();
Name signerKeyName = m_keyChain.getDefaultKeyNameForIdentity(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(),
signerKeyName,
contact->getProfile(),
endorseList));
m_keyChain.signByIdentity(*cert, m_identity);
return cert;
}
void
ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate)
{
Name endorsee = endorseCertificate.getPublicKeyName().getPrefix(-1);
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());
m_keyChain.signByIdentity(*data, m_identity);
m_contactStorage->updateDnsEndorseOthers(*data, dnsName.get(-3).toUri());
m_face.put(*data);
}
void
ContactManager::sendInterest(const Interest& interest,
const OnDataValidated& onValidated,
const OnDataValidationFailed& 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));
}
void
ContactManager::onTargetData(const Interest& interest,
const Data& data,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed)
{
// _LOG_DEBUG("On receiving data: " << data.getName());
m_validator->validate(data, onValidated, onValidationFailed);
}
void
ContactManager::onTargetTimeout(const Interest& interest,
int retry,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed,
const TimeoutNotify& timeoutNotify)
{
// _LOG_DEBUG("On interest timeout: " << interest.getName());
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()));
}
// public slots
void
ContactManager::onIdentityUpdated(const QString& identity)
{
m_identity = Name(identity.toStdString());
m_contactStorage = make_shared<ContactStorage>(m_identity);
Name dnsPrefix;
dnsPrefix.append(m_identity).append("DNS");
const ndn::RegisteredPrefixId* dnsListenerId =
m_face.setInterestFilter(dnsPrefix,
bind(&ContactManager::onDnsInterest,
this, _1, _2),
bind(&ContactManager::onDnsRegisterFailed,
this, _1, _2));
if (m_dnsListenerId != 0)
m_face.unsetInterestFilter(m_dnsListenerId);
m_dnsListenerId = dnsListenerId;
m_contactList.clear();
m_contactStorage->getAllContacts(m_contactList);
m_bufferedContacts.clear();
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");
// _LOG_DEBUG("onFetchContactInfo " << identity.toStdString() << " profile: " << interestName);
Interest interest(interestName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setMustBeFresh(true);
OnDataValidated onValidated =
bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
OnDataValidationFailed 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)
{
// _LOG_DEBUG("onAddFetchedContact");
Name identityName(identity.toStdString());
BufferedContacts::const_iterator it = m_bufferedContacts.find(identityName);
if (it != m_bufferedContacts.end()) {
Contact contact(*(it->second.m_selfEndorseCert));
// _LOG_DEBUG("onAddFetchedContact: contact ready");
try {
m_contactStorage->addContact(contact);
m_bufferedContacts.erase(identityName);
m_contactList.clear();
m_contactStorage->getAllContacts(m_contactList);
onWaitForContactList();
}
catch(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;
// _LOG_DEBUG("ContactManager::onUpdateProfile: getProfile");
shared_ptr<EndorseCertificate> newEndorseCertificate =
getSignedSelfEndorseCertificate(*newProfile);
m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate);
publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
}
void
ContactManager::onRefreshBrowseContact()
{
vector<string> bufferedIdCertNames;
try {
using namespace boost::asio::ip;
tcp::iostream request_stream;
request_stream.expires_from_now(boost::posix_time::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(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 (vector<string>::const_iterator it = bufferedIdCertNames.begin();
it != bufferedIdCertNames.end(); it++) {
Name certName(*it);
Interest interest(certName);
interest.setInterestLifetime(time::milliseconds(1000));
interest.setMustBeFresh(true);
OnDataValidated onValidated =
bind(&ContactManager::onIdentityCertValidated, this, _1);
OnDataValidationFailed onValidationFailed =
bind(&ContactManager::onIdentityCertValidationFailed, this, _1, _2);
TimeoutNotify timeoutNotify =
bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);
sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}
}
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 = IdentityCertificate::certificateNameToPublicKeyName(certName).getPrefix(-1);
BufferedIdCerts::const_iterator 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(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 (ContactList::const_iterator 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 (ContactList::const_iterator 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<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identityName);
if (!static_cast<bool>(newEndorseCertificate))
return;
m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identityName);
publishEndorseCertificateInDNS(*newEndorseCertificate);
}
} // namespace chronochat
#if WAF
#include "contact-manager.moc"
// #include "contact-manager.cpp.moc"
#endif