1 /*
2 * Copyright 2019 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 "facade/grpc_root_server.h"
18
19 #include <string>
20
21 #include "blueberry/facade/rootservice.grpc.pb.h"
22 #include "facade/read_only_property_server.h"
23 #include "grpc/grpc_module.h"
24 #include "hal/facade.h"
25 #include "hci/facade/acl_manager_facade.h"
26 #include "hci/facade/controller_facade.h"
27 #include "hci/facade/facade.h"
28 #include "hci/facade/le_acl_manager_facade.h"
29 #include "hci/facade/le_advertising_manager_facade.h"
30 #include "hci/facade/le_initiator_address_facade.h"
31 #include "hci/facade/le_scanning_manager_facade.h"
32 #include "iso/facade.h"
33 #include "l2cap/classic/facade.h"
34 #include "l2cap/le/facade.h"
35 #include "neighbor/facade/facade.h"
36 #include "os/log.h"
37 #include "os/thread.h"
38 #include "security/facade.h"
39 #include "shim/facade/facade.h"
40 #include "stack_manager.h"
41
42 namespace bluetooth {
43 namespace facade {
44
45 using ::blueberry::facade::BluetoothModule;
46 using ::bluetooth::grpc::GrpcModule;
47 using ::bluetooth::os::Thread;
48
49 class RootFacadeService : public ::blueberry::facade::RootFacade::Service {
50 public:
RootFacadeService(int grpc_port)51 explicit RootFacadeService(int grpc_port) : grpc_port_(grpc_port) {}
52
StartStack(::grpc::ServerContext * context,const::blueberry::facade::StartStackRequest * request,::blueberry::facade::StartStackResponse * response)53 ::grpc::Status StartStack(
54 ::grpc::ServerContext* context,
55 const ::blueberry::facade::StartStackRequest* request,
56 ::blueberry::facade::StartStackResponse* response) override {
57 if (is_running_) {
58 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is running");
59 }
60
61 ModuleList modules;
62 modules.add<::bluetooth::grpc::GrpcModule>();
63
64 BluetoothModule module_under_test = request->module_under_test();
65 switch (module_under_test) {
66 case BluetoothModule::HAL:
67 modules.add<::bluetooth::hal::HciHalFacadeModule>();
68 break;
69 case BluetoothModule::HCI:
70 modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
71 modules.add<::bluetooth::hci::facade::HciFacadeModule>();
72 break;
73 case BluetoothModule::HCI_INTERFACES:
74 modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
75 modules.add<::bluetooth::hci::facade::HciFacadeModule>();
76 modules.add<::bluetooth::hci::facade::AclManagerFacadeModule>();
77 modules.add<::bluetooth::hci::facade::ControllerFacadeModule>();
78 modules.add<::bluetooth::hci::facade::LeAclManagerFacadeModule>();
79 modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>();
80 modules.add<::bluetooth::hci::facade::LeInitiatorAddressFacadeModule>();
81 modules.add<::bluetooth::hci::facade::LeScanningManagerFacadeModule>();
82 modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>();
83 modules.add<::bluetooth::iso::IsoModuleFacadeModule>();
84 break;
85 case BluetoothModule::L2CAP:
86 modules.add<::bluetooth::hci::facade::ControllerFacadeModule>();
87 modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>();
88 modules.add<::bluetooth::hci::facade::LeInitiatorAddressFacadeModule>();
89 modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>();
90 modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
91 modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>();
92 modules.add<::bluetooth::l2cap::le::L2capLeModuleFacadeModule>();
93 modules.add<::bluetooth::hci::facade::HciFacadeModule>();
94 modules.add<::bluetooth::iso::IsoModuleFacadeModule>();
95 break;
96 case BluetoothModule::SECURITY:
97 modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
98 modules.add<::bluetooth::hci::facade::ControllerFacadeModule>();
99 modules.add<::bluetooth::security::SecurityModuleFacadeModule>();
100 modules.add<::bluetooth::neighbor::facade::NeighborFacadeModule>();
101 modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>();
102 modules.add<::bluetooth::hci::facade::HciFacadeModule>();
103 modules.add<::bluetooth::hci::facade::ControllerFacadeModule>();
104 modules.add<::bluetooth::hci::facade::LeAdvertisingManagerFacadeModule>();
105 modules.add<::bluetooth::hci::facade::LeScanningManagerFacadeModule>();
106 break;
107 case BluetoothModule::SHIM:
108 modules.add<::bluetooth::shim::facade::ShimFacadeModule>();
109 break;
110 default:
111 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test");
112 }
113
114 stack_thread_ = std::make_unique<Thread>("stack_thread", Thread::Priority::NORMAL);
115 stack_manager_.StartUp(&modules, stack_thread_.get());
116
117 GrpcModule* grpc_module = stack_manager_.GetInstance<GrpcModule>();
118 grpc_module->StartServer("0.0.0.0", grpc_port_);
119
120 grpc_loop_thread_ = std::make_unique<std::thread>([grpc_module] { grpc_module->RunGrpcLoop(); });
121 is_running_ = true;
122
123 return ::grpc::Status::OK;
124 }
125
StopStack(::grpc::ServerContext * context,const::blueberry::facade::StopStackRequest * request,::blueberry::facade::StopStackResponse * response)126 ::grpc::Status StopStack(
127 ::grpc::ServerContext* context,
128 const ::blueberry::facade::StopStackRequest* request,
129 ::blueberry::facade::StopStackResponse* response) override {
130 if (!is_running_) {
131 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is not running");
132 }
133
134 stack_manager_.GetInstance<GrpcModule>()->StopServer();
135 grpc_loop_thread_->join();
136 grpc_loop_thread_.reset();
137
138 stack_manager_.ShutDown();
139 stack_thread_.reset();
140 is_running_ = false;
141 return ::grpc::Status::OK;
142 }
143
144 private:
145 std::unique_ptr<Thread> stack_thread_ = nullptr;
146 bool is_running_ = false;
147 std::unique_ptr<std::thread> grpc_loop_thread_ = nullptr;
148 StackManager stack_manager_;
149 int grpc_port_ = 8898;
150 };
151
152 struct GrpcRootServer::impl {
153 bool started_ = false;
154 std::unique_ptr<RootFacadeService> root_facade_service_ = nullptr;
155 std::unique_ptr<::grpc::Server> server_ = nullptr;
156 };
157
GrpcRootServer()158 GrpcRootServer::GrpcRootServer() : pimpl_(new impl()) {}
159
160 GrpcRootServer::~GrpcRootServer() = default;
161
StartServer(const std::string & address,int grpc_root_server_port,int grpc_port)162 void GrpcRootServer::StartServer(const std::string& address, int grpc_root_server_port, int grpc_port) {
163 ASSERT(!pimpl_->started_);
164 pimpl_->started_ = true;
165
166 std::string listening_port = address + ":" + std::to_string(grpc_root_server_port);
167 ::grpc::ServerBuilder builder;
168
169 pimpl_->root_facade_service_ = std::make_unique<RootFacadeService>(grpc_port);
170 builder.RegisterService(pimpl_->root_facade_service_.get());
171 builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials());
172 pimpl_->server_ = builder.BuildAndStart();
173
174 ASSERT(pimpl_->server_ != nullptr);
175 }
176
StopServer()177 void GrpcRootServer::StopServer() {
178 ASSERT(pimpl_->started_);
179 pimpl_->server_->Shutdown();
180 pimpl_->started_ = false;
181 }
182
RunGrpcLoop()183 void GrpcRootServer::RunGrpcLoop() {
184 ASSERT(pimpl_->started_);
185 pimpl_->server_->Wait();
186 }
187
188 } // namespace facade
189 } // namespace bluetooth
190