1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "DumpstateGrpcServer.h"
18 #include "ServiceDescriptor.h"
19 
20 #include <array>
21 #include <iostream>
22 #include <unordered_set>
23 
24 #include <grpc++/grpc++.h>
25 
26 struct GrpcServiceOutputConsumer : public ServiceDescriptor::OutputConsumer {
27     using Dest = ::grpc::ServerWriter<dumpstate_proto::DumpstateBuffer>*;
28 
GrpcServiceOutputConsumerGrpcServiceOutputConsumer29     explicit GrpcServiceOutputConsumer(Dest s) : stream(s) {}
30 
WriteGrpcServiceOutputConsumer31     void Write(char* ptr, size_t len) override {
32         dumpstate_proto::DumpstateBuffer dumpstateBuffer;
33         dumpstateBuffer.set_buffer(ptr, len);
34         stream->Write(dumpstateBuffer);
35     }
36 
37     Dest stream;
38 };
39 
getServerCredentials()40 static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() {
41     // TODO(chenhaosjtuacm): get secured credentials here
42     return ::grpc::InsecureServerCredentials();
43 }
44 
toGRpcStatus(const ServiceDescriptor::Error & err)45 static ::grpc::Status toGRpcStatus(const ServiceDescriptor::Error& err) {
46     if (err == std::nullopt)
47         return ::grpc::Status::OK;
48     else
49         return ::grpc::Status(::grpc::StatusCode::INTERNAL, *err);
50 }
51 
DumpstateGrpcServer(const std::string & addr,const ServiceSupplier & services)52 DumpstateGrpcServer::DumpstateGrpcServer(const std::string& addr, const ServiceSupplier& services)
53     : DumpstateServer(services), mServiceAddr(addr) {}
54 
GetSystemLogs(::grpc::ServerContext *,const::google::protobuf::Empty *,::grpc::ServerWriter<dumpstate_proto::DumpstateBuffer> * stream)55 grpc::Status DumpstateGrpcServer::GetSystemLogs(
56         ::grpc::ServerContext*, const ::google::protobuf::Empty*,
57         ::grpc::ServerWriter<dumpstate_proto::DumpstateBuffer>* stream) {
58     GrpcServiceOutputConsumer consumer(stream);
59 
60     const auto ok = this->DumpstateServer::GetSystemLogs(&consumer);
61     return toGRpcStatus(ok);
62 }
63 
GetAvailableServices(::grpc::ServerContext *,const::google::protobuf::Empty *,dumpstate_proto::ServiceNameList * serviceList)64 grpc::Status DumpstateGrpcServer::GetAvailableServices(
65         ::grpc::ServerContext*, const ::google::protobuf::Empty*,
66         dumpstate_proto::ServiceNameList* serviceList) {
67     const auto services = this->DumpstateServer::GetAvailableServices();
68 
69     for (const auto& svc : services) serviceList->add_service_names(svc);
70 
71     return ::grpc::Status::OK;
72 }
73 
GetServiceLogs(::grpc::ServerContext *,const dumpstate_proto::ServiceLogRequest * request,::grpc::ServerWriter<dumpstate_proto::DumpstateBuffer> * stream)74 grpc::Status DumpstateGrpcServer::GetServiceLogs(
75         ::grpc::ServerContext*, const dumpstate_proto::ServiceLogRequest* request,
76         ::grpc::ServerWriter<dumpstate_proto::DumpstateBuffer>* stream) {
77     const auto& serviceName = request->service_name();
78     if (serviceName.empty()) {
79         return ::grpc::Status::OK;
80     }
81 
82     GrpcServiceOutputConsumer consumer(stream);
83     const auto ok = this->DumpstateServer::GetServiceLogs(serviceName, &consumer);
84     return toGRpcStatus(ok);
85 }
86 
Start()87 void DumpstateGrpcServer::Start() {
88     ::grpc::ServerBuilder builder;
89     builder.RegisterService(this);
90     builder.AddListeningPort(mServiceAddr, getServerCredentials());
91     std::unique_ptr<::grpc::Server> server(builder.BuildAndStart());
92 
93     if (!server) {
94         std::cerr << __func__ << ": failed to create the GRPC server, "
95                   << "please make sure the configuration and permissions are correct" << std::endl;
96         std::abort();
97     }
98 
99     server->Wait();
100 }
101