1use std::io::{ Write};
2use std::io::{BufReader, BufRead};
3use std::net::TcpStream;
4use std::str;
5use std::path::Path;
6
7use crate::e::{ErrorKind, S5Error};
9
10use libtor::{Tor,TorFlag,log};
11
12use sha1::{Sha1, Digest};
13
14use bitcoin::secp256k1::rand::prelude::thread_rng;
15use bitcoin::secp256k1::rand::Rng;
16
17
18fn _tor_salted_password_hash(password: &str)->String{{
19 let salt = thread_rng().gen::<[u8; 8]>().to_vec();
20 let salt_hex = hex::encode(salt);
21 let to_hash = salt_hex.clone() + password;
22
23 let mut hasher = Sha1::new();
24 hasher.update(to_hash.as_bytes());
25 let hashed_password = hasher.finalize();
26 let mut hashed_password_hex = hex::encode(&hashed_password);
27 hashed_password_hex.insert_str(0, &salt_hex);
28 hashed_password_hex.insert_str(0, "16:");
29 hashed_password_hex
30}}
31
32
33pub fn start(tmp_path: &str) -> String {
34 let tmp_path = Path::new(tmp_path);
35 let exists = tmp_path.exists();
36 let tmp_path = if exists {
37 tmp_path.join("tor-rust")
38 } else {
39 eprintln!("Bad base path! using /tmp");
40 Path::new("/tmp/tor-rust").to_path_buf()
41 };
42
43 Tor::new()
47 .flag(TorFlag::DataDirectory(tmp_path.to_string_lossy().to_string()))
48 .flag(TorFlag::SocksPort(19050))
49 .flag(TorFlag::ControlPort(9000))
50 .flag(TorFlag::LogTo(log::LogLevel::Err,log::LogDestination::Stderr))
51 .start_background();
59 "control_key".to_string()
60}
61
62pub fn bootstrap_progress(_control_key: &str) -> Result<usize, S5Error> {
63 let mut stream = match TcpStream::connect("127.0.0.1:9000") {
64 Ok(result) => result,
65 Err(_) => {
66 return Err(S5Error::new(
67 ErrorKind::Network,
68 "Could not connect to tor daemon.",
69 ))
70 }
71 };
72 let _result = stream.write(b"AUTHENTICATE ").unwrap();
76 let _result = stream.write(b"\r\n").unwrap();
78 let _result = stream.write(b"GETINFO status/bootstrap-phase").unwrap();
79 let _result = stream.write(b"\r\n").unwrap();
80
81 let mut reader = BufReader::new(&mut stream);
82 let received: Vec<u8> = reader.fill_buf().unwrap().to_vec();
83 reader.consume(received.len());
85
86 let response_string = str::from_utf8(&received).unwrap().to_string();
87 stream.flush().unwrap();
88 let parts = response_string.split("\r\n").collect::<Vec<&str>>();
89 println!("{:?}", parts[1]);
90 let progress = if !parts[1].is_empty() {parts[1].split(' ').collect::<Vec<&str>>()[2]}else{"PROGRESS=101"};
91 let progress_value = progress.split('=').collect::<Vec<&str>>()[1].parse::<usize>().unwrap_or(101);
94 println!("PV:{:?}", progress_value);
95 Ok(progress_value)
96}
97
98pub fn circuit_established(_control_key: &str) -> Result<bool, S5Error> {
99 let mut stream = match TcpStream::connect("127.0.0.1:9000") {
100 Ok(result) => result,
101 Err(_) => {
102 return Err(S5Error::new(
103 ErrorKind::Network,
104 "Could not connect to tor daemon.",
105 ))
106 }
107 };
108 let _result = stream.write(b"AUTHENTICATE ").unwrap();
112 let _result = stream.write(b"\r\n").unwrap();
114 let _result = stream.write(b"GETINFO status/circuit-established").unwrap();
115 let _result = stream.write(b"\r\n").unwrap();
116
117 let mut reader = BufReader::new(&mut stream);
118 let received: Vec<u8> = reader.fill_buf().unwrap().to_vec();
119 reader.consume(received.len());
121
122 let response_str = str::from_utf8(&received).unwrap();
123 Ok(response_str.contains("circuit-established=1"))
124}
125
126pub fn shutdown(_control_key: &str) -> Result<bool, S5Error> {
127 let mut stream = match TcpStream::connect("127.0.0.1:9000") {
128 Ok(result) => result,
129 Err(_) => {
130 return Err(S5Error::new(
131 ErrorKind::Network,
132 "Could not connect to tor daemon.",
133 ))
134 }
135 };
136
137 let _result = stream.write(b"AUTHENTICATE ").unwrap();
138 let _result = stream.write(b"\r\n").unwrap();
140 let _result = stream.flush().unwrap();
141 let _result = stream.write(b"SIGNAL SHUTDOWN").unwrap();
142 let _result = stream.write(b"\r\n").unwrap();
143
144 let mut reader = BufReader::new(&mut stream);
145 let received: Vec<u8> = reader.fill_buf().unwrap().to_vec();
146 reader.consume(received.len());
148
149 let response_str = str::from_utf8(&received).unwrap();
150 Ok(response_str.contains("250 OK\r\n"))
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156 use crate::config::{WalletConfig, DEFAULT_MAINNET_NODE};
157 use crate::network::fees;
158 use std::thread::sleep;
159 use std::time;
160 #[test] #[ignore]
163 fn test_tor() {
164 let control_key = start("/tmp");
165 let duration = time::Duration::from_secs(1);
168
169 sleep(duration);
170 sleep(duration);
171
172 println!("{:#?}", bootstrap_progress(&control_key).unwrap());
173
174 sleep(duration);
175 println!("{:#?}", bootstrap_progress(&control_key).unwrap());
176
177 sleep(duration);
178 println!("{:#?}", bootstrap_progress(&control_key).unwrap());
179
180 sleep(duration);
181 println!("{:#?}", bootstrap_progress(&control_key).unwrap());
182
183 sleep(duration);
184 println!("{:#?}", bootstrap_progress(&control_key).unwrap());
185
186 sleep(duration);
187 println!("{:#?}", bootstrap_progress(&control_key).unwrap());
188
189 let deposit_desc = "/0/*";
190 let config = WalletConfig::new(
191 deposit_desc,
192 DEFAULT_MAINNET_NODE,
193 Some("127.0.0.1:19050".to_string()),
194 )
195 .unwrap();
196 let fees = fees::estimate_rate(config, 6).unwrap();
197 assert!(fees.rate > 0.1);
198
199 assert!( circuit_established(&control_key).unwrap());
200 assert!(shutdown(&control_key).unwrap());
201 }
202}