My Project 1.7.4
C++ Distributed Hash Table
value.h
1/*
2 * Copyright (C) 2014-2017 Savoir-faire Linux Inc.
3 * Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
4 * Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include "infohash.h"
23#include "crypto.h"
24#include "utils.h"
25#include "sockaddr.h"
26
27#include <msgpack.hpp>
28
29#include <string>
30#include <sstream>
31#include <bitset>
32#include <vector>
33#include <iostream>
34#include <algorithm>
35#include <functional>
36#include <memory>
37#include <chrono>
38#include <set>
39
40#ifdef OPENDHT_JSONCPP
41#include <json/json.h>
42#endif
43
44namespace dht {
45
46struct Value;
47struct Query;
48
59using StorePolicy = std::function<bool(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr& addr)>;
60
75using EditPolicy = std::function<bool(InfoHash key, const std::shared_ptr<Value>& old_val, std::shared_ptr<Value>& new_val, const InfoHash& from, const SockAddr& addr)>;
76
77static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
78
79struct OPENDHT_PUBLIC ValueType {
80 typedef uint16_t Id;
81
82 static bool DEFAULT_STORE_POLICY(InfoHash, std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&);
83 static bool DEFAULT_EDIT_POLICY(InfoHash, const std::shared_ptr<Value>&, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&) {
84 return false;
85 }
86
87 ValueType () {}
88
89 ValueType (Id id, std::string name, duration e = std::chrono::minutes(10))
90 : id(id), name(name), expiration(e) {}
91
92 ValueType (Id id, std::string name, duration e, StorePolicy sp, EditPolicy ep = DEFAULT_EDIT_POLICY)
93 : id(id), name(name), expiration(e), storePolicy(sp), editPolicy(ep) {}
94
95 virtual ~ValueType() {}
96
97 bool operator==(const ValueType& o) {
98 return id == o.id;
99 }
100
101 // Generic value type
102 static const ValueType USER_DATA;
103
104
105 Id id {0};
106 std::string name {};
107 duration expiration {60 * 10};
108 StorePolicy storePolicy {DEFAULT_STORE_POLICY};
109 EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
110};
111
113public:
114 void registerType(const ValueType& type) {
115 types[type.id] = type;
116 }
117 const ValueType& getType(ValueType::Id type_id) const {
118 const auto& t_it = types.find(type_id);
119 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
120 }
121private:
122 std::map<ValueType::Id, ValueType> types {};
123};
124
134struct OPENDHT_PUBLIC Value
135{
136 enum class Field : int {
137 None = 0,
138 Id, /* Value::id */
139 ValueType, /* Value::type */
140 OwnerPk, /* Value::owner */
141 SeqNum, /* Value::seq */
142 UserType, /* Value::user_type */
143
144 COUNT /* the total number of fields */
145 };
146
147 typedef uint64_t Id;
148 static const constexpr Id INVALID_ID {0};
149
150 class Filter : public std::function<bool(const Value&)> {
151 public:
152 Filter() {}
153
154 template<typename Functor>
155 Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
156
157 Filter chain(Filter&& f2) {
158 auto f1 = *this;
159 return chain(std::move(f1), std::move(f2));
160 }
161 Filter chainOr(Filter&& f2) {
162 auto f1 = *this;
163 return chainOr(std::move(f1), std::move(f2));
164 }
165 static Filter chain(Filter&& f1, Filter&& f2) {
166 if (not f1) return f2;
167 if (not f2) return f1;
168 return [f1,f2](const Value& v) {
169 return f1(v) and f2(v);
170 };
171 }
172 static Filter chainAll(std::vector<Filter>&& set) {
173 if (set.empty()) return {};
174 return std::bind([](const Value& v, std::vector<Filter>& s) {
175 for (const auto& f : s)
176 if (f and not f(v))
177 return false;
178 return true;
179 }, std::placeholders::_1, std::move(set));
180 }
181 static Filter chain(std::initializer_list<Filter> l) {
182 return chainAll(std::vector<Filter>(l.begin(), l.end()));
183 }
184 static Filter chainOr(Filter&& f1, Filter&& f2) {
185 if (not f1 or not f2) return AllFilter();
186 return [f1,f2](const Value& v) {
187 return f1(v) or f2(v);
188 };
189 }
190 std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
191 if (not (*this))
192 return values;
193 std::vector<Sp<Value>> ret;
194 for (const auto& v : values)
195 if ((*this)(v))
196 ret.emplace_back(v);
197 return ret;
198 }
199 };
200
201 /* Sneaky functions disguised in classes */
202
203 static const Filter AllFilter() {
204 return {};
205 }
206
207 static Filter TypeFilter(const ValueType& t) {
208 const auto tid = t.id;
209 return [tid](const Value& v) {
210 return v.type == tid;
211 };
212 }
213 static Filter TypeFilter(const ValueType::Id& tid) {
214 return [tid](const Value& v) {
215 return v.type == tid;
216 };
217 }
218
219 static Filter IdFilter(const Id id) {
220 return [id](const Value& v) {
221 return v.id == id;
222 };
223 }
224
225 static Filter RecipientFilter(const InfoHash& r) {
226 return [r](const Value& v) {
227 return v.recipient == r;
228 };
229 }
230
231 static Filter OwnerFilter(const crypto::PublicKey& pk) {
232 return OwnerFilter(pk.getId());
233 }
234
235 static Filter OwnerFilter(const InfoHash& pkh) {
236 return [pkh](const Value& v) {
237 return v.owner and v.owner->getId() == pkh;
238 };
239 }
240
241 static Filter SeqNumFilter(uint16_t seq_no) {
242 return [seq_no](const Value& v) {
243 return v.seq == seq_no;
244 };
245 }
246
247 static Filter UserTypeFilter(const std::string& ut) {
248 return [ut](const Value& v) {
249 return v.user_type == ut;
250 };
251 }
252
254 {
255 public:
257 virtual ~SerializableBase() {};
258 virtual const ValueType& getType() const = 0;
259 virtual void unpackValue(const Value& v) = 0;
260 virtual Value packValue() const = 0;
261 };
262
263 template <typename Derived, typename Base=SerializableBase>
264 class Serializable : public Base
265 {
266 public:
267 using Base::Base;
268
269 virtual const ValueType& getType() const {
270 return Derived::TYPE;
271 }
272
273 virtual void unpackValue(const Value& v) {
274 auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
275 msg.get().convert(*static_cast<Derived*>(this));
276 }
277
278 virtual Value packValue() const {
279 return Value {getType(), static_cast<const Derived&>(*this)};
280 }
281 };
282
283 template <typename T,
284 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
285 static Value pack(const T& obj)
286 {
287 return obj.packValue();
288 }
289
290 template <typename T,
291 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
292 static Value pack(const T& obj)
293 {
294 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
295 }
296
297 template <typename T,
298 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
299 static T unpack(const Value& v)
300 {
301 T msg;
302 msg.unpackValue(v);
303 return msg;
304 }
305
306 template <typename T,
307 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
308 static T unpack(const Value& v)
309 {
310 return unpackMsg<T>(v.data);
311 }
312
313 template <typename T>
314 T unpack()
315 {
316 return unpack<T>(*this);
317 }
318
319 bool isEncrypted() const {
320 return not cypher.empty();
321 }
322 bool isSigned() const {
323 return owner and not signature.empty();
324 }
325
331 void sign(const crypto::PrivateKey& key) {
332 if (isEncrypted())
333 throw DhtException("Can't sign encrypted data.");
334 owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
335 signature = key.sign(getToSign());
336 }
337
342 bool checkSignature() const {
343 return isSigned() and owner->checkSignature(getToSign(), signature);
344 }
345
346 std::shared_ptr<const crypto::PublicKey> getOwner() const {
347 return std::static_pointer_cast<const crypto::PublicKey>(owner);
348 }
349
354 if (isEncrypted())
355 throw DhtException("Data is already encrypted.");
356 setRecipient(to.getId());
357 sign(from);
358 Value nv {id};
359 nv.setCypher(to.encrypt(getToEncrypt()));
360 return nv;
361 }
362
363 Value() {}
364
365 Value (Id id) : id(id) {}
366
368 Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
369 : id(id), type(t), data(data) {}
370 Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
371 : id(id), type(t), data(std::move(data)) {}
372 Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
373 : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
374
375#ifdef OPENDHT_JSONCPP
380 Value(Json::Value& json);
381#endif
382
383 template <typename Type>
384 Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
385 : id(id), type(t), data(packMsg(d)) {}
386
387 template <typename Type>
388 Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
389 : id(id), type(t.id), data(packMsg(d)) {}
390
392 Value(const Blob& userdata) : data(userdata) {}
393 Value(Blob&& userdata) : data(std::move(userdata)) {}
394 Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
395
396 Value(Value&& o) noexcept
397 : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
398 type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq), signature(std::move(o.signature)), cypher(std::move(o.cypher)) {}
399
400 template <typename Type>
401 Value(const Type& vs)
402 : Value(pack<Type>(vs)) {}
403
407 Value(const msgpack::object& o) {
408 msgpack_unpack(o);
409 }
410
411 inline bool operator== (const Value& o) {
412 return id == o.id &&
413 (isEncrypted() ? cypher == o.cypher :
414 ((owner == o.owner || *owner == *o.owner) && type == o.type && data == o.data && user_type == o.user_type && signature == o.signature));
415 }
416
417 void setRecipient(const InfoHash& r) {
418 recipient = r;
419 }
420
421 void setCypher(Blob&& c) {
422 cypher = std::move(c);
423 }
424
428 Blob getToSign() const {
429 msgpack::sbuffer buffer;
430 msgpack::packer<msgpack::sbuffer> pk(&buffer);
431 msgpack_pack_to_sign(pk);
432 return {buffer.data(), buffer.data()+buffer.size()};
433 }
434
439 msgpack::sbuffer buffer;
440 msgpack::packer<msgpack::sbuffer> pk(&buffer);
441 msgpack_pack_to_encrypt(pk);
442 return {buffer.data(), buffer.data()+buffer.size()};
443 }
444
446 OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
447
448 std::string toString() const {
449 std::stringstream ss;
450 ss << *this;
451 return ss.str();
452 }
453
454#ifdef OPENDHT_JSONCPP
463 Json::Value toJson() const;
464#endif
465
467 size_t size() const;
468
469 template <typename Packer>
470 void msgpack_pack_to_sign(Packer& pk) const
471 {
472 bool has_owner = owner && *owner;
473 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
474 if (has_owner) { // isSigned
475 pk.pack(std::string("seq")); pk.pack(seq);
476 pk.pack(std::string("owner")); owner->msgpack_pack(pk);
477 if (recipient) {
478 pk.pack(std::string("to")); pk.pack(recipient);
479 }
480 }
481 pk.pack(std::string("type")); pk.pack(type);
482 pk.pack(std::string("data")); pk.pack_bin(data.size());
483 pk.pack_bin_body((const char*)data.data(), data.size());
484 if (not user_type.empty()) {
485 pk.pack(std::string("utype")); pk.pack(user_type);
486 }
487 }
488
489 template <typename Packer>
490 void msgpack_pack_to_encrypt(Packer& pk) const
491 {
492 if (isEncrypted()) {
493 pk.pack_bin(cypher.size());
494 pk.pack_bin_body((const char*)cypher.data(), cypher.size());
495 } else {
496 pk.pack_map(isSigned() ? 2 : 1);
497 pk.pack(std::string("body")); msgpack_pack_to_sign(pk);
498 if (isSigned()) {
499 pk.pack(std::string("sig")); pk.pack_bin(signature.size());
500 pk.pack_bin_body((const char*)signature.data(), signature.size());
501 }
502 }
503 }
504
505 template <typename Packer>
506 void msgpack_pack(Packer& pk) const
507 {
508 pk.pack_map(2);
509 pk.pack(std::string("id")); pk.pack(id);
510 pk.pack(std::string("dat")); msgpack_pack_to_encrypt(pk);
511 }
512
513 template <typename Packer>
514 void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
515 {
516 for (const auto& field : fields)
517 switch (field) {
518 case Value::Field::Id:
519 pk.pack(static_cast<uint64_t>(id));
520 break;
521 case Value::Field::ValueType:
522 pk.pack(static_cast<uint64_t>(type));
523 break;
524 case Value::Field::OwnerPk:
525 if (owner)
526 owner->msgpack_pack(pk);
527 else
528 InfoHash().msgpack_pack(pk);
529 break;
530 case Value::Field::SeqNum:
531 pk.pack(static_cast<uint64_t>(seq));
532 break;
533 case Value::Field::UserType:
534 pk.pack(user_type);
535 break;
536 default:
537 break;
538 }
539 }
540
541 void msgpack_unpack(msgpack::object o);
542 void msgpack_unpack_body(const msgpack::object& o);
543 Blob getPacked() const {
544 msgpack::sbuffer buffer;
545 msgpack::packer<msgpack::sbuffer> pk(&buffer);
546 pk.pack(*this);
547 return {buffer.data(), buffer.data()+buffer.size()};
548 }
549
550 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
551
552 Id id {INVALID_ID};
553
557 std::shared_ptr<const crypto::PublicKey> owner {};
558
564 InfoHash recipient {};
565
569 ValueType::Id type {ValueType::USER_DATA.id};
570 Blob data {};
571
575 std::string user_type {};
576
580 uint16_t seq {0};
581
585 Blob signature {};
586
590 Blob cypher {};
591};
592
593using ValuesExport = std::pair<InfoHash, Blob>;
594
602struct OPENDHT_PUBLIC FieldValue
603{
604 FieldValue() {}
605 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
606 FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
607 FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(blob_value) {}
608
609 bool operator==(const FieldValue& fd) const;
610
611 // accessors
612 Value::Field getField() const { return field; }
613 uint64_t getInt() const { return intValue; }
614 InfoHash getHash() const { return hashValue; }
615 Blob getBlob() const { return blobValue; }
616
617 template <typename Packer>
618 void msgpack_pack(Packer& p) const {
619 p.pack_map(2);
620 p.pack(std::string("f")); p.pack(static_cast<uint8_t>(field));
621
622 p.pack(std::string("v"));
623 switch (field) {
624 case Value::Field::Id:
625 case Value::Field::ValueType:
626 p.pack(intValue);
627 break;
628 case Value::Field::OwnerPk:
629 p.pack(hashValue);
630 break;
631 case Value::Field::UserType:
632 p.pack_bin(blobValue.size());
633 p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
634 break;
635 default:
636 throw msgpack::type_error();
637 }
638 }
639
640 void msgpack_unpack(msgpack::object msg) {
641 hashValue = {};
642 blobValue.clear();
643
644 if (auto f = findMapValue(msg, "f"))
645 field = (Value::Field)f->as<unsigned>();
646 else
647 throw msgpack::type_error();
648
649 auto v = findMapValue(msg, "v");
650 if (not v)
651 throw msgpack::type_error();
652 else
653 switch (field) {
654 case Value::Field::Id:
655 case Value::Field::ValueType:
656 intValue = v->as<decltype(intValue)>();
657 break;
658 case Value::Field::OwnerPk:
659 hashValue = v->as<decltype(hashValue)>();
660 break;
661 case Value::Field::UserType:
662 blobValue = unpackBlob(*v);
663 break;
664 default:
665 throw msgpack::type_error();
666 }
667 }
668
669 Value::Filter getLocalFilter() const;
670
671private:
672 Value::Field field {Value::Field::None};
673 // three possible value types
674 uint64_t intValue {};
675 InfoHash hashValue {};
676 Blob blobValue {};
677};
678
686struct OPENDHT_PUBLIC Select
687{
688 Select() { }
689 Select(const std::string& q_str);
690
691 bool isSatisfiedBy(const Select& os) const;
692
700 Select& field(Value::Field field) {
701 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
702 fieldSelection_.emplace_back(field);
703 return *this;
704 }
705
711 std::set<Value::Field> getSelection() const {
712 return {fieldSelection_.begin(), fieldSelection_.end()};
713 }
714
715 template <typename Packer>
716 void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
717 void msgpack_unpack(const msgpack::object& o) {
718 fieldSelection_ = o.as<decltype(fieldSelection_)>();
719 }
720
721 std::string toString() const {
722 std::stringstream ss;
723 ss << *this;
724 return ss.str();
725 }
726
727 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
728private:
729 std::vector<Value::Field> fieldSelection_ {};
730};
731
739struct OPENDHT_PUBLIC Where
740{
741 Where() { }
742 Where(const std::string& q_str);
743
744 bool isSatisfiedBy(const Where& where) const;
745
753 Where& id(Value::Id id) {
754 FieldValue fv {Value::Field::Id, id};
755 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
756 filters_.emplace_back(std::move(fv));
757 return *this;
758 }
759
767 Where& valueType(ValueType::Id type) {
768 FieldValue fv {Value::Field::ValueType, type};
769 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
770 filters_.emplace_back(std::move(fv));
771 return *this;
772 }
773
781 Where& owner(InfoHash owner_pk_hash) {
782 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
783 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
784 filters_.emplace_back(std::move(fv));
785 return *this;
786 }
787
795 Where& seq(uint16_t seq_no) {
796 FieldValue fv {Value::Field::SeqNum, seq_no};
797 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
798 filters_.emplace_back(std::move(fv));
799 return *this;
800 }
801
809 Where& userType(std::string user_type) {
810 FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
811 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
812 filters_.emplace_back(std::move(fv));
813 return *this;
814 }
815
822 if (filters_.empty()) return {};
823 std::vector<Value::Filter> fset;
824 fset.reserve(filters_.size());
825 for (const auto& f : filters_) {
826 if (auto lf = f.getLocalFilter())
827 fset.emplace_back(std::move(lf));
828 }
829 return Value::Filter::chainAll(std::move(fset));
830 }
831
832 template <typename Packer>
833 void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
834 void msgpack_unpack(const msgpack::object& o) {
835 filters_.clear();
836 filters_ = o.as<decltype(filters_)>();
837 }
838
839 std::string toString() const {
840 std::stringstream ss;
841 ss << *this;
842 return ss.str();
843 }
844
845 bool empty() const {
846 return filters_.empty();
847 }
848
849 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
850
851private:
852 std::vector<FieldValue> filters_;
853};
854
863struct OPENDHT_PUBLIC Query
864{
865 static const std::string QUERY_PARSE_ERROR;
866
867 Query(Select s = {}, Where w = {}, bool none = false) : select(s), where(w), none(none) { };
868
882 Query(std::string q_str) {
883 auto pos_W = q_str.find("WHERE");
884 auto pos_w = q_str.find("where");
885 auto pos = std::min(pos_W != std::string::npos ? pos_W : q_str.size(),
886 pos_w != std::string::npos ? pos_w : q_str.size());
887 select = q_str.substr(0, pos);
888 where = q_str.substr(pos, q_str.size()-pos);
889 }
890
894 bool isSatisfiedBy(const Query& q) const;
895
896 template <typename Packer>
897 void msgpack_pack(Packer& pk) const {
898 pk.pack_map(2);
899 pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
900 pk.pack(std::string("w")); pk.pack(where); /* packing filters */
901 }
902
903 void msgpack_unpack(const msgpack::object& o);
904
905 std::string toString() const {
906 std::stringstream ss;
907 ss << *this;
908 return ss.str();
909 }
910
911 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
912 return s << "Query[" << q.select << " " << q.where << "]";
913 }
914
915 Select select {};
916 Where where {};
917 bool none {false}; /* When true, any query satisfies this. */
918};
919
927struct OPENDHT_PUBLIC FieldValueIndex {
928 FieldValueIndex() {}
929 FieldValueIndex(const Value& v, Select s = {});
936 bool containedIn(const FieldValueIndex& other) const;
937
938 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
939
940 void msgpack_unpack_fields(const std::set<Value::Field>& fields,
941 const msgpack::object& o,
942 unsigned offset);
943
944 std::map<Value::Field, FieldValue> index {};
945};
946
947template <typename T,
948 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
949Value::Filter
950getFilterSet(Value::Filter f)
951{
952 return Value::Filter::chain({
953 Value::TypeFilter(T::TYPE),
954 T::getFilter(),
955 f
956 });
957}
958
959template <typename T,
960 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
961Value::Filter
962getFilterSet(Value::Filter f)
963{
964 return f;
965}
966
967template <typename T,
968 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
969Value::Filter
970getFilterSet()
971{
972 return Value::Filter::chain({
973 Value::TypeFilter(T::TYPE),
974 T::getFilter()
975 });
976}
977
978template <typename T,
979 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
980Value::Filter
981getFilterSet()
982{
983 return Value::AllFilter();
984}
985
986template <class T>
987std::vector<T>
988unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
989 std::vector<T> ret;
990 ret.reserve(vals.size());
991 for (const auto& v : vals) {
992 try {
993 ret.emplace_back(Value::unpack<T>(*v));
994 } catch (const std::exception&) {}
995 }
996 return ret;
997}
998
999#ifdef OPENDHT_JSONCPP
1000uint64_t unpackId(const Json::Value& json, const std::string& key);
1001#endif
1002
1003}
1004
1005MSGPACK_ADD_ENUM(dht::Value::Field)
Definition: callbacks.h:34
OPENDHT_PUBLIC Blob unpackBlob(msgpack::object &o)
std::function< bool(InfoHash key, const std::shared_ptr< Value > &old_val, std::shared_ptr< Value > &new_val, const InfoHash &from, const SockAddr &addr)> EditPolicy
Definition: value.h:75
std::vector< uint8_t > Blob
Definition: utils.h:114
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
Definition: value.h:59
An index for field values.
Definition: value.h:927
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Definition: value.h:603
Describes a query destined to another peer.
Definition: value.h:864
Query(std::string q_str)
Definition: value.h:882
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
Definition: value.h:687
std::set< Value::Field > getSelection() const
Definition: value.h:711
Select & field(Value::Field field)
Definition: value.h:700
bool checkSignature() const
Definition: value.h:342
Blob cypher
Definition: value.h:590
std::shared_ptr< const crypto::PublicKey > owner
Definition: value.h:557
size_t size() const
Blob signature
Definition: value.h:585
Value(const msgpack::object &o)
Definition: value.h:407
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
Definition: value.h:368
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
Definition: value.h:353
Blob getToSign() const
Definition: value.h:428
Blob getToEncrypt() const
Definition: value.h:438
std::string user_type
Definition: value.h:575
Value(const Blob &userdata)
Definition: value.h:392
ValueType::Id type
Definition: value.h:569
void sign(const crypto::PrivateKey &key)
Definition: value.h:331
Serializable dht::Value filter.
Definition: value.h:740
Value::Filter getFilter() const
Definition: value.h:821
Where & seq(uint16_t seq_no)
Definition: value.h:795
Where & valueType(ValueType::Id type)
Definition: value.h:767
Where & userType(std::string user_type)
Definition: value.h:809
Where & owner(InfoHash owner_pk_hash)
Definition: value.h:781
Where & id(Value::Id id)
Definition: value.h:753
Blob sign(const Blob &) const