• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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