From a21e7f28d11a0e85f2727744642cab64cecd9a2c Mon Sep 17 00:00:00 2001 From: lynncui00 Date: Fri, 26 Aug 2016 16:08:54 +0800 Subject: [PATCH 01/49] version 0.8.0 --- phxrpc/rpc/phxrpc.proto | 8 ++++---- sample/search.proto | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/phxrpc/rpc/phxrpc.proto b/phxrpc/rpc/phxrpc.proto index d9853e8..1a031c4 100644 --- a/phxrpc/rpc/phxrpc.proto +++ b/phxrpc/rpc/phxrpc.proto @@ -1,12 +1,12 @@ -syntax = "proto2"; +syntax = "proto3"; package phxrpc; import "google/protobuf/descriptor.proto"; extend google.protobuf.MethodOptions { - optional int32 CmdID = 2000000; - optional string OptString = 2000001; - optional string Usage = 2000002; + int32 CmdID = 2000000; + string OptString = 2000001; + string Usage = 2000002; } diff --git a/sample/search.proto b/sample/search.proto index e6e01ce..93614dd 100644 --- a/sample/search.proto +++ b/sample/search.proto @@ -1,4 +1,4 @@ -syntax = "proto2"; +syntax = "proto3"; package search; @@ -15,14 +15,14 @@ enum SiteType { UNKNOWN = 3; } message Site { - required string url = 1; - required string title = 2; - required SiteType type = 3; - optional string summary = 4; + string url = 1; + string title = 2; + SiteType type = 3; + string summary = 4; } message SearchRequest { - required string query = 1; + string query = 1; } message SearchResult { repeated Site sites = 1; From 81ca386ba756f7baae70ff550ca0f016607716c7 Mon Sep 17 00:00:00 2001 From: Haochuan Cui Date: Fri, 26 Aug 2016 16:10:43 +0800 Subject: [PATCH 02/49] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 70c8518..536282c 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ PhxRPC在ServerIO以及Client并发连接管理上使用了ucontext,而boost 下面是sample目录下的proto文件样例。 ```c++ +syntax = "proto3"; package search; import "google/protobuf/wrappers.proto"; import "google/protobuf/empty.proto"; From 99b09d0f4ea5f86acb158e15a623bea1ae0882d5 Mon Sep 17 00:00:00 2001 From: lynncui00 Date: Fri, 26 Aug 2016 16:53:39 +0800 Subject: [PATCH 03/49] add submodule protobuf --- third_party/protobuf | 1 + 1 file changed, 1 insertion(+) create mode 160000 third_party/protobuf diff --git a/third_party/protobuf b/third_party/protobuf new file mode 160000 index 0000000..3d9d1a1 --- /dev/null +++ b/third_party/protobuf @@ -0,0 +1 @@ +Subproject commit 3d9d1a1255583bac550f7bf94f3016e8c238fa5e From a08249576b7c61975f9eb60ea37f878a2875d83e Mon Sep 17 00:00:00 2001 From: WeChat Date: Sun, 28 Aug 2016 22:24:05 +0800 Subject: [PATCH 04/49] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 536282c..e6ca03a 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ PhxRPC在ServerIO以及Client并发连接管理上使用了ucontext,而boost 进入PhxRPC根目录。 make (默认是-O2编译,如需编译debug版,执行 make debug=y) - make boost (可选,编译PhxRPC的boost优化插件,编译之前先准备放置好boost库) + make boost (可选,编译PhxRPC的boost优化插件,编译之前先准备好boost库) # 如何使用 #### 编写proto文件 @@ -78,13 +78,13 @@ enum SiteType { UNKNOWN = 3; } message Site { - required string url = 1; - required string title = 2; - required SiteType type = 3; - optional string summary = 4; + string url = 1; + string title = 2; + SiteType type = 3; + tring summary = 4; } message SearchRequest { - required string query = 1; + string query = 1; } message SearchResult { repeated Site sites = 1; From a5f5af70f27406880013d49780fc4819ba3b75ef Mon Sep 17 00:00:00 2001 From: WeChat Date: Sun, 28 Aug 2016 23:16:07 +0800 Subject: [PATCH 05/49] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6ca03a..293fa0f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 - 半同步半异步模式,采用独立多IO线程,通过Epoll管理请求的接入以及读写,工作线程采用固定线程池。IO线程与工作线程通过内存队列进行交互。 - - 提供完善的过载保护,无需配置阀值,支持动态自适应拒绝请求。 + - 提供完善的过载保护,无需配置阈值,支持动态自适应拒绝请求。 - 提供简易的Client/Server配置读入方式。 - 基于lambda函数实现并发访问Server,可以非常方便地实现Google提出的 [Backup Requests](http://static.googleusercontent.com/media/research.google.com/zh-CN//people/jeff/Berkeley-Latency-Mar2012.pdf) 模式。 From ca193c9117c102e54594d8498461f98010dae32c Mon Sep 17 00:00:00 2001 From: mariohuang Date: Fri, 2 Sep 2016 11:36:38 +0800 Subject: [PATCH 06/49] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 293fa0f..a1ffd2e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,10 @@ **PhxRPC是微信后台团队推出的一个非常简洁小巧的RPC框架,编译生成的库只有450K。** -作者: Sifan Liu (stephenliu@tencent.com), Haochuan Cui (lynncui@tencent.com) 和 Duokai Huang (mariohuang@tencent.com) + +作者: Sifan Liu, Haochuan Cui 和 Duokai Huang + +联系我们:phxteam@tencent.com # 总览 - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 From 8e6e694183891c8c487d8db0d7812dab08def900 Mon Sep 17 00:00:00 2001 From: lynncui00 Date: Mon, 5 Sep 2016 16:10:57 +0800 Subject: [PATCH 07/49] add uthread stack protect. --- codegen/server_template.cpp | 1 + phxrpc/network/test_uthread.cpp | 2 +- phxrpc/network/test_uthread_context.cpp | 4 +- phxrpc/network/uthread_context_base.cpp | 5 ++- phxrpc/network/uthread_context_base.h | 5 ++- phxrpc/network/uthread_context_system.cpp | 20 ++++----- phxrpc/network/uthread_context_system.h | 11 ++--- phxrpc/network/uthread_context_util.cpp | 44 ++++++++++++++----- phxrpc/network/uthread_context_util.h | 18 ++++++-- phxrpc/network/uthread_epoll.cpp | 33 +++++++------- phxrpc/network/uthread_epoll.h | 13 +++--- phxrpc/network/uthread_runtime.cpp | 8 ++-- phxrpc/network/uthread_runtime.h | 3 +- phxrpc/rpc/hsha_server.cpp | 17 +++---- phxrpc/rpc/server_config.cpp | 10 +++++ phxrpc/rpc/server_config.h | 4 ++ .../network/uthread_context_boost.cpp | 18 +++----- plugin_boost/network/uthread_context_boost.h | 10 ++--- 18 files changed, 134 insertions(+), 92 deletions(-) diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index 0f694d1..af9f1aa 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -168,6 +168,7 @@ PackageName = $PackageName$ MaxConnections = 800000 MaxQueueLength = 20480 FastRejectThresholdMS = 20 +FastRejectAdjustRate = 5 [ServerTimeout] SocketTimeoutMS = 5000 diff --git a/phxrpc/network/test_uthread.cpp b/phxrpc/network/test_uthread.cpp index 8905de2..84db8ad 100644 --- a/phxrpc/network/test_uthread.cpp +++ b/phxrpc/network/test_uthread.cpp @@ -67,7 +67,7 @@ void execute(UThreadRuntime & runtime, size_t count) { } void run(size_t count) { - UThreadRuntime runtime(64 * 1024); + UThreadRuntime runtime(64 * 1024, false); execute(runtime, count); diff --git a/phxrpc/network/test_uthread_context.cpp b/phxrpc/network/test_uthread_context.cpp index 87e3346..9abfe2d 100644 --- a/phxrpc/network/test_uthread_context.cpp +++ b/phxrpc/network/test_uthread_context.cpp @@ -26,8 +26,8 @@ using namespace phxrpc; void f1(void *); void f2(void *); -UThreadContextSystem c1(64 * 1024, &f1, nullptr, nullptr); -UThreadContextSystem c2(64 * 1024, &f2, nullptr, nullptr); +UThreadContextSystem c1(64 * 1024, &f1, nullptr, nullptr, true); +UThreadContextSystem c2(64 * 1024, &f2, nullptr, nullptr, true); int test_count = 0; diff --git a/phxrpc/network/uthread_context_base.cpp b/phxrpc/network/uthread_context_base.cpp index b292dc5..d0fa089 100644 --- a/phxrpc/network/uthread_context_base.cpp +++ b/phxrpc/network/uthread_context_base.cpp @@ -26,9 +26,10 @@ namespace phxrpc { ContextCreateFunc_t UThreadContext::context_create_func_ = nullptr; UThreadContext * UThreadContext :: Create(size_t stack_size, - UThreadFunc_t func, void * args, UThreadDoneCallback_t callback) { + UThreadFunc_t func, void * args, + UThreadDoneCallback_t callback, const bool need_stack_protect) { if (context_create_func_ != nullptr) { - return context_create_func_(stack_size, func, args, callback); + return context_create_func_(stack_size, func, args, callback, need_stack_protect); } return nullptr; } diff --git a/phxrpc/network/uthread_context_base.h b/phxrpc/network/uthread_context_base.h index 00ffee7..294ec20 100644 --- a/phxrpc/network/uthread_context_base.h +++ b/phxrpc/network/uthread_context_base.h @@ -31,7 +31,7 @@ class UThreadContext; typedef std::function< void(void *) > UThreadFunc_t; typedef std::function< void() > UThreadDoneCallback_t; typedef std::function< UThreadContext* - (size_t, UThreadFunc_t, void *, UThreadDoneCallback_t) > ContextCreateFunc_t; + (size_t, UThreadFunc_t, void *, UThreadDoneCallback_t, const bool) > ContextCreateFunc_t; class UThreadContext { public: @@ -39,7 +39,8 @@ class UThreadContext { virtual ~UThreadContext() { } static UThreadContext * Create(size_t stack_size, - UThreadFunc_t func, void * args, UThreadDoneCallback_t callback); + UThreadFunc_t func, void * args, + UThreadDoneCallback_t callback, const bool need_stack_protect); static void SetContextCreateFunc(ContextCreateFunc_t context_create_func); static ContextCreateFunc_t GetContextCreateFunc(); diff --git a/phxrpc/network/uthread_context_system.cpp b/phxrpc/network/uthread_context_system.cpp index 8bf1b65..6366c0a 100644 --- a/phxrpc/network/uthread_context_system.cpp +++ b/phxrpc/network/uthread_context_system.cpp @@ -28,31 +28,27 @@ See the AUTHORS file for names of contributors. namespace phxrpc { -UThreadContextSystem :: UThreadContextSystem(size_t stack_size, UThreadFunc_t func, void * args, UThreadDoneCallback_t callback) - : func_(func), args_(args), stack_(nullptr), stack_size_(stack_size), - protect_page_(0), callback_(callback) { - - stack_ = (char *)calloc(1, stack_size_); - assert(stack_ != nullptr); - +UThreadContextSystem :: UThreadContextSystem(size_t stack_size, UThreadFunc_t func, void * args, + UThreadDoneCallback_t callback, const bool need_stack_protect) + : func_(func), args_(args), stack_(stack_size, need_stack_protect), callback_(callback) { Make(func, args); } UThreadContextSystem :: ~UThreadContextSystem() { - free(stack_); } UThreadContext * UThreadContextSystem :: DoCreate(size_t stack_size, - UThreadFunc_t func, void * args, UThreadDoneCallback_t callback) { - return new UThreadContextSystem(stack_size, func, args, callback); + UThreadFunc_t func, void * args, UThreadDoneCallback_t callback, + const bool need_stack_protect) { + return new UThreadContextSystem(stack_size, func, args, callback, need_stack_protect); } void UThreadContextSystem :: Make(UThreadFunc_t func, void * args) { func_ = func; args_ = args; getcontext(&context_); - context_.uc_stack.ss_sp = stack_; - context_.uc_stack.ss_size = stack_size_; + context_.uc_stack.ss_sp = stack_.top(); + context_.uc_stack.ss_size = stack_.size(); context_.uc_stack.ss_flags = 0; context_.uc_link = GetMainContext(); uintptr_t ptr = (uintptr_t)this; diff --git a/phxrpc/network/uthread_context_system.h b/phxrpc/network/uthread_context_system.h index b2865aa..2c10405 100644 --- a/phxrpc/network/uthread_context_system.h +++ b/phxrpc/network/uthread_context_system.h @@ -27,16 +27,19 @@ See the AUTHORS file for names of contributors. #include #include "uthread_context_base.h" +#include "uthread_context_util.h" namespace phxrpc { class UThreadContextSystem : public UThreadContext { public: - UThreadContextSystem(size_t stack_size, UThreadFunc_t func, void * args, UThreadDoneCallback_t callback); + UThreadContextSystem(size_t stack_size, UThreadFunc_t func, void * args, + UThreadDoneCallback_t callback, const bool need_stack_protect); ~UThreadContextSystem(); static UThreadContext * DoCreate(size_t stack_size, - UThreadFunc_t func, void * args, UThreadDoneCallback_t callback); + UThreadFunc_t func, void * args, UThreadDoneCallback_t callback, + const bool need_stack_protect); void Make(UThreadFunc_t func, void * args) override; bool Resume() override; @@ -50,9 +53,7 @@ class UThreadContextSystem : public UThreadContext { ucontext_t context_; UThreadFunc_t func_; void * args_; - char * stack_; - size_t stack_size_; - int protect_page_; + UThreadStackMemory stack_; UThreadDoneCallback_t callback_; }; diff --git a/phxrpc/network/uthread_context_util.cpp b/phxrpc/network/uthread_context_util.cpp index e43e993..7d0bc00 100644 --- a/phxrpc/network/uthread_context_util.cpp +++ b/phxrpc/network/uthread_context_util.cpp @@ -22,27 +22,47 @@ See the AUTHORS file for names of contributors. #include "uthread_context_util.h" #include #include +#include namespace phxrpc { -int UThreadProtectStack(void * stack_top, size_t stack_size) { - int page = STACK_PROTECT_PAGE; +UThreadStackMemory :: UThreadStackMemory(const size_t stack_size, const bool need_protect) : + raw_stack_(nullptr), stack_(nullptr), need_protect_(need_protect) { int page_size = getpagesize(); - assert(stack_size >= (size_t)page_size * (page + 1)); - void * protect_addr = stack_top; - if ((size_t)protect_addr & (page_size - 1)) { - protect_addr = (void *)(((size_t)stack_top & (~(page_size - 1))) + page_size); + if ((stack_size % page_size) != 0) { + stack_size_ = (stack_size / page_size + 1) * page_size; + } else { + stack_size_ = stack_size; + } + + if (need_protect) { + raw_stack_ = mmap(NULL, stack_size_ + page_size * 2, + PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + assert(raw_stack_ != nullptr); + assert(mprotect(raw_stack_, page_size, PROT_NONE) == 0); + assert(mprotect((void *)((char *)raw_stack_ + stack_size_ + page_size), page_size, PROT_NONE) == 0); + stack_ = (void *)((char *)raw_stack_ + page_size); + } else { + raw_stack_ = mmap(NULL, stack_size_, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + assert(raw_stack_ != nullptr); + stack_ = raw_stack_; } - return mprotect(protect_addr, page_size * page, PROT_NONE); } -int UThreadUnProtectStack(void * stack_top, int page) { - void * protect_addr = stack_top; +UThreadStackMemory :: ~UThreadStackMemory() { int page_size = getpagesize(); - if ((size_t)protect_addr & (page_size - 1)) { - protect_addr = (void *)(((size_t)stack_top & (~(page_size - 1))) + page_size); + if (need_protect_) { + assert(mprotect(raw_stack_, page_size, PROT_READ | PROT_WRITE) == 0); + assert(mprotect((void *)((char *)raw_stack_ + stack_size_ + page_size), page_size, PROT_READ | PROT_WRITE) == 0); } - return mprotect(protect_addr, page_size * page, PROT_READ | PROT_WRITE); +} + +void * UThreadStackMemory :: top() { + return stack_; +} + +size_t UThreadStackMemory :: size() { + return stack_size_; } } //namespace phxrpc diff --git a/phxrpc/network/uthread_context_util.h b/phxrpc/network/uthread_context_util.h index 1747f99..65a7e85 100644 --- a/phxrpc/network/uthread_context_util.h +++ b/phxrpc/network/uthread_context_util.h @@ -26,9 +26,19 @@ See the AUTHORS file for names of contributors. namespace phxrpc { -#define STACK_PROTECT_PAGE 1 - -int UThreadProtectStack(void * stack_top, size_t stack_size); -int UThreadUnProtectStack(void * stack_top, int page); +class UThreadStackMemory { +public: + UThreadStackMemory(const size_t stack_size, const bool need_protect = true); + ~UThreadStackMemory(); + + void * top(); + size_t size(); + +private: + void * raw_stack_; + void * stack_; + size_t stack_size_; + int need_protect_; +}; } //namespace phxrpc diff --git a/phxrpc/network/uthread_epoll.cpp b/phxrpc/network/uthread_epoll.cpp index 227b43a..fe0037b 100644 --- a/phxrpc/network/uthread_epoll.cpp +++ b/phxrpc/network/uthread_epoll.cpp @@ -102,9 +102,8 @@ enum UThreadEpollREventStatus { UThreadEpollREvent_Close = -2, }; -UThreadEpollScheduler::UThreadEpollScheduler(size_t stack_size, int max_task) : - epoll_wake_up_(this) { - runtime_ = new UThreadRuntime(stack_size); +UThreadEpollScheduler::UThreadEpollScheduler(size_t stack_size, int max_task, const bool need_stack_protect) : + runtime_(stack_size, need_stack_protect), epoll_wake_up_(this) { max_task_ = max_task; epoll_fd_ = epoll_create(max_task_); @@ -125,8 +124,6 @@ UThreadEpollScheduler::UThreadEpollScheduler(size_t stack_size, int max_task) : } UThreadEpollScheduler::~UThreadEpollScheduler() { - delete runtime_; - close(epoll_fd_); } @@ -148,11 +145,11 @@ void UThreadEpollScheduler :: SetHandlerAcceptedFdFunc(UThreadHanderAcceptedFdFu } bool UThreadEpollScheduler::YieldTask() { - return runtime_->Yield(); + return runtime_.Yield(); } int UThreadEpollScheduler::GetCurrUThread() { - return runtime_->GetCurrUThread(); + return runtime_.GetCurrUThread(); } UThreadSocket_t * UThreadEpollScheduler::CreateSocket(int fd, int socket_timeout_ms, @@ -181,8 +178,8 @@ UThreadSocket_t * UThreadEpollScheduler::CreateSocket(int fd, int socket_timeout void UThreadEpollScheduler::ConsumeTodoList() { while (!todo_list_.empty()) { auto & it = todo_list_.front(); - int id = runtime_->Create(it.first, it.second); - runtime_->Resume(id); + int id = runtime_.Create(it.first, it.second); + runtime_.Resume(id); todo_list_.pop(); } @@ -203,7 +200,7 @@ void UThreadEpollScheduler :: ResumeAll(int flag) { std::vector exist_socket_list = timer_.GetSocketList(); for (auto & socket : exist_socket_list) { socket->waited_events = flag; - runtime_->Resume(socket->uthread_id); + runtime_.Resume(socket->uthread_id); } } @@ -231,21 +228,21 @@ bool UThreadEpollScheduler::Run() { int next_timeout = timer_.GetNextTimeout(); - for (; (run_forever_) || (!runtime_->IsAllDone());) { + for (; (run_forever_) || (!runtime_.IsAllDone());) { int nfds = epoll_wait(epoll_fd_, events, max_task_, 4); if (nfds != -1) { for (int i = 0; i < nfds; i++) { UThreadSocket_t * socket = (UThreadSocket_t*) events[i].data.ptr; socket->waited_events = events[i].events; - runtime_->Resume(socket->uthread_id); + runtime_.Resume(socket->uthread_id); } //for server mode if (active_socket_func_ != nullptr) { UThreadSocket_t * socket = nullptr; while ((socket = active_socket_func_()) != nullptr) { - runtime_->Resume(socket->uthread_id); + runtime_.Resume(socket->uthread_id); } } @@ -298,7 +295,7 @@ void UThreadEpollScheduler::DealwithTimeout(int & next_timeout) { UThreadSocket_t * socket = timer_.PopTimeout(); socket->waited_events = UThreadEpollREvent_Timeout; - runtime_->Resume(socket->uthread_id); + runtime_.Resume(socket->uthread_id); } } @@ -503,22 +500,22 @@ void UThreadSetArgs(UThreadSocket_t & socket, void * args) { socket.args = args; } -void * UthreadGetArgs(UThreadSocket_t & socket) { +void * UThreadGetArgs(UThreadSocket_t & socket) { return socket.args; } -void UthreadWait(UThreadSocket_t & socket, int timeout_ms) { +void UThreadWait(UThreadSocket_t & socket, int timeout_ms) { socket.uthread_id = socket.scheduler->GetCurrUThread(); socket.scheduler->AddTimer(&socket, timeout_ms); socket.scheduler->YieldTask(); socket.scheduler->RemoveTimer(socket.timer_id); } -void UthreadLazyDestory(UThreadSocket_t & socket) { +void UThreadLazyDestory(UThreadSocket_t & socket) { socket.uthread_id = -1; } -bool IsUthreadDestory(UThreadSocket_t & socket) { +bool IsUThreadDestory(UThreadSocket_t & socket) { return socket.uthread_id == -1; } diff --git a/phxrpc/network/uthread_epoll.h b/phxrpc/network/uthread_epoll.h index dcc6ec0..67b85cb 100644 --- a/phxrpc/network/uthread_epoll.h +++ b/phxrpc/network/uthread_epoll.h @@ -58,7 +58,7 @@ class EpollNotifier { class UThreadEpollScheduler { public: - UThreadEpollScheduler(size_t stack_size, int max_task); + UThreadEpollScheduler(size_t stack_size, int max_task, const bool need_stack_protect = true); ~UThreadEpollScheduler(); static UThreadEpollScheduler * Instance(); @@ -95,7 +95,7 @@ class UThreadEpollScheduler { void StatEpollwaitEvents(const int event_count); private: - UThreadRuntime * runtime_; + UThreadRuntime runtime_; int max_task_; TaskQueue todo_list_; int epoll_fd_; @@ -126,6 +126,7 @@ class __uthread { }; #define uthread_begin phxrpc::UThreadEpollScheduler _uthread_scheduler(64 * 1024, 300); +#define uthread_begin_withargs(stack_size, max_task) phxrpc::UThreadEpollScheduler _uthread_scheduler(stack_size, max_task); #define uthread_s _uthread_scheduler #define uthread_t phxrpc::__uthread(_uthread_scheduler)- #define uthread_end _uthread_scheduler.Run(); @@ -162,13 +163,13 @@ UThreadSocket_t * NewUThreadSocket(); void UThreadSetArgs(UThreadSocket_t & socket, void * args); -void * UthreadGetArgs(UThreadSocket_t & socket); +void * UThreadGetArgs(UThreadSocket_t & socket); -void UthreadWait(UThreadSocket_t & socket, int timeout_ms); +void UThreadWait(UThreadSocket_t & socket, int timeout_ms); -void UthreadLazyDestory(UThreadSocket_t & socket); +void UThreadLazyDestory(UThreadSocket_t & socket); -bool IsUthreadDestory(UThreadSocket_t & socket); +bool IsUThreadDestory(UThreadSocket_t & socket); }; diff --git a/phxrpc/network/uthread_runtime.cpp b/phxrpc/network/uthread_runtime.cpp index 7741684..80448dc 100644 --- a/phxrpc/network/uthread_runtime.cpp +++ b/phxrpc/network/uthread_runtime.cpp @@ -33,9 +33,10 @@ enum { namespace phxrpc { -UThreadRuntime :: UThreadRuntime(size_t stack_size) +UThreadRuntime :: UThreadRuntime(size_t stack_size, const bool need_stack_protect) :stack_size_(stack_size), first_done_item_(-1), - current_uthread_(-1), unfinished_item_count_(0) { + current_uthread_(-1), unfinished_item_count_(0), + need_stack_protect_(need_stack_protect) { if (UThreadContext::GetContextCreateFunc() == nullptr) { UThreadContext::SetContextCreateFunc(UThreadContextSystem::DoCreate); } @@ -59,7 +60,8 @@ int UThreadRuntime :: Create(UThreadFunc_t func, void * args) { } else { index = context_list_.size(); auto new_context = UThreadContext::Create(stack_size_, func, args, - std::bind(&UThreadRuntime::UThreadDoneCallback, this)); + std::bind(&UThreadRuntime::UThreadDoneCallback, this), + need_stack_protect_); assert(new_context != nullptr); ContextSlot context_slot; context_slot.context = new_context; diff --git a/phxrpc/network/uthread_runtime.h b/phxrpc/network/uthread_runtime.h index aba9354..765858c 100644 --- a/phxrpc/network/uthread_runtime.h +++ b/phxrpc/network/uthread_runtime.h @@ -30,7 +30,7 @@ namespace phxrpc { class UThreadRuntime { public: - UThreadRuntime(size_t stack_size); + UThreadRuntime(size_t stack_size, const bool need_stack_protect); ~UThreadRuntime(); int Create(UThreadFunc_t func, void * args); @@ -57,6 +57,7 @@ class UThreadRuntime { int first_done_item_; int current_uthread_; int unfinished_item_count_; + bool need_stack_protect_; }; } //namespace phxrpc diff --git a/phxrpc/rpc/hsha_server.cpp b/phxrpc/rpc/hsha_server.cpp index 4ab4fdc..cc2ffed 100644 --- a/phxrpc/rpc/hsha_server.cpp +++ b/phxrpc/rpc/hsha_server.cpp @@ -341,13 +341,14 @@ void HshaServerQos :: CalFunc() { int avg_queue_wait_time = (hsha_server_stat_->inqueue_avg_wait_time_costs_per_second_ + hsha_server_stat_->outqueue_avg_wait_time_costs_per_second_) / 2; + int rate = config_->GetFastRejectAdjustRate(); if (avg_queue_wait_time > config_->GetFastRejectThresholdMS()) { if (enqueue_reject_rate_ != 99) { - enqueue_reject_rate_ = enqueue_reject_rate_ + 5 > 99 ? 99 : enqueue_reject_rate_ + 5; + enqueue_reject_rate_ = enqueue_reject_rate_ + rate > 99 ? 99 : enqueue_reject_rate_ + rate; } } else { if (enqueue_reject_rate_ != 0) { - enqueue_reject_rate_ = enqueue_reject_rate_ - 5 < 0 ? 0 : enqueue_reject_rate_ - 5; + enqueue_reject_rate_ = enqueue_reject_rate_ - rate < 0 ? 0 : enqueue_reject_rate_ - rate; } } inqueue_avg_wait_time_costs_per_second_cal_last_seq_ = @@ -508,15 +509,15 @@ void HshaServerIO :: IOFunc(int accepted_fd) { data_flow_->PushRequest((void *)socket, request); UThreadSetArgs(*socket, nullptr); - UthreadWait(*socket, config_->GetSocketTimeoutMS()); - if (UthreadGetArgs(*socket) == nullptr) { + UThreadWait(*socket, config_->GetSocketTimeoutMS()); + if (UThreadGetArgs(*socket) == nullptr) { //timeout hsha_server_stat_->worker_timeouts_++; hsha_server_stat_->rpc_time_costs_count_++; //because have enqueue, so socket will be closed after pop. socket = stream.DetachSocket(); - UthreadLazyDestory(*socket); + UThreadLazyDestory(*socket); //phxrpc::log(LOG_ERR, "%s timeout, fd %d sockettimeoutms %d", //__func__, accepted_fd, config_->GetSocketTimeoutMS()); @@ -524,7 +525,7 @@ void HshaServerIO :: IOFunc(int accepted_fd) { } hsha_server_stat_->io_write_responses_++; - HttpResponse * response = (HttpResponse *)UthreadGetArgs(*socket); + HttpResponse * response = (HttpResponse *)UThreadGetArgs(*socket); HttpProto::FixRespHeaders(is_keep_alive, version.c_str(), response); socket_ret = HttpProto::SendResp(stream, *response); hsha_server_stat_->io_write_bytes_ += response->GetContent().size(); @@ -560,7 +561,7 @@ UThreadSocket_t * HshaServerIO :: ActiveSocketFunc() { hsha_server_stat_->outqueue_wait_time_costs_count_++; UThreadSocket_t * socket = (UThreadSocket_t *)args; - if (socket != nullptr && IsUthreadDestory(*socket)) { + if (socket != nullptr && IsUThreadDestory(*socket)) { //socket aready timeout. //phxrpc::log(LOG_ERR, "%s socket aready timeout", __func__); UThreadClose(*socket); @@ -587,7 +588,7 @@ void HshaServerIO :: RunForever() { HshaServerUnit :: HshaServerUnit(HshaServer * hsha_server, int idx, int worker_thread_count, Dispatch_t dispatch, void * args) : hsha_server_(hsha_server), - scheduler_(16 * 1024, 1000000), + scheduler_(8 * 1024, 1000000, false), hsha_server_io_(idx, &scheduler_, hsha_server_->config_, &data_flow_, &hsha_server_->hsha_server_stat_, &hsha_server_->hsha_server_qos_), worker_pool_(&scheduler_, worker_thread_count, &data_flow_, diff --git a/phxrpc/rpc/server_config.cpp b/phxrpc/rpc/server_config.cpp index 9b27a37..393952e 100644 --- a/phxrpc/rpc/server_config.cpp +++ b/phxrpc/rpc/server_config.cpp @@ -108,6 +108,7 @@ HshaServerConfig :: HshaServerConfig() : max_connections_(800000), max_queue_length_(20480), fast_reject_threshold_ms_(20), + fast_reject_adjust_rate_(5), io_thread_count_(3) { } @@ -119,6 +120,7 @@ bool HshaServerConfig :: DoRead(Config & config) { config.ReadItem("Server", "IOThreadCount", &io_thread_count_, 3); config.ReadItem("Server", "MaxQueueLength", &max_queue_length_, 20480); config.ReadItem("Server", "FastRejectThresholdMS", &fast_reject_threshold_ms_, 20); + config.ReadItem("Server", "FastRejectAdjustRate", &fast_reject_adjust_rate_, 5); return true; } @@ -146,6 +148,14 @@ int HshaServerConfig :: GetFastRejectThresholdMS() const { return fast_reject_threshold_ms_; } +void HshaServerConfig :: SetFastRejectAdjustRate(const int fast_reject_adjust_rate) { + fast_reject_adjust_rate_ = fast_reject_adjust_rate; +} + +int HshaServerConfig :: GetFastRejectAdjustRate() const { + return fast_reject_adjust_rate_; +} + void HshaServerConfig :: SetIOThreadCount(const int io_thread_count) { io_thread_count_ = io_thread_count; } diff --git a/phxrpc/rpc/server_config.h b/phxrpc/rpc/server_config.h index e98321e..9a995b5 100644 --- a/phxrpc/rpc/server_config.h +++ b/phxrpc/rpc/server_config.h @@ -75,6 +75,9 @@ class HshaServerConfig : public ServerConfig { void SetFastRejectThresholdMS(const int fast_reject_threshold_ms); int GetFastRejectThresholdMS() const; + void SetFastRejectAdjustRate(const int fast_reject_adjust_rate); + int GetFastRejectAdjustRate() const; + void SetIOThreadCount(const int io_thread_count); int GetIOThreadCount() const; @@ -82,6 +85,7 @@ class HshaServerConfig : public ServerConfig { int max_connections_; int max_queue_length_; int fast_reject_threshold_ms_; + int fast_reject_adjust_rate_; int io_thread_count_; }; diff --git a/plugin_boost/network/uthread_context_boost.cpp b/plugin_boost/network/uthread_context_boost.cpp index f55075c..14d01d2 100644 --- a/plugin_boost/network/uthread_context_boost.cpp +++ b/plugin_boost/network/uthread_context_boost.cpp @@ -36,29 +36,25 @@ UThreadContextBoostInit :: UThreadContextBoostInit() { } UThreadContextBoost :: UThreadContextBoost(size_t stack_size, UThreadFunc_t func, - void * args, UThreadDoneCallback_t callback) - : func_(func), args_(args), stack_(nullptr), stack_size_(stack_size), - protect_page_(0), callback_(callback) { - stack_ = (char *)calloc(1, stack_size_); - assert(stack_ != nullptr); - + void * args, UThreadDoneCallback_t callback, const bool need_stack_protect) + : func_(func), args_(args), stack_(stack_size, need_stack_protect), callback_(callback) { Make(func, args); } UThreadContextBoost :: ~UThreadContextBoost() { - free(stack_); } UThreadContext * UThreadContextBoost:: DoCreate(size_t stack_size, - UThreadFunc_t func, void * args, UThreadDoneCallback_t callback) { - return new UThreadContextBoost(stack_size, func, args, callback); + UThreadFunc_t func, void * args, UThreadDoneCallback_t callback, + const bool need_stack_protect) { + return new UThreadContextBoost(stack_size, func, args, callback, need_stack_protect); } void UThreadContextBoost :: Make(UThreadFunc_t func, void * args) { func_ = func; args_ = args; - void * stack_p = (void *)(stack_ + stack_size_); - context_ = boost::context::make_fcontext(stack_p, stack_size_, &UThreadFuncWrapper); + void * stack_p = (void *)((char *)stack_.top() + stack_.size()); + context_ = boost::context::make_fcontext(stack_p, stack_.size(), &UThreadFuncWrapper); } bool UThreadContextBoost :: Resume() { diff --git a/plugin_boost/network/uthread_context_boost.h b/plugin_boost/network/uthread_context_boost.h index 3816c10..a1b69cc 100644 --- a/plugin_boost/network/uthread_context_boost.h +++ b/plugin_boost/network/uthread_context_boost.h @@ -36,11 +36,13 @@ class UThreadContextBoostInit { class UThreadContextBoost : public UThreadContext { public: - UThreadContextBoost(size_t stack_size, UThreadFunc_t func, void * args, UThreadDoneCallback_t callback); + UThreadContextBoost(size_t stack_size, UThreadFunc_t func, void * args, + UThreadDoneCallback_t callback, const bool need_stack_protect); ~UThreadContextBoost(); static UThreadContext * DoCreate(size_t stack_size, - UThreadFunc_t func, void * args, UThreadDoneCallback_t callback); + UThreadFunc_t func, void * args, UThreadDoneCallback_t callback, + const bool need_stack_protect); void Make(UThreadFunc_t func, void * args) override; bool Resume() override; @@ -54,9 +56,7 @@ class UThreadContextBoost : public UThreadContext { boost::context::fcontext_t context_; UThreadFunc_t func_; void * args_; - char * stack_; - size_t stack_size_; - int protect_page_; + UThreadStackMemory stack_; UThreadDoneCallback_t callback_; }; From 9ef9f20ec8803ad618c322950665ed6f936037df Mon Sep 17 00:00:00 2001 From: lynncui00 Date: Mon, 5 Sep 2016 16:20:31 +0800 Subject: [PATCH 08/49] add uthread stack protect. --- phxrpc/network/uthread_context_util.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/phxrpc/network/uthread_context_util.cpp b/phxrpc/network/uthread_context_util.cpp index 7d0bc00..2b665b3 100644 --- a/phxrpc/network/uthread_context_util.cpp +++ b/phxrpc/network/uthread_context_util.cpp @@ -54,6 +54,9 @@ UThreadStackMemory :: ~UThreadStackMemory() { if (need_protect_) { assert(mprotect(raw_stack_, page_size, PROT_READ | PROT_WRITE) == 0); assert(mprotect((void *)((char *)raw_stack_ + stack_size_ + page_size), page_size, PROT_READ | PROT_WRITE) == 0); + assert(munmap(raw_stack_, stack_size_ + page_size * 2) == 0); + } else { + assert(munmap(raw_stack_, stack_size_) == 0); } } From 3beafd5e39498e167d91d815fea6429b37bd572a Mon Sep 17 00:00:00 2001 From: Zhijiang TAO Date: Tue, 6 Sep 2016 21:13:55 +0800 Subject: [PATCH 09/49] fix protobuf bin include path --- codegen/server_template.cpp | 2 +- phxrpc/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index af9f1aa..063c9ad 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -216,7 +216,7 @@ lib$ClientFile$.a: $(CLI_OBJS) $MessageFile$.cc: $MessageFile$.h $MessageFile$.h: $ProtoFile$ - $(PROTOBUF_ROOT)/src/protoc -I$(PROTOBUF_ROOT)/src --cpp_out=. -I$(PHXRPC_ROOT) -I. $^ + $(PROTOBUF_ROOT)/bin/protoc -I$(PROTOBUF_ROOT)/include --cpp_out=. -I$(PHXRPC_ROOT) -I. $^ ########## client ########## diff --git a/phxrpc/Makefile b/phxrpc/Makefile index e8e9aa5..46c933d 100644 --- a/phxrpc/Makefile +++ b/phxrpc/Makefile @@ -27,7 +27,7 @@ libphxrpc.a: $(LIB_OBJS) rpc/phxrpc.pb.cc: rpc/phxrpc.pb.h rpc/phxrpc.pb.h: rpc/phxrpc.proto - cd ..; $(PROTOBUF_ROOT)/src/protoc -I$(PROTOBUF_ROOT)/src -I. --cpp_out=. phxrpc/$<; + cd ..; $(PROTOBUF_ROOT)/bin/protoc -I$(PROTOBUF_ROOT)/include -I. --cpp_out=. phxrpc/$<; clean: @( $(RM) $(TARGETS) $(TEST_TARGETS) ) From dd828fd20d9d08764e33a266839f385743652bde Mon Sep 17 00:00:00 2001 From: lynncui00 Date: Wed, 7 Sep 2016 18:42:11 +0800 Subject: [PATCH 10/49] modify submodule --- third_party/protobuf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/protobuf b/third_party/protobuf index 3d9d1a1..e8ae137 160000 --- a/third_party/protobuf +++ b/third_party/protobuf @@ -1 +1 @@ -Subproject commit 3d9d1a1255583bac550f7bf94f3016e8c238fa5e +Subproject commit e8ae137c96444ea313485ed1118c5e43b2099cf1 From 859d6ef74557bb5ff41fe1b4bdd319ebbcd519c3 Mon Sep 17 00:00:00 2001 From: Haochuan Cui Date: Wed, 7 Sep 2016 19:37:05 +0800 Subject: [PATCH 11/49] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a1ffd2e..02b86ad 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,12 @@ **PhxRPC是微信后台团队推出的一个非常简洁小巧的RPC框架,编译生成的库只有450K。** - 作者: Sifan Liu, Haochuan Cui 和 Duokai Huang 联系我们:phxteam@tencent.com +想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/tencent-wechat/phxpaxos/wiki),和扫描右侧二维码关注我们的公众号 + # 总览 - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 From b0070b7f276af7c2a460b2657be952bfce20121e Mon Sep 17 00:00:00 2001 From: Haochuan Cui Date: Wed, 7 Sep 2016 19:37:24 +0800 Subject: [PATCH 12/49] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02b86ad..afb159c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ 联系我们:phxteam@tencent.com -想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/tencent-wechat/phxpaxos/wiki),和扫描右侧二维码关注我们的公众号 +想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/tencent-wechat/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 # 总览 - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 From 8cf4a7956bc697f9b353cd2f67d9ca2063a2a3cc Mon Sep 17 00:00:00 2001 From: stephen Date: Fri, 16 Sep 2016 16:52:51 +0800 Subject: [PATCH 13/49] add travis build file --- .travis.yml | 4 ++++ build.sh | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 .travis.yml create mode 100755 build.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..07aa53f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +git: + submodules: false +script: + - ./build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..d12c224 --- /dev/null +++ b/build.sh @@ -0,0 +1,17 @@ + +cd third_party; + +test -f protobuf-cpp-3.0.0.tar.gz || wget https://github.com/google/protobuf/releases/download/v3.0.2/protobuf-cpp-3.0.0.tar.gz + +tar zxvf protobuf-cpp-3.0.0.tar.gz + +cd protobuf-3.0.0 + +./configure --prefix=`pwd`/../protobuf +make +make install + +cd ../.. + +make + From 4b35d1464cdd9c30b56bba6247daf800ad907090 Mon Sep 17 00:00:00 2001 From: liusifan Date: Fri, 16 Sep 2016 17:23:08 +0800 Subject: [PATCH 14/49] add plugin_darwin --- plugin_darwin/Makefile | 16 +++++ plugin_darwin/network/epoll-darwin.cpp | 84 ++++++++++++++++++++++++++ plugin_darwin/network/epoll-darwin.h | 60 ++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 plugin_darwin/Makefile create mode 100644 plugin_darwin/network/epoll-darwin.cpp create mode 100644 plugin_darwin/network/epoll-darwin.h diff --git a/plugin_darwin/Makefile b/plugin_darwin/Makefile new file mode 100644 index 0000000..43092c9 --- /dev/null +++ b/plugin_darwin/Makefile @@ -0,0 +1,16 @@ + +include ../phxrpc.mk + +LIB_OBJS = network/epoll-darwin.o + +TARGETS = libphxrpc_plugin_darwin.a + +all: $(TARGETS) + +libphxrpc_plugin_darwin.a: $(LIB_OBJS) + $(AR) $@ $^ + mkdir -p $(PHXRPC_ROOT)/lib; cp $@ $(PHXRPC_ROOT)/lib + +clean: + @( $(RM) $(TARGETS) ) + @( $(RM) *.o core.* $(LIB_OBJS) ) diff --git a/plugin_darwin/network/epoll-darwin.cpp b/plugin_darwin/network/epoll-darwin.cpp new file mode 100644 index 0000000..258bce7 --- /dev/null +++ b/plugin_darwin/network/epoll-darwin.cpp @@ -0,0 +1,84 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include "epoll-darwin.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +int epoll_create(int size) +{ + return kqueue(); +} + +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) +{ + struct kevent kev; + if (op == EPOLL_CTL_ADD) { + if (event->events == EPOLLIN) { + EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, event->data.ptr); + } else { + EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, event->data.ptr); + } + } else if (op == EPOLL_CTL_DEL) { + if (event->events == EPOLLIN) { + EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); + } else { + EV_SET(&kev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); + } + } else { + errno = EINVAL; + return -1; + } + + return kevent(epfd, &kev, 1, NULL, 0, NULL); +} + +int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + struct kevent * evlist = (struct kevent*)malloc(sizeof(struct kevent)*maxevents); + + struct timespec to = {0, 0}; + if (timeout > 0) { + to.tv_sec = timeout / 1000; + to.tv_nsec = (timeout % 1000) * 1000 * 1000; + } + + int ret = kevent(epfd, NULL, 0, evlist, maxevents, timeout == -1 ? NULL : &to); + if (ret > 0) { + for (int i = 0; i < ret; ++i) { + events[i].events = ( evlist[i].filter == EVFILT_READ ) ? EPOLLIN : EPOLLOUT; + events[i].data.ptr = evlist[i].udata; + } + } + + free( evlist ); + + return ret; +} + diff --git a/plugin_darwin/network/epoll-darwin.h b/plugin_darwin/network/epoll-darwin.h new file mode 100644 index 0000000..38e8fa9 --- /dev/null +++ b/plugin_darwin/network/epoll-darwin.h @@ -0,0 +1,60 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define EPOLLIN 0x001 +#define EPOLLOUT 0x004 +#define EPOLLERR 0x008 +#define EPOLLHUP 0x010 + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 + +typedef union epoll_data { + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event { + uint32_t events; + epoll_data_t data; +}; + +int epoll_create(int); +int epoll_ctl(int, int, int, struct epoll_event *); +int epoll_wait(int, struct epoll_event *, int, int); + +#ifdef __cplusplus +} +#endif + From 6ef882e682a603dc832d5f1f0ce43ec518476e05 Mon Sep 17 00:00:00 2001 From: liusifan Date: Fri, 16 Sep 2016 17:24:51 +0800 Subject: [PATCH 15/49] change for plugin_darwin --- Makefile | 3 ++- build.sh | 22 +++++++++++++++------- phxrpc.mk | 7 ++++--- phxrpc/Makefile | 9 +++++++-- phxrpc/network/timer.cpp | 1 + phxrpc/network/uthread_context_system.cpp | 2 +- phxrpc/network/uthread_context_util.cpp | 4 ++++ phxrpc/network/uthread_epoll.cpp | 7 ++++++- phxrpc/network/uthread_epoll.h | 2 -- phxrpc/rpc/hsha_server.cpp | 2 ++ 10 files changed, 42 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 39d3d04..9d77834 100644 --- a/Makefile +++ b/Makefile @@ -19,8 +19,9 @@ phxrpc-$(version).src.tar.gz: clean: @( rm -rf lib/*; ) - @( cd plugin_boost; make clean ) @( cd phxrpc; make clean ) @( cd codegen; make clean ) @( cd sample; test -f Makefile && make clean ) + @( cd plugin_boost; make clean ) + @( cd plugin_darwin; make clean ) diff --git a/build.sh b/build.sh index d12c224..7596cf8 100755 --- a/build.sh +++ b/build.sh @@ -1,17 +1,25 @@ +set -e # exit immediately on error +set -x # display all commands + cd third_party; -test -f protobuf-cpp-3.0.0.tar.gz || wget https://github.com/google/protobuf/releases/download/v3.0.2/protobuf-cpp-3.0.0.tar.gz +if [ ! -f protobuf/bin/protoc ]; then + if [ ! -f protobuf-cpp-3.0.0.tar.gz ]; then + wget https://github.com/google/protobuf/releases/download/v3.0.2/protobuf-cpp-3.0.0.tar.gz + fi -tar zxvf protobuf-cpp-3.0.0.tar.gz + tar zxvf protobuf-cpp-3.0.0.tar.gz + cd protobuf-3.0.0 -cd protobuf-3.0.0 + ./configure --prefix=`pwd`/../protobuf + make + make install -./configure --prefix=`pwd`/../protobuf -make -make install + cd ../ +fi -cd ../.. +cd .. make diff --git a/phxrpc.mk b/phxrpc.mk index d2486dd..48c5241 100644 --- a/phxrpc.mk +++ b/phxrpc.mk @@ -6,12 +6,13 @@ where-am-i = $(abspath $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) PHXRPC_ROOT=$(dir $(call where-am-i)) +OS := $(shell uname) + PROTOBUF_ROOT=$(PHXRPC_ROOT)/third_party/protobuf BOOST_ROOT=$(PHXRPC_ROOT)/third_party/boost PLUGIN_BOOST_LDFLAGS = -Wl,--whole-archive -L$(PHXRPC_ROOT)/lib/ -lphxrpc_plugin_boost \ - -Wl,--no-whole-archive -L$(BOOST_ROOT)/lib/ -lboost_context - + -Wl,--no-whole-archive -L$(BOOST_ROOT)/lib/ -lboost_context #-------------------------------------------------------------------- @@ -31,7 +32,7 @@ LINKER = $(CC) LINT = lint -c RM = /bin/rm -f -CFLAGS = -std=c++11 -Wall -D_REENTRANT -D_GNU_SOURCE -fPIC -m64 $(OPT) \ +CFLAGS = -stdlib=libc++ -std=c++11 -Wall -D_REENTRANT -D_GNU_SOURCE -D_XOPEN_SOURCE -fPIC -m64 $(OPT) \ -I$(PROTOBUF_ROOT)/include \ -I$(PHXRPC_ROOT) \ diff --git a/phxrpc/Makefile b/phxrpc/Makefile index 46c933d..15505fd 100644 --- a/phxrpc/Makefile +++ b/phxrpc/Makefile @@ -6,7 +6,7 @@ LIB_HTTP_OBJS = http/http_client.o http/http_client.o http/http_msg.o http/http_ LIB_NETWORK_OBJS = network/socket_stream_base.o network/uthread_runtime.o network/uthread_epoll.o \ network/socket_stream_block.o network/socket_stream_uthread.o \ network/uthread_context_util.o network/uthread_context_base.o \ - network/uthread_context_system.o network/timer.o \ + network/uthread_context_system.o network/timer.o LIB_FILE_OBJS = file/log_utils.o file/file_utils.o file/opt_map.o file/config.o @@ -14,6 +14,11 @@ LIB_RPC_OBJS = rpc/phxrpc.pb.o rpc/http_caller.o rpc/server_config.o rpc/client_ rpc/socket_stream_phxrpc.o rpc/uthread_caller.o rpc/client_monitor.o rpc/server_monitor.o \ rpc/monitor_factory.o rpc/hsha_server.o \ +ifeq ($(OS),Darwin) + CFLAGS += -I$(PHXRPC_ROOT)/plugin_darwin/network + LIB_NETWORK_OBJS += ../plugin_darwin/network/epoll-darwin.o +endif + LIB_OBJS = $(LIB_RPC_OBJS) $(LIB_HTTP_OBJS) $(LIB_NETWORK_OBJS) $(LIB_FILE_OBJS) \ TARGETS = libphxrpc.a @@ -27,7 +32,7 @@ libphxrpc.a: $(LIB_OBJS) rpc/phxrpc.pb.cc: rpc/phxrpc.pb.h rpc/phxrpc.pb.h: rpc/phxrpc.proto - cd ..; $(PROTOBUF_ROOT)/bin/protoc -I$(PROTOBUF_ROOT)/include -I. --cpp_out=. phxrpc/$<; + cd ..; $(PROTOBUF_ROOT)/bin/protoc -I$(PROTOBUF_ROOT)/src -I. --cpp_out=. phxrpc/$<; clean: @( $(RM) $(TARGETS) $(TEST_TARGETS) ) diff --git a/phxrpc/network/timer.cpp b/phxrpc/network/timer.cpp index c18ece3..e0d4e18 100644 --- a/phxrpc/network/timer.cpp +++ b/phxrpc/network/timer.cpp @@ -29,6 +29,7 @@ See the AUTHORS file for names of contributors. #include "uthread_epoll.h" #include #include +#include using namespace std; diff --git a/phxrpc/network/uthread_context_system.cpp b/phxrpc/network/uthread_context_system.cpp index 6366c0a..2843452 100644 --- a/phxrpc/network/uthread_context_system.cpp +++ b/phxrpc/network/uthread_context_system.cpp @@ -67,7 +67,7 @@ bool UThreadContextSystem :: Yield() { } ucontext_t * UThreadContextSystem :: GetMainContext() { - static thread_local ucontext_t main_context; + static __thread ucontext_t main_context; return &main_context; } diff --git a/phxrpc/network/uthread_context_util.cpp b/phxrpc/network/uthread_context_util.cpp index 2b665b3..a787dce 100644 --- a/phxrpc/network/uthread_context_util.cpp +++ b/phxrpc/network/uthread_context_util.cpp @@ -26,6 +26,10 @@ See the AUTHORS file for names of contributors. namespace phxrpc { +#ifdef __APPLE__ + #define MAP_ANONYMOUS MAP_ANON +#endif + UThreadStackMemory :: UThreadStackMemory(const size_t stack_size, const bool need_protect) : raw_stack_(nullptr), stack_(nullptr), need_protect_(need_protect) { int page_size = getpagesize(); diff --git a/phxrpc/network/uthread_epoll.cpp b/phxrpc/network/uthread_epoll.cpp index fe0037b..edbf491 100644 --- a/phxrpc/network/uthread_epoll.cpp +++ b/phxrpc/network/uthread_epoll.cpp @@ -22,7 +22,6 @@ See the AUTHORS file for names of contributors. #include #include #include -#include #include #include #include @@ -34,6 +33,12 @@ See the AUTHORS file for names of contributors. #include #include +#ifdef __APPLE__ + #include "epoll-darwin.h" +#else + #include +#endif + #include "uthread_epoll.h" #include "socket_stream_base.h" #include "phxrpc/file/log_utils.h" diff --git a/phxrpc/network/uthread_epoll.h b/phxrpc/network/uthread_epoll.h index 67b85cb..f8a395c 100644 --- a/phxrpc/network/uthread_epoll.h +++ b/phxrpc/network/uthread_epoll.h @@ -24,8 +24,6 @@ See the AUTHORS file for names of contributors. #include #include #include - -#include #include #include "uthread_runtime.h" diff --git a/phxrpc/rpc/hsha_server.cpp b/phxrpc/rpc/hsha_server.cpp index cc2ffed..3312226 100644 --- a/phxrpc/rpc/hsha_server.cpp +++ b/phxrpc/rpc/hsha_server.cpp @@ -626,6 +626,7 @@ void HshaServerAcceptor :: LoopAccept(const char * bind_ip, const int port) { printf("listen succ, ip %s port %d\n", bind_ip, port); +#ifndef __APPLE__ cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(0, &mask); @@ -634,6 +635,7 @@ void HshaServerAcceptor :: LoopAccept(const char * bind_ip, const int port) { if (ret != 0) { printf("sched_setaffinity fail\n"); } +#endif while (true) { struct sockaddr_in addr; From 09cce9691da13c7c3784ff5e2d4e1b635636d438 Mon Sep 17 00:00:00 2001 From: liusifan Date: Fri, 16 Sep 2016 17:38:59 +0800 Subject: [PATCH 16/49] add travis --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 07aa53f..aa79dcd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,8 @@ +language: cpp +compiler: g++ git: submodules: false script: - ./build.sh +notifications: + email: true From 582986a980dca0a1451ceec88a717b1532cc6e7d Mon Sep 17 00:00:00 2001 From: liusifan Date: Fri, 16 Sep 2016 17:47:06 +0800 Subject: [PATCH 17/49] correct protobuf's url --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 7596cf8..3563cb5 100755 --- a/build.sh +++ b/build.sh @@ -6,7 +6,7 @@ cd third_party; if [ ! -f protobuf/bin/protoc ]; then if [ ! -f protobuf-cpp-3.0.0.tar.gz ]; then - wget https://github.com/google/protobuf/releases/download/v3.0.2/protobuf-cpp-3.0.0.tar.gz + wget https://github.com/google/protobuf/releases/download/v3.0.0/protobuf-cpp-3.0.0.tar.gz fi tar zxvf protobuf-cpp-3.0.0.tar.gz From 0c773682bf08cffc652a00fe2ee67672c0a84d38 Mon Sep 17 00:00:00 2001 From: liusifan Date: Fri, 16 Sep 2016 18:01:39 +0800 Subject: [PATCH 18/49] fix --- build.sh | 2 +- phxrpc.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 3563cb5..261df71 100755 --- a/build.sh +++ b/build.sh @@ -13,7 +13,7 @@ if [ ! -f protobuf/bin/protoc ]; then cd protobuf-3.0.0 ./configure --prefix=`pwd`/../protobuf - make + make -j2 make install cd ../ diff --git a/phxrpc.mk b/phxrpc.mk index 48c5241..cee1ab1 100644 --- a/phxrpc.mk +++ b/phxrpc.mk @@ -32,7 +32,7 @@ LINKER = $(CC) LINT = lint -c RM = /bin/rm -f -CFLAGS = -stdlib=libc++ -std=c++11 -Wall -D_REENTRANT -D_GNU_SOURCE -D_XOPEN_SOURCE -fPIC -m64 $(OPT) \ +CFLAGS = -std=c++11 -Wall -D_REENTRANT -D_GNU_SOURCE -D_XOPEN_SOURCE -fPIC -m64 $(OPT) \ -I$(PROTOBUF_ROOT)/include \ -I$(PHXRPC_ROOT) \ From 6ffa76b6800d4d3d6c0047f59059ca86152a57d8 Mon Sep 17 00:00:00 2001 From: liusifan Date: Fri, 16 Sep 2016 18:20:50 +0800 Subject: [PATCH 19/49] use up-to-date compiler --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index aa79dcd..2816042 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,7 @@ +# Ubuntu 14.04 Trusty support +sudo: required +dist: trusty + language: cpp compiler: g++ git: From 63edc9f0fc18d36cfa409898990c6acd5c0c4179 Mon Sep 17 00:00:00 2001 From: liusifan Date: Fri, 16 Sep 2016 19:42:59 +0800 Subject: [PATCH 20/49] add travis --- .travis.yml | 12 ++++++++++++ build.sh | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 .travis.yml create mode 100755 build.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2816042 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +# Ubuntu 14.04 Trusty support +sudo: required +dist: trusty + +language: cpp +compiler: g++ +git: + submodules: false +script: + - ./build.sh +notifications: + email: true diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..261df71 --- /dev/null +++ b/build.sh @@ -0,0 +1,25 @@ + +set -e # exit immediately on error +set -x # display all commands + +cd third_party; + +if [ ! -f protobuf/bin/protoc ]; then + if [ ! -f protobuf-cpp-3.0.0.tar.gz ]; then + wget https://github.com/google/protobuf/releases/download/v3.0.0/protobuf-cpp-3.0.0.tar.gz + fi + + tar zxvf protobuf-cpp-3.0.0.tar.gz + cd protobuf-3.0.0 + + ./configure --prefix=`pwd`/../protobuf + make -j2 + make install + + cd ../ +fi + +cd .. + +make + From 4a26c47a259af670c66f03ec0115c0dc1c7593cb Mon Sep 17 00:00:00 2001 From: WeChat Date: Fri, 16 Sep 2016 19:53:19 +0800 Subject: [PATCH 21/49] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index afb159c..1d47602 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ 想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/tencent-wechat/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 +PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https://travis-ci.org/tencent-wechat/phxrpc) + # 总览 - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 From 8d331b930c2b54cc5614b52f139150752ce7026a Mon Sep 17 00:00:00 2001 From: liusifan Date: Sat, 17 Sep 2016 14:20:49 +0800 Subject: [PATCH 22/49] extend stacksize for epoll_io_uthread --- phxrpc/rpc/hsha_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phxrpc/rpc/hsha_server.cpp b/phxrpc/rpc/hsha_server.cpp index 3312226..17bfc77 100644 --- a/phxrpc/rpc/hsha_server.cpp +++ b/phxrpc/rpc/hsha_server.cpp @@ -588,7 +588,7 @@ void HshaServerIO :: RunForever() { HshaServerUnit :: HshaServerUnit(HshaServer * hsha_server, int idx, int worker_thread_count, Dispatch_t dispatch, void * args) : hsha_server_(hsha_server), - scheduler_(8 * 1024, 1000000, false), + scheduler_(32 * 1024, 1000000, false), hsha_server_io_(idx, &scheduler_, hsha_server_->config_, &data_flow_, &hsha_server_->hsha_server_stat_, &hsha_server_->hsha_server_qos_), worker_pool_(&scheduler_, worker_thread_count, &data_flow_, From b603ea07d9a9b22c9ebe32aa226b36ad803e47b5 Mon Sep 17 00:00:00 2001 From: liusifan Date: Sat, 17 Sep 2016 21:37:20 +0800 Subject: [PATCH 23/49] support daemonize --- codegen/phxrpc_pb2server.cpp | 11 +++++------ codegen/server_template.cpp | 8 ++++++-- phxrpc/Makefile | 2 +- phxrpc/rpc/client_config.cpp | 5 +++-- phxrpc/rpc/hsha_server.cpp | 2 +- phxrpc/rpc/server_base.h | 6 ++++++ third_party/protobuf | 1 - 7 files changed, 22 insertions(+), 13 deletions(-) delete mode 160000 third_party/protobuf diff --git a/codegen/phxrpc_pb2server.cpp b/codegen/phxrpc_pb2server.cpp index 53430bf..7676306 100644 --- a/codegen/phxrpc_pb2server.cpp +++ b/codegen/phxrpc_pb2server.cpp @@ -45,7 +45,6 @@ void PrintHelp(const char * program) { printf(" Usage: -f # Proto File\n"); printf(" -d # destination file dir\n"); printf(" -I # include path dir\n"); - printf(" -e # epoll server\n"); printf(" -v # print this screen\n"); printf("\n"); @@ -81,7 +80,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } @@ -97,7 +96,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } @@ -113,7 +112,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } @@ -129,7 +128,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } @@ -144,7 +143,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } } diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index 063c9ad..39404e3 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -53,7 +53,7 @@ void HttpDispatch( const phxrpc::HttpRequest & request, phxrpc::HttpResponse * r void showUsage( const char * program ) { printf( "\n" ); - printf( "Usage: %s [-c ] [-v]\n", program ); + printf( "Usage: %s [-c ] [-d] [-v]\n", program ); printf( "\n" ); exit( 0 ); @@ -65,17 +65,21 @@ void LogImpl(int priority, const char * format, va_list args) { int main( int argc, char * argv[] ) { const char * config_file = NULL; + bool daemonize = false;; extern char *optarg ; int c ; - while( ( c = getopt( argc, argv, "c:v" ) ) != EOF ) { + while( ( c = getopt( argc, argv, "c:vd" ) ) != EOF ) { switch ( c ) { case 'c' : config_file = optarg; break; + case 'd' : daemonize = true; break; case 'v' : default: showUsage( argv[ 0 ] ); break; } } + if( daemonize ) phxrpc::ServerUtils::Daemonize(); + assert(signal(SIGPIPE, SIG_IGN) != SIG_ERR); //set your logfunc diff --git a/phxrpc/Makefile b/phxrpc/Makefile index 15505fd..7185e22 100644 --- a/phxrpc/Makefile +++ b/phxrpc/Makefile @@ -12,7 +12,7 @@ LIB_FILE_OBJS = file/log_utils.o file/file_utils.o file/opt_map.o file/config.o LIB_RPC_OBJS = rpc/phxrpc.pb.o rpc/http_caller.o rpc/server_config.o rpc/client_config.o \ rpc/socket_stream_phxrpc.o rpc/uthread_caller.o rpc/client_monitor.o rpc/server_monitor.o \ - rpc/monitor_factory.o rpc/hsha_server.o \ + rpc/monitor_factory.o rpc/hsha_server.o rpc/server_base.o ifeq ($(OS),Darwin) CFLAGS += -I$(PHXRPC_ROOT)/plugin_darwin/network diff --git a/phxrpc/rpc/client_config.cpp b/phxrpc/rpc/client_config.cpp index a6ae018..d695c33 100644 --- a/phxrpc/rpc/client_config.cpp +++ b/phxrpc/rpc/client_config.cpp @@ -57,12 +57,13 @@ bool ClientConfig::Read(const char * config_file) { int count = 0; bool succ = true; succ &= config.ReadItem("Server", "ServerCount", &count); - succ &= config.ReadItem("Server", "PackageName", package_name_, sizeof(package_name_)); if (!succ) { - log(LOG_ERR, "Config::%s key ServerCount | PackageName not found", __func__); + log(LOG_ERR, "Config::%s key ServerCount not found", __func__); return false; } + config.ReadItem("Server", "PackageName", package_name_, sizeof(package_name_)); + for (int i = 0; i < count; i++) { char section[64] = { 0 }; snprintf(section, sizeof(section), "Server%d", i); diff --git a/phxrpc/rpc/hsha_server.cpp b/phxrpc/rpc/hsha_server.cpp index 17bfc77..5fbf2bc 100644 --- a/phxrpc/rpc/hsha_server.cpp +++ b/phxrpc/rpc/hsha_server.cpp @@ -588,7 +588,7 @@ void HshaServerIO :: RunForever() { HshaServerUnit :: HshaServerUnit(HshaServer * hsha_server, int idx, int worker_thread_count, Dispatch_t dispatch, void * args) : hsha_server_(hsha_server), - scheduler_(32 * 1024, 1000000, false), + scheduler_(64 * 1024, 1000000, false), hsha_server_io_(idx, &scheduler_, hsha_server_->config_, &data_flow_, &hsha_server_->hsha_server_stat_, &hsha_server_->hsha_server_qos_), worker_pool_(&scheduler_, worker_thread_count, &data_flow_, diff --git a/phxrpc/rpc/server_base.h b/phxrpc/rpc/server_base.h index 484d134..03b7a15 100644 --- a/phxrpc/rpc/server_base.h +++ b/phxrpc/rpc/server_base.h @@ -37,4 +37,10 @@ typedef struct tagDispatcherArgs { } }DispatcherArgs_t; +class ServerUtils { +public: + static void Daemonize(); +}; + } + diff --git a/third_party/protobuf b/third_party/protobuf deleted file mode 160000 index e8ae137..0000000 --- a/third_party/protobuf +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e8ae137c96444ea313485ed1118c5e43b2099cf1 From 995fa8e91c4bedf1597b85b6c3036743798ccf06 Mon Sep 17 00:00:00 2001 From: liusifan Date: Sat, 17 Sep 2016 21:40:09 +0800 Subject: [PATCH 24/49] create third_party --- build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.sh b/build.sh index 261df71..b522cee 100755 --- a/build.sh +++ b/build.sh @@ -2,6 +2,8 @@ set -e # exit immediately on error set -x # display all commands +mkdir -p third_party + cd third_party; if [ ! -f protobuf/bin/protoc ]; then From b7a01e803b338f42b1ea25dd1375760bb66fea2f Mon Sep 17 00:00:00 2001 From: liusifan Date: Sat, 17 Sep 2016 21:49:31 +0800 Subject: [PATCH 25/49] add --- phxrpc/rpc/server_base.cpp | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 phxrpc/rpc/server_base.cpp diff --git a/phxrpc/rpc/server_base.cpp b/phxrpc/rpc/server_base.cpp new file mode 100644 index 0000000..8d00f75 --- /dev/null +++ b/phxrpc/rpc/server_base.cpp @@ -0,0 +1,48 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include "server_base.h" + +#include +#include +#include + +namespace phxrpc { + +void ServerUtils :: Daemonize() { + int fd; + + if (fork() != 0) exit(0); /* parent exits */ + setsid(); /* create a new session */ + + /* Every output goes to /dev/null. If Redis is daemonized but + * the 'logfile' is set to 'stdout' in the configuration file + * it will not log at all. */ + if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > STDERR_FILENO) close(fd); + } +} + +} + From 1f2625c04eb57bf60979a61f3cf5685aca32ca74 Mon Sep 17 00:00:00 2001 From: liusifan Date: Sat, 17 Sep 2016 21:52:55 +0800 Subject: [PATCH 26/49] return make result --- build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sh b/build.sh index b522cee..d4e8044 100755 --- a/build.sh +++ b/build.sh @@ -25,3 +25,4 @@ cd .. make +exit $? From fd9b544afe643040e0268dad8eacb73c49232257 Mon Sep 17 00:00:00 2001 From: liusifan Date: Sun, 18 Sep 2016 00:58:59 +0800 Subject: [PATCH 27/49] convert ~ to getenv("HOME") in filepath --- phxrpc/file/file_utils.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/phxrpc/file/file_utils.cpp b/phxrpc/file/file_utils.cpp index cbc9c2b..6baee61 100644 --- a/phxrpc/file/file_utils.cpp +++ b/phxrpc/file/file_utils.cpp @@ -34,9 +34,17 @@ See the AUTHORS file for names of contributors. namespace phxrpc { bool FileUtils::ReadFile(const char * path, std::string * content) { + + char newpath[ 1024 ] = { 0 }; + if( '~' == path[0] ) { + snprintf( newpath, sizeof( newpath ), "%s%s", getenv( "HOME" ), path + 1 ); + } else { + snprintf( newpath, sizeof( newpath ), "%s", path ); + } + bool ret = false; - int fd = ::open(path, O_RDONLY); + int fd = ::open(newpath, O_RDONLY); if (fd >= 0) { struct stat file_stat; if (0 == fstat(fd, &file_stat)) { @@ -49,12 +57,12 @@ bool FileUtils::ReadFile(const char * path, std::string * content) { (unsigned long long) file_stat.st_size, errno, strerror(errno)); } } else { - phxrpc::log(LOG_ERR, "WARN: stat %s fail, errno %d, %s", path, errno, strerror(errno)); + phxrpc::log(LOG_ERR, "WARN: stat %s fail, errno %d, %s", newpath, errno, strerror(errno)); } close(fd); } else { - phxrpc::log(LOG_ERR, "WARN: open %s fail, errno %d, %s", path, errno, strerror(errno)); + phxrpc::log(LOG_ERR, "WARN: open %s fail, errno %d, %s", newpath, errno, strerror(errno)); } return ret; From 52ed931cbef2af37818dfecd8191f44ecb953f72 Mon Sep 17 00:00:00 2001 From: liusifan Date: Tue, 20 Sep 2016 21:30:37 +0800 Subject: [PATCH 28/49] keep whole ServiceArgs_t --- codegen/name_render.cpp | 8 ++++---- codegen/server_template.cpp | 3 ++- codegen/service_code_render.cpp | 8 ++++---- codegen/syntax_tree.cpp | 8 ++++---- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/codegen/name_render.cpp b/codegen/name_render.cpp index 9ec63b1..16cf1f0 100644 --- a/codegen/name_render.cpp +++ b/codegen/name_render.cpp @@ -72,8 +72,8 @@ const char * NameRender::GetMessageFileName(const char *name, char * dest, int s return dest; } -char * NameRender::ToLower(register char *s) { - register char *ret = s; +char * NameRender::ToLower(char *s) { + char *ret = s; for (; *s != '\0'; ++s) *s = tolower(*s); @@ -81,8 +81,8 @@ char * NameRender::ToLower(register char *s) { return ret; } -char * NameRender::ToUpper(register char *s) { - register char * ret = s; +char * NameRender::ToUpper(char *s) { + char * ret = s; for (; *s != '\0'; s++) *s = toupper(*s); diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index 39404e3..ad91a05 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -40,7 +40,7 @@ void HttpDispatch( const phxrpc::HttpRequest & request, phxrpc::HttpResponse * r ServiceArgs_t * service_args = (ServiceArgs_t *)(args->service_args); - $ServiceImplClass$ service( service_args ); + $ServiceImplClass$ service( * service_args ); $DispatcherClass$ dispatcher( service, args ); phxrpc::HttpDispatcher<$DispatcherClass$> http_dispatcher( @@ -260,6 +260,7 @@ lib$ClientFile$.a: $(CLI_OBJS) @($(RM) $(TARGETS)) @($(RM) *.o) @($(RM) phxrpc_*) + @($(RM) *.pb.*) )"; diff --git a/codegen/service_code_render.cpp b/codegen/service_code_render.cpp index 6af64c2..db37428 100644 --- a/codegen/service_code_render.cpp +++ b/codegen/service_code_render.cpp @@ -172,7 +172,7 @@ void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write) fprintf(write, "class %s : public %s\n", clasname, base_name); fprintf(write, "{\n"); fprintf(write, "public:\n"); - fprintf(write, " %s( ServiceArgs_t * app_args );\n", clasname); + fprintf(write, " %s( ServiceArgs_t & args );\n", clasname); fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); @@ -186,7 +186,7 @@ void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write) } fprintf(write, "private:\n"); - fprintf(write, " const %s & config_;\n", config_name); + fprintf(write, " ServiceArgs_t & args_;\n" ); fprintf(write, "};\n"); @@ -219,8 +219,8 @@ void ServiceCodeRender::GenerateServiceImplCpp(SyntaxTree * stree, FILE * write) name_render_.GetServiceImplClasname(stree->GetName(), clasname, sizeof(clasname)); name_render_.GetServerConfigClasname(stree->GetName(), config_name, sizeof(config_name)); - fprintf(write, "%s :: %s( ServiceArgs_t * app_args )\n", clasname, clasname); - fprintf(write, " : config_( *(app_args->config) )\n"); + fprintf(write, "%s :: %s( ServiceArgs_t & args )\n", clasname, clasname); + fprintf(write, " : args_( args )\n"); fprintf(write, "{\n"); fprintf(write, "}\n"); fprintf(write, "\n"); diff --git a/codegen/syntax_tree.cpp b/codegen/syntax_tree.cpp index 1f7fa0e..1897824 100644 --- a/codegen/syntax_tree.cpp +++ b/codegen/syntax_tree.cpp @@ -171,8 +171,8 @@ SyntaxFunc * SyntaxTree::FindFunc(const char * name) { return ret; } -char * SyntaxTree::ToLower(register char *s) { - register char *ret = s; +char * SyntaxTree::ToLower(char *s) { + char *ret = s; for (; *s != '\0'; ++s) *s = tolower(*s); @@ -180,8 +180,8 @@ char * SyntaxTree::ToLower(register char *s) { return ret; } -char * SyntaxTree::ToUpper(register char *s) { - register char * ret = s; +char * SyntaxTree::ToUpper(char *s) { + char * ret = s; for (; *s != '\0'; s++) *s = toupper(*s); From f4566e03d81094973e3d59193eed230cc37efee8 Mon Sep 17 00:00:00 2001 From: liusifan Date: Wed, 21 Sep 2016 13:22:36 +0800 Subject: [PATCH 29/49] add more log --- codegen/phxrpc_pb2client.cpp | 2 +- codegen/phxrpc_pb2tool.cpp | 6 +++--- phxrpc/rpc/client_config.cpp | 2 ++ phxrpc/rpc/http_caller.cpp | 7 +++++++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/codegen/phxrpc_pb2client.cpp b/codegen/phxrpc_pb2client.cpp index c658a78..2b7883c 100644 --- a/codegen/phxrpc_pb2client.cpp +++ b/codegen/phxrpc_pb2client.cpp @@ -140,7 +140,7 @@ void Proto2Client(const char * program, const char * proto_file, const char * di printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } } diff --git a/codegen/phxrpc_pb2tool.cpp b/codegen/phxrpc_pb2tool.cpp index e6e8438..4e5dc4f 100644 --- a/codegen/phxrpc_pb2tool.cpp +++ b/codegen/phxrpc_pb2tool.cpp @@ -105,7 +105,7 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } @@ -122,7 +122,7 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } @@ -139,7 +139,7 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat printf("\n%s: Build %s file ... done\n", program, filename); } else { - printf("\n%s: %s is exist, ip\n", program, filename); + printf("\n%s: %s is exist, skip\n", program, filename); } } } diff --git a/phxrpc/rpc/client_config.cpp b/phxrpc/rpc/client_config.cpp index d695c33..41d5cbf 100644 --- a/phxrpc/rpc/client_config.cpp +++ b/phxrpc/rpc/client_config.cpp @@ -99,6 +99,8 @@ const Endpoint_t * ClientConfig::GetRandom() const { if ( client_monitor_.get() ) { client_monitor_->GetEndpointFail(); } + + log( LOG_ERR, "GetRandom fail, list.size %lu", endpoints_.size() ); } return ret; } diff --git a/phxrpc/rpc/http_caller.cpp b/phxrpc/rpc/http_caller.cpp index c177ee8..44d1061 100644 --- a/phxrpc/rpc/http_caller.cpp +++ b/phxrpc/rpc/http_caller.cpp @@ -27,6 +27,7 @@ See the AUTHORS file for names of contributors. #include "phxrpc/network.h" #include "phxrpc/http.h" +#include "phxrpc/file.h" namespace phxrpc { @@ -77,6 +78,7 @@ int HttpCaller::Call(const google::protobuf::MessageLite & request, google::prot response_.GetContent().size(), call_begin, Timer::GetSteadyClockMS() ); if (ret != 0) { + phxrpc::log( LOG_ERR, "ERROR: httpcall %d", ret ); return ret; } @@ -86,6 +88,11 @@ int HttpCaller::Call(const google::protobuf::MessageLite & request, google::prot const char * result = response_.GetHeaderValue(HttpMessage::HEADER_X_PHXRPC_RESULT); ret = atoi(NULL == result ? "-1" : result); + + if( ret < 0 ) { + phxrpc::log( LOG_ERR, "ERROR: httpcall( %s ) %d", request_.GetURI(), ret ); + } + return ret; } From 04c157a1cd17d8c5a9a0e44e75ac411e894ecd9d Mon Sep 17 00:00:00 2001 From: liusifan Date: Thu, 22 Sep 2016 03:44:38 +0800 Subject: [PATCH 30/49] support full log functions --- .gitignore | 11 ++++++++++ codegen/server_template.cpp | 31 ++++++++++++++++++--------- phxrpc/file/log_utils.cpp | 41 +++++++++++++++++++++++++++++++++--- phxrpc/file/log_utils.h | 9 +++++++- phxrpc/rpc/server_config.cpp | 17 +++++++++++++++ phxrpc/rpc/server_config.h | 7 ++++++ 6 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..667fe51 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.o +*.a +*.pb.* +*_dispatcher.* +*_stub.* +*_service.* +*_tool.* +*_main +third_party/* +sbin/* + diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index ad91a05..6b3014a 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -53,25 +53,23 @@ void HttpDispatch( const phxrpc::HttpRequest & request, phxrpc::HttpResponse * r void showUsage( const char * program ) { printf( "\n" ); - printf( "Usage: %s [-c ] [-d] [-v]\n", program ); + printf( "Usage: %s [-c ] [-d] [-l ] [-v]\n", program ); printf( "\n" ); exit( 0 ); } -void LogImpl(int priority, const char * format, va_list args) { - //or implement your logmode here -} - int main( int argc, char * argv[] ) { const char * config_file = NULL; bool daemonize = false;; + int log_level = -1; extern char *optarg ; int c ; - while( ( c = getopt( argc, argv, "c:vd" ) ) != EOF ) { + while( ( c = getopt( argc, argv, "c:vl:d" ) ) != EOF ) { switch ( c ) { case 'c' : config_file = optarg; break; case 'd' : daemonize = true; break; + case 'l' : log_level = atoi( optarg ); break; case 'v' : default: showUsage( argv[ 0 ] ); break; @@ -82,19 +80,28 @@ int main( int argc, char * argv[] ) { assert(signal(SIGPIPE, SIG_IGN) != SIG_ERR); - //set your logfunc - //phxrpc::setvlog(LogImpl); + //set customize log/monitor + //phxrpc::setlog(openlog, closelog, vlog); //phxrpc::MonitorFactory::SetFactory( new YourSelfsMonitorFactory() ); if( NULL == config_file ) showUsage( argv[0] ); + $ServerConfigClass$ config; if( ! config.Read( config_file ) ) showUsage( argv[0] ); + if( log_level > 0 ) config.GetHshaServerConfig().SetLogLevel( log_level ); + + phxrpc::openlog( argv[0], config.GetHshaServerConfig().GetLogDir(), + config.GetHshaServerConfig().GetLogLevel() ); + ServiceArgs_t service_args; service_args.config = &config; phxrpc::HshaServer server( config.GetHshaServerConfig(), HttpDispatch, &service_args ); server.RunForever(); + + phxrpc::closelog(); + return 0; } @@ -116,7 +123,7 @@ class $ServerConfigClass$ bool Read( const char * config_file ); - const phxrpc::HshaServerConfig & GetHshaServerConfig(); + phxrpc::HshaServerConfig & GetHshaServerConfig(); private: phxrpc::HshaServerConfig ep_server_config_; @@ -151,7 +158,7 @@ bool $ServerConfigClass$ :: Read( const char * config_file ) return ret; } -const phxrpc::HshaServerConfig & $ServerConfigClass$ :: GetHshaServerConfig() +phxrpc::HshaServerConfig & $ServerConfigClass$ :: GetHshaServerConfig() { return ep_server_config_; } @@ -174,6 +181,10 @@ MaxQueueLength = 20480 FastRejectThresholdMS = 20 FastRejectAdjustRate = 5 +[Log] +LogDir = ~/log +LogLevel = 3 + [ServerTimeout] SocketTimeoutMS = 5000 diff --git a/phxrpc/file/log_utils.cpp b/phxrpc/file/log_utils.cpp index 2da5336..ef01a2e 100644 --- a/phxrpc/file/log_utils.cpp +++ b/phxrpc/file/log_utils.cpp @@ -22,20 +22,55 @@ See the AUTHORS file for names of contributors. #include "log_utils.h" #include +#include +#include namespace phxrpc { -static vlog_t global_vlog = vsyslog; +static openlog_t global_openlog_ = NULL; +static closelog_t global_closelog_ = ::closelog; +static vlog_t global_vlog_ = vsyslog; +static int global_priority_ = LOG_ERR; + +void openlog(const char * argv0, const char * log_dir, int priority) { + + char new_path[ 1024 ] = { 0 }; + if( '~' == log_dir[0] ) { + snprintf( new_path, sizeof( new_path ), "%s%s", getenv( "HOME" ), log_dir + 1 ); + } else { + snprintf( new_path, sizeof( new_path ), "%s", log_dir ); + } + + global_priority_ = priority; + if( NULL != global_openlog_ ) { + global_openlog_( argv0, new_path, priority ); + } else { + ::openlog( argv0, LOG_CONS | LOG_PID, priority ); + } +} + +void closelog() { + global_closelog_(); +} void log(int priority, const char * format, ...) { + + if( priority > global_priority_ ) return; + va_list args; va_start(args, format); - global_vlog(priority, format, args); + global_vlog_(priority, format, args); va_end(args); } void setvlog(vlog_t vlog) { - global_vlog = vlog; + global_vlog_ = vlog; +} + +void setlog(openlog_t open_log, closelog_t close_log, vlog_t vlog) { + global_openlog_ = open_log; + global_closelog_ = close_log; + global_vlog_ = vlog; } } diff --git a/phxrpc/file/log_utils.h b/phxrpc/file/log_utils.h index d8fa426..d4b65a6 100644 --- a/phxrpc/file/log_utils.h +++ b/phxrpc/file/log_utils.h @@ -26,11 +26,18 @@ See the AUTHORS file for names of contributors. namespace phxrpc { +extern void openlog( const char * argv0, const char * log_dir, int priority ); +extern void closelog(); + extern void log(int priority, const char * format, ...) __attribute__((format(printf, 2, 3))); +typedef void (*openlog_t)(const char*, const char *, int); +typedef void (*closelog_t)(); + typedef void (*vlog_t)(int, const char *, va_list); -extern void setvlog(vlog_t vlog); +extern void setvlog(vlog_t); +extern void setlog(openlog_t, closelog_t, vlog_t); } ; diff --git a/phxrpc/rpc/server_config.cpp b/phxrpc/rpc/server_config.cpp index 393952e..d3d79aa 100644 --- a/phxrpc/rpc/server_config.cpp +++ b/phxrpc/rpc/server_config.cpp @@ -48,6 +48,8 @@ bool ServerConfig::Read(const char * config_file) { succ &= config.ReadItem("Server", "Port", &port_); succ &= config.ReadItem("Server", "PackageName", package_name_, sizeof(package_name_)); config.ReadItem("Server", "MaxThreads", &max_threads_, 20); + config.ReadItem("Log", "LogDir", log_dir_, sizeof(log_dir_), "~/log"); + config.ReadItem("Log", "LogLevel", &log_level_, LOG_ERR); config.ReadItem("ServerTimeout", "SocketTimeoutMS", &socket_timeout_ms_, 5000); if (succ) { @@ -102,6 +104,21 @@ const char * ServerConfig :: GetPackageName() const { return package_name_; } +const char * ServerConfig :: GetLogDir() const +{ + return log_dir_; +} + +void ServerConfig :: SetLogLevel( int log_level ) +{ + log_level_ = log_level; +} + +int ServerConfig :: GetLogLevel() const +{ + return log_level_; +} + ////////////////////////////////////////////////////// HshaServerConfig :: HshaServerConfig() diff --git a/phxrpc/rpc/server_config.h b/phxrpc/rpc/server_config.h index 9a995b5..b736510 100644 --- a/phxrpc/rpc/server_config.h +++ b/phxrpc/rpc/server_config.h @@ -51,12 +51,19 @@ class ServerConfig { void SetPackageName(const char * package_name); const char * GetPackageName() const; + const char * GetLogDir() const; + + void SetLogLevel( int log_level ); + int GetLogLevel() const; + private: char bind_ip_[32]; int port_; int max_threads_; int socket_timeout_ms_; char package_name_[64]; + char log_dir_[128]; + int log_level_; }; class HshaServerConfig : public ServerConfig { From b5fdcf156981fadf33d9e77364f4e77c19edce60 Mon Sep 17 00:00:00 2001 From: liusifan Date: Thu, 22 Sep 2016 21:13:08 +0800 Subject: [PATCH 31/49] fix compiler warning --- .gitignore | 2 +- phxrpc/file/opt_map.cpp | 2 +- phxrpc/http/http_proto.cpp | 4 ++-- phxrpc/rpc/hsha_server.cpp | 12 ++++++++---- phxrpc/rpc/hsha_server.h | 3 --- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 667fe51..0820720 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ *_main third_party/* sbin/* - +sample/* diff --git a/phxrpc/file/opt_map.cpp b/phxrpc/file/opt_map.cpp index e9b72e7..9bd8c59 100644 --- a/phxrpc/file/opt_map.cpp +++ b/phxrpc/file/opt_map.cpp @@ -62,7 +62,7 @@ size_t OptMap::GetNonOptCount() { } const char * OptMap::GetNonOpt(size_t index) { - if (index >= 0 && index < non_opt_.size()) { + if (index > 0 && index < non_opt_.size()) { return non_opt_[index].c_str(); } diff --git a/phxrpc/http/http_proto.cpp b/phxrpc/http/http_proto.cpp index 6cf7748..c48c4e3 100644 --- a/phxrpc/http/http_proto.cpp +++ b/phxrpc/http/http_proto.cpp @@ -110,7 +110,7 @@ int HttpProto::SendReqHeader(BaseTcpStream & socket, const char * method, const socket << name << ": " << val << "\r\n"; } - if (req.GetContent().size() >= 0) { + if (req.GetContent().size() > 0) { if (NULL == req.GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH)) { socket << HttpMessage::HEADER_CONTENT_LENGTH << ": " << req.GetContent().size() << "\r\n"; } @@ -166,7 +166,7 @@ int HttpProto::SendResp(BaseTcpStream & socket, const HttpResponse & resp) { socket << resp.GetHeaderName(i) << ": " << resp.GetHeaderValue(i) << "\r\n"; } - if (resp.GetContent().size() >= 0) { + if (resp.GetContent().size() > 0) { if (NULL == resp.GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH)) { socket << HttpMessage::HEADER_CONTENT_LENGTH << ": " << resp.GetContent().size() << "\r\n"; } diff --git a/phxrpc/rpc/hsha_server.cpp b/phxrpc/rpc/hsha_server.cpp index 5fbf2bc..814b4a0 100644 --- a/phxrpc/rpc/hsha_server.cpp +++ b/phxrpc/rpc/hsha_server.cpp @@ -108,7 +108,7 @@ int HshaServerStat :: TimeCost :: Cost() { } HshaServerStat :: HshaServerStat(const HshaServerConfig * config, ServerMonitorPtr hsha_server_monitor ) : - config_(config), thread_(&HshaServerStat::CalFunc, this), break_out_(false), + thread_(&HshaServerStat::CalFunc, this), break_out_(false), hsha_server_monitor_(hsha_server_monitor) { hold_fds_ = 0; accepted_fds_ = 0; @@ -436,8 +436,8 @@ WorkerPool :: ~WorkerPool() { HshaServerIO :: HshaServerIO(int idx, UThreadEpollScheduler * scheduler, const HshaServerConfig * config, DataFlow * data_flow, HshaServerStat * hsha_server_stat, HshaServerQos * hsha_server_qos) - : idx_(idx), scheduler_(scheduler), config_(config), - data_flow_(data_flow), listen_fd_(-1), hsha_server_stat_(hsha_server_stat), + : scheduler_(scheduler), config_(config), + data_flow_(data_flow), hsha_server_stat_(hsha_server_stat), hsha_server_qos_(hsha_server_qos){ } @@ -588,7 +588,11 @@ void HshaServerIO :: RunForever() { HshaServerUnit :: HshaServerUnit(HshaServer * hsha_server, int idx, int worker_thread_count, Dispatch_t dispatch, void * args) : hsha_server_(hsha_server), - scheduler_(64 * 1024, 1000000, false), +#ifndef __APPLE__ + scheduler_(8 * 1024, 1000000, false), +#else + scheduler_(32 * 1024, 1000000, false), +#endif hsha_server_io_(idx, &scheduler_, hsha_server_->config_, &data_flow_, &hsha_server_->hsha_server_stat_, &hsha_server_->hsha_server_qos_), worker_pool_(&scheduler_, worker_thread_count, &data_flow_, diff --git a/phxrpc/rpc/hsha_server.h b/phxrpc/rpc/hsha_server.h index dfc683d..23608c6 100644 --- a/phxrpc/rpc/hsha_server.h +++ b/phxrpc/rpc/hsha_server.h @@ -102,7 +102,6 @@ class HshaServerStat { friend class Worker; friend class HshaServerQos; friend class HshaServerAcceptor; - const HshaServerConfig * config_; std::mutex mutex_; std::condition_variable cv_; std::thread thread_; @@ -252,11 +251,9 @@ class HshaServerIO { UThreadSocket_t * ActiveSocketFunc(); private: - int idx_; UThreadEpollScheduler * scheduler_; const HshaServerConfig * config_; DataFlow * data_flow_; - int listen_fd_; HshaServerStat * hsha_server_stat_; HshaServerQos * hsha_server_qos_; From f05f2f19b28f9c2c69e720ee24b4330e3f61c6cf Mon Sep 17 00:00:00 2001 From: Haochuan Cui Date: Tue, 18 Oct 2016 15:43:36 +0800 Subject: [PATCH 32/49] Update uthread_epoll.cpp --- phxrpc/network/uthread_epoll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phxrpc/network/uthread_epoll.cpp b/phxrpc/network/uthread_epoll.cpp index edbf491..08eb83b 100644 --- a/phxrpc/network/uthread_epoll.cpp +++ b/phxrpc/network/uthread_epoll.cpp @@ -95,7 +95,7 @@ void EpollNotifier :: Func() { void EpollNotifier :: Notify() { ssize_t write_len = write(pipe_fds_[1], (void *)"a", 1); if (write_len < 0) { - log(LOG_ERR, "%s write err", __func__); + //log(LOG_ERR, "%s write err", __func__); } } From b02d7073834e8dd98ec60228068979d51f6af154 Mon Sep 17 00:00:00 2001 From: liusifan Date: Tue, 8 Nov 2016 23:41:12 +0800 Subject: [PATCH 33/49] The origin code cannot read the first section if the section is the first line of the config file. Add empty line to the head of config buffer to fix it. --- phxrpc/file/config.cpp | 63 +++++++++++++++++++++++++++++++++++++++++- phxrpc/file/config.h | 5 ++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/phxrpc/file/config.cpp b/phxrpc/file/config.cpp index 12257da..7ef95d4 100644 --- a/phxrpc/file/config.cpp +++ b/phxrpc/file/config.cpp @@ -39,7 +39,14 @@ Config :: ~Config() { } bool Config::InitConfig(const char * path) { - return FileUtils::ReadFile(path, &content_); + bool ret = FileUtils::ReadFile(path, &content_); + if( ret ) content_.insert( 0, "\n" ); + return ret; +} + +void Config::SetContent(const std::string & content) { + content_.clear(); + content_.append( "\n" ).append( content ); } bool Config::ReadItem(const char * section, const char * key, int * value) { @@ -131,5 +138,59 @@ bool Config::ReadItem(const char * section, const char * key, char * value, size return ret; } +int Config::TrimCStr( char * src_str ) +{ + int len = 0; + char *pos = 0; + + len = strlen ( src_str ) ; + while ( len > 0 && isspace( src_str [len - 1] ) ) + len--; + src_str [len] = '\0' ; + for ( pos = src_str; isspace(*pos); pos ++ ) + len--; + if ( pos != src_str ) + memmove ( src_str, pos, len + 1 ) ; + return 0; +} + +bool Config::GetSection(const char * name, + std::vector * section) { + + char tmp_section[ 128 ] = { 0 }; + snprintf(tmp_section, sizeof( tmp_section ), "\n[%s]", name); + + char line[ 1024 ] = { 0 }; + + const char * pos = strstr( content_.c_str(), tmp_section ); + if(!pos) { + return false; + } else { + ++pos; + } + + for( ; NULL != pos; ) + { + pos = strchr( pos, '\n' ); + + if( NULL == pos ) break; + pos++; + + if( '[' == *pos ) break; + + if( ';' == *pos || '#' == *pos ) continue; + + strncpy( line, pos, sizeof( line ) - 1 ); + + char * tmp_pos = strchr( line, '\n' ); + if( NULL != tmp_pos ) *tmp_pos = '\0'; + + TrimCStr( line ); + + if( '\0' != line[0] ) section->push_back( line ); + } + return true; +} + } diff --git a/phxrpc/file/config.h b/phxrpc/file/config.h index ddf04db..9c27c0d 100644 --- a/phxrpc/file/config.h +++ b/phxrpc/file/config.h @@ -22,6 +22,7 @@ See the AUTHORS file for names of contributors. #pragma once #include +#include namespace phxrpc { @@ -31,13 +32,17 @@ class Config { ~Config(); bool InitConfig(const char * path); + void SetContent(const std::string & content); bool ReadItem(const char * section, const char * key, char * value, size_t size, const char * default_value); bool ReadItem(const char * section, const char * key, int * value, const int default_value); bool ReadItem(const char * section, const char * key, char * value, size_t size); bool ReadItem(const char * section, const char * key, int * value); + bool GetSection(const char * name, + std::vector * section); private: + int TrimCStr( char * src_str ); std::string content_; }; From 1e7914eeca71551446c978a43b1d4240ec40b1dc Mon Sep 17 00:00:00 2001 From: Haochuan Cui Date: Thu, 5 Jan 2017 14:09:12 +0800 Subject: [PATCH 34/49] Update http_msg.cpp --- phxrpc/http/http_msg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phxrpc/http/http_msg.cpp b/phxrpc/http/http_msg.cpp index 7b3be5f..518e874 100644 --- a/phxrpc/http/http_msg.cpp +++ b/phxrpc/http/http_msg.cpp @@ -64,7 +64,7 @@ void HttpMessage::AppendContent(const void * content, int length, int max_length int total = content_.size() + length; total = total > max_length ? total : max_length; - content_.reserve(total); + //content_.reserve(total); content_.append((char*) content, length); } From 644e270183d1972f3b0cf5b81ac27565bc6db172 Mon Sep 17 00:00:00 2001 From: lynncui00 Date: Fri, 6 Jan 2017 15:27:53 +0800 Subject: [PATCH 35/49] support uthread worker and auto gen uthread client --- AUTHORS | 2 +- codegen/client_code_render.cpp | 73 +++++++--- codegen/client_code_render.h | 7 +- codegen/client_template.cpp | 105 +++++++++++++++ codegen/client_template.h | 6 + codegen/phxrpc_pb2client.cpp | 56 +++++++- codegen/phxrpc_pb2server.cpp | 18 ++- codegen/phxrpc_pb2service.cpp | 14 +- codegen/server_code_render.cpp | 28 +++- codegen/server_code_render.h | 6 +- codegen/server_template.cpp | 205 +++++++++++++++++++++++++++++ codegen/server_template.h | 10 +- codegen/service_code_render.cpp | 25 +++- codegen/service_code_render.h | 4 +- phxrpc/network/uthread_epoll.cpp | 19 ++- phxrpc/network/uthread_epoll.h | 13 +- phxrpc/network/uthread_runtime.cpp | 4 + phxrpc/network/uthread_runtime.h | 1 + phxrpc/rpc/hsha_server.cpp | 163 ++++++++++++++++++----- phxrpc/rpc/hsha_server.h | 46 ++++++- phxrpc/rpc/server_base.h | 10 +- phxrpc/rpc/server_config.cpp | 24 +++- phxrpc/rpc/server_config.h | 8 ++ phxrpc/rpc/thread_queue.h | 12 ++ 24 files changed, 750 insertions(+), 109 deletions(-) diff --git a/AUTHORS b/AUTHORS index a337409..000cc63 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,7 +4,7 @@ Tencent Inc. Sifan Liu -Haochuan Cui +Haochuan Cui Duokai Huang diff --git a/codegen/client_code_render.cpp b/codegen/client_code_render.cpp index 921784c..8cdb4a0 100644 --- a/codegen/client_code_render.cpp +++ b/codegen/client_code_render.cpp @@ -196,7 +196,7 @@ void ClientCodeRender::GenerateStubFunc(SyntaxTree * stree, SyntaxFunc * func, F fprintf(write, "\n"); } -void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write) { +void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { char filename[128] = { 0 }; name_render_.GetClientFileName(stree->GetName(), filename, sizeof(filename)); @@ -218,7 +218,7 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write) { SyntaxFuncVector::iterator fit = flist->begin(); for (; flist->end() != fit; ++fit) { std::string buffer; - GetClienfuncDeclaration(stree, &(*fit), 1, &buffer); + GetClienfuncDeclaration(stree, &(*fit), 1, &buffer, is_uthread_mode); declarations.append(" ").append(buffer).append(";\n\n"); @@ -226,7 +226,7 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write) { SyntaxFunc echo_func = *fit; echo_func.SetName("PhxBatchEcho"); std::string buffer; - GetClienfuncDeclaration(stree, &echo_func, 1, &buffer); + GetClienfuncDeclaration(stree, &echo_func, 1, &buffer, is_uthread_mode); declarations.append(" ").append(buffer).append(";\n\n"); } @@ -239,11 +239,24 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write) { name_render_.GetClientClasnameLower(stree->GetName(), client_class_lower, sizeof(client_class_lower)); name_render_.GetMessageFileName(stree->GetProtoFile(), message_file, sizeof(message_file)); - std::string content(PHXRPC_CLIENT_HPP_TEMPLATE); + string client_class_str = string(client_class); + string client_class_lower_str = string(client_class_lower); + if (is_uthread_mode) { + client_class_str += "UThread"; + client_class_lower_str += "uthread"; + } + + std::string content; + if (!is_uthread_mode) { + content = PHXRPC_CLIENT_HPP_TEMPLATE; + } else { + content = PHXRPC_UTHREAD_CLIENT_HPP_TEMPLATE; + } + StrTrim(&content); StrReplaceAll(&content, "$MessageFile$", message_file); - StrReplaceAll(&content, "$ClientClass$", client_class); - StrReplaceAll(&content, "$ClientClassLower$", client_class_lower); + StrReplaceAll(&content, "$ClientClass$", client_class_str.c_str()); + StrReplaceAll(&content, "$ClientClassLower$", client_class_lower_str.c_str()); StrReplaceAll(&content, "$ClientClassFuncDeclarations$", declarations); fprintf(write, "%s", content.c_str()); @@ -251,7 +264,7 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); } -void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write) { +void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { char client_class[128] = { 0 }, client_file[128] = { 0 }; char client_class_lower[128] = { 0 }; char stub_class[128] = { 0 }, stub_file[128] = { 0 }; @@ -261,6 +274,13 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write) { name_render_.GetStubClasname(stree->GetName(), stub_class, sizeof(stub_class)); name_render_.GetStubFileName(stree->GetName(), stub_file, sizeof(stub_file)); + string client_class_str = string(client_class); + string client_class_lower_str = string(client_class_lower); + if (is_uthread_mode) { + client_class_str += "UThread"; + client_class_lower_str += "uthread"; + } + std::string buffer; name_render_.GetCopyright("phxrpc_pb2client", stree->GetProtoFile(), &buffer, false); @@ -276,15 +296,20 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write) { SyntaxFuncVector::iterator fit = flist->begin(); for (; flist->end() != fit; ++fit) { std::string buffer; - GetClienfuncDeclaration(stree, &(*fit), 0, &buffer); + GetClienfuncDeclaration(stree, &(*fit), 0, &buffer, is_uthread_mode); functions.append(buffer).append("\n"); - std::string content = PHXRPC_CLIENT_FUNC_TEMPLATE; + std::string content; + if (!is_uthread_mode) { + content = PHXRPC_CLIENT_FUNC_TEMPLATE; + } else { + content = PHXRPC_UTHREAD_CLIENT_FUNC_TEMPLATE; + } StrTrim(&content); - StrReplaceAll(&content, "$ClientClass$", client_class); - StrReplaceAll(&content, "$ClientClassLower$", client_class_lower); + StrReplaceAll(&content, "$ClientClass$", client_class_str.c_str()); + StrReplaceAll(&content, "$ClientClassLower$", client_class_lower_str.c_str()); StrReplaceAll(&content, "$StubClass$", stub_class); StrReplaceAll(&content, "$Func$", fit->GetName()); @@ -295,15 +320,15 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write) { echo_func.SetName("PhxBatchEcho"); std::string buffer; - GetClienfuncDeclaration(stree, &echo_func, 0, &buffer); + GetClienfuncDeclaration(stree, &echo_func, 0, &buffer, is_uthread_mode); functions.append(buffer).append("\n"); std::string content = PHXRPC_BATCH_CLIENT_FUNC_TEMPLATE; StrTrim(&content); - StrReplaceAll(&content, "$ClientClass$", client_class); - StrReplaceAll(&content, "$ClientClassLower$", client_class_lower); + StrReplaceAll(&content, "$ClientClass$", client_class_str.c_str()); + StrReplaceAll(&content, "$ClientClassLower$", client_class_lower_str.c_str()); StrReplaceAll(&content, "$StubClass$", stub_class); StrReplaceAll(&content, "$Func$", echo_func.GetName()); @@ -312,13 +337,19 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write) { } } - std::string content(PHXRPC_CLIENT_CPP_TEMPLATE); + std::string content; + if (!is_uthread_mode) { + content = PHXRPC_CLIENT_CPP_TEMPLATE; + } else { + content = PHXRPC_UTHREAD_CLIENT_CPP_TEMPLATE; + } + StrTrim(&content); StrReplaceAll(&content, "$PackageName$", stree->GetPackageName() ); StrReplaceAll(&content, "$ClientFile$", client_file); StrReplaceAll(&content, "$StubFile$", stub_file); - StrReplaceAll(&content, "$ClientClass$", client_class); - StrReplaceAll(&content, "$ClientClassLower$", client_class_lower); + StrReplaceAll(&content, "$ClientClass$", client_class_str); + StrReplaceAll(&content, "$ClientClassLower$", client_class_lower_str.c_str()); StrReplaceAll(&content, "$ClientClassFuncs$", functions); fprintf(write, "%s", content.c_str()); @@ -327,15 +358,19 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write) { } void ClientCodeRender::GetClienfuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, - std::string * result) { + std::string * result, const bool is_uthread_mode) { char clasname[128] = { 0 }, type_name[128] = { 0 }; name_render_.GetClientClasname(stree->GetName(), clasname, sizeof(clasname)); + string clasname_str = string(clasname); + if (is_uthread_mode) { + clasname_str += "UThread"; + } if (is_header) { phxrpc::StrAppendFormat(result, "int %s( ", func->GetName()); } else { - phxrpc::StrAppendFormat(result, "int %s :: %s( ", clasname, func->GetName()); + phxrpc::StrAppendFormat(result, "int %s :: %s( ", clasname_str.c_str(), func->GetName()); } name_render_.GetMessageClasname(func->GetReq()->GetType(), type_name, sizeof(type_name)); diff --git a/codegen/client_code_render.h b/codegen/client_code_render.h index 0203bdc..d9e7a1c 100755 --- a/codegen/client_code_render.h +++ b/codegen/client_code_render.h @@ -39,9 +39,9 @@ class ClientCodeRender { void GenerateStubCpp(SyntaxTree * stree, FILE * write); - void GenerateClientHpp(SyntaxTree * stree, FILE * write); + void GenerateClientHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); - void GenerateClientCpp(SyntaxTree * stree, FILE * write); + void GenerateClientCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); void GenerateClientEtc(SyntaxTree * stree, FILE * write); @@ -51,7 +51,8 @@ class ClientCodeRender { void GenerateStubFunc(SyntaxTree * stree, SyntaxFunc * func, FILE * write); - void GetClienfuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, std::string * result); + void GetClienfuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, std::string * result, + const bool is_uthread_mode); private: NameRender & name_render_; diff --git a/codegen/client_template.cpp b/codegen/client_template.cpp index c7f575a..24f9904 100644 --- a/codegen/client_template.cpp +++ b/codegen/client_template.cpp @@ -43,6 +43,34 @@ class $ClientClass$ ////////////////////////////////////////////////////////////////////// +const char * PHXRPC_UTHREAD_CLIENT_HPP_TEMPLATE = + R"( + +#include "$MessageFile$.h" +#include "phxrpc/rpc.h" +#include "phxrpc/network.h" + +class $ClientClass$ +{ +public: + static bool Init( const char * config_file ); + + static const char * GetPackageName(); + +public: + $ClientClass$(phxrpc::UThreadEpollScheduler * uthread_scheduler); + ~$ClientClass$(); + +$ClientClassFuncDeclarations$ + +private: + phxrpc::UThreadEpollScheduler * uthread_scheduler_; +}; + +)"; + +////////////////////////////////////////////////////////////////////// + const char * PHXRPC_CLIENT_CPP_TEMPLATE = R"( @@ -95,6 +123,59 @@ const char * $ClientClass$ :: GetPackageName() { ////////////////////////////////////////////////////////////////////// +const char * PHXRPC_UTHREAD_CLIENT_CPP_TEMPLATE = + R"( + +#include +#include +#include +#include + +#include "$ClientFile$_uthread.h" +#include "$StubFile$.h" + +#include "phxrpc/rpc.h" + +static phxrpc::ClientConfig global_$ClientClassLower$_config_; +static phxrpc::ClientMonitorPtr global_$ClientClassLower$_monitor_; + +bool $ClientClass$ :: Init( const char * config_file ) +{ + return global_$ClientClassLower$_config_.Read( config_file ); +} + +const char * $ClientClass$ :: GetPackageName() { + const char * ret = global_$ClientClassLower$_config_.GetPackageName(); + if (strlen(ret) == 0) { + ret = "$PackageName$"; + } + return ret; +} + +$ClientClass$ :: $ClientClass$(phxrpc::UThreadEpollScheduler * uthread_scheduler) +{ + uthread_scheduler_ = uthread_scheduler; + static std::mutex monitor_mutex; + if ( !global_$ClientClassLower$_monitor_.get() ) { + monitor_mutex.lock(); + if ( !global_$ClientClassLower$_monitor_.get() ) { + global_$ClientClassLower$_monitor_ = phxrpc::MonitorFactory::GetFactory() + ->CreateClientMonitor( GetPackageName() ); + } + global_$ClientClassLower$_config_.SetClientMonitor( global_$ClientClassLower$_monitor_ ); + monitor_mutex.unlock(); + } +} + +$ClientClass$ :: ~$ClientClass$() +{ +} + +$ClientClassFuncs$ +)"; + +////////////////////////////////////////////////////////////////////// + const char * PHXRPC_CLIENT_FUNC_TEMPLATE = R"( { @@ -119,6 +200,30 @@ const char * PHXRPC_CLIENT_FUNC_TEMPLATE = ////////////////////////////////////////////////////////////////////// +const char * PHXRPC_UTHREAD_CLIENT_FUNC_TEMPLATE = + R"( +{ + const phxrpc::Endpoint_t * ep = global_$ClientClassLower$_config_.GetRandom(); + + if(uthread_scheduler_ != nullptr && ep != nullptr) { + phxrpc::UThreadTcpStream socket; + bool open_ret = phxrpc::PhxrpcTcpUtils::Open(uthread_scheduler_, &socket, ep->ip, ep->port, + global_$ClientClassLower$_config_.GetConnectTimeoutMS(), + *(global_$ClientClassLower$_monitor_.get())); + if ( open_ret ) { + socket.SetTimeout(global_$ClientClassLower$_config_.GetSocketTimeoutMS()); + + $StubClass$ stub(socket, *(global_$ClientClassLower$_monitor_.get())); + return stub.$Func$(req, resp); + } + } + + return -1; +} +)"; + +////////////////////////////////////////////////////////////////////// + const char * PHXRPC_BATCH_CLIENT_FUNC_TEMPLATE = R"( { diff --git a/codegen/client_template.h b/codegen/client_template.h index 5f7e36b..0d6c1c7 100644 --- a/codegen/client_template.h +++ b/codegen/client_template.h @@ -22,7 +22,13 @@ See the AUTHORS file for names of contributors. #pragma once extern const char * PHXRPC_CLIENT_HPP_TEMPLATE; +extern const char * PHXRPC_UTHREAD_CLIENT_HPP_TEMPLATE; + extern const char * PHXRPC_CLIENT_CPP_TEMPLATE; +extern const char * PHXRPC_UTHREAD_CLIENT_CPP_TEMPLATE; + extern const char * PHXRPC_CLIENT_FUNC_TEMPLATE; +extern const char * PHXRPC_UTHREAD_CLIENT_FUNC_TEMPLATE; + extern const char * PHXRPC_BATCH_CLIENT_FUNC_TEMPLATE; extern const char * PHXRPC_CLIENT_ETC_TEMPLATE; diff --git a/codegen/phxrpc_pb2client.cpp b/codegen/phxrpc_pb2client.cpp index 2b7883c..6eeeebb 100644 --- a/codegen/phxrpc_pb2client.cpp +++ b/codegen/phxrpc_pb2client.cpp @@ -50,7 +50,7 @@ void PrintHelp(const char * program) { } void Proto2Client(const char * program, const char * proto_file, const char * dir_path, - const std::vector & include_list) { + const std::vector & include_list, const bool is_uthread_mode) { SyntaxTree syntax_tree; int ret = ProtoUtils::Parse(proto_file, &syntax_tree, include_list); @@ -89,6 +89,7 @@ void Proto2Client(const char * program, const char * proto_file, const char * di printf("\n%s: Build %s file ... done\n", program, filename); } + // [xx]client.h { name_render.GetClientFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); @@ -100,7 +101,31 @@ void Proto2Client(const char * program, const char * proto_file, const char * di if (0 != access(name4hpp, F_OK)) { if (0 != access(filename, F_OK)) { FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateClientHpp(&syntax_tree, fp); + clientCodeRender.GenerateClientHpp(&syntax_tree, fp, false); + fclose(fp); + + printf("\n%s: Build %s file ... done\n", program, filename); + } else { + printf("\n%s: %s is exist, skip\n", program, filename); + } + } else { + printf("\n%s: %s is exist, skip\n", program, name4hpp); + } + } + + // [xx]client_uthread.h + if (is_uthread_mode) + { + name_render.GetClientFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); + snprintf(filename, sizeof(filename), "%s/%s_uthread.h", dir_path, tmp); + + char name4hpp[256] = { 0 }; + snprintf(name4hpp, sizeof(name4hpp), "%s/%s_uthread.hpp", dir_path, tmp); + + if (0 != access(name4hpp, F_OK)) { + if (0 != access(filename, F_OK)) { + FILE * fp = fopen(filename, "w"); + clientCodeRender.GenerateClientHpp(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -119,7 +144,24 @@ void Proto2Client(const char * program, const char * proto_file, const char * di if (0 != access(filename, F_OK)) { FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateClientCpp(&syntax_tree, fp); + clientCodeRender.GenerateClientCpp(&syntax_tree, fp, false); + fclose(fp); + + printf("\n%s: Build %s file ... done\n", program, filename); + } else { + printf("\n%s: %s is exist, skip\n", program, filename); + } + } + + // [xx]client_uthread.cpp + if (is_uthread_mode) + { + name_render.GetClientFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); + snprintf(filename, sizeof(filename), "%s/%s_uthread.cpp", dir_path, tmp); + + if (0 != access(filename, F_OK)) { + FILE * fp = fopen(filename, "w"); + clientCodeRender.GenerateClientCpp(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -154,8 +196,9 @@ int main(int argc, char * argv[]) { std::vector include_list; char real_path[1024] = {0}; char * rp = nullptr; + bool is_uthread_mode = false; - while ((c = getopt(argc, argv, "f:d:I:v")) != EOF) { + while ((c = getopt(argc, argv, "f:d:I:uv")) != EOF) { switch (c) { case 'f': proto_file = optarg; @@ -169,6 +212,9 @@ int main(int argc, char * argv[]) { include_list.push_back(rp); } break; + case 'u': + is_uthread_mode = true; + break; default: PrintHelp(argv[0]); exit(-1); @@ -195,7 +241,7 @@ int main(int argc, char * argv[]) { path[strlen(path) - 1] = '\0'; } - Proto2Client(argv[0], proto_file, path, include_list); + Proto2Client(argv[0], proto_file, path, include_list, is_uthread_mode); printf("\n"); diff --git a/codegen/phxrpc_pb2server.cpp b/codegen/phxrpc_pb2server.cpp index 7676306..06b472b 100644 --- a/codegen/phxrpc_pb2server.cpp +++ b/codegen/phxrpc_pb2server.cpp @@ -45,6 +45,7 @@ void PrintHelp(const char * program) { printf(" Usage: -f # Proto File\n"); printf(" -d # destination file dir\n"); printf(" -I # include path dir\n"); + printf(" -e # epoll server\n"); printf(" -v # print this screen\n"); printf("\n"); @@ -52,7 +53,8 @@ void PrintHelp(const char * program) { } void Proto2Server(const char * program, const char * pb_file, const char * dir_path, - const std::vector & include_list, const std::string & mk_dir_path) { + const std::vector & include_list, const std::string & mk_dir_path, + const bool is_uthread_mode) { SyntaxTree syntax_tree; std::map parsed_file_map; @@ -107,7 +109,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p if (0 != access(filename, F_OK)) { FILE * fp = fopen(filename, "w"); - codeRender.GenerateServerMainCpp(&syntax_tree, fp); + codeRender.GenerateServerMainCpp(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -123,7 +125,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p if (0 != access(filename, F_OK)) { FILE * fp = fopen(filename, "w"); - codeRender.GenerateServerEtc(&syntax_tree, fp); + codeRender.GenerateServerEtc(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -138,7 +140,7 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p if (0 != access(filename, F_OK)) { FILE * fp = fopen(filename, "w"); - codeRender.GenerateMakefile(&syntax_tree, mk_dir_path, fp); + codeRender.GenerateMakefile(&syntax_tree, mk_dir_path, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -157,8 +159,9 @@ int main(int argc, char * argv[]) { std::vector include_list; char real_path[1024] = {0}; char * rp = nullptr; + bool is_uthread_mode = false; - while ((c = getopt(argc, argv, "f:d:I:v")) != EOF) { + while ((c = getopt(argc, argv, "f:d:I:uv")) != EOF) { switch (c) { case 'f': pb_file = optarg; @@ -172,6 +175,9 @@ int main(int argc, char * argv[]) { include_list.push_back(rp); } break; + case 'u': + is_uthread_mode = true; + break; default: PrintHelp(argv[0]); exit(-1); @@ -208,7 +214,7 @@ int main(int argc, char * argv[]) { } } - Proto2Server(argv[0], pb_file, path, include_list, mk_dir_path); + Proto2Server(argv[0], pb_file, path, include_list, mk_dir_path, is_uthread_mode); return 0; } diff --git a/codegen/phxrpc_pb2service.cpp b/codegen/phxrpc_pb2service.cpp index 7be1667..3e375a6 100644 --- a/codegen/phxrpc_pb2service.cpp +++ b/codegen/phxrpc_pb2service.cpp @@ -51,7 +51,7 @@ void PrintHelp(const char * program) { } void Proto2Service(const char * program, const char * pb_file, const char * dir_path, - const std::vector & include_list) { + const std::vector & include_list, const bool is_uthread_mode) { std::map parsed_file_map; SyntaxTree syntax_tree; @@ -101,7 +101,7 @@ void Proto2Service(const char * program, const char * pb_file, const char * dir_ if (0 != access(filename, F_OK)) { FILE * fp = fopen(filename, "w"); assert(NULL != fp); - codeRender.GenerateServiceImplHpp(&syntax_tree, fp); + codeRender.GenerateServiceImplHpp(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -118,7 +118,7 @@ void Proto2Service(const char * program, const char * pb_file, const char * dir_ if (0 != access(filename, F_OK)) { FILE * fp = fopen(filename, "w"); assert(NULL != fp); - codeRender.GenerateServiceImplCpp(&syntax_tree, fp); + codeRender.GenerateServiceImplCpp(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -163,8 +163,9 @@ int main(int argc, char * argv[]) { std::vector include_list; char real_path[1024] = {0}; char * rp = nullptr; + bool is_uthread_mode = false; - while ((c = getopt(argc, argv, "f:d:I:v")) != EOF) { + while ((c = getopt(argc, argv, "f:d:I:uv")) != EOF) { switch (c) { case 'f': pb_file = optarg; @@ -178,6 +179,9 @@ int main(int argc, char * argv[]) { include_list.push_back(rp); } break; + case 'u': + is_uthread_mode = true; + break; default: PrintHelp(argv[0]); exit(-1); @@ -205,7 +209,7 @@ int main(int argc, char * argv[]) { path[strlen(path) - 1] = '\0'; } - Proto2Service(argv[0], pb_file, path, include_list); + Proto2Service(argv[0], pb_file, path, include_list, is_uthread_mode); printf("\n"); diff --git a/codegen/server_code_render.cpp b/codegen/server_code_render.cpp index af8523d..c433822 100644 --- a/codegen/server_code_render.cpp +++ b/codegen/server_code_render.cpp @@ -116,7 +116,7 @@ void ServerCodeRender::GenerateServerConfigCpp(SyntaxTree * stree, FILE * write) fprintf(write, "\n"); } -void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write) { +void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { char svrfile[128] = { 0 }; name_render_.GetServerMainFileName(stree->GetName(), svrfile, sizeof(svrfile)); @@ -139,7 +139,12 @@ void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write) { name_render_.GetServerConfigClasname(stree->GetName(), server_config_class, sizeof(server_config_class)); name_render_.GetServerConfigFileName(stree->GetName(), server_config_file, sizeof(server_config_file)); - std::string content = PHXRPC_EPOLL_SERVER_MAIN_TEMPLATE; + std::string content; + if (!is_uthread_mode) { + content = PHXRPC_EPOLL_SERVER_MAIN_TEMPLATE; + } else { + content = PHXRPC_EPOLL_UTHREAD_SERVER_MAIN_TEMPLATE; + } StrTrim(&content); StrReplaceAll(&content, "$DispatcherFile$", dispatcher_file); @@ -154,7 +159,7 @@ void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); } -void ServerCodeRender::GenerateServerEtc(SyntaxTree * stree, FILE * write) { +void ServerCodeRender::GenerateServerEtc(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { char etcfile[128] = { 0 }; name_render_.GetServerEtcFileName(stree->GetName(), etcfile, sizeof(etcfile)); @@ -166,7 +171,12 @@ void ServerCodeRender::GenerateServerEtc(SyntaxTree * stree, FILE * write) { fprintf(write, "#\n"); fprintf(write, "\n"); - std::string content = PHXRPC_EPOLL_SERVER_ETC_TEMPLATE; + std::string content; + if (!is_uthread_mode) { + content = PHXRPC_EPOLL_SERVER_ETC_TEMPLATE; + } else { + content = PHXRPC_EPOLL_UTHREAD_SERVER_ETC_TEMPLATE; + } StrTrim(&content); StrReplaceAll(&content, "$PackageName$", stree->GetPackageName() ); @@ -176,7 +186,7 @@ void ServerCodeRender::GenerateServerEtc(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); } -void ServerCodeRender::GenerateMakefile(SyntaxTree * stree, const std::string & mk_dir_path, FILE * write) { +void ServerCodeRender::GenerateMakefile(SyntaxTree * stree, const std::string & mk_dir_path, FILE * write, const bool is_uthread_mode) { std::string buffer; name_render_.GetCopyright("phxrpc_pb2server", stree->GetProtoFile(), &buffer, false, "#"); @@ -205,7 +215,13 @@ void ServerCodeRender::GenerateMakefile(SyntaxTree * stree, const std::string & name_render_.GetStubFileName(stree->GetName(), stub_file, sizeof(stub_file)); name_render_.GetMessageFileName(stree->GetProtoFile(), message_file, sizeof(message_file)); - std::string content(PHXRPC_SERVER_MAKEFILE_TEMPLATE); + std::string content; + if (!is_uthread_mode) { + content = PHXRPC_SERVER_MAKEFILE_TEMPLATE; + } else { + content = PHXRPC_UTHREAD_SERVER_MAKEFILE_TEMPLATE; + } + StrTrim(&content); StrReplaceAll(&content, "$PhxRPCMKDir$", mk_dir_path); StrReplaceAll(&content, "$DispatcherFile$", dispatcher_file); diff --git a/codegen/server_code_render.h b/codegen/server_code_render.h index 2b744f3..296178a 100644 --- a/codegen/server_code_render.h +++ b/codegen/server_code_render.h @@ -38,11 +38,11 @@ class ServerCodeRender { void GenerateServerConfigCpp(SyntaxTree * stree, FILE * write); - void GenerateServerMainCpp(SyntaxTree * stree, FILE * write); + void GenerateServerMainCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); - void GenerateServerEtc(SyntaxTree * stree, FILE * write); + void GenerateServerEtc(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); - void GenerateMakefile(SyntaxTree * stree, const std::string & mk_dir_path, FILE * write); + void GenerateMakefile(SyntaxTree * stree, const std::string & mk_dir_path, FILE * write, const bool is_uthread_mode); private: NameRender & name_render_; diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index 6b3014a..ae426d6 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -109,6 +109,96 @@ int main( int argc, char * argv[] ) { ////////////////////////////////////////////////////////////////////// +const char * PHXRPC_EPOLL_UTHREAD_SERVER_MAIN_TEMPLATE = + R"( + +#include +#include +#include +#include +#include "$DispatcherFile$.h" +#include "$ServiceImplFile$.h" +#include "$ServerConfigFile$.h" + +#include "phxrpc/rpc.h" +#include "phxrpc/http.h" +#include "phxrpc/file.h" + +using namespace std; + +void HttpDispatch( const phxrpc::HttpRequest & request, phxrpc::HttpResponse * response, phxrpc::DispatcherArgs_t * args ) { + + ServiceArgs_t * service_args = (ServiceArgs_t *)(args->service_args); + + $ServiceImplClass$ service( * service_args, args->server_worker_uthread_scheduler ); + $DispatcherClass$ dispatcher( service, args ); + + phxrpc::HttpDispatcher<$DispatcherClass$> http_dispatcher( + dispatcher, $DispatcherClass$::GetURIFuncMap() ); + if( ! http_dispatcher.Dispatch( request, response ) ) { + response->SetStatusCode( 404 ); + response->SetReasonPhrase( "Not Found" ); + } +} + +void showUsage( const char * program ) { + printf( "\n" ); + printf( "Usage: %s [-c ] [-d] [-l ] [-v]\n", program ); + printf( "\n" ); + + exit( 0 ); +} + +int main( int argc, char * argv[] ) { + const char * config_file = NULL; + bool daemonize = false;; + int log_level = -1; + extern char *optarg ; + int c ; + while( ( c = getopt( argc, argv, "c:vl:d" ) ) != EOF ) { + switch ( c ) { + case 'c' : config_file = optarg; break; + case 'd' : daemonize = true; break; + case 'l' : log_level = atoi( optarg ); break; + + case 'v' : + default: showUsage( argv[ 0 ] ); break; + } + } + + if( daemonize ) phxrpc::ServerUtils::Daemonize(); + + assert(signal(SIGPIPE, SIG_IGN) != SIG_ERR); + + //set customize log/monitor + //phxrpc::setlog(openlog, closelog, vlog); + //phxrpc::MonitorFactory::SetFactory( new YourSelfsMonitorFactory() ); + + if( NULL == config_file ) showUsage( argv[0] ); + + $ServerConfigClass$ config; + if( ! config.Read( config_file ) ) showUsage( argv[0] ); + + if( log_level > 0 ) config.GetHshaServerConfig().SetLogLevel( log_level ); + + phxrpc::openlog( argv[0], config.GetHshaServerConfig().GetLogDir(), + config.GetHshaServerConfig().GetLogLevel() ); + + ServiceArgs_t service_args; + service_args.config = &config; + + phxrpc::HshaServer server( config.GetHshaServerConfig(), HttpDispatch, &service_args ); + server.RunForever(); + + phxrpc::closelog(); + + return 0; +} + +)"; + +////////////////////////////////////////////////////////////////////// + const char * PHXRPC_EPOLL_SERVER_CONFIG_HPP_TEMPLATE = R"( @@ -192,6 +282,33 @@ SocketTimeoutMS = 5000 ////////////////////////////////////////////////////////////////////// +const char * PHXRPC_EPOLL_UTHREAD_SERVER_ETC_TEMPLATE = + R"( + +[Server] +BindIP = 127.0.0.1 +Port = 16161 +MaxThreads = 16 +WorkerUThreadCount = 50 +WorkerUThreadStackSize = 65536 +IOThreadCount = 3 +PackageName = $PackageName$ +MaxConnections = 800000 +MaxQueueLength = 20480 +FastRejectThresholdMS = 20 +FastRejectAdjustRate = 5 + +[Log] +LogDir = ~/log +LogLevel = 3 + +[ServerTimeout] +SocketTimeoutMS = 5000 + +)"; + +////////////////////////////////////////////////////////////////////// + const char * PHXRPC_SERVER_MAKEFILE_TEMPLATE = R"( @@ -275,3 +392,91 @@ lib$ClientFile$.a: $(CLI_OBJS) )"; +///////////////////////////////////////////////////////////////////// + +const char * PHXRPC_UTHREAD_SERVER_MAKEFILE_TEMPLATE = + R"( + +include $PhxRPCMKDir$/phxrpc.mk + +LDFLAGS := -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) + +#choose to use boost for network +#LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS) + +SVR_OBJS = $MessageFile$.o \ + $ServiceImplFile$.o \ + $ServiceFile$.o \ + $DispatcherFile$.o \ + $ServerConfigFile$.o \ + $ServerMainFile$.o + +CLI_OBJS = $MessageFile$.o \ + $ClientFile$.o \ + $ClientFile$_uthread.o \ + $StubFile$.o + +TARGETS = lib$ClientFile$.a $ServerMainFile$ $ToolMainFile$ + +all: $(TARGETS) + +$ServerMainFile$: $(SVR_OBJS) + $(LINKER) $^ $(LDFLAGS) -o $@ + +lib$ClientFile$.a: $(CLI_OBJS) + $(AR) $@ $^ + +$ToolMainFile$: $ToolFile$.o $ToolImplFile$.o $ToolMainFile$.o + $(LINKER) $^ -L. -l$ClientFile$ $(LDFLAGS) -o $@ + +########## message ########## + +$MessageFile$.cc: $MessageFile$.h + +$MessageFile$.h: $ProtoFile$ + $(PROTOBUF_ROOT)/bin/protoc -I$(PROTOBUF_ROOT)/include --cpp_out=. -I$(PHXRPC_ROOT) -I. $^ + +########## client ########## + +$StubFile$.cpp: $StubFile$.h +$StubFile$.o: $StubFile$.h +$ClientFile$.cpp: $StubFile$.h +$ClientFile$.o: $StubFile$.h +$ClientFile$_uthread.cpp: $StubFile$.h +$ClientFile$_uthread.o: $StubFile$.h + +$StubFile$.h: $ProtoFile$ + $(PHXRPC_ROOT)/codegen/phxrpc_pb2client $(PBFLAGS) -f $^ -d . -u + +########## service ########## + +$ServiceFile$.cpp: $ServiceFile$.h +$ServiceFile$.o: $ServiceFile$.h +$ServiceImplFile$.cpp: $ServiceFile$.h +$ServiceImplFile$.o: $ServiceFile$.h +$DispatcherFile$.cpp: $ServiceFile$.h +$DispatcherFile$.o: $ServiceFile$.h + +$ServiceFile$.h: $ProtoFile$ + $(PHXRPC_ROOT)/codegen/phxrpc_pb2service $(PBFLAGS) -f $^ -d . -u + +########## tool ########## + +$ToolFile$.cpp: $ToolFile$.h +$ToolFile$.o: $ToolFile$.h +$ToolImplFile$.cpp: $ToolFile$.h +$ToolImplFile$.o: $ToolFile$.h +$ToolMainFile$.cpp: $ToolFile$.h +$ToolMainFile$.o: $ToolFile$.h + +$ToolFile$.h: $ProtoFile$ + $(PHXRPC_ROOT)/codegen/phxrpc_pb2tool $(PBFLAGS) -f $^ -d . + +clean: + @($(RM) $(TARGETS)) + @($(RM) *.o) + @($(RM) phxrpc_*) + @($(RM) *.pb.*) + +)"; + diff --git a/codegen/server_template.h b/codegen/server_template.h index e5a896d..bafd54c 100644 --- a/codegen/server_template.h +++ b/codegen/server_template.h @@ -21,14 +21,16 @@ See the AUTHORS file for names of contributors. #pragma once -extern const char * PHXRPC_SERVER_MAIN_TEMPLATE; extern const char * PHXRPC_EPOLL_SERVER_MAIN_TEMPLATE; -extern const char * PHXRPC_SERVER_CONFIG_HPP_TEMPLATE; +extern const char * PHXRPC_EPOLL_UTHREAD_SERVER_MAIN_TEMPLATE; + extern const char * PHXRPC_EPOLL_SERVER_CONFIG_HPP_TEMPLATE; -extern const char * PHXRPC_SERVER_CONFIG_CPP_TEMPLATE; + extern const char * PHXRPC_EPOLL_SERVER_CONFIG_CPP_TEMPLATE; -extern const char * PHXRPC_SERVER_ETC_TEMPLATE; + extern const char * PHXRPC_EPOLL_SERVER_ETC_TEMPLATE; +extern const char * PHXRPC_EPOLL_UTHREAD_SERVER_ETC_TEMPLATE; extern const char * PHXRPC_SERVER_MAKEFILE_TEMPLATE; +extern const char * PHXRPC_UTHREAD_SERVER_MAKEFILE_TEMPLATE; diff --git a/codegen/service_code_render.cpp b/codegen/service_code_render.cpp index db37428..0d4641a 100644 --- a/codegen/service_code_render.cpp +++ b/codegen/service_code_render.cpp @@ -131,7 +131,7 @@ void ServiceCodeRender::GenerateServiceCpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); } -void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write) { +void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { char filename[128] = { 0 }; name_render_.GetServiceImplFileName(stree->GetName(), filename, sizeof(filename)); @@ -152,6 +152,9 @@ void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write) name_render_.GetServiceFileName(stree->GetName(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); + if (is_uthread_mode) { + fprintf(write, "#include \"phxrpc/network.h\"\n"); + } fprintf(write, "\n"); @@ -172,7 +175,11 @@ void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write) fprintf(write, "class %s : public %s\n", clasname, base_name); fprintf(write, "{\n"); fprintf(write, "public:\n"); - fprintf(write, " %s( ServiceArgs_t & args );\n", clasname); + if (!is_uthread_mode) { + fprintf(write, " %s( ServiceArgs_t & app_args );\n", clasname); + } else { + fprintf(write, " %s( ServiceArgs_t & app_args, phxrpc::UThreadEpollScheduler * worker_uthread_scheduler );\n", clasname); + } fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); @@ -187,13 +194,16 @@ void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write) fprintf(write, "private:\n"); fprintf(write, " ServiceArgs_t & args_;\n" ); + if (is_uthread_mode) { + fprintf(write, " phxrpc::UThreadEpollScheduler * worker_uthread_scheduler_;\n" ); + } fprintf(write, "};\n"); fprintf(write, "\n"); } -void ServiceCodeRender::GenerateServiceImplCpp(SyntaxTree * stree, FILE * write) { +void ServiceCodeRender::GenerateServiceImplCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { char filename[128] = { 0 }, config_file[128] = { 0 }; name_render_.GetServiceImplFileName(stree->GetName(), filename, sizeof(filename)); name_render_.GetServerConfigFileName(stree->GetName(), config_file, sizeof(config_file)); @@ -219,8 +229,13 @@ void ServiceCodeRender::GenerateServiceImplCpp(SyntaxTree * stree, FILE * write) name_render_.GetServiceImplClasname(stree->GetName(), clasname, sizeof(clasname)); name_render_.GetServerConfigClasname(stree->GetName(), config_name, sizeof(config_name)); - fprintf(write, "%s :: %s( ServiceArgs_t & args )\n", clasname, clasname); - fprintf(write, " : args_( args )\n"); + if (!is_uthread_mode) { + fprintf(write, "%s :: %s(ServiceArgs_t & app_args)\n", clasname, clasname); + fprintf(write, " : args_(app_args)\n"); + } else { + fprintf(write, "%s :: %s(ServiceArgs_t & app_args, phxrpc::UThreadEpollScheduler * worker_uthread_scheduler)\n", clasname, clasname); + fprintf(write, " : args_(app_args), worker_uthread_scheduler_(worker_uthread_scheduler)\n"); + } fprintf(write, "{\n"); fprintf(write, "}\n"); fprintf(write, "\n"); diff --git a/codegen/service_code_render.h b/codegen/service_code_render.h index b7a371b..9dd5345 100755 --- a/codegen/service_code_render.h +++ b/codegen/service_code_render.h @@ -40,9 +40,9 @@ class ServiceCodeRender { virtual void GenerateServiceCpp(SyntaxTree * stree, FILE * write); - virtual void GenerateServiceImplHpp(SyntaxTree * stree, FILE * write); + virtual void GenerateServiceImplHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); - virtual void GenerateServiceImplCpp(SyntaxTree * stree, FILE * write); + virtual void GenerateServiceImplCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); virtual void GenerateDispatcherHpp(SyntaxTree * stree, FILE * write); diff --git a/phxrpc/network/uthread_epoll.cpp b/phxrpc/network/uthread_epoll.cpp index 08eb83b..245609d 100644 --- a/phxrpc/network/uthread_epoll.cpp +++ b/phxrpc/network/uthread_epoll.cpp @@ -109,7 +109,8 @@ enum UThreadEpollREventStatus { UThreadEpollScheduler::UThreadEpollScheduler(size_t stack_size, int max_task, const bool need_stack_protect) : runtime_(stack_size, need_stack_protect), epoll_wake_up_(this) { - max_task_ = max_task; + //epoll notifier use one task. + max_task_ = max_task + 1; epoll_fd_ = epoll_create(max_task_); @@ -122,6 +123,7 @@ UThreadEpollScheduler::UThreadEpollScheduler(size_t stack_size, int max_task, co run_forever_ = false; active_socket_func_ = nullptr; handler_accepted_fd_func_ = nullptr; + handler_new_request_func_ = nullptr; epoll_wait_events_ = 0; epoll_wait_events_per_second_ = 0; @@ -137,6 +139,10 @@ UThreadEpollScheduler * UThreadEpollScheduler :: Instance() { return &obj; } +bool UThreadEpollScheduler :: IsTaskFull() { + return (runtime_.GetUnfinishedItemCount() + (int)todo_list_.size()) >= max_task_; +} + void UThreadEpollScheduler::AddTask(UThreadFunc_t func, void * args) { todo_list_.push(std::make_pair(func, args)); } @@ -145,7 +151,11 @@ void UThreadEpollScheduler :: SetActiveSocketFunc(UThreadActiveSocket_t active_s active_socket_func_ = active_socket_func; } -void UThreadEpollScheduler :: SetHandlerAcceptedFdFunc(UThreadHanderAcceptedFdFunc_t handler_accepted_fd_func) { +void UThreadEpollScheduler :: SetHandlerNewRequestFunc(UThreadHandlerNewRequest_t handler_new_request_func) { + handler_new_request_func_ = handler_new_request_func; +} + +void UThreadEpollScheduler :: SetHandlerAcceptedFdFunc(UThreadHandlerAcceptedFdFunc_t handler_accepted_fd_func) { handler_accepted_fd_func_ = handler_accepted_fd_func; } @@ -251,6 +261,11 @@ bool UThreadEpollScheduler::Run() { } } + //for server uthread worker + if (handler_new_request_func_ != nullptr) { + handler_new_request_func_(); + } + if (handler_accepted_fd_func_ != nullptr) { handler_accepted_fd_func_(); } diff --git a/phxrpc/network/uthread_epoll.h b/phxrpc/network/uthread_epoll.h index f8a395c..48ffb49 100644 --- a/phxrpc/network/uthread_epoll.h +++ b/phxrpc/network/uthread_epoll.h @@ -38,7 +38,8 @@ typedef struct tagUThreadSocket UThreadSocket_t; typedef std::pair UThreadEpollArgs_t; typedef std::function< UThreadSocket_t *() > UThreadActiveSocket_t; -typedef std::function< void() > UThreadHanderAcceptedFdFunc_t; +typedef std::function< void() > UThreadHandlerAcceptedFdFunc_t; +typedef std::function< void() > UThreadHandlerNewRequest_t; class EpollNotifier { public: @@ -61,6 +62,8 @@ class UThreadEpollScheduler { static UThreadEpollScheduler * Instance(); + bool IsTaskFull(); + void AddTask(UThreadFunc_t func, void * args); UThreadSocket_t * CreateSocket(int fd, int socket_timeout_ms = 5000, @@ -68,7 +71,9 @@ class UThreadEpollScheduler { void SetActiveSocketFunc(UThreadActiveSocket_t active_socket_func); - void SetHandlerAcceptedFdFunc(UThreadHanderAcceptedFdFunc_t handler_accepted_fd_func); + void SetHandlerAcceptedFdFunc(UThreadHandlerAcceptedFdFunc_t handler_accepted_fd_func); + + void SetHandlerNewRequestFunc(UThreadHandlerNewRequest_t handler_new_request_func); bool YieldTask(); @@ -103,7 +108,9 @@ class UThreadEpollScheduler { bool run_forever_; UThreadActiveSocket_t active_socket_func_; - UThreadHanderAcceptedFdFunc_t handler_accepted_fd_func_; + UThreadHandlerAcceptedFdFunc_t handler_accepted_fd_func_; + UThreadHandlerNewRequest_t handler_new_request_func_; + int epoll_wait_events_; int epoll_wait_events_per_second_; uint64_t epoll_wait_events_last_cal_time_; diff --git a/phxrpc/network/uthread_runtime.cpp b/phxrpc/network/uthread_runtime.cpp index 80448dc..2caf21c 100644 --- a/phxrpc/network/uthread_runtime.cpp +++ b/phxrpc/network/uthread_runtime.cpp @@ -119,5 +119,9 @@ bool UThreadRuntime::IsAllDone() { return unfinished_item_count_ == 0; } +int UThreadRuntime :: GetUnfinishedItemCount() const { + return unfinished_item_count_; +} + } diff --git a/phxrpc/network/uthread_runtime.h b/phxrpc/network/uthread_runtime.h index 765858c..0a37175 100644 --- a/phxrpc/network/uthread_runtime.h +++ b/phxrpc/network/uthread_runtime.h @@ -38,6 +38,7 @@ class UThreadRuntime { bool Yield(); bool Resume(size_t index); bool IsAllDone(); + int GetUnfinishedItemCount() const; void UThreadDoneCallback(); diff --git a/phxrpc/rpc/hsha_server.cpp b/phxrpc/rpc/hsha_server.cpp index 814b4a0..64e5ec2 100644 --- a/phxrpc/rpc/hsha_server.cpp +++ b/phxrpc/rpc/hsha_server.cpp @@ -61,6 +61,19 @@ int DataFlow :: PluckRequest(void *& args, HttpRequest *& request) { return now_time > rp.first.enqueue_time_ms ? now_time - rp.first.enqueue_time_ms : 0; } +int DataFlow :: PickRequest(void *& args, HttpRequest *& request) { + pair rp; + bool succ = in_queue_.pick(rp); + if (!succ) { + return 0; + } + args = rp.first.args; + request = rp.second; + + auto now_time = Timer::GetSteadyClockMS(); + return now_time > rp.first.enqueue_time_ms ? now_time - rp.first.enqueue_time_ms : 0; +} + void DataFlow :: PushResponse(void * args, HttpResponse * response) { out_queue_.push(make_pair(QueueExtData(args), response)); } @@ -108,7 +121,7 @@ int HshaServerStat :: TimeCost :: Cost() { } HshaServerStat :: HshaServerStat(const HshaServerConfig * config, ServerMonitorPtr hsha_server_monitor ) : - thread_(&HshaServerStat::CalFunc, this), break_out_(false), + config_(config), thread_(&HshaServerStat::CalFunc, this), break_out_(false), hsha_server_monitor_(hsha_server_monitor) { hold_fds_ = 0; accepted_fds_ = 0; @@ -364,15 +377,25 @@ void HshaServerQos :: CalFunc() { //////////////////////////////////////// -Worker :: Worker(WorkerPool * pool) - : pool_(pool), shut_down_(false), thread_(&Worker::Func, this) { +Worker :: Worker(WorkerPool * pool, const int uthread_count, int utherad_stack_size) + : pool_(pool), uthread_count_(uthread_count), utherad_stack_size_(utherad_stack_size), shut_down_(false), + worker_scheduler_(nullptr), thread_(&Worker::Func, this) { } Worker :: ~Worker() { thread_.join(); + delete worker_scheduler_; } void Worker :: Func() { + if (uthread_count_ == 0) { + ThreadMode(); + } else { + UThreadMode(); + } +} + +void Worker :: ThreadMode() { while (!shut_down_) { pool_->hsha_server_stat_->worker_idles_++; @@ -385,25 +408,67 @@ void Worker :: Func() { } pool_->hsha_server_stat_->worker_idles_--; - pool_->hsha_server_stat_->inqueue_pop_requests_++; - pool_->hsha_server_stat_->inqueue_wait_time_costs_ += queue_wait_time_ms; - pool_->hsha_server_stat_->inqueue_wait_time_costs_count_++; + WorkerLogic(args, request, queue_wait_time_ms); + } +} - HttpResponse * response = new HttpResponse; - if (queue_wait_time_ms < MAX_QUEUE_WAIT_TIME_COST) { - HshaServerStat::TimeCost time_cost; - pool_->dispatch_(*request, response, &(pool_->dispatcher_args_)); - pool_->hsha_server_stat_->worker_time_costs_ += time_cost.Cost(); - } else { - pool_->hsha_server_stat_->worker_drop_requests_++; - } - pool_->data_flow_->PushResponse(args, response); - pool_->hsha_server_stat_->outqueue_push_responses_++; +void Worker :: UThreadMode() { + worker_scheduler_ = new UThreadEpollScheduler(utherad_stack_size_, uthread_count_, true); + assert(worker_scheduler_ != nullptr); + worker_scheduler_->SetHandlerNewRequestFunc(std::bind(&Worker::HandlerNewRequestFunc, this)); + worker_scheduler_->RunForever(); +} - pool_->scheduler_->NotifyEpoll(); +void Worker :: HandlerNewRequestFunc() { + if (worker_scheduler_->IsTaskFull()) { + return; + } - delete request; + void * args = nullptr; + HttpRequest * request = nullptr; + int queue_wait_time_ms = pool_->data_flow_->PickRequest(args, request); + if (request == nullptr) { + return; } + + worker_scheduler_->AddTask(std::bind(&Worker::UThreadFunc, this, args, request, queue_wait_time_ms), nullptr); +} + +void Worker :: UThreadFunc(void * args, HttpRequest * request, int queue_wait_time_ms) { + WorkerLogic(args, request, queue_wait_time_ms); +} + +void Worker :: WorkerLogic(void * args, HttpRequest * request, int queue_wait_time_ms) { + pool_->hsha_server_stat_->inqueue_pop_requests_++; + pool_->hsha_server_stat_->inqueue_wait_time_costs_ += queue_wait_time_ms; + pool_->hsha_server_stat_->inqueue_wait_time_costs_count_++; + + HttpResponse * response = new HttpResponse; + if (queue_wait_time_ms < MAX_QUEUE_WAIT_TIME_COST) { + HshaServerStat::TimeCost time_cost; + + DispatcherArgs_t dispatcher_args(pool_->hsha_server_stat_->hsha_server_monitor_, + worker_scheduler_, pool_->args_); + pool_->dispatch_(*request, response, &dispatcher_args); + + pool_->hsha_server_stat_->worker_time_costs_ += time_cost.Cost(); + } else { + pool_->hsha_server_stat_->worker_drop_requests_++; + } + pool_->data_flow_->PushResponse(args, response); + pool_->hsha_server_stat_->outqueue_push_responses_++; + + pool_->scheduler_->NotifyEpoll(); + + delete request; +} + +void Worker :: Notify() { + if (uthread_count_ == 0) { + return; + } + + worker_scheduler_->NotifyEpoll(); } void Worker :: Shutdown() { @@ -413,13 +478,20 @@ void Worker :: Shutdown() { //////////////////////////////////////// -WorkerPool :: WorkerPool(UThreadEpollScheduler * scheduler, size_t thread_count, DataFlow * data_flow, - HshaServerStat * hsha_server_stat, Dispatch_t dispatch, void * args) +WorkerPool :: WorkerPool( + UThreadEpollScheduler * scheduler, + int thread_count, + int uthread_count_per_thread, + int utherad_stack_size, + DataFlow * data_flow, + HshaServerStat * hsha_server_stat, + Dispatch_t dispatch, + void * args) : scheduler_(scheduler), data_flow_(data_flow), hsha_server_stat_(hsha_server_stat), dispatch_(dispatch), - dispatcher_args_(hsha_server_stat_->hsha_server_monitor_, args ) { - for (size_t i = 0; i < thread_count; i++) { - auto worker = new Worker(this); + args_(args), last_notify_idx_(0) { + for (int i = 0; i < thread_count; i++) { + auto worker = new Worker(this, uthread_count_per_thread, utherad_stack_size); assert(worker != nullptr); worker_list_.push_back(worker); } @@ -432,13 +504,23 @@ WorkerPool :: ~WorkerPool() { } } +void WorkerPool :: Notify() { + std::lock_guard lock(mutex_); + if (last_notify_idx_ == worker_list_.size()) { + last_notify_idx_ = 0; + } + + worker_list_[last_notify_idx_++]->Notify(); +} + //////////////////////////////////////// HshaServerIO :: HshaServerIO(int idx, UThreadEpollScheduler * scheduler, const HshaServerConfig * config, - DataFlow * data_flow, HshaServerStat * hsha_server_stat, HshaServerQos * hsha_server_qos) - : scheduler_(scheduler), config_(config), - data_flow_(data_flow), hsha_server_stat_(hsha_server_stat), - hsha_server_qos_(hsha_server_qos){ + DataFlow * data_flow, HshaServerStat * hsha_server_stat, HshaServerQos * hsha_server_qos, + WorkerPool * worker_pool) + : idx_(idx), scheduler_(scheduler), config_(config), + data_flow_(data_flow), listen_fd_(-1), hsha_server_stat_(hsha_server_stat), + hsha_server_qos_(hsha_server_qos), worker_pool_(worker_pool) { } HshaServerIO :: ~HshaServerIO() { @@ -507,6 +589,8 @@ void HshaServerIO :: IOFunc(int accepted_fd) { hsha_server_stat_->inqueue_push_requests_++; data_flow_->PushRequest((void *)socket, request); + //if is uthread worker mode, need notify. + worker_pool_->Notify(); UThreadSetArgs(*socket, nullptr); UThreadWait(*socket, config_->GetSocketTimeoutMS()); @@ -585,18 +669,24 @@ void HshaServerIO :: RunForever() { ///////////////////////////////////////////////// -HshaServerUnit :: HshaServerUnit(HshaServer * hsha_server, int idx, int worker_thread_count, - Dispatch_t dispatch, void * args) : +HshaServerUnit :: HshaServerUnit( + HshaServer * hsha_server, + int idx, + int worker_thread_count, + int worker_uthread_count_per_thread, + int worker_utherad_stack_size, + Dispatch_t dispatch, + void * args) : hsha_server_(hsha_server), #ifndef __APPLE__ scheduler_(8 * 1024, 1000000, false), #else scheduler_(32 * 1024, 1000000, false), #endif + worker_pool_(&scheduler_, worker_thread_count, worker_uthread_count_per_thread, + worker_utherad_stack_size, &data_flow_, &hsha_server_->hsha_server_stat_, dispatch, args), hsha_server_io_(idx, &scheduler_, hsha_server_->config_, &data_flow_, - &hsha_server_->hsha_server_stat_, &hsha_server_->hsha_server_qos_), - worker_pool_(&scheduler_, worker_thread_count, &data_flow_, - &hsha_server_->hsha_server_stat_, dispatch, args), + &hsha_server_->hsha_server_stat_, &hsha_server_->hsha_server_qos_, &worker_pool_), thread_(&HshaServerUnit::RunFunc, this) { } @@ -688,16 +778,23 @@ HshaServer :: HshaServer( if (worker_thread_count < io_count) { io_count = worker_thread_count; } + + int worker_utherad_stack_size = config.GetWorkerUThreadStackSize(); size_t worker_thread_count_per_io = worker_thread_count / io_count; for (size_t i = 0; i < io_count; i++) { if (i == io_count - 1) { worker_thread_count_per_io = worker_thread_count - (worker_thread_count_per_io * (io_count - 1)); } - auto hsha_server_unit = new HshaServerUnit(this, i, worker_thread_count_per_io, dispatch, args); + auto hsha_server_unit = + new HshaServerUnit(this, i, (int)worker_thread_count_per_io, + config.GetWorkerUThreadCount(), worker_utherad_stack_size, dispatch, args); assert(hsha_server_unit != nullptr); server_unit_list_.push_back(hsha_server_unit); } printf("server already started, %zu io threads %zu workers\n", io_count, worker_thread_count); + if (config.GetWorkerUThreadCount() > 0) { + printf("server in uthread mode, %d uthread per worker\n", config.GetWorkerUThreadCount()); + } } HshaServer :: ~HshaServer() { diff --git a/phxrpc/rpc/hsha_server.h b/phxrpc/rpc/hsha_server.h index 23608c6..059e8d6 100644 --- a/phxrpc/rpc/hsha_server.h +++ b/phxrpc/rpc/hsha_server.h @@ -47,6 +47,7 @@ class DataFlow { void PushRequest(void * args, HttpRequest * request); int PluckRequest(void *& args, HttpRequest *& request); + int PickRequest(void *& args, HttpRequest *& request); void PushResponse(void * args, HttpResponse * response); int PluckResponse(void *& args, HttpResponse *& response); bool CanPushRequest(const int max_queue_length); @@ -102,6 +103,7 @@ class HshaServerStat { friend class Worker; friend class HshaServerQos; friend class HshaServerAcceptor; + const HshaServerConfig * config_; std::mutex mutex_; std::condition_variable cv_; std::thread thread_; @@ -200,15 +202,25 @@ class HshaServerQos { class Worker { public: - Worker(WorkerPool * pool); + Worker(WorkerPool * pool, int uthread_count, int utherad_stack_size); ~Worker(); void Func(); void Shutdown(); + void ThreadMode(); + void UThreadMode(); + void HandlerNewRequestFunc(); + void UThreadFunc(void * args, HttpRequest * request, int queue_wait_time_ms); + void WorkerLogic(void * args, HttpRequest * request, int queue_wait_time_ms); + void Notify(); + private: WorkerPool * pool_; + int uthread_count_; + int utherad_stack_size_; bool shut_down_; + UThreadEpollScheduler * worker_scheduler_; std::thread thread_; }; @@ -218,18 +230,28 @@ typedef std::function< void(const HttpRequest &, HttpResponse *, DispatcherArgs_ class WorkerPool { public: - WorkerPool(UThreadEpollScheduler * scheduler, size_t thread_count, DataFlow * data_flow, - HshaServerStat * hsha_server_stat, Dispatch_t dispatch, void * args); + WorkerPool(UThreadEpollScheduler * scheduler, + int thread_count, + int uthread_count_per_thread, + int utherad_stack_size, + DataFlow * data_flow, + HshaServerStat * hsha_server_stat, + Dispatch_t dispatch, + void * args); ~WorkerPool(); + void Notify(); + private: friend class Worker; UThreadEpollScheduler * scheduler_; DataFlow * data_flow_; HshaServerStat * hsha_server_stat_; Dispatch_t dispatch_; - DispatcherArgs_t dispatcher_args_; + void * args_; std::vector worker_list_; + size_t last_notify_idx_; + std::mutex mutex_; }; ///////////////////////////////// @@ -237,7 +259,8 @@ class WorkerPool { class HshaServerIO { public: HshaServerIO(int idx, UThreadEpollScheduler * scheduler, const HshaServerConfig * config, - DataFlow * data_flow, HshaServerStat * hsha_server_stat, HshaServerQos * hsha_server_qos); + DataFlow * data_flow, HshaServerStat * hsha_server_stat, HshaServerQos * hsha_server_qos, + WorkerPool * worker_pool); ~HshaServerIO(); void RunForever(); @@ -251,11 +274,14 @@ class HshaServerIO { UThreadSocket_t * ActiveSocketFunc(); private: + int idx_; UThreadEpollScheduler * scheduler_; const HshaServerConfig * config_; DataFlow * data_flow_; + int listen_fd_; HshaServerStat * hsha_server_stat_; HshaServerQos * hsha_server_qos_; + WorkerPool * worker_pool_; std::queue accepted_fd_list_; std::mutex queue_mutex_; @@ -266,7 +292,13 @@ class HshaServerIO { class HshaServer; class HshaServerUnit { public: - HshaServerUnit(HshaServer * hsha_server, int idx, int worker_thread_count, Dispatch_t dispatch, void * args); + HshaServerUnit(HshaServer * hsha_server, + int idx, + int worker_thread_count, + int worker_uthread_count_per_thread, + int worker_utherad_stack_size, + Dispatch_t dispatch, + void * args); ~HshaServerUnit(); void RunFunc(); @@ -276,8 +308,8 @@ class HshaServerUnit { HshaServer * hsha_server_; UThreadEpollScheduler scheduler_; DataFlow data_flow_; - HshaServerIO hsha_server_io_; WorkerPool worker_pool_; + HshaServerIO hsha_server_io_; std::thread thread_; }; diff --git a/phxrpc/rpc/server_base.h b/phxrpc/rpc/server_base.h index 03b7a15..95a1719 100644 --- a/phxrpc/rpc/server_base.h +++ b/phxrpc/rpc/server_base.h @@ -22,20 +22,23 @@ See the AUTHORS file for names of contributors. #pragma once #include "server_monitor.h" +#include "phxrpc/network.h" namespace phxrpc { typedef struct tagDispatcherArgs { phxrpc::ServerMonitorPtr server_monitor; + phxrpc::UThreadEpollScheduler * server_worker_uthread_scheduler; void * service_args; tagDispatcherArgs() : service_args(NULL) { } - tagDispatcherArgs( phxrpc::ServerMonitorPtr monitor, void * args ) : - server_monitor(monitor), service_args(args) { + tagDispatcherArgs(phxrpc::ServerMonitorPtr monitor, + phxrpc::UThreadEpollScheduler * uthread_scheduler, void * args) : + server_monitor(monitor), server_worker_uthread_scheduler(uthread_scheduler), service_args(args) { } -}DispatcherArgs_t; +} DispatcherArgs_t; class ServerUtils { public: @@ -43,4 +46,3 @@ class ServerUtils { }; } - diff --git a/phxrpc/rpc/server_config.cpp b/phxrpc/rpc/server_config.cpp index d3d79aa..9f14b9a 100644 --- a/phxrpc/rpc/server_config.cpp +++ b/phxrpc/rpc/server_config.cpp @@ -126,7 +126,9 @@ HshaServerConfig :: HshaServerConfig() max_queue_length_(20480), fast_reject_threshold_ms_(20), fast_reject_adjust_rate_(5), - io_thread_count_(3) { + io_thread_count_(3), + worker_uthread_count_(0), + worker_uthread_stack_size_(64 * 1024) { } HshaServerConfig :: ~HshaServerConfig() { @@ -135,6 +137,8 @@ HshaServerConfig :: ~HshaServerConfig() { bool HshaServerConfig :: DoRead(Config & config) { config.ReadItem("Server", "MaxConnections", &max_connections_, 800000); config.ReadItem("Server", "IOThreadCount", &io_thread_count_, 3); + config.ReadItem("Server", "WorkerUThreadCount", &worker_uthread_count_, 0); + config.ReadItem("Server", "WorkerUThreadStackSize", &worker_uthread_stack_size_, 64 * 1024); config.ReadItem("Server", "MaxQueueLength", &max_queue_length_, 20480); config.ReadItem("Server", "FastRejectThresholdMS", &fast_reject_threshold_ms_, 20); config.ReadItem("Server", "FastRejectAdjustRate", &fast_reject_adjust_rate_, 5); @@ -181,4 +185,22 @@ int HshaServerConfig :: GetIOThreadCount() const { return io_thread_count_; } +void HshaServerConfig :: SetWorkerUThreadCount(const int worker_uthread_count) { + worker_uthread_count_ = worker_uthread_count; +} + +int HshaServerConfig :: GetWorkerUThreadCount() const { + return worker_uthread_count_; +} + +void HshaServerConfig :: SetWorkerUThreadStackSize(const int worker_uthread_stack_size) +{ + worker_uthread_stack_size_ = worker_uthread_stack_size; +} + +int HshaServerConfig :: GetWorkerUThreadStackSize() const +{ + return worker_uthread_stack_size_; +} + } diff --git a/phxrpc/rpc/server_config.h b/phxrpc/rpc/server_config.h index b736510..dc3d67a 100644 --- a/phxrpc/rpc/server_config.h +++ b/phxrpc/rpc/server_config.h @@ -88,12 +88,20 @@ class HshaServerConfig : public ServerConfig { void SetIOThreadCount(const int io_thread_count); int GetIOThreadCount() const; + void SetWorkerUThreadCount(const int worker_uthread_count); + int GetWorkerUThreadCount() const; + + void SetWorkerUThreadStackSize(const int worker_uthread_stack_size); + int GetWorkerUThreadStackSize() const; + private: int max_connections_; int max_queue_length_; int fast_reject_threshold_ms_; int fast_reject_adjust_rate_; int io_thread_count_; + int worker_uthread_count_; + int worker_uthread_stack_size_; }; } diff --git a/phxrpc/rpc/thread_queue.h b/phxrpc/rpc/thread_queue.h index 8892014..822df6e 100644 --- a/phxrpc/rpc/thread_queue.h +++ b/phxrpc/rpc/thread_queue.h @@ -66,6 +66,18 @@ class ThdQueue { return true; } + bool pick(T & value) { + std::lock_guard lock(mutex_); + if (queue_.empty()) { + return false; + } + + size_--; + value = queue_.front(); + queue_.pop(); + return true; + } + void break_out() { std::lock_guard lock(mutex_); break_out_ = true; From 4949c7cbcc0df57f130bafe6bde0a228c9c98a06 Mon Sep 17 00:00:00 2001 From: Haochuan Cui Date: Fri, 6 Jan 2017 15:44:21 +0800 Subject: [PATCH 36/49] Update README.md --- README.md | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1d47602..f168cdc 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https:/ - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 - 半同步半异步模式,采用独立多IO线程,通过Epoll管理请求的接入以及读写,工作线程采用固定线程池。IO线程与工作线程通过内存队列进行交互。 +  - New: 支持协程Worker,可配置多个线程,每个线程多个协程。 - 提供完善的过载保护,无需配置阈值,支持动态自适应拒绝请求。 - 提供简易的Client/Server配置读入方式。 - 基于lambda函数实现并发访问Server,可以非常方便地实现Google提出的 [Backup Requests](http://static.googleusercontent.com/media/research.google.com/zh-CN//people/jeff/Berkeley-Latency-Mar2012.pdf) 模式。 @@ -117,7 +118,11 @@ service Search{ #sample ../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . +../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . -u +两种生成模式,区别在于-u参数。 +第一种生成默认的线程池worker模型。 +第二种-u参数指定生成uthread worker模型,也就是工作线程池里面每个线程里面运行着多个协程。 调用完工具后,在生成代码放置目录下执行make,即可生成全部的RPC相关代码。 ``` @@ -181,6 +186,36 @@ int SearchClient :: PHXEcho( const google::protobuf::StringValue & req, } ``` +##### UThread Client (xxx_client_uthread.cpp) + +```c++ +//这个是默认生成的代码, 可自行修改,或利用我们提供的stub API自定义封装Client +//UThread Client只能在采用PhxRPC uthread worker模型的server中调用。 +//UThread Client构造函数需要传入UThreadEpollScheduler*类型参数, +//这个参数来源可以在xxx_service_impl.h的私有变量中获得。 + +int SearchClientUThread :: PHXEcho( const google::protobuf::StringValue & req, + google::protobuf::StringValue * resp ) +{ + const phxrpc::Endpoint_t * ep = global_searchclientuthread_config_.GetRandom(); + + if(uthread_scheduler_ != nullptr && ep != nullptr) { + phxrpc::UThreadTcpStream socket; + bool open_ret = phxrpc::PhxrpcTcpUtils::Open(uthread_scheduler_, &socket, ep->ip, ep->port, + global_searchclientuthread_config_.GetConnectTimeoutMS(), + *(global_searchclientuthread_monitor_.get())); + if ( open_ret ) { + socket.SetTimeout(global_searchclientuthread_config_.GetSocketTimeoutMS()); + + SearchStub stub(socket, *(global_searchclientuthread_monitor_.get())); + return stub.PHXEcho(req, resp); + } + } + + return -1; +} +``` + ##### Client并发调用样例 ```c++ @@ -224,14 +259,16 @@ int SearchClient :: PhxBatchEcho( const google::protobuf::StringValue & req, ```c++ [Server] -BindIP = 127.0.0.1 //Server IP -Port = 16161 //Server Port -MaxThreads = 16 //Worker 线程数 -IOThreadCount = 3 //IO线程数,针对业务请自行调节 -PackageName = search //Server 名字,用于自行实现的监控统计上报 -MaxConnections = 800000 //最大并发连接数 -MaxQueueLength = 20480 //IO队列最大长度 -FastRejectThresholdMS = 20 //快速拒绝自适应调节阀值,建议保持默认20ms,不做修改 +BindIP = 127.0.0.1 //Server IP +Port = 16161 //Server Port +MaxThreads = 16 //Worker 线程数 +WorkerUThreadCount = 50     //每个线程开启的协程数,采用-u生成的Server必须配置这一项 +WorkerUThreadStackSize = 65536 //UThread worker的栈大小 +IOThreadCount = 3               //IO线程数,针对业务请自行调节 +PackageName = search //Server 名字,用于自行实现的监控统计上报 +MaxConnections = 800000 //最大并发连接数 +MaxQueueLength = 20480 //IO队列最大长度 +FastRejectThresholdMS = 20 //快速拒绝自适应调节阀值,建议保持默认20ms,不做修改 [ServerTimeout] SocketTimeoutMS = 5000 //Server读写超时,Worker处理超时 From 05bebb99a627862c009c0ee2bb78a3869c77b97f Mon Sep 17 00:00:00 2001 From: Haochuan Cui Date: Fri, 6 Jan 2017 15:45:14 +0800 Subject: [PATCH 37/49] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f168cdc..3598516 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https:/ - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 - 半同步半异步模式,采用独立多IO线程,通过Epoll管理请求的接入以及读写,工作线程采用固定线程池。IO线程与工作线程通过内存队列进行交互。 -  - New: 支持协程Worker,可配置多个线程,每个线程多个协程。 + - New: 支持协程Worker,可配置多个线程,每个线程多个协程。 - 提供完善的过载保护,无需配置阈值,支持动态自适应拒绝请求。 - 提供简易的Client/Server配置读入方式。 - 基于lambda函数实现并发访问Server,可以非常方便地实现Google提出的 [Backup Requests](http://static.googleusercontent.com/media/research.google.com/zh-CN//people/jeff/Berkeley-Latency-Mar2012.pdf) 模式。 @@ -271,6 +271,6 @@ MaxQueueLength = 20480 //IO队列最大长度 FastRejectThresholdMS = 20 //快速拒绝自适应调节阀值,建议保持默认20ms,不做修改 [ServerTimeout] -SocketTimeoutMS = 5000 //Server读写超时,Worker处理超时 +SocketTimeoutMS = 5000 //Server读写超时,Worker处理超时 ``` From 90776339b562529398255efcaffc099ace88bece Mon Sep 17 00:00:00 2001 From: taohe Date: Wed, 2 Aug 2017 16:15:36 +0800 Subject: [PATCH 38/49] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3598516..e9f4e7c 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ 联系我们:phxteam@tencent.com -想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/tencent-wechat/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 +想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/Tencent/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 -PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https://travis-ci.org/tencent-wechat/phxrpc) +PhxRPC[![Build Status](https://travis-ci.org/Tencent/phxrpc.png)](https://travis-ci.org/Tencent/phxrpc) # 总览 - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 From 172e292b9bfb798daf645177be1b5b4aaccd9680 Mon Sep 17 00:00:00 2001 From: taohe Date: Thu, 7 Dec 2017 12:10:11 +0800 Subject: [PATCH 39/49] add mqtt protocol --- Makefile | 1 - README.md | 67 +- codegen/client_code_render.cpp | 322 +++-- codegen/client_code_render.h | 64 +- codegen/client_template.cpp | 151 ++- codegen/code_utils.cpp | 32 +- codegen/code_utils.h | 27 +- codegen/name_render.cpp | 101 +- codegen/name_render.h | 90 +- codegen/phxrpc_pb2client.cpp | 118 +- codegen/phxrpc_pb2server.cpp | 94 +- codegen/phxrpc_pb2service.cpp | 129 +- codegen/phxrpc_pb2tool.cpp | 111 +- codegen/proto_utils.cpp | 30 +- codegen/proto_utils.h | 31 +- codegen/server_code_render.cpp | 92 +- codegen/server_code_render.h | 35 +- codegen/server_template.cpp | 222 ++-- codegen/service_code_render.cpp | 488 +++++--- codegen/service_code_render.h | 77 +- codegen/syntax_tree.cpp | 82 +- codegen/syntax_tree.h | 93 +- codegen/tool_code_render.cpp | 286 +++-- codegen/tool_code_render.h | 52 +- codegen/tool_template.cpp | 88 +- phxrpc.mk | 25 +- phxrpc/Makefile | 28 +- phxrpc/file/log_utils.cpp | 33 +- phxrpc/file/log_utils.h | 32 +- phxrpc/http.h | 21 +- phxrpc/http/Makefile | 2 +- phxrpc/http/http_client.cpp | 105 +- phxrpc/http/http_client.h | 53 +- phxrpc/http/http_dispatcher.h | 38 +- phxrpc/http/http_msg.cpp | 255 ++-- phxrpc/http/http_msg.h | 143 +-- phxrpc/http/http_proto.h | 74 -- .../{http_proto.cpp => http_protocol.cpp} | 268 ++-- phxrpc/http/http_protocol.h | 67 + phxrpc/http/test_http_client.cpp | 75 +- phxrpc/mqtt.h | 28 + phxrpc/mqtt/Makefile | 16 + phxrpc/mqtt/mqtt_client.cpp | 135 ++ phxrpc/mqtt/mqtt_client.h | 91 ++ phxrpc/mqtt/mqtt_msg.cpp | 1098 +++++++++++++++++ phxrpc/mqtt/mqtt_msg.h | 548 ++++++++ phxrpc/mqtt/mqtt_protocol.cpp | 142 +++ phxrpc/mqtt/mqtt_protocol.h | 52 + phxrpc/mqtt/test_mqtt_client.cpp | 146 +++ phxrpc/mqtt/test_mqtt_protocol.cpp | 151 +++ phxrpc/msg.h | 29 + phxrpc/network/Makefile | 7 +- phxrpc/network/timer.cpp | 6 + phxrpc/network/uthread_epoll.cpp | 14 +- phxrpc/rpc.h | 18 +- phxrpc/rpc/Makefile | 11 +- phxrpc/rpc/client_config.cpp | 63 +- phxrpc/rpc/client_config.h | 40 +- phxrpc/rpc/client_monitor.cpp | 51 +- phxrpc/rpc/client_monitor.h | 34 +- phxrpc/rpc/hsha_server.cpp | 374 +++--- phxrpc/rpc/hsha_server.h | 157 +-- phxrpc/rpc/http_caller.cpp | 97 +- phxrpc/rpc/http_caller.h | 68 +- phxrpc/rpc/monitor_factory.cpp | 44 +- phxrpc/rpc/monitor_factory.h | 34 +- phxrpc/rpc/mqtt_caller.cpp | 199 +++ phxrpc/rpc/mqtt_caller.h | 89 ++ phxrpc/rpc/phxrpc.proto | 28 + phxrpc/rpc/server_config.cpp | 86 +- phxrpc/rpc/server_config.h | 53 +- phxrpc/rpc/socket_stream_phxrpc.cpp | 43 +- phxrpc/rpc/socket_stream_phxrpc.h | 37 +- phxrpc/rpc/test_hsha_server.cpp | 36 +- .../{test_client.cpp => test_http_client.cpp} | 45 +- phxrpc/rpc/test_mqtt_client.cpp | 101 ++ phxrpc/rpc/test_thread_queue.cpp | 28 +- phxrpc/rpc/uthread_caller.cpp | 95 +- phxrpc/rpc/uthread_caller.h | 107 +- sample/regen.sh | 2 +- sample/search.proto | 22 +- 81 files changed, 6056 insertions(+), 2471 deletions(-) delete mode 100644 phxrpc/http/http_proto.h rename phxrpc/http/{http_proto.cpp => http_protocol.cpp} (58%) create mode 100644 phxrpc/http/http_protocol.h create mode 100644 phxrpc/mqtt.h create mode 100644 phxrpc/mqtt/Makefile create mode 100644 phxrpc/mqtt/mqtt_client.cpp create mode 100644 phxrpc/mqtt/mqtt_client.h create mode 100644 phxrpc/mqtt/mqtt_msg.cpp create mode 100644 phxrpc/mqtt/mqtt_msg.h create mode 100644 phxrpc/mqtt/mqtt_protocol.cpp create mode 100644 phxrpc/mqtt/mqtt_protocol.h create mode 100644 phxrpc/mqtt/test_mqtt_client.cpp create mode 100644 phxrpc/mqtt/test_mqtt_protocol.cpp create mode 100644 phxrpc/msg.h create mode 100644 phxrpc/rpc/mqtt_caller.cpp create mode 100644 phxrpc/rpc/mqtt_caller.h rename phxrpc/rpc/{test_client.cpp => test_http_client.cpp} (58%) create mode 100644 phxrpc/rpc/test_mqtt_client.cpp diff --git a/Makefile b/Makefile index 9d77834..3a8118f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,3 @@ - version = 0.8.0 all: diff --git a/README.md b/README.md index e9f4e7c..31f0cfc 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,14 @@ 联系我们:phxteam@tencent.com -想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/Tencent/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 +想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/tencent-wechat/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 -PhxRPC[![Build Status](https://travis-ci.org/Tencent/phxrpc.png)](https://travis-ci.org/Tencent/phxrpc) +PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https://travis-ci.org/tencent-wechat/phxrpc) # 总览 - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 - 半同步半异步模式,采用独立多IO线程,通过Epoll管理请求的接入以及读写,工作线程采用固定线程池。IO线程与工作线程通过内存队列进行交互。 - - New: 支持协程Worker,可配置多个线程,每个线程多个协程。 - 提供完善的过载保护,无需配置阈值,支持动态自适应拒绝请求。 - 提供简易的Client/Server配置读入方式。 - 基于lambda函数实现并发访问Server,可以非常方便地实现Google提出的 [Backup Requests](http://static.googleusercontent.com/media/research.google.com/zh-CN//people/jeff/Berkeley-Latency-Mar2012.pdf) 模式。 @@ -118,11 +117,7 @@ service Search{ #sample ../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . -../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . -u -两种生成模式,区别在于-u参数。 -第一种生成默认的线程池worker模型。 -第二种-u参数指定生成uthread worker模型,也就是工作线程池里面每个线程里面运行着多个协程。 调用完工具后,在生成代码放置目录下执行make,即可生成全部的RPC相关代码。 ``` @@ -138,7 +133,7 @@ service Search{ ##### Server(xxx_service_impl.cpp) ```c++ -int SearchServiceImpl :: PHXEcho( const google::protobuf::StringValue & req, +int SearchServiceImpl :: PhxEcho( const google::protobuf::StringValue & req, google::protobuf::StringValue * resp ) { resp->set_value( req.value() ); @@ -164,7 +159,7 @@ int SearchServiceImpl :: Notify( const google::protobuf::StringValue & req, ```c++ //这个是默认生成的代码, 可自行修改,或利用我们提供的stub API自定义封装Client -int SearchClient :: PHXEcho( const google::protobuf::StringValue & req, +int SearchClient :: PhxEcho( const google::protobuf::StringValue & req, google::protobuf::StringValue * resp ) { const phxrpc::Endpoint_t * ep = global_searchclient_config_.GetRandom(); @@ -178,7 +173,7 @@ int SearchClient :: PHXEcho( const google::protobuf::StringValue & req, socket.SetTimeout(global_searchclient_config_.GetSocketTimeoutMS()); SearchStub stub(socket, *(global_searchclient_monitor_.get())); - return stub.PHXEcho(req, resp); + return stub.PhxEcho(req, resp); } } @@ -186,36 +181,6 @@ int SearchClient :: PHXEcho( const google::protobuf::StringValue & req, } ``` -##### UThread Client (xxx_client_uthread.cpp) - -```c++ -//这个是默认生成的代码, 可自行修改,或利用我们提供的stub API自定义封装Client -//UThread Client只能在采用PhxRPC uthread worker模型的server中调用。 -//UThread Client构造函数需要传入UThreadEpollScheduler*类型参数, -//这个参数来源可以在xxx_service_impl.h的私有变量中获得。 - -int SearchClientUThread :: PHXEcho( const google::protobuf::StringValue & req, - google::protobuf::StringValue * resp ) -{ - const phxrpc::Endpoint_t * ep = global_searchclientuthread_config_.GetRandom(); - - if(uthread_scheduler_ != nullptr && ep != nullptr) { - phxrpc::UThreadTcpStream socket; - bool open_ret = phxrpc::PhxrpcTcpUtils::Open(uthread_scheduler_, &socket, ep->ip, ep->port, - global_searchclientuthread_config_.GetConnectTimeoutMS(), - *(global_searchclientuthread_monitor_.get())); - if ( open_ret ) { - socket.SetTimeout(global_searchclientuthread_config_.GetSocketTimeoutMS()); - - SearchStub stub(socket, *(global_searchclientuthread_monitor_.get())); - return stub.PHXEcho(req, resp); - } - } - - return -1; -} -``` - ##### Client并发调用样例 ```c++ @@ -235,7 +200,7 @@ int SearchClient :: PhxBatchEcho( const google::protobuf::StringValue & req, *(global_searchclient_monitor_.get()))) { socket.SetTimeout(global_searchclient_config_.GetSocketTimeoutMS()); SearchStub stub(socket, *(global_searchclient_monitor_.get())); - int this_ret = stub.PHXEcho(req, resp); + int this_ret = stub.PhxEcho(req, resp); if (this_ret == 0) { ret = this_ret; uthread_s.Close(); @@ -259,18 +224,16 @@ int SearchClient :: PhxBatchEcho( const google::protobuf::StringValue & req, ```c++ [Server] -BindIP = 127.0.0.1 //Server IP -Port = 16161 //Server Port -MaxThreads = 16 //Worker 线程数 -WorkerUThreadCount = 50     //每个线程开启的协程数,采用-u生成的Server必须配置这一项 -WorkerUThreadStackSize = 65536 //UThread worker的栈大小 -IOThreadCount = 3               //IO线程数,针对业务请自行调节 -PackageName = search //Server 名字,用于自行实现的监控统计上报 -MaxConnections = 800000 //最大并发连接数 -MaxQueueLength = 20480 //IO队列最大长度 -FastRejectThresholdMS = 20 //快速拒绝自适应调节阀值,建议保持默认20ms,不做修改 +BindIP = 127.0.0.1 //Server IP +Port = 16161 //Server Port +MaxThreads = 16 //Worker 线程数 +IOThreadCount = 3 //IO线程数,针对业务请自行调节 +PackageName = search //Server 名字,用于自行实现的监控统计上报 +MaxConnections = 800000 //最大并发连接数 +MaxQueueLength = 20480 //IO队列最大长度 +FastRejectThresholdMS = 20 //快速拒绝自适应调节阀值,建议保持默认20ms,不做修改 [ServerTimeout] -SocketTimeoutMS = 5000 //Server读写超时,Worker处理超时 +SocketTimeoutMS = 5000 //Server读写超时,Worker处理超时 ``` diff --git a/codegen/client_code_render.cpp b/codegen/client_code_render.cpp index 8cdb4a0..4e87f0f 100644 --- a/codegen/client_code_render.cpp +++ b/codegen/client_code_render.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -30,19 +30,22 @@ See the AUTHORS file for names of contributors. #include #include -using namespace std; using namespace phxrpc; +using namespace std; + -ClientCodeRender::ClientCodeRender(NameRender & name_render) +ClientCodeRender::ClientCodeRender(NameRender &name_render) : name_render_(name_render) { } ClientCodeRender::~ClientCodeRender() { } -void ClientCodeRender::GenerateStubHpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ClientCodeRender::GenerateStubHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetStubFileName(stree->GetName(), filename, sizeof(filename)); string buffer; @@ -60,41 +63,53 @@ void ClientCodeRender::GenerateStubHpp(SyntaxTree * stree, FILE * write) { name_render_.GetMessageFileName(stree->GetProtoFile(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); + fprintf(write, "\n"); fprintf(write, "\n"); fprintf(write, "namespace phxrpc {\n"); - fprintf(write, " class BaseTcpStream;\n"); - fprintf(write, " class ClientMonitor;\n"); + fprintf(write, "\n"); + fprintf(write, "\n"); + fprintf(write, "class BaseTcpStream;\n"); + fprintf(write, "class ClientMonitor;\n"); + fprintf(write, "\n"); + fprintf(write, "\n"); fprintf(write, "}\n"); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetStubClasname(stree->GetName(), clasname, sizeof(clasname)); { - fprintf(write, "class %s\n", clasname); - fprintf(write, "{\n"); - fprintf(write, "public:\n"); - fprintf(write, " %s( phxrpc::BaseTcpStream & socket, phxrpc::ClientMonitor & client_monitor );\n", clasname); - fprintf(write, " ~%s();\n", clasname); + fprintf(write, "class %s {\n", clasname); + fprintf(write, " public:\n"); + fprintf(write, " %s(phxrpc::BaseTcpStream &socket, phxrpc::ClientMonitor &client_monitor);\n", clasname); + fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); - fprintf(write, " void SetKeepAlive( const bool keep_alive );\n\n"); + fprintf(write, " void SetKeepAlive(const bool keep_alive);\n\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + string buffer; + GetStubFuncDeclaration(stree, &(*mqtt_it), 1, &buffer); + fprintf(write, " %s;\n", buffer.c_str()); + } + fprintf(write, "\n"); - std::string buffer; + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + string buffer; GetStubFuncDeclaration(stree, &(*fit), 1, &buffer); fprintf(write, " %s;\n", buffer.c_str()); - fprintf(write, "\n"); } + fprintf(write, "\n"); - fprintf(write, "private:\n"); - fprintf(write, " phxrpc::BaseTcpStream & socket_;\n"); - fprintf(write, " phxrpc::ClientMonitor & client_monitor_;\n"); + fprintf(write, " private:\n"); + fprintf(write, " phxrpc::BaseTcpStream &socket_;\n"); + fprintf(write, " phxrpc::ClientMonitor &client_monitor_;\n"); fprintf(write, " bool keep_alive_;\n"); fprintf(write, "};\n"); @@ -103,32 +118,37 @@ void ClientCodeRender::GenerateStubHpp(SyntaxTree * stree, FILE * write) { } } -void ClientCodeRender::GetStubFuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, - std::string * result) { - char clasname[128] = { 0 }, type_name[128] = { 0 }; +void ClientCodeRender::GetStubFuncDeclaration(SyntaxTree *stree, + const SyntaxFunc *const func, + int is_header, string *result) { + char clasname[128]{0}, type_name[128]{0}; name_render_.GetStubClasname(stree->GetName(), clasname, sizeof(clasname)); if (is_header) { - phxrpc::StrAppendFormat(result, "int %s( ", func->GetName()); + phxrpc::StrAppendFormat(result, "int %s(", func->GetName()); } else { - phxrpc::StrAppendFormat(result, "int %s :: %s( ", clasname, func->GetName()); + phxrpc::StrAppendFormat(result, "int %s::%s(", clasname, func->GetName()); } name_render_.GetMessageClasname(func->GetReq()->GetType(), type_name, sizeof(type_name)); - phxrpc::StrAppendFormat(result, "const %s & req,\n", type_name); + phxrpc::StrAppendFormat(result, "const %s &req", type_name); - name_render_.GetMessageClasname(func->GetResp()->GetType(), type_name, sizeof(type_name)); - phxrpc::StrAppendFormat(result, " %s * resp", type_name); + const char *const resp_type{func->GetResp()->GetType()}; + if (resp_type && 0 < strlen(resp_type)) { + name_render_.GetMessageClasname(resp_type, type_name, sizeof(type_name)); + phxrpc::StrAppendFormat(result, ", %s *resp", type_name); + } - phxrpc::StrAppendFormat(result, " )"); + phxrpc::StrAppendFormat(result, ")"); } -void ClientCodeRender::GenerateStubCpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ClientCodeRender::GenerateStubCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, FILE *write) { + char filename[128]{0}; name_render_.GetStubFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2client", stree->GetProtoFile(), &buffer); fprintf(write, "/* %s.cpp\n", filename); @@ -146,61 +166,87 @@ void ClientCodeRender::GenerateStubCpp(SyntaxTree * stree, FILE * write) { name_render_.GetMessageFileName(stree->GetProtoFile(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); fprintf(write, "\n"); + fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetStubClasname(stree->GetName(), clasname, sizeof(clasname)); { - fprintf(write, "%s :: %s( phxrpc::BaseTcpStream & socket, phxrpc::ClientMonitor & client_monitor )\n", + fprintf(write, "%s::%s(phxrpc::BaseTcpStream &socket, phxrpc::ClientMonitor &client_monitor)\n", clasname, clasname); - fprintf(write, " : socket_( socket ), client_monitor_(client_monitor), keep_alive_(false)\n"); - fprintf(write, "{\n"); + fprintf(write, " : socket_(socket), client_monitor_(client_monitor), keep_alive_(false) {\n"); fprintf(write, "}\n"); fprintf(write, "\n"); - fprintf(write, "%s :: ~%s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::~%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - fprintf(write, "void %s :: SetKeepAlive( const bool keep_alive )\n", clasname ); - fprintf(write, "{\n"); + fprintf(write, "void %s::SetKeepAlive(const bool keep_alive) {\n", clasname ); fprintf(write, " keep_alive_ = keep_alive;\n"); fprintf(write, "}\n"); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + GenerateMqttStubFunc(stree, &(*mqtt_it), write); + } + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { GenerateStubFunc(stree, &(*fit), write); } + } } -void ClientCodeRender::GenerateStubFunc(SyntaxTree * stree, SyntaxFunc * func, FILE * write) { - std::string buffer; +void ClientCodeRender::GenerateStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, + FILE *write) { + string buffer; GetStubFuncDeclaration(stree, func, 0, &buffer); - fprintf(write, "%s\n", buffer.c_str()); + fprintf(write, "%s {\n", buffer.c_str()); - fprintf(write, "{\n"); - fprintf(write, " phxrpc::HttpCaller caller( socket_, client_monitor_ );\n"); - fprintf(write, " caller.SetURI( \"/%s/%s\", %d );\n", stree->GetPackageName(), func->GetName(), - func->GetCmdID()); - fprintf(write, " caller.SetKeepAlive( keep_alive_ );\n"); - fprintf(write, " return caller.Call( req, resp );\n"); + fprintf(write, " phxrpc::HttpCaller caller(socket_, client_monitor_);\n"); + fprintf(write, " caller.SetURI(\"/%s/%s\", %d);\n", + stree->GetPackageName(), func->GetName(), func->GetCmdID()); + fprintf(write, " caller.SetKeepAlive(keep_alive_);\n"); + fprintf(write, " return caller.Call(req, resp);\n"); fprintf(write, "}\n"); fprintf(write, "\n"); } -void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { - char filename[128] = { 0 }; +void ClientCodeRender::GenerateMqttStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, + FILE *write) { + string buffer; + + GetStubFuncDeclaration(stree, func, 0, &buffer); + + fprintf(write, "%s {\n", buffer.c_str()); + + fprintf(write, " phxrpc::MqttCaller caller(socket_, client_monitor_);\n"); + fprintf(write, " caller.SetCmdId(%d);\n", func->GetCmdID()); + if (0 == strcmp(func->GetName(), "PhxMqttDisconnect")) { + fprintf(write, " return caller.%sCall(req);\n", func->GetName()); + } else { + fprintf(write, " return caller.%sCall(req, resp);\n", func->GetName()); + } + + fprintf(write, "}\n"); + fprintf(write, "\n"); +} + +void ClientCodeRender::GenerateClientHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write, const bool is_uthread_mode) { + char filename[128]{0}; name_render_.GetClientFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2client", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.h\n", filename); @@ -212,29 +258,41 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write, const fprintf(write, "\n"); - std::string declarations; + string declarations; + { - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - std::string buffer; + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + string buffer; + GetClienfuncDeclaration(stree, &(*mqtt_it), 1, &buffer, is_uthread_mode); + + declarations.append(" ").append(buffer).append(";\n"); + } + declarations.append("\n"); + } + + { + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + string buffer; GetClienfuncDeclaration(stree, &(*fit), 1, &buffer, is_uthread_mode); - declarations.append(" ").append(buffer).append(";\n\n"); + declarations.append(" ").append(buffer).append(";\n"); - if (strcmp(fit->GetName(), "PHXEcho") == 0) { + if (0 == strcmp(fit->GetName(), "PhxEcho")) { SyntaxFunc echo_func = *fit; echo_func.SetName("PhxBatchEcho"); - std::string buffer; + string buffer; GetClienfuncDeclaration(stree, &echo_func, 1, &buffer, is_uthread_mode); - declarations.append(" ").append(buffer).append(";\n\n"); + declarations.append(" ").append(buffer).append(";\n"); } } } - char client_class[128] = { 0 }, message_file[128] = { 0 }; - char client_class_lower[128] = { 0 }; + char client_class[128]{0}, message_file[128]{0}; + char client_class_lower[128]{0}; name_render_.GetClientClasname(stree->GetName(), client_class, sizeof(client_class)); name_render_.GetClientClasnameLower(stree->GetName(), client_class_lower, sizeof(client_class_lower)); name_render_.GetMessageFileName(stree->GetProtoFile(), message_file, sizeof(message_file)); @@ -246,7 +304,7 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write, const client_class_lower_str += "uthread"; } - std::string content; + string content; if (!is_uthread_mode) { content = PHXRPC_CLIENT_HPP_TEMPLATE; } else { @@ -262,12 +320,15 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree * stree, FILE * write, const fprintf(write, "%s", content.c_str()); fprintf(write, "\n"); + fprintf(write, "\n"); } -void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { - char client_class[128] = { 0 }, client_file[128] = { 0 }; - char client_class_lower[128] = { 0 }; - char stub_class[128] = { 0 }, stub_file[128] = { 0 }; +void ClientCodeRender::GenerateClientCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, FILE *write, + const bool is_uthread_mode) { + char client_class[128]{0}, client_file[128]{0}; + char client_class_lower[128]{0}; + char stub_class[128]{0}, stub_file[128]{0}; name_render_.GetClientClasname(stree->GetName(), client_class, sizeof(client_class)); name_render_.GetClientClasnameLower(stree->GetName(), client_class_lower, sizeof(client_class_lower)); name_render_.GetClientFileName(stree->GetName(), client_file, sizeof(client_file)); @@ -281,7 +342,7 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write, const client_class_lower_str += "uthread"; } - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2client", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.cpp\n", client_file); @@ -290,17 +351,50 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write, const fprintf(write, "\n"); - std::string functions; + string functions; + { - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - std::string buffer; + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + string buffer; + GetClienfuncDeclaration(stree, &(*mqtt_it), 0, &buffer, is_uthread_mode); + + functions.append(buffer).append(" "); + + string content; + if (!is_uthread_mode) { + content = PHXRPC_CLIENT_FUNC_TEMPLATE; + } else { + content = PHXRPC_UTHREAD_CLIENT_FUNC_TEMPLATE; + } + + StrTrim(&content); + StrReplaceAll(&content, "$ClientClass$", client_class_str.c_str()); + StrReplaceAll(&content, "$ClientClassLower$", client_class_lower_str.c_str()); + StrReplaceAll(&content, "$StubClass$", stub_class); + string func_string(mqtt_it->GetName()); + const char *const resp_type{mqtt_it->GetResp()->GetType()}; + if (resp_type && 0 < strlen(resp_type)) { + func_string += "(req, resp)"; + } else { + func_string += "(req)"; + } + StrReplaceAll(&content, "$Func$", func_string); + + functions.append(content).append("\n\n"); + } + } + + { + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + string buffer; GetClienfuncDeclaration(stree, &(*fit), 0, &buffer, is_uthread_mode); - functions.append(buffer).append("\n"); + functions.append(buffer).append(" "); - std::string content; + string content; if (!is_uthread_mode) { content = PHXRPC_CLIENT_FUNC_TEMPLATE; } else { @@ -311,33 +405,37 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write, const StrReplaceAll(&content, "$ClientClass$", client_class_str.c_str()); StrReplaceAll(&content, "$ClientClassLower$", client_class_lower_str.c_str()); StrReplaceAll(&content, "$StubClass$", stub_class); - StrReplaceAll(&content, "$Func$", fit->GetName()); + string func_string(fit->GetName()); + func_string += "(req, resp)"; + StrReplaceAll(&content, "$Func$", func_string); functions.append(content).append("\n\n"); - if (strcmp(fit->GetName(), "PHXEcho") == 0) { + if (strcmp(fit->GetName(), "PhxEcho") == 0) { SyntaxFunc echo_func = *fit; echo_func.SetName("PhxBatchEcho"); - std::string buffer; + string buffer; GetClienfuncDeclaration(stree, &echo_func, 0, &buffer, is_uthread_mode); - functions.append(buffer).append("\n"); + functions.append(buffer).append(" "); - std::string content = PHXRPC_BATCH_CLIENT_FUNC_TEMPLATE; + string content = PHXRPC_BATCH_CLIENT_FUNC_TEMPLATE; StrTrim(&content); StrReplaceAll(&content, "$ClientClass$", client_class_str.c_str()); StrReplaceAll(&content, "$ClientClassLower$", client_class_lower_str.c_str()); StrReplaceAll(&content, "$StubClass$", stub_class); - StrReplaceAll(&content, "$Func$", echo_func.GetName()); + string echo_func_string(echo_func.GetName()); + echo_func_string += "(req, resp)"; + StrReplaceAll(&content, "$Func$", echo_func_string); functions.append(content).append("\n\n"); } } } - std::string content; + string content; if (!is_uthread_mode) { content = PHXRPC_CLIENT_CPP_TEMPLATE; } else { @@ -353,13 +451,13 @@ void ClientCodeRender::GenerateClientCpp(SyntaxTree * stree, FILE * write, const StrReplaceAll(&content, "$ClientClassFuncs$", functions); fprintf(write, "%s", content.c_str()); - - fprintf(write, "\n"); } -void ClientCodeRender::GetClienfuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, - std::string * result, const bool is_uthread_mode) { - char clasname[128] = { 0 }, type_name[128] = { 0 }; +void ClientCodeRender::GetClienfuncDeclaration(SyntaxTree *stree, + const SyntaxFunc *const func, + int is_header, string *result, + const bool is_uthread_mode) { + char clasname[128]{0}, type_name[128]{0}; name_render_.GetClientClasname(stree->GetName(), clasname, sizeof(clasname)); string clasname_str = string(clasname); @@ -368,25 +466,28 @@ void ClientCodeRender::GetClienfuncDeclaration(SyntaxTree * stree, SyntaxFunc * } if (is_header) { - phxrpc::StrAppendFormat(result, "int %s( ", func->GetName()); + phxrpc::StrAppendFormat(result, "int %s(", func->GetName()); } else { - phxrpc::StrAppendFormat(result, "int %s :: %s( ", clasname_str.c_str(), func->GetName()); + phxrpc::StrAppendFormat(result, "int %s::%s(", clasname_str.c_str(), func->GetName()); } name_render_.GetMessageClasname(func->GetReq()->GetType(), type_name, sizeof(type_name)); - phxrpc::StrAppendFormat(result, "const %s & req,\n", type_name); + phxrpc::StrAppendFormat(result, "const %s &req", type_name); - name_render_.GetMessageClasname(func->GetResp()->GetType(), type_name, sizeof(type_name)); - phxrpc::StrAppendFormat(result, " %s * resp", type_name); + const char *const resp_type{func->GetResp()->GetType()}; + if (resp_type && 0 < strlen(resp_type)) { + name_render_.GetMessageClasname(resp_type, type_name, sizeof(type_name)); + phxrpc::StrAppendFormat(result, ", %s *resp", type_name); + } - phxrpc::StrAppendFormat(result, " )"); + phxrpc::StrAppendFormat(result, ")"); } -void ClientCodeRender::GenerateClientEtc(SyntaxTree * stree, FILE * write) { - char etcfile[128] = { 0 }; +void ClientCodeRender::GenerateClientEtc(SyntaxTree *stree, FILE *write) { + char etcfile[128]{0}; name_render_.GetClientEtcFileName(stree->GetName(), etcfile, sizeof(etcfile)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2server", stree->GetProtoFile(), &buffer, false, "#"); fprintf(write, "# %s\n", etcfile); @@ -394,11 +495,12 @@ void ClientCodeRender::GenerateClientEtc(SyntaxTree * stree, FILE * write) { fprintf(write, "#\n"); fprintf(write, "\n"); - std::string content(PHXRPC_CLIENT_ETC_TEMPLATE); + string content(PHXRPC_CLIENT_ETC_TEMPLATE); StrTrim(&content); StrReplaceAll(&content, "$PackageName$", stree->GetPackageName() ); fprintf(write, "%s", content.c_str()); fprintf(write, "\n"); + fprintf(write, "\n"); } diff --git a/codegen/client_code_render.h b/codegen/client_code_render.h index d9e7a1c..f704af0 100755 --- a/codegen/client_code_render.h +++ b/codegen/client_code_render.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,42 +21,58 @@ See the AUTHORS file for names of contributors. #pragma once -#include +#include #include +#include + namespace phxrpc { + class NameRender; class SyntaxTree; class SyntaxFunc; +typedef std::vector SyntaxFuncVector; class ClientCodeRender { - public: - ClientCodeRender(NameRender & name_render); - ~ClientCodeRender(); + public: + ClientCodeRender(NameRender &name_render); + virtual ~ClientCodeRender(); - void GenerateStubHpp(SyntaxTree * stree, FILE * write); + void GenerateStubHpp(SyntaxTree *stree, const SyntaxFuncVector &mqtt_funcs, + FILE *write); - void GenerateStubCpp(SyntaxTree * stree, FILE * write); + void GenerateStubCpp(SyntaxTree *stree, const SyntaxFuncVector &mqtt_funcs, + FILE *write); - void GenerateClientHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); + void GenerateClientHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write, const bool is_uthread_mode); - void GenerateClientCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); + void GenerateClientCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write, const bool is_uthread_mode); - void GenerateClientEtc(SyntaxTree * stree, FILE * write); + void GenerateClientEtc(SyntaxTree *stree, FILE *write); - private: + private: + void GetStubFuncDeclaration(SyntaxTree *stree, const SyntaxFunc *const func, + int is_header, std::string *result); - void GetStubFuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, std::string * result); + void GenerateStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, + FILE *write); - void GenerateStubFunc(SyntaxTree * stree, SyntaxFunc * func, FILE * write); + void GenerateMqttStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, + FILE *write); - void GetClienfuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, std::string * result, - const bool is_uthread_mode); + void GetClienfuncDeclaration(SyntaxTree *stree, + const SyntaxFunc *const func, + int is_header, std::string *result, + const bool is_uthread_mode); - private: - NameRender & name_render_; + NameRender &name_render_; }; + } diff --git a/codegen/client_template.cpp b/codegen/client_template.cpp index 24f9904..56a6926 100644 --- a/codegen/client_template.cpp +++ b/codegen/client_template.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -25,16 +25,15 @@ const char * PHXRPC_CLIENT_HPP_TEMPLATE = #include "$MessageFile$.h" #include "phxrpc/rpc.h" -class $ClientClass$ -{ -public: - static bool Init( const char * config_file ); - static const char * GetPackageName(); +class $ClientClass$ { + public: + static bool Init(const char *config_file); + + static const char *GetPackageName(); -public: $ClientClass$(); - ~$ClientClass$(); + virtual ~$ClientClass$(); $ClientClassFuncDeclarations$ }; @@ -50,21 +49,19 @@ const char * PHXRPC_UTHREAD_CLIENT_HPP_TEMPLATE = #include "phxrpc/rpc.h" #include "phxrpc/network.h" -class $ClientClass$ -{ -public: - static bool Init( const char * config_file ); - static const char * GetPackageName(); +class $ClientClass$ { + public: + static bool Init(const char *config_file); -public: - $ClientClass$(phxrpc::UThreadEpollScheduler * uthread_scheduler); - ~$ClientClass$(); + static const char *GetPackageName(); -$ClientClassFuncDeclarations$ + $ClientClass$(phxrpc::UThreadEpollScheduler *uthread_scheduler); + virtual ~$ClientClass$(); -private: - phxrpc::UThreadEpollScheduler * uthread_scheduler_; +$ClientClassFuncDeclarations$ + private: + phxrpc::UThreadEpollScheduler *uthread_scheduler_; }; )"; @@ -74,48 +71,48 @@ class $ClientClass$ const char * PHXRPC_CLIENT_CPP_TEMPLATE = R"( +#include "$ClientFile$.h" + +#include #include #include -#include #include -#include "$ClientFile$.h" #include "$StubFile$.h" #include "phxrpc/rpc.h" + static phxrpc::ClientConfig global_$ClientClassLower$_config_; static phxrpc::ClientMonitorPtr global_$ClientClassLower$_monitor_; -bool $ClientClass$ :: Init( const char * config_file ) -{ - return global_$ClientClassLower$_config_.Read( config_file ); + +bool $ClientClass$::Init(const char *config_file) { + return global_$ClientClassLower$_config_.Read(config_file); } -const char * $ClientClass$ :: GetPackageName() { - const char * ret = global_$ClientClassLower$_config_.GetPackageName(); +const char *$ClientClass$::GetPackageName() { + const char *ret = global_$ClientClassLower$_config_.GetPackageName(); if (strlen(ret) == 0) { ret = "$PackageName$"; } return ret; } -$ClientClass$ :: $ClientClass$() -{ +$ClientClass$::$ClientClass$() { static std::mutex monitor_mutex; - if ( !global_$ClientClassLower$_monitor_.get() ) { + if (!global_$ClientClassLower$_monitor_.get()) { monitor_mutex.lock(); - if ( !global_$ClientClassLower$_monitor_.get() ) { + if (!global_$ClientClassLower$_monitor_.get()) { global_$ClientClassLower$_monitor_ = phxrpc::MonitorFactory::GetFactory() - ->CreateClientMonitor( GetPackageName() ); + ->CreateClientMonitor(GetPackageName()); } - global_$ClientClassLower$_config_.SetClientMonitor( global_$ClientClassLower$_monitor_ ); + global_$ClientClassLower$_config_.SetClientMonitor(global_$ClientClassLower$_monitor_); monitor_mutex.unlock(); } } -$ClientClass$ :: ~$ClientClass$() -{ +$ClientClass$::~$ClientClass$() { } $ClientClassFuncs$ @@ -126,49 +123,49 @@ const char * $ClientClass$ :: GetPackageName() { const char * PHXRPC_UTHREAD_CLIENT_CPP_TEMPLATE = R"( +#include "$ClientFile$_uthread.h" + +#include #include #include -#include #include -#include "$ClientFile$_uthread.h" #include "$StubFile$.h" #include "phxrpc/rpc.h" + static phxrpc::ClientConfig global_$ClientClassLower$_config_; static phxrpc::ClientMonitorPtr global_$ClientClassLower$_monitor_; -bool $ClientClass$ :: Init( const char * config_file ) -{ - return global_$ClientClassLower$_config_.Read( config_file ); + +bool $ClientClass$::Init(const char *config_file) { + return global_$ClientClassLower$_config_.Read(config_file); } -const char * $ClientClass$ :: GetPackageName() { - const char * ret = global_$ClientClassLower$_config_.GetPackageName(); +const char *$ClientClass$::GetPackageName() { + const char *ret = global_$ClientClassLower$_config_.GetPackageName(); if (strlen(ret) == 0) { ret = "$PackageName$"; } return ret; } -$ClientClass$ :: $ClientClass$(phxrpc::UThreadEpollScheduler * uthread_scheduler) -{ +$ClientClass$::$ClientClass$(phxrpc::UThreadEpollScheduler *uthread_scheduler) { uthread_scheduler_ = uthread_scheduler; static std::mutex monitor_mutex; - if ( !global_$ClientClassLower$_monitor_.get() ) { + if (!global_$ClientClassLower$_monitor_.get()) { monitor_mutex.lock(); - if ( !global_$ClientClassLower$_monitor_.get() ) { + if (!global_$ClientClassLower$_monitor_.get()) { global_$ClientClassLower$_monitor_ = phxrpc::MonitorFactory::GetFactory() - ->CreateClientMonitor( GetPackageName() ); + ->CreateClientMonitor(GetPackageName()); } - global_$ClientClassLower$_config_.SetClientMonitor( global_$ClientClassLower$_monitor_ ); + global_$ClientClassLower$_config_.SetClientMonitor(global_$ClientClassLower$_monitor_); monitor_mutex.unlock(); } } -$ClientClass$ :: ~$ClientClass$() -{ +$ClientClass$::~$ClientClass$() { } $ClientClassFuncs$ @@ -179,19 +176,19 @@ const char * $ClientClass$ :: GetPackageName() { const char * PHXRPC_CLIENT_FUNC_TEMPLATE = R"( { - const phxrpc::Endpoint_t * ep = global_$ClientClassLower$_config_.GetRandom(); + const phxrpc::Endpoint_t *ep = global_$ClientClassLower$_config_.GetRandom(); - if(ep != nullptr) { + if (ep != nullptr) { phxrpc::BlockTcpStream socket; bool open_ret = phxrpc::PhxrpcTcpUtils::Open(&socket, ep->ip, ep->port, - global_$ClientClassLower$_config_.GetConnectTimeoutMS(), NULL, 0, + global_$ClientClassLower$_config_.GetConnectTimeoutMS(), nullptr, 0, *(global_$ClientClassLower$_monitor_.get())); - if ( open_ret ) { + if (open_ret) { socket.SetTimeout(global_$ClientClassLower$_config_.GetSocketTimeoutMS()); $StubClass$ stub(socket, *(global_$ClientClassLower$_monitor_.get())); - return stub.$Func$(req, resp); - } + return stub.$Func$; + } } return -1; @@ -203,19 +200,19 @@ const char * PHXRPC_CLIENT_FUNC_TEMPLATE = const char * PHXRPC_UTHREAD_CLIENT_FUNC_TEMPLATE = R"( { - const phxrpc::Endpoint_t * ep = global_$ClientClassLower$_config_.GetRandom(); + const phxrpc::Endpoint_t *ep = global_$ClientClassLower$_config_.GetRandom(); - if(uthread_scheduler_ != nullptr && ep != nullptr) { + if (uthread_scheduler_ != nullptr && ep != nullptr) { phxrpc::UThreadTcpStream socket; bool open_ret = phxrpc::PhxrpcTcpUtils::Open(uthread_scheduler_, &socket, ep->ip, ep->port, - global_$ClientClassLower$_config_.GetConnectTimeoutMS(), + global_$ClientClassLower$_config_.GetConnectTimeoutMS(), *(global_$ClientClassLower$_monitor_.get())); - if ( open_ret ) { + if (open_ret) { socket.SetTimeout(global_$ClientClassLower$_config_.GetSocketTimeoutMS()); $StubClass$ stub(socket, *(global_$ClientClassLower$_monitor_.get())); - return stub.$Func$(req, resp); - } + return stub.$Func$; + } } return -1; @@ -227,27 +224,27 @@ const char * PHXRPC_UTHREAD_CLIENT_FUNC_TEMPLATE = const char * PHXRPC_BATCH_CLIENT_FUNC_TEMPLATE = R"( { - int ret = -1; + int ret = -1; size_t echo_server_count = 2; uthread_begin; - for (size_t i = 0; i < echo_server_count; i++) { + for (size_t i{0}; echo_server_count > i; ++i) { uthread_t [=, &uthread_s, &ret](void *) { - const phxrpc::Endpoint_t * ep = global_$ClientClassLower$_config_.GetByIndex(i); + const phxrpc::Endpoint_t *ep = global_$ClientClassLower$_config_.GetByIndex(i); if (ep != nullptr) { phxrpc::UThreadTcpStream socket; if(phxrpc::PhxrpcTcpUtils::Open(&uthread_s, &socket, ep->ip, ep->port, - global_$ClientClassLower$_config_.GetConnectTimeoutMS(), *(global_$ClientClassLower$_monitor_.get()))) { + global_$ClientClassLower$_config_.GetConnectTimeoutMS(), *(global_$ClientClassLower$_monitor_.get()))) { socket.SetTimeout(global_$ClientClassLower$_config_.GetSocketTimeoutMS()); $StubClass$ stub(socket, *(global_$ClientClassLower$_monitor_.get())); - int this_ret = stub.PHXEcho(req, resp); + int this_ret = stub.PhxEcho(req, resp); if (this_ret == 0) { ret = this_ret; uthread_s.Close(); - } - } + } + } } - }; - } + }; + } uthread_end; return ret; } diff --git a/codegen/code_utils.cpp b/codegen/code_utils.cpp index dc7c1d8..83ed7e6 100644 --- a/codegen/code_utils.cpp +++ b/codegen/code_utils.cpp @@ -1,34 +1,37 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include +#include +#include #include "code_utils.h" + using namespace std; + namespace phxrpc { -void StrTrim(string * str, const char * to_trim) { + +void StrTrim(string *str, const char *to_trim) { string::size_type start_pos = 0; string::size_type end_pos = 0; @@ -43,7 +46,7 @@ void StrTrim(string * str, const char * to_trim) { } } -void StrReplaceAll(string * haystack, string needle, string s) { +void StrReplaceAll(string *haystack, string needle, string s) { string::size_type pos = 0; while ((pos = haystack->find(needle, pos)) != string::npos) { haystack->erase(pos, needle.length()); @@ -52,8 +55,8 @@ void StrReplaceAll(string * haystack, string needle, string s) { } } -void StrAppendFormat(string * result, const char * fmt, ...) { - if (NULL == fmt) +void StrAppendFormat(string *result, const char *fmt, ...) { + if (nullptr == fmt) return; size_t len = 0; @@ -75,5 +78,6 @@ void StrAppendFormat(string * result, const char * fmt, ...) { } } + } diff --git a/codegen/code_utils.h b/codegen/code_utils.h index f36af10..1229eb8 100644 --- a/codegen/code_utils.h +++ b/codegen/code_utils.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -23,11 +23,16 @@ See the AUTHORS file for names of contributors. #include + namespace phxrpc { -void StrTrim(std::string * str, const char * to_trim = "\t\r\n"); -void StrReplaceAll(std::string * haystack, std::string needle, std::string s); -void StrAppendFormat(std::string * result, const char* fmt, ...) __attribute__((format(printf, 2, 3))); +void StrTrim(std::string *str, const char *to_trim = "\t\r\n"); + +void StrReplaceAll(std::string *haystack, std::string needle, std::string s); + +void StrAppendFormat(std::string *result, const char *fmt, ...) __attribute__((format(printf, 2, 3))); + + } diff --git a/codegen/name_render.cpp b/codegen/name_render.cpp index 16cf1f0..7540788 100644 --- a/codegen/name_render.cpp +++ b/codegen/name_render.cpp @@ -1,28 +1,27 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include - +#include +#include +#include #include #include "name_render.h" @@ -30,9 +29,12 @@ See the AUTHORS file for names of contributors. #include "code_utils.h" + using namespace phxrpc; +using namespace std; + -NameRender::NameRender(const char * prefix) { +NameRender::NameRender(const char *prefix) { memset(prefix_, 0, sizeof(prefix_)); strncpy(prefix_, prefix, sizeof(prefix_) - 1); } @@ -40,7 +42,7 @@ NameRender::NameRender(const char * prefix) { NameRender::~NameRender() { } -const char * NameRender::GetPrefix(char * dest, int size) { +const char *NameRender::GetPrefix(char *dest, int size) { snprintf(dest, size, "%s", prefix_); ToUpper(dest); @@ -48,8 +50,8 @@ const char * NameRender::GetPrefix(char * dest, int size) { return dest; } -const char * NameRender::GetMessageClasname(const char * type, char * name, int size) { - std::string tmp = type; +const char *NameRender::GetMessageClasname(const char *type, char *name, int size) { + string tmp = type; phxrpc::StrReplaceAll(&tmp, ".", "::"); @@ -58,11 +60,11 @@ const char * NameRender::GetMessageClasname(const char * type, char * name, int return name; } -const char * NameRender::GetMessageFileName(const char *name, char * dest, int size) { +const char *NameRender::GetMessageFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%s", prefix_, name); - char * pos = strrchr(dest, '.'); - if (NULL != pos) + char *pos{strrchr(dest, '.')}; + if (nullptr != pos) *pos = '\0'; strncat(dest, ".pb", size); @@ -72,7 +74,7 @@ const char * NameRender::GetMessageFileName(const char *name, char * dest, int s return dest; } -char * NameRender::ToLower(char *s) { +char *NameRender::ToLower(char *s) { char *ret = s; for (; *s != '\0'; ++s) @@ -81,7 +83,7 @@ char * NameRender::ToLower(char *s) { return ret; } -char * NameRender::ToUpper(char *s) { +char *NameRender::ToUpper(char *s) { char * ret = s; for (; *s != '\0'; s++) @@ -90,13 +92,13 @@ char * NameRender::ToUpper(char *s) { return ret; } -const char * NameRender::GetStubClasname(const char * name, char *dest, int size) { +const char *NameRender::GetStubClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sStub", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetStubFileName(const char *name, char * dest, int size) { +const char *NameRender::GetStubFileName(const char *name, char *dest, int size) { snprintf(dest, size, "phxrpc_%s%c%s_stub", prefix_, toupper(*name), name + 1); ToLower(dest); @@ -104,13 +106,13 @@ const char * NameRender::GetStubFileName(const char *name, char * dest, int size return dest; } -const char * NameRender::GetClientClasname(const char *name, char * dest, int size) { +const char *NameRender::GetClientClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sClient", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetClientClasnameLower(const char *name, char * dest, int size) { +const char *NameRender::GetClientClasnameLower(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sClient", prefix_, toupper(*name), name + 1); ToLower(dest); @@ -118,7 +120,7 @@ const char * NameRender::GetClientClasnameLower(const char *name, char * dest, i return dest; } -const char * NameRender::GetClientFileName(const char *name, char * dest, int size) { +const char *NameRender::GetClientFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%s_client", prefix_, toupper(*name), name + 1); ToLower(dest); @@ -126,7 +128,7 @@ const char * NameRender::GetClientFileName(const char *name, char * dest, int si return dest; } -const char * NameRender::GetClientEtcFileName(const char *name, char * dest, int size) { +const char *NameRender::GetClientEtcFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%s_client.conf", prefix_, name); ToLower(dest); @@ -134,12 +136,12 @@ const char * NameRender::GetClientEtcFileName(const char *name, char * dest, int return dest; } -const char * NameRender::GetServerConfigClasname(const char *name, char * dest, int size) { +const char *NameRender::GetServerConfigClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sServerConfig", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetServerConfigFileName(const char *name, char * dest, int size) { +const char *NameRender::GetServerConfigFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%s_server_config", prefix_, toupper(*name), name + 1); ToLower(dest); @@ -147,7 +149,7 @@ const char * NameRender::GetServerConfigFileName(const char *name, char * dest, return dest; } -const char * NameRender::GetServerEtcFileName(const char *name, char * dest, int size) { +const char *NameRender::GetServerEtcFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%s_server.conf", prefix_, name); ToLower(dest); @@ -155,7 +157,7 @@ const char * NameRender::GetServerEtcFileName(const char *name, char * dest, int return dest; } -const char * NameRender::GetServerMainFileName(const char *name, char * dest, int size) { +const char *NameRender::GetServerMainFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%s_main", prefix_, toupper(*name), name + 1); ToLower(dest); @@ -163,13 +165,13 @@ const char * NameRender::GetServerMainFileName(const char *name, char * dest, in return dest; } -const char * NameRender::GetToolClasname(const char * name, char * dest, int size) { +const char *NameRender::GetToolClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sTool", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetToolFileName(const char * name, char * dest, int size) { +const char *NameRender::GetToolFileName(const char *name, char *dest, int size) { snprintf(dest, size, "phxrpc_%s%s_tool", prefix_, name); ToLower(dest); @@ -177,13 +179,13 @@ const char * NameRender::GetToolFileName(const char * name, char * dest, int siz return dest; } -const char * NameRender::GetToolImplClasname(const char * name, char * dest, int size) { +const char *NameRender::GetToolImplClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sToolImpl", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetToolImplFileName(const char * name, char * dest, int size) { +const char *NameRender::GetToolImplFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%s_tool_impl", prefix_, name); ToLower(dest); @@ -191,7 +193,7 @@ const char * NameRender::GetToolImplFileName(const char * name, char * dest, int return dest; } -const char * NameRender::GetToolMainFileName(const char * name, char * dest, int size) { +const char *NameRender::GetToolMainFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%s_tool_main", prefix_, name); ToLower(dest); @@ -199,29 +201,30 @@ const char * NameRender::GetToolMainFileName(const char * name, char * dest, int return dest; } -void NameRender::GetCopyright(const char * tool_name, const char * proto_file, std::string * result, bool dont_edit, - const char * comment_prefix) { - std::ostringstream tmp; +void NameRender::GetCopyright(const char *tool_name, const char *proto_file, + string *result, bool dont_edit, + const char *comment_prefix) { + ostringstream tmp; - tmp << comment_prefix << std::endl; - tmp << comment_prefix << " Generated by " << tool_name << " from " << proto_file << std::endl; + tmp << comment_prefix << endl; + tmp << comment_prefix << " Generated by " << tool_name << " from " << proto_file << endl; if (dont_edit) { - tmp << comment_prefix << std::endl; + tmp << comment_prefix << endl; tmp << comment_prefix << " Please DO NOT edit unless you know exactly what you are doing.\n"; } - tmp << comment_prefix << std::endl; + tmp << comment_prefix << endl; *result = tmp.str(); } -const char * NameRender::GetServiceClasname(const char * name, char * dest, int size) { +const char *NameRender::GetServiceClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sService", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetServiceFileName(const char * name, char * dest, int size) { +const char *NameRender::GetServiceFileName(const char *name, char *dest, int size) { snprintf(dest, size, "phxrpc_%s%c%s_service", prefix_, toupper(*name), name + 1); ToLower(dest); @@ -229,13 +232,13 @@ const char * NameRender::GetServiceFileName(const char * name, char * dest, int return dest; } -const char * NameRender::GetServiceImplClasname(const char * name, char * dest, int size) { +const char *NameRender::GetServiceImplClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sServiceImpl", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetServiceImplFileName(const char * name, char * dest, int size) { +const char *NameRender::GetServiceImplFileName(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%s_service_impl", prefix_, toupper(*name), name + 1); ToLower(dest); @@ -243,13 +246,13 @@ const char * NameRender::GetServiceImplFileName(const char * name, char * dest, return dest; } -const char * NameRender::GetDispatcherClasname(const char * name, char * dest, int size) { +const char *NameRender::GetDispatcherClasname(const char *name, char *dest, int size) { snprintf(dest, size, "%s%c%sDispatcher", prefix_, toupper(*name), name + 1); return dest; } -const char * NameRender::GetDispatcherFileName(const char * name, char * dest, int size) { +const char *NameRender::GetDispatcherFileName(const char *name, char *dest, int size) { snprintf(dest, size, "phxrpc_%s%c%s_dispatcher", prefix_, toupper(*name), name + 1); ToLower(dest); diff --git a/codegen/name_render.h b/codegen/name_render.h index fbb21c7..6c53518 100644 --- a/codegen/name_render.h +++ b/codegen/name_render.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,80 +21,80 @@ See the AUTHORS file for names of contributors. #pragma once -#include -#include - +#include +#include #include + namespace phxrpc { + class SyntaxTree; class NameRender { - public: - NameRender(const char * prefix); + public: + NameRender(const char *prefix); virtual ~NameRender(); - virtual const char * GetPrefix(char * dest, int size); + virtual const char *GetPrefix(char *dest, int size); - virtual const char * GetMessageClasname(const char * type, char * name, int size); - virtual const char * GetMessageFileName(const char *name, char * dest, int size); + virtual const char *GetMessageClasname(const char *type, char *name, int size); + virtual const char *GetMessageFileName(const char *name, char *dest, int size); //================================================================ - virtual const char * GetStubClasname(const char * name, char *dest, int size); - virtual const char * GetStubFileName(const char *name, char * dest, int size); + virtual const char *GetStubClasname(const char *name, char *dest, int size); + virtual const char *GetStubFileName(const char *name, char *dest, int size); - virtual const char * GetClientClasname(const char * name, char *dest, int size); + virtual const char *GetClientClasname(const char *name, char *dest, int size); - virtual const char * GetClientClasnameLower(const char * name, char *dest, int size); + virtual const char *GetClientClasnameLower(const char *name, char *dest, int size); - virtual const char * GetClientFileName(const char *name, char * dest, int size); + virtual const char *GetClientFileName(const char *name, char *dest, int size); - virtual const char * GetClientEtcFileName(const char *name, char * dest, int size); + virtual const char *GetClientEtcFileName(const char *name, char *dest, int size); //================================================================ - virtual const char * GetServiceClasname(const char * name, char * dest, int size); - virtual const char * GetServiceFileName(const char * name, char * dest, int size); + virtual const char *GetServiceClasname(const char *name, char *dest, int size); + virtual const char *GetServiceFileName(const char *name, char *dest, int size); - virtual const char * GetServiceImplClasname(const char * name, char * dest, int size); - virtual const char * GetServiceImplFileName(const char * name, char * dest, int size); + virtual const char *GetServiceImplClasname(const char *name, char *dest, int size); + virtual const char *GetServiceImplFileName(const char *name, char *dest, int size); - virtual const char * GetDispatcherClasname(const char * name, char * dest, int size); - virtual const char * GetDispatcherFileName(const char * name, char * dest, int size); + virtual const char *GetDispatcherClasname(const char *name, char *dest, int size); + virtual const char *GetDispatcherFileName(const char *name, char *dest, int size); //================================================================ - virtual const char * GetServerConfigClasname(const char *name, char * dest, int size); - virtual const char * GetServerConfigFileName(const char *name, char * dest, int size); + virtual const char *GetServerConfigClasname(const char *name, char *dest, int size); + virtual const char *GetServerConfigFileName(const char *name, char *dest, int size); - virtual const char * GetServerEtcFileName(const char *name, char * dest, int size); + virtual const char *GetServerEtcFileName(const char *name, char *dest, int size); - virtual const char * GetServerMainFileName(const char *name, char * dest, int size); + virtual const char *GetServerMainFileName(const char *name, char *dest, int size); //================================================================ - virtual const char * GetToolClasname(const char * name, char * dest, int size); - virtual const char * GetToolFileName(const char * name, char * dest, int size); + virtual const char *GetToolClasname(const char *name, char *dest, int size); + virtual const char *GetToolFileName(const char *name, char *dest, int size); - virtual const char * GetToolImplClasname(const char * name, char * dest, int size); - virtual const char * GetToolImplFileName(const char * name, char * dest, int size); + virtual const char *GetToolImplClasname(const char *name, char *dest, int size); + virtual const char *GetToolImplFileName(const char *name, char *dest, int size); - virtual const char * GetToolMainFileName(const char * name, char * dest, int size); + virtual const char *GetToolMainFileName(const char *name, char *dest, int size); - virtual void GetCopyright(const char * tool_name, const char * proto_file, std::string * result, bool dont_edit = - true, - const char * comment_prefix = ""); + virtual void GetCopyright(const char *tool_name, const char *proto_file, + std::string *result, bool dont_edit = true, + const char *comment_prefix = ""); - public: + static char *ToLower(register char *s); + static char *ToUpper(register char *s); - static char * ToLower(register char *s); - static char * ToUpper(register char *s); - - protected: + protected: char prefix_[128]; }; + } diff --git a/codegen/phxrpc_pb2client.cpp b/codegen/phxrpc_pb2client.cpp index 6eeeebb..e0290c9 100644 --- a/codegen/phxrpc_pb2client.cpp +++ b/codegen/phxrpc_pb2client.cpp @@ -1,30 +1,30 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include -#include +#include +#include +#include #include #include +#include #include "syntax_tree.h" #include "name_render.h" @@ -32,12 +32,14 @@ See the AUTHORS file for names of contributors. #include "client_code_render.h" #include "proto_utils.h" + using namespace phxrpc; using namespace std; -void PrintHelp(const char * program) { + +void PrintHelp(const char *program) { printf("\n"); - printf("PHXRPC ProtoBuf tool\n"); + printf("PhxRPC ProtoBuf tool\n"); printf("\n"); printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); printf(" Usage: -f # Proto File\n"); @@ -49,29 +51,53 @@ void PrintHelp(const char * program) { return; } -void Proto2Client(const char * program, const char * proto_file, const char * dir_path, - const std::vector & include_list, const bool is_uthread_mode) { +void Proto2Client(const char *program, const char *proto_file, const char *dir_path, + const vector &include_list, const bool is_uthread_mode) { SyntaxTree syntax_tree; - int ret = ProtoUtils::Parse(proto_file, &syntax_tree, include_list); + int ret{ProtoUtils::Parse(proto_file, &syntax_tree, include_list)}; if (0 != ret) { printf("parse Proto file fail, please check error log\n"); return; } + // mqtt + SyntaxFuncVector mqtt_funcs; + + SyntaxFunc connect_func; + connect_func.SetCmdID(-201); + connect_func.SetName("PhxMqttConnect"); + connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); + connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); + mqtt_funcs.push_back(connect_func); + + SyntaxFunc publish_func; + publish_func.SetCmdID(-202); + publish_func.SetName("PhxMqttPublish"); + publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); + publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); + mqtt_funcs.push_back(publish_func); + + SyntaxFunc disconnect_func; + disconnect_func.SetCmdID(-207); + disconnect_func.SetName("PhxMqttDisconnect"); + disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); + disconnect_func.GetResp()->SetType(""); + mqtt_funcs.push_back(disconnect_func); + NameRender name_render(syntax_tree.GetPrefix()); - ClientCodeRender clientCodeRender(name_render); + ClientCodeRender code_render(name_render); - char filename[256] = { 0 }, tmp[256] = { 0 }; + char filename[256]{0}, tmp[256]{0}; // [xx]stub.h { name_render.GetStubFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateStubHpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateStubHpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -82,8 +108,8 @@ void Proto2Client(const char * program, const char * proto_file, const char * di name_render.GetStubFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateStubCpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateStubCpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -95,13 +121,13 @@ void Proto2Client(const char * program, const char * proto_file, const char * di name_render.GetClientFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); - char name4hpp[256] = { 0 }; + char name4hpp[256]{0}; snprintf(name4hpp, sizeof(name4hpp), "%s/%s.hpp", dir_path, tmp); if (0 != access(name4hpp, F_OK)) { if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateClientHpp(&syntax_tree, fp, false); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateClientHpp(&syntax_tree, mqtt_funcs, fp, false); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -112,20 +138,20 @@ void Proto2Client(const char * program, const char * proto_file, const char * di printf("\n%s: %s is exist, skip\n", program, name4hpp); } } - + // [xx]client_uthread.h if (is_uthread_mode) { name_render.GetClientFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s_uthread.h", dir_path, tmp); - char name4hpp[256] = { 0 }; + char name4hpp[256]{0}; snprintf(name4hpp, sizeof(name4hpp), "%s/%s_uthread.hpp", dir_path, tmp); if (0 != access(name4hpp, F_OK)) { if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateClientHpp(&syntax_tree, fp, is_uthread_mode); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateClientHpp(&syntax_tree, mqtt_funcs, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -143,8 +169,8 @@ void Proto2Client(const char * program, const char * proto_file, const char * di snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateClientCpp(&syntax_tree, fp, false); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateClientCpp(&syntax_tree, mqtt_funcs, fp, false); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -160,8 +186,8 @@ void Proto2Client(const char * program, const char * proto_file, const char * di snprintf(filename, sizeof(filename), "%s/%s_uthread.cpp", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateClientCpp(&syntax_tree, fp, is_uthread_mode); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateClientCpp(&syntax_tree, mqtt_funcs, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -176,8 +202,8 @@ void Proto2Client(const char * program, const char * proto_file, const char * di snprintf(filename, sizeof(filename), "%s/%s", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - clientCodeRender.GenerateClientEtc(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateClientEtc(&syntax_tree, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -187,18 +213,18 @@ void Proto2Client(const char * program, const char * proto_file, const char * di } } -int main(int argc, char * argv[]) { - const char * proto_file = NULL; - const char * dir_path = NULL; +int main(int argc, char **argv) { + const char *proto_file{nullptr}; + const char *dir_path{nullptr}; extern char *optarg; int c; - std::vector include_list; - char real_path[1024] = {0}; - char * rp = nullptr; - bool is_uthread_mode = false; + vector include_list; + char real_path[1024]{0}; + char *rp{nullptr}; + bool is_uthread_mode{false}; - while ((c = getopt(argc, argv, "f:d:I:uv")) != EOF) { + while (EOF != (c = getopt(argc, argv, "f:d:I:uv"))) { switch (c) { case 'f': proto_file = optarg; @@ -222,7 +248,7 @@ int main(int argc, char * argv[]) { } } - if (NULL == proto_file || NULL == dir_path) { + if (nullptr == proto_file || nullptr == dir_path) { printf("Invalid arguments\n"); PrintHelp(argv[0]); @@ -235,7 +261,7 @@ int main(int argc, char * argv[]) { exit(0); } - char path[128] = { 0 }; + char path[128]{0}; strncpy(path, dir_path, sizeof(path)); if ('/' == path[strlen(path) - 1]) { path[strlen(path) - 1] = '\0'; diff --git a/codegen/phxrpc_pb2server.cpp b/codegen/phxrpc_pb2server.cpp index 06b472b..2be0e3c 100644 --- a/codegen/phxrpc_pb2server.cpp +++ b/codegen/phxrpc_pb2server.cpp @@ -1,33 +1,32 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include -#include +#include +#include +#include #include #include #include -#include #include +#include #include "syntax_tree.h" @@ -35,11 +34,14 @@ See the AUTHORS file for names of contributors. #include "name_render.h" #include "server_code_render.h" + using namespace phxrpc; +using namespace std; + void PrintHelp(const char * program) { printf("\n"); - printf("PHXRPC ProtoBuf tool\n"); + printf("PhxRPC ProtoBuf tool\n"); printf("\n"); printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); printf(" Usage: -f # Proto File\n"); @@ -52,13 +54,13 @@ void PrintHelp(const char * program) { return; } -void Proto2Server(const char * program, const char * pb_file, const char * dir_path, - const std::vector & include_list, const std::string & mk_dir_path, - const bool is_uthread_mode) { +void Proto2Server(const char *program, const char *pb_file, const char *dir_path, + const vector &include_list, const string &mk_dir_path, + const bool is_uthread_mode) { SyntaxTree syntax_tree; - std::map parsed_file_map; + map parsed_file_map; - int ret = ProtoUtils::Parse(pb_file, &syntax_tree, &parsed_file_map, include_list); + int ret{ProtoUtils::Parse(pb_file, &syntax_tree, &parsed_file_map, include_list)}; if (0 != ret) { printf("parse proto file fail, please check error log\n"); @@ -66,9 +68,9 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p } NameRender name_render(syntax_tree.GetPrefix()); - ServerCodeRender codeRender(name_render); + ServerCodeRender code_render(name_render); - char filename[256] = { 0 }, tmp[256] = { 0 }; + char filename[256]{0}, tmp[256]{0}; // [xx]svrconfig.h { @@ -76,8 +78,8 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - codeRender.GenerateServerConfigHpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateServerConfigHpp(&syntax_tree, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -92,8 +94,8 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - codeRender.GenerateServerConfigCpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateServerConfigCpp(&syntax_tree, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -108,8 +110,8 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - codeRender.GenerateServerMainCpp(&syntax_tree, fp, is_uthread_mode); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateServerMainCpp(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -124,8 +126,8 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p snprintf(filename, sizeof(filename), "%s/%s", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - codeRender.GenerateServerEtc(&syntax_tree, fp, is_uthread_mode); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateServerEtc(&syntax_tree, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -139,8 +141,8 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p snprintf(filename, sizeof(filename), "%s/Makefile", dir_path); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - codeRender.GenerateMakefile(&syntax_tree, mk_dir_path, fp, is_uthread_mode); + FILE *fp{fopen(filename, "w")}; + code_render.GenerateMakefile(&syntax_tree, mk_dir_path, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -150,18 +152,18 @@ void Proto2Server(const char * program, const char * pb_file, const char * dir_p } } -int main(int argc, char * argv[]) { - const char * pb_file = NULL; - const char * dir_path = NULL; +int main(int argc, char **argv) { + const char *pb_file{nullptr}; + const char *dir_path{nullptr}; extern char *optarg; int c; - std::vector include_list; - char real_path[1024] = {0}; - char * rp = nullptr; - bool is_uthread_mode = false; + vector include_list; + char real_path[1024]{0}; + char *rp{nullptr}; + bool is_uthread_mode{false}; - while ((c = getopt(argc, argv, "f:d:I:uv")) != EOF) { + while (EOF != (c = getopt(argc, argv, "f:d:I:uv"))) { switch (c) { case 'f': pb_file = optarg; @@ -185,7 +187,7 @@ int main(int argc, char * argv[]) { } } - if (NULL == pb_file || NULL == dir_path) { + if (nullptr == pb_file || nullptr == dir_path) { printf("Invalid arguments\n"); PrintHelp(argv[0]); @@ -198,18 +200,18 @@ int main(int argc, char * argv[]) { exit(0); } - char path[128] = { 0 }; + char path[128]{0}; strncpy(path, dir_path, sizeof(path)); if ('/' == path[strlen(path) - 1]) { path[strlen(path) - 1] = '\0'; } - std::string mk_dir_path; - char * real_p_path = realpath(argv[0], real_path); - if (real_p_path != nullptr) { - mk_dir_path = std::string(real_p_path); + string mk_dir_path; + char *real_p_path = realpath(argv[0], real_path); + if (nullptr != real_p_path) { + mk_dir_path = string(real_p_path); size_t pos = mk_dir_path.find("/codegen/phxrpc_pb2server"); - if (pos != std::string::npos) { + if (pos != string::npos) { mk_dir_path = mk_dir_path.substr(0, pos); } } diff --git a/codegen/phxrpc_pb2service.cpp b/codegen/phxrpc_pb2service.cpp index 3e375a6..0e86d01 100644 --- a/codegen/phxrpc_pb2service.cpp +++ b/codegen/phxrpc_pb2service.cpp @@ -1,32 +1,32 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include -#include +#include +#include +#include +#include #include -#include #include #include +#include #include "syntax_tree.h" @@ -34,12 +34,14 @@ See the AUTHORS file for names of contributors. #include "service_code_render.h" #include "proto_utils.h" + using namespace phxrpc; using namespace std; -void PrintHelp(const char * program) { + +void PrintHelp(const char *program) { printf("\n"); - printf("PHXRPC ProtoBuf tool\n"); + printf("PhxRPC ProtoBuf tool\n"); printf("\n"); printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); printf(" Usage: -f # Proto File\n"); @@ -47,35 +49,62 @@ void PrintHelp(const char * program) { printf(" -I # include path dir\n"); printf(" -v # print this screen\n"); printf("\n"); + return; } -void Proto2Service(const char * program, const char * pb_file, const char * dir_path, - const std::vector & include_list, const bool is_uthread_mode) { - std::map parsed_file_map; +void Proto2Service(const char *program, const char *pb_file, const char *dir_path, + const vector &include_list, const bool is_uthread_mode) { + map parsed_file_map; SyntaxTree syntax_tree; - int ret = ProtoUtils::Parse(pb_file, &syntax_tree, &parsed_file_map, include_list); + int ret{ProtoUtils::Parse(pb_file, &syntax_tree, &parsed_file_map, include_list)}; if (0 != ret) { printf("parse proto file fail, please check error log\n"); return; } - // printf( "parse(%s) = %d\n", pb_file, ret ); + // printf("parse(%s) = %d\n", pb_file, ret); + + // mqtt + SyntaxFuncVector mqtt_funcs; + + SyntaxFunc connect_func; + connect_func.SetCmdID(-201); + connect_func.SetName("PhxMqttConnect"); + connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); + connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); + mqtt_funcs.push_back(connect_func); + + SyntaxFunc publish_func; + publish_func.SetCmdID(-202); + publish_func.SetName("PhxMqttPublish"); + publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); + publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); + mqtt_funcs.push_back(publish_func); + + SyntaxFunc disconnect_func; + disconnect_func.SetCmdID(-207); + disconnect_func.SetName("PhxMqttDisconnect"); + disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); + disconnect_func.GetResp()->SetType(""); + mqtt_funcs.push_back(disconnect_func); NameRender name_render(syntax_tree.GetPrefix()); - ServiceCodeRender codeRender(name_render); + ServiceCodeRender code_render(name_render); + + // generate files - char filename[256] = { 0 }, tmp[256] = { 0 }; + char filename[256]{0}, tmp[256]{0}; // [xx]service.h { name_render.GetServiceFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateServiceHpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateServiceHpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -85,9 +114,9 @@ void Proto2Service(const char * program, const char * pb_file, const char * dir_ { name_render.GetServiceFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateServiceCpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateServiceCpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -99,9 +128,9 @@ void Proto2Service(const char * program, const char * pb_file, const char * dir_ snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateServiceImplHpp(&syntax_tree, fp, is_uthread_mode); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateServiceImplHpp(&syntax_tree, mqtt_funcs, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -116,9 +145,9 @@ void Proto2Service(const char * program, const char * pb_file, const char * dir_ snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateServiceImplCpp(&syntax_tree, fp, is_uthread_mode); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateServiceImplCpp(&syntax_tree, mqtt_funcs, fp, is_uthread_mode); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -132,9 +161,9 @@ void Proto2Service(const char * program, const char * pb_file, const char * dir_ name_render.GetDispatcherFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateDispatcherHpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateDispatcherHpp(&syntax_tree, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -145,27 +174,27 @@ void Proto2Service(const char * program, const char * pb_file, const char * dir_ name_render.GetDispatcherFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateDispatcherCpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateDispatcherCpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); } } -int main(int argc, char * argv[]) { - const char * pb_file = NULL; - const char * dir_path = NULL; +int main(int argc, char **argv) { + const char *pb_file{nullptr}; + const char *dir_path{nullptr}; extern char *optarg; int c; - std::vector include_list; - char real_path[1024] = {0}; - char * rp = nullptr; - bool is_uthread_mode = false; + vector include_list; + char real_path[1024]{0}; + char *rp{nullptr}; + bool is_uthread_mode{false}; - while ((c = getopt(argc, argv, "f:d:I:uv")) != EOF) { + while (EOF != (c = getopt(argc, argv, "f:d:I:uv"))) { switch (c) { case 'f': pb_file = optarg; @@ -189,7 +218,7 @@ int main(int argc, char * argv[]) { } } - if (NULL == pb_file || NULL == dir_path) { + if (nullptr == pb_file || nullptr == dir_path) { printf("Invalid arguments\n"); PrintHelp(argv[0]); @@ -203,7 +232,7 @@ int main(int argc, char * argv[]) { exit(0); } - char path[128] = { 0 }; + char path[128]{0}; strncpy(path, dir_path, sizeof(path)); if ('/' == path[strlen(path) - 1]) { path[strlen(path) - 1] = '\0'; diff --git a/codegen/phxrpc_pb2tool.cpp b/codegen/phxrpc_pb2tool.cpp index 4e5dc4f..b3c8ce7 100644 --- a/codegen/phxrpc_pb2tool.cpp +++ b/codegen/phxrpc_pb2tool.cpp @@ -1,31 +1,31 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include -#include +#include +#include +#include +#include #include -#include #include +#include #include "syntax_tree.h" @@ -33,11 +33,14 @@ See the AUTHORS file for names of contributors. #include "proto_utils.h" #include "name_render.h" + using namespace phxrpc; +using namespace std; + void PrintHelp(const char * program) { printf("\n"); - printf("PHXRPC ProtoBuf tool\n"); + printf("PhxRPC ProtoBuf tool\n"); printf("\n"); printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); printf(" Usage: -f # Proto File\n"); @@ -49,8 +52,8 @@ void PrintHelp(const char * program) { return; } -void Proto2Tool(const char * program, const char * pb_file, const char * dir_path, - const std::vector & include_list) { +void Proto2Tool(const char *program, const char *pb_file, const char *dir_path, + const vector &include_list) { SyntaxTree syntax_tree; int ret = ProtoUtils::Parse(pb_file, &syntax_tree, include_list); @@ -62,8 +65,34 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat // printf( "parse(%s) = %d\n", pb_file, ret ); + // mqtt + SyntaxFuncVector mqtt_funcs; + + SyntaxFunc connect_func; + connect_func.SetCmdID(-201); + connect_func.SetName("PhxMqttConnect"); + connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); + connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); + mqtt_funcs.push_back(connect_func); + + SyntaxFunc publish_func; + publish_func.SetCmdID(-202); + publish_func.SetName("PhxMqttPublish"); + publish_func.SetOptString("s:"); + publish_func.SetUsage("-s "); + publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); + publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); + mqtt_funcs.push_back(publish_func); + + SyntaxFunc disconnect_func; + disconnect_func.SetCmdID(-207); + disconnect_func.SetName("PhxMqttDisconnect"); + disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); + disconnect_func.GetResp()->SetType(""); + mqtt_funcs.push_back(disconnect_func); + NameRender name_render(syntax_tree.GetPrefix()); - ToolCodeRender codeRender(name_render); + ToolCodeRender code_render(name_render); char filename[256] = { 0 }, tmp[256] = { 0 }; @@ -71,9 +100,9 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat { name_render.GetToolFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateToolHpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateToolHpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -84,9 +113,9 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat name_render.GetToolFileName(syntax_tree.GetName(), tmp, sizeof(tmp)); snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateToolCpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateToolCpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -98,9 +127,9 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat snprintf(filename, sizeof(filename), "%s/%s.h", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateToolImplHpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateToolImplHpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -115,9 +144,9 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateToolImplCpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateToolImplCpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -132,9 +161,9 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat snprintf(filename, sizeof(filename), "%s/%s.cpp", dir_path, tmp); if (0 != access(filename, F_OK)) { - FILE * fp = fopen(filename, "w"); - assert(NULL != fp); - codeRender.GenerateToolMainCpp(&syntax_tree, fp); + FILE *fp{fopen(filename, "w")}; + assert(nullptr != fp); + code_render.GenerateToolMainCpp(&syntax_tree, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -144,17 +173,17 @@ void Proto2Tool(const char * program, const char * pb_file, const char * dir_pat } } -int main(int argc, char * argv[]) { - const char * pb_file = NULL; - const char * dir_path = NULL; +int main(int argc, char **argv) { + const char *pb_file{nullptr}; + const char *dir_path{nullptr}; extern char *optarg; int c; - std::vector include_list; - char real_path[1024] = {0}; - char * rp = nullptr; + vector include_list; + char real_path[1024]{0}; + char *rp{nullptr}; - while ((c = getopt(argc, argv, "f:d:I:v")) != EOF) { + while (EOF != (c = getopt(argc, argv, "f:d:I:v"))) { switch (c) { case 'f': pb_file = optarg; @@ -175,7 +204,7 @@ int main(int argc, char * argv[]) { } } - if (NULL == pb_file || NULL == dir_path) { + if (nullptr == pb_file || nullptr == dir_path) { printf("Invalid arguments\n"); PrintHelp(argv[0]); @@ -188,7 +217,7 @@ int main(int argc, char * argv[]) { exit(0); } - char path[128] = { 0 }; + char path[128]{0}; strncpy(path, dir_path, sizeof(path)); if ('/' == path[strlen(path) - 1]) { path[strlen(path) - 1] = '\0'; diff --git a/codegen/proto_utils.cpp b/codegen/proto_utils.cpp index 53fb379..75b6547 100644 --- a/codegen/proto_utils.cpp +++ b/codegen/proto_utils.cpp @@ -1,43 +1,45 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include +#include #include +#include #include - #include -#include + #include "proto_utils.h" + using namespace google::protobuf::compiler; using namespace google::protobuf; using namespace phxrpc; using namespace std; + class MyErrorPrinter : public MultiFileErrorCollector { - public: + public: MyErrorPrinter() { } - ~MyErrorPrinter() { + virtual ~MyErrorPrinter() override { } void AddError(const std::string& filename, int line, int column, const std::string& message) { @@ -166,7 +168,7 @@ int ProtoUtils::AddEcho(SyntaxTree * stree) { // always add a echo function { SyntaxFunc echo_func; - echo_func.SetName("PHXEcho"); + echo_func.SetName("PhxEcho"); echo_func.GetReq()->SetName("request"); echo_func.GetReq()->SetType(name); echo_func.GetResp()->SetName("response"); diff --git a/codegen/proto_utils.h b/codegen/proto_utils.h index 8cc46d5..77614d3 100644 --- a/codegen/proto_utils.h +++ b/codegen/proto_utils.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -24,20 +24,24 @@ See the AUTHORS file for names of contributors. #include #include #include -#include "syntax_tree.h" + #include #include +#include "syntax_tree.h" + + namespace phxrpc { + class ProtoUtils { - public: + public: static int Parse(const char * file, phxrpc::SyntaxTree * stree, const std::vector & include_list); static int Parse(const char * file, phxrpc::SyntaxTree * stree, std::map * parsed_file_map, const std::vector & include_list); - private: + private: static int LoadNormal(const char * file, phxrpc::SyntaxTree * stree, std::map * parsed_file_map, google::protobuf::compiler::DiskSourceTree & tree); @@ -47,11 +51,10 @@ class ProtoUtils { static int AddEcho(phxrpc::SyntaxTree * stree); - private: ProtoUtils(); - ~ProtoUtils(); + virtual ~ProtoUtils(); }; + } -; diff --git a/codegen/server_code_render.cpp b/codegen/server_code_render.cpp index c433822..76448dc 100644 --- a/codegen/server_code_render.cpp +++ b/codegen/server_code_render.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -27,20 +27,23 @@ See the AUTHORS file for names of contributors. #include "code_utils.h" #include + using namespace phxrpc; +using namespace std; + -ServerCodeRender::ServerCodeRender(NameRender & name_render) +ServerCodeRender::ServerCodeRender(NameRender &name_render) : name_render_(name_render) { } ServerCodeRender::~ServerCodeRender() { } -void ServerCodeRender::GenerateServerConfigHpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ServerCodeRender::GenerateServerConfigHpp(SyntaxTree *stree, FILE *write) { + char filename[128]{0}; name_render_.GetServerConfigFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2server", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.h\n", filename); @@ -55,7 +58,7 @@ void ServerCodeRender::GenerateServerConfigHpp(SyntaxTree * stree, FILE * write) char classname[128] = { 0 }; name_render_.GetServerConfigClasname(stree->GetName(), classname, sizeof(classname)); - std::string content = PHXRPC_EPOLL_SERVER_CONFIG_HPP_TEMPLATE; + string content = PHXRPC_EPOLL_SERVER_CONFIG_HPP_TEMPLATE; StrTrim(&content); StrReplaceAll(&content, "$ServerConfigClass$", classname); @@ -63,13 +66,14 @@ void ServerCodeRender::GenerateServerConfigHpp(SyntaxTree * stree, FILE * write) fprintf(write, "%s", content.c_str()); fprintf(write, "\n"); + fprintf(write, "\n"); } -void ServerCodeRender::GenerateServerConfigCpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ServerCodeRender::GenerateServerConfigCpp(SyntaxTree *stree, FILE *write) { + char filename[128]{0}; name_render_.GetServerConfigFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2server", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.cpp\n", filename); @@ -77,22 +81,22 @@ void ServerCodeRender::GenerateServerConfigCpp(SyntaxTree * stree, FILE * write) fprintf(write, "*/\n"); fprintf(write, "\n"); - char classname[128] = { 0 }; - char message_file[128] = {0}; + char classname[128]{0}; + char message_file[128]{0}; name_render_.GetServerConfigClasname(stree->GetName(), classname, sizeof(classname)); name_render_.GetMessageFileName(stree->GetProtoFile(), message_file, sizeof(message_file)); - std::string content = PHXRPC_EPOLL_SERVER_CONFIG_CPP_TEMPLATE; + string content = PHXRPC_EPOLL_SERVER_CONFIG_CPP_TEMPLATE; - std::string package_name = "\"" + std::string(stree->GetPackageName()) + "\""; + string package_name = "\"" + string(stree->GetPackageName()) + "\""; { - std::string message_name = ""; + string message_name; for( auto itr : *(stree->GetFuncList()) ) { - if ( std::string(itr.GetReq()->GetType()).find( stree->GetPackageName() ) != std::string::npos ) { + if ( string(itr.GetReq()->GetType()).find( stree->GetPackageName() ) != string::npos ) { message_name = itr.GetReq()->GetType(); break; - } else if ( std::string(itr.GetResp()->GetType()).find( stree->GetPackageName() ) != std::string::npos ) { + } else if ( string(itr.GetResp()->GetType()).find( stree->GetPackageName() ) != string::npos ) { message_name = itr.GetResp()->GetType(); break; } @@ -100,7 +104,7 @@ void ServerCodeRender::GenerateServerConfigCpp(SyntaxTree * stree, FILE * write) if( message_name != "" ) { int package_name_len = strlen(stree->GetPackageName()); message_name = message_name.substr( package_name_len + 1, message_name.size() - package_name_len - 1 ); - package_name = "\n" + std::string(stree->GetPackageName()) + "::" + message_name + package_name = "\n" + string(stree->GetPackageName()) + "::" + message_name + "::default_instance().GetDescriptor()->file()->package().c_str()"; } } @@ -114,13 +118,14 @@ void ServerCodeRender::GenerateServerConfigCpp(SyntaxTree * stree, FILE * write) fprintf(write, "%s", content.c_str()); fprintf(write, "\n"); + fprintf(write, "\n"); } -void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { - char svrfile[128] = { 0 }; +void ServerCodeRender::GenerateServerMainCpp(SyntaxTree *stree, FILE *write, const bool is_uthread_mode) { + char svrfile[128]{0}; name_render_.GetServerMainFileName(stree->GetName(), svrfile, sizeof(svrfile)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2server", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.cpp\n", svrfile); @@ -128,9 +133,9 @@ void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write, c fprintf(write, "*/\n"); fprintf(write, "\n"); - char dispatcher_calss[128] = { 0 }, dispatcher_file[128] = { 0 }; - char service_impl_class[128] = { 0 }, service_impl_file[128] = { 0 }; - char server_config_class[128] = { 0 }, server_config_file[128] = { 0 }; + char dispatcher_calss[128]{0}, dispatcher_file[128]{0}; + char service_impl_class[128]{0}, service_impl_file[128]{0}; + char server_config_class[128]{0}, server_config_file[128]{0}; name_render_.GetDispatcherClasname(stree->GetName(), dispatcher_calss, sizeof(dispatcher_calss)); name_render_.GetDispatcherFileName(stree->GetName(), dispatcher_file, sizeof(dispatcher_file)); @@ -139,7 +144,7 @@ void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write, c name_render_.GetServerConfigClasname(stree->GetName(), server_config_class, sizeof(server_config_class)); name_render_.GetServerConfigFileName(stree->GetName(), server_config_file, sizeof(server_config_file)); - std::string content; + string content; if (!is_uthread_mode) { content = PHXRPC_EPOLL_SERVER_MAIN_TEMPLATE; } else { @@ -157,13 +162,14 @@ void ServerCodeRender::GenerateServerMainCpp(SyntaxTree * stree, FILE * write, c fprintf(write, "%s", content.c_str()); fprintf(write, "\n"); + fprintf(write, "\n"); } -void ServerCodeRender::GenerateServerEtc(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { - char etcfile[128] = { 0 }; +void ServerCodeRender::GenerateServerEtc(SyntaxTree *stree, FILE *write, const bool is_uthread_mode) { + char etcfile[128]{0}; name_render_.GetServerEtcFileName(stree->GetName(), etcfile, sizeof(etcfile)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2server", stree->GetProtoFile(), &buffer, false, "#"); fprintf(write, "# %s\n", etcfile); @@ -171,7 +177,7 @@ void ServerCodeRender::GenerateServerEtc(SyntaxTree * stree, FILE * write, const fprintf(write, "#\n"); fprintf(write, "\n"); - std::string content; + string content; if (!is_uthread_mode) { content = PHXRPC_EPOLL_SERVER_ETC_TEMPLATE; } else { @@ -184,10 +190,12 @@ void ServerCodeRender::GenerateServerEtc(SyntaxTree * stree, FILE * write, const fprintf(write, "%s", content.c_str()); fprintf(write, "\n"); + fprintf(write, "\n"); } -void ServerCodeRender::GenerateMakefile(SyntaxTree * stree, const std::string & mk_dir_path, FILE * write, const bool is_uthread_mode) { - std::string buffer; +void ServerCodeRender::GenerateMakefile(SyntaxTree *stree, + const string &mk_dir_path, FILE *write, const bool is_uthread_mode) { + string buffer; name_render_.GetCopyright("phxrpc_pb2server", stree->GetProtoFile(), &buffer, false, "#"); fprintf(write, "# Makefile\n"); @@ -195,10 +203,10 @@ void ServerCodeRender::GenerateMakefile(SyntaxTree * stree, const std::string & fprintf(write, "#\n"); fprintf(write, "\n"); - char dispatcher_file[128] = { 0 }, service_file[128] = { 0 }, service_impl_file[128] = { 0 }; - char server_config_file[128] = { 0 }, server_main_file[128] = { 0 }; - char message_file[128] = { 0 }, stub_file[128] = { 0 }, client_file[128] = { 0 }; - char tool_file[128] = { 0 }, tool_impl_file[128] = { 0 }, tool_main_file[128] = { 0 }; + char dispatcher_file[128]{0}, service_file[128]{0}, service_impl_file[128]{0}; + char server_config_file[128]{0}, server_main_file[128]{0}; + char message_file[128]{0}, stub_file[128]{0}, client_file[128]{0}; + char tool_file[128]{0}, tool_impl_file[128]{0}, tool_main_file[128]{0}; name_render_.GetDispatcherFileName(stree->GetName(), dispatcher_file, sizeof(dispatcher_file)); name_render_.GetServiceImplFileName(stree->GetName(), service_impl_file, sizeof(service_impl_file)); @@ -215,7 +223,7 @@ void ServerCodeRender::GenerateMakefile(SyntaxTree * stree, const std::string & name_render_.GetStubFileName(stree->GetName(), stub_file, sizeof(stub_file)); name_render_.GetMessageFileName(stree->GetProtoFile(), message_file, sizeof(message_file)); - std::string content; + string content; if (!is_uthread_mode) { content = PHXRPC_SERVER_MAKEFILE_TEMPLATE; } else { diff --git a/codegen/server_code_render.h b/codegen/server_code_render.h index 296178a..58a5542 100644 --- a/codegen/server_code_render.h +++ b/codegen/server_code_render.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -30,21 +30,22 @@ class NameRender; class SyntaxTree; class ServerCodeRender { - public: - ServerCodeRender(NameRender & name_render); - ~ServerCodeRender(); + public: + ServerCodeRender(NameRender &name_render); + virtual ~ServerCodeRender(); - void GenerateServerConfigHpp(SyntaxTree * stree, FILE * write); + void GenerateServerConfigHpp(SyntaxTree *stree, FILE *write); - void GenerateServerConfigCpp(SyntaxTree * stree, FILE * write); + void GenerateServerConfigCpp(SyntaxTree *stree, FILE *write); - void GenerateServerMainCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); + void GenerateServerMainCpp(SyntaxTree *stree, FILE *write, const bool is_uthread_mode); - void GenerateServerEtc(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); + void GenerateServerEtc(SyntaxTree *stree, FILE *write, const bool is_uthread_mode); - void GenerateMakefile(SyntaxTree * stree, const std::string & mk_dir_path, FILE * write, const bool is_uthread_mode); + void GenerateMakefile(SyntaxTree *stree, const std::string &mk_dir_path, + FILE *write, const bool is_uthread_mode); - private: + private: NameRender & name_render_; }; diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index ae426d6..f9bdfba 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -26,78 +26,82 @@ const char * PHXRPC_EPOLL_SERVER_MAIN_TEMPLATE = #include #include #include + #include "$DispatcherFile$.h" #include "$ServiceImplFile$.h" #include "$ServerConfigFile$.h" #include "phxrpc/rpc.h" -#include "phxrpc/http.h" +#include "phxrpc/msg.h" #include "phxrpc/file.h" + using namespace std; -void HttpDispatch( const phxrpc::HttpRequest & request, phxrpc::HttpResponse * response, phxrpc::DispatcherArgs_t * args ) { - ServiceArgs_t * service_args = (ServiceArgs_t *)(args->service_args); +void Dispatch(const phxrpc::BaseRequest *request, + phxrpc::BaseResponse *response, + phxrpc::DispatcherArgs_t *args) { + ServiceArgs_t *service_args = (ServiceArgs_t *)(args->service_args); - $ServiceImplClass$ service( * service_args ); - $DispatcherClass$ dispatcher( service, args ); + $ServiceImplClass$ service(*service_args); + $DispatcherClass$ dispatcher(service, args); - phxrpc::HttpDispatcher<$DispatcherClass$> http_dispatcher( - dispatcher, $DispatcherClass$::GetURIFuncMap() ); - if( ! http_dispatcher.Dispatch( request, response ) ) { - response->SetStatusCode( 404 ); - response->SetReasonPhrase( "Not Found" ); + phxrpc::BaseDispatcher<$DispatcherClass$> base_dispatcher( + dispatcher, $DispatcherClass$::GetURIFuncMap(), + $DispatcherClass$::GetMqttFuncMap()); + if (!base_dispatcher.Dispatch(request, response)) { + response->DispatchErr(); } } -void showUsage( const char * program ) { - printf( "\n" ); - printf( "Usage: %s [-c ] [-d] [-l ] [-v]\n", program ); - printf( "\n" ); +void ShowUsage(const char *program) { + printf("\n"); + printf("Usage: %s [-c ] [-d] [-l ] [-v]\n", program); + printf("\n"); - exit( 0 ); + exit(0); } -int main( int argc, char * argv[] ) { - const char * config_file = NULL; - bool daemonize = false;; - int log_level = -1; - extern char *optarg ; - int c ; - while( ( c = getopt( argc, argv, "c:vl:d" ) ) != EOF ) { - switch ( c ) { +int main(int argc, char **argv) { + const char *config_file{nullptr}; + bool daemonize{false}; + int log_level{-1}; + extern char *optarg; + int c; + while (EOF != (c = getopt(argc, argv, "c:vl:d"))) { + switch (c) { case 'c' : config_file = optarg; break; case 'd' : daemonize = true; break; - case 'l' : log_level = atoi( optarg ); break; + case 'l' : log_level = atoi(optarg); break; case 'v' : - default: showUsage( argv[ 0 ] ); break; + default: ShowUsage(argv[0]); break; } } - if( daemonize ) phxrpc::ServerUtils::Daemonize(); + if (daemonize) phxrpc::ServerUtils::Daemonize(); assert(signal(SIGPIPE, SIG_IGN) != SIG_ERR); //set customize log/monitor //phxrpc::setlog(openlog, closelog, vlog); - //phxrpc::MonitorFactory::SetFactory( new YourSelfsMonitorFactory() ); + //phxrpc::MonitorFactory::SetFactory(new YourSelfsMonitorFactory()); - if( NULL == config_file ) showUsage( argv[0] ); + if (nullptr == config_file) ShowUsage(argv[0]); $ServerConfigClass$ config; - if( ! config.Read( config_file ) ) showUsage( argv[0] ); + if (!config.Read(config_file)) ShowUsage(argv[0]); - if( log_level > 0 ) config.GetHshaServerConfig().SetLogLevel( log_level ); + if (log_level > 0) config.GetHshaServerConfig().SetLogLevel(log_level); - phxrpc::openlog( argv[0], config.GetHshaServerConfig().GetLogDir(), - config.GetHshaServerConfig().GetLogLevel() ); + phxrpc::openlog(argv[0], config.GetHshaServerConfig().GetLogDir(), + config.GetHshaServerConfig().GetLogLevel()); ServiceArgs_t service_args; service_args.config = &config; - phxrpc::HshaServer server( config.GetHshaServerConfig(), HttpDispatch, &service_args ); + phxrpc::HshaServer server(config.GetHshaServerConfig(), Dispatch, &service_args); server.RunForever(); phxrpc::closelog(); @@ -116,78 +120,82 @@ const char * PHXRPC_EPOLL_UTHREAD_SERVER_MAIN_TEMPLATE = #include #include #include + #include "$DispatcherFile$.h" #include "$ServiceImplFile$.h" #include "$ServerConfigFile$.h" #include "phxrpc/rpc.h" -#include "phxrpc/http.h" +#include "phxrpc/msg.h" #include "phxrpc/file.h" + using namespace std; -void HttpDispatch( const phxrpc::HttpRequest & request, phxrpc::HttpResponse * response, phxrpc::DispatcherArgs_t * args ) { - ServiceArgs_t * service_args = (ServiceArgs_t *)(args->service_args); +void Dispatch(const phxrpc::BaseRequest *request, + phxrpc::BaseResponse *response, + phxrpc::DispatcherArgs_t *args) { + ServiceArgs_t *service_args = (ServiceArgs_t *)(args->service_args); - $ServiceImplClass$ service( * service_args, args->server_worker_uthread_scheduler ); - $DispatcherClass$ dispatcher( service, args ); + $ServiceImplClass$ service(*service_args, args->server_worker_uthread_scheduler); + $DispatcherClass$ dispatcher(service, args); - phxrpc::HttpDispatcher<$DispatcherClass$> http_dispatcher( - dispatcher, $DispatcherClass$::GetURIFuncMap() ); - if( ! http_dispatcher.Dispatch( request, response ) ) { - response->SetStatusCode( 404 ); - response->SetReasonPhrase( "Not Found" ); + phxrpc::BaseDispatcher<$DispatcherClass$> base_dispatcher( + dispatcher, $DispatcherClass$::GetURIFuncMap(), + $DispatcherClass$::GetMqttFuncMap()); + if (!base_dispatcher.Dispatch(request, response)) { + response->DispatchErr(); } } -void showUsage( const char * program ) { - printf( "\n" ); - printf( "Usage: %s [-c ] [-d] [-l ] [-v]\n", program ); - printf( "\n" ); +void ShowUsage(const char *program) { + printf("\n"); + printf("Usage: %s [-c ] [-d] [-l ] [-v]\n", program); + printf("\n"); - exit( 0 ); + exit(0); } -int main( int argc, char * argv[] ) { - const char * config_file = NULL; - bool daemonize = false;; - int log_level = -1; - extern char *optarg ; - int c ; - while( ( c = getopt( argc, argv, "c:vl:d" ) ) != EOF ) { - switch ( c ) { +int main(int argc, char **argv) { + const char *config_file{nullptr}; + bool daemonize{false}; + int log_level{-1}; + extern char *optarg; + int c; + while (EOF != (c = getopt( argc, argv, "c:vl:d"))) { + switch (c) { case 'c' : config_file = optarg; break; case 'd' : daemonize = true; break; - case 'l' : log_level = atoi( optarg ); break; + case 'l' : log_level = atoi(optarg); break; case 'v' : - default: showUsage( argv[ 0 ] ); break; + default: ShowUsage(argv[0]); break; } } - if( daemonize ) phxrpc::ServerUtils::Daemonize(); + if (daemonize) phxrpc::ServerUtils::Daemonize(); assert(signal(SIGPIPE, SIG_IGN) != SIG_ERR); //set customize log/monitor //phxrpc::setlog(openlog, closelog, vlog); - //phxrpc::MonitorFactory::SetFactory( new YourSelfsMonitorFactory() ); + //phxrpc::MonitorFactory::SetFactory(new YourSelfsMonitorFactory()); - if( NULL == config_file ) showUsage( argv[0] ); + if (nullptr == config_file) ShowUsage(argv[0]); $ServerConfigClass$ config; - if( ! config.Read( config_file ) ) showUsage( argv[0] ); + if (!config.Read(config_file)) ShowUsage(argv[0]); - if( log_level > 0 ) config.GetHshaServerConfig().SetLogLevel( log_level ); + if (log_level > 0) config.GetHshaServerConfig().SetLogLevel(log_level); - phxrpc::openlog( argv[0], config.GetHshaServerConfig().GetLogDir(), - config.GetHshaServerConfig().GetLogLevel() ); + phxrpc::openlog(argv[0], config.GetHshaServerConfig().GetLogDir(), + config.GetHshaServerConfig().GetLogLevel()); ServiceArgs_t service_args; service_args.config = &config; - phxrpc::HshaServer server( config.GetHshaServerConfig(), HttpDispatch, &service_args ); + phxrpc::HshaServer server(config.GetHshaServerConfig(), Dispatch, &service_args); server.RunForever(); phxrpc::closelog(); @@ -204,18 +212,18 @@ const char * PHXRPC_EPOLL_SERVER_CONFIG_HPP_TEMPLATE = #include "phxrpc/rpc.h" -class $ServerConfigClass$ -{ -public: + +class $ServerConfigClass$ { + public: $ServerConfigClass$(); - ~$ServerConfigClass$(); + virtual ~$ServerConfigClass$(); - bool Read( const char * config_file ); + bool Read(const char *config_file); - phxrpc::HshaServerConfig & GetHshaServerConfig(); + phxrpc::HshaServerConfig &GetHshaServerConfig(); -private: + private: phxrpc::HshaServerConfig ep_server_config_; }; @@ -226,30 +234,28 @@ class $ServerConfigClass$ const char * PHXRPC_EPOLL_SERVER_CONFIG_CPP_TEMPLATE = R"( -#include "$MessageFile$.h" #include "$ServerConfigFile$.h" -$ServerConfigClass$ :: $ServerConfigClass$() -{ +#include "$MessageFile$.h" + + +$ServerConfigClass$::$ServerConfigClass$() { } -$ServerConfigClass$ :: ~$ServerConfigClass$() -{ +$ServerConfigClass$::~$ServerConfigClass$() { } -bool $ServerConfigClass$ :: Read( const char * config_file ) -{ - bool ret = ep_server_config_.Read( config_file ); +bool $ServerConfigClass$::Read(const char *config_file) { + bool ret{ep_server_config_.Read(config_file)}; - if ( strlen( ep_server_config_.GetPackageName() ) == 0 ) { - ep_server_config_.SetPackageName( $PackageName$ ); + if (0 == strlen(ep_server_config_.GetPackageName())) { + ep_server_config_.SetPackageName($PackageName$); } return ret; } -phxrpc::HshaServerConfig & $ServerConfigClass$ :: GetHshaServerConfig() -{ +phxrpc::HshaServerConfig &$ServerConfigClass$::GetHshaServerConfig() { return ep_server_config_; } @@ -320,15 +326,15 @@ LDFLAGS := -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) #LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS) SVR_OBJS = $MessageFile$.o \ - $ServiceImplFile$.o \ - $ServiceFile$.o \ - $DispatcherFile$.o \ - $ServerConfigFile$.o \ - $ServerMainFile$.o + $ServiceImplFile$.o \ + $ServiceFile$.o \ + $DispatcherFile$.o \ + $ServerConfigFile$.o \ + $ServerMainFile$.o CLI_OBJS = $MessageFile$.o \ - $ClientFile$.o \ - $StubFile$.o + $ClientFile$.o \ + $StubFile$.o TARGETS = lib$ClientFile$.a $ServerMainFile$ $ToolMainFile$ @@ -405,16 +411,16 @@ LDFLAGS := -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) #LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS) SVR_OBJS = $MessageFile$.o \ - $ServiceImplFile$.o \ - $ServiceFile$.o \ - $DispatcherFile$.o \ - $ServerConfigFile$.o \ - $ServerMainFile$.o + $ServiceImplFile$.o \ + $ServiceFile$.o \ + $DispatcherFile$.o \ + $ServerConfigFile$.o \ + $ServerMainFile$.o CLI_OBJS = $MessageFile$.o \ - $ClientFile$.o \ - $ClientFile$_uthread.o \ - $StubFile$.o + $ClientFile$.o \ + $ClientFile$_uthread.o \ + $StubFile$.o TARGETS = lib$ClientFile$.a $ServerMainFile$ $ToolMainFile$ diff --git a/codegen/service_code_render.cpp b/codegen/service_code_render.cpp index 0d4641a..2dd65d6 100644 --- a/codegen/service_code_render.cpp +++ b/codegen/service_code_render.cpp @@ -1,25 +1,26 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include +#include +#include #include "service_code_render.h" @@ -28,20 +29,25 @@ See the AUTHORS file for names of contributors. #include "code_utils.h" + using namespace phxrpc; +using namespace std; + -ServiceCodeRender::ServiceCodeRender(NameRender & name_render) +ServiceCodeRender::ServiceCodeRender(NameRender &name_render) : name_render_(name_render) { } ServiceCodeRender::~ServiceCodeRender() { } -void ServiceCodeRender::GenerateServiceHpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ServiceCodeRender::GenerateServiceHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetServiceFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2service", stree->GetProtoFile(), &buffer); fprintf(write, "/* %s.h\n", filename); @@ -56,25 +62,32 @@ void ServiceCodeRender::GenerateServiceHpp(SyntaxTree * stree, FILE * write) { name_render_.GetMessageFileName(stree->GetProtoFile(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetServiceClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "class %s\n", clasname); - fprintf(write, "{\n"); - fprintf(write, "public:\n"); + fprintf(write, "class %s {\n", clasname); + fprintf(write, " public:\n"); fprintf(write, " %s();\n", clasname); fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + string buffer; + GetServiceFuncDeclaration(stree, &(*mqtt_it), 1, 0, 1, &buffer); + fprintf(write, " virtual %s;\n", buffer.c_str()); + } + fprintf(write, "\n"); + + SyntaxFuncVector *flist{stree->GetFuncList()}; SyntaxFuncVector::iterator fit = flist->begin(); for (; flist->end() != fit; ++fit) { - std::string buffer; + string buffer; GetServiceFuncDeclaration(stree, &(*fit), 1, 0, 1, &buffer); fprintf(write, " virtual %s;\n", buffer.c_str()); - fprintf(write, "\n"); } fprintf(write, "};\n"); @@ -82,11 +95,13 @@ void ServiceCodeRender::GenerateServiceHpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); } -void ServiceCodeRender::GenerateServiceCpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ServiceCodeRender::GenerateServiceCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetServiceFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2service", stree->GetProtoFile(), &buffer); fprintf(write, "/* %s.cpp\n", filename); @@ -100,42 +115,52 @@ void ServiceCodeRender::GenerateServiceCpp(SyntaxTree * stree, FILE * write) { fprintf(write, "#include \"%s.h\"\n", filename); fprintf(write, "#include \"phxrpc/file.h\"\n"); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetServiceClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "%s :: %s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - fprintf(write, "%s :: ~%s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::~%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + string buffer; + GetServiceFuncDeclaration(stree, &(*mqtt_it), 0, 0, 0, &buffer); + fprintf(write, "%s {\n", buffer.c_str()); + fprintf(write, " phxrpc::log(LOG_ERR, \"ERROR: %s unimplemented\");\n", mqtt_it->GetName()); + fprintf(write, " return -1;\n"); + fprintf(write, "}\n"); + fprintf(write, "\n"); + } + + SyntaxFuncVector *flist{stree->GetFuncList()}; SyntaxFuncVector::iterator fit = flist->begin(); for (; flist->end() != fit; ++fit) { - std::string buffer; + string buffer; GetServiceFuncDeclaration(stree, &(*fit), 0, 0, 0, &buffer); - fprintf(write, "%s\n", buffer.c_str()); - fprintf(write, "{\n"); - fprintf(write, " phxrpc::log( LOG_ERR, \"ERROR: %s unimplemented\" );\n", fit->GetName()); + fprintf(write, "%s {\n", buffer.c_str()); + fprintf(write, " phxrpc::log(LOG_ERR, \"ERROR: %s unimplemented\");\n", fit->GetName()); fprintf(write, " return -1;\n"); fprintf(write, "}\n"); fprintf(write, "\n"); } - - fprintf(write, "\n"); } -void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { - char filename[128] = { 0 }; +void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write, + const bool is_uthread_mode) { + char filename[128]{0}; name_render_.GetServiceImplFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2service", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.h\n", filename); @@ -156,46 +181,57 @@ void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write, fprintf(write, "#include \"phxrpc/network.h\"\n"); } + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }, base_name[128] = { 0 }, config_name[128] = { 0 }; + char clasname[128]{0}, base_name[128]{0}, config_name[128]{0}; name_render_.GetServiceClasname(stree->GetName(), base_name, sizeof(base_name)); name_render_.GetServiceImplClasname(stree->GetName(), clasname, sizeof(clasname)); name_render_.GetServerConfigClasname(stree->GetName(), config_name, sizeof(config_name)); fprintf(write, "class %s;\n", config_name); fprintf(write, "\n"); + fprintf(write, "\n"); fprintf(write, "typedef struct tagServiceArgs {\n"); - fprintf(write, " %s * config;\n", config_name); + fprintf(write, " %s *config;\n", config_name); fprintf(write, " //You can add other arguments here and initiate in main().\n"); - fprintf(write, "}ServiceArgs_t;\n"); + fprintf(write, "} ServiceArgs_t;\n"); + fprintf(write, "\n"); fprintf(write, "\n"); - fprintf(write, "class %s : public %s\n", clasname, base_name); - fprintf(write, "{\n"); - fprintf(write, "public:\n"); + fprintf(write, "class %s : public %s {\n", clasname, base_name); + fprintf(write, " public:\n"); if (!is_uthread_mode) { - fprintf(write, " %s( ServiceArgs_t & app_args );\n", clasname); + fprintf(write, " %s(ServiceArgs_t &app_args);\n", clasname); } else { - fprintf(write, " %s( ServiceArgs_t & app_args, phxrpc::UThreadEpollScheduler * worker_uthread_scheduler );\n", clasname); + fprintf(write, " %s(ServiceArgs_t &app_args,\n", clasname); + fprintf(write, " phxrpc::UThreadEpollScheduler *worker_uthread_scheduler);\n", clasname); } fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - std::string buffer; + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + string buffer; + GetServiceFuncDeclaration(stree, &(*mqtt_it), 1, 1, 1, &buffer); + fprintf(write, " virtual %s override;\n", buffer.c_str()); + } + fprintf(write, "\n"); + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + string buffer; GetServiceFuncDeclaration(stree, &(*fit), 1, 1, 1, &buffer); - fprintf(write, " virtual %s;\n", buffer.c_str()); - fprintf(write, "\n"); + fprintf(write, " virtual %s override;\n", buffer.c_str()); } + fprintf(write, "\n"); - fprintf(write, "private:\n"); - fprintf(write, " ServiceArgs_t & args_;\n" ); + fprintf(write, " private:\n"); + fprintf(write, " ServiceArgs_t &args_;\n" ); if (is_uthread_mode) { - fprintf(write, " phxrpc::UThreadEpollScheduler * worker_uthread_scheduler_;\n" ); + fprintf(write, " phxrpc::UThreadEpollScheduler *worker_uthread_scheduler_;\n" ); } fprintf(write, "};\n"); @@ -203,12 +239,15 @@ void ServiceCodeRender::GenerateServiceImplHpp(SyntaxTree * stree, FILE * write, fprintf(write, "\n"); } -void ServiceCodeRender::GenerateServiceImplCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode) { - char filename[128] = { 0 }, config_file[128] = { 0 }; +void ServiceCodeRender::GenerateServiceImplCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write, + const bool is_uthread_mode) { + char filename[128]{0}, config_file[128]{0}; name_render_.GetServiceImplFileName(stree->GetName(), filename, sizeof(filename)); name_render_.GetServerConfigFileName(stree->GetName(), config_file, sizeof(config_file)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2service", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.cpp\n", filename); @@ -217,58 +256,78 @@ void ServiceCodeRender::GenerateServiceImplCpp(SyntaxTree * stree, FILE * write, fprintf(write, "\n"); fprintf(write, "#include \"%s.h\"\n", filename); + fprintf(write, "\n"); + fprintf(write, "#include \"%s.h\"\n", config_file); name_render_.GetMessageFileName(stree->GetProtoFile(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); fprintf(write, "#include \"phxrpc/file.h\"\n"); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }, config_name[128] = { 0 }; + char clasname[128]{0}, config_name[128]{0}; name_render_.GetServiceImplClasname(stree->GetName(), clasname, sizeof(clasname)); name_render_.GetServerConfigClasname(stree->GetName(), config_name, sizeof(config_name)); if (!is_uthread_mode) { - fprintf(write, "%s :: %s(ServiceArgs_t & app_args)\n", clasname, clasname); - fprintf(write, " : args_(app_args)\n"); + fprintf(write, "%s::%s(ServiceArgs_t &app_args)\n", clasname, clasname); + fprintf(write, " : args_(app_args) {\n"); } else { - fprintf(write, "%s :: %s(ServiceArgs_t & app_args, phxrpc::UThreadEpollScheduler * worker_uthread_scheduler)\n", clasname, clasname); - fprintf(write, " : args_(app_args), worker_uthread_scheduler_(worker_uthread_scheduler)\n"); + fprintf(write, "%s::%s(ServiceArgs_t &app_args,\n", clasname, clasname); + fprintf(write, " phxrpc::UThreadEpollScheduler *worker_uthread_scheduler)\n", clasname, clasname); + fprintf(write, " : args_(app_args), worker_uthread_scheduler_(worker_uthread_scheduler) {\n"); } - fprintf(write, "{\n"); fprintf(write, "}\n"); fprintf(write, "\n"); - fprintf(write, "%s :: ~%s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::~%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - std::string buffer; + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + string buffer; + GetServiceFuncDeclaration(stree, &(*mqtt_it), 0, 1, 1, &buffer); + fprintf(write, "%s {\n", buffer.c_str()); + + if (0 == strcmp("PhxMqttPublish", mqtt_it->GetName())) { + fprintf(write, " // TODO: process req.content()\n"); + fprintf(write, "\n"); + fprintf(write, " return -1;\n"); + } else { + fprintf(write, " return 0;\n"); + } + + fprintf(write, "}\n"); + fprintf(write, "\n"); + } + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + string buffer; GetServiceFuncDeclaration(stree, &(*fit), 0, 1, 1, &buffer); - fprintf(write, "%s\n", buffer.c_str()); - fprintf(write, "{\n"); + fprintf(write, "%s {\n", buffer.c_str()); - if (0 == strcmp("PHXEcho", fit->GetName())) { - fprintf(write, " resp->set_value( req.value() );\n"); + if (0 == strcmp("PhxEcho", fit->GetName())) { + fprintf(write, " resp->set_value(req.value());\n"); + fprintf(write, "\n"); fprintf(write, " return 0;\n"); } else { fprintf(write, " return -1;\n"); } + fprintf(write, "}\n"); fprintf(write, "\n"); } - - fprintf(write, "\n"); } -void ServiceCodeRender::GetServiceFuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, int is_impl, - int need_param_name, std::string * result) { - char clasname[128] = { 0 }, type_name[128] = { 0 }; +void ServiceCodeRender::GetServiceFuncDeclaration(SyntaxTree *stree, + const SyntaxFunc *const func, int is_header, int is_impl, + int need_param_name, string *result) { + char clasname[128]{0}, type_name[128]{0}; if (is_impl) { name_render_.GetServiceImplClasname(stree->GetName(), clasname, sizeof(clasname)); @@ -277,25 +336,28 @@ void ServiceCodeRender::GetServiceFuncDeclaration(SyntaxTree * stree, SyntaxFunc } if (is_header) { - StrAppendFormat(result, "int %s( ", func->GetName()); + StrAppendFormat(result, "int %s(", func->GetName()); } else { - StrAppendFormat(result, "int %s :: %s( ", clasname, func->GetName()); + StrAppendFormat(result, "int %s::%s(", clasname, func->GetName()); } name_render_.GetMessageClasname(func->GetReq()->GetType(), type_name, sizeof(type_name)); - StrAppendFormat(result, "const %s & %s,\n", type_name, need_param_name ? "req" : "/* req */"); + StrAppendFormat(result, "const %s &%s", type_name, need_param_name ? "req" : "/* req */"); - name_render_.GetMessageClasname(func->GetResp()->GetType(), type_name, sizeof(type_name)); - StrAppendFormat(result, " %s * %s", type_name, need_param_name ? "resp" : "/* resp */"); + const char *const resp_type{func->GetResp()->GetType()}; + if (resp_type && 0 < strlen(resp_type)) { + name_render_.GetMessageClasname(func->GetResp()->GetType(), type_name, sizeof(type_name)); + StrAppendFormat(result, ", %s *%s", type_name, need_param_name ? "resp" : "/* resp */"); + } - result->append(" )"); + result->append(")"); } -void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree *stree, FILE *write) { + char filename[128]{0}; name_render_.GetDispatcherFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2service", stree->GetProtoFile(), &buffer); fprintf(write, "/* %s.h\n", filename); @@ -310,41 +372,46 @@ void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree * stree, FILE * write) fprintf(write, "#include \"phxrpc/http.h\"\n"); fprintf(write, "#include \"phxrpc/rpc.h\"\n"); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }, service_name[128] = { 0 }; + char clasname[128]{0}, service_name[128]{0}; name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); name_render_.GetServiceClasname(stree->GetName(), service_name, sizeof(service_name)); fprintf(write, "class %s;\n", service_name); fprintf(write, "\n"); - fprintf(write, "class %s\n", clasname); - fprintf(write, "{\n"); - fprintf(write, "public:\n"); + fprintf(write, "class %s {\n", clasname); - fprintf(write, " %s( %s & service, phxrpc::DispatcherArgs_t * dispatcher_args );\n", clasname, service_name); + fprintf(write, " public:\n"); + fprintf(write, " static const phxrpc::BaseDispatcher<%s>::MqttFuncMap &GetMqttFuncMap();\n", clasname); + fprintf(write, " static const phxrpc::BaseDispatcher<%s>::URIFuncMap &GetURIFuncMap();\n", clasname); fprintf(write, "\n"); - fprintf(write, " ~%s();\n", clasname); + fprintf(write, " %s(%s &service, phxrpc::DispatcherArgs_t *dispatcher_args);\n", clasname, service_name); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - fprintf(write, " int %s( const phxrpc::HttpRequest & request, " - "phxrpc::HttpResponse * response );\n", + fprintf(write, " virtual ~%s();\n", clasname); + fprintf(write, "\n"); + + fprintf(write, " int PhxMqttConnect(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp);\n"); + fprintf(write, " int PhxMqttPublish(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp);\n"); + fprintf(write, " int PhxMqttDisconnect(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp);\n"); + fprintf(write, "\n"); + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + fprintf(write, " int %s(const phxrpc::BaseRequest *request, " + "phxrpc::BaseResponse *response);\n", fit->GetName()); - fprintf(write, "\n"); } - - fprintf(write, "private:\n"); - fprintf(write, " %s & service_;\n", service_name); - fprintf(write, " phxrpc::DispatcherArgs_t * dispatcher_args_;\n" ); fprintf(write, "\n"); - fprintf(write, "public:\n"); - fprintf(write, " static const phxrpc::HttpDispatcher< %s >::URIFuncMap & GetURIFuncMap();\n", clasname); + fprintf(write, " private:\n"); + fprintf(write, " %s &service_;\n", service_name); + fprintf(write, " phxrpc::DispatcherArgs_t *dispatcher_args_;\n" ); fprintf(write, "\n"); fprintf(write, "};\n"); @@ -352,11 +419,13 @@ void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree * stree, FILE * write) fprintf(write, "\n"); } -void ServiceCodeRender::GenerateDispatcherCpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ServiceCodeRender::GenerateDispatcherCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetDispatcherFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2service", stree->GetProtoFile(), &buffer); fprintf(write, "/* %s.h\n", filename); @@ -367,6 +436,9 @@ void ServiceCodeRender::GenerateDispatcherCpp(SyntaxTree * stree, FILE * write) fprintf(write, "#include \"%s.h\"\n", filename); fprintf(write, "\n"); + fprintf(write, "#include \n"); + fprintf(write, "\n"); + name_render_.GetMessageFileName(stree->GetProtoFile(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); @@ -375,52 +447,99 @@ void ServiceCodeRender::GenerateDispatcherCpp(SyntaxTree * stree, FILE * write) fprintf(write, "#include \"phxrpc/http.h\"\n"); fprintf(write, "#include \"phxrpc/file.h\"\n"); - fprintf(write, "#include \n"); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }, service_name[128] = { 0 }; + char clasname[128]{0}, service_name[128]{0}; name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); name_render_.GetServiceClasname(stree->GetName(), service_name, sizeof(service_name)); - fprintf(write, "%s :: %s( %s & service, phxrpc::DispatcherArgs_t * dispatcher_args )\n", clasname, clasname, service_name); - fprintf(write, " : service_( service ), dispatcher_args_(dispatcher_args)\n"); - - fprintf(write, "{\n"); + fprintf(write, "%s::%s(%s &service, phxrpc::DispatcherArgs_t *dispatcher_args)\n", clasname, clasname, service_name); + fprintf(write, " : service_(service), dispatcher_args_(dispatcher_args) {\n"); fprintf(write, "}\n"); fprintf(write, "\n"); - fprintf(write, "%s :: ~%s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::~%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); + vector functions; + + FunctionItem connect_item; + connect_item.protocol_name = "MQTT_CONNECT"; + connect_item.function_name = "PhxMqttConnect"; + functions.push_back(connect_item); + + FunctionItem publish_item; + publish_item.protocol_name = "MQTT_PUBLISH"; + publish_item.function_name = "PhxMqttPublish"; + functions.push_back(publish_item); + + FunctionItem disconnect_item; + disconnect_item.protocol_name = "MQTT_DISCONNECT"; + disconnect_item.function_name = "PhxMqttDisconnect"; + functions.push_back(disconnect_item); + + GenerateMqttFuncMap(stree, functions, write); + + fprintf(write, "\n"); + GenerateURIFuncMap(stree, write); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + GenerateMqttDispatcherFunc(stree, &(*mqtt_it), write); + } + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { GenerateDispatcherFunc(stree, &(*fit), write); } +} + +void ServiceCodeRender::GenerateMqttFuncMap(SyntaxTree *stree, + const vector functions, + FILE *write) { + char clasname[128]{0}; + name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); + + fprintf(write, "const phxrpc::BaseDispatcher<%s>::MqttFuncMap &%s::GetMqttFuncMap() {\n", + clasname, clasname); + + fprintf(write, " static phxrpc::BaseDispatcher<%s>::MqttFuncMap mqtt_func_map = {\n", + clasname); + + for (auto it(functions.cbegin()); functions.cend() != it; ++it) { + if (it != functions.cbegin()) { + fprintf(write, ",\n"); + } + fprintf(write, " {phxrpc::BaseMessage::Protocol::%s, &%s::%s}", + it->protocol_name.c_str(), clasname, + it->function_name.c_str()); + } + fprintf(write, "};\n"); - fprintf(write, "\n"); + fprintf(write, " return mqtt_func_map;\n"); + + fprintf(write, "}\n"); } -void ServiceCodeRender::GenerateURIFuncMap(SyntaxTree * stree, FILE * write) { - char clasname[128] = { 0 }; +void ServiceCodeRender::GenerateURIFuncMap(SyntaxTree *stree, FILE *write) { + char clasname[128]{0}; name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "const phxrpc::HttpDispatcher< %s >::URIFuncMap & %s :: GetURIFuncMap()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "const phxrpc::BaseDispatcher<%s>::URIFuncMap &%s::GetURIFuncMap() {\n", clasname, clasname); - fprintf(write, " static phxrpc::HttpDispatcher< %s >::URIFuncMap uri_func_map = {\n", clasname); + fprintf(write, " static phxrpc::BaseDispatcher<%s>::URIFuncMap uri_func_map = {\n", clasname); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - if (fit != flist->begin()) { + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + if (fit != flist->cbegin()) { fprintf(write, ",\n"); } fprintf(write, " {\"/%s/%s\", &%s::%s}", stree->GetPackageName(), fit->GetName(), clasname, @@ -433,66 +552,129 @@ void ServiceCodeRender::GenerateURIFuncMap(SyntaxTree * stree, FILE * write) { fprintf(write, "}\n"); } -void ServiceCodeRender::GenerateDispatcherFunc(SyntaxTree * stree, SyntaxFunc * func, FILE * write) { - char clasname[128] = { 0 }, type_name[128] = { 0 }; +void ServiceCodeRender::GenerateMqttDispatcherFunc(SyntaxTree *stree, + const SyntaxFunc *const func, + FILE *write) { + char clasname[128]{0}, type_name[128]{0}; + + name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); + + fprintf(write, "int %s::%s(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp) {\n", + clasname, func->GetName()); + fprintf(write, " dispatcher_args_->server_monitor->SvrCall(%d, \"%s\", 1);\n", + func->GetCmdID(), func->GetName()); + fprintf(write, "\n"); + fprintf(write, " int ret{0};\n"); + fprintf(write, "\n"); + name_render_.GetMessageClasname(func->GetReq()->GetType(), type_name, sizeof(type_name)); + fprintf(write, " %s req_pb;\n", type_name); + bool has_resp{func->GetResp()->GetType() && 0 < strlen(func->GetResp()->GetType())}; + if (has_resp) { + name_render_.GetMessageClasname(func->GetResp()->GetType(), type_name, sizeof(type_name)); + fprintf(write, " %s resp_pb;\n", type_name); + } + fprintf(write, "\n"); + fprintf(write, " // unpack request\n"); + fprintf(write, " {\n"); + fprintf(write, " phxrpc::ReturnCode ret_code{req->ToPb(&req_pb)};\n"); + fprintf(write, " if (phxrpc::ReturnCode::OK != ret_code) {\n"); + fprintf(write, " phxrpc::log(LOG_ERR, \"ToPb ip %%s err %%d\", req->GetClientIP(), static_cast(ret_code));\n"); + fprintf(write, "\n"); + fprintf(write, " return -EINVAL;\n"); + fprintf(write, " }\n"); + fprintf(write, " }\n"); + fprintf(write, "\n"); + fprintf(write, " // logic process\n"); + fprintf(write, " {\n"); + fprintf(write, " if (0 == ret) {\n"); + if (has_resp) { + fprintf(write, " ret = service_.%s(req_pb, &resp_pb);\n", func->GetName()); + } else { + fprintf(write, " ret = service_.%s(req_pb);\n", func->GetName()); + } + fprintf(write, " }\n"); + fprintf(write, " }\n"); + fprintf(write, "\n"); + if (has_resp) { + fprintf(write, " // pack response\n"); + fprintf(write, " {\n"); + fprintf(write, " phxrpc::ReturnCode ret_code{resp->FromPb(resp_pb)};\n"); + fprintf(write, " if (phxrpc::ReturnCode::OK != ret_code) {\n"); + fprintf(write, " phxrpc::log(LOG_ERR, \"FromPb ip %%s err %%d\", req->GetClientIP(), static_cast(ret_code));\n"); + fprintf(write, "\n"); + fprintf(write, " return -ENOMEM;\n"); + fprintf(write, " }\n"); + fprintf(write, " }\n"); + fprintf(write, "\n"); + } + fprintf(write, " phxrpc::log(LOG_DEBUG, \"ret %%d\", ret);\n"); + fprintf(write, "\n"); + fprintf(write, " return ret;\n"); + fprintf(write, "}\n"); + + fprintf(write, "\n"); +} + +void ServiceCodeRender::GenerateDispatcherFunc(SyntaxTree *stree, + const SyntaxFunc *const func, + FILE *write) { + char clasname[128]{0}, type_name[128]{0}; name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "int %s :: %s( const phxrpc::HttpRequest & request, " - "phxrpc::HttpResponse * response )\n", + fprintf(write, "int %s::%s(const phxrpc::BaseRequest *request, " + "phxrpc::BaseResponse *response) {\n", clasname, func->GetName()); - fprintf(write, "{\n"); - fprintf(write, " dispatcher_args_->server_monitor->SvrCall(%d, \"%s\", 1);\n", func->GetCmdID(), func->GetName() ); + fprintf(write, " dispatcher_args_->server_monitor->SvrCall(%d, \"%s\", 1);\n", + func->GetCmdID(), func->GetName()); fprintf(write, "\n"); - fprintf(write, " int ret = 0;\n"); + fprintf(write, " int ret{0};\n"); fprintf(write, "\n"); name_render_.GetMessageClasname(func->GetReq()->GetType(), type_name, sizeof(type_name)); - fprintf(write, " %s req;\n", type_name); + fprintf(write, " %s req_pb;\n", type_name); name_render_.GetMessageClasname(func->GetResp()->GetType(), type_name, sizeof(type_name)); - fprintf(write, " %s resp;\n", type_name); + fprintf(write, " %s resp_pb;\n", type_name); fprintf(write, "\n"); - fprintf(write, " //unpack request\n"); + fprintf(write, " // unpack request\n"); fprintf(write, " {\n"); - fprintf(write, " if( ! req.ParseFromString( request.GetContent() ) )\n"); - fprintf(write, " {\n"); + fprintf(write, " if (!req_pb.ParseFromString(request->GetContent())) {\n"); - fprintf(write, " phxrpc::log( LOG_ERR, \"ERROR: FromBuffer fail size %%zu ip %%s\",\n" - " request.GetContent().size(), request.GetClientIP() );\n"); + fprintf(write, " phxrpc::log(LOG_ERR, \"ERROR: FromBuffer fail size %%zu ip %%s\",\n" + " request->GetContent().size(), request->GetClientIP());\n"); - fprintf(write, " return -1 * EINVAL;\n"); + fprintf(write, " return -EINVAL;\n"); fprintf(write, " }\n"); fprintf(write, " }\n"); fprintf(write, "\n"); - fprintf(write, " //logic process\n"); + fprintf(write, " // logic process\n"); fprintf(write, " {\n"); - fprintf(write, " if( 0 == ret ) ret = service_.%s( req, &resp );\n", func->GetName()); + fprintf(write, " if (0 == ret) ret = service_.%s(req_pb, &resp_pb);\n", func->GetName()); fprintf(write, " }\n\n"); - fprintf(write, " //pack response\n"); + fprintf(write, " // pack response\n"); fprintf(write, " {\n"); - fprintf(write, " if( ! resp.SerializeToString( &( response->GetContent() ) ) )\n"); - fprintf(write, " {\n"); + fprintf(write, " if (!resp_pb.SerializeToString(&(response->GetContent()))) {\n"); - fprintf(write, " phxrpc::log( LOG_ERR, \"ERROR: ToBuffer fail ip %%s\", request.GetClientIP() );\n"); + fprintf(write, " phxrpc::log(LOG_ERR, \"ERROR: ToBuffer fail ip %%s\", request->GetClientIP());\n"); - fprintf(write, " return -1 * ENOMEM;\n"); + fprintf(write, " return -ENOMEM;\n"); fprintf(write, " }\n"); fprintf(write, " }\n"); fprintf(write, "\n"); - fprintf(write, " phxrpc::log( LOG_DEBUG, \"RETN: %s = %%d\", ret );\n", func->GetName()); + fprintf(write, " phxrpc::log(LOG_DEBUG, \"RETN: %s = %%d\", ret);\n", func->GetName()); fprintf(write, "\n"); fprintf(write, " return ret;\n"); diff --git a/codegen/service_code_render.h b/codegen/service_code_render.h index 9dd5345..5439cc2 100755 --- a/codegen/service_code_render.h +++ b/codegen/service_code_render.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,45 +21,74 @@ See the AUTHORS file for names of contributors. #pragma once -#include +#include #include #include +#include + namespace phxrpc { + class NameRender; class SyntaxTree; class SyntaxFunc; +typedef std::vector SyntaxFuncVector; class ServiceCodeRender { - public: - ServiceCodeRender(NameRender & name_render); + public: + ServiceCodeRender(NameRender &name_render); virtual ~ServiceCodeRender(); - virtual void GenerateServiceHpp(SyntaxTree * stree, FILE * write); + virtual void GenerateServiceHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); + + virtual void GenerateServiceCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); - virtual void GenerateServiceCpp(SyntaxTree * stree, FILE * write); + virtual void GenerateServiceImplHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write, const bool is_uthread_mode); - virtual void GenerateServiceImplHpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); + virtual void GenerateServiceImplCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write, const bool is_uthread_mode); - virtual void GenerateServiceImplCpp(SyntaxTree * stree, FILE * write, const bool is_uthread_mode); + virtual void GenerateDispatcherHpp(SyntaxTree *stree, FILE *write); - virtual void GenerateDispatcherHpp(SyntaxTree * stree, FILE * write); + virtual void GenerateDispatcherCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); - virtual void GenerateDispatcherCpp(SyntaxTree * stree, FILE * write); + protected: + struct FunctionItem { + std::string protocol_name; + std::string function_name; + }; - protected: + virtual void GetServiceFuncDeclaration(SyntaxTree *stree, + const SyntaxFunc *const func, int is_header, int is_impl, + int need_param_name, std::string *result); - virtual void GetServiceFuncDeclaration(SyntaxTree * stree, SyntaxFunc * func, int is_header, int is_impl, - int need_param_name, std::string * result); + virtual void GenerateMqttDispatcherFunc(SyntaxTree *stree, + const SyntaxFunc *const func, + FILE *write); - virtual void GenerateDispatcherFunc(SyntaxTree * stree, SyntaxFunc * func, FILE * write); + virtual void GenerateDispatcherFunc(SyntaxTree *stree, + const SyntaxFunc *const func, + FILE *write); - virtual void GenerateURIFuncMap(SyntaxTree * stree, FILE * write); + virtual void GenerateMqttFuncMap(SyntaxTree *stree, + const std::vector functions, + FILE *write); - protected: - NameRender & name_render_; + virtual void GenerateURIFuncMap(SyntaxTree *stree, FILE *write); + + NameRender &name_render_; }; + } diff --git a/codegen/syntax_tree.cpp b/codegen/syntax_tree.cpp index 1897824..22eac92 100644 --- a/codegen/syntax_tree.cpp +++ b/codegen/syntax_tree.cpp @@ -1,33 +1,35 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include -#include +#include +#include +#include +#include #include "syntax_tree.h" + using namespace phxrpc; + SyntaxNode::SyntaxNode() { memset(name_, 0, sizeof(name_)); } @@ -35,11 +37,11 @@ SyntaxNode::SyntaxNode() { SyntaxNode::~SyntaxNode() { } -void SyntaxNode::SetName(const char * name) { +void SyntaxNode::SetName(const char *name) { strncpy(name_, name, sizeof(name_) - 1); } -const char * SyntaxNode::GetName() const { +const char *SyntaxNode::GetName() const { return name_; } @@ -52,11 +54,11 @@ SyntaxParam::SyntaxParam() { SyntaxParam::~SyntaxParam() { } -void SyntaxParam::SetType(const char * type) { +void SyntaxParam::SetType(const char *type) { strncpy(type_, type, sizeof(type_) - 1); } -const char * SyntaxParam::GetType() const { +const char *SyntaxParam::GetType() const { return type_; } @@ -71,43 +73,43 @@ SyntaxFunc::SyntaxFunc() { SyntaxFunc::~SyntaxFunc() { } -const SyntaxParam * SyntaxFunc::GetReq() const { +const SyntaxParam *SyntaxFunc::GetReq() const { return &req_; } -const SyntaxParam * SyntaxFunc::GetResp() const { +const SyntaxParam *SyntaxFunc::GetResp() const { return &resp_; } -SyntaxParam * SyntaxFunc::GetReq() { +SyntaxParam *SyntaxFunc::GetReq() { return &req_; } -SyntaxParam * SyntaxFunc::GetResp() { +SyntaxParam *SyntaxFunc::GetResp() { return &resp_; } -void SyntaxFunc::SetOptString(const char * opt_string) { +void SyntaxFunc::SetOptString(const char *opt_string) { strncpy(opt_string_, opt_string, sizeof(opt_string_)); } -const char * SyntaxFunc::GetOptString() const { +const char *SyntaxFunc::GetOptString() const { return opt_string_; } -void SyntaxFunc::SetUsage(const char * usage) { +void SyntaxFunc::SetUsage(const char *usage) { strncpy(usage_, usage, sizeof(usage_)); } -const char * SyntaxFunc::GetUsage() const { +const char *SyntaxFunc::GetUsage() const { return usage_; } -void SyntaxFunc::SetCmdID(int32_t cmdid) { +void SyntaxFunc::SetCmdID(const int32_t cmdid) { cmdid_ = cmdid; } -int32_t SyntaxFunc::GetCmdID() { +int32_t SyntaxFunc::GetCmdID() const { return cmdid_; } @@ -125,43 +127,43 @@ SyntaxTree::~SyntaxTree() { void SyntaxTree::Print() { } -void SyntaxTree::SetProtoFile(const char * proto_file) { +void SyntaxTree::SetProtoFile(const char *proto_file) { strncpy(proto_file_, proto_file, sizeof(proto_file_) - 1); } -const char * SyntaxTree::GetProtoFile() const { +const char *SyntaxTree::GetProtoFile() const { return proto_file_; } -const char * SyntaxTree::GetPackageName() const { +const char *SyntaxTree::GetPackageName() const { return package_name_; } -void SyntaxTree::SetPackageName(const char * package_name) { +void SyntaxTree::SetPackageName(const char *package_name) { strncpy(package_name_, package_name, sizeof(package_name_) - 1); } -void SyntaxTree::SetPrefix(const char * prefix) { +void SyntaxTree::SetPrefix(const char *prefix) { strncpy(prefix_, prefix, sizeof(prefix_) - 1); ToUpper(prefix_); } -const char * SyntaxTree::GetPrefix() const { +const char *SyntaxTree::GetPrefix() const { return prefix_; } -const SyntaxFuncVector * SyntaxTree::GetFuncList() const { +const SyntaxFuncVector *SyntaxTree::GetFuncList() const { return &func_list_; } -SyntaxFuncVector * SyntaxTree::GetFuncList() { +SyntaxFuncVector *SyntaxTree::GetFuncList() { return &func_list_; } -SyntaxFunc * SyntaxTree::FindFunc(const char * name) { - SyntaxFunc * ret = NULL; +SyntaxFunc *SyntaxTree::FindFunc(const char *name) { + SyntaxFunc *ret{nullptr}; - for (SyntaxFuncVector::iterator iter = func_list_.begin(); func_list_.end() != iter; ++iter) { + for (SyntaxFuncVector::iterator iter(func_list_.begin()); func_list_.end() != iter; ++iter) { if (0 == strcasecmp(name, iter->GetName())) { ret = &(*iter); break; @@ -171,7 +173,7 @@ SyntaxFunc * SyntaxTree::FindFunc(const char * name) { return ret; } -char * SyntaxTree::ToLower(char *s) { +char *SyntaxTree::ToLower(char *s) { char *ret = s; for (; *s != '\0'; ++s) @@ -180,8 +182,8 @@ char * SyntaxTree::ToLower(char *s) { return ret; } -char * SyntaxTree::ToUpper(char *s) { - char * ret = s; +char *SyntaxTree::ToUpper(char *s) { + char *ret = s; for (; *s != '\0'; s++) *s = toupper(*s); diff --git a/codegen/syntax_tree.h b/codegen/syntax_tree.h index 0d2edbe..1b3d769 100644 --- a/codegen/syntax_tree.h +++ b/codegen/syntax_tree.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -24,61 +24,64 @@ See the AUTHORS file for names of contributors. #include #include + namespace phxrpc { + enum { _SYNTAX_NAME_LEN = 512, _SYNTAX_DESC_LEN = 512, _SYNTAX_TYPE_LEN = 512 }; + class SyntaxNode { - public: + public: SyntaxNode(); virtual ~SyntaxNode(); - void SetName(const char * name); - const char * GetName() const; + void SetName(const char *name); + const char *GetName() const; - private: + private: char name_[_SYNTAX_NAME_LEN]; }; class SyntaxParam : public SyntaxNode { - public: + public: SyntaxParam(); - ~SyntaxParam(); + virtual ~SyntaxParam() override; - void SetType(const char * type); - const char * GetType() const; + void SetType(const char *type); + const char *GetType() const; - private: + private: char type_[_SYNTAX_TYPE_LEN]; }; class SyntaxFunc : public SyntaxNode { - public: + public: SyntaxFunc(); - ~SyntaxFunc(); + virtual ~SyntaxFunc() override; - const SyntaxParam * GetReq() const; + const SyntaxParam *GetReq() const; - const SyntaxParam * GetResp() const; + const SyntaxParam *GetResp() const; - SyntaxParam * GetReq(); + SyntaxParam *GetReq(); - SyntaxParam * GetResp(); + SyntaxParam *GetResp(); - void SetOptString(const char * opt_string); - const char * GetOptString() const; + void SetOptString(const char *opt_string); + const char *GetOptString() const; - void SetUsage(const char * usage); - const char * GetUsage() const; + void SetUsage(const char *usage); + const char *GetUsage() const; - void SetCmdID(int32_t cmdid ); - int32_t GetCmdID(); + void SetCmdID(const int32_t cmdid); + int32_t GetCmdID() const; - private: + private: SyntaxParam req_; SyntaxParam resp_; char opt_string_[_SYNTAX_DESC_LEN]; @@ -95,31 +98,30 @@ class SyntaxTree; typedef std::vector SyntaxTreeVector; class SyntaxTree : public SyntaxNode { - public: + public: SyntaxTree(); - ~SyntaxTree(); + virtual ~SyntaxTree() override; - void SetProtoFile(const char * proto_file); - const char * GetProtoFile() const; + void SetProtoFile(const char *proto_file); + const char *GetProtoFile() const; - void SetPrefix(const char * prefix); - const char * GetPrefix() const; + void SetPrefix(const char *prefix); + const char *GetPrefix() const; - void SetPackageName(const char * sPBPackageName); - const char * GetPackageName() const; + void SetPackageName(const char *sPBPackageName); + const char *GetPackageName() const; - const SyntaxFuncVector * GetFuncList() const; - SyntaxFuncVector * GetFuncList(); + const SyntaxFuncVector *GetFuncList() const; + SyntaxFuncVector *GetFuncList(); - SyntaxFunc * FindFunc(const char * name); + SyntaxFunc *FindFunc(const char *name); void Print(); - public: - static char * ToLower(register char *s); - static char * ToUpper(register char *s); + static char *ToLower(register char *s); + static char *ToUpper(register char *s); - private: + private: char proto_file_[128]; char prefix_[32]; char package_name_[128]; @@ -127,5 +129,6 @@ class SyntaxTree : public SyntaxNode { SyntaxFuncVector func_list_; }; + } diff --git a/codegen/tool_code_render.cpp b/codegen/tool_code_render.cpp index 4d69952..9edc71f 100644 --- a/codegen/tool_code_render.cpp +++ b/codegen/tool_code_render.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -28,81 +28,102 @@ See the AUTHORS file for names of contributors. #include "name_render.h" #include "code_utils.h" + using namespace phxrpc; +using namespace std; + -ToolCodeRender::ToolCodeRender(NameRender & name_render) +ToolCodeRender::ToolCodeRender(NameRender &name_render) : name_render_(name_render) { } ToolCodeRender::~ToolCodeRender() { } -void ToolCodeRender::GenerateToolHpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ToolCodeRender::GenerateToolHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetToolFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer); fprintf(write, "/* %s.h\n", filename); fprintf(write, "%s", buffer.c_str()); fprintf(write, "*/\n"); fprintf(write, "\n"); - fprintf(write, "#include \n"); fprintf(write, "#pragma once\n"); - fprintf(write, "\n"); + fprintf(write, "#include \n"); + fprintf(write, "\n"); fprintf(write, "\n"); fprintf(write, "namespace phxrpc {\n"); - fprintf(write, " class OptMap;\n"); + fprintf(write, "\n"); + fprintf(write, "\n"); + fprintf(write, "class OptMap;\n"); + fprintf(write, "\n"); + fprintf(write, "\n"); fprintf(write, "}\n"); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetToolClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "class %s\n", clasname); - fprintf(write, "{\n"); - fprintf(write, "public:\n"); + fprintf(write, "class %s {\n", clasname); + fprintf(write, " public:\n"); fprintf(write, " %s();\n", clasname); fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - fprintf(write, " virtual int %s( phxrpc::OptMap & bigmap );\n", fit->GetName()); - fprintf(write, "\n"); + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + fprintf(write, " virtual int %s(phxrpc::OptMap &bigmap);\n", mqtt_it->GetName()); + } + fprintf(write, "\n"); + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + fprintf(write, " virtual int %s(phxrpc::OptMap &bigmap);\n", fit->GetName()); } + fprintf(write, "\n"); - fprintf(write, "public:\n"); - fprintf(write, " typedef int (%s::*ToolFunc_t) ( phxrpc::OptMap & );\n", clasname); + fprintf(write, " typedef int (%s::*ToolFunc_t)(phxrpc::OptMap &);\n", clasname); fprintf(write, "\n"); fprintf(write, " typedef struct tagName2Func {\n"); - fprintf(write, " const char * name;\n"); + fprintf(write, " const char *name;\n"); fprintf(write, " %s::ToolFunc_t func;\n", clasname); - fprintf(write, " const char * opt_string;\n"); - fprintf(write, " const char * usage;\n"); + fprintf(write, " const char *opt_string;\n"); + fprintf(write, " const char *usage;\n"); fprintf(write, " } Name2Func_t;\n"); fprintf(write, "\n"); - fprintf(write, " static Name2Func_t * GetName2Func()\n"); - fprintf(write, " {\n"); - fprintf(write, " static Name2Func_t name2func [] = {\n"); + fprintf(write, " static Name2Func_t *GetName2Func() {\n"); + fprintf(write, " static Name2Func_t name2func[]{\n"); { - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - if (strlen(fit->GetOptString()) > 0) { - fprintf(write, " { \"%s\", &%s::%s, \"c:f:v%s\",\n \"%s\" },\n", fit->GetName(), clasname, + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + fprintf(write, " {\"%s\", &%s::%s, \"c:f:v%s\",\n \"%s\"},\n", + mqtt_it->GetName(), clasname, + mqtt_it->GetName(), mqtt_it->GetOptString(), mqtt_it->GetUsage()); + } + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + if (0 < strlen(fit->GetOptString())) { + fprintf(write, " {\"%s\", &%s::%s, \"c:f:v%s\",\n \"%s\"},\n", + fit->GetName(), clasname, fit->GetName(), fit->GetOptString(), fit->GetUsage()); } } - fprintf(write, " { NULL, NULL }\n"); + fprintf(write, " {nullptr, nullptr}\n"); } fprintf(write, " };\n"); fprintf(write, "\n"); @@ -114,11 +135,13 @@ void ToolCodeRender::GenerateToolHpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); } -void ToolCodeRender::GenerateToolCpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ToolCodeRender::GenerateToolCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetToolFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer); fprintf(write, "/* %s.cpp\n", filename); @@ -132,44 +155,53 @@ void ToolCodeRender::GenerateToolCpp(SyntaxTree * stree, FILE * write) { name_render_.GetClientFileName(stree->GetName(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); + fprintf(write, "\n"); fprintf(write, "\n"); fprintf(write, "using namespace phxrpc;\n"); fprintf(write, "\n"); + fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetToolClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "%s :: %s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - fprintf(write, "%s :: ~%s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::~%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - char client_class[128] = { 0 }; + char client_class[128]{0}; name_render_.GetClientClasname(stree->GetName(), client_class, sizeof(client_class)); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - fprintf(write, "int %s :: %s( phxrpc::OptMap & /* opt_map */ )\n", clasname, fit->GetName()); - fprintf(write, "{\n"); - fprintf(write, " printf( \"\\n *** %s unimplement ***\\n\" );\n\n", fit->GetName()); + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + fprintf(write, "int %s::%s(phxrpc::OptMap &/* opt_map */) {\n", clasname, mqtt_it->GetName()); + fprintf(write, " printf(\"\\n *** %s unimplement ***\\n\");\n\n", mqtt_it->GetName()); + fprintf(write, " return -1;\n"); + fprintf(write, "}\n"); + fprintf(write, "\n"); + } + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + fprintf(write, "int %s::%s(phxrpc::OptMap &/* opt_map */) {\n", clasname, fit->GetName()); + fprintf(write, " printf(\"\\n *** %s unimplement ***\\n\");\n\n", fit->GetName()); fprintf(write, " return -1;\n"); fprintf(write, "}\n"); fprintf(write, "\n"); } - fprintf(write, "\n"); } -void ToolCodeRender::GenerateToolImplHpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ToolCodeRender::GenerateToolImplHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetToolImplFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.h\n", filename); @@ -180,38 +212,48 @@ void ToolCodeRender::GenerateToolImplHpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); - fprintf(write, "#include \n"); + char toolfile[128]{0}; + name_render_.GetToolFileName(stree->GetName(), toolfile, sizeof(toolfile)); - fprintf(write, "\n"); + fprintf(write, "#include \"%s.h\"\n", toolfile); - char toolfile[128] = { 0 }; - name_render_.GetToolFileName(stree->GetName(), toolfile, sizeof(toolfile)); + fprintf(write, "\n"); - fprintf(write, "#include \"%s.h\"", toolfile); + fprintf(write, "#include \n"); + fprintf(write, "\n"); fprintf(write, "\n"); fprintf(write, "namespace phxrpc {\n"); - fprintf(write, " class OptMap;\n"); + fprintf(write, "\n"); + fprintf(write, "\n"); + fprintf(write, "class OptMap;\n"); + fprintf(write, "\n"); + fprintf(write, "\n"); fprintf(write, "}\n"); + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetToolClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "class %sImpl : public %s\n", clasname, clasname); - fprintf(write, "{\n"); - fprintf(write, "public:\n"); + fprintf(write, "class %sImpl : public %s {\n", clasname, clasname); + fprintf(write, " public:\n"); fprintf(write, " %sImpl();\n", clasname); fprintf(write, " virtual ~%sImpl();\n", clasname); fprintf(write, "\n"); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { - fprintf(write, " virtual int %s( phxrpc::OptMap & opt_map );\n", fit->GetName()); - fprintf(write, "\n"); + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + fprintf(write, " virtual int %s(phxrpc::OptMap &opt_map) override;\n", mqtt_it->GetName()); + } + fprintf(write, "\n"); + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { + fprintf(write, " virtual int %s(phxrpc::OptMap &opt_map) override;\n", fit->GetName()); } fprintf(write, "};\n"); @@ -219,11 +261,13 @@ void ToolCodeRender::GenerateToolImplHpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); } -void ToolCodeRender::GenerateToolImplCpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ToolCodeRender::GenerateToolImplCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { + char filename[128]{0}; name_render_.GetToolImplFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.cpp\n", filename); @@ -232,6 +276,7 @@ void ToolCodeRender::GenerateToolImplCpp(SyntaxTree * stree, FILE * write) { fprintf(write, "\n"); fprintf(write, "#include \"%s.h\"\n", filename); + fprintf(write, "\n"); name_render_.GetClientFileName(stree->GetName(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); @@ -239,50 +284,88 @@ void ToolCodeRender::GenerateToolImplCpp(SyntaxTree * stree, FILE * write) { fprintf(write, "#include \"phxrpc/file.h\"\n"); fprintf(write, "\n"); + fprintf(write, "\n"); + fprintf(write, "using namespace phxrpc;\n"); + + fprintf(write, "\n"); fprintf(write, "\n"); - char clasname[128] = { 0 }; + char clasname[128]{0}; name_render_.GetToolImplClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "%s:: %s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - fprintf(write, "%s:: ~%s()\n", clasname, clasname); - fprintf(write, "{\n"); + fprintf(write, "%s::~%s() {\n", clasname, clasname); fprintf(write, "}\n"); fprintf(write, "\n"); - char client_class[128] = { 0 }, req_class[128] = { 0 }, resp_class[128] = { 0 }; + char client_class[128]{0}, req_class[128]{0}, resp_class[128]{0}; name_render_.GetClientClasname(stree->GetName(), client_class, sizeof(client_class)); - SyntaxFuncVector * flist = stree->GetFuncList(); - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + name_render_.GetMessageClasname(mqtt_it->GetReq()->GetType(), req_class, sizeof(req_class)); + const char *const resp_type{mqtt_it->GetResp()->GetType()}; + if (resp_type && 0 < strlen(resp_type)) { + name_render_.GetMessageClasname(mqtt_it->GetResp()->GetType(), resp_class, sizeof(resp_class)); + } + + fprintf(write, "int %s::%s(phxrpc::OptMap &opt_map) {\n", clasname, mqtt_it->GetName()); + fprintf(write, " %s req;\n", req_class); + if (resp_type && 0 < strlen(resp_type)) { + fprintf(write, " %s resp;\n", resp_class); + } + fprintf(write, "\n"); + + if (0 == strcmp("PhxMqttPublish", mqtt_it->GetName())) { + fprintf(write, " if (nullptr == opt_map.Get('s')) return -1;\n\n"); + fprintf(write, " req.set_content(opt_map.Get('s'));\n"); + } + + fprintf(write, "\n"); + fprintf(write, " %s client;\n", client_class); + if (resp_type && 0 < strlen(resp_type)) { + fprintf(write, " int ret{client.%s(req, &resp)};\n", mqtt_it->GetName()); + } else { + fprintf(write, " int ret{client.%s(req)};\n", mqtt_it->GetName()); + } + fprintf(write, " printf(\"%%s return %%d\\n\", __func__, ret);\n"); + if (resp_type && 0 < strlen(resp_type)) { + fprintf(write, " printf(\"resp: {\\n%%s}\\n\", resp.DebugString().c_str());\n"); + } + fprintf(write, "\n"); + fprintf(write, " return ret;\n"); + fprintf(write, "}\n"); + fprintf(write, "\n"); + } + fprintf(write, "\n"); + + SyntaxFuncVector *flist{stree->GetFuncList()}; + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { name_render_.GetMessageClasname(fit->GetReq()->GetType(), req_class, sizeof(req_class)); name_render_.GetMessageClasname(fit->GetResp()->GetType(), resp_class, sizeof(resp_class)); - fprintf(write, "int %s :: %s( phxrpc::OptMap & opt_map )\n", clasname, fit->GetName()); - fprintf(write, "{\n"); + fprintf(write, "int %s::%s(phxrpc::OptMap &opt_map) {\n", clasname, fit->GetName()); fprintf(write, " %s req;\n", req_class); fprintf(write, " %s resp;\n", resp_class); fprintf(write, "\n"); - if (0 == strcmp("PHXEcho", fit->GetName())) { - fprintf(write, " if( NULL == opt_map.Get( 's' ) ) return -1;\n\n"); - fprintf(write, " req.set_value( opt_map.Get( 's' ) );\n"); + if (0 == strcmp("PhxEcho", fit->GetName())) { + fprintf(write, " if (nullptr == opt_map.Get('s')) return -1;\n\n"); + fprintf(write, " req.set_value(opt_map.Get('s'));\n"); } else { - fprintf(write, " //TODO: fill req from opt_map\n"); - fprintf(write, "\n"); + fprintf(write, " // TODO: fill req from opt_map\n"); } fprintf(write, "\n"); fprintf(write, " %s client;\n", client_class); - fprintf(write, " int ret = client.%s( req, &resp );\n", fit->GetName()); - fprintf(write, " printf( \"%%s return %%d\\n\", __func__, ret );\n"); - fprintf(write, " printf( \"resp: {\\n%%s}\\n\", resp.DebugString().c_str() );\n"); + fprintf(write, " int ret{client.%s(req, &resp)};\n", fit->GetName()); + fprintf(write, " printf(\"%%s return %%d\\n\", __func__, ret);\n"); + fprintf(write, " printf(\"resp: {\\n%%s}\\n\", resp.DebugString().c_str());\n"); fprintf(write, "\n"); fprintf(write, " return ret;\n"); fprintf(write, "}\n"); @@ -290,11 +373,11 @@ void ToolCodeRender::GenerateToolImplCpp(SyntaxTree * stree, FILE * write) { } } -void ToolCodeRender::GenerateToolMainCpp(SyntaxTree * stree, FILE * write) { - char filename[128] = { 0 }; +void ToolCodeRender::GenerateToolMainCpp(SyntaxTree *stree, FILE *write) { + char filename[128]{0}; name_render_.GetToolMainFileName(stree->GetName(), filename, sizeof(filename)); - std::string buffer; + string buffer; name_render_.GetCopyright("phxrpc_pb2tool", stree->GetProtoFile(), &buffer, false); fprintf(write, "/* %s.cpp\n", filename); @@ -302,9 +385,9 @@ void ToolCodeRender::GenerateToolMainCpp(SyntaxTree * stree, FILE * write) { fprintf(write, "*/\n"); fprintf(write, "\n"); - char tool_class[128] = { 0 }, tool_file[128] = { 0 }; - char tool_impl_class[128] = { 0 }, tool_impl_file[128] = { 0 }; - char client_class[128] = { 0 }, client_file[128] = { 0 }; + char tool_class[128]{0}, tool_file[128]{0}; + char tool_impl_class[128]{0}, tool_impl_file[128]{0}; + char client_class[128]{0}, client_file[128]{0}; name_render_.GetToolClasname(stree->GetName(), tool_class, sizeof(tool_class)); name_render_.GetToolFileName(stree->GetName(), tool_file, sizeof(tool_file)); @@ -313,7 +396,7 @@ void ToolCodeRender::GenerateToolMainCpp(SyntaxTree * stree, FILE * write) { name_render_.GetClientClasname(stree->GetName(), client_class, sizeof(client_class)); name_render_.GetClientFileName(stree->GetName(), client_file, sizeof(client_file)); - std::string content(PHXRPC_TOOL_MAIN_TEMPLATE); + string content(PHXRPC_TOOL_MAIN_TEMPLATE); StrTrim(&content); StrReplaceAll(&content, "$ClientFile$", client_file); StrReplaceAll(&content, "$ClientClass$", client_class); @@ -325,5 +408,6 @@ void ToolCodeRender::GenerateToolMainCpp(SyntaxTree * stree, FILE * write) { fprintf(write, "%s", content.c_str()); fprintf(write, "\n"); + fprintf(write, "\n"); } diff --git a/codegen/tool_code_render.h b/codegen/tool_code_render.h index 94286ab..9c6cfb9 100755 --- a/codegen/tool_code_render.h +++ b/codegen/tool_code_render.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,31 +21,45 @@ See the AUTHORS file for names of contributors. #pragma once -#include +#include +#include + namespace phxrpc { + class NameRender; class SyntaxTree; +class SyntaxFunc; +typedef std::vector SyntaxFuncVector; class ToolCodeRender { - public: - ToolCodeRender(NameRender & name_render); - ~ToolCodeRender(); + public: + ToolCodeRender(NameRender &name_render); + virtual ~ToolCodeRender(); - void GenerateToolHpp(SyntaxTree * stree, FILE * write); + void GenerateToolHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); - void GenerateToolCpp(SyntaxTree * stree, FILE * write); + void GenerateToolCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); - void GenerateToolImplHpp(SyntaxTree * stree, FILE * write); + void GenerateToolImplHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); - void GenerateToolImplCpp(SyntaxTree * stree, FILE * write); + void GenerateToolImplCpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); - void GenerateToolMainCpp(SyntaxTree * stree, FILE * write); + void GenerateToolMainCpp(SyntaxTree *stree, FILE *write); - private: - NameRender & name_render_; + private: + NameRender &name_render_; }; + } diff --git a/codegen/tool_template.cpp b/codegen/tool_template.cpp index 28320d9..9eacfa9 100644 --- a/codegen/tool_template.cpp +++ b/codegen/tool_template.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -22,10 +22,10 @@ See the AUTHORS file for names of contributors. const char * PHXRPC_TOOL_MAIN_TEMPLATE = R"( -#include +#include +#include +#include #include -#include -#include #include "$ToolFile$.h" #include "$ToolImplFile$.h" @@ -34,72 +34,72 @@ const char * PHXRPC_TOOL_MAIN_TEMPLATE = #include "phxrpc/file.h" + using namespace phxrpc; -void showUsage( const char * program ) -{ - printf( "\nUsage: %s [-c ] [-f ] [-v]\n", program ); - $ToolClass$::Name2Func_t * name2func = $ToolClass$::GetName2Func(); +void ShowUsage(const char *program) { + printf("\nUsage: %s [-c ] [-f ] [-v]\n", program); + + $ToolClass$::Name2Func_t *name2func = $ToolClass$::GetName2Func(); - for( int i = 0; ; i++ ) { - $ToolClass$::Name2Func_t * iter = &( name2func[i] ); + for (int i{0}; ; ++i) { + $ToolClass$::Name2Func_t *iter = &(name2func[i]); - if( NULL == iter->name ) break; + if (nullptr == iter->name) break; - printf( " -f %s %s\n", iter->name, iter->usage ); + printf(" -f %s %s\n", iter->name, iter->usage); } - printf( "\n" ); - exit( 0 ); + printf("\n"); + exit(0); } -int main( int argc, char * argv[] ) -{ - const char * func = NULL; - const char * config = NULL; +int main(int argc, char **argv) { + const char *func{nullptr}; + const char *config{nullptr}; - for( int i = 1; i < argc - 1; i++ ) { - if( 0 == strcmp( argv[i], "-c" ) ) { - config = argv[ ++i ]; + for (int i{1}; argc - 1 > i; ++i) { + if (0 == strcmp(argv[i], "-c")) { + config = argv[++i]; } - if( 0 == strcmp( argv[i], "-f" ) ) { - func = argv[ ++i ]; + if (0 == strcmp(argv[i], "-f")) { + func = argv[++i]; } - if( 0 == strcmp( argv[i], "-v" ) ) { - showUsage( argv[0] ); + if (0 == strcmp(argv[i], "-v")) { + ShowUsage(argv[0]); } } - if( NULL == func ) showUsage( argv[0] ); + if (nullptr == func) ShowUsage(argv[0]); - if( NULL != config ) $ClientClass$::Init( config ); + if (nullptr != config) $ClientClass$::Init(config); - $ToolClass$::Name2Func_t * target = NULL; + $ToolClass$::Name2Func_t *target{nullptr}; - $ToolClass$::Name2Func_t * name2func = $ToolClass$::GetName2Func(); + $ToolClass$::Name2Func_t *name2func{$ToolClass$::GetName2Func()}; - for( int i = 0; i < 100; i++ ) { - $ToolClass$::Name2Func_t * iter = &( name2func[i] ); + for (int i{0}; 100 > i; ++i) { + $ToolClass$::Name2Func_t *iter = &(name2func[i]); - if( NULL == iter->name ) break; + if (nullptr == iter->name) break; - if( 0 == strcasecmp( func, iter->name ) ) { + if (0 == strcasecmp(func, iter->name)) { target = iter; break; } } - if( NULL == target ) showUsage( argv[0] ); + if (nullptr == target) ShowUsage(argv[0]); - OptMap opt_map( target->opt_string ); + OptMap opt_map(target->opt_string); - if( ! opt_map.Parse( argc, argv ) ) showUsage( argv[0] ); + if (!opt_map.Parse(argc, argv)) ShowUsage(argv[0]); $ToolClass$::ToolFunc_t targefunc = target->func; $ToolImplClass$ tool; - if( 0 != ( tool.*targefunc ) ( opt_map ) ) showUsage( argv[0] ); + if (0 != (tool.*targefunc)(opt_map)) ShowUsage(argv[0]); return 0; } diff --git a/phxrpc.mk b/phxrpc.mk index cee1ab1..43f3039 100644 --- a/phxrpc.mk +++ b/phxrpc.mk @@ -1,22 +1,24 @@ #-------------------------------------------------------------------- -where-am-i = $(abspath $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) +#debug = y + +where-am-i = $(abspath $(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST))) #$(warning $(dir $(call where-am-i))) -PHXRPC_ROOT=$(dir $(call where-am-i)) +PHXRPC_ROOT = $(dir $(call where-am-i)) OS := $(shell uname) -PROTOBUF_ROOT=$(PHXRPC_ROOT)/third_party/protobuf -BOOST_ROOT=$(PHXRPC_ROOT)/third_party/boost +PROTOBUF_ROOT = $(PHXRPC_ROOT)/third_party/protobuf +BOOST_ROOT = $(PHXRPC_ROOT)/third_party/boost PLUGIN_BOOST_LDFLAGS = -Wl,--whole-archive -L$(PHXRPC_ROOT)/lib/ -lphxrpc_plugin_boost \ -Wl,--no-whole-archive -L$(BOOST_ROOT)/lib/ -lboost_context #-------------------------------------------------------------------- -ifeq ($(debug),y) +ifeq ($(debug), y) # (1) Debug OPT = -g2 else @@ -33,11 +35,11 @@ LINT = lint -c RM = /bin/rm -f CFLAGS = -std=c++11 -Wall -D_REENTRANT -D_GNU_SOURCE -D_XOPEN_SOURCE -fPIC -m64 $(OPT) \ - -I$(PROTOBUF_ROOT)/include \ - -I$(PHXRPC_ROOT) \ + -I$(PROTOBUF_ROOT)/include \ + -I$(PHXRPC_ROOT) \ LDFLAGS = -L$(PROTOBUF_ROOT)/lib/ $(PROTOBUF_ROOT)/lib/libprotobuf.a \ - -lstdc++ -lpthread -lm + -lstdc++ -lpthread -lm PBFLAGS = -I $(PROTOBUF_ROOT)/include -I $(PHXRPC_ROOT) @@ -45,10 +47,11 @@ PBFLAGS = -I $(PROTOBUF_ROOT)/include -I $(PHXRPC_ROOT) # make rule %.o : %.c - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -c $< -o $@ %.o : %.cc - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -c $< -o $@ %.o : %.cpp - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -c $< -o $@ + diff --git a/phxrpc/Makefile b/phxrpc/Makefile index 7185e22..c916b66 100644 --- a/phxrpc/Makefile +++ b/phxrpc/Makefile @@ -1,25 +1,32 @@ - include ../phxrpc.mk -LIB_HTTP_OBJS = http/http_client.o http/http_client.o http/http_msg.o http/http_proto.o +LIB_HTTP_OBJS = http/http_client.o http/http_msg.o http/http_protocol.o + +LIB_MQTT_OBJS = mqtt/mqtt_client.o mqtt/mqtt_msg.o mqtt/mqtt_protocol.o -LIB_NETWORK_OBJS = network/socket_stream_base.o network/uthread_runtime.o network/uthread_epoll.o \ - network/socket_stream_block.o network/socket_stream_uthread.o \ - network/uthread_context_util.o network/uthread_context_base.o \ - network/uthread_context_system.o network/timer.o +LIB_NETWORK_OBJS = network/socket_stream_base.o network/uthread_runtime.o \ + network/uthread_epoll.o network/socket_stream_block.o \ + network/socket_stream_uthread.o network/uthread_context_util.o \ + network/uthread_context_base.o network/uthread_context_system.o \ + network/timer.o LIB_FILE_OBJS = file/log_utils.o file/file_utils.o file/opt_map.o file/config.o -LIB_RPC_OBJS = rpc/phxrpc.pb.o rpc/http_caller.o rpc/server_config.o rpc/client_config.o \ - rpc/socket_stream_phxrpc.o rpc/uthread_caller.o rpc/client_monitor.o rpc/server_monitor.o \ - rpc/monitor_factory.o rpc/hsha_server.o rpc/server_base.o +LIB_RPC_OBJS = rpc/phxrpc.pb.o rpc/http_caller.o rpc/mqtt_caller.o \ + rpc/server_config.o rpc/client_config.o rpc/socket_stream_phxrpc.o \ + rpc/uthread_caller.o rpc/client_monitor.o rpc/server_monitor.o \ + rpc/monitor_factory.o rpc/hsha_server.o rpc/server_base.o + +LIB_MSG_OBJS = msg/base_msg.o msg/base_protocol.o msg/protocol_factory.o + ifeq ($(OS),Darwin) CFLAGS += -I$(PHXRPC_ROOT)/plugin_darwin/network LIB_NETWORK_OBJS += ../plugin_darwin/network/epoll-darwin.o endif -LIB_OBJS = $(LIB_RPC_OBJS) $(LIB_HTTP_OBJS) $(LIB_NETWORK_OBJS) $(LIB_FILE_OBJS) \ +LIB_OBJS = $(LIB_RPC_OBJS) $(LIB_MSG_OBJS) $(LIB_HTTP_OBJS) $(LIB_MQTT_OBJS) \ + $(LIB_NETWORK_OBJS) $(LIB_FILE_OBJS) TARGETS = libphxrpc.a @@ -38,3 +45,4 @@ clean: @( $(RM) $(TARGETS) $(TEST_TARGETS) ) @( $(RM) *.o core.* $(LIB_OBJS) ) @( cd rpc; $(RM) *.pb.* ) + diff --git a/phxrpc/file/log_utils.cpp b/phxrpc/file/log_utils.cpp index ef01a2e..9195980 100644 --- a/phxrpc/file/log_utils.cpp +++ b/phxrpc/file/log_utils.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,18 +21,19 @@ See the AUTHORS file for names of contributors. #include "log_utils.h" -#include -#include -#include +#include +#include + namespace phxrpc { + static openlog_t global_openlog_ = NULL; static closelog_t global_closelog_ = ::closelog; static vlog_t global_vlog_ = vsyslog; static int global_priority_ = LOG_ERR; -void openlog(const char * argv0, const char * log_dir, int priority) { +void openlog(const char *argv0, const char *log_dir, int priority) { char new_path[ 1024 ] = { 0 }; if( '~' == log_dir[0] ) { @@ -45,7 +46,7 @@ void openlog(const char * argv0, const char * log_dir, int priority) { if( NULL != global_openlog_ ) { global_openlog_( argv0, new_path, priority ); } else { - ::openlog( argv0, LOG_CONS | LOG_PID, priority ); + ::openlog( argv0, LOG_CONS | LOG_PID, 0 ); } } @@ -53,7 +54,7 @@ void closelog() { global_closelog_(); } -void log(int priority, const char * format, ...) { +void log(int priority, const char *format, ...) { if( priority > global_priority_ ) return; @@ -73,6 +74,6 @@ void setlog(openlog_t open_log, closelog_t close_log, vlog_t vlog) { global_vlog_ = vlog; } -} -; + +} // namespace phxrpc diff --git a/phxrpc/file/log_utils.h b/phxrpc/file/log_utils.h index d4b65a6..2a9ff02 100644 --- a/phxrpc/file/log_utils.h +++ b/phxrpc/file/log_utils.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,23 +21,27 @@ See the AUTHORS file for names of contributors. #pragma once -#include #include +#include + + namespace phxrpc { -extern void openlog( const char * argv0, const char * log_dir, int priority ); + +extern void openlog(const char *argv0, const char *log_dir, int priority); extern void closelog(); -extern void log(int priority, const char * format, ...) __attribute__((format(printf, 2, 3))); +extern void log(int priority, const char *format, ...) __attribute__((format(printf, 2, 3))); -typedef void (*openlog_t)(const char*, const char *, int); +typedef void (*openlog_t)(const char *, const char *, int); typedef void (*closelog_t)(); typedef void (*vlog_t)(int, const char *, va_list); extern void setvlog(vlog_t); extern void setlog(openlog_t, closelog_t, vlog_t); -} -; + + +} // namespace phxrpc diff --git a/phxrpc/http.h b/phxrpc/http.h index f775833..88b8950 100644 --- a/phxrpc/http.h +++ b/phxrpc/http.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -22,6 +22,7 @@ See the AUTHORS file for names of contributors. #pragma once #include "http/http_client.h" +//#include "http/http_dispatcher.h" #include "http/http_msg.h" -#include "http/http_proto.h" -#include "http/http_dispatcher.h" +#include "http/http_protocol.h" + diff --git a/phxrpc/http/Makefile b/phxrpc/http/Makefile index a69be84..b892ce2 100644 --- a/phxrpc/http/Makefile +++ b/phxrpc/http/Makefile @@ -1,4 +1,3 @@ - include ../../phxrpc.mk TEST_TARGETS = test_http_client @@ -11,3 +10,4 @@ test_http_client: test_http_client.o clean: @( $(RM) $(TEST_TARGETS) ) @( $(RM) *.o core.* $(LIB_OBJS) ) + diff --git a/phxrpc/http/http_client.cpp b/phxrpc/http/http_client.cpp index 7cc3ae8..87500db 100644 --- a/phxrpc/http/http_client.cpp +++ b/phxrpc/http/http_client.cpp @@ -1,106 +1,111 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "http_client.h" #include "http_msg.h" -#include "http_proto.h" +#include "http_protocol.h" #include "phxrpc/file/log_utils.h" #include "phxrpc/network/socket_stream_base.h" + namespace phxrpc { -int HttpClient::Get(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp ) { - int socket_ret = HttpProto::SendReqHeader(socket, "GET", req); - if (socket_ret == 0) { - socket_ret = HttpProto::RecvRespStartLine(socket, resp); - if (socket_ret == 0) - socket_ret = HttpProto::RecvHeaders(socket, resp); - if (socket_ret == 0 && SC_NOT_MODIFIED != resp->GetStatusCode()) { - socket_ret = HttpProto::RecvBody(socket, resp); +int HttpClient::Get(BaseTcpStream &socket, const HttpRequest &req, HttpResponse *resp) { + ReturnCode ret{HttpProtocol::SendReqHeader(socket, "GET", req)}; + + if (ReturnCode::OK == ret) { + ret = HttpProtocol::RecvRespStartLine(socket, resp); + if (ReturnCode::OK == ret) + ret = HttpProtocol::RecvHeaders(socket, resp); + if (ReturnCode::OK == ret && SC_NOT_MODIFIED != resp->GetStatusCode()) { + ret = HttpProtocol::RecvBody(socket, resp); } } - return socket_ret; + return static_cast(ret); } -int HttpClient::Post(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp) { +int HttpClient::Post(BaseTcpStream &socket, const HttpRequest &req, HttpResponse *resp) { PostStat stat; - int ret = Post( socket, req, resp, &stat ); - return ret; + int ret{Post(socket, req, resp, &stat)}; + return ret; } -int HttpClient::Post(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp, - PostStat * post_stat ) { - int socket_ret = HttpProto::SendReqHeader(socket, "POST", req); +int HttpClient::Post(BaseTcpStream &socket, const HttpRequest &req, HttpResponse *resp, + PostStat *post_stat) { + ReturnCode ret{HttpProtocol::SendReqHeader(socket, "POST", req)}; - if (socket_ret == 0) { + if (ReturnCode::OK == ret) { socket << req.GetContent(); - socket_ret = socket.flush().good() ? 0 : socket.LastError(); + if(!socket.flush().good()) + ret = static_cast(socket.LastError()); } else { - if (socket_ret != SocketStreamError_Normal_Closed) { + if (ReturnCode::ERROR_SOCKET_STREAM_NORMAL_CLOSED != ret) { post_stat->send_error_ = true; phxrpc::log(LOG_ERR, "ERR: sendReqHeader fail"); } - return socket_ret; + return static_cast(ret); } - if (socket_ret == 0) { - socket_ret = HttpProto::RecvRespStartLine(socket, resp); - if (socket_ret == 0) - socket_ret = HttpProto::RecvHeaders(socket, resp); + if (ReturnCode::OK == ret) { + ret = HttpProtocol::RecvRespStartLine(socket, resp); + if (ReturnCode::OK == ret) + ret = HttpProtocol::RecvHeaders(socket, resp); - if (socket_ret == 0 && SC_NOT_MODIFIED != resp->GetStatusCode()) { - socket_ret = HttpProto::RecvBody(socket, resp); + if (ReturnCode::OK == ret && SC_NOT_MODIFIED != resp->GetStatusCode()) { + ret = HttpProtocol::RecvBody(socket, resp); } - if (socket_ret != 0 && socket_ret != SocketStreamError_Normal_Closed) { + if (ReturnCode::OK != ret && ReturnCode::ERROR_SOCKET_STREAM_NORMAL_CLOSED != ret) { post_stat->recv_error_ = true; } } else { - if (socket_ret != SocketStreamError_Normal_Closed) { + if (ReturnCode::ERROR_SOCKET_STREAM_NORMAL_CLOSED != ret) { post_stat->send_error_ = true; phxrpc::log(LOG_ERR, "ERR: sendReqBody fail"); } } - return socket_ret; + return static_cast(ret); } -int HttpClient::Head(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp) { - int socket_ret = HttpProto::SendReqHeader(socket, "HEAD", req); +int HttpClient::Head(BaseTcpStream & socket, const HttpRequest &req, HttpResponse *resp) { + ReturnCode ret{HttpProtocol::SendReqHeader(socket, "HEAD", req)}; - if (socket_ret == 0) - socket_ret = HttpProto::RecvRespStartLine(socket, resp); + if (ReturnCode::OK == ret) + ret = HttpProtocol::RecvRespStartLine(socket, resp); - if (socket_ret == 0) - socket_ret = HttpProto::RecvHeaders(socket, resp); + if (ReturnCode::OK == ret) + ret = HttpProtocol::RecvHeaders(socket, resp); - return socket_ret; + return static_cast(ret); } -} + +} // namespace phxrpc + diff --git a/phxrpc/http/http_client.h b/phxrpc/http/http_client.h index 26339db..08eb903 100644 --- a/phxrpc/http/http_client.h +++ b/phxrpc/http/http_client.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,46 +21,47 @@ See the AUTHORS file for names of contributors. #pragma once + namespace phxrpc { + class BaseTcpStream; class HttpRequest; class HttpResponse; class ClientMonitor; class HttpClient { - public: - struct PostStat { - bool send_error_; - bool recv_error_; + public: + struct PostStat { + bool send_error_{false}; + bool recv_error_{false}; - PostStat(): send_error_(false), recv_error_(false) { - } + PostStat() = default; - PostStat( bool send_error, bool recv_error ) : - send_error_(send_error), recv_error_(recv_error) { - } - }; + PostStat(bool send_error, bool recv_error) + : send_error_(send_error), recv_error_(recv_error) { + } + }; - public: enum { SC_NOT_MODIFIED = 304 }; // @return true : socket ok, false : socket error - static int Get(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp); + static int Get(BaseTcpStream &socket, const HttpRequest &req, HttpResponse *resp); // @return true : socket ok, false : socket error - static int Post(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp, - PostStat * post_stat ); - static int Post(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp); + static int Post(BaseTcpStream &socket, const HttpRequest &req, HttpResponse *resp, + PostStat *post_stat); + static int Post(BaseTcpStream &socket, const HttpRequest &req, HttpResponse *resp); // @return true : socket ok, false : socket error - static int Head(BaseTcpStream & socket, const HttpRequest & req, HttpResponse * resp); + static int Head(BaseTcpStream &socket, const HttpRequest &req, HttpResponse *resp); - private: + private: HttpClient(); }; -} + +} // namespace phxrpc diff --git a/phxrpc/http/http_dispatcher.h b/phxrpc/http/http_dispatcher.h index 8698015..a840fa3 100644 --- a/phxrpc/http/http_dispatcher.h +++ b/phxrpc/http/http_dispatcher.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -26,25 +26,26 @@ See the AUTHORS file for names of contributors. #include "http_msg.h" + namespace phxrpc { + template class HttpDispatcher { - public: - typedef int (Dispatcher::*URIFunc_t)(const HttpRequest & request, HttpResponse * response); + public: + typedef int (Dispatcher::*URIFunc_t)(const HttpRequest &request, HttpResponse *response); typedef std::map URIFuncMap; - public: - HttpDispatcher(Dispatcher & dispatcher, const URIFuncMap & uri_func_map) + HttpDispatcher(Dispatcher &dispatcher, const URIFuncMap &uri_func_map) : dispatcher_(dispatcher), uri_func_map_(uri_func_map) { } - ~HttpDispatcher() { + virtual ~HttpDispatcher() { } - bool Dispatch(const HttpRequest & request, HttpResponse * response) { + bool Dispatch(const HttpRequest &request, HttpResponse *response) { int ret = -1; typename URIFuncMap::const_iterator iter = uri_func_map_.find(request.GetURI()); @@ -58,10 +59,11 @@ class HttpDispatcher { return uri_func_map_.end() != iter;; } - private: - Dispatcher & dispatcher_; - const URIFuncMap & uri_func_map_; + private: + Dispatcher &dispatcher_; + const URIFuncMap &uri_func_map_; }; -} + +} // namespace phxrpc diff --git a/phxrpc/http/http_msg.cpp b/phxrpc/http/http_msg.cpp index 518e874..75cc9c7 100644 --- a/phxrpc/http/http_msg.cpp +++ b/phxrpc/http/http_msg.cpp @@ -1,103 +1,101 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include +#include +#include +#include + +#include "phxrpc/rpc/phxrpc.pb.h" #include "http_msg.h" +#include "http_protocol.h" -namespace phxrpc { -const char * HttpMessage::HEADER_CONTENT_LENGTH = "Content-Length"; -const char * HttpMessage::HEADER_CONTENT_TYPE = "Content-Type"; -const char * HttpMessage::HEADER_CONNECTION = "Connection"; -const char * HttpMessage::HEADER_PROXY_CONNECTION = "Proxy-Connection"; -const char * HttpMessage::HEADER_TRANSFER_ENCODING = "Transfer-Encoding"; -const char * HttpMessage::HEADER_DATE = "Date"; -const char * HttpMessage::HEADER_SERVER = "Server"; +namespace phxrpc { -const char * HttpMessage::HEADER_X_PHXRPC_RESULT = "X-PHXRPC-Result"; -HttpMessage::HttpMessage(int type) - : type_(type) { - snprintf(version_, sizeof(version_), "%s", "HTTP/1.0"); -} +using namespace std; -HttpMessage::~HttpMessage() { -} -int HttpMessage::GetType() const { - return type_; -} +const char *HttpMessage::HEADER_CONTENT_LENGTH = "Content-Length"; +const char *HttpMessage::HEADER_CONTENT_TYPE = "Content-Type"; +const char *HttpMessage::HEADER_CONNECTION = "Connection"; +const char *HttpMessage::HEADER_PROXY_CONNECTION = "Proxy-Connection"; +const char *HttpMessage::HEADER_TRANSFER_ENCODING = "Transfer-Encoding"; +const char *HttpMessage::HEADER_DATE = "Date"; +const char *HttpMessage::HEADER_SERVER = "Server"; -void HttpMessage::SetVersion(const char * version) { - snprintf(version_, sizeof(version_), "%s", version); -} +const char *HttpMessage::HEADER_X_PHXRPC_RESULT = "X-PHXRPC-Result"; -const char * HttpMessage::GetVersion() const { - return version_; +/* +HttpMessage::HttpMessage(int type) + : BaseMessage(type, BaseMessage::Protocol::HTTP) { + SetVersion("HTTP/1.0"); } +*/ -void HttpMessage::AppendContent(const void * content, int length, int max_length) { - if (length <= 0) - length = strlen((char*) content); +ReturnCode HttpMessage::ToPb(google::protobuf::Message *const message) const { + google::protobuf::StringValue string_value; - int total = content_.size() + length; - total = total > max_length ? total : max_length; + string_value.set_value(GetContent()); - //content_.reserve(total); + try { + message->CopyFrom(string_value); + } catch (exception) { + return ReturnCode::ERROR; + } - content_.append((char*) content, length); + return ReturnCode::OK; } -void HttpMessage::SetContent(const void * content, int length) { - content_.clear(); - content_.append((char*) content, length); -} +ReturnCode HttpMessage::FromPb(const google::protobuf::Message &message) { + google::protobuf::StringValue string_value; -const std::string & HttpMessage::GetContent() const { - return content_; -} + try { + string_value.CopyFrom(message); + } catch (exception) { + return ReturnCode::ERROR; + } + + SetContent(string_value.value().data(), string_value.value().length()); -std::string & HttpMessage::GetContent() { - return content_; + return ReturnCode::OK; } -void HttpMessage::AddHeader(const char * name, const char * value) { +void HttpMessage::AddHeader(const char *name, const char *value) { header_name_list_.push_back(name); header_value_list_.push_back(value); } -void HttpMessage::AddHeader(const char * name, int value) { - char tmp[32] = { 0 }; +void HttpMessage::AddHeader(const char *name, int value) { + char tmp[32]{0}; snprintf(tmp, sizeof(tmp), "%d", value); AddHeader(name, tmp); } -bool HttpMessage::RemoveHeader(const char * name) { - bool ret = false; +bool HttpMessage::RemoveHeader(const char *name) { + bool ret{false}; - for (size_t i = 0; i < header_name_list_.size() && false == ret; i++) { + for (size_t i{0}; header_name_list_.size() > i && false == ret; ++i) { if (0 == strcasecmp(name, header_name_list_[i].c_str())) { header_name_list_.erase(header_name_list_.begin() + i); header_value_list_.erase(header_value_list_.begin() + i); @@ -112,18 +110,18 @@ size_t HttpMessage::GetHeaderCount() const { return header_name_list_.size(); } -const char * HttpMessage::GetHeaderName(size_t index) const { - return index < header_name_list_.size() ? header_name_list_[index].c_str() : NULL; +const char *HttpMessage::GetHeaderName(size_t index) const { + return index < header_name_list_.size() ? header_name_list_[index].c_str() : nullptr; } -const char * HttpMessage::GetHeaderValue(size_t index) const { - return index < header_value_list_.size() ? header_value_list_[index].c_str() : NULL; +const char *HttpMessage::GetHeaderValue(size_t index) const { + return index < header_value_list_.size() ? header_value_list_[index].c_str() : nullptr; } -const char * HttpMessage::GetHeaderValue(const char * name) const { - const char * value = NULL; +const char *HttpMessage::GetHeaderValue(const char *name) const { + const char *value{nullptr}; - for (size_t i = 0; i < header_name_list_.size() && NULL == value; i++) { + for (size_t i{0}; i < header_name_list_.size() && nullptr == value; i++) { if (0 == strcasecmp(name, header_name_list_[i].c_str())) { value = header_value_list_[i].c_str(); } @@ -132,22 +130,13 @@ const char * HttpMessage::GetHeaderValue(const char * name) const { return value; } -int HttpMessage::IsKeepAlive() const { - const char * proxy = GetHeaderValue(HEADER_PROXY_CONNECTION); - const char * local = GetHeaderValue(HEADER_CONNECTION); - if ((NULL != proxy && 0 == strcasecmp(proxy, "Keep-Alive")) - || (NULL != local && 0 == strcasecmp(local, "Keep-Alive"))) { - return 1; - } - - return 0; -} //--------------------------------------------------------- HttpRequest::HttpRequest() - : HttpMessage(eRequest) { + : HttpMessage(), BaseRequest(Protocol::HTTP_POST) { + SetVersion("HTTP/1.0"); memset(method_, 0, sizeof(method_)); memset(client_ip_, 0, sizeof(client_ip_)); } @@ -155,49 +144,29 @@ HttpRequest::HttpRequest() HttpRequest::~HttpRequest() { } -void HttpRequest::SetMethod(const char * method) { - if (method != nullptr) { +void HttpRequest::SetMethod(const char *method) { + if (nullptr != method) { snprintf(method_, sizeof(method_), "%s", method); } } -const char * HttpRequest::GetMethod() const { +const char *HttpRequest::GetMethod() const { return method_; } -int HttpRequest::IsMethod(const char * method) const { +int HttpRequest::IsMethod(const char *method) const { return 0 == strcasecmp(method, method_); } -void HttpRequest::SetURI(const char * uri) { - if (uri != nullptr) { - uri_ = std::string(uri); - } -} - -const char * HttpRequest::GetURI() const { - return uri_.c_str(); -} - -void HttpRequest::SetClientIP(const char * client_ip) { - if (client_ip != nullptr) { - snprintf(client_ip_, sizeof(client_ip_), "%s", client_ip); - } -} - -const char * HttpRequest::GetClientIP() const { - return client_ip_; -} - -void HttpRequest::AddParam(const char * name, const char * value) { +void HttpRequest::AddParam(const char *name, const char *value) { param_name_list_.push_back(name); param_value_list_.push_back(value); } -bool HttpRequest::RemoveParam(const char * name) { - bool ret = false; +bool HttpRequest::RemoveParam(const char *name) { + bool ret{false}; - for (size_t i = 0; i < param_name_list_.size() && false == ret; i++) { + for (size_t i{0}; param_name_list_.size() > i && false == ret; ++i) { if (0 == strcasecmp(name, param_name_list_[i].c_str())) { param_name_list_.erase(param_name_list_.begin() + i); param_value_list_.erase(param_value_list_.begin() + i); @@ -212,18 +181,18 @@ size_t HttpRequest::GetParamCount() const { return param_name_list_.size(); } -const char * HttpRequest::GetParamName(size_t index) const { - return index < param_name_list_.size() ? param_name_list_[index].c_str() : NULL; +const char *HttpRequest::GetParamName(size_t index) const { + return index < param_name_list_.size() ? param_name_list_[index].c_str() : nullptr; } -const char * HttpRequest::GetParamValue(size_t index) const { - return index < param_value_list_.size() ? param_value_list_[index].c_str() : NULL; +const char *HttpRequest::GetParamValue(size_t index) const { + return index < param_value_list_.size() ? param_value_list_[index].c_str() : nullptr; } -const char * HttpRequest::GetParamValue(const char * name) const { - const char * value = NULL; +const char *HttpRequest::GetParamValue(const char *name) const { + const char *value{nullptr}; - for (size_t i = 0; i < param_name_list_.size() && NULL == value; i++) { + for (size_t i{0}; param_name_list_.size() > i && nullptr == value; ++i) { if (0 == strcasecmp(name, param_name_list_[i].c_str())) { value = param_value_list_[i].c_str(); } @@ -232,10 +201,29 @@ const char * HttpRequest::GetParamValue(const char * name) const { return value; } +BaseResponse *HttpRequest::GenResponse() const { + return new HttpResponse; +} + +int HttpRequest::IsKeepAlive() const { + const char *proxy{GetHeaderValue(HEADER_PROXY_CONNECTION)}; + const char *local{GetHeaderValue(HEADER_CONNECTION)}; + + if ((nullptr != proxy && 0 == strcasecmp(proxy, "Keep-Alive")) + || (nullptr != local && 0 == strcasecmp(local, "Keep-Alive"))) { + return 1; + } + + return 0; +} + + + //--------------------------------------------------------- HttpResponse::HttpResponse() - : HttpMessage(eResponse) { + : HttpMessage(), BaseResponse(Protocol::HTTP_POST) { + SetVersion("HTTP/1.0"); status_code_ = 200; snprintf(reason_phrase_, sizeof(reason_phrase_), "%s", "OK"); } @@ -243,6 +231,46 @@ HttpResponse::HttpResponse() HttpResponse::~HttpResponse() { } +void HttpResponse::SetPhxRpcResult(const int result) { + AddHeader(HttpMessage::HEADER_X_PHXRPC_RESULT, result); +} + +void HttpResponse::DispatchErr() { + SetStatusCode(404); + SetReasonPhrase("Not Found"); +} + +ReturnCode HttpResponse::Send(BaseTcpStream &socket) const { + socket << GetVersion() << " " << GetStatusCode() << " " << GetReasonPhrase() << "\r\n"; + + for (size_t i{0}; GetHeaderCount() > i; ++i) { + socket << GetHeaderName(i) << ": " << GetHeaderValue(i) << "\r\n"; + } + + if (GetContent().size() > 0) { + if (nullptr == GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH)) { + socket << HttpMessage::HEADER_CONTENT_LENGTH << ": " << GetContent().size() << "\r\n"; + } + } + + socket << "\r\n"; + + if (GetContent().size() > 0) + socket << GetContent(); + + if (socket.flush().good()) { + return ReturnCode::OK; + } else { + return static_cast(socket.LastError()); + } +} + +ReturnCode HttpResponse::ModifyResp(const bool keep_alive, const string &version) { + HttpProtocol::FixRespHeaders(keep_alive, version.c_str(), this); + + return ReturnCode::OK; +} + void HttpResponse::SetStatusCode(int status_code) { status_code_ = status_code; } @@ -251,13 +279,14 @@ int HttpResponse::GetStatusCode() const { return status_code_; } -void HttpResponse::SetReasonPhrase(const char * reason_phrase) { +void HttpResponse::SetReasonPhrase(const char *reason_phrase) { snprintf(reason_phrase_, sizeof(reason_phrase_), "%s", reason_phrase); } -const char * HttpResponse::GetReasonPhrase() const { +const char *HttpResponse::GetReasonPhrase() const { return reason_phrase_; } -} + +} // namespace phxrpc diff --git a/phxrpc/http/http_msg.h b/phxrpc/http/http_msg.h index 2575176..247aed7 100644 --- a/phxrpc/http/http_msg.h +++ b/phxrpc/http/http_msg.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -24,102 +24,95 @@ See the AUTHORS file for names of contributors. #include #include +#include "phxrpc/msg.h" + + namespace phxrpc { -class HttpMessage { - public: - static const char * HEADER_CONTENT_LENGTH; - static const char * HEADER_CONTENT_TYPE; - static const char * HEADER_CONNECTION; - static const char * HEADER_PROXY_CONNECTION; - static const char * HEADER_TRANSFER_ENCODING; - static const char * HEADER_DATE; - static const char * HEADER_SERVER; - - static const char * HEADER_X_PHXRPC_RESULT; - - public: - HttpMessage(int type); - virtual ~HttpMessage(); - - enum { - eRequest, - eResponse - }; - int GetType() const; - - void SetVersion(const char * version); - const char * GetVersion() const; - - void AppendContent(const void * content, int length = 0, int max_length = 0); - void SetContent(const void * content, int length = 0); - const std::string & GetContent() const; - std::string & GetContent(); - - void AddHeader(const char * name, const char * value); - void AddHeader(const char * name, int value); - bool RemoveHeader(const char * name); - size_t GetHeaderCount() const; - const char * GetHeaderName(size_t index) const; - const char * GetHeaderValue(size_t index) const; - const char * GetHeaderValue(const char * name) const; - int IsKeepAlive() const; +class HttpMessage : virtual public BaseMessage { + public: + static const char *HEADER_CONTENT_LENGTH; + static const char *HEADER_CONTENT_TYPE; + static const char *HEADER_CONNECTION; + static const char *HEADER_PROXY_CONNECTION; + static const char *HEADER_TRANSFER_ENCODING; + static const char *HEADER_DATE; + static const char *HEADER_SERVER; + + static const char *HEADER_X_PHXRPC_RESULT; + + HttpMessage() = default; + virtual ~HttpMessage() override = default; - protected: - const int type_; + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override; + virtual ReturnCode FromPb(const google::protobuf::Message &message) override; - char version_[16]; - std::string content_; + void AddHeader(const char *name, const char *value); + void AddHeader(const char *name, int value); + bool RemoveHeader(const char *name); + size_t GetHeaderCount() const; + const char *GetHeaderName(size_t index) const; + const char *GetHeaderValue(size_t index) const; + const char *GetHeaderValue(const char *name) const; + protected: std::vector header_name_list_, header_value_list_; }; -class HttpRequest : public HttpMessage { - public: +class HttpRequest : public HttpMessage, public BaseRequest { + public: HttpRequest(); - virtual ~HttpRequest(); + virtual ~HttpRequest() override; - void SetMethod(const char * method); - const char * GetMethod() const; + virtual ReturnCode Send(BaseTcpStream &socket) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } - int IsMethod(const char * method) const; + virtual BaseResponse *GenResponse() const override; + virtual int IsKeepAlive() const override; - void SetURI(const char * uri); - const char * GetURI() const; + void SetMethod(const char *method); + const char *GetMethod() const; - void SetClientIP(const char * client_ip); - const char * GetClientIP() const; + int IsMethod(const char *method) const; - void AddParam(const char * name, const char * value); - bool RemoveParam(const char * name); + void AddParam(const char *name, const char *value); + bool RemoveParam(const char *name); size_t GetParamCount() const; - const char * GetParamName(size_t index) const; - const char * GetParamValue(size_t index) const; - const char * GetParamValue(const char * name) const; + const char *GetParamName(size_t index) const; + const char *GetParamValue(size_t index) const; + const char *GetParamValue(const char *name) const; - private: - char method_[16], client_ip_[16]; - std::string uri_; + private: + char method_[16]; std::vector param_name_list_, param_value_list_; }; -class HttpResponse : public HttpMessage { - public: +class HttpResponse : public HttpMessage, public BaseResponse { + public: HttpResponse(); - virtual ~HttpResponse(); + virtual ~HttpResponse() override; + + virtual ReturnCode Send(BaseTcpStream &socket) const override; + + virtual void SetPhxRpcResult(const int result) override; + virtual void DispatchErr() override; + + virtual ReturnCode ModifyResp(const bool keep_alive, const std::string &version) override; void SetStatusCode(int status_code); int GetStatusCode() const; - void SetReasonPhrase(const char * reason_phrase); - const char * GetReasonPhrase() const; + void SetReasonPhrase(const char *reason_phrase); + const char *GetReasonPhrase() const; - private: + private: int status_code_; char reason_phrase_[128]; }; -} + +} // namespace phxrpc diff --git a/phxrpc/http/http_proto.h b/phxrpc/http/http_proto.h deleted file mode 100644 index d8df4f5..0000000 --- a/phxrpc/http/http_proto.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -Tencent is pleased to support the open source community by making -PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. -All rights reserved. - -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may -obtain a copy of the License at - -https://opensource.org/licenses/BSD-3-Clause - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing -permissions and limitations under the License. - -See the AUTHORS file for names of contributors. -*/ - -#pragma once - -namespace phxrpc { - -class BaseTcpStream; - -class HttpMessage; -class HttpRequest; -class HttpResponse; - -class HttpProto { - public: - enum { - MAX_RECV_LEN = 8192 - }; - - static void URLEncode(const char * source, char * dest, size_t length); - - static char * strsep(char ** s, const char * del); - - // @return 0: socket ok, !=0: socket error - static int SendResp(BaseTcpStream & socket, const HttpResponse & resp); - - // @return 0: socket ok, !=0: socket error - static int SendReqHeader(BaseTcpStream & socket, const char * method, const HttpRequest & req); - - public: - - static void FixRespHeaders(const HttpRequest & req, HttpResponse * resp); - - static void FixRespHeaders(bool is_keep_alive, const char * version, HttpResponse * resp); - - // @return 0: socket ok, !=0: socket error - static int RecvReq(BaseTcpStream & socket, HttpRequest * req); - - // @return 0: socket ok, !=0: socket error - static int RecvRespStartLine(BaseTcpStream & socket, HttpResponse * resp); - - // @return 0: socket ok, !=0: socket error - static int RecvReqStartLine(BaseTcpStream & socket, HttpRequest * req); - - // @return 0: socket ok, !=0: socket error - static int RecvHeaders(BaseTcpStream & socket, HttpMessage * msg); - - // @return 0: socket ok, !=0: socket error - static int RecvBody(BaseTcpStream & socket, HttpMessage * msg); - - private: - HttpProto(); -}; - -} - diff --git a/phxrpc/http/http_proto.cpp b/phxrpc/http/http_protocol.cpp similarity index 58% rename from phxrpc/http/http_proto.cpp rename to phxrpc/http/http_protocol.cpp index c48c4e3..635e0a5 100644 --- a/phxrpc/http/http_proto.cpp +++ b/phxrpc/http/http_protocol.cpp @@ -1,44 +1,49 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include "http_proto.h" +#include "http_protocol.h" #include "http_msg.h" #include "phxrpc/file/log_utils.h" #include "phxrpc/network/socket_stream_base.h" -namespace phxrpc { -char * HttpProto::strsep(char ** s, const char * del) { +namespace { + + +using namespace std; + + +char *SeparateStr(char **s, const char *del) { char *d, *tok; if (!s || !*s) - return NULL; + return nullptr; tok = *s; d = strstr(tok, del); @@ -46,13 +51,13 @@ char * HttpProto::strsep(char ** s, const char * del) { *s = d + strlen(del); *d = '\0'; } else { - *s = NULL; + *s = nullptr; } return tok; } -void HttpProto::URLEncode(const char * source, char * dest, size_t length) { +void URLEncode(const char *source, char *dest, size_t length) { const char urlencstring[] = "0123456789abcdef"; const char *p = source; @@ -82,66 +87,29 @@ void HttpProto::URLEncode(const char * source, char * dest, size_t length) { *q = 0; } -int HttpProto::SendReqHeader(BaseTcpStream & socket, const char * method, const HttpRequest & req) { - std::string url; - - if (req.GetParamCount() > 0) { - url.append(req.GetURI()); - url.append("?"); - - char tmp[1024] = { 0 }; - for (size_t i = 0; i < req.GetParamCount(); i++) { - if (i > 0) - url.append("&"); - URLEncode(req.GetParamName(i), tmp, sizeof(tmp) - 1); - url.append(tmp); - url.append("="); - URLEncode(req.GetParamValue(i), tmp, sizeof(tmp) - 1); - url.append(tmp); - } - } - - socket << method << " " << (url.size() > 0 ? url.c_str() : req.GetURI()) << " " << req.GetVersion() << "\r\n"; - for (size_t i = 0; i < req.GetHeaderCount(); i++) { - const char * name = req.GetHeaderName(i); - const char * val = req.GetHeaderValue(i); +} // namespace - socket << name << ": " << val << "\r\n"; - } - if (req.GetContent().size() > 0) { - if (NULL == req.GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH)) { - socket << HttpMessage::HEADER_CONTENT_LENGTH << ": " << req.GetContent().size() << "\r\n"; - } - } +namespace phxrpc { - socket << "\r\n"; - if (req.GetContent().size() == 0) { - if (socket.flush().good()) { - return 0; - } else { - return socket.LastError(); - } - } +using namespace std; - return 0; -} -void HttpProto :: FixRespHeaders(bool is_keep_alive, const char * version, HttpResponse * resp) { - char buffer[256] = { 0 }; +void HttpProtocol::FixRespHeaders(bool is_keep_alive, const char *version, HttpResponse *resp) { + char buffer[256]{0}; // check keep alive header if (is_keep_alive) { - if (NULL == resp->GetHeaderValue(HttpMessage::HEADER_CONNECTION)) { + if (nullptr == resp->GetHeaderValue(HttpMessage::HEADER_CONNECTION)) { resp->AddHeader(HttpMessage::HEADER_CONNECTION, "Keep-Alive"); } } // check date header resp->RemoveHeader(HttpMessage::HEADER_DATE); - time_t t_time = time(NULL); + time_t t_time = time(nullptr); struct tm tm_time; gmtime_r(&t_time, &tm_time); strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S %Z", &tm_time); @@ -155,62 +123,74 @@ void HttpProto :: FixRespHeaders(bool is_keep_alive, const char * version, HttpR resp->SetVersion(version); } -void HttpProto::FixRespHeaders(const HttpRequest & req, HttpResponse * resp) { +void HttpProtocol::FixRespHeaders(const HttpRequest &req, HttpResponse *resp) { FixRespHeaders(req.IsKeepAlive(), req.GetVersion(), resp); } -int HttpProto::SendResp(BaseTcpStream & socket, const HttpResponse & resp) { - socket << resp.GetVersion() << " " << resp.GetStatusCode() << " " << resp.GetReasonPhrase() << "\r\n"; +ReturnCode HttpProtocol::SendReqHeader(BaseTcpStream &socket, const char *method, const HttpRequest &req) { + string url; - for (size_t i = 0; i < resp.GetHeaderCount(); i++) { - socket << resp.GetHeaderName(i) << ": " << resp.GetHeaderValue(i) << "\r\n"; - } + if (req.GetParamCount() > 0) { + url.append(req.GetURI()); + url.append("?"); - if (resp.GetContent().size() > 0) { - if (NULL == resp.GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH)) { - socket << HttpMessage::HEADER_CONTENT_LENGTH << ": " << resp.GetContent().size() << "\r\n"; + char tmp[1024]{0}; + for (size_t i = 0; i < req.GetParamCount(); i++) { + if (i > 0) + url.append("&"); + URLEncode(req.GetParamName(i), tmp, sizeof(tmp) - 1); + url.append(tmp); + url.append("="); + URLEncode(req.GetParamValue(i), tmp, sizeof(tmp) - 1); + url.append(tmp); } } - socket << "\r\n"; + socket << method << " " << (url.size() > 0 ? url.c_str() : req.GetURI()) + << " " << req.GetVersion() << "\r\n"; - if (resp.GetContent().size() > 0) - socket << resp.GetContent(); + for (size_t i{0}; req.GetHeaderCount() > i; ++i) { + const char *name{req.GetHeaderName(i)}; + const char *val{req.GetHeaderValue(i)}; - if (socket.flush().good()) { - return 0; - } else { - return socket.LastError(); + socket << name << ": " << val << "\r\n"; } -} -int HttpProto::RecvReq(BaseTcpStream & socket, HttpRequest * req) { - int socket_ret = RecvReqStartLine(socket, req); + if (req.GetContent().size() > 0) { + if (nullptr == req.GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH)) { + socket << HttpMessage::HEADER_CONTENT_LENGTH << ": " + << req.GetContent().size() << "\r\n"; + } + } - if (socket_ret == 0) - socket_ret = RecvHeaders(socket, req); + socket << "\r\n"; - if (socket_ret == 0) - socket_ret = RecvBody(socket, req); + if (req.GetContent().size() == 0) { + if (socket.flush().good()) { + return ReturnCode::OK; + } else { + return static_cast(socket.LastError()); + } + } - return socket_ret; + return ReturnCode::OK; } -int HttpProto::RecvRespStartLine(BaseTcpStream & socket, HttpResponse * resp) { - char line[1024] = {0}; +ReturnCode HttpProtocol::RecvRespStartLine(BaseTcpStream &socket, HttpResponse *resp) { + char line[1024]{0}; - bool is_good = socket.getlineWithTrimRight(line, sizeof(line)).good(); + bool is_good{socket.getlineWithTrimRight(line, sizeof(line)).good()}; if (is_good) { if (0 == strncasecmp(line, "HTTP", strlen("HTTP"))) { - char * pos = line; - char * first = strsep(&pos, " "); - char * second = strsep(&pos, " "); + char *pos = line; + char *first = SeparateStr(&pos, " "); + char *second = SeparateStr(&pos, " "); - if (NULL != first) + if (nullptr != first) resp->SetVersion(first); - if (NULL != second) + if (nullptr != second) resp->SetStatusCode(atoi(second)); - if (NULL != pos) + if (nullptr != pos) resp->SetReasonPhrase(pos); } else { is_good = false; @@ -219,27 +199,27 @@ int HttpProto::RecvRespStartLine(BaseTcpStream & socket, HttpResponse * resp) { } if (is_good) { - return 0; + return ReturnCode::OK; } else { phxrpc::log(LOG_WARNING, "%s, fail", __func__); - return socket.LastError(); + return static_cast(socket.LastError()); } } -int HttpProto::RecvReqStartLine(BaseTcpStream & socket, HttpRequest * req) { - char line[1024] = { 0 }; +ReturnCode HttpProtocol::RecvReqStartLine(BaseTcpStream &socket, HttpRequest *req) { + char line[1024]{0}; bool is_good = socket.getlineWithTrimRight(line, sizeof(line)).good(); if (is_good) { - char * pos = line; - char * first = strsep(&pos, " "); - char * second = strsep(&pos, " "); + char *pos = line; + char *first = SeparateStr(&pos, " "); + char *second = SeparateStr(&pos, " "); - if (NULL != first) + if (nullptr != first) req->SetMethod(first); - if (NULL != second) + if (nullptr != second) req->SetURI(second); - if (NULL != pos) + if (nullptr != pos) req->SetVersion(pos); char peer[128] = { 0 }; @@ -250,20 +230,20 @@ int HttpProto::RecvReqStartLine(BaseTcpStream & socket, HttpRequest * req) { } if (is_good) { - return 0; + return ReturnCode::OK; } else { - return socket.LastError(); + return static_cast(socket.LastError()); } } -int HttpProto::RecvHeaders(BaseTcpStream & socket, HttpMessage * msg) { - bool is_good = false; +ReturnCode HttpProtocol::RecvHeaders(BaseTcpStream &socket, HttpMessage *msg) { + bool is_good{false}; - char * line = (char*) malloc(MAX_RECV_LEN); - assert(NULL != line); + char *line = (char *)malloc(MAX_RECV_LEN); + assert(nullptr != line); - std::string multi_line; - char * pos = NULL; + string multi_line; + char *pos{nullptr}; do { is_good = socket.getlineWithTrimRight(line, MAX_RECV_LEN).good(); @@ -274,10 +254,10 @@ int HttpProto::RecvHeaders(BaseTcpStream & socket, HttpMessage * msg) { if (multi_line.size() > 0) { char * header = (char*) multi_line.c_str(); pos = header; - strsep(&pos, ":"); - for (; NULL != pos && '\0' != *pos && isspace(*pos);) + SeparateStr(&pos, ":"); + for (; nullptr != pos && '\0' != *pos && isspace(*pos);) pos++; - msg->AddHeader(header, NULL == pos ? "" : pos); + msg->AddHeader(header, nullptr == pos ? "" : pos); } multi_line.clear(); } @@ -289,24 +269,24 @@ int HttpProto::RecvHeaders(BaseTcpStream & socket, HttpMessage * msg) { } while (is_good && '\0' != *line); free(line); - line = NULL; + line = nullptr; if (is_good) { - return 0; + return ReturnCode::OK; } else { - return socket.LastError(); + return static_cast(socket.LastError()); } } -int HttpProto::RecvBody(BaseTcpStream & socket, HttpMessage * msg) { - bool is_good = true; +ReturnCode HttpProtocol::RecvBody(BaseTcpStream &socket, HttpMessage *msg) { + bool is_good{true}; - const char * encoding = msg->GetHeaderValue(HttpMessage::HEADER_TRANSFER_ENCODING); + const char *encoding{msg->GetHeaderValue(HttpMessage::HEADER_TRANSFER_ENCODING)}; - char * buff = (char*) malloc(MAX_RECV_LEN); - assert(NULL != buff); + char *buff{(char *)malloc(MAX_RECV_LEN)}; + assert(nullptr != buff); - if (NULL != encoding && 0 == strcasecmp(encoding, "chunked")) { + if (nullptr != encoding && 0 == strcasecmp(encoding, "chunked")) { // read chunked, refer to rfc2616 section[19.4.6] for (; is_good;) { @@ -314,7 +294,7 @@ int HttpProto::RecvBody(BaseTcpStream & socket, HttpMessage * msg) { if (!is_good) break; - int size = strtol(buff, NULL, 16); + int size{strtol(buff, nullptr, 16)}; if (size > 0) { for (; size > 0;) { int read_len = size > MAX_RECV_LEN ? MAX_RECV_LEN : size; @@ -332,10 +312,10 @@ int HttpProto::RecvBody(BaseTcpStream & socket, HttpMessage * msg) { } } } else { - const char * content_length = msg->GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH); + const char *content_length{msg->GetHeaderValue(HttpMessage::HEADER_CONTENT_LENGTH)}; - if (NULL != content_length) { - int size = atoi(content_length); + if (nullptr != content_length) { + int size{atoi(content_length)}; for (; size > 0 && is_good;) { int read_len = size > MAX_RECV_LEN ? MAX_RECV_LEN : size; @@ -347,7 +327,7 @@ int HttpProto::RecvBody(BaseTcpStream & socket, HttpMessage * msg) { break; } } - } else if (HttpMessage::eResponse == msg->GetType()) { + } else if (BaseMessage::Direction::RESPONSE == msg->direction()) { // hasn't Content-Length header, read until socket close for (; is_good;) { is_good = socket.read(buff, MAX_RECV_LEN).good(); @@ -363,11 +343,31 @@ int HttpProto::RecvBody(BaseTcpStream & socket, HttpMessage * msg) { free(buff); if (is_good) { - return 0; + return ReturnCode::OK; } else { - return socket.LastError(); + return static_cast(socket.LastError()); } } +ReturnCode HttpProtocol::RecvReq(BaseTcpStream &socket, HttpRequest *req) { + ReturnCode ret{RecvReqStartLine(socket, req)}; + + if (ReturnCode::OK == ret) + ret = RecvHeaders(socket, req); + + if (ReturnCode::OK == ret) + ret = RecvBody(socket, req); + + return ret; +} + +ReturnCode HttpProtocol::ServerRecv(BaseTcpStream &socket, BaseRequest *&req) { + HttpRequest *http_req{new HttpRequest}; + req = http_req; + + return RecvReq(socket, http_req); } + +} // namespace phxrpc + diff --git a/phxrpc/http/http_protocol.h b/phxrpc/http/http_protocol.h new file mode 100644 index 0000000..f8c2e0e --- /dev/null +++ b/phxrpc/http/http_protocol.h @@ -0,0 +1,67 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include "phxrpc/msg/base_protocol.h" + + +namespace phxrpc { + + +class BaseTcpStream; + +class HttpMessage; +class HttpRequest; +class HttpResponse; + +class HttpProtocol : public BaseProtocol { + public: + enum { + MAX_RECV_LEN = 8192 + }; + + HttpProtocol() = default; + virtual ~HttpProtocol() override = default; + + static void FixRespHeaders(const HttpRequest &req, HttpResponse *resp); + + static void FixRespHeaders(bool is_keep_alive, const char *version, HttpResponse *resp); + + static ReturnCode SendReqHeader(BaseTcpStream &socket, const char *method, const HttpRequest &req); + + static ReturnCode RecvRespStartLine(BaseTcpStream &socket, HttpResponse *resp); + + static ReturnCode RecvReqStartLine(BaseTcpStream &socket, HttpRequest *req); + + static ReturnCode RecvHeaders(BaseTcpStream &socket, HttpMessage *msg); + + static ReturnCode RecvBody(BaseTcpStream &socket, HttpMessage *msg); + + static ReturnCode RecvReq(BaseTcpStream &socket, HttpRequest *req); + + virtual ReturnCode ServerRecv(BaseTcpStream &socket, + BaseRequest *&req) override; +}; + + +} // namespace phxrpc + diff --git a/phxrpc/http/test_http_client.cpp b/phxrpc/http/test_http_client.cpp index fd5412c..cda89f5 100644 --- a/phxrpc/http/test_http_client.cpp +++ b/phxrpc/http/test_http_client.cpp @@ -1,32 +1,31 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include - #include "http_msg.h" #include "http_client.h" @@ -36,7 +35,7 @@ See the AUTHORS file for names of contributors. using namespace phxrpc; -void showUsage(const char * program) { +void ShowUsage(const char *program) { printf("\n%s [-h host] [-p port] [-r POST|GET] [-u URI] [-f file] [-v]\n", program); printf("\t-h http host\n"); @@ -50,33 +49,33 @@ void showUsage(const char * program) { exit(0); } -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { assert(sigset(SIGPIPE, SIG_IGN) != SIG_ERR); OptMap optMap("h:p:r:u:f:ov"); if ((!optMap.Parse(argc, argv)) || optMap.Has('v')) - showUsage(argv[0]); + ShowUsage(argv[0]); - int port = 0; - const char * host = optMap.Get('h'); - const char * method = optMap.Get('r'); - const char * uri = optMap.Get('u'); - const char * file = optMap.Get('f'); + int port{0}; + const char *host{optMap.Get('h')}; + const char *method{optMap.Get('r')}; + const char *uri{optMap.Get('u')}; + const char *file{optMap.Get('f')}; - if ((NULL == host) || (!optMap.GetInt('p', &port))) { + if ((nullptr == host) || (!optMap.GetInt('p', &port))) { printf("\nPlease specify host and port!\n"); - showUsage(argv[0]); + ShowUsage(argv[0]); } - if (NULL == method || NULL == uri) { + if (nullptr == method || nullptr == uri) { printf("\nPlease specify URI and method!\n"); - showUsage(argv[0]); + ShowUsage(argv[0]); } - if (0 == strcasecmp(method, "POST") && NULL == file) { + if (0 == strcasecmp(method, "POST") && nullptr == file) { printf("\nPlease specify the file for POST body!\n"); - showUsage(argv[0]); + ShowUsage(argv[0]); } HttpRequest request; @@ -94,40 +93,40 @@ int main(int argc, char * argv[]) { } BlockTcpStream socket; - if (!BlockTcpUtils::Open(&socket, host, port, 100, NULL, 0)) { + if (!BlockTcpUtils::Open(&socket, host, port, 100, nullptr, 0)) { printf("Connect %s:%d fail\n", host, port); exit(-1); } HttpResponse response; - bool socket_ret = false; + int ret{0}; if (request.IsMethod("GET")) { - socket_ret = HttpClient::Get(socket, request, &response); + ret = HttpClient::Get(socket, request, &response); } else if (request.IsMethod("POST")) { - socket_ret = HttpClient::Post(socket, request, &response); + ret = HttpClient::Post(socket, request, &response); } else if (request.IsMethod("HEAD")) { - socket_ret = HttpClient::Head(socket, request, &response); + ret = HttpClient::Head(socket, request, &response); } else { printf("unsupport method %s\n", request.GetMethod()); } - if (socket_ret) { + if (0 == ret) { printf("response:\n"); printf("%s %d %s\n", response.GetVersion(), response.GetStatusCode(), response.GetReasonPhrase()); printf("%zu headers\n", response.GetHeaderCount()); - for (size_t i = 0; i < response.GetHeaderCount(); i++) { - const char * name = response.GetHeaderName(i); - const char * val = response.GetHeaderValue(i); + for (size_t i{0}; response.GetHeaderCount() > i; ++i) { + const char *name{response.GetHeaderName(i)}; + const char *val{response.GetHeaderValue(i)}; printf("%s: %s\r\n", name, val); } printf("%zu bytes body\n", response.GetContent().size()); if (response.GetContent().size() > 0) { - //printf( "%s\n", (char*)response.getContent() ); + //printf("%s\n", (char*)response.getContent()); } } else { printf("http request fail\n"); diff --git a/phxrpc/mqtt.h b/phxrpc/mqtt.h new file mode 100644 index 0000000..a7bdb7e --- /dev/null +++ b/phxrpc/mqtt.h @@ -0,0 +1,28 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include "mqtt/mqtt_client.h" +//#include "mqtt/mqtt_dispatcher.h" +#include "mqtt/mqtt_msg.h" +#include "mqtt/mqtt_protocol.h" + diff --git a/phxrpc/mqtt/Makefile b/phxrpc/mqtt/Makefile new file mode 100644 index 0000000..a8d802f --- /dev/null +++ b/phxrpc/mqtt/Makefile @@ -0,0 +1,16 @@ +include ../../phxrpc.mk + +TEST_TARGETS = test_mqtt_protocol test_mqtt_client + +all: $(TEST_TARGETS) + +test_mqtt_protocol: test_mqtt_protocol.o + $(LINKER) $^ -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -o $@ + +test_mqtt_client: test_mqtt_client.o + $(LINKER) $^ -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -o $@ + +clean: + @( $(RM) $(TEST_TARGETS) ) + @( $(RM) *.o core.* $(LIB_OBJS) ) + diff --git a/phxrpc/mqtt/mqtt_client.cpp b/phxrpc/mqtt/mqtt_client.cpp new file mode 100644 index 0000000..a55943b --- /dev/null +++ b/phxrpc/mqtt/mqtt_client.cpp @@ -0,0 +1,135 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include "mqtt_client.h" + +#include +#include +#include +#include +#include + +#include "phxrpc/file/log_utils.h" +#include "phxrpc/network/socket_stream_base.h" + +#include "mqtt_msg.h" +#include "mqtt_protocol.h" + + +namespace { + + +phxrpc::ReturnCode DoMethod(phxrpc::BaseTcpStream &socket, const phxrpc::MqttMessage *const req, + phxrpc::MqttMessage *const resp, + phxrpc::MqttClient::MqttStat &mqtt_stat) { + phxrpc::ReturnCode ret{phxrpc::MqttProtocol::SendMessage(socket, req)}; + if (phxrpc::ReturnCode::OK != ret) { + if (phxrpc::ReturnCode::ERROR_SOCKET_STREAM_NORMAL_CLOSED != ret) { + mqtt_stat.send_error_ = true; + phxrpc::log(LOG_ERR, "SendMessage err %d", ret); + } + + return ret; + } + + if (!socket.flush().good()) { + phxrpc::log(LOG_ERR, "socket err %d", socket.LastError()); + + return static_cast(socket.LastError()); + } + + if (!resp->fake()) { + ret = phxrpc::MqttProtocol::RecvMessage(socket, resp); + if (phxrpc::ReturnCode::OK != ret) { + if (phxrpc::ReturnCode::ERROR_SOCKET_STREAM_NORMAL_CLOSED != ret) { + mqtt_stat.recv_error_ = true; + phxrpc::log(LOG_ERR, "RecvMessage err %d", ret); + } + + return ret; + } + } + + return ret; +} + +phxrpc::ReturnCode DoMethod(phxrpc::BaseTcpStream &socket, const phxrpc::MqttMessage *const req, + phxrpc::MqttMessage *const resp) { + phxrpc::MqttClient::MqttStat mqtt_stat; + return DoMethod(socket, req, resp, mqtt_stat); +} + + +} // namespace + + +namespace phxrpc { + + +int MqttClient::Connect(BaseTcpStream &socket, const MqttConnect &req, + MqttConnack &resp, MqttClient::MqttStat &mqtt_stat) { + return static_cast(DoMethod(socket, &req, &resp, mqtt_stat)); +} + +int MqttClient::Connect(BaseTcpStream &socket, const MqttConnect &req, + MqttConnack &resp) { + return static_cast(DoMethod(socket, &req, &resp)); +} + +int MqttClient::Publish(BaseTcpStream &socket, const MqttPublish &req, + MqttPuback &resp, MqttClient::MqttStat &mqtt_stat) { + return static_cast(DoMethod(socket, &req, &resp, mqtt_stat)); +} + +int MqttClient::Publish(BaseTcpStream &socket, const MqttPublish &req, + MqttPuback &resp) { + return static_cast(DoMethod(socket, &req, &resp)); +} + +int MqttClient::Subscribe(BaseTcpStream &socket, const MqttSubscribe &req, + MqttSuback &resp) { + return static_cast(DoMethod(socket, &req, &resp)); +} + +int MqttClient::Unsubscribe(BaseTcpStream &socket, const MqttUnsubscribe &req, + MqttUnsuback &resp) { + return static_cast(DoMethod(socket, &req, &resp)); +} + +int MqttClient::Ping(BaseTcpStream &socket, const MqttPingreq &req, + MqttPingresp &resp) { + return static_cast(DoMethod(socket, &req, &resp)); +} + +int MqttClient::Disconnect(BaseTcpStream &socket, const MqttDisconnect &req, + MqttClient::MqttStat &mqtt_stat) { + MqttFakeDisconnack resp; + return static_cast(DoMethod(socket, &req, &resp, mqtt_stat)); +} + +int MqttClient::Disconnect(BaseTcpStream &socket, const MqttDisconnect &req) { + MqttFakeDisconnack resp; + return static_cast(DoMethod(socket, &req, &resp)); +} + + +} // namespace phxrpc + diff --git a/phxrpc/mqtt/mqtt_client.h b/phxrpc/mqtt/mqtt_client.h new file mode 100644 index 0000000..6920f9a --- /dev/null +++ b/phxrpc/mqtt/mqtt_client.h @@ -0,0 +1,91 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + + +namespace phxrpc { + + +class BaseTcpStream; +class ClientMonitor; + +class MqttConnect; +class MqttConnack; +class MqttPublish; +class MqttPuback; +class MqttSubscribe; +class MqttSuback; +class MqttUnsubscribe; +class MqttUnsuback; +class MqttPingreq; +class MqttPingresp; +class MqttDisconnect; + +class MqttClient { + public: + struct MqttStat { + bool send_error_{false}; + bool recv_error_{false}; + + MqttStat() = default; + + MqttStat(bool send_error, bool recv_error) + : send_error_(send_error), recv_error_(recv_error) { + } + }; + + // @return true: socket ok; false: socket error + static int Connect(BaseTcpStream &socket, const MqttConnect &req, + MqttConnack &resp, MqttStat &mqtt_stat); + static int Connect(BaseTcpStream &socket, const MqttConnect &req, + MqttConnack &resp); + + // @return true: socket ok; false: socket error + static int Publish(BaseTcpStream &socket, const MqttPublish &req, + MqttPuback &resp, MqttStat &mqtt_stat); + static int Publish(BaseTcpStream &socket, const MqttPublish &req, + MqttPuback &resp); + + // @return true: socket ok; false: socket error + static int Subscribe(BaseTcpStream &socket, const MqttSubscribe &req, + MqttSuback &resp); + + // @return true: socket ok; false: socket error + static int Unsubscribe(BaseTcpStream &socket, const MqttUnsubscribe &req, + MqttUnsuback &resp); + + // @return true: socket ok; false: socket error + static int Ping(BaseTcpStream &socket, const MqttPingreq &req, + MqttPingresp &resp); + + // @return true: socket ok; false: socket error + static int Disconnect(BaseTcpStream &socket, const MqttDisconnect &req, + MqttStat &mqtt_stat); + static int Disconnect(BaseTcpStream &socket, const MqttDisconnect &req); + + private: + MqttClient(); +}; + + +} // namespace phxrpc + diff --git a/phxrpc/mqtt/mqtt_msg.cpp b/phxrpc/mqtt/mqtt_msg.cpp new file mode 100644 index 0000000..ac7b8f8 --- /dev/null +++ b/phxrpc/mqtt/mqtt_msg.cpp @@ -0,0 +1,1098 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include "mqtt_msg.h" + +#include +#include +#include +#include + +#include "phxrpc/file/log_utils.h" +#include "phxrpc/network/socket_stream_base.h" +#include "phxrpc/rpc/phxrpc.pb.h" + +#include "mqtt_protocol.h" + + +namespace phxrpc { + + +using namespace std; + + +const char MqttMessage::FixedHeader[]{ + '\x00', // FAKE_NONE + '\x10', // CONNECT + '\x20', // CONNACK + '\x32', // PUBLISH QoS 1 + '\x40', // PUBACK + '\x50', // PUBREC + '\x62', // PUBREL + '\x70', // PUBCOMP + '\x82', // SUBSCRIBE + '\x90', // SUBACK + '\xa2', // UNSUBSCRIBE + '\xb0', // UNSUBACK + '\xc0', // PINGREQ + '\xd0', // PINGRESP + '\xe0', // DISCONNECT + '\xf0', // FAKE_DISCONNACK +}; + +//const bool MqttMessage::NeedPacketIdentifier[]{ +// false, // FAKE_NONE +// false, // CONNECT +// false, // CONNACK +// true, // PUBLISH QoS 1 +// true, // PUBACK +// true, // PUBREC +// true, // PUBREL +// true, // PUBCOMP +// true, // SUBSCRIBE +// true, // SUBACK +// true, // UNSUBSCRIBE +// true, // UNSUBACK +// false, // PINGREQ +// false, // PINGRESP +// false, // DISCONNECT +// false, // FAKE_DISCONNACK +//}; + +int MqttMessage::EncodeUint16(string &dest, const uint16_t src) { + dest.clear(); + dest.resize(2); + dest[0] = static_cast(src >> 8); + dest[1] = static_cast(src); + + return 0; +} + +int MqttMessage::EncodeUint16(char *const dest, const size_t dest_size, + const uint16_t src) { + if (2 != dest_size) + return -1; + + dest[0] = static_cast(src >> 8); + dest[1] = static_cast(src); + + return 0; +} + +int MqttMessage::EncodeUnicode(string &dest, const string &src) { + dest.clear(); + dest.resize(2 + src.size()); + uint16_t src_size{static_cast(src.size())}; + dest[0] = static_cast(src_size >> 8); + dest[1] = static_cast(src_size); + for (int i{0}; src_size > i; ++i) { + dest[i + 2] = src.at(i); + } + + return 0; +} + +int MqttMessage::EncodeUnicode(char *const dest, const size_t dest_size, + const string &src) { + if (2 + src.size() != dest_size) + return -1; + + uint16_t src_size{static_cast(src.size())}; + dest[0] = static_cast(src_size >> 8); + dest[1] = static_cast(src_size); + for (int i{0}; src_size > i; ++i) { + dest[i + 2] = src.at(i); + } + + return 0; +} + + +ReturnCode MqttMessage::SendChar(ostringstream &out_stream, + const char &content) { + out_stream.put(content); + + // TODO: check stream + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvChar(istringstream &in_stream, char &content) { + in_stream.get(content); + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::SendUint16(ostringstream &out_stream, + const uint16_t content) { + out_stream.put(static_cast(content >> 8)); + out_stream.put(static_cast(content)); + + // TODO: check stream + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvUint16(istringstream &in_stream, + uint16_t &content) { + char temp; + in_stream.get(temp); + content = (static_cast(temp) << 8); + temp = '\0'; + in_stream.get(temp); + content |= static_cast(temp); + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::SendChars(ostringstream &out_stream, + const char *const content, + const int content_length) { + out_stream.write(content, content_length); + + // TODO: check stream + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvChars(istringstream &in_stream, + char *const content, + const int content_length) { + in_stream.read(content, content_length); + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::SendUnicode(ostringstream &out_stream, + const string &content) { + uint16_t content_size{static_cast(content.size())}; + ReturnCode ret{SendUint16(out_stream, content_size)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendUint16 err %d", ret); + + return ret; + } + + out_stream.write(content.data(), content.size()); + + // TODO: check stream + return ret; +} + +ReturnCode MqttMessage::RecvUnicode(istringstream &in_stream, string &content) { + uint16_t content_size{0}; + ReturnCode ret{RecvUint16(in_stream, content_size)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvUint16 err %d", ret); + + return ret; + } + + content.resize(content_size); + in_stream.read(&content[0], content_size); + + return ret; +} + + +ReturnCode MqttMessage::SendChar(BaseTcpStream &out_stream, + const char &content) { + out_stream.put(content); + + // TODO: check stream + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvChar(BaseTcpStream &in_stream, char &content) { + in_stream.get(content); + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::SendUint16(BaseTcpStream &out_stream, + const uint16_t content) { + out_stream.put(static_cast(content >> 8)); + out_stream.put(static_cast(content)); + + // TODO: check stream + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvUint16(BaseTcpStream &in_stream, uint16_t &content) { + char temp; + in_stream.get(temp); + content = (static_cast(temp) << 8); + temp = '\0'; + in_stream.get(temp); + content |= static_cast(temp); + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::SendChars(BaseTcpStream &out_stream, + const char *const content, + const int content_length) { + out_stream.write(content, content_length); + + // TODO: check stream + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvChars(BaseTcpStream &in_stream, + char *const content, + const int content_length) { + in_stream.read(content, content_length); + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::SendUnicode(BaseTcpStream &out_stream, + const string &content) { + uint16_t content_size{static_cast(content.size())}; + ReturnCode ret{SendUint16(out_stream, content_size)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendUint16 err %d", ret); + + return ret; + } + + out_stream.write(content.data(), content.size()); + + // TODO: check stream + return ret; +} + +ReturnCode MqttMessage::RecvUnicode(BaseTcpStream &in_stream, string &content) { + uint16_t content_size{0}; + ReturnCode ret{RecvUint16(in_stream, content_size)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvUint16 err %d", ret); + + return ret; + } + + content.resize(content_size); + in_stream.read(&content[0], content_size); + + return ret; +} + + +MqttMessage::MqttMessage() { + SetVersion("MQTT/3.1.1"); + memset(client_ip_, 0, sizeof(client_ip_)); +} + +MqttMessage::~MqttMessage() {} + +ReturnCode MqttMessage::SendFixedHeaderAndRemainingBuffer( + BaseTcpStream &out_stream, + const ControlPacketType control_packet_type, + const string &remaining_buffer) { + char fixed_header{FixedHeader[static_cast(control_packet_type)]}; + ReturnCode ret{SendChar(out_stream, fixed_header)}; + // TODO: + printf("%s:%d test4 type %d fixed_header %u\n", __func__, __LINE__, + static_cast(control_packet_type), static_cast(fixed_header)); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChar err %d", ret); + + return ret; + } + + const int remaining_length{static_cast(remaining_buffer.size())}; + ret = SendRemainingLength(out_stream, remaining_length); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendRemainingLength err %d", ret); + + return ret; + } + + ret = SendChars(out_stream, remaining_buffer.data(), + remaining_buffer.size()); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChars err %d", ret); + + return ret; + } + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvFixedHeaderAndRemainingBuffer( + BaseTcpStream &in_stream, ControlPacketType &control_packet_type, + string &remaining_buffer) { + char fixed_header{0x0}; + ReturnCode ret{RecvChar(in_stream, fixed_header)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChar err %d", ret); + + return ret; + } + + // TODO: + printf("%s:%d test4 fixed_header %u\n", __func__, __LINE__, static_cast(fixed_header)); + uint8_t temp{fixed_header}; + temp >>= 4; + temp &= 0x0f; + // must convert to unsigned first + control_packet_type = static_cast(temp); + // TODO: + printf("%s:%d test4 type %d\n", __func__, __LINE__, static_cast(control_packet_type)); + + int remaining_length{0}; + ret = RecvRemainingLength(in_stream, remaining_length); + + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvRemainingLength err %d", ret); + + return ret; + } + + remaining_buffer.resize(remaining_length); + ret = RecvChars(in_stream, &remaining_buffer[0], remaining_length); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChars err %d", ret); + + return ret; + } + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::SendRemainingLength(BaseTcpStream &out_stream, + const int remaining_length) { + char temp{0x0}; + char continue_bit{0x0}; + uint32_t temp_remaining_length{remaining_length}; + + for (int i{0}; 4 > i; ++i) { + temp = (temp_remaining_length & 0x7f); + temp_remaining_length >>= 8; + continue_bit = (temp_remaining_length > 0) ? 0x80 : 0x0; + out_stream.put(temp | continue_bit); + if (0x0 == continue_bit) { + return ReturnCode::OK; + } + } + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvRemainingLength(BaseTcpStream &in_stream, + int &remaining_length) { + uint32_t temp_remaining_length{0}; + + char temp{0x0}; + in_stream.get(temp); + temp_remaining_length = (static_cast(temp) & 0x7f); + + if (!(static_cast(temp) & 0x80)) { + remaining_length = temp_remaining_length; + + return ReturnCode::OK; + } + + in_stream.get(temp); + temp_remaining_length |= (static_cast(temp) & 0x7f) << 7; + if (!(static_cast(temp) & 0x80)) { + remaining_length = temp_remaining_length; + + return ReturnCode::OK; + } + + in_stream.get(temp); + temp_remaining_length |= (static_cast(temp) & 0x7f) << 14; + if (!(static_cast(temp) & 0x80)) { + remaining_length = temp_remaining_length; + + return ReturnCode::OK; + } + + in_stream.get(temp); + temp_remaining_length |= (static_cast(temp) & 0x7f) << 21; + + remaining_length = temp_remaining_length; + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::Send(BaseTcpStream &socket) const { + ostringstream ss; + ReturnCode ret{SendRemaining(ss)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendRemaining err %d", ret); + + return ret; + } + + ret = SendFixedHeaderAndRemainingBuffer(socket, control_packet_type(), ss.str()); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendFixedHeaderAndRemainingBuffer err %d", ret); + + return ret; + } + + if (!socket.flush().good()) { + phxrpc::log(LOG_ERR, "socket err %d", socket.LastError()); + + return static_cast(socket.LastError()); + } + + return ret; +} + +ReturnCode MqttMessage::SendRemaining(ostringstream &out_stream) const { + ReturnCode ret{SendVariableHeader(out_stream)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendVariableHeader err %d", ret); + + return ret; + } + + ret = SendPayload(out_stream); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendPayload err %d", ret); + + return ret; + } + + return ret; +} + +ReturnCode MqttMessage::RecvRemaining(istringstream &in_stream) { + ReturnCode ret{RecvVariableHeader(in_stream)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvVariableHeader err %d", ret); + + return ret; + } + + ret = RecvPayload(in_stream); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvPayload err %d", ret); + + return ret; + } + + return ret; +} + +ReturnCode MqttMessage::SendPacketIdentifier(ostringstream &out_stream) const { + //const int packet_type{static_cast(control_packet_type_)}; + //if (!NeedPacketIdentifier[packet_type]) { + // phxrpc::log(LOG_WARNING, "type %d ignored packet identifier", + // packet_type); + + // return ReturnCode::OK; + //} + + ReturnCode ret{SendUint16(out_stream, packet_identifier_)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendUint16 err %d", ret); + + return ret; + } + + return ReturnCode::OK; +} + +ReturnCode MqttMessage::RecvPacketIdentifier(istringstream &in_stream) { + //const int packet_type{static_cast(control_packet_type_)}; + //if (!NeedPacketIdentifier[packet_type]) { + // phxrpc::log(LOG_WARNING, "type %d ignored packet identifier", + // packet_type); + + // return ReturnCode::OK; + //} + + ReturnCode ret{RecvUint16(in_stream, packet_identifier_)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvUint16 err %d", ret); + + return ret; + } + + return ReturnCode::OK; +} + +ReturnCode MqttResponse::ModifyResp(const bool keep_alive, const string &version) { + return ReturnCode::OK; +} + + +MqttConnect::MqttConnect() : MqttRequest(Protocol::MQTT_CONNECT) { + set_control_packet_type(ControlPacketType::CONNECT); + + proto_name_.resize(6); + proto_name_[0] = 0; + proto_name_[1] = 4; + proto_name_[2] = 'M'; + proto_name_[3] = 'Q'; + proto_name_[4] = 'T'; + proto_name_[5] = 'T'; +} + +ReturnCode MqttConnect::ToPb(google::protobuf::Message *const message) const { + phxrpc::MqttConnectPb connect; + + connect.set_clean_session(clean_session_); + connect.set_keep_alive(keep_alive_); + connect.set_client_identifier(client_identifier_); + connect.set_proto_name(proto_name_); + connect.set_proto_level(proto_level_); + + try { + message->CopyFrom(connect); + } catch (exception) { + return ReturnCode::ERROR; + } + + return ReturnCode::OK; +} + +ReturnCode MqttConnect::FromPb(const google::protobuf::Message &message) { + phxrpc::MqttConnectPb connect; + + try { + connect.CopyFrom(message); + } catch (exception) { + return ReturnCode::ERROR; + } + + clean_session_ = connect.clean_session(); + keep_alive_ = connect.keep_alive(); + client_identifier_ = connect.client_identifier(); + proto_name_ = connect.proto_name(); + proto_level_ = connect.proto_level(); + + return ReturnCode::OK; +} + +BaseResponse *MqttConnect::GenResponse() const { return new MqttConnack; } + +ReturnCode MqttConnect::SendVariableHeader(ostringstream &out_stream) const { + ReturnCode ret{SendChars(out_stream, proto_name_.data(), + proto_name_.size())}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChars err %d", ret); + + return ret; + } + + ret = SendChar(out_stream, proto_level_); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChar err %d", ret); + + return ret; + } + + uint8_t connect_flags{0}; + connect_flags |= ((clean_session_ ? 1u : 0u) << 1); + ret = SendChar(out_stream, static_cast(connect_flags)); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChar err %d", ret); + + return ret; + } + + ret = SendUint16(out_stream, keep_alive_); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendUint16 err %d", ret); + + return ret; + } + + return ret; +} + +ReturnCode MqttConnect::RecvVariableHeader(istringstream &in_stream) { + char proto_name[6]{0x0}; + ReturnCode ret{RecvChars(in_stream, proto_name, 6)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChars err %d", ret); + + return ret; + } + proto_name_.resize(6); + proto_name_[0] = proto_name[0]; + proto_name_[1] = proto_name[1]; + proto_name_[2] = proto_name[2]; + proto_name_[3] = proto_name[3]; + proto_name_[4] = proto_name[4]; + proto_name_[5] = proto_name[5]; + + ret = RecvChar(in_stream, proto_level_); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChar err %d", ret); + + return ret; + } + + char connect_flags{0x0}; + ret = RecvChar(in_stream, connect_flags); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChar err %d", ret); + + return ret; + } + clean_session_ = ((connect_flags & 0x2) >> 1); + + ret = RecvUint16(in_stream, keep_alive_); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvUint16 err %d", ret); + + return ret; + } + + return ret; +} + +ReturnCode MqttConnect::SendPayload(ostringstream &out_stream) const { + return SendUnicode(out_stream, client_identifier_); +} + +ReturnCode MqttConnect::RecvPayload(istringstream &in_stream) { + return RecvUnicode(in_stream, client_identifier_); +} + + +MqttConnack::MqttConnack() : MqttResponse(Protocol::MQTT_CONNECT) { + set_control_packet_type(ControlPacketType::CONNACK); +} + +ReturnCode MqttConnack::ToPb(google::protobuf::Message *const message) const { + phxrpc::MqttConnackPb connack; + + connack.set_session_present(session_present_); + connack.set_connect_return_code(connect_return_code_); + + try { + message->CopyFrom(connack); + } catch (exception) { + return ReturnCode::ERROR; + } + + return ReturnCode::OK; +} + +ReturnCode MqttConnack::FromPb(const google::protobuf::Message &message) { + phxrpc::MqttConnackPb connack; + + try { + connack.CopyFrom(message); + } catch (exception) { + return ReturnCode::ERROR; + } + + session_present_ = connack.session_present(); + connect_return_code_ = connack.connect_return_code(); + + return ReturnCode::OK; +} + +ReturnCode MqttConnack::SendVariableHeader(ostringstream &out_stream) const { + ReturnCode ret{SendChar(out_stream, session_present_ ? 0x1 : 0x0)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChar err %d", ret); + + return ret; + } + + ret = SendChar(out_stream, connect_return_code_); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChar err %d", ret); + + return ret; + } + + return ReturnCode::OK; +} + +ReturnCode MqttConnack::RecvVariableHeader(istringstream &in_stream) { + char connect_acknowledge_flags{0x0}; + ReturnCode ret{RecvChar(in_stream, connect_acknowledge_flags)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChar err %d", ret); + + return ret; + } + session_present_ = (0x1 == (connect_acknowledge_flags & 0x1)); + + ret = RecvChar(in_stream, connect_return_code_); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChar err %d", ret); + + return ret; + } + + return ReturnCode::OK; +} + + +MqttPublish::MqttPublish() : MqttRequest(Protocol::MQTT_PUBLISH) { + set_control_packet_type(ControlPacketType::PUBLISH); +} + +ReturnCode MqttPublish::ToPb(google::protobuf::Message *const message) const { + phxrpc::MqttPublishPb publish; + + publish.set_topic_name(topic_name_); + publish.set_content(GetContent()); + publish.set_package_identifier(packet_identifier()); + + try { + message->CopyFrom(publish); + } catch (exception) { + return ReturnCode::ERROR; + } + + return ReturnCode::OK; +} + +ReturnCode MqttPublish::FromPb(const google::protobuf::Message &message) { + phxrpc::MqttPublishPb publish; + + try { + publish.CopyFrom(message); + } catch (exception) { + return ReturnCode::ERROR; + } + + topic_name_ = publish.topic_name(); + SetContent(publish.content().data(), publish.content().length()); + set_packet_identifier(publish.package_identifier()); + + return ReturnCode::OK; +} + +BaseResponse *MqttPublish::GenResponse() const { return new MqttPuback; } + +ReturnCode MqttPublish::SendVariableHeader(ostringstream &out_stream) const { + ReturnCode ret{SendUnicode(out_stream, topic_name_)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendUnicode err %d", ret); + + return ret; + } + + ret = SendPacketIdentifier(out_stream); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendPacketIdentifier err %d", ret); + + return ret; + } + + return ret; +} + +ReturnCode MqttPublish::RecvVariableHeader(istringstream &in_stream) { + ReturnCode ret{RecvUnicode(in_stream, topic_name_)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvUnicode err %d", ret); + + return ret; + } + + ret = RecvPacketIdentifier(in_stream); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvPacketIdentifier err %d", ret); + + return ret; + } + + return ret; +} + +ReturnCode MqttPublish::SendPayload(ostringstream &out_stream) const { + return SendUnicode(out_stream, GetContent()); +} + +ReturnCode MqttPublish::RecvPayload(istringstream &in_stream) { + return RecvUnicode(in_stream, GetContent()); +} + + +MqttPuback::MqttPuback() : MqttResponse(Protocol::MQTT_PUBLISH) { + set_control_packet_type(ControlPacketType::PUBACK); +} + +ReturnCode MqttPuback::ToPb(google::protobuf::Message *const message) const { + phxrpc::MqttPubackPb puback; + + puback.set_package_identifier(packet_identifier()); + + try { + message->CopyFrom(puback); + } catch (exception) { + return ReturnCode::ERROR; + } + + return ReturnCode::OK; +} + +ReturnCode MqttPuback::FromPb(const google::protobuf::Message &message) { + phxrpc::MqttPubackPb puback; + + try { + puback.CopyFrom(message); + } catch (exception) { + return ReturnCode::ERROR; + } + + set_packet_identifier(puback.package_identifier()); + + return ReturnCode::OK; +} + +ReturnCode MqttPuback::SendVariableHeader(ostringstream &out_stream) const { + return SendPacketIdentifier(out_stream); +} + +ReturnCode MqttPuback::RecvVariableHeader(istringstream &in_stream) { + return RecvPacketIdentifier(in_stream); +} + + +MqttSubscribe::MqttSubscribe() : MqttRequest(Protocol::MQTT_SUBSCRIBE) { + set_control_packet_type(ControlPacketType::SUBSCRIBE); +} + +BaseResponse *MqttSubscribe::GenResponse() const { return new MqttSuback; } + +ReturnCode MqttSubscribe::SendVariableHeader(ostringstream &out_stream) const { + return SendPacketIdentifier(out_stream); +} + +ReturnCode MqttSubscribe::RecvVariableHeader(istringstream &in_stream) { + return RecvPacketIdentifier(in_stream); +} + +ReturnCode MqttSubscribe::SendPayload(ostringstream &out_stream) const { + for (int i{0}; topic_filters_.size() > i; ++i) { + ReturnCode ret{SendUnicode(out_stream, topic_filters_.at(i))}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendUnicode err %d", ret); + + return ret; + } + + ret = SendChar(out_stream, 0x0); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChar err %d", ret); + + return ret; + } + } + + return ReturnCode::OK; +} + +ReturnCode MqttSubscribe::RecvPayload(istringstream &in_stream) { + while (EOF != in_stream.peek()) { + string topic_filter; + ReturnCode ret{RecvUnicode(in_stream, topic_filter)}; + if (ReturnCode::ERROR_LENGTH_OVERFLOW != ret) { + return ReturnCode::OK; + } + + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvUnicode err %d", ret); + + return ret; + } + + char requested_qos{0x0}; + ret = RecvChar(in_stream, requested_qos); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChar err %d", ret); + + return ret; + } + + topic_filters_.emplace_back(topic_filter); + } + + return ReturnCode::OK; +} + + +MqttSuback::MqttSuback() : MqttResponse(Protocol::MQTT_SUBSCRIBE) { + set_control_packet_type(ControlPacketType::SUBACK); +} + +ReturnCode MqttSuback::SendVariableHeader(ostringstream &out_stream) const { + return SendPacketIdentifier(out_stream); +} + +ReturnCode MqttSuback::RecvVariableHeader(istringstream &in_stream) { + return RecvPacketIdentifier(in_stream); +} + +ReturnCode MqttSuback::SendPayload(ostringstream &out_stream) const { + for (int i{0}; return_codes_.size() > i; ++i) { + ReturnCode ret{SendChar(out_stream, return_codes_.at(i))}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendChar err %d", ret); + + return ret; + } + } + + return ReturnCode::OK; +} + +ReturnCode MqttSuback::RecvPayload(istringstream &in_stream) { + while (EOF != in_stream.peek()) { + char return_code{0x0}; + ReturnCode ret{RecvChar(in_stream, return_code)}; + if (ReturnCode::ERROR_LENGTH_OVERFLOW != ret) { + return ReturnCode::OK; + } + + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvChar err %d", ret); + + return ret; + } + + return_codes_.resize(return_codes_.size() + 1); + return_codes_[return_codes_.size()] = return_code; + } + + return ReturnCode::OK; +} + + +MqttUnsubscribe::MqttUnsubscribe() : MqttRequest(Protocol::MQTT_UNSUBSCRIBE) { + set_control_packet_type(ControlPacketType::UNSUBSCRIBE); +} + +BaseResponse *MqttUnsubscribe::GenResponse() const { return new MqttUnsuback; } + +ReturnCode +MqttUnsubscribe::SendVariableHeader(ostringstream &out_stream) const { + return SendPacketIdentifier(out_stream); +} + +ReturnCode +MqttUnsubscribe::RecvVariableHeader(istringstream &in_stream) { + return RecvPacketIdentifier(in_stream); +} + +ReturnCode +MqttUnsubscribe::SendPayload(ostringstream &out_stream) const { + for (int i{0}; topic_filters_.size() > i; ++i) { + ReturnCode ret{SendUnicode(out_stream, topic_filters_.at(i))}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendUnicode err %d", ret); + + return ret; + } + } + + return ReturnCode::OK; +} + +ReturnCode +MqttUnsubscribe::RecvPayload(istringstream &in_stream) { + while (EOF != in_stream.peek()){ + string topic_filter; + ReturnCode ret{RecvUnicode(in_stream, topic_filter)}; + if (ReturnCode::ERROR_LENGTH_OVERFLOW != ret) { + return ReturnCode::OK; + } + + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvUnicode err %d", ret); + + return ret; + } + + topic_filters_.emplace_back(topic_filter); + } + + return ReturnCode::OK; +} + + +MqttUnsuback::MqttUnsuback() : MqttResponse(Protocol::MQTT_UNSUBSCRIBE) { + set_control_packet_type(ControlPacketType::UNSUBACK); +} + +ReturnCode MqttUnsuback::SendVariableHeader(ostringstream &out_stream) const { + return SendPacketIdentifier(out_stream); +} + +ReturnCode MqttUnsuback::RecvVariableHeader(istringstream &in_stream) { + return RecvPacketIdentifier(in_stream); +} + + +MqttPingreq::MqttPingreq() : MqttRequest(Protocol::MQTT_PING) { + set_control_packet_type(ControlPacketType::PINGREQ); +} + +BaseResponse *MqttPingreq::GenResponse() const { return new MqttPingresp; } + + +MqttPingresp::MqttPingresp() : MqttResponse(Protocol::MQTT_PING) { + set_control_packet_type(ControlPacketType::PINGRESP); +} + + +MqttDisconnect::MqttDisconnect() : MqttRequest(Protocol::MQTT_DISCONNECT) { + set_control_packet_type(ControlPacketType::DISCONNECT); +} + +ReturnCode MqttDisconnect::ToPb(google::protobuf::Message *const message) const { + phxrpc::MqttDisconnectPb disconnect; + + try { + message->CopyFrom(disconnect); + } catch (exception) { + return ReturnCode::ERROR; + } + + return ReturnCode::OK; +} + +ReturnCode MqttDisconnect::FromPb(const google::protobuf::Message &message) { + phxrpc::MqttDisconnectPb disconnect; + + try { + disconnect.CopyFrom(message); + } catch (exception) { + return ReturnCode::ERROR; + } + + return ReturnCode::OK; +} + +BaseResponse *MqttDisconnect::GenResponse() const { return new MqttFakeDisconnack; } + + +MqttFakeDisconnack::MqttFakeDisconnack() + : MqttResponse(Protocol::MQTT_FAKE_DISCONNACK) { + set_control_packet_type(ControlPacketType::FAKE_DISCONNACK); + set_fake(true); +} + + +} // namespace phxrpc + diff --git a/phxrpc/mqtt/mqtt_msg.h b/phxrpc/mqtt/mqtt_msg.h new file mode 100644 index 0000000..65d497c --- /dev/null +++ b/phxrpc/mqtt/mqtt_msg.h @@ -0,0 +1,548 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include +#include + +#include "phxrpc/msg.h" + + +namespace phxrpc { + + +class MqttMessage : virtual public BaseMessage { + public: + enum class ControlPacketType { + FAKE_NONE = 0, + CONNECT = 1, + CONNACK, + PUBLISH, + PUBACK, + PUBREC, + PUBREL, + PUBCOMP, + SUBSCRIBE, + SUBACK, + UNSUBSCRIBE, + UNSUBACK, + PINGREQ, + PINGRESP, + DISCONNECT, + FAKE_DISCONNACK, + FAKE_MAX, + }; + + static const char FixedHeader[]; + + //static const bool NeedPacketIdentifier[]; + + static int EncodeUint16(std::string &dest, const uint16_t src); + static int EncodeUint16(char *const dest, const size_t dest_size, + const uint16_t src); + static int EncodeUnicode(std::string &dest, const std::string &src); + static int EncodeUnicode(char *const dest, const size_t dest_size, + const std::string &src); + + static ReturnCode SendChar(std::ostringstream &out_stream, const char &content); + static ReturnCode RecvChar(std::istringstream &in_stream, char &content); + static ReturnCode SendUint16(std::ostringstream &out_stream, + const uint16_t content); + static ReturnCode RecvUint16(std::istringstream &in_stream, + uint16_t &content); + static ReturnCode SendChars(std::ostringstream &out_stream, + const char *const content, + const int content_length); + static ReturnCode RecvChars(std::istringstream &in_stream, + char *const content, + const int content_length); + static ReturnCode SendUnicode(std::ostringstream &out_stream, + const std::string &content); + static ReturnCode RecvUnicode(std::istringstream &in_stream, + std::string &content); + + static ReturnCode SendChar(BaseTcpStream &out_stream, const char &content); + static ReturnCode RecvChar(BaseTcpStream &in_stream, char &content); + static ReturnCode SendUint16(BaseTcpStream &out_stream, + const uint16_t content); + static ReturnCode RecvUint16(BaseTcpStream &in_stream, uint16_t &content); + static ReturnCode SendChars(BaseTcpStream &out_stream, + const char *const content, + const int content_length); + static ReturnCode RecvChars(BaseTcpStream &in_stream, + char *const content, + const int content_length); + static ReturnCode SendUnicode(BaseTcpStream &out_stream, + const std::string &content); + static ReturnCode RecvUnicode(BaseTcpStream &in_stream, + std::string &content); + + // control packet type and flags + static ReturnCode SendFixedHeaderAndRemainingBuffer( + BaseTcpStream &out_stream, + const ControlPacketType control_packet_type, + const std::string &remaining_buffer); + static ReturnCode RecvFixedHeaderAndRemainingBuffer( + BaseTcpStream &in_stream, + ControlPacketType &control_packet_type, + std::string &remaining_buffer); + + // remaining length + static ReturnCode SendRemainingLength(BaseTcpStream &out_stream, + const int remaining_length); + static ReturnCode RecvRemainingLength(BaseTcpStream &in_stream, + int &remaining_length); + + MqttMessage(); + virtual ~MqttMessage() override; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const = 0; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) = 0; + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const = 0; + virtual ReturnCode RecvPayload(std::istringstream &in_stream) = 0; + + virtual ReturnCode Send(BaseTcpStream &socket) const override; + + ReturnCode SendRemaining(std::ostringstream &out_stream) const; + ReturnCode RecvRemaining(std::istringstream &in_stream); + + // packet identifier + ReturnCode SendPacketIdentifier(std::ostringstream &out_stream) const; + ReturnCode RecvPacketIdentifier(std::istringstream &in_stream); + + ControlPacketType control_packet_type() const { + return control_packet_type_; + } + + int remaining_length() const { return remaining_length_; } + + uint16_t packet_identifier() const { return packet_identifier_; } + + void set_packet_identifier(const uint16_t packet_identifier) { + packet_identifier_ = packet_identifier; + } + + protected: + void set_control_packet_type(const ControlPacketType control_packet_type) { + control_packet_type_ = control_packet_type; + } + + void set_remaining_length(const int remaining_length) { + remaining_length_ = remaining_length; + } + + private: + ControlPacketType control_packet_type_{ControlPacketType::FAKE_NONE}; + uint16_t packet_identifier_{0x0}; + int remaining_length_{0}; +}; + + +class MqttRequest : public MqttMessage, public BaseRequest { + public: + MqttRequest(const Protocol protocol) : BaseRequest(protocol) {} + virtual ~MqttRequest() = default; + + private: +}; + + +class MqttResponse : public MqttMessage, public BaseResponse { + public: + MqttResponse(const Protocol protocol) : BaseResponse(protocol) {} + virtual ~MqttResponse() = default; + + virtual void SetPhxRpcResult(const int result) override {} + virtual void DispatchErr() override {} + + virtual ReturnCode ModifyResp(const bool keep_alive, const std::string &version) override; + + private: +}; + + +class MqttConnect final : public MqttRequest { + public: + MqttConnect(); + virtual ~MqttConnect() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override; + virtual ReturnCode FromPb(const google::protobuf::Message &message) override; + + virtual BaseResponse *GenResponse() const override; + virtual int IsKeepAlive() const override { return 1; }; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override; + + bool clean_session() const { return clean_session_; } + void set_clean_session(const bool clean_session) { + clean_session_ = clean_session; + } + + uint16_t keep_alive() const { return keep_alive_; } + void set_keep_alive(const uint16_t keep_alive) { + keep_alive_ = keep_alive; + } + + const std::string &client_identifier() const { return client_identifier_; } + void set_client_identifier(const std::string &client_identifier) { + client_identifier_ = client_identifier; + } + + // read only + const std::string &proto_name() const { return proto_name_; } + + // read only + char proto_level() const { return proto_level_; } + + private: + bool clean_session_{false}; + uint16_t keep_alive_{0}; + std::string client_identifier_; + std::string proto_name_; + char proto_level_{4}; +}; + + +class MqttConnack final : public MqttResponse { + public: + MqttConnack(); + virtual ~MqttConnack() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override; + virtual ReturnCode FromPb(const google::protobuf::Message &message) override; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override { + return ReturnCode::OK; + } + + bool session_present() const { return session_present_; } + void set_session_present(const bool session_present) { + session_present_ = session_present; + } + + char connect_return_code() const { return connect_return_code_; } + void set_connect_return_code(const char connect_return_code) { + connect_return_code_ = connect_return_code; + } + + private: + bool session_present_{0}; + char connect_return_code_{0}; +}; + + +class MqttPublish final : public MqttRequest { + public: + MqttPublish(); + virtual ~MqttPublish() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override; + virtual ReturnCode FromPb(const google::protobuf::Message &message) override; + + virtual BaseResponse *GenResponse() const override; + virtual int IsKeepAlive() const override { return 1; }; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override; + + const std::string &topic_name() const { return topic_name_; } + void set_topic_name(const std::string &topic_name) { + topic_name_ = topic_name; + } + + private: + std::string topic_name_; +}; + + +class MqttPuback final : public MqttResponse { + public: + MqttPuback(); + virtual ~MqttPuback() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override; + virtual ReturnCode FromPb(const google::protobuf::Message &message) override; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override { + return ReturnCode::OK; + } +}; + + +class MqttSubscribe final : public MqttRequest { + public: + MqttSubscribe(); + virtual ~MqttSubscribe() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode FromPb(const google::protobuf::Message &message) override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual BaseResponse *GenResponse() const override; + virtual int IsKeepAlive() const override { return 1; }; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override; + + const std::vector &topic_filters() const { + return topic_filters_; + } + void set_topic_filters(const std::vector &topic_filters) { + topic_filters_ = topic_filters; + } + + private: + std::vector topic_filters_; +}; + + +class MqttSuback final : public MqttResponse { + public: + MqttSuback(); + virtual ~MqttSuback() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode FromPb(const google::protobuf::Message &message) override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override; + + const std::string &return_codes() const { return return_codes_; } + void set_return_codes(const std::string &return_codes) { + return_codes_ = return_codes; + } + + private: + std::string return_codes_; +}; + + +class MqttUnsubscribe final : public MqttRequest { + public: + MqttUnsubscribe(); + virtual ~MqttUnsubscribe() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode FromPb(const google::protobuf::Message &message) override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual BaseResponse *GenResponse() const override; + virtual int IsKeepAlive() const override { return 1; }; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override; + + const std::vector &topic_filters() const { + return topic_filters_; + } + void set_topic_filters(const std::vector &topic_filters) { + topic_filters_ = topic_filters; + } + + private: + std::vector topic_filters_; +}; + + +class MqttUnsuback final : public MqttResponse { + public: + MqttUnsuback(); + virtual ~MqttUnsuback() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode FromPb(const google::protobuf::Message &message) override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override; + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override; + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override { + return ReturnCode::OK; + } +}; + + +class MqttPingreq final : public MqttRequest { + public: + MqttPingreq(); + virtual ~MqttPingreq() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode FromPb(const google::protobuf::Message &message) override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual BaseResponse *GenResponse() const override; + virtual int IsKeepAlive() const override { return 1; }; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override { + return ReturnCode::OK; + } + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override { + return ReturnCode::OK; + } +}; + + +class MqttPingresp final : public MqttResponse { + public: + MqttPingresp(); + virtual ~MqttPingresp() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode FromPb(const google::protobuf::Message &message) override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override { + return ReturnCode::OK; + } + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override { + return ReturnCode::OK; + } +}; + + +class MqttDisconnect final : public MqttRequest { + public: + MqttDisconnect(); + virtual ~MqttDisconnect() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override; + virtual ReturnCode FromPb(const google::protobuf::Message &message) override; + + virtual BaseResponse *GenResponse() const override; + virtual int IsKeepAlive() const override { return 1; }; + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override { + return ReturnCode::OK; + } + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override { + return ReturnCode::OK; + } +}; + + +class MqttFakeDisconnack final : public MqttResponse { + public: + MqttFakeDisconnack(); + virtual ~MqttFakeDisconnack() = default; + + virtual ReturnCode ToPb(google::protobuf::Message *const message) const override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode FromPb(const google::protobuf::Message &message) override { + return ReturnCode::ERROR_UNIMPLEMENT; + } + + virtual ReturnCode SendVariableHeader(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvVariableHeader(std::istringstream &in_stream) override { + return ReturnCode::OK; + } + + virtual ReturnCode SendPayload(std::ostringstream &out_stream) const override { + return ReturnCode::OK; + } + virtual ReturnCode RecvPayload(std::istringstream &in_stream) override { + return ReturnCode::OK; + } +}; + + +} // namespace phxrpc + diff --git a/phxrpc/mqtt/mqtt_protocol.cpp b/phxrpc/mqtt/mqtt_protocol.cpp new file mode 100644 index 0000000..1840860 --- /dev/null +++ b/phxrpc/mqtt/mqtt_protocol.cpp @@ -0,0 +1,142 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include "mqtt_protocol.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mqtt_msg.h" + +#include "phxrpc/file/log_utils.h" +#include "phxrpc/network/socket_stream_base.h" + + +namespace phxrpc { + + +using namespace std; + + +ReturnCode MqttProtocol::SendMessage(BaseTcpStream &socket, + const MqttMessage *const msg) { + ostringstream ss; + ReturnCode ret{msg->SendRemaining(ss)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendRemaining err %d", ret); + + return ret; + } + + ret = MqttMessage::SendFixedHeaderAndRemainingBuffer(socket, + msg->control_packet_type(), ss.str()); + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "SendFixedHeaderAndRemainingBuffer err %d", ret); + + return ret; + } + + if (!socket.flush().good()) { + phxrpc::log(LOG_ERR, "socket err %d", socket.LastError()); + + return static_cast(socket.LastError()); + } + + return ret; +} + +ReturnCode MqttProtocol::RecvMessage(BaseTcpStream &socket, + MqttMessage *const msg) { + MqttMessage::ControlPacketType control_packet_type{ + MqttMessage::ControlPacketType::FAKE_NONE}; + string remaining_buffer; + ReturnCode ret{MqttMessage::RecvFixedHeaderAndRemainingBuffer(socket, + control_packet_type, remaining_buffer)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvFixedHeaderAndRemainingBuffer err %d", ret); + + return ret; + } + + istringstream ss(remaining_buffer); + + if (msg->control_packet_type() == control_packet_type) { + return msg->RecvRemaining(ss); + } + phxrpc::log(LOG_ERR, "msg_type %d != recv_type %d", + static_cast(msg->control_packet_type()), + static_cast(control_packet_type)); + + return ReturnCode::ERROR; +} + +ReturnCode MqttProtocol::ServerRecv(BaseTcpStream &socket, BaseRequest *&req) { + MqttMessage::ControlPacketType control_packet_type{ + MqttMessage::ControlPacketType::FAKE_NONE}; + string remaining_buffer; + ReturnCode ret{MqttMessage::RecvFixedHeaderAndRemainingBuffer(socket, + control_packet_type, remaining_buffer)}; + if (ReturnCode::OK != ret) { + phxrpc::log(LOG_ERR, "RecvFixedHeaderAndRemainingBuffer err %d", ret); + + return ret; + } + + istringstream ss(remaining_buffer); + + if (MqttMessage::ControlPacketType::CONNECT == control_packet_type) { + MqttConnect *connect{new MqttConnect}; + req = connect; + return connect->RecvRemaining(ss); + } else if (MqttMessage::ControlPacketType::PUBLISH == control_packet_type) { + MqttPublish *publish{new MqttPublish}; + req = publish; + return publish->RecvRemaining(ss); + } else if (MqttMessage::ControlPacketType::SUBSCRIBE == control_packet_type) { + MqttSubscribe *subscribe{new MqttSubscribe}; + req = subscribe; + return subscribe->RecvRemaining(ss); + } else if (MqttMessage::ControlPacketType::UNSUBSCRIBE == control_packet_type) { + MqttUnsubscribe *unsubscribe{new MqttUnsubscribe}; + req = unsubscribe; + return unsubscribe->RecvRemaining(ss); + } else if (MqttMessage::ControlPacketType::PINGREQ == control_packet_type) { + MqttPingreq *pingreq{new MqttPingreq}; + req = pingreq; + return pingreq->RecvRemaining(ss); + } else if (MqttMessage::ControlPacketType::DISCONNECT == control_packet_type) { + MqttDisconnect *disconnect{new MqttDisconnect}; + req = disconnect; + return disconnect->RecvRemaining(ss); + } + phxrpc::log(LOG_ERR, "type %d not supported", static_cast(control_packet_type)); + + return ReturnCode::ERROR; +} + + +} // namespace phxrpc + diff --git a/phxrpc/mqtt/mqtt_protocol.h b/phxrpc/mqtt/mqtt_protocol.h new file mode 100644 index 0000000..9148b46 --- /dev/null +++ b/phxrpc/mqtt/mqtt_protocol.h @@ -0,0 +1,52 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include "phxrpc/msg/base_protocol.h" + + +namespace phxrpc { + + +enum class ReturnCode; + +class BaseTcpStream; + +class MqttMessage; + +class MqttProtocol : public BaseProtocol { + public: + MqttProtocol() = default; + virtual ~MqttProtocol() override = default; + + static ReturnCode SendMessage(BaseTcpStream &socket, + const MqttMessage *const msg); + static ReturnCode RecvMessage(BaseTcpStream &socket, + MqttMessage *const msg); + + virtual ReturnCode ServerRecv(BaseTcpStream &socket, + BaseRequest *&req) override; +}; + + +} + diff --git a/phxrpc/mqtt/test_mqtt_client.cpp b/phxrpc/mqtt/test_mqtt_client.cpp new file mode 100644 index 0000000..a2d3230 --- /dev/null +++ b/phxrpc/mqtt/test_mqtt_client.cpp @@ -0,0 +1,146 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include +#include +#include +#include +#include +#include + +#include "mqtt_msg.h" +#include "mqtt_client.h" + +#include "phxrpc/file/file_utils.h" +#include "phxrpc/file/opt_map.h" +#include "phxrpc/network/socket_stream_block.h" + + +using namespace phxrpc; +using namespace std; + + +void ShowUsage(const char *program) { + printf("\n%s [-h host] [-p port] [-r CONNECT|PUBLISH|SUBSCRIBE|UNSUBSCRIBE|PING|DISCONNECT] [-f file] [-v]\n", program); + + printf("\t-h mqtt host\n"); + printf("\t-p mqtt port\n"); + printf("\t-r mqtt method, only support CONNECT|PUBLISH|SUBSCRIBE|UNSUBSCRIBE|PING|DISCONNECT\n"); + printf("\t-f the file for content\n"); + printf("\t-v show this usage\n"); + printf("\n"); + + exit(0); +} + +int main(int argc, char *argv[]) { + assert(sigset(SIGPIPE, SIG_IGN) != SIG_ERR); + + OptMap optMap("h:p:r:f:v"); + + if ((!optMap.Parse(argc, argv)) || optMap.Has('v')) + ShowUsage(argv[0]); + + int port{0}; + const char *host{optMap.Get('h')}; + const char *method{optMap.Get('r')}; + const char *file{optMap.Get('f')}; + + if ((nullptr == host) || (!optMap.GetInt('p', &port))) { + printf("\nPlease specify host and port!\n"); + ShowUsage(argv[0]); + } + + if (nullptr == method) { + printf("\nPlease specify method!\n"); + ShowUsage(argv[0]); + } + + BlockTcpStream socket; + if (!BlockTcpUtils::Open(&socket, host, port, 100, nullptr, 0)) { + printf("Connect %s:%d fail\n", host, port); + exit(-1); + } + + int ret{0}; + + if (0 == strcasecmp(method, "CONNECT")) { + MqttConnect req; + MqttConnack resp; + ret = MqttClient::Connect(socket, req, resp); + if (0 == ret) { + printf("mqtt connect ret %d connect_return_code %d\n", + ret, resp.connect_return_code()); + } else { + printf("mqtt connect fail ret %d\n", ret); + } + } else if (0 == strcasecmp(method, "PUBLISH")) { + MqttPublish req; + MqttPuback resp; + ret = MqttClient::Publish(socket, req, resp); + if (0 == ret) { + printf("mqtt publish ret %d packet_identifier %u\n", + ret, resp.packet_identifier()); + } else { + printf("mqtt publish fail ret %d\n", ret); + } + } else if (0 == strcasecmp(method, "SUBSCRIBE")) { + MqttSubscribe req; + MqttSuback resp; + ret = MqttClient::Subscribe(socket, req, resp); + if (0 == ret) { + printf("mqtt subscribe ret %d\n", ret); + } else { + printf("mqtt subscribe fail ret %d\n", ret); + } + } else if (0 == strcasecmp(method, "UNSUBSCRIBE")) { + MqttUnsubscribe req; + MqttUnsuback resp; + ret = MqttClient::Unsubscribe(socket, req, resp); + if (0 == ret) { + printf("mqtt unsubscribe ret %d\n", ret); + } else { + printf("mqtt unsubscribe fail ret %d\n", ret); + } + } else if (0 == strcasecmp(method, "PING")) { + MqttPingreq req; + MqttPingresp resp; + ret = MqttClient::Ping(socket, req, resp); + if (0 == ret) { + printf("mqtt ping ret %d\n", ret); + } else { + printf("mqtt ping fail ret %d\n", ret); + } + } else if (0 == strcasecmp(method, "DISCONNECT")) { + MqttDisconnect req; + ret = MqttClient::Disconnect(socket, req); + if (0 == ret) { + printf("mqtt disconnect ret %d\n", ret); + } else { + printf("mqtt disconnect fail ret %d\n", ret); + } + } else { + printf("unsupport method %s\n", method); + } + + return 0; +} + diff --git a/phxrpc/mqtt/test_mqtt_protocol.cpp b/phxrpc/mqtt/test_mqtt_protocol.cpp new file mode 100644 index 0000000..81372c9 --- /dev/null +++ b/phxrpc/mqtt/test_mqtt_protocol.cpp @@ -0,0 +1,151 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "mqtt_msg.h" +#include "mqtt_protocol.h" + +#include "phxrpc/file/file_utils.h" +#include "phxrpc/file/opt_map.h" +#include "phxrpc/network/socket_stream_block.h" + + +using namespace phxrpc; +using namespace std; + + +void ShowUsage(const char *program) { + printf("\n%s [-r CONNECT|PUBLISH|SUBSCRIBE|UNSUBSCRIBE|PING|DISCONNECT] [-f file] [-v]\n", program); + + printf("\t-r mqtt method, only support CONNECT|PUBLISH|SUBSCRIBE|UNSUBSCRIBE|PING|DISCONNECT\n"); + printf("\t-f the file for content\n"); + printf("\t-v show this usage\n"); + printf("\n"); + + exit(0); +} + +void TraceMsg(const MqttMessage &msg) { + ostringstream ss_req; + msg.SendRemaining(ss_req); + const string &s_req(ss_req.str()); + cout << s_req.size() << ":" << endl; + for (int i{0}; s_req.size() > i; ++i) { + cout << static_cast(s_req.data()[i]) << "\t"; + } + cout << endl; + for (int i{0}; s_req.size() > i; ++i) { + if (isalnum(s_req.data()[i]) || '_' == s_req.data()[i]) + cout << s_req.data()[i] << "\t"; + else + cout << '.' << "\t"; + } + cout << endl; +} + +int main(int argc, char *argv[]) { + assert(sigset(SIGPIPE, SIG_IGN) != SIG_ERR); + + OptMap optMap("r:f:v"); + + if ((!optMap.Parse(argc, argv)) || optMap.Has('v')) + ShowUsage(argv[0]); + + const char *method{optMap.Get('r')}; + const char *file{optMap.Get('f')}; + + if (nullptr == method) { + printf("\nPlease specify method!\n"); + ShowUsage(argv[0]); + } + + int ret{0}; + + if (0 == strcasecmp(method, "CONNECT")) { + cout << "Req:" << endl; + TraceMsg(MqttConnect()); + + cout << "Resp:" << endl; + TraceMsg(MqttConnack()); + } else if (0 == strcasecmp(method, "PUBLISH")) { + cout << "Req:" << endl; + MqttPublish publish; + publish.set_topic_name("test_topic_1"); + publish.set_packet_identifier(11); + TraceMsg(publish); + + cout << "Resp:" << endl; + MqttPuback puback; + puback.set_packet_identifier(11); + TraceMsg(puback); + } else if (0 == strcasecmp(method, "SUBSCRIBE")) { + cout << "Req:" << endl; + TraceMsg(MqttSubscribe()); + cout << "Resp:" << endl; + TraceMsg(MqttSuback()); + } else if (0 == strcasecmp(method, "UNSUBSCRIBE")) { + cout << "Req:" << endl; + TraceMsg(MqttUnsubscribe()); + cout << "Resp:" << endl; + TraceMsg(MqttUnsuback()); + } else if (0 == strcasecmp(method, "PING")) { + cout << "Req:" << endl; + TraceMsg(MqttPingreq()); + cout << "Resp:" << endl; + TraceMsg(MqttPingresp()); + } else if (0 == strcasecmp(method, "DISCONNECT")) { + cout << "Req:" << endl; + TraceMsg(MqttDisconnect()); + } else { + printf("unsupport method %s\n", method); + } + + //if (0 == ret) { + // printf("response:\n"); + + // printf("%s %d %s\n", response.GetVersion(), response.GetStatusCode(), + // response.GetReasonPhrase()); + + // printf("%zu headers\n", response.GetHeaderCount()); + // for (size_t i{0}; i < response.GetHeaderCount(); ++i) { + // const char *name{response.GetHeaderName(i)}; + // const char *val{response.GetHeaderValue(i)}; + // printf("%s: %s\r\n", name, val); + // } + + // printf("%zu bytes body\n", response.GetContent().size()); + // if (response.GetContent().size() > 0) { + // //printf("%s\n", (char*)response.getContent()); + // } + //} else { + // printf("mqtt request fail\n"); + //} + + return 0; +} + diff --git a/phxrpc/msg.h b/phxrpc/msg.h new file mode 100644 index 0000000..b734b41 --- /dev/null +++ b/phxrpc/msg.h @@ -0,0 +1,29 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include "msg/base_dispatcher.h" +#include "msg/base_msg.h" +#include "msg/base_protocol.h" +#include "msg/common.h" +#include "msg/protocol_factory.h" + diff --git a/phxrpc/network/Makefile b/phxrpc/network/Makefile index 29bc02c..fc148e2 100644 --- a/phxrpc/network/Makefile +++ b/phxrpc/network/Makefile @@ -1,8 +1,8 @@ include ../../phxrpc.mk TEST_TARGETS = test_echo_client test_echo_server \ - test_epoll_server test_epoll_client \ - test_uthread test_timer test_uthread_context \ + test_epoll_server test_epoll_client \ + test_uthread test_timer test_uthread_context all: $(TEST_TARGETS) @@ -12,7 +12,7 @@ test_echo_client: test_echo_client.o test_echo_server: test_echo_server.o $(LINKER) $^ -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -o $@ -test_uthread: test_uthread.o +test_uthread: test_uthread.o $(LINKER) $^ -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -o $@ test_epoll_server: test_epoll_server.o @@ -30,3 +30,4 @@ test_uthread_context : test_uthread_context.o clean: @( $(RM) $(TEST_TARGETS) ) @( $(RM) *.o core.* $(LIB_OBJS) ) + diff --git a/phxrpc/network/timer.cpp b/phxrpc/network/timer.cpp index e0d4e18..2f88013 100644 --- a/phxrpc/network/timer.cpp +++ b/phxrpc/network/timer.cpp @@ -42,9 +42,15 @@ const uint64_t Timer::GetTimestampMS() { } const uint64_t Timer::GetSteadyClockMS() { + auto now_time = chrono::system_clock::now(); + uint64_t now = (chrono::duration_cast(now_time.time_since_epoch())).count(); + return now; + + /* auto now_time = chrono::steady_clock::now(); uint64_t now = (chrono::duration_cast(now_time.time_since_epoch())).count(); return now; + */ } void Timer :: MsSleep(const int time_ms) { diff --git a/phxrpc/network/uthread_epoll.cpp b/phxrpc/network/uthread_epoll.cpp index 245609d..4ee9434 100644 --- a/phxrpc/network/uthread_epoll.cpp +++ b/phxrpc/network/uthread_epoll.cpp @@ -440,31 +440,33 @@ int UThreadAccept(UThreadSocket_t & socket, struct sockaddr *addr, socklen_t *ad } ssize_t UThreadRead(UThreadSocket_t & socket, void * buf, size_t len, int flags) { - int ret = read(socket.socket, buf, len); + //int ret = read(socket.socket, buf, len); + int ret = -1; - if (ret < 0 && EAGAIN == errno) { + //if (ret < 0 && EAGAIN == errno) { int revents = 0; if (UThreadPoll(socket, EPOLLIN, &revents, socket.socket_timeout_ms) > 0) { ret = read(socket.socket, buf, len); } else { ret = -1; } - } + //} return ret; } ssize_t UThreadRecv(UThreadSocket_t & socket, void * buf, size_t len, int flags) { - int ret = recv(socket.socket, buf, len, flags); + //int ret = recv(socket.socket, buf, len, flags); + int ret = -1; - if (ret < 0 && EAGAIN == errno) { + //if (ret < 0 && EAGAIN == errno) { int revents = 0; if (UThreadPoll(socket, EPOLLIN, &revents, socket.socket_timeout_ms) > 0) { ret = recv(socket.socket, buf, len, flags); } else { ret = -1; } - } + //} return ret; } diff --git a/phxrpc/rpc.h b/phxrpc/rpc.h index b5b2e39..64e67e4 100644 --- a/phxrpc/rpc.h +++ b/phxrpc/rpc.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -28,7 +28,9 @@ See the AUTHORS file for names of contributors. #include "rpc/socket_stream_phxrpc.h" #include "rpc/uthread_caller.h" #include "rpc/http_caller.h" +#include "rpc/mqtt_caller.h" #include "rpc/client_monitor.h" #include "rpc/server_monitor.h" #include "rpc/monitor_factory.h" #include "rpc/server_base.h" + diff --git a/phxrpc/rpc/Makefile b/phxrpc/rpc/Makefile index fb1850f..9ff9c2e 100644 --- a/phxrpc/rpc/Makefile +++ b/phxrpc/rpc/Makefile @@ -1,7 +1,6 @@ - include ../../phxrpc.mk -TEST_TARGETS = test_thread_queue test_hsha_server test_client \ +TEST_TARGETS = test_thread_queue test_hsha_server test_http_client test_mqtt_client \ all: $(TEST_TARGETS) @@ -11,9 +10,13 @@ test_thread_queue: test_thread_queue.o test_hsha_server: test_hsha_server.o $(LINKER) $^ -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -o $@ -test_client: test_client.o +test_http_client: test_http_client.o + $(LINKER) $^ -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -o $@ + +test_mqtt_client: test_mqtt_client.o $(LINKER) $^ -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -o $@ - + clean: @( $(RM) $(TEST_TARGETS) ) @( $(RM) *.o core.* $(LIB_OBJS) ) + diff --git a/phxrpc/rpc/client_config.cpp b/phxrpc/rpc/client_config.cpp index 41d5cbf..8c23bb0 100644 --- a/phxrpc/rpc/client_config.cpp +++ b/phxrpc/rpc/client_config.cpp @@ -1,26 +1,26 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include -#include +#include +#include #include #include "client_config.h" @@ -29,8 +29,10 @@ See the AUTHORS file for names of contributors. #include "phxrpc/file.h" + namespace phxrpc { + ClientConfig::ClientConfig() { connect_timeout_ms_ = 200; socket_timeout_ms_ = 5000; @@ -40,22 +42,22 @@ ClientConfig::ClientConfig() { ClientConfig::~ClientConfig() { } -void ClientConfig :: SetClientMonitor( ClientMonitorPtr client_monitor ) { +void ClientConfig::SetClientMonitor(ClientMonitorPtr client_monitor) { client_monitor_ = client_monitor; } -ClientMonitorPtr ClientConfig :: GetClientMonitor() { +ClientMonitorPtr ClientConfig::GetClientMonitor() { return client_monitor_; } -bool ClientConfig::Read(const char * config_file) { +bool ClientConfig::Read(const char *config_file) { Config config; if (!config.InitConfig(config_file)) { return false; } - int count = 0; - bool succ = true; + int count{0}; + bool succ{true}; succ &= config.ReadItem("Server", "ServerCount", &count); if (!succ) { log(LOG_ERR, "Config::%s key ServerCount not found", __func__); @@ -64,12 +66,12 @@ bool ClientConfig::Read(const char * config_file) { config.ReadItem("Server", "PackageName", package_name_, sizeof(package_name_)); - for (int i = 0; i < count; i++) { - char section[64] = { 0 }; + for (int i{0}; count > i; ++i) { + char section[64]{0}; snprintf(section, sizeof(section), "Server%d", i); Endpoint_t ep; - bool succ = true; + bool succ{true}; succ &= config.ReadItem(section, "IP", ep.ip, sizeof(ep.ip)); succ &= config.ReadItem(section, "Port", &(ep.port)); if (!succ) { @@ -88,32 +90,32 @@ bool ClientConfig::Read(const char * config_file) { return endpoints_.size() > 0; } -const Endpoint_t * ClientConfig::GetRandom() const { - const Endpoint_t * ret = NULL; +const Endpoint_t *ClientConfig::GetRandom() const { + const Endpoint_t *ret{nullptr}; if (endpoints_.size() > 0) { ret = &(endpoints_[random() % endpoints_.size()]); } - - if ( !ret ) { - if ( client_monitor_.get() ) { + + if (!ret) { + if (client_monitor_.get()) { client_monitor_->GetEndpointFail(); } - log( LOG_ERR, "GetRandom fail, list.size %lu", endpoints_.size() ); + log(LOG_ERR, "GetRandom fail, list.size %lu", endpoints_.size()); } return ret; } -const Endpoint_t * ClientConfig::GetByIndex(const size_t index) const { - const Endpoint_t * ret = NULL; +const Endpoint_t *ClientConfig::GetByIndex(const size_t index) const { + const Endpoint_t *ret{nullptr}; if (index < endpoints_.size()) { ret = &(endpoints_[index]); } - if ( !ret ) { - if ( client_monitor_.get() ) { + if (!ret) { + if (client_monitor_.get()) { client_monitor_->GetEndpointFail(); } } @@ -128,9 +130,10 @@ int ClientConfig::GetSocketTimeoutMS() { return socket_timeout_ms_; } -const char * ClientConfig :: GetPackageName() const { +const char *ClientConfig::GetPackageName() const { return package_name_; } -} + +} // namespace phxrpc diff --git a/phxrpc/rpc/client_config.h b/phxrpc/rpc/client_config.h index 96e26ad..b2b3b97 100644 --- a/phxrpc/rpc/client_config.h +++ b/phxrpc/rpc/client_config.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -23,40 +23,43 @@ See the AUTHORS file for names of contributors. #include "client_monitor.h" +#include #include #include -#include + namespace phxrpc { + typedef struct tagEndpoint { char ip[32]; int port; } Endpoint_t; + class ClientConfig { - public: + public: ClientConfig(); - ~ClientConfig(); + virtual ~ClientConfig(); - bool Read(const char * config_file); + bool Read(const char *config_file); - const Endpoint_t * GetRandom() const; + const Endpoint_t *GetRandom() const; - const Endpoint_t * GetByIndex(const size_t index) const; + const Endpoint_t *GetByIndex(const size_t index) const; int GetConnectTimeoutMS(); int GetSocketTimeoutMS(); - const char * GetPackageName() const; + const char *GetPackageName() const; - void SetClientMonitor( ClientMonitorPtr client_monitor ); + void SetClientMonitor(ClientMonitorPtr client_monitor); ClientMonitorPtr GetClientMonitor(); - private: + private: std::vector endpoints_; int connect_timeout_ms_; @@ -67,5 +70,6 @@ class ClientConfig { ClientMonitorPtr client_monitor_; }; -} + +} // namespace phxrpc diff --git a/phxrpc/rpc/client_monitor.cpp b/phxrpc/rpc/client_monitor.cpp index 5856933..191f415 100644 --- a/phxrpc/rpc/client_monitor.cpp +++ b/phxrpc/rpc/client_monitor.cpp @@ -1,69 +1,70 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include +#include #include #include #include "client_monitor.h" - + + namespace phxrpc { -//ClientMonitor begin -ClientMonitor :: ClientMonitor() { -} -ClientMonitor :: ~ClientMonitor() { +ClientMonitor::ClientMonitor() { } -void ClientMonitor :: ClientConnect( bool result ) { +ClientMonitor::~ClientMonitor() { } -void ClientMonitor :: SendBytes( size_t bytes ) { +void ClientMonitor::ClientConnect(bool result) { } -void ClientMonitor :: RecvBytes( size_t bytes ) { +void ClientMonitor::SendBytes(size_t bytes) { } -void ClientMonitor :: RequestCost( uint64_t begin_time, uint64_t end_time ) { +void ClientMonitor::RecvBytes(size_t bytes) { } -void ClientMonitor :: SendError() { +void ClientMonitor::RequestCost(uint64_t begin_time, uint64_t end_time) { } -void ClientMonitor :: SendCount() { +void ClientMonitor::SendError() { } -void ClientMonitor :: RecvError() { +void ClientMonitor::SendCount() { } -void ClientMonitor :: RecvCount() { +void ClientMonitor::RecvError() { } -void ClientMonitor :: GetEndpointFail() { +void ClientMonitor::RecvCount() { } -void ClientMonitor :: ClientCall( int cmdid, const char * method_name ) { +void ClientMonitor::GetEndpointFail() { } -//ClientMonitor end +void ClientMonitor::ClientCall(const int cmd_id, const char *method_name) { } + +} // namespace phxrpc + diff --git a/phxrpc/rpc/client_monitor.h b/phxrpc/rpc/client_monitor.h index 2514084..f4ce913 100644 --- a/phxrpc/rpc/client_monitor.h +++ b/phxrpc/rpc/client_monitor.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,41 +21,43 @@ See the AUTHORS file for names of contributors. #pragma once -#include + +#include #include #include + namespace phxrpc { class ClientMonitor { - public: + public: ClientMonitor(); virtual ~ClientMonitor(); - virtual void ClientConnect( bool result ); + virtual void ClientConnect(bool result); - virtual void SendBytes( size_t bytes ); + virtual void SendBytes(size_t bytes); virtual void SendError(); virtual void SendCount(); - virtual void RecvBytes( size_t bytes ); + virtual void RecvBytes(size_t bytes); virtual void RecvCount(); virtual void RecvError(); - virtual void RequestCost( uint64_t begin_time, uint64_t end_time ); + virtual void RequestCost(uint64_t begin_time, uint64_t end_time); virtual void GetEndpointFail(); - virtual void ClientCall( int cmd, const char * method_name ); + virtual void ClientCall(const int cmd_id, const char *method_name); }; typedef std::shared_ptr ClientMonitorPtr; -} +} // namespace phxrpc diff --git a/phxrpc/rpc/hsha_server.cpp b/phxrpc/rpc/hsha_server.cpp index 64e5ec2..364d962 100644 --- a/phxrpc/rpc/hsha_server.cpp +++ b/phxrpc/rpc/hsha_server.cpp @@ -1,55 +1,60 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ #include "hsha_server.h" -#include -#include + +#include #include #include +#include +#include + +#include "phxrpc/file.h" +#include "phxrpc/http.h" +#include "phxrpc/mqtt.h" +#include "phxrpc/msg.h" +#include "phxrpc/network.h" #include "server_monitor.h" #include "monitor_factory.h" -#include "phxrpc/network.h" -#include "phxrpc/http.h" -#include "phxrpc/file.h" - -#include using namespace std; + namespace phxrpc { -DataFlow :: DataFlow() { + +DataFlow::DataFlow() { } -DataFlow :: ~DataFlow() { +DataFlow::~DataFlow() { } -void DataFlow :: PushRequest(void * args, HttpRequest * request) { +void DataFlow::PushRequest(void * args, BaseRequest * request) { in_queue_.push(make_pair(QueueExtData(args), request)); } -int DataFlow :: PluckRequest(void *& args, HttpRequest *& request) { - pair rp; +int DataFlow::PluckRequest(void *& args, BaseRequest *& request) { + pair rp; bool succ = in_queue_.pluck(rp); if (!succ) { return 0; @@ -61,8 +66,8 @@ int DataFlow :: PluckRequest(void *& args, HttpRequest *& request) { return now_time > rp.first.enqueue_time_ms ? now_time - rp.first.enqueue_time_ms : 0; } -int DataFlow :: PickRequest(void *& args, HttpRequest *& request) { - pair rp; +int DataFlow::PickRequest(void *& args, BaseRequest *& request) { + pair rp; bool succ = in_queue_.pick(rp); if (!succ) { return 0; @@ -74,12 +79,12 @@ int DataFlow :: PickRequest(void *& args, HttpRequest *& request) { return now_time > rp.first.enqueue_time_ms ? now_time - rp.first.enqueue_time_ms : 0; } -void DataFlow :: PushResponse(void * args, HttpResponse * response) { +void DataFlow::PushResponse(void * args, BaseResponse * response) { out_queue_.push(make_pair(QueueExtData(args), response)); } -int DataFlow :: PluckResponse(void *& args, HttpResponse *& response) { - pair rp; +int DataFlow::PluckResponse(void *& args, BaseResponse *& response) { + pair rp; bool succ = out_queue_.pluck(rp); if (!succ) { return 0; @@ -89,39 +94,39 @@ int DataFlow :: PluckResponse(void *& args, HttpResponse *& response) { auto now_time = Timer::GetSteadyClockMS(); return now_time > rp.first.enqueue_time_ms ? now_time - rp.first.enqueue_time_ms : 0; -} +} -bool DataFlow :: CanPushRequest(const int max_queue_length) { +bool DataFlow::CanPushRequest(const int max_queue_length) { return in_queue_.size() < (size_t)max_queue_length; -} +} -bool DataFlow :: CanPluckResponse() { +bool DataFlow::CanPluckResponse() { return !out_queue_.empty(); } -void DataFlow :: BreakOut() { +void DataFlow::BreakOut() { in_queue_.break_out(); out_queue_.break_out(); } //////////////////////////////////////// -HshaServerStat :: TimeCost :: TimeCost() { +HshaServerStat::TimeCost::TimeCost() { now_time_ms_ = Timer::GetSteadyClockMS(); } -HshaServerStat :: TimeCost :: ~TimeCost() { +HshaServerStat::TimeCost::~TimeCost() { } -int HshaServerStat :: TimeCost :: Cost() { +int HshaServerStat::TimeCost::Cost() { auto now_time_ms = Timer::GetSteadyClockMS(); auto cost_time_ms = now_time_ms > now_time_ms_ ? now_time_ms - now_time_ms_ : 0; now_time_ms_ = now_time_ms; return cost_time_ms; } -HshaServerStat :: HshaServerStat(const HshaServerConfig * config, ServerMonitorPtr hsha_server_monitor ) : - config_(config), thread_(&HshaServerStat::CalFunc, this), break_out_(false), +HshaServerStat::HshaServerStat(const HshaServerConfig *config, ServerMonitorPtr hsha_server_monitor) : + /* config_(config), */ thread_(&HshaServerStat::CalFunc, this), break_out_(false), hsha_server_monitor_(hsha_server_monitor) { hold_fds_ = 0; accepted_fds_ = 0; @@ -183,16 +188,19 @@ HshaServerStat :: HshaServerStat(const HshaServerConfig * config, ServerMonitorP worker_drop_requests_ = 0; worker_drop_reqeust_qps_ = 0; worker_time_costs_ = 0; + worker_time_costs_count_ = 0; + worker_avg_time_cost_per_second_ = 0; + worker_time_cost_per_period_ = 0; worker_time_costs_per_second_ = 0; } -HshaServerStat :: ~HshaServerStat() { +HshaServerStat::~HshaServerStat() { break_out_ = true; cv_.notify_all(); thread_.join(); } -void HshaServerStat :: MonitorReport() { +void HshaServerStat::MonitorReport() { //accept hsha_server_monitor_->Accept( accept_qps_ ); hsha_server_monitor_->AcceptFail( accept_fail_qps_ ); @@ -216,10 +224,10 @@ void HshaServerStat :: MonitorReport() { hsha_server_monitor_->WrokerInQueueTimeout( worker_drop_reqeust_qps_ ); } -void HshaServerStat :: CalFunc() { +void HshaServerStat::CalFunc() { while (!break_out_) { - std::unique_lock lock(mutex_); - cv_.wait_for(lock, std::chrono::seconds(1)); + unique_lock lock(mutex_); + cv_.wait_for(lock, chrono::seconds(1)); //acceptor accept_qps_ = static_cast(accepted_fds_); @@ -265,16 +273,26 @@ void HshaServerStat :: CalFunc() { //time cost rpc_time_cost_per_period_ = 0; if (rpc_time_costs_count_ >= RPC_TIME_COST_CAL_RATE) { - rpc_avg_time_cost_per_second_ = + rpc_avg_time_cost_per_second_ = static_cast(rpc_time_costs_) / rpc_time_costs_count_; rpc_time_cost_per_period_ = static_cast(rpc_time_costs_); rpc_time_costs_ = 0; rpc_time_costs_count_ = 0; } + //worker time cost + worker_time_cost_per_period_ = 0; + if (worker_time_costs_count_ >= RPC_TIME_COST_CAL_RATE) { + worker_avg_time_cost_per_second_ = + static_cast(worker_time_costs_) / worker_time_costs_count_; + worker_time_cost_per_period_ = static_cast(worker_time_costs_); + worker_time_costs_ = 0; + worker_time_costs_count_ = 0; + } + inqueue_wait_time_costs_per_period_ = 0; if (inqueue_wait_time_costs_count_ >= QUEUE_WAIT_TIME_COST_CAL_RATE) { - inqueue_avg_wait_time_costs_per_second_ = + inqueue_avg_wait_time_costs_per_second_ = static_cast(inqueue_wait_time_costs_) / inqueue_wait_time_costs_count_; inqueue_wait_time_costs_per_period_ = static_cast(inqueue_wait_time_costs_); inqueue_wait_time_costs_ = 0; @@ -284,7 +302,7 @@ void HshaServerStat :: CalFunc() { outqueue_wait_time_costs_per_period_ = 0; if (outqueue_wait_time_costs_count_ >= QUEUE_WAIT_TIME_COST_CAL_RATE) { - outqueue_avg_wait_time_costs_per_second_ = + outqueue_avg_wait_time_costs_per_second_ = static_cast(outqueue_wait_time_costs_) / outqueue_wait_time_costs_count_; outqueue_wait_time_costs_per_period_ = static_cast(outqueue_wait_time_costs_); outqueue_wait_time_costs_ = 0; @@ -304,15 +322,15 @@ void HshaServerStat :: CalFunc() { phxrpc::log(LOG_NOTICE, "[SERVER_STAT] hold_fds %d accept_qps %d accept_reject_qps %d queue_full_reject_qps %d" " read_request_qps %d write_response_qps %d" - " inqueue_push_qps %d rpc_time_cost_avg %d" + " inqueue_push_qps %d rpc_time_cost_avg %d worker_time_cost_avg %d" " inqueue_wait_time_avg %d outqueue_wait_time_qvg %d" " fast_reject_qps %d" " worker_idles %d worker_drop_request_qps %d io_read_fails %d, io_write_fails %d", static_cast(hold_fds_), accept_qps_, reject_qps_, queue_full_rejected_after_accepted_qps_, io_read_request_qps_, io_write_response_qps_, - inqueue_push_qps_, rpc_avg_time_cost_per_second_, + inqueue_push_qps_, rpc_avg_time_cost_per_second_, worker_avg_time_cost_per_second_, inqueue_avg_wait_time_costs_per_second_, outqueue_avg_wait_time_costs_per_second_, - enqueue_fast_reject_qps_, + enqueue_fast_reject_qps_, static_cast(worker_idles_), worker_drop_reqeust_qps_, io_read_fail_qps_, io_write_fail_qps_ ); } @@ -320,32 +338,32 @@ void HshaServerStat :: CalFunc() { //////////////////////////////////////// -HshaServerQos :: HshaServerQos(const HshaServerConfig * config, HshaServerStat * hsha_server_stat) - : config_(config), hsha_server_stat_(hsha_server_stat), +HshaServerQos::HshaServerQos(const HshaServerConfig * config, HshaServerStat * hsha_server_stat) + : config_(config), hsha_server_stat_(hsha_server_stat), thread_(&HshaServerQos::CalFunc, this), break_out_(false) { enqueue_reject_rate_ = 0; inqueue_avg_wait_time_costs_per_second_cal_last_seq_ = 0; } -HshaServerQos :: ~HshaServerQos() { +HshaServerQos::~HshaServerQos() { break_out_ = true; cv_.notify_all(); thread_.join(); } -bool HshaServerQos :: CanAccept() { +bool HshaServerQos::CanAccept() { return static_cast(hsha_server_stat_->hold_fds_) < config_->GetMaxConnections(); } -bool HshaServerQos :: CanEnqueue() { - static std::default_random_engine e_rand((int)time(nullptr)); +bool HshaServerQos::CanEnqueue() { + static default_random_engine e_rand((int)time(nullptr)); return ((int)(e_rand() % 100)) >= enqueue_reject_rate_; } -void HshaServerQos :: CalFunc() { +void HshaServerQos::CalFunc() { while (!break_out_) { - std::unique_lock lock(mutex_); - cv_.wait_for(lock, std::chrono::seconds(1)); + unique_lock lock(mutex_); + cv_.wait_for(lock, chrono::seconds(1)); //fast reject if (hsha_server_stat_->inqueue_avg_wait_time_costs_per_second_cal_seq_ @@ -377,17 +395,17 @@ void HshaServerQos :: CalFunc() { //////////////////////////////////////// -Worker :: Worker(WorkerPool * pool, const int uthread_count, int utherad_stack_size) - : pool_(pool), uthread_count_(uthread_count), utherad_stack_size_(utherad_stack_size), shut_down_(false), +Worker::Worker(WorkerPool *pool, const int uthread_count, int utherad_stack_size) + : pool_(pool), uthread_count_(uthread_count), utherad_stack_size_(utherad_stack_size), shut_down_(false), worker_scheduler_(nullptr), thread_(&Worker::Func, this) { } -Worker :: ~Worker() { +Worker::~Worker() { thread_.join(); delete worker_scheduler_; } -void Worker :: Func() { +void Worker::Func() { if (uthread_count_ == 0) { ThreadMode(); } else { @@ -395,12 +413,12 @@ void Worker :: Func() { } } -void Worker :: ThreadMode() { +void Worker::ThreadMode() { while (!shut_down_) { pool_->hsha_server_stat_->worker_idles_++; void * args = nullptr; - HttpRequest * request = nullptr; + BaseRequest * request = nullptr; int queue_wait_time_ms = pool_->data_flow_->PluckRequest(args, request); if (request == nullptr) { //break out @@ -412,58 +430,59 @@ void Worker :: ThreadMode() { } } -void Worker :: UThreadMode() { +void Worker::UThreadMode() { worker_scheduler_ = new UThreadEpollScheduler(utherad_stack_size_, uthread_count_, true); assert(worker_scheduler_ != nullptr); - worker_scheduler_->SetHandlerNewRequestFunc(std::bind(&Worker::HandlerNewRequestFunc, this)); + worker_scheduler_->SetHandlerNewRequestFunc(bind(&Worker::HandlerNewRequestFunc, this)); worker_scheduler_->RunForever(); } -void Worker :: HandlerNewRequestFunc() { +void Worker::HandlerNewRequestFunc() { if (worker_scheduler_->IsTaskFull()) { return; } void * args = nullptr; - HttpRequest * request = nullptr; + BaseRequest * request = nullptr; int queue_wait_time_ms = pool_->data_flow_->PickRequest(args, request); if (request == nullptr) { return; } - worker_scheduler_->AddTask(std::bind(&Worker::UThreadFunc, this, args, request, queue_wait_time_ms), nullptr); + worker_scheduler_->AddTask(bind(&Worker::UThreadFunc, this, args, request, queue_wait_time_ms), nullptr); } -void Worker :: UThreadFunc(void * args, HttpRequest * request, int queue_wait_time_ms) { - WorkerLogic(args, request, queue_wait_time_ms); +void Worker::UThreadFunc(void *args, BaseRequest *req, int queue_wait_time_ms) { + WorkerLogic(args, req, queue_wait_time_ms); } -void Worker :: WorkerLogic(void * args, HttpRequest * request, int queue_wait_time_ms) { +void Worker::WorkerLogic(void *args, BaseRequest *req, int queue_wait_time_ms) { pool_->hsha_server_stat_->inqueue_pop_requests_++; pool_->hsha_server_stat_->inqueue_wait_time_costs_ += queue_wait_time_ms; pool_->hsha_server_stat_->inqueue_wait_time_costs_count_++; - HttpResponse * response = new HttpResponse; + BaseResponse *resp{req->GenResponse()}; if (queue_wait_time_ms < MAX_QUEUE_WAIT_TIME_COST) { HshaServerStat::TimeCost time_cost; - DispatcherArgs_t dispatcher_args(pool_->hsha_server_stat_->hsha_server_monitor_, + DispatcherArgs_t dispatcher_args(pool_->hsha_server_stat_->hsha_server_monitor_, worker_scheduler_, pool_->args_); - pool_->dispatch_(*request, response, &dispatcher_args); + pool_->dispatch_(req, resp, &dispatcher_args); pool_->hsha_server_stat_->worker_time_costs_ += time_cost.Cost(); + pool_->hsha_server_stat_->worker_time_costs_count_++; } else { pool_->hsha_server_stat_->worker_drop_requests_++; } - pool_->data_flow_->PushResponse(args, response); + pool_->data_flow_->PushResponse(args, resp); pool_->hsha_server_stat_->outqueue_push_responses_++; pool_->scheduler_->NotifyEpoll(); - delete request; + delete req; } -void Worker :: Notify() { +void Worker::Notify() { if (uthread_count_ == 0) { return; } @@ -471,23 +490,23 @@ void Worker :: Notify() { worker_scheduler_->NotifyEpoll(); } -void Worker :: Shutdown() { +void Worker::Shutdown() { shut_down_ = true; pool_->data_flow_->BreakOut(); } //////////////////////////////////////// -WorkerPool :: WorkerPool( - UThreadEpollScheduler * scheduler, - int thread_count, +WorkerPool::WorkerPool( + UThreadEpollScheduler * scheduler, + int thread_count, int uthread_count_per_thread, int utherad_stack_size, - DataFlow * data_flow, - HshaServerStat * hsha_server_stat, - Dispatch_t dispatch, + DataFlow * data_flow, + HshaServerStat * hsha_server_stat, + Dispatch_t dispatch, void * args) - : scheduler_(scheduler), data_flow_(data_flow), + : scheduler_(scheduler), data_flow_(data_flow), hsha_server_stat_(hsha_server_stat), dispatch_(dispatch), args_(args), last_notify_idx_(0) { for (int i = 0; i < thread_count; i++) { @@ -497,15 +516,15 @@ WorkerPool :: WorkerPool( } } -WorkerPool :: ~WorkerPool() { +WorkerPool::~WorkerPool() { for (auto & worker : worker_list_) { worker->Shutdown(); delete worker; } } -void WorkerPool :: Notify() { - std::lock_guard lock(mutex_); +void WorkerPool::Notify() { + lock_guard lock(mutex_); if (last_notify_idx_ == worker_list_.size()) { last_notify_idx_ = 0; } @@ -515,127 +534,143 @@ void WorkerPool :: Notify() { //////////////////////////////////////// -HshaServerIO :: HshaServerIO(int idx, UThreadEpollScheduler * scheduler, const HshaServerConfig * config, +HshaServerIO::HshaServerIO(int idx, UThreadEpollScheduler * scheduler, const HshaServerConfig * config, DataFlow * data_flow, HshaServerStat * hsha_server_stat, HshaServerQos * hsha_server_qos, WorkerPool * worker_pool) - : idx_(idx), scheduler_(scheduler), config_(config), - data_flow_(data_flow), listen_fd_(-1), hsha_server_stat_(hsha_server_stat), + : /* idx_(idx), */ scheduler_(scheduler), config_(config), + data_flow_(data_flow), /* listen_fd_(-1), */ hsha_server_stat_(hsha_server_stat), hsha_server_qos_(hsha_server_qos), worker_pool_(worker_pool) { } -HshaServerIO :: ~HshaServerIO() { +HshaServerIO::~HshaServerIO() { } -bool HshaServerIO :: AddAcceptedFd(int accepted_fd) { - std::lock_guard lock(queue_mutex_); +bool HshaServerIO::AddAcceptedFd(int accepted_fd) { + lock_guard lock(queue_mutex_); if (accepted_fd_list_.size() > MAX_ACCEPT_QUEUE_LENGTH) { return false; } accepted_fd_list_.push(accepted_fd); - if (static_cast(hsha_server_stat_->io_read_request_qps_) < 5000 - && static_cast(hsha_server_stat_->accept_qps_) < 5000) { + if (static_cast(hsha_server_stat_->io_read_request_qps_) < 5000 && + static_cast(hsha_server_stat_->accept_qps_) < 5000) { scheduler_->NotifyEpoll(); } return true; } -void HshaServerIO :: HandlerAcceptedFd() { - std::lock_guard lock(queue_mutex_); +void HshaServerIO::HandlerAcceptedFd() { + lock_guard lock(queue_mutex_); while (!accepted_fd_list_.empty()) { int accepted_fd = accepted_fd_list_.front(); accepted_fd_list_.pop(); - scheduler_->AddTask(std::bind(&HshaServerIO::IOFunc, this, accepted_fd), nullptr); + scheduler_->AddTask(bind(&HshaServerIO::IOFunc, this, accepted_fd), nullptr); } } -void HshaServerIO :: IOFunc(int accepted_fd) { - UThreadSocket_t * socket = scheduler_->CreateSocket(accepted_fd); +void HshaServerIO::IOFunc(int accepted_fd) { + UThreadSocket_t *socket{scheduler_->CreateSocket(accepted_fd)}; UThreadTcpStream stream; stream.Attach(socket); - UThreadSetSocketTimeout(*socket, config_->GetSocketTimeoutMS()); - HshaServerStat::TimeCost time_cost; + UThreadSetSocketTimeout(*socket, config_->GetSocketTimeoutMS()); while (true) { + HshaServerStat::TimeCost time_cost; + hsha_server_stat_->io_read_requests_++; - HttpRequest * request = new HttpRequest; - int socket_ret = HttpProto::RecvReq(stream, request); - if (socket_ret != 0) { - delete request; + + // TODO: unique_ptr not support dervied class dtor? + unique_ptr factory( + BaseProtocolFactory::CreateFactory(stream)); + unique_ptr protocol(factory->GenProtocol()); + // will be deleted by worker + BaseRequest *req{nullptr}; + ReturnCode ret{protocol->ServerRecv(stream, req)}; + if (ReturnCode::OK != ret) { + delete req; hsha_server_stat_->io_read_fails_++; hsha_server_stat_->rpc_time_costs_count_++; - //phxrpc::log(LOG_ERR, "%s read request fail, fd %d", __func__, accepted_fd); + hsha_server_stat_->rpc_time_costs_ += time_cost.Cost(); + phxrpc::log(LOG_ERR, "%s read request fail, fd %d", __func__, accepted_fd); + break; } - hsha_server_stat_->io_read_bytes_ += request->GetContent().size(); + hsha_server_stat_->io_read_bytes_ += req->GetContent().size(); if (!data_flow_->CanPushRequest(config_->GetMaxQueueLength())) { - delete request; + delete req; hsha_server_stat_->queue_full_rejected_after_accepted_fds_++; + break; } if (!hsha_server_qos_->CanEnqueue()) { - //fast reject don't cal rpc_time_cost; - delete request; + // fast reject don't cal rpc_time_cost; + delete req; hsha_server_stat_->enqueue_fast_rejects_++; - //phxrpc::log(LOG_ERR, "%s fast reject, can't enqueue, fd %d", __func__, accepted_fd); + phxrpc::log(LOG_ERR, "%s fast reject, can't enqueue, fd %d", + __func__, accepted_fd); + break; } - //if have enqueue, request will be deleted after pop. - bool is_keep_alive = request->IsKeepAlive(); - std::string version = string(request->GetVersion() != nullptr ? request->GetVersion() : ""); + // if have enqueue, request will be deleted after pop. + const bool is_keep_alive{0 != req->IsKeepAlive()}; + const string version(req->GetVersion() != nullptr ? req->GetVersion() : ""); hsha_server_stat_->inqueue_push_requests_++; - data_flow_->PushRequest((void *)socket, request); - //if is uthread worker mode, need notify. + data_flow_->PushRequest((void *)socket, req); + // if is uthread worker mode, need notify. + // req deleted by worker after this line worker_pool_->Notify(); UThreadSetArgs(*socket, nullptr); UThreadWait(*socket, config_->GetSocketTimeoutMS()); if (UThreadGetArgs(*socket) == nullptr) { - //timeout + // timeout hsha_server_stat_->worker_timeouts_++; hsha_server_stat_->rpc_time_costs_count_++; + hsha_server_stat_->rpc_time_costs_ += time_cost.Cost(); - //because have enqueue, so socket will be closed after pop. - socket = stream.DetachSocket(); + // because have enqueue, so socket will be closed after pop. + socket = stream.DetachSocket(); UThreadLazyDestory(*socket); - //phxrpc::log(LOG_ERR, "%s timeout, fd %d sockettimeoutms %d", - //__func__, accepted_fd, config_->GetSocketTimeoutMS()); + phxrpc::log(LOG_ERR, "%s timeout, fd %d sockettimeoutms %d", + __func__, accepted_fd, config_->GetSocketTimeoutMS()); break; } hsha_server_stat_->io_write_responses_++; - HttpResponse * response = (HttpResponse *)UThreadGetArgs(*socket); - HttpProto::FixRespHeaders(is_keep_alive, version.c_str(), response); - socket_ret = HttpProto::SendResp(stream, *response); - hsha_server_stat_->io_write_bytes_ += response->GetContent().size(); - delete response; + { + BaseResponse *resp((BaseResponse *)UThreadGetArgs(*socket)); + if (!resp->fake()) { + ret = resp->ModifyResp(is_keep_alive, version); + ret = resp->Send(stream); + hsha_server_stat_->io_write_bytes_ += resp->GetContent().size(); + } + delete resp; + } hsha_server_stat_->rpc_time_costs_count_++; + hsha_server_stat_->rpc_time_costs_ += time_cost.Cost(); - if (socket_ret != 0) { + if (ReturnCode::OK != ret) { hsha_server_stat_->io_write_fails_++; } - if(!is_keep_alive || (socket_ret != 0)) { + if (!is_keep_alive || (ReturnCode::OK != ret)) { break; - } else { - hsha_server_stat_->rpc_time_costs_ += time_cost.Cost(); } } - hsha_server_stat_->rpc_time_costs_ += time_cost.Cost(); hsha_server_stat_->hold_fds_--; } -UThreadSocket_t * HshaServerIO :: ActiveSocketFunc() { +UThreadSocket_t *HshaServerIO::ActiveSocketFunc() { while (data_flow_->CanPluckResponse()) { - void * args = nullptr; - HttpResponse * response = nullptr; + void *args = nullptr; + BaseResponse *response = nullptr; int queue_wait_time_ms = data_flow_->PluckResponse(args, response); if (response == nullptr) { //break out @@ -644,7 +679,7 @@ UThreadSocket_t * HshaServerIO :: ActiveSocketFunc() { hsha_server_stat_->outqueue_wait_time_costs_ += queue_wait_time_ms; hsha_server_stat_->outqueue_wait_time_costs_count_++; - UThreadSocket_t * socket = (UThreadSocket_t *)args; + UThreadSocket_t *socket = (UThreadSocket_t *)args; if (socket != nullptr && IsUThreadDestory(*socket)) { //socket aready timeout. //phxrpc::log(LOG_ERR, "%s socket aready timeout", __func__); @@ -661,57 +696,57 @@ UThreadSocket_t * HshaServerIO :: ActiveSocketFunc() { return nullptr; } -void HshaServerIO :: RunForever() { - scheduler_->SetHandlerAcceptedFdFunc(std::bind(&HshaServerIO::HandlerAcceptedFd, this)); - scheduler_->SetActiveSocketFunc(std::bind(&HshaServerIO::ActiveSocketFunc, this)); +void HshaServerIO::RunForever() { + scheduler_->SetHandlerAcceptedFdFunc(bind(&HshaServerIO::HandlerAcceptedFd, this)); + scheduler_->SetActiveSocketFunc(bind(&HshaServerIO::ActiveSocketFunc, this)); scheduler_->RunForever(); } ///////////////////////////////////////////////// -HshaServerUnit :: HshaServerUnit( - HshaServer * hsha_server, - int idx, - int worker_thread_count, +HshaServerUnit::HshaServerUnit( + HshaServer *hsha_server, + int idx, + int worker_thread_count, int worker_uthread_count_per_thread, int worker_utherad_stack_size, - Dispatch_t dispatch, - void * args) : + Dispatch_t dispatch, + void *args) : hsha_server_(hsha_server), #ifndef __APPLE__ - scheduler_(8 * 1024, 1000000, false), + scheduler_(8 * 1024, 1000000, false), #else - scheduler_(32 * 1024, 1000000, false), + scheduler_(32 * 1024, 1000000, false), #endif - worker_pool_(&scheduler_, worker_thread_count, worker_uthread_count_per_thread, + worker_pool_(&scheduler_, worker_thread_count, worker_uthread_count_per_thread, worker_utherad_stack_size, &data_flow_, &hsha_server_->hsha_server_stat_, dispatch, args), - hsha_server_io_(idx, &scheduler_, hsha_server_->config_, &data_flow_, + hsha_server_io_(idx, &scheduler_, hsha_server_->config_, &data_flow_, &hsha_server_->hsha_server_stat_, &hsha_server_->hsha_server_qos_, &worker_pool_), thread_(&HshaServerUnit::RunFunc, this) { } -HshaServerUnit :: ~HshaServerUnit() { +HshaServerUnit::~HshaServerUnit() { thread_.join(); } -void HshaServerUnit :: RunFunc() { +void HshaServerUnit::RunFunc() { hsha_server_io_.RunForever(); } -bool HshaServerUnit :: AddAcceptedFd(int accepted_fd) { +bool HshaServerUnit::AddAcceptedFd(int accepted_fd) { return hsha_server_io_.AddAcceptedFd(accepted_fd); } ///////////////////////////////////////////////// -HshaServerAcceptor :: HshaServerAcceptor(HshaServer * hsha_server) - : hsha_server_(hsha_server), idx_(0) { +HshaServerAcceptor::HshaServerAcceptor(HshaServer * hsha_server) + : hsha_server_(hsha_server), idx_(0) { } -HshaServerAcceptor :: ~HshaServerAcceptor() { +HshaServerAcceptor::~HshaServerAcceptor() { } -void HshaServerAcceptor :: LoopAccept(const char * bind_ip, const int port) { +void HshaServerAcceptor::LoopAccept(const char * bind_ip, const int port) { int listen_fd = -1; if (!BlockTcpUtils::Listen(&listen_fd, bind_ip, port)) { printf("listen fail, ip %s port %d\n", bind_ip, port); @@ -763,15 +798,14 @@ void HshaServerAcceptor :: LoopAccept(const char * bind_ip, const int port) { //////////////////////////////////////// -HshaServer :: HshaServer( - const HshaServerConfig & config, - Dispatch_t dispatch, - void * args) : - config_(&config), - hsha_server_monitor_(MonitorFactory::GetFactory()->CreateServerMonitor(config.GetPackageName())), - hsha_server_stat_(&config, hsha_server_monitor_), - hsha_server_qos_(&config, &hsha_server_stat_), - hsha_server_acceptor_(this) { +HshaServer::HshaServer(const HshaServerConfig &config, + Dispatch_t dispatch, void *args) + : config_(&config), + hsha_server_monitor_(MonitorFactory::GetFactory()-> + CreateServerMonitor(config.GetPackageName())), + hsha_server_stat_(&config, hsha_server_monitor_), + hsha_server_qos_(&config, &hsha_server_stat_), + hsha_server_acceptor_(this) { size_t io_count = (size_t)config.GetIOThreadCount(); size_t worker_thread_count = (size_t)config.GetMaxThreads(); assert(worker_thread_count > 0); @@ -785,7 +819,7 @@ HshaServer :: HshaServer( if (i == io_count - 1) { worker_thread_count_per_io = worker_thread_count - (worker_thread_count_per_io * (io_count - 1)); } - auto hsha_server_unit = + auto hsha_server_unit = new HshaServerUnit(this, i, (int)worker_thread_count_per_io, config.GetWorkerUThreadCount(), worker_utherad_stack_size, dispatch, args); assert(hsha_server_unit != nullptr); @@ -797,14 +831,16 @@ HshaServer :: HshaServer( } } -HshaServer :: ~HshaServer() { - for (auto & hsha_server_unit : server_unit_list_) { +HshaServer::~HshaServer() { + for (auto &hsha_server_unit : server_unit_list_) { delete hsha_server_unit; } } -void HshaServer :: RunForever() { +void HshaServer::RunForever() { hsha_server_acceptor_.LoopAccept(config_->GetBindIP(), config_->GetPort()); } -} //namespace phxrpc + +} //namespace phxrpc + diff --git a/phxrpc/rpc/hsha_server.h b/phxrpc/rpc/hsha_server.h index 059e8d6..c5fc519 100644 --- a/phxrpc/rpc/hsha_server.h +++ b/phxrpc/rpc/hsha_server.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,41 +21,44 @@ See the AUTHORS file for names of contributors. #pragma once -#include -#include -#include #include #include +#include +#include #include +#include #include + #include "server_config.h" #include "thread_queue.h" #include "phxrpc/network.h" -#include "phxrpc/http.h" +#include "phxrpc/msg.h" #include "server_base.h" #include "server_monitor.h" + namespace phxrpc { + class WorkerPool; -class DataFlow { -public: +class DataFlow final { + public: DataFlow(); ~DataFlow(); - void PushRequest(void * args, HttpRequest * request); - int PluckRequest(void *& args, HttpRequest *& request); - int PickRequest(void *& args, HttpRequest *& request); - void PushResponse(void * args, HttpResponse * response); - int PluckResponse(void *& args, HttpResponse *& response); + void PushRequest(void * args, BaseRequest * request); + int PluckRequest(void *& args, BaseRequest *& request); + int PickRequest(void *& args, BaseRequest *& request); + void PushResponse(void * args, BaseResponse * response); + int PluckResponse(void *& args, BaseResponse *& response); bool CanPushRequest(const int max_queue_length); bool CanPluckResponse(); void BreakOut(); -private: + private: struct QueueExtData { QueueExtData() { enqueue_time_ms = 0; @@ -68,20 +71,20 @@ class DataFlow { uint64_t enqueue_time_ms; void * args; }; - ThdQueue > in_queue_; - ThdQueue > out_queue_; + ThdQueue > in_queue_; + ThdQueue > out_queue_; }; ///////////////////////////////// -#define RPC_TIME_COST_CAL_RATE 1000 -#define QUEUE_WAIT_TIME_COST_CAL_RATE 1000 +#define RPC_TIME_COST_CAL_RATE 1000 +#define QUEUE_WAIT_TIME_COST_CAL_RATE 1000 #define MAX_QUEUE_WAIT_TIME_COST 500 -#define MAX_ACCEPT_QUEUE_LENGTH 102400 +#define MAX_ACCEPT_QUEUE_LENGTH 102400 -class HshaServerStat { -public: - HshaServerStat(const HshaServerConfig * config, ServerMonitorPtr hsha_server_monitor); +class HshaServerStat final { + public: + HshaServerStat(const HshaServerConfig *config, ServerMonitorPtr hsha_server_monitor); ~HshaServerStat(); void CalFunc(); @@ -95,7 +98,7 @@ class HshaServerStat { uint64_t now_time_ms_; }; -private: + private: void MonitorReport(); friend class HshaServerIO; @@ -103,7 +106,7 @@ class HshaServerStat { friend class Worker; friend class HshaServerQos; friend class HshaServerAcceptor; - const HshaServerConfig * config_; + //const HshaServerConfig *config_; std::mutex mutex_; std::condition_variable cv_; std::thread thread_; @@ -171,15 +174,19 @@ class HshaServerStat { std::atomic_int worker_drop_requests_; int worker_drop_reqeust_qps_; + std::atomic_long worker_time_costs_; + std::atomic_int worker_time_costs_count_; + int worker_avg_time_cost_per_second_; + int worker_time_cost_per_period_; long worker_time_costs_per_second_; }; ////////////////////////////////// -class HshaServerQos { -public: +class HshaServerQos final { + public: HshaServerQos(const HshaServerConfig * config, HshaServerStat * hsha_server_stat); ~HshaServerQos(); @@ -187,7 +194,7 @@ class HshaServerQos { bool CanAccept(); bool CanEnqueue(); -private: + private: const HshaServerConfig * config_; HshaServerStat * hsha_server_stat_; std::mutex mutex_; @@ -200,49 +207,49 @@ class HshaServerQos { ////////////////////////////////// -class Worker { -public: - Worker(WorkerPool * pool, int uthread_count, int utherad_stack_size); +class Worker final { + public: + Worker(WorkerPool *pool, int uthread_count, int utherad_stack_size); ~Worker(); - void Func(); + void Func(); void Shutdown(); void ThreadMode(); void UThreadMode(); void HandlerNewRequestFunc(); - void UThreadFunc(void * args, HttpRequest * request, int queue_wait_time_ms); - void WorkerLogic(void * args, HttpRequest * request, int queue_wait_time_ms); + void UThreadFunc(void *args, BaseRequest *req, int queue_wait_time_ms); + void WorkerLogic(void *args, BaseRequest *req, int queue_wait_time_ms); void Notify(); -private: - WorkerPool * pool_; + private: + WorkerPool *pool_; int uthread_count_; int utherad_stack_size_; bool shut_down_; - UThreadEpollScheduler * worker_scheduler_; + UThreadEpollScheduler *worker_scheduler_; std::thread thread_; }; ///////////////////////////////// -typedef std::function< void(const HttpRequest &, HttpResponse *, DispatcherArgs_t *) > Dispatch_t; +typedef std::function Dispatch_t; -class WorkerPool { -public: - WorkerPool(UThreadEpollScheduler * scheduler, - int thread_count, +class WorkerPool final { + public: + WorkerPool(UThreadEpollScheduler * scheduler, + int thread_count, int uthread_count_per_thread, int utherad_stack_size, - DataFlow * data_flow, - HshaServerStat * hsha_server_stat, - Dispatch_t dispatch, + DataFlow * data_flow, + HshaServerStat * hsha_server_stat, + Dispatch_t dispatch, void * args); ~WorkerPool(); void Notify(); -private: + private: friend class Worker; UThreadEpollScheduler * scheduler_; DataFlow * data_flow_; @@ -256,9 +263,9 @@ class WorkerPool { ///////////////////////////////// -class HshaServerIO { -public: - HshaServerIO(int idx, UThreadEpollScheduler * scheduler, const HshaServerConfig * config, +class HshaServerIO final { + public: + HshaServerIO(int idx, UThreadEpollScheduler * scheduler, const HshaServerConfig * config, DataFlow * data_flow, HshaServerStat * hsha_server_stat, HshaServerQos * hsha_server_qos, WorkerPool * worker_pool); ~HshaServerIO(); @@ -271,14 +278,14 @@ class HshaServerIO { void IOFunc(int accept_fd); - UThreadSocket_t * ActiveSocketFunc(); + UThreadSocket_t *ActiveSocketFunc(); -private: - int idx_; + private: + //int idx_; UThreadEpollScheduler * scheduler_; const HshaServerConfig * config_; DataFlow * data_flow_; - int listen_fd_; + //int listen_fd_; HshaServerStat * hsha_server_stat_; HshaServerQos * hsha_server_qos_; WorkerPool * worker_pool_; @@ -290,22 +297,22 @@ class HshaServerIO { ///////////////////////////////// class HshaServer; -class HshaServerUnit { -public: - HshaServerUnit(HshaServer * hsha_server, - int idx, - int worker_thread_count, +class HshaServerUnit final { + public: + HshaServerUnit(HshaServer *hsha_server, + int idx, + int worker_thread_count, int worker_uthread_count_per_thread, int worker_utherad_stack_size, - Dispatch_t dispatch, - void * args); + Dispatch_t dispatch, + void *args); ~HshaServerUnit(); void RunFunc(); bool AddAcceptedFd(int accepted_fd); -private: - HshaServer * hsha_server_; + private: + HshaServer *hsha_server_; UThreadEpollScheduler scheduler_; DataFlow data_flow_; WorkerPool worker_pool_; @@ -315,23 +322,23 @@ class HshaServerUnit { ///////////////////////////////// -class HshaServerAcceptor { -public: +class HshaServerAcceptor final { + public: HshaServerAcceptor(HshaServer * hsha_server); ~HshaServerAcceptor(); void LoopAccept(const char * bind_ip, const int port); -private: + private: HshaServer * hsha_server_; size_t idx_; }; ///////////////////////////////// -class HshaServer { -public: - HshaServer(const HshaServerConfig & config, Dispatch_t dispatch, void * args); +class HshaServer final { + public: + HshaServer(const HshaServerConfig &config, Dispatch_t dispatch, void *args); ~HshaServer(); void RunForever(); @@ -345,4 +352,6 @@ class HshaServer { std::vector server_unit_list_; }; -} //namespace phxrpc + +} //namespace phxrpc + diff --git a/phxrpc/rpc/http_caller.cpp b/phxrpc/rpc/http_caller.cpp index 44d1061..f2a9205 100644 --- a/phxrpc/rpc/http_caller.cpp +++ b/phxrpc/rpc/http_caller.cpp @@ -1,25 +1,26 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ #include + #include #include "http_caller.h" @@ -29,79 +30,85 @@ See the AUTHORS file for names of contributors. #include "phxrpc/http.h" #include "phxrpc/file.h" + namespace phxrpc { -HttpCaller::HttpCaller(BaseTcpStream & socket, ClientMonitor & client_monitor ) - : socket_(socket), client_monitor_(client_monitor), cmdid_(-1) { + +HttpCaller::HttpCaller(BaseTcpStream &socket, ClientMonitor &client_monitor) + : socket_(socket), client_monitor_(client_monitor), cmd_id_(-1) { } HttpCaller::~HttpCaller() { } -HttpRequest & HttpCaller::GetRequest() { - return request_; +HttpRequest &HttpCaller::GetRequest() { + return req_; } -HttpResponse & HttpCaller::GetResponse() { - return response_; +HttpResponse &HttpCaller::GetResponse() { + return resp_; } -void HttpCaller::MonitorReport( ClientMonitor & client_monitor, bool send_error, bool recv_error, size_t send_size, - size_t recv_size, uint64_t call_begin, uint64_t call_end ) { - - if ( send_error ) { +void HttpCaller::MonitorReport(ClientMonitor &client_monitor, bool send_error, + bool recv_error, size_t send_size, + size_t recv_size, uint64_t call_begin, + uint64_t call_end) { + if (send_error) { client_monitor.SendError(); } - if ( recv_error ) { + if (recv_error) { client_monitor.RecvError(); } - client_monitor.SendBytes( send_size ); - client_monitor.RecvBytes( recv_size ); - client_monitor.RequestCost( call_begin, call_end ); - if ( cmdid_ > 0 ) { - client_monitor.ClientCall( cmdid_, GetRequest().GetURI() ); + client_monitor.SendBytes(send_size); + client_monitor.RecvBytes(recv_size); + client_monitor.RequestCost(call_begin, call_end); + if (0 < cmd_id_) { + client_monitor.ClientCall(cmd_id_, GetRequest().GetURI()); } } -int HttpCaller::Call(const google::protobuf::MessageLite & request, google::protobuf::MessageLite * response) { - if (!request.SerializeToString(&request_.GetContent())) { +int HttpCaller::Call(const google::protobuf::MessageLite &req, + google::protobuf::MessageLite *resp) { + if (!req.SerializeToString(&req_.GetContent())) { return -1; } - uint64_t call_begin = Timer::GetSteadyClockMS(); - request_.AddHeader(HttpMessage::HEADER_CONTENT_LENGTH, request_.GetContent().size()); + uint64_t call_begin{Timer::GetSteadyClockMS()}; + req_.AddHeader(HttpMessage::HEADER_CONTENT_LENGTH, req_.GetContent().size()); HttpClient::PostStat post_stat; - int ret = HttpClient::Post(socket_, request_, &response_, &post_stat); - MonitorReport( client_monitor_, post_stat.send_error_, post_stat.recv_error_, request_.GetContent().size(), - response_.GetContent().size(), call_begin, Timer::GetSteadyClockMS() ); - - if (ret != 0) { - phxrpc::log( LOG_ERR, "ERROR: httpcall %d", ret ); + int ret{HttpClient::Post(socket_, req_, &resp_, &post_stat)}; + MonitorReport(client_monitor_, post_stat.send_error_, + post_stat.recv_error_, req_.GetContent().size(), + resp_.GetContent().size(), call_begin, + Timer::GetSteadyClockMS()); + + if (0 != ret) { + phxrpc::log(LOG_ERR, "http call err %d", ret); return ret; } - if (!response->ParseFromString(response_.GetContent())) { + if (!resp->ParseFromString(resp_.GetContent())) { return -1; } - const char * result = response_.GetHeaderValue(HttpMessage::HEADER_X_PHXRPC_RESULT); - ret = atoi(NULL == result ? "-1" : result); + const char *result{resp_.GetHeaderValue(HttpMessage::HEADER_X_PHXRPC_RESULT)}; + ret = atoi(nullptr == result ? "-1" : result); - if( ret < 0 ) { - phxrpc::log( LOG_ERR, "ERROR: httpcall( %s ) %d", request_.GetURI(), ret ); + if (ret < 0) { + phxrpc::log(LOG_ERR, "http call %s err %d", req_.GetURI(), ret); } return ret; } -void HttpCaller :: SetURI( const char * uri, int cmdid ) { - cmdid_ = cmdid; - GetRequest().SetURI( uri ); +void HttpCaller::SetURI(const char *uri, const int cmdid) { + cmd_id_ = cmdid; + GetRequest().SetURI(uri); } -void HttpCaller :: SetKeepAlive( const bool keep_alive ) { +void HttpCaller::SetKeepAlive(const bool keep_alive) { if (keep_alive) { GetRequest().AddHeader(HttpMessage::HEADER_CONNECTION, "Keep-Alive"); } else { @@ -109,4 +116,6 @@ void HttpCaller :: SetKeepAlive( const bool keep_alive ) { } } -} + +} // namespace phxrpc + diff --git a/phxrpc/rpc/http_caller.h b/phxrpc/rpc/http_caller.h index 9818fa5..bb1341f 100644 --- a/phxrpc/rpc/http_caller.h +++ b/phxrpc/rpc/http_caller.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -24,43 +24,55 @@ See the AUTHORS file for names of contributors. #include "client_monitor.h" #include "phxrpc/http.h" + namespace google { + namespace protobuf { + + class MessageLite; -}; -}; + + +} + +} + namespace phxrpc { + class BaseTcpStream; class HttpCaller { -public: - HttpCaller(BaseTcpStream & socket, ClientMonitor & client_monitor ); + public: + HttpCaller(BaseTcpStream &socket, ClientMonitor &client_monitor); + + virtual ~HttpCaller(); - ~HttpCaller(); + HttpRequest &GetRequest(); - HttpRequest & GetRequest(); + HttpResponse &GetResponse(); - HttpResponse & GetResponse(); + int Call(const google::protobuf::MessageLite &req, + google::protobuf::MessageLite *resp); - int Call(const google::protobuf::MessageLite & request, google::protobuf::MessageLite * response); + void SetURI(const char *uri, const int cmdid); - void SetURI( const char * uri, int cmdid ); + void SetKeepAlive(const bool keep_alive); - void SetKeepAlive( const bool keep_alive ); + private: + void MonitorReport(phxrpc::ClientMonitor &client_monitor, bool send_error, + bool recv_error, size_t send_size, size_t recv_size, + uint64_t call_begin, uint64_t call_end); -private: - void MonitorReport( phxrpc::ClientMonitor & client_monitor, bool send_error, bool recv_error, - size_t send_size, size_t recv_size, uint64_t call_begin, uint64_t call_end ); -private: - BaseTcpStream & socket_; - ClientMonitor & client_monitor_; - int cmdid_; + BaseTcpStream &socket_; + ClientMonitor &client_monitor_; + int cmd_id_; - HttpRequest request_; - HttpResponse response_; + HttpRequest req_; + HttpResponse resp_; }; -} + +} // namespace phxrpc diff --git a/phxrpc/rpc/monitor_factory.cpp b/phxrpc/rpc/monitor_factory.cpp index e07483f..9937432 100644 --- a/phxrpc/rpc/monitor_factory.cpp +++ b/phxrpc/rpc/monitor_factory.cpp @@ -1,57 +1,61 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include #include -#include #include "monitor_factory.h" + namespace phxrpc { -static MonitorFactory * g_monitor_factory_ = NULL; -MonitorFactory :: MonitorFactory() { +static MonitorFactory *g_monitor_factory_ = nullptr; + +MonitorFactory::MonitorFactory() { } -MonitorFactory :: ~MonitorFactory() { +MonitorFactory::~MonitorFactory() { } -void MonitorFactory :: SetFactory( MonitorFactory * factory ) { +void MonitorFactory::SetFactory(MonitorFactory *factory) { g_monitor_factory_ = factory; } -MonitorFactory * MonitorFactory :: GetFactory() { +MonitorFactory *MonitorFactory::GetFactory() { static MonitorFactory monitor_factory; - if ( !g_monitor_factory_ ) { + if (!g_monitor_factory_) { return &monitor_factory; } return g_monitor_factory_; } -ClientMonitorPtr MonitorFactory :: CreateClientMonitor( const char * package_name ) { - return ClientMonitorPtr( new ClientMonitor() ); +ClientMonitorPtr MonitorFactory::CreateClientMonitor(const char *package_name) { + return ClientMonitorPtr(new ClientMonitor()); } -ServerMonitorPtr MonitorFactory :: CreateServerMonitor( const char * package_name ) { - return ServerMonitorPtr( new ServerMonitor() ); +ServerMonitorPtr MonitorFactory::CreateServerMonitor(const char *package_name) { + return ServerMonitorPtr(new ServerMonitor()); } -} + +} // namespace phxrpc + diff --git a/phxrpc/rpc/monitor_factory.h b/phxrpc/rpc/monitor_factory.h index c1c9428..0f16b63 100644 --- a/phxrpc/rpc/monitor_factory.h +++ b/phxrpc/rpc/monitor_factory.h @@ -1,52 +1,54 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ #pragma once + +#include #include #include -#include #include "client_monitor.h" #include "server_monitor.h" + namespace phxrpc { typedef std::shared_ptr ServerMonitorPtr; class MonitorFactory { - public: + public: MonitorFactory(); virtual ~MonitorFactory(); - virtual ClientMonitorPtr CreateClientMonitor( const char * package_name ); - virtual ServerMonitorPtr CreateServerMonitor( const char * package_name ); + virtual ClientMonitorPtr CreateClientMonitor(const char *package_name); + virtual ServerMonitorPtr CreateServerMonitor(const char *package_name); - public: - static void SetFactory( MonitorFactory * factory ); + static void SetFactory(MonitorFactory *factory); - static MonitorFactory * GetFactory(); + static MonitorFactory *GetFactory(); }; -} +} // namespace phxrpc + diff --git a/phxrpc/rpc/mqtt_caller.cpp b/phxrpc/rpc/mqtt_caller.cpp new file mode 100644 index 0000000..249f615 --- /dev/null +++ b/phxrpc/rpc/mqtt_caller.cpp @@ -0,0 +1,199 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include + +#include + +#include "mqtt_caller.h" +#include "monitor_factory.h" + +#include "phxrpc/network.h" +#include "phxrpc/http.h" +#include "phxrpc/file.h" + + +namespace phxrpc { + + +MqttCaller::MqttCaller(BaseTcpStream &socket, ClientMonitor &client_monitor) + : socket_(socket), client_monitor_(client_monitor), cmd_id_(-1) { +} + +MqttCaller::~MqttCaller() { +} + +MqttConnect &MqttCaller::GetConnect() { + return connect_; +} + +MqttPublish &MqttCaller::GetPublish() { + return publish_; +} + +MqttDisconnect &MqttCaller::GetDisconnect() { + return disconnect_; +} + +MqttConnack &MqttCaller::GetConnack() { + return connack_; +} + +MqttPuback &MqttCaller::GetPuback() { + return puback_; +} + +void MqttCaller::MonitorReport(ClientMonitor &client_monitor, bool send_error, + bool recv_error, size_t send_size, + size_t recv_size, uint64_t call_begin, + uint64_t call_end) { + if (send_error) { + client_monitor.SendError(); + } + + if (recv_error) { + client_monitor.RecvError(); + } + + client_monitor.SendBytes(send_size); + client_monitor.RecvBytes(recv_size); + client_monitor.RequestCost(call_begin, call_end); + if (0 < cmd_id_) { + client_monitor.ClientCall(cmd_id_, ""); + } +} + +int MqttCaller::PhxMqttConnectCall(const phxrpc::MqttConnectPb &connect, + phxrpc::MqttConnackPb *connack) { + int ret{-1}; + + // unpack request + { + ret = static_cast(connect_.FromPb(connect)); + if (0 != ret) { + phxrpc::log(LOG_ERR, "FromPb err %d", ret); + + return ret; + } + } + + uint64_t call_begin{Timer::GetSteadyClockMS()}; + MqttClient::MqttStat mqtt_stat; + ret = MqttClient::Connect(socket_, connect_, connack_, mqtt_stat); + MonitorReport(client_monitor_, mqtt_stat.send_error_, + mqtt_stat.recv_error_, connect_.GetContent().size(), + connack_.GetContent().size(), call_begin, + Timer::GetSteadyClockMS()); + + if (0 != ret) { + phxrpc::log(LOG_ERR, "mqtt connect call err %d", ret); + return ret; + } + + // pack response + { + ret = static_cast(connack_.ToPb(connack)); + if (0 != ret) { + phxrpc::log(LOG_ERR, "ToPb ret %d", ret); + + return ret; + } + } + + return ret; +} + +int MqttCaller::PhxMqttPublishCall(const phxrpc::MqttPublishPb &publish, + phxrpc::MqttPubackPb *puback) { + int ret{-1}; + + // unpack request + { + ret = static_cast(publish_.FromPb(publish)); + if (0 != ret) { + phxrpc::log(LOG_ERR, "FromPb err %d", ret); + + return ret; + } + } + + uint64_t call_begin{Timer::GetSteadyClockMS()}; + MqttClient::MqttStat mqtt_stat; + publish_.set_packet_identifier(packet_identifier_++); + ret = MqttClient::Publish(socket_, publish_, puback_, mqtt_stat); + MonitorReport(client_monitor_, mqtt_stat.send_error_, + mqtt_stat.recv_error_, publish_.GetContent().size(), + puback_.GetContent().size(), call_begin, + Timer::GetSteadyClockMS()); + + if (0 != ret) { + phxrpc::log(LOG_ERR, "mqtt publish call err %d", ret); + return ret; + } + + // pack response + { + ret = static_cast(puback_.ToPb(puback)); + if (0 != ret) { + phxrpc::log(LOG_ERR, "ToPb ret %d", ret); + + return ret; + } + } + + return ret; +} + +int MqttCaller::PhxMqttDisconnectCall(const phxrpc::MqttDisconnectPb &disconnect) { + int ret{-1}; + + // unpack request + { + ret = static_cast(disconnect_.FromPb(disconnect)); + if (0 != ret) { + phxrpc::log(LOG_ERR, "FromPb err %d", ret); + + return ret; + } + } + + uint64_t call_begin{Timer::GetSteadyClockMS()}; + MqttClient::MqttStat mqtt_stat; + ret = MqttClient::Disconnect(socket_, disconnect_, mqtt_stat); + MonitorReport(client_monitor_, mqtt_stat.send_error_, + mqtt_stat.recv_error_, disconnect_.GetContent().size(), + 0, call_begin, Timer::GetSteadyClockMS()); + + if (0 != ret) { + phxrpc::log(LOG_ERR, "mqtt disconnect call err %d", ret); + return ret; + } + + return ret; +} + +void MqttCaller::SetCmdId(const int cmd_id) { + cmd_id_ = cmd_id; +} + + +} // namespace phxrpc + diff --git a/phxrpc/rpc/mqtt_caller.h b/phxrpc/rpc/mqtt_caller.h new file mode 100644 index 0000000..7b5e10d --- /dev/null +++ b/phxrpc/rpc/mqtt_caller.h @@ -0,0 +1,89 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include "phxrpc/mqtt.h" +#include "phxrpc/rpc/phxrpc.pb.h" + +#include "client_monitor.h" + + +namespace google { + +namespace protobuf { + + +class MessageLite; + + +} + +} + + +namespace phxrpc { + + +class BaseTcpStream; + +class MqttCaller { + public: + MqttCaller(BaseTcpStream &socket, ClientMonitor &client_monitor); + + virtual ~MqttCaller(); + + MqttConnect &GetConnect(); + MqttPublish &GetPublish(); + MqttDisconnect &GetDisconnect(); + + MqttConnack &GetConnack(); + MqttPuback &GetPuback(); + + int PhxMqttConnectCall(const phxrpc::MqttConnectPb &connect, + phxrpc::MqttConnackPb *connack); + int PhxMqttPublishCall(const phxrpc::MqttPublishPb &publish, + phxrpc::MqttPubackPb *puback); + int PhxMqttDisconnectCall(const phxrpc::MqttDisconnectPb &disconnect); + + void SetCmdId(const int cmd_id); + + private: + void MonitorReport(phxrpc::ClientMonitor &client_monitor, bool send_error, + bool recv_error, size_t send_size, size_t recv_size, + uint64_t call_begin, uint64_t call_end); + + BaseTcpStream &socket_; + ClientMonitor &client_monitor_; + int cmd_id_; + + MqttConnect connect_; + MqttConnack connack_; + MqttPublish publish_; + MqttPuback puback_; + MqttDisconnect disconnect_; + + uint16_t packet_identifier_{1}; +}; + + +} // namespace phxrpc + diff --git a/phxrpc/rpc/phxrpc.proto b/phxrpc/rpc/phxrpc.proto index 1a031c4..b25d1a6 100644 --- a/phxrpc/rpc/phxrpc.proto +++ b/phxrpc/rpc/phxrpc.proto @@ -3,6 +3,8 @@ syntax = "proto3"; package phxrpc; import "google/protobuf/descriptor.proto"; +import "google/protobuf/wrappers.proto"; + extend google.protobuf.MethodOptions { int32 CmdID = 2000000; @@ -10,3 +12,29 @@ extend google.protobuf.MethodOptions { string Usage = 2000002; } +message MqttConnectPb { + bool clean_session = 1; + uint32 keep_alive = 2; + string client_identifier = 3; + string proto_name = 4; + uint32 proto_level = 5; +} + +message MqttConnackPb { + bool session_present = 1; + uint32 connect_return_code = 2; +} + +message MqttPublishPb { + uint32 package_identifier = 1; + string topic_name = 2; + string content = 3; +} + +message MqttPubackPb { + uint32 package_identifier = 1; +} + +message MqttDisconnectPb { +} + diff --git a/phxrpc/rpc/server_config.cpp b/phxrpc/rpc/server_config.cpp index 9f14b9a..108aa71 100644 --- a/phxrpc/rpc/server_config.cpp +++ b/phxrpc/rpc/server_config.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -24,8 +24,10 @@ See the AUTHORS file for names of contributors. #include "server_config.h" #include "phxrpc/file.h" + namespace phxrpc { + ServerConfig::ServerConfig() { memset(bind_ip_, 0, sizeof(bind_ip_)); port_ = -1; @@ -37,7 +39,7 @@ ServerConfig::ServerConfig() { ServerConfig::~ServerConfig() { } -bool ServerConfig::Read(const char * config_file) { +bool ServerConfig::Read(const char *config_file) { Config config; if (!config.InitConfig(config_file)) { return false; @@ -48,7 +50,8 @@ bool ServerConfig::Read(const char * config_file) { succ &= config.ReadItem("Server", "Port", &port_); succ &= config.ReadItem("Server", "PackageName", package_name_, sizeof(package_name_)); config.ReadItem("Server", "MaxThreads", &max_threads_, 20); - config.ReadItem("Log", "LogDir", log_dir_, sizeof(log_dir_), "~/log"); + // TODO: + config.ReadItem("Log", "LogDir", log_dir_, sizeof(log_dir_), "/data1/mm64/walnuthe/log"); config.ReadItem("Log", "LogLevel", &log_level_, LOG_ERR); config.ReadItem("ServerTimeout", "SocketTimeoutMS", &socket_timeout_ms_, 5000); @@ -60,15 +63,15 @@ bool ServerConfig::Read(const char * config_file) { } } -bool ServerConfig :: DoRead(Config & config) { +bool ServerConfig::DoRead(Config &config) { return true; } -void ServerConfig::SetBindIP(const char * ip) { +void ServerConfig::SetBindIP(const char *ip) { snprintf(bind_ip_, sizeof(bind_ip_), "%s", ip); } -const char * ServerConfig::GetBindIP() const { +const char *ServerConfig::GetBindIP() const { return bind_ip_; } @@ -96,34 +99,31 @@ int ServerConfig::GetSocketTimeoutMS() const { return socket_timeout_ms_; } -void ServerConfig::SetPackageName(const char * package_name) { +void ServerConfig::SetPackageName(const char *package_name) { strncpy(package_name_,package_name, sizeof(package_name_) - 1); } -const char * ServerConfig :: GetPackageName() const { +const char *ServerConfig::GetPackageName() const { return package_name_; } -const char * ServerConfig :: GetLogDir() const -{ +const char *ServerConfig::GetLogDir() const { return log_dir_; } -void ServerConfig :: SetLogLevel( int log_level ) -{ +void ServerConfig::SetLogLevel(int log_level) { log_level_ = log_level; } -int ServerConfig :: GetLogLevel() const -{ +int ServerConfig::GetLogLevel() const { return log_level_; } ////////////////////////////////////////////////////// -HshaServerConfig :: HshaServerConfig() - : max_connections_(800000), - max_queue_length_(20480), +HshaServerConfig::HshaServerConfig() + : max_connections_(800000), + max_queue_length_(20480), fast_reject_threshold_ms_(20), fast_reject_adjust_rate_(5), io_thread_count_(3), @@ -131,10 +131,10 @@ HshaServerConfig :: HshaServerConfig() worker_uthread_stack_size_(64 * 1024) { } -HshaServerConfig :: ~HshaServerConfig() { +HshaServerConfig::~HshaServerConfig() { } -bool HshaServerConfig :: DoRead(Config & config) { +bool HshaServerConfig::DoRead(Config &config) { config.ReadItem("Server", "MaxConnections", &max_connections_, 800000); config.ReadItem("Server", "IOThreadCount", &io_thread_count_, 3); config.ReadItem("Server", "WorkerUThreadCount", &worker_uthread_count_, 0); @@ -145,62 +145,62 @@ bool HshaServerConfig :: DoRead(Config & config) { return true; } -void HshaServerConfig :: SetMaxConnections(const int max_connections) { +void HshaServerConfig::SetMaxConnections(const int max_connections) { max_connections_ = max_connections; } -int HshaServerConfig :: GetMaxConnections() const { +int HshaServerConfig::GetMaxConnections() const { return max_connections_; } -void HshaServerConfig :: SetMaxQueueLength(const int max_queue_length) { +void HshaServerConfig::SetMaxQueueLength(const int max_queue_length) { max_queue_length_ = max_queue_length; } -int HshaServerConfig :: GetMaxQueueLength() const { +int HshaServerConfig::GetMaxQueueLength() const { return max_queue_length_; } -void HshaServerConfig :: SetFastRejectThresholdMS(const int fast_reject_threshold_ms) { +void HshaServerConfig::SetFastRejectThresholdMS(const int fast_reject_threshold_ms) { fast_reject_threshold_ms_ = fast_reject_threshold_ms; } -int HshaServerConfig :: GetFastRejectThresholdMS() const { +int HshaServerConfig::GetFastRejectThresholdMS() const { return fast_reject_threshold_ms_; } -void HshaServerConfig :: SetFastRejectAdjustRate(const int fast_reject_adjust_rate) { +void HshaServerConfig::SetFastRejectAdjustRate(const int fast_reject_adjust_rate) { fast_reject_adjust_rate_ = fast_reject_adjust_rate; } -int HshaServerConfig :: GetFastRejectAdjustRate() const { +int HshaServerConfig::GetFastRejectAdjustRate() const { return fast_reject_adjust_rate_; } -void HshaServerConfig :: SetIOThreadCount(const int io_thread_count) { +void HshaServerConfig::SetIOThreadCount(const int io_thread_count) { io_thread_count_ = io_thread_count; } -int HshaServerConfig :: GetIOThreadCount() const { +int HshaServerConfig::GetIOThreadCount() const { return io_thread_count_; } -void HshaServerConfig :: SetWorkerUThreadCount(const int worker_uthread_count) { +void HshaServerConfig::SetWorkerUThreadCount(const int worker_uthread_count) { worker_uthread_count_ = worker_uthread_count; } -int HshaServerConfig :: GetWorkerUThreadCount() const { +int HshaServerConfig::GetWorkerUThreadCount() const { return worker_uthread_count_; } -void HshaServerConfig :: SetWorkerUThreadStackSize(const int worker_uthread_stack_size) -{ +void HshaServerConfig::SetWorkerUThreadStackSize(const int worker_uthread_stack_size) { worker_uthread_stack_size_ = worker_uthread_stack_size; } -int HshaServerConfig :: GetWorkerUThreadStackSize() const -{ +int HshaServerConfig::GetWorkerUThreadStackSize() const { return worker_uthread_stack_size_; } -} + +} // namespace phxrpc + diff --git a/phxrpc/rpc/server_config.h b/phxrpc/rpc/server_config.h index dc3d67a..35a8a45 100644 --- a/phxrpc/rpc/server_config.h +++ b/phxrpc/rpc/server_config.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,23 +21,26 @@ See the AUTHORS file for names of contributors. #pragma once -#include #include +#include + #include "phxrpc/file.h" + namespace phxrpc { + class ServerConfig { -public: + public: ServerConfig(); virtual ~ServerConfig(); - bool Read(const char * config_file); + bool Read(const char *config_file); - virtual bool DoRead(Config & config); + virtual bool DoRead(Config &config); - void SetBindIP(const char * ip); - const char * GetBindIP() const; + void SetBindIP(const char *ip); + const char *GetBindIP() const; void SetPort(int port); int GetPort() const; @@ -48,15 +51,15 @@ class ServerConfig { void SetSocketTimeoutMS(int socket_timeout_ms); int GetSocketTimeoutMS() const; - void SetPackageName(const char * package_name); - const char * GetPackageName() const; + void SetPackageName(const char *package_name); + const char *GetPackageName() const; - const char * GetLogDir() const; + const char *GetLogDir() const; - void SetLogLevel( int log_level ); + void SetLogLevel(int log_level); int GetLogLevel() const; -private: + private: char bind_ip_[32]; int port_; int max_threads_; @@ -66,12 +69,13 @@ class ServerConfig { int log_level_; }; + class HshaServerConfig : public ServerConfig { -public: + public: HshaServerConfig(); - ~HshaServerConfig(); + virtual ~HshaServerConfig() override; - bool DoRead(Config & config); + bool DoRead(Config &config); void SetMaxConnections(const int max_connections); int GetMaxConnections() const; @@ -94,7 +98,7 @@ class HshaServerConfig : public ServerConfig { void SetWorkerUThreadStackSize(const int worker_uthread_stack_size); int GetWorkerUThreadStackSize() const; -private: + private: int max_connections_; int max_queue_length_; int fast_reject_threshold_ms_; @@ -104,5 +108,6 @@ class HshaServerConfig : public ServerConfig { int worker_uthread_stack_size_; }; -} + +} // namespace phxrpc diff --git a/phxrpc/rpc/socket_stream_phxrpc.cpp b/phxrpc/rpc/socket_stream_phxrpc.cpp index 5257bf3..bf0b26d 100644 --- a/phxrpc/rpc/socket_stream_phxrpc.cpp +++ b/phxrpc/rpc/socket_stream_phxrpc.cpp @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -21,28 +21,37 @@ See the AUTHORS file for names of contributors. #include "socket_stream_phxrpc.h" + namespace phxrpc { -bool PhxrpcTcpUtils :: Open(BlockTcpStream * stream, const char * ip, unsigned short port, int connect_timeout_ms, - const char * bind_addr, int bind_port, ClientMonitor & client_monitor ) { - bool ret = BlockTcpUtils::Open( stream, ip, port, connect_timeout_ms, - bind_addr, bind_port ); - client_monitor.ClientConnect( ret ); + +bool PhxrpcTcpUtils::Open(BlockTcpStream *stream, const char *ip, + unsigned short port, int connect_timeout_ms, + const char *bind_addr, int bind_port, + ClientMonitor &client_monitor) { + bool ret = BlockTcpUtils::Open(stream, ip, port, connect_timeout_ms, + bind_addr, bind_port); + client_monitor.ClientConnect(ret); + return ret; } -bool PhxrpcTcpUtils :: Open(UThreadEpollScheduler * tt, UThreadTcpStream* stream, const char * ip, unsigned short port, - int connect_timeout_ms, ClientMonitor & client_monitor ) { - bool ret = UThreadTcpUtils::Open( tt, stream, ip, port, connect_timeout_ms ); +bool PhxrpcTcpUtils::Open(UThreadEpollScheduler *tt, UThreadTcpStream *stream, + const char *ip, unsigned short port, + int connect_timeout_ms, + ClientMonitor &client_monitor) { + bool ret = UThreadTcpUtils::Open(tt, stream, ip, port, connect_timeout_ms); if (!ret && errno == 0) { //normal active close client_monitor.ClientConnect(true); } else { client_monitor.ClientConnect(ret); } + return ret; } -} +} // namespace phxrpc + diff --git a/phxrpc/rpc/socket_stream_phxrpc.h b/phxrpc/rpc/socket_stream_phxrpc.h index 0a13ace..f031628 100644 --- a/phxrpc/rpc/socket_stream_phxrpc.h +++ b/phxrpc/rpc/socket_stream_phxrpc.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -24,15 +24,22 @@ See the AUTHORS file for names of contributors. #include "client_monitor.h" #include "phxrpc/network.h" + namespace phxrpc { -class PhxrpcTcpUtils { - public: - static bool Open(BlockTcpStream * stream, const char * ip, unsigned short port, int connect_timeout_ms, - const char * bind_addr, int bind_port, ClientMonitor & client_monitor ); - static bool Open(UThreadEpollScheduler * tt, UThreadTcpStream* stream, const char * ip, unsigned short port, - int connect_timeout_ms, ClientMonitor & client_monitor ); +class PhxrpcTcpUtils { + public: + static bool Open(BlockTcpStream *stream, const char *ip, + unsigned short port, int connect_timeout_ms, + const char *bind_addr, int bind_port, + ClientMonitor &client_monitor); + + static bool Open(UThreadEpollScheduler *tt, UThreadTcpStream *stream, + const char *ip, unsigned short port, + int connect_timeout_ms, ClientMonitor &client_monitor); }; -} + +} // namespace phxrpc + diff --git a/phxrpc/rpc/test_hsha_server.cpp b/phxrpc/rpc/test_hsha_server.cpp index e32d50a..56c9c57 100644 --- a/phxrpc/rpc/test_hsha_server.cpp +++ b/phxrpc/rpc/test_hsha_server.cpp @@ -1,44 +1,54 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include + #include "phxrpc/rpc.h" -#include + using namespace phxrpc; -void Dispatch(const HttpRequest & request, HttpResponse * response, void * args) { + +void Dispatch(const BaseRequest *req, BaseResponse *resp, void *args) { printf("dispatch args %p\n", args); - response->AddHeader(HttpMessage::HEADER_X_PHXRPC_RESULT, 0); + resp->SetPhxRpcResult(0); } -int main(int argc, char ** argv) { +int main(int argc, char **argv) { HshaServerConfig config; config.SetBindIP("127.0.0.1"); config.SetPort(26161); config.SetMaxThreads(2); + //config.SetLogDir("~/log"); + //config.SetLogLevel(3); printf("args %p\n", &config); + phxrpc::openlog(argv[0], config.GetLogDir(), config.GetLogLevel()); + HshaServer server(config, Dispatch, &config); server.RunForever(); - + + phxrpc::closelog(); + return 0; } + diff --git a/phxrpc/rpc/test_client.cpp b/phxrpc/rpc/test_http_client.cpp similarity index 58% rename from phxrpc/rpc/test_client.cpp rename to phxrpc/rpc/test_http_client.cpp index 3c6610d..d6d508c 100644 --- a/phxrpc/rpc/test_client.cpp +++ b/phxrpc/rpc/test_http_client.cpp @@ -1,26 +1,28 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include #include + +#include + #include #include "monitor_factory.h" @@ -29,30 +31,33 @@ See the AUTHORS file for names of contributors. #include "phxrpc/network.h" #include "phxrpc/http.h" + using namespace phxrpc; -int main(int argc, char ** argv) { - for (size_t i = 0; i < 20; i++) { + +int main(int argc, char **argv) { + for (size_t i{0}; 20 > i; ++i) { phxrpc::BlockTcpStream socket; - if(phxrpc::BlockTcpUtils::Open(&socket, "127.0.0.1", 26161, 200, NULL, 0)) { + if(phxrpc::BlockTcpUtils::Open(&socket, "127.0.0.1", 26161, 200, nullptr, 0)) { socket.SetTimeout(5000); - HttpRequest request; - HttpResponse response; + HttpRequest req; + HttpResponse resp; - request.GetContent() = "hello grpc"; - request.SetURI("abc"); - request.AddHeader(HttpMessage::HEADER_CONTENT_LENGTH, request.GetContent().size()); - int ret = HttpClient::Post(socket, request, &response); + req.GetContent() = "hello grpc"; + req.SetURI("abc"); + req.AddHeader(HttpMessage::HEADER_CONTENT_LENGTH, req.GetContent().size()); + int ret{HttpClient::Post(socket, req, &resp)}; if (ret != 0) { printf("post fail, %zu, ret %d\n", i, ret); continue; } - const char * result = response.GetHeaderValue(HttpMessage::HEADER_X_PHXRPC_RESULT); - ret = atoi(NULL == result ? "-1" : result); + const char *result{resp.GetHeaderValue(HttpMessage::HEADER_X_PHXRPC_RESULT)}; + ret = atoi(nullptr == result ? "-1" : result); printf("post ret %d\n", ret); } } return 0; } + diff --git a/phxrpc/rpc/test_mqtt_client.cpp b/phxrpc/rpc/test_mqtt_client.cpp new file mode 100644 index 0000000..d1eafb3 --- /dev/null +++ b/phxrpc/rpc/test_mqtt_client.cpp @@ -0,0 +1,101 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include + +#include + +#include + +#include "monitor_factory.h" +#include "http_caller.h" + +#include "phxrpc/network.h" +#include "phxrpc/mqtt.h" + + +using namespace phxrpc; + + +int main(int argc, char **argv) { + // 1. connect + + for (size_t i{0}; 20 > i; ++i) { + phxrpc::BlockTcpStream socket; + if(phxrpc::BlockTcpUtils::Open(&socket, "127.0.0.1", 26161, 200, nullptr, 0)) { + socket.SetTimeout(5000); + MqttConnect req; + MqttConnack resp; + + int ret{MqttClient::Connect(socket, req, resp)}; + if (0 != ret) { + printf("try %zu connect fail ret %d\n", i, ret); + continue; + } + + printf("try %zu connect ret %d connect_return_code %d\n", + i, ret, resp.connect_return_code()); + } + } + + // 2. publish + + for (size_t i{0}; 20 > i; ++i) { + phxrpc::BlockTcpStream socket; + if(phxrpc::BlockTcpUtils::Open(&socket, "127.0.0.1", 26161, 200, nullptr, 0)) { + socket.SetTimeout(5000); + MqttPublish req; + MqttPuback resp; + req.set_topic_name("test_topic_1"); + req.set_packet_identifier(i); + + int ret{MqttClient::Publish(socket, req, resp)}; + if (0 != ret) { + printf("try %zu publish fail ret %d\n", i, ret); + continue; + } + + printf("try %zu publish ret %d packet_identifier %u\n", + i, ret, resp.packet_identifier()); + } + } + + // 3. disconnect + + for (size_t i{0}; 20 > i; ++i) { + phxrpc::BlockTcpStream socket; + if(phxrpc::BlockTcpUtils::Open(&socket, "127.0.0.1", 26161, 200, nullptr, 0)) { + socket.SetTimeout(5000); + MqttDisconnect req; + + int ret{MqttClient::Disconnect(socket, req)}; + if (0 != ret) { + printf("try %zu disconnect fail ret %d\n", i, ret); + continue; + } + + printf("try %zu disconnect ret %d\n", i, ret); + } + } + + return 0; +} + diff --git a/phxrpc/rpc/test_thread_queue.cpp b/phxrpc/rpc/test_thread_queue.cpp index 5d5dc0e..d0d1177 100644 --- a/phxrpc/rpc/test_thread_queue.cpp +++ b/phxrpc/rpc/test_thread_queue.cpp @@ -1,35 +1,38 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include #include -#include -#include #include +#include + #include "thread_queue.h" + using namespace std; using namespace phxrpc; + class PluckThread { -public: + public: PluckThread(ThdQueue * thd_queue, const size_t thread_count) : thd_queue_(thd_queue) { for (size_t i = 0; i < thread_count; i++) { @@ -58,7 +61,7 @@ class PluckThread { } while (!thd_queue_->empty()); } -private: + private: ThdQueue * thd_queue_; vector thread_list_; }; @@ -74,3 +77,4 @@ int main(int argc, char ** argv) { return 0; } + diff --git a/phxrpc/rpc/uthread_caller.cpp b/phxrpc/rpc/uthread_caller.cpp index 01ce222..3330178 100644 --- a/phxrpc/rpc/uthread_caller.cpp +++ b/phxrpc/rpc/uthread_caller.cpp @@ -1,25 +1,25 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. */ -#include +#include #include "uthread_caller.h" #include "http_caller.h" @@ -27,18 +27,29 @@ See the AUTHORS file for names of contributors. #include "phxrpc/network.h" + namespace phxrpc { -UThreadCaller::UThreadCaller(UThreadEpollScheduler * uthread_scheduler, google::protobuf::MessageLite & request, - google::protobuf::MessageLite * response, ClientMonitor & client_monitor, const std::string & uri, int cmdid, - const Endpoint_t & ep, const int connect_timeout_ms, const int socket_timeout_ms, UThreadCallback callback, - void * args) + +using namespace std; + + +UThreadCaller::UThreadCaller(UThreadEpollScheduler *uthread_scheduler, + google::protobuf::MessageLite &request, + google::protobuf::MessageLite *response, + ClientMonitor &client_monitor, + const Protocol protocol, const string &uri, + const int cmd_id, const Endpoint_t &ep, + const int connect_timeout_ms, + const int socket_timeout_ms, + UThreadCallback callback, void *args) : uthread_scheduler_(uthread_scheduler), request_(&request), response_(response), client_monitor_(client_monitor), + protocol_(protocol), uri_(uri), - cmdid_(cmdid), + cmd_id_(cmd_id), ep_(ep), mconnect_timeout_ms(connect_timeout_ms), msocket_timeout_ms(socket_timeout_ms), @@ -50,27 +61,27 @@ UThreadCaller::UThreadCaller(UThreadEpollScheduler * uthread_scheduler, google:: UThreadCaller::~UThreadCaller() { } -google::protobuf::MessageLite & UThreadCaller::GetRequest() { +google::protobuf::MessageLite &UThreadCaller::GetRequest() { return *request_; } -google::protobuf::MessageLite * UThreadCaller::GetResponse() { +google::protobuf::MessageLite *UThreadCaller::GetResponse() { return response_; } -const std::string & UThreadCaller::GetURI() { +const string &UThreadCaller::GetURI() { return uri_; } int UThreadCaller::GetCmdID() { - return cmdid_; + return cmd_id_; } -UThreadEpollScheduler * UThreadCaller::Getuthread_scheduler() { +UThreadEpollScheduler *UThreadCaller::Getuthread_scheduler() { return uthread_scheduler_; } -Endpoint_t * UThreadCaller::GetEP() { +Endpoint_t *UThreadCaller::GetEP() { return &ep_; } @@ -83,27 +94,29 @@ void UThreadCaller::SetRet(const int ret) { } void UThreadCaller::Callback() { - if (NULL != callback_) { + if (nullptr != callback_) { callback_(this, args_); } } -void UThreadCaller::Call(void * args) { - UThreadCaller * uthread_caller = (UThreadCaller *) args; +void UThreadCaller::Call(void *args) { + UThreadCaller *uthread_caller = (UThreadCaller *)args; UThreadTcpStream socket; - Endpoint_t * ep = uthread_caller->GetEP(); - bool open_ret = phxrpc::UThreadTcpUtils::Open(uthread_caller->Getuthread_scheduler(), &socket, ep->ip, ep->port, - uthread_caller->mconnect_timeout_ms ); - if ( open_ret ) { + Endpoint_t *ep = uthread_caller->GetEP(); + bool open_ret = phxrpc::UThreadTcpUtils::Open( + uthread_caller->Getuthread_scheduler(), &socket, ep->ip, ep->port, + uthread_caller->mconnect_timeout_ms); + if (open_ret) { socket.SetTimeout(uthread_caller->msocket_timeout_ms); phxrpc::HttpCaller caller(socket, uthread_caller->client_monitor_); caller.GetRequest().SetURI(uthread_caller->GetURI().c_str()); - uthread_caller->SetRet(caller.Call(uthread_caller->GetRequest(), uthread_caller->GetResponse())); + uthread_caller->SetRet(caller.Call(uthread_caller->GetRequest(), + uthread_caller->GetResponse())); } else { uthread_caller->SetRet(-1); } - uthread_caller->client_monitor_.ClientConnect( open_ret ); + uthread_caller->client_monitor_.ClientConnect(open_ret); uthread_caller->Callback(); } @@ -119,8 +132,8 @@ UThreadMultiCaller::UThreadMultiCaller( ClientMonitor & client_monitor ) } UThreadMultiCaller::~UThreadMultiCaller() { - for (size_t i = 0; i < uthread_caller_list_.size(); i++) { - if (NULL != uthread_caller_list_[i]) { + for (size_t i{0}; i < uthread_caller_list_.size(); ++i) { + if (nullptr != uthread_caller_list_[i]) { delete uthread_caller_list_[i]; } } @@ -135,21 +148,27 @@ const int UThreadMultiCaller::GetRet(size_t index) { return uthread_caller_list_[index]->GetRet(); } -void UThreadMultiCaller::AddCaller(google::protobuf::MessageLite & request, google::protobuf::MessageLite * response, - const std::string & uri, int cmdid, const Endpoint_t & ep, const int connect_timeout_ms, - const int socket_timeout_ms, UThreadCallback callback, void * args) { - UThreadCaller * caller = new UThreadCaller(&uthread_scheduler_, request, response, client_monitor_, uri, cmdid, - ep, connect_timeout_ms, socket_timeout_ms, callback, args); - assert(NULL != caller); +void UThreadMultiCaller::AddCaller(google::protobuf::MessageLite &request, + google::protobuf::MessageLite *response, + const Protocol protocol, const string &uri, + const int cmd_id, const Endpoint_t &ep, + const int connect_timeout_ms, + const int socket_timeout_ms, + UThreadCallback callback, void *args) { + UThreadCaller *caller = new UThreadCaller(&uthread_scheduler_, + request, response, client_monitor_, protocol, uri, cmd_id, ep, + connect_timeout_ms, socket_timeout_ms, callback, args); + assert(nullptr != caller); uthread_caller_list_.push_back(caller); - uthread_scheduler_.AddTask(UThreadCaller::Call, (void *) caller); + uthread_scheduler_.AddTask(UThreadCaller::Call, (void *)caller); } void UThreadMultiCaller::MultiCall() { uthread_scheduler_.Run(); } + } diff --git a/phxrpc/rpc/uthread_caller.h b/phxrpc/rpc/uthread_caller.h index 579c288..8458186 100644 --- a/phxrpc/rpc/uthread_caller.h +++ b/phxrpc/rpc/uthread_caller.h @@ -1,19 +1,19 @@ /* -Tencent is pleased to support the open source community by making +Tencent is pleased to support the open source community by making PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. +Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may obtain a copy of the License at https://opensource.org/licenses/BSD-3-Clause -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing permissions and limitations under the License. See the AUTHORS file for names of contributors. @@ -23,86 +23,111 @@ See the AUTHORS file for names of contributors. #include #include -#include "client_config.h" + +#include "phxrpc/msg/common.h" #include "phxrpc/network.h" +#include "client_config.h" + + namespace google { + namespace protobuf { + + class MessageLite; + + } -; + } -; + namespace phxrpc { + class UThreadEpollScheduler; class UThreadCaller; class ClientMonitor; -typedef void (*UThreadCallback)(UThreadCaller * caller, void * args); +class MqttConnect; +class MqttConnack; +class MqttPublish; +class MqttPuback; +class MqttDisconnect; + +typedef void (*UThreadCallback)(UThreadCaller *caller, void *args); class UThreadCaller { - public: - UThreadCaller(UThreadEpollScheduler * uthread_scheduler, google::protobuf::MessageLite & request, - google::protobuf::MessageLite * response, ClientMonitor & client_monitor, const std::string & uri, int cmdid, - const Endpoint_t & ep, const int connect_timeout_ms, const int socket_timeout_ms, UThreadCallback callback, void * args); + public: + UThreadCaller(UThreadEpollScheduler *uthread_scheduler, + google::protobuf::MessageLite &request, + google::protobuf::MessageLite *response, + ClientMonitor &client_monitor, + const Protocol protocol, const std::string &uri, + const int cmd_id, const Endpoint_t &ep, + const int connect_timeout_ms, const int socket_timeout_ms, + UThreadCallback callback, void *args); virtual ~UThreadCaller(); void Close(); - virtual google::protobuf::MessageLite & GetRequest(); - virtual google::protobuf::MessageLite * GetResponse(); - const std::string & GetURI(); + virtual google::protobuf::MessageLite &GetRequest(); + virtual google::protobuf::MessageLite *GetResponse(); + const std::string &GetURI(); int GetCmdID(); - UThreadEpollScheduler * Getuthread_scheduler(); - Endpoint_t * GetEP(); + UThreadEpollScheduler *Getuthread_scheduler(); + Endpoint_t *GetEP(); const int GetRet(); void SetRet(const int ret); void Callback(); - static void Call(void * args); - - private: - UThreadEpollScheduler * uthread_scheduler_; - google::protobuf::MessageLite * request_; - google::protobuf::MessageLite * response_; - ClientMonitor & client_monitor_; - std::string uri_; - int cmdid_; - Endpoint_t ep_; + static void Call(void *args); - public: int mconnect_timeout_ms; int msocket_timeout_ms; - private: + private: + UThreadEpollScheduler *uthread_scheduler_; + google::protobuf::MessageLite *request_; + google::protobuf::MessageLite *response_; + ClientMonitor &client_monitor_; + Protocol protocol_; + std::string uri_; + int cmd_id_; + Endpoint_t ep_; + int call_ret_; UThreadCallback callback_; - void * args_; + void *args_; }; /////////////////////////////////////////////////////// class UThreadMultiCaller { - public: - UThreadMultiCaller( ClientMonitor & client_monitor ); - ~UThreadMultiCaller(); + public: + UThreadMultiCaller(ClientMonitor &client_monitor); + virtual ~UThreadMultiCaller(); - void AddCaller(google::protobuf::MessageLite & request, google::protobuf::MessageLite * response, const std::string & uri, - int cmdid, const Endpoint_t & ep, const int connect_timeout_ms, const int socket_timeout_ms, - UThreadCallback callback = NULL, void * args = NULL); + void AddCaller(google::protobuf::MessageLite &request, + google::protobuf::MessageLite *response, + const Protocol protocol, const std::string &uri, + const int cmd_id, const Endpoint_t &ep, + const int connect_timeout_ms, const int socket_timeout_ms, + UThreadCallback callback = nullptr, void *args = nullptr); void MultiCall(); const int GetRet(size_t index); - private: + private: UThreadEpollScheduler uthread_scheduler_; std::vector uthread_caller_list_; ClientMonitor & client_monitor_; }; + } + diff --git a/sample/regen.sh b/sample/regen.sh index a1aa26b..9909cbd 100755 --- a/sample/regen.sh +++ b/sample/regen.sh @@ -2,6 +2,6 @@ test -f Makefile && make clean rm -f *.h *.cc *.cpp Makefile *.conf -../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . +../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . -u diff --git a/sample/search.proto b/sample/search.proto index 93614dd..4300787 100644 --- a/sample/search.proto +++ b/sample/search.proto @@ -14,6 +14,7 @@ enum SiteType { VIDEO = 2; UNKNOWN = 3; } + message Site { string url = 1; string title = 2; @@ -24,21 +25,24 @@ message Site { message SearchRequest { string query = 1; } + message SearchResult { repeated Site sites = 1; } -service Search{ - rpc Search( SearchRequest ) returns( SearchResult ) { - option( phxrpc.CmdID ) = 1; - option( phxrpc.OptString ) = "q:"; - option( phxrpc.Usage ) = "-q "; +service Search { + + rpc Search(SearchRequest) returns (SearchResult) { + option(phxrpc.CmdID) = 1; + option(phxrpc.OptString) = "q:"; + option(phxrpc.Usage) = "-q "; } - rpc Notify( google.protobuf.StringValue ) returns( google.protobuf.Empty ) { - option( phxrpc.CmdID ) = 2; - option( phxrpc.OptString ) = "m:"; - option( phxrpc.Usage ) = "-m "; + rpc Notify(google.protobuf.StringValue) returns (google.protobuf.Empty) { + option(phxrpc.CmdID) = 2; + option(phxrpc.OptString) = "m:"; + option(phxrpc.Usage) = "-m "; } + } From f04afd62f448b4761ea4d2ef3d0b8458e7cefc7b Mon Sep 17 00:00:00 2001 From: taohe Date: Thu, 7 Dec 2017 12:56:28 +0800 Subject: [PATCH 40/49] add mqtt protocol --- phxrpc/msg/base_msg.cpp | 114 ++++++++++++++++++++++++++ phxrpc/msg/base_msg.h | 139 ++++++++++++++++++++++++++++++++ phxrpc/msg/base_protocol.cpp | 38 +++++++++ phxrpc/msg/base_protocol.h | 42 ++++++++++ phxrpc/msg/common.h | 65 +++++++++++++++ phxrpc/msg/protocol_factory.cpp | 48 +++++++++++ phxrpc/msg/protocol_factory.h | 62 ++++++++++++++ 7 files changed, 508 insertions(+) create mode 100644 phxrpc/msg/base_msg.cpp create mode 100644 phxrpc/msg/base_msg.h create mode 100644 phxrpc/msg/base_protocol.cpp create mode 100644 phxrpc/msg/base_protocol.h create mode 100644 phxrpc/msg/common.h create mode 100644 phxrpc/msg/protocol_factory.cpp create mode 100644 phxrpc/msg/protocol_factory.h diff --git a/phxrpc/msg/base_msg.cpp b/phxrpc/msg/base_msg.cpp new file mode 100644 index 0000000..fc904e9 --- /dev/null +++ b/phxrpc/msg/base_msg.cpp @@ -0,0 +1,114 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include +#include +#include + +#include "base_msg.h" + + +namespace phxrpc { + + +using namespace std; + + +BaseMessage::BaseMessage() { +} + +BaseMessage::~BaseMessage() { +} + +void BaseMessage::SetVersion(const char *version) { + snprintf(version_, sizeof(version_), "%s", version); +} + +const char *BaseMessage::GetVersion() const { + return version_; +} + +void BaseMessage::SetClientIP(const char *client_ip) { + if (client_ip != nullptr) { + snprintf(client_ip_, sizeof(client_ip_), "%s", client_ip); + } +} + +const char *BaseMessage::GetClientIP() const { + return client_ip_; +} + +void BaseMessage::AppendContent(const void *content, const int length, const int max_length) { + int valid_length{length}; + if (valid_length <= 0) + valid_length = strlen((char *)content); + + int total = content_.size() + valid_length; + total = total > max_length ? total : max_length; + + //content_.reserve(total); + + content_.append((char *) content, valid_length); +} + +void BaseMessage::SetContent(const void *content, const int length) { + content_.clear(); + content_.append((char *)content, length); +} + +const string &BaseMessage::GetContent() const { + return content_; +} + +string &BaseMessage::GetContent() { + return content_; +} + + +BaseRequest::BaseRequest(const BaseMessage::Protocol protocol) { + set_direction(BaseMessage::Direction::REQUEST); + set_protocol(protocol); +} + +BaseRequest::~BaseRequest() { +} + +void BaseRequest::SetURI(const char *uri) { + if (nullptr != uri) { + uri_ = string(uri); + } +} + +const char *BaseRequest::GetURI() const { + return uri_.c_str(); +} + + +BaseResponse::BaseResponse(const BaseMessage::Protocol protocol) { + set_direction(BaseMessage::Direction::RESPONSE); + set_protocol(protocol); +} + +BaseResponse::~BaseResponse() {} + + +} + diff --git a/phxrpc/msg/base_msg.h b/phxrpc/msg/base_msg.h new file mode 100644 index 0000000..ca62d63 --- /dev/null +++ b/phxrpc/msg/base_msg.h @@ -0,0 +1,139 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include +#include + +#include "phxrpc/network.h" + +#include "common.h" + + +namespace google { + +namespace protobuf { + +class Message; + +} // protobuf + +} // google + + +namespace phxrpc { + + +class BaseMessage { + public: + enum class Direction { + NONE = 0, + REQUEST, + RESPONSE, + MAX, + }; + + enum class Protocol { + NONE = 0, + HTTP_GET = 101, + HTTP_POST = 102, + HTTP_HEAD = 103, + MQTT_CONNECT = 201, + MQTT_PUBLISH = 202, + MQTT_PUBREL = 203, + MQTT_SUBSCRIBE = 204, + MQTT_UNSUBSCRIBE = 205, + MQTT_PING = 206, + MQTT_DISCONNECT = 207, + MQTT_FAKE_DISCONNACK = 208, + MAX, + }; + + BaseMessage(); + virtual ~BaseMessage(); + + virtual ReturnCode Send(BaseTcpStream &socket) const = 0; + virtual ReturnCode ToPb(google::protobuf::Message *const message) const = 0; + virtual ReturnCode FromPb(const google::protobuf::Message &message) = 0; + + void SetVersion(const char *version); + const char *GetVersion() const; + + void SetClientIP(const char *client_ip); + const char *GetClientIP() const; + + void AppendContent(const void *content, const int length = 0, const int max_length = 0); + void SetContent(const void *content, const int length = 0); + const std::string &GetContent() const; + std::string &GetContent(); + + Direction direction() const { return direction_; } + Protocol protocol() const { return protocol_; } + bool fake() const { return fake_; }; + + protected: + void set_direction(const Direction direction) { direction_ = direction; } + void set_protocol(const Protocol protocol) { protocol_ = protocol; } + void set_fake(const bool fake) { fake_ = fake; } + + char client_ip_[16]; + + private: + Direction direction_{Direction::NONE}; + Protocol protocol_{Protocol::NONE}; + char version_[16]; + std::string content_; + bool fake_{false}; +}; + + +class BaseResponse; + +class BaseRequest : virtual public BaseMessage { + public: + BaseRequest(const Protocol protocol); + virtual ~BaseRequest() override; + + void SetURI(const char *uri); + const char *GetURI() const; + + virtual BaseResponse *GenResponse() const = 0; + virtual int IsKeepAlive() const = 0; + + private: + std::string uri_; +}; + + +class BaseResponse : virtual public BaseMessage { + public: + BaseResponse(const Protocol protocol); + virtual ~BaseResponse() override; + + virtual void SetPhxRpcResult(const int result) = 0; + virtual void DispatchErr() = 0; + virtual ReturnCode ModifyResp(const bool keep_alive, const std::string &version) = 0; +}; + + +} + diff --git a/phxrpc/msg/base_protocol.cpp b/phxrpc/msg/base_protocol.cpp new file mode 100644 index 0000000..b10d23f --- /dev/null +++ b/phxrpc/msg/base_protocol.cpp @@ -0,0 +1,38 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include "base_protocol.h" + +#include +#include +#include +#include +#include +#include + +#include "phxrpc/file/log_utils.h" + + +namespace phxrpc { + + +} + diff --git a/phxrpc/msg/base_protocol.h b/phxrpc/msg/base_protocol.h new file mode 100644 index 0000000..a5659ac --- /dev/null +++ b/phxrpc/msg/base_protocol.h @@ -0,0 +1,42 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include "base_msg.h" + +#include "phxrpc/network.h" + + +namespace phxrpc { + + +class BaseProtocol { + public: + BaseProtocol() = default; + virtual ~BaseProtocol() = default; + + virtual ReturnCode ServerRecv(BaseTcpStream &socket, BaseRequest *&req) = 0; +}; + + +} + diff --git a/phxrpc/msg/common.h b/phxrpc/msg/common.h new file mode 100644 index 0000000..111c517 --- /dev/null +++ b/phxrpc/msg/common.h @@ -0,0 +1,65 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + + +namespace phxrpc { + + +enum class ReturnCode { + OK = 0, + ERROR = -1, + ERROR_UNIMPLEMENT = -101, + ERROR_STEAM_BAD_OR_FAILED = -102, + ERROR_LENGTH_OVERFLOW = -103, + ERROR_SOCKET_STREAM_TIMEOUT = -202, + ERROR_SOCKET_STREAM_NORMAL_CLOSED = -303, + MAX, +}; + + +enum class Direction { + NONE = 0, + REQUEST, + RESPONSE, + MAX, +}; + +enum class Protocol { + NONE = 0, + HTTP_GET = 101, + HTTP_POST = 102, + HTTP_HEAD = 103, + MQTT_CONNECT = 201, + MQTT_PUBLISH = 202, + MQTT_PUBREL = 203, + MQTT_SUBSCRIBE = 204, + MQTT_UNSUBSCRIBE = 205, + MQTT_PING = 206, + MQTT_DISCONNECT = 207, + MQTT_FAKE_DISCONNACK = 208, + MAX, +}; + + +} + diff --git a/phxrpc/msg/protocol_factory.cpp b/phxrpc/msg/protocol_factory.cpp new file mode 100644 index 0000000..97c3c3b --- /dev/null +++ b/phxrpc/msg/protocol_factory.cpp @@ -0,0 +1,48 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#include "phxrpc/http.h" +#include "phxrpc/mqtt.h" + + +namespace phxrpc { + + +BaseProtocolFactory *BaseProtocolFactory::CreateFactory(UThreadTcpStream &in_stream) { + char c{in_stream.peek()}; + if ('P' == c || 'G' == c || 'H' == c) { // look for POST GET HEAD + return new HttpProtocolFactory; + } + + return new MqttProtocolFactory; +} + +BaseProtocol *HttpProtocolFactory::GenProtocol() { + return new HttpProtocol; +} + +BaseProtocol *MqttProtocolFactory::GenProtocol() { + return new MqttProtocol; +} + + +} + diff --git a/phxrpc/msg/protocol_factory.h b/phxrpc/msg/protocol_factory.h new file mode 100644 index 0000000..70887b8 --- /dev/null +++ b/phxrpc/msg/protocol_factory.h @@ -0,0 +1,62 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + + +namespace phxrpc { + + +class BaseRequest; +class BaseProtocol; + + +class BaseProtocolFactory { + public: + BaseProtocolFactory() = default; + virtual ~BaseProtocolFactory() = default; + + static BaseProtocolFactory *CreateFactory(UThreadTcpStream &in_stream); + + virtual BaseProtocol *GenProtocol() = 0; +}; + + +class HttpProtocolFactory : public BaseProtocolFactory { + public: + HttpProtocolFactory() = default; + virtual ~HttpProtocolFactory() = default; + + virtual BaseProtocol *GenProtocol() override; +}; + + +class MqttProtocolFactory : public BaseProtocolFactory { + public: + MqttProtocolFactory() = default; + virtual ~MqttProtocolFactory() = default; + + virtual BaseProtocol *GenProtocol() override; +}; + + +} + From 333b1db128e90cf8377e41484d4dc2255ac89952 Mon Sep 17 00:00:00 2001 From: taohe Date: Thu, 7 Dec 2017 13:05:14 +0800 Subject: [PATCH 41/49] add mqtt protocol --- .gitignore | 4 ++ phxrpc/msg/base_dispatcher.h | 88 ++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 phxrpc/msg/base_dispatcher.h diff --git a/.gitignore b/.gitignore index 0820720..107caae 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ *.a *.pb.* *_dispatcher.* +!base_dispatcher.* +!http_dispatcher.* +!mqtt_dispatcher.* *_stub.* *_service.* *_tool.* @@ -9,3 +12,4 @@ third_party/* sbin/* sample/* + diff --git a/phxrpc/msg/base_dispatcher.h b/phxrpc/msg/base_dispatcher.h new file mode 100644 index 0000000..82836e5 --- /dev/null +++ b/phxrpc/msg/base_dispatcher.h @@ -0,0 +1,88 @@ +/* +Tencent is pleased to support the open source community by making +PhxRPC available. +Copyright (C) 2016 THL A29 Limited, a Tencent company. +All rights reserved. + +Licensed under the BSD 3-Clause License (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at + +https://opensource.org/licenses/BSD-3-Clause + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + +See the AUTHORS file for names of contributors. +*/ + +#pragma once + +#include +#include + +#include "base_msg.h" + + +namespace phxrpc { + + +template +class BaseDispatcher { + public: + typedef int (Dispatcher::*URIFunc_t)(const BaseRequest *req, BaseResponse *resp); + typedef int (Dispatcher::*MqttFunc_t)(const BaseRequest *req, BaseResponse *resp); + + typedef std::map URIFuncMap; + typedef std::map MqttFuncMap; + + BaseDispatcher(Dispatcher &dispatcher, const URIFuncMap &uri_func_map, + const MqttFuncMap &mqtt_func_map) + : dispatcher_(dispatcher), uri_func_map_(uri_func_map), + mqtt_func_map_(mqtt_func_map) { + } + + virtual ~BaseDispatcher() = default; + + bool Dispatch(const BaseRequest *req, BaseResponse *resp) { + int ret{-1}; + + if (BaseMessage::Protocol::HTTP_POST == req->protocol() || + BaseMessage::Protocol::HTTP_GET == req->protocol() || + BaseMessage::Protocol::HTTP_HEAD == req->protocol()) { + typename URIFuncMap::const_iterator iter(uri_func_map_.find(req->GetURI())); + + if (uri_func_map_.end() != iter) { + ret = (dispatcher_.*iter->second)(req, resp); + } + + resp->SetPhxRpcResult(ret); + + return uri_func_map_.end() != iter; + } else { + typename MqttFuncMap::const_iterator iter(mqtt_func_map_.find(req->protocol())); + + if (mqtt_func_map_.end() != iter) { + ret = (dispatcher_.*iter->second)(req, resp); + } + + resp->SetPhxRpcResult(ret); + + return mqtt_func_map_.end() != iter; + } + + return ret; + } + + private: + Dispatcher &dispatcher_; + const URIFuncMap &uri_func_map_; + const MqttFuncMap &mqtt_func_map_; +}; + + +} // namespace phxrpc + From cb00c89b9607a70150a0160d932f867a08af7923 Mon Sep 17 00:00:00 2001 From: taohe Date: Thu, 7 Dec 2017 14:19:00 +0800 Subject: [PATCH 42/49] add mqtt protocol --- phxrpc/mqtt/mqtt_msg.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/phxrpc/mqtt/mqtt_msg.cpp b/phxrpc/mqtt/mqtt_msg.cpp index ac7b8f8..70dd15b 100644 --- a/phxrpc/mqtt/mqtt_msg.cpp +++ b/phxrpc/mqtt/mqtt_msg.cpp @@ -306,13 +306,14 @@ ReturnCode MqttMessage::SendFixedHeaderAndRemainingBuffer( const string &remaining_buffer) { char fixed_header{FixedHeader[static_cast(control_packet_type)]}; ReturnCode ret{SendChar(out_stream, fixed_header)}; - // TODO: - printf("%s:%d test4 type %d fixed_header %u\n", __func__, __LINE__, - static_cast(control_packet_type), static_cast(fixed_header)); if (ReturnCode::OK != ret) { phxrpc::log(LOG_ERR, "SendChar err %d", ret); return ret; + } else { + phxrpc::log(LOG_DEBUG, "SendChar type %d fixed_header %u", + static_cast(control_packet_type), + static_cast(fixed_header)); } const int remaining_length{static_cast(remaining_buffer.size())}; @@ -345,15 +346,15 @@ ReturnCode MqttMessage::RecvFixedHeaderAndRemainingBuffer( return ret; } - // TODO: - printf("%s:%d test4 fixed_header %u\n", __func__, __LINE__, static_cast(fixed_header)); uint8_t temp{fixed_header}; temp >>= 4; temp &= 0x0f; // must convert to unsigned first control_packet_type = static_cast(temp); - // TODO: - printf("%s:%d test4 type %d\n", __func__, __LINE__, static_cast(control_packet_type)); + + phxrpc::log(LOG_DEBUG, "RecvChar type %d fixed_header %u", + static_cast(control_packet_type), + static_cast(fixed_header)); int remaining_length{0}; ret = RecvRemainingLength(in_stream, remaining_length); From f323428a482b36254d83f6b7044396b0ca6f645c Mon Sep 17 00:00:00 2001 From: taohe Date: Thu, 7 Dec 2017 14:33:23 +0800 Subject: [PATCH 43/49] add mqtt protocol --- phxrpc/http.h | 1 - phxrpc/http/http_dispatcher.h | 69 --------------------------------- phxrpc/http/http_protocol.cpp | 2 +- phxrpc/mqtt/mqtt_msg.cpp | 4 +- phxrpc/msg/protocol_factory.cpp | 2 +- 5 files changed, 4 insertions(+), 74 deletions(-) delete mode 100644 phxrpc/http/http_dispatcher.h diff --git a/phxrpc/http.h b/phxrpc/http.h index 88b8950..46a26d7 100644 --- a/phxrpc/http.h +++ b/phxrpc/http.h @@ -22,7 +22,6 @@ See the AUTHORS file for names of contributors. #pragma once #include "http/http_client.h" -//#include "http/http_dispatcher.h" #include "http/http_msg.h" #include "http/http_protocol.h" diff --git a/phxrpc/http/http_dispatcher.h b/phxrpc/http/http_dispatcher.h deleted file mode 100644 index a840fa3..0000000 --- a/phxrpc/http/http_dispatcher.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Tencent is pleased to support the open source community by making -PhxRPC available. -Copyright (C) 2016 THL A29 Limited, a Tencent company. -All rights reserved. - -Licensed under the BSD 3-Clause License (the "License"); you may -not use this file except in compliance with the License. You may -obtain a copy of the License at - -https://opensource.org/licenses/BSD-3-Clause - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" basis, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied. See the License for the specific language governing -permissions and limitations under the License. - -See the AUTHORS file for names of contributors. -*/ - -#pragma once - -#include -#include - -#include "http_msg.h" - - -namespace phxrpc { - - -template -class HttpDispatcher { - public: - typedef int (Dispatcher::*URIFunc_t)(const HttpRequest &request, HttpResponse *response); - - typedef std::map URIFuncMap; - - HttpDispatcher(Dispatcher &dispatcher, const URIFuncMap &uri_func_map) - : dispatcher_(dispatcher), - uri_func_map_(uri_func_map) { - } - - virtual ~HttpDispatcher() { - } - - bool Dispatch(const HttpRequest &request, HttpResponse *response) { - int ret = -1; - - typename URIFuncMap::const_iterator iter = uri_func_map_.find(request.GetURI()); - - if (uri_func_map_.end() != iter) { - ret = (dispatcher_.*iter->second)(request, response); - } - - response->AddHeader(HttpMessage::HEADER_X_PHXRPC_RESULT, ret); - - return uri_func_map_.end() != iter;; - } - - private: - Dispatcher &dispatcher_; - const URIFuncMap &uri_func_map_; -}; - - -} // namespace phxrpc - diff --git a/phxrpc/http/http_protocol.cpp b/phxrpc/http/http_protocol.cpp index 635e0a5..e9c07ce 100644 --- a/phxrpc/http/http_protocol.cpp +++ b/phxrpc/http/http_protocol.cpp @@ -294,7 +294,7 @@ ReturnCode HttpProtocol::RecvBody(BaseTcpStream &socket, HttpMessage *msg) { if (!is_good) break; - int size{strtol(buff, nullptr, 16)}; + int size{static_cast(strtol(buff, nullptr, 16))}; if (size > 0) { for (; size > 0;) { int read_len = size > MAX_RECV_LEN ? MAX_RECV_LEN : size; diff --git a/phxrpc/mqtt/mqtt_msg.cpp b/phxrpc/mqtt/mqtt_msg.cpp index 70dd15b..e1513d8 100644 --- a/phxrpc/mqtt/mqtt_msg.cpp +++ b/phxrpc/mqtt/mqtt_msg.cpp @@ -346,7 +346,7 @@ ReturnCode MqttMessage::RecvFixedHeaderAndRemainingBuffer( return ret; } - uint8_t temp{fixed_header}; + uint8_t temp{static_cast(fixed_header)}; temp >>= 4; temp &= 0x0f; // must convert to unsigned first @@ -380,7 +380,7 @@ ReturnCode MqttMessage::SendRemainingLength(BaseTcpStream &out_stream, const int remaining_length) { char temp{0x0}; char continue_bit{0x0}; - uint32_t temp_remaining_length{remaining_length}; + uint32_t temp_remaining_length{static_cast(remaining_length)}; for (int i{0}; 4 > i; ++i) { temp = (temp_remaining_length & 0x7f); diff --git a/phxrpc/msg/protocol_factory.cpp b/phxrpc/msg/protocol_factory.cpp index 97c3c3b..51512f3 100644 --- a/phxrpc/msg/protocol_factory.cpp +++ b/phxrpc/msg/protocol_factory.cpp @@ -27,7 +27,7 @@ namespace phxrpc { BaseProtocolFactory *BaseProtocolFactory::CreateFactory(UThreadTcpStream &in_stream) { - char c{in_stream.peek()}; + char c{static_cast(in_stream.peek())}; if ('P' == c || 'G' == c || 'H' == c) { // look for POST GET HEAD return new HttpProtocolFactory; } From a1cbdc55e3e664978970812cce19eff3d7249762 Mon Sep 17 00:00:00 2001 From: taohe Date: Thu, 7 Dec 2017 15:20:32 +0800 Subject: [PATCH 44/49] add mqtt protocol --- README.md | 145 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 31f0cfc..6f7b196 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,22 @@ PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https://travis-ci.org/tencent-wechat/phxrpc) -# 总览 +## 总览 + - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 - 半同步半异步模式,采用独立多IO线程,通过Epoll管理请求的接入以及读写,工作线程采用固定线程池。IO线程与工作线程通过内存队列进行交互。 - 提供完善的过载保护,无需配置阈值,支持动态自适应拒绝请求。 - 提供简易的Client/Server配置读入方式。 + - 支持HTTP和MQTT协议。 - 基于lambda函数实现并发访问Server,可以非常方便地实现Google提出的 [Backup Requests](http://static.googleusercontent.com/media/research.google.com/zh-CN//people/jeff/Berkeley-Latency-Mar2012.pdf) 模式。 -# 局限 +## 局限 + - 不支持多进程模式。 - -# 性能 + +## 性能 + >使用Sample目录下的Search RPC C/S进行Echo RPC调用的压测,相当于Worker空转情况。 ### 运行环境 @@ -48,26 +52,33 @@ PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https:/ | system | 55k | 160k | 360k | 500k | | boost | 62k | 175k | 410k | 500k | -# 如何编译 -#### Protobuf准备 +## 如何编译 + +### Protobuf准备 + PhxRPC必须依赖的第三方库只有Protobuf。在编译前,在third_party目录放置好protobuf目录,或者通过软链的形式。 -#### boost优化 +### boost优化 + PhxRPC在ServerIO以及Client并发连接管理上使用了ucontext,而boost的ucontext实现要比system默认的更为高效,推荐使用boost。如果需要使用boost的话需要在third_party目录放置好boost目录,或者通过软链的形式。 -#### 编译环境 +### 编译环境 + - Linux. - GCC-4.8及以上版本。 - boost 1.56及以上版本.(可选) -#### 编译安装方法 +### 编译安装方法 + 进入PhxRPC根目录。 make (默认是-O2编译,如需编译debug版,执行 make debug=y) - make boost (可选,编译PhxRPC的boost优化插件,编译之前先准备好boost库) - -# 如何使用 -#### 编写proto文件 + make boost (可选,编译PhxRPC的boost优化插件,编译之前先准备好boost库) + +## 如何使用 + +### 编写proto文件 + 下面是sample目录下的proto文件样例。 ```c++ @@ -83,36 +94,41 @@ enum SiteType { VIDEO = 2; UNKNOWN = 3; } + message Site { string url = 1; string title = 2; SiteType type = 3; tring summary = 4; } + message SearchRequest { string query = 1; } + message SearchResult { repeated Site sites = 1; } -service Search{ - rpc Search( SearchRequest ) returns( SearchResult ) { - option( phxrpc.CmdID ) = 1; - option( phxrpc.OptString ) = "q:"; - option( phxrpc.Usage ) = "-q "; - } - rpc Notify( google.protobuf.StringValue ) returns( google.protobuf.Empty ) { - option( phxrpc.CmdID ) = 2; - option( phxrpc.OptString ) = "m:"; - option( phxrpc.Usage ) = "-m "; - } + +service Search { + rpc Search(SearchRequest) returns (SearchResult) { + option(phxrpc.CmdID) = 1; + option(phxrpc.OptString) = "q:"; + option(phxrpc.Usage) = "-q "; + } + rpc Notify(google.protobuf.StringValue) returns (google.protobuf.Empty) { + option(phxrpc.CmdID) = 2; + option(phxrpc.OptString) = "m:"; + option(phxrpc.Usage) = "-m "; + } } ``` -#### 生成代码 + +### 生成代码 ```bash -(PhxRPC根目录)/codegen/phxrpc_pb2server +(PhxRPC根目录)/codegen/phxrpc_pb2server -I (PhxRPC根目录) -I (Protobuf include目录) -f (proto文件路径) -d (生成代码放置路径) #sample @@ -121,82 +137,85 @@ service Search{ 调用完工具后,在生成代码放置目录下执行make,即可生成全部的RPC相关代码。 ``` -#### 选择是否启用boost优化 +### 选择是否启用boost优化 + 打开生成代码放置目录下的Makefile文件。 + ```bash #choose to use boost for network #LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS) ``` + 可以看到以上两行,取消注释掉第二行,重新make clean, make即可开启boost对PhxRPC的优化。开启前记得编译好PhxRPC的boost插件。 -#### 补充自己的代码 -##### Server(xxx_service_impl.cpp) +### 补充自己的代码 + +#### Server(xxx_service_impl.cpp) ```c++ -int SearchServiceImpl :: PhxEcho( const google::protobuf::StringValue & req, - google::protobuf::StringValue * resp ) -{ - resp->set_value( req.value() ); +int SearchServiceImpl::PhxEcho(const google::protobuf::StringValue &req, + google::protobuf::StringValue *resp) { + resp->set_value(req.value()); return 0; } -int SearchServiceImpl :: Search( const search::SearchRequest & req, - search::SearchResult * resp ) -{ - //这里补充这个RPC调用的Server端代码 - return -1; +int SearchServiceImpl::Search(const search::SearchRequest &req, + search::SearchResult *resp) { + // 这里补充这个RPC调用的Server端代码 + return -1; } -int SearchServiceImpl :: Notify( const google::protobuf::StringValue & req, - google::protobuf::Empty * resp ) -{ - //这里补充这个RPC调用的Server端代码 - return -1; +int SearchServiceImpl::Notify(const google::protobuf::StringValue &req, + google::protobuf::Empty *resp) { + // 这里补充这个RPC调用的Server端代码 + return -1; } ``` -##### Client (xxx_client.cpp) +如果要使用MQTT协议,可对应编写`PhxMqttXxx`实现。 + +#### Client (xxx_client.cpp) ```c++ -//这个是默认生成的代码, 可自行修改,或利用我们提供的stub API自定义封装Client -int SearchClient :: PhxEcho( const google::protobuf::StringValue & req, - google::protobuf::StringValue * resp ) -{ - const phxrpc::Endpoint_t * ep = global_searchclient_config_.GetRandom(); +// 这个是默认生成的代码,可自行修改,或利用我们提供的stub API自定义封装Client +int SearchClient::PhxEcho(const google::protobuf::StringValue &req, + google::protobuf::StringValue *resp) { + const phxrpc::Endpoint_t *ep = global_searchclient_config_.GetRandom(); - if(ep != nullptr) { + if (ep != nullptr) { phxrpc::BlockTcpStream socket; bool open_ret = phxrpc::PhxrpcTcpUtils::Open(&socket, ep->ip, ep->port, - global_searchclient_config_.GetConnectTimeoutMS(), NULL, 0, + global_searchclient_config_.GetConnectTimeoutMS(), nullptr, 0, *(global_searchclient_monitor_.get())); - if ( open_ret ) { + if (open_ret) { socket.SetTimeout(global_searchclient_config_.GetSocketTimeoutMS()); SearchStub stub(socket, *(global_searchclient_monitor_.get())); return stub.PhxEcho(req, resp); - } - } + } + } - return -1; + return -1; } ``` -##### Client并发调用样例 +如果要使用MQTT协议,可对应编写`PhxMqttXxx`实现。 + +#### Client并发调用样例 ```c++ -int SearchClient :: PhxBatchEcho( const google::protobuf::StringValue & req, - google::protobuf::StringValue * resp ) -{ - int ret = -1; +int SearchClient::PhxBatchEcho(const google::protobuf::StringValue &req, + google::protobuf::StringValue *resp) { + int ret = -1; size_t echo_server_count = 2; uthread_begin; for (size_t i = 0; i < echo_server_count; i++) { uthread_t [=, &uthread_s, &ret](void *) { - const phxrpc::Endpoint_t * ep = global_searchclient_config_.GetByIndex(i); + const phxrpc::Endpoint_t *ep = global_searchclient_config_.GetByIndex(i); if (ep != nullptr) { phxrpc::UThreadTcpStream socket; if(phxrpc::PhxrpcTcpUtils::Open(&uthread_s, &socket, ep->ip, ep->port, - global_searchclient_config_.GetConnectTimeoutMS(), + global_searchclient_config_.GetConnectTimeoutMS(), *(global_searchclient_monitor_.get()))) { socket.SetTimeout(global_searchclient_config_.GetSocketTimeoutMS()); SearchStub stub(socket, *(global_searchclient_monitor_.get())); @@ -220,7 +239,7 @@ int SearchClient :: PhxBatchEcho( const google::protobuf::StringValue & req, 当然你可以借用这4个宏定义,以同步代码的写法,进行更自定义的并发访问。 -##### Server配置说明 (xxx_server.conf) +#### Server配置说明 (xxx_server.conf) ```c++ [Server] From a12789a1a5d012240933679e3291f6bad7145652 Mon Sep 17 00:00:00 2001 From: taohe Date: Fri, 8 Dec 2017 14:49:38 +0800 Subject: [PATCH 45/49] fix mqtt protocol --- README.md | 74 +++++++++++++++++++++++++-------- codegen/server_template.cpp | 8 ++-- codegen/service_code_render.cpp | 20 +++++---- phxrpc/msg/base_dispatcher.h | 20 +++++---- 4 files changed, 84 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 6f7b196..cebe014 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,19 @@ 联系我们:phxteam@tencent.com -想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/tencent-wechat/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 +想了解更多, 以及更详细的编译手册,请进入[中文WIKI](https://github.com/Tencent/phxrpc/wiki),和扫描右侧二维码关注我们的公众号 -PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https://travis-ci.org/tencent-wechat/phxrpc) +PhxRPC[![Build Status](https://travis-ci.org/Tencent/phxrpc.png)](https://travis-ci.org/Tencent/phxrpc) ## 总览 - 使用Protobuf作为IDL用于描述RPC接口以及通信数据结构。 - 基于Protobuf文件自动生成Client以及Server接口,用于Client的构建,以及Server的实现。 - 半同步半异步模式,采用独立多IO线程,通过Epoll管理请求的接入以及读写,工作线程采用固定线程池。IO线程与工作线程通过内存队列进行交互。 + - 支持协程Worker,可配置多个线程,每个线程多个协程。 - 提供完善的过载保护,无需配置阈值,支持动态自适应拒绝请求。 + - New: 支持HTTP和MQTT协议。 - 提供简易的Client/Server配置读入方式。 - - 支持HTTP和MQTT协议。 - 基于lambda函数实现并发访问Server,可以非常方便地实现Google提出的 [Backup Requests](http://static.googleusercontent.com/media/research.google.com/zh-CN//people/jeff/Berkeley-Latency-Mar2012.pdf) 模式。 ## 局限 @@ -29,6 +30,7 @@ PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https:/ >使用Sample目录下的Search RPC C/S进行Echo RPC调用的压测,相当于Worker空转情况。 ### 运行环境 + CPU:24 x Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz 内存:32 GB 网卡:千兆网卡 @@ -38,6 +40,7 @@ PhxRPC[![Build Status](https://travis-ci.org/tencent-wechat/phxrpc.png)](https:/ Worker线程数:20 ### 性能测试结果(qps) + #### 短连接 | ucontext类型/IO线程 | 1 | 3 | 8 | 20 | @@ -128,12 +131,15 @@ service Search { ### 生成代码 ```bash -(PhxRPC根目录)/codegen/phxrpc_pb2server --I (PhxRPC根目录) -I (Protobuf include目录) -f (proto文件路径) -d (生成代码放置路径) +(PhxRPC根目录)/codegen/phxrpc_pb2server -I (PhxRPC根目录) -I (Protobuf include目录) -f (proto文件路径) -d (生成代码放置路径) -#sample +# sample ../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . +../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . -u +两种生成模式,区别在于-u参数。 +第一种生成默认的线程池worker模型。 +第二种-u参数指定生成uthread worker模型,也就是工作线程池里面每个线程里面运行着多个协程。 调用完工具后,在生成代码放置目录下执行make,即可生成全部的RPC相关代码。 ``` @@ -172,12 +178,13 @@ int SearchServiceImpl::Notify(const google::protobuf::StringValue &req, } ``` -如果要使用MQTT协议,可对应编写`PhxMqttXxx`实现。 +如果要使用MQTT协议,可对应补充`PhxMqttXxx`实现。 #### Client (xxx_client.cpp) ```c++ // 这个是默认生成的代码,可自行修改,或利用我们提供的stub API自定义封装Client + int SearchClient::PhxEcho(const google::protobuf::StringValue &req, google::protobuf::StringValue *resp) { const phxrpc::Endpoint_t *ep = global_searchclient_config_.GetRandom(); @@ -199,7 +206,38 @@ int SearchClient::PhxEcho(const google::protobuf::StringValue &req, } ``` -如果要使用MQTT协议,可对应编写`PhxMqttXxx`实现。 +如果要使用MQTT协议,可对应补充`PhxMqttXxx`实现。 + +#### UThread Client (xxx_client_uthread.cpp) + +```c++ +// 这个是默认生成的代码,可自行修改,或利用我们提供的stub API自定义封装Client +// UThread Client只能在采用PhxRPC uthread worker模型的server中调用。 +// UThread Client构造函数需要传入UThreadEpollScheduler*类型参数, +// 这个参数来源可以在xxx_service_impl.h的私有变量中获得。 + +int SearchClientUThread::PhxEcho(const google::protobuf::StringValue &req, + google::protobuf::StringValue *resp) { + const phxrpc::Endpoint_t *ep = global_searchclientuthread_config_.GetRandom(); + + if (uthread_scheduler_ != nullptr && ep != nullptr) { + phxrpc::UThreadTcpStream socket; + bool open_ret = phxrpc::PhxrpcTcpUtils::Open(uthread_scheduler_, &socket, ep->ip, ep->port, + global_searchclientuthread_config_.GetConnectTimeoutMS(), + *(global_searchclientuthread_monitor_.get())); + if (open_ret) { + socket.SetTimeout(global_searchclientuthread_config_.GetSocketTimeoutMS()); + + SearchStub stub(socket, *(global_searchclientuthread_monitor_.get())); + return stub.PhxEcho(req, resp); + } + } + + return -1; +} +``` + +如果要使用MQTT协议,可对应补充`PhxMqttXxx`实现。 #### Client并发调用样例 @@ -243,16 +281,18 @@ int SearchClient::PhxBatchEcho(const google::protobuf::StringValue &req, ```c++ [Server] -BindIP = 127.0.0.1 //Server IP -Port = 16161 //Server Port -MaxThreads = 16 //Worker 线程数 -IOThreadCount = 3 //IO线程数,针对业务请自行调节 -PackageName = search //Server 名字,用于自行实现的监控统计上报 -MaxConnections = 800000 //最大并发连接数 -MaxQueueLength = 20480 //IO队列最大长度 -FastRejectThresholdMS = 20 //快速拒绝自适应调节阀值,建议保持默认20ms,不做修改 +BindIP = 127.0.0.1 // Server IP +Port = 16161 // Server Port +MaxThreads = 16 // Worker 线程数 +WorkerUThreadCount = 50     // 每个线程开启的协程数,采用-u生成的Server必须配置这一项 +WorkerUThreadStackSize = 65536 // UThread worker的栈大小 +IOThreadCount = 3               // IO线程数,针对业务请自行调节 +PackageName = search // Server 名字,用于自行实现的监控统计上报 +MaxConnections = 800000 // 最大并发连接数 +MaxQueueLength = 20480 // IO队列最大长度 +FastRejectThresholdMS = 20 // 快速拒绝自适应调节阀值,建议保持默认20ms,不做修改 [ServerTimeout] -SocketTimeoutMS = 5000 //Server读写超时,Worker处理超时 +SocketTimeoutMS = 5000 // Server读写超时,Worker处理超时 ``` diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index f9bdfba..1e3133a 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -48,8 +48,8 @@ void Dispatch(const phxrpc::BaseRequest *request, $DispatcherClass$ dispatcher(service, args); phxrpc::BaseDispatcher<$DispatcherClass$> base_dispatcher( - dispatcher, $DispatcherClass$::GetURIFuncMap(), - $DispatcherClass$::GetMqttFuncMap()); + dispatcher, $DispatcherClass$::GetMqttFuncMap(), + $DispatcherClass$::GetURIFuncMap()); if (!base_dispatcher.Dispatch(request, response)) { response->DispatchErr(); } @@ -142,8 +142,8 @@ void Dispatch(const phxrpc::BaseRequest *request, $DispatcherClass$ dispatcher(service, args); phxrpc::BaseDispatcher<$DispatcherClass$> base_dispatcher( - dispatcher, $DispatcherClass$::GetURIFuncMap(), - $DispatcherClass$::GetMqttFuncMap()); + dispatcher, $DispatcherClass$::GetMqttFuncMap(), + $DispatcherClass$::GetURIFuncMap()); if (!base_dispatcher.Dispatch(request, response)) { response->DispatchErr(); } diff --git a/codegen/service_code_render.cpp b/codegen/service_code_render.cpp index 2dd65d6..e9c70f2 100644 --- a/codegen/service_code_render.cpp +++ b/codegen/service_code_render.cpp @@ -395,16 +395,19 @@ void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree *stree, FILE *write) { fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); - fprintf(write, " int PhxMqttConnect(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp);\n"); - fprintf(write, " int PhxMqttPublish(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp);\n"); - fprintf(write, " int PhxMqttDisconnect(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp);\n"); + fprintf(write, " int PhxMqttConnect(const phxrpc::BaseRequest *const req, " + "phxrpc::BaseResponse *const resp);\n"); + fprintf(write, " int PhxMqttPublish(const phxrpc::BaseRequest *const req, " + "phxrpc::BaseResponse *const resp);\n"); + fprintf(write, " int PhxMqttDisconnect(const phxrpc::BaseRequest *const req, " + "phxrpc::BaseResponse *const resp);\n"); fprintf(write, "\n"); SyntaxFuncVector *flist{stree->GetFuncList()}; auto fit(flist->cbegin()); for (; flist->cend() != fit; ++fit) { - fprintf(write, " int %s(const phxrpc::BaseRequest *request, " - "phxrpc::BaseResponse *response);\n", + fprintf(write, " int %s(const phxrpc::BaseRequest *const request, " + "phxrpc::BaseResponse *const response);\n", fit->GetName()); } fprintf(write, "\n"); @@ -559,7 +562,8 @@ void ServiceCodeRender::GenerateMqttDispatcherFunc(SyntaxTree *stree, name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "int %s::%s(const phxrpc::BaseRequest *req, phxrpc::BaseResponse *resp) {\n", + fprintf(write, "int %s::%s(const phxrpc::BaseRequest *const req, " + "phxrpc::BaseResponse *const resp) {\n", clasname, func->GetName()); fprintf(write, " dispatcher_args_->server_monitor->SvrCall(%d, \"%s\", 1);\n", func->GetCmdID(), func->GetName()); @@ -622,8 +626,8 @@ void ServiceCodeRender::GenerateDispatcherFunc(SyntaxTree *stree, name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "int %s::%s(const phxrpc::BaseRequest *request, " - "phxrpc::BaseResponse *response) {\n", + fprintf(write, "int %s::%s(const phxrpc::BaseRequest *const request, " + "phxrpc::BaseResponse *const response) {\n", clasname, func->GetName()); fprintf(write, " dispatcher_args_->server_monitor->SvrCall(%d, \"%s\", 1);\n", diff --git a/phxrpc/msg/base_dispatcher.h b/phxrpc/msg/base_dispatcher.h index 82836e5..f01fb03 100644 --- a/phxrpc/msg/base_dispatcher.h +++ b/phxrpc/msg/base_dispatcher.h @@ -33,21 +33,23 @@ namespace phxrpc { template class BaseDispatcher { public: - typedef int (Dispatcher::*URIFunc_t)(const BaseRequest *req, BaseResponse *resp); - typedef int (Dispatcher::*MqttFunc_t)(const BaseRequest *req, BaseResponse *resp); + typedef int (Dispatcher::*MqttFunc_t)(const BaseRequest *const req, + BaseResponse *const resp); + typedef int (Dispatcher::*URIFunc_t)(const BaseRequest *const req, + BaseResponse *const resp); - typedef std::map URIFuncMap; typedef std::map MqttFuncMap; + typedef std::map URIFuncMap; - BaseDispatcher(Dispatcher &dispatcher, const URIFuncMap &uri_func_map, - const MqttFuncMap &mqtt_func_map) - : dispatcher_(dispatcher), uri_func_map_(uri_func_map), - mqtt_func_map_(mqtt_func_map) { + BaseDispatcher(Dispatcher &dispatcher, const MqttFuncMap &mqtt_func_map, + const URIFuncMap &uri_func_map) + : dispatcher_(dispatcher), mqtt_func_map_(mqtt_func_map), + uri_func_map_(uri_func_map) { } virtual ~BaseDispatcher() = default; - bool Dispatch(const BaseRequest *req, BaseResponse *resp) { + bool Dispatch(const BaseRequest *const req, BaseResponse *const resp) { int ret{-1}; if (BaseMessage::Protocol::HTTP_POST == req->protocol() || @@ -79,8 +81,8 @@ class BaseDispatcher { private: Dispatcher &dispatcher_; - const URIFuncMap &uri_func_map_; const MqttFuncMap &mqtt_func_map_; + const URIFuncMap &uri_func_map_; }; From d4cdd289e336829900b9ffc5021dfa0a639159d5 Mon Sep 17 00:00:00 2001 From: taohe Date: Fri, 8 Dec 2017 17:33:03 +0800 Subject: [PATCH 46/49] add option for generating mqtt protocol --- README.md | 11 +++-- codegen/client_code_render.cpp | 2 - codegen/phxrpc_pb2client.cpp | 68 ++++++++++++++++++------------- codegen/phxrpc_pb2server.cpp | 15 +++---- codegen/phxrpc_pb2service.cpp | 70 ++++++++++++++++++-------------- codegen/phxrpc_pb2tool.cpp | 71 +++++++++++++++++++-------------- codegen/server_template.cpp | 16 ++++---- codegen/service_code_render.cpp | 59 ++++++++++++++------------- codegen/service_code_render.h | 4 +- codegen/tool_code_render.cpp | 2 - 10 files changed, 179 insertions(+), 139 deletions(-) diff --git a/README.md b/README.md index cebe014..ce5070a 100644 --- a/README.md +++ b/README.md @@ -137,10 +137,15 @@ service Search { ../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . ../codegen/phxrpc_pb2server -I ../ -I ../third_party/protobuf/include -f search.proto -d . -u -两种生成模式,区别在于-u参数。 +两种生成模式,区别在于`-u`参数。 + 第一种生成默认的线程池worker模型。 -第二种-u参数指定生成uthread worker模型,也就是工作线程池里面每个线程里面运行着多个协程。 + +第二种`-u`参数指定生成uthread worker模型,也就是工作线程池里面每个线程里面运行着多个协程。 + 调用完工具后,在生成代码放置目录下执行make,即可生成全部的RPC相关代码。 + +`-p mqtt`可生成支持MQTT协议的代码。 ``` ### 选择是否启用boost优化 @@ -148,7 +153,7 @@ service Search { 打开生成代码放置目录下的Makefile文件。 ```bash -#choose to use boost for network +# choose to use boost for network #LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS) ``` diff --git a/codegen/client_code_render.cpp b/codegen/client_code_render.cpp index 4e87f0f..d01fb6d 100644 --- a/codegen/client_code_render.cpp +++ b/codegen/client_code_render.cpp @@ -96,7 +96,6 @@ void ClientCodeRender::GenerateStubHpp(SyntaxTree *stree, GetStubFuncDeclaration(stree, &(*mqtt_it), 1, &buffer); fprintf(write, " %s;\n", buffer.c_str()); } - fprintf(write, "\n"); SyntaxFuncVector *flist{stree->GetFuncList()}; auto fit(flist->cbegin()); @@ -268,7 +267,6 @@ void ClientCodeRender::GenerateClientHpp(SyntaxTree *stree, declarations.append(" ").append(buffer).append(";\n"); } - declarations.append("\n"); } { diff --git a/codegen/phxrpc_pb2client.cpp b/codegen/phxrpc_pb2client.cpp index e0290c9..018a9e8 100644 --- a/codegen/phxrpc_pb2client.cpp +++ b/codegen/phxrpc_pb2client.cpp @@ -19,12 +19,13 @@ permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include +#include + #include #include #include -#include #include -#include #include "syntax_tree.h" #include "name_render.h" @@ -41,18 +42,20 @@ void PrintHelp(const char *program) { printf("\n"); printf("PhxRPC ProtoBuf tool\n"); printf("\n"); - printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); - printf(" Usage: -f # Proto File\n"); + printf("%s <-f profo file> <-d destination file dir> [-v]\n", program); + printf(" Usage: -f # proto file\n"); printf(" -d # destination file dir\n"); printf(" -I # include path dir\n"); + printf(" -p # http or mqtt\n"); printf(" -v # print this screen\n"); printf("\n"); return; } -void Proto2Client(const char *program, const char *proto_file, const char *dir_path, - const vector &include_list, const bool is_uthread_mode) { +void Proto2Client(const char *program, const char *proto_file, + const char *dir_path, const vector &include_list, + const bool is_uthread_mode, const bool mqtt) { SyntaxTree syntax_tree; int ret{ProtoUtils::Parse(proto_file, &syntax_tree, include_list)}; @@ -65,26 +68,30 @@ void Proto2Client(const char *program, const char *proto_file, const char *dir_p // mqtt SyntaxFuncVector mqtt_funcs; - SyntaxFunc connect_func; - connect_func.SetCmdID(-201); - connect_func.SetName("PhxMqttConnect"); - connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); - connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); - mqtt_funcs.push_back(connect_func); - - SyntaxFunc publish_func; - publish_func.SetCmdID(-202); - publish_func.SetName("PhxMqttPublish"); - publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); - publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); - mqtt_funcs.push_back(publish_func); - - SyntaxFunc disconnect_func; - disconnect_func.SetCmdID(-207); - disconnect_func.SetName("PhxMqttDisconnect"); - disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); - disconnect_func.GetResp()->SetType(""); - mqtt_funcs.push_back(disconnect_func); + if (mqtt) { + SyntaxFunc connect_func; + connect_func.SetCmdID(-201); + connect_func.SetName("PhxMqttConnect"); + connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); + connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); + mqtt_funcs.push_back(connect_func); + + SyntaxFunc publish_func; + publish_func.SetCmdID(-202); + publish_func.SetName("PhxMqttPublish"); + publish_func.SetOptString("s:"); + publish_func.SetUsage("-s "); + publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); + publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); + mqtt_funcs.push_back(publish_func); + + SyntaxFunc disconnect_func; + disconnect_func.SetCmdID(-207); + disconnect_func.SetName("PhxMqttDisconnect"); + disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); + disconnect_func.GetResp()->SetType(""); + mqtt_funcs.push_back(disconnect_func); + } NameRender name_render(syntax_tree.GetPrefix()); ClientCodeRender code_render(name_render); @@ -223,8 +230,9 @@ int main(int argc, char **argv) { char real_path[1024]{0}; char *rp{nullptr}; bool is_uthread_mode{false}; + bool mqtt{false}; - while (EOF != (c = getopt(argc, argv, "f:d:I:uv"))) { + while (EOF != (c = getopt(argc, argv, "f:d:I:p:uv"))) { switch (c) { case 'f': proto_file = optarg; @@ -238,6 +246,10 @@ int main(int argc, char **argv) { include_list.push_back(rp); } break; + case 'p': + if (0 == strcasecmp(optarg, "mqtt")) + mqtt = true; + break; case 'u': is_uthread_mode = true; break; @@ -267,7 +279,7 @@ int main(int argc, char **argv) { path[strlen(path) - 1] = '\0'; } - Proto2Client(argv[0], proto_file, path, include_list, is_uthread_mode); + Proto2Client(argv[0], proto_file, path, include_list, is_uthread_mode, mqtt); printf("\n"); diff --git a/codegen/phxrpc_pb2server.cpp b/codegen/phxrpc_pb2server.cpp index 2be0e3c..908c6f8 100644 --- a/codegen/phxrpc_pb2server.cpp +++ b/codegen/phxrpc_pb2server.cpp @@ -19,13 +19,14 @@ permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include +#include + #include #include #include -#include #include #include -#include #include #include "syntax_tree.h" @@ -43,8 +44,8 @@ void PrintHelp(const char * program) { printf("\n"); printf("PhxRPC ProtoBuf tool\n"); printf("\n"); - printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); - printf(" Usage: -f # Proto File\n"); + printf("%s <-f profo file> <-d destination file dir> [-v]\n", program); + printf(" Usage: -f # proto file\n"); printf(" -d # destination file dir\n"); printf(" -I # include path dir\n"); printf(" -e # epoll server\n"); @@ -54,9 +55,9 @@ void PrintHelp(const char * program) { return; } -void Proto2Server(const char *program, const char *pb_file, const char *dir_path, - const vector &include_list, const string &mk_dir_path, - const bool is_uthread_mode) { +void Proto2Server(const char *program, const char *pb_file, + const char *dir_path, const vector &include_list, + const string &mk_dir_path, const bool is_uthread_mode) { SyntaxTree syntax_tree; map parsed_file_map; diff --git a/codegen/phxrpc_pb2service.cpp b/codegen/phxrpc_pb2service.cpp index 0e86d01..dc89a97 100644 --- a/codegen/phxrpc_pb2service.cpp +++ b/codegen/phxrpc_pb2service.cpp @@ -19,14 +19,15 @@ permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include +#include + #include #include #include #include -#include #include #include -#include #include "syntax_tree.h" @@ -43,18 +44,20 @@ void PrintHelp(const char *program) { printf("\n"); printf("PhxRPC ProtoBuf tool\n"); printf("\n"); - printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); - printf(" Usage: -f # Proto File\n"); + printf("%s <-f profo file> <-d destination file dir> [-p] [-v]\n", program); + printf(" Usage: -f # proto file\n"); printf(" -d # destination file dir\n"); printf(" -I # include path dir\n"); + printf(" -p # http or mqtt\n"); printf(" -v # print this screen\n"); printf("\n"); return; } -void Proto2Service(const char *program, const char *pb_file, const char *dir_path, - const vector &include_list, const bool is_uthread_mode) { +void Proto2Service(const char *program, const char *pb_file, + const char *dir_path, const vector &include_list, + const bool is_uthread_mode, const bool mqtt) { map parsed_file_map; SyntaxTree syntax_tree; @@ -70,26 +73,30 @@ void Proto2Service(const char *program, const char *pb_file, const char *dir_pat // mqtt SyntaxFuncVector mqtt_funcs; - SyntaxFunc connect_func; - connect_func.SetCmdID(-201); - connect_func.SetName("PhxMqttConnect"); - connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); - connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); - mqtt_funcs.push_back(connect_func); - - SyntaxFunc publish_func; - publish_func.SetCmdID(-202); - publish_func.SetName("PhxMqttPublish"); - publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); - publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); - mqtt_funcs.push_back(publish_func); - - SyntaxFunc disconnect_func; - disconnect_func.SetCmdID(-207); - disconnect_func.SetName("PhxMqttDisconnect"); - disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); - disconnect_func.GetResp()->SetType(""); - mqtt_funcs.push_back(disconnect_func); + if (mqtt) { + SyntaxFunc connect_func; + connect_func.SetCmdID(-201); + connect_func.SetName("PhxMqttConnect"); + connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); + connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); + mqtt_funcs.push_back(connect_func); + + SyntaxFunc publish_func; + publish_func.SetCmdID(-202); + publish_func.SetName("PhxMqttPublish"); + publish_func.SetOptString("s:"); + publish_func.SetUsage("-s "); + publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); + publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); + mqtt_funcs.push_back(publish_func); + + SyntaxFunc disconnect_func; + disconnect_func.SetCmdID(-207); + disconnect_func.SetName("PhxMqttDisconnect"); + disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); + disconnect_func.GetResp()->SetType(""); + mqtt_funcs.push_back(disconnect_func); + } NameRender name_render(syntax_tree.GetPrefix()); ServiceCodeRender code_render(name_render); @@ -163,7 +170,7 @@ void Proto2Service(const char *program, const char *pb_file, const char *dir_pat FILE *fp{fopen(filename, "w")}; assert(nullptr != fp); - code_render.GenerateDispatcherHpp(&syntax_tree, fp); + code_render.GenerateDispatcherHpp(&syntax_tree, mqtt_funcs, fp); fclose(fp); printf("\n%s: Build %s file ... done\n", program, filename); @@ -193,8 +200,9 @@ int main(int argc, char **argv) { char real_path[1024]{0}; char *rp{nullptr}; bool is_uthread_mode{false}; + bool mqtt{false}; - while (EOF != (c = getopt(argc, argv, "f:d:I:uv"))) { + while (EOF != (c = getopt(argc, argv, "f:d:I:p:uv"))) { switch (c) { case 'f': pb_file = optarg; @@ -208,6 +216,10 @@ int main(int argc, char **argv) { include_list.push_back(rp); } break; + case 'p': + if (0 == strcasecmp(optarg, "mqtt")) + mqtt = true; + break; case 'u': is_uthread_mode = true; break; @@ -238,7 +250,7 @@ int main(int argc, char **argv) { path[strlen(path) - 1] = '\0'; } - Proto2Service(argv[0], pb_file, path, include_list, is_uthread_mode); + Proto2Service(argv[0], pb_file, path, include_list, is_uthread_mode, mqtt); printf("\n"); diff --git a/codegen/phxrpc_pb2tool.cpp b/codegen/phxrpc_pb2tool.cpp index b3c8ce7..59a0df4 100644 --- a/codegen/phxrpc_pb2tool.cpp +++ b/codegen/phxrpc_pb2tool.cpp @@ -19,13 +19,14 @@ permissions and limitations under the License. See the AUTHORS file for names of contributors. */ +#include +#include + #include #include #include #include -#include #include -#include #include "syntax_tree.h" @@ -38,14 +39,15 @@ using namespace phxrpc; using namespace std; -void PrintHelp(const char * program) { +void PrintHelp(const char *program) { printf("\n"); printf("PhxRPC ProtoBuf tool\n"); printf("\n"); - printf("%s <-f Profo file> <-d destination file dir> [-v]\n", program); - printf(" Usage: -f # Proto File\n"); + printf("%s <-f profo file> <-d destination file dir> [-p] [-v]\n", program); + printf(" Usage: -f # proto file\n"); printf(" -d # destination file dir\n"); printf(" -I # include path dir\n"); + printf(" -p # http or mqtt\n"); printf(" -v # print this screen\n"); printf("\n"); @@ -53,7 +55,7 @@ void PrintHelp(const char * program) { } void Proto2Tool(const char *program, const char *pb_file, const char *dir_path, - const vector &include_list) { + const vector &include_list, const bool mqtt) { SyntaxTree syntax_tree; int ret = ProtoUtils::Parse(pb_file, &syntax_tree, include_list); @@ -68,33 +70,35 @@ void Proto2Tool(const char *program, const char *pb_file, const char *dir_path, // mqtt SyntaxFuncVector mqtt_funcs; - SyntaxFunc connect_func; - connect_func.SetCmdID(-201); - connect_func.SetName("PhxMqttConnect"); - connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); - connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); - mqtt_funcs.push_back(connect_func); - - SyntaxFunc publish_func; - publish_func.SetCmdID(-202); - publish_func.SetName("PhxMqttPublish"); - publish_func.SetOptString("s:"); - publish_func.SetUsage("-s "); - publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); - publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); - mqtt_funcs.push_back(publish_func); - - SyntaxFunc disconnect_func; - disconnect_func.SetCmdID(-207); - disconnect_func.SetName("PhxMqttDisconnect"); - disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); - disconnect_func.GetResp()->SetType(""); - mqtt_funcs.push_back(disconnect_func); + if (mqtt) { + SyntaxFunc connect_func; + connect_func.SetCmdID(-201); + connect_func.SetName("PhxMqttConnect"); + connect_func.GetReq()->SetType("phxrpc::MqttConnectPb"); + connect_func.GetResp()->SetType("phxrpc::MqttConnackPb"); + mqtt_funcs.push_back(connect_func); + + SyntaxFunc publish_func; + publish_func.SetCmdID(-202); + publish_func.SetName("PhxMqttPublish"); + publish_func.SetOptString("s:"); + publish_func.SetUsage("-s "); + publish_func.GetReq()->SetType("phxrpc::MqttPublishPb"); + publish_func.GetResp()->SetType("phxrpc::MqttPubackPb"); + mqtt_funcs.push_back(publish_func); + + SyntaxFunc disconnect_func; + disconnect_func.SetCmdID(-207); + disconnect_func.SetName("PhxMqttDisconnect"); + disconnect_func.GetReq()->SetType("phxrpc::MqttDisconnectPb"); + disconnect_func.GetResp()->SetType(""); + mqtt_funcs.push_back(disconnect_func); + } NameRender name_render(syntax_tree.GetPrefix()); ToolCodeRender code_render(name_render); - char filename[256] = { 0 }, tmp[256] = { 0 }; + char filename[256]{0}, tmp[256]{0}; // [xx]tool.h { @@ -182,8 +186,9 @@ int main(int argc, char **argv) { vector include_list; char real_path[1024]{0}; char *rp{nullptr}; + bool mqtt{false}; - while (EOF != (c = getopt(argc, argv, "f:d:I:v"))) { + while (EOF != (c = getopt(argc, argv, "f:d:I:p:v"))) { switch (c) { case 'f': pb_file = optarg; @@ -197,6 +202,10 @@ int main(int argc, char **argv) { include_list.push_back(rp); } break; + case 'p': + if (0 == strcasecmp(optarg, "mqtt")) + mqtt = true; + break; default: PrintHelp(argv[0]); exit(-1); @@ -223,7 +232,7 @@ int main(int argc, char **argv) { path[strlen(path) - 1] = '\0'; } - Proto2Tool(argv[0], pb_file, path, include_list); + Proto2Tool(argv[0], pb_file, path, include_list, mqtt); printf("\n"); diff --git a/codegen/server_template.cpp b/codegen/server_template.cpp index 1e3133a..7973150 100644 --- a/codegen/server_template.cpp +++ b/codegen/server_template.cpp @@ -322,7 +322,7 @@ include $PhxRPCMKDir$/phxrpc.mk LDFLAGS := -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -#choose to use boost for network +# choose to use boost for network #LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS) SVR_OBJS = $MessageFile$.o \ @@ -364,7 +364,7 @@ lib$ClientFile$.a: $(CLI_OBJS) $ClientFile$.o: $StubFile$.h $StubFile$.h: $ProtoFile$ - $(PHXRPC_ROOT)/codegen/phxrpc_pb2client $(PBFLAGS) -f $^ -d . + $(PHXRPC_ROOT)/codegen/phxrpc_pb2client $(PBFLAGS) -f $^ -d . -p mqtt ########## service ########## @@ -376,7 +376,7 @@ lib$ClientFile$.a: $(CLI_OBJS) $DispatcherFile$.o: $ServiceFile$.h $ServiceFile$.h: $ProtoFile$ - $(PHXRPC_ROOT)/codegen/phxrpc_pb2service $(PBFLAGS) -f $^ -d . + $(PHXRPC_ROOT)/codegen/phxrpc_pb2service $(PBFLAGS) -f $^ -d . -p mqtt ########## tool ########## @@ -388,7 +388,7 @@ lib$ClientFile$.a: $(CLI_OBJS) $ToolMainFile$.o: $ToolFile$.h $ToolFile$.h: $ProtoFile$ - $(PHXRPC_ROOT)/codegen/phxrpc_pb2tool $(PBFLAGS) -f $^ -d . + $(PHXRPC_ROOT)/codegen/phxrpc_pb2tool $(PBFLAGS) -f $^ -d . -p mqtt clean: @($(RM) $(TARGETS)) @@ -407,7 +407,7 @@ include $PhxRPCMKDir$/phxrpc.mk LDFLAGS := -L$(PHXRPC_ROOT)/lib -lphxrpc $(LDFLAGS) -#choose to use boost for network +# choose to use boost for network #LDFLAGS := $(PLUGIN_BOOST_LDFLAGS) $(LDFLAGS) SVR_OBJS = $MessageFile$.o \ @@ -452,7 +452,7 @@ lib$ClientFile$.a: $(CLI_OBJS) $ClientFile$_uthread.o: $StubFile$.h $StubFile$.h: $ProtoFile$ - $(PHXRPC_ROOT)/codegen/phxrpc_pb2client $(PBFLAGS) -f $^ -d . -u + $(PHXRPC_ROOT)/codegen/phxrpc_pb2client $(PBFLAGS) -f $^ -d . -u -p mqtt ########## service ########## @@ -464,7 +464,7 @@ lib$ClientFile$.a: $(CLI_OBJS) $DispatcherFile$.o: $ServiceFile$.h $ServiceFile$.h: $ProtoFile$ - $(PHXRPC_ROOT)/codegen/phxrpc_pb2service $(PBFLAGS) -f $^ -d . -u + $(PHXRPC_ROOT)/codegen/phxrpc_pb2service $(PBFLAGS) -f $^ -d . -u -p mqtt ########## tool ########## @@ -476,7 +476,7 @@ lib$ClientFile$.a: $(CLI_OBJS) $ToolMainFile$.o: $ToolFile$.h $ToolFile$.h: $ProtoFile$ - $(PHXRPC_ROOT)/codegen/phxrpc_pb2tool $(PBFLAGS) -f $^ -d . + $(PHXRPC_ROOT)/codegen/phxrpc_pb2tool $(PBFLAGS) -f $^ -d . -p mqtt clean: @($(RM) $(TARGETS)) diff --git a/codegen/service_code_render.cpp b/codegen/service_code_render.cpp index e9c70f2..db42b89 100644 --- a/codegen/service_code_render.cpp +++ b/codegen/service_code_render.cpp @@ -80,11 +80,10 @@ void ServiceCodeRender::GenerateServiceHpp(SyntaxTree *stree, GetServiceFuncDeclaration(stree, &(*mqtt_it), 1, 0, 1, &buffer); fprintf(write, " virtual %s;\n", buffer.c_str()); } - fprintf(write, "\n"); SyntaxFuncVector *flist{stree->GetFuncList()}; - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { string buffer; GetServiceFuncDeclaration(stree, &(*fit), 1, 0, 1, &buffer); fprintf(write, " virtual %s;\n", buffer.c_str()); @@ -110,6 +109,7 @@ void ServiceCodeRender::GenerateServiceCpp(SyntaxTree *stree, fprintf(write, "\n"); fprintf(write, "#include \"%s.h\"\n", filename); + fprintf(write, "\n"); name_render_.GetMessageFileName(stree->GetProtoFile(), filename, sizeof(filename)); fprintf(write, "#include \"%s.h\"\n", filename); @@ -141,8 +141,8 @@ void ServiceCodeRender::GenerateServiceCpp(SyntaxTree *stree, } SyntaxFuncVector *flist{stree->GetFuncList()}; - SyntaxFuncVector::iterator fit = flist->begin(); - for (; flist->end() != fit; ++fit) { + auto fit(flist->cbegin()); + for (; flist->cend() != fit; ++fit) { string buffer; GetServiceFuncDeclaration(stree, &(*fit), 0, 0, 0, &buffer); fprintf(write, "%s {\n", buffer.c_str()); @@ -353,7 +353,9 @@ void ServiceCodeRender::GetServiceFuncDeclaration(SyntaxTree *stree, result->append(")"); } -void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree *stree, FILE *write) { +void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write) { char filename[128]{0}; name_render_.GetDispatcherFileName(stree->GetName(), filename, sizeof(filename)); @@ -395,19 +397,18 @@ void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree *stree, FILE *write) { fprintf(write, " virtual ~%s();\n", clasname); fprintf(write, "\n"); - fprintf(write, " int PhxMqttConnect(const phxrpc::BaseRequest *const req, " - "phxrpc::BaseResponse *const resp);\n"); - fprintf(write, " int PhxMqttPublish(const phxrpc::BaseRequest *const req, " - "phxrpc::BaseResponse *const resp);\n"); - fprintf(write, " int PhxMqttDisconnect(const phxrpc::BaseRequest *const req, " - "phxrpc::BaseResponse *const resp);\n"); - fprintf(write, "\n"); + for (auto mqtt_it(mqtt_funcs.cbegin()); mqtt_funcs.cend() != mqtt_it; + ++mqtt_it) { + fprintf(write, " int %s(const phxrpc::BaseRequest *const req, " + "phxrpc::BaseResponse *const resp);\n", + mqtt_it->GetName()); + } SyntaxFuncVector *flist{stree->GetFuncList()}; auto fit(flist->cbegin()); for (; flist->cend() != fit; ++fit) { fprintf(write, " int %s(const phxrpc::BaseRequest *const request, " - "phxrpc::BaseResponse *const response);\n", + "phxrpc::BaseResponse *const resp);\n", fit->GetName()); } fprintf(write, "\n"); @@ -469,20 +470,22 @@ void ServiceCodeRender::GenerateDispatcherCpp(SyntaxTree *stree, vector functions; - FunctionItem connect_item; - connect_item.protocol_name = "MQTT_CONNECT"; - connect_item.function_name = "PhxMqttConnect"; - functions.push_back(connect_item); - - FunctionItem publish_item; - publish_item.protocol_name = "MQTT_PUBLISH"; - publish_item.function_name = "PhxMqttPublish"; - functions.push_back(publish_item); - - FunctionItem disconnect_item; - disconnect_item.protocol_name = "MQTT_DISCONNECT"; - disconnect_item.function_name = "PhxMqttDisconnect"; - functions.push_back(disconnect_item); + if (0 < mqtt_funcs.size()) { + FunctionItem connect_item; + connect_item.protocol_name = "MQTT_CONNECT"; + connect_item.function_name = "PhxMqttConnect"; + functions.push_back(connect_item); + + FunctionItem publish_item; + publish_item.protocol_name = "MQTT_PUBLISH"; + publish_item.function_name = "PhxMqttPublish"; + functions.push_back(publish_item); + + FunctionItem disconnect_item; + disconnect_item.protocol_name = "MQTT_DISCONNECT"; + disconnect_item.function_name = "PhxMqttDisconnect"; + functions.push_back(disconnect_item); + } GenerateMqttFuncMap(stree, functions, write); diff --git a/codegen/service_code_render.h b/codegen/service_code_render.h index 5439cc2..9e389d6 100755 --- a/codegen/service_code_render.h +++ b/codegen/service_code_render.h @@ -56,7 +56,9 @@ class ServiceCodeRender { const SyntaxFuncVector &mqtt_funcs, FILE *write, const bool is_uthread_mode); - virtual void GenerateDispatcherHpp(SyntaxTree *stree, FILE *write); + virtual void GenerateDispatcherHpp(SyntaxTree *stree, + const SyntaxFuncVector &mqtt_funcs, + FILE *write); virtual void GenerateDispatcherCpp(SyntaxTree *stree, const SyntaxFuncVector &mqtt_funcs, diff --git a/codegen/tool_code_render.cpp b/codegen/tool_code_render.cpp index 9edc71f..d861a7a 100644 --- a/codegen/tool_code_render.cpp +++ b/codegen/tool_code_render.cpp @@ -85,7 +85,6 @@ void ToolCodeRender::GenerateToolHpp(SyntaxTree *stree, ++mqtt_it) { fprintf(write, " virtual int %s(phxrpc::OptMap &bigmap);\n", mqtt_it->GetName()); } - fprintf(write, "\n"); SyntaxFuncVector *flist{stree->GetFuncList()}; auto fit(flist->cbegin()); @@ -248,7 +247,6 @@ void ToolCodeRender::GenerateToolImplHpp(SyntaxTree *stree, ++mqtt_it) { fprintf(write, " virtual int %s(phxrpc::OptMap &opt_map) override;\n", mqtt_it->GetName()); } - fprintf(write, "\n"); SyntaxFuncVector *flist{stree->GetFuncList()}; auto fit(flist->cbegin()); From a1b7ce5c5ae633bac3d9df85ee874a1e8a82d353 Mon Sep 17 00:00:00 2001 From: taohe Date: Fri, 8 Dec 2017 20:06:56 +0800 Subject: [PATCH 47/49] fix mqtt protocol --- codegen/client_code_render.cpp | 32 ++++++++++++++++---------------- codegen/client_code_render.h | 6 +++--- codegen/service_code_render.cpp | 14 +++++++------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/codegen/client_code_render.cpp b/codegen/client_code_render.cpp index d01fb6d..1dcb025 100644 --- a/codegen/client_code_render.cpp +++ b/codegen/client_code_render.cpp @@ -201,39 +201,39 @@ void ClientCodeRender::GenerateStubCpp(SyntaxTree *stree, } } -void ClientCodeRender::GenerateStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, - FILE *write) { +void ClientCodeRender::GenerateMqttStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, + FILE *write) { string buffer; GetStubFuncDeclaration(stree, func, 0, &buffer); fprintf(write, "%s {\n", buffer.c_str()); - fprintf(write, " phxrpc::HttpCaller caller(socket_, client_monitor_);\n"); - fprintf(write, " caller.SetURI(\"/%s/%s\", %d);\n", - stree->GetPackageName(), func->GetName(), func->GetCmdID()); - fprintf(write, " caller.SetKeepAlive(keep_alive_);\n"); - fprintf(write, " return caller.Call(req, resp);\n"); + fprintf(write, " phxrpc::MqttCaller caller(socket_, client_monitor_);\n"); + fprintf(write, " caller.SetCmdId(%d);\n", func->GetCmdID()); + if (0 == strcmp(func->GetName(), "PhxMqttDisconnect")) { + fprintf(write, " return caller.%sCall(req);\n", func->GetName()); + } else { + fprintf(write, " return caller.%sCall(req, resp);\n", func->GetName()); + } fprintf(write, "}\n"); fprintf(write, "\n"); } -void ClientCodeRender::GenerateMqttStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, - FILE *write) { +void ClientCodeRender::GenerateStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, + FILE *write) { string buffer; GetStubFuncDeclaration(stree, func, 0, &buffer); fprintf(write, "%s {\n", buffer.c_str()); - fprintf(write, " phxrpc::MqttCaller caller(socket_, client_monitor_);\n"); - fprintf(write, " caller.SetCmdId(%d);\n", func->GetCmdID()); - if (0 == strcmp(func->GetName(), "PhxMqttDisconnect")) { - fprintf(write, " return caller.%sCall(req);\n", func->GetName()); - } else { - fprintf(write, " return caller.%sCall(req, resp);\n", func->GetName()); - } + fprintf(write, " phxrpc::HttpCaller caller(socket_, client_monitor_);\n"); + fprintf(write, " caller.SetURI(\"/%s/%s\", %d);\n", + stree->GetPackageName(), func->GetName(), func->GetCmdID()); + fprintf(write, " caller.SetKeepAlive(keep_alive_);\n"); + fprintf(write, " return caller.Call(req, resp);\n"); fprintf(write, "}\n"); fprintf(write, "\n"); diff --git a/codegen/client_code_render.h b/codegen/client_code_render.h index f704af0..8af144c 100755 --- a/codegen/client_code_render.h +++ b/codegen/client_code_render.h @@ -59,12 +59,12 @@ class ClientCodeRender { void GetStubFuncDeclaration(SyntaxTree *stree, const SyntaxFunc *const func, int is_header, std::string *result); - void GenerateStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, - FILE *write); - void GenerateMqttStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, FILE *write); + void GenerateStubFunc(SyntaxTree *stree, const SyntaxFunc *const func, + FILE *write); + void GetClienfuncDeclaration(SyntaxTree *stree, const SyntaxFunc *const func, int is_header, std::string *result, diff --git a/codegen/service_code_render.cpp b/codegen/service_code_render.cpp index db42b89..80f063f 100644 --- a/codegen/service_code_render.cpp +++ b/codegen/service_code_render.cpp @@ -407,7 +407,7 @@ void ServiceCodeRender::GenerateDispatcherHpp(SyntaxTree *stree, SyntaxFuncVector *flist{stree->GetFuncList()}; auto fit(flist->cbegin()); for (; flist->cend() != fit; ++fit) { - fprintf(write, " int %s(const phxrpc::BaseRequest *const request, " + fprintf(write, " int %s(const phxrpc::BaseRequest *const req, " "phxrpc::BaseResponse *const resp);\n", fit->GetName()); } @@ -629,8 +629,8 @@ void ServiceCodeRender::GenerateDispatcherFunc(SyntaxTree *stree, name_render_.GetDispatcherClasname(stree->GetName(), clasname, sizeof(clasname)); - fprintf(write, "int %s::%s(const phxrpc::BaseRequest *const request, " - "phxrpc::BaseResponse *const response) {\n", + fprintf(write, "int %s::%s(const phxrpc::BaseRequest *const req, " + "phxrpc::BaseResponse *const resp) {\n", clasname, func->GetName()); fprintf(write, " dispatcher_args_->server_monitor->SvrCall(%d, \"%s\", 1);\n", @@ -651,10 +651,10 @@ void ServiceCodeRender::GenerateDispatcherFunc(SyntaxTree *stree, fprintf(write, " // unpack request\n"); fprintf(write, " {\n"); - fprintf(write, " if (!req_pb.ParseFromString(request->GetContent())) {\n"); + fprintf(write, " if (!req_pb.ParseFromString(req->GetContent())) {\n"); fprintf(write, " phxrpc::log(LOG_ERR, \"ERROR: FromBuffer fail size %%zu ip %%s\",\n" - " request->GetContent().size(), request->GetClientIP());\n"); + " req->GetContent().size(), req->GetClientIP());\n"); fprintf(write, " return -EINVAL;\n"); fprintf(write, " }\n"); @@ -671,9 +671,9 @@ void ServiceCodeRender::GenerateDispatcherFunc(SyntaxTree *stree, fprintf(write, " // pack response\n"); fprintf(write, " {\n"); - fprintf(write, " if (!resp_pb.SerializeToString(&(response->GetContent()))) {\n"); + fprintf(write, " if (!resp_pb.SerializeToString(&(resp->GetContent()))) {\n"); - fprintf(write, " phxrpc::log(LOG_ERR, \"ERROR: ToBuffer fail ip %%s\", request->GetClientIP());\n"); + fprintf(write, " phxrpc::log(LOG_ERR, \"ERROR: ToBuffer fail ip %%s\", req->GetClientIP());\n"); fprintf(write, " return -ENOMEM;\n"); fprintf(write, " }\n"); From 1cb381f91faf1d5e98ea661dbee20225fb84a01b Mon Sep 17 00:00:00 2001 From: taohe Date: Tue, 27 Feb 2018 16:25:49 +0800 Subject: [PATCH 48/49] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce5070a..26c5175 100644 --- a/README.md +++ b/README.md @@ -284,7 +284,7 @@ int SearchClient::PhxBatchEcho(const google::protobuf::StringValue &req, #### Server配置说明 (xxx_server.conf) -```c++ +```ini [Server] BindIP = 127.0.0.1 // Server IP Port = 16161 // Server Port From 8b4b82ad9ecffc07f6c473e7af2ac208afe0c6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=82=80?= Date: Thu, 1 Mar 2018 21:48:31 +0800 Subject: [PATCH 49/49] Update uthread_epoll.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更加精确的超时控制 --- phxrpc/network/uthread_epoll.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/phxrpc/network/uthread_epoll.cpp b/phxrpc/network/uthread_epoll.cpp index 4ee9434..aa18a21 100644 --- a/phxrpc/network/uthread_epoll.cpp +++ b/phxrpc/network/uthread_epoll.cpp @@ -241,10 +241,12 @@ bool UThreadEpollScheduler::Run() { struct epoll_event * events = (struct epoll_event*) calloc(max_task_, sizeof(struct epoll_event)); - int next_timeout = timer_.GetNextTimeout(); - for (; (run_forever_) || (!runtime_.IsAllDone());) { - int nfds = epoll_wait(epoll_fd_, events, max_task_, 4); + int next_timeout = timer_.GetNextTimeout(); + int timeout = 4; + if(next_timeout > 0 && next_timeout < timeout) + timeout = next_timeout; + int nfds = epoll_wait(epoll_fd_, events, max_task_, timeout); if (nfds != -1) { for (int i = 0; i < nfds; i++) { UThreadSocket_t * socket = (UThreadSocket_t*) events[i].data.ptr;