blob: b344a3e7e688a4b089e9c7407ff9344ce1efe0f1 [file] [log] [blame]
Alexander Afanasyev8722d872014-07-02 13:00:29 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
Yingdi Yu43e71612013-10-30 22:19:31 -07002/*
Alexander Afanasyev8722d872014-07-02 13:00:29 -07003 * Copyright (c) 2012-2014 University of California, Los Angeles
Yingdi Yu43e71612013-10-30 22:19:31 -07004 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -07005 * This file is part of ChronoSync, synchronization library for distributed realtime
6 * applications for NDN.
Yingdi Yu43e71612013-10-30 22:19:31 -07007 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -07008 * ChronoSync is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation, either
10 * version 3 of the License, or (at your option) any later version.
Yingdi Yu43e71612013-10-30 22:19:31 -070011 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -070012 * ChronoSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
Yingdi Yu43e71612013-10-30 22:19:31 -070015 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -070016 * You should have received a copy of the GNU General Public License along with
17 * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
20 * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
21 * @author Chaoyi Bian <bcy@pku.edu.cn>
22 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Yingdi Yu43e71612013-10-30 22:19:31 -070023 */
24
25#include "sync-socket.h"
Yingdi Yu46c9f1a2013-12-18 15:15:46 +080026#include "sync-logging.h"
27
Yingdi Yu43e71612013-10-30 22:19:31 -070028using namespace ndn;
Yingdi Yu46c9f1a2013-12-18 15:15:46 +080029
Yingdi Yu06a678a2014-08-01 17:07:08 -070030INIT_LOGGER ("SyncSocket")
Yingdi Yu43e71612013-10-30 22:19:31 -070031
32namespace Sync {
33
Alexander Afanasyev531803b2014-02-05 15:57:35 -080034using ndn::shared_ptr;
35
Yingdi Yud4ef5d32014-03-01 02:02:01 -080036static const uint8_t ROUTING_PREFIX_SEPARATOR[2] = {0xF0, 0x2E};
37
38const Name SyncSocket::EMPTY_NAME = Name();
39
Yingdi Yu0eee6002014-02-11 15:54:17 -080040SyncSocket::SyncSocket (const Name& syncPrefix,
Yingdi Yud4ef5d32014-03-01 02:02:01 -080041 const Name& dataPrefix,
Yingdi Yu3da10fe2014-02-27 16:37:34 -080042 uint64_t dataSession,
Yingdi Yud4ef5d32014-03-01 02:02:01 -080043 bool withRoutingPrefix,
Yingdi Yua873d642014-04-15 21:31:33 -070044 const Name& routingPrefix,
Yingdi Yuaed0f3e2014-02-28 14:54:16 -080045 shared_ptr<Face> face,
Yingdi Yu3da10fe2014-02-27 16:37:34 -080046 const IdentityCertificate& myCertificate,
47 shared_ptr<SecRuleRelative> dataRule,
Yingdi Yua873d642014-04-15 21:31:33 -070048 NewDataCallback dataCallback,
Yingdi Yu43e71612013-10-30 22:19:31 -070049 RemoveCallback rmCallback )
Yingdi Yu3da10fe2014-02-27 16:37:34 -080050 : m_dataPrefix(dataPrefix)
51 , m_dataSession(dataSession)
Yingdi Yud4ef5d32014-03-01 02:02:01 -080052 , m_withRoutingPrefix(false)
Yingdi Yu3da10fe2014-02-27 16:37:34 -080053 , m_newDataCallback(dataCallback)
54 , m_myCertificate(myCertificate)
Yingdi Yu6e235db2013-12-27 08:40:53 +080055 , m_face(face)
Alexander Afanasyev7fe59832014-07-02 12:17:46 -070056 , m_ioService(face->getIoService())
Yingdi Yuaed0f3e2014-02-28 14:54:16 -080057{
Yingdi Yud4ef5d32014-03-01 02:02:01 -080058 if(withRoutingPrefix && !routingPrefix.isPrefixOf(m_dataPrefix))
59 {
60 m_withRoutingPrefix = true;
61 m_routableDataPrefix.append(routingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2).append(m_dataPrefix);
62 }
63
64
Yingdi Yuaed0f3e2014-02-28 14:54:16 -080065 if(static_cast<bool>(dataRule))
66 {
67 m_withSecurity = true;
Yingdi Yua873d642014-04-15 21:31:33 -070068 m_syncValidator = shared_ptr<Validator>(new SyncValidator(syncPrefix,
69 m_myCertificate,
70 *m_face,
Yingdi Yuaed0f3e2014-02-28 14:54:16 -080071 bind(&SyncSocket::publishData, this, _1, _2, _3, true),
72 dataRule));
73 }
74 else
75 {
76 m_withSecurity = false;
77 m_syncValidator = shared_ptr<Validator>(new ValidatorNull());
78 }
79
Yingdi Yua873d642014-04-15 21:31:33 -070080
Yingdi Yuaed0f3e2014-02-28 14:54:16 -080081 m_syncLogic = shared_ptr<SyncLogic>(new SyncLogic(syncPrefix,
82 myCertificate,
83 m_syncValidator,
84 m_face,
85 bind(&SyncSocket::passCallback, this, _1),
86 rmCallback));
87}
Yingdi Yu43e71612013-10-30 22:19:31 -070088
89SyncSocket::~SyncSocket()
Yingdi Yu479e1172013-11-06 16:36:19 -080090{
Yingdi Yu46c9f1a2013-12-18 15:15:46 +080091}
92
Yingdi Yu3da10fe2014-02-27 16:37:34 -080093void
94SyncSocket::publishData(const uint8_t* buf, size_t len, int freshness, bool isCert)
Yingdi Yu43e71612013-10-30 22:19:31 -070095{
Yingdi Yu51c80252014-02-10 19:32:05 -080096 shared_ptr<Data> data = make_shared<Data>();
97 data->setContent(reinterpret_cast<const uint8_t*>(buf), len);
Yingdi Yu6e1c9cd2014-03-25 10:26:54 -070098 data->setFreshnessPeriod(time::milliseconds(1000*freshness));
Yingdi Yu51c80252014-02-10 19:32:05 -080099
Alexander Afanasyev7fe59832014-07-02 12:17:46 -0700100 m_ioService.post(bind(&SyncSocket::publishDataInternal, this,
101 data, isCert));
Yingdi Yu51c80252014-02-10 19:32:05 -0800102}
103
104void
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800105SyncSocket::publishDataInternal(shared_ptr<Data> data, bool isCert)
Yingdi Yu51c80252014-02-10 19:32:05 -0800106{
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800107 Name dataPrefix = (m_withRoutingPrefix ? m_routableDataPrefix : m_dataPrefix);
108
109 uint64_t sequence = getNextSeq();
110
111 Name dataName;
112 dataName.append(m_dataPrefix)
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700113 .append(boost::lexical_cast<std::string>(m_dataSession))
114 .append(boost::lexical_cast<std::string>(sequence));
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800115 if(isCert)
116 dataName.append("INTRO-CERT");
Yingdi Yu51c80252014-02-10 19:32:05 -0800117 data->setName(dataName);
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800118 m_keyChain.sign(*data, m_myCertificate.getName());
Yingdi Yu46c9f1a2013-12-18 15:15:46 +0800119
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800120 if(m_withRoutingPrefix)
121 {
122 Name wrappedName;
123 wrappedName.append(m_routableDataPrefix)
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700124 .append(boost::lexical_cast<std::string>(m_dataSession))
125 .append(boost::lexical_cast<std::string>(sequence));
Yingdi Yu51c80252014-02-10 19:32:05 -0800126
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800127 Data wrappedData(wrappedName);
128 wrappedData.setContent(data->wireEncode());
129 m_keyChain.sign(wrappedData, m_myCertificate.getName());
130
131 m_face->put(wrappedData);
132 }
133 else
134 {
135 m_face->put(*data);
136 }
137
138 SeqNo s(m_dataSession, sequence + 1);
139 m_sequenceLog[dataPrefix] = s;
140 m_syncLogic->addLocalNames (dataPrefix, m_dataSession, sequence); // If DNS works, we should use pure m_dataprefix rather than the one with routing prefix.
Yingdi Yu43e71612013-10-30 22:19:31 -0700141}
142
Yingdi Yua873d642014-04-15 21:31:33 -0700143void
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800144SyncSocket::fetchData(const Name& prefix, const SeqNo& seq, const OnDataValidated& dataCallback, int retry)
Yingdi Yu43e71612013-10-30 22:19:31 -0700145{
Yingdi Yu6d638f02014-01-24 11:01:21 -0800146 Name interestName = prefix;
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700147 interestName.append(boost::lexical_cast<std::string>(seq.getSession())).append(boost::lexical_cast<std::string>(seq.getSeq()));
Yingdi Yu6d638f02014-01-24 11:01:21 -0800148
Yingdi Yu6d638f02014-01-24 11:01:21 -0800149 ndn::Interest interest(interestName);
Yingdi Yu280bb962014-01-30 09:52:43 -0800150 interest.setMustBeFresh(true);
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800151
Yingdi Yua873d642014-04-15 21:31:33 -0700152 m_face->expressInterest(interest,
153 bind(&SyncSocket::onData, this, _1, _2, dataCallback),
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800154 bind(&SyncSocket::onDataTimeout, this, _1, retry, dataCallback));
155
156}
157
158void
159SyncSocket::onData(const ndn::Interest& interest, Data& data, const OnDataValidated& dataCallback)
160{
161 bool encaped = false;
162
163 Name interestName = interest.getName();
164 Name::const_iterator it = interestName.begin();
165 Name::const_iterator end = interestName.end();
166
167 size_t offset = interestName.size();
168 for(; it != end; it++)
169 {
170 offset--;
Alexander Afanasyev7fe59832014-07-02 12:17:46 -0700171 if(it->toUri() == "%F0.")
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800172 {
173 encaped = true;
174 break;
175 }
176 }
177
178 if(!encaped)
179 offset = interestName.size();
180
181 const OnDataValidated& onValidated = bind(&SyncSocket::onDataValidated, this, _1, offset, dataCallback);
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800182 const OnDataValidationFailed& onValidationFailed = bind(&SyncSocket::onDataValidationFailed, this, _1, _2);
183
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800184 if(encaped)
185 {
186 shared_ptr<Data> innerData = make_shared<Data>();
187 innerData->wireDecode(data.getContent().blockFromValue());
188 m_syncValidator->validate(*innerData, onValidated, onValidationFailed);
189 }
190 else
191 m_syncValidator->validate(data, onValidated, onValidationFailed);
Yingdi Yu43e71612013-10-30 22:19:31 -0700192}
193
194void
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800195SyncSocket::onDataTimeout(const ndn::Interest& interest, int retry, const OnDataValidated& dataCallback)
Yingdi Yu43e71612013-10-30 22:19:31 -0700196{
197 if(retry > 0)
198 {
Yingdi Yu51c80252014-02-10 19:32:05 -0800199 m_face->expressInterest(interest,
Yingdi Yu6d638f02014-01-24 11:01:21 -0800200 bind(&SyncSocket::onData,
Yingdi Yu46c9f1a2013-12-18 15:15:46 +0800201 this,
202 _1,
203 _2,
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800204 dataCallback),
Yingdi Yua873d642014-04-15 21:31:33 -0700205 bind(&SyncSocket::onDataTimeout,
Yingdi Yu46c9f1a2013-12-18 15:15:46 +0800206 this,
207 _1,
208 retry - 1,
Yingdi Yud4ef5d32014-03-01 02:02:01 -0800209 dataCallback));
Yingdi Yua873d642014-04-15 21:31:33 -0700210
Yingdi Yu43e71612013-10-30 22:19:31 -0700211 }
Yingdi Yu46c9f1a2013-12-18 15:15:46 +0800212 else
Yingdi Yu6d638f02014-01-24 11:01:21 -0800213 _LOG_DEBUG("interest eventually time out!");
Yingdi Yu43e71612013-10-30 22:19:31 -0700214}
215
216void
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800217SyncSocket::onDataValidated(const shared_ptr<const Data>& data,
218 size_t interestNameSize,
219 const OnDataValidated& onValidated)
Yingdi Yu46c9f1a2013-12-18 15:15:46 +0800220{
Yingdi Yua873d642014-04-15 21:31:33 -0700221 if(data->getName().size() > interestNameSize
Alexander Afanasyev7fe59832014-07-02 12:17:46 -0700222 && data->getName().get(interestNameSize).toUri() == "INTRO-CERT")
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800223 {
Yingdi Yua873d642014-04-15 21:31:33 -0700224 if(!m_withSecurity)
Yingdi Yuaed0f3e2014-02-28 14:54:16 -0800225 return;
226
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800227 Data rawData;
228 rawData.wireDecode(data->getContent().blockFromValue());
229 IntroCertificate introCert(rawData);
Yingdi Yuaed0f3e2014-02-28 14:54:16 -0800230 dynamic_pointer_cast<SyncValidator>(m_syncValidator)->addParticipant(introCert);
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800231 }
232 else
233 {
234 onValidated(data);
235 }
Yingdi Yu46c9f1a2013-12-18 15:15:46 +0800236}
Yingdi Yu43e71612013-10-30 22:19:31 -0700237
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800238void
239SyncSocket::onDataValidationFailed(const shared_ptr<const Data>& data,
240 const std::string& failureInfo)
Yingdi Yu43e71612013-10-30 22:19:31 -0700241{
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800242 _LOG_DEBUG("data cannot be verified!: " << failureInfo);
Yingdi Yu43e71612013-10-30 22:19:31 -0700243}
244
245}//Sync