blob: b7b0858eae6f9bc78b5fc07da70679f356d6fd91 [file] [log] [blame]
Yingdi Yu31ad44c2014-08-28 14:55:42 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Ashlesh Gawandeaae853c2018-02-06 17:28:50 -06003 * Copyright (c) 2012-2018 University of California, Los Angeles
Yingdi Yu31ad44c2014-08-28 14:55:42 -07004 *
5 * This file is part of ChronoSync, synchronization library for distributed realtime
6 * applications for NDN.
7 *
8 * 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.
11 *
12 * 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.
15 *
16 * 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 Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
20 * @author Chaoyi Bian <bcy@pku.edu.cn>
21 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
22 * @author Yingdi Yu <yingdi@cs.ucla.edu>
23 */
24
25#ifndef CHRONOSYNC_SOCKET_HPP
26#define CHRONOSYNC_SOCKET_HPP
27
Yingdi Yu31ad44c2014-08-28 14:55:42 -070028#include "logic.hpp"
29
Ashlesh Gawande687cf922017-05-30 15:04:16 -050030#include <unordered_map>
31
Ashlesh Gawande08784d42017-09-06 23:40:21 -050032#include <ndn-cxx/ims/in-memory-storage-persistent.hpp>
33
Yingdi Yu31ad44c2014-08-28 14:55:42 -070034namespace chronosync {
35
36/**
37 * @brief A simple interface to interact with client code
38 *
39 * Though it is called Socket, it is not a real socket. It just trying to provide
40 * a simplified interface for data publishing and fetching.
41 *
42 * This interface simplify data publishing. Client can simply dump raw data
43 * into this interface without handling the ChronoSync specific details, such
44 * as sequence number and session id.
45 *
46 * This interface also simplify data fetching. Client only needs to provide a
47 * data fetching strategy (through a updateCallback).
48 */
49class Socket : noncopyable
50{
51public:
52 class Error : public std::runtime_error
53 {
54 public:
55 explicit
56 Error(const std::string& what)
57 : std::runtime_error(what)
58 {
59 }
60 };
61
62 Socket(const Name& syncPrefix,
63 const Name& userPrefix,
64 ndn::Face& face,
Yingdi Yucd339022014-11-05 17:51:19 -080065 const UpdateCallback& updateCallback,
66 const Name& signingId = DEFAULT_NAME,
Ashlesh Gawandeaae853c2018-02-06 17:28:50 -060067 std::shared_ptr<Validator> validator = DEFAULT_VALIDATOR,
68 const time::milliseconds& syncInterestLifetime = Logic::DEFAULT_SYNC_INTEREST_LIFETIME);
Yingdi Yu31ad44c2014-08-28 14:55:42 -070069
Qiuhan Ding03b9de32015-01-30 14:03:12 -080070 ~Socket();
71
Ashlesh Gawande08784d42017-09-06 23:40:21 -050072 using DataValidatedCallback = function<void(const Data&)>;
73
74 using DataValidationErrorCallback = function<void(const Data&, const ValidationError& error)> ;
75
Qiuhan Ding03b9de32015-01-30 14:03:12 -080076 /**
77 * @brief Add a sync node under same logic
78 *
79 * This method will add a new sync node in logic and then register this prefix.
80 * If pass an empty prefix, it will return directly without doing anything
81 * If the prefix is already registered, return directly
82 *
83 * @param prefix Prefix of the new node
84 * @param signingId Signing ID for the packet sent out by the new node
85 */
Yingdi Yu31ad44c2014-08-28 14:55:42 -070086 void
Qiuhan Dinge246b622014-12-03 21:57:48 -080087 addSyncNode(const Name& prefix, const Name& signingId = DEFAULT_NAME);
Yingdi Yu31ad44c2014-08-28 14:55:42 -070088
89 /**
Qiuhan Ding03b9de32015-01-30 14:03:12 -080090 * @brief Remove a sync node under same logic
91 *
92 * This method will remove a sync node in logic, unregister this prefix
93 * and then clear the in memory storage about this prefix.
94 * logic will be reset after removal of this node
95 *
96 * @param prefix Prefix of the node to remove
97 */
98 void
99 removeSyncNode(const Name& prefix);
100
101 /**
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700102 * @brief Publish a data packet in the session and trigger synchronization updates
103 *
104 * This method will create a data packet with the supplied content.
105 * The packet name is the local session + seqNo.
106 * The seqNo is automatically maintained by internal Logic.
107 *
Qiuhan Dinge246b622014-12-03 21:57:48 -0800108 * @throws It will throw error, if the prefix does not exist in m_logic
109 *
110 * @param buf Pointer to the bytes in content
111 * @param len size of the bytes in content
112 * @param freshness FreshnessPeriod of the data packet.
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500113 * @param prefix The user prefix that will be used to publish the data.
Qiuhan Dinge246b622014-12-03 21:57:48 -0800114 */
115 void
116 publishData(const uint8_t* buf, size_t len, const ndn::time::milliseconds& freshness,
117 const Name& prefix = DEFAULT_PREFIX);
118
119 /**
120 * @brief Publish a data packet in the session and trigger synchronization updates
121 *
122 * This method will create a data packet with the supplied content.
123 * The packet name is the local session + seqNo.
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500124 * The seqNo is set by the application.
125 *
126 * @throws It will throw error, if the prefix does not exist in m_logic
127 *
128 * @param buf Pointer to the bytes in content
129 * @param len size of the bytes in content
130 * @param freshness FreshnessPeriod of the data packet.
131 * @param seqNo Sequence number of the data
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500132 * @param prefix The user prefix that will be used to publish the data.
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500133 */
134 void
135 publishData(const uint8_t* buf, size_t len, const ndn::time::milliseconds& freshness,
136 const uint64_t& seqNo, const Name& prefix = DEFAULT_PREFIX);
137
138 /**
139 * @brief Publish a data packet in the session and trigger synchronization updates
140 *
141 * This method will create a data packet with the supplied content.
142 * The packet name is the local session + seqNo.
Qiuhan Dinge246b622014-12-03 21:57:48 -0800143 * The seqNo is automatically maintained by internal Logic.
144 *
145 * @throws It will throw error, if the prefix does not exist in m_logic
146 *
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700147 * @param content Block that will be set as the content of the data packet.
148 * @param freshness FreshnessPeriod of the data packet.
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500149 * @param prefix The user prefix that will be used to publish the data.
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700150 */
151 void
Qiuhan Dinge246b622014-12-03 21:57:48 -0800152 publishData(const Block& content, const ndn::time::milliseconds& freshness,
153 const Name& prefix = DEFAULT_PREFIX);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700154
155 /**
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500156 * @brief Publish a data packet in the session and trigger synchronization updates
157 *
158 * This method will create a data packet with the supplied content.
159 * The packet name is the local session + seqNo.
160 * The seqNo is set by the application.
161 *
162 * @throws It will throw error, if the prefix does not exist in m_logic
163 *
164 * @param content Block that will be set as the content of the data packet.
165 * @param freshness FreshnessPeriod of the data packet.
166 * @param seqNo Sequence number of the data
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500167 * @param prefix The user prefix that will be used to publish the data.
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500168 */
169 void
170 publishData(const Block& content, const ndn::time::milliseconds& freshness,
171 const uint64_t& seqNo, const Name& prefix = DEFAULT_PREFIX);
172
173 /**
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700174 * @brief Retrive a data packet with a particular seqNo from a session
175 *
176 * @param sessionName The name of the target session.
177 * @param seq The seqNo of the data packet.
178 * @param onValidated The callback when the retrieved packet has been validated.
179 * @param nRetries The number of retries.
180 */
181 void
182 fetchData(const Name& sessionName, const SeqNo& seq,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500183 const DataValidatedCallback& onValidated,
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700184 int nRetries = 0);
185
186 /**
187 * @brief Retrive a data packet with a particular seqNo from a session
188 *
189 * @param sessionName The name of the target session.
190 * @param seq The seqNo of the data packet.
191 * @param onValidated The callback when the retrieved packet has been validated.
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500192 * @param onValidationFailed The callback when the retrieved packet failed validation.
193 * @param onTimeout The callback when data is not retrieved.
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700194 * @param nRetries The number of retries.
195 */
196 void
197 fetchData(const Name& sessionName, const SeqNo& seq,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500198 const DataValidatedCallback& onValidated,
199 const DataValidationErrorCallback& onValidationFailed,
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800200 const ndn::TimeoutCallback& onTimeout,
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700201 int nRetries = 0);
202
203 /// @brief Get the root digest of current sync tree
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500204 ConstBufferPtr
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700205 getRootDigest() const;
206
207 Logic&
208 getLogic()
209 {
210 return m_logic;
211 }
212
213private:
214 void
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800215 onInterest(const Name& prefix, const Interest& interest);
216
217 void
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800218 onData(const Interest& interest, const Data& data,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500219 const DataValidatedCallback& dataCallback,
220 const DataValidationErrorCallback& failCallback);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700221
222 void
223 onDataTimeout(const Interest& interest, int nRetries,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500224 const DataValidatedCallback& dataCallback,
225 const DataValidationErrorCallback& failCallback);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700226
227 void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500228 onDataValidationFailed(const Data& data,
229 const ValidationError& error);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700230
Yingdi Yucd339022014-11-05 17:51:19 -0800231public:
232 static const ndn::Name DEFAULT_NAME;
Qiuhan Dinge246b622014-12-03 21:57:48 -0800233 static const ndn::Name DEFAULT_PREFIX;
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500234 static const std::shared_ptr<Validator> DEFAULT_VALIDATOR;
Yingdi Yucd339022014-11-05 17:51:19 -0800235
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700236private:
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500237 using RegisteredPrefixList = std::unordered_map<ndn::Name, const ndn::RegisteredPrefixId*>;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700238
239 Name m_userPrefix;
240 ndn::Face& m_face;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700241 Logic m_logic;
242
Ashlesh Gawande687cf922017-05-30 15:04:16 -0500243 Name m_signingId;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700244 ndn::KeyChain m_keyChain;
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500245 std::shared_ptr<Validator> m_validator;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800246
247 RegisteredPrefixList m_registeredPrefixList;
Ashlesh Gawande687cf922017-05-30 15:04:16 -0500248 ndn::InMemoryStoragePersistent m_ims;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700249};
250
251} // namespace chronosync
252
253#endif // CHRONOSYNC_SOCKET_HPP