blob: 234e4a30577e584fe4eb88f8dde25683c4a04aaf [file] [log] [blame]
Yingdi Yud45777b2014-10-16 23:54:11 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
Junxiao Shid5798f22016-08-22 02:33:26 +00003 * Copyright (c) 2013-2016, Regents of the University of California
4 * Yingdi Yu
Yingdi Yud45777b2014-10-16 23:54:11 -07005 *
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
Junxiao Shid5798f22016-08-22 02:33:26 +000017#include <boost/iostreams/stream.hpp>
Yingdi Yud45777b2014-10-16 23:54:11 -070018#include <ndn-cxx/util/io.hpp>
Varun Patil3d850902020-11-23 12:19:14 +053019#include "cryptopp.hpp"
Yingdi Yud45777b2014-10-16 23:54:11 -070020#endif
21
Varun Patil3d850902020-11-23 12:19:14 +053022using namespace CryptoPP;
Yingdi Yud45777b2014-10-16 23:54:11 -070023
Yingdi Yueb692ac2015-02-10 18:46:18 -080024namespace chronochat {
Yingdi Yud45777b2014-10-16 23:54:11 -070025
26static const time::milliseconds FRESHNESS_PERIOD(60000);
27static const time::seconds HELLO_INTERVAL(60);
Qiuhan Dingba3e57a2015-01-08 19:07:39 -080028static const ndn::Name::Component ROUTING_HINT_SEPARATOR =
29 ndn::name::Component::fromEscapedString("%F0%2E");
Qiuhan Ding43c8e162015-02-02 15:16:48 -080030static const int IDENTITY_OFFSET = -3;
Yingdi Yuf3401182015-02-02 20:21:07 -080031static const int CONNECTION_RETRY_TIMER = 3;
Yingdi Yud45777b2014-10-16 23:54:11 -070032
33ChatDialogBackend::ChatDialogBackend(const Name& chatroomPrefix,
34 const Name& userChatPrefix,
35 const Name& routingPrefix,
36 const std::string& chatroomName,
37 const std::string& nick,
Yingdi Yu45da92a2015-02-02 13:17:03 -080038 const Name& signingId,
Yingdi Yud45777b2014-10-16 23:54:11 -070039 QObject* parent)
40 : QThread(parent)
Yingdi Yuf3401182015-02-02 20:21:07 -080041 , m_shouldResume(false)
Yingdi Yud45777b2014-10-16 23:54:11 -070042 , m_localRoutingPrefix(routingPrefix)
43 , m_chatroomPrefix(chatroomPrefix)
44 , m_userChatPrefix(userChatPrefix)
45 , m_chatroomName(chatroomName)
46 , m_nick(nick)
Yingdi Yu45da92a2015-02-02 13:17:03 -080047 , m_signingId(signingId)
Yingdi Yud45777b2014-10-16 23:54:11 -070048{
49 updatePrefixes();
50}
51
52
53ChatDialogBackend::~ChatDialogBackend()
54{
55}
56
57// protected methods:
58void
59ChatDialogBackend::run()
60{
Yingdi Yu4647f022015-02-01 00:26:38 -080061 bool shouldResume = false;
62 do {
63 initializeSync();
Yingdi Yud45777b2014-10-16 23:54:11 -070064
Yingdi Yu4647f022015-02-01 00:26:38 -080065 if (m_face == nullptr)
66 break;
67
Yingdi Yuf3401182015-02-02 20:21:07 -080068 try {
69 m_face->getIoService().run();
70 }
71 catch (std::runtime_error& e) {
72 {
73 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
74 m_isNfdConnected = false;
75 }
76 emit nfdError();
77 {
78 std::lock_guard<std::mutex>lock(m_resumeMutex);
79 m_shouldResume = true;
80 }
81#ifdef BOOST_THREAD_USES_CHRONO
82 time::seconds reconnectTimer = time::seconds(CONNECTION_RETRY_TIMER);
83#else
84 boost::posix_time::time_duration reconnectTimer;
85 reconnectTimer = boost::posix_time::seconds(CONNECTION_RETRY_TIMER);
86#endif
87 while (!m_isNfdConnected) {
88#ifdef BOOST_THREAD_USES_CHRONO
89 boost::this_thread::sleep_for(reconnectTimer);
90#else
91 boost::this_thread::sleep(reconnectTimer);
92#endif
93 }
94 emit refreshChatDialog(m_routableUserChatPrefix);
95 }
Qiuhan Dingf22c41b2015-03-11 13:19:01 -070096 {
Yingdi Yuf3401182015-02-02 20:21:07 -080097 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -070098 shouldResume = m_shouldResume;
99 m_shouldResume = false;
100 }
Yingdi Yuf3401182015-02-02 20:21:07 -0800101 close();
Yingdi Yu4647f022015-02-01 00:26:38 -0800102
103 } while (shouldResume);
Yingdi Yud45777b2014-10-16 23:54:11 -0700104
105 std::cerr << "Bye!" << std::endl;
106}
107
108// private methods:
109void
110ChatDialogBackend::initializeSync()
111{
Yingdi Yu4647f022015-02-01 00:26:38 -0800112 BOOST_ASSERT(m_sock == nullptr);
Yingdi Yud45777b2014-10-16 23:54:11 -0700113
Yingdi Yu45da92a2015-02-02 13:17:03 -0800114 m_face = make_shared<ndn::Face>();
Yingdi Yu4647f022015-02-01 00:26:38 -0800115 m_scheduler = unique_ptr<ndn::Scheduler>(new ndn::Scheduler(m_face->getIoService()));
Yingdi Yud45777b2014-10-16 23:54:11 -0700116
Yingdi Yu45da92a2015-02-02 13:17:03 -0800117 // initialize validator
Varun Patil3d850902020-11-23 12:19:14 +0530118 m_validator = make_shared<ndn::security::ValidatorConfig>(*m_face);
119 m_validator->load("security/validation-chat.conf");
Yingdi Yu45da92a2015-02-02 13:17:03 -0800120
Yingdi Yud45777b2014-10-16 23:54:11 -0700121 // create a new SyncSocket
122 m_sock = make_shared<chronosync::Socket>(m_chatroomPrefix,
123 m_routableUserChatPrefix,
Yingdi Yu4647f022015-02-01 00:26:38 -0800124 ref(*m_face),
Yingdi Yu45da92a2015-02-02 13:17:03 -0800125 bind(&ChatDialogBackend::processSyncUpdate, this, _1),
126 m_signingId,
127 m_validator);
Yingdi Yud45777b2014-10-16 23:54:11 -0700128
129 // schedule a new join event
Varun Patil3d850902020-11-23 12:19:14 +0530130 m_scheduler->schedule(time::milliseconds(600),
131 bind(&ChatDialogBackend::sendJoin, this));
Yingdi Yud45777b2014-10-16 23:54:11 -0700132
133 // cancel existing hello event if it exists
Varun Patil3d850902020-11-23 12:19:14 +0530134 if (m_helloEventId) {
135 m_helloEventId.cancel();
Yingdi Yud45777b2014-10-16 23:54:11 -0700136 m_helloEventId.reset();
137 }
138}
139
Yingdi Yu45da92a2015-02-02 13:17:03 -0800140class IoDeviceSource
141{
142public:
143 typedef char char_type;
144 typedef boost::iostreams::source_tag category;
145
146 explicit
147 IoDeviceSource(QIODevice& source)
148 : m_source(source)
149 {
150 }
151
152 std::streamsize
153 read(char* buffer, std::streamsize n)
154 {
155 return m_source.read(buffer, n);
156 }
157private:
158 QIODevice& m_source;
159};
160
Yingdi Yud45777b2014-10-16 23:54:11 -0700161void
Yingdi Yuf3401182015-02-02 20:21:07 -0800162ChatDialogBackend::exitChatroom() {
Yingdi Yu4647f022015-02-01 00:26:38 -0800163 if (m_joined)
164 sendLeave();
165
166 usleep(100000);
Yingdi Yuf3401182015-02-02 20:21:07 -0800167}
Yingdi Yu4647f022015-02-01 00:26:38 -0800168
Yingdi Yuf3401182015-02-02 20:21:07 -0800169void
170ChatDialogBackend::close()
171{
Yingdi Yu4647f022015-02-01 00:26:38 -0800172 m_scheduler->cancelAllEvents();
173 m_helloEventId.reset();
174 m_roster.clear();
Yingdi Yu45da92a2015-02-02 13:17:03 -0800175 m_validator.reset();
Yingdi Yu4647f022015-02-01 00:26:38 -0800176 m_sock.reset();
177}
178
179void
Yingdi Yud45777b2014-10-16 23:54:11 -0700180ChatDialogBackend::processSyncUpdate(const std::vector<chronosync::MissingDataInfo>& updates)
181{
Yingdi Yud45777b2014-10-16 23:54:11 -0700182 if (updates.empty()) {
183 return;
184 }
185
186 std::vector<NodeInfo> nodeInfos;
187
188
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800189 for (size_t i = 0; i < updates.size(); i++) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700190 // update roster
191 if (m_roster.find(updates[i].session) == m_roster.end()) {
192 m_roster[updates[i].session].sessionPrefix = updates[i].session;
193 m_roster[updates[i].session].hasNick = false;
194 }
195
196 // fetch missing chat data
197 if (updates[i].high - updates[i].low < 3) {
198 for (chronosync::SeqNo seq = updates[i].low; seq <= updates[i].high; ++seq) {
199 m_sock->fetchData(updates[i].session, seq,
Varun Patil3d850902020-11-23 12:19:14 +0530200 bind(&ChatDialogBackend::processChatData, this, _1, true, true),
201 bind(&ChatDialogBackend::processChatData, this, _1, true, false),
202 [] (const ndn::Interest& interest) {},
Yingdi Yud45777b2014-10-16 23:54:11 -0700203 2);
Yingdi Yud45777b2014-10-16 23:54:11 -0700204 }
205 }
206 else {
207 // There are too many msgs to fetch, let's just fetch the latest one
208 m_sock->fetchData(updates[i].session, updates[i].high,
Varun Patil3d850902020-11-23 12:19:14 +0530209 bind(&ChatDialogBackend::processChatData, this, _1, true, true),
210 bind(&ChatDialogBackend::processChatData, this, _1, true, false),
211 [] (const ndn::Interest& interest) {},
Yingdi Yud45777b2014-10-16 23:54:11 -0700212 2);
213 }
214
Yingdi Yud45777b2014-10-16 23:54:11 -0700215 }
216
217 // reflect the changes on GUI
218 emit syncTreeUpdated(nodeInfos,
219 QString::fromStdString(getHexEncodedDigest(m_sock->getRootDigest())));
220}
221
222void
Varun Patil3d850902020-11-23 12:19:14 +0530223ChatDialogBackend::processChatData(const ndn::Data& data,
Yingdi Yu45da92a2015-02-02 13:17:03 -0800224 bool needDisplay,
225 bool isValidated)
Yingdi Yud45777b2014-10-16 23:54:11 -0700226{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800227 ChatMessage msg;
Yingdi Yud45777b2014-10-16 23:54:11 -0700228
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800229 try {
Varun Patil3d850902020-11-23 12:19:14 +0530230 msg.wireDecode(data.getContent().blockFromValue());
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800231 }
Varun Patil3d850902020-11-23 12:19:14 +0530232 catch (tlv::Error&) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700233 // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800234 msg.setNick("inconnu");
235 msg.setMsgType(ChatMessage::OTHER);
Yingdi Yud45777b2014-10-16 23:54:11 -0700236 return;
237 }
238
Varun Patil3d850902020-11-23 12:19:14 +0530239 Name remoteSessionPrefix = data.getName().getPrefix(-1);
Yingdi Yud45777b2014-10-16 23:54:11 -0700240
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800241 if (msg.getMsgType() == ChatMessage::LEAVE) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700242 BackendRoster::iterator it = m_roster.find(remoteSessionPrefix);
243
244 if (it != m_roster.end()) {
245 // cancel timeout event
246 if (static_cast<bool>(it->second.timeoutEventId))
Varun Patil3d850902020-11-23 12:19:14 +0530247 it->second.timeoutEventId.cancel();
Yingdi Yud45777b2014-10-16 23:54:11 -0700248
249 // notify frontend to remove the remote session (node)
250 emit sessionRemoved(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800251 QString::fromStdString(msg.getNick()),
252 msg.getTimestamp());
Yingdi Yud45777b2014-10-16 23:54:11 -0700253
254 // remove roster entry
255 m_roster.erase(remoteSessionPrefix);
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800256
257 emit eraseInRoster(remoteSessionPrefix.getPrefix(IDENTITY_OFFSET),
258 Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700259 }
260 }
261 else {
262 BackendRoster::iterator it = m_roster.find(remoteSessionPrefix);
263
264 if (it == m_roster.end()) {
265 // Should not happen
266 BOOST_ASSERT(false);
267 }
268
Varun Patil3d850902020-11-23 12:19:14 +0530269 uint64_t seqNo = data.getName().get(-1).toNumber();
Yingdi Yud45777b2014-10-16 23:54:11 -0700270
271 // If a timeout event has been scheduled, cancel it.
272 if (static_cast<bool>(it->second.timeoutEventId))
Varun Patil3d850902020-11-23 12:19:14 +0530273 it->second.timeoutEventId.cancel();
Yingdi Yud45777b2014-10-16 23:54:11 -0700274
275 // (Re)schedule another timeout event after 3 HELLO_INTERVAL;
276 it->second.timeoutEventId =
Varun Patil3d850902020-11-23 12:19:14 +0530277 m_scheduler->schedule(HELLO_INTERVAL * 3,
278 bind(&ChatDialogBackend::remoteSessionTimeout,
279 this, remoteSessionPrefix));
Yingdi Yud45777b2014-10-16 23:54:11 -0700280
281 // If chat message, notify the frontend
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800282 if (msg.getMsgType() == ChatMessage::CHAT) {
Yingdi Yu45da92a2015-02-02 13:17:03 -0800283 if (isValidated)
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800284 emit chatMessageReceived(QString::fromStdString(msg.getNick()),
285 QString::fromStdString(msg.getData()),
286 msg.getTimestamp());
Yingdi Yu45da92a2015-02-02 13:17:03 -0800287 else
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800288 emit chatMessageReceived(QString::fromStdString(msg.getNick() + " (Unverified)"),
289 QString::fromStdString(msg.getData()),
290 msg.getTimestamp());
Yingdi Yu45da92a2015-02-02 13:17:03 -0800291 }
Yingdi Yud45777b2014-10-16 23:54:11 -0700292
293 // Notify frontend to plot notification on DigestTree.
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800294
295 // If we haven't got any message from this session yet.
296 if (m_roster[remoteSessionPrefix].hasNick == false) {
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800297 m_roster[remoteSessionPrefix].userNick = msg.getNick();
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800298 m_roster[remoteSessionPrefix].hasNick = true;
299
300 emit messageReceived(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800301 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800302 seqNo,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800303 msg.getTimestamp(),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800304 true);
305
306 emit addInRoster(remoteSessionPrefix.getPrefix(IDENTITY_OFFSET),
307 Name::Component(m_chatroomName));
308 }
309 else
310 emit messageReceived(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800311 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800312 seqNo,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800313 msg.getTimestamp(),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800314 false);
Yingdi Yud45777b2014-10-16 23:54:11 -0700315 }
316}
317
318void
319ChatDialogBackend::remoteSessionTimeout(const Name& sessionPrefix)
320{
321 time_t timestamp =
322 static_cast<time_t>(time::toUnixTimestamp(time::system_clock::now()).count() / 1000);
323
324 // notify frontend
325 emit sessionRemoved(QString::fromStdString(sessionPrefix.toUri()),
326 QString::fromStdString(m_roster[sessionPrefix].userNick),
327 timestamp);
328
329 // remove roster entry
330 m_roster.erase(sessionPrefix);
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800331
332 emit eraseInRoster(sessionPrefix.getPrefix(IDENTITY_OFFSET),
333 Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700334}
335
336void
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800337ChatDialogBackend::sendMsg(ChatMessage& msg)
Yingdi Yud45777b2014-10-16 23:54:11 -0700338{
339 // send msg
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800340 ndn::Block buf = msg.wireEncode();
Yingdi Yud45777b2014-10-16 23:54:11 -0700341
342 uint64_t nextSequence = m_sock->getLogic().getSeqNo() + 1;
343
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800344 m_sock->publishData(buf.wire(), buf.size(), FRESHNESS_PERIOD);
Yingdi Yud45777b2014-10-16 23:54:11 -0700345
346 std::vector<NodeInfo> nodeInfos;
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800347 Name sessionName = m_sock->getLogic().getSessionName();
348 NodeInfo nodeInfo = {QString::fromStdString(sessionName.toUri()),
Yingdi Yud45777b2014-10-16 23:54:11 -0700349 nextSequence};
350 nodeInfos.push_back(nodeInfo);
351
352 emit syncTreeUpdated(nodeInfos,
353 QString::fromStdString(getHexEncodedDigest(m_sock->getRootDigest())));
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800354
355 emit messageReceived(QString::fromStdString(sessionName.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800356 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800357 nextSequence,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800358 msg.getTimestamp(),
359 msg.getMsgType() == ChatMessage::JOIN);
Yingdi Yud45777b2014-10-16 23:54:11 -0700360}
361
362void
363ChatDialogBackend::sendJoin()
364{
365 m_joined = true;
366
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800367 ChatMessage msg;
368 prepareControlMessage(msg, ChatMessage::JOIN);
Yingdi Yud45777b2014-10-16 23:54:11 -0700369 sendMsg(msg);
370
Varun Patil3d850902020-11-23 12:19:14 +0530371 m_helloEventId = m_scheduler->schedule(HELLO_INTERVAL,
372 bind(&ChatDialogBackend::sendHello, this));
Yingdi Yuf3401182015-02-02 20:21:07 -0800373 emit newChatroomForDiscovery(Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700374}
375
376void
377ChatDialogBackend::sendHello()
378{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800379 ChatMessage msg;
380 prepareControlMessage(msg, ChatMessage::HELLO);
Yingdi Yud45777b2014-10-16 23:54:11 -0700381 sendMsg(msg);
382
Varun Patil3d850902020-11-23 12:19:14 +0530383 m_helloEventId = m_scheduler->schedule(HELLO_INTERVAL,
384 bind(&ChatDialogBackend::sendHello, this));
Yingdi Yud45777b2014-10-16 23:54:11 -0700385}
386
387void
388ChatDialogBackend::sendLeave()
389{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800390 ChatMessage msg;
391 prepareControlMessage(msg, ChatMessage::LEAVE);
Yingdi Yud45777b2014-10-16 23:54:11 -0700392 sendMsg(msg);
393
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800394 // get my own identity with routable prefix by getPrefix(-2)
395 emit eraseInRoster(m_routableUserChatPrefix.getPrefix(-2),
396 Name::Component(m_chatroomName));
397
Yingdi Yud45777b2014-10-16 23:54:11 -0700398 usleep(5000);
399 m_joined = false;
400}
401
402void
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800403ChatDialogBackend::prepareControlMessage(ChatMessage& msg,
404 ChatMessage::ChatMessageType type)
Yingdi Yud45777b2014-10-16 23:54:11 -0700405{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800406 msg.setNick(m_nick);
407 msg.setChatroomName(m_chatroomName);
Yingdi Yud45777b2014-10-16 23:54:11 -0700408 int32_t seconds =
409 static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count() / 1000);
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800410 msg.setTimestamp(seconds);
411 msg.setMsgType(type);
Yingdi Yud45777b2014-10-16 23:54:11 -0700412}
413
414void
415ChatDialogBackend::prepareChatMessage(const QString& text,
416 time_t timestamp,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800417 ChatMessage &msg)
Yingdi Yud45777b2014-10-16 23:54:11 -0700418{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800419 msg.setNick(m_nick);
420 msg.setChatroomName(m_chatroomName);
421 msg.setData(text.toStdString());
422 msg.setTimestamp(timestamp);
423 msg.setMsgType(ChatMessage::CHAT);
Yingdi Yud45777b2014-10-16 23:54:11 -0700424}
425
426void
427ChatDialogBackend::updatePrefixes()
428{
429 m_routableUserChatPrefix.clear();
430
431 if (m_localRoutingPrefix.isPrefixOf(m_userChatPrefix))
432 m_routableUserChatPrefix = m_userChatPrefix;
433 else
434 m_routableUserChatPrefix.append(m_localRoutingPrefix)
Qiuhan Dingba3e57a2015-01-08 19:07:39 -0800435 .append(ROUTING_HINT_SEPARATOR)
Yingdi Yud45777b2014-10-16 23:54:11 -0700436 .append(m_userChatPrefix);
437
438 emit chatPrefixChanged(m_routableUserChatPrefix);
439}
440
441std::string
442ChatDialogBackend::getHexEncodedDigest(ndn::ConstBufferPtr digest)
443{
444 std::stringstream os;
445
Varun Patil3d850902020-11-23 12:19:14 +0530446 CryptoPP::StringSource(digest->data(), digest->size(), true,
Yingdi Yud45777b2014-10-16 23:54:11 -0700447 new CryptoPP::HexEncoder(new CryptoPP::FileSink(os), false));
448 return os.str();
449}
450
451
452// public slots:
453void
454ChatDialogBackend::sendChatMessage(QString text, time_t timestamp)
455{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800456 ChatMessage msg;
Yingdi Yud45777b2014-10-16 23:54:11 -0700457 prepareChatMessage(text, timestamp, msg);
458 sendMsg(msg);
459
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800460 emit chatMessageReceived(QString::fromStdString(msg.getNick()),
461 QString::fromStdString(msg.getData()),
462 msg.getTimestamp());
Yingdi Yud45777b2014-10-16 23:54:11 -0700463}
464
465void
466ChatDialogBackend::updateRoutingPrefix(const QString& localRoutingPrefix)
467{
468 Name newLocalRoutingPrefix(localRoutingPrefix.toStdString());
469
470 if (!newLocalRoutingPrefix.empty() && newLocalRoutingPrefix != m_localRoutingPrefix) {
471 // Update localPrefix
472 m_localRoutingPrefix = newLocalRoutingPrefix;
473
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700474 {
Yingdi Yuf3401182015-02-02 20:21:07 -0800475 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700476 m_shouldResume = true;
477 }
Yingdi Yu4647f022015-02-01 00:26:38 -0800478
Yingdi Yuf3401182015-02-02 20:21:07 -0800479 exitChatroom();
Yingdi Yu4647f022015-02-01 00:26:38 -0800480
Qiuhan Ding112ee482015-03-11 11:54:11 -0700481 updatePrefixes();
482
Yingdi Yu4647f022015-02-01 00:26:38 -0800483 m_face->getIoService().stop();
Yingdi Yud45777b2014-10-16 23:54:11 -0700484 }
485}
486
487void
488ChatDialogBackend::shutdown()
489{
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700490 {
Yingdi Yuf3401182015-02-02 20:21:07 -0800491 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700492 m_shouldResume = false;
493 }
Yingdi Yu2c9e7712014-10-20 11:55:05 -0700494
Yingdi Yuf3401182015-02-02 20:21:07 -0800495 {
496 // In this case, we just stop checking the nfd connection and exit
497 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
498 m_isNfdConnected = true;
499 }
500
501 exitChatroom();
Yingdi Yu2c9e7712014-10-20 11:55:05 -0700502
Yingdi Yu4647f022015-02-01 00:26:38 -0800503 m_face->getIoService().stop();
Yingdi Yud45777b2014-10-16 23:54:11 -0700504}
505
Yingdi Yuf3401182015-02-02 20:21:07 -0800506void
507ChatDialogBackend::onNfdReconnect()
508{
509 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
510 m_isNfdConnected = true;
511}
512
Yingdi Yueb692ac2015-02-10 18:46:18 -0800513} // namespace chronochat
Yingdi Yud45777b2014-10-16 23:54:11 -0700514
515#if WAF
516#include "chat-dialog-backend.moc"
517// #include "chat-dialog-backend.cpp.moc"
518#endif