From aa15407d59b2777a132ee10ecec28254056e817e Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sat, 13 Jun 2020 19:20:49 +0200 Subject: [PATCH] init torrent.get_peers() with async_std::UdpSocket --- Cargo.toml | 1 + README.md | 2 ++ src/lib.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 README.md diff --git a/Cargo.toml b/Cargo.toml index 790e680..f3b3c58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] +async-std = { version = "1.6.1", features = ["attributes"] } serde_bencode = "^0.2.1" serde = "^1.0.0" serde_derive = "^1.0.0" diff --git a/README.md b/README.md new file mode 100644 index 0000000..167bc5b --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# torrent-rs +BitTorrent client diff --git a/src/lib.rs b/src/lib.rs index 2c16cf3..d327610 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,9 @@ +use async_std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; +use std::error::Error; + use byteorder::{BigEndian, ByteOrder}; use rand::Rng; -use sha1::{Digest, Sha1}; +use sha1::{Sha1, Digest}; extern crate serde; extern crate serde_bencode; @@ -87,10 +90,67 @@ impl Torrent { let result = hasher.finalize(); result.to_vec() } -} + pub fn protocol(&self) -> Option<&str> { + match &self.announce { + Some(s) => { + let aux: Vec<&str> = s.split(":").collect(); + Some(aux[0]) + } + _ => None, + } + } + // pub fn peer(&self) -> Option<&str> { + // match &self.announce { + // Some(s) => { + // let aux: Vec<&str> = s.split(":").collect(); + // Some(aux[1]) + // } + // _ => None, + // } + // } + pub async fn get_peers(&self) -> Result<(), Box> { + if self.protocol().unwrap() != "udp" { + panic!("not udp: {:?}", self.protocol().unwrap()); + } -const CONNECT_MSG: u32 = 0; -const ANNOUNCE_MSG: u32 = 1; + let peer = self.announce.clone().unwrap().replace("udp://", ""); + println!("peer {:?}", peer); + let socket = UdpSocket::bind("0.0.0.0:6681").await?; + + let conn_req = conn_req_msg().to_vec(); + println!("SENDING conn_req {:?}", conn_req); + socket.send_to(&conn_req, &peer).await?; + + // let mut res: Vec; + let mut buf = vec![0; 1024]; + + let peers = loop { + let (n, src) = socket.recv_from(&mut buf).await?; + + let typ = resp_type(&buf); + println!("res {:?}", &buf[0..n]); + println!("t {:?}", typ); + // match typ { + if typ == CONNECT_MSG { + println!("TYPE: CONNECT: {:?}", CONNECT_MSG); + let conn_resp = parse_connect_resp(&buf); + println!("conn_resp {:?}", conn_resp); + let announce_req = ann_req_msg(conn_resp.connection_id, self, 6681); + println!("announce_req {:?}", announce_req); + socket.send_to(&announce_req[..], &src).await?; + } else if typ==ANNOUNCE_MSG { + println!("TYPE: ANNOUNCE: {:?}", ANNOUNCE_MSG); + let ann_resp = parse_announce_resp(&buf); + println!("PEERS1 {:?}", ann_resp.peers); + break ann_resp.peers; + } + println!("End"); + }; + println!("PEERS2 {:?}", peers); + + Ok(()) + } +} fn conn_req_msg() -> [u8; 16] { let mut b: [u8; 16] = [0; 16]; @@ -113,11 +173,9 @@ fn ann_req_msg(connection_id: u64, torrent: &Torrent, port: u16) -> Vec { // 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) @@ -125,6 +183,8 @@ fn ann_req_msg(connection_id: u64, torrent: &Torrent, port: u16) -> Vec { b.to_vec() } +const CONNECT_MSG: u32 = 0; +const ANNOUNCE_MSG: u32 = 1; fn resp_type(b: &Vec) -> u32 { let action = BigEndian::read_u32(&b[0..4]); if action == 0 { @@ -151,7 +211,7 @@ fn parse_connect_resp(b: &Vec) -> ConnResp { #[derive(Debug)] struct Peer { ip: u32, - port: u32, + port: u32 } #[derive(Debug)] @@ -165,11 +225,11 @@ struct AnnResp { } fn parse_announce_resp(b: &Vec) -> AnnResp { let mut peers: Vec = Vec::new(); - let n_peers = (b.len() - 20) / 6; + let n_peers = (b.len()-20)/6; for i in 0..n_peers { let peer: Peer = Peer { - ip: BigEndian::read_u32(&b[20 + (6 * i)..24 + (6 * i)]), - port: BigEndian::read_u32(&b[24 + (6 * i)..26 + (6 * i)]), + ip: BigEndian::read_u32(&b[20+(6*i)..24+(6*i)]), + port: BigEndian::read_u32(&b[24+(6*i)..26+(6*i)]), }; peers.push(peer); } @@ -180,7 +240,7 @@ fn parse_announce_resp(b: &Vec) -> AnnResp { interval: BigEndian::read_u32(&b[8..12]), leechers: BigEndian::read_u32(&b[12..16]), seeders: BigEndian::read_u32(&b[16..20]), - peers: peers, + peers: peers }; ann_resp @@ -190,12 +250,18 @@ fn parse_announce_resp(b: &Vec) -> AnnResp { mod tests { use super::*; - #[test] - fn test_read() { + // #[test] + #[async_std::test] + async fn test_read() { let t = Torrent::open("test.torrent"); + // println!("{:?}", t); println!("torrent: {:?}", t.info.name); println!("announce: {:?}", t.announce.clone().unwrap()); + println!("protocol: {:?}", t.protocol().unwrap()); println!("conn_req_msg: {:?}", conn_req_msg()); + + let r = t.get_peers().await; + println!("get_peers r: {:?}", r); } }