My Project 3.7.1
C++ Distributed Hash Table
Loading...
Searching...
No Matches
value.h
1// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include "infohash.h"
6#include "crypto.h"
7#include "utils.h"
8#include "sockaddr.h"
9
10#include <msgpack.hpp>
11
12#include <string>
13#include <string_view>
14#include <sstream>
15#include <bitset>
16#include <vector>
17#include <iostream>
18#include <algorithm>
19#include <functional>
20#include <memory>
21#include <chrono>
22#include <set>
23
24#ifdef OPENDHT_JSONCPP
25#include <json/json.h>
26#endif
27
28namespace dht {
29using namespace std::literals;
30
31static constexpr auto VALUE_KEY_ID("id");
32static const std::string VALUE_KEY_DAT("dat");
33static const std::string VALUE_KEY_PRIO("p");
34static const std::string VALUE_KEY_SIGNATURE("sig");
35
36static const std::string VALUE_KEY_SEQ("seq");
37static const std::string VALUE_KEY_DATA("data");
38static const std::string VALUE_KEY_OWNER("owner");
39static const std::string VALUE_KEY_TYPE("type");
40static const std::string VALUE_KEY_TO("to");
41static const std::string VALUE_KEY_BODY("body");
42static const std::string VALUE_KEY_USERTYPE("utype");
43
44struct Value;
45struct Query;
46
58 = std::function<bool(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr& addr)>;
59
74using EditPolicy = std::function<bool(InfoHash key,
75 const std::shared_ptr<Value>& old_val,
76 std::shared_ptr<Value>& new_val,
77 const InfoHash& from,
78 const SockAddr& addr)>;
79
80static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
81static constexpr const duration DEFAULT_VALUE_EXPIRATION {std::chrono::minutes(10)};
83struct ValueType
84{
85 typedef uint16_t Id;
86
87 OPENDHT_PUBLIC static bool DEFAULT_STORE_POLICY(InfoHash,
88 const std::shared_ptr<Value>& v,
89 const InfoHash&,
90 const SockAddr&);
91 static inline bool DEFAULT_EDIT_POLICY(
92 InfoHash, const std::shared_ptr<Value>&, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&)
93 {
94 return false;
95 }
96
97 ValueType() {}
98
99 ValueType(Id id, std::string name, duration e = DEFAULT_VALUE_EXPIRATION)
100 : id(id)
101 , name(name)
102 , expiration(e)
103 {}
104
105 ValueType(Id id, std::string name, duration e, StorePolicy sp, EditPolicy ep = DEFAULT_EDIT_POLICY)
106 : id(id)
107 , name(name)
108 , expiration(e)
109 , storePolicy(sp)
110 , editPolicy(ep)
111 {}
112
113 virtual ~ValueType() {}
114
115 bool operator==(const ValueType& o) { return id == o.id; }
116
117 // Generic value type
118 OPENDHT_PUBLIC static const ValueType USER_DATA;
119
120 Id id {0};
121 std::string name {};
122 duration expiration {DEFAULT_VALUE_EXPIRATION};
123 StorePolicy storePolicy {DEFAULT_STORE_POLICY};
124 EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
125};
127class TypeStore
128{
129public:
130 void registerType(const ValueType& type) { types[type.id] = type; }
131 const ValueType& getType(ValueType::Id type_id) const
132 {
133 const auto& t_it = types.find(type_id);
134 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
135 }
136
137private:
138 std::map<ValueType::Id, ValueType> types {};
139};
140
149 */
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};
166 class Filter : public std::function<bool(const Value&)>
167 {
168 public:
169 Filter() {}
170
171 template<typename Functor>
172 Filter(Functor f)
173 : std::function<bool(const Value&)>::function(f)
174 {}
175
176 inline Filter chain(Filter&& f2)
177 {
178 auto f1 = *this;
179 return chain(std::move(f1), std::move(f2));
180 }
181 inline Filter chainOr(Filter&& f2)
182 {
183 auto f1 = *this;
184 return chainOr(std::move(f1), std::move(f2));
185 }
186 static inline Filter chain(Filter&& f1, Filter&& f2)
187 {
188 if (not f1)
189 return std::move(f2);
190 if (not f2)
191 return std::move(f1);
192 return [f1 = std::move(f1), f2 = std::move(f2)](const Value& v) {
193 return f1(v) and f2(v);
194 };
195 }
196 static inline Filter chain(const Filter& f1, const Filter& f2)
197 {
198 if (not f1)
199 return f2;
200 if (not f2)
201 return f1;
202 return [f1, f2](const Value& v) {
203 return f1(v) and f2(v);
204 };
205 }
206 static inline Filter chainAll(std::vector<Filter>&& set)
207 {
208 if (set.empty())
209 return {};
210 return [set = std::move(set)](const Value& v) {
211 for (const auto& f : set)
212 if (f and not f(v))
213 return false;
214 return true;
215 };
216 }
217 static inline Filter chain(std::initializer_list<Filter> l)
218 {
219 return chainAll(std::vector<Filter>(l.begin(), l.end()));
220 }
221 static inline Filter chainOr(Filter&& f1, Filter&& f2)
222 {
223 if (not f1 or not f2)
224 return {};
225 return [f1 = std::move(f1), f2 = std::move(f2)](const Value& v) {
226 return f1(v) or f2(v);
227 };
228 }
229 static inline Filter notFilter(Filter&& f)
230 {
231 if (not f)
232 return [](const Value&) {
233 return false;
234 };
235 return [f = std::move(f)](const Value& v) {
236 return not f(v);
237 };
238 }
239 std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values)
240 {
241 if (not(*this))
242 return values;
243 std::vector<Sp<Value>> ret;
244 for (const auto& v : values)
245 if ((*this)(v))
246 ret.emplace_back(v);
247 return ret;
248 }
249 };
250
251 /* Sneaky functions disguised in classes */
252
253 static inline Filter AllFilter() { return {}; }
254
255 static inline Filter TypeFilter(const ValueType& t)
256 {
257 return [tid = t.id](const Value& v) {
258 return v.type == tid;
259 };
260 }
261 static inline Filter TypeFilter(const ValueType::Id& tid)
262 {
263 return [tid](const Value& v) {
264 return v.type == tid;
265 };
266 }
267
268 static inline Filter IdFilter(const Id id)
269 {
270 return [id](const Value& v) {
271 return v.id == id;
272 };
273 }
274
275 static inline Filter RecipientFilter(const InfoHash& r)
276 {
277 return [r](const Value& v) {
278 return v.recipient == r;
279 };
280 }
281
282 static inline Filter OwnerFilter(const crypto::PublicKey& pk) { return OwnerFilter(pk.getId()); }
283
284 static inline Filter OwnerFilter(const InfoHash& pkh)
285 {
286 return [pkh](const Value& v) {
287 return v.owner and v.owner->getId() == pkh;
288 };
289 }
290
291 static inline Filter SeqNumFilter(uint16_t seq_no)
292 {
293 return [seq_no](const Value& v) {
294 return v.seq == seq_no;
295 };
296 }
297
298 static inline Filter UserTypeFilter(std::string ut)
299 {
300 return [ut = std::move(ut)](const Value& v) {
301 return v.user_type == ut;
302 };
303 }
305 class SerializableBase
306 {
307 public:
308 SerializableBase() {}
309 virtual ~SerializableBase() {};
310 virtual const ValueType& getType() const = 0;
311 virtual void unpackValue(const Value& v) = 0;
312 virtual Value packValue() const = 0;
313 };
314
315 template<typename Derived, typename Base = SerializableBase>
316 class Serializable : public Base
317 {
318 public:
319 using Base::Base;
320
321 virtual const ValueType& getType() const { return Derived::TYPE; }
322
323 virtual void unpackValue(const Value& v)
324 {
325 auto msg = msgpack::unpack((const char*) v.data.data(), v.data.size());
326 msg.get().convert(*static_cast<Derived*>(this));
327 }
328
329 virtual Value packValue() const { return Value {getType(), static_cast<const Derived&>(*this)}; }
330 };
331
332 template<typename T, typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
333 static Value pack(const T& obj)
334 {
335 return obj.packValue();
336 }
337
338 template<typename T, typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
339 static Value pack(const T& obj)
340 {
341 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
342 }
343
344 template<typename T, typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
345 static T unpack(const Value& v)
346 {
347 T msg;
348 msg.unpackValue(v);
349 return msg;
350 }
351
352 template<typename T, typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
353 static T unpack(const Value& v)
354 {
355 return unpackMsg<T>(v.data);
356 }
357
358 template<typename T>
359 T unpack()
360 {
361 return unpack<T>(*this);
362 }
363
364 inline bool isEncrypted() const { return not cypher.empty(); }
365 inline bool isSigned() const { return owner and not signature.empty(); }
366
372 void sign(const crypto::PrivateKey& key);
373
378 inline bool checkSignature() const { return isSigned() and owner->checkSignature(getToSign(), signature); }
379
380 inline std::shared_ptr<crypto::PublicKey> getOwner() const { return owner; }
381
385 Value encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to);
386
387 Value() {}
388
389 Value(Id id)
390 : id(id)
391 {}
392
393 /** Generic constructor */
394 Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
395 : id(id)
396 , type(t)
397 , data(data)
398 {}
399 Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
400 : id(id)
401 , type(t)
402 , data(std::move(data))
403 {}
404 Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
405 : id(id)
406 , type(t)
407 , data(dat_ptr, dat_ptr + dat_len)
408 {}
409
410#ifdef OPENDHT_JSONCPP
415 Value(const Json::Value& json);
416#endif
417
418 template<typename Type>
419 Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
420 : id(id)
421 , type(t)
422 , data(packMsg(d))
423 {}
424
425 template<typename Type>
426 Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
427 : id(id)
428 , type(t.id)
429 , data(packMsg(d))
430 {}
431
432 /** Custom user data constructor */
433 Value(const Blob& userdata)
434 : data(userdata)
435 {}
436 Value(Blob&& userdata)
437 : data(std::move(userdata))
438 {}
439 Value(const uint8_t* dat_ptr, size_t dat_len)
440 : data(dat_ptr, dat_ptr + dat_len)
441 {}
442
443 Value(Value&& o) noexcept
444 : id(o.id)
445 , owner(std::move(o.owner))
446 , recipient(o.recipient)
447 , type(o.type)
448 , data(std::move(o.data))
449 , user_type(std::move(o.user_type))
450 , seq(o.seq)
451 , signature(std::move(o.signature))
452 , cypher(std::move(o.cypher))
453 , priority(o.priority)
454 {}
455
456 template<typename Type>
457 Value(const Type& vs)
458 : Value(pack<Type>(vs))
459 {}
460
464 Value(const msgpack::object& o) { msgpack_unpack(o); }
465
468 */
469 inline bool contentEquals(const Value& o) const
470 {
471 return isEncrypted() ? cypher == o.cypher
472 : ((owner == o.owner || (owner and o.owner and *owner == *o.owner)) && type == o.type
473 && data == o.data && user_type == o.user_type && signature == o.signature);
474 }
475
476 inline bool operator==(const Value& o) const { return id == o.id and contentEquals(o); }
477 inline bool operator!=(const Value& o) const { return !(*this == o); }
478
479 inline void setRecipient(const InfoHash& r) { recipient = r; }
480
481 inline void setCypher(Blob&& c) { cypher = std::move(c); }
482
485 */
486 inline Blob getToSign() const
487 {
488 msgpack::sbuffer buffer;
489 msgpack::packer<msgpack::sbuffer> pk(&buffer);
490 msgpack_pack_to_sign(pk);
491 return {buffer.data(), buffer.data() + buffer.size()};
492 }
493
496 */
497 inline Blob getToEncrypt() const
498 {
499 msgpack::sbuffer buffer;
500 msgpack::packer<msgpack::sbuffer> pk(&buffer);
501 msgpack_pack_to_encrypt(pk);
502 return {buffer.data(), buffer.data() + buffer.size()};
503 }
504
506 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const Value& v);
507
508 inline std::string toString() const
509 {
510 std::ostringstream ss;
511 ss << *this;
512 return ss.str();
513 }
514
515#ifdef OPENDHT_JSONCPP
524 Json::Value toJson() const;
525#endif
526
528 size_t size() const;
529
530 template<typename Packer>
531 void msgpack_pack_to_sign(Packer& pk) const
532 {
533 bool has_owner = owner && *owner;
534 pk.pack_map((user_type.empty() ? 0 : 1) + (has_owner ? (recipient ? 5 : 4) : 2));
535 if (has_owner) { // isSigned
536 pk.pack(VALUE_KEY_SEQ);
537 pk.pack(seq);
538 pk.pack(VALUE_KEY_OWNER);
539 owner->msgpack_pack(pk);
540 if (recipient) {
541 pk.pack(VALUE_KEY_TO);
542 pk.pack(recipient);
543 }
544 }
545 pk.pack(VALUE_KEY_TYPE);
546 pk.pack(type);
547 pk.pack(VALUE_KEY_DATA);
548 pk.pack_bin(data.size());
549 pk.pack_bin_body((const char*) data.data(), data.size());
550 if (not user_type.empty()) {
551 pk.pack(VALUE_KEY_USERTYPE);
552 pk.pack(user_type);
553 }
554 }
555
556 template<typename Packer>
557 void msgpack_pack_to_encrypt(Packer& pk) const
558 {
559 if (isEncrypted()) {
560 pk.pack_bin(cypher.size());
561 pk.pack_bin_body((const char*) cypher.data(), cypher.size());
562 } else {
563 pk.pack_map(isSigned() ? 2 : 1);
564 pk.pack(VALUE_KEY_BODY);
565 msgpack_pack_to_sign(pk);
566 if (isSigned()) {
567 pk.pack(VALUE_KEY_SIGNATURE);
568 pk.pack_bin(signature.size());
569 pk.pack_bin_body((const char*) signature.data(), signature.size());
570 }
571 }
572 }
573
574 template<typename Packer>
575 void msgpack_pack(Packer& pk) const
576 {
577 pk.pack_map(2 + (priority ? 1 : 0));
578 pk.pack(VALUE_KEY_ID);
579 pk.pack(id);
580 pk.pack(VALUE_KEY_DAT);
581 msgpack_pack_to_encrypt(pk);
582 if (priority) {
583 pk.pack(VALUE_KEY_PRIO);
584 pk.pack(priority);
585 }
586 }
587
588 template<typename Packer>
589 void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
590 {
591 for (const auto& field : fields)
592 switch (field) {
593 case Value::Field::Id:
594 pk.pack(static_cast<uint64_t>(id));
595 break;
596 case Value::Field::ValueType:
597 pk.pack(static_cast<uint64_t>(type));
598 break;
599 case Value::Field::OwnerPk:
600 if (owner)
601 owner->msgpack_pack(pk);
602 else
603 InfoHash().msgpack_pack(pk);
604 break;
605 case Value::Field::SeqNum:
606 pk.pack(static_cast<uint64_t>(seq));
607 break;
608 case Value::Field::UserType:
609 pk.pack(user_type);
610 break;
611 default:
612 break;
613 }
614 }
615
616 void msgpack_unpack(const msgpack::object& o);
617 void msgpack_unpack_body(const msgpack::object& o);
618 Blob getPacked() const
619 {
620 msgpack::sbuffer buffer;
621 msgpack::packer<msgpack::sbuffer> pk(&buffer);
622 pk.pack(*this);
623 return {buffer.data(), buffer.data() + buffer.size()};
624 }
625
626 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
627
628 Id id {INVALID_ID};
629
633 std::shared_ptr<crypto::PublicKey> owner {};
634
640 InfoHash recipient {};
641
645 ValueType::Id type {ValueType::USER_DATA.id};
646 Blob data {};
647
651 std::string user_type {};
652
656 uint16_t seq {0};
657
661 Blob signature {};
662
666 Blob cypher {};
667
673 unsigned priority {0};
674
675 inline bool isSignatureChecked() const { return signatureChecked; }
676 inline bool isDecrypted() const { return decrypted; }
677 bool checkSignature();
678 Sp<Value> decrypt(const crypto::PrivateKey& key);
679
680private:
681 /* Cache for crypto ops */
682 bool signatureChecked {false};
683 bool signatureValid {false};
684 bool decrypted {false};
685 Sp<Value> decryptedValue {};
686};
687
688using ValuesExport = std::pair<InfoHash, Blob>;
689
696 */
697struct OPENDHT_PUBLIC FieldValue
698{
699 FieldValue() {}
700 FieldValue(Value::Field f, uint64_t int_value)
701 : field(f)
702 , intValue(int_value)
703 {}
704 FieldValue(Value::Field f, InfoHash hash_value)
705 : field(f)
706 , hashValue(hash_value)
707 {}
708 FieldValue(Value::Field f, Blob blob_value)
709 : field(f)
710 , blobValue(std::move(blob_value))
711 {}
712
713 bool operator==(const FieldValue& fd) const;
714
715 // accessors
716 Value::Field getField() const { return field; }
717 uint64_t getInt() const { return intValue; }
718 InfoHash getHash() const { return hashValue; }
719 Blob getBlob() const { return blobValue; }
720
721 template<typename Packer>
722 void msgpack_pack(Packer& p) const
723 {
724 p.pack_map(2);
725 p.pack("f"sv);
726 p.pack(static_cast<uint8_t>(field));
727
728 p.pack("v"sv);
729 switch (field) {
730 case Value::Field::Id:
731 case Value::Field::ValueType:
732 p.pack(intValue);
733 break;
734 case Value::Field::OwnerPk:
735 p.pack(hashValue);
736 break;
737 case Value::Field::UserType:
738 p.pack_bin(blobValue.size());
739 p.pack_bin_body((const char*) blobValue.data(), blobValue.size());
740 break;
741 default:
742 throw msgpack::type_error();
743 }
744 }
745
746 void msgpack_unpack(const msgpack::object& msg)
747 {
748 hashValue = {};
749 blobValue.clear();
750
751 if (auto f = findMapValue(msg, "f"sv))
752 field = (Value::Field) f->as<unsigned>();
753 else
754 throw msgpack::type_error();
755
756 auto v = findMapValue(msg, "v"sv);
757 if (not v)
758 throw msgpack::type_error();
759 else
760 switch (field) {
761 case Value::Field::Id:
762 case Value::Field::ValueType:
763 intValue = v->as<decltype(intValue)>();
764 break;
765 case Value::Field::OwnerPk:
766 hashValue = v->as<decltype(hashValue)>();
767 break;
768 case Value::Field::UserType:
769 blobValue = unpackBlob(*v);
770 break;
771 default:
772 throw msgpack::type_error();
773 }
774 }
775
776 Value::Filter getLocalFilter() const;
777
778private:
779 Value::Field field {Value::Field::None};
780 // three possible value types
781 uint64_t intValue {};
782 InfoHash hashValue {};
783 Blob blobValue {};
784};
785
792 */
793struct OPENDHT_PUBLIC Select
794{
795 Select() {}
796 Select(std::string_view q_str);
797
798 bool isSatisfiedBy(const Select& os) const;
799
806 */
807 Select& field(Value::Field field)
808 {
809 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
810 fieldSelection_.emplace_back(field);
811 return *this;
812 }
813
819 std::set<Value::Field> getSelection() const { return {fieldSelection_.begin(), fieldSelection_.end()}; }
820
821 template<typename Packer>
822 void msgpack_pack(Packer& pk) const
823 {
824 pk.pack(fieldSelection_);
825 }
826 void msgpack_unpack(const msgpack::object& o) { fieldSelection_ = o.as<decltype(fieldSelection_)>(); }
827
828 std::string toString() const
829 {
830 std::ostringstream ss;
831 ss << *this;
832 return ss.str();
833 }
834
835 bool empty() const { return fieldSelection_.empty(); }
836
837 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
838
839private:
840 std::vector<Value::Field> fieldSelection_ {};
841};
842
849 */
850struct OPENDHT_PUBLIC Where
851{
852 Where() {}
853 Where(std::string_view q_str);
854
855 bool isSatisfiedBy(const Where& where) const;
856
863 */
864 Where&& id(Value::Id id)
865 {
866 FieldValue fv {Value::Field::Id, id};
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 */
879 Where&& valueType(ValueType::Id type)
880 {
881 FieldValue fv {Value::Field::ValueType, type};
882 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
883 filters_.emplace_back(std::move(fv));
884 return std::move(*this);
885 }
886
893 */
894 Where&& owner(InfoHash owner_pk_hash)
895 {
896 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
897 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
898 filters_.emplace_back(std::move(fv));
899 return std::move(*this);
900 }
901
908 */
909 Where&& seq(uint16_t seq_no)
910 {
911 FieldValue fv {Value::Field::SeqNum, seq_no};
912 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
913 filters_.emplace_back(std::move(fv));
914 return std::move(*this);
915 }
916
923 */
924 Where&& userType(std::string_view user_type)
925 {
926 FieldValue fv {
927 Value::Field::UserType, Blob {user_type.begin(), user_type.end()}
928 };
929 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
930 filters_.emplace_back(std::move(fv));
931 return std::move(*this);
932 }
933
938 */
940 {
941 if (filters_.empty())
942 return {};
943 if (filters_.size() == 1)
944 return filters_[0].getLocalFilter();
945 std::vector<Value::Filter> fset;
946 fset.reserve(filters_.size());
947 for (const auto& f : filters_) {
948 if (auto lf = f.getLocalFilter())
949 fset.emplace_back(std::move(lf));
950 }
951 return Value::Filter::chainAll(std::move(fset));
952 }
953
954 template<typename Packer>
955 void msgpack_pack(Packer& pk) const
956 {
957 pk.pack(filters_);
958 }
959 void msgpack_unpack(const msgpack::object& o)
960 {
961 filters_.clear();
962 filters_ = o.as<decltype(filters_)>();
963 }
964
965 std::string toString() const
966 {
967 std::ostringstream ss;
968 ss << *this;
969 return ss.str();
970 }
971
972 bool empty() const { return filters_.empty(); }
973
974 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
975
976private:
977 std::vector<FieldValue> filters_;
978};
979
987 */
988struct OPENDHT_PUBLIC Query
989{
990 static const std::string QUERY_PARSE_ERROR;
991
992 Query(Select s = {}, Where w = {}, bool none = false)
993 : select(std::move(s))
994 , where(std::move(w))
995 , none(none) {};
996
1010 Query(std::string_view q_str)
1011 {
1012 auto pos_W = q_str.find("WHERE");
1013 auto pos_w = q_str.find("where");
1014 auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
1015 pos_w != std::string_view::npos ? pos_w : q_str.size());
1016 select = q_str.substr(0, pos);
1017 where = q_str.substr(pos, q_str.size() - pos);
1018 }
1019
1023 bool isSatisfiedBy(const Query& q) const;
1024
1025 template<typename Packer>
1026 void msgpack_pack(Packer& pk) const
1027 {
1028 pk.pack_map(2);
1029 pk.pack("s"sv);
1030 pk.pack(select); /* packing field selectors */
1031 pk.pack("w"sv);
1032 pk.pack(where); /* packing filters */
1033 }
1034
1035 void msgpack_unpack(const msgpack::object& o);
1036
1037 std::string toString() const
1038 {
1039 std::ostringstream ss;
1040 ss << *this;
1041 return ss.str();
1042 }
1043
1044 friend std::ostream& operator<<(std::ostream& s, const dht::Query& q)
1045 {
1046 return s << "Query[" << q.select << " " << q.where << "]";
1047 }
1048
1049 Select select {};
1050 Where where {};
1051 bool none {false}; /* When true, any query satisfies this. */
1052};
1053
1061struct OPENDHT_PUBLIC FieldValueIndex
1062{
1063 FieldValueIndex() {}
1064 FieldValueIndex(const Value& v, const Select& s = {});
1071 bool containedIn(const FieldValueIndex& other) const;
1072
1073 OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
1074
1075 void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
1076
1077 std::map<Value::Field, FieldValue> index {};
1078};
1079
1080template<typename T, typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1081Value::Filter
1082getFilterSet(Value::Filter f)
1083{
1084 return Value::Filter::chain({Value::TypeFilter(T::TYPE), T::getFilter(), std::move(f)});
1085}
1086
1087template<typename T, typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1089getFilterSet(Value::Filter f)
1090{
1091 return f;
1092}
1093
1094template<typename T, typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1096getFilterSet()
1097{
1098 return Value::Filter::chain({Value::TypeFilter(T::TYPE), T::getFilter()});
1099}
1100
1101template<typename T, typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
1103getFilterSet()
1104{
1105 return {};
1106}
1107
1108template<class T>
1109std::vector<T>
1110unpackVector(const std::vector<std::shared_ptr<Value>>& vals)
1111{
1112 std::vector<T> ret;
1113 ret.reserve(vals.size());
1114 for (const auto& v : vals) {
1115 try {
1116 ret.emplace_back(Value::unpack<T>(*v));
1117 } catch (const std::exception&) {
1118 }
1119 }
1120 return ret;
1121}
1122
1123#ifdef OPENDHT_JSONCPP
1124uint64_t unpackId(const Json::Value& json, const std::string& key);
1125#endif
1126
1127} // namespace dht
1128
1129MSGPACK_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:57
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:73
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object &o)
std::vector< uint8_t > Blob
Definition utils.h:156
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Definition value.h:697
Describes a query destined to another peer.
Definition value.h:988
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
Definition value.h:793
std::set< Value::Field > getSelection() const
Definition value.h:818
Select & field(Value::Field field)
Definition value.h:806
bool contentEquals(const Value &o) const
Definition value.h:468
bool checkSignature() const
Definition value.h:377
Blob cypher
Definition value.h:665
std::shared_ptr< crypto::PublicKey > owner
Definition value.h:632
uint16_t seq
Definition value.h:655
size_t size() const
InfoHash recipient
Definition value.h:639
Blob signature
Definition value.h:660
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
Blob getToSign() const
Definition value.h:485
OPENDHT_PUBLIC friend std::ostream & operator<<(std::ostream &s, const Value &v)
Blob getToEncrypt() const
Definition value.h:496
std::string user_type
Definition value.h:650
ValueType::Id type
Definition value.h:644
void sign(const crypto::PrivateKey &key)
unsigned priority
Definition value.h:672
Serializable dht::Value filter.
Definition value.h:850
Value::Filter getFilter() const
Definition value.h:938
Where && userType(std::string_view user_type)
Definition value.h:923
Where && seq(uint16_t seq_no)
Definition value.h:908
Where && id(Value::Id id)
Definition value.h:863
Where && valueType(ValueType::Id type)
Definition value.h:878
Where && owner(InfoHash owner_pk_hash)
Definition value.h:893