blob: ff1a51e9f165090043938444d455a952d395f8fd [file] [log] [blame]
Yingdi Yud45777b2014-10-16 23:54:11 -07001/* -*- 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>
Yingdi Yuf3401182015-02-02 20:21:07 -08009 * Qiuhan Ding <qiuhanding@cs.ucla.edu>
Yingdi Yud45777b2014-10-16 23:54:11 -070010 */
11
12#include "chat-dialog-backend.hpp"
13
Yingdi Yu45da92a2015-02-02 13:17:03 -080014#include <QFile>
15
Yingdi Yud45777b2014-10-16 23:54:11 -070016#ifndef Q_MOC_RUN
17#include <ndn-cxx/util/io.hpp>
Yingdi Yu45da92a2015-02-02 13:17:03 -080018#include <ndn-cxx/security/validator-regex.hpp>
Yingdi Yud45777b2014-10-16 23:54:11 -070019#include "logging.h"
20#endif
21
22
23INIT_LOGGER("ChatDialogBackend");
24
Yingdi Yueb692ac2015-02-10 18:46:18 -080025namespace chronochat {
Yingdi Yud45777b2014-10-16 23:54:11 -070026
27static const time::milliseconds FRESHNESS_PERIOD(60000);
28static const time::seconds HELLO_INTERVAL(60);
Qiuhan Dingba3e57a2015-01-08 19:07:39 -080029static const ndn::Name::Component ROUTING_HINT_SEPARATOR =
30 ndn::name::Component::fromEscapedString("%F0%2E");
Qiuhan Ding43c8e162015-02-02 15:16:48 -080031static const int IDENTITY_OFFSET = -3;
Yingdi Yuf3401182015-02-02 20:21:07 -080032static const int CONNECTION_RETRY_TIMER = 3;
Yingdi Yud45777b2014-10-16 23:54:11 -070033
34ChatDialogBackend::ChatDialogBackend(const Name& chatroomPrefix,
35 const Name& userChatPrefix,
36 const Name& routingPrefix,
37 const std::string& chatroomName,
38 const std::string& nick,
Yingdi Yu45da92a2015-02-02 13:17:03 -080039 const Name& signingId,
Yingdi Yud45777b2014-10-16 23:54:11 -070040 QObject* parent)
41 : QThread(parent)
Yingdi Yuf3401182015-02-02 20:21:07 -080042 , m_shouldResume(false)
Yingdi Yud45777b2014-10-16 23:54:11 -070043 , m_localRoutingPrefix(routingPrefix)
44 , m_chatroomPrefix(chatroomPrefix)
45 , m_userChatPrefix(userChatPrefix)
46 , m_chatroomName(chatroomName)
47 , m_nick(nick)
Yingdi Yu45da92a2015-02-02 13:17:03 -080048 , m_signingId(signingId)
Yingdi Yud45777b2014-10-16 23:54:11 -070049{
50 updatePrefixes();
51}
52
53
54ChatDialogBackend::~ChatDialogBackend()
55{
56}
57
58// protected methods:
59void
60ChatDialogBackend::run()
61{
Yingdi Yu4647f022015-02-01 00:26:38 -080062 bool shouldResume = false;
63 do {
64 initializeSync();
Yingdi Yud45777b2014-10-16 23:54:11 -070065
Yingdi Yu4647f022015-02-01 00:26:38 -080066 if (m_face == nullptr)
67 break;
68
Yingdi Yuf3401182015-02-02 20:21:07 -080069 try {
70 m_face->getIoService().run();
71 }
72 catch (std::runtime_error& e) {
73 {
74 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
75 m_isNfdConnected = false;
76 }
77 emit nfdError();
78 {
79 std::lock_guard<std::mutex>lock(m_resumeMutex);
80 m_shouldResume = true;
81 }
82#ifdef BOOST_THREAD_USES_CHRONO
83 time::seconds reconnectTimer = time::seconds(CONNECTION_RETRY_TIMER);
84#else
85 boost::posix_time::time_duration reconnectTimer;
86 reconnectTimer = boost::posix_time::seconds(CONNECTION_RETRY_TIMER);
87#endif
88 while (!m_isNfdConnected) {
89#ifdef BOOST_THREAD_USES_CHRONO
90 boost::this_thread::sleep_for(reconnectTimer);
91#else
92 boost::this_thread::sleep(reconnectTimer);
93#endif
94 }
95 emit refreshChatDialog(m_routableUserChatPrefix);
96 }
Qiuhan Dingf22c41b2015-03-11 13:19:01 -070097 {
Yingdi Yuf3401182015-02-02 20:21:07 -080098 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -070099 shouldResume = m_shouldResume;
100 m_shouldResume = false;
101 }
Yingdi Yuf3401182015-02-02 20:21:07 -0800102 close();
Yingdi Yu4647f022015-02-01 00:26:38 -0800103
104 } while (shouldResume);
Yingdi Yud45777b2014-10-16 23:54:11 -0700105
106 std::cerr << "Bye!" << std::endl;
107}
108
109// private methods:
110void
111ChatDialogBackend::initializeSync()
112{
Yingdi Yu4647f022015-02-01 00:26:38 -0800113 BOOST_ASSERT(m_sock == nullptr);
Yingdi Yud45777b2014-10-16 23:54:11 -0700114
Yingdi Yu45da92a2015-02-02 13:17:03 -0800115 m_face = make_shared<ndn::Face>();
Yingdi Yu4647f022015-02-01 00:26:38 -0800116 m_scheduler = unique_ptr<ndn::Scheduler>(new ndn::Scheduler(m_face->getIoService()));
Yingdi Yud45777b2014-10-16 23:54:11 -0700117
Yingdi Yu45da92a2015-02-02 13:17:03 -0800118 // initialize validator
119 shared_ptr<ndn::IdentityCertificate> anchor = loadTrustAnchor();
120
121 if (static_cast<bool>(anchor)) {
122 shared_ptr<ndn::ValidatorRegex> validator =
123 make_shared<ndn::ValidatorRegex>(m_face.get()); // TODO: Change to Face*
124 validator->addDataVerificationRule(
125 make_shared<ndn::SecRuleRelative>("^<>*<%F0.>(<>*)$",
126 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
127 ">", "\\1", "\\1\\2", true));
128 validator->addDataVerificationRule(
129 make_shared<ndn::SecRuleRelative>("(<>*)$",
130 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
131 ">", "\\1", "\\1\\2", true));
132 validator->addTrustAnchor(anchor);
133
134 m_validator = validator;
135 }
136 else
137 m_validator = shared_ptr<ndn::Validator>();
138
139
Yingdi Yud45777b2014-10-16 23:54:11 -0700140 // create a new SyncSocket
141 m_sock = make_shared<chronosync::Socket>(m_chatroomPrefix,
142 m_routableUserChatPrefix,
Yingdi Yu4647f022015-02-01 00:26:38 -0800143 ref(*m_face),
Yingdi Yu45da92a2015-02-02 13:17:03 -0800144 bind(&ChatDialogBackend::processSyncUpdate, this, _1),
145 m_signingId,
146 m_validator);
Yingdi Yud45777b2014-10-16 23:54:11 -0700147
148 // schedule a new join event
Yingdi Yu4647f022015-02-01 00:26:38 -0800149 m_scheduler->scheduleEvent(time::milliseconds(600),
150 bind(&ChatDialogBackend::sendJoin, this));
Yingdi Yud45777b2014-10-16 23:54:11 -0700151
152 // cancel existing hello event if it exists
Yingdi Yu4647f022015-02-01 00:26:38 -0800153 if (m_helloEventId != nullptr) {
154 m_scheduler->cancelEvent(m_helloEventId);
Yingdi Yud45777b2014-10-16 23:54:11 -0700155 m_helloEventId.reset();
156 }
157}
158
Yingdi Yu45da92a2015-02-02 13:17:03 -0800159class IoDeviceSource
160{
161public:
162 typedef char char_type;
163 typedef boost::iostreams::source_tag category;
164
165 explicit
166 IoDeviceSource(QIODevice& source)
167 : m_source(source)
168 {
169 }
170
171 std::streamsize
172 read(char* buffer, std::streamsize n)
173 {
174 return m_source.read(buffer, n);
175 }
176private:
177 QIODevice& m_source;
178};
179
180shared_ptr<ndn::IdentityCertificate>
181ChatDialogBackend::loadTrustAnchor()
182{
183 QFile anchorFile(":/security/anchor.cert");
184
185 if (!anchorFile.open(QIODevice::ReadOnly)) {
186 return {};
187 }
188
189 boost::iostreams::stream<IoDeviceSource> anchorFileStream(anchorFile);
190 return ndn::io::load<ndn::IdentityCertificate>(anchorFileStream);
191}
192
Yingdi Yud45777b2014-10-16 23:54:11 -0700193void
Yingdi Yuf3401182015-02-02 20:21:07 -0800194ChatDialogBackend::exitChatroom() {
Yingdi Yu4647f022015-02-01 00:26:38 -0800195 if (m_joined)
196 sendLeave();
197
198 usleep(100000);
Yingdi Yuf3401182015-02-02 20:21:07 -0800199}
Yingdi Yu4647f022015-02-01 00:26:38 -0800200
Yingdi Yuf3401182015-02-02 20:21:07 -0800201void
202ChatDialogBackend::close()
203{
Yingdi Yu4647f022015-02-01 00:26:38 -0800204 m_scheduler->cancelAllEvents();
205 m_helloEventId.reset();
206 m_roster.clear();
Yingdi Yu45da92a2015-02-02 13:17:03 -0800207 m_validator.reset();
Yingdi Yu4647f022015-02-01 00:26:38 -0800208 m_sock.reset();
209}
210
211void
Yingdi Yud45777b2014-10-16 23:54:11 -0700212ChatDialogBackend::processSyncUpdate(const std::vector<chronosync::MissingDataInfo>& updates)
213{
214 _LOG_DEBUG("<<< processing Tree Update");
215
216 if (updates.empty()) {
217 return;
218 }
219
220 std::vector<NodeInfo> nodeInfos;
221
222
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800223 for (size_t i = 0; i < updates.size(); i++) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700224 // update roster
225 if (m_roster.find(updates[i].session) == m_roster.end()) {
226 m_roster[updates[i].session].sessionPrefix = updates[i].session;
227 m_roster[updates[i].session].hasNick = false;
228 }
229
230 // fetch missing chat data
231 if (updates[i].high - updates[i].low < 3) {
232 for (chronosync::SeqNo seq = updates[i].low; seq <= updates[i].high; ++seq) {
233 m_sock->fetchData(updates[i].session, seq,
Yingdi Yu45da92a2015-02-02 13:17:03 -0800234 [this] (const shared_ptr<const ndn::Data>& data) {
235 this->processChatData(data, true, true);
236 },
237 [this] (const shared_ptr<const ndn::Data>& data, const std::string& msg) {
238 this->processChatData(data, true, false);
239 },
240 ndn::OnTimeout(),
Yingdi Yud45777b2014-10-16 23:54:11 -0700241 2);
242 _LOG_DEBUG("<<< Fetching " << updates[i].session << "/" << seq);
243 }
244 }
245 else {
246 // There are too many msgs to fetch, let's just fetch the latest one
247 m_sock->fetchData(updates[i].session, updates[i].high,
Yingdi Yu45da92a2015-02-02 13:17:03 -0800248 [this] (const shared_ptr<const ndn::Data>& data) {
249 this->processChatData(data, false, true);
250 },
251 [this] (const shared_ptr<const ndn::Data>& data, const std::string& msg) {
252 this->processChatData(data, false, false);
253 },
254 ndn::OnTimeout(),
Yingdi Yud45777b2014-10-16 23:54:11 -0700255 2);
256 }
257
Yingdi Yud45777b2014-10-16 23:54:11 -0700258 }
259
260 // reflect the changes on GUI
261 emit syncTreeUpdated(nodeInfos,
262 QString::fromStdString(getHexEncodedDigest(m_sock->getRootDigest())));
263}
264
265void
Yingdi Yu45da92a2015-02-02 13:17:03 -0800266ChatDialogBackend::processChatData(const ndn::shared_ptr<const ndn::Data>& data,
267 bool needDisplay,
268 bool isValidated)
Yingdi Yud45777b2014-10-16 23:54:11 -0700269{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800270 ChatMessage msg;
Yingdi Yud45777b2014-10-16 23:54:11 -0700271
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800272 try {
273 msg.wireDecode(data->getContent().blockFromValue());
274 }
275 catch (tlv::Error) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700276 _LOG_DEBUG("Errrrr.. Can not parse msg with name: " <<
277 data->getName() << ". what is happening?");
278 // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800279 msg.setNick("inconnu");
280 msg.setMsgType(ChatMessage::OTHER);
Yingdi Yud45777b2014-10-16 23:54:11 -0700281 return;
282 }
283
284 Name remoteSessionPrefix = data->getName().getPrefix(-1);
285
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800286 if (msg.getMsgType() == ChatMessage::LEAVE) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700287 BackendRoster::iterator it = m_roster.find(remoteSessionPrefix);
288
289 if (it != m_roster.end()) {
290 // cancel timeout event
291 if (static_cast<bool>(it->second.timeoutEventId))
Yingdi Yu4647f022015-02-01 00:26:38 -0800292 m_scheduler->cancelEvent(it->second.timeoutEventId);
Yingdi Yud45777b2014-10-16 23:54:11 -0700293
294 // notify frontend to remove the remote session (node)
295 emit sessionRemoved(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800296 QString::fromStdString(msg.getNick()),
297 msg.getTimestamp());
Yingdi Yud45777b2014-10-16 23:54:11 -0700298
299 // remove roster entry
300 m_roster.erase(remoteSessionPrefix);
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800301
302 emit eraseInRoster(remoteSessionPrefix.getPrefix(IDENTITY_OFFSET),
303 Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700304 }
305 }
306 else {
307 BackendRoster::iterator it = m_roster.find(remoteSessionPrefix);
308
309 if (it == m_roster.end()) {
310 // Should not happen
311 BOOST_ASSERT(false);
312 }
313
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800314 uint64_t seqNo = data->getName().get(-1).toNumber();
Yingdi Yud45777b2014-10-16 23:54:11 -0700315
316 // If a timeout event has been scheduled, cancel it.
317 if (static_cast<bool>(it->second.timeoutEventId))
Yingdi Yu4647f022015-02-01 00:26:38 -0800318 m_scheduler->cancelEvent(it->second.timeoutEventId);
Yingdi Yud45777b2014-10-16 23:54:11 -0700319
320 // (Re)schedule another timeout event after 3 HELLO_INTERVAL;
321 it->second.timeoutEventId =
Yingdi Yu4647f022015-02-01 00:26:38 -0800322 m_scheduler->scheduleEvent(HELLO_INTERVAL * 3,
323 bind(&ChatDialogBackend::remoteSessionTimeout,
324 this, remoteSessionPrefix));
Yingdi Yud45777b2014-10-16 23:54:11 -0700325
326 // If chat message, notify the frontend
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800327 if (msg.getMsgType() == ChatMessage::CHAT) {
Yingdi Yu45da92a2015-02-02 13:17:03 -0800328 if (isValidated)
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800329 emit chatMessageReceived(QString::fromStdString(msg.getNick()),
330 QString::fromStdString(msg.getData()),
331 msg.getTimestamp());
Yingdi Yu45da92a2015-02-02 13:17:03 -0800332 else
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800333 emit chatMessageReceived(QString::fromStdString(msg.getNick() + " (Unverified)"),
334 QString::fromStdString(msg.getData()),
335 msg.getTimestamp());
Yingdi Yu45da92a2015-02-02 13:17:03 -0800336 }
Yingdi Yud45777b2014-10-16 23:54:11 -0700337
338 // Notify frontend to plot notification on DigestTree.
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800339
340 // If we haven't got any message from this session yet.
341 if (m_roster[remoteSessionPrefix].hasNick == false) {
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800342 m_roster[remoteSessionPrefix].userNick = msg.getNick();
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800343 m_roster[remoteSessionPrefix].hasNick = true;
344
345 emit messageReceived(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800346 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800347 seqNo,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800348 msg.getTimestamp(),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800349 true);
350
351 emit addInRoster(remoteSessionPrefix.getPrefix(IDENTITY_OFFSET),
352 Name::Component(m_chatroomName));
353 }
354 else
355 emit messageReceived(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800356 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800357 seqNo,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800358 msg.getTimestamp(),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800359 false);
Yingdi Yud45777b2014-10-16 23:54:11 -0700360 }
361}
362
363void
364ChatDialogBackend::remoteSessionTimeout(const Name& sessionPrefix)
365{
366 time_t timestamp =
367 static_cast<time_t>(time::toUnixTimestamp(time::system_clock::now()).count() / 1000);
368
369 // notify frontend
370 emit sessionRemoved(QString::fromStdString(sessionPrefix.toUri()),
371 QString::fromStdString(m_roster[sessionPrefix].userNick),
372 timestamp);
373
374 // remove roster entry
375 m_roster.erase(sessionPrefix);
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800376
377 emit eraseInRoster(sessionPrefix.getPrefix(IDENTITY_OFFSET),
378 Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700379}
380
381void
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800382ChatDialogBackend::sendMsg(ChatMessage& msg)
Yingdi Yud45777b2014-10-16 23:54:11 -0700383{
384 // send msg
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800385 ndn::Block buf = msg.wireEncode();
Yingdi Yud45777b2014-10-16 23:54:11 -0700386
387 uint64_t nextSequence = m_sock->getLogic().getSeqNo() + 1;
388
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800389 m_sock->publishData(buf.wire(), buf.size(), FRESHNESS_PERIOD);
Yingdi Yud45777b2014-10-16 23:54:11 -0700390
391 std::vector<NodeInfo> nodeInfos;
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800392 Name sessionName = m_sock->getLogic().getSessionName();
393 NodeInfo nodeInfo = {QString::fromStdString(sessionName.toUri()),
Yingdi Yud45777b2014-10-16 23:54:11 -0700394 nextSequence};
395 nodeInfos.push_back(nodeInfo);
396
397 emit syncTreeUpdated(nodeInfos,
398 QString::fromStdString(getHexEncodedDigest(m_sock->getRootDigest())));
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800399
400 emit messageReceived(QString::fromStdString(sessionName.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800401 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800402 nextSequence,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800403 msg.getTimestamp(),
404 msg.getMsgType() == ChatMessage::JOIN);
Yingdi Yud45777b2014-10-16 23:54:11 -0700405}
406
407void
408ChatDialogBackend::sendJoin()
409{
410 m_joined = true;
411
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800412 ChatMessage msg;
413 prepareControlMessage(msg, ChatMessage::JOIN);
Yingdi Yud45777b2014-10-16 23:54:11 -0700414 sendMsg(msg);
415
Yingdi Yu4647f022015-02-01 00:26:38 -0800416 m_helloEventId = m_scheduler->scheduleEvent(HELLO_INTERVAL,
417 bind(&ChatDialogBackend::sendHello, this));
Yingdi Yuf3401182015-02-02 20:21:07 -0800418 emit newChatroomForDiscovery(Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700419}
420
421void
422ChatDialogBackend::sendHello()
423{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800424 ChatMessage msg;
425 prepareControlMessage(msg, ChatMessage::HELLO);
Yingdi Yud45777b2014-10-16 23:54:11 -0700426 sendMsg(msg);
427
Yingdi Yu4647f022015-02-01 00:26:38 -0800428 m_helloEventId = m_scheduler->scheduleEvent(HELLO_INTERVAL,
429 bind(&ChatDialogBackend::sendHello, this));
Yingdi Yud45777b2014-10-16 23:54:11 -0700430}
431
432void
433ChatDialogBackend::sendLeave()
434{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800435 ChatMessage msg;
436 prepareControlMessage(msg, ChatMessage::LEAVE);
Yingdi Yud45777b2014-10-16 23:54:11 -0700437 sendMsg(msg);
438
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800439 // get my own identity with routable prefix by getPrefix(-2)
440 emit eraseInRoster(m_routableUserChatPrefix.getPrefix(-2),
441 Name::Component(m_chatroomName));
442
Yingdi Yud45777b2014-10-16 23:54:11 -0700443 usleep(5000);
444 m_joined = false;
445}
446
447void
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800448ChatDialogBackend::prepareControlMessage(ChatMessage& msg,
449 ChatMessage::ChatMessageType type)
Yingdi Yud45777b2014-10-16 23:54:11 -0700450{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800451 msg.setNick(m_nick);
452 msg.setChatroomName(m_chatroomName);
Yingdi Yud45777b2014-10-16 23:54:11 -0700453 int32_t seconds =
454 static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count() / 1000);
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800455 msg.setTimestamp(seconds);
456 msg.setMsgType(type);
Yingdi Yud45777b2014-10-16 23:54:11 -0700457}
458
459void
460ChatDialogBackend::prepareChatMessage(const QString& text,
461 time_t timestamp,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800462 ChatMessage &msg)
Yingdi Yud45777b2014-10-16 23:54:11 -0700463{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800464 msg.setNick(m_nick);
465 msg.setChatroomName(m_chatroomName);
466 msg.setData(text.toStdString());
467 msg.setTimestamp(timestamp);
468 msg.setMsgType(ChatMessage::CHAT);
Yingdi Yud45777b2014-10-16 23:54:11 -0700469}
470
471void
472ChatDialogBackend::updatePrefixes()
473{
474 m_routableUserChatPrefix.clear();
475
476 if (m_localRoutingPrefix.isPrefixOf(m_userChatPrefix))
477 m_routableUserChatPrefix = m_userChatPrefix;
478 else
479 m_routableUserChatPrefix.append(m_localRoutingPrefix)
Qiuhan Dingba3e57a2015-01-08 19:07:39 -0800480 .append(ROUTING_HINT_SEPARATOR)
Yingdi Yud45777b2014-10-16 23:54:11 -0700481 .append(m_userChatPrefix);
482
483 emit chatPrefixChanged(m_routableUserChatPrefix);
484}
485
486std::string
487ChatDialogBackend::getHexEncodedDigest(ndn::ConstBufferPtr digest)
488{
489 std::stringstream os;
490
491 CryptoPP::StringSource(digest->buf(), digest->size(), true,
492 new CryptoPP::HexEncoder(new CryptoPP::FileSink(os), false));
493 return os.str();
494}
495
496
497// public slots:
498void
499ChatDialogBackend::sendChatMessage(QString text, time_t timestamp)
500{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800501 ChatMessage msg;
Yingdi Yud45777b2014-10-16 23:54:11 -0700502 prepareChatMessage(text, timestamp, msg);
503 sendMsg(msg);
504
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800505 emit chatMessageReceived(QString::fromStdString(msg.getNick()),
506 QString::fromStdString(msg.getData()),
507 msg.getTimestamp());
Yingdi Yud45777b2014-10-16 23:54:11 -0700508}
509
510void
511ChatDialogBackend::updateRoutingPrefix(const QString& localRoutingPrefix)
512{
513 Name newLocalRoutingPrefix(localRoutingPrefix.toStdString());
514
515 if (!newLocalRoutingPrefix.empty() && newLocalRoutingPrefix != m_localRoutingPrefix) {
516 // Update localPrefix
517 m_localRoutingPrefix = newLocalRoutingPrefix;
518
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700519 {
Yingdi Yuf3401182015-02-02 20:21:07 -0800520 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700521 m_shouldResume = true;
522 }
Yingdi Yu4647f022015-02-01 00:26:38 -0800523
Yingdi Yuf3401182015-02-02 20:21:07 -0800524 exitChatroom();
Yingdi Yu4647f022015-02-01 00:26:38 -0800525
Qiuhan Ding112ee482015-03-11 11:54:11 -0700526 updatePrefixes();
527
Yingdi Yu4647f022015-02-01 00:26:38 -0800528 m_face->getIoService().stop();
Yingdi Yud45777b2014-10-16 23:54:11 -0700529 }
530}
531
532void
533ChatDialogBackend::shutdown()
534{
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700535 {
Yingdi Yuf3401182015-02-02 20:21:07 -0800536 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700537 m_shouldResume = false;
538 }
Yingdi Yu2c9e7712014-10-20 11:55:05 -0700539
Yingdi Yuf3401182015-02-02 20:21:07 -0800540 {
541 // In this case, we just stop checking the nfd connection and exit
542 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
543 m_isNfdConnected = true;
544 }
545
546 exitChatroom();
Yingdi Yu2c9e7712014-10-20 11:55:05 -0700547
Yingdi Yu4647f022015-02-01 00:26:38 -0800548 m_face->getIoService().stop();
Yingdi Yud45777b2014-10-16 23:54:11 -0700549}
550
Yingdi Yuf3401182015-02-02 20:21:07 -0800551void
552ChatDialogBackend::onNfdReconnect()
553{
554 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
555 m_isNfdConnected = true;
556}
557
Yingdi Yueb692ac2015-02-10 18:46:18 -0800558} // namespace chronochat
Yingdi Yud45777b2014-10-16 23:54:11 -0700559
560#if WAF
561#include "chat-dialog-backend.moc"
562// #include "chat-dialog-backend.cpp.moc"
563#endif