AlteriomPainlessMesh v2.1.1
Easy ESP32/ESP8266 mesh networking with Alteriom IoT extensions
Loading...
Searching...
No Matches
layout.hpp
Go to the documentation of this file.
1#ifndef _PAINLESS_MESH_LAYOUT_HPP_
2#define _PAINLESS_MESH_LAYOUT_HPP_
3
4#include <list>
5#include <memory>
6
8
9namespace painlessmesh {
10namespace layout {
11
12#include <memory>
16inline bool contains(protocol::NodeTree nodeTree, uint32_t nodeId) {
17 if (nodeTree.nodeId == nodeId) {
18 return true;
19 }
20 for (auto&& s : nodeTree.subs) {
21 if (contains(s, nodeId)) return true;
22 }
23 return false;
24}
25
37inline bool forget(protocol::NodeTree& tree, uint32_t nodeId) {
38 for (auto it = tree.subs.begin(); it != tree.subs.end(); ++it) {
39 if (it->nodeId == nodeId) {
40 tree.subs.erase(it);
41 return true;
42 }
43 if (forget(*it, nodeId)) return true;
44 }
45 return false;
46}
47
58inline size_t forgetAll(protocol::NodeTree& tree,
59 const protocol::NodeTree& elsewhere) {
60 size_t removed = forget(tree, elsewhere.nodeId) ? 1 : 0;
61 for (auto&& s : elsewhere.subs) removed += forgetAll(tree, s);
62 return removed;
63}
64
72inline uint32_t fingerprint(const protocol::NodeTree& tree,
73 uint32_t hash = 2166136261u) {
74 auto mix = [&hash](uint32_t v) {
75 for (int i = 0; i < 4; ++i) {
76 hash ^= (v >> (8 * i)) & 0xff;
77 hash *= 16777619u;
78 }
79 };
80 mix(tree.nodeId);
81 mix((tree.root ? 1u : 0u) | (tree.hasTimeAuthority ? 2u : 0u));
82 for (auto&& s : tree.subs) hash = fingerprint(s, hash);
83 mix(0xffffffffu); // end of this node's subs
84 return hash == 0 ? 1 : hash;
85}
86
88 uint32_t exclude) {
89 // Make sure to exclude any subs with nodeId == 0,
90 // even if exlude is not set to zero
91 tree.subs.remove_if([exclude](protocol::NodeTree s) {
92 return s.nodeId == 0 || s.nodeId == exclude;
93 });
94 return tree;
95}
96
97template <class T>
98class Layout {
99 public:
100 size_t stability = 0;
101 std::list<std::shared_ptr<T> > subs;
102
108 uint32_t getNodeId() const { return nodeId; }
109
113 bool isRoot() const { return root; }
114
117 for (auto&& s : subs) {
118 if (s->nodeId == 0) continue;
119 nt.subs.push_back(protocol::NodeTree(*s));
120 }
121 return nt;
122 }
123
124 protected:
125 uint32_t nodeId = 0;
126 bool root = false;
127 bool hasTimeAuthority = false;
128};
129
138template <class T>
139size_t liveSubs(const Layout<T>& layout) {
140 size_t live = 0;
141 for (auto&& sub : layout.subs)
142 if (sub->connected()) ++live;
143 return live;
144}
145
146template <class T>
147void syncLayout(Layout<T>& layout, uint32_t changedId) {
148 // TODO: this should be called from changed connections and dropped
149 // connections events
150 for (auto&& sub : layout.subs) {
151 if (sub->connected() && !sub->newConnection && sub->nodeId != 0 &&
152 sub->nodeId != changedId) { // Exclude current
153 sub->nodeSyncTask.forceNextIteration();
154 }
155 }
156 layout.stability /= 2;
157}
158
160 public:
161 // Inherit constructors
163
169 uint32_t presented = 0;
170
178 if (nodeId == 0) // Cant really know, so valid as far as we know
179 return true;
180 if (nodeId != tree.nodeId) return false;
181 for (auto&& s : tree.subs) {
182 if (layout::contains(s, nodeId)) return false;
183 }
184 return true;
185 }
186
198 if (nodeId == 0 || tree != (*this)) {
199 nodeId = tree.nodeId;
200 subs = tree.subs;
201 root = tree.root;
203 return true;
204 }
205 return false;
206 }
207
212 auto subTree = excludeRoute(std::move(layout), nodeId);
213 auto req = protocol::NodeSyncRequest(subTree.nodeId, nodeId, subTree.subs,
214 subTree.root);
215 req.hasTimeAuthority = subTree.hasTimeAuthority;
216 return req;
217 }
218
223 auto subTree = excludeRoute(std::move(layout), nodeId);
224 return protocol::NodeSyncReply(subTree.nodeId, nodeId, subTree.subs,
225 subTree.root);
226 }
227};
228
232inline uint32_t size(protocol::NodeTree nodeTree) {
233 auto no = 1;
234 for (auto&& s : nodeTree.subs) {
235 no += size(s);
236 }
237 return no;
238}
239
243inline bool isRoot(protocol::NodeTree nodeTree) {
244 if (nodeTree.root) return true;
245 return false;
246}
247
251inline bool isRooted(protocol::NodeTree nodeTree) {
252 if (isRoot(nodeTree)) return true;
253 for (auto&& s : nodeTree.subs) {
254 if (isRooted(s)) return true;
255 }
256 return false;
257}
258
262inline std::list<uint32_t> asList(protocol::NodeTree nodeTree,
263 bool includeSelf = true) {
264 std::list<uint32_t> lst;
265 if (includeSelf) lst.push_back(nodeTree.nodeId);
266 for (auto&& s : nodeTree.subs) {
267 lst.splice(lst.end(), asList(s));
268 }
269 return lst;
270}
271
272} // namespace layout
273} // namespace painlessmesh
274
275#endif
276
Definition layout.hpp:98
bool hasTimeAuthority
Definition layout.hpp:127
uint32_t getNodeId() const
Definition layout.hpp:108
bool isRoot() const
Definition layout.hpp:113
uint32_t nodeId
Definition layout.hpp:125
bool root
Definition layout.hpp:126
protocol::NodeTree asNodeTree()
Definition layout.hpp:115
size_t stability
Definition layout.hpp:100
std::list< std::shared_ptr< T > > subs
Definition layout.hpp:101
Definition layout.hpp:159
bool validSubs(protocol::NodeTree tree)
Definition layout.hpp:177
bool updateSubs(protocol::NodeTree tree)
Definition layout.hpp:197
protocol::NodeSyncReply reply(NodeTree &&layout)
Definition layout.hpp:222
uint32_t presented
Definition layout.hpp:169
protocol::NodeSyncRequest request(NodeTree &&layout)
Definition layout.hpp:211
Definition protocol.hpp:332
Definition protocol.hpp:277
Definition protocol.hpp:167
std::list< NodeTree > subs
Definition protocol.hpp:172
NodeTree()
Definition protocol.hpp:174
bool hasTimeAuthority
Definition protocol.hpp:171
uint32_t nodeId
Definition protocol.hpp:169
bool root
Definition protocol.hpp:170
protocol::NodeTree excludeRoute(protocol::NodeTree &&tree, uint32_t exclude)
Definition layout.hpp:87
bool isRoot(protocol::NodeTree nodeTree)
Definition layout.hpp:243
bool isRooted(protocol::NodeTree nodeTree)
Definition layout.hpp:251
bool forget(protocol::NodeTree &tree, uint32_t nodeId)
Definition layout.hpp:37
size_t liveSubs(const Layout< T > &layout)
Definition layout.hpp:139
uint32_t fingerprint(const protocol::NodeTree &tree, uint32_t hash=2166136261u)
Definition layout.hpp:72
bool contains(protocol::NodeTree nodeTree, uint32_t nodeId)
Definition layout.hpp:16
std::list< uint32_t > asList(protocol::NodeTree nodeTree, bool includeSelf=true)
Definition layout.hpp:262
size_t forgetAll(protocol::NodeTree &tree, const protocol::NodeTree &elsewhere)
Definition layout.hpp:58
void syncLayout(Layout< T > &layout, uint32_t changedId)
Definition layout.hpp:147
uint32_t size(protocol::NodeTree nodeTree)
Definition layout.hpp:232
Definition wifi.hpp:34