Invitation works
diff --git a/src/chatdialog.cpp b/src/chatdialog.cpp
index 1c3e37e..5f1d3eb 100644
--- a/src/chatdialog.cpp
+++ b/src/chatdialog.cpp
@@ -11,31 +11,142 @@
 #include "chatdialog.h"
 #include "ui_chatdialog.h"
 
+#ifndef Q_MOC_RUN
+#include <ndn.cxx/security/identity/identity-manager.h>
+#include <ndn.cxx/security/identity/basic-identity-storage.h>
+#include <ndn.cxx/security/identity/osx-privatekey-storage.h>
+#include <ndn.cxx/security/encryption/basic-encryption-manager.h>
+#include "logging.h"
+#endif
+
 using namespace std;
 using namespace ndn;
 
+INIT_LOGGER("ChatDialog");
+
 ChatDialog::ChatDialog(const Name& chatroomPrefix,
 		       const Name& localPrefix,
+                       const Name& defaultIdentity,
 		       QWidget *parent) 
     : QDialog(parent)
     , m_chatroomPrefix(chatroomPrefix)
     , m_localPrefix(localPrefix)
+    , m_defaultIdentity(defaultIdentity)
+    , m_policyManager(Ptr<ChatroomPolicyManager>(new ChatroomPolicyManager))
     , ui(new Ui::ChatDialog)
 {
-    ui->setupUi(this);
+  ui->setupUi(this);
+
+  setWrapper();
 }
 
 ChatDialog::~ChatDialog()
 {
-    delete ui;
+  delete ui;
+  m_handler->shutdown();
 }
 
 void
-ChatDialog::sendInvitation()
+ChatDialog::setWrapper()
 {
-  
+  Ptr<security::OSXPrivatekeyStorage> privateStorage = Ptr<security::OSXPrivatekeyStorage>::Create();
+  m_identityManager = Ptr<security::IdentityManager>(new security::IdentityManager(Ptr<security::BasicIdentityStorage>::Create(), privateStorage));
+  Ptr<security::EncryptionManager> encryptionManager = Ptr<security::EncryptionManager>(new security::BasicEncryptionManager(privateStorage, "/tmp/encryption.db"));
+
+  m_keychain = Ptr<security::Keychain>(new security::Keychain(m_identityManager, m_policyManager, encryptionManager));
+
+  m_handler = Ptr<Wrapper>(new Wrapper(m_keychain));
 }
 
+void
+ChatDialog::sendInvitation(Ptr<ContactItem> contact)
+{
+  m_policyManager->addTrustAnchor(contact->getSelfEndorseCertificate());
+
+  Name certificateName = m_identityManager->getDefaultCertificateNameByIdentity(m_defaultIdentity);
+
+  Name interestName("/ndn/broadcast/chronos/invitation");
+  interestName.append(contact->getNameSpace());
+  interestName.append("chatroom");
+  interestName.append(m_chatroomPrefix.get(-1));
+  interestName.append("inviter-prefix");
+  interestName.append(m_localPrefix);
+  interestName.append("inviter");
+  interestName.append(certificateName);
+
+  string signedUri = interestName.toUri();
+  Blob signedBlob(signedUri.c_str(), signedUri.size());
+
+  Ptr<const signature::Sha256WithRsa> sha256sig = DynamicCast<const signature::Sha256WithRsa>(m_identityManager->signByCertificate(signedBlob, certificateName));
+  const Blob& sigBits = sha256sig->getSignatureBits();
+
+  interestName.append(sigBits.buf(), sigBits.size());
+
+  Ptr<Interest> interest = Ptr<Interest>(new Interest(interestName));
+  Ptr<Closure> closure = Ptr<Closure>(new Closure(boost::bind(&ChatDialog::onInviteReplyVerified,
+                                                              this,
+                                                              _1,
+                                                              contact->getNameSpace()),
+                                                  boost::bind(&ChatDialog::onInviteTimeout,
+                                                              this,
+                                                              _1,
+                                                              _2,
+                                                              contact->getNameSpace(),
+                                                              7),
+                                                  boost::bind(&ChatDialog::onUnverified,
+                                                              this,
+                                                              _1)));
+
+  m_handler->sendInterest(interest, closure);
+}
+
+void
+ChatDialog::invitationRejected(const Name& identity)
+{
+  _LOG_DEBUG(" " << identity.toUri() << " rejected your invitation!");
+}
+
+void
+ChatDialog::invitationAccepted(const Name& identity)
+{
+  _LOG_DEBUG(" " << identity.toUri() << " accepted your invitation!");
+}
+
+void 
+ChatDialog::onInviteReplyVerified(Ptr<Data> data, const Name& identity)
+{
+  string content(data->content().buf(), data->content().size());
+  if(content.empty())
+    invitationRejected(identity);
+  else
+    invitationAccepted(identity);
+}
+
+void 
+ChatDialog::onInviteTimeout(Ptr<Closure> closure, Ptr<Interest> interest, const Name& identity, int retry)
+{
+  if(retry > 0)
+    {
+      Ptr<Closure> newClosure = Ptr<Closure>(new Closure(closure->m_dataCallback,
+                                                         boost::bind(&ChatDialog::onInviteTimeout, 
+                                                                     this, 
+                                                                     _1, 
+                                                                     _2, 
+                                                                     identity,
+                                                                     retry - 1),
+                                                         closure->m_unverifiedCallback,
+                                                         closure->m_stepCount)
+                                             );
+      m_handler->sendInterest(interest, newClosure);
+    }
+  else
+    invitationRejected(identity);
+}
+ 
+void
+ChatDialog::onUnverified(Ptr<Data> data)
+{}
+
 #if WAF
 #include "chatdialog.moc"
 #include "chatdialog.cpp.moc"
