Alexander Afanasyev | fa2f662 | 2016-12-25 12:28:00 -0800 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 | /** |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 3 | * Copyright (c) 2013-2017, Regents of the University of California. |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 4 | * |
Alexander Afanasyev | fa2f662 | 2016-12-25 12:28:00 -0800 | [diff] [blame] | 5 | * This file is part of ChronoShare, a decentralized file sharing application over NDN. |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 6 | * |
Alexander Afanasyev | fa2f662 | 2016-12-25 12:28:00 -0800 | [diff] [blame] | 7 | * ChronoShare is free software: you can redistribute it and/or modify it under the terms |
| 8 | * of the GNU General Public License as published by the Free Software Foundation, either |
| 9 | * version 3 of the License, or (at your option) any later version. |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 10 | * |
Alexander Afanasyev | fa2f662 | 2016-12-25 12:28:00 -0800 | [diff] [blame] | 11 | * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY |
| 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
| 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 14 | * |
Alexander Afanasyev | fa2f662 | 2016-12-25 12:28:00 -0800 | [diff] [blame] | 15 | * You should have received copies of the GNU General Public License along with |
| 16 | * ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * |
| 18 | * See AUTHORS.md for complete list of ChronoShare authors and contributors. |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 19 | */ |
| 20 | |
| 21 | #ifndef SYNC_CORE_H |
| 22 | #define SYNC_CORE_H |
| 23 | |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 24 | #include "sync-log.hpp" |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 25 | #include "core/chronoshare-common.hpp" |
| 26 | #include "core/random-interval-generator.hpp" |
Alexander Afanasyev | abe952a | 2013-01-17 17:06:32 -0800 | [diff] [blame] | 27 | |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 28 | #include <ndn-cxx/face.hpp> |
| 29 | #include <ndn-cxx/security/key-chain.hpp> |
| 30 | #include <ndn-cxx/util/scheduler-scoped-event-id.hpp> |
| 31 | #include <ndn-cxx/util/scheduler.hpp> |
| 32 | |
| 33 | #include <boost/iostreams/device/back_inserter.hpp> |
| 34 | #include <boost/iostreams/filter/gzip.hpp> |
| 35 | #include <boost/iostreams/filtering_stream.hpp> |
| 36 | |
| 37 | namespace ndn { |
| 38 | namespace chronoshare { |
| 39 | |
| 40 | // No use this now |
| 41 | template <class Msg> |
| 42 | BufferPtr |
| 43 | serializeMsg(const Msg& msg) |
| 44 | { |
| 45 | int size = msg.ByteSize(); |
| 46 | BufferPtr bytes = std::make_shared<Buffer>(size); |
| 47 | msg.SerializeToArray(bytes->buf(), size); |
| 48 | return bytes; |
| 49 | } |
| 50 | |
| 51 | template <class Msg> |
| 52 | shared_ptr<Msg> |
| 53 | deserializeMsg(const Buffer& bytes) |
| 54 | { |
| 55 | shared_ptr<Msg> retval(new Msg()); |
| 56 | if (!retval->ParseFromArray(bytes.buf(), bytes.size())) { |
| 57 | // to indicate an error |
| 58 | return shared_ptr<Msg>(); |
| 59 | } |
| 60 | return retval; |
| 61 | } |
| 62 | |
| 63 | template <class Msg> |
| 64 | BufferPtr |
| 65 | serializeGZipMsg(const Msg& msg) |
| 66 | { |
| 67 | std::vector<char> bytes; // Bytes couldn't work |
| 68 | { |
| 69 | boost::iostreams::filtering_ostream out; |
| 70 | out.push(boost::iostreams::gzip_compressor()); // gzip filter |
| 71 | out.push(boost::iostreams::back_inserter(bytes)); // back_inserter sink |
| 72 | |
| 73 | msg.SerializeToOstream(&out); |
| 74 | } |
| 75 | BufferPtr uBytes = std::make_shared<Buffer>(bytes.size()); |
| 76 | memcpy(&(*uBytes)[0], &bytes[0], bytes.size()); |
| 77 | return uBytes; |
| 78 | } |
| 79 | |
| 80 | template <class Msg> |
| 81 | shared_ptr<Msg> |
| 82 | deserializeGZipMsg(const Buffer& bytes) |
| 83 | { |
| 84 | std::vector<char> sBytes(bytes.size()); |
| 85 | memcpy(&sBytes[0], &bytes[0], bytes.size()); |
| 86 | boost::iostreams::filtering_istream in; |
| 87 | in.push(boost::iostreams::gzip_decompressor()); // gzip filter |
| 88 | in.push(boost::make_iterator_range(sBytes)); // source |
| 89 | |
| 90 | shared_ptr<Msg> retval = make_shared<Msg>(); |
| 91 | if (!retval->ParseFromIstream(&in)) { |
| 92 | // to indicate an error |
| 93 | return shared_ptr<Msg>(); |
| 94 | } |
| 95 | |
| 96 | return retval; |
| 97 | } |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 98 | |
| 99 | class SyncCore |
| 100 | { |
| 101 | public: |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 102 | typedef function<void(SyncStateMsgPtr stateMsg)> StateMsgCallback; |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 103 | |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 104 | static const int FRESHNESS; // seconds |
| 105 | static const std::string RECOVER; |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 106 | static const double WAIT; // seconds; |
Zhenkai Zhu | e851b95 | 2013-01-13 22:29:57 -0800 | [diff] [blame] | 107 | static const double RANDOM_PERCENT; // seconds; |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 108 | |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 109 | class Error : public boost::exception, public std::runtime_error |
| 110 | { |
| 111 | public: |
| 112 | explicit Error(const std::string& what) |
| 113 | : std::runtime_error(what) |
| 114 | { |
| 115 | } |
| 116 | }; |
| 117 | |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 118 | public: |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 119 | SyncCore(Face& face, SyncLogPtr syncLog, const Name& userName, |
| 120 | const Name& localPrefix // routable name used by the local user |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 121 | , |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 122 | const Name& syncPrefix // the prefix for the sync collection |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 123 | , |
| 124 | const StateMsgCallback& callback // callback when state change is detected |
| 125 | , |
Lijing Wang | 8e56d08 | 2016-12-25 14:45:23 -0800 | [diff] [blame] | 126 | time::seconds syncInterestInterval = time::seconds(0)); |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 127 | ~SyncCore(); |
| 128 | |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 129 | void updateLocalState(sqlite3_int64); |
| 130 | |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 131 | void |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 132 | localStateChanged(); |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 133 | |
Alexander Afanasyev | a2fabcf | 2013-02-05 11:26:37 -0800 | [diff] [blame] | 134 | /** |
| 135 | * @brief Schedule an event to update local state with a small delay |
| 136 | * |
| 137 | * This call is preferred to localStateChanged if many local state updates |
| 138 | * are anticipated within a short period of time |
| 139 | */ |
| 140 | void |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 141 | localStateChangedDelayed(); |
Alexander Afanasyev | a2fabcf | 2013-02-05 11:26:37 -0800 | [diff] [blame] | 142 | |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 143 | // ------------------ only used in test ------------------------- |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 144 | |
Alexander Afanasyev | 49a30d0 | 2013-01-21 21:38:48 -0800 | [diff] [blame] | 145 | public: |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 146 | ConstBufferPtr |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 147 | root() const |
| 148 | { |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 149 | return m_rootDigest; |
Alexander Afanasyev | eda3b7a | 2016-12-25 11:26:40 -0800 | [diff] [blame] | 150 | } |
Alexander Afanasyev | 49a30d0 | 2013-01-21 21:38:48 -0800 | [diff] [blame] | 151 | |
| 152 | sqlite3_int64 |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 153 | seq(const Name& name); |
Alexander Afanasyev | 49a30d0 | 2013-01-21 21:38:48 -0800 | [diff] [blame] | 154 | |
| 155 | private: |
| 156 | void |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 157 | onRegisterFailed(const Name& prefix, const std::string& reason) |
| 158 | { |
| 159 | std::cerr << "ERROR: Failed to register prefix \"" << prefix << "\" in local hub's daemon (" |
| 160 | << reason << ")" << std::endl; |
| 161 | throw Error("ERROR: Failed to register prefix (" + reason + ")"); |
| 162 | } |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 163 | |
| 164 | void |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 165 | sendSyncInterest(); |
| 166 | |
Zhenkai Zhu | e851b95 | 2013-01-13 22:29:57 -0800 | [diff] [blame] | 167 | void |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 168 | sendPeriodicSyncInterest(const time::seconds& interval); |
Zhenkai Zhu | e851b95 | 2013-01-13 22:29:57 -0800 | [diff] [blame] | 169 | |
| 170 | void |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 171 | recover(ConstBufferPtr digest); |
Zhenkai Zhu | e851b95 | 2013-01-13 22:29:57 -0800 | [diff] [blame] | 172 | |
| 173 | void |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 174 | handleInterest(const InterestFilter& filter, const Interest& interest); |
| 175 | |
| 176 | void |
| 177 | handleSyncInterest(const Name& name); |
| 178 | |
| 179 | void |
| 180 | handleRecoverInterest(const Name& name); |
| 181 | |
| 182 | void |
| 183 | handleSyncInterestTimeout(const Interest& interest); |
| 184 | |
| 185 | void |
| 186 | handleRecoverInterestTimeout(const Interest& interest); |
| 187 | |
| 188 | void |
| 189 | handleSyncData(const Interest& interest, Data& data); |
| 190 | |
| 191 | void |
| 192 | handleRecoverData(const Interest& interest, Data& data); |
| 193 | |
| 194 | void |
| 195 | handleStateData(const Buffer& content); |
| 196 | |
| 197 | void |
| 198 | deregister(const Name& name); |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 199 | |
Alexander Afanasyev | c507ac2 | 2013-01-21 16:01:58 -0800 | [diff] [blame] | 200 | private: |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 201 | Face& m_face; |
Alexander Afanasyev | 49a30d0 | 2013-01-21 21:38:48 -0800 | [diff] [blame] | 202 | |
Zhenkai Zhu | b330aed | 2013-01-17 13:29:37 -0800 | [diff] [blame] | 203 | SyncLogPtr m_log; |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 204 | |
| 205 | Scheduler m_scheduler; |
| 206 | util::scheduler::ScopedEventId m_syncInterestEvent; |
| 207 | util::scheduler::ScopedEventId m_periodicInterestEvent; |
| 208 | util::scheduler::ScopedEventId m_localStateDelayedEvent; |
| 209 | |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 210 | StateMsgCallback m_stateMsgCallback; |
Alexander Afanasyev | 49a30d0 | 2013-01-21 21:38:48 -0800 | [diff] [blame] | 211 | |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 212 | Name m_syncPrefix; |
| 213 | ConstBufferPtr m_rootDigest; |
Zhenkai Zhu | 74dd53c | 2013-01-10 23:39:57 -0800 | [diff] [blame] | 214 | |
Zhenkai Zhu | e573ae8 | 2013-01-15 13:15:52 -0800 | [diff] [blame] | 215 | IntervalGeneratorPtr m_recoverWaitGenerator; |
Zhenkai Zhu | 3b40659 | 2013-01-25 21:07:49 -0800 | [diff] [blame] | 216 | |
Lijing Wang | 8e56d08 | 2016-12-25 14:45:23 -0800 | [diff] [blame] | 217 | time::seconds m_syncInterestInterval; |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 218 | KeyChain m_keyChain; |
| 219 | const RegisteredPrefixId* m_registeredPrefixId; |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 220 | }; |
| 221 | |
Lijing Wang | e84adea | 2015-05-31 16:25:16 -0700 | [diff] [blame] | 222 | } // namespace chronoshare |
| 223 | } // namespace ndn |
| 224 | |
Zhenkai Zhu | 8224bb6 | 2013-01-06 15:58:02 -0800 | [diff] [blame] | 225 | #endif // SYNC_CORE_H |