• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::load_protos;
2 use crate::{Flag, FlagSource};
3 use crate::{FlagPermission, FlagValue, ValuePickedFrom};
4 use aconfigd_protos::{
5     ProtoFlagQueryReturnMessage, ProtoListStorageMessage, ProtoListStorageMessageMsg,
6     ProtoStorageRequestMessage, ProtoStorageRequestMessageMsg, ProtoStorageRequestMessages,
7     ProtoStorageReturnMessage, ProtoStorageReturnMessageMsg, ProtoStorageReturnMessages,
8 };
9 use anyhow::anyhow;
10 use anyhow::Result;
11 use protobuf::Message;
12 use protobuf::SpecialFields;
13 use std::collections::HashMap;
14 use std::io::{Read, Write};
15 use std::net::Shutdown;
16 use std::os::unix::net::UnixStream;
17 
18 pub struct AconfigStorageSource {}
19 
20 static ACONFIGD_SYSTEM_SOCKET_NAME: &str = "/dev/socket/aconfigd_system";
21 static ACONFIGD_MAINLINE_SOCKET_NAME: &str = "/dev/socket/aconfigd_mainline";
22 
23 enum AconfigdSocket {
24     System,
25     Mainline,
26 }
27 
28 impl AconfigdSocket {
name(&self) -> &str29     pub fn name(&self) -> &str {
30         match self {
31             AconfigdSocket::System => ACONFIGD_SYSTEM_SOCKET_NAME,
32             AconfigdSocket::Mainline => ACONFIGD_MAINLINE_SOCKET_NAME,
33         }
34     }
35 }
36 
load_flag_to_container() -> Result<HashMap<String, String>>37 fn load_flag_to_container() -> Result<HashMap<String, String>> {
38     Ok(load_protos::load()?.into_iter().map(|p| (p.qualified_name(), p.container)).collect())
39 }
40 
convert(msg: ProtoFlagQueryReturnMessage, containers: &HashMap<String, String>) -> Result<Flag>41 fn convert(msg: ProtoFlagQueryReturnMessage, containers: &HashMap<String, String>) -> Result<Flag> {
42     let (value, value_picked_from) = match (
43         &msg.boot_flag_value,
44         msg.default_flag_value,
45         msg.local_flag_value,
46         msg.has_local_override,
47     ) {
48         (_, _, Some(local), Some(has_local)) if has_local => {
49             (FlagValue::try_from(local.as_str())?, ValuePickedFrom::Local)
50         }
51         (Some(boot), Some(default), _, _) => {
52             let value = FlagValue::try_from(boot.as_str())?;
53             if *boot == default {
54                 (value, ValuePickedFrom::Default)
55             } else {
56                 (value, ValuePickedFrom::Server)
57             }
58         }
59         _ => return Err(anyhow!("missing override")),
60     };
61 
62     let staged_value = match (msg.boot_flag_value, msg.server_flag_value, msg.has_server_override) {
63         (Some(boot), Some(server), _) if boot == server => None,
64         (Some(boot), Some(server), Some(has_server)) if boot != server && has_server => {
65             Some(FlagValue::try_from(server.as_str())?)
66         }
67         _ => None,
68     };
69 
70     let permission = match msg.is_readwrite {
71         Some(is_readwrite) => {
72             if is_readwrite {
73                 FlagPermission::ReadWrite
74             } else {
75                 FlagPermission::ReadOnly
76             }
77         }
78         None => return Err(anyhow!("missing permission")),
79     };
80 
81     let name = msg.flag_name.ok_or(anyhow!("missing flag name"))?;
82     let package = msg.package_name.ok_or(anyhow!("missing package name"))?;
83     let qualified_name = format!("{package}.{name}");
84     Ok(Flag {
85         name,
86         package,
87         value,
88         permission,
89         value_picked_from,
90         staged_value,
91         container: containers
92             .get(&qualified_name)
93             .cloned()
94             .unwrap_or_else(|| "<no container>".to_string())
95             .to_string(),
96         // TODO: remove once DeviceConfig is not in the CLI.
97         namespace: "-".to_string(),
98     })
99 }
100 
read_from_socket(socket: AconfigdSocket) -> Result<Vec<ProtoFlagQueryReturnMessage>>101 fn read_from_socket(socket: AconfigdSocket) -> Result<Vec<ProtoFlagQueryReturnMessage>> {
102     let messages = ProtoStorageRequestMessages {
103         msgs: vec![ProtoStorageRequestMessage {
104             msg: Some(ProtoStorageRequestMessageMsg::ListStorageMessage(ProtoListStorageMessage {
105                 msg: Some(ProtoListStorageMessageMsg::All(true)),
106                 special_fields: SpecialFields::new(),
107             })),
108             special_fields: SpecialFields::new(),
109         }],
110         special_fields: SpecialFields::new(),
111     };
112 
113     let mut socket = UnixStream::connect(socket.name())?;
114 
115     let message_buffer = messages.write_to_bytes()?;
116     let mut message_length_buffer: [u8; 4] = [0; 4];
117     let message_size = &message_buffer.len();
118     message_length_buffer[0] = (message_size >> 24) as u8;
119     message_length_buffer[1] = (message_size >> 16) as u8;
120     message_length_buffer[2] = (message_size >> 8) as u8;
121     message_length_buffer[3] = *message_size as u8;
122     socket.write_all(&message_length_buffer)?;
123     socket.write_all(&message_buffer)?;
124     socket.shutdown(Shutdown::Write)?;
125 
126     let mut response_length_buffer: [u8; 4] = [0; 4];
127     socket.read_exact(&mut response_length_buffer)?;
128     let response_length = u32::from_be_bytes(response_length_buffer) as usize;
129     let mut response_buffer = vec![0; response_length];
130     socket.read_exact(&mut response_buffer)?;
131 
132     let response: ProtoStorageReturnMessages =
133         protobuf::Message::parse_from_bytes(&response_buffer)?;
134 
135     match response.msgs.as_slice() {
136         [ProtoStorageReturnMessage {
137             msg: Some(ProtoStorageReturnMessageMsg::ListStorageMessage(list_storage_message)),
138             ..
139         }] => Ok(list_storage_message.flags.clone()),
140         _ => Err(anyhow!("unexpected response from aconfigd")),
141     }
142 }
143 
144 impl FlagSource for AconfigStorageSource {
list_flags() -> Result<Vec<Flag>>145     fn list_flags() -> Result<Vec<Flag>> {
146         let containers = load_flag_to_container()?;
147         let system_messages = read_from_socket(AconfigdSocket::System);
148         let mainline_messages = read_from_socket(AconfigdSocket::Mainline);
149 
150         let mut all_messages = vec![];
151         if let Ok(system_messages) = system_messages {
152             all_messages.extend_from_slice(&system_messages);
153         }
154         if let Ok(mainline_messages) = mainline_messages {
155             all_messages.extend_from_slice(&mainline_messages);
156         }
157 
158         all_messages
159             .into_iter()
160             .map(|query_message| convert(query_message.clone(), &containers))
161             .collect()
162     }
163 
override_flag(_namespace: &str, _qualified_name: &str, _value: &str) -> Result<()>164     fn override_flag(_namespace: &str, _qualified_name: &str, _value: &str) -> Result<()> {
165         todo!()
166     }
167 }
168