blob: c72d7edf6b9c8eed039ba4358d28c2c814c9dcab [file] [log] [blame]
Yingdi Yud45777b2014-10-16 23:54:11 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
Varun Patilb3d03b92021-01-08 17:09:32 +05303 * Copyright (c) 2013-2021, Regents of the University of California
Junxiao Shid5798f22016-08-22 02:33:26 +00004 * 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
Davide Pesavento7676b562020-12-14 00:41:26 -050019#include <ndn-cxx/util/io.hpp>
20#include <ndn-cxx/util/string-helper.hpp>
21#endif
Yingdi Yud45777b2014-10-16 23:54:11 -070022
Yingdi Yueb692ac2015-02-10 18:46:18 -080023namespace chronochat {
Yingdi Yud45777b2014-10-16 23:54:11 -070024
25static const time::milliseconds FRESHNESS_PERIOD(60000);
26static const time::seconds HELLO_INTERVAL(60);
Davide Pesavento7676b562020-12-14 00:41:26 -050027static const Name::Component ROUTING_HINT_SEPARATOR = Name::Component::fromEscapedString("%F0%2E");
Qiuhan Ding43c8e162015-02-02 15:16:48 -080028static const int IDENTITY_OFFSET = -3;
Yingdi Yuf3401182015-02-02 20:21:07 -080029static const int CONNECTION_RETRY_TIMER = 3;
Yingdi Yud45777b2014-10-16 23:54:11 -070030
31ChatDialogBackend::ChatDialogBackend(const Name& chatroomPrefix,
32 const Name& userChatPrefix,
33 const Name& routingPrefix,
34 const std::string& chatroomName,
35 const std::string& nick,
Yingdi Yu45da92a2015-02-02 13:17:03 -080036 const Name& signingId,
Yingdi Yud45777b2014-10-16 23:54:11 -070037 QObject* parent)
38 : QThread(parent)
Yingdi Yuf3401182015-02-02 20:21:07 -080039 , m_shouldResume(false)
Yingdi Yud45777b2014-10-16 23:54:11 -070040 , m_localRoutingPrefix(routingPrefix)
41 , m_chatroomPrefix(chatroomPrefix)
42 , m_userChatPrefix(userChatPrefix)
43 , m_chatroomName(chatroomName)
44 , m_nick(nick)
Yingdi Yu45da92a2015-02-02 13:17:03 -080045 , m_signingId(signingId)
Yingdi Yud45777b2014-10-16 23:54:11 -070046{
47 updatePrefixes();
48}
49
Davide Pesavento7676b562020-12-14 00:41:26 -050050ChatDialogBackend::~ChatDialogBackend() = default;
Yingdi Yud45777b2014-10-16 23:54:11 -070051
52// protected methods:
53void
54ChatDialogBackend::run()
55{
Yingdi Yu4647f022015-02-01 00:26:38 -080056 bool shouldResume = false;
57 do {
58 initializeSync();
Yingdi Yud45777b2014-10-16 23:54:11 -070059
Yingdi Yu4647f022015-02-01 00:26:38 -080060 if (m_face == nullptr)
61 break;
62
Yingdi Yuf3401182015-02-02 20:21:07 -080063 try {
64 m_face->getIoService().run();
65 }
Varun Patila24bd3e2020-11-24 10:08:33 +053066 catch (const std::runtime_error& e) {
Yingdi Yuf3401182015-02-02 20:21:07 -080067 {
68 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
69 m_isNfdConnected = false;
70 }
71 emit nfdError();
72 {
73 std::lock_guard<std::mutex>lock(m_resumeMutex);
74 m_shouldResume = true;
75 }
76#ifdef BOOST_THREAD_USES_CHRONO
77 time::seconds reconnectTimer = time::seconds(CONNECTION_RETRY_TIMER);
78#else
79 boost::posix_time::time_duration reconnectTimer;
80 reconnectTimer = boost::posix_time::seconds(CONNECTION_RETRY_TIMER);
81#endif
82 while (!m_isNfdConnected) {
83#ifdef BOOST_THREAD_USES_CHRONO
84 boost::this_thread::sleep_for(reconnectTimer);
85#else
86 boost::this_thread::sleep(reconnectTimer);
87#endif
88 }
89 emit refreshChatDialog(m_routableUserChatPrefix);
90 }
Qiuhan Dingf22c41b2015-03-11 13:19:01 -070091 {
Yingdi Yuf3401182015-02-02 20:21:07 -080092 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -070093 shouldResume = m_shouldResume;
94 m_shouldResume = false;
95 }
Yingdi Yuf3401182015-02-02 20:21:07 -080096 close();
Yingdi Yu4647f022015-02-01 00:26:38 -080097
98 } while (shouldResume);
Yingdi Yud45777b2014-10-16 23:54:11 -070099}
100
101// private methods:
102void
103ChatDialogBackend::initializeSync()
104{
Yingdi Yu4647f022015-02-01 00:26:38 -0800105 BOOST_ASSERT(m_sock == nullptr);
Yingdi Yud45777b2014-10-16 23:54:11 -0700106
Varun Patilb3d03b92021-01-08 17:09:32 +0530107 m_face = std::make_shared<ndn::Face>();
108 m_scheduler = std::make_unique<ndn::Scheduler>(m_face->getIoService());
Yingdi Yud45777b2014-10-16 23:54:11 -0700109
Yingdi Yu45da92a2015-02-02 13:17:03 -0800110 // initialize validator
Varun Patilb3d03b92021-01-08 17:09:32 +0530111 m_validator = std::make_shared<ndn::security::ValidatorConfig>(*m_face);
Varun Patil3d850902020-11-23 12:19:14 +0530112 m_validator->load("security/validation-chat.conf");
Yingdi Yu45da92a2015-02-02 13:17:03 -0800113
Yingdi Yud45777b2014-10-16 23:54:11 -0700114 // create a new SyncSocket
Varun Patilb3d03b92021-01-08 17:09:32 +0530115 m_sock = std::make_shared<chronosync::Socket>(m_chatroomPrefix,
116 m_routableUserChatPrefix,
117 ref(*m_face),
118 bind(&ChatDialogBackend::processSyncUpdate, this, _1),
119 m_signingId,
120 m_validator);
Yingdi Yud45777b2014-10-16 23:54:11 -0700121
122 // schedule a new join event
Varun Patil3d850902020-11-23 12:19:14 +0530123 m_scheduler->schedule(time::milliseconds(600),
124 bind(&ChatDialogBackend::sendJoin, this));
Yingdi Yud45777b2014-10-16 23:54:11 -0700125
126 // cancel existing hello event if it exists
Varun Patila24bd3e2020-11-24 10:08:33 +0530127 if (m_helloEventId)
Varun Patil3d850902020-11-23 12:19:14 +0530128 m_helloEventId.cancel();
Yingdi Yud45777b2014-10-16 23:54:11 -0700129}
130
Yingdi Yu45da92a2015-02-02 13:17:03 -0800131class IoDeviceSource
132{
133public:
134 typedef char char_type;
135 typedef boost::iostreams::source_tag category;
136
137 explicit
138 IoDeviceSource(QIODevice& source)
139 : m_source(source)
140 {
141 }
142
143 std::streamsize
144 read(char* buffer, std::streamsize n)
145 {
146 return m_source.read(buffer, n);
147 }
148private:
149 QIODevice& m_source;
150};
151
Yingdi Yud45777b2014-10-16 23:54:11 -0700152void
Yingdi Yuf3401182015-02-02 20:21:07 -0800153ChatDialogBackend::exitChatroom() {
Yingdi Yu4647f022015-02-01 00:26:38 -0800154 if (m_joined)
155 sendLeave();
156
157 usleep(100000);
Yingdi Yuf3401182015-02-02 20:21:07 -0800158}
Yingdi Yu4647f022015-02-01 00:26:38 -0800159
Yingdi Yuf3401182015-02-02 20:21:07 -0800160void
161ChatDialogBackend::close()
162{
Yingdi Yu4647f022015-02-01 00:26:38 -0800163 m_scheduler->cancelAllEvents();
164 m_helloEventId.reset();
165 m_roster.clear();
Yingdi Yu45da92a2015-02-02 13:17:03 -0800166 m_validator.reset();
Yingdi Yu4647f022015-02-01 00:26:38 -0800167 m_sock.reset();
168}
169
170void
Yingdi Yud45777b2014-10-16 23:54:11 -0700171ChatDialogBackend::processSyncUpdate(const std::vector<chronosync::MissingDataInfo>& updates)
172{
Yingdi Yud45777b2014-10-16 23:54:11 -0700173 if (updates.empty()) {
174 return;
175 }
176
177 std::vector<NodeInfo> nodeInfos;
178
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800179 for (size_t i = 0; i < updates.size(); i++) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700180 // update roster
181 if (m_roster.find(updates[i].session) == m_roster.end()) {
182 m_roster[updates[i].session].sessionPrefix = updates[i].session;
183 m_roster[updates[i].session].hasNick = false;
184 }
185
186 // fetch missing chat data
187 if (updates[i].high - updates[i].low < 3) {
188 for (chronosync::SeqNo seq = updates[i].low; seq <= updates[i].high; ++seq) {
189 m_sock->fetchData(updates[i].session, seq,
Varun Patil3d850902020-11-23 12:19:14 +0530190 bind(&ChatDialogBackend::processChatData, this, _1, true, true),
191 bind(&ChatDialogBackend::processChatData, this, _1, true, false),
192 [] (const ndn::Interest& interest) {},
Yingdi Yud45777b2014-10-16 23:54:11 -0700193 2);
Yingdi Yud45777b2014-10-16 23:54:11 -0700194 }
195 }
196 else {
197 // There are too many msgs to fetch, let's just fetch the latest one
198 m_sock->fetchData(updates[i].session, updates[i].high,
Varun Patil3d850902020-11-23 12:19:14 +0530199 bind(&ChatDialogBackend::processChatData, this, _1, true, true),
200 bind(&ChatDialogBackend::processChatData, this, _1, true, false),
201 [] (const ndn::Interest& interest) {},
Yingdi Yud45777b2014-10-16 23:54:11 -0700202 2);
203 }
204
Yingdi Yud45777b2014-10-16 23:54:11 -0700205 }
206
207 // reflect the changes on GUI
208 emit syncTreeUpdated(nodeInfos,
Davide Pesavento7676b562020-12-14 00:41:26 -0500209 QString::fromStdString(ndn::toHex(*m_sock->getRootDigest(), false)));
Yingdi Yud45777b2014-10-16 23:54:11 -0700210}
211
212void
Davide Pesavento7676b562020-12-14 00:41:26 -0500213ChatDialogBackend::processChatData(const ndn::Data& data, bool needDisplay, bool isValidated)
Yingdi Yud45777b2014-10-16 23:54:11 -0700214{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800215 ChatMessage msg;
Yingdi Yud45777b2014-10-16 23:54:11 -0700216
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800217 try {
Varun Patil3d850902020-11-23 12:19:14 +0530218 msg.wireDecode(data.getContent().blockFromValue());
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800219 }
Varun Patila24bd3e2020-11-24 10:08:33 +0530220 catch (const tlv::Error&) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700221 // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800222 msg.setNick("inconnu");
223 msg.setMsgType(ChatMessage::OTHER);
Yingdi Yud45777b2014-10-16 23:54:11 -0700224 return;
225 }
226
Varun Patil3d850902020-11-23 12:19:14 +0530227 Name remoteSessionPrefix = data.getName().getPrefix(-1);
Yingdi Yud45777b2014-10-16 23:54:11 -0700228
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800229 if (msg.getMsgType() == ChatMessage::LEAVE) {
Yingdi Yud45777b2014-10-16 23:54:11 -0700230 BackendRoster::iterator it = m_roster.find(remoteSessionPrefix);
231
232 if (it != m_roster.end()) {
233 // cancel timeout event
Varun Patila24bd3e2020-11-24 10:08:33 +0530234 if (it->second.timeoutEventId)
Varun Patil3d850902020-11-23 12:19:14 +0530235 it->second.timeoutEventId.cancel();
Yingdi Yud45777b2014-10-16 23:54:11 -0700236
237 // notify frontend to remove the remote session (node)
238 emit sessionRemoved(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800239 QString::fromStdString(msg.getNick()),
240 msg.getTimestamp());
Yingdi Yud45777b2014-10-16 23:54:11 -0700241
242 // remove roster entry
243 m_roster.erase(remoteSessionPrefix);
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800244
245 emit eraseInRoster(remoteSessionPrefix.getPrefix(IDENTITY_OFFSET),
246 Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700247 }
248 }
249 else {
250 BackendRoster::iterator it = m_roster.find(remoteSessionPrefix);
251
252 if (it == m_roster.end()) {
253 // Should not happen
254 BOOST_ASSERT(false);
255 }
256
Varun Patil3d850902020-11-23 12:19:14 +0530257 uint64_t seqNo = data.getName().get(-1).toNumber();
Yingdi Yud45777b2014-10-16 23:54:11 -0700258
Yingdi Yud45777b2014-10-16 23:54:11 -0700259 // (Re)schedule another timeout event after 3 HELLO_INTERVAL;
260 it->second.timeoutEventId =
Varun Patil3d850902020-11-23 12:19:14 +0530261 m_scheduler->schedule(HELLO_INTERVAL * 3,
262 bind(&ChatDialogBackend::remoteSessionTimeout,
263 this, remoteSessionPrefix));
Yingdi Yud45777b2014-10-16 23:54:11 -0700264
265 // If chat message, notify the frontend
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800266 if (msg.getMsgType() == ChatMessage::CHAT) {
Yingdi Yu45da92a2015-02-02 13:17:03 -0800267 if (isValidated)
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800268 emit chatMessageReceived(QString::fromStdString(msg.getNick()),
269 QString::fromStdString(msg.getData()),
270 msg.getTimestamp());
Yingdi Yu45da92a2015-02-02 13:17:03 -0800271 else
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800272 emit chatMessageReceived(QString::fromStdString(msg.getNick() + " (Unverified)"),
273 QString::fromStdString(msg.getData()),
274 msg.getTimestamp());
Yingdi Yu45da92a2015-02-02 13:17:03 -0800275 }
Yingdi Yud45777b2014-10-16 23:54:11 -0700276
277 // Notify frontend to plot notification on DigestTree.
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800278
279 // If we haven't got any message from this session yet.
280 if (m_roster[remoteSessionPrefix].hasNick == false) {
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800281 m_roster[remoteSessionPrefix].userNick = msg.getNick();
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800282 m_roster[remoteSessionPrefix].hasNick = true;
283
284 emit messageReceived(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800285 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800286 seqNo,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800287 msg.getTimestamp(),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800288 true);
289
290 emit addInRoster(remoteSessionPrefix.getPrefix(IDENTITY_OFFSET),
291 Name::Component(m_chatroomName));
292 }
293 else
294 emit messageReceived(QString::fromStdString(remoteSessionPrefix.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800295 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800296 seqNo,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800297 msg.getTimestamp(),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800298 false);
Yingdi Yud45777b2014-10-16 23:54:11 -0700299 }
300}
301
302void
303ChatDialogBackend::remoteSessionTimeout(const Name& sessionPrefix)
304{
305 time_t timestamp =
306 static_cast<time_t>(time::toUnixTimestamp(time::system_clock::now()).count() / 1000);
307
308 // notify frontend
309 emit sessionRemoved(QString::fromStdString(sessionPrefix.toUri()),
310 QString::fromStdString(m_roster[sessionPrefix].userNick),
311 timestamp);
312
313 // remove roster entry
314 m_roster.erase(sessionPrefix);
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800315
316 emit eraseInRoster(sessionPrefix.getPrefix(IDENTITY_OFFSET),
317 Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700318}
319
320void
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800321ChatDialogBackend::sendMsg(ChatMessage& msg)
Yingdi Yud45777b2014-10-16 23:54:11 -0700322{
323 // send msg
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800324 ndn::Block buf = msg.wireEncode();
Yingdi Yud45777b2014-10-16 23:54:11 -0700325
326 uint64_t nextSequence = m_sock->getLogic().getSeqNo() + 1;
327
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800328 m_sock->publishData(buf.wire(), buf.size(), FRESHNESS_PERIOD);
Yingdi Yud45777b2014-10-16 23:54:11 -0700329
330 std::vector<NodeInfo> nodeInfos;
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800331 Name sessionName = m_sock->getLogic().getSessionName();
332 NodeInfo nodeInfo = {QString::fromStdString(sessionName.toUri()),
Yingdi Yud45777b2014-10-16 23:54:11 -0700333 nextSequence};
334 nodeInfos.push_back(nodeInfo);
335
336 emit syncTreeUpdated(nodeInfos,
Davide Pesavento7676b562020-12-14 00:41:26 -0500337 QString::fromStdString(ndn::toHex(*m_sock->getRootDigest(), false)));
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800338
339 emit messageReceived(QString::fromStdString(sessionName.toUri()),
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800340 QString::fromStdString(msg.getNick()),
Qiuhan Ding7a4e7ef2015-02-03 20:25:50 -0800341 nextSequence,
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800342 msg.getTimestamp(),
343 msg.getMsgType() == ChatMessage::JOIN);
Yingdi Yud45777b2014-10-16 23:54:11 -0700344}
345
346void
347ChatDialogBackend::sendJoin()
348{
349 m_joined = true;
350
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800351 ChatMessage msg;
352 prepareControlMessage(msg, ChatMessage::JOIN);
Yingdi Yud45777b2014-10-16 23:54:11 -0700353 sendMsg(msg);
354
Varun Patil3d850902020-11-23 12:19:14 +0530355 m_helloEventId = m_scheduler->schedule(HELLO_INTERVAL,
356 bind(&ChatDialogBackend::sendHello, this));
Yingdi Yuf3401182015-02-02 20:21:07 -0800357 emit newChatroomForDiscovery(Name::Component(m_chatroomName));
Yingdi Yud45777b2014-10-16 23:54:11 -0700358}
359
360void
361ChatDialogBackend::sendHello()
362{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800363 ChatMessage msg;
364 prepareControlMessage(msg, ChatMessage::HELLO);
Yingdi Yud45777b2014-10-16 23:54:11 -0700365 sendMsg(msg);
366
Varun Patil3d850902020-11-23 12:19:14 +0530367 m_helloEventId = m_scheduler->schedule(HELLO_INTERVAL,
368 bind(&ChatDialogBackend::sendHello, this));
Yingdi Yud45777b2014-10-16 23:54:11 -0700369}
370
371void
372ChatDialogBackend::sendLeave()
373{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800374 ChatMessage msg;
375 prepareControlMessage(msg, ChatMessage::LEAVE);
Yingdi Yud45777b2014-10-16 23:54:11 -0700376 sendMsg(msg);
377
Qiuhan Ding43c8e162015-02-02 15:16:48 -0800378 // get my own identity with routable prefix by getPrefix(-2)
379 emit eraseInRoster(m_routableUserChatPrefix.getPrefix(-2),
380 Name::Component(m_chatroomName));
381
Yingdi Yud45777b2014-10-16 23:54:11 -0700382 usleep(5000);
383 m_joined = false;
384}
385
386void
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800387ChatDialogBackend::prepareControlMessage(ChatMessage& msg,
388 ChatMessage::ChatMessageType type)
Yingdi Yud45777b2014-10-16 23:54:11 -0700389{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800390 msg.setNick(m_nick);
391 msg.setChatroomName(m_chatroomName);
Yingdi Yud45777b2014-10-16 23:54:11 -0700392 int32_t seconds =
393 static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count() / 1000);
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800394 msg.setTimestamp(seconds);
395 msg.setMsgType(type);
Yingdi Yud45777b2014-10-16 23:54:11 -0700396}
397
398void
399ChatDialogBackend::prepareChatMessage(const QString& text,
400 time_t timestamp,
Varun Patila24bd3e2020-11-24 10:08:33 +0530401 ChatMessage& msg)
Yingdi Yud45777b2014-10-16 23:54:11 -0700402{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800403 msg.setNick(m_nick);
404 msg.setChatroomName(m_chatroomName);
405 msg.setData(text.toStdString());
406 msg.setTimestamp(timestamp);
407 msg.setMsgType(ChatMessage::CHAT);
Yingdi Yud45777b2014-10-16 23:54:11 -0700408}
409
410void
411ChatDialogBackend::updatePrefixes()
412{
413 m_routableUserChatPrefix.clear();
414
415 if (m_localRoutingPrefix.isPrefixOf(m_userChatPrefix))
416 m_routableUserChatPrefix = m_userChatPrefix;
417 else
418 m_routableUserChatPrefix.append(m_localRoutingPrefix)
Qiuhan Dingba3e57a2015-01-08 19:07:39 -0800419 .append(ROUTING_HINT_SEPARATOR)
Yingdi Yud45777b2014-10-16 23:54:11 -0700420 .append(m_userChatPrefix);
421
422 emit chatPrefixChanged(m_routableUserChatPrefix);
423}
424
Yingdi Yud45777b2014-10-16 23:54:11 -0700425
426// public slots:
427void
428ChatDialogBackend::sendChatMessage(QString text, time_t timestamp)
429{
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800430 ChatMessage msg;
Yingdi Yud45777b2014-10-16 23:54:11 -0700431 prepareChatMessage(text, timestamp, msg);
432 sendMsg(msg);
433
Qiuhan Ding0cfc1512015-02-17 17:44:11 -0800434 emit chatMessageReceived(QString::fromStdString(msg.getNick()),
435 QString::fromStdString(msg.getData()),
436 msg.getTimestamp());
Yingdi Yud45777b2014-10-16 23:54:11 -0700437}
438
439void
440ChatDialogBackend::updateRoutingPrefix(const QString& localRoutingPrefix)
441{
442 Name newLocalRoutingPrefix(localRoutingPrefix.toStdString());
443
444 if (!newLocalRoutingPrefix.empty() && newLocalRoutingPrefix != m_localRoutingPrefix) {
445 // Update localPrefix
446 m_localRoutingPrefix = newLocalRoutingPrefix;
447
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700448 {
Yingdi Yuf3401182015-02-02 20:21:07 -0800449 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700450 m_shouldResume = true;
451 }
Yingdi Yu4647f022015-02-01 00:26:38 -0800452
Yingdi Yuf3401182015-02-02 20:21:07 -0800453 exitChatroom();
Yingdi Yu4647f022015-02-01 00:26:38 -0800454
Qiuhan Ding112ee482015-03-11 11:54:11 -0700455 updatePrefixes();
456
Yingdi Yu4647f022015-02-01 00:26:38 -0800457 m_face->getIoService().stop();
Yingdi Yud45777b2014-10-16 23:54:11 -0700458 }
459}
460
461void
462ChatDialogBackend::shutdown()
463{
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700464 {
Yingdi Yuf3401182015-02-02 20:21:07 -0800465 std::lock_guard<std::mutex>lock(m_resumeMutex);
Qiuhan Dingf22c41b2015-03-11 13:19:01 -0700466 m_shouldResume = false;
467 }
Yingdi Yu2c9e7712014-10-20 11:55:05 -0700468
Yingdi Yuf3401182015-02-02 20:21:07 -0800469 {
470 // In this case, we just stop checking the nfd connection and exit
471 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
472 m_isNfdConnected = true;
473 }
474
475 exitChatroom();
Yingdi Yu2c9e7712014-10-20 11:55:05 -0700476
Yingdi Yu4647f022015-02-01 00:26:38 -0800477 m_face->getIoService().stop();
Yingdi Yud45777b2014-10-16 23:54:11 -0700478}
479
Yingdi Yuf3401182015-02-02 20:21:07 -0800480void
481ChatDialogBackend::onNfdReconnect()
482{
483 std::lock_guard<std::mutex>lock(m_nfdConnectionMutex);
484 m_isNfdConnected = true;
485}
486
Yingdi Yueb692ac2015-02-10 18:46:18 -0800487} // namespace chronochat
Yingdi Yud45777b2014-10-16 23:54:11 -0700488
489#if WAF
490#include "chat-dialog-backend.moc"
Yingdi Yud45777b2014-10-16 23:54:11 -0700491#endif