#include "tinypb_dispatcher.hpp" #include "logger.hpp" #include "tinypb_closure.hpp" #include "tinypb_controller.hpp" #include "tinypb_data.hpp" #include "error_code.hpp" #include #include namespace tinyrpc { TinypbDispatcher::TinypbDispatcher() {} TinypbDispatcher::~TinypbDispatcher() { } void TinypbDispatcher::dispatcher(ServerTcpConnection& conn, AbstractData& data, AbstractData& resp) { logger() << "dispatcher"; TinypbData& request = dynamic_cast(data); TinypbData& respond = dynamic_cast(resp); std::string service_name; std::string method_name; respond.service_full_name = request.service_full_name; respond.msg_req = request.msg_req; logger() << "request service_full_name:" << "[" << request.service_full_name << "]"; logger() << "request msg_req:" << "[" << request.msg_req << "]"; bool ret = parseServiceFullName(request.service_full_name, service_name, method_name); if(ret == false) { respond.err_code = ERROR_PARSE_SERVICE_NAME; std::stringstream ss; ss << "not found service_name:[" << service_name << "]"; respond.err_info = ss.str(); return; } logger() << "request method_name:" << "[" << method_name << "]"; auto it = m_service_map.find(service_name); if (it == m_service_map.end() || !(it->second)) { respond.err_code = ERROR_SERVICE_NOT_FOUND; std::stringstream ss; ss << "not found service_name:[" << service_name << "]"; respond.err_info = ss.str(); return; } std::shared_ptr service = it->second; const Method* method = service->GetDescriptor()->FindMethodByName(method_name); // const Method* method = nullptr; if(method == nullptr) { respond.err_code = ERROR_METHOD_NOT_FOUND; std::stringstream ss; ss << "not found service_name:[" << service_name << "]"; respond.err_info = ss.str(); return; } std::unique_ptr requestMsg (service->GetRequestPrototype(method).New()); ret = requestMsg->ParseFromString(request.pb_data); if(ret == false) { respond.err_code = ERROR_FAILED_SERIALIZE; std::stringstream ss; ss << "faild to parse request data, request.name:[" << requestMsg->GetDescriptor()->full_name() << "]"; respond.err_info = ss.str(); return; } std::unique_ptr respondMsg (service->GetResponsePrototype(method).New()); auto callback = [&respond, &respondMsg] { if(!respondMsg->SerializePartialToString(&respond.pb_data)) { respond.pb_data = ""; logger() << respond.msg_req << "|reply error! encode reply package error"; respond.err_code = ERROR_FAILED_SERIALIZE; respond.err_info = "failed to serilize relpy data"; } else { logger() << respond.msg_req << "|Set server response data:" << respondMsg->ShortDebugString(); } }; std::unique_ptr rpcController(new TinypbController); rpcController->SetMsgReq(respond.msg_req); rpcController->SetFullName(respond.service_full_name); rpcController->SetMethodName(method_name); TinypbClosure done(callback); service->CallMethod(method, rpcController.get(), requestMsg.get(), respondMsg.get(), &done /* callback */); } bool TinypbDispatcher::parseServiceFullName(const std::string& name, std::string& serviceName, std::string& methodName) { if(name.empty()) return false; auto pos = name.find("."); if(pos == std::string::npos) return false; serviceName = name.substr(0, pos); methodName = name.substr(pos + 1); // logger() << "serviceName=" << serviceName; // logger() << "methodName=" << methodName; return true; } void TinypbDispatcher::registerService(std::shared_ptr& service) { std::string service_name = service->GetDescriptor()->full_name(); m_service_map[service_name] = service; logger() << "success register service:" << "[" << service_name << "]"; } }