1 /*
2 * Copyright (C) 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 "device_config.h"
18
19 #include <chrono>
20 #include <thread>
21
22 #include <cutils/properties.h>
23 #include <android-base/logging.h>
24
25 namespace cuttlefish {
26
27 namespace {
28
29 static constexpr auto kDataSize = sizeof(DeviceConfig::RawData);
30 static constexpr int kRetries = 5;
31 static constexpr int kRetryDelaySeconds = 5;
32
GetRawFromServer(DeviceConfig::RawData * data)33 bool GetRawFromServer(DeviceConfig::RawData* data) {
34 auto port_property = "ro.boot.cuttlefish_config_server_port";
35 auto port = property_get_int64(port_property, -1);
36 if (port < 0) {
37 LOG(ERROR) << "Unable to get config server port from property: " <<
38 port_property;
39 return false;
40 }
41 auto config_server =
42 SharedFD::VsockClient(2 /*host cid*/,
43 static_cast<unsigned int>(port), SOCK_STREAM);
44 if (!config_server->IsOpen()) {
45 LOG(ERROR) << "Unable to connect to config server: "
46 << config_server->StrError();
47 return false;
48 }
49 uint8_t* buffer = reinterpret_cast<uint8_t*>(data);
50 size_t read_idx = 0;
51 while (read_idx < kDataSize) {
52 auto read = config_server->Read(buffer + read_idx, kDataSize - read_idx);
53 if (read == 0) {
54 LOG(ERROR) << "Unexpected EOF while reading from config server, read "
55 << read_idx << " bytes, expected " << kDataSize;
56 return false;
57 }
58 if (read < 0) {
59 LOG(ERROR) << "Error reading from config server: "
60 << config_server->StrError();
61 return false;
62 }
63 read_idx += read;
64 }
65 return true;
66 }
67
68 } // namespace
69
Get()70 std::unique_ptr<DeviceConfig> DeviceConfig::Get() {
71 DeviceConfig::RawData data;
72
73 int attempts_remaining = 1 + kRetries;
74 while (attempts_remaining > 0) {
75 if (GetRawFromServer(&data)) {
76 return std::unique_ptr<DeviceConfig>(new DeviceConfig(data));
77 }
78
79 std::this_thread::sleep_for(std::chrono::seconds(kRetryDelaySeconds));
80
81 --attempts_remaining;
82 }
83 return nullptr;
84 }
85
DeviceConfig(const DeviceConfig::RawData & data)86 DeviceConfig::DeviceConfig(const DeviceConfig::RawData& data) : data_(data) {
87 generate_address_and_prefix();
88 }
89
90 } // namespace cuttlefish
91