diff --git a/src/chatdialog.h b/src/chatdialog.h
index 77feea1..e482169 100644
--- a/src/chatdialog.h
+++ b/src/chatdialog.h
@@ -15,6 +15,10 @@
 
 #ifndef Q_MOC_RUN
 #include <ndn.cxx/data.h>
+#include <ndn.cxx/security/keychain.h>
+#include <ndn.cxx/wrapper/wrapper.h>
+#include "chatroom-policy-manager.h"
+#include "contact-item.h"
 #endif
 
 namespace Ui {
@@ -28,6 +32,7 @@
 public:
   explicit ChatDialog(const ndn::Name& chatroomPrefix,
                       const ndn::Name& localPrefix,
+                      const ndn::Name& defaultIdentity,
                       QWidget *parent = 0);
   ~ChatDialog();
 
@@ -40,12 +45,39 @@
   { return m_localPrefix; }
 
   void
-  sendInvitation();
+  sendInvitation(ndn::Ptr<ContactItem> contact);
 
 private:
+  void
+  setWrapper();
+  
+  void 
+  onInviteReplyVerified(ndn::Ptr<ndn::Data> data, const ndn::Name& identity);
+
+  void 
+  onInviteTimeout(ndn::Ptr<ndn::Closure> closure, 
+                  ndn::Ptr<ndn::Interest> interest, 
+                  const ndn::Name& identity, 
+                  int retry);
+
+  void
+  invitationRejected(const ndn::Name& identity);
+  
+  void 
+  invitationAccepted(const ndn::Name& identity);
+
+  void
+  onUnverified(ndn::Ptr<ndn::Data> data);
+    
+private:
   Ui::ChatDialog *ui;
   ndn::Name m_chatroomPrefix;
   ndn::Name m_localPrefix;
+  ndn::Name m_defaultIdentity;
+  ndn::Ptr<ChatroomPolicyManager> m_policyManager;
+  ndn::Ptr<ndn::security::IdentityManager> m_identityManager;
+  ndn::Ptr<ndn::security::Keychain> m_keychain;
+  ndn::Ptr<ndn::Wrapper> m_handler;
 };
 
 #endif // ChatDIALOG_H
diff --git a/src/contact-manager.cpp b/src/contact-manager.cpp
index af094a7..bc324b7 100644
--- a/src/contact-manager.cpp
+++ b/src/contact-manager.cpp
@@ -301,7 +301,7 @@
   
   Ptr<Blob> dnsBlob = data->encodeToWire();
 
-  m_wrapper->putToCcnd(*dnsBlob);
+  m_wrapper->putToNdnd(*dnsBlob);
 }
 
 
