临时保存
This commit is contained in:
parent
21c2b81ac6
commit
df8789f6c6
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
bin/
|
bin/
|
||||||
build/
|
build/
|
||||||
lib/
|
lib/
|
||||||
core*
|
protobuf/
|
@ -2,18 +2,22 @@ cmake_minimum_required(VERSION 3.0)
|
|||||||
|
|
||||||
project(tinyrpc)
|
project(tinyrpc)
|
||||||
|
|
||||||
|
# set(CMAKE_CXX_STANDARD 14)
|
||||||
|
|
||||||
enable_language(CXX ASM)
|
enable_language(CXX ASM)
|
||||||
|
|
||||||
add_compile_options(-g -Wall -std=c++11)
|
add_compile_options(-g -Wall -std=c++17)
|
||||||
|
|
||||||
include_directories(includes/coroutine)
|
include_directories(includes/coroutine)
|
||||||
include_directories(includes/log)
|
include_directories(includes/log)
|
||||||
include_directories(includes/net)
|
include_directories(includes/net)
|
||||||
include_directories(includes/net/tcp)
|
include_directories(includes/net/tcp)
|
||||||
|
include_directories(includes/net/tinypb)
|
||||||
|
|
||||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src/coroutine COROUTINE_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 NET_SRC_LIST)
|
||||||
aux_source_directory(${CMAKE_SOURCE_DIR}/src/net/tcp TCP_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)
|
set(ASM_FILES ${CMAKE_SOURCE_DIR}/src/coroutine/coctx_swap.S)
|
||||||
@ -28,6 +32,7 @@ add_library(tinyrpc
|
|||||||
${COROUTINE_SRC_LIST}
|
${COROUTINE_SRC_LIST}
|
||||||
${TCP_SRC_LIST}
|
${TCP_SRC_LIST}
|
||||||
${NET_SRC_LIST}
|
${NET_SRC_LIST}
|
||||||
|
${TINYPB_SRC_LIST}
|
||||||
${ASM_FILES}
|
${ASM_FILES}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,4 +44,5 @@ add_executable(test_tinyrpc
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(test_tinyrpc PRIVATE tinyrpc)
|
target_link_libraries(test_tinyrpc PRIVATE tinyrpc)
|
||||||
target_link_libraries(test_tinyrpc PUBLIC stdc++)
|
target_link_libraries(test_tinyrpc PUBLIC protobuf)
|
||||||
|
target_link_libraries(test_tinyrpc PUBLIC stdc++)
|
||||||
|
38
includes/net/abstract_coder.hpp
Normal file
38
includes/net/abstract_coder.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
includes/net/abstract_dispatcher.hpp
Normal file
20
includes/net/abstract_dispatcher.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#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:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
26
includes/net/error_code.hpp
Normal file
26
includes/net/error_code.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#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,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "reactor.hpp"
|
#include "reactor.hpp"
|
||||||
#include "tcp_connection.hpp"
|
#include "tcp_connection.hpp"
|
||||||
#include <atomic>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -9,11 +8,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace tinyrpc {
|
namespace tinyrpc {
|
||||||
|
class TcpServer;
|
||||||
class IOThread {
|
class IOThread {
|
||||||
friend class IOThreadPool;
|
friend class IOThreadPool;
|
||||||
public:
|
public:
|
||||||
void addClient(int fd);
|
void addClient(TcpServer* ser, int fd);
|
||||||
static IOThread* getThisIoThread();
|
static IOThread* getThisIoThread();
|
||||||
// void removeFd(int fd);
|
// void removeFd(int fd);
|
||||||
Reactor* getReactor() {return m_reactor;}
|
Reactor* getReactor() {return m_reactor;}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "abstract_coder.hpp"
|
||||||
#include "coroutine.hpp"
|
#include "coroutine.hpp"
|
||||||
#include "fd_event.hpp"
|
#include "fd_event.hpp"
|
||||||
#include "reactor.hpp"
|
#include "reactor.hpp"
|
||||||
#include "tcp_buffer.hpp"
|
#include "tcp_buffer.hpp"
|
||||||
|
|
||||||
namespace tinyrpc {
|
namespace tinyrpc {
|
||||||
|
class TcpServer;
|
||||||
class TcpConnection {
|
class TcpConnection {
|
||||||
public:
|
public:
|
||||||
enum class State{
|
enum class State{
|
||||||
@ -14,9 +15,9 @@ namespace tinyrpc {
|
|||||||
Connected
|
Connected
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TcpConnection(int fd, Reactor* reactor);
|
TcpConnection(int fd, Reactor& reactor, TcpServer& ser);
|
||||||
void clearClient();
|
void clearClient();
|
||||||
void mainLoopFun();
|
void mainLoopFun();
|
||||||
|
|
||||||
@ -34,7 +35,8 @@ namespace tinyrpc {
|
|||||||
State m_state{State::Connected};
|
State m_state{State::Connected};
|
||||||
TcpBuffer m_writeBuffer{};
|
TcpBuffer m_writeBuffer{};
|
||||||
TcpBuffer m_readBuffer{};
|
TcpBuffer m_readBuffer{};
|
||||||
Reactor* m_reactor{};
|
Reactor& m_reactor;
|
||||||
|
TcpServer& m_server;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "abstract_coder.hpp"
|
||||||
|
#include "abstract_dispatcher.hpp"
|
||||||
#include "coroutine.hpp"
|
#include "coroutine.hpp"
|
||||||
#include "io_thread.hpp"
|
#include "io_thread.hpp"
|
||||||
#include "net_address.hpp"
|
#include "net_address.hpp"
|
||||||
@ -22,7 +24,10 @@ namespace tinyrpc {
|
|||||||
TcpServer();
|
TcpServer();
|
||||||
TcpServer(const NetAddress& addr);
|
TcpServer(const NetAddress& addr);
|
||||||
TcpServer(const std::string& ip, uint16_t port);
|
TcpServer(const std::string& ip, uint16_t port);
|
||||||
|
~TcpServer();
|
||||||
void start();
|
void start();
|
||||||
|
AbstractCoder& getCoder() {return *m_coder;}
|
||||||
|
AbstractDispatcher& getDispatcher() {return *m_dispatcher;}
|
||||||
private:
|
private:
|
||||||
void mainAcceptCorFun();
|
void mainAcceptCorFun();
|
||||||
private:
|
private:
|
||||||
@ -34,6 +39,8 @@ namespace tinyrpc {
|
|||||||
// int m_conn_cnt{0};
|
// int m_conn_cnt{0};
|
||||||
// IOThread m_ioThread{};
|
// IOThread m_ioThread{};
|
||||||
IOThreadPool m_ioThreadPool{4};
|
IOThreadPool m_ioThreadPool{4};
|
||||||
|
AbstractCoder* m_coder{};
|
||||||
|
AbstractDispatcher* m_dispatcher{};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
19
includes/net/tinypb/tinypb_coder.hpp
Normal file
19
includes/net/tinypb/tinypb_coder.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#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:
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
31
includes/net/tinypb/tinypb_data.hpp
Normal file
31
includes/net/tinypb/tinypb_data.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
25
includes/net/tinypb/tinypb_dispatcher.hpp
Normal file
25
includes/net/tinypb/tinypb_dispatcher.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#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;
|
||||||
|
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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
#include "reactor.hpp"
|
#include "reactor.hpp"
|
||||||
#include "coroutine.hpp"
|
#include "coroutine.hpp"
|
||||||
#include "tcp_connection.hpp"
|
#include "tcp_connection.hpp"
|
||||||
|
#include "tcp_server.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -23,9 +24,9 @@ namespace tinyrpc {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void IOThread::addClient(int fd) {
|
void IOThread::addClient(TcpServer* ser, int fd) {
|
||||||
|
|
||||||
m_clients[fd] = std::make_shared<TcpConnection>(fd, m_reactor);
|
m_clients[fd] = std::make_shared<TcpConnection>(fd, *m_reactor, *ser);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,31 @@
|
|||||||
#include "tcp_connection.hpp"
|
#include "tcp_connection.hpp"
|
||||||
|
#include "abstract_coder.hpp"
|
||||||
#include "coroutine_hook.hpp"
|
#include "coroutine_hook.hpp"
|
||||||
#include "fd_event.hpp"
|
#include "fd_event.hpp"
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
#include "reactor.hpp"
|
#include "reactor.hpp"
|
||||||
|
#include "tcp_server.hpp"
|
||||||
|
#include "tinypb_data.hpp"
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
namespace tinyrpc {
|
namespace tinyrpc {
|
||||||
TcpConnection::TcpConnection(int fd, Reactor* reactor) :
|
TcpConnection::TcpConnection(int fd, Reactor& reactor, TcpServer& ser) :
|
||||||
m_fdEvent(FdEventPool::getInstance()->getFdEvent(fd)),
|
m_fdEvent(FdEventPool::getInstance()->getFdEvent(fd)),
|
||||||
m_mainCoroutine(std::bind(&TcpConnection::mainLoopFun, this)),
|
m_mainCoroutine(std::bind(&TcpConnection::mainLoopFun, this)),
|
||||||
m_reactor(reactor)
|
m_reactor(reactor),
|
||||||
|
m_server(ser)
|
||||||
{
|
{
|
||||||
Reactor::Task task = [this] {
|
Reactor::Task task = [this] {
|
||||||
logger() << "conn coroutine is resume";
|
logger() << "conn coroutine is resume";
|
||||||
m_mainCoroutine.resume();
|
m_mainCoroutine.resume();
|
||||||
};
|
};
|
||||||
|
|
||||||
reactor->addTask(task, true);
|
reactor.addTask(task, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +41,7 @@ namespace tinyrpc {
|
|||||||
void TcpConnection::clearClient() {
|
void TcpConnection::clearClient() {
|
||||||
logger() << "clearClient";
|
logger() << "clearClient";
|
||||||
m_state = State::Disconnected;
|
m_state = State::Disconnected;
|
||||||
m_reactor->delFdEvent(m_fdEvent);
|
m_reactor.delFdEvent(m_fdEvent);
|
||||||
m_fdEvent->reset();
|
m_fdEvent->reset();
|
||||||
close(m_fdEvent->getFd());
|
close(m_fdEvent->getFd());
|
||||||
}
|
}
|
||||||
@ -110,17 +115,31 @@ namespace tinyrpc {
|
|||||||
|
|
||||||
void TcpConnection::process() {
|
void TcpConnection::process() {
|
||||||
logger() << "process";
|
logger() << "process";
|
||||||
if(m_state == State::Disconnected) {
|
// if(m_state == State::Disconnected) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
if(m_writeBuffer.getWriteable() < m_readBuffer.getReadable()) {
|
// if(m_writeBuffer.getWriteable() < m_readBuffer.getReadable()) {
|
||||||
m_writeBuffer.resize(m_readBuffer.getReadable() * 2);
|
// m_writeBuffer.resize(m_readBuffer.getReadable() * 2);
|
||||||
}
|
// }
|
||||||
std::memcpy(m_writeBuffer.getWriteAddress(), m_readBuffer.getReadAddress(), m_readBuffer.getReadable());
|
// std::memcpy(m_writeBuffer.getWriteAddress(), m_readBuffer.getReadAddress(), m_readBuffer.getReadable());
|
||||||
m_writeBuffer.writeOffset(m_readBuffer.getReadable());
|
// m_writeBuffer.writeOffset(m_readBuffer.getReadable());
|
||||||
m_readBuffer.readOffset(m_readBuffer.getReadable());
|
// m_readBuffer.readOffset(m_readBuffer.getReadable());
|
||||||
|
|
||||||
logger() << "write data " << m_writeBuffer.getReadable() << " byte";
|
// 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TcpConnection::~TcpConnection() {
|
TcpConnection::~TcpConnection() {
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "coroutine_hook.hpp"
|
#include "coroutine_hook.hpp"
|
||||||
#include "net_address.hpp"
|
#include "net_address.hpp"
|
||||||
#include "reactor.hpp"
|
#include "reactor.hpp"
|
||||||
|
#include "tinypb_coder.hpp"
|
||||||
|
#include "tinypb_dispatcher.hpp"
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -58,21 +60,25 @@ namespace tinyrpc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TcpServer::TcpServer() :
|
|
||||||
m_accept_cor(std::bind(&TcpServer::mainAcceptCorFun, this)),
|
|
||||||
m_acceptor(NetAddress())
|
|
||||||
{
|
|
||||||
m_acceptor.init();
|
|
||||||
}
|
|
||||||
TcpServer::TcpServer(const NetAddress& addr) :
|
TcpServer::TcpServer(const NetAddress& addr) :
|
||||||
m_accept_cor(std::bind(&TcpServer::mainAcceptCorFun, this)),
|
m_accept_cor(std::bind(&TcpServer::mainAcceptCorFun, this)),
|
||||||
m_acceptor(addr)
|
m_acceptor(addr),
|
||||||
|
m_coder(new TinypbCoder),
|
||||||
|
m_dispatcher(new TinypbDispatcher)
|
||||||
{
|
{
|
||||||
m_acceptor.init();
|
m_acceptor.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
TcpServer::TcpServer(const std::string& ip, uint16_t port) : TcpServer(NetAddress(ip, port)) {
|
TcpServer::TcpServer() :
|
||||||
|
TcpServer(NetAddress("127.0.0.1", 9001)) {}
|
||||||
|
|
||||||
|
TcpServer::TcpServer(const std::string& ip, uint16_t port) :
|
||||||
|
TcpServer(NetAddress(ip, port)) {}
|
||||||
|
|
||||||
|
TcpServer::~TcpServer() {
|
||||||
|
delete m_coder;
|
||||||
|
delete m_dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpServer::start() {
|
void TcpServer::start() {
|
||||||
@ -93,7 +99,7 @@ namespace tinyrpc {
|
|||||||
logger() << "new connect fd = " << fd;
|
logger() << "new connect fd = " << fd;
|
||||||
|
|
||||||
logger() << " 添加 fd 到子 reactor 中 " << fd;
|
logger() << " 添加 fd 到子 reactor 中 " << fd;
|
||||||
m_ioThreadPool.getIOThread()->addClient(fd);
|
m_ioThreadPool.getIOThread()->addClient(this, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
215
src/net/tinypb/tinypb_coder.cc
Normal file
215
src/net/tinypb/tinypb_coder.cc
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
#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);
|
||||||
|
|
||||||
|
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 < buffer.getReadable(); i++) {
|
||||||
|
if(buff[i] == PB_START) {
|
||||||
|
|
||||||
|
if(i + 1 >= buffer.getReadable()) {
|
||||||
|
return false; // 包不完整
|
||||||
|
}
|
||||||
|
|
||||||
|
pack_len = getInt32FromNetByte(buff[i + 1]);
|
||||||
|
end_index = pack_len + i - 1;
|
||||||
|
|
||||||
|
if(end_index >= 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 + 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 + 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 + 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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
61
src/net/tinypb/tinypb_dispatcher.cc
Normal file
61
src/net/tinypb/tinypb_dispatcher.cc
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "tinypb_dispatcher.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
#include "tinypb_data.hpp"
|
||||||
|
#include "error_code.hpp"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace tinyrpc {
|
||||||
|
TinypbDispatcher::TinypbDispatcher() {}
|
||||||
|
// TODO
|
||||||
|
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 google::protobuf::MethodDescriptor* method = service->GetDescriptor()->FindMethodByName(method_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user