My Project 3.4.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
149struct OPENDHT_PUBLIC Value
150{
151 enum class Field : int {
152 None = 0,
153 Id, /* Value::id */
154 ValueType, /* Value::type */
155 OwnerPk, /* Value::owner */
156 SeqNum, /* Value::seq */
157 UserType, /* Value::user_type */
158
159 COUNT /* the total number of fields */
160 };
161
162 typedef uint64_t Id;
163 static const constexpr Id INVALID_ID {0};
164
165 class Filter : public std::function<bool(const Value&)> {
166 public:
167 Filter() {}
168
169 template<typename Functor>
170 Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
171
172 inline Filter chain(Filter&& f2) {
173 auto f1 = *this;
174 return chain(std::move(f1), std::move(f2));
175 }
176 inline Filter chainOr(Filter&& f2) {
177 auto f1 = *this;
178 return chainOr(std::move(f1), std::move(f2));
179 }
180 static inline Filter chain(Filter&& f1, Filter&& f2) {
181 if (not f1) return std::move(f2);
182 if (not f2) return std::move(f1);
183 return [f1 = std::move(f1), f2 = std::move(f2)](const Value& v) {
184 return f1(v) and f2(v);
185 };
186 }
187 static inline Filter chain(const Filter& f1, const Filter& f2) {
188 if (not f1) return f2;
189 if (not f2) return f1;
190 return [f1,f2](const Value& v) {
191 return f1(v) and f2(v);
192 };
193 }
194 static inline Filter chainAll(std::vector<Filter>&& set) {
195 if (set.empty()) return {};
196 return [set = std::move(set)](const Value& v) {
197 for (const auto& f : set)
198 if (f and not f(v))
199 return false;
200 return true;
201 };
202 }
203 static inline Filter chain(std::initializer_list<Filter> l) {
204 return chainAll(std::vector<Filter>(l.begin(), l.end()));
205 }
206 static inline Filter chainOr(Filter&& f1, Filter&& f2) {
207 if (not f1 or not f2) return {};
208 return [f1=std::move(f1),f2=std::move(f2)](const Value& v) {
209 return f1(v) or f2(v);
210 };
211 }
212 static inline Filter notFilter(Filter&& f) {
213 if (not f) return [](const Value&) { return false; };
214 return [f = std::move(f)](const Value& v) { return not f(v); };
215 }
216 std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
217 if (not (*this))
218 return values;
219 std::vector<Sp<Value>> ret;
220 for (const auto& v : values)
221 if ((*this)(v))
222 ret.emplace_back(v);
223 return ret;
224 }
225 };
226
227 /* Sneaky functions disguised in classes */
228
229 static inline Filter AllFilter() {
230 return {};
231 }
232
233 static inline Filter TypeFilter(const ValueType& t) {
234 return [tid = t.id](const Value& v) {
235 return v.type == tid;
236 };
237 }
238 static inline Filter TypeFilter(const ValueType::Id& tid) {
239 return [tid](const Value& v) {
240 return v.type == tid;
241 };
242 }
243
244 static inline Filter IdFilter(const Id id) {
245 return [id](const Value& v) {
246 return v.id == id;
247 };
248 }
249
250 static inline Filter RecipientFilter(const InfoHash& r) {
251 return [r](const Value& v) {
252 return v.recipient == r;
253 };
254 }
255
256 static inline Filter OwnerFilter(const crypto::PublicKey& pk) {
257 return OwnerFilter(pk.getId());
258 }
259
260 static inline Filter OwnerFilter(const InfoHash& pkh) {
261 return [pkh](const Value& v) {
262 return v.owner and v.owner->getId() == pkh;
263 };
264 }
265
266 static inline Filter SeqNumFilter(uint16_t seq_no) {
267 return [seq_no](const Value& v) {
268 return v.seq == seq_no;
269 };
270 }
271
272 static inline Filter UserTypeFilter(std::string ut) {
273 return [ut = std::move(ut)](const Value& v) {
274 return v.user_type == ut;
275 };
276 }
277
278 class SerializableBase
279 {
280 public:
281 SerializableBase() {}
282 virtual ~SerializableBase() {};
283 virtual const ValueType& getType() const = 0;
284 virtual void unpackValue(const Value& v) = 0;
285 virtual Value packValue() const = 0;
286 };
287
288 template <typename Derived, typename Base=SerializableBase>
289 class Serializable : public Base
290 {
291 public:
292 using Base::Base;
293
294 virtual const ValueType& getType() const {
295 return Derived::TYPE;
296 }
297
298 virtual void unpackValue(const Value& v) {
299 auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
300 msg.get().convert(*static_cast<Derived*>(this));
301 }
302
303 virtual Value packValue() const {
304 return Value {getType(), static_cast<const Derived&>(*this)};
305 }
306 };
307
308 template <typename T,
309 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
310 static Value pack(const T& obj)
311 {
312 return obj.packValue();
313 }
314
315 template <typename T,
316 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
317 static Value pack(const T& obj)
318 {
319 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
320 }
321
322 template <typename T,
323 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
324 static T unpack(const Value& v)
325 {
326 T msg;
327 msg.unpackValue(v);
328 return msg;
329 }
330
331 template <typename T,
332 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
333 static T unpack(const Value& v)
334 {
335 return unpackMsg<T>(v.data);
336 }
337
338 template <typename T>
339 T unpack()
340 {
341 return unpack<T>(*this);
342 }
343
344 inline bool isEncrypted() const {
345 return not cypher.empty();
346 }
347 inline bool isSigned() const {
348 return owner and not signature.empty();
349 }
350
356 void sign(const crypto::PrivateKey& key);
357
362 inline bool checkSignature() const {
363 return isSigned() and owner->checkSignature(getToSign(), signature);
364 }
365
366 inline std::shared_ptr<crypto::PublicKey> getOwner() const {
367 return owner;
368 }
369
373 Value encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to);
374
375 Value() {}
376
377 Value (Id id) : id(id) {}
378
380 Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
381 : id(id), type(t), data(data) {}
382 Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
383 : id(id), type(t), data(std::move(data)) {}
384 Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
385 : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
386
387#ifdef OPENDHT_JSONCPP
392 Value(const Json::Value& json);
393#endif
394
395 template <typename Type>
396 Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
397 : id(id), type(t), data(packMsg(d)) {}
398
399 template <typename Type>
400 Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
401 : id(id), type(t.id), data(packMsg(d)) {}
402
404 Value(const Blob& userdata) : data(userdata) {}
405 Value(Blob&& userdata) : data(std::move(userdata)) {}
406 Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
407
408 Value(Value&& o) noexcept
409 : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
410 type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq)
411 , signature(std::move(o.signature)), cypher(std::move(o.cypher))
412 , priority(o.priority) {}
413
414 template <typename Type>
415 Value(const Type& vs)
416 : Value(pack<Type>(vs)) {}
417
421 Value(const msgpack::object& o) {
422 msgpack_unpack(o);
423 }
424
428 inline bool contentEquals(const Value& o) const {
429 return isEncrypted() ? cypher == o.cypher :
430 ((owner == o.owner || (owner and o.owner and *owner == *o.owner))
431 && type == o.type
432 && data == o.data
433 && user_type == o.user_type
434 && signature == o.signature);
435 }
436
437 inline bool operator== (const Value& o) const {
438 return id == o.id and contentEquals(o);
439 }
440 inline bool operator!= (const Value& o) const {
441 return !(*this == o);
442 }
443
444 inline void setRecipient(const InfoHash& r) {
445 recipient = r;
446 }
447
448 inline void setCypher(Blob&& c) {
449 cypher = std::move(c);
450 }
451
455 inline Blob getToSign() const {
456 msgpack::sbuffer buffer;
457 msgpack::packer<msgpack::sbuffer> pk(&buffer);
458 msgpack_pack_to_sign(pk);
459 return {buffer.data(), buffer.data()+buffer.size()};
460 }
461
465 inline Blob getToEncrypt() const {
466 msgpack::sbuffer buffer;
467 msgpack::packer<msgpack::sbuffer> pk(&buffer);
468 msgpack_pack_to_encrypt(pk);
469 return {buffer.data(), buffer.data()+buffer.size()};
470 }
471
473 OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
474
475 inline std::string toString() const {
476 std::ostringstream ss;
477 ss << *this;
478 return ss.str();
479 }
480
481#ifdef OPENDHT_JSONCPP
490 Json::Value toJson() const;
491#endif
492
494 size_t size() const;
495
496 template <typename Packer>
497 void msgpack_pack_to_sign(Packer& pk) const
498 {
499 bool has_owner = owner && *owner;
500 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
501 if (has_owner) { // isSigned
502 pk.pack(VALUE_KEY_SEQ); pk.pack(seq);
503 pk.pack(VALUE_KEY_OWNER); owner->msgpack_pack(pk);
504 if (recipient) {
505 pk.pack(VALUE_KEY_TO); pk.pack(recipient);
506 }
507 }
508 pk.pack(VALUE_KEY_TYPE); pk.pack(type);
509 pk.pack(VALUE_KEY_DATA); pk.pack_bin(data.size());
510 pk.pack_bin_body((const char*)data.data(), data.size());
511 if (not user_type.empty()) {
512 pk.pack(VALUE_KEY_USERTYPE); pk.pack(user_type);
513 }
514 }
515
516 template <typename Packer>
517 void msgpack_pack_to_encrypt(Packer& pk) const
518 {
519 if (isEncrypted()) {
520 pk.pack_bin(cypher.size());
521 pk.pack_bin_body((const char*)cypher.data(), cypher.size());
522 } else {
523 pk.pack_map(isSigned() ? 2 : 1);
524 pk.pack(VALUE_KEY_BODY); msgpack_pack_to_sign(pk);
525 if (isSigned()) {
526 pk.pack(VALUE_KEY_SIGNATURE); pk.pack_bin(signature.size());
527 pk.pack_bin_body((const char*)signature.data(), signature.size());
528 }
529 }
530 }
531
532 template <typename Packer>
533 void msgpack_pack(Packer& pk) const
534 {
535 pk.pack_map(2 + (priority?1:0));
536 pk.pack(VALUE_KEY_ID); pk.pack(id);
537 pk.pack(VALUE_KEY_DAT); msgpack_pack_to_encrypt(pk);
538 if (priority) {
539 pk.pack(VALUE_KEY_PRIO); pk.pack(priority);
540 }
541 }
542
543 template <typename Packer>
544 void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
545 {
546 for (const auto& field : fields)
547 switch (field) {
548 case Value::Field::Id:
549 pk.pack(static_cast<uint64_t>(id));
550 break;
551 case Value::Field::ValueType:
552 pk.pack(static_cast<uint64_t>(type));
553 break;
554 case Value::Field::OwnerPk:
555 if (owner)
556 owner->msgpack_pack(pk);
557 else
558 InfoHash().msgpack_pack(pk);
559 break;
560 case Value::Field::SeqNum:
561 pk.pack(static_cast<uint64_t>(seq));
562 break;
563 case Value::Field::UserType:
564 pk.pack(user_type);
565 break;
566 default:
567 break;
568 }
569 }
570
571 void msgpack_unpack(const msgpack::object& o);
572 void msgpack_unpack_body(const msgpack::object& o);
573 Blob getPacked() const {
574 msgpack::sbuffer buffer;
575 msgpack::packer<msgpack::sbuffer> pk(&buffer);
576 pk.pack(*this);
577 return {buffer.data(), buffer.data()+buffer.size()};
578 }
579
580 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
581
582 Id id {INVALID_ID};
583
587 std::shared_ptr<crypto::PublicKey> owner {};
588
594 InfoHash recipient {};
595
599 ValueType::Id type {ValueType::USER_DATA.id};
600 Blob data {};
601
605 std::string user_type {};
606
610 uint16_t seq {0};
611
616
621
627 unsigned priority {0};
628
629 inline bool isSignatureChecked() const {
630 return signatureChecked;
631 }
632 inline bool isDecrypted() const {
633 return decrypted;
634 }
635 bool checkSignature();
636 Sp<Value> decrypt(const crypto::PrivateKey& key);
637
638private:
639 /* Cache for crypto ops */
640 bool signatureChecked {false};
641 bool signatureValid {false};
642 bool decrypted {false};
643 Sp<Value> decryptedValue {};
644};
645
646using ValuesExport = std::pair<InfoHash, Blob>;
647
655struct OPENDHT_PUBLIC FieldValue
656{
657 FieldValue() {}
658 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
659 FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
660 FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(std::move(blob_value)) {}
661
662 bool operator==(const FieldValue& fd) const;
663
664 // accessors
665 Value::Field getField() const { return field; }
666 uint64_t getInt() const { return intValue; }
667 InfoHash getHash() const { return hashValue; }
668 Blob getBlob() const { return blobValue; }
669
670 template <typename Packer>
671 void msgpack_pack(Packer& p) const {
672 p.pack_map(2);
673 p.pack("f"sv); p.pack(static_cast<uint8_t>(field));
674
675 p.pack("v"sv);
676 switch (field) {
677 case Value::Field::Id:
678 case Value::Field::ValueType:
679 p.pack(intValue);
680 break;
681 case Value::Field::OwnerPk:
682 p.pack(hashValue);
683 break;
684 case Value::Field::UserType:
685 p.pack_bin(blobValue.size());
686 p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
687 break;
688 default:
689 throw msgpack::type_error();
690 }
691 }
692
693 void msgpack_unpack(const msgpack::object& msg) {
694 hashValue = {};
695 blobValue.clear();
696
697 if (auto f = findMapValue(msg, "f"sv))
698 field = (Value::Field)f->as<unsigned>();
699 else
700 throw msgpack::type_error();
701
702 auto v = findMapValue(msg, "v"sv);
703 if (not v)
704 throw msgpack::type_error();
705 else
706 switch (field) {
707 case Value::Field::Id:
708 case Value::Field::ValueType:
709 intValue = v->as<decltype(intValue)>();
710 break;
711 case Value::Field::OwnerPk:
712 hashValue = v->as<decltype(hashValue)>();
713 break;
714 case Value::Field::UserType:
715 blobValue = unpackBlob(*v);
716 break;
717 default:
718 throw msgpack::type_error();
719 }
720 }
721
722 Value::Filter getLocalFilter() const;
723
724private:
725 Value::Field field {Value::Field::None};
726 // three possible value types
727 uint64_t intValue {};
728 InfoHash hashValue {};
729 Blob blobValue {};
730};
731
739struct OPENDHT_PUBLIC Select
740{
741 Select() { }
742 Select(std::string_view q_str);
743
744 bool isSatisfiedBy(const Select& os) const;
745
753 Select& field(Value::Field field) {
754 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
755 fieldSelection_.emplace_back(field);
756 return *this;
757 }
758
764 std::set<Value::Field> getSelection() const {
765 return {fieldSelection_.begin(), fieldSelection_.end()};
766 }
767
768 template <typename Packer>
769 void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
770 void msgpack_unpack(const msgpack::object& o) {
771 fieldSelection_ = o.as<decltype(fieldSelection_)>();
772 }
773
774 std::string toString() const {
775 std::ostringstream ss;
776 ss << *this;
777 return ss.str();
778 }
779
780 bool empty() const { return fieldSelection_.empty(); }
781
782 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
783private:
784 std::vector<Value::Field> fieldSelection_ {};
785};
786
794struct OPENDHT_PUBLIC Where
795{
796 Where() { }
797 Where(std::string_view q_str);
798
799 bool isSatisfiedBy(const Where& where) const;
800
808 Where&& id(Value::Id id) {
809 FieldValue fv {Value::Field::Id, id};
810 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
811 filters_.emplace_back(std::move(fv));
812 return std::move(*this);
813 }
814
822 Where&& valueType(ValueType::Id type) {
823 FieldValue fv {Value::Field::ValueType, type};
824 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
825 filters_.emplace_back(std::move(fv));
826 return std::move(*this);
827 }
828
836 Where&& owner(InfoHash owner_pk_hash) {
837 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
838 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
839 filters_.emplace_back(std::move(fv));
840 return std::move(*this);
841 }
842
850 Where&& seq(uint16_t seq_no) {
851 FieldValue fv {Value::Field::SeqNum, seq_no};
852 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
853 filters_.emplace_back(std::move(fv));
854 return std::move(*this);
855 }
856
864 Where&& userType(std::string_view user_type) {
865 FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
866 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
867 filters_.emplace_back(std::move(fv));
868 return std::move(*this);
869 }
870
877 if (filters_.empty())
878 return {};
879 if (filters_.size() == 1)
880 return filters_[0].getLocalFilter();
881 std::vector<Value::Filter> fset;
882 fset.reserve(filters_.size());
883 for (const auto& f : filters_) {
884 if (auto lf = f.getLocalFilter())
885 fset.emplace_back(std::move(lf));
886 }
887 return Value::Filter::chainAll(std::move(fset));
888 }
889
890 template <typename Packer>
891 void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
892 void msgpack_unpack(const msgpack::object& o) {
893 filters_.clear();
894 filters_ = o.as<decltype(filters_)>();
895 }
896
897 std::string toString() const {
898 std::ostringstream ss;
899 ss << *this;
900 return ss.str();
901 }
902
903 bool empty() const {
904 return filters_.empty();
905 }
906
907 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
908
909private:
910 std::vector<FieldValue> filters_;
911};
912
921struct OPENDHT_PUBLIC Query
922{
923 static const std::string QUERY_PARSE_ERROR;
924
925 Query(Select s = {}, Where w = {}, bool none = false) : select(std::move(s)), where(std::move(w)), none(none) { };
926
940 Query(std::string_view q_str) {
941 auto pos_W = q_str.find("WHERE");
942 auto pos_w = q_str.find("where");
943 auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
944 pos_w != std::string_view::npos ? pos_w : q_str.size());
945 select = q_str.substr(0, pos);
946 where = q_str.substr(pos, q_str.size()-pos);
947 }
948
952 bool isSatisfiedBy(const Query& q) const;
953
954 template <typename Packer>
955 void msgpack_pack(Packer& pk) const {
956 pk.pack_map(2);
957 pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
958 pk.pack(std::string("w")); pk.pack(where); /* packing filters */
959 }
960
961 void msgpack_unpack(const msgpack::object& o);
962
963 std::string toString() const {
964 std::ostringstream ss;
965 ss << *this;
966 return ss.str();
967 }
968
969 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
970 return s << "Query[" << q.select << " " << q.where << "]";
971 }
972
973 Select select {};
974 Where where {};
975 bool none {false}; /* When true, any query satisfies this. */
976};
977
985struct OPENDHT_PUBLIC FieldValueIndex {
986 FieldValueIndex() {}
987 FieldValueIndex(const Value& v, const Select& s = {});
994 bool containedIn(const FieldValueIndex& other) const;
995
996 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
997
998 void msgpack_unpack_fields(const std::set<Value::Field>& fields,
999 const msgpack::object& o,
1000 unsigned offset);
1001
1002 std::map<Value::Field, FieldValue> index {};
1003};
1004
1005template <typename T,
1006 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1007Value::Filter
1008getFilterSet(Value::Filter f)
1009{
1010 return Value::Filter::chain({
1011 Value::TypeFilter(T::TYPE),
1012 T::getFilter(),
1013 f
1014 });
1015}
1016
1017template <typename T,
1018 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1020getFilterSet(Value::Filter f)
1021{
1022 return f;
1023}
1024
1025template <typename T,
1026 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1028getFilterSet()
1029{
1030 return Value::Filter::chain({
1031 Value::TypeFilter(T::TYPE),
1032 T::getFilter()
1033 });
1034}
1035
1036template <typename T,
1037 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1039getFilterSet()
1040{
1041 return {};
1042}
1043
1044template <class T>
1045std::vector<T>
1046unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
1047 std::vector<T> ret;
1048 ret.reserve(vals.size());
1049 for (const auto& v : vals) {
1050 try {
1051 ret.emplace_back(Value::unpack<T>(*v));
1052 } catch (const std::exception&) {}
1053 }
1054 return ret;
1055}
1056
1057#ifdef OPENDHT_JSONCPP
1058uint64_t unpackId(const Json::Value& json, const std::string& key);
1059#endif
1060
1061}
1062
1063MSGPACK_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:138
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Definition value.h:656
Describes a query destined to another peer.
Definition value.h:922
Query(std::string_view q_str)
Definition value.h:940
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
Definition value.h:740
std::set< Value::Field > getSelection() const
Definition value.h:764
Select & field(Value::Field field)
Definition value.h:753
bool contentEquals(const Value &o) const
Definition value.h:428
bool checkSignature() const
Definition value.h:362
Blob cypher
Definition value.h:620
std::shared_ptr< crypto::PublicKey > owner
Definition value.h:587
uint16_t seq
Definition value.h:610
size_t size() const
InfoHash recipient
Definition value.h:594
Blob signature
Definition value.h:615
Value(const msgpack::object &o)
Definition value.h:421
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
Definition value.h:380
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
Blob getToSign() const
Definition value.h:455
Blob getToEncrypt() const
Definition value.h:465
std::string user_type
Definition value.h:605
Value(const Blob &userdata)
Definition value.h:404
ValueType::Id type
Definition value.h:599
void sign(const crypto::PrivateKey &key)
unsigned priority
Definition value.h:627
Serializable dht::Value filter.
Definition value.h:795
Value::Filter getFilter() const
Definition value.h:876
Where && userType(std::string_view user_type)
Definition value.h:864
Where && seq(uint16_t seq_no)
Definition value.h:850
Where && id(Value::Id id)
Definition value.h:808
Where && valueType(ValueType::Id type)
Definition value.h:822
Where && owner(InfoHash owner_pk_hash)
Definition value.h:836