diff --git a/src/contactpanel.cpp b/src/contactpanel.cpp
index 4ba7323..5c4cfc3 100644
--- a/src/contactpanel.cpp
+++ b/src/contactpanel.cpp
@@ -58,56 +58,59 @@
 {
   qRegisterMetaType<ndn::security::IdentityCertificate>("IdentityCertificate");
   
-   ui->setupUi(this);
-   refreshContactList();
+  ui->setupUi(this);
+  refreshContactList();
 
-   openDB();    
+  openDB();    
 
-   setKeychain();
-   m_handler = Ptr<Wrapper>(new Wrapper(m_keychain));
+  setKeychain();
+  m_handler = Ptr<Wrapper>(new Wrapper(m_keychain));
    
-   setLocalPrefix();
+  setLocalPrefix();
     
-   // Set Identity, TODO: through user interface
-   m_defaultIdentity = m_keychain->getDefaultIdentity();
-   m_settingDialog->setIdentity(m_defaultIdentity.toUri());
-   setInvitationListener();
+  // Set Identity, TODO: through user interface
+  m_defaultIdentity = m_keychain->getDefaultIdentity();
+  m_settingDialog->setIdentity(m_defaultIdentity.toUri());
+  setInvitationListener();
+  
+  ui->ContactList->setModel(m_contactListModel);
+  
+  QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
 
-   ui->ContactList->setModel(m_contactListModel);
+  connect(selectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+          this, SLOT(updateSelection(const QItemSelection &, const QItemSelection &)));
 
-   QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
+  connect(ui->ContactList, SIGNAL(customContextMenuRequested(const QPoint&)),
+          this, SLOT(showContextMenu(const QPoint&)));
 
-   connect(selectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
-           this, SLOT(updateSelection(const QItemSelection &, const QItemSelection &)));
+  connect(ui->EditProfileButton, SIGNAL(clicked()), 
+          this, SLOT(openProfileEditor()));
 
-   connect(ui->ContactList, SIGNAL(customContextMenuRequested(const QPoint&)),
-           this, SLOT(showContextMenu(const QPoint&)));
-
-   connect(ui->EditProfileButton, SIGNAL(clicked()), 
-           this, SLOT(openProfileEditor()));
-
-   connect(ui->AddContactButton, SIGNAL(clicked()),
-           this, SLOT(openAddContactPanel()));
+  connect(ui->AddContactButton, SIGNAL(clicked()),
+          this, SLOT(openAddContactPanel()));
    
-   connect(ui->settingButton, SIGNAL(clicked()),
-           this, SLOT(openSettingDialog()));
+  connect(ui->settingButton, SIGNAL(clicked()),
+          this, SLOT(openSettingDialog()));
    
-   connect(m_addContactPanel, SIGNAL(newContactAdded()),
-           this, SLOT(refreshContactList()));
+  connect(m_addContactPanel, SIGNAL(newContactAdded()),
+          this, SLOT(refreshContactList()));
 
-   connect(m_setAliasDialog, SIGNAL(aliasChanged()),
-           this, SLOT(refreshContactList()));
+  connect(m_setAliasDialog, SIGNAL(aliasChanged()),
+          this, SLOT(refreshContactList()));
 
-   connect(m_startChatDialog, SIGNAL(chatroomConfirmed(const QString&, const QString&, bool)),
-           this, SLOT(startChatroom(const QString&, const QString&, bool)));
+  connect(m_startChatDialog, SIGNAL(chatroomConfirmed(const QString&, const QString&, bool)),
+          this, SLOT(startChatroom(const QString&, const QString&, bool)));
 
-   connect(m_invitationDialog, SIGNAL(invitationAccepted(const ndn::Name&, const ndn::security::IdentityCertificate&, QString, QString)),
-           this, SLOT(acceptInvitation(const ndn::Name&, const ndn::security::IdentityCertificate&, QString, QString)));
-   connect(m_invitationDialog, SIGNAL(invitationRejected(const ndn::Name&)),
-           this, SLOT(rejectInvitation(const ndn::Name&)));
+  connect(m_invitationDialog, SIGNAL(invitationAccepted(const ndn::Name&, const ndn::security::IdentityCertificate&, QString, QString)),
+          this, SLOT(acceptInvitation(const ndn::Name&, const ndn::security::IdentityCertificate&, QString, QString)));
+  connect(m_invitationDialog, SIGNAL(invitationRejected(const ndn::Name&)),
+          this, SLOT(rejectInvitation(const ndn::Name&)));
 
-   connect(m_settingDialog, SIGNAL(identitySet(const QString&)),
-           this, SLOT(updateDefaultIdentity(const QString&)));
+  connect(m_settingDialog, SIGNAL(identitySet(const QString&)),
+          this, SLOT(updateDefaultIdentity(const QString&)));
+
+  connect(this, SIGNAL(newInvitationReady()),
+          this, SLOT(openInvitationDialog()));
 
 
 
@@ -115,12 +118,16 @@
 
 ContactPanel::~ContactPanel()
 {
-    delete ui;
-    delete m_contactListModel;
-    delete m_profileEditor;
-    delete m_addContactPanel;
+  delete ui;
+  delete m_contactListModel;
+  delete m_profileEditor;
+  delete m_addContactPanel;
 
-    delete m_menuInvite;
+  delete m_menuInvite;
+
+  map<Name, ChatDialog*>::iterator it = m_chatDialogs.begin();
+  for(; it != m_chatDialogs.end(); it++)
+    delete it->second;
 }
 
 void
@@ -175,9 +182,8 @@
   string originPrefix(data->content().buf(), data->content().size());
   string prefix = QString::fromStdString (originPrefix).trimmed ().toUtf8().constData();
   string randomSuffix = getRandomString();
-  _LOG_DEBUG("prefix: " << prefix);
-  _LOG_DEBUG("randomSuffix: " << randomSuffix);
   m_localPrefix = Name(prefix);
+  m_localPrefix.append(randomSuffix);
 }
 
 void
