From 612b3b5e108c6c09be1860aca0804754951a7970 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sat, 13 Jun 2020 13:11:26 +0200 Subject: [PATCH] Add conn_req_msg & ann_req_msg contructors, torrent.size() & .info_hash() --- Cargo.toml | 3 +++ src/lib.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 29243ad..790e680 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,6 @@ serde_bencode = "^0.2.1" serde = "^1.0.0" serde_derive = "^1.0.0" serde_bytes = "0.10.0" +byteorder = "1.3.4" +rand = "0.7" +sha-1 = "0.9.0" diff --git a/src/lib.rs b/src/lib.rs index ba98ef0..b0eeb26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +use byteorder::{BigEndian, ByteOrder}; +use rand::Rng; +use sha1::{Digest, Sha1}; + extern crate serde; extern crate serde_bencode; #[macro_use] @@ -68,6 +72,55 @@ impl Torrent { let b = std::fs::read(path).unwrap(); de::from_bytes::(&b).unwrap() } + pub fn size(&self) -> u64 { + let files = self.info.files.as_ref().unwrap(); + let mut size: u64 = 0; + for i in 0..files.len() { + size = size + files[i].length as u64; + } + size + } + pub fn info_hash(&self) -> Vec { + let info_bytes: Vec = ser::to_bytes(&self.info).unwrap(); + let mut hasher = Sha1::new(); + hasher.update(info_bytes); + let result = hasher.finalize(); + result.to_vec() + } +} + +const CONNECT_MSG: u32 = 0; +const ANNOUNCE_MSG: u32 = 1; + +fn conn_req_msg() -> [u8; 16] { + let mut b: [u8; 16] = [0; 16]; + BigEndian::write_u64(&mut b[0..8], 0x41727101980); // connection_id + let random_bytes = rand::thread_rng().gen::<[u8; 4]>(); + b[12..16].clone_from_slice(&random_bytes[..]); + b +} + +fn ann_req_msg(connection_id: u64, torrent: &Torrent, port: u16) -> Vec { + let mut b: [u8; 98] = [0; 98]; + BigEndian::write_u64(&mut b[0..8], connection_id); + BigEndian::write_u32(&mut b[8..12], CONNECT_MSG); // action + let random_bytes = rand::thread_rng().gen::<[u8; 4]>(); + b[12..16].clone_from_slice(&random_bytes[..]); + // println!("md5sum {:?}", torrent); + b[16..36].clone_from_slice(&torrent.info_hash()[..]); + println!("info_hash: {:?}", &b[16..36]); + // TODO [36..56] peerId b[36..56].clone_from_slice("todo".as_bytes()); + // TODO [56..64] downloaded + println!("torrent.size(): {:?}", torrent.size()); + BigEndian::write_u64(&mut b[64..72], torrent.size()); // [64..72] left + // TODO [72..80] uploaded + // TODO [80..84] event (0:none, 1:completed, 2:started, 3:stopped) + // TODO [84..88] ip address + let random_bytes = rand::thread_rng().gen::<[u8; 4]>(); + b[88..92].clone_from_slice(&random_bytes[..]); // [88..92] key (random) + BigEndian::write_i32(&mut b[92..96], -1); // [92..96] num_want (default: -1) + BigEndian::write_u16(&mut b[96..98], port); // [96..98] port + b.to_vec() } #[cfg(test)] @@ -77,6 +130,9 @@ mod tests { #[test] fn test_read() { let t = Torrent::open("test.torrent"); - println!("{:?}", t); + println!("torrent: {:?}", t.info.name); + println!("announce: {:?}", t.announce.clone().unwrap()); + + println!("conn_req_msg: {:?}", conn_req_msg()); } }