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