blob: 4aa0ef7314cd22c78870cb0d8dd2d35709404347 [file] [log] [blame]
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2014-2018, The University of Memphis
4 *
5 * This file is part of PSync.
6 * See AUTHORS.md for complete list of PSync authors and contributors.
7 *
8 * PSync 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,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * PSync 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 * PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 **/
19
20#ifndef PSYNC_PRODUCER_BASE_HPP
21#define PSYNC_PRODUCER_BASE_HPP
22
23#include "detail/iblt.hpp"
24#include "detail/bloom-filter.hpp"
25#include "detail/util.hpp"
26#include "detail/test-access-control.hpp"
Ashlesh Gawandeec43b362018-08-01 15:15:01 -050027#include "segment-publisher.hpp"
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050028
29#include <ndn-cxx/face.hpp>
30#include <ndn-cxx/util/scheduler.hpp>
31#include <ndn-cxx/util/time.hpp>
32#include <ndn-cxx/security/key-chain.hpp>
33#include <ndn-cxx/security/validator-config.hpp>
34
35#include <map>
36#include <unordered_set>
37#include <random>
38
39namespace psync {
40
41using namespace ndn::literals::time_literals;
42
43const ndn::time::milliseconds SYNC_REPLY_FRESHNESS = 1_s;
44const ndn::time::milliseconds HELLO_REPLY_FRESHNESS = 1_s;
45
46/**
47 * @brief Base class for PartialProducer and FullProducer
48 *
49 * Contains code common to both
50 */
51class ProducerBase
52{
53 class Error : public std::runtime_error
54 {
55 public:
56 using std::runtime_error::runtime_error;
57 };
58
59PUBLIC_WITH_TESTS_ELSE_PROTECTED:
60 /**
61 * @brief constructor
62 *
63 * @param expectedNumEntries expected number entries in IBF
64 * @param face application's face
65 * @param syncPrefix The prefix of the sync group
66 * @param userPrefix The prefix of the first user in the group
67 * @param syncReplyFreshness freshness of sync data
68 * @param helloReplyFreshness freshness of hello data
69 */
70 ProducerBase(size_t expectedNumEntries,
71 ndn::Face& face,
72 const ndn::Name& syncPrefix,
73 const ndn::Name& userPrefix,
74 ndn::time::milliseconds syncReplyFreshness = SYNC_REPLY_FRESHNESS,
75 ndn::time::milliseconds helloReplyFreshness = HELLO_REPLY_FRESHNESS);
76public:
77 /**
78 * @brief Returns the current sequence number of the given prefix
79 *
80 * @param prefix prefix to get the sequence number of
81 */
82 ndn::optional<uint64_t>
83 getSeqNo(const ndn::Name& prefix) const
84 {
85 auto it = m_prefixes.find(prefix);
86 if (it == m_prefixes.end()) {
87 return ndn::nullopt;
88 }
89 return it->second;
90 }
91
92 /**
93 * @brief Adds a user node for synchronization
94 *
95 * Initializes m_prefixes[prefix] to zero
96 * Does not add zero-th sequence number to IBF
97 * because if a large number of user nodes are added
98 * then decoding of the difference between own IBF and
99 * other IBF will not be possible
100 *
101 * @param prefix the user node to be added
102 */
103 bool
104 addUserNode(const ndn::Name& prefix);
105
106 /**
107 * @brief Remove the user node from synchronization
108 *
109 * Erases prefix from IBF and other maps
110 *
111 * @param prefix the user node to be removed
112 */
113 void
114 removeUserNode(const ndn::Name& prefix);
115
116PUBLIC_WITH_TESTS_ELSE_PROTECTED:
117 /**
118 * @brief Update m_prefixes and IBF with the given prefix and seq
119 *
120 * Whoever calls this needs to make sure that prefix is in m_prefixes
121 * We remove already existing prefix/seq from IBF
122 * (unless seq is zero because we don't insert zero seq into IBF)
123 * Then we update m_prefix, m_prefix2hash, m_hash2prefix, and IBF
124 *
125 * @param prefix prefix of the update
126 * @param seq sequence number of the update
127 */
128 void
129 updateSeqNo(const ndn::Name& prefix, uint64_t seq);
130
131 bool
132 isUserNode(const ndn::Name& prefix) {
133 if (m_prefixes.find(prefix) == m_prefixes.end()) {
134 return false;
135 }
136 return true;
137 }
138
139 /**
140 * @brief Sends a data packet with content type nack
141 *
142 * Producer sends a nack to consumer if consumer has very old IBF
143 * whose differences with latest IBF can't be decoded successfully
144 *
145 * @param name send application nack with this name
146 */
147 void
148 sendApplicationNack(const ndn::Name& name);
149
150 /**
151 * @brief Logs a message if setting an interest filter fails
152 *
153 * @param prefix
154 * @param msg
155 */
156 void
157 onRegisterFailed(const ndn::Name& prefix, const std::string& msg) const;
158
159PUBLIC_WITH_TESTS_ELSE_PROTECTED:
160 IBLT m_iblt;
161 uint32_t m_expectedNumEntries;
162 // Threshold is used check if the differences are greater
163 // than it and whether we need to update the other side.
164 uint32_t m_threshold;
165
166 // prefix and sequence number
167 std::map <ndn::Name, uint64_t> m_prefixes;
168 // Just for looking up hash faster (instead of calculating it again)
169 // Only used in updateSeqNo, prefix/seqNo is the key
170 std::map <ndn::Name, uint32_t> m_prefix2hash;
171 // Value is prefix (and not prefix/seqNo)
172 std::map <uint32_t, ndn::Name> m_hash2prefix;
173
174 ndn::Face& m_face;
175 ndn::KeyChain m_keyChain;
176 ndn::Scheduler m_scheduler;
177
178 ndn::Name m_syncPrefix;
179 ndn::Name m_userPrefix;
180
181 ndn::time::milliseconds m_syncReplyFreshness;
182 ndn::time::milliseconds m_helloReplyFreshness;
183
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500184 SegmentPublisher m_segmentPublisher;
185
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500186 std::mt19937 m_rng;
187};
188
189} // namespace psync
190
191#endif // PSYNC_PRODUCER_BASE_HPP