| 
					
				 | 
			
			
				@@ -43,9 +43,12 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc++/server_credentials.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc++/thread_pool_interface.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/cpp/proto/proto_utils.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 namespace grpc { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Server::Server(ThreadPoolInterface *thread_pool, bool thread_pool_owned, ServerCredentials *creds) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Server::Server(ThreadPoolInterface *thread_pool, bool thread_pool_owned, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               ServerCredentials *creds) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     : started_(false), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       shutdown_(false), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       num_running_cb_(0), 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -53,8 +56,7 @@ Server::Server(ThreadPoolInterface *thread_pool, bool thread_pool_owned, ServerC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       thread_pool_owned_(thread_pool_owned), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       secure_(creds != nullptr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (creds) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    server_ = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        grpc_secure_server_create(creds->GetRawCreds(), nullptr, nullptr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    server_ = grpc_secure_server_create(creds->GetRawCreds(), nullptr, nullptr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     server_ = grpc_server_create(nullptr, nullptr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -87,7 +89,8 @@ bool Server::RegisterService(RpcService *service) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     RpcServiceMethod *method = service->GetMethod(i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     void *tag = grpc_server_register_method(server_, method->name(), nullptr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!tag) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", method->name()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              method->name()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     methods_.emplace_back(method, tag); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -104,6 +107,105 @@ int Server::AddPort(const grpc::string &addr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class Server::MethodRequestData final : public CompletionQueueTag { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  MethodRequestData(RpcServiceMethod *method, void *tag) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      : method_(method), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tag_(tag), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        has_request_payload_(method->method_type() == RpcMethod::NORMAL_RPC || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                             method->method_type() == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 RpcMethod::SERVER_STREAMING), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        has_response_payload_(method->method_type() == RpcMethod::NORMAL_RPC || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                              method->method_type() == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  RpcMethod::CLIENT_STREAMING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_metadata_array_init(&request_metadata_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  static MethodRequestData *Wait(CompletionQueue *cq, bool *ok) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void *tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!cq->Next(&tag, ok)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    auto *mrd = static_cast<MethodRequestData *>(tag); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(mrd->in_flight_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return mrd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  void Request(grpc_server *server, CompletionQueue *cq) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(!in_flight_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    in_flight_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cq_ = grpc_completion_queue_create(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(GRPC_CALL_OK == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               grpc_server_request_registered_call( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   server, tag_, &call_, &deadline_, &request_metadata_, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   has_request_payload_ ? &request_payload_ : nullptr, cq->cq(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   cq_, this)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  void FinalizeResult(void *tag, bool *status) override {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  class CallData { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    explicit CallData(MethodRequestData *mrd) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        : cq_(mrd->cq_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          call_(mrd->call_, nullptr, &cq_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ctx_(mrd->deadline_, mrd->request_metadata_.metadata, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               mrd->request_metadata_.count), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          has_request_payload_(mrd->has_request_payload_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          has_response_payload_(mrd->has_response_payload_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          request_payload_(mrd->request_payload_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          method_(mrd->method_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      GPR_ASSERT(mrd->in_flight_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      mrd->in_flight_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      mrd->request_metadata_.count = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void Run() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      std::unique_ptr<google::protobuf::Message> req; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      std::unique_ptr<google::protobuf::Message> res; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (has_request_payload_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        req.reset(method_->AllocateRequestProto()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!DeserializeProto(request_payload_, req.get())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          abort();  // for now 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (has_response_payload_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        req.reset(method_->AllocateResponseProto()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      auto status = method_->handler()->RunHandler( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          MethodHandler::HandlerParameter(&call_, &ctx_, req.get(), res.get())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      CallOpBuffer buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      buf.AddServerSendStatus(nullptr, status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (has_response_payload_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        buf.AddSendMessage(*res); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      call_.PerformOps(&buf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      GPR_ASSERT(cq_.Pluck(&buf)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CompletionQueue cq_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Call call_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ServerContext ctx_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const bool has_request_payload_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const bool has_response_payload_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_byte_buffer *request_payload_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    RpcServiceMethod *const method_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  RpcServiceMethod *const method_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  void *const tag_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bool in_flight_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const bool has_request_payload_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const bool has_response_payload_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_call *call_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_timespec deadline_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_metadata_array request_metadata_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_byte_buffer *request_payload_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_completion_queue *cq_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 bool Server::Start() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(!started_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   started_ = true; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -111,8 +213,8 @@ bool Server::Start() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Start processing rpcs. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (cq_sync_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (auto& m : methods_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      m.Request(cq_sync_.get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (auto &m : methods_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      m.Request(server_, cq_sync_.get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ScheduleCallback(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -146,14 +248,17 @@ void Server::ScheduleCallback() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void Server::RunRpc() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Wait for one more incoming rpc. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  auto* mrd = MethodRequestData::Wait(cq_sync_.get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bool ok; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  auto *mrd = MethodRequestData::Wait(cq_sync_.get(), &ok); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (mrd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     MethodRequestData::CallData cd(mrd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mrd->Request(cq_sync_.get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ScheduleCallback(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (ok) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      mrd->Request(server_, cq_sync_.get()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ScheduleCallback(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    cd.Run(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      cd.Run(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   { 
			 |