• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 "wifi/wifi_facade.h"
16 
17 #include <memory>
18 
19 #include "netsim-daemon/src/ffi.rs.h"
20 #include "netsim/config.pb.h"
21 #include "rust/cxx.h"
22 #include "util/log.h"
23 #include "util/string_utils.h"
24 #ifdef NETSIM_ANDROID_EMULATOR
25 #include "android-qemu2-glue/emulation/WifiService.h"
26 #include "android-qemu2-glue/netsim/libslirp_driver.h"
27 #endif
28 
29 namespace netsim::wifi {
30 namespace {
31 
32 #ifdef NETSIM_ANDROID_EMULATOR
33 std::shared_ptr<android::qemu2::WifiService> wifi_service;
34 #endif
35 ;
36 
37 }  // namespace
38 
39 namespace facade {
40 
HandleWifiCallback(const uint8_t * buf,size_t size)41 size_t HandleWifiCallback(const uint8_t *buf, size_t size) {
42   //  Broadcast the response to all WiFi chips.
43   std::vector<uint8_t> packet(buf, buf + size);
44   rust::Slice<const uint8_t> packet_slice(packet.data(), packet.size());
45   wifi::facade::HandleWiFiResponse(packet_slice);
46   return size;
47 }
48 
Start(const rust::Slice<::std::uint8_t const> proto_bytes)49 void Start(const rust::Slice<::std::uint8_t const> proto_bytes) {
50 #ifdef NETSIM_ANDROID_EMULATOR
51   // Initialize hostapd and slirp inside WiFi Service.
52   config::WiFi config;
53   config.ParseFromArray(proto_bytes.data(), proto_bytes.size());
54 
55   android::qemu2::HostapdOptions hostapd = {
56       .disabled = config.hostapd_options().disabled(),
57       .ssid = config.hostapd_options().ssid(),
58       .passwd = config.hostapd_options().passwd()};
59 
60   auto host_dns = stringutils::Split(config.slirp_options().host_dns(), ",");
61   android::qemu2::SlirpOptions slirpOpts = {
62       .disabled = config.slirp_options().disabled(),
63       .ipv4 = (config.slirp_options().has_ipv4() ? config.slirp_options().ipv4()
64                                                  : true),
65       .restricted = config.slirp_options().restricted(),
66       .vnet = config.slirp_options().vnet(),
67       .vhost = config.slirp_options().vhost(),
68       .vmask = config.slirp_options().vmask(),
69       .ipv6 = (config.slirp_options().has_ipv6() ? config.slirp_options().ipv6()
70                                                  : true),
71       .vprefix6 = config.slirp_options().vprefix6(),
72       .vprefixLen = (uint8_t)config.slirp_options().vprefixlen(),
73       .vhost6 = config.slirp_options().vhost6(),
74       .vhostname = config.slirp_options().vhostname(),
75       .tftpath = config.slirp_options().tftpath(),
76       .bootfile = config.slirp_options().bootfile(),
77       .dhcpstart = config.slirp_options().dhcpstart(),
78       .dns = config.slirp_options().dns(),
79       .dns6 = config.slirp_options().dns6(),
80       .host_dns = host_dns,
81   };
82   if (!config.slirp_options().host_dns().empty()) {
83     BtsLogInfo("Host DNS server: %s",
84                config.slirp_options().host_dns().c_str());
85   }
86   auto builder = android::qemu2::WifiService::Builder()
87                      .withHostapd(hostapd)
88                      .withSlirp(slirpOpts)
89                      .withOnReceiveCallback(HandleWifiCallback)
90                      .withVerboseLogging(true);
91   wifi_service = builder.build();
92   if (!wifi_service->init()) {
93     BtsLogWarn("Failed to initialize wifi service");
94   }
95 #endif
96 }
Stop()97 void Stop() {
98 #ifdef NETSIM_ANDROID_EMULATOR
99   wifi_service->stop();
100 #endif
101 }
102 
103 }  // namespace facade
104 
libslirp_main_loop_wait()105 void libslirp_main_loop_wait() {
106 #ifdef NETSIM_ANDROID_EMULATOR
107   // main_loop_wait is a non-blocking call where fds maintained by the
108   // WiFi service (slirp) are polled and serviced for I/O. When any fd
109   // become ready for I/O, slirp_pollfds_poll() will be invoked to read
110   // from the open sockets therefore incoming packets are serviced.
111   android::qemu2::libslirp_main_loop_wait(true);
112 #endif
113 }
114 
HandleWifiRequestCxx(uint32_t chip_id,const rust::Vec<uint8_t> & packet)115 void HandleWifiRequestCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet) {
116 #ifdef NETSIM_ANDROID_EMULATOR
117   // Send the packet to the WiFi service.
118   struct iovec iov[1];
119   iov[0].iov_base = (void *)packet.data();
120   iov[0].iov_len = packet.size();
121   wifi_service->send(android::base::IOVector(iov, iov + 1));
122 #endif
123 }
124 
HostapdSendCxx(uint32_t chip_id,const rust::Vec<uint8_t> & packet)125 void HostapdSendCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet) {
126 #ifdef NETSIM_ANDROID_EMULATOR
127   // Send the packet to Hostapd.
128   struct iovec iov[1];
129   iov[0].iov_base = (void *)packet.data();
130   iov[0].iov_len = packet.size();
131   wifi_service->hostapd_send(android::base::IOVector(iov, iov + 1));
132 #endif
133 }
134 
LibslirpSendCxx(uint32_t chip_id,const rust::Vec<uint8_t> & packet)135 void LibslirpSendCxx(uint32_t chip_id, const rust::Vec<uint8_t> &packet) {
136 #ifdef NETSIM_ANDROID_EMULATOR
137   // Send the packet to libslirp.
138   struct iovec iov[1];
139   iov[0].iov_base = (void *)packet.data();
140   iov[0].iov_len = packet.size();
141   wifi_service->libslirp_send(android::base::IOVector(iov, iov + 1));
142 #endif
143 }
144 
145 }  // namespace netsim::wifi
146