if(header.length>size)
throw bad_packet("truncated");
const PacketDefBase &pdef = get_packet_by_id(header.type-base_id);
- ptr = pdef.dispatch(rcv, ptr, ptr+header.length);
+ if(DynamicReceiver *drcv = dynamic_cast<DynamicReceiver *>(&rcv))
+ {
+ Variant pkt;
+ ptr = pdef.deserialize(pkt, ptr, ptr+header.length);
+ drcv->receive(pdef.get_id(), pkt);
+ }
+ else
+ ptr = pdef.dispatch(rcv, ptr, ptr+header.length);
return ptr-buf;
}
virtual unsigned get_class_id() const = 0;
unsigned get_id() const { return id; }
virtual std::uint64_t get_hash() const = 0;
+ virtual const char *deserialize(Variant &, const char *, const char *) const = 0;
virtual const char *dispatch(ReceiverBase &, const char *, const char *) const = 0;
};
std::uint64_t get_hash() const override { return serializer->get_hash(); }
char *serialize(const P &, char *, char *) const;
const char *deserialize(P &, const char *, const char *) const;
+ const char *deserialize(Variant &, const char *, const char *) const override;
const char *dispatch(ReceiverBase &, const char *, const char *) const override;
};
return serializer->deserialize(pkt, buf, end);
}
+template<typename P>
+const char *Protocol::PacketTypeDef<P>::deserialize(Variant &var_pkt, const char *buf, const char *end) const
+{
+ P pkt;
+ const char *ptr = serializer->deserialize(pkt, buf, end);
+ var_pkt = std::move(pkt);
+ return ptr;
+}
+
template<typename P>
const char *Protocol::PacketTypeDef<P>::dispatch(ReceiverBase &rcv, const char *buf, const char *end) const
{
--- /dev/null
+#include "receiver.h"
+
+namespace Msp {
+namespace Net {
+
+void DynamicDispatcher::receive(unsigned packet_id, const Variant &packet)
+{
+ auto i = lower_bound_member(targets, packet_id, &Target::packet_id);
+ if(i==targets.end() || i->packet_id!=packet_id)
+ throw key_error(packet_id);
+
+ i->func(*i->receiver, packet);
+}
+
+} // namespace Net
+} // namespace Msp
#ifndef MSP_NET_RECEIVER_H_
#define MSP_NET_RECEIVER_H_
+#include <vector>
+#include <msp/core/algorithm.h>
+#include <msp/core/maputils.h>
+#include <msp/core/variant.h>
#include "mspnet_api.h"
namespace Msp {
virtual ~ReceiverBase() = default;
};
+
template<typename P>
class PacketReceiver: public virtual ReceiverBase
{
virtual void receive(const P &) = 0;
};
+
+class MSPNET_API DynamicReceiver: public ReceiverBase
+{
+protected:
+ DynamicReceiver() = default;
+public:
+ virtual void receive(unsigned, const Variant &) = 0;
+};
+
+
+class MSPNET_API DynamicDispatcher: public DynamicReceiver
+{
+private:
+ using DispatchFunc = void(ReceiverBase &, const Variant &);
+
+ struct Target
+ {
+ unsigned packet_id;
+ ReceiverBase *receiver;
+ DispatchFunc *func;
+
+ Target(unsigned i, ReceiverBase &r, DispatchFunc *f): packet_id(i), receiver(&r), func(f) { }
+ };
+
+ std::vector<Target> targets;
+
+public:
+ template<typename P>
+ void add_receiver(unsigned, PacketReceiver<P> &);
+
+ void receive(unsigned, const Variant &) override;
+};
+
+
+template<typename P>
+void DynamicDispatcher::add_receiver(unsigned packet_id, PacketReceiver<P> &r)
+{
+ auto i = lower_bound_member(targets, packet_id, &Target::packet_id);
+ if(i!=targets.end() && i->packet_id==packet_id)
+ throw key_error(packet_id);
+
+ auto dispatch = [](ReceiverBase &receiver, const Variant &packet){
+ dynamic_cast<PacketReceiver<P> &>(receiver).receive(packet.value<P>());
+ };
+
+ targets.emplace(i, packet_id, r, +dispatch);
+}
+
} // namespace Net
} // namespace Msp