Skip to content
Snippets Groups Projects
Commit 1a888dbe authored by Guillaume Roguez's avatar Guillaume Roguez
Browse files

Fix RCTP multi-inheriting in Serialized and derived classes

This patch fixes Serialized derived classes, using CRTP idom,
by fixing the "constructor forwarding problem".

A derived class has no to use dht::Value::Serialized<Derived, Base>
as super class, by replacing itself in "Derived" and use the
right "Base" class. Ex:

class MyImMessage : public dht::Value::Serializable<MyImMessage, dht::ImMessage>
{
  ...
}

No more needed to overload getType and define TYPE static.
parent 94bfc677
Branches
Tags
No related merge requests found
......@@ -23,18 +23,17 @@
namespace dht {
struct DhtMessage : public Value::Serializable<DhtMessage>
class DhtMessage : public Value::Serializable<DhtMessage>
{
public:
static const ValueType TYPE;
DhtMessage(std::string s = {}, Blob msg = {}) : service(s), data(msg) {}
std::string getService() const {
return service;
}
static const ValueType TYPE;
virtual const ValueType& getType() const override {
return TYPE;
}
static Value::Filter getFilter() { return {}; }
static bool storePolicy(InfoHash key, std::shared_ptr<Value>& value, InfoHash from, const sockaddr* from_addr, socklen_t from_len);
......@@ -44,57 +43,64 @@ struct DhtMessage : public Value::Serializable<DhtMessage>
/** print value for debugging */
friend std::ostream& operator<< (std::ostream&, const DhtMessage&);
public:
std::string service;
Blob data;
MSGPACK_DEFINE(service, data);
};
template <typename Type>
struct SignedValue : public Value::Serializable<Type>
template <typename T>
class SignedValue : public Value::Serializable<T>
{
private:
using BaseClass = Value::Serializable<T>;
public:
virtual void unpackValue(const Value& v) override {
from = v.owner.getId();
Value::Serializable<Type>::unpackValue(v);
BaseClass::unpackValue(v);
}
static Value::Filter getFilter() {
return [](const Value& v){ return v.isSigned(); };
}
public:
dht::InfoHash from;
};
template <typename Type>
struct EncryptedValue : public SignedValue<Type>
template <typename T>
class EncryptedValue : public SignedValue<T>
{
public:
using BaseClass = SignedValue<T>;
public:
virtual void unpackValue(const Value& v) override {
to = v.recipient;
SignedValue<Type>::unpackValue(v);
BaseClass::unpackValue(v);
}
static Value::Filter getFilter() {
return Value::Filter::chain(
SignedValue<Type>::getFilter(),
BaseClass::getFilter(),
[](const Value& v){ return v.recipient != InfoHash(); }
);
}
public:
dht::InfoHash to;
};
struct ImMessage : public SignedValue<ImMessage>
class ImMessage : public SignedValue<ImMessage>
{
private:
using BaseClass = SignedValue<ImMessage>;
public:
static const ValueType TYPE;
ImMessage() {}
ImMessage(dht::Value::Id id, std::string&& m, long d = 0)
: id(id), msg(std::move(m)), date(d) {}
static const ValueType TYPE;
virtual const ValueType& getType() const override {
return TYPE;
}
static Value::Filter getFilter() {
return SignedValue::getFilter();
}
virtual void unpackValue(const Value& v) override {
to = v.recipient;
SignedValue::unpackValue(v);
......@@ -103,20 +109,22 @@ struct ImMessage : public SignedValue<ImMessage>
dht::InfoHash to;
dht::Value::Id id;
std::string msg;
long date;
long date {0};
MSGPACK_DEFINE_MAP(id, msg, date);
};
struct TrustRequest : public EncryptedValue<TrustRequest>
class TrustRequest : public EncryptedValue<TrustRequest>
{
private:
using BaseClass = EncryptedValue<TrustRequest>;
public:
static const ValueType TYPE;
TrustRequest() {}
TrustRequest(std::string s) : service(s) {}
TrustRequest(std::string s, const Blob& d) : service(s), payload(d) {}
static const ValueType TYPE;
virtual const ValueType& getType() const override {
return TYPE;
}
static Value::Filter getFilter() {
return EncryptedValue::getFilter();
}
......@@ -126,15 +134,17 @@ struct TrustRequest : public EncryptedValue<TrustRequest>
MSGPACK_DEFINE(service, payload);
};
struct IceCandidates : public EncryptedValue<IceCandidates>
class IceCandidates : public EncryptedValue<IceCandidates>
{
private:
using BaseClass = EncryptedValue<IceCandidates>;
public:
static const ValueType TYPE;
IceCandidates() {}
IceCandidates(Value::Id msg_id, Blob ice) : id(msg_id), ice_data(ice) {}
static const ValueType TYPE;
virtual const ValueType& getType() const override {
return TYPE;
}
static Value::Filter getFilter() {
return EncryptedValue::getFilter();
}
......@@ -168,11 +178,16 @@ struct IceCandidates : public EncryptedValue<IceCandidates>
Blob ice_data;
};
/* "Peer" announcement
*/
struct IpServiceAnnouncement : public Value::Serializable<IpServiceAnnouncement>
class IpServiceAnnouncement : public Value::Serializable<IpServiceAnnouncement>
{
private:
using BaseClass = Value::Serializable<IpServiceAnnouncement>;
public:
static const ValueType TYPE;
IpServiceAnnouncement(in_port_t p = 0) {
ss.ss_family = 0;
setPort(p);
......@@ -226,7 +241,6 @@ struct IpServiceAnnouncement : public Value::Serializable<IpServiceAnnouncement>
return ss;
}
static const ValueType TYPE;
virtual const ValueType& getType() const {
return TYPE;
}
......
......@@ -175,38 +175,52 @@ struct Value
};
}
template <typename T>
struct Serializable
class SerializableBase
{
public:
SerializableBase() {}
virtual ~SerializableBase() {};
virtual const ValueType& getType() const = 0;
virtual void unpackValue(const Value& v) = 0;
virtual Value packValue() const = 0;
};
template <typename Derived, typename Base=SerializableBase>
class Serializable : public Base
{
public:
using Base::Base;
virtual const ValueType& getType() const {
return Derived::TYPE;
}
virtual void unpackValue(const Value& v) {
auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
msgpack::object obj = msg.get();
obj.convert(static_cast<T*>(this));
msg.get().convert(static_cast<Derived*>(this));
}
virtual Value packValue() const {
return Value {getType(), static_cast<const T&>(*this)};
return Value {getType(), static_cast<const Derived&>(*this)};
}
virtual ~Serializable() = default;
};
template <typename T,
typename std::enable_if<std::is_base_of<Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
static Value pack(const T& obj)
{
return obj.packValue();
}
template <typename T,
typename std::enable_if<!std::is_base_of<Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
static Value pack(const T& obj)
{
return {ValueType::USER_DATA.id, packMsg<T>(obj)};
}
template <typename T,
typename std::enable_if<std::is_base_of<Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
static T unpack(const Value& v)
{
T msg;
......@@ -215,7 +229,7 @@ struct Value
}
template <typename T,
typename std::enable_if<!std::is_base_of<Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
static T unpack(const Value& v)
{
return unpackMsg<T>(v.data);
......@@ -405,7 +419,7 @@ struct Value
};
template <typename T,
typename std::enable_if<std::is_base_of<Value::Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
Value::Filter
getFilterSet(Value::Filter f)
{
......@@ -417,7 +431,7 @@ getFilterSet(Value::Filter f)
}
template <typename T,
typename std::enable_if<!std::is_base_of<Value::Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
Value::Filter
getFilterSet(Value::Filter f)
{
......@@ -425,7 +439,7 @@ getFilterSet(Value::Filter f)
}
template <typename T,
typename std::enable_if<std::is_base_of<Value::Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
Value::Filter
getFilterSet()
{
......@@ -436,7 +450,7 @@ getFilterSet()
}
template <typename T,
typename std::enable_if<!std::is_base_of<Value::Serializable<T>, T>::value, T>::type* = nullptr>
typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
Value::Filter
getFilterSet()
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment