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