blob: cde6c552b717fc68935ca9dc4a85501d2963995b [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013, Regents of the University of California
* Yingdi Yu
*
* BSD license, See the LICENSE file for more information
*
* Author: Yingdi Yu <yingdi@cs.ucla.edu>
*/
#include "contactpanel.h"
#include "ui_contactpanel.h"
#include <QStringList>
#include <QItemSelectionModel>
#include <QModelIndex>
#include <QDir>
#include <QtSql/QSqlRecord>
#include <QtSql/QSqlField>
#include <QtSql/QSqlError>
#ifndef Q_MOC_RUN
#include <ndn-cpp/security/verifier.hpp>
#include <ndn-cpp/security/signature-sha256-with-rsa.hpp>
#include <boost/filesystem.hpp>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include "logging.h"
#endif
namespace fs = boost::filesystem;
using namespace ndn;
using namespace ndn::ptr_lib;
using namespace std;
INIT_LOGGER("ContactPanel");
Q_DECLARE_METATYPE(ndn::IdentityCertificate)
Q_DECLARE_METATYPE(ChronosInvitation)
ContactPanel::ContactPanel(QWidget *parent)
: QDialog(parent)
, ui(new Ui::ContactPanel)
, m_warningDialog(new WarningDialog)
, m_contactListModel(new QStringListModel)
, m_startChatDialog(new StartChatDialog)
, m_invitationDialog(new InvitationDialog)
, m_settingDialog(new SettingDialog)
, m_policy(new SecPolicyChronoChatPanel())
{
qRegisterMetaType<IdentityCertificate>("IdentityCertificate");
qRegisterMetaType<ChronosInvitation>("ChronosInvitation");
startFace();
createAction();
m_keyChain = make_shared<KeyChain>();
m_contactManager = make_shared<ContactManager>(m_keyChain, m_face);
connect(&*m_contactManager, SIGNAL(noNdnConnection(const QString&)),
this, SLOT(showError(const QString&)));
openDB();
refreshContactList();
loadTrustAnchor();
m_defaultIdentity = m_keyChain->getDefaultIdentity();
if(m_defaultIdentity.size() == 0)
showError(QString::fromStdString("certificate of ") + QString::fromStdString(m_defaultIdentity.toUri()) + " is missing!\nHave you installed the certificate?");
Name defaultCertName = m_keyChain->getDefaultCertificateNameForIdentity(m_defaultIdentity);
if(defaultCertName.size() == 0)
showError(QString::fromStdString("certificate of ") + QString::fromStdString(m_defaultIdentity.toUri()) + " is missing!\nHave you installed the certificate?");
m_contactManager->setDefaultIdentity(m_defaultIdentity);
m_nickName = m_defaultIdentity.get(-1).toEscapedString();
m_settingDialog->setIdentity(m_defaultIdentity.toUri(), m_nickName);
m_profileEditor = new ProfileEditor(m_contactManager);
m_profileEditor->setCurrentIdentity(m_defaultIdentity);
m_addContactPanel = new AddContactPanel(m_contactManager);
m_browseContactDialog = new BrowseContactDialog(m_contactManager);
m_setAliasDialog = new SetAliasDialog(m_contactManager);
ui->setupUi(this);
m_localPrefix = Name("/private/local");
setLocalPrefix();
setInvitationListener();
collectEndorsement();
ui->ContactList->setModel(m_contactListModel);
connect(ui->ContactList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
this, SLOT(updateSelection(const QItemSelection &, const QItemSelection &)));
connect(ui->ContactList, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(showContextMenu(const QPoint&)));
connect(ui->EditProfileButton, SIGNAL(clicked()),
this, SLOT(openProfileEditor()));
connect(m_profileEditor, SIGNAL(noKeyOrCert(const QString&)),
this, SLOT(showWarning(const QString&)));
connect(ui->AddContactButton, SIGNAL(clicked()),
this, SLOT(openBrowseContactDialog()));
connect(m_browseContactDialog, SIGNAL(directAddClicked()),
this, SLOT(openAddContactPanel()));
connect(this, SIGNAL(refreshCertDirectory()),
m_browseContactDialog, SLOT(refreshList()));
connect(ui->DeleteContactButton, SIGNAL(clicked()),
this, SLOT(removeContactButton()));
connect(ui->settingButton, SIGNAL(clicked()),
this, SLOT(openSettingDialog()));
connect(m_addContactPanel, SIGNAL(newContactAdded()),
this, SLOT(refreshContactList()));
connect(m_browseContactDialog, SIGNAL(newContactAdded()),
this, SLOT(refreshContactList()));
connect(m_setAliasDialog, SIGNAL(aliasChanged()),
this, SLOT(refreshContactList()));
connect(m_startChatDialog, SIGNAL(chatroomConfirmed(const QString&, const QString&, bool)),
this, SLOT(startChatroom(const QString&, const QString&, bool)));
connect(m_invitationDialog, SIGNAL(invitationAccepted(const ChronosInvitation&, const ndn::IdentityCertificate&)),
this, SLOT(acceptInvitation(const ChronosInvitation&, const ndn::IdentityCertificate&)));
connect(m_invitationDialog, SIGNAL(invitationRejected(const ChronosInvitation&)),
this, SLOT(rejectInvitation(const ChronosInvitation&)));
connect(&*m_contactManager, SIGNAL(contactAdded(const ndn::Name&)),
this, SLOT(addContactIntoPanelPolicy(const ndn::Name&)));
connect(&*m_contactManager, SIGNAL(contactRemoved(const ndn::Name&)),
this, SLOT(removeContactFromPanelPolicy(const ndn::Name&)));
connect(m_settingDialog, SIGNAL(identitySet(const QString&, const QString&)),
this, SLOT(updateDefaultIdentity(const QString&, const QString&)));
connect(this, SIGNAL(newInvitationReady()),
this, SLOT(openInvitationDialog()));
connect(ui->isIntroducer, SIGNAL(stateChanged(int)),
this, SLOT(isIntroducerChanged(int)));
connect(ui->addScope, SIGNAL(clicked()),
this, SLOT(addScopeClicked()));
connect(ui->deleteScope, SIGNAL(clicked()),
this, SLOT(deleteScopeClicked()));
connect(ui->saveButton, SIGNAL(clicked()),
this, SLOT(saveScopeClicked()));
connect(ui->endorseButton, SIGNAL(clicked()),
this, SLOT(endorseButtonClicked()));
}
ContactPanel::~ContactPanel()
{
delete ui;
delete m_contactListModel;
delete m_startChatDialog;
delete m_invitationDialog;
delete m_settingDialog;
delete m_profileEditor;
delete m_addContactPanel;
delete m_browseContactDialog;
delete m_setAliasDialog;
delete m_trustScopeModel;
delete m_endorseDataModel;
delete m_endorseComboBoxDelegate;
delete m_menuInvite;
delete m_menuAlias;
map<Name, ChatDialog*>::iterator it = m_chatDialogs.begin();
for(; it != m_chatDialogs.end(); it++)
delete it->second;
shutdownFace();
}
void
ContactPanel::startFace()
{
m_face = make_shared<Face>();
connectToDaemon();
m_running = true;
m_thread = boost::thread (&ContactPanel::eventLoop, this);
}
void
ContactPanel::shutdownFace()
{
{
boost::unique_lock<boost::recursive_mutex> lock(m_mutex);
m_running = false;
}
m_thread.join();
m_face->shutdown();
}
void
ContactPanel::eventLoop()
{
while (m_running)
{
try{
m_face->processEvents();
usleep(100);
}catch(std::exception& e){
_LOG_DEBUG(" " << e.what() );
}
}
}
void
ContactPanel::connectToDaemon()
{
//Hack! transport does not connect to daemon unless an interest is expressed.
Name name("/ndn");
ndn::Interest interest(name);
m_face->expressInterest(interest,
func_lib::bind(&ContactPanel::onConnectionData, this, _1, _2),
func_lib::bind(&ContactPanel::onConnectionDataTimeout, this, _1));
}
void
ContactPanel::onConnectionData(const shared_ptr<const ndn::Interest>& interest,
const shared_ptr<Data>& data)
{ _LOG_DEBUG("onConnectionData"); }
void
ContactPanel::onConnectionDataTimeout(const shared_ptr<const ndn::Interest>& interest)
{ _LOG_DEBUG("onConnectionDataTimeout"); }
void
ContactPanel::createAction()
{
m_menuInvite = new QAction("&Chat", this);
m_menuAlias = new QAction("&Set Alias", this);
}
void
ContactPanel::openDB()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
QString path = (QDir::home().path());
path.append(QDir::separator()).append(".chronos").append(QDir::separator()).append("chronos.db");
db.setDatabaseName(path);
bool ok = db.open();
_LOG_DEBUG("DB opened: " << std::boolalpha << ok );
m_trustScopeModel = new QSqlTableModel;
m_endorseDataModel = new QSqlTableModel;
m_endorseComboBoxDelegate = new EndorseComboBoxDelegate;
}
void
ContactPanel::loadTrustAnchor()
{
vector<shared_ptr<ContactItem> >::const_iterator it = m_contactList.begin();
for(; it != m_contactList.end(); it++)
{
_LOG_DEBUG("load contact: " << (*it)->getNameSpace().toUri());
m_policy->addTrustAnchor((*it)->getSelfEndorseCertificate());
}
}
void
ContactPanel::setLocalPrefix(int retry)
{
Name interestName("/local/ndn/prefix");
Interest interest(interestName);
m_face->expressInterest(interest,
func_lib::bind(&ContactPanel::onLocalPrefix, this, _1, _2),
func_lib::bind(&ContactPanel::onLocalPrefixTimeout, this, _1, 10));
}
void
ContactPanel::onLocalPrefix(const shared_ptr<const Interest>& interest,
const shared_ptr<Data>& data)
{
string originPrefix((const char*)data->getContent().value(), data->getContent().value_size());
string prefix = QString::fromStdString (originPrefix).trimmed ().toUtf8().constData();
string randomSuffix = getRandomString();
m_localPrefix = Name(prefix);
}
void
ContactPanel::onLocalPrefixTimeout(const shared_ptr<const Interest>& interest,
int retry)
{
if(retry > 0)
{
setLocalPrefix(retry - 1);
return;
}
else{
m_localPrefix = Name("/private/local");
}
}
void
ContactPanel::setInvitationListener()
{
m_inviteListenPrefix = Name("/ndn/broadcast/chronos/invitation");
m_inviteListenPrefix.append(m_defaultIdentity);
_LOG_DEBUG("Listening for invitation on prefix: " << m_inviteListenPrefix.toUri());
m_invitationListenerId = m_face->setInterestFilter(m_inviteListenPrefix,
func_lib::bind(&ContactPanel::onInvitation, this, _1, _2, _3, _4),
func_lib::bind(&ContactPanel::onInvitationRegisterFailed, this, _1));
}
void
ContactPanel::sendInterest(const Interest& interest,
const OnVerified& onVerified,
const OnVerifyFailed& onVerifyFailed,
const TimeoutNotify& timeoutNotify,
int retry /* = 1 */,
int stepCount /* = 0 */)
{
m_face->expressInterest(interest,
func_lib::bind(&ContactPanel::onTargetData,
this,
_1,
_2,
stepCount,
onVerified,
onVerifyFailed,
timeoutNotify),
func_lib::bind(&ContactPanel::onTargetTimeout,
this,
_1,
retry,
stepCount,
onVerified,
onVerifyFailed,
timeoutNotify));
}
void
ContactPanel::onTargetData(const shared_ptr<const ndn::Interest>& interest,
const shared_ptr<Data>& data,
int stepCount,
const OnVerified& onVerified,
const OnVerifyFailed& onVerifyFailed,
const TimeoutNotify& timeoutNotify)
{
shared_ptr<ValidationRequest> nextStep = m_policy->checkVerificationPolicy(data, stepCount, onVerified, onVerifyFailed);
if (nextStep)
m_face->expressInterest
(*nextStep->interest_,
func_lib::bind(&ContactPanel::onCertData, this, _1, _2, nextStep),
func_lib::bind(&ContactPanel::onCertTimeout, this, _1, onVerifyFailed, data, nextStep));
}
void
ContactPanel::onTargetTimeout(const shared_ptr<const ndn::Interest>& interest,
int retry,
int stepCount,
const OnVerified& onVerified,
const OnVerifyFailed& onVerifyFailed,
const TimeoutNotify& timeoutNotify)
{
if(retry > 0)
sendInterest(*interest, onVerified, onVerifyFailed, timeoutNotify, retry-1, stepCount);
else
{
_LOG_DEBUG("Interest: " << interest->getName().toUri() << " eventually times out!");
timeoutNotify();
}
}
void
ContactPanel::onCertData(const shared_ptr<const ndn::Interest>& interest,
const shared_ptr<Data>& cert,
shared_ptr<ValidationRequest> previousStep)
{
shared_ptr<ValidationRequest> nextStep = m_policy->checkVerificationPolicy(cert,
previousStep->stepCount_,
previousStep->onVerified_,
previousStep->onVerifyFailed_);
if (nextStep)
m_face->expressInterest
(*nextStep->interest_,
func_lib::bind(&ContactPanel::onCertData, this, _1, _2, nextStep),
func_lib::bind(&ContactPanel::onCertTimeout, this, _1, previousStep->onVerifyFailed_, cert, nextStep));
}
void
ContactPanel::onCertTimeout(const shared_ptr<const ndn::Interest>& interest,
const OnVerifyFailed& onVerifyFailed,
const shared_ptr<Data>& data,
shared_ptr<ValidationRequest> nextStep)
{
if(nextStep->retry_ > 0)
m_face->expressInterest(*interest,
func_lib::bind(&ContactPanel::onCertData,
this,
_1,
_2,
nextStep),
func_lib::bind(&ContactPanel::onCertTimeout,
this,
_1,
onVerifyFailed,
data,
nextStep));
else
onVerifyFailed(data);
}
void
ContactPanel::onInvitationRegisterFailed(const shared_ptr<const Name>& prefix)
{
showError(QString::fromStdString("Cannot register invitation listening prefix"));
}
void
ContactPanel::onInvitation(const shared_ptr<const Name>& prefix,
const shared_ptr<const Interest>& interest,
Transport& transport,
uint64_t registeredPrefixId)
{
_LOG_DEBUG("Receive invitation!" << interest->getName().toUri());
shared_ptr<ChronosInvitation> invitation;
try{
invitation = make_shared<ChronosInvitation>(interest->getName());
}catch(std::exception& e){
_LOG_ERROR("Exception: " << e.what());
return;
}
Name chatroomName("/ndn/broadcast/chronos");
chatroomName.append(invitation->getChatroom());
map<Name, ChatDialog*>::iterator it = m_chatDialogs.find(chatroomName);
if(it != m_chatDialogs.end())
{
_LOG_ERROR("Exisiting chatroom!");
return;
}
shared_ptr<PublicKey> keyPtr = m_policy->getTrustedKey(invitation->getInviterCertificateName());
SignatureSha256WithRsa invitationSig;
Block sigBlock(invitation->getSignatureBits().buf(), invitation->getSignatureBits().size());
invitationSig.setValue(sigBlock);
if(static_cast<bool>(keyPtr) && Verifier::verifySignature(invitation->getSignedBlob(), invitationSig, *keyPtr))
{
shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
// hack: incomplete certificate, we don't send it to the wire nor store it anywhere, we only use it to carry information
certificate->setName(invitation->getInviterCertificateName());
bool findCert = false;
vector<shared_ptr<ContactItem> >::const_iterator it = m_contactList.begin();
for(; it != m_contactList.end(); it++)
{
if((*it)->getNameSpace() == invitation->getInviterNameSpace())
{
certificate->setNotBefore((*it)->getSelfEndorseCertificate().getNotBefore());
certificate->setNotAfter((*it)->getSelfEndorseCertificate().getNotAfter());
findCert = true;
break;
}
}
if(findCert == false)
{
_LOG_ERROR("No SelfEndorseCertificate found!");
return;
}
certificate->setPublicKeyInfo(*keyPtr);
popChatInvitation(invitation, invitation->getInviterNameSpace(), certificate);
return;
}
_LOG_DEBUG("Cannot find the inviter's key in trust anchors");
Interest newInterest(invitation->getInviterCertificateName());
OnVerified onVerified = func_lib::bind(&ContactPanel::onInvitationCertVerified, this, _1, invitation);
OnVerifyFailed onVerifyFailed = func_lib::bind(&ContactPanel::onInvitationCertVerifyFailed, this, _1);
TimeoutNotify timeoutNotify = func_lib::bind(&ContactPanel::onInvitationCertTimeoutNotify, this);
sendInterest(newInterest, onVerified, onVerifyFailed, timeoutNotify);
}
void
ContactPanel::onInvitationCertVerified(const shared_ptr<Data>& data,
shared_ptr<ChronosInvitation> invitation)
{
shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>(*data);
SignatureSha256WithRsa invitationSig;
Block sigBlock(invitation->getSignatureBits().buf(), invitation->getSignatureBits().size());
invitationSig.setValue(sigBlock);
if(Verifier::verifySignature(invitation->getSignedBlob(), invitationSig, certificate->getPublicKeyInfo()))
{
Name keyName = certificate->getPublicKeyName();
Name inviterNameSpace = keyName.getPrefix(-1);
popChatInvitation(invitation, inviterNameSpace, certificate);
}
}
void
ContactPanel::onInvitationCertVerifyFailed(const shared_ptr<Data>& data)
{ _LOG_DEBUG("Cannot verify invitation certificate!"); }
void
ContactPanel::onInvitationCertTimeoutNotify()
{ _LOG_DEBUG("interest for invitation certificate times out eventually!"); }
void
ContactPanel::popChatInvitation(shared_ptr<ChronosInvitation> invitation,
const Name& inviterNameSpace,
shared_ptr<IdentityCertificate> certificate)
{
string alias;
vector<shared_ptr<ContactItem> >::iterator it = m_contactList.begin();
for(; it != m_contactList.end(); it++)
if((*it)->getNameSpace() == inviterNameSpace)
alias = (*it)->getAlias();
if(it != m_contactList.end())
return;
m_invitationDialog->setInvitation(alias, invitation, certificate);
emit newInvitationReady();
}
void
ContactPanel::collectEndorsement()
{
m_collectStatus = make_shared<vector<bool> >();
m_collectStatus->assign(m_contactList.size(), false);
vector<shared_ptr<ContactItem> >::iterator it = m_contactList.begin();
int count = 0;
for(; it != m_contactList.end(); it++, count++)
{
Name interestName = (*it)->getNameSpace();
interestName.append("DNS").append(m_defaultIdentity).append("ENDORSEE");
Interest interest(interestName);
interest.setInterestLifetime(1000);
OnVerified onVerified = func_lib::bind(&ContactPanel::onDnsEndorseeVerified, this, _1, count);
OnVerifyFailed onVerifyFailed = func_lib::bind(&ContactPanel::onDnsEndorseeVerifyFailed, this, _1, count);
TimeoutNotify timeoutNotify = func_lib::bind(&ContactPanel::onDnsEndorseeTimeoutNotify, this, count);
sendInterest(interest, onVerified, onVerifyFailed, timeoutNotify, 0);
}
}
void
ContactPanel::onDnsEndorseeVerified(const shared_ptr<Data>& data, int count)
{
Data endorseData;
endorseData.wireDecode(Block(data->getContent().value(), data->getContent().value_size()));
EndorseCertificate endorseCertificate(endorseData);
m_contactManager->getContactStorage()->updateCollectEndorse(endorseCertificate);
updateCollectStatus(count);
}
void
ContactPanel::onDnsEndorseeTimeoutNotify(int count)
{ updateCollectStatus(count); }
void
ContactPanel::onDnsEndorseeVerifyFailed(const shared_ptr<Data>& data, int count)
{ updateCollectStatus(count); }
void
ContactPanel::updateCollectStatus(int count)
{
m_collectStatus->at(count) = true;
vector<bool>::const_iterator it = m_collectStatus->begin();
for(; it != m_collectStatus->end(); it++)
if(*it == false)
return;
m_contactManager->publishEndorsedDataInDns(m_defaultIdentity);
}
static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
string
ContactPanel::getRandomString()
{
string randStr;
boost::random::random_device rng;
boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
for (int i = 0; i < 10; i ++)
{
randStr += chars[index_dist(rng)];
}
return randStr;
}
void
ContactPanel::showError(const QString& msg){
QMessageBox::critical(this, tr("Chronos"), msg, QMessageBox::Ok);
exit(1);
}
void
ContactPanel::showWarning(const QString& msg){
QMessageBox::information(this, tr("Chronos"), msg);
}
void
ContactPanel::updateSelection(const QItemSelection &selected,
const QItemSelection &deselected)
{
QModelIndexList items = selected.indexes();
QString text = m_contactListModel->data(items.first(), Qt::DisplayRole).toString();
string alias = text.toStdString();
int i = 0;
for(; i < m_contactList.size(); i++)
{
if(alias == m_contactList[i]->getAlias())
break;
}
m_currentSelectedContact = m_contactList[i];
ui->NameData->setText(QString::fromStdString(m_currentSelectedContact->getName()));
ui->NameSpaceData->setText(QString::fromStdString(m_currentSelectedContact->getNameSpace().toUri()));
ui->InstitutionData->setText(QString::fromStdString(m_currentSelectedContact->getInstitution()));
if(m_currentSelectedContact->isIntroducer())
{
ui->isIntroducer->setChecked(true);
ui->addScope->setEnabled(true);
ui->deleteScope->setEnabled(true);
ui->trustScopeList->setEnabled(true);
string filter("contact_namespace = '");
filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");
m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
m_trustScopeModel->setTable("TrustScope");
m_trustScopeModel->setFilter(filter.c_str());
m_trustScopeModel->select();
m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));
ui->trustScopeList->setModel(m_trustScopeModel);
ui->trustScopeList->setColumnHidden(0, true);
ui->trustScopeList->setColumnHidden(1, true);
ui->trustScopeList->show();
}
else
{
ui->isIntroducer->setChecked(false);
ui->addScope->setEnabled(false);
ui->deleteScope->setEnabled(false);
string filter("contact_namespace = '");
filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");
m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
m_trustScopeModel->setTable("TrustScope");
m_trustScopeModel->setFilter(filter.c_str());
m_trustScopeModel->select();
m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));
ui->trustScopeList->setModel(m_trustScopeModel);
ui->trustScopeList->setColumnHidden(0, true);
ui->trustScopeList->setColumnHidden(1, true);
ui->trustScopeList->show();
ui->trustScopeList->setEnabled(false);
}
string filter("profile_identity = '");
filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");
m_endorseDataModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
m_endorseDataModel->setTable("ContactProfile");
m_endorseDataModel->setFilter(filter.c_str());
m_endorseDataModel->select();
m_endorseDataModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Identity"));
m_endorseDataModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Type"));
m_endorseDataModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Value"));
m_endorseDataModel->setHeaderData(3, Qt::Horizontal, QObject::tr("Endorse"));
ui->endorseList->setModel(m_endorseDataModel);
ui->endorseList->setColumnHidden(0, true);
ui->endorseList->resizeColumnToContents(1);
ui->endorseList->resizeColumnToContents(2);
ui->endorseList->setItemDelegateForColumn(3, m_endorseComboBoxDelegate);
ui->endorseList->show();
}
void
ContactPanel::updateDefaultIdentity(const QString& identity, const QString& nickName)
{
// _LOG_DEBUG(identity.toStdString());
Name defaultIdentity = Name(identity.toStdString());
Name defaultCertName = m_keyChain->getDefaultCertificateNameForIdentity(defaultIdentity);
if(defaultCertName.size() == 0)
{
showWarning(QString::fromStdString("Corresponding certificate is missing!\nHave you installed the certificate?"));
return;
}
m_defaultIdentity = defaultIdentity;
m_profileEditor->setCurrentIdentity(m_defaultIdentity);
m_nickName = nickName.toStdString();
m_face->unsetInterestFilter(m_invitationListenerId);
m_contactManager->setDefaultIdentity(m_defaultIdentity);
setInvitationListener();
collectEndorsement();
}
void
ContactPanel::openProfileEditor()
{ m_profileEditor->show(); }
void
ContactPanel::openAddContactPanel()
{ m_addContactPanel->show(); }
void
ContactPanel::openBrowseContactDialog()
{
m_browseContactDialog->show();
emit refreshCertDirectory();
}
void
ContactPanel::removeContactButton()
{
QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
QModelIndexList selectedList = selectionModel->selectedIndexes();
QModelIndexList::iterator it = selectedList.begin();
for(; it != selectedList.end(); it++)
{
string alias = m_contactListModel->data(*it, Qt::DisplayRole).toString().toStdString();
vector<shared_ptr<ContactItem> >::iterator contactIt = m_contactList.begin();
for(; contactIt != m_contactList.end(); contactIt++)
{
if((*contactIt)->getAlias() == alias)
{
m_contactManager->getContactStorage()->removeContact((*contactIt)->getNameSpace());
m_contactList.erase(contactIt);
break;
}
}
}
refreshContactList();
}
void
ContactPanel::openInvitationDialog()
{ m_invitationDialog->show(); }
void
ContactPanel::addContactIntoPanelPolicy(const Name& contactNameSpace)
{
shared_ptr<ContactItem> contact = m_contactManager->getContact(contactNameSpace);
if(static_cast<bool>(contact))
m_policy->addTrustAnchor(contact->getSelfEndorseCertificate());
}
void
ContactPanel::removeContactFromPanelPolicy(const Name& keyName)
{ m_policy->removeTrustAnchor(keyName); }
void
ContactPanel::refreshContactList()
{
m_contactList.clear();
m_contactManager->getContactItemList(m_contactList);
QStringList contactNameList;
for(int i = 0; i < m_contactList.size(); i++)
contactNameList << QString::fromStdString(m_contactList[i]->getAlias());
m_contactListModel->setStringList(contactNameList);
}
void
ContactPanel::showContextMenu(const QPoint& pos)
{
QMenu menu(ui->ContactList);
menu.addAction(m_menuInvite);
connect(m_menuInvite, SIGNAL(triggered()),
this, SLOT(openStartChatDialog()));
menu.addSeparator();
menu.addAction(m_menuAlias);
connect(m_menuAlias, SIGNAL(triggered()),
this, SLOT(openSetAliasDialog()));
menu.exec(ui->ContactList->mapToGlobal(pos));
}
void
ContactPanel::openSetAliasDialog()
{
m_setAliasDialog->setTargetIdentity(m_currentSelectedContact->getNameSpace().toUri());
m_setAliasDialog->show();
}
void
ContactPanel::openSettingDialog()
{
m_settingDialog->setIdentity(m_defaultIdentity.toUri(), m_nickName);
m_settingDialog->show();
}
void
ContactPanel::openStartChatDialog()
{
Name chatroom("/ndn/broadcast/chronos");
chatroom.append(string("chatroom-") + getRandomString());
m_startChatDialog->setInvitee(m_currentSelectedContact->getNameSpace().toUri(), chatroom.toUri());
m_startChatDialog->show();
}
// For inviter
void
ContactPanel::startChatroom(const QString& chatroom, const QString& invitee, bool isIntroducer)
{
Name chatroomName(chatroom.toStdString());
Name inviteeNamespace(invitee.toStdString());
shared_ptr<ContactItem> inviteeItem = m_contactManager->getContact(inviteeNamespace);
ChatDialog* chatDialog = new ChatDialog(m_contactManager, chatroomName, m_localPrefix, m_defaultIdentity, m_nickName);
m_chatDialogs.insert(pair <Name, ChatDialog*> (chatroomName, chatDialog));
connect(chatDialog, SIGNAL(closeChatDialog(const ndn::Name&)),
this, SLOT(removeChatDialog(const ndn::Name&)));
connect(chatDialog, SIGNAL(noNdnConnection(const QString&)),
this, SLOT(showError(const QString&)));
connect(chatDialog, SIGNAL(inivationRejection(const QString&)),
this, SLOT(showWarning(const QString&)));
// send invitation
chatDialog->sendInvitation(inviteeItem, isIntroducer);
chatDialog->show();
}
// For Invitee
void
ContactPanel::startChatroom2(const ChronosInvitation& invitation,
const IdentityCertificate& identityCertificate)
{
shared_ptr<ContactItem> inviterItem = m_contactManager->getContact(invitation.getInviterNameSpace());
Name chatroomName("/ndn/broadcast/chronos");
chatroomName.append(invitation.getChatroom());
ChatDialog* chatDialog = new ChatDialog(m_contactManager, chatroomName, m_localPrefix, m_defaultIdentity, m_nickName, true);
connect(chatDialog, SIGNAL(closeChatDialog(const ndn::Name&)),
this, SLOT(removeChatDialog(const ndn::Name&)));
connect(chatDialog, SIGNAL(noNdnConnection(const QString&)),
this, SLOT(showError(const QString&)));
connect(chatDialog, SIGNAL(inivationRejection(const QString&)),
this, SLOT(showWarning(const QString&)));
chatDialog->addChatDataRule(invitation.getInviterPrefix(), identityCertificate, true);
chatDialog->publishIntroCert(identityCertificate, true);
chatDialog->addTrustAnchor(inviterItem->getSelfEndorseCertificate());
m_chatDialogs.insert(pair <Name, ChatDialog*> (chatroomName, chatDialog));
chatDialog->show();
}
void
ContactPanel::acceptInvitation(const ChronosInvitation& invitation,
const IdentityCertificate& identityCertificate)
{
Name dataName = invitation.getInterestName();
time_t nowSeconds = time(NULL);
struct tm current = *gmtime(&nowSeconds);
MillisecondsSince1970 version = timegm(&current) * 1000.0;
dataName.appendVersion(version);
Data data(dataName);
string content = m_localPrefix.toUri();
data.setContent((const uint8_t *)&content[0], content.size());
Name certificateName;
Name inferredIdentity = m_policy->inferSigningIdentity(data.getName());
if(inferredIdentity.getComponentCount() == 0)
certificateName = m_keyChain->getDefaultCertificateName();
else
certificateName = m_keyChain->getDefaultCertificateNameForIdentity(inferredIdentity);
m_keyChain->sign(data, certificateName);
m_face->put(data);
startChatroom2(invitation, identityCertificate);
}
void
ContactPanel::rejectInvitation(const ChronosInvitation& invitation)
{
Data data(invitation.getInterestName());
string content("nack");
data.setContent((const uint8_t *)&content[0], content.size());
Name certificateName;
Name inferredIdentity = m_policy->inferSigningIdentity(data.getName());
if(inferredIdentity.getComponentCount() == 0)
certificateName = m_keyChain->getDefaultCertificateName();
else
certificateName = m_keyChain->getDefaultCertificateNameForIdentity(inferredIdentity);
m_keyChain->sign(data, certificateName);
m_face->put(data);
}
void
ContactPanel::isIntroducerChanged(int state)
{
if(state == Qt::Checked)
{
ui->addScope->setEnabled(true);
ui->deleteScope->setEnabled(true);
ui->trustScopeList->setEnabled(true);
string filter("contact_namespace = '");
filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");
m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
m_trustScopeModel->setTable("TrustScope");
m_trustScopeModel->setFilter(filter.c_str());
m_trustScopeModel->select();
m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));
ui->trustScopeList->setModel(m_trustScopeModel);
ui->trustScopeList->setColumnHidden(0, true);
ui->trustScopeList->setColumnHidden(1, true);
ui->trustScopeList->show();
m_currentSelectedContact->setIsIntroducer(true);
}
else
{
ui->addScope->setEnabled(false);
ui->deleteScope->setEnabled(false);
string filter("contact_namespace = '");
filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");
m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
m_trustScopeModel->setTable("TrustScope");
m_trustScopeModel->setFilter(filter.c_str());
m_trustScopeModel->select();
m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));
ui->trustScopeList->setModel(m_trustScopeModel);
ui->trustScopeList->setColumnHidden(0, true);
ui->trustScopeList->setColumnHidden(1, true);
ui->trustScopeList->show();
ui->trustScopeList->setEnabled(false);
m_currentSelectedContact->setIsIntroducer(false);
}
m_contactManager->getContactStorage()->updateIsIntroducer(m_currentSelectedContact->getNameSpace(), m_currentSelectedContact->isIntroducer());
}
void
ContactPanel::addScopeClicked()
{
int rowCount = m_trustScopeModel->rowCount();
QSqlRecord record;
QSqlField identityField("contact_namespace", QVariant::String);
record.append(identityField);
record.setValue("contact_namespace", QString::fromStdString(m_currentSelectedContact->getNameSpace().toUri()));
m_trustScopeModel->insertRow(rowCount);
m_trustScopeModel->setRecord(rowCount, record);
}
void
ContactPanel::deleteScopeClicked()
{
QItemSelectionModel* selectionModel = ui->trustScopeList->selectionModel();
QModelIndexList indexList = selectionModel->selectedIndexes();
int i = indexList.size() - 1;
for(; i >= 0; i--)
m_trustScopeModel->removeRow(indexList[i].row());
m_trustScopeModel->submitAll();
}
void
ContactPanel::saveScopeClicked()
{ m_trustScopeModel->submitAll(); }
void
ContactPanel::endorseButtonClicked()
{
m_endorseDataModel->submitAll();
m_contactManager->updateEndorseCertificate(m_currentSelectedContact->getNameSpace(), m_defaultIdentity);
}
void
ContactPanel::removeChatDialog(const ndn::Name& chatroomName)
{
map<Name, ChatDialog*>::iterator it = m_chatDialogs.find(chatroomName);
ChatDialog* deletedChat = NULL;
if(it != m_chatDialogs.end())
{
deletedChat = it->second;
m_chatDialogs.erase(it);
}
if (deletedChat != NULL)
delete deletedChat;
}
#if WAF
#include "contactpanel.moc"
#include "contactpanel.cpp.moc"
#endif