major change: Add security support & Adjust GUI
Change-Id: I7abef37169dec1ef4b68e760dee5214c147c1915
diff --git a/src/add-contact-panel.cpp b/src/add-contact-panel.cpp
new file mode 100644
index 0000000..5ce575c
--- /dev/null
+++ b/src/add-contact-panel.cpp
@@ -0,0 +1,97 @@
+/* -*- 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 "add-contact-panel.h"
+#include "ui_add-contact-panel.h"
+
+#ifndef Q_MOC_RUN
+#endif
+
+AddContactPanel::AddContactPanel(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::AddContactPanel)
+{
+ ui->setupUi(this);
+
+ connect(ui->cancelButton, SIGNAL(clicked()),
+ this, SLOT(onCancelClicked()));
+ connect(ui->searchButton, SIGNAL(clicked()),
+ this, SLOT(onSearchClicked()));
+ connect(ui->addButton, SIGNAL(clicked()),
+ this, SLOT(onAddClicked()));
+
+ ui->infoView->setColumnCount(3);
+
+ m_typeHeader = new QTableWidgetItem(QString("Type"));
+ ui->infoView->setHorizontalHeaderItem(0, m_typeHeader);
+ m_valueHeader = new QTableWidgetItem(QString("Value"));
+ ui->infoView->setHorizontalHeaderItem(1, m_valueHeader);
+ m_endorseHeader = new QTableWidgetItem(QString("Endorse"));
+ ui->infoView->setHorizontalHeaderItem(2, m_endorseHeader);
+
+}
+
+AddContactPanel::~AddContactPanel()
+{
+ delete m_typeHeader;
+ delete m_valueHeader;
+ delete m_endorseHeader;
+
+ delete ui;
+}
+
+void
+AddContactPanel::onCancelClicked()
+{
+ this->close();
+}
+
+void
+AddContactPanel::onSearchClicked()
+{
+ // ui->infoView->clear();
+ for(int i = ui->infoView->rowCount() - 1; i >= 0 ; i--)
+ ui->infoView->removeRow(i);
+
+ m_searchIdentity = ui->contactInput->text();
+ emit fetchInfo(m_searchIdentity);
+}
+
+void
+AddContactPanel::onAddClicked()
+{
+ emit addContact(m_searchIdentity);
+ this->close();
+}
+
+void
+AddContactPanel::onContactEndorseInfoReady(const chronos::EndorseInfo& endorseInfo)
+{
+ int entrySize = endorseInfo.endorsement_size();
+
+ for(int rowCount = 0; rowCount < entrySize; rowCount++)
+ {
+ ui->infoView->insertRow(rowCount);
+ QTableWidgetItem* type = new QTableWidgetItem(QString::fromStdString(endorseInfo.endorsement(rowCount).type()));
+ ui->infoView->setItem(rowCount, 0, type);
+
+ QTableWidgetItem* value = new QTableWidgetItem(QString::fromStdString(endorseInfo.endorsement(rowCount).value()));
+ ui->infoView->setItem(rowCount, 1, value);
+
+ QTableWidgetItem* endorse = new QTableWidgetItem(QString::fromStdString(endorseInfo.endorsement(rowCount).endorse()));
+ ui->infoView->setItem(rowCount, 2, endorse);
+ }
+}
+
+
+#if WAF
+#include "add-contact-panel.moc"
+#include "add-contact-panel.cpp.moc"
+#endif
diff --git a/src/add-contact-panel.h b/src/add-contact-panel.h
new file mode 100644
index 0000000..5e8255d
--- /dev/null
+++ b/src/add-contact-panel.h
@@ -0,0 +1,65 @@
+/* -*- 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>
+ */
+
+#ifndef ADD_CONTACT_PANEL_H
+#define ADD_CONTACT_PANEL_H
+
+#include <QDialog>
+#include <QTableWidgetItem>
+
+#ifndef Q_MOC_RUN
+#include "endorse-info.pb.h"
+#endif
+
+namespace Ui {
+class AddContactPanel;
+}
+
+class AddContactPanel : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit
+ AddContactPanel(QWidget *parent = 0);
+
+ ~AddContactPanel();
+
+public slots:
+ void
+ onContactEndorseInfoReady(const chronos::EndorseInfo& endorseInfo);
+
+private slots:
+ void
+ onCancelClicked();
+
+ void
+ onSearchClicked();
+
+ void
+ onAddClicked();
+
+signals:
+ void
+ fetchInfo(const QString& identity);
+
+ void
+ addContact(const QString& identity);
+
+private:
+ Ui::AddContactPanel *ui;
+ QString m_searchIdentity;
+
+ QTableWidgetItem* m_typeHeader;
+ QTableWidgetItem* m_valueHeader;
+ QTableWidgetItem* m_endorseHeader;
+};
+
+#endif // ADD_CONTACT_PANEL_H
diff --git a/src/add-contact-panel.ui b/src/add-contact-panel.ui
new file mode 100644
index 0000000..5cf399a
--- /dev/null
+++ b/src/add-contact-panel.ui
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddContactPanel</class>
+ <widget class="QDialog" name="AddContactPanel">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>500</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Add Contact</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="addContactPanelLayout" stretch="1,30,1">
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="contactSearchLayout" stretch="3,5,2">
+ <item>
+ <widget class="QLabel" name="contactLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Contact identity:</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::AutoText</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="contactInput"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="searchButton">
+ <property name="text">
+ <string>Fetch</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTableWidget" name="infoView">
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="buttonLayout">
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addButton">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/addcontactpanel.cpp b/src/addcontactpanel.cpp
deleted file mode 100644
index add341a..0000000
--- a/src/addcontactpanel.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/* -*- 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 "addcontactpanel.h"
-#include "ui_addcontactpanel.h"
-#include <QMessageBox>
-
-#ifndef Q_MOC_RUN
-#include <ndn-cpp-dev/security/validator.hpp>
-#include <boost/iostreams/stream.hpp>
-#include "endorse-collection.pb.h"
-#include "logging.h"
-#endif
-
-using namespace ndn;
-using namespace chronos;
-using namespace std;
-
-INIT_LOGGER("AddContactPanel");
-
-AddContactPanel::AddContactPanel(shared_ptr<ContactManager> contactManager,
- QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::AddContactPanel)
- , m_contactManager(contactManager)
- , m_warningDialog(new WarningDialog())
-{
- ui->setupUi(this);
-
- qRegisterMetaType<ndn::Name>("NdnName");
- qRegisterMetaType<chronos::EndorseCertificate>("EndorseCertificate");
- qRegisterMetaType<ndn::Data>("NdnData");
-
- connect(ui->cancelButton, SIGNAL(clicked()),
- this, SLOT(onCancelClicked()));
- connect(ui->searchButton, SIGNAL(clicked()),
- this, SLOT(onSearchClicked()));
- connect(ui->addButton, SIGNAL(clicked()),
- this, SLOT(onAddClicked()));
- connect(&*m_contactManager, SIGNAL(contactFetched(const chronos::EndorseCertificate&)),
- this, SLOT(selfEndorseCertificateFetched(const chronos::EndorseCertificate&)));
- connect(&*m_contactManager, SIGNAL(contactFetchFailed(const ndn::Name&)),
- this, SLOT(selfEndorseCertificateFetchFailed(const ndn::Name&)));
- connect(&*m_contactManager, SIGNAL(collectEndorseFetched(const ndn::Data&)),
- this, SLOT(onCollectEndorseFetched(const ndn::Data&)));
- connect(&*m_contactManager, SIGNAL(collectEndorseFetchFailed(const ndn::Name&)),
- this, SLOT(onCollectEndorseFetchFailed(const ndn::Name&)));
- connect(&*m_contactManager, SIGNAL(contactKeyFetched(const chronos::EndorseCertificate&)),
- this, SLOT(onContactKeyFetched(const chronos::EndorseCertificate&)));
- connect(&*m_contactManager, SIGNAL(contactKeyFetchFailed(const ndn::Name&)),
- this, SLOT(onContactKeyFetchFailed(const ndn::Name&)));
-
-
-}
-
-AddContactPanel::~AddContactPanel()
-{
- delete ui;
- delete m_warningDialog;
-}
-
-void
-AddContactPanel::onCancelClicked()
-{ this->close(); }
-
-void
-AddContactPanel::onSearchClicked()
-{
- m_currentEndorseCertificateReady = false;
- m_currentCollectEndorseReady = false;
- ui->infoView->clear();
- for(int i = ui->infoView->rowCount() - 1; i >= 0 ; i--)
- ui->infoView->removeRow(i);
- QString inputIdentity = ui->contactInput->text();
- m_searchIdentity = Name(inputIdentity.toStdString());
-
- if(Qt::Checked == ui->fetchBox->checkState())
- {
- m_contactManager->fetchSelfEndorseCertificate(m_searchIdentity);
- m_contactManager->fetchCollectEndorse(m_searchIdentity);
- }
- else
- {
- if(isCorrectName(m_searchIdentity))
- m_contactManager->fetchKey(m_searchIdentity);
- else
- {
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString("Wrong key certificate name!"));
- }
- }
-}
-
-bool
-AddContactPanel::isCorrectName(const Name& name)
-{
- if(name.get(-1).toEscapedString() != "ID-CERT")
- return false;
-
- int keyIndex = -1;
- for(int i = 0; i < name.size(); i++)
- {
- if(name.get(i).toEscapedString() == "KEY")
- {
- keyIndex = i;
- break;
- }
- }
-
- if(keyIndex < 0)
- return false;
- else
- return true;
-}
-
-void
-AddContactPanel::onAddClicked()
-{
- ContactItem contactItem(*m_currentEndorseCertificate);
- try{
- m_contactManager->getContactStorage()->addContact(contactItem);
- }catch(ContactStorage::Error& e){
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString(e.what()));
- _LOG_ERROR("Exception: " << e.what());
- return;
- }
- emit newContactAdded();
- this->close();
-}
-
-void
-AddContactPanel::selfEndorseCertificateFetched(const EndorseCertificate& endorseCertificate)
-{
-
- m_currentEndorseCertificate = make_shared<EndorseCertificate>(endorseCertificate);
-
- m_currentEndorseCertificateReady = true;
-
- if(m_currentCollectEndorseReady == true)
- displayContactInfo();
-}
-
-void
-AddContactPanel::selfEndorseCertificateFetchFailed(const Name& identity)
-{
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString("Cannot fetch contact profile"));
-}
-
-void
-AddContactPanel::onContactKeyFetched(const EndorseCertificate& endorseCertificate)
-{
- m_currentEndorseCertificate = make_shared<EndorseCertificate>(endorseCertificate);
-
- m_currentCollectEndorseReady = false;
-
- displayContactInfo();
-}
-
-void
-AddContactPanel::onContactKeyFetchFailed(const Name& identity)
-{
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString("Cannot fetch contact ksk certificate"));
-}
-
-void
-AddContactPanel::onCollectEndorseFetched(const Data& data)
-{
- m_currentCollectEndorse = make_shared<Data>(data);
-
- m_currentCollectEndorseReady = true;
-
- if(m_currentEndorseCertificateReady == true)
- displayContactInfo();
-}
-
-void
-AddContactPanel::onCollectEndorseFetchFailed(const Name& identity)
-{
- m_currentCollectEndorse = shared_ptr<Data>();
-
- m_currentCollectEndorseReady = true;
-
- if(m_currentEndorseCertificateReady == true)
- displayContactInfo();
-}
-
-void
-AddContactPanel::displayContactInfo()
-{
- // _LOG_TRACE("displayContactInfo");
- const Profile& profile = m_currentEndorseCertificate->getProfile();
-
- map<string, int> endorseCount;
-
- if(!static_cast<bool>(m_currentCollectEndorse))
- {
- Chronos::EndorseCollection endorseCollection;
-
- boost::iostreams::stream
- <boost::iostreams::array_source> is (reinterpret_cast<const char*>(m_currentCollectEndorse->getContent().value()),
- m_currentCollectEndorse->getContent().value_size());
-
- endorseCollection.ParseFromIstream(&is);
-
- for(int i = 0; i < endorseCollection.endorsement_size(); i ++)
- {
- try{
- Data data;
- data.wireDecode(Block(reinterpret_cast<const uint8_t*>(endorseCollection.endorsement(i).blob().c_str()),
- endorseCollection.endorsement(i).blob().size()));
- EndorseCertificate endorseCert(data);
-
- Name signerName = endorseCert.getSigner().getPrefix(-1);
-
- shared_ptr<ContactItem> contact = m_contactManager->getContact(signerName);
- if(!static_cast<bool>(contact))
- continue;
-
- if(!contact->isIntroducer() || !contact->canBeTrustedFor(m_currentEndorseCertificate->getProfile().getIdentityName()))
- continue;
-
- if(!Validator::verifySignature(data, data.getSignature(), contact->getSelfEndorseCertificate().getPublicKeyInfo()))
- continue;
-
- const Profile& tmpProfile = endorseCert.getProfile();
- if(!(profile == tmpProfile))
- continue;
-
- const vector<string>& endorseList = endorseCert.getEndorseList();
- vector<string>::const_iterator it = endorseList.begin();
- for(; it != endorseList.end(); it++)
- endorseCount[*it] += 1;
- }catch(std::runtime_error& e){
- continue;
- }
- }
- }
-
- ui->infoView->setColumnCount(3);
- Profile::const_iterator it = profile.begin();
- int rowCount = 0;
-
- QTableWidgetItem *typeHeader = new QTableWidgetItem(QString::fromUtf8("Type"));
- ui->infoView->setHorizontalHeaderItem(0, typeHeader);
- QTableWidgetItem *valueHeader = new QTableWidgetItem(QString::fromUtf8("Value"));
- ui->infoView->setHorizontalHeaderItem(1, valueHeader);
- QTableWidgetItem *endorseHeader = new QTableWidgetItem(QString::fromUtf8("Endorse"));
- ui->infoView->setHorizontalHeaderItem(2, endorseHeader);
-
- for(; it != profile.end(); it++)
- {
- ui->infoView->insertRow(rowCount);
- QTableWidgetItem *type = new QTableWidgetItem(QString::fromStdString(it->first));
- ui->infoView->setItem(rowCount, 0, type);
-
- QTableWidgetItem *value = new QTableWidgetItem(QString::fromStdString(it->second));
- ui->infoView->setItem(rowCount, 1, value);
-
- map<string, int>::iterator map_it = endorseCount.find(it->first);
- QTableWidgetItem *endorse = NULL;
- if(map_it == endorseCount.end())
- endorse = new QTableWidgetItem(QString::number(0));
- else
- endorse = new QTableWidgetItem(QString::number(map_it->second));
- ui->infoView->setItem(rowCount, 2, endorse);
-
- rowCount++;
- }
-}
-
-
-#if WAF
-#include "addcontactpanel.moc"
-#include "addcontactpanel.cpp.moc"
-#endif
diff --git a/src/addcontactpanel.h b/src/addcontactpanel.h
deleted file mode 100644
index a65635a..0000000
--- a/src/addcontactpanel.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef ADDCONTACTPANEL_H
-#define ADDCONTACTPANEL_H
-
-#include <QDialog>
-#include <QMetaType>
-#include "warningdialog.h"
-
-#ifndef Q_MOC_RUN
-#include "endorse-certificate.h"
-#include "profile.h"
-#include "contact-manager.h"
-#endif
-
-namespace Ui {
-class AddContactPanel;
-}
-
-Q_DECLARE_METATYPE(ndn::Name)
-
-Q_DECLARE_METATYPE(chronos::EndorseCertificate)
-
-Q_DECLARE_METATYPE(ndn::Data)
-
-class AddContactPanel : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit AddContactPanel(ndn::shared_ptr<chronos::ContactManager> contactManager,
- QWidget *parent = 0);
-
- ~AddContactPanel();
-
-private:
- void
- displayContactInfo();
-
- bool
- isCorrectName(const ndn::Name& name);
-
- // static bool
- // isSameBlob(const ndn::Blob& blobA, const ndn::Blob& blobB);
-
-private slots:
- void
- onCancelClicked();
-
- void
- onSearchClicked();
-
- void
- onAddClicked();
-
- void
- selfEndorseCertificateFetched(const chronos::EndorseCertificate& endorseCertificate);
-
- void
- selfEndorseCertificateFetchFailed(const ndn::Name& identity);
-
- void
- onContactKeyFetched(const chronos::EndorseCertificate& endorseCertificate);
-
- void
- onContactKeyFetchFailed(const ndn::Name& identity);
-
- void
- onCollectEndorseFetched(const ndn::Data& data);
-
- void
- onCollectEndorseFetchFailed(const ndn::Name& identity);
-
-signals:
- void
- newContactAdded();
-
-private:
-
- Ui::AddContactPanel *ui;
- ndn::Name m_searchIdentity;
- ndn::shared_ptr<chronos::ContactManager> m_contactManager;
- WarningDialog* m_warningDialog;
- ndn::shared_ptr<chronos::EndorseCertificate> m_currentEndorseCertificate;
- ndn::shared_ptr<ndn::Data> m_currentCollectEndorse;
- bool m_currentEndorseCertificateReady;
- bool m_currentCollectEndorseReady;
-};
-
-#endif // ADDCONTACTPANEL_H
diff --git a/src/addcontactpanel.ui b/src/addcontactpanel.ui
deleted file mode 100644
index fb6f4fa..0000000
--- a/src/addcontactpanel.ui
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>AddContactPanel</class>
- <widget class="QDialog" name="AddContactPanel">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>500</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Add Contact</string>
- </property>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>381</width>
- <height>481</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="addContactPanelLayout" stretch="1,25,0,1">
- <property name="spacing">
- <number>10</number>
- </property>
- <item>
- <layout class="QHBoxLayout" name="contactSearchLayout" stretch="1,5,2">
- <item>
- <widget class="QLabel" name="contactLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Contact:</string>
- </property>
- <property name="textFormat">
- <enum>Qt::AutoText</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="contactInput"/>
- </item>
- <item>
- <widget class="QPushButton" name="searchButton">
- <property name="text">
- <string>Fetch</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QTableWidget" name="infoView">
- <attribute name="horizontalHeaderStretchLastSection">
- <bool>true</bool>
- </attribute>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="fetchBox">
- <property name="text">
- <string>Fetch profile</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="buttonLayout">
- <item>
- <widget class="QPushButton" name="cancelButton">
- <property name="text">
- <string>Cancel</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="addButton">
- <property name="text">
- <string>Add</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/browse-contact-dialog.cpp b/src/browse-contact-dialog.cpp
new file mode 100644
index 0000000..5cf2ba9
--- /dev/null
+++ b/src/browse-contact-dialog.cpp
@@ -0,0 +1,136 @@
+/* -*- 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 "browse-contact-dialog.h"
+#include "ui_browse-contact-dialog.h"
+
+#ifndef Q_MOC_RUN
+#include "profile.h"
+#endif
+
+using namespace std;
+using namespace ndn;
+using namespace chronos;
+
+BrowseContactDialog::BrowseContactDialog(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::BrowseContactDialog)
+ , m_contactListModel(new QStringListModel)
+{
+ ui->setupUi(this);
+
+ m_typeHeader = new QTableWidgetItem(QString("Type"));
+ m_valueHeader = new QTableWidgetItem(QString("Value"));
+ ui->InfoTable->setHorizontalHeaderItem(0, m_typeHeader);
+ ui->InfoTable->setHorizontalHeaderItem(1, m_valueHeader);
+
+ ui->ContactList->setModel(m_contactListModel);
+
+ connect(ui->ContactList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+ this, SLOT(onSelectionChanged(const QItemSelection &, const QItemSelection &)));
+ connect(ui->AddButton, SIGNAL(clicked()),
+ this, SLOT(onAddClicked()));
+ connect(ui->DirectAddButton, SIGNAL(clicked()),
+ this, SLOT(onDirectAddClicked()));
+}
+
+BrowseContactDialog::~BrowseContactDialog()
+{
+ delete m_typeHeader;
+ delete m_valueHeader;
+ delete ui;
+}
+
+void
+BrowseContactDialog::onSelectionChanged(const QItemSelection& selected,
+ const QItemSelection& deselected)
+{
+ QModelIndexList items = selected.indexes();
+ QString certName = m_contactCertNameList[items.first().row()];
+ emit fetchIdCert(certName);
+}
+
+void
+BrowseContactDialog::onAddClicked()
+{
+ QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
+ QModelIndexList selectedList = selectionModel->selectedIndexes();
+ QModelIndexList::iterator it = selectedList.begin();
+ for(; it != selectedList.end(); it++)
+ emit addContact(m_contactNameList[it->row()]);
+
+ this->close();
+}
+
+void
+BrowseContactDialog::onDirectAddClicked()
+{
+ emit directAddClicked();
+ this->close();
+}
+
+void
+BrowseContactDialog::closeEvent(QCloseEvent *e)
+{
+ ui->InfoTable->clear();
+ for(int i = ui->InfoTable->rowCount() - 1; i >= 0 ; i--)
+ ui->InfoTable->removeRow(i);
+ ui->InfoTable->horizontalHeader()->hide();
+
+ hide();
+ e->ignore();
+}
+
+void
+BrowseContactDialog::onIdCertNameListReady(const QStringList& qCertNameList)
+{
+ m_contactCertNameList = qCertNameList;
+}
+
+void
+BrowseContactDialog::onNameListReady(const QStringList& qNameList)
+{
+ m_contactNameList = qNameList;
+ m_contactListModel->setStringList(m_contactNameList);
+}
+
+void
+BrowseContactDialog::onIdCertReady(const IdentityCertificate& idCert)
+{
+ Profile profile(idCert);
+
+ ui->InfoTable->clear();
+
+ for(int i = ui->InfoTable->rowCount() - 1; i >= 0 ; i--)
+ ui->InfoTable->removeRow(i);
+
+ ui->InfoTable->horizontalHeader()->show();
+ ui->InfoTable->setColumnCount(2);
+
+ Profile::const_iterator proIt = profile.begin();
+ Profile::const_iterator proEnd = profile.end();
+ int rowCount = 0;
+
+ for(; proIt != proEnd; proIt++, rowCount++)
+ {
+ ui->InfoTable->insertRow(rowCount);
+ QTableWidgetItem* type = new QTableWidgetItem(QString::fromStdString(proIt->first));
+ ui->InfoTable->setItem(rowCount, 0, type);
+
+ QTableWidgetItem* value = new QTableWidgetItem(QString::fromStdString(proIt->second));
+ ui->InfoTable->setItem(rowCount, 1, value);
+ }
+}
+
+#if WAF
+#include "browse-contact-dialog.moc"
+#include "browse-contact-dialog.cpp.moc"
+#endif
diff --git a/src/browse-contact-dialog.h b/src/browse-contact-dialog.h
new file mode 100644
index 0000000..f13770e
--- /dev/null
+++ b/src/browse-contact-dialog.h
@@ -0,0 +1,90 @@
+/* -*- 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>
+ */
+
+#ifndef BROWSE_CONTACT_DIALOG_H
+#define BROWSE_CONTACT_DIALOG_H
+
+#include <QDialog>
+#include <QStringListModel>
+#include <QCloseEvent>
+#include <QTableWidgetItem>
+
+#ifndef Q_MOC_RUN
+#include <ndn-cpp-dev/security/identity-certificate.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#endif
+
+namespace Ui {
+class BrowseContactDialog;
+}
+
+class BrowseContactDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit
+ BrowseContactDialog(QWidget *parent = 0);
+
+ ~BrowseContactDialog();
+
+protected:
+ void
+ closeEvent(QCloseEvent *e);
+
+private slots:
+ void
+ onSelectionChanged(const QItemSelection &selected,
+ const QItemSelection &deselected);
+
+ void
+ onAddClicked();
+
+ void
+ onDirectAddClicked();
+
+public slots:
+ void
+ onIdCertNameListReady(const QStringList& certNameList);
+
+ void
+ onNameListReady(const QStringList& nameList);
+
+ void
+ onIdCertReady(const ndn::IdentityCertificate& idCert);
+
+signals:
+ void
+ directAddClicked();
+
+ void
+ fetchIdCert(const QString& certName);
+
+ void
+ addContact(const QString& qCertName);
+
+private:
+
+ typedef boost::recursive_mutex RecLock;
+ typedef boost::unique_lock<RecLock> UniqueRecLock;
+
+ Ui::BrowseContactDialog *ui;
+
+ QTableWidgetItem* m_typeHeader;
+ QTableWidgetItem* m_valueHeader;
+
+ QStringListModel* m_contactListModel;
+
+ QStringList m_contactNameList;
+ QStringList m_contactCertNameList;
+};
+
+#endif // BROWSE_CONTACT_DIALOG_H
diff --git a/src/browse-contact-dialog.ui b/src/browse-contact-dialog.ui
new file mode 100644
index 0000000..1ef6355
--- /dev/null
+++ b/src/browse-contact-dialog.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BrowseContactDialog</class>
+ <widget class="QDialog" name="BrowseContactDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>BrowseContacts</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="20,1">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="2,3">
+ <item>
+ <widget class="QListView" name="ContactList">
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableWidget" name="InfoTable">
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0">
+ <item>
+ <widget class="QPushButton" name="AddButton">
+ <property name="text">
+ <string>Add </string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="DirectAddButton">
+ <property name="text">
+ <string>Direct Add</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/browsecontactdialog.cpp b/src/browsecontactdialog.cpp
deleted file mode 100644
index ba0664d..0000000
--- a/src/browsecontactdialog.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/* -*- 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 "browsecontactdialog.h"
-#include "ui_browsecontactdialog.h"
-#include <QMessageBox>
-
-#ifndef Q_MOC_RUN
-#include <boost/asio.hpp>
-#include <boost/tokenizer.hpp>
-#include "logging.h"
-#endif
-
-using namespace std;
-using namespace ndn;
-using namespace chronos;
-
-INIT_LOGGER("BrowseContactDialog");
-
-// Q_DECLARE_METATYPE(ndn::security::IdentityCertificate)
-
-BrowseContactDialog::BrowseContactDialog(shared_ptr<ContactManager> contactManager,
- QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::BrowseContactDialog)
- , m_contactManager(contactManager)
- , m_warningDialog(new WarningDialog)
- , m_contactListModel(new QStringListModel)
-{
- // qRegisterMetaType<ndn::security::IdentityCertificate>("NDNIdentityCertificate");
-
- ui->setupUi(this);
-
- ui->ContactList->setModel(m_contactListModel);
-
- connect(ui->ContactList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
- this, SLOT(updateSelection(const QItemSelection &, const QItemSelection &)));
- connect(&*m_contactManager, SIGNAL(contactCertificateFetched(const ndn::IdentityCertificate &)),
- this, SLOT(onCertificateFetched(const ndn::IdentityCertificate &)));
- connect(&*m_contactManager, SIGNAL(contactCertificateFetchFailed(const ndn::Name&)),
- this, SLOT(onCertificateFetchFailed(const ndn::Name&)));
- connect(&*m_contactManager, SIGNAL(warning(QString)),
- this, SLOT(onWarning(QString)));
-
- connect(ui->AddButton, SIGNAL(clicked()),
- this, SLOT(onAddClicked()));
-
- connect(ui->DirectAddButton, SIGNAL(clicked()),
- this, SLOT(onDirectAddClicked()));
-}
-
-BrowseContactDialog::~BrowseContactDialog()
-{
- delete ui;
-}
-
-
-void
-BrowseContactDialog::getCertNames(vector<string> &names)
-{
- 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)
- {
- QMessageBox::information(this, tr("Chronos"), 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)
- {
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString("Fail to fetch certificate directory! #2"));
- return;
- }
-
- std::stringstream response_stream(line1);
- std::string http_version;
- response_stream >> http_version;
- unsigned int status_code;
- response_stream >> status_code;
- std::string status_message;
- std::getline(response_stream,status_message);
-
- if (!response_stream||http_version.substr(0,5)!="HTTP/")
- {
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString("Fail to fetch certificate directory! #3"));
- return;
- }
- if (status_code!=200)
- {
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString("Fail to fetch certificate directory! #4"));
- return;
- }
- vector<string> headers;
- std::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())
- {
- names.push_back(*it);
- }
- }
- }catch(std::exception &e){
- QMessageBox::information(this, tr("Chronos"), QString::fromStdString("Fail to fetch certificate directory! #N"));
- }
-}
-
-void
-BrowseContactDialog::updateCertificateMap(bool filter)
-{
- vector<string> certNameList;
- getCertNames(certNameList);
- _LOG_DEBUG("Get Certificate Name List");
- for(int i = 0; i < certNameList.size(); i++)
- {
- _LOG_DEBUG(" " << certNameList[i]);
- }
-
- if(filter)
- {
- map<Name, Name> certificateMap;
-
- vector<string>::iterator it = certNameList.begin();
-
- for(; it != certNameList.end(); it++)
- {
- Name newCertName(*it);
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(newCertName);
- Name identity = keyName.getPrefix(-1);
-
- map<Name, Name>::iterator map_it = certificateMap.find(identity);
- if(map_it != certificateMap.end())
- {
- Name oldCertName = map_it->second;
- Name oldKeyName = IdentityCertificate::certificateNameToPublicKeyName(oldCertName);
- if(keyName.get(-1).toEscapedString() > oldKeyName.get(-1).toEscapedString())
- map_it->second = newCertName;
- else if(keyName == oldKeyName && newCertName.get(-1).toVersion() > oldCertName.get(-1).toVersion())
- map_it->second = newCertName;
- }
- else
- {
- certificateMap.insert(pair<Name, Name>(identity, newCertName));
- }
- }
- map<Name, Name>::iterator map_it = certificateMap.begin();
- for(; map_it != certificateMap.end(); map_it++)
- m_certificateNameList.push_back(map_it->second);
- }
- else
- {
- vector<string>::iterator it = certNameList.begin();
-
- for(; it != certNameList.end(); it++)
- {
- m_certificateNameList.push_back(Name (*it));
- // try {
- // m_certificateNameList.push_back(Name (*it));
- // }
- // catch(error::Name)
- // {
- // _LOG_ERROR ("Error parsing: [" << *it << "]");
- // }
- // catch(error::name::Component)
- // {
- // _LOG_ERROR ("Error parsing: [" << *it << "]");
- // }
- }
- }
-}
-
-void
-BrowseContactDialog::fetchCertificate()
-{
- vector<Name>::iterator it = m_certificateNameList.begin();
- int count = 0;
- for(; it != m_certificateNameList.end(); it++)
- {
- _LOG_DEBUG("fetch " << it->toUri());
- usleep(1000);
- m_contactManager->fetchIdCertificate(*it);
- }
-}
-
-void
-BrowseContactDialog::onCertificateFetched(const IdentityCertificate& identityCertificate)
-{
- Name certNameNoVersion = identityCertificate.getName().getPrefix(-1);
- _LOG_DEBUG("Fetch: " << certNameNoVersion.toUri());
- m_certificateMap.insert(pair<Name, IdentityCertificate>(certNameNoVersion, identityCertificate));
- m_profileMap.insert(pair<Name, Profile>(certNameNoVersion, Profile(identityCertificate)));
- string name = m_profileMap[certNameNoVersion].get("name");
- // Name contactName = m_profileMap[certNameNoVersion].getIdentityName();
- {
- UniqueRecLock lock(m_mutex);
- m_contactList << QString::fromStdString(name);
- m_contactListModel->setStringList(m_contactList);
- m_contactNameList.push_back(certNameNoVersion);
- }
-}
-
-void
-BrowseContactDialog::onCertificateFetchFailed(const Name& identity)
-{
- _LOG_DEBUG("Cannot fetch " << identity.toUri());
-}
-
-void
-BrowseContactDialog::refreshList()
-{
- {
- UniqueRecLock lock(m_mutex);
- m_contactList.clear();
- m_contactNameList.clear();
- }
- m_certificateNameList.clear();
- m_certificateMap.clear();
- m_profileMap.clear();
-
- updateCertificateMap();
-
- fetchCertificate();
-}
-
-void
-BrowseContactDialog::updateSelection(const QItemSelection& selected,
- const QItemSelection& deselected)
-{
- QModelIndexList items = selected.indexes();
- Name certName = m_contactNameList[items.first().row()];
-
- ui->InfoTable->clear();
- for(int i = ui->InfoTable->rowCount() - 1; i >= 0 ; i--)
- ui->InfoTable->removeRow(i);
-
- ui->InfoTable->horizontalHeader()->show();
-
- map<Name, Profile>::iterator it = m_profileMap.find(certName);
- if(it != m_profileMap.end())
- {
- ui->InfoTable->setColumnCount(2);
-
- QTableWidgetItem *typeHeader = new QTableWidgetItem(QString::fromUtf8("Type"));
- ui->InfoTable->setHorizontalHeaderItem(0, typeHeader);
- QTableWidgetItem *valueHeader = new QTableWidgetItem(QString::fromUtf8("Value"));
- ui->InfoTable->setHorizontalHeaderItem(1, valueHeader);
-
- Profile::const_iterator pro_it = it->second.begin();
- int rowCount = 0;
-
- for(; pro_it != it->second.end(); pro_it++, rowCount++)
- {
- ui->InfoTable->insertRow(rowCount);
- QTableWidgetItem *type = new QTableWidgetItem(QString::fromStdString(pro_it->first));
- ui->InfoTable->setItem(rowCount, 0, type);
-
- QTableWidgetItem *value = new QTableWidgetItem(QString::fromStdString(pro_it->second));
- ui->InfoTable->setItem(rowCount, 1, value);
- }
- }
-}
-
-void
-BrowseContactDialog::onWarning(QString msg)
-{
- m_warningDialog->setMsg(msg.toStdString());
- m_warningDialog->show();
-}
-
-void
-BrowseContactDialog::onAddClicked()
-{
- QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
- QModelIndexList selectedList = selectionModel->selectedIndexes();
- QModelIndexList::iterator it = selectedList.begin();
- for(; it != selectedList.end(); it++)
- {
- Name certName = m_contactNameList[it->row()];
- if(m_certificateMap.find(certName) != m_certificateMap.end() && m_profileMap.find(certName) != m_profileMap.end())
- m_contactManager->addContact(m_certificateMap[certName], m_profileMap[certName]);
- else
- {
- m_warningDialog->setMsg("Not enough information to add contact!");
- m_warningDialog->show();
- }
- }
- emit newContactAdded();
- this->close();
-}
-
-void
-BrowseContactDialog::onDirectAddClicked()
-{
- emit directAddClicked();
- this->close();
-}
-
-void
-BrowseContactDialog::closeEvent(QCloseEvent *e)
-{
- ui->InfoTable->clear();
- for(int i = ui->InfoTable->rowCount() - 1; i >= 0 ; i--)
- ui->InfoTable->removeRow(i);
- ui->InfoTable->horizontalHeader()->hide();
-
- hide();
- e->ignore();
-}
-
-#if WAF
-#include "browsecontactdialog.moc"
-#include "browsecontactdialog.cpp.moc"
-#endif
diff --git a/src/browsecontactdialog.h b/src/browsecontactdialog.h
deleted file mode 100644
index 5cd610f..0000000
--- a/src/browsecontactdialog.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- 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>
- */
-
-
-#ifndef BROWSECONTACTDIALOG_H
-#define BROWSECONTACTDIALOG_H
-
-#include <QDialog>
-#include <QStringListModel>
-#include <QCloseEvent>
-#include "warningdialog.h"
-
-
-#ifndef Q_MOC_RUN
-#include <ndn-cpp-dev/security/identity-certificate.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/recursive_mutex.hpp>
-#include "profile.h"
-#include "contact-manager.h"
-#endif
-
-namespace Ui {
-class BrowseContactDialog;
-}
-
-class BrowseContactDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit BrowseContactDialog(ndn::shared_ptr<chronos::ContactManager> contactManager,
- QWidget *parent = 0);
-
- ~BrowseContactDialog();
-
-protected:
- typedef boost::recursive_mutex RecLock;
- typedef boost::unique_lock<RecLock> UniqueRecLock;
-
-private:
- void
- getCertNames(std::vector<std::string>& names);
-
- void
- updateCertificateMap(bool filter = false);
-
- void
- updateCertificateFetchingStatus(int count);
-
- void
- fetchCertificate();
-
-protected:
- void
- closeEvent(QCloseEvent *e);
-
-private slots:
- void
- updateSelection(const QItemSelection &selected,
- const QItemSelection &deselected);
-
- void
- onCertificateFetched(const ndn::IdentityCertificate& identityCertificate);
-
- void
- onCertificateFetchFailed(const ndn::Name& identity);
-
- void
- onWarning(QString msg);
-
- void
- onAddClicked();
-
- void
- onDirectAddClicked();
-
-public slots:
- void
- refreshList();
-
-signals:
- void
- newContactAdded();
-
- void
- directAddClicked();
-
-private:
- Ui::BrowseContactDialog *ui;
-
- ndn::shared_ptr<chronos::ContactManager> m_contactManager;
-
- WarningDialog* m_warningDialog;
- QStringListModel* m_contactListModel;
-
- QStringList m_contactList;
- std::vector<ndn::Name> m_contactNameList;
- std::vector<ndn::Name> m_certificateNameList;
- std::map<ndn::Name, ndn::IdentityCertificate> m_certificateMap;
- std::map<ndn::Name, chronos::Profile> m_profileMap;
-
- RecLock m_mutex;
-};
-
-#endif // BROWSECONTACTDIALOG_H
diff --git a/src/browsecontactdialog.ui b/src/browsecontactdialog.ui
deleted file mode 100644
index 2c73de9..0000000
--- a/src/browsecontactdialog.ui
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>BrowseContactDialog</class>
- <widget class="QDialog" name="BrowseContactDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>600</width>
- <height>480</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>BrowseContacts</string>
- </property>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>12</x>
- <y>10</y>
- <width>581</width>
- <height>471</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout" stretch="20,1">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout" stretch="2,3">
- <item>
- <widget class="QListView" name="ContactList">
- <property name="contextMenuPolicy">
- <enum>Qt::CustomContextMenu</enum>
- </property>
- <property name="acceptDrops">
- <bool>false</bool>
- </property>
- <property name="editTriggers">
- <set>QAbstractItemView::NoEditTriggers</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTableWidget" name="InfoTable">
- <attribute name="horizontalHeaderStretchLastSection">
- <bool>true</bool>
- </attribute>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0">
- <item>
- <widget class="QPushButton" name="AddButton">
- <property name="text">
- <string>Add </string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="DirectAddButton">
- <property name="text">
- <string>Direct Add</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/chat-dialog.cpp b/src/chat-dialog.cpp
new file mode 100644
index 0000000..954a4c6
--- /dev/null
+++ b/src/chat-dialog.cpp
@@ -0,0 +1,1174 @@
+/* -*- 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: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include "chat-dialog.h"
+#include "ui_chat-dialog.h"
+
+#include <QScrollBar>
+#include <QMessageBox>
+#include <QCloseEvent>
+
+#ifndef Q_MOC_RUN
+#include <sync-intro-certificate.h>
+#include <boost/random/random_device.hpp>
+#include <boost/random/uniform_int_distribution.hpp>
+#include <ndn-cpp-dev/util/random.hpp>
+#include <cryptopp/hex.h>
+#include <cryptopp/files.h>
+#include "logging.h"
+#endif
+
+using namespace std;
+using namespace ndn;
+using namespace chronos;
+
+INIT_LOGGER("ChatDialog");
+
+static const int HELLO_INTERVAL = FRESHNESS * 3 / 4;
+static const uint8_t CHRONOS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.
+
+Q_DECLARE_METATYPE(std::vector<Sync::MissingDataInfo> )
+Q_DECLARE_METATYPE(ndn::Data)
+Q_DECLARE_METATYPE(ndn::Interest)
+Q_DECLARE_METATYPE(size_t)
+
+ChatDialog::ChatDialog(ContactManager* contactManager,
+ shared_ptr<Face> face,
+ const IdentityCertificate& myCertificate,
+ const Name& chatroomPrefix,
+ const Name& localPrefix,
+ const string& nick,
+ bool withSecurity,
+ QWidget* parent)
+ : QDialog(parent)
+ , ui(new Ui::ChatDialog)
+ , m_contactManager(contactManager)
+ , m_face(face)
+ , m_myCertificate(myCertificate)
+ , m_chatroomName(chatroomPrefix.get(-1).toEscapedString())
+ , m_chatroomPrefix(chatroomPrefix)
+ , m_localPrefix(localPrefix)
+ , m_useRoutablePrefix(false)
+ , m_nick(nick)
+ , m_lastMsgTime(time::now())
+ , m_joined(false)
+ , m_sock(NULL)
+ , m_session(static_cast<uint64_t>(time::now()))
+ , m_inviteListDialog(new InviteListDialog)
+{
+ qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
+ qRegisterMetaType<ndn::Data>("ndn.Data");
+ qRegisterMetaType<ndn::Interest>("ndn.Interest");
+ qRegisterMetaType<size_t>("size_t");
+
+ m_scene = new DigestTreeScene(this);
+ m_rosterModel = new QStringListModel(this);
+ m_timer = new QTimer(this);
+
+ ui->setupUi(this);
+ ui->treeViewer->setScene(m_scene);
+ m_scene->setSceneRect(m_scene->itemsBoundingRect());
+ ui->treeViewer->hide();
+ ui->listView->setModel(m_rosterModel);
+
+ m_identity = IdentityCertificate::certificateNameToPublicKeyName(m_myCertificate.getName()).getPrefix(-1);
+ updatePrefix();
+ updateLabels();
+
+ m_scene->setCurrentPrefix(QString(m_localChatPrefix.toUri().c_str()));
+ m_scene->plot("Empty");
+
+ connect(ui->lineEdit, SIGNAL(returnPressed()),
+ this, SLOT(onReturnPressed()));
+ connect(ui->treeButton, SIGNAL(pressed()),
+ this, SLOT(onTreeButtonPressed()));
+ connect(m_scene, SIGNAL(replot()),
+ this, SLOT(onReplot()));
+ connect(m_scene, SIGNAL(rosterChanged(QStringList)),
+ this, SLOT(onRosterChanged(QStringList)));
+ connect(m_timer, SIGNAL(timeout()),
+ this, SLOT(onReplot()));
+
+ connect(this, SIGNAL(processData(const ndn::Data&, bool, bool)),
+ this, SLOT(onProcessData(const ndn::Data&, bool, bool)));
+ connect(this, SIGNAL(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)),
+ this, SLOT(onProcessTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
+ connect(this, SIGNAL(reply(const ndn::Interest&, const ndn::Data&, size_t, bool)),
+ this, SLOT(onReply(const ndn::Interest&, const ndn::Data&, size_t, bool)));
+ connect(this, SIGNAL(replyTimeout(const ndn::Interest&, size_t)),
+ this, SLOT(onReplyTimeout(const ndn::Interest&, size_t)));
+ connect(this, SIGNAL(introCert(const ndn::Interest&, const ndn::Data&)),
+ this, SLOT(onIntroCert(const ndn::Interest&, const ndn::Data&)));
+ connect(this, SIGNAL(introCertTimeout(const ndn::Interest&, int, const QString&)),
+ this, SLOT(onIntroCertTimeout(const ndn::Interest&, int, const QString&)));
+
+ if(withSecurity)
+ {
+
+ m_invitationValidator = make_shared<chronos::ValidatorInvitation>();
+ m_dataRule = make_shared<SecRuleRelative>("([^<CHRONOCHAT-DATA>]*)<CHRONOCHAT-DATA><>",
+ "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
+ "==", "\\1", "\\1", true);
+
+ ui->inviteButton->setEnabled(true);
+ connect(ui->inviteButton, SIGNAL(clicked()),
+ this, SLOT(onInviteListDialogRequested()));
+ connect(m_inviteListDialog, SIGNAL(sendInvitation(const QString&)),
+ this, SLOT(onSendInvitation(const QString&)));
+ connect(m_contactManager, SIGNAL(contactAliasListReady(const QStringList&)),
+ m_inviteListDialog, SLOT(onContactAliasListReady(const QStringList&)));
+ connect(m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
+ m_inviteListDialog, SLOT(onContactIdListReady(const QStringList&)));
+ }
+
+ initializeSync();
+}
+
+
+ChatDialog::~ChatDialog()
+{
+ if(m_certListPrefixId)
+ m_face->unsetInterestFilter(m_certListPrefixId);
+
+ if(m_certSinglePrefixId)
+ m_face->unsetInterestFilter(m_certSinglePrefixId);
+
+ if(m_sock != NULL)
+ {
+ sendLeave();
+ delete m_sock;
+ m_sock = NULL;
+ }
+}
+
+// public methods:
+void
+ChatDialog::addSyncAnchor(const Invitation& invitation)
+{
+ // Add inviter certificate as trust anchor.
+ m_sock->addParticipant(invitation.getInviterCertificate());
+
+ // Ask inviter for IntroCertificate
+ Name inviterNameSpace = IdentityCertificate::certificateNameToPublicKeyName(invitation.getInviterCertificate().getName()).getPrefix(-1);
+ fetchIntroCert(inviterNameSpace, invitation.getInviterRoutingPrefix());
+}
+
+void
+ChatDialog::processTreeUpdateWrapper(const vector<Sync::MissingDataInfo>& v, Sync::SyncSocket *sock)
+{
+ emit processTreeUpdate(v);
+ _LOG_DEBUG("<<< Tree update signal emitted");
+}
+
+void
+ChatDialog::processDataWrapper(const shared_ptr<const Data>& data)
+{
+ emit processData(*data, true, false);
+ _LOG_DEBUG("<<< " << data->getName() << " fetched");
+}
+
+void
+ChatDialog::processDataNoShowWrapper(const shared_ptr<const Data>& data)
+{
+ emit processData(*data, false, false);
+}
+
+void
+ChatDialog::processRemoveWrapper(string prefix)
+{
+ _LOG_DEBUG("Sync REMOVE signal received for prefix: " << prefix);
+}
+
+// protected methods:
+void
+ChatDialog::closeEvent(QCloseEvent *e)
+{
+ QMessageBox::information(this, tr("ChronoChat"),
+ tr("The chatroom will keep running in the "
+ "system tray. To close the chatroom, "
+ "choose <b>Close chatroom</b> in the "
+ "context memu of the system tray entry."));
+ hide();
+ e->ignore();
+}
+
+void
+ChatDialog::resizeEvent(QResizeEvent *e)
+{
+ fitView();
+}
+
+void
+ChatDialog::showEvent(QShowEvent *e)
+{
+ fitView();
+}
+
+// private methods:
+void
+ChatDialog::updatePrefix()
+{
+ m_certListPrefix.clear();
+ m_certSinglePrefix.clear();
+ m_localChatPrefix.clear();
+ m_chatPrefix.clear();
+ m_chatPrefix.append(m_identity).append("CHRONOCHAT-DATA").append(m_chatroomName).append(getRandomString());
+ if(!m_localPrefix.isPrefixOf(m_identity))
+ {
+ m_useRoutablePrefix = true;
+ m_certListPrefix.append(m_localPrefix).append(CHRONOS_RP_SEPARATOR, 2);
+ m_certSinglePrefix.append(m_localPrefix).append(CHRONOS_RP_SEPARATOR, 2);
+ m_localChatPrefix.append(m_localPrefix).append(CHRONOS_RP_SEPARATOR, 2);
+ }
+ m_certListPrefix.append(m_identity).append("CHRONOCHAT-CERT-LIST").append(m_chatroomName);
+ m_certSinglePrefix.append(m_identity).append("CHRONOCHAT-CERT-SINGLE").append(m_chatroomName);
+ m_localChatPrefix.append(m_chatPrefix);
+
+ if(m_certListPrefixId)
+ m_face->unsetInterestFilter(m_certListPrefixId);
+ m_certListPrefixId = m_face->setInterestFilter (m_certListPrefix,
+ bind(&ChatDialog::onCertListInterest, this, _1, _2),
+ bind(&ChatDialog::onCertListRegisterFailed, this, _1, _2));
+
+ if(m_certSinglePrefixId)
+ m_face->unsetInterestFilter(m_certSinglePrefixId);
+ m_certSinglePrefixId = m_face->setInterestFilter (m_certSinglePrefix,
+ bind(&ChatDialog::onCertSingleInterest, this, _1, _2),
+ bind(&ChatDialog::onCertSingleRegisterFailed, this, _1, _2));
+}
+
+void
+ChatDialog::updateLabels()
+{
+ QString settingDisp = QString("Chatroom: %1").arg(QString::fromStdString(m_chatroomName));
+ ui->infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
+ ui->infoLabel->setText(settingDisp);
+ QString prefixDisp;
+ Name privatePrefix("/private/local");
+ if(privatePrefix.isPrefixOf(m_localChatPrefix))
+ {
+ prefixDisp =
+ QString("<Warning: no connection to hub or hub does not support prefix autoconfig.>\n <Prefix = %1>")
+ .arg(QString::fromStdString(m_localChatPrefix.toUri()));
+ ui->prefixLabel->setStyleSheet("QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
+ }
+ else
+ {
+ prefixDisp = QString("<Prefix = %1>")
+ .arg(QString::fromStdString(m_localChatPrefix.toUri()));
+ ui->prefixLabel->setStyleSheet("QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
+ }
+ ui->prefixLabel->setText(prefixDisp);
+}
+
+void
+ChatDialog::initializeSync()
+{
+
+ m_sock = new Sync::SyncSocket(m_chatroomPrefix,
+ m_chatPrefix,
+ m_session,
+ m_useRoutablePrefix,
+ m_localPrefix,
+ m_face,
+ m_myCertificate,
+ m_dataRule,
+ bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
+ bind(&ChatDialog::processRemoveWrapper, this, _1));
+
+ usleep(100000);
+
+ QTimer::singleShot(600, this, SLOT(sendJoin()));
+ m_timer->start(FRESHNESS * 1000);
+ disableTreeDisplay();
+ QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
+}
+
+void
+ChatDialog::sendInvitation(shared_ptr<Contact> contact, bool isIntroducer)
+{
+ // Add invitee as a trust anchor.
+ m_invitationValidator->addTrustAnchor(contact->getPublicKeyName(),
+ contact->getPublicKey());
+
+ // Prepared an invitation interest without routable prefix.
+ Invitation invitation(contact->getNameSpace(),
+ m_chatroomName,
+ m_localPrefix,
+ m_myCertificate);
+ Interest tmpInterest(invitation.getUnsignedInterestName());
+ m_keyChain.sign(tmpInterest, m_myCertificate.getName());
+
+ // Get invitee's routable prefix (ideally it will do some DNS lookup, but we assume everyone use /ndn/broadcast
+ Name routablePrefix = getInviteeRoutablePrefix(contact->getNameSpace());
+
+ // Check if we need to prepend the routable prefix to the interest name.
+ bool requireRoutablePrefix = false;
+ Name interestName;
+ size_t routablePrefixOffset = 0;
+ if(!routablePrefix.isPrefixOf(tmpInterest.getName()))
+ {
+ interestName.append(routablePrefix).append(CHRONOS_RP_SEPARATOR, 2);
+ requireRoutablePrefix = true;
+ routablePrefixOffset = routablePrefix.size() + 1;
+ }
+ interestName.append(tmpInterest.getName());
+
+ // Send the invitation out
+ Interest interest(interestName);
+ interest.setMustBeFresh(true);
+ m_face->expressInterest(interest,
+ bind(&ChatDialog::replyWrapper, this, _1, _2, routablePrefixOffset, isIntroducer),
+ bind(&ChatDialog::replyTimeoutWrapper, this, _1, routablePrefixOffset));
+}
+
+void
+ChatDialog::replyWrapper(const Interest& interest,
+ Data& data,
+ size_t routablePrefixOffset,
+ bool isIntroducer)
+{
+ emit reply(interest, data, routablePrefixOffset, isIntroducer);
+}
+
+void
+ChatDialog::replyTimeoutWrapper(const Interest& interest,
+ size_t routablePrefixOffset)
+{
+ emit replyTimeout(interest, routablePrefixOffset);
+}
+
+void
+ChatDialog::onReplyValidated(const shared_ptr<const Data>& data,
+ size_t inviteeRoutablePrefixOffset,
+ bool isIntroducer)
+{
+ if(data->getName().size() <= inviteeRoutablePrefixOffset)
+ {
+ Invitation invitation(data->getName());
+ invitationRejected(invitation.getInviteeNameSpace());
+ }
+ else
+ {
+ Name inviteePrefix;
+ inviteePrefix.wireDecode(data->getName().get(inviteeRoutablePrefixOffset).blockFromValue());
+ IdentityCertificate inviteeCert;
+ inviteeCert.wireDecode(data->getContent().blockFromValue());
+ invitationAccepted(inviteeCert, inviteePrefix, isIntroducer);
+ }
+}
+
+void
+ChatDialog::onReplyValidationFailed(const shared_ptr<const Data>& data,
+ const string& failureInfo)
+{
+ _LOG_DEBUG("Invitation reply cannot be validated: " + failureInfo + " ==> " + data->getName().toUri());
+}
+
+void
+ChatDialog::invitationRejected(const Name& identity)
+{
+ QString msg = QString::fromStdString(identity.toUri()) + " rejected your invitation!";
+ emit inivationRejection(msg);
+}
+
+void
+ChatDialog::invitationAccepted(const IdentityCertificate& inviteeCert,
+ const Name& inviteePrefix,
+ bool isIntroducer)
+{
+ // Add invitee certificate as trust anchor.
+ m_sock->addParticipant(inviteeCert);
+
+ // Ask invitee for IntroCertificate.
+ Name inviteeNameSpace = IdentityCertificate::certificateNameToPublicKeyName(inviteeCert.getName()).getPrefix(-1);
+ fetchIntroCert(inviteeNameSpace, inviteePrefix);
+}
+
+void
+ChatDialog::fetchIntroCert(const Name& identity, const Name& prefix)
+{
+ Name interestName;
+
+ if(!prefix.isPrefixOf(identity))
+ interestName.append(prefix).append(CHRONOS_RP_SEPARATOR, 2);
+
+ interestName.append(identity)
+ .append("CHRONOCHAT-CERT-LIST")
+ .append(m_chatroomName)
+ .appendVersion();
+
+ Interest interest(interestName);
+ interest.setMustBeFresh(true);
+
+ m_face->expressInterest(interest,
+ bind(&ChatDialog::onIntroCertList, this, _1, _2),
+ bind(&ChatDialog::onIntroCertListTimeout, this, _1, 1,
+ "IntroCertList: " + interestName.toUri()));
+}
+
+void
+ChatDialog::onIntroCertList(const Interest& interest, const Data& data)
+{
+ Chronos::IntroCertListMsg introCertList;
+ if(!introCertList.ParseFromArray(data.getContent().value(), data.getContent().value_size()))
+ return;
+
+ for(int i = 0; i < introCertList.certname_size(); i++)
+ {
+ Name certName(introCertList.certname(i));
+ Interest interest(certName);
+ interest.setMustBeFresh(true);
+
+ m_face->expressInterest(interest,
+ bind(&ChatDialog::introCertWrapper, this, _1, _2),
+ bind(&ChatDialog::introCertTimeoutWrapper, this, _1, 0,
+ QString("IntroCert: %1").arg(introCertList.certname(i).c_str())));
+ }
+}
+
+void
+ChatDialog::onIntroCertListTimeout(const Interest& interest, int retry, const string& msg)
+{
+ if(retry > 0)
+ m_face->expressInterest(interest,
+ bind(&ChatDialog::onIntroCertList, this, _1, _2),
+ bind(&ChatDialog::onIntroCertListTimeout, this, _1, retry - 1, msg));
+ else
+ _LOG_DEBUG(msg << " TIMEOUT!");
+}
+
+void
+ChatDialog::introCertWrapper(const Interest& interest, Data& data)
+{
+ emit introCert(interest, data);
+}
+
+void
+ChatDialog::introCertTimeoutWrapper(const Interest& interest, int retry, const QString& msg)
+{
+ emit introCertTimeout(interest, retry, msg);
+}
+
+void
+ChatDialog::onCertListInterest(const Name& prefix, const ndn::Interest& interest)
+{
+ vector<Name> certNameList;
+ m_sock->getIntroCertNames(certNameList);
+
+ Chronos::IntroCertListMsg msg;
+
+ vector<Name>::const_iterator it = certNameList.begin();
+ vector<Name>::const_iterator end = certNameList.end();
+ for(; it != end; it++)
+ {
+ Name certName;
+ certName.append(m_certSinglePrefix).append(*it);
+ msg.add_certname(certName.toUri());
+ }
+ OBufferStream os;
+ msg.SerializeToOstream(&os);
+
+ Data data(interest.getName());
+ data.setContent(os.buf());
+ m_keyChain.sign(data, m_myCertificate.getName());
+
+ m_face->put(data);
+}
+
+void
+ChatDialog::onCertListRegisterFailed(const Name& prefix, const string& msg)
+{
+ _LOG_DEBUG("ChatDialog::onCertListRegisterFailed failed: " + msg);
+}
+
+void
+ChatDialog::onCertSingleInterest(const Name& prefix, const ndn::Interest& interest)
+{
+ try
+ {
+ Name certName = interest.getName().getSubName(prefix.size());
+ const Sync::IntroCertificate& introCert = m_sock->getIntroCertificate(certName);
+ Data data(interest.getName());
+ data.setContent(introCert.wireEncode());
+ m_face->put(data);
+ }
+ catch(Sync::SyncSocket::Error& e)
+ {
+ return;
+ }
+}
+
+void
+ChatDialog::onCertSingleRegisterFailed(const Name& prefix, const string& msg)
+{
+ _LOG_DEBUG("ChatDialog::onCertListRegisterFailed failed: " + msg);
+}
+
+void
+ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
+{
+ // send msg
+ OBufferStream os;
+ msg.SerializeToOstream(&os);
+
+ if (!msg.IsInitialized())
+ {
+ _LOG_DEBUG("Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?");
+ abort();
+ }
+ m_sock->publishData(os.buf()->buf(), os.buf()->size(), FRESHNESS);
+
+ m_lastMsgTime = time::now();
+
+ uint64_t nextSequence = m_sock->getNextSeq();
+ Sync::MissingDataInfo mdi = {m_localChatPrefix.toUri(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
+ std::vector<Sync::MissingDataInfo> v;
+ v.push_back(mdi);
+ {
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
+ m_scene->msgReceived(QString::fromStdString(m_localChatPrefix.toUri()),
+ QString::fromStdString(m_nick));
+ }
+}
+
+void ChatDialog::disableTreeDisplay()
+{
+ ui->treeButton->setEnabled(false);
+ ui->treeViewer->hide();
+ fitView();
+}
+
+void
+ChatDialog::appendMessage(const SyncDemo::ChatMessage msg, bool isHistory)
+{
+ boost::recursive_mutex::scoped_lock lock(m_msgMutex);
+
+ if (msg.type() == SyncDemo::ChatMessage::CHAT)
+ {
+
+ if (!msg.has_data())
+ {
+ return;
+ }
+
+ if (msg.from().empty() || msg.data().empty())
+ {
+ return;
+ }
+
+ if (!msg.has_timestamp())
+ {
+ return;
+ }
+
+ // if (m_history.size() == MAX_HISTORY_ENTRY)
+ // {
+ // m_history.dequeue();
+ // }
+
+ // m_history.enqueue(msg);
+
+ QTextCharFormat nickFormat;
+ nickFormat.setForeground(Qt::darkGreen);
+ nickFormat.setFontWeight(QFont::Bold);
+ nickFormat.setFontUnderline(true);
+ nickFormat.setUnderlineColor(Qt::gray);
+
+ QTextCursor cursor(ui->textEdit->textCursor());
+ cursor.movePosition(QTextCursor::End);
+ QTextTableFormat tableFormat;
+ tableFormat.setBorder(0);
+ QTextTable *table = cursor.insertTable(1, 2, tableFormat);
+ QString from = QString("%1 ").arg(msg.from().c_str());
+ QTextTableCell fromCell = table->cellAt(0, 0);
+ fromCell.setFormat(nickFormat);
+ fromCell.firstCursorPosition().insertText(from);
+
+ time_t timestamp = msg.timestamp();
+ printTimeInCell(table, timestamp);
+
+ QTextCursor nextCursor(ui->textEdit->textCursor());
+ nextCursor.movePosition(QTextCursor::End);
+ table = nextCursor.insertTable(1, 1, tableFormat);
+ table->cellAt(0, 0).firstCursorPosition().insertText(QString::fromUtf8(msg.data().c_str()));
+ if (!isHistory)
+ {
+ showMessage(from, QString::fromUtf8(msg.data().c_str()));
+ }
+ }
+
+ if (msg.type() == SyncDemo::ChatMessage::JOIN || msg.type() == SyncDemo::ChatMessage::LEAVE)
+ {
+ QTextCharFormat nickFormat;
+ nickFormat.setForeground(Qt::gray);
+ nickFormat.setFontWeight(QFont::Bold);
+ nickFormat.setFontUnderline(true);
+ nickFormat.setUnderlineColor(Qt::gray);
+
+ QTextCursor cursor(ui->textEdit->textCursor());
+ cursor.movePosition(QTextCursor::End);
+ QTextTableFormat tableFormat;
+ tableFormat.setBorder(0);
+ QTextTable *table = cursor.insertTable(1, 2, tableFormat);
+ QString action;
+ if (msg.type() == SyncDemo::ChatMessage::JOIN)
+ {
+ action = "enters room";
+ }
+ else
+ {
+ action = "leaves room";
+ }
+
+ QString from = QString("%1 %2 ").arg(msg.from().c_str()).arg(action);
+ QTextTableCell fromCell = table->cellAt(0, 0);
+ fromCell.setFormat(nickFormat);
+ fromCell.firstCursorPosition().insertText(from);
+
+ time_t timestamp = msg.timestamp();
+ printTimeInCell(table, timestamp);
+ }
+
+ QScrollBar *bar = ui->textEdit->verticalScrollBar();
+ bar->setValue(bar->maximum());
+}
+
+void
+ChatDialog::processRemove(QString prefix)
+{
+ _LOG_DEBUG("<<< remove node for prefix" << prefix.toStdString());
+
+ bool removed = m_scene->removeNode(prefix);
+ if (removed)
+ {
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ m_scene->plot(m_sock->getRootDigest().c_str());
+ }
+}
+
+Name
+ChatDialog::getInviteeRoutablePrefix(const Name& invitee)
+{
+ return ndn::Name("/ndn/broadcast");
+}
+
+void
+ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
+ msg.set_from(m_nick);
+ msg.set_to(m_chatroomName);
+ msg.set_data(text.toStdString());
+ int32_t seconds = static_cast<int32_t>(time::now()/1000000000);
+ msg.set_timestamp(seconds);
+ msg.set_type(SyncDemo::ChatMessage::CHAT);
+}
+
+void
+ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type)
+{
+ msg.set_from(m_nick);
+ msg.set_to(m_chatroomName);
+ int32_t seconds = static_cast<int32_t>(time::now()/1000000000);
+ msg.set_timestamp(seconds);
+ msg.set_type(type);
+}
+
+QString
+ChatDialog::formatTime(time_t timestamp)
+{
+ struct tm *tm_time = localtime(×tamp);
+ int hour = tm_time->tm_hour;
+ QString amOrPM;
+ if (hour > 12)
+ {
+ hour -= 12;
+ amOrPM = "PM";
+ }
+ else
+ {
+ amOrPM = "AM";
+ if (hour == 0)
+ {
+ hour = 12;
+ }
+ }
+
+ char textTime[12];
+ sprintf(textTime, "%d:%02d:%02d %s", hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
+ return QString(textTime);
+}
+
+void
+ChatDialog::printTimeInCell(QTextTable *table, time_t timestamp)
+{
+ QTextCharFormat timeFormat;
+ timeFormat.setForeground(Qt::gray);
+ timeFormat.setFontUnderline(true);
+ timeFormat.setUnderlineColor(Qt::gray);
+ QTextTableCell timeCell = table->cellAt(0, 1);
+ timeCell.setFormat(timeFormat);
+ timeCell.firstCursorPosition().insertText(formatTime(timestamp));
+}
+
+string
+ChatDialog::getRandomString()
+{
+ uint32_t r = random::generateWord32();
+ stringstream ss;
+ {
+ using namespace CryptoPP;
+ StringSource(reinterpret_cast<uint8_t*>(&r), 4, true,
+ new HexEncoder(new FileSink(ss), false));
+
+ }
+
+ return ss.str();
+}
+
+void
+ChatDialog::showMessage(const QString& from, const QString& data)
+{
+ if (!isActiveWindow())
+ emit showChatMessage(QString::fromStdString(m_chatroomName),
+ from, data);
+}
+
+void
+ChatDialog::fitView()
+{
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ QRectF rect = m_scene->itemsBoundingRect();
+ m_scene->setSceneRect(rect);
+ ui->treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
+}
+
+void
+ChatDialog::summonReaper()
+{
+ Sync::SyncLogic &logic = m_sock->getLogic ();
+ map<string, bool> branches = logic.getBranchPrefixes();
+ QMap<QString, DisplayUserPtr> roster = m_scene->getRosterFull();
+
+ m_zombieList.clear();
+
+ QMapIterator<QString, DisplayUserPtr> it(roster);
+ map<string, bool>::iterator mapIt;
+ while(it.hasNext())
+ {
+ it.next();
+ DisplayUserPtr p = it.value();
+ if (p != DisplayUserNullPtr)
+ {
+ mapIt = branches.find(p->getPrefix().toStdString());
+ if (mapIt != branches.end())
+ {
+ mapIt->second = true;
+ }
+ }
+ }
+
+ for (mapIt = branches.begin(); mapIt != branches.end(); ++mapIt)
+ {
+ // this is zombie. all active users should have been marked true
+ if (! mapIt->second)
+ {
+ m_zombieList.append(mapIt->first.c_str());
+ }
+ }
+
+ m_zombieIndex = 0;
+
+ // start reaping
+ reap();
+}
+
+
+// public slots:
+void
+ChatDialog::onLocalPrefixUpdated(const QString& localPrefix)
+{
+ Name newLocalPrefix(localPrefix.toStdString());
+ if(!newLocalPrefix.empty() && newLocalPrefix != m_localPrefix)
+ {
+ // Update localPrefix
+ m_localPrefix = newLocalPrefix;
+
+ updatePrefix();
+ updateLabels();
+ m_scene->setCurrentPrefix(QString(m_localChatPrefix.toUri().c_str()));
+
+ if(m_sock != NULL)
+ {
+ {
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ m_scene->clearAll();
+ m_scene->plot("Empty");
+ }
+
+ ui->textEdit->clear();
+
+ if (m_joined)
+ {
+ sendLeave();
+ }
+
+ delete m_sock;
+ m_sock = NULL;
+
+ usleep(100000);
+ m_sock = new Sync::SyncSocket(m_chatroomPrefix,
+ m_chatPrefix,
+ m_session,
+ m_useRoutablePrefix,
+ m_localPrefix,
+ m_face,
+ m_myCertificate,
+ m_dataRule,
+ bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
+ bind(&ChatDialog::processRemoveWrapper, this, _1));
+ usleep(100000);
+ QTimer::singleShot(600, this, SLOT(sendJoin()));
+ m_timer->start(FRESHNESS * 1000);
+ disableTreeDisplay();
+ QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
+ }
+ else
+ initializeSync();
+ }
+ else
+ if (m_sock == NULL)
+ initializeSync();
+
+ fitView();
+}
+
+void
+ChatDialog::onClose()
+{
+ hide();
+ emit closeChatDialog(QString::fromStdString(m_chatroomName));
+}
+
+
+// private slots:
+void
+ChatDialog::onReturnPressed()
+{
+ QString text = ui->lineEdit->text();
+ if (text.isEmpty())
+ return;
+
+ ui->lineEdit->clear();
+
+ if (text.startsWith("boruoboluomi"))
+ {
+ summonReaper ();
+ // reapButton->show();
+ fitView();
+ return;
+ }
+
+ if (text.startsWith("minimanihong"))
+ {
+ // reapButton->hide();
+ fitView();
+ return;
+ }
+
+ SyncDemo::ChatMessage msg;
+ formChatMessage(text, msg);
+
+ appendMessage(msg);
+
+ sendMsg(msg);
+
+ fitView();
+}
+
+void
+ChatDialog::onTreeButtonPressed()
+{
+ if (ui->treeViewer->isVisible())
+ {
+ ui->treeViewer->hide();
+ ui->treeButton->setText("Show ChronoSync Tree");
+ }
+ else
+ {
+ ui->treeViewer->show();
+ ui->treeButton->setText("Hide ChronoSync Tree");
+ }
+
+ fitView();
+}
+
+void
+ChatDialog::onProcessData(const Data& data, bool show, bool isHistory)
+{
+ SyncDemo::ChatMessage msg;
+ bool corrupted = false;
+ if (!msg.ParseFromArray(data.getContent().value(), data.getContent().value_size()))
+ {
+ _LOG_DEBUG("Errrrr.. Can not parse msg with name: " << data.getName() << ". what is happening?");
+ // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
+ msg.set_from("inconnu");
+ msg.set_type(SyncDemo::ChatMessage::OTHER);
+ corrupted = true;
+ }
+
+ // display msg received from network
+ // we have to do so; this function is called by ccnd thread
+ // so if we call appendMsg directly
+ // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
+ // the "cannonical" way to is use signal-slot
+ if (show && !corrupted)
+ {
+ appendMessage(msg, isHistory);
+ }
+
+ if (!isHistory)
+ {
+ // update the tree view
+ std::string stdStrName = data.getName().toUri();
+ std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
+ std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
+ _LOG_DEBUG("<<< updating scene for" << prefix << ": " << msg.from());
+ if (msg.type() == SyncDemo::ChatMessage::LEAVE)
+ {
+ processRemove(prefix.c_str());
+ }
+ else
+ {
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
+ }
+ }
+ fitView();
+}
+
+void
+ChatDialog::onProcessTreeUpdate(const vector<Sync::MissingDataInfo>& v)
+{
+ _LOG_DEBUG("<<< processing Tree Update");
+
+ if (v.empty())
+ {
+ return;
+ }
+
+ // reflect the changes on digest tree
+ {
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
+ }
+
+ int n = v.size();
+ int totalMissingPackets = 0;
+ for (int i = 0; i < n; i++)
+ {
+ totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ if (totalMissingPackets < 4)
+ {
+ for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
+ {
+ m_sock->fetchData(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1), 2);
+ _LOG_DEBUG("<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq());
+ }
+ }
+ else
+ {
+ m_sock->fetchData(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1), 2);
+ }
+ }
+ // adjust the view
+ fitView();
+}
+
+void
+ChatDialog::onReplot()
+{
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ m_scene->plot(m_sock->getRootDigest().c_str());
+ fitView();
+}
+
+void
+ChatDialog::onRosterChanged(QStringList staleUserList)
+{
+ boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
+ QStringList rosterList = m_scene->getRosterList();
+ m_rosterModel->setStringList(rosterList);
+ QString user;
+ QStringListIterator it(staleUserList);
+ while(it.hasNext())
+ {
+ std::string nick = it.next().toStdString();
+ if (nick.empty())
+ continue;
+
+ SyncDemo::ChatMessage msg;
+ formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
+ msg.set_from(nick);
+ appendMessage(msg);
+ }
+}
+
+void
+ChatDialog::onInviteListDialogRequested()
+{
+ m_inviteListDialog->setInviteLabel(m_chatroomPrefix.toUri());
+ m_inviteListDialog->show();
+}
+
+void
+ChatDialog::sendJoin()
+{
+ m_joined = true;
+ SyncDemo::ChatMessage msg;
+ formControlMessage(msg, SyncDemo::ChatMessage::JOIN);
+ sendMsg(msg);
+ boost::random::random_device rng;
+ boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
+ m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
+ QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
+}
+
+void
+ChatDialog::sendHello()
+{
+ int64_t now = time::now();
+ int elapsed = (now - m_lastMsgTime) / 1000000000;
+ if (elapsed >= m_randomizedInterval / 1000)
+ {
+ SyncDemo::ChatMessage msg;
+ formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
+ sendMsg(msg);
+ boost::random::random_device rng;
+ boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
+ m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
+ QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
+ }
+ else
+ {
+ QTimer::singleShot((m_randomizedInterval - elapsed * 1000), this, SLOT(sendHello()));
+ }
+}
+
+void
+ChatDialog::sendLeave()
+{
+ SyncDemo::ChatMessage msg;
+ formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
+ sendMsg(msg);
+ usleep(500000);
+ m_sock->leave();
+ usleep(5000);
+ m_joined = false;
+ _LOG_DEBUG("Sync REMOVE signal sent");
+}
+
+void ChatDialog::enableTreeDisplay()
+{
+ ui->treeButton->setEnabled(true);
+ // treeViewer->show();
+ // fitView();
+}
+
+void
+ChatDialog::reap()
+{
+ if (m_zombieIndex < m_zombieList.size())
+ {
+ string prefix = m_zombieList.at(m_zombieIndex).toStdString();
+ m_sock->remove(prefix);
+ _LOG_DEBUG("Reaped: prefix = " << prefix);
+ m_zombieIndex++;
+ // reap again in 10 seconds
+ QTimer::singleShot(10000, this, SLOT(reap()));
+ }
+}
+
+void
+ChatDialog::onSendInvitation(QString invitee)
+{
+ Name inviteeNamespace(invitee.toStdString());
+ shared_ptr<Contact> inviteeItem = m_contactManager->getContact(inviteeNamespace);
+ sendInvitation(inviteeItem, true);
+}
+
+void
+ChatDialog::onReply(const Interest& interest,
+ const Data& data,
+ size_t routablePrefixOffset,
+ bool isIntroducer)
+{
+ OnDataValidated onValidated = bind(&ChatDialog::onReplyValidated,
+ this, _1,
+ interest.getName().size()-routablePrefixOffset, //RoutablePrefix will be removed before data is passed to the validator
+ isIntroducer);
+
+ OnDataValidationFailed onFailed = bind(&ChatDialog::onReplyValidationFailed,
+ this, _1, _2);
+
+ if(routablePrefixOffset > 0)
+ {
+ // It is an encapsulated packet, we only validate the inner packet.
+ Data innerData;
+ innerData.wireDecode(data.getContent().blockFromValue());
+ m_invitationValidator->validate(innerData, onValidated, onFailed);
+ }
+ else
+ m_invitationValidator->validate(data, onValidated, onFailed);
+}
+
+void
+ChatDialog::onReplyTimeout(const Interest& interest,
+ size_t routablePrefixOffset)
+{
+ Name interestName;
+ if(routablePrefixOffset > 0)
+ interestName = interest.getName().getSubName(routablePrefixOffset);
+ else
+ interestName = interest.getName();
+
+ Invitation invitation(interestName);
+
+ QString msg = QString::fromUtf8("Your invitation to ") + QString::fromStdString(invitation.getInviteeNameSpace().toUri()) + " times out!";
+ emit inivationRejection(msg);
+}
+
+void
+ChatDialog::onIntroCert(const ndn::Interest& interest, const Data& data)
+{
+ Data innerData;
+ innerData.wireDecode(data.getContent().blockFromValue());
+ Sync::IntroCertificate introCert(innerData);
+ m_sock->addParticipant(introCert);
+}
+
+void
+ChatDialog::onIntroCertTimeout(const ndn::Interest& interest, int retry, const QString& msg)
+{
+ _LOG_DEBUG("onIntroCertTimeout: " << msg.toStdString());
+}
+
+
+
+#if WAF
+#include "chat-dialog.moc"
+#include "chat-dialog.cpp.moc"
+#endif
diff --git a/src/chat-dialog.h b/src/chat-dialog.h
new file mode 100644
index 0000000..f136b82
--- /dev/null
+++ b/src/chat-dialog.h
@@ -0,0 +1,329 @@
+/* -*- 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: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#ifndef CHAT_DIALOG_H
+#define CHAT_DIALOG_H
+
+#include <QDialog>
+#include <QTextTable>
+#include <QStringListModel>
+#include <QSystemTrayIcon>
+#include <QMenu>
+#include <QTimer>
+
+#include "invite-list-dialog.h"
+
+#ifndef Q_MOC_RUN
+#include "contact-manager.h"
+#include "invitation.h"
+#include "contact.h"
+#include "chatbuf.pb.h"
+#include "intro-cert-list.pb.h"
+#include "digesttreescene.h"
+#include <sync-socket.h>
+#include <sync-seq-no.h>
+#include <ndn-cpp-dev/security/key-chain.hpp>
+#include "validator-invitation.h"
+
+#include <boost/thread/locks.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/thread.hpp>
+#endif
+
+#define MAX_HISTORY_ENTRY 20
+
+namespace Ui {
+class ChatDialog;
+}
+
+class ChatDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit
+ ChatDialog(chronos::ContactManager* contactManager,
+ ndn::shared_ptr<ndn::Face> face,
+ const ndn::IdentityCertificate& myCertificate,
+ const ndn::Name& chatroomPrefix,
+ const ndn::Name& localPrefix,
+ const std::string& nick,
+ bool witSecurity,
+ QWidget* parent = 0);
+
+ ~ChatDialog();
+
+ void
+ addSyncAnchor(const chronos::Invitation& invitation);
+
+ void
+ processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo>&, Sync::SyncSocket *);
+
+ void
+ processDataWrapper(const ndn::shared_ptr<const ndn::Data>& data);
+
+ void
+ processDataNoShowWrapper(const ndn::shared_ptr<const ndn::Data>& data);
+
+ void
+ processRemoveWrapper(std::string);
+
+protected:
+ void
+ closeEvent(QCloseEvent *e);
+
+ void
+ resizeEvent(QResizeEvent *);
+
+ void
+ showEvent(QShowEvent *);
+
+private:
+ void
+ updatePrefix();
+
+ void
+ updateLabels();
+
+ void
+ initializeSync();
+
+ void
+ sendInvitation(ndn::shared_ptr<chronos::Contact> contact, bool isIntroducer);
+
+ void
+ replyWrapper(const ndn::Interest& interest,
+ ndn::Data& data,
+ size_t routablePrefixOffset,
+ bool isIntroducer);
+
+ void
+ replyTimeoutWrapper(const ndn::Interest& interest,
+ size_t routablePrefixOffset);
+
+ void
+ onReplyValidated(const ndn::shared_ptr<const ndn::Data>& data,
+ size_t inviteeRoutablePrefixOffset,
+ bool isIntroduce);
+
+ void
+ onReplyValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
+ const std::string& failureInfo);
+
+ void
+ invitationRejected(const ndn::Name& identity);
+
+ void
+ invitationAccepted(const ndn::IdentityCertificate& inviteeCert,
+ const ndn::Name& inviteePrefix,
+ bool isIntroducer);
+
+ void
+ fetchIntroCert(const ndn::Name& identity, const ndn::Name& prefix);
+
+ void
+ onIntroCertList(const ndn::Interest& interest, const ndn::Data& data);
+
+ void
+ onIntroCertListTimeout(const ndn::Interest& interest, int retry, const std::string& msg);
+
+ void
+ introCertWrapper(const ndn::Interest& interest, ndn::Data& data);
+
+ void
+ introCertTimeoutWrapper(const ndn::Interest& interest, int retry, const QString& msg);
+
+ void
+ onCertListInterest(const ndn::Name& prefix, const ndn::Interest& interest);
+
+ void
+ onCertListRegisterFailed(const ndn::Name& prefix, const std::string& msg);
+
+ void
+ onCertSingleInterest(const ndn::Name& prefix, const ndn::Interest& interest);
+
+ void
+ onCertSingleRegisterFailed(const ndn::Name& prefix, const std::string& msg);
+
+
+ void
+ sendMsg(SyncDemo::ChatMessage &msg);
+
+ void
+ disableTreeDisplay();
+
+ void
+ appendMessage(const SyncDemo::ChatMessage msg, bool isHistory = false);
+
+ void
+ processRemove(QString prefix);
+
+ ndn::Name
+ getInviteeRoutablePrefix(const ndn::Name& invitee);
+
+ void
+ formChatMessage(const QString &text, SyncDemo::ChatMessage &msg);
+
+ void
+ formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type);
+
+ QString
+ formatTime(time_t);
+
+ void
+ printTimeInCell(QTextTable *, time_t);
+
+ std::string
+ getRandomString();
+
+ void
+ showMessage(const QString&, const QString&);
+
+ void
+ fitView();
+
+ void
+ summonReaper();
+
+signals:
+ void
+ processData(const ndn::Data& data, bool show, bool isHistory);
+
+ void
+ processTreeUpdate(const std::vector<Sync::MissingDataInfo>);
+
+ void
+ closeChatDialog(const QString& chatroomName);
+
+ void
+ inivationRejection(const QString& msg);
+
+ void
+ showChatMessage(const QString& chatroomName, const QString& from, const QString& data);
+
+ void
+ reply(const ndn::Interest& interest, const ndn::Data& data, size_t routablePrefixOffset, bool isIntroducer);
+
+ void
+ replyTimeout(const ndn::Interest& interest, size_t routablePrefixOffset);
+
+ void
+ introCert(const ndn::Interest& interest, const ndn::Data& data);
+
+ void
+ introCertTimeout(const ndn::Interest& interest, int retry, const QString& msg);
+
+
+public slots:
+ void
+ onLocalPrefixUpdated(const QString& localPrefix);
+
+ void
+ onClose();
+
+private slots:
+ void
+ onReturnPressed();
+
+ void
+ onTreeButtonPressed();
+
+ void
+ onProcessData(const ndn::Data& data, bool show, bool isHistory);
+
+ void
+ onProcessTreeUpdate(const std::vector<Sync::MissingDataInfo>&);
+
+ void
+ onReplot();
+
+ void
+ onRosterChanged(QStringList);
+
+ void
+ onInviteListDialogRequested();
+
+ void
+ sendJoin();
+
+ void
+ sendHello();
+
+ void
+ sendLeave();
+
+ void
+ enableTreeDisplay();
+
+ void
+ reap();
+
+ void
+ onSendInvitation(QString);
+
+ void
+ onReply(const ndn::Interest& interest, const ndn::Data& data, size_t routablePrefixOffset, bool isIntroducer);
+
+ void
+ onReplyTimeout(const ndn::Interest& interest, size_t routablePrefixOffset);
+
+ void
+ onIntroCert(const ndn::Interest& interest, const ndn::Data& data);
+
+ void
+ onIntroCertTimeout(const ndn::Interest& interest, int retry, const QString& msg);
+
+private:
+ Ui::ChatDialog *ui;
+ ndn::KeyChain m_keyChain;
+
+ chronos::ContactManager* m_contactManager;
+ ndn::shared_ptr<ndn::Face> m_face;
+
+ ndn::IdentityCertificate m_myCertificate;
+ ndn::Name m_identity;
+
+ ndn::Name m_certListPrefix;
+ const ndn::RegisteredPrefixId* m_certListPrefixId;
+ ndn::Name m_certSinglePrefix;
+ const ndn::RegisteredPrefixId* m_certSinglePrefixId;
+
+ std::string m_chatroomName;
+ ndn::Name m_chatroomPrefix;
+ ndn::Name m_localPrefix;
+ bool m_useRoutablePrefix;
+ ndn::Name m_chatPrefix;
+ ndn::Name m_localChatPrefix;
+ std::string m_nick;
+ DigestTreeScene *m_scene;
+ QStringListModel *m_rosterModel;
+ QTimer* m_timer;
+
+
+ int64_t m_lastMsgTime;
+ int m_randomizedInterval;
+ bool m_joined;
+
+ Sync::SyncSocket *m_sock;
+ uint64_t m_session;
+ ndn::shared_ptr<ndn::SecRuleRelative> m_dataRule;
+
+ InviteListDialog* m_inviteListDialog;
+ ndn::shared_ptr<chronos::ValidatorInvitation> m_invitationValidator;
+
+ boost::recursive_mutex m_msgMutex;
+ boost::recursive_mutex m_sceneMutex;
+ QList<QString> m_zombieList;
+ int m_zombieIndex;
+};
+
+#endif // CHAT_DIALOG_H
diff --git a/src/chatdialog.ui b/src/chat-dialog.ui
similarity index 90%
rename from src/chatdialog.ui
rename to src/chat-dialog.ui
index 256aadf..2d174c0 100644
--- a/src/chatdialog.ui
+++ b/src/chat-dialog.ui
@@ -18,12 +18,12 @@
<number>6</number>
</property>
<item>
- <layout class="QHBoxLayout">
+ <layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>-1</number>
</property>
<item>
- <layout class="QVBoxLayout">
+ <layout class="QVBoxLayout" name="infoLayout">
<item>
<widget class="QLabel" name="infoLabel">
<property name="focusPolicy">
@@ -32,7 +32,7 @@
</widget>
</item>
<item>
- <layout class="QHBoxLayout">
+ <layout class="QHBoxLayout" name="prefixLayout">
<item>
<widget class="QLabel" name="prefixLabel">
<property name="focusPolicy">
@@ -58,12 +58,15 @@
</spacer>
</item>
<item>
- <layout class="QVBoxLayout">
+ <layout class="QVBoxLayout" name="buttonLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<widget class="QPushButton" name="inviteButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>Invite</string>
</property>
@@ -108,7 +111,7 @@
</layout>
</item>
<item>
- <layout class="QHBoxLayout">
+ <layout class="QHBoxLayout" name="chatLayout_2">
<item>
<widget class="QListView" name="listView">
<property name="sizePolicy">
@@ -143,7 +146,7 @@
</widget>
</item>
<item>
- <layout class="QVBoxLayout">
+ <layout class="QVBoxLayout" name="messageLayout">
<item>
<widget class="QGraphicsView" name="treeViewer">
<property name="focusPolicy">
@@ -162,7 +165,7 @@
</widget>
</item>
<item>
- <layout class="QHBoxLayout">
+ <layout class="QHBoxLayout" name="inputLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
diff --git a/src/chatdialog.cpp b/src/chatdialog.cpp
deleted file mode 100644
index 6603183..0000000
--- a/src/chatdialog.cpp
+++ /dev/null
@@ -1,1172 +0,0 @@
-/* -*- 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: Zhenkai Zhu <zhenkai@cs.ucla.edu>
- * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- * Yingdi Yu <yingdi@cs.ucla.edu>
- */
-
-#include "chatdialog.h"
-#include "ui_chatdialog.h"
-
-#include <QScrollBar>
-#include <QMessageBox>
-#include <QCloseEvent>
-
-#ifndef Q_MOC_RUN
-#include "invitation.h"
-
-#ifdef WITH_SECURITY
-#include <sync-intro-certificate.h>
-#endif
-
-#include <boost/random/random_device.hpp>
-#include <boost/random/uniform_int_distribution.hpp>
-#include <ndn-cpp-dev/security/signature-sha256-with-rsa.hpp>
-#include "logging.h"
-#endif
-
-using namespace std;
-using namespace ndn;
-using namespace chronos;
-
-INIT_LOGGER("ChatDialog");
-
-static const int HELLO_INTERVAL = FRESHNESS * 3 / 4;
-
-Q_DECLARE_METATYPE(std::vector<Sync::MissingDataInfo> )
-Q_DECLARE_METATYPE(ndn::shared_ptr<const ndn::Data> )
-Q_DECLARE_METATYPE(size_t)
-
-ChatDialog::ChatDialog(shared_ptr<ContactManager> contactManager,
- shared_ptr<Face> face,
- const Name& chatroomPrefix,
- const Name& localPrefix,
- const Name& defaultIdentity,
- const string& nick,
- QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::ChatDialog)
- , m_contactManager(contactManager)
- , m_face(face)
- , m_ioService(face->ioService())
- , m_chatroomPrefix(chatroomPrefix)
- , m_localPrefix(localPrefix)
- , m_defaultIdentity(defaultIdentity)
- , m_nick(nick)
- , m_scheduler(*face->ioService())
- , m_keyChain(new KeyChain())
- , m_sock(NULL)
- , m_lastMsgTime(time::now())
- , m_joined(false)
- , m_inviteListDialog(new InviteListDialog(m_contactManager))
-{
- qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
- qRegisterMetaType<ndn::shared_ptr<const ndn::Data> >("ndn::shared_ptr<const ndn::Data>");
- qRegisterMetaType<size_t>("size_t");
-
- ui->setupUi(this);
-
- QString randString = getRandomString();
- m_localChatPrefix = m_localPrefix;
- m_localChatPrefix.append("%F0.").append(m_defaultIdentity);
- m_localChatPrefix.append("chronos").append(m_chatroomPrefix.get(-1)).append(randString.toStdString());
-
- m_session = static_cast<uint64_t>(time::now());
- m_scene = new DigestTreeScene(m_ioService, this);
-
- initializeSetting();
- updateLabels();
-
- ui->treeViewer->setScene(m_scene);
- ui->treeViewer->hide();
- m_scene->plot("Empty");
- QRectF rect = m_scene->itemsBoundingRect();
- m_scene->setSceneRect(rect);
-
- m_rosterModel = new QStringListModel(this);
- ui->listView->setModel(m_rosterModel);
-
- createActions();
- createTrayIcon();
-
-#ifndef SECURITY
- m_invitationValidator = make_shared<ValidatorNull>();
- m_syncValidator = make_shared<ValidatorNull>();
-#else
- m_invitationValidator = make_shared<chronos::ValidatorInvitation>();
- m_syncValidator = ...;
-#endif
-
- connect(ui->inviteButton, SIGNAL(clicked()),
- this, SLOT(openInviteListDialog()));
- connect(m_inviteListDialog, SIGNAL(invitionDetermined(QString, bool)),
- this, SLOT(sendInvitationWrapper(QString, bool)));
- connect(ui->lineEdit, SIGNAL(returnPressed()),
- this, SLOT(returnPressed()));
- connect(ui->treeButton, SIGNAL(pressed()),
- this, SLOT(treeButtonPressed()));
- connect(this, SIGNAL(dataReceived(ndn::shared_ptr<const ndn::Data>, bool, bool)),
- this, SLOT(processData(ndn::shared_ptr<const ndn::Data>, bool, bool)));
- connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)),
- this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
- connect(m_scene, SIGNAL(replot()),
- this, SLOT(replot()));
- connect(trayIcon, SIGNAL(messageClicked()),
- this, SLOT(showNormal()));
- connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
- this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
- connect(m_scene, SIGNAL(rosterChanged(QStringList)),
- this, SLOT(updateRosterList(QStringList)));
- connect(this, SIGNAL(triggerHello()),
- this, SLOT(sendHello()));
- connect(this, SIGNAL(triggerJoin()),
- this, SLOT(sendJoin()));
- connect(this, SIGNAL(triggerLeave()),
- this, SLOT(sendLeave()));
- connect(this, SIGNAL(triggerReplot()),
- this, SLOT(replot()));
- connect(this, SIGNAL(triggerEnableTreeDisplay()),
- this, SLOT(enableTreeDisplay()));
- connect(this, SIGNAL(triggerReap()),
- this, SLOT(reap()));
-
-
-
- initializeSync();
-}
-
-
-ChatDialog::~ChatDialog()
-{
- if(m_sock != NULL)
- {
- sendLeave();
- delete m_sock;
- m_sock = NULL;
- }
-}
-
-void
-ChatDialog::initializeSetting()
-{
- m_user.setNick(QString::fromStdString(m_nick));
- m_user.setChatroom(QString::fromStdString(m_chatroomPrefix.get(-1).toEscapedString()));
- m_user.setOriginPrefix(QString::fromStdString(m_localPrefix.toUri()));
- m_user.setPrefix(QString::fromStdString(m_localChatPrefix.toUri()));
- m_scene->setCurrentPrefix(QString::fromStdString(m_localChatPrefix.toUri()));
-}
-
-void
-ChatDialog::updateLabels()
-{
- QString settingDisp = QString("Chatroom: %1").arg(m_user.getChatroom());
- ui->infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
- ui->infoLabel->setText(settingDisp);
- QString prefixDisp;
- if (m_user.getPrefix().startsWith("/private/local"))
- {
- prefixDisp = QString("<Warning: no connection to hub or hub does not support prefix autoconfig.>\n <Prefix = %1>").arg(m_user.getPrefix());
- ui->prefixLabel->setStyleSheet("QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
- }
- else
- {
- prefixDisp = QString("<Prefix = %1>").arg(m_user.getPrefix());
- ui->prefixLabel->setStyleSheet("QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
- }
- ui->prefixLabel->setText(prefixDisp);
-}
-
-void
-ChatDialog::initializeSync()
-{
-
- m_sock = new Sync::SyncSocket(m_chatroomPrefix.toUri(),
- m_syncValidator,
- m_face,
- bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
- bind(&ChatDialog::processRemoveWrapper, this, _1));
-
- usleep(100000);
-
- m_scheduler.scheduleEvent(time::milliseconds(600), bind(&ChatDialog::sendJoinWrapper, this));
-
- if(static_cast<bool>(m_replotEventId))
- m_scheduler.cancelEvent(m_replotEventId);
- m_replotEventId = m_scheduler.schedulePeriodicEvent(time::seconds(0), time::milliseconds(FRESHNESS * 1000),
- bind(&ChatDialog::replotWrapper, this));
- disableTreeDisplay();
- m_scheduler.scheduleEvent(time::milliseconds(2200), bind(&ChatDialog::enableTreeDisplayWrapper, this));
-}
-
-void
-ChatDialog::sendInterest(const ndn::Interest& interest,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onValidationFailed,
- const OnEventualTimeout& timeoutNotify,
- int retry /* = 1 */)
-{
- m_face->expressInterest(interest,
- bind(&ChatDialog::onTargetData,
- this, _1, _2, onValidated, onValidationFailed),
- bind(&ChatDialog::onTargetTimeout,
- this, _1, retry,
- onValidated, onValidationFailed, timeoutNotify));
-}
-
-void
-ChatDialog::sendInvitation(shared_ptr<ContactItem> contact, bool isIntroducer)
-{
-#ifdef WITH_SECURITY
- m_invitationValidator->addTrustAnchor(contact->getSelfEndorseCertificate());
-#endif
-
- Invitation invitation(contact->getNameSpace(),
- m_chatroomPrefix.get(-1),
- m_localPrefix);
- ndn::Interest interest(invitation.getUnsignedInterestName());
-
- m_keyChain->signByIdentity(interest, m_defaultIdentity);
-
- OnDataValidated onValidated = bind(&ChatDialog::onInviteReplyValidated,
- this, _1, contact->getNameSpace(), isIntroducer);
-
- OnDataValidationFailed onValidationFailed = bind(&ChatDialog::onInviteReplyValidationFailed,
- this, _1, contact->getNameSpace());
-
- OnEventualTimeout timeoutNotify = bind(&ChatDialog::onInviteReplyTimeout,
- this, contact->getNameSpace());
-
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
-}
-
-void
-ChatDialog::onInviteReplyValidated(const shared_ptr<const Data>& data,
- const Name& identity,
- bool isIntroducer)
-{
- string content(reinterpret_cast<const char*>(data->getContent().value()), data->getContent().value_size());
- if(content == string("nack"))
- invitationRejected(identity);
- else
- invitationAccepted(identity, data, content, isIntroducer);
-}
-
-void
-ChatDialog::onInviteReplyValidationFailed(const shared_ptr<const Data>& data,
- const Name& identity)
-{
- QString msg = QString::fromUtf8("Reply from ") + QString::fromStdString(identity.toUri()) + " cannot be verified!";
- emit inivationRejection(msg);
-}
-
-
-void
-ChatDialog::onInviteReplyTimeout(const Name& identity)
-{
- QString msg = QString::fromUtf8("Your invitation to ") + QString::fromStdString(identity.toUri()) + " times out!";
- emit inivationRejection(msg);
-}
-
-void
-ChatDialog::invitationRejected(const Name& identity)
-{
- QString msg = QString::fromStdString(identity.toUri()) + " Rejected your invitation!";
- emit inivationRejection(msg);
-}
-
-void
-ChatDialog::invitationAccepted(const Name& identity,
- shared_ptr<const Data> data,
- const string& inviteePrefix,
- bool isIntroducer)
-{
- _LOG_DEBUG(" " << identity.toUri() << " Accepted your invitation!");
-
-#ifdef WITH_SECURITY
- SignatureSha256WithRsa sig(data->getSignature());
- const Name & keyLocatorName = sig.getKeyLocator().getName();
- shared_ptr<IdentityCertificate> dskCertificate = m_invitationValidator->getValidatedDskCertificate(keyLocatorName);
- m_syncPolicy->addSyncDataRule(inviteePrefix, *dskCertificate, isIntroducer);
- publishIntroCert(*dskCertificate, isIntroducer);
-#endif
-}
-
-void
-ChatDialog::publishIntroCert(const IdentityCertificate& dskCertificate, bool isIntroducer)
-{
-#ifdef WITH_SECURITY
- SyncIntroCertificate syncIntroCertificate(m_chatroomPrefix,
- dskCertificate.getPublicKeyName(),
- m_keyChain->getDefaultKeyNameForIdentity(m_defaultIdentity),
- dskCertificate.getNotBefore(),
- dskCertificate.getNotAfter(),
- dskCertificate.getPublicKeyInfo(),
- (isIntroducer ? SyncIntroCertificate::INTRODUCER : SyncIntroCertificate::PRODUCER));
- ndn::Name certName = m_keyChain->getDefaultCertificateNameForIdentity(m_defaultIdentity);
- _LOG_DEBUG("Publish Intro Certificate: " << syncIntroCertificate.getName());
- m_keyChain->sign(syncIntroCertificate, certName);
- m_face->put(syncIntroCertificate);
-#endif
-}
-
-void
-ChatDialog::addChatDataRule(const Name& prefix,
- const IdentityCertificate& identityCertificate,
- bool isIntroducer)
-{
-#ifdef WITH_SECURITY
- m_syncValidator->addSyncDataRule(prefix, identityCertificate, isIntroducer);
-#endif
-}
-
-void
-ChatDialog::addTrustAnchor(const EndorseCertificate& cert)
-{
-#ifdef WITH_SECURITY
- m_syncValidator->addTrustAnchor(cert);
-#endif
-}
-
-
-void
-ChatDialog::returnPressed()
-{
- QString text = ui->lineEdit->text();
- if (text.isEmpty())
- return;
-
- ui->lineEdit->clear();
-
- if (text.startsWith("boruoboluomi"))
- {
- summonReaper ();
- // reapButton->show();
- fitView();
- return;
- }
-
- if (text.startsWith("minimanihong"))
- {
- // reapButton->hide();
- fitView();
- return;
- }
-
- SyncDemo::ChatMessage msg;
- formChatMessage(text, msg);
-
- appendMessage(msg);
-
- sendMsg(msg);
-
- fitView();
-}
-
-void
-ChatDialog::treeButtonPressed()
-{
- if (ui->treeViewer->isVisible())
- {
- ui->treeViewer->hide();
- ui->treeButton->setText("Show ChronoSync Tree");
- }
- else
- {
- ui->treeViewer->show();
- ui->treeButton->setText("Hide ChronoSync Tree");
- }
-
- fitView();
-}
-
-void ChatDialog::disableTreeDisplay()
-{
- ui->treeButton->setEnabled(false);
- ui->treeViewer->hide();
- fitView();
-}
-
-void ChatDialog::enableTreeDisplay()
-{
- ui->treeButton->setEnabled(true);
- // treeViewer->show();
- // fitView();
-}
-
-void
-ChatDialog::enableTreeDisplayWrapper()
-{ emit triggerEnableTreeDisplay(); }
-
-void
-ChatDialog::processTreeUpdateWrapper(const vector<Sync::MissingDataInfo>& v, Sync::SyncSocket *sock)
-{
- emit treeUpdated(v);
- _LOG_DEBUG("<<< Tree update signal emitted");
-}
-
-void
-ChatDialog::processRemoveWrapper(string prefix)
-{
- _LOG_DEBUG("Sync REMOVE signal received for prefix: " << prefix);
-}
-
-void
-ChatDialog::processTreeUpdate(const vector<Sync::MissingDataInfo>& v)
-{
- _LOG_DEBUG("<<< processing Tree Update");
-
- if (v.empty())
- {
- return;
- }
-
- // reflect the changes on digest tree
- {
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
- }
-
- int n = v.size();
- int totalMissingPackets = 0;
- for (int i = 0; i < n; i++)
- {
- totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
- }
-
- for (int i = 0; i < n; i++)
- {
- if (totalMissingPackets < 4)
- {
- for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq)
- {
- m_sock->fetchData(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1), 2);
- _LOG_DEBUG("<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq());
- }
- }
- else
- {
- m_sock->fetchData(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1), 2);
- }
- }
-
- // adjust the view
- fitView();
-
-}
-
-void
-ChatDialog::processDataWrapper(const shared_ptr<const Data>& data)
-{
- emit dataReceived(data, true, false);
- _LOG_DEBUG("<<< " << data->getName() << " fetched");
-}
-
-void
-ChatDialog::processDataNoShowWrapper(const shared_ptr<const Data>& data)
-{ emit dataReceived(data, false, false); }
-
-void
-ChatDialog::processData(shared_ptr<const Data> data, bool show, bool isHistory)
-{
- SyncDemo::ChatMessage msg;
- bool corrupted = false;
- if (!msg.ParseFromArray(data->getContent().value(), data->getContent().value_size()))
- {
- _LOG_DEBUG("Errrrr.. Can not parse msg with name: " << data->getName() << ". what is happening?");
- // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
- msg.set_from("inconnu");
- msg.set_type(SyncDemo::ChatMessage::OTHER);
- corrupted = true;
- }
-
- // display msg received from network
- // we have to do so; this function is called by ccnd thread
- // so if we call appendMsg directly
- // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
- // the "cannonical" way to is use signal-slot
- if (show && !corrupted)
- {
- appendMessage(msg, isHistory);
- }
-
- if (!isHistory)
- {
- // update the tree view
- std::string stdStrName = data->getName().toUri();
- std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
- std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
- _LOG_DEBUG("<<< updating scene for" << prefix << ": " << msg.from());
- if (msg.type() == SyncDemo::ChatMessage::LEAVE)
- {
- processRemove(prefix.c_str());
- }
- else
- {
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
- }
- }
- fitView();
-}
-
-void
-ChatDialog::processRemove(QString prefix)
-{
- _LOG_DEBUG("<<< remove node for prefix" << prefix.toStdString());
-
- bool removed = m_scene->removeNode(prefix);
- if (removed)
- {
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- m_scene->plot(m_sock->getRootDigest().c_str());
- }
-}
-
-void
-ChatDialog::sendJoin()
-{
- m_joined = true;
- SyncDemo::ChatMessage msg;
- formControlMessage(msg, SyncDemo::ChatMessage::JOIN);
- sendMsg(msg);
- boost::random::random_device rng;
- boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
- m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
- m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval), bind(&ChatDialog::sendHelloWrapper, this));
-}
-
-void
-ChatDialog::sendJoinWrapper()
-{ emit triggerJoin(); }
-
-void
-ChatDialog::sendHello()
-{
- int64_t now = time::now();
- int elapsed = (now - m_lastMsgTime) / 1000000000;
- if (elapsed >= m_randomizedInterval / 1000)
- {
- SyncDemo::ChatMessage msg;
- formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
- sendMsg(msg);
- boost::random::random_device rng;
- boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
- m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
- m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval), bind(&ChatDialog::sendHelloWrapper, this));
- }
- else
- {
- m_scheduler.scheduleEvent(time::milliseconds(m_randomizedInterval - elapsed * 1000),
- bind(&ChatDialog::sendHelloWrapper, this));
- }
-}
-
-void
-ChatDialog::sendHelloWrapper()
-{ emit triggerHello(); }
-
-void
-ChatDialog::sendLeave()
-{
- SyncDemo::ChatMessage msg;
- formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
- sendMsg(msg);
- usleep(500000);
- m_sock->remove(m_user.getPrefix().toStdString());
- usleep(5000);
- m_joined = false;
- _LOG_DEBUG("Sync REMOVE signal sent");
-}
-
-void
-ChatDialog::sendLeaveWrapper()
-{ emit triggerLeave(); }
-
-void
-ChatDialog::replot()
-{
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- m_scene->plot(m_sock->getRootDigest().c_str());
- fitView();
-}
-
-void
-ChatDialog::replotWrapper()
-{ emit triggerReplot(); }
-
-void
-ChatDialog::summonReaper()
-{
- Sync::SyncLogic &logic = m_sock->getLogic ();
- map<string, bool> branches = logic.getBranchPrefixes();
- QMap<QString, DisplayUserPtr> roster = m_scene->getRosterFull();
-
- m_zombieList.clear();
-
- QMapIterator<QString, DisplayUserPtr> it(roster);
- map<string, bool>::iterator mapIt;
- while(it.hasNext())
- {
- it.next();
- DisplayUserPtr p = it.value();
- if (p != DisplayUserNullPtr)
- {
- mapIt = branches.find(p->getPrefix().toStdString());
- if (mapIt != branches.end())
- {
- mapIt->second = true;
- }
- }
- }
-
- for (mapIt = branches.begin(); mapIt != branches.end(); ++mapIt)
- {
- // this is zombie. all active users should have been marked true
- if (! mapIt->second)
- {
- m_zombieList.append(mapIt->first.c_str());
- }
- }
-
- m_zombieIndex = 0;
-
- // start reaping
- reap();
-}
-
-void
-ChatDialog::reap()
-{
- if (m_zombieIndex < m_zombieList.size())
- {
- string prefix = m_zombieList.at(m_zombieIndex).toStdString();
- m_sock->remove(prefix);
- _LOG_DEBUG("Reaped: prefix = " << prefix);
- m_zombieIndex++;
- // reap again in 10 seconds
- m_scheduler.scheduleEvent(time::milliseconds(10000),
- bind(&ChatDialog::reapWrapper, this));
- }
-}
-
-void
-ChatDialog::reapWrapper()
-{ emit triggerReap(); }
-
-void
-ChatDialog::updateRosterList(QStringList staleUserList)
-{
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- QStringList rosterList = m_scene->getRosterList();
- m_rosterModel->setStringList(rosterList);
- QString user;
- QStringListIterator it(staleUserList);
- while(it.hasNext())
- {
- std::string nick = it.next().toStdString();
- if (nick.empty())
- continue;
-
- SyncDemo::ChatMessage msg;
- formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
- msg.set_from(nick);
- appendMessage(msg);
- }
-}
-
-void
-ChatDialog::settingUpdated(QString nick, QString chatroom, QString originPrefix)
-{
- _LOG_DEBUG("called");
- QString randString = getRandomString();
- bool needWrite = false;
- bool needFresh = false;
-
- QString oldPrefix = m_user.getPrefix();
- if (!originPrefix.isEmpty() && originPrefix != m_user.getOriginPrefix()) {
- m_user.setOriginPrefix(originPrefix);
-
- m_localPrefix = ndn::Name(originPrefix.toStdString());
- m_localChatPrefix = m_localPrefix;
- m_localChatPrefix.append("%F0.").append(m_defaultIdentity);
- m_localChatPrefix.append("chronos").append(m_chatroomPrefix.get(-1)).append(randString.toStdString());
- m_user.setPrefix(QString::fromStdString(m_localChatPrefix.toUri()));
- m_scene->setCurrentPrefix(QString::fromStdString(m_localChatPrefix.toUri()));
- needWrite = true;
- needFresh = true;
- }
-
- if (needWrite) {
- updateLabels();
- }
-
- if (needFresh && m_sock != NULL)
- {
-
- {
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- m_scene->clearAll();
- m_scene->plot("Empty");
- }
-
- ui->textEdit->clear();
-
- // keep the new prefix
- QString newPrefix = m_user.getPrefix();
- // send leave for the old
- m_user.setPrefix(oldPrefix);
- // there is no point to send leave if we haven't joined yet
- if (m_joined)
- {
- sendLeave();
- }
- // resume new prefix
- m_user.setPrefix(newPrefix);
- delete m_sock;
- m_sock = NULL;
-
- try
- {
- usleep(100000);
- m_sock = new Sync::SyncSocket(m_chatroomPrefix.toUri(),
- m_syncValidator,
- m_face,
- bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
- bind(&ChatDialog::processRemoveWrapper, this, _1));
- usleep(100000);
- m_scheduler.scheduleEvent(time::milliseconds(600), bind(&ChatDialog::sendJoinWrapper, this));
- if(static_cast<bool>(m_replotEventId))
- m_scheduler.cancelEvent(m_replotEventId);
- m_replotEventId = m_scheduler.schedulePeriodicEvent(time::seconds(0), time::milliseconds(FRESHNESS * 1000),
- bind(&ChatDialog::replotWrapper, this));
- disableTreeDisplay();
- m_scheduler.scheduleEvent(time::milliseconds(2200), bind(&ChatDialog::enableTreeDisplayWrapper, this));
- }catch(Face::Error& e){
- emit noNdnConnection(QString::fromStdString("Cannot conect to ndnd!\n Have you started your ndnd?"));
- }
- }
- else if (needFresh && m_sock == NULL)
- {
- initializeSync();
- }
- else if (m_sock == NULL)
- {
- initializeSync();
- }
- else
- {
-// #ifdef __DEBUG
-// std::cout << "Just changing nicks, we're good. " << std::endl;
-// #endif
- }
-
- fitView();
-}
-
-void
-ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
-{
- switch (reason)
- {
- case QSystemTrayIcon::Trigger:
- case QSystemTrayIcon::DoubleClick:
- break;
- case QSystemTrayIcon::MiddleClick:
- // showMessage();
- break;
- default:;
- }
-}
-
-
-void
-ChatDialog::messageClicked()
-{
- this->showMaximized();
-}
-
-
-void
-ChatDialog::createActions()
-{
- minimizeAction = new QAction(tr("Mi&nimize"), this);
- connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
-
- maximizeAction = new QAction(tr("Ma&ximize"), this);
- connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
-
- restoreAction = new QAction(tr("&Restore"), this);
- connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
-
- // settingsAction = new QAction(tr("Settings"), this);
- // connect (settingsAction, SIGNAL(triggered()), this, SLOT(buttonPressed()));
-
- // settingsAction->setMenuRole (QAction::PreferencesRole);
-
- updateLocalPrefixAction = new QAction(tr("Update local prefix"), this);
- connect (updateLocalPrefixAction, SIGNAL(triggered()), this, SLOT(updateLocalPrefix()));
-
- quitAction = new QAction(tr("Quit"), this);
- connect(quitAction, SIGNAL(triggered()), this, SLOT(quit()));
-}
-
-void
-ChatDialog::createTrayIcon()
-{
- trayIconMenu = new QMenu(this);
- trayIconMenu->addAction(minimizeAction);
- trayIconMenu->addAction(maximizeAction);
- trayIconMenu->addAction(restoreAction);
- // trayIconMenu->addSeparator();
- // trayIconMenu->addAction(settingsAction);
- trayIconMenu->addSeparator();
- trayIconMenu->addAction(updateLocalPrefixAction);
- trayIconMenu->addSeparator();
- trayIconMenu->addAction(quitAction);
-
- trayIcon = new QSystemTrayIcon(this);
- trayIcon->setContextMenu(trayIconMenu);
-
- QIcon icon(":/images/icon_small.png");
- trayIcon->setIcon(icon);
- setWindowIcon(icon);
- trayIcon->setToolTip("ChronoChat System Tray Icon");
- trayIcon->setVisible(true);
-}
-
-
-void
-ChatDialog::resizeEvent(QResizeEvent *e)
-{
- fitView();
-}
-
-void
-ChatDialog::showEvent(QShowEvent *e)
-{
- fitView();
-}
-
-void
-ChatDialog::fitView()
-{
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- QRectF rect = m_scene->itemsBoundingRect();
- m_scene->setSceneRect(rect);
- ui->treeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);
-}
-
-void
-ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
- msg.set_from(m_user.getNick().toStdString());
- msg.set_to(m_user.getChatroom().toStdString());
- msg.set_data(text.toUtf8().constData());
- int32_t seconds = static_cast<int32_t>(time::now()/1000000000);
- msg.set_timestamp(seconds);
- msg.set_type(SyncDemo::ChatMessage::CHAT);
-}
-
-void
-ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type)
-{
- msg.set_from(m_user.getNick().toStdString());
- msg.set_to(m_user.getChatroom().toStdString());
- int32_t seconds = static_cast<int32_t>(time::now()/1000000000);
- msg.set_timestamp(seconds);
- msg.set_type(type);
-}
-
-void
-ChatDialog::updateLocalPrefix()
-{
- ndn::Name interestName("/local/ndn/prefix");
- ndn::Interest interest(interestName);
- interest.setInterestLifetime(1000);
-
- m_face->expressInterest(interest,
- bind(&ChatDialog::onLocalPrefix, this, _1, _2),
- bind(&ChatDialog::onLocalPrefixTimeout, this, _1));
-}
-
-
-void
-ChatDialog::onLocalPrefix(const ndn::Interest& interest,
- ndn::Data& data)
-{
- string dataString(reinterpret_cast<const char*>(data.getContent().value()), data.getContent().value_size());
- QString originPrefix = QString::fromStdString (dataString).trimmed ();
- string trimmedString = originPrefix.toStdString();
- m_newLocalPrefix = Name(trimmedString);
-
- _LOG_DEBUG("now the prefix is " << m_newLocalPrefix.toUri());
- _LOG_DEBUG("in use prefix is " << m_user.getOriginPrefix().toStdString());
-
- if (originPrefix != "" && m_user.getOriginPrefix () != originPrefix)
- emit settingUpdated(m_user.getNick (), m_user.getChatroom (), originPrefix);
-}
-
-void
-ChatDialog::onLocalPrefixTimeout(const ndn::Interest& interest)
-{
- m_newLocalPrefix = m_localPrefix;
-
- _LOG_DEBUG("now the prefix is " << m_newLocalPrefix.toUri());
- _LOG_DEBUG("in use prefix is " << m_user.getOriginPrefix().toStdString());
- QString originPrefix = QString::fromStdString(m_newLocalPrefix.toUri());
-
- if (originPrefix != "" && m_user.getOriginPrefix () != originPrefix)
- emit settingUpdated(m_user.getNick (), m_user.getChatroom (), originPrefix);
-}
-
-static std::string chars2("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
-
-QString
-ChatDialog::getRandomString()
-{
- std::string randStr;
- boost::random::random_device rng;
- boost::random::uniform_int_distribution<> index_dist(0, chars2.size() - 1);
- for (int i = 0; i < 10; i ++)
- {
- randStr += chars2[index_dist(rng)];
- }
- return randStr.c_str();
-}
-
-void
-ChatDialog::changeEvent(QEvent *e)
-{
- switch(e->type())
- {
- case QEvent::ActivationChange:
- if (isActiveWindow())
- {
- trayIcon->setIcon(QIcon(":/images/icon_small.png"));
- }
- break;
- default:
- break;
- }
-}
-
-void
-ChatDialog::appendMessage(const SyncDemo::ChatMessage msg, bool isHistory)
-{
- boost::recursive_mutex::scoped_lock lock(m_msgMutex);
-
- if (msg.type() == SyncDemo::ChatMessage::CHAT)
- {
-
- if (!msg.has_data())
- {
- return;
- }
-
- if (msg.from().empty() || msg.data().empty())
- {
- return;
- }
-
- if (!msg.has_timestamp())
- {
- return;
- }
-
- // if (m_history.size() == MAX_HISTORY_ENTRY)
- // {
- // m_history.dequeue();
- // }
-
- // m_history.enqueue(msg);
-
- QTextCharFormat nickFormat;
- nickFormat.setForeground(Qt::darkGreen);
- nickFormat.setFontWeight(QFont::Bold);
- nickFormat.setFontUnderline(true);
- nickFormat.setUnderlineColor(Qt::gray);
-
- QTextCursor cursor(ui->textEdit->textCursor());
- cursor.movePosition(QTextCursor::End);
- QTextTableFormat tableFormat;
- tableFormat.setBorder(0);
- QTextTable *table = cursor.insertTable(1, 2, tableFormat);
- QString from = QString("%1 ").arg(msg.from().c_str());
- QTextTableCell fromCell = table->cellAt(0, 0);
- fromCell.setFormat(nickFormat);
- fromCell.firstCursorPosition().insertText(from);
-
- time_t timestamp = msg.timestamp();
- printTimeInCell(table, timestamp);
-
- QTextCursor nextCursor(ui->textEdit->textCursor());
- nextCursor.movePosition(QTextCursor::End);
- table = nextCursor.insertTable(1, 1, tableFormat);
- table->cellAt(0, 0).firstCursorPosition().insertText(QString::fromUtf8(msg.data().c_str()));
- if (!isHistory)
- {
- showMessage(from, QString::fromUtf8(msg.data().c_str()));
- }
- }
-
- if (msg.type() == SyncDemo::ChatMessage::JOIN || msg.type() == SyncDemo::ChatMessage::LEAVE)
- {
- QTextCharFormat nickFormat;
- nickFormat.setForeground(Qt::gray);
- nickFormat.setFontWeight(QFont::Bold);
- nickFormat.setFontUnderline(true);
- nickFormat.setUnderlineColor(Qt::gray);
-
- QTextCursor cursor(ui->textEdit->textCursor());
- cursor.movePosition(QTextCursor::End);
- QTextTableFormat tableFormat;
- tableFormat.setBorder(0);
- QTextTable *table = cursor.insertTable(1, 2, tableFormat);
- QString action;
- if (msg.type() == SyncDemo::ChatMessage::JOIN)
- {
- action = "enters room";
- }
- else
- {
- action = "leaves room";
- }
-
- QString from = QString("%1 %2 ").arg(msg.from().c_str()).arg(action);
- QTextTableCell fromCell = table->cellAt(0, 0);
- fromCell.setFormat(nickFormat);
- fromCell.firstCursorPosition().insertText(from);
-
- time_t timestamp = msg.timestamp();
- printTimeInCell(table, timestamp);
- }
-
- QScrollBar *bar = ui->textEdit->verticalScrollBar();
- bar->setValue(bar->maximum());
-}
-
-QString
-ChatDialog::formatTime(time_t timestamp)
-{
- struct tm *tm_time = localtime(×tamp);
- int hour = tm_time->tm_hour;
- QString amOrPM;
- if (hour > 12)
- {
- hour -= 12;
- amOrPM = "PM";
- }
- else
- {
- amOrPM = "AM";
- if (hour == 0)
- {
- hour = 12;
- }
- }
-
- char textTime[12];
- sprintf(textTime, "%d:%02d:%02d %s", hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
- return QString(textTime);
-}
-
-void
-ChatDialog::printTimeInCell(QTextTable *table, time_t timestamp)
-{
- QTextCharFormat timeFormat;
- timeFormat.setForeground(Qt::gray);
- timeFormat.setFontUnderline(true);
- timeFormat.setUnderlineColor(Qt::gray);
- QTextTableCell timeCell = table->cellAt(0, 1);
- timeCell.setFormat(timeFormat);
- timeCell.firstCursorPosition().insertText(formatTime(timestamp));
-}
-
-void
-ChatDialog::showMessage(QString from, QString data)
-{
- if (!isActiveWindow())
- {
- trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
- trayIcon->setIcon(QIcon(":/images/note.png"));
- }
-}
-
-void
-ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
-{
- // send msg
- size_t size = msg.ByteSize();
- char *buf = new char[size];
- msg.SerializeToArray(buf, size);
-
- if (!msg.IsInitialized())
- {
- _LOG_DEBUG("Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?");
- abort();
- }
- m_sock->publishData(m_user.getPrefix().toStdString(), m_session, buf, size, FRESHNESS);
-
- delete[] buf;
-
- m_lastMsgTime = time::now();
-
- uint64_t nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
- Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
- std::vector<Sync::MissingDataInfo> v;
- v.push_back(mdi);
- {
- boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
- m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
- m_scene->msgReceived(m_user.getPrefix(), m_user.getNick());
- }
-}
-
-void
-ChatDialog::openInviteListDialog()
-{
- m_inviteListDialog->setInviteLabel(m_chatroomPrefix.toUri());
- m_inviteListDialog->show();
-}
-
-void
-ChatDialog::sendInvitationWrapper(QString invitee, bool isIntroducer)
-{
- Name inviteeNamespace(invitee.toStdString());
- shared_ptr<ContactItem> inviteeItem = m_contactManager->getContact(inviteeNamespace);
- sendInvitation(inviteeItem, isIntroducer);
-}
-
-void
-ChatDialog::closeEvent(QCloseEvent *e)
-{
- if (trayIcon->isVisible())
- {
- QMessageBox::information(this, tr("Chronos"),
- tr("The program will keep running in the "
- "system tray. To terminate the program"
- "choose <b>Quit</b> in the context memu"
- "of the system tray entry."));
- hide();
- e->ignore();
- }
-}
-
-void
-ChatDialog::quit()
-{
- hide();
- emit closeChatDialog(m_chatroomPrefix);
-}
-
-
-
-
-#if WAF
-#include "chatdialog.moc"
-#include "chatdialog.cpp.moc"
-#endif
diff --git a/src/chatdialog.h b/src/chatdialog.h
deleted file mode 100644
index 5b7eea2..0000000
--- a/src/chatdialog.h
+++ /dev/null
@@ -1,392 +0,0 @@
-/* -*- 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: Zhenkai Zhu <zhenkai@cs.ucla.edu>
- * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- * Yingdi Yu <yingdi@cs.ucla.edu>
- */
-
-#ifndef CHATDIALOG_H
-#define CHATDIALOG_H
-
-#include <QDialog>
-#include <QTextTable>
-#include <QStringListModel>
-#include <QSystemTrayIcon>
-#include <QMenu>
-
-#include "invitelistdialog.h"
-
-#ifndef Q_MOC_RUN
-#include "contact-item.h"
-#include "chatbuf.pb.h"
-#include "digesttreescene.h"
-#include <sync-socket.h>
-#include <sync-seq-no.h>
-#include <ndn-cpp-dev/security/key-chain.hpp>
-#ifdef WITH_SECURITY
-#include "validator-invitation.h"
-#include <validator-sync.h>
-#else
-#include <ndn-cpp-dev/security/validator-null.hpp>
-#endif
-
-#include <boost/thread/locks.hpp>
-#include <boost/thread/recursive_mutex.hpp>
-#include <boost/thread/thread.hpp>
-#endif
-
-typedef ndn::function<void()> OnEventualTimeout;
-
-#define MAX_HISTORY_ENTRY 20
-
-namespace Ui {
-class ChatDialog;
-}
-
-class ChatDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit ChatDialog(ndn::shared_ptr<chronos::ContactManager> contactManager,
- ndn::shared_ptr<ndn::Face> face,
- const ndn::Name& chatroomPrefix,
- const ndn::Name& localPrefix,
- const ndn::Name& defaultIdentity,
- const std::string& nick,
- QWidget *parent = 0);
-
- ~ChatDialog();
-
- const ndn::Name&
- getChatroomPrefix() const
- { return m_chatroomPrefix; }
-
- const ndn::Name&
- getLocalPrefix() const
- { return m_localPrefix; }
-
- void
- sendInvitation(ndn::shared_ptr<chronos::ContactItem> contact, bool isIntroducer);
-
- void
- addChatDataRule(const ndn::Name& prefix,
- const ndn::IdentityCertificate& identityCertificate,
- bool isIntroducer);
-
- void
- addTrustAnchor(const chronos::EndorseCertificate& selfEndorseCertificate);
-
- void
- appendMessage(const SyncDemo::ChatMessage msg, bool isHistory = false);
-
- void
- processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo>&, Sync::SyncSocket *);
-
- void
- processDataWrapper(const ndn::shared_ptr<const ndn::Data>& data);
-
- void
- processDataNoShowWrapper(const ndn::shared_ptr<const ndn::Data>& data);
-
- void
- processRemoveWrapper(std::string);
-
- void
- publishIntroCert(const ndn::IdentityCertificate& dskCertificate, bool isIntroducer);
-
-protected:
- void
- closeEvent(QCloseEvent *e);
-
- void
- changeEvent(QEvent *e);
-
-private:
-
- void
- initializeSetting();
-
- QString
- getRandomString();
-
- void
- updateLabels();
-
- void
- initializeSync();
-
- void
- onTargetData(const ndn::Interest& interest,
- const ndn::Data& data,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed)
- { m_invitationValidator->validate(data, onValidated, onValidationFailed); }
-
- void
- onTargetTimeout(const ndn::Interest& interest,
- int retry,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed,
- const OnEventualTimeout& timeoutNotify)
- {
- if(retry > 0)
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
- else
- timeoutNotify();
- }
-
- void
- sendInterest(const ndn::Interest& interest,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed,
- const OnEventualTimeout& timeoutNotify,
- int retry = 1);
-
- void
- onInviteReplyValidated(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity,
- bool isIntroduce);
-
- void
- onInviteReplyValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity);
-
- void
- onInviteReplyTimeout(const ndn::Name& identity);
-
-
- void
- invitationRejected(const ndn::Name& identity);
-
- void
- invitationAccepted(const ndn::Name& identity,
- ndn::shared_ptr<const ndn::Data> data,
- const std::string& inviteePrefix,
- bool isIntroducer);
-
- void
- onLocalPrefix(const ndn::Interest& interest,
- ndn::Data& data);
-
- void
- onLocalPrefixTimeout(const ndn::Interest& interest);
-
- // void
- // fetchHistory(std::string name);
-
- void
- formChatMessage(const QString &text, SyncDemo::ChatMessage &msg);
-
- void
- formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type);
-
- void
- sendMsg(SyncDemo::ChatMessage &msg);
-
- void
- resizeEvent(QResizeEvent *);
-
- void
- showEvent(QShowEvent *);
-
- void
- fitView();
-
- void
- createActions();
-
- void
- createTrayIcon();
-
- QString
- formatTime(time_t);
-
- void
- printTimeInCell(QTextTable *, time_t);
-
- void
- disableTreeDisplay();
-
-signals:
- void
- dataReceived(ndn::shared_ptr<const ndn::Data> data, bool show, bool isHistory);
-
- void
- treeUpdated(const std::vector<Sync::MissingDataInfo>);
-
- void
- removeReceived(QString prefix);
-
- void
- closeChatDialog(const ndn::Name& chatroomPrefix);
-
- void
- noNdnConnection(const QString& msg);
-
- void
- inivationRejection(const QString& msg);
-
- void
- triggerHello();
-
- void
- triggerJoin();
-
- void
- triggerLeave();
-
- void
- triggerReplot();
-
- void
- triggerEnableTreeDisplay();
-
- void
- triggerReap();
-
-public slots:
- void
- processTreeUpdate(const std::vector<Sync::MissingDataInfo>&);
-
- void
- processData(ndn::shared_ptr<const ndn::Data> data, bool show, bool isHistory);
-
- void
- processRemove(QString prefix);
-
-private slots:
- void
- returnPressed();
-
- void
- treeButtonPressed();
-
- void
- settingUpdated(QString, QString, QString);
-
- void
- sendJoinWrapper();
-
- void
- sendJoin();
-
- void
- sendHelloWrapper();
-
- void
- sendHello();
-
- void
- sendLeave();
-
- void
- sendLeaveWrapper();
-
- void
- replot();
-
- void
- replotWrapper();
-
- void
- updateRosterList(QStringList);
-
- void
- enableTreeDisplay();
-
- void
- enableTreeDisplayWrapper();
-
- void
- updateLocalPrefix();
-
- void
- summonReaper();
-
- void
- reap();
-
- void
- reapWrapper();
-
- void
- iconActivated(QSystemTrayIcon::ActivationReason reason);
-
- void
- messageClicked();
-
- void
- showMessage(QString, QString);
-
- void
- openInviteListDialog();
-
- void
- sendInvitationWrapper(QString, bool);
-
- void
- quit();
-
-private:
- Ui::ChatDialog *ui;
- ndn::shared_ptr<chronos::ContactManager> m_contactManager;
- ndn::shared_ptr<ndn::Face> m_face;
- ndn::shared_ptr<boost::asio::io_service> m_ioService;
-
- ndn::Name m_chatroomPrefix;
- ndn::Name m_localPrefix;
- ndn::Name m_localChatPrefix;
- ndn::Name m_defaultIdentity;
- User m_user;
- std::string m_nick;
-
- ndn::Scheduler m_scheduler;
- ndn::EventId m_replotEventId;
-
-#ifndef WITH_SECURITY
- ndn::shared_ptr<ndn::Validator> m_invitationValidator;
- ndn::shared_ptr<ndn::Validator> m_syncValidator;
-#else
- ndn::shared_ptr<chronos::ValidatorInvitation> m_invitationValidator;
- ndn::shared_ptr<Sync::ValidatorSync> m_syncValidator;
-#endif
- ndn::shared_ptr<ndn::KeyChain> m_keyChain;
-
- ndn::Name m_newLocalPrefix;
- bool m_newLocalPrefixReady;
-
-
- Sync::SyncSocket *m_sock;
- uint64_t m_session;
- DigestTreeScene *m_scene;
- boost::recursive_mutex m_msgMutex;
- boost::recursive_mutex m_sceneMutex;
- int64_t m_lastMsgTime;
- int m_randomizedInterval;
-
-
- QStringListModel *m_rosterModel;
- QSystemTrayIcon *trayIcon;
-
- QAction *minimizeAction;
- QAction *maximizeAction;
- QAction *restoreAction;
- QAction *updateLocalPrefixAction;
- QAction *quitAction;
- QMenu *trayIconMenu;
-
- bool m_joined;
-
- QList<QString> m_zombieList;
- int m_zombieIndex;
-
- InviteListDialog* m_inviteListDialog;
-};
-
-#endif // ChatDIALOG_H
diff --git a/src/config.proto b/src/config.proto
new file mode 100644
index 0000000..59cd8cc
--- /dev/null
+++ b/src/config.proto
@@ -0,0 +1,6 @@
+package ChronoChat;
+
+message Conf {
+ required string identity = 1;
+ optional string nick = 2;
+}
\ No newline at end of file
diff --git a/src/contact-item.cpp b/src/contact-item.cpp
deleted file mode 100644
index 13201ae..0000000
--- a/src/contact-item.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- 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 "contact-item.h"
-
-#include "logging.h"
-
-using namespace std;
-using namespace ndn;
-
-INIT_LOGGER("ContactItem");
-
-namespace chronos{
-
-ContactItem::ContactItem(const EndorseCertificate& selfEndorseCertificate,
- bool isIntroducer,
- const string& alias)
- : m_selfEndorseCertificate(selfEndorseCertificate)
- , m_isIntroducer(isIntroducer)
-{
- Name endorsedkeyName = selfEndorseCertificate.getPublicKeyName();
-
- m_namespace = endorsedkeyName.getSubName(0, endorsedkeyName.size() - 1);
-
-
- m_name = selfEndorseCertificate.getProfile().get("name");
- m_alias = alias.empty() ? m_name : alias;
- m_institution = selfEndorseCertificate.getProfile().get("institution");
-}
-
-ContactItem::ContactItem(const ContactItem& contactItem)
- : m_selfEndorseCertificate(contactItem.m_selfEndorseCertificate)
- , m_namespace(contactItem.m_namespace)
- , m_alias(contactItem.m_alias)
- , m_name(contactItem.m_name)
- , m_institution(contactItem.m_institution)
- , m_isIntroducer(contactItem.m_isIntroducer)
- , m_trustScope(contactItem.m_trustScope)
-{}
-
-}
diff --git a/src/contact-item.h b/src/contact-item.h
deleted file mode 100644
index bd3ab8a..0000000
--- a/src/contact-item.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef CHRONOS_CONTACT_ITEM_H
-#define CHRONOS_CONTACT_ITEM_H
-
-#include "endorse-certificate.h"
-#include <ndn-cpp-dev/util/regex.hpp>
-#include <vector>
-
-
-namespace chronos{
-
-class ContactItem
-{
-public:
- typedef std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> >::const_iterator const_iterator;
- typedef std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> >::iterator iterator;
-
- ContactItem(const EndorseCertificate& selfEndorseCertificate,
- bool isIntroducer = false,
- const std::string& alias = "");
-
- ContactItem(const ContactItem& contactItem);
-
- virtual
- ~ContactItem() {}
-
- const EndorseCertificate&
- getSelfEndorseCertificate() const
- { return m_selfEndorseCertificate; }
-
- const ndn::Name&
- getNameSpace() const
- { return m_namespace; }
-
- const std::string&
- getAlias() const
- { return m_alias; }
-
- const std::string&
- getName() const
- { return m_name; }
-
- const std::string&
- getInstitution() const
- { return m_institution; }
-
- const ndn::Name&
- getPublicKeyName() const
- { return m_selfEndorseCertificate.getPublicKeyName(); }
-
- bool
- isIntroducer() const
- { return m_isIntroducer; }
-
- void
- setIsIntroducer(bool isIntroducer)
- { m_isIntroducer = isIntroducer; }
-
- void
- addTrustScope(const ndn::Name& nameSpace)
- { m_trustScope[nameSpace] = ndn::Regex::fromName(nameSpace); }
-
- void
- deleteTrustScope(const ndn::Name& nameSpace)
- {
- std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> >::iterator it = m_trustScope.find(nameSpace);
- if(it != m_trustScope.end())
- m_trustScope.erase(it);
- }
-
- bool
- canBeTrustedFor(const ndn::Name& name)
- {
- std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> >::iterator it = m_trustScope.begin();
-
- for(; it != m_trustScope.end(); it++)
- if(it->second->match(name))
- return true;
- return false;
- }
-
- const_iterator
- trustScopeBegin() const
- { return m_trustScope.begin(); }
-
- const_iterator
- trustScopeEnd() const
- { return m_trustScope.end(); }
-
- iterator
- trustScopeBegin()
- { return m_trustScope.begin(); }
-
- iterator
- trustScopeEnd()
- { return m_trustScope.end(); }
-
-
-protected:
- EndorseCertificate m_selfEndorseCertificate;
-
- ndn::Name m_namespace;
- std::string m_alias;
-
- std::string m_name;
- std::string m_institution;
-
- bool m_isIntroducer;
-
- std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> > m_trustScope;
-};
-
-}//chronos
-
-#endif
diff --git a/src/contact-manager.cpp b/src/contact-manager.cpp
index f755965..7be5017 100644
--- a/src/contact-manager.cpp
+++ b/src/contact-manager.cpp
@@ -12,38 +12,38 @@
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
-
#include "contact-manager.h"
+#include <QStringList>
#ifndef Q_MOC_RUN
-#include <ndn-cpp-dev/face.hpp>
-#include <ndn-cpp-dev/security/signature-sha256-with-rsa.hpp>
-
-#ifndef WITH_SECURITY
-#include <ndn-cpp-dev/security/validator-null.hpp>
-#else
+#include <ndn-cpp-dev/util/crypto.hpp>
+#include <ndn-cpp-dev/util/io.hpp>
+#include <ndn-cpp-dev/security/sec-rule-relative.hpp>
#include <ndn-cpp-dev/security/validator-regex.hpp>
#include <cryptopp/base64.h>
-#include <ndn-cpp-dev/security/sec-rule-relative.hpp>
-#endif
-
-#include "endorse-collection.pb.h"
+#include <cryptopp/files.h>
+#include <cryptopp/sha.h>
+#include <boost/asio.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/filesystem.hpp>
#include "logging.h"
#endif
using namespace ndn;
using namespace std;
+namespace fs = boost::filesystem;
-INIT_LOGGER("ContactManager");
+INIT_LOGGER("chronos.ContactManager");
namespace chronos{
+static const uint8_t DNS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.
+
ContactManager::ContactManager(shared_ptr<Face> face,
QObject* parent)
: QObject(parent)
- , m_contactStorage(new ContactStorage())
- , m_dnsStorage(new DnsStorage())
, m_face(face)
+ , m_dnsListenerId(0)
{
initializeSecurity();
}
@@ -51,108 +51,37 @@
ContactManager::~ContactManager()
{}
+// private methods
void
ContactManager::initializeSecurity()
{
-
-#ifndef WITH_SECURITY
-
- m_keyChain = make_shared<KeyChain>();
- m_validator = make_shared<ValidatorNull>();
+ fs::path anchorPath = fs::path(getenv("HOME")) / ".chronos" / "anchor.cert";
+ shared_ptr<IdentityCertificate> anchor = io::load<IdentityCertificate>(anchorPath.c_str());
-#else
-
- shared_ptr<SecPolicySimple> policy = make_shared<SecPolicySimple>();
- m_verifier = make_shared<Verifier>(policy);
- m_verifier->setFace(m_face);
-
- policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><ENDORSED>",
- "^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
- "==", "\\1", "\\1\\2", true));
- policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
- "^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
- "==", "\\1", "\\1\\2", true));
- policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
- "^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$",
- "==", "\\1", "\\1\\2", true));
- policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
- "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
- ">", "\\1\\2", "\\1", true));
- policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
- "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
- "==", "\\1", "\\1\\2", true));
- policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^(<>*)$",
- "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
- ">", "\\1", "\\1\\2", true));
-
-
- policy->addSigningPolicyRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
- "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
- "==", "\\1", "\\1\\2", true));
-
-
- const string TrustAnchor("BIICqgOyEIWlKzDI2xX2hdq5Azheu9IVyewcV4uM7ylfh67Y8MIxF3tDCTx5JgEn\
-HYMuCaYQm6XuaXTlVfDdWff/K7Xebq8IgGxjNBeU9eMf7Gy9iIMrRAOdBG0dBHmo\
-67biGs8F+P1oh1FwKu/FN1AE9vh8HSOJ94PWmjO+6PvITFIXuI3QbcCz8rhvbsfb\
-5X/DmfbJ8n8c4X3nVxrBm6fd4z8kOFOvvhgJImvqsow69Uy+38m8gJrmrcWMoPBJ\
-WsNLcEriZCt/Dlg7EqqVrIn6ukylKCvVrxA9vm/cEB74J/N+T0JyMRDnTLm17gpq\
-Gd75rhj+bLmpOMOBT7Nb27wUKq8gcXzeAADy+p1uZG4A+p1LRVkA+vVrc2stMTM4\
-MzMyNTcyMAD6vUlELUNFUlQA+q39PgurHgAAAaID4gKF5vjua9EIr3/Fn8k1AdSc\
-nEryjVDW3ikvYoSwjK7egTkAArq1BSc+C6sdAAHiAery+p1uZG4A+p1LRVkA+vVr\
-c2stMTM4MzMyNTcyMAD6vUlELUNFUlQAAAAAAAGaFr0wggFjMCIYDzIwMTMxMTAx\
-MTcxMTIyWhgPMjAxNDExMDExNzExMjJaMBkwFwYDVQQpExBORE4gVGVzdGJlZCBS\
-b290MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA06x+elwzWCHa4I3b\
-yrYCMAIVxQpRVLuOXp0h+BS+5GNgMVPi7+40o4zSJG+kiU8CIH1mtj8RQAzBX9hF\
-I5VAyOC8nS8D8YOfBwt2yRDZPgt1E5PpyYUBiDYuq/zmJDL8xjxAlxrMzVOqD/uj\
-/vkkcBM/T1t9Q6p1CpRyq+GMRbV4EAHvH7MFb6bDrH9t8DHEg7NPUCaSQBrd7PvL\
-72P+QdiNH9zs/EiVzAkeMG4iniSXLuYM3z0gMqqcyUUUr6r1F9IBmDO+Kp97nZh8\
-VCL+cnIEwyzAFAupQH5GoXUWGiee8oKWwH2vGHX7u6sWZsCp15NMSG3OC4jUIZOE\
-iVUF1QIBEQAA");
-
- string decoded;
- CryptoPP::StringSource ss(reinterpret_cast<const unsigned char *>(TrustAnchor.c_str()),
- TrustAnchor.size(),
- true,
- new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
- Data data;
- data.wireDecode(Block(reinterpret_cast<const uint8_t*>(decoded.c_str()), decoded.size()));
- shared_ptr<IdentityCertificate> anchor = make_shared<IdentityCertificate>(data);
- policy->addTrustAnchor(anchor);
-#endif
-}
-
-
-void
-ContactManager::fetchSelfEndorseCertificate(const ndn::Name& identity)
-{
- Name interestName = identity;
- interestName.append("DNS").append("PROFILE");
-
- Interest interest(interestName);
- interest.setMustBeFresh(true);
-
- OnDataValidated onValidated = bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identity);
- OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, identity);
- TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, identity);
-
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
-}
-
-void
-ContactManager::onDnsSelfEndorseCertValidated(const shared_ptr<const Data>& data,
- const Name& identity)
-{
- try{
- Data plainData;
- plainData.wireDecode(data->getContent().blockFromValue());
- EndorseCertificate selfEndorseCertificate(plainData);
- if(Validator::verifySignature(plainData, plainData.getSignature(), selfEndorseCertificate.getPublicKeyInfo()))
- emit contactFetched(selfEndorseCertificate);
- else
- emit contactFetchFailed(identity);
- }catch(...){
- emit contactFetchFailed (identity);
- }
+ shared_ptr<ValidatorRegex> validator = make_shared<ValidatorRegex>(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
@@ -167,254 +96,799 @@
OnDataValidated onValidated = bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsCollectEndorseValidationFailed, this, _1, identity);
- TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, identity);
+ TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, _1, identity);
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
+ sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}
void
-ContactManager::fetchKey(const Name& certName)
+ContactManager::fetchEndorseCertificateInternal(const Name& identity, int certIndex)
{
- Name interestName = certName;
-
+ shared_ptr<EndorseCollection> endorseCollection = m_bufferedContacts[identity].m_endorseCollection;
+
+ if(certIndex >= endorseCollection->endorsement_size())
+ prepareEndorseInfo(identity);
+
+ Name interestName(endorseCollection->endorsement(certIndex).certname());
+
Interest interest(interestName);
interest.setInterestLifetime(1000);
interest.setMustBeFresh(true);
- OnDataValidated onValidated = bind(&ContactManager::onKeyValidated, this, _1, certName);
- OnDataValidationFailed onValidationFailed = bind(&ContactManager::onKeyValidationFailed, this, _1, certName);
- TimeoutNotify timeoutNotify = bind(&ContactManager::onKeyTimeoutNotify, this, certName);
-
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
+ m_face->expressInterest(interest,
+ bind(&ContactManager::onEndorseCertificateInternal,
+ this, _1, _2, identity, certIndex,
+ endorseCollection->endorsement(certIndex).hash()),
+ bind(&ContactManager::onEndorseCertificateInternalTimeout,
+ this, _1, identity, certIndex));
}
void
-ContactManager::onKeyValidated(const shared_ptr<const Data>& data, const Name& identity)
+ContactManager::prepareEndorseInfo(const Name& identity)
{
- IdentityCertificate identityCertificate(*data);
- Profile profile(identityCertificate);
+ // _LOG_DEBUG("prepareEndorseInfo");
+ const Profile& profile = m_bufferedContacts[identity].m_selfEndorseCert->getProfile();
- try{
- EndorseCertificate endorseCertificate(identityCertificate, profile);
- m_keyChain->sign(endorseCertificate);
- emit contactKeyFetched (endorseCertificate);
- }catch(...){
- return;
+ shared_ptr<EndorseInfo> endorseInfo = make_shared<EndorseInfo>();
+ m_bufferedContacts[identity].m_endorseInfo = endorseInfo;
+
+ Profile::const_iterator pIt = profile.begin();
+ Profile::const_iterator pEnd = profile.end();
+
+ map<string, int> endorseCount;
+ for(; pIt != pEnd; pIt++)
+ {
+ // _LOG_DEBUG("prepareEndorseInfo: profile[" << pIt->first << "]: " << pIt->second);
+ endorseCount[pIt->first] = 0;
+ }
+
+ int 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();
+ vector<string>::const_iterator eIt = endorseList.begin();
+ for(; eIt != endorseList.end(); eIt++)
+ endorseCount[*eIt] += 1;
+ }
+
+ pIt = profile.begin();
+ pEnd = profile.end();
+ for(; pIt != pEnd; pIt++)
+ {
+ EndorseInfo::Endorsement* endorsement = endorseInfo->add_endorsement();
+ endorsement->set_type(pIt->first);
+ endorsement->set_value(pIt->second);
+ stringstream ss;
+ ss << endorseCount[pIt->first] << "/" << endorseCertCount;
+ endorsement->set_endorse(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(Data::Error& e)
+ {
+ emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+ }
+ catch(EndorseCertificate::Error& e)
+ {
+ emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+ }
+}
+
+void
+ContactManager::onDnsSelfEndorseCertValidationFailed(const shared_ptr<const Data>& data,
+ 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)
+{
+ shared_ptr<EndorseCollection> endorseCollection = make_shared<EndorseCollection>();
+ if(!endorseCollection->ParseFromArray(data->getContent().value(), data->getContent().value_size()))
+ {
+ m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
+ fetchEndorseCertificateInternal(identity, 0);
+ }
+ else
+ prepareEndorseInfo(identity);
+}
+
+void
+ContactManager::onDnsCollectEndorseValidationFailed(const shared_ptr<const Data>& data,
+ 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,
+ int certIndex,
+ string hash)
+{
+ 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,
+ int certIndex)
+{
+ fetchEndorseCertificateInternal(identity, certIndex+1);
+}
+
+void
+ContactManager::collectEndorsement()
+{
+ {
+ boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
+ m_collectCount = m_contactList.size();
+
+ ContactList::iterator it = m_contactList.begin();
+ ContactList::iterator end = m_contactList.end();
+
+ for(; it != end ; it++)
+ {
+ Name interestName = (*it)->getNameSpace();
+ interestName.append("DNS").append(m_identity.wireEncode()).append("ENDORSEE");
+
+ Interest interest(interestName);
+ interest.setInterestLifetime(1000);
+
+ OnDataValidated onValidated = bind(&ContactManager::onDnsEndorseeValidated, this, _1);
+ OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1);
+ TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);
+
+ sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
+ }
}
}
void
-ContactManager::fetchIdCertificate(const Name& certName)
+ContactManager::onDnsEndorseeValidated(const shared_ptr<const Data>& data)
{
- Name interestName = certName;
-
- Interest interest(interestName);
- interest.setInterestLifetime(1000);
- interest.setMustBeFresh(true);
+ Data endorseData;
+ endorseData.wireDecode(data->getContent().blockFromValue());
- OnDataValidated onValidated = bind(&ContactManager::onIdCertValidated, this, _1, certName);
- OnDataValidationFailed onValidationFailed = bind(&ContactManager::onIdCertValidationFailed, this, _1, certName);
- TimeoutNotify timeoutNotify = bind(&ContactManager::onIdCertTimeoutNotify, this, certName);
+ EndorseCertificate endorseCertificate(endorseData);
+ m_contactStorage->updateCollectEndorse(endorseCertificate);
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
+ decreaseCollectStatus();
}
void
-ContactManager::updateProfileData(const Name& identity)
+ContactManager::onDnsEndorseeValidationFailed(const shared_ptr<const Data>& data)
{
- // Get current profile;
- shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile(identity);
- if(!static_cast<bool>(newProfile))
- return;
-
- shared_ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
-
- if(!static_cast<bool>(newEndorseCertificate))
- return;
-
- m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate, identity);
-
- publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
+ decreaseCollectStatus();
}
void
-ContactManager::updateEndorseCertificate(const ndn::Name& identity, const ndn::Name& signerIdentity)
+ContactManager::onDnsEndorseeTimeoutNotify(const Interest& interest)
{
- shared_ptr<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identity, signerIdentity);
-
- if(!static_cast<bool>(newEndorseCertificate))
- return;
-
- m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identity);
-
- publishEndorseCertificateInDNS(*newEndorseCertificate, signerIdentity);
+ decreaseCollectStatus();
}
-shared_ptr<EndorseCertificate>
-ContactManager::generateEndorseCertificate(const Name& identity, const Name& signerIdentity)
+void
+ContactManager::decreaseCollectStatus()
{
- shared_ptr<ContactItem> contact = getContact(identity);
- if(!static_cast<bool>(contact))
- return shared_ptr<EndorseCertificate>();
+ int count;
+ {
+ boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
+ m_collectCount--;
+ count = m_collectCount;
+ }
- Name signerKeyName = m_keyChain->getDefaultKeyNameForIdentity(signerIdentity);
+ if(count == 0)
+ publishCollectEndorsedDataInDNS();
+}
- vector<string> endorseList;
- m_contactStorage->getEndorseList(identity, endorseList);
+void
+ContactManager::publishCollectEndorsedDataInDNS()
+{
+ Name dnsName = m_identity;
+ dnsName.append("DNS").append("ENDORSED").appendVersion();
- try{
- shared_ptr<EndorseCertificate> cert = make_shared<EndorseCertificate>(contact->getSelfEndorseCertificate(), signerKeyName, endorseList);
- m_keyChain->signByIdentity(*cert, signerIdentity);
- return cert;
- }catch(...){
- return shared_ptr<EndorseCertificate>();
- }
+ Data data;
+ data.setName(dnsName);
+
+ EndorseCollection endorseCollection;
+ m_contactStorage->getCollectEndorse(endorseCollection);
+
+ OBufferStream os;
+ endorseCollection.SerializeToOstream(&os);
+
+ data.setContent(os.buf());
+ 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)
+{
+ _LOG_DEBUG("ContactManager::onIdentityCertValidationFailed " << data->getName());
+ decreaseIdCertCount();
+}
+
+void
+ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
+{
+ _LOG_DEBUG("ContactManager::onIdentityCertTimeoutNotify: " << interest.getName());
+ decreaseIdCertCount();
+}
+
+void
+ContactManager::decreaseIdCertCount()
+{
+ int count;
+ {
+ boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
+ m_idCertCount--;
+ count = m_idCertCount;
+ }
+
+ if(count == 0)
+ {
+ QStringList certNameList;
+ QStringList nameList;
+
+ BufferedIdCerts::const_iterator it = m_bufferedIdCerts.begin();
+ BufferedIdCerts::const_iterator end = m_bufferedIdCerts.end();
+ for(; it != 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 Name& identity,
- const Profile& profile)
+ContactManager::getSignedSelfEndorseCertificate(const Profile& profile)
{
- Name certificateName = m_keyChain->getDefaultCertificateNameForIdentity(identity);
- if(0 == certificateName.size())
- return shared_ptr<EndorseCertificate>();
+ Name certificateName = m_keyChain.getDefaultCertificateNameForIdentity(m_identity);
- Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
- shared_ptr<IdentityCertificate> kskCert;
-
- if(signingKeyName.get(-1).toEscapedString().substr(0,4) == "dsk-")
- {
- shared_ptr<IdentityCertificate> signingCert = m_keyChain->getCertificate(certificateName);
- if(!static_cast<bool>(signingCert))
- return shared_ptr<EndorseCertificate>();
-
- try{
- SignatureSha256WithRsa dskCertSig(signingCert->getSignature());
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(dskCertSig.getKeyLocator().getName());
- Name kskCertName = m_keyChain->getDefaultCertificateNameForKey(keyName);
- kskCert = m_keyChain->getCertificate(kskCertName);
- }catch(...){
- return shared_ptr<EndorseCertificate>();
- }
- }
- else
- kskCert = m_keyChain->getCertificate(certificateName);
-
- if(!static_cast<bool>(kskCert))
- return shared_ptr<EndorseCertificate>();
+ shared_ptr<IdentityCertificate> signingCert = m_keyChain.getCertificate(certificateName);
vector<string> endorseList;
Profile::const_iterator it = profile.begin();
for(; it != profile.end(); it++)
endorseList.push_back(it->first);
- try{
- shared_ptr<EndorseCertificate> selfEndorseCertificate = make_shared<EndorseCertificate>(*kskCert, profile, endorseList);
- m_keyChain->sign(*selfEndorseCertificate, kskCert->getName());
- return selfEndorseCertificate;
- }catch(...){
- return shared_ptr<EndorseCertificate>();
- }
+ shared_ptr<EndorseCertificate> selfEndorseCertificate =
+ shared_ptr<EndorseCertificate>(new EndorseCertificate(*signingCert, profile, endorseList));
+
+ m_keyChain.sign(*selfEndorseCertificate, certificateName);
+
+ return selfEndorseCertificate;
}
void
ContactManager::publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate)
{
- Data data;
-
- Name identity = selfEndorseCertificate.getPublicKeyName().getPrefix(-1);
-
- Name dnsName = identity;
+ Name dnsName = m_identity;
dnsName.append("DNS").append("PROFILE").appendVersion();
+
+ Data data;
data.setName(dnsName);
data.setContent(selfEndorseCertificate.wireEncode());
+ data.setFreshnessPeriod(1000);
- m_keyChain->signByIdentity(data, identity);
- m_dnsStorage->updateDnsSelfProfileData(data, identity);
+ m_keyChain.signByIdentity(data, m_identity);
+
+ m_contactStorage->updateDnsSelfProfileData(data);
m_face->put(data);
}
-void
-ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate, const Name& signerIdentity)
+shared_ptr<EndorseCertificate>
+ContactManager::generateEndorseCertificate(const Name& identity)
{
- Data data;
+ 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();
- Name dnsName = signerIdentity;
- dnsName.append("DNS").append(endorsee.wireEncode()).append("ENDORSEE").appendVersion();
+ Data data;
data.setName(dnsName);
-
data.setContent(endorseCertificate.wireEncode());
- m_keyChain->signByIdentity(data, signerIdentity);
- m_dnsStorage->updateDnsEndorseOthers(data, signerIdentity, endorsee);
+ m_keyChain.signByIdentity(data, m_identity);
+
+ m_contactStorage->updateDnsEndorseOthers(data, dnsName.get(-3).toEscapedString());
m_face->put(data);
}
void
-ContactManager::publishCollectEndorsedDataInDNS(const Name& identity)
+ContactManager::sendInterest(const Interest& interest,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ const TimeoutNotify& timeoutNotify,
+ int retry /* = 1 */)
{
- Data data;
+ m_face->expressInterest(interest,
+ bind(&ContactManager::onTargetData,
+ this, _1, _2, onValidated, onValidationFailed),
+ bind(&ContactManager::onTargetTimeout,
+ this, _1, retry, onValidated, onValidationFailed, timeoutNotify));
+}
- Name dnsName = identity;
- dnsName.append("DNS").append("ENDORSED").appendVersion();
- data.setName(dnsName);
-
- vector<Buffer> collectEndorseList;
- m_contactStorage->getCollectEndorseList(identity, collectEndorseList);
-
- Chronos::EndorseCollection endorseCollection;
+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);
+}
- vector<Buffer>::const_iterator it = collectEndorseList.begin();
- for(; it != collectEndorseList.end(); it++)
+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))
{
- string entryStr(reinterpret_cast<const char*>(it->buf()), it->size());
- endorseCollection.add_endorsement()->set_blob(entryStr);
+ data = m_contactStorage->getDnsData("N/A", interestName.get(prefix.size()).toEscapedString());
+ if(static_cast<bool>(data))
+ m_face->put(*data);
+ return;
}
- string encoded;
- endorseCollection.SerializeToString(&encoded);
-
- data.setContent(reinterpret_cast<const uint8_t*>(encoded.c_str()), encoded.size());
+ if(interestName.size() == (prefix.size()+2))
+ {
+ data = m_contactStorage->getDnsData(interestName.get(prefix.size()).toEscapedString(),
+ interestName.get(prefix.size()+1).toEscapedString());
+ if(static_cast<bool>(data))
+ m_face->put(*data);
+ return;
+ }
+}
- m_keyChain->signByIdentity(data, identity);
- m_dnsStorage->updateDnsOthersEndorse(data, identity);
- m_face->put(data);
+void
+ContactManager::onDnsRegisterFailed(const Name& prefix, const 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);
+
+ if(m_dnsListenerId)
+ m_face->unsetInterestFilter(m_dnsListenerId);
+
+ Name dnsPrefix;
+ dnsPrefix.append(m_identity).append("DNS");
+ m_dnsListenerId = m_face->setInterestFilter(dnsPrefix,
+ bind(&ContactManager::onDnsInterest, this, _1, _2),
+ bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));
+
+ m_contactList.clear();
+ m_contactStorage->getAllContacts(m_contactList);
+
+ m_bufferedContacts.clear();
+
+ collectEndorsement();
}
void
-ContactManager::addContact(const IdentityCertificate& identityCertificate, const Profile& profile)
+ContactManager::onFetchContactInfo(const QString& identity)
{
- try{
- EndorseCertificate endorseCertificate(identityCertificate, profile);
-
- m_keyChain->signByIdentity(endorseCertificate, m_defaultIdentity);
+ // try to fetch self-endorse-certificate via DNS PROFILE first.
+ Name identityName(identity.toStdString());
+ Name interestName;
+ interestName.append(identityName).append("DNS").append("PROFILE");
- ContactItem contactItem(endorseCertificate);
+ // _LOG_DEBUG("onFetchContactInfo " << identity.toStdString() << " profile: " << interestName);
+
+ Interest interest(interestName);
+ interest.setInterestLifetime(1000);
+ interest.setMustBeFresh(true);
- m_contactStorage->addContact(contactItem);
+ OnDataValidated onValidated = bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
+ OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, identityName);
+ TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, _1, identityName);
- emit contactAdded(contactItem.getNameSpace());
+ sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
+}
- }catch(std::runtime_error& e){
- emit warning(e.what());
- _LOG_ERROR("Exception: " << e.what());
+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()
+{
+ return; // the website info is not available.
+
+ std::vector<std::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);
+ std::string http_version;
+ response_stream >> http_version;
+ unsigned int status_code;
+ response_stream >> status_code;
+ std::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;
+ std::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();
+
+ std::vector<std::string>::const_iterator it = bufferedIdCertNames.begin();
+ std::vector<std::string>::const_iterator end = bufferedIdCertNames.end();
+ for(; it != end; it++)
+ {
+ Name certName(*it);
+
+ Interest interest(certName);
+ interest.setInterestLifetime(1000);
+ interest.setMustBeFresh(true);
+
+ OnDataValidated onValidated = bind(&ContactManager::onIdentityCertValidated, this, _1);
+ OnDataValidationFailed onValidationFailed = bind(&ContactManager::onIdentityCertValidationFailed, this, _1);
+ TimeoutNotify timeoutNotify = bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);
+
+ sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
+ }
+
}
void
-ContactManager::removeContact(const Name& contactNameSpace)
+ContactManager::onFetchIdCert(const QString& qCertName)
{
- shared_ptr<ContactItem> contact = getContact(contactNameSpace);
- if(!static_cast<bool>(contact))
- return;
- m_contactStorage->removeContact(contactNameSpace);
- emit contactRemoved(contact->getPublicKeyName());
+ Name certName(qCertName.toStdString());
+ if(m_bufferedIdCerts.find(certName) != m_bufferedIdCerts.end())
+ {
+ emit idCertReady(*m_bufferedIdCerts[certName]);
+ }
}
-}//chronos
+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()
+{
+ ContactList::const_iterator it = m_contactList.begin();
+ ContactList::const_iterator end = m_contactList.end();
+
+ QStringList aliasList;
+ QStringList idList;
+ for(; it != 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)
+{
+ ContactList::const_iterator it = m_contactList.begin();
+ ContactList::const_iterator end = m_contactList.end();
+
+ for(; it != 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 chronos
#if WAF
diff --git a/src/contact-manager.h b/src/contact-manager.h
index c61a720..6bcd429 100644
--- a/src/contact-manager.h
+++ b/src/contact-manager.h
@@ -15,17 +15,21 @@
#ifndef Q_MOC_RUN
#include "contact-storage.h"
-#include "dns-storage.h"
#include "endorse-certificate.h"
#include "profile.h"
+#include "endorse-info.pb.h"
+#include "endorse-collection.pb.h"
#include <ndn-cpp-dev/face.hpp>
#include <ndn-cpp-dev/security/key-chain.hpp>
#include <ndn-cpp-dev/security/validator.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/recursive_mutex.hpp>
#endif
namespace chronos{
-typedef ndn::function<void()> TimeoutNotify;
+typedef ndn::function<void(const ndn::Interest&)> TimeoutNotify;
+typedef std::vector<ndn::shared_ptr<Contact> > ContactList;
class ContactManager : public QObject
{
@@ -37,273 +41,253 @@
~ContactManager();
- void
- fetchSelfEndorseCertificate(const ndn::Name& identity);
+ ndn::shared_ptr<Contact>
+ getContact(const ndn::Name& identity)
+ {
+ return m_contactStorage->getContact(identity);
+ }
void
- fetchKey(const ndn::Name& identity);
+ getContactList(ContactList& contactList)
+ {
+ contactList.clear();
+ contactList.insert(contactList.end(), m_contactList.begin(), m_contactList.end());
+ }
+private:
+ void
+ initializeSecurity();
void
fetchCollectEndorse(const ndn::Name& identity);
void
- fetchIdCertificate(const ndn::Name& certName);
+ fetchEndorseCertificateInternal(const ndn::Name& identity, int certIndex);
void
- updateProfileData(const ndn::Name& identity);
+ prepareEndorseInfo(const ndn::Name& identity);
+
+ // PROFILE: self-endorse-certificate
+ void
+ onDnsSelfEndorseCertValidated(const ndn::shared_ptr<const ndn::Data>& selfEndorseCertificate,
+ const ndn::Name& identity);
void
- updateEndorseCertificate(const ndn::Name& identity, const ndn::Name& signerIdentity);
-
- inline void
- getContactItemList(std::vector<ndn::shared_ptr<ContactItem> >& contacts);
-
- ndn::shared_ptr<ContactStorage>
- getContactStorage()
- { return m_contactStorage; }
-
- inline ndn::shared_ptr<ContactItem>
- getContact(const ndn::Name& contactNamespace);
-
- ndn::shared_ptr<DnsStorage>
- getDnsStorage()
- { return m_dnsStorage; }
-
- ndn::Name
- getDefaultIdentity()
- { return m_keyChain->getDefaultIdentity(); }
+ onDnsSelfEndorseCertValidationFailed(const ndn::shared_ptr<const ndn::Data>& selfEndorseCertificate,
+ const ndn::Name& identity);
void
- publishCollectEndorsedDataInDNS(const ndn::Name& identity);
+ onDnsSelfEndorseCertTimeoutNotify(const ndn::Interest& interest,
+ const ndn::Name& identity);
+
+ // ENDORSED: endorse-collection
+ void
+ onDnsCollectEndorseValidated(const ndn::shared_ptr<const ndn::Data>& data,
+ const ndn::Name& identity);
void
- setDefaultIdentity(const ndn::Name& identity)
- { m_defaultIdentity = identity; }
+ onDnsCollectEndorseValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
+ const ndn::Name& identity);
void
- addContact(const ndn::IdentityCertificate& idCert, const Profile& profile);
+ onDnsCollectEndorseTimeoutNotify(const ndn::Interest& interest,
+ const ndn::Name& identity);
+
+ // PROFILE-CERT: endorse-certificate
+ void
+ onEndorseCertificateInternal(const ndn::Interest& interest,
+ ndn::Data& data,
+ const ndn::Name& identity,
+ int certIndex,
+ std::string hash);
void
- removeContact(const ndn::Name& contactNameSpace);
+ onEndorseCertificateInternalTimeout(const ndn::Interest& interest,
+ const ndn::Name& identity,
+ int certIndex);
+
+ // Collect endorsement
+ void
+ collectEndorsement();
+
+ void
+ onDnsEndorseeValidated(const ndn::shared_ptr<const ndn::Data>& data);
+
+ void
+ onDnsEndorseeValidationFailed(const ndn::shared_ptr<const ndn::Data>& data);
+
+ void
+ onDnsEndorseeTimeoutNotify(const ndn::Interest& interest);
+
+ void
+ decreaseCollectStatus();
+
+ void
+ publishCollectEndorsedDataInDNS();
+
+ // Identity certificate
+ void
+ onIdentityCertValidated(const ndn::shared_ptr<const ndn::Data>& data);
-private:
void
- initializeSecurity();
+ onIdentityCertValidationFailed(const ndn::shared_ptr<const ndn::Data>& data);
+ void
+ onIdentityCertTimeoutNotify(const ndn::Interest& interest);
+
+ void
+ decreaseIdCertCount();
+
+ // Publish self-endorse certificate
ndn::shared_ptr<EndorseCertificate>
- getSignedSelfEndorseCertificate(const ndn::Name& identity, const Profile& profile);
-
- ndn::shared_ptr<EndorseCertificate>
- generateEndorseCertificate(const ndn::Name& identity, const ndn::Name& signerIdentity);
+ getSignedSelfEndorseCertificate(const Profile& profile);
void
publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate);
- void
- publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate, const ndn::Name& signerIdentity);
+ // Publish endorse certificate
+ ndn::shared_ptr<EndorseCertificate>
+ generateEndorseCertificate(const ndn::Name& identity);
- inline void
+ void
+ publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate);
+
+ // Communication
+ void
sendInterest(const ndn::Interest& interest,
const ndn::OnDataValidated& onValidated,
const ndn::OnDataValidationFailed& onValidationFailed,
const TimeoutNotify& timeoutNotify,
int retry = 1);
- inline void
+ void
onTargetData(const ndn::Interest& interest,
const ndn::Data& data,
const ndn::OnDataValidated& onValidated,
const ndn::OnDataValidationFailed& onValidationFailed);
- inline void
+ void
onTargetTimeout(const ndn::Interest& interest,
int retry,
const ndn::OnDataValidated& onValidated,
const ndn::OnDataValidationFailed& onValidationFailed,
const TimeoutNotify& timeoutNotify);
- void
- onDnsSelfEndorseCertValidated(const ndn::shared_ptr<const ndn::Data>& selfEndorseCertificate, const ndn::Name& identity);
-
- inline void
- onDnsSelfEndorseCertValidationFailed(const ndn::shared_ptr<const ndn::Data>& selfEndorseCertificate, const ndn::Name& identity);
-
- inline void
- onDnsSelfEndorseCertTimeoutNotify(const ndn::Name& identity);
-
-
- inline void
- onDnsCollectEndorseValidated(const ndn::shared_ptr<const ndn::Data>& data, const ndn::Name& identity);
-
- inline void
- onDnsCollectEndorseValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const ndn::Name& identity);
-
- inline void
- onDnsCollectEndorseTimeoutNotify(const ndn::Name& identity);
-
-
+ // DNS listener
void
- onKeyValidated(const ndn::shared_ptr<const ndn::Data>& data, const ndn::Name& identity);
-
- inline void
- onKeyValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const ndn::Name& identity);
-
- inline void
- onKeyTimeoutNotify(const ndn::Name& identity);
-
-
- inline void
- onIdCertValidated(const ndn::shared_ptr<const ndn::Data>& data, const ndn::Name& identity);
-
- inline void
- onIdCertValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const ndn::Name& identity);
-
- inline void
- onIdCertTimeoutNotify(const ndn::Name& identity);
+ onDnsInterest(const ndn::Name& prefix, const ndn::Interest& interest);
+ void
+ onDnsRegisterFailed(const ndn::Name& prefix, const std::string& failInfo);
signals:
void
- noNdnConnection(const QString& msg);
-
- void
- contactFetched(const chronos::EndorseCertificate& endorseCertificate);
+ contactEndorseInfoReady(const chronos::EndorseInfo& endorseInfo);
+
+ void
+ contactInfoFetchFailed(const QString& identity);
+
+ void
+ idCertNameListReady(const QStringList& certNameList);
void
- contactFetchFailed(const ndn::Name& identity);
+ nameListReady(const QStringList& certNameList);
void
- contactKeyFetched(const chronos::EndorseCertificate& endorseCertificate);
+ idCertReady(const ndn::IdentityCertificate& idCert);
void
- contactKeyFetchFailed(const ndn::Name& identity);
+ contactAliasListReady(const QStringList& aliasList);
- void
- contactCertificateFetched(const ndn::IdentityCertificate& identityCertificate);
+ void
+ contactIdListReady(const QStringList& idList);
+
+ void
+ contactInfoReady(const QString& identity,
+ const QString& name,
+ const QString& institute,
+ bool isIntro);
+
+ void
+ warning(const QString& msg);
+
+public slots:
+ void
+ onIdentityUpdated(const QString& identity);
+
+ void
+ onFetchContactInfo(const QString& identity);
void
- contactCertificateFetchFailed(const ndn::Name& identity);
-
- void
- collectEndorseFetched(const ndn::Data& data);
+ onAddFetchedContact(const QString& identity);
void
- collectEndorseFetchFailed(const ndn::Name& identity);
+ onUpdateProfile();
void
- warning(QString msg);
+ onRefreshBrowseContact();
void
- contactRemoved(const ndn::Name& identity);
+ onFetchIdCert(const QString& certName);
void
- contactAdded(const ndn::Name& identity);
+ onAddFetchedContactIdCert(const QString& identity);
-private slots:
+ void
+ onWaitForContactList();
+
+ void
+ onWaitForContactInfo(const QString& identity);
-
+ void
+ onRemoveContact(const QString& identity);
+
+ void
+ onUpdateAlias(const QString& identity, const QString& alias);
+
+ void
+ onUpdateIsIntroducer(const QString& identity, bool isIntro);
+
+ void
+ onUpdateEndorseCertificate(const QString& identity);
+
private:
+ class FetchedInfo {
+ public:
+ ndn::shared_ptr<EndorseCertificate> m_selfEndorseCert;
+ ndn::shared_ptr<EndorseCollection> m_endorseCollection;
+ std::vector<ndn::shared_ptr<EndorseCertificate> > m_endorseCertList;
+ ndn::shared_ptr<EndorseInfo> m_endorseInfo;
+ };
+
+ typedef std::map<ndn::Name, FetchedInfo> BufferedContacts;
+ typedef std::map<ndn::Name, ndn::shared_ptr<ndn::IdentityCertificate> > BufferedIdCerts;
+
+ typedef boost::recursive_mutex RecLock;
+ typedef boost::unique_lock<RecLock> UniqueRecLock;
+
+ // Conf
ndn::shared_ptr<ContactStorage> m_contactStorage;
- ndn::shared_ptr<DnsStorage> m_dnsStorage;
ndn::shared_ptr<ndn::Validator> m_validator;
ndn::shared_ptr<ndn::Face> m_face;
- ndn::shared_ptr<ndn::KeyChain> m_keyChain;
- ndn::Name m_defaultIdentity;
+ ndn::KeyChain m_keyChain;
+ ndn::Name m_identity;
+ ContactList m_contactList;
+
+ // Buffer
+ BufferedContacts m_bufferedContacts;
+ BufferedIdCerts m_bufferedIdCerts;
+
+ // Tmp Dns
+ const ndn::RegisteredPrefixId* m_dnsListenerId;
+
+ RecLock m_collectCountMutex;
+ int m_collectCount;
+
+ RecLock m_idCertCountMutex;
+ int m_idCertCount;
};
-void
-ContactManager::sendInterest(const ndn::Interest& interest,
- const ndn::OnDataValidated& onValidated,
- const ndn::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));
-}
+} // namespace chronos
-void
-ContactManager::onTargetData(const ndn::Interest& interest,
- const ndn::Data& data,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed)
-{ m_validator->validate(data, onValidated, onValidationFailed); }
-
-void
-ContactManager::onTargetTimeout(const ndn::Interest& interest,
- int retry,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed,
- const TimeoutNotify& timeoutNotify)
-{
- if(retry > 0)
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
- else
- timeoutNotify();
-}
-
-
-void
-ContactManager::onDnsSelfEndorseCertValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity)
-{ emit contactFetchFailed (identity); }
-
-void
-ContactManager::onDnsSelfEndorseCertTimeoutNotify(const ndn::Name& identity)
-{ emit contactFetchFailed(identity); }
-
-void
-ContactManager::onDnsCollectEndorseValidated(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity)
-{ emit collectEndorseFetched (*data); }
-
-void
-ContactManager::onDnsCollectEndorseValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity)
-{ emit collectEndorseFetchFailed (identity); }
-
-void
-ContactManager::onDnsCollectEndorseTimeoutNotify(const ndn::Name& identity)
-{ emit collectEndorseFetchFailed (identity); }
-
-void
-ContactManager::onKeyValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity)
-{ emit contactKeyFetchFailed (identity); }
-
-void
-ContactManager::onKeyTimeoutNotify(const ndn::Name& identity)
-{ emit contactKeyFetchFailed(identity); }
-
-void
-ContactManager::onIdCertValidated(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity)
-{
- ndn::IdentityCertificate identityCertificate(*data);
- emit contactCertificateFetched(identityCertificate);
-}
-
-void
-ContactManager::onIdCertValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
- const ndn::Name& identity)
-{ emit contactCertificateFetchFailed (identity); }
-
-void
-ContactManager::onIdCertTimeoutNotify(const ndn::Name& identity)
-{ emit contactCertificateFetchFailed (identity); }
-
-ndn::shared_ptr<ContactItem>
-ContactManager::getContact(const ndn::Name& contactNamespace)
-{ return m_contactStorage->getContact(contactNamespace); }
-
-void
-ContactManager::getContactItemList(std::vector<ndn::shared_ptr<ContactItem> >& contacts)
-{ return m_contactStorage->getAllContacts(contacts); }
-
-}//chronos
-
-#endif
+#endif //CHRONOS_CONTACT_MANAGER_H
diff --git a/src/contact-panel.cpp b/src/contact-panel.cpp
new file mode 100644
index 0000000..2c2c8e9
--- /dev/null
+++ b/src/contact-panel.cpp
@@ -0,0 +1,349 @@
+/* -*- 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 "contact-panel.h"
+#include "ui_contact-panel.h"
+
+#include <QMenu>
+#include <QItemSelectionModel>
+#include <QModelIndex>
+#include <QtSql/QSqlRecord>
+#include <QtSql/QSqlField>
+#include <QtSql/QSqlError>
+
+#ifndef Q_MOC_RUN
+#include "logging.h"
+#endif
+
+INIT_LOGGER("ContactPanel");
+
+ContactPanel::ContactPanel(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::ContactPanel)
+ , m_setAliasDialog(new SetAliasDialog)
+ , m_contactListModel(new QStringListModel)
+ , m_trustScopeModel(0)
+ , m_endorseDataModel(0)
+ , m_endorseComboBoxDelegate(new EndorseComboBoxDelegate)
+{
+ ui->setupUi(this);
+ ui->ContactList->setModel(m_contactListModel);
+ m_menuAlias = new QAction("Set Alias", this);
+ m_menuDelete = new QAction("Delete", this);
+
+ connect(ui->ContactList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+ this, SLOT(onSelectionChanged(const QItemSelection &, const QItemSelection &)));
+ connect(ui->ContactList, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(onContextMenuRequested(const QPoint&)));
+ connect(ui->isIntroducer, SIGNAL(stateChanged(int)),
+ this, SLOT(onIsIntroducerChanged(int)));
+ connect(ui->addScope, SIGNAL(clicked()),
+ this, SLOT(onAddScopeClicked()));
+ connect(ui->deleteScope, SIGNAL(clicked()),
+ this, SLOT(onDeleteScopeClicked()));
+ connect(ui->saveButton, SIGNAL(clicked()),
+ this, SLOT(onSaveScopeClicked()));
+ connect(ui->endorseButton, SIGNAL(clicked()),
+ this, SLOT(onEndorseButtonClicked()));
+ connect(m_setAliasDialog, SIGNAL(aliasChanged(const QString&, const QString&)),
+ this, SLOT(onAliasChanged(const QString&, const QString&)));
+}
+
+ContactPanel::~ContactPanel()
+{
+ if(m_contactListModel) delete m_contactListModel;
+ if(m_trustScopeModel) delete m_trustScopeModel;
+ if(m_endorseDataModel) delete m_endorseDataModel;
+
+ delete m_setAliasDialog;
+ delete m_endorseComboBoxDelegate;
+
+ delete m_menuAlias;
+ delete m_menuDelete;
+
+ delete ui;
+}
+
+//private methods
+void
+ContactPanel::resetPanel()
+{
+ // Clean up General tag.
+ ui->NameData->clear();
+ ui->NameSpaceData->clear();
+ ui->InstitutionData->clear();
+
+ // Clean up TrustScope tag.
+ ui->isIntroducer->setChecked(false);
+ ui->addScope->setEnabled(false);
+ ui->deleteScope->setEnabled(false);
+
+ m_trustScopeModel = new QSqlTableModel;
+ 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);
+
+ // Clean up Endorse tag.
+ m_endorseDataModel = new QSqlTableModel;
+ 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();
+ ui->endorseList->setEnabled(false);
+
+ // Clean up contact list.
+ m_contactAliasList.clear();
+ m_contactIdList.clear();
+ m_currentSelectedContact.clear();
+ m_contactListModel->setStringList(m_contactAliasList);
+}
+
+// public slots
+void
+ContactPanel::onCloseDBModule()
+{
+ _LOG_DEBUG("close db module");
+ if(m_trustScopeModel)
+ {
+ delete m_trustScopeModel;
+ _LOG_DEBUG("trustScopeModel closed");
+ }
+ if(m_endorseDataModel)
+ {
+ delete m_endorseDataModel;
+ _LOG_DEBUG("endorseDataModel closed");
+ }
+}
+
+void
+ContactPanel::onIdentityUpdated(const QString& identity)
+{
+ resetPanel();
+
+ emit waitForContactList(); // Re-load contact list;
+}
+
+void
+ContactPanel::onContactAliasListReady(const QStringList& aliasList)
+{
+ m_contactAliasList = aliasList;
+ m_contactListModel->setStringList(m_contactAliasList);
+}
+
+void
+ContactPanel::onContactIdListReady(const QStringList& idList)
+{
+ m_currentSelectedContact.clear();
+ m_contactIdList = idList;
+}
+
+void
+ContactPanel::onContactInfoReady(const QString& identity,
+ const QString& name,
+ const QString& institute,
+ bool isIntro)
+{
+ ui->NameData->setText(name);
+ ui->NameSpaceData->setText(identity);
+ ui->InstitutionData->setText(institute);
+
+ QString filter = QString("contact_namespace = '%1'").arg(identity);
+ m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
+ m_trustScopeModel->setTable("TrustScope");
+ m_trustScopeModel->setFilter(filter);
+ m_trustScopeModel->select();
+ ui->trustScopeList->setModel(m_trustScopeModel);
+ ui->trustScopeList->setColumnHidden(0, true);
+ ui->trustScopeList->setColumnHidden(1, true);
+ ui->trustScopeList->show();
+
+ if(isIntro)
+ {
+ ui->isIntroducer->setChecked(true);
+ ui->addScope->setEnabled(true);
+ ui->deleteScope->setEnabled(true);
+ ui->trustScopeList->setEnabled(true);
+ }
+ else
+ {
+ ui->isIntroducer->setChecked(false);
+ ui->addScope->setEnabled(false);
+ ui->deleteScope->setEnabled(false);
+ ui->trustScopeList->setEnabled(false);
+ }
+
+ QString filter2 = QString("profile_identity = '%1'").arg(identity);
+ m_endorseDataModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
+ m_endorseDataModel->setTable("ContactProfile");
+ m_endorseDataModel->setFilter(filter2);
+ m_endorseDataModel->select();
+ 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();
+ ui->endorseList->setEnabled(true);
+}
+
+// private slots
+void
+ContactPanel::onSelectionChanged(const QItemSelection &selected,
+ const QItemSelection &deselected)
+{
+ QModelIndexList items = selected.indexes();
+ QString alias = m_contactListModel->data(items.first(), Qt::DisplayRole).toString();
+
+ bool contactFound = false;
+ for(int i = 0; i < m_contactAliasList.size(); i++)
+ {
+ if(alias == m_contactAliasList[i])
+ {
+ contactFound = true;
+ m_currentSelectedContact = m_contactIdList[i];
+ break;
+ }
+ }
+
+ if(!contactFound)
+ {
+ emit warning("This should not happen: ContactPanel::updateSelection #1");
+ return;
+ }
+
+ emit waitForContactInfo(m_currentSelectedContact);
+}
+
+void
+ContactPanel::onContextMenuRequested(const QPoint& pos)
+{
+ QMenu menu(ui->ContactList);
+
+ menu.addAction(m_menuAlias);
+ connect(m_menuAlias, SIGNAL(triggered()),
+ this, SLOT(onSetAliasDialogRequested()));
+
+ menu.addAction(m_menuDelete);
+ connect(m_menuDelete, SIGNAL(triggered()),
+ this, SLOT(onContactDeletionRequested()));
+
+ menu.exec(ui->ContactList->mapToGlobal(pos));
+}
+
+void
+ContactPanel::onSetAliasDialogRequested()
+{
+ for(int i = 0; i < m_contactIdList.size(); i++)
+ if(m_contactIdList[i] == m_currentSelectedContact)
+ {
+ m_setAliasDialog->setTargetIdentity(m_currentSelectedContact, m_contactAliasList[i]);
+ m_setAliasDialog->show();
+ return;
+ }
+}
+
+void
+ContactPanel::onContactDeletionRequested()
+{
+ QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
+ QModelIndexList selectedList = selectionModel->selectedIndexes();
+ QModelIndexList::iterator it = selectedList.begin();
+ for(; it != selectedList.end(); it++)
+ {
+ QString alias = m_contactListModel->data(*it, Qt::DisplayRole).toString();
+ for(int i = 0; i < m_contactAliasList.size(); i++)
+ if(m_contactAliasList[i] == alias)
+ {
+ emit removeContact(m_contactIdList[i]);
+ return;
+ }
+ }
+}
+
+void
+ContactPanel::onIsIntroducerChanged(int state)
+{
+ if(state == Qt::Checked)
+ {
+ ui->addScope->setEnabled(true);
+ ui->deleteScope->setEnabled(true);
+ ui->trustScopeList->setEnabled(true);
+ emit updateIsIntroducer(m_currentSelectedContact, true);
+ }
+ else
+ {
+ ui->addScope->setEnabled(false);
+ ui->deleteScope->setEnabled(false);
+ ui->trustScopeList->setEnabled(false);
+ emit updateIsIntroducer(m_currentSelectedContact, false);
+ }
+}
+
+void
+ContactPanel::onAddScopeClicked()
+{
+ int rowCount = m_trustScopeModel->rowCount();
+ QSqlRecord record;
+ QSqlField identityField("contact_namespace", QVariant::String);
+ record.append(identityField);
+ record.setValue("contact_namespace", m_currentSelectedContact);
+ m_trustScopeModel->insertRow(rowCount);
+ m_trustScopeModel->setRecord(rowCount, record);
+}
+
+void
+ContactPanel::onDeleteScopeClicked()
+{
+ 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::onSaveScopeClicked()
+{
+ m_trustScopeModel->submitAll();
+}
+
+void
+ContactPanel::onEndorseButtonClicked()
+{
+ m_endorseDataModel->submitAll();
+ emit updateEndorseCertificate(m_currentSelectedContact);
+}
+
+void
+ContactPanel::onAliasChanged(const QString& identity, const QString& alias)
+{
+ emit updateAlias(identity, alias);
+}
+
+#if WAF
+#include "contact-panel.moc"
+#include "contact-panel.cpp.moc"
+#endif
diff --git a/src/contact-panel.h b/src/contact-panel.h
new file mode 100644
index 0000000..74010fc
--- /dev/null
+++ b/src/contact-panel.h
@@ -0,0 +1,141 @@
+/* -*- 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>
+ */
+
+#ifndef CONTACT_PANEL_H
+#define CONTACT_PANEL_H
+
+#include <QDialog>
+#include <QStringListModel>
+#include <QSqlTableModel>
+
+#include "set-alias-dialog.h"
+#include "endorse-combobox-delegate.h"
+
+#ifndef Q_MOC_RUN
+#endif
+
+
+namespace Ui {
+class ContactPanel;
+}
+
+class ContactPanel : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit
+ ContactPanel(QWidget *parent = 0);
+
+ virtual
+ ~ContactPanel();
+
+private:
+ void
+ resetPanel();
+
+signals:
+ void
+ waitForContactList();
+
+ void
+ waitForContactInfo(const QString& identity);
+
+ void
+ removeContact(const QString& identity);
+
+ void
+ updateAlias(const QString& identity, const QString& alias);
+
+ void
+ updateIsIntroducer(const QString& identity, bool isIntro);
+
+ void
+ updateEndorseCertificate(const QString& identity);
+
+ void
+ warning(const QString& msg);
+
+public slots:
+ void
+ onCloseDBModule();
+
+ void
+ onIdentityUpdated(const QString& identity);
+
+ void
+ onContactAliasListReady(const QStringList& aliasList);
+
+ void
+ onContactIdListReady(const QStringList& idList);
+
+ void
+ onContactInfoReady(const QString& identity,
+ const QString& name,
+ const QString& institute,
+ bool isIntro);
+
+private slots:
+ void
+ onSelectionChanged(const QItemSelection &selected,
+ const QItemSelection &deselected);
+
+ void
+ onContextMenuRequested(const QPoint& pos);
+
+ void
+ onSetAliasDialogRequested();
+
+ void
+ onContactDeletionRequested();
+
+ void
+ onIsIntroducerChanged(int state);
+
+ void
+ onAddScopeClicked();
+
+ void
+ onDeleteScopeClicked();
+
+ void
+ onSaveScopeClicked();
+
+ void
+ onEndorseButtonClicked();
+
+ void
+ onAliasChanged(const QString& identity, const QString& alias);
+
+private:
+ Ui::ContactPanel* ui;
+
+ // Dialogs.
+ SetAliasDialog* m_setAliasDialog;
+
+ // Models.
+ QStringListModel* m_contactListModel;
+ QSqlTableModel* m_trustScopeModel;
+ QSqlTableModel* m_endorseDataModel;
+
+ // Delegates.
+ EndorseComboBoxDelegate* m_endorseComboBoxDelegate;
+
+ // Actions.
+ QAction* m_menuAlias;
+ QAction* m_menuDelete;
+
+ // Internal data structure.
+ QStringList m_contactAliasList;
+ QStringList m_contactIdList;
+ QString m_currentSelectedContact;
+};
+
+#endif // CONTACT_PANEL_H
diff --git a/src/contact-panel.ui b/src/contact-panel.ui
new file mode 100644
index 0000000..68c0f6d
--- /dev/null
+++ b/src/contact-panel.ui
@@ -0,0 +1,315 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ContactPanel</class>
+ <widget class="QDialog" name="ContactPanel">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>ChronoChat Contacts</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <layout class="QHBoxLayout" name="ContactPanelLayout" stretch="3,7">
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <widget class="QListView" name="ContactList">
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTabWidget" name="ContactInfo">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="General">
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_6" stretch="2,2,1">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7" stretch="2,3,2">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QGraphicsView" name="Avatar"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="35,100">
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="NameSpaceLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Name space</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="NameSpaceData">
+ <property name="font">
+ <font>
+ <family>Lucida Grande</family>
+ </font>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="35,100">
+ <item>
+ <widget class="QLabel" name="NameLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="NameData">
+ <property name="font">
+ <font>
+ <family>Lucida Grande</family>
+ </font>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="35,100">
+ <item>
+ <widget class="QLabel" name="InstitutionLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Institution </string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="InstitutionData">
+ <property name="font">
+ <font>
+ <family>Lucida Grande</family>
+ </font>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="TrustScope">
+ <attribute name="title">
+ <string>Trust Scope</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="isIntroducer">
+ <property name="text">
+ <string>Set as introducer</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableView" name="trustScopeList">
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QPushButton" name="addScope">
+ <property name="text">
+ <string>Add Scope</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deleteScope">
+ <property name="text">
+ <string>Delete Scope</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="saveButton">
+ <property name="text">
+ <string>Save</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="Endorse">
+ <attribute name="title">
+ <string>Endorse</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QTableView" name="endorseList">
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="3,1">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="endorseButton">
+ <property name="text">
+ <string>Endorse</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/contact-storage.cpp b/src/contact-storage.cpp
index f107f0c..e3c513f 100644
--- a/src/contact-storage.cpp
+++ b/src/contact-storage.cpp
@@ -11,28 +11,32 @@
#include "contact-storage.h"
#include <boost/filesystem.hpp>
+#include <cryptopp/sha.h>
+#include <cryptopp/filters.h>
+#include <cryptopp/hex.h>
+#include <cryptopp/files.h>
#include "logging.h"
using namespace std;
using namespace ndn;
namespace fs = boost::filesystem;
-INIT_LOGGER ("ContactStorage");
+
+INIT_LOGGER ("chronos.ContactStorage");
namespace chronos{
const string INIT_SP_TABLE = "\
CREATE TABLE IF NOT EXISTS \n \
SelfProfile( \n \
- profile_identity BLOB NOT NULL, \n \
profile_type BLOB NOT NULL, \n \
profile_value BLOB NOT NULL, \n \
\
- PRIMARY KEY (profile_identity, profile_type) \n \
+ PRIMARY KEY (profile_type) \n \
); \n \
\
-CREATE INDEX sp_index ON SelfProfile(profile_identity,profile_type); \n \
-";
+CREATE INDEX sp_index ON SelfProfile(profile_type); \n \
+"; // user's own profile;
const string INIT_SE_TABLE = "\
CREATE TABLE IF NOT EXISTS \n \
@@ -43,21 +47,24 @@
PRIMARY KEY (identity) \n \
); \n \
CREATE INDEX se_index ON SelfEndorse(identity); \n \
-";
+"; // user's self endorse cert;
const string INIT_CONTACT_TABLE = "\
CREATE TABLE IF NOT EXISTS \n \
Contact( \n \
contact_namespace BLOB NOT NULL, \n \
contact_alias BLOB NOT NULL, \n \
- self_certificate BLOB NOT NULL, \n \
+ contact_keyName BLOB NOT NULL, \n \
+ contact_key BLOB NOT NULL, \n \
+ notBefore INTEGER DEFAULT 0, \n \
+ notAfter INTEGER DEFAULT 0, \n \
is_introducer INTEGER DEFAULT 0, \n \
\
PRIMARY KEY (contact_namespace) \n \
); \n \
\
CREATE INDEX contact_index ON Contact(contact_namespace); \n \
-";
+"; // contact's basic info
const string INIT_TS_TABLE = "\
CREATE TABLE IF NOT EXISTS \n \
@@ -68,7 +75,7 @@
); \n \
\
CREATE INDEX ts_index ON TrustScope(contact_namespace); \n \
-";
+"; // contact's trust scope;
const string INIT_CP_TABLE = "\
CREATE TABLE IF NOT EXISTS \n \
@@ -82,7 +89,7 @@
); \n \
\
CREATE INDEX cp_index ON ContactProfile(profile_identity); \n \
-";
+"; // contact's profile
const string INIT_PE_TABLE = "\
CREATE TABLE IF NOT EXISTS \n \
@@ -94,28 +101,40 @@
); \n \
\
CREATE INDEX pe_index ON ProfileEndorse(identity); \n \
-";
+"; // user's endorsement on contacts
const string INIT_CE_TABLE = "\
CREATE TABLE IF NOT EXISTS \n \
CollectEndorse( \n \
- endorsee BLOB NOT NULL, \n \
endorser BLOB NOT NULL, \n \
endorse_name BLOB NOT NULL, \n \
endorse_data BLOB NOT NULL, \n \
\
- PRIMARY KEY (endorsee, endorser) \n \
+ PRIMARY KEY (endorser) \n \
); \n \
- \
-CREATE INDEX ce_index ON CollectEndorse(endorsee); \n \
-";
+"; // contact's endorsements on the user
-ContactStorage::ContactStorage()
+const string INIT_DD_TABLE = "\
+CREATE TABLE IF NOT EXISTS \n \
+ DnsData( \n \
+ dns_name BLOB NOT NULL, \n \
+ dns_type BLOB NOT NULL, \n \
+ data_name BLOB NOT NULL, \n \
+ dns_value BLOB NOT NULL, \n \
+ \
+ PRIMARY KEY (dns_name, dns_type) \n \
+ ); \
+CREATE INDEX dd_index ON DnsData(dns_name, dns_type); \n \
+CREATE INDEX dd_index2 ON DnsData(data_name); \n \
+"; // dns data;
+
+ContactStorage::ContactStorage(const Name& identity)
+ : m_identity(identity)
{
fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
fs::create_directories (chronosDir);
- int res = sqlite3_open((chronosDir / "chronos.db").c_str (), &m_db);
+ int res = sqlite3_open((chronosDir / getDBName()).c_str (), &m_db);
if (res != SQLITE_OK)
throw Error("Chronos DB cannot be open/created");
@@ -126,9 +145,28 @@
initializeTable("ContactProfile", INIT_CP_TABLE);
initializeTable("ProfileEndorse", INIT_PE_TABLE);
initializeTable("CollectEndorse", INIT_CE_TABLE);
+ initializeTable("DnsData", INIT_DD_TABLE);
}
+string
+ContactStorage::getDBName()
+{
+ string dbName("chronos-");
+
+ stringstream ss;
+ {
+ using namespace CryptoPP;
+
+ SHA256 hash;
+ StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
+ new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
+ }
+ dbName.append(ss.str()).append(".db");
+
+ return dbName;
+}
+
void
ContactStorage::initializeTable(const string& tableName, const string& sqlCreateStmt)
{
@@ -152,16 +190,14 @@
}
shared_ptr<Profile>
-ContactStorage::getSelfProfile(const Name& identity) const
+ContactStorage::getSelfProfile()
{
- shared_ptr<Profile> profile;
+ shared_ptr<Profile> profile = make_shared<Profile>(m_identity);
sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_identity=?", -1, &stmt, 0);
- sqlite3_bind_text (stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
+ sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM SelfProfile", -1, &stmt, 0);
while( sqlite3_step (stmt) == SQLITE_ROW)
{
- profile = make_shared<Profile>(identity);
string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
string profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
(*profile)[profileType] = profileValue;
@@ -172,61 +208,20 @@
return profile;
}
-// Block
-// ContactStorage::getSelfEndorseCertificate(const Name& identity)
-// {
-// sqlite3_stmt *stmt;
-// sqlite3_prepare_v2 (m_db, "SELECT endorse_data FROM SelfEndorse where identity=?", -1, &stmt, 0);
-// sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
-
-// if(sqlite3_step (stmt) == SQLITE_ROW)
-// {
-// Block result(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
-// sqlite3_finalize (stmt);
-// return result;
-// }
-
-// sqlite3_finalize (stmt);
-
-// throw Error("ContactStorage: No self-endorse certificate found!");
-// }
-
void
-ContactStorage::addSelfEndorseCertificate(const EndorseCertificate& newEndorseCertificate, const Name& identity)
+ContactStorage::addSelfEndorseCertificate(const EndorseCertificate& newEndorseCertificate)
{
const Block& newEndorseCertificateBlock = newEndorseCertificate.wireEncode();
sqlite3_stmt *stmt;
sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO SelfEndorse (identity, endorse_data) values (?, ?)", -1, &stmt, 0);
- sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 1, m_identity.toUri().c_str(), m_identity.toUri().size(), SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, reinterpret_cast<const char*>(newEndorseCertificateBlock.wire()), newEndorseCertificateBlock.size(), SQLITE_TRANSIENT);
- sqlite3_step(stmt);
+ int res = sqlite3_step(stmt);
sqlite3_finalize (stmt);
}
-// Block
-// ContactStorage::getEndorseCertificate(const Name& identity)
-// {
-// sqlite3_stmt *stmt;
-// sqlite3_prepare_v2 (m_db, "SELECT endorse_data FROM ProfileEndorse where identity=?", -1, &stmt, 0);
-// sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
-
-
-// if(sqlite3_step (stmt) == SQLITE_ROW)
-// {
-// Block result(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
-// sqlite3_finalize (stmt);
-// return result;
-// }
-
-// sqlite3_finalize (stmt);
-
-// throw Error("ContactStorage: No endorse certificate found!");
-
-// return Block();
-// }
-
void
ContactStorage::addEndorseCertificate(const EndorseCertificate& endorseCertificate, const Name& identity)
{
@@ -235,7 +230,7 @@
sqlite3_stmt *stmt;
sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO ProfileEndorse (identity, endorse_data) values (?, ?)", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 2, reinterpret_cast<const char*>(newEndorseCertificateBlock.value()), newEndorseCertificateBlock.size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, reinterpret_cast<const char*>(newEndorseCertificateBlock.wire()), newEndorseCertificateBlock.size(), SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize (stmt);
@@ -245,33 +240,39 @@
ContactStorage::updateCollectEndorse(const EndorseCertificate& endorseCertificate)
{
Name endorserName = endorseCertificate.getSigner();
- Name keyName = endorseCertificate.getPublicKeyName();
- Name endorseeName = keyName.getPrefix(keyName.size()-1);
- Name getCertName = endorseCertificate.getName();
+ Name certName = endorseCertificate.getName();
sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO CollectEndorse (endorser, endorsee, endorse_name, endorse_data) VALUES (?, ?, ?, ?)", -1, &stmt, 0);
+ sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO CollectEndorse (endorser, endorse_name, endorse_data) VALUES (?, ?, ?, ?)", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, endorserName.toUri().c_str(), endorserName.toUri().size(), SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 2, endorseeName.toUri().c_str(), endorseeName.toUri().size(), SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 3, getCertName.toUri().c_str(), getCertName.toUri().size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, certName.toUri().c_str(), certName.toUri().size(), SQLITE_TRANSIENT);
const Block &block = endorseCertificate.wireEncode();
- sqlite3_bind_text(stmt, 4, reinterpret_cast<const char*>(block.wire()), block.size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 3, reinterpret_cast<const char*>(block.wire()), block.size(), SQLITE_TRANSIENT);
int res = sqlite3_step (stmt);
sqlite3_finalize (stmt);
return;
}
void
-ContactStorage::getCollectEndorseList(const Name& name, vector<Buffer>& endorseList)
+ContactStorage::getCollectEndorse(EndorseCollection& endorseCollection)
{
sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT endorse_data FROM CollectEndorse WHERE endorsee=?", -1, &stmt, 0);
- sqlite3_bind_text(stmt, 1, name.toUri().c_str(), name.toUri().size(), SQLITE_TRANSIENT);
+ sqlite3_prepare_v2 (m_db, "SELECT endorse_name, endorse_data FROM CollectEndorse", -1, &stmt, 0);
while(sqlite3_step (stmt) == SQLITE_ROW)
{
- Buffer blob(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
- endorseList.push_back(blob);
+ string certName(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes(stmt, 1));
+ stringstream ss;
+ {
+ using namespace CryptoPP;
+ SHA256 hash;
+
+ StringSource(sqlite3_column_text(stmt, 1), sqlite3_column_bytes (stmt, 0), true,
+ new HashFilter(hash, new FileSink(ss)));
+ }
+ EndorseCollection::Endorsement* endorsement = endorseCollection.add_endorsement();
+ endorsement->set_certname(certName);
+ endorsement->set_hash(ss.str());
}
sqlite3_finalize (stmt);
@@ -294,9 +295,9 @@
void
-ContactStorage::removeContact(const Name& contactNameSpace)
+ContactStorage::removeContact(const Name& identityName)
{
- string identity = contactNameSpace.toUri();
+ string identity = identityName.toUri();
sqlite3_stmt *stmt;
sqlite3_prepare_v2 (m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
@@ -316,32 +317,38 @@
}
void
-ContactStorage::addContact(const ContactItem& contact)
+ContactStorage::addContact(const Contact& contact)
{
if(doesContactExist(contact.getNameSpace()))
throw Error("Normal Contact has already existed");
+ string identity = contact.getNameSpace().toUri();
bool isIntroducer = contact.isIntroducer();
sqlite3_stmt *stmt;
sqlite3_prepare_v2 (m_db,
- "INSERT INTO Contact (contact_namespace, contact_alias, self_certificate, is_introducer) values (?, ?, ?, ?)",
- -1,
- &stmt,
+ "INSERT INTO Contact (contact_namespace, contact_alias, contact_keyName, contact_key, notBefore, notAfter, is_introducer) values (?, ?, ?, ?, ?, ?, ?)",
+ -1,
+ &stmt,
0);
- sqlite3_bind_text(stmt, 1, contact.getNameSpace().toUri().c_str(), contact.getNameSpace().toUri().size (), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, contact.getAlias().c_str(), contact.getAlias().size(), SQLITE_TRANSIENT);
- const Block& selfCertificateBlock = contact.getSelfEndorseCertificate().wireEncode();
- sqlite3_bind_text(stmt, 3, reinterpret_cast<const char*>(selfCertificateBlock.wire()), selfCertificateBlock.size(), SQLITE_TRANSIENT);
- sqlite3_bind_int(stmt, 4, (isIntroducer ? 1 : 0));
+ sqlite3_bind_text(stmt, 3, contact.getPublicKeyName().toUri().c_str(), contact.getPublicKeyName().toUri().size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 4, reinterpret_cast<const char*>(contact.getPublicKey().get().buf()), contact.getPublicKey().get().size(), SQLITE_TRANSIENT);
+ sqlite3_bind_int64(stmt, 5, contact.getNotBefore());
+ sqlite3_bind_int64(stmt, 6, contact.getNotAfter());
+ sqlite3_bind_int(stmt, 7, (isIntroducer ? 1 : 0));
int res = sqlite3_step (stmt);
+
+ // _LOG_DEBUG("addContact: " << res);
+
sqlite3_finalize (stmt);
- const Profile& profile = contact.getSelfEndorseCertificate().getProfile();
+ const Profile& profile = contact.getProfile();
Profile::const_iterator it = profile.begin();
- string identity = contact.getNameSpace().toUri();
+
for(; it != profile.end(); it++)
{
sqlite3_prepare_v2 (m_db,
@@ -358,17 +365,17 @@
if(isIntroducer)
{
- ContactItem::const_iterator it = contact.trustScopeBegin();
- string nameSpace = contact.getNameSpace().toUri();
-
- while(it != contact.trustScopeEnd())
+ Contact::const_iterator it = contact.trustScopeBegin();
+ Contact::const_iterator end = contact.trustScopeEnd();
+
+ while(it != end)
{
sqlite3_prepare_v2 (m_db,
"INSERT INTO TrustScope (contact_namespace, trust_scope) values (?, ?)",
-1,
&stmt,
0);
- sqlite3_bind_text(stmt, 1, nameSpace.c_str(), nameSpace.size (), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, it->first.toUri().c_str(), it->first.toUri().size(), SQLITE_TRANSIENT);
res = sqlite3_step (stmt);
sqlite3_finalize (stmt);
@@ -378,43 +385,55 @@
}
-shared_ptr<ContactItem>
-ContactStorage::getContact(const Name& name)
+shared_ptr<Contact>
+ContactStorage::getContact(const Name& identity) const
{
+ shared_ptr<Contact> contact;
+ Profile profile;
+
sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT contact_alias, self_certificate, is_introducer FROM Contact where contact_namespace=?", -1, &stmt, 0);
- sqlite3_bind_text (stmt, 1, name.toUri().c_str(), name.toUri().size(), SQLITE_TRANSIENT);
-
- if( sqlite3_step (stmt) == SQLITE_ROW)
+ sqlite3_prepare_v2 (m_db, "SELECT contact_alias, contact_keyName, contact_key, notBefore, notAfter, is_introducer FROM Contact where contact_namespace=?", -1, &stmt, 0);
+ sqlite3_bind_text (stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
+
+ if(sqlite3_step (stmt) == SQLITE_ROW)
{
- string alias(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
+ string alias(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
+ string keyName(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
+ PublicKey key(sqlite3_column_text(stmt, 2), sqlite3_column_bytes (stmt, 2));
+ int64_t notBefore = sqlite3_column_int64 (stmt, 3);
+ int64_t notAfter = sqlite3_column_int64 (stmt, 4);
+ int isIntroducer = sqlite3_column_int (stmt, 5);
- Data certData;
- certData.wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
- EndorseCertificate endorseCertificate(certData);
+ contact = shared_ptr<Contact>(new Contact(identity, alias, Name(keyName), notBefore, notAfter, key, isIntroducer));
+ }
+ sqlite3_finalize (stmt);
- int isIntroducer = sqlite3_column_int (stmt, 2);
+ sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM ContactProfile where profile_identity=?", -1, &stmt, 0);
+ sqlite3_bind_text (stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
+
+ while(sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ string type(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
+ string value(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
+ profile[type] = value;
+ }
+ sqlite3_finalize (stmt);
+ contact->setProfile(profile);
- sqlite3_finalize (stmt);
-
- shared_ptr<ContactItem> contact = make_shared<ContactItem>(endorseCertificate, isIntroducer, alias);
+ if(contact->isIntroducer())
+ {
+ sqlite3_prepare_v2 (m_db, "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
+ sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
- if(contact->isIntroducer())
+ while(sqlite3_step (stmt) == SQLITE_ROW)
{
- sqlite3_prepare_v2 (m_db, "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
- sqlite3_bind_text(stmt, 1, name.toUri().c_str(), name.toUri().size(), SQLITE_TRANSIENT);
-
- while( sqlite3_step (stmt) == SQLITE_ROW)
- {
- Name scope(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
- contact->addTrustScope(scope);
- }
- sqlite3_finalize (stmt);
+ Name scope(string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+ contact->addTrustScope(scope);
}
+ sqlite3_finalize (stmt);
+ }
- return contact;
- }
- return shared_ptr<ContactItem>();
+ return contact;
}
@@ -464,41 +483,85 @@
}
void
-ContactStorage::getAllContacts(vector<shared_ptr<ContactItem> >& contacts) const
+ContactStorage::getAllContacts(vector<shared_ptr<Contact> >& contacts) const
{
+ vector<Name> contactNames;
+
sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT contact_alias, self_certificate, is_introducer FROM Contact", -1, &stmt, 0);
+ sqlite3_prepare_v2 (m_db, "SELECT contact_namespace FROM Contact", -1, &stmt, 0);
- while( sqlite3_step (stmt) == SQLITE_ROW)
+ while(sqlite3_step (stmt) == SQLITE_ROW)
{
- string alias(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
-
- Data certData;
- certData.wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
- EndorseCertificate endorseCertificate(certData);
-
- int isIntroducer = sqlite3_column_int (stmt, 2);
-
- contacts.push_back(make_shared<ContactItem>(endorseCertificate, isIntroducer, alias));
+ string identity(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes(stmt, 0));
+ contactNames.push_back(Name(identity));
}
- sqlite3_finalize (stmt);
+ sqlite3_finalize (stmt);
- vector<shared_ptr<ContactItem> >::iterator it = contacts.begin();
- for(; it != contacts.end(); it++)
+ vector<Name>::iterator it = contactNames.begin();
+ vector<Name>::iterator end = contactNames.end();
+ for(; it != end; it++)
{
- if((*it)->isIntroducer())
- {
- sqlite3_prepare_v2 (m_db, "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
- sqlite3_bind_text(stmt, 1, (*it)->getNameSpace().toUri().c_str(), (*it)->getNameSpace().toUri().size(), SQLITE_TRANSIENT);
-
- while( sqlite3_step (stmt) == SQLITE_ROW)
- {
- Name scope(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
- (*it)->addTrustScope(scope);
- }
- sqlite3_finalize (stmt);
- }
+ shared_ptr<Contact> contact = getContact(*it);
+ if(static_cast<bool>(contact))
+ contacts.push_back(contact);
}
}
+void
+ContactStorage::updateDnsData(const Block& data,
+ const string& name,
+ const string& type,
+ const string& dataName)
+{
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO DnsData (dns_name, dns_type, dns_value, data_name) VALUES (?, ?, ?, ?)", -1, &stmt, 0);
+ sqlite3_bind_text(stmt, 1, name.c_str(), name.size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, type.c_str(), type.size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 3, reinterpret_cast<const char*>(data.wire()), data.size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 4, dataName.c_str(), dataName.size(), SQLITE_TRANSIENT);
+ int res = sqlite3_step(stmt);
+
+ // _LOG_DEBUG("updateDnsData " << res);
+ sqlite3_finalize(stmt);
+}
+
+shared_ptr<Data>
+ContactStorage::getDnsData(const Name& dataName)
+{
+ shared_ptr<Data> data;
+
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2 (m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, 0);
+ sqlite3_bind_text(stmt, 1, dataName.toUri().c_str(), dataName.toUri().size(), SQLITE_TRANSIENT);
+
+ if(sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ data = make_shared<Data>();
+ data->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+ }
+ sqlite3_finalize(stmt);
+
+ return data;
+}
+
+shared_ptr<Data>
+ContactStorage::getDnsData(const string& name, const string& type)
+{
+ shared_ptr<Data> data;
+
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2 (m_db, "SELECT dns_value FROM DnsData where dns_name=? and dns_type=?", -1, &stmt, 0);
+ sqlite3_bind_text(stmt, 1, name.c_str(), name.size(), SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, type.c_str(), type.size(), SQLITE_TRANSIENT);
+
+ if(sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ data = make_shared<Data>();
+ data->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+ }
+ sqlite3_finalize(stmt);
+
+ return data;
+}
+
}//chronos
diff --git a/src/contact-storage.h b/src/contact-storage.h
index da6c812..5662ebb 100644
--- a/src/contact-storage.h
+++ b/src/contact-storage.h
@@ -11,7 +11,8 @@
#ifndef CHRONOS_CONTACT_STORAGE_H
#define CHRONOS_CONTACT_STORAGE_H
-#include "contact-item.h"
+#include "contact.h"
+#include "endorse-collection.pb.h"
#include <sqlite3.h>
@@ -23,22 +24,18 @@
public:
struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
- ContactStorage();
+ ContactStorage(const ndn::Name& identity);
~ContactStorage()
- { sqlite3_close(m_db); }
+ {
+ sqlite3_close(m_db);
+ }
ndn::shared_ptr<Profile>
- getSelfProfile(const ndn::Name& identity) const;
-
- // ndn::Block
- // getSelfEndorseCertificate(const ndn::Name& identity);
+ getSelfProfile();
void
- addSelfEndorseCertificate(const EndorseCertificate& endorseCertificate, const ndn::Name& identity);
-
- // ndn::Block
- // getEndorseCertificate(const ndn::Name& identity);
+ addSelfEndorseCertificate(const EndorseCertificate& endorseCertificate);
void
addEndorseCertificate(const EndorseCertificate& endorseCertificate, const ndn::Name& identity);
@@ -47,7 +44,7 @@
updateCollectEndorse(const EndorseCertificate& endorseCertificate);
void
- getCollectEndorseList(const ndn::Name& name, std::vector<ndn::Buffer>& endorseList);
+ getCollectEndorse(EndorseCollection& endorseCollection);
void
getEndorseList(const ndn::Name& identity, std::vector<std::string>& endorseList);
@@ -58,10 +55,10 @@
removeContact(const ndn::Name& identity);
void
- addContact(const ContactItem& contactItem);
+ addContact(const Contact& contact);
- ndn::shared_ptr<ContactItem>
- getContact(const ndn::Name& name);
+ ndn::shared_ptr<Contact>
+ getContact(const ndn::Name& identity) const;
void
updateIsIntroducer(const ndn::Name& identity, bool isIntroducer);
@@ -70,19 +67,48 @@
updateAlias(const ndn::Name& identity, std::string alias);
void
- getAllContacts(std::vector<ndn::shared_ptr<ContactItem> >& contacts) const;
+ getAllContacts(std::vector<ndn::shared_ptr<Contact> >& contacts) const;
-
+ void
+ updateDnsSelfProfileData(const ndn::Data& data)
+ {
+ updateDnsData(data.wireEncode(), "N/A", "PROFILE", data.getName().toUri());
+ }
+
+ void
+ updateDnsEndorseOthers(const ndn::Data& data, const std::string& endorsee)
+ {
+ updateDnsData(data.wireEncode(), endorsee, "ENDORSEE", data.getName().toUri());
+ }
+ void
+ updateDnsOthersEndorse(const ndn::Data& data)
+ {
+ updateDnsData(data.wireEncode(), "N/A", "ENDORSED", data.getName().toUri());
+ }
+
+ ndn::shared_ptr<ndn::Data>
+ getDnsData(const ndn::Name& name);
+
+ ndn::shared_ptr<ndn::Data>
+ getDnsData(const std::string& name, const std::string& type);
private:
+ std::string
+ getDBName();
+
void
initializeTable(const std::string& tableName, const std::string& sqlCreateStmt);
bool
doesContactExist(const ndn::Name& name);
+ void
+ updateDnsData(const ndn::Block& data, const std::string& name, const std::string& type, const std::string& dataName);
+
private:
+ ndn::Name m_identity;
+
sqlite3 *m_db;
};
diff --git a/src/contact.h b/src/contact.h
new file mode 100644
index 0000000..4960972
--- /dev/null
+++ b/src/contact.h
@@ -0,0 +1,238 @@
+/* -*- 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>
+ */
+
+#ifndef CHRONOS_CONTACT_H
+#define CHRONOS_CONTACT_H
+
+#include <ndn-cpp-dev/security/identity-certificate.hpp>
+#include <ndn-cpp-dev/util/regex.hpp>
+#include "endorse-certificate.h"
+#include <vector>
+
+namespace chronos{
+
+class Contact
+{
+public:
+ typedef std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> >::const_iterator const_iterator;
+ typedef std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> >::iterator iterator;
+
+ Contact(const ndn::IdentityCertificate& identityCertificate,
+ bool isIntroducer = false,
+ const std::string& alias = "")
+ : m_notBefore(identityCertificate.getNotBefore())
+ , m_notAfter(identityCertificate.getNotAfter())
+ , m_isIntroducer(isIntroducer)
+ , m_profile(identityCertificate)
+ {
+ m_name = m_profile.get("name");
+ m_alias = alias.empty() ? m_name : alias;
+ m_institution = m_profile.get("institution");
+
+ m_keyName = identityCertificate.getPublicKeyName();
+ m_namespace = m_keyName.getPrefix(-1);
+ m_publicKey = identityCertificate.getPublicKeyInfo();
+ }
+
+ Contact(const EndorseCertificate& endorseCertificate,
+ bool isIntroducer = false,
+ const std::string& alias = "")
+ : m_notBefore(endorseCertificate.getNotBefore())
+ , m_notAfter(endorseCertificate.getNotAfter())
+ , m_isIntroducer(isIntroducer)
+ {
+ m_profile = endorseCertificate.getProfile();
+
+ m_name = m_profile.get("name");
+ m_alias = alias.empty() ? m_name : alias;
+ m_institution = m_profile.get("institution");
+
+ m_keyName = endorseCertificate.getPublicKeyName();;
+ m_namespace = m_keyName.getPrefix(-1);
+ m_publicKey = endorseCertificate.getPublicKeyInfo();
+ }
+
+ Contact(const ndn::Name& identity,
+ const std::string& alias,
+ const ndn::Name& keyName,
+ ndn::MillisecondsSince1970 notBefore,
+ ndn::MillisecondsSince1970 notAfter,
+ const ndn::PublicKey& key,
+ bool isIntroducer)
+ : m_namespace(identity)
+ , m_alias(alias)
+ , m_keyName(keyName)
+ , m_publicKey(key)
+ , m_notBefore(notBefore)
+ , m_notAfter(notAfter)
+ , m_isIntroducer(isIntroducer)
+ {
+ }
+
+ Contact(const Contact& contact)
+ : m_namespace(contact.m_namespace)
+ , m_alias(contact.m_alias)
+ , m_name(contact.m_name)
+ , m_institution(contact.m_institution)
+ , m_keyName(contact.m_keyName)
+ , m_publicKey(contact.m_publicKey)
+ , m_notBefore(contact.m_notBefore)
+ , m_notAfter(contact.m_notAfter)
+ , m_isIntroducer(contact.m_isIntroducer)
+ , m_profile(contact.m_profile)
+ , m_trustScope(contact.m_trustScope)
+ {}
+
+ virtual
+ ~Contact()
+ {}
+
+ const ndn::Name&
+ getNameSpace() const
+ {
+ return m_namespace;
+ }
+
+ const std::string&
+ getAlias() const
+ {
+ return m_alias;
+ }
+
+ const std::string&
+ getName() const
+ {
+ return m_name;
+ }
+
+ const std::string&
+ getInstitution() const
+ {
+ return m_institution;
+ }
+
+ const ndn::Name&
+ getPublicKeyName() const
+ {
+ return m_keyName;
+ }
+
+ const ndn::PublicKey&
+ getPublicKey() const
+ {
+ return m_publicKey;
+ }
+
+ ndn::MillisecondsSince1970
+ getNotBefore() const
+ {
+ return m_notBefore;
+ }
+
+ ndn::MillisecondsSince1970
+ getNotAfter() const
+ {
+ return m_notAfter;
+ }
+
+ const Profile&
+ getProfile() const
+ {
+ return m_profile;
+ }
+
+ void
+ setProfile(const Profile& profile)
+ {
+ m_name = profile.get("name");
+ m_institution = profile.get("institution");
+ m_profile = profile;
+ }
+
+ bool
+ isIntroducer() const
+ {
+ return m_isIntroducer;
+ }
+
+ void
+ setIsIntroducer(bool isIntroducer)
+ {
+ m_isIntroducer = isIntroducer;
+ }
+
+ void
+ addTrustScope(const ndn::Name& nameSpace)
+ {
+ m_trustScope[nameSpace] = ndn::Regex::fromName(nameSpace);
+ }
+
+ void
+ deleteTrustScope(const ndn::Name& nameSpace)
+ {
+ m_trustScope.erase(nameSpace);
+ }
+
+ bool
+ canBeTrustedFor(const ndn::Name& name)
+ {
+ std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> >::iterator it = m_trustScope.begin();
+
+ for(; it != m_trustScope.end(); it++)
+ if(it->second->match(name))
+ return true;
+ return false;
+ }
+
+ const_iterator
+ trustScopeBegin() const
+ {
+ return m_trustScope.begin();
+ }
+
+ const_iterator
+ trustScopeEnd() const
+ {
+ return m_trustScope.end();
+ }
+
+ iterator
+ trustScopeBegin()
+ {
+ return m_trustScope.begin();
+ }
+
+ iterator
+ trustScopeEnd()
+ {
+ return m_trustScope.end();
+ }
+
+protected:
+ typedef std::map<ndn::Name, ndn::shared_ptr<ndn::Regex> > TrustScopes;
+
+ ndn::Name m_namespace;
+ std::string m_alias;
+ std::string m_name;
+ std::string m_institution;
+ ndn::Name m_keyName;
+ ndn::PublicKey m_publicKey;
+ ndn::MillisecondsSince1970 m_notBefore;
+ ndn::MillisecondsSince1970 m_notAfter;
+
+ bool m_isIntroducer;
+ Profile m_profile;
+
+ TrustScopes m_trustScope;
+};
+
+} // namespace chronos
+
+#endif // CHRONOS_CONTACT_H
diff --git a/src/contactpanel.cpp b/src/contactpanel.cpp
deleted file mode 100644
index 413f32b..0000000
--- a/src/contactpanel.cpp
+++ /dev/null
@@ -1,828 +0,0 @@
-/* -*- 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-dev/security/validator.hpp>
-#include <ndn-cpp-dev/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 chronos;
-using namespace std;
-
-INIT_LOGGER("ContactPanel");
-
-Q_DECLARE_METATYPE(ndn::IdentityCertificate)
-
-ContactPanel::ContactPanel(shared_ptr<Face> face,
- 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_keyChain(new KeyChain)
- , m_face(face)
- , m_ioService(face->ioService())
- , m_contactManager(new ContactManager(m_face))
-{
-
- qRegisterMetaType<ndn::IdentityCertificate>("IdentityCertificate");
-
- createAction();
-
-#ifdef WITH_SECURITY
- m_panelValidator = make_shared<chronos::ValidatorPanel>();
- m_invitationValidator = make_shared<chronos::ValidatorInvitation>();
-#else
- m_panelValidator = make_shared<ndn::ValidatorNull>();
- m_invitationValidator = make_shared<ndn::ValidatorNull>();
-#endif
-
- 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?");
-
- m_keyChain->createIdentity(m_defaultIdentity);
-
- 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(ui->chatButton, SIGNAL(clicked()),
- this, SLOT(openStartChatDialog()));
-
- 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&)),
- this, SLOT(startChatroom(const QString&)));
-
- connect(m_invitationDialog, SIGNAL(invitationAccepted(const ndn::Name&)),
- this, SLOT(acceptInvitation(const ndn::Name&)));
- connect(m_invitationDialog, SIGNAL(invitationRejected(const ndn::Name&)),
- this, SLOT(rejectInvitation(const ndn::Name&)));
-
- connect(&*m_contactManager, SIGNAL(contactAdded(const ndn::Name&)),
- this, SLOT(addContactIntoValidator(const ndn::Name&)));
- connect(&*m_contactManager, SIGNAL(contactRemoved(const ndn::Name&)),
- this, SLOT(removeContactFromValidator(const ndn::Name&)));
-
- connect(m_settingDialog, SIGNAL(identitySet(const QString&, const QString&)),
- this, SLOT(updateDefaultIdentity(const QString&, const QString&)));
-
- 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_menuAlias;
-
- map<Name, ChatDialog*>::iterator it = m_chatDialogs.begin();
- for(; it != m_chatDialogs.end(); it++)
- delete it->second;
-}
-
-void
-ContactPanel::createAction()
-{
- 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()
-{
-#ifdef WITH_SECURITY
- vector<shared_ptr<ContactItem> >::const_iterator it = m_contactList.begin();
- for(; it != m_contactList.end(); it++)
- {
- _LOG_DEBUG("load contact: " << (*it)->getNameSpace().toUri());
- m_invitationValidator->addTrustAnchor((*it)->getSelfEndorseCertificate());
- m_panelValidator->addTrustAnchor((*it)->getSelfEndorseCertificate());
- }
-#endif
-}
-
-void
-ContactPanel::setLocalPrefix(int retry)
-{
- Name interestName("/local/ndn/prefix");
- Interest interest(interestName);
-
- m_face->expressInterest(interest,
- bind(&ContactPanel::onLocalPrefix, this, _1, _2),
- bind(&ContactPanel::onLocalPrefixTimeout, this, _1, 10));
-
-}
-
-void
-ContactPanel::onLocalPrefix(const Interest& interest, Data& data)
-{
- string originPrefix(reinterpret_cast<const char*>(data.getContent().value()), data.getContent().value_size());
- string prefix = QString::fromStdString (originPrefix).trimmed ().toStdString();
- m_localPrefix = Name(prefix);
-}
-
-void
-ContactPanel::onLocalPrefixTimeout(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,
- bind(&ContactPanel::onInvitation, this, _1, _2),
- bind(&ContactPanel::onInvitationRegisterFailed, this, _1, _2));
-}
-
-void
-ContactPanel::sendInterest(const Interest& interest,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onValidationFailed,
- const TimeoutNotify& timeoutNotify,
- int retry /* = 1 */)
-{
- m_face->expressInterest(interest,
- bind(&ContactPanel::onTargetData,
- this, _1, _2, onValidated, onValidationFailed),
- bind(&ContactPanel::onTargetTimeout,
- this, _1, retry, onValidated, onValidationFailed, timeoutNotify));
-}
-
-void
-ContactPanel::onTargetData(const ndn::Interest& interest,
- Data& data,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onValidationFailed)
-{
- m_panelValidator->validate(data, onValidated, onValidationFailed);
-}
-
-void
-ContactPanel::onTargetTimeout(const ndn::Interest& interest,
- int retry,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onValidationFailed,
- const TimeoutNotify& timeoutNotify)
-{
- if(retry > 0)
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
- else
- {
- _LOG_DEBUG("Interest: " << interest.getName() << " eventually times out!");
- timeoutNotify();
- }
-}
-
-void
-ContactPanel::onInvitationRegisterFailed(const Name& prefix, const string& msg)
-{
- showError(QString::fromStdString("Cannot register invitation listening prefix! " + msg));
-}
-
-void
-ContactPanel::onInvitation(const Name& prefix, const Interest& interest)
-{
- _LOG_DEBUG("Receive invitation!" << interest.getName() << " " << prefix);
-
- OnInterestValidated onValidated = bind(&ContactPanel::onInvitationValidated, this, _1);
- OnInterestValidationFailed onValidationFailed = bind(&ContactPanel::onInvitationValidationFailed, this, _1);
- m_invitationValidator->validate(interest, onValidated, onValidationFailed);
-}
-
-void
-ContactPanel::popChatInvitation(const Name& interestName)
-{
- Invitation invitation(interestName);
- string alias;
-
- vector<shared_ptr<ContactItem> >::iterator it = m_contactList.begin();
- for(; it != m_contactList.end(); it++)
- if((*it)->getNameSpace() == invitation.getInviteeNameSpace())
- alias = (*it)->getAlias();
-
- if(it != m_contactList.end())
- return;
-
- m_invitationDialog->setInvitation(alias, interestName);
- m_invitationDialog->show();
-}
-
-void
-ContactPanel::collectEndorsement()
-{
-#ifdef WITH_SECURITY
- 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);
-
- OnDataValidated onValidated = bind(&ContactPanel::onDnsEndorseeValidated, this, _1, count);
- OnDataValidationFailed onValidationFailed = bind(&ContactPanel::onDnsEndorseeValidationFailed, this, _1, count);
- TimeoutNotify timeoutNotify = bind(&ContactPanel::onDnsEndorseeTimeoutNotify, this, count);
-
- sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
- }
-#endif
-}
-
-void
-ContactPanel::onDnsEndorseeValidated(const shared_ptr<const 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::onDnsEndorseeValidationFailed(const shared_ptr<const 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->publishCollectEndorsedDataInDNS(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(identity.toStdString());
- Name defaultCertName = m_keyChain->createIdentity(defaultIdentity);
-
- 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::addContactIntoValidator(const Name& contactNameSpace)
-{
-#ifdef WITH_SECURITY
- shared_ptr<ContactItem> contact = m_contactManager->getContact(contactNameSpace);
- if(static_cast<bool>(contact))
- {
- m_panelValidator->addTrustAnchor(contact->getSelfEndorseCertificate());
- m_invitationValidator->addTrustAnchor(contact->getSelfEndorseCertificate());
- }
-#endif
-}
-
-void
-ContactPanel::removeContactFromValidator(const Name& keyName)
-{
-#ifdef WITH_SECURITY
- m_panelValidator->removeTrustAnchor(keyName);
- m_invitationValidator->removeTrustAnchor(keyName);
-#endif
-}
-
-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_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->setChatroom(chatroom.toUri());
- m_startChatDialog->show();
-}
-
-// For inviter
-void
-ContactPanel::startChatroom(const QString& chatroom)
-{
- Name chatroomName(chatroom.toStdString());
-
- ChatDialog* chatDialog = new ChatDialog(m_contactManager, m_face, chatroomName, m_localPrefix, m_defaultIdentity, m_nickName);
- m_chatDialogs[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&)));
-
- chatDialog->show();
-}
-
-// For Invitee
-void
-ContactPanel::startChatroom2(const Name& invitationInterest)
-{
- Invitation invitation(invitationInterest);
- Name chatroomName("/ndn/broadcast/chronos");
- chatroomName.append(invitation.getChatroom());
-
- ChatDialog* chatDialog = new ChatDialog(m_contactManager, m_face, chatroomName, m_localPrefix, m_defaultIdentity, m_nickName);
- 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&)));
-
- Block signatureBlock = invitationInterest.get(-1).blockFromValue();
- Block signatureInfo = invitationInterest.get(-2).blockFromValue();
- Signature signature(signatureInfo, signatureBlock);
-
- SignatureSha256WithRsa sig(signature);
- Name keyLocatorName = sig.getKeyLocator().getName();
- Name inviter = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName).getPrefix(-1);
-
-#ifdef WITH_SECURITY
- shared_ptr<IdentityCertificate> idCert = m_invitationValidator->getValidatedDskCertificate(keyLocatorName);
- chatDialog->addChatDataRule(invitation.getInviterRoutingPrefix(), *idCert, true);
- chatDialog->publishIntroCert(*idCert, true);
- shared_ptr<ContactItem> inviterItem = m_contactManager->getContact(inviter);
- chatDialog->addTrustAnchor(inviterItem->getSelfEndorseCertificate());
-#endif
-
- m_chatDialogs[chatroomName] = chatDialog;
-
- chatDialog->show();
-}
-
-void
-ContactPanel::prepareInvitationReply(const Name& invitationInterest, const string& content)
-{
- Invitation invitation(invitationInterest);
-
- Name dataName = invitationInterest;
- dataName.appendVersion();
-
- Data data(dataName);
- data.setContent(reinterpret_cast<const uint8_t*>(content.c_str()), content.size());
- data.setFreshnessPeriod(1000);
-
- m_keyChain->signByIdentity(data, invitation.getInviteeNameSpace());
-
- 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
diff --git a/src/contactpanel.h b/src/contactpanel.h
deleted file mode 100644
index 9e0c3b3..0000000
--- a/src/contactpanel.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef CONTACTPANEL_H
-#define CONTACTPANEL_H
-
-#include <QDialog>
-#include <QStringListModel>
-#include <QtSql/QSqlDatabase>
-#include <QMenu>
-#include <QMessageBox>
-
-#include "profileeditor.h"
-#include "addcontactpanel.h"
-#include "setaliasdialog.h"
-#include "startchatdialog.h"
-#include "invitationdialog.h"
-#include "settingdialog.h"
-#include "chatdialog.h"
-#include "endorse-combobox-delegate.h"
-#include "browsecontactdialog.h"
-#include "warningdialog.h"
-
-#ifndef Q_MOC_RUN
-#include "contact-manager.h"
-#include "invitation.h"
-
-#ifdef WITH_SECURITY
-#include "validator-panel.h"
-#include "validator-invitation.h"
-#else
-#include <ndn-cpp-dev/security/validator-null.hpp>
-#endif
-
-#endif
-
-
-namespace Ui {
-class ContactPanel;
-}
-
-class ContactPanel : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit ContactPanel(ndn::shared_ptr<ndn::Face> face,
- QWidget *parent = 0);
-
- ~ContactPanel();
-
-private:
- void
- createAction();
-
- void
- openDB();
-
- void
- loadTrustAnchor();
-
- void
- setLocalPrefix(int retry = 10);
-
- void
- onLocalPrefix(const ndn::Interest& interest, ndn::Data& data);
-
- void
- onLocalPrefixTimeout(const ndn::Interest& interest, int retry);
-
- void
- setInvitationListener();
-
- void
- onInvitation(const ndn::Name& prefix, const ndn::Interest& interest);
-
- void
- onInvitationRegisterFailed(const ndn::Name& prefix, const std::string& msg);
-
- inline void
- onInvitationValidated(const ndn::shared_ptr<const ndn::Interest>& interest);
-
- inline void
- onInvitationValidationFailed(const ndn::shared_ptr<const ndn::Interest>& interest);
-
- void
- popChatInvitation(const ndn::Name& interestName);
-
- void
- sendInterest(const ndn::Interest& interest,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed,
- const chronos::TimeoutNotify& timeoutNotify,
- int retry = 1);
-
- void
- onTargetData(const ndn::Interest& interest,
- ndn::Data& data,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed);
-
- void
- onTargetTimeout(const ndn::Interest& interest,
- int retry,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed,
- const chronos::TimeoutNotify& timeoutNotify);
-
- void
- collectEndorsement();
-
- void
- onDnsEndorseeValidated(const ndn::shared_ptr<const ndn::Data>& data, int count);
-
- void
- onDnsEndorseeValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, int count);
-
- void
- onDnsEndorseeTimeoutNotify(int count);
-
- void
- updateCollectStatus(int count);
-
- std::string
- getRandomString();
-
-signals:
- void
- refreshCertDirectory();
-
-private slots:
- void
- showError(const QString& msg);
-
- void
- showWarning(const QString& msg);
-
- void
- updateSelection(const QItemSelection &selected,
- const QItemSelection &deselected);
-
- void
- updateDefaultIdentity(const QString& identity,
- const QString& nickName);
-
- void
- openProfileEditor();
-
- void
- openAddContactPanel();
-
- void
- openBrowseContactDialog();
-
- void
- openSetAliasDialog();
-
- void
- removeContactButton();
-
- void
- openStartChatDialog();
-
- void
- openSettingDialog();
-
- void
- refreshContactList();
-
- void
- showContextMenu(const QPoint& pos);
-
- void
- startChatroom(const QString& chatroom);
-
- void
- startChatroom2(const ndn::Name& invitationInterest);
-
- inline void
- acceptInvitation(const ndn::Name& invitationInterest);
-
- inline void
- rejectInvitation(const ndn::Name& invitationInterest);
-
- void
- prepareInvitationReply(const ndn::Name& invitationInterest, const std::string& content);
-
- void
- isIntroducerChanged(int state);
-
- void
- addScopeClicked();
-
- void
- deleteScopeClicked();
-
- void
- saveScopeClicked();
-
- void
- endorseButtonClicked();
-
- void
- removeChatDialog(const ndn::Name& chatroomName);
-
- void
- addContactIntoValidator(const ndn::Name& nameSpace);
-
- void
- removeContactFromValidator(const ndn::Name& keyName);
-
-
-private:
-
- Ui::ContactPanel *ui;
- WarningDialog* m_warningDialog;
- QStringListModel* m_contactListModel;
- ProfileEditor* m_profileEditor;
- AddContactPanel* m_addContactPanel;
- BrowseContactDialog* m_browseContactDialog;
- SetAliasDialog* m_setAliasDialog;
- StartChatDialog* m_startChatDialog;
- InvitationDialog* m_invitationDialog;
- SettingDialog* m_settingDialog;
- std::map<ndn::Name, ChatDialog*> m_chatDialogs;
- QAction* m_menuAlias;
-
-#ifdef WITH_SECURITY
- ndn::shared_ptr<chronos::ValidatorPanel> m_panelValidator;
- ndn::shared_ptr<chronos::ValidatorInvitation> m_invitationValidator;
-#else
- ndn::shared_ptr<ndn::Validator> m_panelValidator;
- ndn::shared_ptr<ndn::Validator> m_invitationValidator;
-#endif
-
- ndn::shared_ptr<ndn::KeyChain> m_keyChain;
- ndn::shared_ptr<ndn::Face> m_face;
- ndn::shared_ptr<boost::asio::io_service> m_ioService;
-
- ndn::shared_ptr<chronos::ContactManager> m_contactManager;
-
- std::vector<ndn::shared_ptr<chronos::ContactItem> > m_contactList;
- ndn::shared_ptr<std::vector<bool> > m_collectStatus;
-
- const ndn::RegisteredPrefixId* m_invitationListenerId;
-
- ndn::Name m_defaultIdentity;
- std::string m_nickName;
- ndn::Name m_localPrefix;
- ndn::Name m_inviteListenPrefix;
-
- ndn::shared_ptr<chronos::ContactItem> m_currentSelectedContact;
- QSqlTableModel* m_trustScopeModel;
- QSqlTableModel* m_endorseDataModel;
- EndorseComboBoxDelegate* m_endorseComboBoxDelegate;
-};
-
-void
-ContactPanel::onInvitationValidated(const ndn::shared_ptr<const ndn::Interest>& interest)
-{ popChatInvitation(interest->getName()); }
-
-void
-ContactPanel::onInvitationValidationFailed(const ndn::shared_ptr<const ndn::Interest>& interest)
-{}
-
-void
-ContactPanel::acceptInvitation(const ndn::Name& invitationInterest)
-{
- prepareInvitationReply(invitationInterest, m_localPrefix.toUri());
- startChatroom2(invitationInterest);
-}
-
-void
-ContactPanel::rejectInvitation(const ndn::Name& invitationInterest)
-{ prepareInvitationReply(invitationInterest, "nack"); }
-
-
-#endif // CONTACTPANEL_H
diff --git a/src/contactpanel.ui b/src/contactpanel.ui
deleted file mode 100644
index 5410c2e..0000000
--- a/src/contactpanel.ui
+++ /dev/null
@@ -1,344 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ContactPanel</class>
- <widget class="QDialog" name="ContactPanel">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>600</width>
- <height>480</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>ChronoChat Contacts</string>
- </property>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>12</x>
- <y>12</y>
- <width>581</width>
- <height>471</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2" stretch="30,1">
- <item>
- <layout class="QHBoxLayout" name="ContactPanelLayout" stretch="3,7">
- <property name="spacing">
- <number>10</number>
- </property>
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <widget class="QListView" name="ContactList">
- <property name="contextMenuPolicy">
- <enum>Qt::CustomContextMenu</enum>
- </property>
- <property name="acceptDrops">
- <bool>false</bool>
- </property>
- <property name="editTriggers">
- <set>QAbstractItemView::NoEditTriggers</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTabWidget" name="ContactInfo">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="General">
- <attribute name="title">
- <string>General</string>
- </attribute>
- <widget class="QGraphicsView" name="Avatar">
- <property name="geometry">
- <rect>
- <x>130</x>
- <y>10</y>
- <width>128</width>
- <height>128</height>
- </rect>
- </property>
- </widget>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>160</y>
- <width>331</width>
- <height>124</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout" stretch="35,100">
- <property name="spacing">
- <number>-1</number>
- </property>
- <item>
- <widget class="QLabel" name="NameSpaceLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Name space</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="NameSpaceData">
- <property name="font">
- <font>
- <family>Lucida Grande</family>
- </font>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="35,100">
- <item>
- <widget class="QLabel" name="NameLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Name</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="NameData">
- <property name="font">
- <font>
- <family>Lucida Grande</family>
- </font>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="35,100">
- <item>
- <widget class="QLabel" name="InstitutionLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Institution </string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="InstitutionData">
- <property name="font">
- <font>
- <family>Lucida Grande</family>
- </font>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- <widget class="QWidget" name="TrustScope">
- <attribute name="title">
- <string>Trust Scope</string>
- </attribute>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>10</y>
- <width>362</width>
- <height>371</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QCheckBox" name="isIntroducer">
- <property name="text">
- <string>Set as introducer</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTableView" name="trustScopeList">
- <attribute name="horizontalHeaderStretchLastSection">
- <bool>true</bool>
- </attribute>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QPushButton" name="addScope">
- <property name="text">
- <string>Add Scope</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="deleteScope">
- <property name="text">
- <string>Delete Scope</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="saveButton">
- <property name="text">
- <string>Save</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- <widget class="QWidget" name="Endorse">
- <attribute name="title">
- <string>Endorse</string>
- </attribute>
- <widget class="QTableView" name="endorseList">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>10</y>
- <width>351</width>
- <height>331</height>
- </rect>
- </property>
- <attribute name="horizontalHeaderStretchLastSection">
- <bool>true</bool>
- </attribute>
- </widget>
- <widget class="QPushButton" name="endorseButton">
- <property name="geometry">
- <rect>
- <x>260</x>
- <y>350</y>
- <width>114</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>Endorse</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </widget>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="4,3,3,3">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,1">
- <property name="spacing">
- <number>-1</number>
- </property>
- <item>
- <widget class="QPushButton" name="AddContactButton">
- <property name="text">
- <string>Add </string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="DeleteContactButton">
- <property name="text">
- <string>Delete</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QPushButton" name="chatButton">
- <property name="text">
- <string>Chat!</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="settingButton">
- <property name="text">
- <string>Setting</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="EditProfileButton">
- <property name="text">
- <string>Edit Profile</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/controller.cpp b/src/controller.cpp
new file mode 100644
index 0000000..723617a
--- /dev/null
+++ b/src/controller.cpp
@@ -0,0 +1,803 @@
+/* -*- 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 <QApplication>
+#include <QMessageBox>
+#include <QDir>
+#include <QTimer>
+#include "controller.h"
+
+#ifndef Q_MOC_RUN
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <ndn-cpp-dev/util/random.hpp>
+#include <cryptopp/sha.h>
+#include <cryptopp/hex.h>
+#include <cryptopp/files.h>
+#include <cryptopp/filters.h>
+#include "config.pb.h"
+#include "endorse-info.pb.h"
+#include "logging.h"
+#endif
+
+INIT_LOGGER("chronos.Controller");
+
+using namespace ndn;
+
+Q_DECLARE_METATYPE(ndn::Name)
+Q_DECLARE_METATYPE(ndn::IdentityCertificate)
+Q_DECLARE_METATYPE(chronos::EndorseInfo)
+
+namespace chronos {
+
+static const uint8_t ROUTING_PREFIX_SEPARATOR[2] = {0xF0, 0x2E};
+
+// constructor & destructor
+Controller::Controller(shared_ptr<Face> face,
+ QWidget* parent)
+ : QDialog(parent)
+ , m_face(face)
+ , m_invitationListenerId(0)
+ , m_contactManager(m_face)
+ , m_settingDialog(new SettingDialog)
+ , m_startChatDialog(new StartChatDialog)
+ , m_profileEditor(new ProfileEditor)
+ , m_invitationDialog(new InvitationDialog)
+ , m_contactPanel(new ContactPanel)
+ , m_browseContactDialog(new BrowseContactDialog)
+ , m_addContactPanel(new AddContactPanel)
+{
+ qRegisterMetaType<ndn::Name>("ndn.Name");
+ qRegisterMetaType<ndn::IdentityCertificate>("ndn.IdentityCertificate");
+ qRegisterMetaType<chronos::EndorseInfo>("chronos.EndorseInfo");
+
+ connect(this, SIGNAL(localPrefixUpdated(const QString&)),
+ this, SLOT(onLocalPrefixUpdated(const QString&)));
+
+ // Connection to ContactManager
+ connect(this, SIGNAL(identityUpdated(const QString&)),
+ &m_contactManager, SLOT(onIdentityUpdated(const QString&)));
+ connect(&m_contactManager, SIGNAL(warning(const QString&)),
+ this, SLOT(onWarning(const QString&)));
+ connect(this, SIGNAL(refreshBrowseContact()),
+ &m_contactManager, SLOT(onRefreshBrowseContact()));
+ connect(&m_contactManager, SIGNAL(contactInfoFetchFailed(const QString&)),
+ this, SLOT(onWarning(const QString&)));
+ connect(&m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
+ this, SLOT(onContactIdListReady(const QStringList&)));
+
+ // Connection to SettingDialog
+ connect(this, SIGNAL(identityUpdated(const QString&)),
+ m_settingDialog, SLOT(onIdentityUpdated(const QString&)));
+ connect(m_settingDialog, SIGNAL(identityUpdated(const QString&)),
+ this, SLOT(onIdentityUpdated(const QString&)));
+ connect(m_settingDialog, SIGNAL(nickUpdated(const QString&)),
+ this, SLOT(onNickUpdated(const QString&)));
+
+ // Connection to ProfileEditor
+ connect(this, SIGNAL(closeDBModule()),
+ m_profileEditor, SLOT(onCloseDBModule()));
+ connect(this, SIGNAL(identityUpdated(const QString&)),
+ m_profileEditor, SLOT(onIdentityUpdated(const QString&)));
+ connect(m_profileEditor, SIGNAL(updateProfile()),
+ &m_contactManager, SLOT(onUpdateProfile()));
+
+ // Connection to StartChatDialog
+ connect(m_startChatDialog, SIGNAL(startChatroom(const QString&, bool)),
+ this, SLOT(onStartChatroom(const QString&, bool)));
+
+ // Connection to InvitationDialog
+ connect(m_invitationDialog, SIGNAL(invitationResponded(const ndn::Name&, bool)),
+ this, SLOT(onInvitationResponded(const ndn::Name&, bool)));
+
+ // Connection to AddContactPanel
+ connect(m_addContactPanel, SIGNAL(fetchInfo(const QString&)),
+ &m_contactManager, SLOT(onFetchContactInfo(const QString&)));
+ connect(m_addContactPanel, SIGNAL(addContact(const QString&)),
+ &m_contactManager, SLOT(onAddFetchedContact(const QString&)));
+ connect(&m_contactManager, SIGNAL(contactEndorseInfoReady(const chronos::EndorseInfo&)),
+ m_addContactPanel, SLOT(onContactEndorseInfoReady(const chronos::EndorseInfo&)));
+
+
+ // Connection to BrowseContactDialog
+ connect(m_browseContactDialog, SIGNAL(directAddClicked()),
+ this, SLOT(onDirectAdd()));
+ connect(m_browseContactDialog, SIGNAL(fetchIdCert(const QString&)),
+ &m_contactManager, SLOT(onFetchIdCert(const QString&)));
+ connect(m_browseContactDialog, SIGNAL(addContact(const QString&)),
+ &m_contactManager, SLOT(onAddFetchedContactIdCert(const QString&)));
+ connect(&m_contactManager, SIGNAL(idCertNameListReady(const QStringList&)),
+ m_browseContactDialog, SLOT(onIdCertNameListReady(const QStringList&)));
+ connect(&m_contactManager, SIGNAL(nameListReady(const QStringList&)),
+ m_browseContactDialog, SLOT(onNameListReady(const QStringList&)));
+ connect(&m_contactManager, SIGNAL(idCertReady(const ndn::IdentityCertificate&)),
+ m_browseContactDialog, SLOT(onIdCertReady(const ndn::IdentityCertificate&)));
+
+ // Connection to ContactPanel
+ connect(m_contactPanel, SIGNAL(waitForContactList()),
+ &m_contactManager, SLOT(onWaitForContactList()));
+ connect(m_contactPanel, SIGNAL(waitForContactInfo(const QString&)),
+ &m_contactManager, SLOT(onWaitForContactInfo(const QString&)));
+ connect(m_contactPanel, SIGNAL(removeContact(const QString&)),
+ &m_contactManager, SLOT(onRemoveContact(const QString&)));
+ connect(m_contactPanel, SIGNAL(updateAlias(const QString&, const QString&)),
+ &m_contactManager, SLOT(onUpdateAlias(const QString&, const QString&)));
+ connect(m_contactPanel, SIGNAL(updateIsIntroducer(const QString&, bool)),
+ &m_contactManager, SLOT(onUpdateIsIntroducer(const QString&, bool)));
+ connect(m_contactPanel, SIGNAL(updateEndorseCertificate(const QString&)),
+ &m_contactManager, SLOT(onUpdateEndorseCertificate(const QString&)));
+ connect(m_contactPanel, SIGNAL(warning(const QString&)),
+ this, SLOT(onWarning(const QString&)));
+ connect(this, SIGNAL(closeDBModule()),
+ m_contactPanel, SLOT(onCloseDBModule()));
+ connect(this, SIGNAL(identityUpdated(const QString&)),
+ m_contactPanel, SLOT(onIdentityUpdated(const QString&)));
+ connect(&m_contactManager, SIGNAL(contactAliasListReady(const QStringList&)),
+ m_contactPanel, SLOT(onContactAliasListReady(const QStringList&)));
+ connect(&m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
+ m_contactPanel, SLOT(onContactIdListReady(const QStringList&)));
+ connect(&m_contactManager, SIGNAL(contactInfoReady(const QString&, const QString&, const QString&, bool)),
+ m_contactPanel, SLOT(onContactInfoReady(const QString&, const QString&, const QString&, bool)));
+
+ initialize();
+
+ createTrayIcon();
+}
+
+Controller::~Controller()
+{
+ saveConf();
+}
+
+// public methods
+
+
+// private methods
+std::string
+Controller::getDBName()
+{
+ std::string dbName("chronos-");
+
+ std::stringstream ss;
+ {
+ using namespace CryptoPP;
+
+ SHA256 hash;
+ StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
+ new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
+ }
+ dbName.append(ss.str()).append(".db");
+
+ return dbName;
+}
+
+void
+Controller::openDB()
+{
+ m_db = QSqlDatabase::addDatabase("QSQLITE");
+ QString path = (QDir::home().path());
+ path.append(QDir::separator()).append(".chronos").append(QDir::separator()).append(getDBName().c_str());
+ m_db.setDatabaseName(path);
+ bool ok = m_db.open();
+
+ _LOG_DEBUG("DB opened: " << std::boolalpha << ok );
+}
+
+void
+Controller::initialize()
+{
+ loadConf();
+
+ m_keyChain.createIdentity(m_identity);
+
+ openDB();
+
+ emit identityUpdated(QString(m_identity.toUri().c_str()));
+
+ setInvitationListener();
+}
+
+void
+Controller::setInvitationListener()
+{
+ if(m_invitationListenerId != 0)
+ m_face->unsetInterestFilter(m_invitationListenerId);
+
+ Name invitationPrefix;
+ Name routingPrefix = getInvitationRoutingPrefix();
+ size_t offset = 0;
+ if(!routingPrefix.isPrefixOf(m_identity))
+ {
+ invitationPrefix.append(routingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2);
+ offset = routingPrefix.size() + 1;
+ }
+ invitationPrefix.append(m_identity).append("CHRONOCHAT-INVITATION");
+
+ m_invitationListenerId = m_face->setInterestFilter(invitationPrefix,
+ bind(&Controller::onInvitationInterest, this, _1, _2, offset),
+ bind(&Controller::onInvitationRegisterFailed, this, _1, _2));
+}
+
+void
+Controller::loadConf()
+{
+ namespace fs = boost::filesystem;
+
+ fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
+ fs::create_directories (chronosDir);
+
+ std::ifstream is((chronosDir / "config").c_str ());
+ ChronoChat::Conf conf;
+ if(conf.ParseFromIstream(&is))
+ {
+ m_identity.clear();
+ m_identity.append(conf.identity());
+ if(conf.has_nick())
+ m_nick = conf.nick();
+ else
+ m_nick = m_identity.get(-1).toUri();
+ }
+ else
+ {
+ m_identity.clear();
+ // TODO: change below to system default;
+ m_identity.append("chronochat-tmp-identity")
+ .append(boost::lexical_cast<std::string>(random::generateWord64()));
+
+ m_nick = m_identity.get(-1).toUri();
+ }
+}
+
+void
+Controller::saveConf()
+{
+ namespace fs = boost::filesystem;
+
+ fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
+ fs::create_directories (chronosDir);
+
+ std::ofstream os((chronosDir / "config").c_str ());
+ ChronoChat::Conf conf;
+ conf.set_identity(m_identity.toUri());
+ if(!m_nick.empty())
+ conf.set_nick(m_nick);
+ conf.SerializeToOstream(&os);
+
+ os.close();
+}
+
+void
+Controller::createActions()
+{
+ m_startChatroom = new QAction(tr("Start new chat"), this);
+ connect(m_startChatroom, SIGNAL(triggered()), this, SLOT(onStartChatAction()));
+
+ m_settingsAction = new QAction(tr("Settings"), this);
+ connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(onSettingsAction()));
+
+ m_editProfileAction = new QAction(tr("Edit profile"), this);
+ connect(m_editProfileAction, SIGNAL(triggered()), this, SLOT(onProfileEditorAction()));
+
+ m_contactListAction = new QAction(tr("Contact List"), this);
+ connect(m_contactListAction, SIGNAL(triggered()), this, SLOT(onContactListAction()));
+
+ m_addContactAction = new QAction(tr("Add contact"), this);
+ connect(m_addContactAction, SIGNAL(triggered()), this, SLOT(onAddContactAction()));
+
+ m_updateLocalPrefixAction = new QAction(tr("Update local prefix"), this);
+ connect(m_updateLocalPrefixAction, SIGNAL(triggered()), this, SLOT(onUpdateLocalPrefixAction()));
+
+ m_minimizeAction = new QAction(tr("Mi&nimize"), this);
+ connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(onMinimizeAction()));
+
+ m_quitAction = new QAction(tr("Quit"), this);
+ connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuitAction()));
+}
+
+void
+Controller::createTrayIcon()
+{
+ createActions();
+
+ m_trayIconMenu = new QMenu(this);
+ m_trayIconMenu->addAction(m_startChatroom);
+ m_trayIconMenu->addSeparator();
+ m_trayIconMenu->addAction(m_settingsAction);
+ m_trayIconMenu->addAction(m_editProfileAction);
+ m_trayIconMenu->addSeparator();
+ m_trayIconMenu->addAction(m_contactListAction);
+ m_trayIconMenu->addAction(m_addContactAction);
+ m_trayIconMenu->addSeparator();
+ m_trayIconMenu->addAction(m_updateLocalPrefixAction);
+ m_trayIconMenu->addSeparator();
+ m_trayIconMenu->addAction(m_minimizeAction);
+ m_closeMenu = m_trayIconMenu->addMenu("Close chatroom");
+ m_closeMenu->setEnabled(false);
+ m_trayIconMenu->addSeparator();
+ m_trayIconMenu->addAction(m_quitAction);
+
+ m_trayIcon = new QSystemTrayIcon(this);
+ m_trayIcon->setContextMenu(m_trayIconMenu);
+
+ m_trayIcon->setIcon(QIcon(":/images/icon_small.png"));
+ m_trayIcon->setToolTip("ChronoChat System Tray Icon");
+ m_trayIcon->setVisible(true);
+}
+
+void
+Controller::updateMenu()
+{
+ QMenu* menu = new QMenu(this);
+ QMenu* closeMenu = 0;
+
+ menu->addAction(m_startChatroom);
+ menu->addSeparator();
+ menu->addAction(m_settingsAction);
+ menu->addAction(m_editProfileAction);
+ menu->addSeparator();
+ menu->addAction(m_addContactAction);
+ menu->addSeparator();
+ {
+ ChatActionList::const_iterator it = m_chatActionList.begin();
+ ChatActionList::const_iterator end = m_chatActionList.end();
+ if(it != end)
+ {
+ for(; it != end; it++)
+ menu->addAction(it->second);
+ menu->addSeparator();
+ }
+ }
+ menu->addAction(m_updateLocalPrefixAction);
+ menu->addSeparator();
+ menu->addAction(m_minimizeAction);
+ closeMenu = menu->addMenu("Close chatroom");
+ {
+ ChatActionList::const_iterator it = m_closeActionList.begin();
+ ChatActionList::const_iterator end = m_closeActionList.end();
+ if(it == end)
+ {
+ closeMenu->setEnabled(false);
+ }
+ else
+ {
+ for(; it != end; it++)
+ closeMenu->addAction(it->second);
+ }
+ }
+ menu->addSeparator();
+ menu->addAction(m_quitAction);
+
+ m_trayIcon->setContextMenu(menu);
+ delete m_trayIconMenu;
+ m_trayIconMenu = menu;
+ m_closeMenu = closeMenu;
+}
+
+void
+Controller::onLocalPrefix(const Interest& interest, Data& data)
+{
+ QString localPrefixStr = QString::fromUtf8
+ (reinterpret_cast<const char*>(data.getContent().value()), data.getContent().value_size())
+ .trimmed();
+
+ Name localPrefix(localPrefixStr.toStdString());
+ if(m_localPrefix.empty() || m_localPrefix != localPrefix)
+ emit localPrefixUpdated(localPrefixStr);
+}
+
+void
+Controller::onLocalPrefixTimeout(const Interest& interest)
+{
+ QString localPrefixStr("/private/local");
+
+ Name localPrefix(localPrefixStr.toStdString());
+ if(m_localPrefix.empty() || m_localPrefix != localPrefix)
+ emit localPrefixUpdated(localPrefixStr);
+}
+
+void
+Controller::onInvitationInterest(const Name& prefix, const Interest& interest, size_t routingPrefixOffset)
+{
+ shared_ptr<Interest> invitationInterest = make_shared<Interest>(boost::cref(interest.getName().getSubName(routingPrefixOffset)));
+
+ // check if the chatroom already exists;
+ try
+ {
+ Invitation invitation(invitationInterest->getName());
+ if(m_chatDialogList.find(invitation.getChatroom()) != m_chatDialogList.end())
+ return;
+ }
+ catch(Invitation::Error& e)
+ {
+ // Cannot parse the invitation;
+ return;
+ }
+
+ OnInterestValidated onValidated = bind(&Controller::onInvitationValidated, this, _1);
+ OnInterestValidationFailed onValidationFailed = bind(&Controller::onInvitationValidationFailed, this, _1, _2);
+ m_validator.validate(*invitationInterest, onValidated, onValidationFailed);
+}
+
+void
+Controller::onInvitationRegisterFailed(const Name& prefix, const std::string& failInfo)
+{
+ std::cerr << "Controller::onInvitationRegisterFailed: " << failInfo << std::endl;
+}
+
+void
+Controller::onInvitationValidated(const shared_ptr<const Interest>& interest)
+{
+ Invitation invitation(interest->getName());
+ std::string alias = invitation.getInviterCertificate().getPublicKeyName().getPrefix(-1).toUri(); // Should be obtained via a method of ContactManager.
+
+ m_invitationDialog->setInvitation(alias, invitation.getChatroom(), interest->getName());
+ m_invitationDialog->show();
+}
+
+void
+Controller::onInvitationValidationFailed(const shared_ptr<const Interest>& interest, std::string failureInfo)
+{
+ std::cerr << "Invitation: " << interest->getName() << " cannot not be validated due to: " << failureInfo << std::endl;
+}
+
+std::string
+Controller::getRandomString()
+{
+ uint32_t r = random::generateWord32();
+ std::stringstream ss;
+ {
+ using namespace CryptoPP;
+ StringSource(reinterpret_cast<uint8_t*>(&r), 4, true,
+ new HexEncoder(new FileSink(ss), false));
+
+ }
+ // for(int i = 0; i < 8; i++)
+ // {
+ // uint32_t t = r & mask;
+ // if(t < 10)
+ // ss << static_cast<char>(t + 0x30);
+ // else
+ // ss << static_cast<char>(t + 0x57);
+ // r = r >> 4;
+ // }
+
+ return ss.str();
+}
+
+ndn::Name
+Controller::getInvitationRoutingPrefix()
+{
+ return Name("/ndn/broadcast");
+}
+
+void
+Controller::addChatDialog(const QString& chatroomName, ChatDialog* chatDialog)
+{
+ m_chatDialogList[chatroomName.toStdString()] = chatDialog;
+ connect(chatDialog, SIGNAL(closeChatDialog(const QString&)),
+ this, SLOT(onRemoveChatDialog(const QString&)));
+ connect(chatDialog, SIGNAL(showChatMessage(const QString&, const QString&, const QString&)),
+ this, SLOT(onShowChatMessage(const QString&, const QString&, const QString&)));
+ connect(this, SIGNAL(localPrefixUpdated(const QString&)),
+ chatDialog, SLOT(onLocalPrefixUpdated(const QString&)));
+
+ QAction* chatAction = new QAction(chatroomName, this);
+ m_chatActionList[chatroomName.toStdString()] = chatAction;
+ connect(chatAction, SIGNAL(triggered()), chatDialog, SLOT(showNormal()));
+
+ QAction* closeAction = new QAction(chatroomName, this);
+ m_closeActionList[chatroomName.toStdString()] = closeAction;
+ connect(closeAction, SIGNAL(triggered()), chatDialog, SLOT(onClose()));
+
+ updateMenu();
+}
+
+// private slots:
+void
+Controller::onIdentityUpdated(const QString& identity)
+{
+ Name identityName(identity.toStdString());
+
+ while(!m_chatDialogList.empty())
+ {
+ ChatDialogList::const_iterator it = m_chatDialogList.begin();
+ onRemoveChatDialog(QString::fromStdString(it->first));
+ }
+
+ m_identity = identityName;
+ m_keyChain.createIdentity(m_identity);
+
+ emit closeDBModule();
+
+ QTimer::singleShot(500, this, SLOT(onIdentityUpdatedContinued()));
+
+}
+
+void
+Controller::onIdentityUpdatedContinued()
+{
+ QString connection = m_db.connectionName();
+ // _LOG_DEBUG("connection name: " << connection.toStdString());
+ QSqlDatabase::removeDatabase(connection);
+ m_db.close();
+
+ openDB();
+
+ emit identityUpdated(QString(m_identity.toUri().c_str()));
+}
+
+void
+Controller::onContactIdListReady(const QStringList& list)
+{
+ ContactList contactList;
+
+ m_contactManager.getContactList(contactList);
+ m_validator.cleanTrustAnchor();
+
+ ContactList::const_iterator it = contactList.begin();
+ ContactList::const_iterator end = contactList.end();
+
+ for(; it != end; it++)
+ m_validator.addTrustAnchor((*it)->getPublicKeyName(), (*it)->getPublicKey());
+
+}
+
+void
+Controller::onNickUpdated(const QString& nick)
+{
+ m_nick = nick.toStdString();
+}
+
+void
+Controller::onLocalPrefixUpdated(const QString& localPrefix)
+{
+ m_localPrefix = Name(localPrefix.toStdString());
+}
+
+void
+Controller::onStartChatAction()
+{
+ std::string chatroom = "chatroom-" + getRandomString();
+
+ m_startChatDialog->setChatroom(chatroom);
+ m_startChatDialog->show();
+ m_startChatDialog->raise();
+}
+
+void
+Controller::onSettingsAction()
+{
+ m_settingDialog->setNick(QString(m_nick.c_str()));
+ m_settingDialog->show();
+ m_settingDialog->raise();
+}
+
+void
+Controller::onProfileEditorAction()
+{
+ m_profileEditor->show();
+ m_profileEditor->raise();
+}
+
+void
+Controller::onAddContactAction()
+{
+ emit refreshBrowseContact();
+ m_browseContactDialog->show();
+ m_browseContactDialog->raise();
+}
+
+void
+Controller::onContactListAction()
+{
+ m_contactPanel->show();
+ m_contactPanel->raise();
+}
+
+void
+Controller::onDirectAdd()
+{
+ m_addContactPanel->show();
+ m_addContactPanel->raise();
+}
+
+void
+Controller::onUpdateLocalPrefixAction()
+{
+ // Name interestName();
+ Interest interest("/local/ndn/prefix");
+ interest.setInterestLifetime(1000);
+ interest.setMustBeFresh(true);
+
+ m_face->expressInterest(interest,
+ bind(&Controller::onLocalPrefix, this, _1, _2),
+ bind(&Controller::onLocalPrefixTimeout, this, _1));
+}
+
+void
+Controller::onMinimizeAction()
+{
+ m_settingDialog->hide();
+ m_startChatDialog->hide();
+ m_profileEditor->hide();
+ m_invitationDialog->hide();
+ m_addContactPanel->hide();
+
+ ChatDialogList::iterator it = m_chatDialogList.begin();
+ ChatDialogList::iterator end = m_chatDialogList.end();
+ for(; it != end; it++)
+ it->second->hide();
+}
+
+void
+Controller::onQuitAction()
+{
+ while(!m_chatDialogList.empty())
+ {
+ ChatDialogList::const_iterator it = m_chatDialogList.begin();
+ onRemoveChatDialog(QString::fromStdString(it->first));
+ }
+
+ delete m_settingDialog;
+ delete m_startChatDialog;
+ delete m_profileEditor;
+ delete m_invitationDialog;
+ delete m_addContactPanel;
+ // TODO: clean up all the dialog.
+
+ QApplication::quit();
+}
+
+void
+Controller::onStartChatroom(const QString& chatroomName, bool secured)
+{
+ Name chatroomPrefix;
+ chatroomPrefix.append("ndn")
+ .append("broadcast")
+ .append("ChronoChat")
+ .append(chatroomName.toStdString());
+
+ // check if the chatroom exists
+ if(m_chatDialogList.find(chatroomName.toStdString()) != m_chatDialogList.end())
+ {
+ QMessageBox::information(this, tr("ChronoChat"),
+ tr("You are creating an existing chatroom."
+ "You can check it in the context memu."));
+ return;
+ }
+
+ // TODO: We should create a chatroom specific key/cert (which should be created in the first half of this method, but let's use the default one for now.
+ shared_ptr<IdentityCertificate> idCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
+ ChatDialog* chatDialog = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix, m_localPrefix, m_nick, secured);
+
+ addChatDialog(chatroomName, chatDialog);
+ chatDialog->show();
+}
+
+void
+Controller::onInvitationResponded(const Name& invitationName, bool accepted)
+{
+ Data response;
+ shared_ptr<IdentityCertificate> chatroomCert;
+
+ // generate reply;
+ if(accepted)
+ {
+ Name responseName = invitationName;
+ responseName.append(m_localPrefix.wireEncode());
+
+ response.setName(responseName);
+
+ // We should create a particular certificate for this chatroom, but let's use default one for now.
+ chatroomCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
+
+ response.setContent(chatroomCert->wireEncode());
+ response.setFreshnessPeriod(1000);
+ }
+ else
+ {
+ response.setName(invitationName);
+ response.setFreshnessPeriod(1000);
+ }
+
+ // Check if we need a wrapper
+ Name invitationRoutingPrefix = getInvitationRoutingPrefix();
+ if(invitationRoutingPrefix.isPrefixOf(m_identity))
+ {
+ m_keyChain.signByIdentity(response, m_identity);
+ m_face->put(response);
+ }
+ else
+ {
+ Name wrappedName;
+ wrappedName.append(invitationRoutingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2);
+
+ Data wrappedData(wrappedName);
+ wrappedData.setContent(response.wireEncode());
+ wrappedData.setFreshnessPeriod(1000);
+
+ m_keyChain.signByIdentity(response, m_identity);
+ m_face->put(response);
+ }
+
+ // create chatroom
+ if(accepted)
+ {
+ Invitation invitation(invitationName);
+ Name chatroomPrefix;
+ chatroomPrefix.append("ndn")
+ .append("broadcast")
+ .append("ChronoChat")
+ .append(invitation.getChatroom());
+
+ //We should create a chatroom specific key/cert (which should be created in the first half of this method, but let's use the default one for now.
+ shared_ptr<IdentityCertificate> idCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
+ ChatDialog* chatDialog = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix, m_localPrefix, m_nick, true);
+
+ addChatDialog(QString::fromStdString(invitation.getChatroom()), chatDialog);
+ chatDialog->addSyncAnchor(invitation);
+ chatDialog->show();
+ }
+}
+
+void
+Controller::onShowChatMessage(const QString& chatroomName, const QString& from, const QString& data)
+{
+ m_trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(chatroomName),
+ QString("<%1>: %2").arg(from).arg(data),
+ QSystemTrayIcon::Information, 20000);
+ m_trayIcon->setIcon(QIcon(":/images/note.png"));
+}
+
+void
+Controller::onRemoveChatDialog(const QString& chatroomName)
+{
+ ChatDialogList::iterator it = m_chatDialogList.find(chatroomName.toStdString());
+
+ if(it != m_chatDialogList.end())
+ {
+ ChatDialog* deletedChat = it->second;
+ if(deletedChat)
+ delete deletedChat;
+ m_chatDialogList.erase(it);
+
+ QAction* chatAction = m_chatActionList[chatroomName.toStdString()];
+ QAction* closeAction = m_closeActionList[chatroomName.toStdString()];
+ if(chatAction)
+ delete chatAction;
+ if(closeAction)
+ delete closeAction;
+
+ m_chatActionList.erase(chatroomName.toStdString());
+ m_closeActionList.erase(chatroomName.toStdString());
+
+ updateMenu();
+ }
+}
+
+void
+Controller::onWarning(const QString& msg)
+{
+ QMessageBox::information(this, tr("ChronoChat"), msg);
+}
+
+void
+Controller::onError(const QString& msg)
+{
+ QMessageBox::critical(this, tr("ChronoChat"), msg, QMessageBox::Ok);
+ exit(1);
+}
+
+} // namespace chronos
+
+#if WAF
+#include "controller.moc"
+#include "controller.cpp.moc"
+#endif
diff --git a/src/controller.h b/src/controller.h
new file mode 100644
index 0000000..85986c7
--- /dev/null
+++ b/src/controller.h
@@ -0,0 +1,226 @@
+/* -*- 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>
+ */
+
+#ifndef CHRONOS_CONTROLLER_H
+#define CHRONOS_CONTROLLER_H
+
+#include <QDialog>
+#include <QMenu>
+#include <QSystemTrayIcon>
+#include <QtSql/QSqlDatabase>
+
+#include "setting-dialog.h"
+#include "start-chat-dialog.h"
+#include "profile-editor.h"
+#include "invitation-dialog.h"
+#include "contact-panel.h"
+#include "browse-contact-dialog.h"
+#include "add-contact-panel.h"
+#include "chat-dialog.h"
+
+#ifndef Q_MOC_RUN
+#include "contact-manager.h"
+#include "validator-invitation.h"
+#include <ndn-cpp-dev/face.hpp>
+#include <ndn-cpp-dev/security/key-chain.hpp>
+#endif
+
+namespace chronos {
+
+class Controller : public QDialog
+{
+ Q_OBJECT
+
+public: // public methods
+ Controller(ndn::shared_ptr<ndn::Face> face,
+ QWidget* parent = 0);
+
+ virtual
+ ~Controller();
+
+private: // private methods
+ std::string
+ getDBName();
+
+ void
+ openDB();
+
+ void
+ initialize();
+
+ void
+ setInvitationListener();
+
+ void
+ loadConf();
+
+ void
+ saveConf();
+
+ void
+ createActions();
+
+ void
+ createTrayIcon();
+
+ void
+ updateMenu();
+
+ void
+ onLocalPrefix(const ndn::Interest& interest, ndn::Data& data);
+
+ void
+ onLocalPrefixTimeout(const ndn::Interest& interest);
+
+ void
+ onInvitationInterest(const ndn::Name& prefix, const ndn::Interest& interest, size_t routingPrefixOffset);
+
+ void
+ onInvitationRegisterFailed(const ndn::Name& prefix, const std::string& failInfo);
+
+ void
+ onInvitationValidated(const ndn::shared_ptr<const ndn::Interest>& interest);
+
+ void
+ onInvitationValidationFailed(const ndn::shared_ptr<const ndn::Interest>& interest, std::string failureInfo);
+
+ std::string
+ getRandomString();
+
+ ndn::Name
+ getInvitationRoutingPrefix();
+
+ void
+ addChatDialog(const QString& chatroomName, ChatDialog* chatDialog);
+
+signals:
+ void
+ closeDBModule();
+
+ void
+ localPrefixUpdated(const QString& localPrefix);
+
+ void
+ identityUpdated(const QString& identity);
+
+ void
+ refreshBrowseContact();
+
+private slots:
+ void
+ onIdentityUpdated(const QString& identity);
+
+ void
+ onIdentityUpdatedContinued();
+
+ void
+ onContactIdListReady(const QStringList& list);
+
+ void
+ onNickUpdated(const QString& nick);
+
+ void
+ onLocalPrefixUpdated(const QString& localPrefix);
+
+ void
+ onStartChatAction();
+
+ void
+ onSettingsAction();
+
+ void
+ onProfileEditorAction();
+
+ void
+ onAddContactAction();
+
+ void
+ onContactListAction();
+
+ void
+ onDirectAdd();
+
+ void
+ onUpdateLocalPrefixAction();
+
+ void
+ onMinimizeAction();
+
+ void
+ onQuitAction();
+
+ void
+ onStartChatroom(const QString& chatroom, bool secured);
+
+ void
+ onInvitationResponded(const ndn::Name& invitationName, bool accepted);
+
+ void
+ onShowChatMessage(const QString& chatroomName, const QString& from, const QString& data);
+
+ void
+ onRemoveChatDialog(const QString& chatroom);
+
+ void
+ onWarning(const QString& msg);
+
+ void
+ onError(const QString& msg);
+
+private: // private member
+ typedef std::map<std::string, QAction*> ChatActionList;
+ typedef std::map<std::string, ChatDialog*> ChatDialogList;
+
+ // Communication
+ ndn::shared_ptr<ndn::Face> m_face;
+ ndn::Name m_localPrefix;
+ const ndn::RegisteredPrefixId* m_invitationListenerId;
+
+ // Contact Manager
+ ContactManager m_contactManager;
+
+ // Tray
+ QAction* m_startChatroom;
+ QAction* m_minimizeAction;
+ QAction* m_settingsAction;
+ QAction* m_editProfileAction;
+ QAction* m_contactListAction;
+ QAction* m_addContactAction;
+ QAction* m_updateLocalPrefixAction;
+ QAction* m_quitAction;
+ QMenu* m_trayIconMenu;
+ QMenu* m_closeMenu;
+ QSystemTrayIcon* m_trayIcon;
+ ChatActionList m_chatActionList;
+ ChatActionList m_closeActionList;
+
+ // Dialogs
+ SettingDialog* m_settingDialog;
+ StartChatDialog* m_startChatDialog;
+ ProfileEditor* m_profileEditor;
+ InvitationDialog* m_invitationDialog;
+ ContactPanel* m_contactPanel;
+ BrowseContactDialog* m_browseContactDialog;
+ AddContactPanel* m_addContactPanel;
+ ChatDialogList m_chatDialogList;
+
+ // Conf
+ ndn::Name m_identity;
+ std::string m_nick;
+ QSqlDatabase m_db;
+
+ // Security related;
+ ndn::KeyChain m_keyChain;
+ chronos::ValidatorInvitation m_validator;
+};
+
+} // namespace chronos
+
+#endif //CHRONOS_CONTROLLER_H
diff --git a/src/digesttreescene.cpp b/src/digesttreescene.cpp
index d692d4e..c2aa865 100644
--- a/src/digesttreescene.cpp
+++ b/src/digesttreescene.cpp
@@ -25,10 +25,8 @@
//DisplayUserPtr DisplayUserNullPtr;
-DigestTreeScene::DigestTreeScene(ndn::shared_ptr<boost::asio::io_service> ioService,
- QWidget *parent)
+DigestTreeScene::DigestTreeScene(QWidget *parent)
: QGraphicsScene(parent)
- , m_scheduler(*ioService)
{
previouslyUpdatedUser = DisplayUserNullPtr;
}
@@ -60,7 +58,7 @@
if (rePlot)
{
plot(digest);
- m_scheduler.scheduleEvent(ndn::time::milliseconds(600), ndn::bind(&DigestTreeScene::emitReplot, this));
+ QTimer::singleShot(2100, this, SLOT(emitReplot()));
}
else
{
diff --git a/src/digesttreescene.h b/src/digesttreescene.h
index c239a49..9f1c63f 100644
--- a/src/digesttreescene.h
+++ b/src/digesttreescene.h
@@ -19,7 +19,6 @@
#include <QMap>
#ifndef Q_MOC_RUN
-#include <ndn-cpp-dev/util/scheduler.hpp>
#include <sync-seq-no.h>
#include <sync-logic.h>
#include <ctime>
@@ -45,8 +44,7 @@
typedef QMapIterator<QString, DisplayUserPtr> RosterIterator;
public:
- DigestTreeScene(ndn::shared_ptr<boost::asio::io_service> ioService,
- QWidget *parent = 0);
+ DigestTreeScene(QWidget *parent = 0);
void processUpdate(const std::vector<Sync::MissingDataInfo> &v, QString digest);
void msgReceived(QString prefix, QString nick);
void clearAll();
@@ -73,7 +71,6 @@
QGraphicsTextItem *m_rootDigest;
DisplayUserPtr previouslyUpdatedUser;
QString m_currentPrefix;
- ndn::Scheduler m_scheduler;
};
class User
diff --git a/src/dns-storage.cpp b/src/dns-storage.cpp
deleted file mode 100644
index 5391edf..0000000
--- a/src/dns-storage.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- 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 "dns-storage.h"
-
-#include <boost/filesystem.hpp>
-#include "logging.h"
-
-
-using namespace std;
-using namespace ndn;
-using namespace ndn::ptr_lib;
-namespace fs = boost::filesystem;
-
-INIT_LOGGER("DnsStorage");
-
-namespace chronos{
-
-const string INIT_DD_TABLE = "\
-CREATE TABLE IF NOT EXISTS \n \
- DnsData( \n \
- dns_identity BLOB NOT NULL, \n \
- dns_name BLOB NOT NULL, \n \
- dns_type BLOB NOT NULL, \n \
- data_name BLOB NOT NULL, \n \
- dns_value BLOB NOT NULL, \n \
- \
- PRIMARY KEY (dns_identity, dns_name, dns_type) \n \
- ); \
-CREATE INDEX dd_index ON DnsData(dns_identity, dns_name, dns_type); \n \
-CREATE INDEX dd_index2 ON DnsData(data_name); \n \
-";
-
-DnsStorage::DnsStorage()
-{
- fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
- fs::create_directories (chronosDir);
-
- int res = sqlite3_open((chronosDir / "dns.db").c_str (), &m_db);
- if (res != SQLITE_OK)
- throw Error("Chronos DNS DB cannot be open/created");
-
- // Check if SelfProfile table exists
- sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='DnsData'", -1, &stmt, 0);
- res = sqlite3_step (stmt);
-
- bool ddTableExist = false;
- if (res == SQLITE_ROW)
- ddTableExist = true;
- sqlite3_finalize (stmt);
-
- if(!ddTableExist)
- {
- char *errmsg = 0;
- res = sqlite3_exec (m_db, INIT_DD_TABLE.c_str (), NULL, NULL, &errmsg);
- if (res != SQLITE_OK && errmsg != 0)
- throw Error("Init \"error\" in DnsData");
- }
-}
-
-void
-DnsStorage::updateDnsData(const ndn::Block& data, const std::string& identity, const std::string& name, const std::string& type, const string& dataName)
-{
- sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "INSERT OR REPLACE INTO DnsData (dns_identity, dns_name, dns_type, dns_value, data_name) VALUES (?, ?, ?, ?, ?)", -1, &stmt, 0);
- sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size(), SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 2, name.c_str(), name.size(), SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 3, type.c_str(), type.size(), SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 4, (const char*)data.wire(), data.size(), SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 5, dataName.c_str(), dataName.size(), SQLITE_TRANSIENT);
- sqlite3_step(stmt);
- sqlite3_finalize(stmt);
-}
-
-shared_ptr<Data>
-DnsStorage::getData(const Name& dataName)
-{
- sqlite3_stmt *stmt;
- sqlite3_prepare_v2 (m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, 0);
- sqlite3_bind_text(stmt, 1, dataName.toUri().c_str(), dataName.toUri().size(), SQLITE_TRANSIENT);
-
- if(sqlite3_step (stmt) == SQLITE_ROW)
- {
- shared_ptr<Data> data = make_shared<Data>();
- data->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
- sqlite3_finalize(stmt);
- return data;
- }
- sqlite3_finalize(stmt);
-
- return shared_ptr<Data>();
-}
-
-}//chronos
diff --git a/src/dns-storage.h b/src/dns-storage.h
deleted file mode 100644
index 89d3876..0000000
--- a/src/dns-storage.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef CHRONOS_DNS_STORAGE_H
-#define CHRONOS_DNS_STORAGE_H
-
-#include "config.h"
-#include <sqlite3.h>
-#include <ndn-cpp-dev/data.hpp>
-
-namespace chronos{
-
-class DnsStorage
-{
-public:
- struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
-
- DnsStorage();
-
- ~DnsStorage()
- { sqlite3_close(m_db); }
-
- void
- updateDnsSelfProfileData(const ndn::Data& data, const ndn::Name& identity)
- { updateDnsData(data.wireEncode(), identity.toUri(), "N/A", "PROFILE", data.getName().toUri()); }
-
- void
- updateDnsEndorseOthers(const ndn::Data& data, const ndn::Name& identity, const ndn::Name& endorsee)
- { updateDnsData(data.wireEncode(), identity.toUri(), endorsee.toUri(), "ENDORSEE", data.getName().toUri()); }
-
- void
- updateDnsOthersEndorse(const ndn::Data& data, const ndn::Name& identity)
- { updateDnsData(data.wireEncode(), identity.toUri(), "N/A", "ENDORSED", data.getName().toUri()); }
-
- ndn::ptr_lib::shared_ptr<ndn::Data>
- getData(const ndn::Name& name);
-
-private:
- void
- updateDnsData(const ndn::Block& data, const std::string& identity, const std::string& name, const std::string& type, const std::string& dataName);
-
-private:
- sqlite3 *m_db;
-};
-
-}//chronos
-
-#endif
diff --git a/src/endorse-certificate.cpp b/src/endorse-certificate.cpp
index 21f5053..3d1f298 100644
--- a/src/endorse-certificate.cpp
+++ b/src/endorse-certificate.cpp
@@ -11,19 +11,17 @@
#include "endorse-certificate.h"
#include "endorse-extension.pb.h"
#include <boost/iostreams/stream.hpp>
-#include "logging.h"
using namespace std;
using namespace ndn;
-
-INIT_LOGGER("EndorseCertificate");
-
namespace chronos{
const OID EndorseCertificate::PROFILE_EXT_OID("1.3.6.1.5.32.2.1");
const OID EndorseCertificate::ENDORSE_EXT_OID("1.3.6.1.5.32.2.2");
+const std::vector<std::string> EndorseCertificate::DEFAULT_ENDORSE_LIST = std::vector<std::string>();
+
Chronos::EndorseExtensionMsg&
operator << (Chronos::EndorseExtensionMsg& endorseExtension, const vector<string>& endorseList)
{
@@ -106,6 +104,41 @@
encode();
}
+EndorseCertificate::EndorseCertificate(const Name& keyName,
+ const PublicKey& key,
+ MillisecondsSince1970 notBefore,
+ MillisecondsSince1970 notAfter,
+ const Name& signer,
+ const Profile& profile,
+ const vector<string>& endorseList)
+ : Certificate()
+ , m_keyName(keyName)
+ , m_signer(signer)
+ , m_profile(profile)
+ , m_endorseList(endorseList)
+{
+ Name dataName = m_keyName;
+ dataName.append("PROFILE-CERT").append(m_signer.wireEncode()).appendVersion();
+ setName(dataName);
+
+ setNotBefore(notBefore);
+ setNotAfter(notAfter);
+ addSubjectDescription(CertificateSubjectDescription("2.5.4.41", m_keyName.toUri()));
+ setPublicKeyInfo(key);
+
+ OBufferStream profileStream;
+ m_profile.encode(profileStream);
+ addExtension(CertificateExtension(PROFILE_EXT_OID, true, *profileStream.buf()));
+
+ OBufferStream endorseStream;
+ Chronos::EndorseExtensionMsg endorseExtension;
+ endorseExtension << m_endorseList;
+ endorseExtension.SerializeToOstream(&endorseStream);
+ addExtension(CertificateExtension(ENDORSE_EXT_OID, true, *endorseStream.buf()));
+
+ encode();
+}
+
EndorseCertificate::EndorseCertificate(const EndorseCertificate& endorseCertificate)
: Certificate(endorseCertificate)
, m_keyName(endorseCertificate.m_keyName)
diff --git a/src/endorse-certificate.h b/src/endorse-certificate.h
index 7352a4d..42f255f 100644
--- a/src/endorse-certificate.h
+++ b/src/endorse-certificate.h
@@ -24,15 +24,25 @@
public:
struct Error : public ndn::Certificate::Error { Error(const std::string &what) : ndn::Certificate::Error(what) {} };
+ static const std::vector<std::string> DEFAULT_ENDORSE_LIST;
+
EndorseCertificate() {}
EndorseCertificate(const ndn::IdentityCertificate& kskCertificate,
const Profile& profile,
- const std::vector<std::string>& endorseList = std::vector<std::string>());
+ const std::vector<std::string>& endorseList = DEFAULT_ENDORSE_LIST);
EndorseCertificate(const EndorseCertificate& endorseCertificate,
const ndn::Name& signer,
- const std::vector<std::string>& endorseList);
+ const std::vector<std::string>& endorseList = DEFAULT_ENDORSE_LIST);
+
+ EndorseCertificate(const ndn::Name& keyName,
+ const ndn::PublicKey& key,
+ ndn::MillisecondsSince1970 notBefore,
+ ndn::MillisecondsSince1970 notAfter,
+ const ndn::Name& signer,
+ const Profile& profile,
+ const std::vector<std::string>& endorseList = DEFAULT_ENDORSE_LIST);
EndorseCertificate(const EndorseCertificate& endorseCertificate);
@@ -63,7 +73,7 @@
static const ndn::OID ENDORSE_EXT_OID;
ndn::Name m_keyName;
- ndn::Name m_signer;
+ ndn::Name m_signer; // signing key name
Profile m_profile;
std::vector<std::string> m_endorseList;
};
diff --git a/src/endorse-collection.proto b/src/endorse-collection.proto
index d3aa574..7aa1af8 100644
--- a/src/endorse-collection.proto
+++ b/src/endorse-collection.proto
@@ -1,10 +1,11 @@
-package Chronos;
+package chronos;
message EndorseCollection
{
message Endorsement
{
- required string blob = 1;
+ required string certname = 1;
+ required string hash = 2;
}
repeated Endorsement endorsement = 1;
}
\ No newline at end of file
diff --git a/src/endorse-info.proto b/src/endorse-info.proto
new file mode 100644
index 0000000..a0612d0
--- /dev/null
+++ b/src/endorse-info.proto
@@ -0,0 +1,12 @@
+package chronos;
+
+message EndorseInfo
+{
+ message Endorsement
+ {
+ required string type = 1;
+ required string value = 2;
+ required string endorse = 3;
+ }
+ repeated Endorsement endorsement = 1;
+}
\ No newline at end of file
diff --git a/src/intro-cert-list.proto b/src/intro-cert-list.proto
new file mode 100644
index 0000000..6b65a83
--- /dev/null
+++ b/src/intro-cert-list.proto
@@ -0,0 +1,6 @@
+package Chronos;
+
+message IntroCertListMsg
+{
+ repeated string certname = 1;
+}
\ No newline at end of file
diff --git a/src/invitation-dialog.cpp b/src/invitation-dialog.cpp
new file mode 100644
index 0000000..8be49fc
--- /dev/null
+++ b/src/invitation-dialog.cpp
@@ -0,0 +1,68 @@
+/* -*- 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 "invitation-dialog.h"
+#include "ui_invitation-dialog.h"
+
+using namespace std;
+using namespace ndn;
+
+InvitationDialog::InvitationDialog(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::InvitationDialog)
+{
+ ui->setupUi(this);
+
+ connect(ui->okButton, SIGNAL(clicked()),
+ this, SLOT(onOkClicked()));
+ connect(ui->cancelButton, SIGNAL(clicked()),
+ this, SLOT(onCancelClicked()));
+}
+
+InvitationDialog::~InvitationDialog()
+{
+ delete ui;
+}
+
+void
+InvitationDialog::setInvitation(const string& alias,
+ const string& chatroom,
+ const Name& interestName)
+{
+ string msg = alias;
+ msg.append(" invites you to: ").append(chatroom);
+ ui->msgLabel->setText(QString::fromStdString(msg));
+}
+
+void
+InvitationDialog::onOkClicked()
+{
+ emit invitationResponded(m_invitationInterest, true);
+ this->close();
+
+ ui->msgLabel->clear();
+ m_invitationInterest.clear();
+}
+
+void
+InvitationDialog::onCancelClicked()
+{
+ emit invitationResponded(m_invitationInterest, false);
+ this->close();
+
+ ui->msgLabel->clear();
+ m_invitationInterest.clear();
+}
+
+#if WAF
+#include "invitation-dialog.moc"
+#include "invitation-dialog.cpp.moc"
+#endif
diff --git a/src/invitationdialog.h b/src/invitation-dialog.h
similarity index 68%
rename from src/invitationdialog.h
rename to src/invitation-dialog.h
index 8edc04d..0112185 100644
--- a/src/invitationdialog.h
+++ b/src/invitation-dialog.h
@@ -8,15 +8,13 @@
* Author: Yingdi Yu <yingdi@cs.ucla.edu>
*/
-#ifndef INVITATIONDIALOG_H
-#define INVITATIONDIALOG_H
+#ifndef INVITATION_DIALOG_H
+#define INVITATION_DIALOG_H
#include <QDialog>
#ifndef Q_MOC_RUN
-#include <ndn-cpp-dev/data.hpp>
-#include <ndn-cpp-dev/security/identity-certificate.hpp>
-#include "invitation.h"
+#include <ndn-cpp-dev/name.hpp>
#endif
namespace Ui {
@@ -33,14 +31,12 @@
void
setInvitation(const std::string& alias,
+ const std::string& chatroom,
const ndn::Name& invitationInterest);
signals:
void
- invitationAccepted(const ndn::Name& invitationInterest);
-
- void
- invitationRejected(const ndn::Name& invitationInterest);
+ invitationResponded(const ndn::Name& invitationName, bool accepted);
private slots:
void
@@ -52,8 +48,7 @@
private:
Ui::InvitationDialog *ui;
- std::string m_inviterAlias;
ndn::Name m_invitationInterest;
};
-#endif // INVITATIONDIALOG_H
+#endif // INVITATION_DIALOG_H
diff --git a/src/invitation-dialog.ui b/src/invitation-dialog.ui
new file mode 100644
index 0000000..ec8e9f6
--- /dev/null
+++ b/src/invitation-dialog.ui
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InvitationDialog</class>
+ <widget class="QDialog" name="InvitationDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="5,1">
+ <property name="leftMargin">
+ <number>10</number>
+ </property>
+ <property name="topMargin">
+ <number>10</number>
+ </property>
+ <property name="rightMargin">
+ <number>10</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="msgLabel">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="buttonLayout" stretch="1,1">
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Reject</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="okButton">
+ <property name="text">
+ <string>Accept</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/invitation.cpp b/src/invitation.cpp
index 9495cec..4aa3358 100644
--- a/src/invitation.cpp
+++ b/src/invitation.cpp
@@ -23,14 +23,14 @@
namespace chronos{
-const size_t Invitation::NAME_SIZE_MIN = 9;
-const size_t Invitation::INVITEE_START = 4;
-const ssize_t Invitation::SIGNATURE = -1;
-const ssize_t Invitation::KEY_LOCATOR = -2;
-const ssize_t Invitation::TIMESTAMP = -3;
-const ssize_t Invitation::INVITER_PREFIX = -4;
-const ssize_t Invitation::CHATROOM = -5;
-const Name Invitation::INVITATION_PREFIX("/ndn/broadcast/chronos/chat-invitation");
+const size_t Invitation::NAME_SIZE_MIN = 7;
+const ssize_t Invitation::SIGNATURE = -1;
+const ssize_t Invitation::KEY_LOCATOR = -2;
+const ssize_t Invitation::TIMESTAMP = -3;
+const ssize_t Invitation::INVITER_CERT = -4;
+const ssize_t Invitation::INVITER_PREFIX = -5;
+const ssize_t Invitation::CHATROOM = -6;
+const ssize_t Invitation::CHRONOCHAT_INVITATION = -7;
Invitation::Invitation(const Name& interestName)
@@ -39,25 +39,34 @@
if(nameSize < NAME_SIZE_MIN)
throw Error("Wrong Invitation Name: Wrong length");
-
- if(!INVITATION_PREFIX.isPrefixOf(interestName))
- throw Error("Wrong Invitation Name: Wrong invitation prefix");
- m_interestName = interestName.getPrefix(-3);
+ if(interestName.get(CHRONOCHAT_INVITATION).toEscapedString() != "CHRONOCHAT-INVITATION")
+ throw Error("Wrong Invitation Name: Wrong application tags");
+
+ m_interestName = interestName.getPrefix(KEY_LOCATOR);
+ m_timestamp = interestName.get(TIMESTAMP).toNumber();
+ m_inviterCertificate.wireDecode(interestName.get(INVITER_CERT).blockFromValue());
m_inviterRoutingPrefix.wireDecode(interestName.get(INVITER_PREFIX).blockFromValue());
- m_chatroom.wireDecode(interestName.get(CHATROOM).blockFromValue());
- m_inviteeNameSpace = interestName.getSubName(INVITEE_START, nameSize - NAME_SIZE_MIN);
+ m_chatroom = interestName.get(CHATROOM).toEscapedString();
+ m_inviteeNameSpace = interestName.getPrefix(CHRONOCHAT_INVITATION);
}
-Invitation::Invitation(const Name &inviteeNameSpace,
- const Name &chatroom,
- const Name &inviterRoutingPrefix)
+Invitation::Invitation(const Name& inviteeNameSpace,
+ const string& chatroom,
+ const Name& inviterRoutingPrefix,
+ const IdentityCertificate& inviterCertificate)
: m_inviteeNameSpace(inviteeNameSpace)
, m_chatroom(chatroom)
, m_inviterRoutingPrefix(inviterRoutingPrefix)
-{
- m_interestName = INVITATION_PREFIX;
- m_interestName.append(inviteeNameSpace).append(chatroom.wireEncode()).append(inviterRoutingPrefix.wireEncode());
+ , m_inviterCertificate(inviterCertificate)
+ , m_timestamp(time::now())
+{
+ m_interestName = m_inviteeNameSpace;
+ m_interestName.append("CHRONOCHAT-INVITATION")
+ .append(m_chatroom)
+ .append(m_inviterRoutingPrefix.wireEncode())
+ .append(m_inviterCertificate.wireEncode())
+ .append(name::Component::fromNumber(m_timestamp));
}
Invitation::Invitation(const Invitation& invitation)
@@ -65,6 +74,9 @@
, m_inviteeNameSpace(invitation.m_inviteeNameSpace)
, m_chatroom(invitation.m_chatroom)
, m_inviterRoutingPrefix(invitation.m_inviterRoutingPrefix)
-{}
+ , m_inviterCertificate(invitation.m_inviterCertificate)
+ , m_timestamp(invitation.m_timestamp)
+{
+}
}//chronos
diff --git a/src/invitation.h b/src/invitation.h
index ba850ac..d002402 100644
--- a/src/invitation.h
+++ b/src/invitation.h
@@ -14,33 +14,42 @@
#include <ndn-cpp-dev/name.hpp>
#include <ndn-cpp-dev/signature.hpp>
+#include <ndn-cpp-dev/security/identity-certificate.hpp>
namespace chronos{
class Invitation
{
-/*
- * /ndn/broadcast/chronos/invitation/[invitee_namespace]/<chatroom_name>/<inviter_routing_prefix>/<timestamp>/<keylocator>/<signature>
- */
+ public:
+ /*
+ * /[invitee_namespace]
+ * /CHRONOCHAT-INVITATION
+ * /<chatroom_name>
+ * /<inviter_routing_prefix>
+ * /<inviter_cert>
+ * /<timestamp>
+ * /<keylocator>
+ * /<signature>
+ */
static const size_t NAME_SIZE_MIN;
- static const size_t INVITEE_START;
static const ssize_t SIGNATURE;
static const ssize_t KEY_LOCATOR;
static const ssize_t TIMESTAMP;
+ static const ssize_t INVITER_CERT;
static const ssize_t INVITER_PREFIX;
static const ssize_t CHATROOM;
- static const ndn::Name INVITATION_PREFIX;
+ static const ssize_t CHRONOCHAT_INVITATION;
-public:
struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
Invitation() {}
Invitation(const ndn::Name& interestName);
- Invitation(const ndn::Name &inviteeNameSpace,
- const ndn::Name &chatroom,
- const ndn::Name &inviterRoutingPrefix);
+ Invitation(const ndn::Name& inviteeNameSpace,
+ const std::string& chatroom,
+ const ndn::Name& inviterRoutingPrefix,
+ const ndn::IdentityCertificate& inviterCertificate);
Invitation(const Invitation& invitation);
@@ -51,13 +60,21 @@
getInviteeNameSpace() const
{ return m_inviteeNameSpace; }
- const ndn::Name&
+ const std::string&
getChatroom() const
{ return m_chatroom; }
const ndn::Name&
getInviterRoutingPrefix() const
{ return m_inviterRoutingPrefix; }
+
+ const ndn::IdentityCertificate&
+ getInviterCertificate() const
+ { return m_inviterCertificate; }
+
+ const uint64_t
+ getTimestamp() const
+ { return m_timestamp; }
const ndn::Name&
getUnsignedInterestName() const
@@ -67,8 +84,10 @@
ndn::Name m_interestName;
ndn::Name m_inviteeNameSpace;
- ndn::Name m_chatroom;
+ std::string m_chatroom;
ndn::Name m_inviterRoutingPrefix;
+ ndn::IdentityCertificate m_inviterCertificate;
+ uint64_t m_timestamp;
};
}//chronos
diff --git a/src/invitationdialog.cpp b/src/invitationdialog.cpp
deleted file mode 100644
index 2a1d21f..0000000
--- a/src/invitationdialog.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- 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 "invitationdialog.h"
-#include "ui_invitationdialog.h"
-
-using namespace std;
-using namespace ndn;
-using namespace chronos;
-
-InvitationDialog::InvitationDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::InvitationDialog)
-{
- ui->setupUi(this);
-
- connect(ui->okButton, SIGNAL(clicked()),
- this, SLOT(onOkClicked()));
- connect(ui->cancelButton, SIGNAL(clicked()),
- this, SLOT(onCancelClicked()));
-}
-
-InvitationDialog::~InvitationDialog()
-{
- delete ui;
-}
-
-void
-InvitationDialog::setInvitation(const string& alias,
- const Name& interestName)
-{
- m_inviterAlias = alias;
- string msg = alias;
- msg.append("\ninvites you to join the chat room: ");
- ui->msgLabel->setText(QString::fromStdString(msg));
-
- m_invitationInterest = interestName;
- Invitation invitation(interestName);
- ui->chatroomLine->setText(QString::fromStdString(invitation.getChatroom().get(0).toEscapedString()));
-}
-
-void
-InvitationDialog::onOkClicked()
-{
- emit invitationAccepted(m_invitationInterest);
- this->close();
-}
-
-void
-InvitationDialog::onCancelClicked()
-{
- ui->msgLabel->clear();
- ui->chatroomLine->clear();
-
- emit invitationRejected(m_invitationInterest);
-
- m_invitationInterest.clear();
- m_inviterAlias.clear();
-
- this->close();
-}
-
-#if WAF
-#include "invitationdialog.moc"
-#include "invitationdialog.cpp.moc"
-#endif
diff --git a/src/invitationdialog.ui b/src/invitationdialog.ui
deleted file mode 100644
index 0348293..0000000
--- a/src/invitationdialog.ui
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>InvitationDialog</class>
- <widget class="QDialog" name="InvitationDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>200</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <widget class="QLabel" name="msgLabel">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>30</y>
- <width>240</width>
- <height>50</height>
- </rect>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- <widget class="QLineEdit" name="chatroomLine">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>100</y>
- <width>241</width>
- <height>21</height>
- </rect>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- </widget>
- <widget class="QPushButton" name="cancelButton">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>150</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>Reject</string>
- </property>
- </widget>
- <widget class="QPushButton" name="okButton">
- <property name="geometry">
- <rect>
- <x>170</x>
- <y>150</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>Accept</string>
- </property>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/invite-list-dialog.cpp b/src/invite-list-dialog.cpp
new file mode 100644
index 0000000..c46036f
--- /dev/null
+++ b/src/invite-list-dialog.cpp
@@ -0,0 +1,85 @@
+/* -*- 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 "invite-list-dialog.h"
+#include "ui_invite-list-dialog.h"
+
+using namespace std;
+
+InviteListDialog::InviteListDialog(QWidget *parent)
+ :QDialog(parent)
+ , ui(new Ui::InviteListDialog)
+ , m_contactListModel(new QStringListModel)
+{
+ ui->setupUi(this);
+
+ ui->contactListView->setModel(m_contactListModel);
+
+ connect(ui->inviteButton, SIGNAL(clicked()),
+ this, SLOT(onInviteClicked()));
+ connect(ui->cancelButton, SIGNAL(clicked()),
+ this, SLOT(onCancelClicked()));
+}
+
+InviteListDialog::~InviteListDialog()
+{
+ delete ui;
+ delete m_contactListModel;
+}
+
+void
+InviteListDialog::setInviteLabel(string label)
+{
+ string msg("invite to chatroom:\n");
+ msg += label;
+ ui->inviteLabel->setText(QString::fromStdString(msg));
+}
+
+void
+InviteListDialog::onInviteClicked()
+{
+ QModelIndexList selected = ui->contactListView->selectionModel()->selectedIndexes();
+ QString alias = m_contactListModel->data(selected.first(), Qt::DisplayRole).toString();
+
+ for(int i = 0; i < m_contactAliasList.size(); i++) // TODO:: could be optimized without using for loop.
+ {
+ if(alias == m_contactAliasList[i])
+ {
+ emit sendInvitation(m_contactIdList[i]);
+ break;
+ }
+ }
+
+ this->close();
+}
+
+void
+InviteListDialog::onCancelClicked()
+{
+ this->close();
+}
+
+void
+InviteListDialog::onContactAliasListReady(const QStringList& aliasList)
+{
+ m_contactAliasList = aliasList;
+ m_contactListModel->setStringList(m_contactAliasList);
+}
+
+void
+InviteListDialog::onContactIdListReady(const QStringList& idList)
+{
+ m_contactIdList = idList;
+}
+
+#if WAF
+#include "invite-list-dialog.moc"
+#include "invite-list-dialog.cpp.moc"
+#endif
diff --git a/src/invite-list-dialog.h b/src/invite-list-dialog.h
new file mode 100644
index 0000000..f5144fc
--- /dev/null
+++ b/src/invite-list-dialog.h
@@ -0,0 +1,62 @@
+/* -*- 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>
+ */
+
+#ifndef INVITE_LIST_DIALOG_H
+#define INVITE_LIST_DIALOG_H
+
+#include <QDialog>
+#include <QStringListModel>
+
+#ifndef Q_MOC_RUN
+#endif
+
+namespace Ui {
+class InviteListDialog;
+}
+
+class InviteListDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit
+ InviteListDialog(QWidget *parent = 0);
+
+ ~InviteListDialog();
+
+ void
+ setInviteLabel(std::string label);
+
+signals:
+ void
+ sendInvitation(const QString&);
+
+public slots:
+ void
+ onContactAliasListReady(const QStringList& aliasList);
+
+ void
+ onContactIdListReady(const QStringList& idList);
+
+private slots:
+ void
+ onInviteClicked();
+
+ void
+ onCancelClicked();
+
+private:
+ Ui::InviteListDialog *ui;
+ QStringListModel* m_contactListModel;
+ QStringList m_contactAliasList;
+ QStringList m_contactIdList;
+};
+
+#endif // INVITE_LIST_DIALOG_H
diff --git a/src/invite-list-dialog.ui b/src/invite-list-dialog.ui
new file mode 100644
index 0000000..157c9e3
--- /dev/null
+++ b/src/invite-list-dialog.ui
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InviteListDialog</class>
+ <widget class="QDialog" name="InviteListDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>400</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="4,20,2">
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="inviteLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListView" name="contactListView"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="inviteButton">
+ <property name="text">
+ <string>Invite</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/invitelistdialog.cpp b/src/invitelistdialog.cpp
deleted file mode 100644
index 50fa50f..0000000
--- a/src/invitelistdialog.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- 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 "invitelistdialog.h"
-#include "ui_invitelistdialog.h"
-
-using namespace std;
-using namespace chronos;
-
-InviteListDialog::InviteListDialog(ndn::shared_ptr<ContactManager> contactManager,
- QWidget *parent)
- :QDialog(parent)
- , ui(new Ui::InviteListDialog)
- , m_contactManager(contactManager)
- , m_contactListModel(new QStringListModel)
-{
- ui->setupUi(this);
-
- refreshContactList();
-
- ui->contactListView->setModel(m_contactListModel);
-
- connect(ui->inviteButton, SIGNAL(clicked()),
- this, SLOT(inviteWrapper()));
- connect(ui->cancelButton, SIGNAL(clicked()),
- this, SLOT(onCancelClicked()));
-}
-
-InviteListDialog::~InviteListDialog()
-{
- delete ui;
- delete m_contactListModel;
-}
-
-void
-InviteListDialog::setInviteLabel(string label)
-{
- string msg("invite to chatroom:\n");
- msg += label;
- ui->inviteLabel->setText(QString::fromStdString(msg));
- refreshContactList();
-}
-
-void
-InviteListDialog::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
-InviteListDialog::inviteWrapper()
-{
- QModelIndexList selected = ui->contactListView->selectionModel()->selectedIndexes();
- QString text = m_contactListModel->data(selected.first(), Qt::DisplayRole).toString();
- string alias = text.toStdString();
-
- int i = 0;
- for(; i < m_contactList.size(); i++)
- {
- if(alias == m_contactList[i]->getAlias())
- break;
- }
-
- QString invitedContactNamespace = QString::fromStdString(m_contactList[i]->getNameSpace().toUri());
-
- bool isIntroducer = true;
-
- emit invitionDetermined(invitedContactNamespace, isIntroducer);
-
- this->close();
-}
-
-void
-InviteListDialog::onCancelClicked()
-{ this->close(); }
-
-#if WAF
-#include "invitelistdialog.moc"
-#include "invitelistdialog.cpp.moc"
-#endif
diff --git a/src/invitelistdialog.h b/src/invitelistdialog.h
deleted file mode 100644
index 83e1b50..0000000
--- a/src/invitelistdialog.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef INVITELISTDIALOG_H
-#define INVITELISTDIALOG_H
-
-#include <QDialog>
-#include <QStringListModel>
-
-#ifndef Q_MOC_RUN
-#include "contact-manager.h"
-#endif
-
-namespace Ui {
-class InviteListDialog;
-}
-
-class InviteListDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit InviteListDialog(ndn::shared_ptr<chronos::ContactManager> contactManager,
- QWidget *parent = 0);
- ~InviteListDialog();
-
- void
- setInviteLabel(std::string label);
-
-signals:
- void
- invitionDetermined(QString, bool);
-
-private slots:
- void
- refreshContactList();
-
- void
- inviteWrapper();
-
- void
- onCancelClicked();
-
-private:
- Ui::InviteListDialog *ui;
- ndn::shared_ptr<chronos::ContactManager> m_contactManager;
- QStringListModel* m_contactListModel;
- std::vector<ndn::shared_ptr<chronos::ContactItem> > m_contactList;
- std::vector<std::string> m_invitedContacts;
-};
-
-#endif // INVITELISTDIALOG_H
diff --git a/src/invitelistdialog.ui b/src/invitelistdialog.ui
deleted file mode 100644
index 71c0fe3..0000000
--- a/src/invitelistdialog.ui
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>InviteListDialog</class>
- <widget class="QDialog" name="InviteListDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>400</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>281</width>
- <height>381</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout" stretch="4,1,20,2">
- <property name="spacing">
- <number>10</number>
- </property>
- <item>
- <widget class="QLabel" name="inviteLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="isIntroducer">
- <property name="text">
- <string>as introducer</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <property name="tristate">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QListView" name="contactListView"/>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QPushButton" name="cancelButton">
- <property name="text">
- <string>Cancel</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="inviteButton">
- <property name="text">
- <string>Invite</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/main.cpp b/src/main.cpp
index 030ba43..009f761 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -9,12 +9,9 @@
*/
#include <QApplication>
-#include <QSystemTrayIcon>
+// #include <QSystemTrayIcon>
-#include "contactpanel.h"
-#include "contact-storage.h"
-#include "dns-storage.h"
-#include "contact-manager.h"
+#include "controller.h"
#include "logging.h"
#include <ndn-cpp-dev/face.hpp>
#include <boost/thread/thread.hpp>
@@ -57,11 +54,9 @@
NewApp app(argc, argv);
shared_ptr<Face> face = make_shared<Face>();
- ContactPanel contactPanel(face);
+ chronos::Controller controller(face);
- contactPanel.show ();
- contactPanel.activateWindow ();
- contactPanel.raise ();
+ app.setQuitOnLastWindowClosed(false);
boost::thread (runIO, face->ioService());
diff --git a/src/profile-data.cpp b/src/profile-data.cpp
deleted file mode 100644
index 98ce957..0000000
--- a/src/profile-data.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- 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 "profile-data.h"
-
-#include "logging.h"
-
-using namespace ndn;
-using namespace std;
-
-INIT_LOGGER("ProfileData");
-
-namespace chronos{
-
-ProfileData::ProfileData()
- : Data()
-{}
-
-ProfileData::ProfileData(const Profile& profile)
- : Data()
- , m_identity(profile.getIdentityName())
- , m_profile(profile)
-{
- Name dataName = m_identity;
- dataName.append("PROFILE").appendVersion();
- setName(dataName);
-
- OBufferStream os;
- profile.encode(os);
- setContent(os.buf());
-}
-
-ProfileData::ProfileData(const Data& data)
- : Data(data)
-{
- if(data.getName().get(-2).toEscapedString() == "PROFILE")
- throw Error("No PROFILE component in data name!");
-
- m_identity = data.getName().getPrefix(-2);
-
- boost::iostreams::stream <boost::iostreams::array_source> is
- (reinterpret_cast<const char*>(data.getContent().value()), data.getContent().value_size());
-
- m_profile.decode(is);
-}
-
-}//chronos
diff --git a/src/profile-data.h b/src/profile-data.h
deleted file mode 100644
index 47fe910..0000000
--- a/src/profile-data.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef CHRONOS_PROFILE_DATA_H
-#define CHRONOS_PROFILE_DATA_H
-
-#include "profile.h"
-#include <ndn-cpp-dev/data.hpp>
-
-
-namespace chronos{
-
-class ProfileData : public ndn::Data
-{
-public:
- struct Error : public ndn::Data::Error { Error(const std::string &what) : ndn::Data::Error(what) {} };
-
- ProfileData();
-
- ProfileData(const Profile& profile);
-
- ProfileData(const ndn::Data& data);
-
- ~ProfileData() {}
-
- const ndn::Name&
- getIdentityName() const
- { return m_identity; }
-
- const Profile&
- getProfile() const
- { return m_profile; }
-
-private:
- ndn::Name m_identity;
- Profile m_profile;
-};
-
-}//chronos
-
-#endif
diff --git a/src/profile-editor.cpp b/src/profile-editor.cpp
new file mode 100644
index 0000000..ac5dcbf
--- /dev/null
+++ b/src/profile-editor.cpp
@@ -0,0 +1,108 @@
+/* -*- 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 "profile-editor.h"
+#include "ui_profile-editor.h"
+#include <QtSql/QSqlRecord>
+#include <QtSql/QSqlField>
+#include <QtSql/QSqlError>
+
+#ifndef Q_MOC_RUN
+#include "logging.h"
+#endif
+
+INIT_LOGGER("ProfileEditor")
+
+using namespace std;
+
+ProfileEditor::ProfileEditor(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::ProfileEditor)
+ , m_tableModel(new QSqlTableModel())
+{
+ ui->setupUi(this);
+
+ connect(ui->addRowButton, SIGNAL(clicked()),
+ this, SLOT(onAddClicked()));
+ connect(ui->deleteRowButton, SIGNAL(clicked()),
+ this, SLOT(onDeleteClicked()));
+ connect(ui->okButton, SIGNAL(clicked()),
+ this, SLOT(onOkClicked()));
+}
+
+ProfileEditor::~ProfileEditor()
+{
+ delete ui;
+ delete m_tableModel;
+}
+
+void
+ProfileEditor::onCloseDBModule()
+{
+ _LOG_DEBUG("close db module");
+ if(m_tableModel)
+ {
+ delete m_tableModel;
+ _LOG_DEBUG("tableModel closed");
+ }
+}
+
+void
+ProfileEditor::onIdentityUpdated(const QString& identity)
+{
+ m_tableModel = new QSqlTableModel();
+
+ m_identity = identity;
+ ui->identityInput->setText(identity);
+
+ m_tableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
+ m_tableModel->setTable("SelfProfile");
+ m_tableModel->select();
+ m_tableModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Type"));
+ m_tableModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Value"));
+
+ ui->profileTable->setModel(m_tableModel);
+ ui->profileTable->show();
+}
+
+void
+ProfileEditor::onAddClicked()
+{
+ int rowCount = m_tableModel->rowCount();
+ QSqlRecord record;
+ m_tableModel->insertRow(rowCount);
+ m_tableModel->setRecord(rowCount, record);
+}
+
+void
+ProfileEditor::onDeleteClicked()
+{
+ QItemSelectionModel* selectionModel = ui->profileTable->selectionModel();
+ QModelIndexList indexList = selectionModel->selectedIndexes();
+
+ int i = indexList.size() - 1;
+ for(; i >= 0; i--)
+ m_tableModel->removeRow(indexList[i].row());
+
+ m_tableModel->submitAll();
+}
+
+void
+ProfileEditor::onOkClicked()
+{
+ m_tableModel->submitAll();
+ emit updateProfile();
+ this->hide();
+}
+
+#if WAF
+#include "profile-editor.moc"
+#include "profile-editor.cpp.moc"
+#endif
diff --git a/src/profile-editor.h b/src/profile-editor.h
new file mode 100644
index 0000000..24c7aa2
--- /dev/null
+++ b/src/profile-editor.h
@@ -0,0 +1,60 @@
+/* -*- 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>
+ */
+
+#ifndef PROFILE_EDITOR_H
+#define PROFILE_EDITOR_H
+
+#include <QDialog>
+#include <QtSql/QSqlTableModel>
+
+#ifndef Q_MOC_RUN
+#endif
+
+namespace Ui {
+class ProfileEditor;
+}
+
+class ProfileEditor : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit ProfileEditor(QWidget *parent = 0);
+
+ ~ProfileEditor();
+
+public slots:
+ void
+ onCloseDBModule();
+
+ void
+ onIdentityUpdated(const QString& identity);
+
+private slots:
+ void
+ onAddClicked();
+
+ void
+ onDeleteClicked();
+
+ void
+ onOkClicked();
+
+signals:
+ void
+ updateProfile();
+
+private:
+ Ui::ProfileEditor *ui;
+ QSqlTableModel* m_tableModel;
+ QString m_identity;
+};
+
+#endif // PROFILE_EDITOR_H
diff --git a/src/profile-editor.ui b/src/profile-editor.ui
new file mode 100644
index 0000000..b555d43
--- /dev/null
+++ b/src/profile-editor.ui
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProfileEditor</class>
+ <widget class="QDialog" name="ProfileEditor">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>500</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Profile Editor</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="profileEditorLayout" stretch="0,20,1">
+ <item>
+ <layout class="QHBoxLayout" name="identityLayout" stretch="2,4">
+ <item>
+ <widget class="QLabel" name="identityLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Current identity:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="identityInput">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTableView" name="profileTable">
+ <attribute name="horizontalHeaderCascadingSectionResizes">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="horizontalHeaderDefaultSectionSize">
+ <number>100</number>
+ </attribute>
+ <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>true</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="buttonLayout" stretch="1,1,1">
+ <item>
+ <widget class="QPushButton" name="addRowButton">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deleteRowButton">
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="okButton">
+ <property name="text">
+ <string>OK</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/profile.h b/src/profile.h
index e085e77..982c5d8 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -83,6 +83,9 @@
inline bool
operator == (const Profile& profile) const;
+ inline bool
+ operator != (const Profile& profile) const;
+
private:
static const std::string OID_NAME;
static const std::string OID_ORG;
@@ -100,7 +103,7 @@
Chronos::ProfileMsg&
operator >> (Chronos::ProfileMsg& msg, Profile& profile);
-bool
+inline bool
Profile::operator == (const Profile& profile) const
{
if(m_entries.size() != profile.m_entries.size())
@@ -119,6 +122,12 @@
return true;
}
+inline bool
+Profile::operator != (const Profile& profile) const
+{
+ return !(*this == profile);
+}
+
}//chronos
#endif
diff --git a/src/profile.proto b/src/profile.proto
index e9b15e8..586c5c0 100644
--- a/src/profile.proto
+++ b/src/profile.proto
@@ -7,5 +7,5 @@
required string oid = 1;
required string data = 2;
}
- repeated ProfileEntry entry = 2;
+ repeated ProfileEntry entry = 1;
}
\ No newline at end of file
diff --git a/src/profileeditor.cpp b/src/profileeditor.cpp
deleted file mode 100644
index 17931d0..0000000
--- a/src/profileeditor.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- 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 "profileeditor.h"
-#include "ui_profileeditor.h"
-#include <QtSql/QSqlRecord>
-#include <QtSql/QSqlField>
-#include <QtSql/QSqlError>
-
-#ifndef Q_MOC_RUN
-#include "logging.h"
-#endif
-
-using namespace ndn;
-using namespace std;
-using namespace chronos;
-
-INIT_LOGGER("ProfileEditor");
-
-ProfileEditor::ProfileEditor(shared_ptr<ContactManager> contactManager,
- QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::ProfileEditor)
- , m_tableModel(new QSqlTableModel())
- , m_contactManager(contactManager)
- , m_keyChain(new KeyChain())
-{
- ui->setupUi(this);
-
- m_currentIdentity = contactManager->getDefaultIdentity();
- ui->identityInput->setText(m_currentIdentity.toUri().c_str());
-
- connect(ui->addRowButton, SIGNAL(clicked()),
- this, SLOT(onAddClicked()));
- connect(ui->deleteRowButton, SIGNAL(clicked()),
- this, SLOT(onDeleteClicked()));
- connect(ui->okButton, SIGNAL(clicked()),
- this, SLOT(onOkClicked()));
- connect(ui->getButton, SIGNAL(clicked()),
- this, SLOT(onGetClicked()));
-
-
-
-}
-
-ProfileEditor::~ProfileEditor()
-{
- delete ui;
- delete m_tableModel;
-}
-
-void
-ProfileEditor::onAddClicked()
-{
- int rowCount = m_tableModel->rowCount();
- QSqlRecord record;
- QSqlField identityField("profile_identity", QVariant::String);
- record.append(identityField);
- record.setValue("profile_identity", QString(m_currentIdentity.toUri().c_str()));
- m_tableModel->insertRow(rowCount);
- m_tableModel->setRecord(rowCount, record);
-}
-
-void
-ProfileEditor::onDeleteClicked()
-{
- QItemSelectionModel* selectionModel = ui->profileTable->selectionModel();
- QModelIndexList indexList = selectionModel->selectedIndexes();
-
- int i = indexList.size() - 1;
- for(; i >= 0; i--)
- m_tableModel->removeRow(indexList[i].row());
-
- m_tableModel->submitAll();
-}
-
-void
-ProfileEditor::onOkClicked()
-{
- m_tableModel->submitAll();
- m_contactManager->updateProfileData(m_currentIdentity);
- this->hide();
-}
-
-void
-ProfileEditor::onGetClicked()
-{
- QString inputIdentity = ui->identityInput->text();
- m_currentIdentity = Name(inputIdentity.toUtf8().constData());
- string filter("profile_identity = '");
- filter.append(m_currentIdentity.toUri()).append("'");
-
- m_tableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
- m_tableModel->setTable("SelfProfile");
- m_tableModel->setFilter(filter.c_str());
- m_tableModel->select();
- m_tableModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Identity"));
- m_tableModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Type"));
- m_tableModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Value"));
-
- ui->profileTable->setModel(m_tableModel);
- ui->profileTable->setColumnHidden(0, true);
- ui->profileTable->show();
-}
-
-#if WAF
-#include "profileeditor.moc"
-#include "profileeditor.cpp.moc"
-#endif
diff --git a/src/profileeditor.h b/src/profileeditor.h
deleted file mode 100644
index e36a695..0000000
--- a/src/profileeditor.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef PROFILEEDITOR_H
-#define PROFILEEDITOR_H
-
-#include <QDialog>
-#include <QtSql/QSqlTableModel>
-
-#ifndef Q_MOC_RUN
-#include "contact-manager.h"
-#include <ndn-cpp-dev/security/key-chain.hpp>
-#endif
-
-namespace Ui {
-class ProfileEditor;
-}
-
-class ProfileEditor : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit ProfileEditor(ndn::shared_ptr<chronos::ContactManager> contactManager,
- QWidget *parent = 0);
-
- ~ProfileEditor();
-
- void
- setCurrentIdentity(const ndn::Name& name)
- { m_currentIdentity = name; }
-
-private slots:
- void
- onAddClicked();
-
- void
- onDeleteClicked();
-
- void
- onOkClicked();
-
- void
- onGetClicked();
-
-signals:
- void
- noKeyOrCert(const QString&);
-
-private:
- Ui::ProfileEditor *ui;
- QSqlTableModel* m_tableModel;
- ndn::shared_ptr<chronos::ContactManager> m_contactManager;
- ndn::shared_ptr<ndn::KeyChain> m_keyChain;
- ndn::Name m_currentIdentity;
-};
-
-#endif // PROFILEEDITOR_H
diff --git a/src/profileeditor.ui b/src/profileeditor.ui
deleted file mode 100644
index f3bdafd..0000000
--- a/src/profileeditor.ui
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ProfileEditor</class>
- <widget class="QDialog" name="ProfileEditor">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>500</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Profile Editor</string>
- </property>
- <widget class="QWidget" name="">
- <property name="geometry">
- <rect>
- <x>11</x>
- <y>10</y>
- <width>381</width>
- <height>491</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="profileEditorLayout" stretch="1,20,1">
- <item>
- <layout class="QHBoxLayout" name="identityLayout" stretch="1,5,1">
- <item>
- <widget class="QLabel" name="identityLabel">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Identity:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="identityInput"/>
- </item>
- <item>
- <widget class="QPushButton" name="getButton">
- <property name="text">
- <string>Get Profile</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QTableView" name="profileTable">
- <attribute name="horizontalHeaderCascadingSectionResizes">
- <bool>false</bool>
- </attribute>
- <attribute name="horizontalHeaderDefaultSectionSize">
- <number>100</number>
- </attribute>
- <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
- <bool>true</bool>
- </attribute>
- <attribute name="horizontalHeaderStretchLastSection">
- <bool>true</bool>
- </attribute>
- <attribute name="verticalHeaderVisible">
- <bool>true</bool>
- </attribute>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="buttonLayout" stretch="1,1,1">
- <item>
- <widget class="QPushButton" name="addRowButton">
- <property name="text">
- <string>Add</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="deleteRowButton">
- <property name="text">
- <string>Delete</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="okButton">
- <property name="text">
- <string>OK</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/set-alias-dialog.cpp b/src/set-alias-dialog.cpp
new file mode 100644
index 0000000..7327c1b
--- /dev/null
+++ b/src/set-alias-dialog.cpp
@@ -0,0 +1,61 @@
+/* -*- 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 "set-alias-dialog.h"
+#include "ui_set-alias-dialog.h"
+
+
+using namespace ndn;
+using namespace std;
+
+SetAliasDialog::SetAliasDialog(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::SetAliasDialog)
+{
+ ui->setupUi(this);
+
+ connect(ui->okButton, SIGNAL(clicked()),
+ this, SLOT(onOkClicked()));
+ connect(ui->cancelButton, SIGNAL(clicked()),
+ this, SLOT(onCancelClicked()));
+}
+
+SetAliasDialog::~SetAliasDialog()
+{
+ delete ui;
+}
+
+void
+SetAliasDialog::onOkClicked()
+{
+ emit aliasChanged(m_targetIdentity, ui->aliasInput->text());
+ this->close();
+}
+
+void
+SetAliasDialog::onCancelClicked()
+{
+ this->close();
+}
+
+void
+SetAliasDialog::setTargetIdentity(const QString& targetIdentity, const QString& alias)
+{
+ m_targetIdentity = targetIdentity;
+ QString msg = QString("Set alias for %1:").arg(targetIdentity);
+ ui->introLabel->setText(msg);
+ ui->aliasInput->setText(alias);
+}
+
+
+#if WAF
+#include "set-alias-dialog.moc"
+#include "set-alias-dialog.cpp.moc"
+#endif
diff --git a/src/setaliasdialog.h b/src/set-alias-dialog.h
similarity index 69%
rename from src/setaliasdialog.h
rename to src/set-alias-dialog.h
index 2358425..777b2c2 100644
--- a/src/setaliasdialog.h
+++ b/src/set-alias-dialog.h
@@ -14,7 +14,7 @@
#include <QDialog>
#ifndef Q_MOC_RUN
-#include "contact-manager.h"
+#include <ndn-cpp-dev/name.hpp>
#endif
namespace Ui {
@@ -26,16 +26,17 @@
Q_OBJECT
public:
- explicit SetAliasDialog(ndn::shared_ptr<chronos::ContactManager> contactManager,
- QWidget *parent = 0);
+ explicit
+ SetAliasDialog(QWidget *parent = 0);
+
~SetAliasDialog();
void
- setTargetIdentity(const std::string& name);
+ setTargetIdentity(const QString& targetIdentity, const QString& alias);
signals:
void
- aliasChanged();
+ aliasChanged(const QString& identity, const QString& alias);
private slots:
void
@@ -46,8 +47,7 @@
private:
Ui::SetAliasDialog *ui;
- ndn::shared_ptr<chronos::ContactManager> m_contactManager;
- std::string m_target;
+ QString m_targetIdentity;
};
#endif // SETALIASDIALOG_H
diff --git a/src/set-alias-dialog.ui b/src/set-alias-dialog.ui
new file mode 100644
index 0000000..df7f7a1
--- /dev/null
+++ b/src/set-alias-dialog.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SetAliasDialog</class>
+ <widget class="QDialog" name="SetAliasDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="2,1,1">
+ <item>
+ <widget class="QLabel" name="introLabel">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="aliasInput"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,1">
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="okButton">
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/setaliasdialog.cpp b/src/setaliasdialog.cpp
deleted file mode 100644
index 553b15c..0000000
--- a/src/setaliasdialog.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- 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 "setaliasdialog.h"
-#include "ui_setaliasdialog.h"
-
-
-using namespace ndn;
-using namespace std;
-
-SetAliasDialog::SetAliasDialog(shared_ptr<chronos::ContactManager> contactManager,
- QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::SetAliasDialog)
- , m_contactManager(contactManager)
-{
- ui->setupUi(this);
-
- connect(ui->okButton, SIGNAL(clicked()),
- this, SLOT(onOkClicked()));
- connect(ui->cancelButton, SIGNAL(clicked()),
- this, SLOT(onCancelClicked()));
-}
-
-SetAliasDialog::~SetAliasDialog()
-{
- delete ui;
-}
-
-void
-SetAliasDialog::onOkClicked()
-{
- QString text = ui->aliasInput->text();
- string alias = text.toStdString();
-
- m_contactManager->getContactStorage()->updateAlias(Name(m_target), alias);
-
- emit aliasChanged();
-
- this->close();
-}
-
-void
-SetAliasDialog::onCancelClicked()
-{ this->close(); }
-
-void
-SetAliasDialog::setTargetIdentity(const string& name)
-{
- m_target = name;
- string msg("Set alias for ");
- msg.append(name).append(":");
- ui->introLabel->setText(QString::fromStdString(msg));
- ui->aliasInput->clear();
-}
-
-
-#if WAF
-#include "setaliasdialog.moc"
-#include "setaliasdialog.cpp.moc"
-#endif
diff --git a/src/setaliasdialog.ui b/src/setaliasdialog.ui
deleted file mode 100644
index 3beeb3a..0000000
--- a/src/setaliasdialog.ui
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>SetAliasDialog</class>
- <widget class="QDialog" name="SetAliasDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>150</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <widget class="QLineEdit" name="aliasInput">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>60</y>
- <width>260</width>
- <height>21</height>
- </rect>
- </property>
- </widget>
- <widget class="QPushButton" name="okButton">
- <property name="geometry">
- <rect>
- <x>180</x>
- <y>100</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- <widget class="QPushButton" name="cancelButton">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>100</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- <widget class="QLabel" name="introLabel">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>20</y>
- <width>260</width>
- <height>30</height>
- </rect>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/setting-dialog.cpp b/src/setting-dialog.cpp
new file mode 100644
index 0000000..d0f98ae
--- /dev/null
+++ b/src/setting-dialog.cpp
@@ -0,0 +1,75 @@
+/* -*- 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 "setting-dialog.h"
+#include "ui_setting-dialog.h"
+
+SettingDialog::SettingDialog(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::SettingDialog)
+{
+ ui->setupUi(this);
+
+ connect(ui->saveButton, SIGNAL(clicked()),
+ this, SLOT(onSaveClicked()));
+ connect(ui->cancelButton, SIGNAL(clicked()),
+ this, SLOT(onCancelClicked()));
+}
+
+SettingDialog::~SettingDialog()
+{
+ delete ui;
+}
+
+void
+SettingDialog::setNick(const QString& nick)
+{
+ m_nick = nick;
+ ui->nickLine->setText(m_nick);
+}
+
+void
+SettingDialog::onIdentityUpdated(const QString& identity)
+{
+ m_identity = identity;
+ ui->identityLine->setText(m_identity);
+}
+
+void
+SettingDialog::onSaveClicked()
+{
+ QString identity = ui->identityLine->text();
+ QString nick = ui->nickLine->text();
+
+ if(identity != m_identity)
+ {
+ m_identity = identity;
+ emit identityUpdated(identity);
+ }
+ if(nick != m_nick)
+ {
+ m_nick = nick;
+ emit nickUpdated(nick);
+ }
+
+ this->close();
+}
+
+void
+SettingDialog::onCancelClicked()
+{
+ this->close();
+}
+
+
+#if WAF
+#include "setting-dialog.moc"
+#include "setting-dialog.cpp.moc"
+#endif
diff --git a/src/setting-dialog.h b/src/setting-dialog.h
new file mode 100644
index 0000000..b38c376
--- /dev/null
+++ b/src/setting-dialog.h
@@ -0,0 +1,60 @@
+/* -*- 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>
+ */
+
+#ifndef SETTING_DIALOG_H
+#define SETTING_DIALOG_H
+
+#include <QDialog>
+
+#ifndef Q_MOC_RUN
+#endif
+
+namespace Ui {
+class SettingDialog;
+}
+
+class SettingDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit
+ SettingDialog(QWidget *parent = 0);
+
+ ~SettingDialog();
+
+ void
+ setNick(const QString& nick);
+
+signals:
+ void
+ identityUpdated(const QString& identity);
+
+ void
+ nickUpdated(const QString& nick);
+
+public slots:
+ void
+ onIdentityUpdated(const QString& identity);
+
+private slots:
+ void
+ onSaveClicked();
+
+ void
+ onCancelClicked();
+
+private:
+ Ui::SettingDialog *ui;
+ QString m_identity;
+ QString m_nick;
+};
+
+#endif // SETTING_DIALOG_H
diff --git a/src/setting-dialog.ui b/src/setting-dialog.ui
new file mode 100644
index 0000000..f3b4d86
--- /dev/null
+++ b/src/setting-dialog.ui
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SettingDialog</class>
+ <widget class="QDialog" name="SettingDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>124</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="identityLayout" stretch="3,7">
+ <item>
+ <widget class="QLabel" name="identityLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Identity:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="identityLine"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="nickLayout" stretch="3,7">
+ <item>
+ <widget class="QLabel" name="nickLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>nick:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="nickLine"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="buttonLayout">
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="saveButton">
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/settingdialog.cpp b/src/settingdialog.cpp
deleted file mode 100644
index ed9a1bd..0000000
--- a/src/settingdialog.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- 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 "settingdialog.h"
-#include "ui_settingdialog.h"
-
-using namespace std;
-
-SettingDialog::SettingDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::SettingDialog)
-{
- ui->setupUi(this);
-
- connect(ui->okButton, SIGNAL(clicked()),
- this, SLOT(onOkClicked()));
-}
-
-SettingDialog::~SettingDialog()
-{
- delete ui;
-}
-
-void
-SettingDialog::setIdentity(const std::string& identity,
- const std::string& nickName)
-{
- m_identity = identity;
- ui->identityLine->setText(QString::fromStdString(m_identity));
- m_nickName = nickName;
- ui->nickLine->setText(QString::fromStdString(m_nickName));
-}
-
-void
-SettingDialog::onOkClicked()
-{
- QString qIdentity = ui->identityLine->text();
- string identity = qIdentity.toStdString();
- QString qNick = ui->nickLine->text();
- string nick = qNick.toStdString();
-
- if(identity != m_identity || nick != m_nickName)
- {
- m_identity = identity;
- m_nickName = nick;
- emit identitySet(qIdentity, qNick);
- }
- this->close();
-}
-
-
-#if WAF
-#include "settingdialog.moc"
-#include "settingdialog.cpp.moc"
-#endif
diff --git a/src/settingdialog.h b/src/settingdialog.h
deleted file mode 100644
index 9ee6865..0000000
--- a/src/settingdialog.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef SETTINGDIALOG_H
-#define SETTINGDIALOG_H
-
-#include <QDialog>
-
-namespace Ui {
-class SettingDialog;
-}
-
-class SettingDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit SettingDialog(QWidget *parent = 0);
- ~SettingDialog();
-
- void
- setIdentity(const std::string& identity,
- const std::string& nickName);
-
-signals:
- void
- identitySet(const QString& identity,
- const QString& nickName);
-
-private slots:
- void
- onOkClicked();
-
-private:
- Ui::SettingDialog *ui;
- std::string m_identity;
- std::string m_nickName;
-};
-
-#endif // SETTINGDIALOG_H
diff --git a/src/settingdialog.ui b/src/settingdialog.ui
deleted file mode 100644
index 271ef23..0000000
--- a/src/settingdialog.ui
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>SettingDialog</class>
- <widget class="QDialog" name="SettingDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>150</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <widget class="QPushButton" name="okButton">
- <property name="geometry">
- <rect>
- <x>100</x>
- <y>110</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- <widget class="QLabel" name="msgLabel">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>150</width>
- <height>16</height>
- </rect>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Current Identity:</string>
- </property>
- </widget>
- <widget class="QLineEdit" name="identityLine">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>30</y>
- <width>280</width>
- <height>21</height>
- </rect>
- </property>
- </widget>
- <widget class="QLabel" name="nickLabel">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>60</y>
- <width>150</width>
- <height>16</height>
- </rect>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Nick Name:</string>
- </property>
- </widget>
- <widget class="QLineEdit" name="nickLine">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>80</y>
- <width>280</width>
- <height>21</height>
- </rect>
- </property>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/startchatdialog.cpp b/src/start-chat-dialog.cpp
similarity index 63%
rename from src/startchatdialog.cpp
rename to src/start-chat-dialog.cpp
index 444f9c7..e9ac1f8 100644
--- a/src/startchatdialog.cpp
+++ b/src/start-chat-dialog.cpp
@@ -8,16 +8,17 @@
* Author: Yingdi Yu <yingdi@cs.ucla.edu>
*/
-#include "startchatdialog.h"
-#include "ui_startchatdialog.h"
+#include "start-chat-dialog.h"
+#include "ui_start-chat-dialog.h"
using namespace std;
-StartChatDialog::StartChatDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::StartChatDialog)
+StartChatDialog::StartChatDialog(QWidget *parent)
+ : QDialog(parent)
+ , ui(new Ui::StartChatDialog)
{
ui->setupUi(this);
+
connect(ui->okButton, SIGNAL(clicked()),
this, SLOT(onOkClicked()));
connect(ui->cancelButton, SIGNAL(clicked()),
@@ -25,25 +26,32 @@
}
StartChatDialog::~StartChatDialog()
-{ delete ui; }
+{
+ delete ui;
+}
void
StartChatDialog::setChatroom(const string& chatroom)
-{ ui->chatroomInput->setText(QString::fromStdString(chatroom)); }
+{
+ ui->chatroomInput->setText(QString::fromStdString(chatroom));
+}
void
StartChatDialog::onOkClicked()
{
QString chatroom = ui->chatroomInput->text();
- emit chatroomConfirmed(chatroom);
+ bool secured = ui->withSecurity->isChecked();
+ emit startChatroom(chatroom, secured);
this->close();
}
void
StartChatDialog::onCancelClicked()
-{ this->close(); }
+{
+ this->close();
+}
#if WAF
-#include "startchatdialog.moc"
-#include "startchatdialog.cpp.moc"
+#include "start-chat-dialog.moc"
+#include "start-chat-dialog.cpp.moc"
#endif
diff --git a/src/startchatdialog.h b/src/start-chat-dialog.h
similarity index 82%
rename from src/startchatdialog.h
rename to src/start-chat-dialog.h
index 056ef9a..7aa916b 100644
--- a/src/startchatdialog.h
+++ b/src/start-chat-dialog.h
@@ -8,8 +8,8 @@
* Author: Yingdi Yu <yingdi@cs.ucla.edu>
*/
-#ifndef STARTCHATDIALOG_H
-#define STARTCHATDIALOG_H
+#ifndef START_CHAT_DIALOG_H
+#define START_CHAT_DIALOG_H
#include <QDialog>
@@ -35,7 +35,7 @@
signals:
void
- chatroomConfirmed(const QString& chatroomName);
+ startChatroom(const QString& chatroomName, bool secured);
private slots:
void
@@ -48,4 +48,4 @@
Ui::StartChatDialog *ui;
};
-#endif // STARTCHATDIALOG_H
+#endif // START_CHAT_DIALOG_H
diff --git a/src/start-chat-dialog.ui b/src/start-chat-dialog.ui
new file mode 100644
index 0000000..ced5bf5
--- /dev/null
+++ b/src/start-chat-dialog.ui
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StartChatDialog</class>
+ <widget class="QDialog" name="StartChatDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>100</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <widget class="QCheckBox" name="withSecurity">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>480</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>with security</string>
+ </property>
+ </widget>
+ <widget class="QWidget" name="">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>281</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="chatroomLineLayout">
+ <item>
+ <widget class="QLabel" name="introLabel">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Chatroom Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="chatroomInput"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>60</y>
+ <width>281</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="buttonLayout" stretch="1,1">
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="okButton">
+ <property name="text">
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/startchatdialog.ui b/src/startchatdialog.ui
deleted file mode 100644
index c6ec4d6..0000000
--- a/src/startchatdialog.ui
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>StartChatDialog</class>
- <widget class="QDialog" name="StartChatDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>200</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Dialog</string>
- </property>
- <widget class="QPushButton" name="okButton">
- <property name="geometry">
- <rect>
- <x>180</x>
- <y>150</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- </widget>
- <widget class="QLineEdit" name="chatroomInput">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>70</y>
- <width>260</width>
- <height>21</height>
- </rect>
- </property>
- </widget>
- <widget class="QLabel" name="introLabel">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>30</y>
- <width>260</width>
- <height>16</height>
- </rect>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Chatroom Prefix:</string>
- </property>
- </widget>
- <widget class="QPushButton" name="cancelButton">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>150</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/validator-invitation.cpp b/src/validator-invitation.cpp
index d22d55b..ec54a38 100644
--- a/src/validator-invitation.cpp
+++ b/src/validator-invitation.cpp
@@ -9,6 +9,7 @@
*/
#include "validator-invitation.h"
+#include "invitation.h"
#include "logging.h"
@@ -21,208 +22,123 @@
const shared_ptr<CertificateCache> ValidatorInvitation::DefaultCertificateCache = shared_ptr<CertificateCache>();
-ValidatorInvitation::ValidatorInvitation(shared_ptr<Face> face,
- const string& chatroomName,
- const Name& signingIdentity,
- shared_ptr<CertificateCache> certificateCache,
- int stepLimit)
- : Validator(face)
- , m_stepLimit(stepLimit)
- , m_certificateCache(certificateCache)
- , m_chatroomName(chatroomName)
- , m_signingIdentity(signingIdentity)
+ValidatorInvitation::ValidatorInvitation()
+ : Validator()
+ , m_invitationReplyRule("^([^<CHRONOCHAT-INVITATION>]*)<CHRONOCHAT-INVITATION>",
+ "^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$",
+ "==", "\\1", "\\1\\2", true)
+ , m_invitationInterestRule("^[^<CHRONOCHAT-INVITATION>]*<CHRONOCHAT-INVITATION><>{6}$")
+ , m_innerKeyRegex("^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT><>$", "\\1\\2")
{
- m_invitationRule = make_shared<SecRuleRelative>("^<ndn><broadcast><chronos><invitation>([^<chatroom>]*)<chatroom>",
- "^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$",
- "==", "\\1", "\\1\\2", true);
-
- m_dskRule = make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT><>$",
- "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
- "==", "\\1", "\\1\\2", true);
-}
+}
void
-ValidatorInvitation::checkPolicy (const shared_ptr<const Data>& data,
+ValidatorInvitation::checkPolicy (const Data& data,
int stepCount,
const OnDataValidated& onValidated,
const OnDataValidationFailed& onValidationFailed,
vector<shared_ptr<ValidationRequest> >& nextSteps)
{
- if(m_stepLimit == stepCount)
+ try
{
- _LOG_DEBUG("reach the maximum steps of verification");
- onValidationFailed(data);
- return;
+ SignatureSha256WithRsa sig(data.getSignature());
+ const Name & keyLocatorName = sig.getKeyLocator().getName();
+
+ if(!m_invitationReplyRule.satisfy(data.getName(), keyLocatorName))
+ return onValidationFailed(data.shared_from_this(),
+ "Does not comply with the invitation rule: "
+ + data.getName().toUri() + " signed by: "
+ + keyLocatorName.toUri());
+
+ Data innerData;
+ innerData.wireDecode(data.getContent().blockFromValue());
+
+ return internalCheck(data.wireEncode().wire(),
+ data.wireEncode().size(),
+ sig,
+ innerData,
+ bind(onValidated, data.shared_from_this()),
+ bind(onValidationFailed, data.shared_from_this(), _1));
}
-
- try{
- SignatureSha256WithRsa sig(data->getSignature());
- const Name & keyLocatorName = sig.getKeyLocator().getName();
- const uint8_t* buf = data->wireEncode().wire();
- const size_t size = data->wireEncode().size();
-
- if(m_invitationRule->satisfy(data->getName(), keyLocatorName))
- processSignature(buf, size,
- sig, keyLocatorName,
- bind(onValidated, data),
- bind(onValidationFailed, data),
- stepCount,
- nextSteps);
-
- if(m_dskRule->satisfy(data->getName(), keyLocatorName))
- processFinalSignature(buf, size,
- sig, keyLocatorName,
- bind(onValidated, data),
- bind(onValidationFailed, data));
-
- }catch(...){
- onValidationFailed(data);
- return;
- }
+ catch(SignatureSha256WithRsa::Error &e)
+ {
+ return onValidationFailed(data.shared_from_this(),
+ "Not SignatureSha256WithRsa signature: " + data.getName().toUri());
+ }
}
void
-ValidatorInvitation::checkPolicy (const shared_ptr<const Interest>& interest,
+ValidatorInvitation::checkPolicy (const Interest& interest,
int stepCount,
const OnInterestValidated& onValidated,
const OnInterestValidationFailed& onValidationFailed,
vector<shared_ptr<ValidationRequest> >& nextSteps)
{
- try{
- Name interestName = interest->getName();
-
- Block signatureBlock = interestName.get(-1).blockFromValue();
- Block signatureInfo = interestName.get(-2).blockFromValue();
- Signature signature(signatureInfo, signatureBlock);
-
- SignatureSha256WithRsa sig(signature);
- const Name & keyLocatorName = sig.getKeyLocator().getName();
-
- Name signedName = interestName.getPrefix(-1);
- Buffer signedBlob = Buffer(signedName.wireEncode().value(), signedName.wireEncode().value_size());
-
- processSignature(signedBlob.buf(), signedBlob.size(),
- sig, keyLocatorName,
- bind(onValidated, interest),
- bind(onValidationFailed, interest),
- stepCount,
- nextSteps);
-
- }catch(...){
- onValidationFailed(interest);
- return;
- }
-
-}
-
-void
-ValidatorInvitation::processSignature (const uint8_t* buf,
- const size_t size,
- const SignatureSha256WithRsa& signature,
- const Name& keyLocatorName,
- const OnValidated& onValidated,
- const OnValidationFailed& onValidationFailed,
- int stepCount,
- vector<shared_ptr<ValidationRequest> >& nextSteps)
-{
- try{
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
-
- if(m_trustAnchors.find(keyName) != m_trustAnchors.end())
- {
- if(Validator::verifySignature(buf, size, signature, m_trustAnchors[keyName]))
- onValidated();
- else
- onValidationFailed();
- return;
- }
-
- if(static_cast<bool>(m_certificateCache))
- {
- shared_ptr<const IdentityCertificate> trustedCert = m_certificateCache->getCertificate(keyLocatorName);
- if(static_cast<bool>(trustedCert)){
- if(Validator::verifySignature(buf, size, signature, trustedCert->getPublicKeyInfo()))
- onValidated();
- else
- onValidationFailed();
- return;
- }
- }
-
- OnDataValidated onKeyLocatorValidated =
- bind(&ValidatorInvitation::onDskKeyLocatorValidated,
- this, _1, buf, size, signature, onValidated, onValidationFailed);
-
- OnDataValidationFailed onKeyLocatorValidationFailed =
- bind(&ValidatorInvitation::onDskKeyLocatorValidationFailed,
- this, _1, onValidationFailed);
-
- Interest interest(keyLocatorName);
- interest.setMustBeFresh(true);
-
- shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>
- (interest, onKeyLocatorValidated, onKeyLocatorValidationFailed, 0, stepCount + 1);
-
- nextSteps.push_back(nextStep);
- return;
- }catch(...){
- onValidationFailed();
- return;
- }
-}
-
-void
-ValidatorInvitation::processFinalSignature (const uint8_t* buf,
- const size_t size,
- const SignatureSha256WithRsa& signature,
- const Name& keyLocatorName,
- const OnValidated& onValidated,
- const OnValidationFailed& onValidationFailed)
-{
- try{
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
-
- if(m_trustAnchors.end() != m_trustAnchors.find(keyName) && Validator::verifySignature(buf, size, signature, m_trustAnchors[keyName]))
- onValidated();
- else
- onValidationFailed();
- return;
- }catch(...){
- onValidationFailed();
- return;
- }
-}
-
-
-void
-ValidatorInvitation::onDskKeyLocatorValidated(const shared_ptr<const Data>& certData,
- const uint8_t* buf,
- const size_t size,
- const SignatureSha256WithRsa& signature,
- const OnValidated& onValidated,
- const OnValidationFailed& onValidationFailed)
-{
- shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>(*certData);
-
- if(!certificate->isTooLate() && !certificate->isTooEarly())
+ try
{
- Name certName = certificate->getName().getPrefix(-1);
- m_dskCertificates[certName] = certificate;
+ Name interestName = interest.getName();
+
+ if(!m_invitationInterestRule.match(interestName))
+ return onValidationFailed(interest.shared_from_this(),
+ "Invalid interest name: " + interest.getName().toUri());
- if(Validator::verifySignature(buf, size, signature, certificate->getPublicKeyInfo()))
- {
- onValidated();
- return;
- }
+ Name signedName = interestName.getPrefix(-1);
+ Buffer signedBlob = Buffer(signedName.wireEncode().value(), signedName.wireEncode().value_size());
+
+ Block signatureBlock = interestName.get(Invitation::SIGNATURE).blockFromValue();
+ Block signatureInfo = interestName.get(Invitation::KEY_LOCATOR).blockFromValue();
+ Signature signature(signatureInfo, signatureBlock);
+ SignatureSha256WithRsa sig(signature);
+
+ Data innerData;
+ innerData.wireDecode(interestName.get(Invitation::INVITER_CERT).blockFromValue());
+
+ return internalCheck(signedBlob.buf(),
+ signedBlob.size(),
+ sig,
+ innerData,
+ bind(onValidated, interest.shared_from_this()),
+ bind(onValidationFailed, interest.shared_from_this(), _1));
}
-
- onValidationFailed();
- return;
+ catch(SignatureSha256WithRsa::Error& e)
+ {
+ return onValidationFailed(interest.shared_from_this(),
+ "Not SignatureSha256WithRsa signature: " + interest.getName().toUri());
+ }
}
void
-ValidatorInvitation::onDskKeyLocatorValidationFailed(const shared_ptr<const Data>& certData,
- const OnValidationFailed& onValidationFailed)
-{ onValidationFailed(); }
+ValidatorInvitation::internalCheck(const uint8_t* buf, size_t size,
+ const SignatureSha256WithRsa& sig,
+ const Data& innerData,
+ const OnValidated& onValidated,
+ const OnValidationFailed& onValidationFailed)
+{
+ try
+ {
+ const Name & keyLocatorName = sig.getKeyLocator().getName();
+ Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
+
+ if(m_trustAnchors.find(signingKeyName) == m_trustAnchors.end())
+ return onValidationFailed("Cannot reach any trust anchor");
+
+ if(!Validator::verifySignature(buf, size, sig, m_trustAnchors[signingKeyName]))
+ return onValidationFailed("Cannot verify interest signature");
+
+ if(!Validator::verifySignature(innerData, m_trustAnchors[signingKeyName]))
+ return onValidationFailed("Cannot verify interest signature");
+
+ if(!m_innerKeyRegex.match(innerData.getName())
+ || m_innerKeyRegex.expand() != signingKeyName.getPrefix(-1))
+ return onValidationFailed("Inner certificate does not comply with the rule");
+
+ return onValidated();
+ }
+ catch(KeyLocator::Error& e)
+ {
+ return onValidationFailed("Key Locator is not a name");
+ }
+}
+
}//chronos
diff --git a/src/validator-invitation.h b/src/validator-invitation.h
index ede1799..cb22d65 100644
--- a/src/validator-invitation.h
+++ b/src/validator-invitation.h
@@ -22,7 +22,7 @@
class ValidatorInvitation : public ndn::Validator
{
- typedef ndn::function< void () > OnValidationFailed;
+ typedef ndn::function< void (const std::string&) > OnValidationFailed;
typedef ndn::function< void () > OnValidated;
public:
@@ -30,101 +30,59 @@
static const ndn::shared_ptr<ndn::CertificateCache> DefaultCertificateCache;
- ValidatorInvitation(ndn::shared_ptr<ndn::Face> face,
- const std::string& chatroomName,
- const ndn::Name& signingIdentity,
- ndn::shared_ptr<ndn::CertificateCache> certificateCache = DefaultCertificateCache,
- int stepLimit = 10);
+ ValidatorInvitation();
virtual
~ValidatorInvitation() {};
void
- addTrustAnchor(const EndorseCertificate& cert)
- { m_trustAnchors[cert.getPublicKeyName()] = cert.getPublicKeyInfo(); }
+ addTrustAnchor(const ndn::Name& keyName, const ndn::PublicKey& key)
+ {
+ m_trustAnchors[keyName] = key;
+ }
void
removeTrustAnchor(const ndn::Name& keyName)
- { m_trustAnchors.erase(keyName); }
-
- ndn::shared_ptr<ndn::IdentityCertificate>
- getValidatedDskCertificate(const ndn::Name& certName)
- {
- ValidatedCertifcates::iterator it = m_dskCertificates.find(certName);
- if(m_dskCertificates.end() != it)
- return it->second;
- else
- return ndn::shared_ptr<ndn::IdentityCertificate>();
+ {
+ m_trustAnchors.erase(keyName);
}
-
+ void
+ cleanTrustAnchor()
+ {
+ m_trustAnchors.clear();
+ }
+
protected:
void
- checkPolicy (const ndn::shared_ptr<const ndn::Data>& data,
- int stepCount,
- const ndn::OnDataValidated& onValidated,
- const ndn::OnDataValidationFailed& onValidationFailed,
- std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
-
- void
- checkPolicy (const ndn::shared_ptr<const ndn::Interest>& interest,
- int stepCount,
- const ndn::OnInterestValidated& onValidated,
- const ndn::OnInterestValidationFailed& onValidationFailed,
- std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
-
-private:
- void
- onDskKeyLocatorValidated(const ndn::shared_ptr<const ndn::Data>& certData,
- const uint8_t* buf,
- const size_t size,
- const ndn::SignatureSha256WithRsa& signature,
- const OnValidated& onValidated,
- const OnValidationFailed& onValidationFailed);
+ checkPolicy(const ndn::Data& data,
+ int stepCount,
+ const ndn::OnDataValidated& onValidated,
+ const ndn::OnDataValidationFailed& onValidationFailed,
+ std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
void
- onDskKeyLocatorValidationFailed(const ndn::shared_ptr<const ndn::Data>& certData,
- const OnValidationFailed& onValidationFailed);
-
- void
- processSignature (const uint8_t* buf,
- const size_t size,
- const ndn::SignatureSha256WithRsa& signature,
- const ndn::Name& keyLocatorName,
- const OnValidated& onValidated,
- const OnValidationFailed& onValidationFailed,
- int stepCount,
- std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
-
- void
- processFinalSignature (const uint8_t* buf,
- const size_t size,
- const ndn::SignatureSha256WithRsa& signature,
- const ndn::Name& keyLocatorName,
- const OnValidated& onValidated,
- const OnValidationFailed& onValidationFailed);
+ checkPolicy(const ndn::Interest& interest,
+ int stepCount,
+ const ndn::OnInterestValidated& onValidated,
+ const ndn::OnInterestValidationFailed& onValidationFailed,
+ std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
private:
+ void
+ internalCheck(const uint8_t* buf, size_t size,
+ const ndn::SignatureSha256WithRsa& sig,
+ const ndn::Data& innerData,
+ const OnValidated& onValidated,
+ const OnValidationFailed& onValidationFailed);
+private:
typedef std::map<ndn::Name, ndn::PublicKey> TrustAnchors;
- typedef std::map<ndn::Name, ndn::shared_ptr<ndn::IdentityCertificate> > ValidatedCertifcates;
- int m_stepLimit;
- ndn::shared_ptr<ndn::CertificateCache> m_certificateCache;
-
- std::string m_chatroomName;
- ndn::Name m_signingIdentity;
-
- ndn::shared_ptr<ndn::SecRuleRelative> m_invitationRule;
- ndn::shared_ptr<ndn::SecRuleRelative> m_dskRule;
-
- ndn::shared_ptr<ndn::Regex> m_kskRegex;
- ndn::shared_ptr<ndn::Regex> m_keyNameRegex;
-
+ ndn::SecRuleRelative m_invitationReplyRule;
+ ndn::Regex m_invitationInterestRule;
+ ndn::Regex m_innerKeyRegex;
TrustAnchors m_trustAnchors;
-
- ValidatedCertifcates m_dskCertificates;
-
};
}//chronos
diff --git a/src/validator-panel.cpp b/src/validator-panel.cpp
index 5622bc6..8de4bb6 100644
--- a/src/validator-panel.cpp
+++ b/src/validator-panel.cpp
@@ -44,32 +44,40 @@
if(m_stepLimit == stepCount)
{
_LOG_ERROR("Reach the maximum steps of verification!");
- onValidationFailed(data.shared_from_this());
+ onValidationFailed(data.shared_from_this(),
+ "Reach maximum validation steps: " + data.getName().toUri());
return;
}
- try{
- SignatureSha256WithRsa sig(data.getSignature());
- const Name& keyLocatorName = sig.getKeyLocator().getName();
+ try
+ {
+ SignatureSha256WithRsa sig(data.getSignature());
+ const Name& keyLocatorName = sig.getKeyLocator().getName();
- if(m_endorseeRule->satisfy(data.getName(), keyLocatorName))
- {
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
+ if(m_endorseeRule->satisfy(data.getName(), keyLocatorName))
+ {
+ Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
- if(m_trustAnchors.end() != m_trustAnchors.find(keyName) && Validator::verifySignature(data, sig, m_trustAnchors[keyName]))
- onValidated(data.shared_from_this());
- else
- onValidationFailed(data.shared_from_this());
- }
- else
- onValidationFailed(data.shared_from_this());
+ if(m_trustAnchors.end() != m_trustAnchors.find(keyName) && Validator::verifySignature(data, sig, m_trustAnchors[keyName]))
+ onValidated(data.shared_from_this());
+ else
+ onValidationFailed(data.shared_from_this(), "Cannot verify signature:" + data.getName().toUri());
+ }
+ else
+ onValidationFailed(data.shared_from_this(), "Does not satisfy rule: " + data.getName().toUri());
- return;
-
- }catch(...){
- onValidationFailed(data.shared_from_this());
- return;
- }
+ return;
+ }
+ catch(SignatureSha256WithRsa::Error &e)
+ {
+ return onValidationFailed(data.shared_from_this(),
+ "Not SignatureSha256WithRsa signature: " + data.getName().toUri());
+ }
+ catch(KeyLocator::Error &e)
+ {
+ return onValidationFailed(data.shared_from_this(),
+ "Key Locator is not a name: " + data.getName().toUri());
+ }
}
}//chronos
diff --git a/src/validator-panel.h b/src/validator-panel.h
index 2bcc226..3b5f670 100644
--- a/src/validator-panel.h
+++ b/src/validator-panel.h
@@ -52,7 +52,10 @@
const ndn::OnInterestValidated& onValidated,
const ndn::OnInterestValidationFailed& onValidationFailed,
std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps)
- { onValidationFailed(interest.shared_from_this()); }
+ {
+ onValidationFailed(interest.shared_from_this(),
+ "No rules for interest.");
+ }
private:
int m_stepLimit;
@@ -62,11 +65,11 @@
};
-void
+inline void
ValidatorPanel::addTrustAnchor(const EndorseCertificate& cert)
{ m_trustAnchors[cert.getPublicKeyName()] = cert.getPublicKeyInfo(); }
-void
+inline void
ValidatorPanel::removeTrustAnchor(const ndn::Name& keyName)
{ m_trustAnchors.erase(keyName); }
diff --git a/src/warningdialog.cpp b/src/warningdialog.cpp
deleted file mode 100644
index 6dcae60..0000000
--- a/src/warningdialog.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- 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 "warningdialog.h"
-#include "ui_warningdialog.h"
-
-using namespace std;
-
-WarningDialog::WarningDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::WarningDialog)
-{
- ui->setupUi(this);
-
- connect(ui->okButton, SIGNAL(clicked()),
- this, SLOT(onOkClicked()));
-}
-
-WarningDialog::~WarningDialog()
-{
- delete ui;
-}
-
-void
-WarningDialog::setMsg(const string& msg)
-{ ui->message->setText(QString::fromStdString(msg)); }
-
-void
-WarningDialog::onOkClicked()
-{ this->hide(); }
-
-#if WAF
-#include "warningdialog.moc"
-#include "warningdialog.cpp.moc"
-#endif
diff --git a/src/warningdialog.h b/src/warningdialog.h
deleted file mode 100644
index a2f3481..0000000
--- a/src/warningdialog.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- 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>
- */
-
-#ifndef WARNINGDIALOG_H
-#define WARNINGDIALOG_H
-
-#include <QDialog>
-
-namespace Ui {
-class WarningDialog;
-}
-
-class WarningDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit WarningDialog(QWidget *parent = 0);
-
- ~WarningDialog();
-
- void
- setMsg(const std::string& msg);
-
-private slots:
- void
- onOkClicked();
-
-private:
- Ui::WarningDialog *ui;
-};
-
-#endif // WARNINGDIALOG_H
diff --git a/src/warningdialog.ui b/src/warningdialog.ui
deleted file mode 100644
index e67bc40..0000000
--- a/src/warningdialog.ui
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>WarningDialog</class>
- <widget class="QDialog" name="WarningDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>300</width>
- <height>200</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Error</string>
- </property>
- <widget class="QLabel" name="message">
- <property name="geometry">
- <rect>
- <x>30</x>
- <y>30</y>
- <width>240</width>
- <height>200</height>
- </rect>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- </widget>
- <widget class="QPushButton" name="okButton">
- <property name="geometry">
- <rect>
- <x>100</x>
- <y>150</y>
- <width>100</width>
- <height>32</height>
- </rect>
- </property>
- <property name="text">
- <string>OK</string>
- </property>
- <property name="autoDefault">
- <bool>false</bool>
- </property>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>