My Project 2.4.4
C++ Distributed Hash Table
Loading...
Searching...
No Matches
value.h
1/*
2 * Copyright (C) 2014-2022 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 Filter chain(Filter&& f2) {
175 auto f1 = *this;
176 return chain(std::move(f1), std::move(f2));
177 }
178 Filter chainOr(Filter&& f2) {
179 auto f1 = *this;
180 return chainOr(std::move(f1), std::move(f2));
181 }
182 static 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 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 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 Filter chain(std::initializer_list<Filter> l) {
206 return chainAll(std::vector<Filter>(l.begin(), l.end()));
207 }
208 static 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 Filter notFilter(Filter&& f) {
215 if (not f) return [](const Value&) { return false; };
216 return [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 const Filter AllFilter() {
232 return {};
233 }
234
235 static Filter TypeFilter(const ValueType& t) {
236 return [tid = t.id](const Value& v) {
237 return v.type == tid;
238 };
239 }
240 static Filter TypeFilter(const ValueType::Id& tid) {
241 return [tid](const Value& v) {
242 return v.type == tid;
243 };
244 }
245
246 static Filter IdFilter(const Id id) {
247 return [id](const Value& v) {
248 return v.id == id;
249 };
250 }
251
252 static Filter RecipientFilter(const InfoHash& r) {
253 return [r](const Value& v) {
254 return v.recipient == r;
255 };
256 }
257
258 static Filter OwnerFilter(const crypto::PublicKey& pk) {
259 return OwnerFilter(pk.getId());
260 }
261
262 static 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 Filter SeqNumFilter(uint16_t seq_no) {
269 return [seq_no](const Value& v) {
270 return v.seq == seq_no;
271 };
272 }
273
274 static 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 bool isEncrypted() const {
347 return not cypher.empty();
348 }
349 bool isSigned() const {
350 return owner and not signature.empty();
351 }
352
358 void sign(const crypto::PrivateKey& key) {
359 if (isEncrypted())
360 throw DhtException("Can't sign encrypted data.");
361 owner = key.getSharedPublicKey();
362 signature = key.sign(getToSign());
363 }
364
369 bool checkSignature() const {
370 return isSigned() and owner->checkSignature(getToSign(), signature);
371 }
372
373 std::shared_ptr<crypto::PublicKey> getOwner() const {
374 return std::static_pointer_cast<crypto::PublicKey>(owner);
375 }
376
381 if (isEncrypted())
382 throw DhtException("Data is already encrypted.");
383 setRecipient(to.getId());
384 sign(from);
385 Value nv {id};
386 nv.setCypher(to.encrypt(getToEncrypt()));
387 return nv;
388 }
389
390 Value() {}
391
392 Value (Id id) : id(id) {}
393
395 Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
396 : id(id), type(t), data(data) {}
397 Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
398 : id(id), type(t), data(std::move(data)) {}
399 Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
400 : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
401
402#ifdef OPENDHT_JSONCPP
407 Value(const Json::Value& json);
408#endif
409
410 template <typename Type>
411 Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
412 : id(id), type(t), data(packMsg(d)) {}
413
414 template <typename Type>
415 Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
416 : id(id), type(t.id), data(packMsg(d)) {}
417
419 Value(const Blob& userdata) : data(userdata) {}
420 Value(Blob&& userdata) : data(std::move(userdata)) {}
421 Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
422
423 Value(Value&& o) noexcept
424 : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
425 type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq)
426 , signature(std::move(o.signature)), cypher(std::move(o.cypher))
427 , priority(o.priority) {}
428
429 template <typename Type>
430 Value(const Type& vs)
431 : Value(pack<Type>(vs)) {}
432
436 Value(const msgpack::object& o) {
437 msgpack_unpack(o);
438 }
439
443 inline bool contentEquals(const Value& o) {
444 return isEncrypted() ? cypher == o.cypher :
445 ((owner == o.owner || (owner and o.owner and *owner == *o.owner))
446 && type == o.type
447 && data == o.data
448 && user_type == o.user_type
449 && signature == o.signature);
450 }
451
452 inline bool operator== (const Value& o) {
453 return id == o.id and contentEquals(o);
454 }
455
456 void setRecipient(const InfoHash& r) {
457 recipient = r;
458 }
459
460 void setCypher(Blob&& c) {
461 cypher = std::move(c);
462 }
463
467 Blob getToSign() const {
468 msgpack::sbuffer buffer;
469 msgpack::packer<msgpack::sbuffer> pk(&buffer);
470 msgpack_pack_to_sign(pk);
471 return {buffer.data(), buffer.data()+buffer.size()};
472 }
473
478 msgpack::sbuffer buffer;
479 msgpack::packer<msgpack::sbuffer> pk(&buffer);
480 msgpack_pack_to_encrypt(pk);
481 return {buffer.data(), buffer.data()+buffer.size()};
482 }
483
485 OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
486
487 std::string toString() const {
488 std::stringstream ss;
489 ss << *this;
490 return ss.str();
491 }
492
493#ifdef OPENDHT_JSONCPP
502 Json::Value toJson() const;
503#endif
504
506 size_t size() const;
507
508 template <typename Packer>
509 void msgpack_pack_to_sign(Packer& pk) const
510 {
511 bool has_owner = owner && *owner;
512 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
513 if (has_owner) { // isSigned
514 pk.pack(VALUE_KEY_SEQ); pk.pack(seq);
515 pk.pack(VALUE_KEY_OWNER); owner->msgpack_pack(pk);
516 if (recipient) {
517 pk.pack(VALUE_KEY_TO); pk.pack(recipient);
518 }
519 }
520 pk.pack(VALUE_KEY_TYPE); pk.pack(type);
521 pk.pack(VALUE_KEY_DATA); pk.pack_bin(data.size());
522 pk.pack_bin_body((const char*)data.data(), data.size());
523 if (not user_type.empty()) {
524 pk.pack(VALUE_KEY_USERTYPE); pk.pack(user_type);
525 }
526 }
527
528 template <typename Packer>
529 void msgpack_pack_to_encrypt(Packer& pk) const
530 {
531 if (isEncrypted()) {
532 pk.pack_bin(cypher.size());
533 pk.pack_bin_body((const char*)cypher.data(), cypher.size());
534 } else {
535 pk.pack_map(isSigned() ? 2 : 1);
536 pk.pack(VALUE_KEY_BODY); msgpack_pack_to_sign(pk);
537 if (isSigned()) {
538 pk.pack(VALUE_KEY_SIGNATURE); pk.pack_bin(signature.size());
539 pk.pack_bin_body((const char*)signature.data(), signature.size());
540 }
541 }
542 }
543
544 template <typename Packer>
545 void msgpack_pack(Packer& pk) const
546 {
547 pk.pack_map(2 + (priority?1:0));
548 pk.pack(VALUE_KEY_ID); pk.pack(id);
549 pk.pack(VALUE_KEY_DAT); msgpack_pack_to_encrypt(pk);
550 if (priority) {
551 pk.pack(VALUE_KEY_PRIO); pk.pack(priority);
552 }
553 }
554
555 template <typename Packer>
556 void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
557 {
558 for (const auto& field : fields)
559 switch (field) {
560 case Value::Field::Id:
561 pk.pack(static_cast<uint64_t>(id));
562 break;
563 case Value::Field::ValueType:
564 pk.pack(static_cast<uint64_t>(type));
565 break;
566 case Value::Field::OwnerPk:
567 if (owner)
568 owner->msgpack_pack(pk);
569 else
570 InfoHash().msgpack_pack(pk);
571 break;
572 case Value::Field::SeqNum:
573 pk.pack(static_cast<uint64_t>(seq));
574 break;
575 case Value::Field::UserType:
576 pk.pack(user_type);
577 break;
578 default:
579 break;
580 }
581 }
582
583 void msgpack_unpack(const msgpack::object& o);
584 void msgpack_unpack_body(const msgpack::object& o);
585 Blob getPacked() const {
586 msgpack::sbuffer buffer;
587 msgpack::packer<msgpack::sbuffer> pk(&buffer);
588 pk.pack(*this);
589 return {buffer.data(), buffer.data()+buffer.size()};
590 }
591
592 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
593
594 Id id {INVALID_ID};
595
599 std::shared_ptr<crypto::PublicKey> owner {};
600
606 InfoHash recipient {};
607
611 ValueType::Id type {ValueType::USER_DATA.id};
612 Blob data {};
613
617 std::string user_type {};
618
622 uint16_t seq {0};
623
627 Blob signature {};
628
632 Blob cypher {};
633
639 unsigned priority {0};
640
641 bool checkSignature();
642 Sp<Value> decrypt(const crypto::PrivateKey& key);
643
644private:
645 /* Cache for crypto ops */
646 bool signatureChecked {false};
647 bool signatureValid {false};
648 bool decrypted {false};
649 Sp<Value> decryptedValue {};
650};
651
652using ValuesExport = std::pair<InfoHash, Blob>;
653
661struct OPENDHT_PUBLIC FieldValue
662{
663 FieldValue() {}
664 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
665 FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
666 FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(std::move(blob_value)) {}
667
668 bool operator==(const FieldValue& fd) const;
669
670 // accessors
671 Value::Field getField() const { return field; }
672 uint64_t getInt() const { return intValue; }
673 InfoHash getHash() const { return hashValue; }
674 Blob getBlob() const { return blobValue; }
675
676 template <typename Packer>
677 void msgpack_pack(Packer& p) const {
678 p.pack_map(2);
679 p.pack("f"sv); p.pack(static_cast<uint8_t>(field));
680
681 p.pack("v"sv);
682 switch (field) {
683 case Value::Field::Id:
684 case Value::Field::ValueType:
685 p.pack(intValue);
686 break;
687 case Value::Field::OwnerPk:
688 p.pack(hashValue);
689 break;
690 case Value::Field::UserType:
691 p.pack_bin(blobValue.size());
692 p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
693 break;
694 default:
695 throw msgpack::type_error();
696 }
697 }
698
699 void msgpack_unpack(const msgpack::object& msg) {
700 hashValue = {};
701 blobValue.clear();
702
703 if (auto f = findMapValue(msg, "f"sv))
704 field = (Value::Field)f->as<unsigned>();
705 else
706 throw msgpack::type_error();
707
708 auto v = findMapValue(msg, "v"sv);
709 if (not v)
710 throw msgpack::type_error();
711 else
712 switch (field) {
713 case Value::Field::Id:
714 case Value::Field::ValueType:
715 intValue = v->as<decltype(intValue)>();
716 break;
717 case Value::Field::OwnerPk:
718 hashValue = v->as<decltype(hashValue)>();
719 break;
720 case Value::Field::UserType:
721 blobValue = unpackBlob(*v);
722 break;
723 default:
724 throw msgpack::type_error();
725 }
726 }
727
728 Value::Filter getLocalFilter() const;
729
730private:
731 Value::Field field {Value::Field::None};
732 // three possible value types
733 uint64_t intValue {};
734 InfoHash hashValue {};
735 Blob blobValue {};
736};
737
745struct OPENDHT_PUBLIC Select
746{
747 Select() { }
748 Select(std::string_view q_str);
749
750 bool isSatisfiedBy(const Select& os) const;
751
759 Select& field(Value::Field field) {
760 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
761 fieldSelection_.emplace_back(field);
762 return *this;
763 }
764
770 std::set<Value::Field> getSelection() const {
771 return {fieldSelection_.begin(), fieldSelection_.end()};
772 }
773
774 template <typename Packer>
775 void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
776 void msgpack_unpack(const msgpack::object& o) {
777 fieldSelection_ = o.as<decltype(fieldSelection_)>();
778 }
779
780 std::string toString() const {
781 std::stringstream ss;
782 ss << *this;
783 return ss.str();
784 }
785
786 bool empty() const { return fieldSelection_.empty(); }
787
788 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
789private:
790 std::vector<Value::Field> fieldSelection_ {};
791};
792
800struct OPENDHT_PUBLIC Where
801{
802 Where() { }
803 Where(std::string_view q_str);
804
805 bool isSatisfiedBy(const Where& where) const;
806
814 Where& id(Value::Id id) {
815 FieldValue fv {Value::Field::Id, id};
816 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
817 filters_.emplace_back(std::move(fv));
818 return *this;
819 }
820
828 Where& valueType(ValueType::Id type) {
829 FieldValue fv {Value::Field::ValueType, type};
830 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
831 filters_.emplace_back(std::move(fv));
832 return *this;
833 }
834
842 Where& owner(InfoHash owner_pk_hash) {
843 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
844 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
845 filters_.emplace_back(std::move(fv));
846 return *this;
847 }
848
856 Where& seq(uint16_t seq_no) {
857 FieldValue fv {Value::Field::SeqNum, seq_no};
858 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
859 filters_.emplace_back(std::move(fv));
860 return *this;
861 }
862
870 Where& userType(std::string_view user_type) {
871 FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
872 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
873 filters_.emplace_back(std::move(fv));
874 return *this;
875 }
876
883 if (filters_.empty()) return {};
884 std::vector<Value::Filter> fset;
885 fset.reserve(filters_.size());
886 for (const auto& f : filters_) {
887 if (auto lf = f.getLocalFilter())
888 fset.emplace_back(std::move(lf));
889 }
890 return Value::Filter::chainAll(std::move(fset));
891 }
892
893 template <typename Packer>
894 void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
895 void msgpack_unpack(const msgpack::object& o) {
896 filters_.clear();
897 filters_ = o.as<decltype(filters_)>();
898 }
899
900 std::string toString() const {
901 std::stringstream ss;
902 ss << *this;
903 return ss.str();
904 }
905
906 bool empty() const {
907 return filters_.empty();
908 }
909
910 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
911
912private:
913 std::vector<FieldValue> filters_;
914};
915
924struct OPENDHT_PUBLIC Query
925{
926 static const std::string QUERY_PARSE_ERROR;
927
928 Query(Select s = {}, Where w = {}, bool none = false) : select(std::move(s)), where(std::move(w)), none(none) { };
929
943 Query(std::string_view q_str) {
944 auto pos_W = q_str.find("WHERE");
945 auto pos_w = q_str.find("where");
946 auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
947 pos_w != std::string_view::npos ? pos_w : q_str.size());
948 select = q_str.substr(0, pos);
949 where = q_str.substr(pos, q_str.size()-pos);
950 }
951
955 bool isSatisfiedBy(const Query& q) const;
956
957 template <typename Packer>
958 void msgpack_pack(Packer& pk) const {
959 pk.pack_map(2);
960 pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
961 pk.pack(std::string("w")); pk.pack(where); /* packing filters */
962 }
963
964 void msgpack_unpack(const msgpack::object& o);
965
966 std::string toString() const {
967 std::stringstream ss;
968 ss << *this;
969 return ss.str();
970 }
971
972 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
973 return s << "Query[" << q.select << " " << q.where << "]";
974 }
975
976 Select select {};
977 Where where {};
978 bool none {false}; /* When true, any query satisfies this. */
979};
980
988struct OPENDHT_PUBLIC FieldValueIndex {
989 FieldValueIndex() {}
990 FieldValueIndex(const Value& v, const Select& s = {});
997 bool containedIn(const FieldValueIndex& other) const;
998
999 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
1000
1001 void msgpack_unpack_fields(const std::set<Value::Field>& fields,
1002 const msgpack::object& o,
1003 unsigned offset);
1004
1005 std::map<Value::Field, FieldValue> index {};
1006};
1007
1008template <typename T,
1009 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1010Value::Filter
1011getFilterSet(Value::Filter f)
1012{
1013 return Value::Filter::chain({
1014 Value::TypeFilter(T::TYPE),
1015 T::getFilter(),
1016 f
1017 });
1018}
1019
1020template <typename T,
1021 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1022Value::Filter
1023getFilterSet(Value::Filter f)
1024{
1025 return f;
1026}
1027
1028template <typename T,
1029 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1030Value::Filter
1031getFilterSet()
1032{
1033 return Value::Filter::chain({
1034 Value::TypeFilter(T::TYPE),
1035 T::getFilter()
1036 });
1037}
1038
1039template <typename T,
1040 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1041Value::Filter
1042getFilterSet()
1043{
1044 return {};
1045}
1046
1047template <class T>
1048std::vector<T>
1049unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
1050 std::vector<T> ret;
1051 ret.reserve(vals.size());
1052 for (const auto& v : vals) {
1053 try {
1054 ret.emplace_back(Value::unpack<T>(*v));
1055 } catch (const std::exception&) {}
1056 }
1057 return ret;
1058}
1059
1060#ifdef OPENDHT_JSONCPP
1061uint64_t unpackId(const Json::Value& json, const std::string& key);
1062#endif
1063
1064}
1065
1066MSGPACK_ADD_ENUM(dht::Value::Field)
Definition: callbacks.h:35
OPENDHT_PUBLIC Blob unpackBlob(const 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:90
std::vector< uint8_t > Blob
Definition: utils.h:151
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
Definition: value.h:74
An index for field values.
Definition: value.h:988
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Definition: value.h:662
Describes a query destined to another peer.
Definition: value.h:925
Query(std::string_view q_str)
Definition: value.h:943
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
Definition: value.h:746
std::set< Value::Field > getSelection() const
Definition: value.h:770
Select & field(Value::Field field)
Definition: value.h:759
bool checkSignature() const
Definition: value.h:369
Blob cypher
Definition: value.h:632
std::shared_ptr< crypto::PublicKey > owner
Definition: value.h:599
size_t size() const
Blob signature
Definition: value.h:627
Value(const msgpack::object &o)
Definition: value.h:436
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
Definition: value.h:395
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
Definition: value.h:380
bool contentEquals(const Value &o)
Definition: value.h:443
Blob getToSign() const
Definition: value.h:467
Blob getToEncrypt() const
Definition: value.h:477
std::string user_type
Definition: value.h:617
Value(const Blob &userdata)
Definition: value.h:419
ValueType::Id type
Definition: value.h:611
void sign(const crypto::PrivateKey &key)
Definition: value.h:358
Serializable dht::Value filter.
Definition: value.h:801
Value::Filter getFilter() const
Definition: value.h:882
Where & seq(uint16_t seq_no)
Definition: value.h:856
Where & valueType(ValueType::Id type)
Definition: value.h:828
Where & owner(InfoHash owner_pk_hash)
Definition: value.h:842
Where & userType(std::string_view user_type)
Definition: value.h:870
Where & id(Value::Id id)
Definition: value.h:814
Blob sign(const uint8_t *data, size_t data_len) const
InfoHash getId() const