You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
7.7 KiB

  1. use async_std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
  2. use std::error::Error;
  3. use byteorder::{BigEndian, ByteOrder};
  4. use rand::Rng;
  5. use sha1::{Sha1, Digest};
  6. extern crate serde;
  7. extern crate serde_bencode;
  8. #[macro_use]
  9. extern crate serde_derive;
  10. extern crate serde_bytes;
  11. use serde_bencode::{de, ser};
  12. use serde_bytes::ByteBuf;
  13. #[derive(Debug, Deserialize)]
  14. struct Node(String, i64);
  15. #[derive(Debug, Serialize, Deserialize)]
  16. struct File {
  17. path: Vec<String>,
  18. length: i64,
  19. #[serde(default)]
  20. md5sum: Option<String>,
  21. }
  22. #[derive(Debug, Serialize, Deserialize)]
  23. struct Info {
  24. name: String,
  25. pieces: ByteBuf,
  26. #[serde(rename = "piece length")]
  27. piece_length: i64,
  28. #[serde(default)]
  29. md5sum: Option<String>,
  30. #[serde(default)]
  31. length: Option<i64>,
  32. #[serde(default)]
  33. files: Option<Vec<File>>,
  34. #[serde(default)]
  35. private: Option<u8>,
  36. #[serde(default)]
  37. path: Option<Vec<String>>,
  38. #[serde(default)]
  39. #[serde(rename = "root hash")]
  40. root_hash: Option<String>,
  41. }
  42. #[derive(Debug, Deserialize)]
  43. struct Torrent {
  44. info: Info,
  45. #[serde(default)]
  46. announce: Option<String>,
  47. #[serde(default)]
  48. nodes: Option<Vec<Node>>,
  49. #[serde(default)]
  50. encoding: Option<String>,
  51. #[serde(default)]
  52. httpseeds: Option<Vec<String>>,
  53. #[serde(default)]
  54. #[serde(rename = "announce-list")]
  55. announce_list: Option<Vec<Vec<String>>>,
  56. #[serde(default)]
  57. #[serde(rename = "creation date")]
  58. creation_date: Option<i64>,
  59. #[serde(rename = "comment")]
  60. comment: Option<String>,
  61. #[serde(default)]
  62. #[serde(rename = "created by")]
  63. created_by: Option<String>,
  64. }
  65. impl Torrent {
  66. pub fn open(path: &str) -> Torrent {
  67. let b = std::fs::read(path).unwrap();
  68. de::from_bytes::<Torrent>(&b).unwrap()
  69. }
  70. pub fn size(&self) -> u64 {
  71. let files = self.info.files.as_ref().unwrap();
  72. let mut size: u64 = 0;
  73. for i in 0..files.len() {
  74. size = size + files[i].length as u64;
  75. }
  76. size
  77. }
  78. pub fn info_hash(&self) -> Vec<u8> {
  79. let info_bytes: Vec<u8> = ser::to_bytes(&self.info).unwrap();
  80. let mut hasher = Sha1::new();
  81. hasher.update(info_bytes);
  82. let result = hasher.finalize();
  83. result.to_vec()
  84. }
  85. pub fn protocol(&self) -> Option<&str> {
  86. match &self.announce {
  87. Some(s) => {
  88. let aux: Vec<&str> = s.split(":").collect();
  89. Some(aux[0])
  90. }
  91. _ => None,
  92. }
  93. }
  94. // pub fn peer(&self) -> Option<&str> {
  95. // match &self.announce {
  96. // Some(s) => {
  97. // let aux: Vec<&str> = s.split(":").collect();
  98. // Some(aux[1])
  99. // }
  100. // _ => None,
  101. // }
  102. // }
  103. pub async fn get_peers(&self) -> Result<(), Box<dyn Error>> {
  104. if self.protocol().unwrap() != "udp" {
  105. panic!("not udp: {:?}", self.protocol().unwrap());
  106. }
  107. let peer = self.announce.clone().unwrap().replace("udp://", "");
  108. println!("peer {:?}", peer);
  109. let socket = UdpSocket::bind("0.0.0.0:6681").await?;
  110. let conn_req = conn_req_msg().to_vec();
  111. println!("SENDING conn_req {:?}", conn_req);
  112. socket.send_to(&conn_req, &peer).await?;
  113. // let mut res: Vec<u8>;
  114. let mut buf = vec![0; 1024];
  115. let peers = loop {
  116. let (n, src) = socket.recv_from(&mut buf).await?;
  117. let typ = resp_type(&buf);
  118. println!("res {:?}", &buf[0..n]);
  119. println!("t {:?}", typ);
  120. // match typ {
  121. if typ == CONNECT_MSG {
  122. println!("TYPE: CONNECT: {:?}", CONNECT_MSG);
  123. let conn_resp = parse_connect_resp(&buf);
  124. println!("conn_resp {:?}", conn_resp);
  125. let announce_req = ann_req_msg(conn_resp.connection_id, self, 6681);
  126. println!("announce_req {:?}", announce_req);
  127. socket.send_to(&announce_req[..], &src).await?;
  128. } else if typ==ANNOUNCE_MSG {
  129. println!("TYPE: ANNOUNCE: {:?}", ANNOUNCE_MSG);
  130. let ann_resp = parse_announce_resp(&buf);
  131. println!("PEERS1 {:?}", ann_resp.peers);
  132. break ann_resp.peers;
  133. }
  134. println!("End");
  135. };
  136. println!("PEERS2 {:?}", peers);
  137. Ok(())
  138. }
  139. }
  140. fn conn_req_msg() -> [u8; 16] {
  141. let mut b: [u8; 16] = [0; 16];
  142. BigEndian::write_u64(&mut b[0..8], 0x41727101980); // connection_id
  143. let random_bytes = rand::thread_rng().gen::<[u8; 4]>();
  144. b[12..16].clone_from_slice(&random_bytes[..]);
  145. b
  146. }
  147. fn ann_req_msg(connection_id: u64, torrent: &Torrent, port: u16) -> Vec<u8> {
  148. let mut b: [u8; 98] = [0; 98];
  149. BigEndian::write_u64(&mut b[0..8], connection_id);
  150. BigEndian::write_u32(&mut b[8..12], CONNECT_MSG); // action
  151. let random_bytes = rand::thread_rng().gen::<[u8; 4]>();
  152. b[12..16].clone_from_slice(&random_bytes[..]);
  153. // println!("md5sum {:?}", torrent);
  154. b[16..36].clone_from_slice(&torrent.info_hash()[..]);
  155. println!("info_hash: {:?}", &b[16..36]);
  156. // TODO [36..56] peerId b[36..56].clone_from_slice("todo".as_bytes());
  157. // TODO [56..64] downloaded
  158. println!("torrent.size(): {:?}", torrent.size());
  159. BigEndian::write_u64(&mut b[64..72], torrent.size()); // [64..72] left
  160. // TODO [72..80] uploaded
  161. // TODO [80..84] event (0:none, 1:completed, 2:started, 3:stopped)
  162. // TODO [84..88] ip address
  163. let random_bytes = rand::thread_rng().gen::<[u8; 4]>();
  164. b[88..92].clone_from_slice(&random_bytes[..]); // [88..92] key (random)
  165. BigEndian::write_i32(&mut b[92..96], -1); // [92..96] num_want (default: -1)
  166. BigEndian::write_u16(&mut b[96..98], port); // [96..98] port
  167. b.to_vec()
  168. }
  169. const CONNECT_MSG: u32 = 0;
  170. const ANNOUNCE_MSG: u32 = 1;
  171. fn resp_type(b: &Vec<u8>) -> u32 {
  172. let action = BigEndian::read_u32(&b[0..4]);
  173. if action == 0 {
  174. return CONNECT_MSG;
  175. } else {
  176. return ANNOUNCE_MSG;
  177. }
  178. }
  179. #[derive(Debug)]
  180. struct ConnResp {
  181. action: u32,
  182. transaction_id: u32,
  183. connection_id: u64,
  184. }
  185. fn parse_connect_resp(b: &Vec<u8>) -> ConnResp {
  186. ConnResp {
  187. action: BigEndian::read_u32(&b[0..4]),
  188. transaction_id: BigEndian::read_u32(&b[4..8]),
  189. connection_id: BigEndian::read_u64(&b[8..]),
  190. }
  191. }
  192. #[derive(Debug)]
  193. struct Peer {
  194. ip: u32,
  195. port: u32
  196. }
  197. #[derive(Debug)]
  198. struct AnnResp {
  199. action: u32,
  200. transaction_id: u32,
  201. interval: u32,
  202. leechers: u32,
  203. seeders: u32,
  204. peers: Vec<Peer>,
  205. }
  206. fn parse_announce_resp(b: &Vec<u8>) -> AnnResp {
  207. let mut peers: Vec<Peer> = Vec::new();
  208. let n_peers = (b.len()-20)/6;
  209. for i in 0..n_peers {
  210. let peer: Peer = Peer {
  211. ip: BigEndian::read_u32(&b[20+(6*i)..24+(6*i)]),
  212. port: BigEndian::read_u32(&b[24+(6*i)..26+(6*i)]),
  213. };
  214. peers.push(peer);
  215. }
  216. let ann_resp: AnnResp = AnnResp {
  217. action: BigEndian::read_u32(&b[0..4]),
  218. transaction_id: BigEndian::read_u32(&b[4..8]),
  219. interval: BigEndian::read_u32(&b[8..12]),
  220. leechers: BigEndian::read_u32(&b[12..16]),
  221. seeders: BigEndian::read_u32(&b[16..20]),
  222. peers: peers
  223. };
  224. ann_resp
  225. }
  226. #[cfg(test)]
  227. mod tests {
  228. use super::*;
  229. // #[test]
  230. #[async_std::test]
  231. async fn test_read() {
  232. let t = Torrent::open("test.torrent");
  233. // println!("{:?}", t);
  234. println!("torrent: {:?}", t.info.name);
  235. println!("announce: {:?}", t.announce.clone().unwrap());
  236. println!("protocol: {:?}", t.protocol().unwrap());
  237. println!("conn_req_msg: {:?}", conn_req_msg());
  238. let r = t.get_peers().await;
  239. println!("get_peers r: {:?}", r);
  240. }
  241. }