My Project 3.2.0
C++ Distributed Hash Table
Loading...
Searching...
No Matches
value.h
1/*
2 * Copyright (C) 2014-2023 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 <string_view>
31#include <sstream>
32#include <bitset>
33#include <vector>
34#include <iostream>
35#include <algorithm>
36#include <functional>
37#include <memory>
38#include <chrono>
39#include <set>
40
41#ifdef OPENDHT_JSONCPP
42#include <json/json.h>
43#endif
44
45namespace dht {
46using namespace std::literals;
47
48static constexpr auto VALUE_KEY_ID("id");
49static const std::string VALUE_KEY_DAT("dat");
50static const std::string VALUE_KEY_PRIO("p");
51static const std::string VALUE_KEY_SIGNATURE("sig");
52
53static const std::string VALUE_KEY_SEQ("seq");
54static const std::string VALUE_KEY_DATA("data");
55static const std::string VALUE_KEY_OWNER("owner");
56static const std::string VALUE_KEY_TYPE("type");
57static const std::string VALUE_KEY_TO("to");
58static const std::string VALUE_KEY_BODY("body");
59static const std::string VALUE_KEY_USERTYPE("utype");
60
61struct Value;
62struct Query;
63
74using StorePolicy = std::function<bool(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr& addr)>;
75
90using 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)>;
91
92static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
93
94struct OPENDHT_PUBLIC ValueType {
95 typedef uint16_t Id;
96
97 static bool DEFAULT_STORE_POLICY(InfoHash, const std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&);
98 static bool DEFAULT_EDIT_POLICY(InfoHash, const std::shared_ptr<Value>&, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&) {
99 return false;
100 }
101
102 ValueType () {}
103
104 ValueType (Id id, std::string name, duration e = std::chrono::minutes(10))
105 : id(id), name(name), expiration(e) {}
106
107 ValueType (Id id, std::string name, duration e, StorePolicy sp, EditPolicy ep = DEFAULT_EDIT_POLICY)
108 : id(id), name(name), expiration(e), storePolicy(sp), editPolicy(ep) {}
109
110 virtual ~ValueType() {}
111
112 bool operator==(const ValueType& o) {
113 return id == o.id;
114 }
115
116 // Generic value type
117 static const ValueType USER_DATA;
118
119
120 Id id {0};
121 std::string name {};
122 duration expiration {std::chrono::minutes(10)};
123 StorePolicy storePolicy {DEFAULT_STORE_POLICY};
124 EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
125};
126
128public:
129 void registerType(const ValueType& type) {
130 types[type.id] = type;
131 }
132 const ValueType& getType(ValueType::Id type_id) const {
133 const auto& t_it = types.find(type_id);
134 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
135 }
136private:
137 std::map<ValueType::Id, ValueType> types {};
138};
139
140struct CryptoValueCache;
141
151struct OPENDHT_PUBLIC Value
152{
153 enum class Field : int {
154 None = 0,
155 Id, /* Value::id */
156 ValueType, /* Value::type */
157 OwnerPk, /* Value::owner */
158 SeqNum, /* Value::seq */
159 UserType, /* Value::user_type */
160
161 COUNT /* the total number of fields */
162 };
163
164 typedef uint64_t Id;
165 static const constexpr Id INVALID_ID {0};
166
167 class Filter : public std::function<bool(const Value&)> {
168 public:
169 Filter() {}
170
171 template<typename Functor>
172 Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
173
174 inline Filter chain(Filter&& f2) {
175 auto f1 = *this;
176 return chain(std::move(f1), std::move(f2));
177 }
178 inline Filter chainOr(Filter&& f2) {
179 auto f1 = *this;
180 return chainOr(std::move(f1), std::move(f2));
181 }
182 static inline Filter chain(Filter&& f1, Filter&& f2) {
183 if (not f1) return std::move(f2);
184 if (not f2) return std::move(f1);
185 return [f1 = std::move(f1), f2 = std::move(f2)](const Value& v) {
186 return f1(v) and f2(v);
187 };
188 }
189 static inline Filter chain(const Filter& f1, const Filter& f2) {
190 if (not f1) return f2;
191 if (not f2) return f1;
192 return [f1,f2](const Value& v) {
193 return f1(v) and f2(v);
194 };
195 }
196 static inline Filter chainAll(std::vector<Filter>&& set) {
197 if (set.empty()) return {};
198 return [set = std::move(set)](const Value& v) {
199 for (const auto& f : set)
200 if (f and not f(v))
201 return false;
202 return true;
203 };
204 }
205 static inline Filter chain(std::initializer_list<Filter> l) {
206 return chainAll(std::vector<Filter>(l.begin(), l.end()));
207 }
208 static inline Filter chainOr(Filter&& f1, Filter&& f2) {
209 if (not f1 or not f2) return {};
210 return [f1=std::move(f1),f2=std::move(f2)](const Value& v) {
211 return f1(v) or f2(v);
212 };
213 }
214 static inline Filter notFilter(Filter&& f) {
215 if (not f) return [](const Value&) { return false; };
216 return [f = std::move(f)](const Value& v) { return not f(v); };
217 }
218 std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
219 if (not (*this))
220 return values;
221 std::vector<Sp<Value>> ret;
222 for (const auto& v : values)
223 if ((*this)(v))
224 ret.emplace_back(v);
225 return ret;
226 }
227 };
228
229 /* Sneaky functions disguised in classes */
230
231 static inline Filter AllFilter() {
232 return {};
233 }
234
235 static inline Filter TypeFilter(const ValueType& t) {
236 return [tid = t.id](const Value& v) {
237 return v.type == tid;
238 };
239 }
240 static inline Filter TypeFilter(const ValueType::Id& tid) {
241 return [tid](const Value& v) {
242 return v.type == tid;
243 };
244 }
245
246 static inline Filter IdFilter(const Id id) {
247 return [id](const Value& v) {
248 return v.id == id;
249 };
250 }
251
252 static inline Filter RecipientFilter(const InfoHash& r) {
253 return [r](const Value& v) {
254 return v.recipient == r;
255 };
256 }
257
258 static inline Filter OwnerFilter(const crypto::PublicKey& pk) {
259 return OwnerFilter(pk.getId());
260 }
261
262 static inline Filter OwnerFilter(const InfoHash& pkh) {
263 return [pkh](const Value& v) {
264 return v.owner and v.owner->getId() == pkh;
265 };
266 }
267
268 static inline Filter SeqNumFilter(uint16_t seq_no) {
269 return [seq_no](const Value& v) {
270 return v.seq == seq_no;
271 };
272 }
273
274 static inline Filter UserTypeFilter(std::string ut) {
275 return [ut = std::move(ut)](const Value& v) {
276 return v.user_type == ut;
277 };
278 }
279
281 {
282 public:
284 virtual ~SerializableBase() {};
285 virtual const ValueType& getType() const = 0;
286 virtual void unpackValue(const Value& v) = 0;
287 virtual Value packValue() const = 0;
288 };
289
290 template <typename Derived, typename Base=SerializableBase>
291 class Serializable : public Base
292 {
293 public:
294 using Base::Base;
295
296 virtual const ValueType& getType() const {
297 return Derived::TYPE;
298 }
299
300 virtual void unpackValue(const Value& v) {
301 auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
302 msg.get().convert(*static_cast<Derived*>(this));
303 }
304
305 virtual Value packValue() const {
306 return Value {getType(), static_cast<const Derived&>(*this)};
307 }
308 };
309
310 template <typename T,
311 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
312 static Value pack(const T& obj)
313 {
314 return obj.packValue();
315 }
316
317 template <typename T,
318 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
319 static Value pack(const T& obj)
320 {
321 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
322 }
323
324 template <typename T,
325 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
326 static T unpack(const Value& v)
327 {
328 T msg;
329 msg.unpackValue(v);
330 return msg;
331 }
332
333 template <typename T,
334 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
335 static T unpack(const Value& v)
336 {
337 return unpackMsg<T>(v.data);
338 }
339
340 template <typename T>
341 T unpack()
342 {
343 return unpack<T>(*this);
344 }
345
346 inline bool isEncrypted() const {
347 return not cypher.empty();
348 }
349 inline bool isSigned() const {
350 return owner and not signature.empty();
351 }
352
358 void sign(const crypto::PrivateKey& key);
359
364 inline bool checkSignature() const {
365 return isSigned() and owner->checkSignature(getToSign(), signature);
366 }
367
368 inline std::shared_ptr<crypto::PublicKey> getOwner() const {
369 return owner;
370 }
371
376
377 Value() {}
378
379 Value (Id id) : id(id) {}
380
382 Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
383 : id(id), type(t), data(data) {}
384 Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
385 : id(id), type(t), data(std::move(data)) {}
386 Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
387 : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
388
389#ifdef OPENDHT_JSONCPP
394 Value(const Json::Value& json);
395#endif
396
397 template <typename Type>
398 Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
399 : id(id), type(t), data(packMsg(d)) {}
400
401 template <typename Type>
402 Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
403 : id(id), type(t.id), data(packMsg(d)) {}
404
406 Value(const Blob& userdata) : data(userdata) {}
407 Value(Blob&& userdata) : data(std::move(userdata)) {}
408 Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
409
410 Value(Value&& o) noexcept
411 : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
412 type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq)
413 , signature(std::move(o.signature)), cypher(std::move(o.cypher))
414 , priority(o.priority) {}
415
416 template <typename Type>
417 Value(const Type& vs)
418 : Value(pack<Type>(vs)) {}
419
423 Value(const msgpack::object& o) {
424 msgpack_unpack(o);
425 }
426
430 inline bool contentEquals(const Value& o) const {
431 return isEncrypted() ? cypher == o.cypher :
432 ((owner == o.owner || (owner and o.owner and *owner == *o.owner))
433 && type == o.type
434 && data == o.data
435 && user_type == o.user_type
436 && signature == o.signature);
437 }
438
439 inline bool operator== (const Value& o) const {
440 return id == o.id and contentEquals(o);
441 }
442 inline bool operator!= (const Value& o) const {
443 return !(*this == o);
444 }
445
446 inline void setRecipient(const InfoHash& r) {
447 recipient = r;
448 }
449
450 inline void setCypher(Blob&& c) {
451 cypher = std::move(c);
452 }
453
457 inline Blob getToSign() const {
458 msgpack::sbuffer buffer;
459 msgpack::packer<msgpack::sbuffer> pk(&buffer);
460 msgpack_pack_to_sign(pk);
461 return {buffer.data(), buffer.data()+buffer.size()};
462 }
463
467 inline Blob getToEncrypt() const {
468 msgpack::sbuffer buffer;
469 msgpack::packer<msgpack::sbuffer> pk(&buffer);
470 msgpack_pack_to_encrypt(pk);
471 return {buffer.data(), buffer.data()+buffer.size()};
472 }
473
475 OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
476
477 inline std::string toString() const {
478 std::ostringstream ss;
479 ss << *this;
480 return ss.str();
481 }
482
483#ifdef OPENDHT_JSONCPP
492 Json::Value toJson() const;
493#endif
494
496 size_t size() const;
497
498 template <typename Packer>
499 void msgpack_pack_to_sign(Packer& pk) const
500 {
501 bool has_owner = owner && *owner;
502 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
503 if (has_owner) { // isSigned
504 pk.pack(VALUE_KEY_SEQ); pk.pack(seq);
505 pk.pack(VALUE_KEY_OWNER); owner->msgpack_pack(pk);
506 if (recipient) {
507 pk.pack(VALUE_KEY_TO); pk.pack(recipient);
508 }
509 }
510 pk.pack(VALUE_KEY_TYPE); pk.pack(type);
511 pk.pack(VALUE_KEY_DATA); pk.pack_bin(data.size());
512 pk.pack_bin_body((const char*)data.data(), data.size());
513 if (not user_type.empty()) {
514 pk.pack(VALUE_KEY_USERTYPE); pk.pack(user_type);
515 }
516 }
517
518 template <typename Packer>
519 void msgpack_pack_to_encrypt(Packer& pk) const
520 {
521 if (isEncrypted()) {
522 pk.pack_bin(cypher.size());
523 pk.pack_bin_body((const char*)cypher.data(), cypher.size());
524 } else {
525 pk.pack_map(isSigned() ? 2 : 1);
526 pk.pack(VALUE_KEY_BODY); msgpack_pack_to_sign(pk);
527 if (isSigned()) {
528 pk.pack(VALUE_KEY_SIGNATURE); pk.pack_bin(signature.size());
529 pk.pack_bin_body((const char*)signature.data(), signature.size());
530 }
531 }
532 }
533
534 template <typename Packer>
535 void msgpack_pack(Packer& pk) const
536 {
537 pk.pack_map(2 + (priority?1:0));
538 pk.pack(VALUE_KEY_ID); pk.pack(id);
539 pk.pack(VALUE_KEY_DAT); msgpack_pack_to_encrypt(pk);
540 if (priority) {
541 pk.pack(VALUE_KEY_PRIO); pk.pack(priority);
542 }
543 }
544
545 template <typename Packer>
546 void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
547 {
548 for (const auto& field : fields)
549 switch (field) {
550 case Value::Field::Id:
551 pk.pack(static_cast<uint64_t>(id));
552 break;
553 case Value::Field::ValueType:
554 pk.pack(static_cast<uint64_t>(type));
555 break;
556 case Value::Field::OwnerPk:
557 if (owner)
558 owner->msgpack_pack(pk);
559 else
560 InfoHash().msgpack_pack(pk);
561 break;
562 case Value::Field::SeqNum:
563 pk.pack(static_cast<uint64_t>(seq));
564 break;
565 case Value::Field::UserType:
566 pk.pack(user_type);
567 break;
568 default:
569 break;
570 }
571 }
572
573 void msgpack_unpack(const msgpack::object& o);
574 void msgpack_unpack_body(const msgpack::object& o);
575 Blob getPacked() const {
576 msgpack::sbuffer buffer;
577 msgpack::packer<msgpack::sbuffer> pk(&buffer);
578 pk.pack(*this);
579 return {buffer.data(), buffer.data()+buffer.size()};
580 }
581
582 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
583
584 Id id {INVALID_ID};
585
589 std::shared_ptr<crypto::PublicKey> owner {};
590
596 InfoHash recipient {};
597
601 ValueType::Id type {ValueType::USER_DATA.id};
602 Blob data {};
603
607 std::string user_type {};
608
612 uint16_t seq {0};
613
617 Blob signature {};
618
622 Blob cypher {};
623
629 unsigned priority {0};
630
631 inline bool isSignatureChecked() const {
632 return signatureChecked;
633 }
634 inline bool isDecrypted() const {
635 return decrypted;
636 }
637 bool checkSignature();
638 Sp<Value> decrypt(const crypto::PrivateKey& key);
639
640private:
641 /* Cache for crypto ops */
642 bool signatureChecked {false};
643 bool signatureValid {false};
644 bool decrypted {false};
645 Sp<Value> decryptedValue {};
646};
647
648using ValuesExport = std::pair<InfoHash, Blob>;
649
657struct OPENDHT_PUBLIC FieldValue
658{
659 FieldValue() {}
660 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
661 FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
662 FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(std::move(blob_value)) {}
663
664 bool operator==(const FieldValue& fd) const;
665
666 // accessors
667 Value::Field getField() const { return field; }
668 uint64_t getInt() const { return intValue; }
669 InfoHash getHash() const { return hashValue; }
670 Blob getBlob() const { return blobValue; }
671
672 template <typename Packer>
673 void msgpack_pack(Packer& p) const {
674 p.pack_map(2);
675 p.pack("f"sv); p.pack(static_cast<uint8_t>(field));
676
677 p.pack("v"sv);
678 switch (field) {
679 case Value::Field::Id:
680 case Value::Field::ValueType:
681 p.pack(intValue);
682 break;
683 case Value::Field::OwnerPk:
684 p.pack(hashValue);
685 break;
686 case Value::Field::UserType:
687 p.pack_bin(blobValue.size());
688 p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
689 break;
690 default:
691 throw msgpack::type_error();
692 }
693 }
694
695 void msgpack_unpack(const msgpack::object& msg) {
696 hashValue = {};
697 blobValue.clear();
698
699 if (auto f = findMapValue(msg, "f"sv))
700 field = (Value::Field)f->as<unsigned>();
701 else
702 throw msgpack::type_error();
703
704 auto v = findMapValue(msg, "v"sv);
705 if (not v)
706 throw msgpack::type_error();
707 else
708 switch (field) {
709 case Value::Field::Id:
710 case Value::Field::ValueType:
711 intValue = v->as<decltype(intValue)>();
712 break;
713 case Value::Field::OwnerPk:
714 hashValue = v->as<decltype(hashValue)>();
715 break;
716 case Value::Field::UserType:
717 blobValue = unpackBlob(*v);
718 break;
719 default:
720 throw msgpack::type_error();
721 }
722 }
723
724 Value::Filter getLocalFilter() const;
725
726private:
727 Value::Field field {Value::Field::None};
728 // three possible value types
729 uint64_t intValue {};
730 InfoHash hashValue {};
731 Blob blobValue {};
732};
733
741struct OPENDHT_PUBLIC Select
742{
743 Select() { }
744 Select(std::string_view q_str);
745
746 bool isSatisfiedBy(const Select& os) const;
747
755 Select& field(Value::Field field) {
756 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
757 fieldSelection_.emplace_back(field);
758 return *this;
759 }
760
766 std::set<Value::Field> getSelection() const {
767 return {fieldSelection_.begin(), fieldSelection_.end()};
768 }
769
770 template <typename Packer>
771 void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
772 void msgpack_unpack(const msgpack::object& o) {
773 fieldSelection_ = o.as<decltype(fieldSelection_)>();
774 }
775
776 std::string toString() const {
777 std::ostringstream ss;
778 ss << *this;
779 return ss.str();
780 }
781
782 bool empty() const { return fieldSelection_.empty(); }
783
784 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
785private:
786 std::vector<Value::Field> fieldSelection_ {};
787};
788
796struct OPENDHT_PUBLIC Where
797{
798 Where() { }
799 Where(std::string_view q_str);
800
801 bool isSatisfiedBy(const Where& where) const;
802
810 Where&& id(Value::Id id) {
811 FieldValue fv {Value::Field::Id, id};
812 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
813 filters_.emplace_back(std::move(fv));
814 return std::move(*this);
815 }
816
824 Where&& valueType(ValueType::Id type) {
825 FieldValue fv {Value::Field::ValueType, type};
826 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
827 filters_.emplace_back(std::move(fv));
828 return std::move(*this);
829 }
830
838 Where&& owner(InfoHash owner_pk_hash) {
839 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
840 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
841 filters_.emplace_back(std::move(fv));
842 return std::move(*this);
843 }
844
852 Where&& seq(uint16_t seq_no) {
853 FieldValue fv {Value::Field::SeqNum, seq_no};
854 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
855 filters_.emplace_back(std::move(fv));
856 return std::move(*this);
857 }
858
866 Where&& userType(std::string_view user_type) {
867 FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
868 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
869 filters_.emplace_back(std::move(fv));
870 return std::move(*this);
871 }
872
879 if (filters_.empty())
880 return {};
881 if (filters_.size() == 1)
882 return filters_[0].getLocalFilter();
883 std::vector<Value::Filter> fset;
884 fset.reserve(filters_.size());
885 for (const auto& f : filters_) {
886 if (auto lf = f.getLocalFilter())
887 fset.emplace_back(std::move(lf));
888 }
889 return Value::Filter::chainAll(std::move(fset));
890 }
891
892 template <typename Packer>
893 void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
894 void msgpack_unpack(const msgpack::object& o) {
895 filters_.clear();
896 filters_ = o.as<decltype(filters_)>();
897 }
898
899 std::string toString() const {
900 std::ostringstream ss;
901 ss << *this;
902 return ss.str();
903 }
904
905 bool empty() const {
906 return filters_.empty();
907 }
908
909 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
910
911private:
912 std::vector<FieldValue> filters_;
913};
914
923struct OPENDHT_PUBLIC Query
924{
925 static const std::string QUERY_PARSE_ERROR;
926
927 Query(Select s = {}, Where w = {}, bool none = false) : select(std::move(s)), where(std::move(w)), none(none) { };
928
942 Query(std::string_view q_str) {
943 auto pos_W = q_str.find("WHERE");
944 auto pos_w = q_str.find("where");
945 auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
946 pos_w != std::string_view::npos ? pos_w : q_str.size());
947 select = q_str.substr(0, pos);
948 where = q_str.substr(pos, q_str.size()-pos);
949 }
950
954 bool isSatisfiedBy(const Query& q) const;
955
956 template <typename Packer>
957 void msgpack_pack(Packer& pk) const {
958 pk.pack_map(2);
959 pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
960 pk.pack(std::string("w")); pk.pack(where); /* packing filters */
961 }
962
963 void msgpack_unpack(const msgpack::object& o);
964
965 std::string toString() const {
966 std::ostringstream ss;
967 ss << *this;
968 return ss.str();
969 }
970
971 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
972 return s << "Query[" << q.select << " " << q.where << "]";
973 }
974
975 Select select {};
976 Where where {};
977 bool none {false}; /* When true, any query satisfies this. */
978};
979
987struct OPENDHT_PUBLIC FieldValueIndex {
988 FieldValueIndex() {}
989 FieldValueIndex(const Value& v, const Select& s = {});
996 bool containedIn(const FieldValueIndex& other) const;
997
998 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
999
1000 void msgpack_unpack_fields(const std::set<Value::Field>& fields,
1001 const msgpack::object& o,
1002 unsigned offset);
1003
1004 std::map<Value::Field, FieldValue> index {};
1005};
1006
1007template <typename T,
1008 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1009Value::Filter
1010getFilterSet(Value::Filter f)
1011{
1012 return Value::Filter::chain({
1013 Value::TypeFilter(T::TYPE),
1014 T::getFilter(),
1015 f
1016 });
1017}
1018
1019template <typename T,
1020 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1021Value::Filter
1022getFilterSet(Value::Filter f)
1023{
1024 return f;
1025}
1026
1027template <typename T,
1028 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1029Value::Filter
1030getFilterSet()
1031{
1032 return Value::Filter::chain({
1033 Value::TypeFilter(T::TYPE),
1034 T::getFilter()
1035 });
1036}
1037
1038template <typename T,
1039 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1040Value::Filter
1041getFilterSet()
1042{
1043 return {};
1044}
1045
1046template <class T>
1047std::vector<T>
1048unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
1049 std::vector<T> ret;
1050 ret.reserve(vals.size());
1051 for (const auto& v : vals) {
1052 try {
1053 ret.emplace_back(Value::unpack<T>(*v));
1054 } catch (const std::exception&) {}
1055 }
1056 return ret;
1057}
1058
1059#ifdef OPENDHT_JSONCPP
1060uint64_t unpackId(const Json::Value& json, const std::string& key);
1061#endif
1062
1063}
1064
1065MSGPACK_ADD_ENUM(dht::Value::Field)
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
Definition value.h:74
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:90
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object &o)
std::vector< uint8_t > Blob
Definition utils.h:151
An index for field values.
Definition value.h:987
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Definition value.h:658
Describes a query destined to another peer.
Definition value.h:924
Query(std::string_view q_str)
Definition value.h:942
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
Definition value.h:742
std::set< Value::Field > getSelection() const
Definition value.h:766
Select & field(Value::Field field)
Definition value.h:755
bool contentEquals(const Value &o) const
Definition value.h:430
bool checkSignature() const
Definition value.h:364
size_t size() const
Value(const msgpack::object &o)
Definition value.h:423
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
Definition value.h:382
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
Blob getToSign() const
Definition value.h:457
Blob getToEncrypt() const
Definition value.h:467
Value(const Blob &userdata)
Definition value.h:406
void sign(const crypto::PrivateKey &key)
Serializable dht::Value filter.
Definition value.h:797
Value::Filter getFilter() const
Definition value.h:878
Where && userType(std::string_view user_type)
Definition value.h:866
Where && seq(uint16_t seq_no)
Definition value.h:852
Where && id(Value::Id id)
Definition value.h:810
Where && valueType(ValueType::Id type)
Definition value.h:824
Where && owner(InfoHash owner_pk_hash)
Definition value.h:838