blob: af84cd7f710dc5712213c1c536e97153012430d2 [file] [log] [blame]
Yingdi Yu2c9e7712014-10-20 11:55:05 -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>
9 */
10
11#include "controller-backend.hpp"
12
13#ifndef Q_MOC_RUN
14#include "invitation.hpp"
15#include "logging.h"
16#endif
17
18
19INIT_LOGGER("ControllerBackend");
20
21namespace chronos {
22
23using std::string;
24
25using ndn::Face;
26using ndn::IdentityCertificate;
27using ndn::OnInterestValidated;
28using ndn::OnInterestValidationFailed;
29
30
31static const uint8_t ROUTING_PREFIX_SEPARATOR[2] = {0xF0, 0x2E};
32
33ControllerBackend::ControllerBackend(QObject* parent)
34 : QThread(parent)
35 , m_contactManager(m_face)
36 , m_invitationListenerId(0)
37{
38 // connection to contact manager
39 connect(this, SIGNAL(identityUpdated(const QString&)),
40 &m_contactManager, SLOT(onIdentityUpdated(const QString&)));
41
42 connect(&m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
43 this, SLOT(onContactIdListReady(const QStringList&)));
44
45}
46
47ControllerBackend::~ControllerBackend()
48{
49}
50
51void
52ControllerBackend::run()
53{
54 setInvitationListener();
55
56 m_face.processEvents();
57
58 std::cerr << "Bye!" << std::endl;
59}
60
61// private methods:
62
63void
64tmpOnInvitationInterest(const ndn::Name& prefix,
65 const ndn::Interest& interest)
66{
67 std::cerr << "tmpOnInvitationInterest" << std::endl;
68}
69
70void
71tmpOnInvitationRegisterFailed(const Name& prefix,
72 const string& failInfo)
73{
74 std::cerr << "tmpOnInvitationRegisterFailed" << std::endl;
75}
76
77void
78tmpUnregisterPrefixSuccessCallback()
79{
80 std::cerr << "tmpUnregisterPrefixSuccessCallback" << std::endl;
81}
82
83void
84tmpUnregisterPrefixFailureCallback(const string& failInfo)
85{
86 std::cerr << "tmpUnregisterPrefixSuccessCallback" << std::endl;
87}
88
89void
90ControllerBackend::setInvitationListener()
91{
92 QMutexLocker locker(&m_mutex);
93
94 Name invitationPrefix;
95 Name routingPrefix = getInvitationRoutingPrefix();
96 size_t offset = 0;
97 if (!routingPrefix.isPrefixOf(m_identity)) {
98 invitationPrefix.append(routingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2);
99 offset = routingPrefix.size() + 1;
100 }
101 invitationPrefix.append(m_identity).append("CHRONOCHAT-INVITATION");
102
103 const ndn::RegisteredPrefixId* invitationListenerId =
104 m_face.setInterestFilter(invitationPrefix,
105 bind(&ControllerBackend::onInvitationInterest,
106 this, _1, _2, offset),
107 bind(&ControllerBackend::onInvitationRegisterFailed,
108 this, _1, _2));
109
110 if (m_invitationListenerId != 0) {
111 m_face.unregisterPrefix(m_invitationListenerId,
112 bind(&ControllerBackend::onInvitationPrefixReset, this),
113 bind(&ControllerBackend::onInvitationPrefixResetFailed, this, _1));
114 }
115
116 m_invitationListenerId = invitationListenerId;
117
118}
119
120ndn::Name
121ControllerBackend::getInvitationRoutingPrefix()
122{
123 return Name("/ndn/broadcast");
124}
125
126void
127ControllerBackend::onInvitationPrefixReset()
128{
129 // _LOG_DEBUG("ControllerBackend::onInvitationPrefixReset");
130}
131
132void
133ControllerBackend::onInvitationPrefixResetFailed(const std::string& failInfo)
134{
135 // _LOG_DEBUG("ControllerBackend::onInvitationPrefixResetFailed: " << failInfo);
136}
137
138
139void
140ControllerBackend::onInvitationInterest(const ndn::Name& prefix,
141 const ndn::Interest& interest,
142 size_t routingPrefixOffset)
143{
144 // _LOG_DEBUG("onInvitationInterest: " << interest.getName());
145 shared_ptr<Interest> invitationInterest =
146 make_shared<Interest>(boost::cref(interest.getName().getSubName(routingPrefixOffset)));
147
148 // check if the chatroom already exists;
149 try {
150 Invitation invitation(invitationInterest->getName());
151 if (m_chatDialogList.contains(QString::fromStdString(invitation.getChatroom())))
152 return;
153 }
154 catch (Invitation::Error& e) {
155 // Cannot parse the invitation;
156 return;
157 }
158
159 OnInterestValidated onValidated = bind(&ControllerBackend::onInvitationValidated, this, _1);
160 OnInterestValidationFailed onFailed = bind(&ControllerBackend::onInvitationValidationFailed,
161 this, _1, _2);
162
163 m_validator.validate(*invitationInterest, onValidated, onFailed);
164}
165
166void
167ControllerBackend::onInvitationRegisterFailed(const Name& prefix, const string& failInfo)
168{
169 // _LOG_DEBUG("ControllerBackend::onInvitationRegisterFailed: " << failInfo);
170}
171
172void
173ControllerBackend::onInvitationValidated(const shared_ptr<const Interest>& interest)
174{
175 Invitation invitation(interest->getName());
176 // Should be obtained via a method of ContactManager.
177 string alias = invitation.getInviterCertificate().getPublicKeyName().getPrefix(-1).toUri();
178
179 emit invitaionValidated(QString::fromStdString(alias),
180 QString::fromStdString(invitation.getChatroom()),
181 interest->getName());
182}
183
184void
185ControllerBackend::onInvitationValidationFailed(const shared_ptr<const Interest>& interest,
186 string failureInfo)
187{
188 // _LOG_DEBUG("Invitation: " << interest->getName() <<
189 // " cannot not be validated due to: " << failureInfo);
190}
191
192void
193ControllerBackend::onLocalPrefix(const Interest& interest, Data& data)
194{
195 Name prefix;
196
197 Block contentBlock = data.getContent();
198 try {
199 contentBlock.parse();
200
201 for (Block::element_const_iterator it = contentBlock.elements_begin();
202 it != contentBlock.elements_end(); it++) {
203 Name candidate;
204 candidate.wireDecode(*it);
205 if (candidate.isPrefixOf(m_identity)) {
206 prefix = candidate;
207 break;
208 }
209 }
210
211 if (prefix.empty()) {
212 if (contentBlock.elements_begin() != contentBlock.elements_end())
213 prefix.wireDecode(*contentBlock.elements_begin());
214 else
215 prefix = Name("/private/local");
216 }
217 }
218 catch (Block::Error& e) {
219 prefix = Name("/private/local");
220 }
221
222 updateLocalPrefix(prefix);
223}
224
225void
226ControllerBackend::onLocalPrefixTimeout(const Interest& interest)
227{
228 Name localPrefix("/private/local");
229 updateLocalPrefix(localPrefix);
230}
231
232void
233ControllerBackend::updateLocalPrefix(const Name& localPrefix)
234{
235 if (m_localPrefix.empty() || m_localPrefix != localPrefix) {
236 m_localPrefix = localPrefix;
237 emit localPrefixUpdated(QString::fromStdString(localPrefix.toUri()));
238 }
239}
240
241// public slots:
242void
243ControllerBackend::shutdown()
244{
245 m_face.getIoService().stop();
246}
247
248void
249ControllerBackend::addChatroom(QString chatroom)
250{
251 m_chatDialogList.append(chatroom);
252}
253
254void
255ControllerBackend::removeChatroom(QString chatroom)
256{
257 m_chatDialogList.removeAll(chatroom);
258}
259
260void
261ControllerBackend::onUpdateLocalPrefixAction()
262{
263 // Name interestName();
264 Interest interest("/localhop/ndn-autoconf/routable-prefixes");
265 interest.setInterestLifetime(time::milliseconds(1000));
266 interest.setMustBeFresh(true);
267
268 m_face.expressInterest(interest,
269 bind(&ControllerBackend::onLocalPrefix, this, _1, _2),
270 bind(&ControllerBackend::onLocalPrefixTimeout, this, _1));
271}
272
273void
274ControllerBackend::onIdentityChanged(const QString& identity)
275{
276 m_chatDialogList.clear();
277
278 m_identity = Name(identity.toStdString());
279
280 std::cerr << "ControllerBackend::onIdentityChanged: " << m_identity << std::endl;
281
282 m_keyChain.createIdentity(m_identity);
283
284 setInvitationListener();
285
286 emit identityUpdated(identity);
287}
288
289void
290ControllerBackend::onInvitationResponded(const ndn::Name& invitationName, bool accepted)
291{
292 shared_ptr<Data> response = make_shared<Data>();
293 shared_ptr<IdentityCertificate> chatroomCert;
294
295 // generate reply;
296 if (accepted) {
297 Name responseName = invitationName;
298 responseName.append(m_localPrefix.wireEncode());
299
300 response->setName(responseName);
301
302 // We should create a particular certificate for this chatroom,
303 //but let's use default one for now.
304 chatroomCert
305 = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
306
307 response->setContent(chatroomCert->wireEncode());
308 response->setFreshnessPeriod(time::milliseconds(1000));
309 }
310 else {
311 response->setName(invitationName);
312 response->setFreshnessPeriod(time::milliseconds(1000));
313 }
314
315 m_keyChain.signByIdentity(*response, m_identity);
316
317 // Check if we need a wrapper
318 Name invitationRoutingPrefix = getInvitationRoutingPrefix();
319 if (invitationRoutingPrefix.isPrefixOf(m_identity))
320 m_face.put(*response);
321 else {
322 Name wrappedName;
323 wrappedName.append(invitationRoutingPrefix)
324 .append(ROUTING_PREFIX_SEPARATOR, 2)
325 .append(response->getName());
326
327 // _LOG_DEBUG("onInvitationResponded: prepare reply " << wrappedName);
328
329 shared_ptr<Data> wrappedData = make_shared<Data>(wrappedName);
330 wrappedData->setContent(response->wireEncode());
331 wrappedData->setFreshnessPeriod(time::milliseconds(1000));
332
333 m_keyChain.signByIdentity(*wrappedData, m_identity);
334 m_face.put(*wrappedData);
335 }
336
337 Invitation invitation(invitationName);
338 emit startChatroomOnInvitation(invitation, true);
339}
340
341void
342ControllerBackend::onContactIdListReady(const QStringList& list)
343{
344 ContactList contactList;
345
346 m_contactManager.getContactList(contactList);
347 m_validator.cleanTrustAnchor();
348
349 for (ContactList::const_iterator it = contactList.begin(); it != contactList.end(); it++)
350 m_validator.addTrustAnchor((*it)->getPublicKeyName(), (*it)->getPublicKey());
351
352}
353
354
355} // namespace chronos
356
357#if WAF
358#include "controller-backend.moc"
359// #include "controller-backend.cpp.moc"
360#endif