hproselet/hprose_srv.hpp

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