cargo_hot_protocol/
lib.rs1pub use subsecond;
2
3#[cfg(feature = "server")]
4pub mod server;
5
6pub type Result<T> = anyhow::Result<T>;
7
8use subsecond::JumpTable;
9
10use std::io::{Read, Write};
11use std::net;
12use std::sync::Once;
13use std::thread;
14use std::time::Duration;
15
16static CLIENT: Once = Once::new();
17
18pub fn connect() {
19 CLIENT.call_once(|| {
20 let aslr_reference = subsecond::aslr_reference();
21
22 let _ = thread::spawn(move || {
24 loop {
25 if let Err(error) = run(aslr_reference) {
26 log::trace!("connection lost: {error}");
27 }
28
29 thread::sleep(Duration::from_secs(5));
30 }
31 });
32 });
33}
34
35fn run(aslr_reference: usize) -> Result<()> {
36 let mut server = net::TcpStream::connect("127.0.0.1:1100")?;
37 log::info!("Connected to `cargo-hot`");
38
39 server.write_all(&usize::to_be_bytes(aslr_reference))?;
40 server.flush()?;
41
42 let mut size = [0; std::mem::size_of::<usize>()];
43 let mut buffer = Vec::new();
44
45 loop {
46 server.read_exact(&mut size)?;
47
48 let start = std::time::Instant::now();
49 let n = usize::from_be_bytes(size);
50
51 buffer.resize(n, 0);
52 server.read_exact(&mut buffer[..n])?;
53
54 log::trace!("Read patch with {n} bytes in {:?}", start.elapsed());
55
56 let (patch, _): (JumpTable, _) =
57 bincode::serde::decode_from_slice(&buffer[..n], bincode::config::standard())?;
58 log::trace!("Decoded jumptable in {:?}", start.elapsed());
59
60 let entries = patch.map.len();
61
62 #[allow(unsafe_code)]
63 unsafe {
64 subsecond::apply_patch(patch)?;
65 }
66
67 log::info!(
68 "Hotpatch applied ({entries} entries) in {:?}",
69 start.elapsed()
70 );
71 }
72}