Compare commits
No commits in common. "yu" and "main" have entirely different histories.
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
bin/
|
||||
build/
|
||||
lib/
|
||||
protobuf/
|
||||
core*
|
@ -2,25 +2,18 @@ cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(tinyrpc)
|
||||
|
||||
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
enable_language(CXX ASM)
|
||||
|
||||
add_compile_options(-g -Wall)
|
||||
add_compile_options(-g -Wall -std=c++11)
|
||||
|
||||
include_directories(includes/coroutine)
|
||||
include_directories(includes/log)
|
||||
include_directories(includes/net)
|
||||
include_directories(includes/net/tcp)
|
||||
include_directories(includes/net/tinypb)
|
||||
|
||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src SRC_LIST)
|
||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src/coroutine COROUTINE_SRC_LIST)
|
||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src/net NET_SRC_LIST)
|
||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src/net/tcp TCP_SRC_LIST)
|
||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src/net/tinypb TINYPB_SRC_LIST)
|
||||
|
||||
|
||||
set(ASM_FILES ${CMAKE_SOURCE_DIR}/src/coroutine/coctx_swap.S)
|
||||
@ -32,11 +25,9 @@ set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
|
||||
|
||||
|
||||
add_library(tinyrpc
|
||||
# ${SRC_LIST}
|
||||
${COROUTINE_SRC_LIST}
|
||||
${TCP_SRC_LIST}
|
||||
${NET_SRC_LIST}
|
||||
${TINYPB_SRC_LIST}
|
||||
${ASM_FILES}
|
||||
)
|
||||
|
||||
@ -47,53 +38,5 @@ add_executable(test_tinyrpc
|
||||
${TEST_SRC_LIST}
|
||||
)
|
||||
|
||||
# 引入 abseil-cpp 子目录
|
||||
add_subdirectory(./third_party/abseil-cpp absl)
|
||||
|
||||
|
||||
set(ABSEL_LIBARARY
|
||||
absl::absl_check
|
||||
absl::absl_log
|
||||
absl::algorithm
|
||||
absl::base
|
||||
absl::bind_front
|
||||
absl::bits
|
||||
absl::btree
|
||||
absl::cleanup
|
||||
absl::cord
|
||||
absl::core_headers
|
||||
absl::debugging
|
||||
absl::die_if_null
|
||||
absl::dynamic_annotations
|
||||
absl::flags
|
||||
absl::flat_hash_map
|
||||
absl::flat_hash_set
|
||||
absl::function_ref
|
||||
absl::hash
|
||||
absl::layout
|
||||
absl::log_initialize
|
||||
absl::log_severity
|
||||
absl::memory
|
||||
absl::node_hash_map
|
||||
absl::node_hash_set
|
||||
absl::optional
|
||||
absl::span
|
||||
absl::status
|
||||
absl::statusor
|
||||
absl::strings
|
||||
absl::synchronization
|
||||
absl::time
|
||||
absl::type_traits
|
||||
absl::utility
|
||||
absl::variant
|
||||
)
|
||||
|
||||
|
||||
# 链接库
|
||||
target_link_libraries(tinyrpc PRIVATE protobuf) # 链接 Protobuf 库
|
||||
target_link_libraries(tinyrpc PRIVATE ${ABSEL_LIBARARY}) # 链接 Protobuf 库
|
||||
target_link_libraries(test_tinyrpc PRIVATE tinyrpc)
|
||||
|
||||
|
||||
|
||||
|
||||
target_link_libraries(test_tinyrpc PUBLIC stdc++)
|
@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_buffer.hpp"
|
||||
#include <cstdint>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
namespace tinyrpc {
|
||||
|
||||
struct AbstractData {
|
||||
AbstractData() = default;
|
||||
virtual ~AbstractData() = default;
|
||||
};
|
||||
|
||||
|
||||
class AbstractCoder {
|
||||
public:
|
||||
AbstractCoder() = default;
|
||||
virtual ~AbstractCoder() = default;
|
||||
|
||||
virtual bool encoder(TcpBuffer& buffer, AbstractData& data) = 0; // 编码
|
||||
|
||||
virtual bool decoder(TcpBuffer& buffer, AbstractData& data) = 0; // 解码
|
||||
|
||||
// virtual std::string getProtocalType() = 0;
|
||||
private:
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
inline int32_t getInt32FromNetByte(char& buf) {
|
||||
int32_t tmp;
|
||||
memcpy(&tmp, &buf, sizeof(tmp));
|
||||
return ntohl(tmp);
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "abstract_coder.hpp"
|
||||
#include "tcp_connection.hpp"
|
||||
|
||||
namespace tinyrpc {
|
||||
|
||||
|
||||
class AbstractDispatcher {
|
||||
public:
|
||||
AbstractDispatcher() = default;
|
||||
virtual ~AbstractDispatcher() = default;
|
||||
virtual void dispatcher(TcpConnection& conn, AbstractData& data, AbstractData& respond) = 0;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
};
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace tinyrpc {
|
||||
|
||||
enum ErrorCode {
|
||||
ERROR_PEER_CLOSED, // connect when peer close
|
||||
ERROR_FAILED_CONNECT, // failed to connection peer host
|
||||
ERROR_FAILED_GET_REPLY, // failed to get server reply
|
||||
ERROR_FAILED_DESERIALIZE, // deserialize failed
|
||||
ERROR_FAILED_SERIALIZE, // serialize failed
|
||||
|
||||
ERROR_FAILED_ENCODE, // encode failed
|
||||
ERROR_FAILED_DECODE, // decode failed
|
||||
|
||||
ERROR_RPC_CALL_TIMEOUT, // call rpc timeout
|
||||
|
||||
ERROR_SERVICE_NOT_FOUND, // not found service name
|
||||
|
||||
ERROR_METHOD_NOT_FOUND, // not found method
|
||||
|
||||
ERROR_PARSE_SERVICE_NAME, // not found service name
|
||||
ERROR_ASYNC_RPC_CALL_SINGLE_IOTHREAD, // not supoort async rpc call when only have single iothread
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "reactor.hpp"
|
||||
#include "tcp_connection.hpp"
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
@ -8,11 +9,11 @@
|
||||
#include <vector>
|
||||
|
||||
namespace tinyrpc {
|
||||
class TcpServer;
|
||||
|
||||
class IOThread {
|
||||
friend class IOThreadPool;
|
||||
public:
|
||||
void addClient(TcpServer* ser, int fd);
|
||||
void addClient(int fd);
|
||||
static IOThread* getThisIoThread();
|
||||
// void removeFd(int fd);
|
||||
Reactor* getReactor() {return m_reactor;}
|
||||
|
@ -1,13 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "abstract_coder.hpp"
|
||||
#include "coroutine.hpp"
|
||||
#include "fd_event.hpp"
|
||||
#include "reactor.hpp"
|
||||
#include "tcp_buffer.hpp"
|
||||
|
||||
namespace tinyrpc {
|
||||
class TcpServer;
|
||||
|
||||
class TcpConnection {
|
||||
public:
|
||||
enum class State{
|
||||
@ -17,7 +16,7 @@ namespace tinyrpc {
|
||||
|
||||
|
||||
public:
|
||||
TcpConnection(int fd, Reactor& reactor, TcpServer& ser);
|
||||
TcpConnection(int fd, Reactor* reactor);
|
||||
void clearClient();
|
||||
void mainLoopFun();
|
||||
|
||||
@ -35,8 +34,7 @@ namespace tinyrpc {
|
||||
State m_state{State::Connected};
|
||||
TcpBuffer m_writeBuffer{};
|
||||
TcpBuffer m_readBuffer{};
|
||||
Reactor& m_reactor;
|
||||
TcpServer& m_server;
|
||||
Reactor* m_reactor{};
|
||||
};
|
||||
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
#pragma once
|
||||
#include "abstract_coder.hpp"
|
||||
#include "abstract_dispatcher.hpp"
|
||||
#include "coroutine.hpp"
|
||||
#include "io_thread.hpp"
|
||||
#include "net_address.hpp"
|
||||
@ -24,10 +22,7 @@ namespace tinyrpc {
|
||||
TcpServer();
|
||||
TcpServer(const NetAddress& addr);
|
||||
TcpServer(const std::string& ip, uint16_t port);
|
||||
~TcpServer();
|
||||
void start();
|
||||
AbstractCoder& getCoder() {return *m_coder;}
|
||||
AbstractDispatcher& getDispatcher() {return *m_dispatcher;}
|
||||
private:
|
||||
void mainAcceptCorFun();
|
||||
private:
|
||||
@ -39,8 +34,6 @@ namespace tinyrpc {
|
||||
// int m_conn_cnt{0};
|
||||
// IOThread m_ioThread{};
|
||||
IOThreadPool m_ioThreadPool{4};
|
||||
AbstractCoder* m_coder{};
|
||||
AbstractDispatcher* m_dispatcher{};
|
||||
};
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "abstract_coder.hpp"
|
||||
namespace tinyrpc {
|
||||
|
||||
class TinypbCoder : public AbstractCoder {
|
||||
public:
|
||||
TinypbCoder();
|
||||
~TinypbCoder();
|
||||
bool encoder(TcpBuffer& buffer, AbstractData& data) override; // 编码
|
||||
bool decoder(TcpBuffer& buffer, AbstractData& data) override; // 解码
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "abstract_coder.hpp"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace tinyrpc {
|
||||
|
||||
struct TinypbData : public AbstractData {
|
||||
|
||||
TinypbData() {};
|
||||
~TinypbData() {};
|
||||
|
||||
// char start = 0x02; // indentify start of a TinyPb protocal data
|
||||
int32_t pk_len {0}; // len of all package(include start char and end char)
|
||||
int32_t msg_req_len {0}; // len of msg_req
|
||||
std::string msg_req; // msg_req, which identify a request
|
||||
int32_t service_name_len {0}; // len of service full name
|
||||
std::string service_full_name; // service full name, like QueryService.query_name
|
||||
int32_t err_code {0}; // err_code, 0 -- call rpc success, otherwise -- call rpc failed. it only be seted by RpcController
|
||||
int32_t err_info_len {0}; // len of err_info
|
||||
std::string err_info; // err_info, empty -- call rpc success, otherwise -- call rpc failed, it will display details of reason why call rpc failed. it only be seted by RpcController
|
||||
std::string pb_data; // business pb data
|
||||
int32_t check_num {-1}; // check_num of all package. to check legality of data
|
||||
// char end = 0x03; // identify end of a TinyPb protocal data
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "abstract_dispatcher.hpp"
|
||||
#include <unordered_map>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/service.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace tinyrpc {
|
||||
|
||||
class TinypbDispatcher : public AbstractDispatcher {
|
||||
using Service = google::protobuf::Service;
|
||||
using Method = google::protobuf::MethodDescriptor;
|
||||
using Message = google::protobuf::Message;
|
||||
public:
|
||||
TinypbDispatcher();
|
||||
~TinypbDispatcher();
|
||||
void dispatcher(TcpConnection& conn, AbstractData& data, AbstractData& respond) override;
|
||||
bool parseServiceFullName(const std::string& name, std::string& serviceName, std::string& methodName);
|
||||
private:
|
||||
std::unordered_map<std::string, Service*> m_service_map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
@ -275,5 +275,3 @@ namespace tinyrpc {
|
||||
t_reactor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "reactor.hpp"
|
||||
#include "coroutine.hpp"
|
||||
#include "tcp_connection.hpp"
|
||||
#include "tcp_server.hpp"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
@ -24,9 +23,9 @@ namespace tinyrpc {
|
||||
|
||||
|
||||
|
||||
void IOThread::addClient(TcpServer* ser, int fd) {
|
||||
void IOThread::addClient(int fd) {
|
||||
|
||||
m_clients[fd] = std::make_shared<TcpConnection>(fd, *m_reactor, *ser);
|
||||
m_clients[fd] = std::make_shared<TcpConnection>(fd, m_reactor);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,31 +1,26 @@
|
||||
#include "tcp_connection.hpp"
|
||||
#include "abstract_coder.hpp"
|
||||
#include "coroutine_hook.hpp"
|
||||
#include "fd_event.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "reactor.hpp"
|
||||
#include "tcp_server.hpp"
|
||||
#include "tinypb_data.hpp"
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace tinyrpc {
|
||||
TcpConnection::TcpConnection(int fd, Reactor& reactor, TcpServer& ser) :
|
||||
TcpConnection::TcpConnection(int fd, Reactor* reactor) :
|
||||
m_fdEvent(FdEventPool::getInstance()->getFdEvent(fd)),
|
||||
m_mainCoroutine(std::bind(&TcpConnection::mainLoopFun, this)),
|
||||
m_reactor(reactor),
|
||||
m_server(ser)
|
||||
m_reactor(reactor)
|
||||
{
|
||||
Reactor::Task task = [this] {
|
||||
logger() << "conn coroutine is resume";
|
||||
m_mainCoroutine.resume();
|
||||
};
|
||||
|
||||
reactor.addTask(task, true);
|
||||
reactor->addTask(task, true);
|
||||
|
||||
}
|
||||
|
||||
@ -41,7 +36,7 @@ namespace tinyrpc {
|
||||
void TcpConnection::clearClient() {
|
||||
logger() << "clearClient";
|
||||
m_state = State::Disconnected;
|
||||
m_reactor.delFdEvent(m_fdEvent);
|
||||
m_reactor->delFdEvent(m_fdEvent);
|
||||
m_fdEvent->reset();
|
||||
close(m_fdEvent->getFd());
|
||||
}
|
||||
@ -115,33 +110,17 @@ namespace tinyrpc {
|
||||
|
||||
void TcpConnection::process() {
|
||||
logger() << "process";
|
||||
// if(m_state == State::Disconnected) {
|
||||
// return;
|
||||
// }
|
||||
// if(m_writeBuffer.getWriteable() < m_readBuffer.getReadable()) {
|
||||
// m_writeBuffer.resize(m_readBuffer.getReadable() * 2);
|
||||
// }
|
||||
// std::memcpy(m_writeBuffer.getWriteAddress(), m_readBuffer.getReadAddress(), m_readBuffer.getReadable());
|
||||
// m_writeBuffer.writeOffset(m_readBuffer.getReadable());
|
||||
// m_readBuffer.readOffset(m_readBuffer.getReadable());
|
||||
|
||||
// logger() << "write data " << m_writeBuffer.getReadable() << " byte";
|
||||
|
||||
while(m_readBuffer.getReadable() > 0) {
|
||||
std::unique_ptr<AbstractData> data(new TinypbData);
|
||||
|
||||
bool ret = m_server.getCoder().decoder(m_readBuffer, *data);
|
||||
if(ret == false) {
|
||||
logger() << "decode error";
|
||||
break;
|
||||
}
|
||||
std::unique_ptr<AbstractData> resp(new TinypbData);
|
||||
m_server.getDispatcher().dispatcher(*this, *data, *resp);
|
||||
|
||||
m_server.getCoder().encoder(m_writeBuffer, *resp);
|
||||
|
||||
if(m_state == State::Disconnected) {
|
||||
return;
|
||||
}
|
||||
if(m_writeBuffer.getWriteable() < m_readBuffer.getReadable()) {
|
||||
m_writeBuffer.resize(m_readBuffer.getReadable() * 2);
|
||||
}
|
||||
std::memcpy(m_writeBuffer.getWriteAddress(), m_readBuffer.getReadAddress(), m_readBuffer.getReadable());
|
||||
m_writeBuffer.writeOffset(m_readBuffer.getReadable());
|
||||
m_readBuffer.readOffset(m_readBuffer.getReadable());
|
||||
|
||||
logger() << "write data " << m_writeBuffer.getReadable() << " byte";
|
||||
}
|
||||
|
||||
TcpConnection::~TcpConnection() {
|
||||
|
@ -5,8 +5,6 @@
|
||||
#include "coroutine_hook.hpp"
|
||||
#include "net_address.hpp"
|
||||
#include "reactor.hpp"
|
||||
#include "tinypb_coder.hpp"
|
||||
#include "tinypb_dispatcher.hpp"
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <netinet/in.h>
|
||||
@ -60,25 +58,21 @@ namespace tinyrpc {
|
||||
}
|
||||
|
||||
|
||||
|
||||
TcpServer::TcpServer() :
|
||||
m_accept_cor(std::bind(&TcpServer::mainAcceptCorFun, this)),
|
||||
m_acceptor(NetAddress())
|
||||
{
|
||||
m_acceptor.init();
|
||||
}
|
||||
TcpServer::TcpServer(const NetAddress& addr) :
|
||||
m_accept_cor(std::bind(&TcpServer::mainAcceptCorFun, this)),
|
||||
m_acceptor(addr),
|
||||
m_coder(new TinypbCoder),
|
||||
m_dispatcher(new TinypbDispatcher)
|
||||
m_acceptor(addr)
|
||||
{
|
||||
m_acceptor.init();
|
||||
}
|
||||
|
||||
TcpServer::TcpServer() :
|
||||
TcpServer(NetAddress("127.0.0.1", 9001)) {}
|
||||
TcpServer::TcpServer(const std::string& ip, uint16_t port) : TcpServer(NetAddress(ip, port)) {
|
||||
|
||||
TcpServer::TcpServer(const std::string& ip, uint16_t port) :
|
||||
TcpServer(NetAddress(ip, port)) {}
|
||||
|
||||
TcpServer::~TcpServer() {
|
||||
delete m_coder;
|
||||
delete m_dispatcher;
|
||||
}
|
||||
|
||||
void TcpServer::start() {
|
||||
@ -99,7 +93,7 @@ namespace tinyrpc {
|
||||
logger() << "new connect fd = " << fd;
|
||||
|
||||
logger() << " 添加 fd 到子 reactor 中 " << fd;
|
||||
m_ioThreadPool.getIOThread()->addClient(this, fd);
|
||||
m_ioThreadPool.getIOThread()->addClient(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,217 +0,0 @@
|
||||
#include "tinypb_coder.hpp"
|
||||
#include "abstract_coder.hpp"
|
||||
#include "tinypb_data.hpp"
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <netinet/in.h>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace tinyrpc {
|
||||
|
||||
static const char PB_START = 0x02; // start char
|
||||
static const char PB_END = 0x03; // end char
|
||||
// static const int MSG_REQ_LEN = 20; // default length of msg_req
|
||||
|
||||
TinypbCoder::TinypbCoder() {
|
||||
// TODO
|
||||
}
|
||||
TinypbCoder::~TinypbCoder() {
|
||||
// TODO
|
||||
}
|
||||
bool TinypbCoder::encoder(TcpBuffer& buffer, AbstractData& data) {
|
||||
TinypbData& pbdata = dynamic_cast<TinypbData&>(data);
|
||||
if(pbdata.msg_req.empty()) return false;
|
||||
if(pbdata.service_full_name.empty()) return false;
|
||||
if(pbdata.pb_data.empty()) return false;
|
||||
// TODO msg_req 处理
|
||||
|
||||
int32_t pk_len = 2 * sizeof(char) + 6 * sizeof(int32_t)
|
||||
+ pbdata.pb_data.length() + pbdata.service_full_name.length()
|
||||
+ pbdata.msg_req.length() + pbdata.err_info.length();
|
||||
|
||||
std::unique_ptr<char[]> buf(new char[pk_len + 1]{});
|
||||
|
||||
int cur_index = 0;
|
||||
buf[cur_index++] = PB_START;
|
||||
int32_t pk_len_net = htonl(pk_len);
|
||||
|
||||
memcpy(&buf[cur_index], &pk_len_net, sizeof(pk_len_net));
|
||||
cur_index += sizeof(pk_len_net);
|
||||
|
||||
int32_t msg_req_len = pbdata.msg_req.length();
|
||||
int32_t msg_req_len_net = htonl(msg_req_len);
|
||||
memcpy(&buf[cur_index], &msg_req_len_net, sizeof(msg_req_len_net));
|
||||
cur_index += sizeof(msg_req_len_net);
|
||||
memcpy(&buf[cur_index], pbdata.msg_req.c_str(), msg_req_len);
|
||||
cur_index += msg_req_len;
|
||||
|
||||
int32_t service_name_len = pbdata.service_full_name.length();
|
||||
int32_t service_name_len_net = htonl(service_name_len);
|
||||
memcpy(&buf[cur_index], &service_name_len_net, sizeof(service_name_len_net));
|
||||
cur_index += sizeof(service_name_len_net);
|
||||
memcpy(&buf[cur_index], pbdata.msg_req.c_str(), service_name_len);
|
||||
cur_index += service_name_len;
|
||||
|
||||
int32_t err_code = pbdata.err_code;
|
||||
int32_t err_code_net = htonl(err_code);
|
||||
memcpy(&buf[cur_index], &err_code_net, sizeof(err_code_net));
|
||||
cur_index += sizeof(err_code_net);
|
||||
|
||||
int32_t err_info_len = pbdata.err_info.length();
|
||||
int32_t err_info_len_net = htonl(err_info_len);
|
||||
memcpy(&buf[cur_index], &err_info_len_net, sizeof(err_info_len_net));
|
||||
cur_index += sizeof(err_info_len_net);
|
||||
memcpy(&buf[cur_index], pbdata.err_info.c_str(), err_info_len);
|
||||
cur_index += err_info_len;
|
||||
|
||||
int32_t pb_data_len = pbdata.err_info.length();
|
||||
memcpy(&buf[cur_index], pbdata.pb_data.c_str(), pb_data_len);
|
||||
cur_index += pb_data_len;
|
||||
|
||||
int32_t check_num = 1;
|
||||
int32_t check_num_net = htonl(check_num);
|
||||
memcpy(&buf[cur_index], &check_num_net, sizeof(check_num_net));
|
||||
cur_index += sizeof(check_num_net);
|
||||
|
||||
buf[cur_index++] = PB_END;
|
||||
|
||||
memcpy(buffer.getWriteAddress(), buf.get(), pk_len);
|
||||
buffer.writeOffset(pk_len);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool TinypbCoder::decoder(TcpBuffer& buffer, AbstractData& data) {
|
||||
|
||||
char* buff = static_cast<char*>(buffer.getReadAddress());
|
||||
|
||||
int start_index = -1;
|
||||
int end_index = -1;
|
||||
bool isFullPack = false;
|
||||
int pack_len = -1;
|
||||
|
||||
for(int i = 0; i < static_cast<int>(buffer.getReadable()); i++) {
|
||||
if(buff[i] == PB_START) {
|
||||
|
||||
if(i + 1 >= static_cast<int>(buffer.getReadable())) {
|
||||
return false; // 包不完整
|
||||
}
|
||||
|
||||
pack_len = getInt32FromNetByte(buff[i + 1]);
|
||||
end_index = pack_len + i - 1;
|
||||
|
||||
if(end_index >= static_cast<int>(buffer.getReadable())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(buff[end_index] == PB_END) {
|
||||
isFullPack = true;
|
||||
start_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(isFullPack == false) {
|
||||
return false; // 包不完整
|
||||
}
|
||||
|
||||
TinypbData& pbdata = dynamic_cast<TinypbData&>(data);
|
||||
pbdata.pk_len = pack_len;
|
||||
|
||||
int cur_index = start_index + sizeof(char) + sizeof(int32_t);
|
||||
|
||||
if (cur_index > end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pbdata.msg_req_len = getInt32FromNetByte(buff[cur_index]);
|
||||
cur_index = cur_index + sizeof(int32_t);
|
||||
|
||||
if (cur_index > end_index || cur_index + pbdata.msg_req_len - 1 > end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> msg_req(new char[pbdata.msg_req_len + 1]{});
|
||||
memcpy(&msg_req[0], &buff[cur_index], pbdata.msg_req_len);
|
||||
|
||||
pbdata.msg_req = std::string(msg_req.get());
|
||||
|
||||
cur_index = cur_index + pbdata.msg_req_len;
|
||||
|
||||
if (cur_index > end_index || cur_index + static_cast<int>(sizeof(int32_t)) - 1 > end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pbdata.service_name_len = getInt32FromNetByte(buff[cur_index]);
|
||||
|
||||
if (pbdata.service_name_len > pack_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_index = cur_index + sizeof(int32_t);
|
||||
|
||||
if (cur_index > end_index || cur_index + pbdata.service_name_len - 1 >end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> service_name(new char[pbdata.service_name_len + 1]{});
|
||||
memcpy(&service_name[0], &buff[cur_index], pbdata.service_name_len);
|
||||
|
||||
pbdata.service_full_name = std::string(service_name.get());
|
||||
|
||||
cur_index = cur_index + pbdata.service_name_len;
|
||||
|
||||
if(cur_index > end_index || cur_index + static_cast<int>(sizeof(int32_t)) - 1 > end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pbdata.err_code = getInt32FromNetByte(buff[cur_index]);
|
||||
|
||||
cur_index = cur_index + sizeof(int32_t);
|
||||
|
||||
if(cur_index > end_index || cur_index + static_cast<int>(sizeof(int32_t)) - 1 > end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pbdata.err_info_len = getInt32FromNetByte(buff[cur_index]);
|
||||
|
||||
cur_index = cur_index + sizeof(int32_t);
|
||||
|
||||
if(cur_index > end_index || cur_index + pbdata.err_info_len - 1 > end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> err_info(new char[pbdata.err_info_len + 1]{});
|
||||
|
||||
memcpy(&err_info[0], &buff[cur_index], pbdata.err_info_len);
|
||||
|
||||
pbdata.err_info = std::string(err_info.get());
|
||||
|
||||
int pb_data_len = pbdata.pk_len
|
||||
- pbdata.service_name_len - pbdata.msg_req_len - pbdata.err_info_len
|
||||
- 2 * sizeof(char) - 6 * sizeof(int32_t);
|
||||
|
||||
cur_index = cur_index + pbdata.err_info_len;
|
||||
|
||||
if(cur_index > end_index || cur_index + pb_data_len - 1 > end_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
pbdata.pb_data = std::string(&buff[cur_index], pb_data_len);
|
||||
cur_index += pb_data_len;
|
||||
|
||||
buffer.readOffset(cur_index - start_index);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,98 +0,0 @@
|
||||
#include "tinypb_dispatcher.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "tinypb_data.hpp"
|
||||
#include "error_code.hpp"
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace tinyrpc {
|
||||
TinypbDispatcher::TinypbDispatcher() {}
|
||||
|
||||
TinypbDispatcher::~TinypbDispatcher() {
|
||||
|
||||
}
|
||||
void TinypbDispatcher::dispatcher(TcpConnection& conn, AbstractData& data, AbstractData& resp) {
|
||||
logger() << "dispatcher";
|
||||
TinypbData& pbdata = dynamic_cast<TinypbData&>(data);
|
||||
TinypbData& respond = dynamic_cast<TinypbData&>(resp);
|
||||
std::string service_name;
|
||||
std::string method_name;
|
||||
|
||||
respond.service_full_name = pbdata.service_full_name;
|
||||
respond.msg_req = pbdata.msg_req;
|
||||
bool ret = parseServiceFullName(pbdata.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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
Service* 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<Message> requestMsg (service->GetRequestPrototype(method).New());
|
||||
|
||||
ret = requestMsg->ParseFromString(pbdata.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<Message> respondMsg (service->GetRequestPrototype(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();
|
||||
}
|
||||
};
|
||||
|
||||
service->CallMethod(method, nullptr, requestMsg.get(), respondMsg.get(), nullptr /* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package tutorial;
|
||||
|
||||
message Person {
|
||||
optional string name = 1;
|
||||
optional int32 id = 2;
|
||||
optional string email = 3;
|
||||
|
||||
enum PhoneType {
|
||||
PHONE_TYPE_UNSPECIFIED = 0;
|
||||
PHONE_TYPE_MOBILE = 1;
|
||||
PHONE_TYPE_HOME = 2;
|
||||
PHONE_TYPE_WORK = 3;
|
||||
}
|
||||
|
||||
message PhoneNumber {
|
||||
optional string number = 1;
|
||||
optional PhoneType type = 2 [default = PHONE_TYPE_HOME];
|
||||
}
|
||||
|
||||
repeated PhoneNumber phones = 4;
|
||||
}
|
||||
|
||||
message AddressBook {
|
||||
repeated Person people = 1;
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "addressbook.pb.h"
|
||||
using namespace std;
|
||||
|
||||
// This function fills in a Person message based on user input.
|
||||
void PromptForAddress(tutorial::Person* person) {
|
||||
cout << "Enter person ID number: ";
|
||||
int id;
|
||||
cin >> id;
|
||||
person->set_id(id);
|
||||
cin.ignore(256, '\n');
|
||||
|
||||
cout << "Enter name: ";
|
||||
getline(cin, *person->mutable_name());
|
||||
|
||||
cout << "Enter email address (blank for none): ";
|
||||
string email;
|
||||
getline(cin, email);
|
||||
if (!email.empty()) {
|
||||
person->set_email(email);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
cout << "Enter a phone number (or leave blank to finish): ";
|
||||
string number;
|
||||
getline(cin, number);
|
||||
if (number.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
tutorial::Person::PhoneNumber* phone_number = person->add_phones();
|
||||
phone_number->set_number(number);
|
||||
|
||||
cout << "Is this a mobile, home, or work phone? ";
|
||||
string type;
|
||||
getline(cin, type);
|
||||
if (type == "mobile") {
|
||||
phone_number->set_type(tutorial::Person::PHONE_TYPE_MOBILE);
|
||||
} else if (type == "home") {
|
||||
phone_number->set_type(tutorial::Person::PHONE_TYPE_HOME);
|
||||
} else if (type == "work") {
|
||||
phone_number->set_type(tutorial::Person::PHONE_TYPE_WORK);
|
||||
} else {
|
||||
cout << "Unknown phone type. Using default." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main function: Reads the entire address book from a file,
|
||||
// adds one person based on user input, then writes it back out to the same
|
||||
// file.
|
||||
int main(int argc, char* argv[]) {
|
||||
// Verify that the version of the library that we linked against is
|
||||
// compatible with the version of the headers we compiled against.
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
if (argc != 2) {
|
||||
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tutorial::AddressBook address_book;
|
||||
|
||||
{
|
||||
// Read the existing address book.
|
||||
fstream input(argv[1], ios::in | ios::binary);
|
||||
if (!input) {
|
||||
cout << argv[1] << ": File not found. Creating a new file." << endl;
|
||||
} else if (!address_book.ParseFromIstream(&input)) {
|
||||
cerr << "Failed to parse address book." << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add an address.
|
||||
PromptForAddress(address_book.add_people());
|
||||
|
||||
{
|
||||
// Write the new address book back to disk.
|
||||
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
|
||||
if (!address_book.SerializeToOstream(&output)) {
|
||||
cerr << "Failed to write address book." << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Delete all global objects allocated by libprotobuf.
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
1
third_party/abseil-cpp
vendored
1
third_party/abseil-cpp
vendored
@ -1 +0,0 @@
|
||||
Subproject commit d7aaad83b488fd62bd51c81ecf16cd938532cc0a
|
Loading…
Reference in New Issue
Block a user