blob: fc4037badb4515a73005300965695fb2fa3db2d1 [file] [log] [blame]
Yingdi Yu348f5ea2014-03-01 14:47:25 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * Yingdi Yu
5 *
6 * BSD license, See the LICENSE file for more information
7 *
8 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
9 */
10
11#include <QApplication>
12#include <QMessageBox>
13#include <QDir>
14#include <QTimer>
Yingdi Yu0b0a7362014-08-05 16:31:30 -070015#include "controller.hpp"
Mengjin Yan391d7242014-08-28 20:51:55 -070016//#include "chatroom-discovery.h"
Yingdi Yu348f5ea2014-03-01 14:47:25 -080017
18#ifndef Q_MOC_RUN
19#include <boost/filesystem.hpp>
20#include <boost/lexical_cast.hpp>
Yingdi Yufa0b6a02014-04-30 14:26:42 -070021#include <ndn-cxx/util/random.hpp>
Yingdi Yu0b0a7362014-08-05 16:31:30 -070022#include "cryptopp.hpp"
Yingdi Yu348f5ea2014-03-01 14:47:25 -080023#include "config.pb.h"
24#include "endorse-info.pb.h"
25#include "logging.h"
26#endif
27
Yingdi Yu0b0a7362014-08-05 16:31:30 -070028// INIT_LOGGER("chronos.Controller");
Yingdi Yu348f5ea2014-03-01 14:47:25 -080029
30Q_DECLARE_METATYPE(ndn::Name)
31Q_DECLARE_METATYPE(ndn::IdentityCertificate)
Yingdi Yu0b0a7362014-08-05 16:31:30 -070032Q_DECLARE_METATYPE(Chronos::EndorseInfo)
Yingdi Yu233a9722014-03-07 15:47:09 -080033Q_DECLARE_METATYPE(ndn::Interest)
34Q_DECLARE_METATYPE(size_t)
Mengjin Yan391d7242014-08-28 20:51:55 -070035Q_DECLARE_METATYPE(chronos::ChatroomInfo)
Yingdi Yu348f5ea2014-03-01 14:47:25 -080036
37namespace chronos {
38
Yingdi Yu0b0a7362014-08-05 16:31:30 -070039using std::string;
40
41using ndn::Face;
42using ndn::IdentityCertificate;
43using ndn::OnInterestValidated;
44using ndn::OnInterestValidationFailed;
Yingdi Yu17032f82014-03-25 15:48:23 -070045
Yingdi Yu348f5ea2014-03-01 14:47:25 -080046static const uint8_t ROUTING_PREFIX_SEPARATOR[2] = {0xF0, 0x2E};
47
48// constructor & destructor
49Controller::Controller(shared_ptr<Face> face,
Yingdi Yufa0b6a02014-04-30 14:26:42 -070050 QWidget* parent)
Yingdi Yu348f5ea2014-03-01 14:47:25 -080051 : QDialog(parent)
52 , m_face(face)
53 , m_invitationListenerId(0)
54 , m_contactManager(m_face)
Mengjin Yan391d7242014-08-28 20:51:55 -070055 , m_discoveryLogic(m_face,
56 bind(&Controller::updateDiscoveryList, this, _1, _2))
Yingdi Yu348f5ea2014-03-01 14:47:25 -080057 , m_settingDialog(new SettingDialog)
58 , m_startChatDialog(new StartChatDialog)
59 , m_profileEditor(new ProfileEditor)
60 , m_invitationDialog(new InvitationDialog)
61 , m_contactPanel(new ContactPanel)
62 , m_browseContactDialog(new BrowseContactDialog)
63 , m_addContactPanel(new AddContactPanel)
Mengjin Yan391d7242014-08-28 20:51:55 -070064 , m_chatroomDiscoveryDialog(new ChatroomDiscoveryDialog)
Yingdi Yu348f5ea2014-03-01 14:47:25 -080065{
66 qRegisterMetaType<ndn::Name>("ndn.Name");
67 qRegisterMetaType<ndn::IdentityCertificate>("ndn.IdentityCertificate");
Yingdi Yu0b0a7362014-08-05 16:31:30 -070068 qRegisterMetaType<Chronos::EndorseInfo>("Chronos.EndorseInfo");
Yingdi Yu233a9722014-03-07 15:47:09 -080069 qRegisterMetaType<ndn::Interest>("ndn.Interest");
70 qRegisterMetaType<size_t>("size_t");
Mengjin Yan391d7242014-08-28 20:51:55 -070071 qRegisterMetaType<chronos::ChatroomInfo>("chronos.Chatroom");
Yingdi Yu348f5ea2014-03-01 14:47:25 -080072
73 connect(this, SIGNAL(localPrefixUpdated(const QString&)),
74 this, SLOT(onLocalPrefixUpdated(const QString&)));
Yingdi Yu233a9722014-03-07 15:47:09 -080075 connect(this, SIGNAL(invitationInterest(const ndn::Name&, const ndn::Interest&, size_t)),
76 this, SLOT(onInvitationInterest(const ndn::Name&, const ndn::Interest&, size_t)));
Yingdi Yu348f5ea2014-03-01 14:47:25 -080077
78 // Connection to ContactManager
79 connect(this, SIGNAL(identityUpdated(const QString&)),
80 &m_contactManager, SLOT(onIdentityUpdated(const QString&)));
81 connect(&m_contactManager, SIGNAL(warning(const QString&)),
82 this, SLOT(onWarning(const QString&)));
83 connect(this, SIGNAL(refreshBrowseContact()),
84 &m_contactManager, SLOT(onRefreshBrowseContact()));
85 connect(&m_contactManager, SIGNAL(contactInfoFetchFailed(const QString&)),
86 this, SLOT(onWarning(const QString&)));
87 connect(&m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
88 this, SLOT(onContactIdListReady(const QStringList&)));
89
90 // Connection to SettingDialog
91 connect(this, SIGNAL(identityUpdated(const QString&)),
92 m_settingDialog, SLOT(onIdentityUpdated(const QString&)));
93 connect(m_settingDialog, SIGNAL(identityUpdated(const QString&)),
94 this, SLOT(onIdentityUpdated(const QString&)));
95 connect(m_settingDialog, SIGNAL(nickUpdated(const QString&)),
96 this, SLOT(onNickUpdated(const QString&)));
97
98 // Connection to ProfileEditor
99 connect(this, SIGNAL(closeDBModule()),
100 m_profileEditor, SLOT(onCloseDBModule()));
101 connect(this, SIGNAL(identityUpdated(const QString&)),
102 m_profileEditor, SLOT(onIdentityUpdated(const QString&)));
103 connect(m_profileEditor, SIGNAL(updateProfile()),
104 &m_contactManager, SLOT(onUpdateProfile()));
105
106 // Connection to StartChatDialog
107 connect(m_startChatDialog, SIGNAL(startChatroom(const QString&, bool)),
108 this, SLOT(onStartChatroom(const QString&, bool)));
109
110 // Connection to InvitationDialog
111 connect(m_invitationDialog, SIGNAL(invitationResponded(const ndn::Name&, bool)),
112 this, SLOT(onInvitationResponded(const ndn::Name&, bool)));
113
114 // Connection to AddContactPanel
115 connect(m_addContactPanel, SIGNAL(fetchInfo(const QString&)),
116 &m_contactManager, SLOT(onFetchContactInfo(const QString&)));
117 connect(m_addContactPanel, SIGNAL(addContact(const QString&)),
118 &m_contactManager, SLOT(onAddFetchedContact(const QString&)));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700119 connect(&m_contactManager, SIGNAL(contactEndorseInfoReady(const Chronos::EndorseInfo&)),
120 m_addContactPanel, SLOT(onContactEndorseInfoReady(const Chronos::EndorseInfo&)));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800121
122
123 // Connection to BrowseContactDialog
124 connect(m_browseContactDialog, SIGNAL(directAddClicked()),
125 this, SLOT(onDirectAdd()));
126 connect(m_browseContactDialog, SIGNAL(fetchIdCert(const QString&)),
127 &m_contactManager, SLOT(onFetchIdCert(const QString&)));
128 connect(m_browseContactDialog, SIGNAL(addContact(const QString&)),
129 &m_contactManager, SLOT(onAddFetchedContactIdCert(const QString&)));
130 connect(&m_contactManager, SIGNAL(idCertNameListReady(const QStringList&)),
131 m_browseContactDialog, SLOT(onIdCertNameListReady(const QStringList&)));
132 connect(&m_contactManager, SIGNAL(nameListReady(const QStringList&)),
133 m_browseContactDialog, SLOT(onNameListReady(const QStringList&)));
134 connect(&m_contactManager, SIGNAL(idCertReady(const ndn::IdentityCertificate&)),
135 m_browseContactDialog, SLOT(onIdCertReady(const ndn::IdentityCertificate&)));
136
137 // Connection to ContactPanel
138 connect(m_contactPanel, SIGNAL(waitForContactList()),
139 &m_contactManager, SLOT(onWaitForContactList()));
140 connect(m_contactPanel, SIGNAL(waitForContactInfo(const QString&)),
141 &m_contactManager, SLOT(onWaitForContactInfo(const QString&)));
142 connect(m_contactPanel, SIGNAL(removeContact(const QString&)),
143 &m_contactManager, SLOT(onRemoveContact(const QString&)));
144 connect(m_contactPanel, SIGNAL(updateAlias(const QString&, const QString&)),
145 &m_contactManager, SLOT(onUpdateAlias(const QString&, const QString&)));
146 connect(m_contactPanel, SIGNAL(updateIsIntroducer(const QString&, bool)),
147 &m_contactManager, SLOT(onUpdateIsIntroducer(const QString&, bool)));
148 connect(m_contactPanel, SIGNAL(updateEndorseCertificate(const QString&)),
149 &m_contactManager, SLOT(onUpdateEndorseCertificate(const QString&)));
150 connect(m_contactPanel, SIGNAL(warning(const QString&)),
151 this, SLOT(onWarning(const QString&)));
152 connect(this, SIGNAL(closeDBModule()),
153 m_contactPanel, SLOT(onCloseDBModule()));
154 connect(this, SIGNAL(identityUpdated(const QString&)),
155 m_contactPanel, SLOT(onIdentityUpdated(const QString&)));
156 connect(&m_contactManager, SIGNAL(contactAliasListReady(const QStringList&)),
157 m_contactPanel, SLOT(onContactAliasListReady(const QStringList&)));
158 connect(&m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
159 m_contactPanel, SLOT(onContactIdListReady(const QStringList&)));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700160 connect(&m_contactManager, SIGNAL(contactInfoReady(const QString&, const QString&,
161 const QString&, bool)),
162 m_contactPanel, SLOT(onContactInfoReady(const QString&, const QString&,
163 const QString&, bool)));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800164
Mengjin Yan391d7242014-08-28 20:51:55 -0700165 // Connection to DiscoveryDialog
166 connect(this,
167 SIGNAL(discoverChatroomChanged(const chronos::ChatroomInfo&, bool)),
168 m_chatroomDiscoveryDialog,
169 SLOT(onDiscoverChatroomChanged(const chronos::ChatroomInfo&, bool)));
170 connect(m_chatroomDiscoveryDialog, SIGNAL(startChatroom(const QString&, bool)),
171 this, SLOT(onStartChatroom(const QString&, bool)));
172
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800173 initialize();
174
Yingdi Yu233a9722014-03-07 15:47:09 -0800175 createTrayIcon();
176
177 onUpdateLocalPrefixAction();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800178}
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700179
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800180Controller::~Controller()
181{
182 saveConf();
183}
184
185// public methods
186
187
188// private methods
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700189string
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800190Controller::getDBName()
191{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700192 string dbName("chronos-");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800193
194 std::stringstream ss;
195 {
196 using namespace CryptoPP;
197
198 SHA256 hash;
199 StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
200 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
201 }
202 dbName.append(ss.str()).append(".db");
203
204 return dbName;
205}
206
207void
208Controller::openDB()
209{
210 m_db = QSqlDatabase::addDatabase("QSQLITE");
211 QString path = (QDir::home().path());
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700212 path.append(QDir::separator())
213 .append(".chronos")
214 .append(QDir::separator())
215 .append(getDBName().c_str());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800216 m_db.setDatabaseName(path);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800217
Yingdi Yu42125862014-08-07 17:04:28 -0700218 m_db.open();
219
220 // bool ok = m_db.open();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700221 // _LOG_DEBUG("DB opened: " << std::boolalpha << ok );
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800222}
223
224void
225Controller::initialize()
226{
227 loadConf();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700228
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800229 m_keyChain.createIdentity(m_identity);
230
231 openDB();
232
233 emit identityUpdated(QString(m_identity.toUri().c_str()));
234
235 setInvitationListener();
Mengjin Yan391d7242014-08-28 20:51:55 -0700236
237 m_discoveryLogic.sendDiscoveryInterest();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800238}
239
240void
241Controller::setInvitationListener()
242{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700243 if (m_invitationListenerId != 0)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800244 m_face->unsetInterestFilter(m_invitationListenerId);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700245
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800246 Name invitationPrefix;
247 Name routingPrefix = getInvitationRoutingPrefix();
248 size_t offset = 0;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700249 if (!routingPrefix.isPrefixOf(m_identity)) {
250 invitationPrefix.append(routingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2);
251 offset = routingPrefix.size() + 1;
252 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800253 invitationPrefix.append(m_identity).append("CHRONOCHAT-INVITATION");
254
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700255 m_invitationListenerId = m_face->setInterestFilter(invitationPrefix,
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700256 bind(&Controller::onInvitationInterestWrapper,
257 this, _1, _2, offset),
258 bind(&Controller::onInvitationRegisterFailed,
259 this, _1, _2));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800260}
261
262void
263Controller::loadConf()
264{
265 namespace fs = boost::filesystem;
266
267 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
268 fs::create_directories (chronosDir);
269
270 std::ifstream is((chronosDir / "config").c_str ());
271 ChronoChat::Conf conf;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700272 if (conf.ParseFromIstream(&is)) {
273 m_identity.clear();
274 m_identity.append(conf.identity());
275 if (conf.has_nick())
276 m_nick = conf.nick();
277 else
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800278 m_nick = m_identity.get(-1).toUri();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700279 }
280 else {
281 m_identity.clear();
282 // TODO: change below to system default;
283 m_identity.append("chronochat-tmp-identity")
284 .append(getRandomString());
285
286 m_nick = m_identity.get(-1).toUri();
287 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800288}
289
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700290void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800291Controller::saveConf()
292{
293 namespace fs = boost::filesystem;
294
295 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
296 fs::create_directories (chronosDir);
297
298 std::ofstream os((chronosDir / "config").c_str ());
299 ChronoChat::Conf conf;
300 conf.set_identity(m_identity.toUri());
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700301 if (!m_nick.empty())
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800302 conf.set_nick(m_nick);
303 conf.SerializeToOstream(&os);
304
305 os.close();
306}
307
308void
309Controller::createActions()
310{
311 m_startChatroom = new QAction(tr("Start new chat"), this);
312 connect(m_startChatroom, SIGNAL(triggered()), this, SLOT(onStartChatAction()));
313
Mengjin Yan391d7242014-08-28 20:51:55 -0700314 m_discoveryAction = new QAction(tr("Ongoing Chatrooms"), this);
315 connect(m_discoveryAction, SIGNAL(triggered()), this, SLOT(onDiscoveryAction()));
316
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800317 m_settingsAction = new QAction(tr("Settings"), this);
318 connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(onSettingsAction()));
319
320 m_editProfileAction = new QAction(tr("Edit profile"), this);
321 connect(m_editProfileAction, SIGNAL(triggered()), this, SLOT(onProfileEditorAction()));
322
323 m_contactListAction = new QAction(tr("Contact List"), this);
324 connect(m_contactListAction, SIGNAL(triggered()), this, SLOT(onContactListAction()));
325
326 m_addContactAction = new QAction(tr("Add contact"), this);
327 connect(m_addContactAction, SIGNAL(triggered()), this, SLOT(onAddContactAction()));
328
329 m_updateLocalPrefixAction = new QAction(tr("Update local prefix"), this);
330 connect(m_updateLocalPrefixAction, SIGNAL(triggered()), this, SLOT(onUpdateLocalPrefixAction()));
331
332 m_minimizeAction = new QAction(tr("Mi&nimize"), this);
333 connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(onMinimizeAction()));
334
335 m_quitAction = new QAction(tr("Quit"), this);
336 connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuitAction()));
Mengjin Yan391d7242014-08-28 20:51:55 -0700337
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800338}
339
340void
341Controller::createTrayIcon()
342{
343 createActions();
344
345 m_trayIconMenu = new QMenu(this);
346 m_trayIconMenu->addAction(m_startChatroom);
Mengjin Yan391d7242014-08-28 20:51:55 -0700347 m_trayIconMenu->addAction(m_discoveryAction);
348
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800349 m_trayIconMenu->addSeparator();
350 m_trayIconMenu->addAction(m_settingsAction);
351 m_trayIconMenu->addAction(m_editProfileAction);
352 m_trayIconMenu->addSeparator();
353 m_trayIconMenu->addAction(m_contactListAction);
354 m_trayIconMenu->addAction(m_addContactAction);
355 m_trayIconMenu->addSeparator();
356 m_trayIconMenu->addAction(m_updateLocalPrefixAction);
357 m_trayIconMenu->addSeparator();
358 m_trayIconMenu->addAction(m_minimizeAction);
359 m_closeMenu = m_trayIconMenu->addMenu("Close chatroom");
360 m_closeMenu->setEnabled(false);
361 m_trayIconMenu->addSeparator();
362 m_trayIconMenu->addAction(m_quitAction);
363
364 m_trayIcon = new QSystemTrayIcon(this);
365 m_trayIcon->setContextMenu(m_trayIconMenu);
366
367 m_trayIcon->setIcon(QIcon(":/images/icon_small.png"));
368 m_trayIcon->setToolTip("ChronoChat System Tray Icon");
369 m_trayIcon->setVisible(true);
370}
371
372void
373Controller::updateMenu()
374{
375 QMenu* menu = new QMenu(this);
376 QMenu* closeMenu = 0;
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700377
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800378 menu->addAction(m_startChatroom);
Mengjin Yan391d7242014-08-28 20:51:55 -0700379 menu->addAction(m_discoveryAction);
380
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800381 menu->addSeparator();
382 menu->addAction(m_settingsAction);
383 menu->addAction(m_editProfileAction);
384 menu->addSeparator();
Yingdi Yu233a9722014-03-07 15:47:09 -0800385 menu->addAction(m_contactListAction);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800386 menu->addAction(m_addContactAction);
387 menu->addSeparator();
388 {
389 ChatActionList::const_iterator it = m_chatActionList.begin();
390 ChatActionList::const_iterator end = m_chatActionList.end();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700391 if (it != end) {
392 for (; it != end; it++)
393 menu->addAction(it->second);
394 menu->addSeparator();
395 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800396 }
397 menu->addAction(m_updateLocalPrefixAction);
398 menu->addSeparator();
399 menu->addAction(m_minimizeAction);
400 closeMenu = menu->addMenu("Close chatroom");
401 {
402 ChatActionList::const_iterator it = m_closeActionList.begin();
403 ChatActionList::const_iterator end = m_closeActionList.end();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700404 if (it == end)
405 closeMenu->setEnabled(false);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800406 else
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700407 for (; it != end; it++)
408 closeMenu->addAction(it->second);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800409 }
410 menu->addSeparator();
411 menu->addAction(m_quitAction);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700412
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800413 m_trayIcon->setContextMenu(menu);
414 delete m_trayIconMenu;
415 m_trayIconMenu = menu;
416 m_closeMenu = closeMenu;
417}
418
419void
420Controller::onLocalPrefix(const Interest& interest, Data& data)
421{
Yingdi Yu106be862014-08-29 09:03:18 -0700422 QString localPrefixStr("/private/local");
423 Name prefix;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800424
Yingdi Yu106be862014-08-29 09:03:18 -0700425 Block contentBlock = data.getContent();
426 try {
427 contentBlock.parse();
428
429 for (Block::element_const_iterator it = contentBlock.elements_begin();
430 it != contentBlock.elements_end(); it++) {
431 Name candidate;
432 candidate.wireDecode(*it);
433 if (candidate.isPrefixOf(m_identity)) {
434 prefix = candidate;
435 break;
436 }
437 }
438
439 if (prefix.empty()) {
440 if (contentBlock.elements_begin() != contentBlock.elements_end())
441 prefix.wireDecode(*contentBlock.elements_begin());
442 else
443 prefix = Name("/private/local");
444 }
445
446 localPrefixStr = QString::fromStdString(prefix.toUri());
447 }
448 catch (Block::Error& e) {
449 prefix = Name("/private/local");
450 }
451
452 if (m_localPrefix.empty() || m_localPrefix != prefix) {
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800453 emit localPrefixUpdated(localPrefixStr);
Mengjin Yan391d7242014-08-28 20:51:55 -0700454 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800455}
456
457void
458Controller::onLocalPrefixTimeout(const Interest& interest)
459{
460 QString localPrefixStr("/private/local");
461
462 Name localPrefix(localPrefixStr.toStdString());
Mengjin Yan391d7242014-08-28 20:51:55 -0700463 if (m_localPrefix.empty() || m_localPrefix != localPrefix) {
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800464 emit localPrefixUpdated(localPrefixStr);
Mengjin Yan391d7242014-08-28 20:51:55 -0700465 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800466}
467
468void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700469Controller::onInvitationInterestWrapper(const Name& prefix,
470 const Interest& interest,
471 size_t routingPrefixOffset)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800472{
Yingdi Yu233a9722014-03-07 15:47:09 -0800473 emit invitationInterest(prefix, interest, routingPrefixOffset);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800474}
475
476void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700477Controller::onInvitationRegisterFailed(const Name& prefix, const string& failInfo)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800478{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700479 // _LOG_DEBUG("Controller::onInvitationRegisterFailed: " << failInfo);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800480}
481
482void
483Controller::onInvitationValidated(const shared_ptr<const Interest>& interest)
484{
485 Invitation invitation(interest->getName());
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700486 // Should be obtained via a method of ContactManager.
487 string alias = invitation.getInviterCertificate().getPublicKeyName().getPrefix(-1).toUri();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800488
489 m_invitationDialog->setInvitation(alias, invitation.getChatroom(), interest->getName());
490 m_invitationDialog->show();
491}
492
493void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700494Controller::onInvitationValidationFailed(const shared_ptr<const Interest>& interest,
495 string failureInfo)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800496{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700497 // _LOG_DEBUG("Invitation: " << interest->getName() <<
498 // " cannot not be validated due to: " << failureInfo);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800499}
500
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700501string
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800502Controller::getRandomString()
503{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700504 uint32_t r = ndn::random::generateWord32();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800505 std::stringstream ss;
506 {
507 using namespace CryptoPP;
508 StringSource(reinterpret_cast<uint8_t*>(&r), 4, true,
509 new HexEncoder(new FileSink(ss), false));
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700510
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800511 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700512 // for (int i = 0; i < 8; i++)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800513 // {
514 // uint32_t t = r & mask;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700515 // if (t < 10)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800516 // ss << static_cast<char>(t + 0x30);
517 // else
518 // ss << static_cast<char>(t + 0x57);
519 // r = r >> 4;
520 // }
521
522 return ss.str();
523}
524
525ndn::Name
526Controller::getInvitationRoutingPrefix()
527{
528 return Name("/ndn/broadcast");
529}
530
531void
532Controller::addChatDialog(const QString& chatroomName, ChatDialog* chatDialog)
533{
534 m_chatDialogList[chatroomName.toStdString()] = chatDialog;
Mengjin Yan391d7242014-08-28 20:51:55 -0700535 m_discoveryLogic.addLocalChatroom(*chatDialog->getChatroomInfo());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800536 connect(chatDialog, SIGNAL(closeChatDialog(const QString&)),
537 this, SLOT(onRemoveChatDialog(const QString&)));
538 connect(chatDialog, SIGNAL(showChatMessage(const QString&, const QString&, const QString&)),
539 this, SLOT(onShowChatMessage(const QString&, const QString&, const QString&)));
Yingdi Yu233a9722014-03-07 15:47:09 -0800540 connect(chatDialog, SIGNAL(resetIcon()),
541 this, SLOT(onResetIcon()));
Mengjin Yan391d7242014-08-28 20:51:55 -0700542 connect(chatDialog, SIGNAL(rosterChanged(const chronos::ChatroomInfo&)),
543 this, SLOT(onRosterChanged(const chronos::ChatroomInfo&)));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800544 connect(this, SIGNAL(localPrefixUpdated(const QString&)),
545 chatDialog, SLOT(onLocalPrefixUpdated(const QString&)));
546
547 QAction* chatAction = new QAction(chatroomName, this);
548 m_chatActionList[chatroomName.toStdString()] = chatAction;
Mengjin Yan391d7242014-08-28 20:51:55 -0700549 connect(chatAction, SIGNAL(triggered()),
Yingdi Yue8323b62014-09-02 17:24:15 -0700550 chatDialog, SLOT(onShow()));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800551
552 QAction* closeAction = new QAction(chatroomName, this);
553 m_closeActionList[chatroomName.toStdString()] = closeAction;
554 connect(closeAction, SIGNAL(triggered()), chatDialog, SLOT(onClose()));
555
556 updateMenu();
557}
558
Mengjin Yan391d7242014-08-28 20:51:55 -0700559void
560Controller::updateDiscoveryList(const ChatroomInfo& info, bool isAdd)
561{
562 emit discoverChatroomChanged(info, isAdd);
563}
564
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800565void
566Controller::onIdentityUpdated(const QString& identity)
567{
568 Name identityName(identity.toStdString());
569
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700570 while (!m_chatDialogList.empty()) {
571 ChatDialogList::const_iterator it = m_chatDialogList.begin();
572 onRemoveChatDialog(QString::fromStdString(it->first));
573 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800574
575 m_identity = identityName;
576 m_keyChain.createIdentity(m_identity);
Yingdi Yu233a9722014-03-07 15:47:09 -0800577 setInvitationListener();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800578
579 emit closeDBModule();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700580
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800581 QTimer::singleShot(500, this, SLOT(onIdentityUpdatedContinued()));
582
583}
584
585void
586Controller::onIdentityUpdatedContinued()
587{
588 QString connection = m_db.connectionName();
589 // _LOG_DEBUG("connection name: " << connection.toStdString());
590 QSqlDatabase::removeDatabase(connection);
591 m_db.close();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700592
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800593 openDB();
594
595 emit identityUpdated(QString(m_identity.toUri().c_str()));
596}
597
598void
599Controller::onContactIdListReady(const QStringList& list)
600{
601 ContactList contactList;
602
603 m_contactManager.getContactList(contactList);
604 m_validator.cleanTrustAnchor();
605
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700606 for (ContactList::const_iterator it = contactList.begin(); it != contactList.end(); it++)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800607 m_validator.addTrustAnchor((*it)->getPublicKeyName(), (*it)->getPublicKey());
608
609}
610
611void
612Controller::onNickUpdated(const QString& nick)
613{
614 m_nick = nick.toStdString();
615}
616
617void
618Controller::onLocalPrefixUpdated(const QString& localPrefix)
619{
620 m_localPrefix = Name(localPrefix.toStdString());
621}
622
623void
624Controller::onStartChatAction()
625{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700626 string chatroom = "chatroom-" + getRandomString();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800627
628 m_startChatDialog->setChatroom(chatroom);
629 m_startChatDialog->show();
630 m_startChatDialog->raise();
631}
632
633void
Mengjin Yan391d7242014-08-28 20:51:55 -0700634Controller::onDiscoveryAction()
635{
636 m_discoveryLogic.sendDiscoveryInterest();
637
638 m_chatroomDiscoveryDialog->updateChatroomList();
639 m_chatroomDiscoveryDialog->show();
640 m_chatroomDiscoveryDialog->raise();
641}
642
643
644void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800645Controller::onSettingsAction()
646{
647 m_settingDialog->setNick(QString(m_nick.c_str()));
648 m_settingDialog->show();
649 m_settingDialog->raise();
650}
651
652void
653Controller::onProfileEditorAction()
654{
655 m_profileEditor->show();
656 m_profileEditor->raise();
657}
658
659void
660Controller::onAddContactAction()
661{
662 emit refreshBrowseContact();
663 m_browseContactDialog->show();
664 m_browseContactDialog->raise();
665}
666
667void
668Controller::onContactListAction()
669{
670 m_contactPanel->show();
671 m_contactPanel->raise();
672}
673
674void
675Controller::onDirectAdd()
676{
677 m_addContactPanel->show();
678 m_addContactPanel->raise();
679}
680
681void
682Controller::onUpdateLocalPrefixAction()
683{
684 // Name interestName();
Yingdi Yu106be862014-08-29 09:03:18 -0700685 Interest interest("/localhop/ndn-autoconf/routable-prefixes");
Yingdi Yua7876722014-03-25 14:46:55 -0700686 interest.setInterestLifetime(time::milliseconds(1000));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800687 interest.setMustBeFresh(true);
688
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700689 m_face->expressInterest(interest,
690 bind(&Controller::onLocalPrefix, this, _1, _2),
691 bind(&Controller::onLocalPrefixTimeout, this, _1));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800692}
693
694void
695Controller::onMinimizeAction()
696{
697 m_settingDialog->hide();
698 m_startChatDialog->hide();
699 m_profileEditor->hide();
700 m_invitationDialog->hide();
701 m_addContactPanel->hide();
702
703 ChatDialogList::iterator it = m_chatDialogList.begin();
704 ChatDialogList::iterator end = m_chatDialogList.end();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700705 for (; it != end; it++)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800706 it->second->hide();
707}
708
709void
710Controller::onQuitAction()
711{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700712 while (!m_chatDialogList.empty()) {
713 ChatDialogList::const_iterator it = m_chatDialogList.begin();
714 onRemoveChatDialog(QString::fromStdString(it->first));
715 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800716
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700717 if (m_invitationListenerId != 0)
Yingdi Yu233a9722014-03-07 15:47:09 -0800718 m_face->unsetInterestFilter(m_invitationListenerId);
719
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800720 delete m_settingDialog;
721 delete m_startChatDialog;
722 delete m_profileEditor;
723 delete m_invitationDialog;
Yingdi Yuf4aaa8b2014-03-10 11:24:31 -0700724 delete m_browseContactDialog;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800725 delete m_addContactPanel;
Yingdi Yuf4aaa8b2014-03-10 11:24:31 -0700726
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700727 m_face->getIoService().stop();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800728
729 QApplication::quit();
730}
731
732void
733Controller::onStartChatroom(const QString& chatroomName, bool secured)
734{
735 Name chatroomPrefix;
736 chatroomPrefix.append("ndn")
737 .append("broadcast")
738 .append("ChronoChat")
739 .append(chatroomName.toStdString());
740
741 // check if the chatroom exists
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700742 if (m_chatDialogList.find(chatroomName.toStdString()) != m_chatDialogList.end()) {
743 QMessageBox::information(this, tr("ChronoChat"),
744 tr("You are creating an existing chatroom."
745 "You can check it in the context memu."));
746 return;
747 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800748
Mengjin Yan391d7242014-08-28 20:51:55 -0700749 // TODO: We should create a chatroom specific key/cert
750 //(which should be created in the first half of this method
751 //, but let's use the default one for now.
752 // std::cout << "start chat room localprefix: " << m_localPrefix.toUri() << std::endl;
753 shared_ptr<IdentityCertificate> idCert
754 = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
755 ChatDialog* chatDialog
756 = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix
757 , m_localPrefix, m_nick, secured);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800758
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700759 addChatDialog(chatroomName, chatDialog);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800760 chatDialog->show();
761}
762
763void
Mengjin Yan391d7242014-08-28 20:51:55 -0700764Controller::onInvitationResponded(const ndn::Name& invitationName, bool accepted)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800765{
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700766 shared_ptr<Data> response = make_shared<Data>();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800767 shared_ptr<IdentityCertificate> chatroomCert;
768
769 // generate reply;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700770 if (accepted) {
771 Name responseName = invitationName;
772 responseName.append(m_localPrefix.wireEncode());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800773
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700774 response->setName(responseName);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800775
Mengjin Yan391d7242014-08-28 20:51:55 -0700776 // We should create a particular certificate for this chatroom,
777 //but let's use default one for now.
778 chatroomCert
779 = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800780
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700781 response->setContent(chatroomCert->wireEncode());
782 response->setFreshnessPeriod(time::milliseconds(1000));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700783 }
784 else {
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700785 response->setName(invitationName);
786 response->setFreshnessPeriod(time::milliseconds(1000));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700787 }
788
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700789 m_keyChain.signByIdentity(*response, m_identity);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700790
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800791 // Check if we need a wrapper
792 Name invitationRoutingPrefix = getInvitationRoutingPrefix();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700793 if (invitationRoutingPrefix.isPrefixOf(m_identity))
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700794 m_face->put(*response);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700795 else {
796 Name wrappedName;
797 wrappedName.append(invitationRoutingPrefix)
798 .append(ROUTING_PREFIX_SEPARATOR, 2)
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700799 .append(response->getName());
Yingdi Yu233a9722014-03-07 15:47:09 -0800800
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700801 // _LOG_DEBUG("onInvitationResponded: prepare reply " << wrappedName);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700802
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700803 shared_ptr<Data> wrappedData = make_shared<Data>(wrappedName);
804 wrappedData->setContent(response->wireEncode());
805 wrappedData->setFreshnessPeriod(time::milliseconds(1000));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800806
Yingdi Yu6c3c5962014-09-09 16:52:38 -0700807 m_keyChain.signByIdentity(*wrappedData, m_identity);
808 m_face->put(*wrappedData);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700809 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800810
811 // create chatroom
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700812 if (accepted) {
813 Invitation invitation(invitationName);
814 Name chatroomPrefix;
815 chatroomPrefix.append("ndn")
816 .append("broadcast")
817 .append("ChronoChat")
818 .append(invitation.getChatroom());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800819
Mengjin Yan391d7242014-08-28 20:51:55 -0700820 //We should create a chatroom specific key/cert
821 //(which should be created in the first half of this method,
822 //but let's use the default one for now.
823 shared_ptr<IdentityCertificate> idCert
824 = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
825 ChatDialog* chatDialog
826 = new ChatDialog(&m_contactManager, m_face, *idCert,
827 chatroomPrefix, m_localPrefix, m_nick, true);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700828 chatDialog->addSyncAnchor(invitation);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800829
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700830 addChatDialog(QString::fromStdString(invitation.getChatroom()), chatDialog);
831 chatDialog->show();
832 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800833}
834
835void
836Controller::onShowChatMessage(const QString& chatroomName, const QString& from, const QString& data)
837{
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700838 m_trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(chatroomName),
839 QString("<%1>: %2").arg(from).arg(data),
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800840 QSystemTrayIcon::Information, 20000);
841 m_trayIcon->setIcon(QIcon(":/images/note.png"));
842}
843
844void
Yingdi Yu233a9722014-03-07 15:47:09 -0800845Controller::onResetIcon()
846{
847 m_trayIcon->setIcon(QIcon(":/images/icon_small.png"));
848}
849
850void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800851Controller::onRemoveChatDialog(const QString& chatroomName)
852{
853 ChatDialogList::iterator it = m_chatDialogList.find(chatroomName.toStdString());
854
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700855 if (it != m_chatDialogList.end()) {
856 ChatDialog* deletedChat = it->second;
857 if (deletedChat)
858 delete deletedChat;
859 m_chatDialogList.erase(it);
Mengjin Yan391d7242014-08-28 20:51:55 -0700860 m_discoveryLogic.removeLocalChatroom(Name::Component(chatroomName.toStdString()));
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800861
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700862 QAction* chatAction = m_chatActionList[chatroomName.toStdString()];
863 QAction* closeAction = m_closeActionList[chatroomName.toStdString()];
864 if (chatAction)
865 delete chatAction;
866 if (closeAction)
867 delete closeAction;
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700868
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700869 m_chatActionList.erase(chatroomName.toStdString());
870 m_closeActionList.erase(chatroomName.toStdString());
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700871
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700872 updateMenu();
873 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800874}
875
876void
877Controller::onWarning(const QString& msg)
878{
879 QMessageBox::information(this, tr("ChronoChat"), msg);
880}
881
882void
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700883Controller::onError(const QString& msg)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800884{
885 QMessageBox::critical(this, tr("ChronoChat"), msg, QMessageBox::Ok);
886 exit(1);
887}
888
Yingdi Yu233a9722014-03-07 15:47:09 -0800889void
Mengjin Yan391d7242014-08-28 20:51:55 -0700890Controller::onInvitationInterest(const ndn::Name& prefix,
891 const ndn::Interest& interest,
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700892 size_t routingPrefixOffset)
Yingdi Yu233a9722014-03-07 15:47:09 -0800893{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700894 // _LOG_DEBUG("onInvitationInterest: " << interest.getName());
895 shared_ptr<Interest> invitationInterest =
896 make_shared<Interest>(boost::cref(interest.getName().getSubName(routingPrefixOffset)));
Yingdi Yu233a9722014-03-07 15:47:09 -0800897
898 // check if the chatroom already exists;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700899 try {
Yingdi Yu233a9722014-03-07 15:47:09 -0800900 Invitation invitation(invitationInterest->getName());
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700901 if (m_chatDialogList.find(invitation.getChatroom()) != m_chatDialogList.end())
Yingdi Yu233a9722014-03-07 15:47:09 -0800902 return;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700903 }
904 catch (Invitation::Error& e) {
905 // Cannot parse the invitation;
906 return;
907 }
Yingdi Yu233a9722014-03-07 15:47:09 -0800908
909 OnInterestValidated onValidated = bind(&Controller::onInvitationValidated, this, _1);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700910 OnInterestValidationFailed onValidationFailed = bind(&Controller::onInvitationValidationFailed,
911 this, _1, _2);
Yingdi Yu233a9722014-03-07 15:47:09 -0800912 m_validator.validate(*invitationInterest, onValidated, onValidationFailed);
913}
914
Mengjin Yan391d7242014-08-28 20:51:55 -0700915void
916Controller::onRosterChanged(const chronos::ChatroomInfo& info)
917{
918 m_discoveryLogic.addLocalChatroom(info);
919}
920
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800921} // namespace chronos
922
923#if WAF
924#include "controller.moc"
Yingdi Yu42125862014-08-07 17:04:28 -0700925// #include "controller.cpp.moc"
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800926#endif