1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "backend/packet_streamer_client.h"
16
17 #include <chrono>
18 #include <cstddef>
19 #include <iostream>
20 #include <mutex>
21 #include <optional>
22 #include <thread>
23 #ifdef _WIN32
24 #include <Windows.h>
25 #else
26 #include <unistd.h>
27 #endif
28
29 #include "aemu/base/process/Command.h"
30 #include "android/base/system/System.h"
31 #include "grpcpp/channel.h"
32 #include "grpcpp/create_channel.h"
33 #include "grpcpp/security/credentials.h"
34 #include "util/log.h"
35 #include "util/os_utils.h"
36
37 namespace netsim::packet {
38 namespace {
39
40 const std::chrono::duration kConnectionDeadline = std::chrono::seconds(1);
41 std::string custom_packet_stream_endpoint = "";
42 std::shared_ptr<grpc::Channel> packet_stream_channel;
43 std::mutex channel_mutex;
44
CreateGrpcChannel()45 std::shared_ptr<grpc::Channel> CreateGrpcChannel() {
46 auto endpoint = custom_packet_stream_endpoint;
47 if (endpoint.empty()) {
48 auto port = netsim::osutils::GetServerAddress();
49 if (!port.has_value()) return nullptr;
50 endpoint = "localhost:" + port.value();
51 }
52
53 if (endpoint.empty()) return nullptr;
54 BtsLog("Creating a Grpc channel to %s", endpoint.c_str());
55 return grpc::CreateChannel(endpoint, grpc::InsecureChannelCredentials());
56 }
57
GrpcChannelReady(const std::shared_ptr<grpc::Channel> & channel)58 bool GrpcChannelReady(const std::shared_ptr<grpc::Channel> &channel) {
59 if (channel) {
60 auto deadline = std::chrono::system_clock::now() + kConnectionDeadline;
61 return channel->WaitForConnected(deadline);
62 }
63 return false;
64 }
65
RunNetsimd()66 void RunNetsimd() {
67 auto exe = android::base::System::get()->findBundledExecutable("netsimd");
68 auto cmd = android::base::Command::create({exe, "-g"});
69
70 auto netsimd = cmd.asDeamon().execute();
71 if (netsimd) {
72 BtsLog("Running netsimd as pid: %d.", netsimd->pid());
73 }
74 }
75
76 } // namespace
77
SetPacketStreamEndpoint(const std::string & endpoint)78 void SetPacketStreamEndpoint(const std::string &endpoint) {
79 if (endpoint != "default") custom_packet_stream_endpoint = endpoint;
80 }
81
GetChannel()82 std::shared_ptr<grpc::Channel> GetChannel() {
83 std::lock_guard<std::mutex> lock(channel_mutex);
84
85 bool is_netsimd_started = false;
86 for (int second : {1, 2, 4, 8}) {
87 if (!packet_stream_channel) packet_stream_channel = CreateGrpcChannel();
88 if (GrpcChannelReady(packet_stream_channel)) return packet_stream_channel;
89
90 packet_stream_channel.reset();
91
92 if (!is_netsimd_started && custom_packet_stream_endpoint.empty()) {
93 BtsLog("Starting netsim.");
94 RunNetsimd();
95 is_netsimd_started = true;
96 }
97 BtsLog("Retry connecting to netsim in %d second.", second);
98 std::this_thread::sleep_for(std::chrono::seconds(second));
99 }
100
101 BtsLog("Unable to get a packet stream channel.");
102 return nullptr;
103 }
104
CreateChannel(std::string _rootcanal_default_commands_file,std::string _rootcanal_controller_properties_file)105 std::shared_ptr<grpc::Channel> CreateChannel(
106 std::string _rootcanal_default_commands_file,
107 std::string _rootcanal_controller_properties_file) {
108 return GetChannel();
109 }
110
111 } // namespace netsim::packet
112