@@ -230,11 +236,10 @@
 
   string chatroom = interestName.get(i+1).toUri();
   string inviter = inviterNameSpace.toUri();
-  
   m_invitationDialog->setMsg(inviter, chatroom);
   m_invitationDialog->setIdentityCertificate(certificate);
   m_invitationDialog->setInterestName(interestName);
-  m_invitationDialog->show();
+  emit newInvitationReady();
 }
 
 static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");
@@ -258,6 +263,8 @@
 {
   Name prefix("/ndn/broadcast/chronos/invitation");
   prefix.append(m_defaultIdentity);
+  _LOG_DEBUG("prefix: " << prefix.toUri());
+  m_inviteListenPrefix = prefix;
   m_handler->setInterestFilter (prefix, 
                                 boost::bind(&ContactPanel::onInvitation, 
                                             this,
@@ -268,6 +275,7 @@
 void
 ContactPanel::onInvitation(Ptr<Interest> interest)
 {
+  _LOG_DEBUG("receive interest!" << interest->getName().toUri());
   const Name& interestName = interest->getName();
   const int end = interestName.size();
   
@@ -350,7 +358,20 @@
 
 void
 ContactPanel::updateDefaultIdentity(const QString& identity)
-{ m_defaultIdentity = Name(identity.toUtf8().constData()); }
+{ 
+  m_defaultIdentity = Name(identity.toUtf8().constData()); 
+  Name prefix("/ndn/broadcast/chronos/invitation");
+  prefix.append(m_defaultIdentity);
+
+  _LOG_DEBUG("reset invite listen prefix: " << prefix.toUri());
+  
+  m_handler->clearInterestFilter(m_inviteListenPrefix);
+  m_handler->setInterestFilter(prefix,
+                               boost::bind(&ContactPanel::onInvitation, 
+                                           this,
+                                           _1));
+  m_inviteListenPrefix = prefix;
+}
 
 void
 ContactPanel::openProfileEditor()
@@ -361,6 +382,10 @@
 { m_addContactPanel->show(); }
 
 void
+ContactPanel::openInvitationDialog()
+{ m_invitationDialog->show(); }
+
+void
 ContactPanel::refreshContactList()
 {
   m_contactList = m_contactManager->getContactItemList();
@@ -419,6 +444,20 @@
   _LOG_DEBUG("room: " << chatroom.toUtf8().constData());
   _LOG_DEBUG("invitee: " << invitee.toUtf8().constData());
   _LOG_DEBUG("introducer: " << std::boolalpha << isIntroducer);
+
+  Name chatroomName("/ndn/broadcast/chronos");
+  chatroomName.append(chatroom.toUtf8().constData());
+  
+  ChatDialog* chatDialog = new ChatDialog(chatroomName, m_localPrefix, m_defaultIdentity);
+  m_chatDialogs.insert(pair <Name, ChatDialog*> (chatroomName, chatDialog));
+  
+  //TODO: send invitation
+  Name inviteeNamespace(invitee.toUtf8().constData());
+  Ptr<ContactItem> inviteeItem = m_contactManager->getContact(inviteeNamespace);
+
+  chatDialog->sendInvitation(inviteeItem); 
+  
+  chatDialog->show();
 }
 
 void
@@ -435,8 +474,11 @@
                                QString chatroom)
 {
   string prefix = m_localPrefix.toUri();
+  _LOG_DEBUG("interestName " << interestName);
+  _LOG_DEBUG("prefix " << prefix);
   m_handler->publishDataByIdentity (interestName, prefix);
   //TODO:: open chat dialog
+  _LOG_DEBUG("ok");
   startChatroom2(chatroom, inviter);
 }
 
diff --git a/src/contactpanel.h b/src/contactpanel.h
index 9803a6a..2f33b49 100644
--- a/src/contactpanel.h
+++ b/src/contactpanel.h
@@ -22,6 +22,7 @@
 #include "startchatdialog.h"
 #include "invitationdialog.h"
 #include "settingdialog.h"
+#include "chatdialog.h"
 
 #ifndef Q_MOC_RUN
 #include "contact-manager.h"
@@ -34,7 +35,7 @@
 
 class ContactPanel : public QDialog
 {
-    Q_OBJECT
+  Q_OBJECT
 
 public:
   explicit ContactPanel(ndn::Ptr<ContactManager> contactManager, QWidget *parent = 0);
@@ -83,6 +84,10 @@
                     const ndn::Name& inviterNameSpace,
                     ndn::Ptr<ndn::security::IdentityCertificate> certificate);
 
+signals:
+  void
+  newInvitationReady();
+
 private slots:
   void
   updateSelection(const QItemSelection &selected,
@@ -107,6 +112,9 @@
   openSettingDialog();
 
   void
+  openInvitationDialog();
+
+  void
   refreshContactList();
 
   void
@@ -137,6 +145,7 @@
   StartChatDialog* m_startChatDialog;
   InvitationDialog* m_invitationDialog;
   SettingDialog* m_settingDialog;
+  std::map<ndn::Name, ChatDialog*> m_chatDialogs;
   QAction* m_menuInvite;
   QAction* m_menuAlias;
   std::vector<ndn::Ptr<ContactItem> > m_contactList;
@@ -146,6 +155,7 @@
 
   ndn::Name m_defaultIdentity;
   ndn::Name m_localPrefix;
+  ndn::Name m_inviteListenPrefix;
 
   std::string m_currentSelectedContactAlias;
   std::string m_currentSelectedContactNamespace;
diff --git a/src/invitation-policy-manager.cpp b/src/invitation-policy-manager.cpp
index b526bb6..a8b75fb 100644
--- a/src/invitation-policy-manager.cpp
+++ b/src/invitation-policy-manager.cpp
@@ -27,9 +27,9 @@
   , m_certificateCache(certificateCache)
   , m_localPrefixRegex(Ptr<Regex>(new Regex("^<local><ndn><prefix><><>$")))
 {
-  // m_invitationDataRule = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^<ndn><broadcast><chronos><invitation>([^<chatroom>]*)<chatroom>", 
-  //       								"^([^<KEY>]*)<KEY><DSK-.*><ID-CERT><>$", 
-  //       								"==", "\\1", "\\1", true));
+  m_invitationDataRule = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^<ndn><broadcast><chronos><invitation>([^<chatroom>]*)<chatroom>", 
+        								"^([^<KEY>]*)<KEY><DSK-.*><ID-CERT><>$", 
+        								"==", "\\1", "\\1", true));
   
   m_dskRule = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY><DSK-.*><ID-CERT><>$", 
 							     "^([^<KEY>]*)<KEY>(<>*)<KSK-.*><ID-CERT><>$", 
diff --git a/src/invitationdialog.cpp b/src/invitationdialog.cpp
index f7b2a59..c00727d 100644
--- a/src/invitationdialog.cpp
+++ b/src/invitationdialog.cpp
@@ -20,6 +20,11 @@
     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()
@@ -36,7 +41,7 @@
   msg.append(" invites you to join the chat room: ");
   
   ui->msgLabel->setText(QString::fromUtf8(msg.c_str()));
-  ui->chatroomLine->setText(QString::fromUtf8(msg.c_str()));
+  ui->chatroomLine->setText(QString::fromUtf8(chatroom.c_str()));
 }
 
 void
@@ -45,6 +50,7 @@
   QString inviter = QString::fromUtf8(m_inviter.c_str());
   QString chatroom = QString::fromUtf8(m_chatroom.c_str());
   emit invitationAccepted(m_interestName, *m_identityCertificate, inviter, chatroom); 
+  this->close();
 }
   
 void
@@ -56,6 +62,7 @@
   m_inviter.clear();
   m_chatroom.clear();
   emit invitationRejected(m_interestName); 
+  this->close();
 }
 
 #if WAF