|
|
@ -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<dyn Error>> {
|
|
|
|
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<u8>;
|
|
|
|
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<u8>) -> 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<u8>) -> AnnResp {
|
|
|
|
let mut peers: Vec<Peer> = 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);
|
|
|
|
}
|
|
|
|
}
|