cargo_hot_protocol/
lib.rs

1pub 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        // TODO: Wasm support
23        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}