169 lines
6.0 KiB
C++
169 lines
6.0 KiB
C++
|
#ifndef _HPROSE_SRV_HPP_
|
||
|
#define _HPROSE_SRV_HPP_
|
||
|
|
||
|
#include <unordered_map>
|
||
|
#include <vector>
|
||
|
|
||
|
#include "hprose_ed.hpp"
|
||
|
#include "hprose_types.hpp"
|
||
|
|
||
|
template<typename RET>
|
||
|
struct Invoker {
|
||
|
template <typename OBJECT, typename HANDLER, typename... ARGS>
|
||
|
bool operator() (OBJECT* objs, HANDLER&& handler, HproseWriter& w, ARGS&... args) const {
|
||
|
return HproseValueHelper<RET>().ToWriterWithResultTag(handler(std::forward<ARGS&>(args)...), w);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<>
|
||
|
struct Invoker<void> {
|
||
|
template <typename OBJECT, typename HANDLER, typename... ARGS>
|
||
|
bool operator() (OBJECT* objs, HANDLER&& handler, HproseWriter& w, ARGS&... args) const {
|
||
|
handler(std::forward<ARGS&>(args)...);
|
||
|
return HproseValueHelperNull().ToWriterWithResultTag(w);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename RET>
|
||
|
struct InvokerObj {
|
||
|
template <typename OBJECT, typename HANDLER, typename... ARGS>
|
||
|
bool operator() (OBJECT* objs, HANDLER&& handler, HproseWriter& w, ARGS&... args) const {
|
||
|
return HproseValueHelper<RET>().ToWriterWithResultTag((*objs.*handler)(std::forward<ARGS&>(args)...), w);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<>
|
||
|
struct InvokerObj<void> {
|
||
|
template <typename OBJECT, typename HANDLER, typename... ARGS>
|
||
|
bool operator() (OBJECT* objs, HANDLER&& handler, HproseWriter& w, ARGS&... args) const {
|
||
|
(*objs.*handler)(std::forward<ARGS&>(args)...);
|
||
|
return HproseValueHelperNull().ToWriterWithResultTag(w);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
struct HandlerType {
|
||
|
using class_type = void;
|
||
|
using arg_helper = std::tuple<>;
|
||
|
using arg_type = std::tuple<>;
|
||
|
using invoke_type = void;
|
||
|
static constexpr int32_t arg_count = 0;
|
||
|
};
|
||
|
|
||
|
template<typename RET, typename... ARGS>
|
||
|
struct HandlerType<std::function<RET(ARGS...)>> {
|
||
|
using class_type = void;
|
||
|
using arg_type = std::tuple<std::remove_const_t<std::remove_reference_t<ARGS>>...>;
|
||
|
using invoke_type = Invoker<RET>;
|
||
|
using call_type = std::function<RET(ARGS...)>;
|
||
|
static constexpr int32_t arg_count = sizeof...(ARGS);
|
||
|
};
|
||
|
|
||
|
template<typename RET, typename CLASS, typename... ARGS>
|
||
|
struct HandlerType<RET(CLASS::*)(ARGS...)> {
|
||
|
using class_type = CLASS;
|
||
|
using arg_type = std::tuple<std::remove_const_t<std::remove_reference_t<ARGS>>...>;
|
||
|
using invoke_type = InvokerObj<RET>;
|
||
|
using call_type = RET(CLASS::*)(ARGS...);
|
||
|
static constexpr int32_t arg_count = sizeof...(ARGS);
|
||
|
};
|
||
|
|
||
|
template<typename RET, typename CLASS, typename... ARGS>
|
||
|
struct HandlerType<RET(CLASS::*)(ARGS...) const> {
|
||
|
using class_type = CLASS;
|
||
|
using arg_type = std::tuple<std::remove_const_t<std::remove_reference_t<ARGS>>...>;
|
||
|
using invoke_type = InvokerObj<RET>;
|
||
|
using call_type = RET(CLASS::*)(ARGS...) const;
|
||
|
static constexpr int32_t arg_count = sizeof...(ARGS);
|
||
|
};
|
||
|
|
||
|
template<typename OBJECT>
|
||
|
struct HproseInvoker {
|
||
|
virtual void Call(OBJECT* obj, HproseReader& r, HproseWriter& w) = 0;
|
||
|
virtual ~HproseInvoker() {};
|
||
|
};
|
||
|
|
||
|
template<typename HANDLER>
|
||
|
class HProseCallType : public HproseInvoker<typename HandlerType<typename FunctionType<HANDLER>::type>::class_type> {
|
||
|
public:
|
||
|
using handler_type = HandlerType<typename FunctionType<HANDLER>::type>;
|
||
|
using args_type = typename handler_type::arg_type;
|
||
|
|
||
|
HProseCallType(HANDLER h, const std::string& name) : handler(h), method(name) {}
|
||
|
|
||
|
virtual void Call(typename handler_type::class_type* obj, HproseReader& r, HproseWriter& w) {
|
||
|
args_type args;
|
||
|
if(r.CheckTag(Tags::List, false))
|
||
|
args = HproseValueHelper<args_type>().FromReader(r);
|
||
|
bool ref = r.CheckTag(Tags::True, true);
|
||
|
bool has_error = CallImpl(obj, args, w, std::make_index_sequence<handler_type::arg_count>{});
|
||
|
if(ref && handler_type::arg_count > 0 && !has_error) {
|
||
|
w.WriteTag(Tags::Argument);
|
||
|
HproseValueHelper<args_type>().ToWriter(args, w);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<size_t... I>
|
||
|
bool CallImpl(typename handler_type::class_type* obj, args_type& args, HproseWriter& w, std::index_sequence<I...>) {
|
||
|
return typename handler_type::invoke_type()(obj, handler, w, std::get<I>(args)...);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
HANDLER handler;
|
||
|
std::string method;
|
||
|
};
|
||
|
|
||
|
template<typename F>
|
||
|
std::unique_ptr<HProseCallType<F>> MakeHproseCallType(F f, const std::string& name) {
|
||
|
return std::unique_ptr<HProseCallType<F>>(new HProseCallType<F>(f, name));
|
||
|
}
|
||
|
|
||
|
template<typename OBJECT>
|
||
|
class HproseServer {
|
||
|
public:
|
||
|
template<typename HANDLER>
|
||
|
void Register(const char* name, HANDLER func) {
|
||
|
auto invoker = std::unique_ptr<HproseInvoker<OBJECT>>(MakeHproseCallType(func, name));
|
||
|
rpc_calls[name] = std::move(invoker);
|
||
|
}
|
||
|
|
||
|
void HandleRequests(OBJECT* sess, HproseReader& reader, HproseWriter& writer) {
|
||
|
auto tag = reader.ReadTag();
|
||
|
while(tag == Tags::Call) {
|
||
|
auto method = HproseValueHelperString().FromReader(reader);
|
||
|
auto iter = rpc_calls.find(method);
|
||
|
if(iter == rpc_calls.end()) {
|
||
|
HproseError err(std::move(std::string("Error: \"").append(method).append("\" not found.")));
|
||
|
HproseValueHelperError().ToWriterWithResultTag(err, writer);
|
||
|
reader.SkipValue();
|
||
|
reader.SkipValue();
|
||
|
tag = reader.ReadTag();
|
||
|
continue;
|
||
|
}
|
||
|
iter->second->Call(sess, reader, writer);
|
||
|
tag = reader.ReadTag();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename SVC>
|
||
|
void UseConnector(SVC& svc) {
|
||
|
svc.SetObjectAllocator([this]() -> std::shared_ptr<OBJECT> {
|
||
|
if(obj_allocator)
|
||
|
return obj_allocator();
|
||
|
return nullptr;
|
||
|
});
|
||
|
svc.SetPacketHandler([this](OBJECT* obj, HproseReader& reader, HproseWriter& writer) {
|
||
|
this->HandleRequests(obj, reader, writer);
|
||
|
});
|
||
|
svc.Start();
|
||
|
}
|
||
|
|
||
|
void SetObjectAllocator(const std::function<std::shared_ptr<OBJECT>()>& cb) { obj_allocator = cb; }
|
||
|
|
||
|
protected:
|
||
|
std::function<std::shared_ptr<OBJECT>()> obj_allocator;
|
||
|
std::unordered_map<std::string, std::unique_ptr<HproseInvoker<OBJECT>>> rpc_calls;
|
||
|
};
|
||
|
|
||
|
#endif
|