blob: 78e67d2ce1e436f0a4c43f162a7f9fece636ebcb [file] [log] [blame]
Yingdi Yu31ad44c2014-08-28 14:55:42 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Davide Pesavento8663ed12022-07-23 03:04:27 -04003 * Copyright (c) 2012-2022 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:
Davide Pesavento8663ed12022-07-23 03:04:27 -040055 using std::runtime_error::runtime_error;
Yingdi Yu31ad44c2014-08-28 14:55:42 -070056 };
57
58 Socket(const Name& syncPrefix,
59 const Name& userPrefix,
60 ndn::Face& face,
Yingdi Yucd339022014-11-05 17:51:19 -080061 const UpdateCallback& updateCallback,
62 const Name& signingId = DEFAULT_NAME,
Ashlesh Gawandeaae853c2018-02-06 17:28:50 -060063 std::shared_ptr<Validator> validator = DEFAULT_VALIDATOR,
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -050064 const time::milliseconds& syncInterestLifetime = Logic::DEFAULT_SYNC_INTEREST_LIFETIME,
Ashlesh Gawandedb862e02018-03-30 17:15:08 -050065 const name::Component& session = name::Component());
Yingdi Yu31ad44c2014-08-28 14:55:42 -070066
Qiuhan Ding03b9de32015-01-30 14:03:12 -080067 ~Socket();
68
Davide Pesavento8663ed12022-07-23 03:04:27 -040069 using DataValidatedCallback = std::function<void(const Data&)>;
70 using DataValidationErrorCallback = std::function<void(const Data&, const ValidationError& error)> ;
Ashlesh Gawande08784d42017-09-06 23:40:21 -050071
Qiuhan Ding03b9de32015-01-30 14:03:12 -080072 /**
73 * @brief Add a sync node under same logic
74 *
75 * This method will add a new sync node in logic and then register this prefix.
76 * If pass an empty prefix, it will return directly without doing anything
77 * If the prefix is already registered, return directly
78 *
79 * @param prefix Prefix of the new node
80 * @param signingId Signing ID for the packet sent out by the new node
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -050081 * @param session Manually defined session number
Qiuhan Ding03b9de32015-01-30 14:03:12 -080082 */
Yingdi Yu31ad44c2014-08-28 14:55:42 -070083 void
Ashlesh Gawandedb862e02018-03-30 17:15:08 -050084 addSyncNode(const Name& prefix, const Name& signingId = DEFAULT_NAME,
85 const name::Component& session = name::Component());
Yingdi Yu31ad44c2014-08-28 14:55:42 -070086
87 /**
Qiuhan Ding03b9de32015-01-30 14:03:12 -080088 * @brief Remove a sync node under same logic
89 *
90 * This method will remove a sync node in logic, unregister this prefix
91 * and then clear the in memory storage about this prefix.
92 * logic will be reset after removal of this node
93 *
94 * @param prefix Prefix of the node to remove
95 */
96 void
97 removeSyncNode(const Name& prefix);
98
99 /**
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700100 * @brief Publish a data packet in the session and trigger synchronization updates
101 *
102 * This method will create a data packet with the supplied content.
103 * The packet name is the local session + seqNo.
104 * The seqNo is automatically maintained by internal Logic.
105 *
Qiuhan Dinge246b622014-12-03 21:57:48 -0800106 * @throws It will throw error, if the prefix does not exist in m_logic
107 *
108 * @param buf Pointer to the bytes in content
109 * @param len size of the bytes in content
110 * @param freshness FreshnessPeriod of the data packet.
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500111 * @param prefix The user prefix that will be used to publish the data.
Qiuhan Dinge246b622014-12-03 21:57:48 -0800112 */
113 void
114 publishData(const uint8_t* buf, size_t len, const ndn::time::milliseconds& freshness,
115 const Name& prefix = DEFAULT_PREFIX);
116
117 /**
118 * @brief Publish a data packet in the session and trigger synchronization updates
119 *
120 * This method will create a data packet with the supplied content.
121 * The packet name is the local session + seqNo.
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500122 * The seqNo is set by the application.
123 *
124 * @throws It will throw error, if the prefix does not exist in m_logic
125 *
126 * @param buf Pointer to the bytes in content
127 * @param len size of the bytes in content
128 * @param freshness FreshnessPeriod of the data packet.
129 * @param seqNo Sequence number of the data
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500130 * @param prefix The user prefix that will be used to publish the data.
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500131 */
132 void
133 publishData(const uint8_t* buf, size_t len, const ndn::time::milliseconds& freshness,
134 const uint64_t& seqNo, const Name& prefix = DEFAULT_PREFIX);
135
136 /**
137 * @brief Publish a data packet in the session and trigger synchronization updates
138 *
139 * This method will create a data packet with the supplied content.
140 * The packet name is the local session + seqNo.
Qiuhan Dinge246b622014-12-03 21:57:48 -0800141 * The seqNo is automatically maintained by internal Logic.
142 *
143 * @throws It will throw error, if the prefix does not exist in m_logic
144 *
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700145 * @param content Block that will be set as the content of the data packet.
146 * @param freshness FreshnessPeriod of the data packet.
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500147 * @param prefix The user prefix that will be used to publish the data.
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700148 */
149 void
Qiuhan Dinge246b622014-12-03 21:57:48 -0800150 publishData(const Block& content, const ndn::time::milliseconds& freshness,
151 const Name& prefix = DEFAULT_PREFIX);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700152
153 /**
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500154 * @brief Publish a data packet in the session and trigger synchronization updates
155 *
156 * This method will create a data packet with the supplied content.
157 * The packet name is the local session + seqNo.
158 * The seqNo is set by the application.
159 *
160 * @throws It will throw error, if the prefix does not exist in m_logic
161 *
162 * @param content Block that will be set as the content of the data packet.
163 * @param freshness FreshnessPeriod of the data packet.
164 * @param seqNo Sequence number of the data
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500165 * @param prefix The user prefix that will be used to publish the data.
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500166 */
167 void
168 publishData(const Block& content, const ndn::time::milliseconds& freshness,
169 const uint64_t& seqNo, const Name& prefix = DEFAULT_PREFIX);
170
171 /**
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700172 * @brief Retrive a data packet with a particular seqNo from a session
173 *
174 * @param sessionName The name of the target session.
175 * @param seq The seqNo of the data packet.
176 * @param onValidated The callback when the retrieved packet has been validated.
177 * @param nRetries The number of retries.
178 */
179 void
180 fetchData(const Name& sessionName, const SeqNo& seq,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500181 const DataValidatedCallback& onValidated,
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700182 int nRetries = 0);
183
184 /**
185 * @brief Retrive a data packet with a particular seqNo from a session
186 *
187 * @param sessionName The name of the target session.
188 * @param seq The seqNo of the data packet.
189 * @param onValidated The callback when the retrieved packet has been validated.
Ashlesh Gawande097bb442017-05-31 13:38:00 -0500190 * @param onValidationFailed The callback when the retrieved packet failed validation.
191 * @param onTimeout The callback when data is not retrieved.
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700192 * @param nRetries The number of retries.
193 */
194 void
195 fetchData(const Name& sessionName, const SeqNo& seq,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500196 const DataValidatedCallback& onValidated,
197 const DataValidationErrorCallback& onValidationFailed,
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800198 const ndn::TimeoutCallback& onTimeout,
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700199 int nRetries = 0);
200
201 /// @brief Get the root digest of current sync tree
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500202 ConstBufferPtr
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700203 getRootDigest() const;
204
205 Logic&
206 getLogic()
207 {
208 return m_logic;
209 }
210
211private:
212 void
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800213 onInterest(const Name& prefix, const Interest& interest);
214
215 void
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800216 onData(const Interest& interest, const Data& data,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500217 const DataValidatedCallback& dataCallback,
218 const DataValidationErrorCallback& failCallback);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700219
220 void
221 onDataTimeout(const Interest& interest, int nRetries,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500222 const DataValidatedCallback& dataCallback,
223 const DataValidationErrorCallback& failCallback);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700224
225 void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500226 onDataValidationFailed(const Data& data,
227 const ValidationError& error);
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700228
Yingdi Yucd339022014-11-05 17:51:19 -0800229public:
Davide Pesavento8663ed12022-07-23 03:04:27 -0400230 static inline const Name DEFAULT_NAME;
231 static inline const Name DEFAULT_PREFIX;
232 static inline const std::shared_ptr<Validator> DEFAULT_VALIDATOR;
Yingdi Yucd339022014-11-05 17:51:19 -0800233
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700234private:
Davide Pesavento8663ed12022-07-23 03:04:27 -0400235 using RegisteredPrefixList = std::unordered_map<Name, ndn::RegisteredPrefixHandle>;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700236
237 Name m_userPrefix;
238 ndn::Face& m_face;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700239 Logic m_logic;
240
Ashlesh Gawande687cf922017-05-30 15:04:16 -0500241 Name m_signingId;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700242 ndn::KeyChain m_keyChain;
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500243 std::shared_ptr<Validator> m_validator;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800244
245 RegisteredPrefixList m_registeredPrefixList;
Ashlesh Gawande687cf922017-05-30 15:04:16 -0500246 ndn::InMemoryStoragePersistent m_ims;
Yingdi Yu31ad44c2014-08-28 14:55:42 -0700247};
248
249} // namespace chronosync
250
251#endif // CHRONOSYNC_SOCKET_HPP