termux_gui/
connection.rs

1//! Low-level socket connection management
2
3use std::os::unix::net::{UnixListener, UnixStream};
4use std::io::{Read, Write};
5use std::process::Command;
6use serde_json::Value;
7use rand::{thread_rng, Rng};
8use rand::distributions::Alphanumeric;
9
10use crate::error::{GuiError, Result};
11
12/// Generate a random address for abstract namespace sockets
13pub fn generate_random_address() -> String {
14    thread_rng()
15        .sample_iter(&Alphanumeric)
16        .take(50)
17        .map(char::from)
18        .collect()
19}
20
21/// Bind an abstract namespace Unix socket
22pub fn bind_abstract_socket(name: &str) -> Result<UnixListener> {
23    unsafe {
24        use std::os::unix::io::FromRawFd;
25        
26        let fd = libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0);
27        if fd < 0 {
28            return Err(GuiError::Io(std::io::Error::last_os_error()));
29        }
30        
31        let mut addr_bytes = vec![0u8];
32        addr_bytes.extend_from_slice(name.as_bytes());
33        
34        let mut addr: libc::sockaddr_un = std::mem::zeroed();
35        addr.sun_family = libc::AF_UNIX as u16;
36        for (i, &byte) in addr_bytes.iter().enumerate() {
37            addr.sun_path[i] = byte as _;
38        }
39        
40        let addr_len = (std::mem::size_of::<libc::sa_family_t>() + addr_bytes.len()) as libc::socklen_t;
41        
42        if libc::bind(fd, &addr as *const _ as *const libc::sockaddr, addr_len) < 0 {
43            libc::close(fd);
44            return Err(GuiError::SocketBind(format!("bind failed for {}", name)));
45        }
46        
47        if libc::listen(fd, 1) < 0 {
48            libc::close(fd);
49            return Err(GuiError::SocketBind(format!("listen failed for {}", name)));
50        }
51        
52        Ok(UnixListener::from_raw_fd(fd))
53    }
54}
55
56/// Send a JSON message to a stream
57pub fn send_message(stream: &mut UnixStream, msg: &Value) -> Result<()> {
58    let json_bytes = msg.to_string().into_bytes();
59    stream.write_all(&(json_bytes.len() as u32).to_be_bytes())?;
60    stream.write_all(&json_bytes)?;
61    stream.flush()?;
62    Ok(())
63}
64
65/// Read a JSON message from a stream
66pub fn read_message(stream: &mut UnixStream) -> Result<Value> {
67    let mut len_buf = [0u8; 4];
68    stream.read_exact(&mut len_buf)?;
69    let len = u32::from_be_bytes(len_buf) as usize;
70    
71    let mut buf = vec![0u8; len];
72    stream.read_exact(&mut buf)?;
73    
74    let value = serde_json::from_slice(&buf)?;
75    Ok(value)
76}
77
78/// Send a message and read the response
79pub fn send_and_read(stream: &mut UnixStream, msg: &Value) -> Result<Value> {
80    eprintln!("[DEBUG] send_and_read: sending...");
81    send_message(stream, msg)?;
82    eprintln!("[DEBUG] send_and_read: reading response...");
83    let response = read_message(stream)?;
84    eprintln!("[DEBUG] send_and_read: got response!");
85    Ok(response)
86}
87
88/// Connection to Termux GUI service
89pub struct Connection {
90    pub main_stream: UnixStream,
91    pub event_stream: UnixStream,
92}
93
94impl Connection {
95    /// Create a new connection to Termux GUI service
96    pub fn new() -> Result<Self> {
97        eprintln!("[DEBUG] Generating addresses...");
98        let addr_main = generate_random_address();
99        let addr_event = generate_random_address();
100        
101        eprintln!("[DEBUG] Binding sockets...");
102        let main_listener = bind_abstract_socket(&addr_main)?;
103        let event_listener = bind_abstract_socket(&addr_event)?;
104        
105        eprintln!("[DEBUG] Sending broadcast...");
106        // Try termux-am first, fall back to am
107        let output = Command::new("termux-am")
108            .args(&[
109                "broadcast",
110                "-n",
111                "com.termux.gui/.GUIReceiver",
112                "--es",
113                "mainSocket",
114                &addr_main,
115                "--es",
116                "eventSocket",
117                &addr_event,
118            ])
119            .output();
120        
121        match output {
122            Ok(out) if !out.status.success() => {
123                eprintln!("[DEBUG] termux-am failed, trying am...");
124                Command::new("am")
125                    .args(&[
126                        "broadcast",
127                        "-n",
128                        "com.termux.gui/.GUIReceiver",
129                        "--es",
130                        "mainSocket",
131                        &addr_main,
132                        "--es",
133                        "eventSocket",
134                        &addr_event,
135                    ])
136                    .output()
137                    .map_err(|_| GuiError::ConnectionFailed)?;
138            }
139            Err(_) => {
140                eprintln!("[DEBUG] termux-am not found, trying am...");
141                Command::new("am")
142                    .args(&[
143                        "broadcast",
144                        "-n",
145                        "com.termux.gui/.GUIReceiver",
146                        "--es",
147                        "mainSocket",
148                        &addr_main,
149                        "--es",
150                        "eventSocket",
151                        &addr_event,
152                    ])
153                    .output()
154                    .map_err(|_| GuiError::ConnectionFailed)?;
155            }
156            _ => {}
157        }
158        
159        eprintln!("[DEBUG] Accepting connections...");
160        let (mut main_stream, _) = main_listener.accept()?;
161        let (event_stream, _) = event_listener.accept()?;
162        
163        eprintln!("[DEBUG] Handshake...");
164        // Protocol handshake
165        main_stream.write_all(&[0x01])?;
166        main_stream.read_exact(&mut [0u8; 1])?;
167        
168        eprintln!("[DEBUG] Connection established!");
169        Ok(Connection {
170            main_stream,
171            event_stream,
172        })
173    }
174    
175    /// Send a message without waiting for response
176    pub fn send(&mut self, msg: &Value) -> Result<()> {
177        send_message(&mut self.main_stream, msg)
178    }
179    
180    /// Send a message and read the response
181    pub fn send_read(&mut self, msg: &Value) -> Result<Value> {
182        send_and_read(&mut self.main_stream, msg)
183    }
184    
185    /// Get a mutable reference to the event stream
186    pub fn event_stream(&mut self) -> &mut UnixStream {
187        &mut self.event_stream
188    }
189}