use anyhow::Result;
const PROTOCOL_ID: &str = "BitTorrent protocol";
pub struct Handshake {
pstrlen: usize,
pstr: Vec<u8>,
reserved: Vec<u8>,
info_hash: Vec<u8>,
peer_id: Vec<u8>,
}
impl Handshake {
pub fn new(peer_id: Vec<u8>, info_hash: Vec<u8>) -> Self {
let pstr = String::from(PROTOCOL_ID).into_bytes();
let pstrlen = pstr.len();
let reserved: Vec<u8> = vec![0; 8];
Handshake {
pstrlen,
pstr,
reserved,
info_hash,
peer_id,
}
}
pub fn get_info_hash(self) -> Vec<u8> {
self.info_hash
}
pub fn serialize(&self) -> Result<Vec<u8>> {
let mut serialized: Vec<u8> = vec![];
serialized.push(self.pstrlen as u8);
let mut pstr: Vec<u8> = self.pstr.clone();
serialized.append(&mut pstr);
let mut reserved: Vec<u8> = self.reserved.clone();
serialized.append(&mut reserved);
let mut info_hash: Vec<u8> = self.info_hash.clone();
serialized.append(&mut info_hash);
let mut peer_id: Vec<u8> = self.peer_id.clone();
serialized.append(&mut peer_id);
Ok(serialized)
}
}
pub fn deserialize_handshake(buf: &Vec<u8>, pstrlen: usize) -> Result<Handshake> {
let pstr = buf[0..pstrlen].to_vec();
let reserved = buf[pstrlen..(pstrlen + 8)].to_vec();
let info_hash = buf[(pstrlen + 8)..(pstrlen + 8 + 20)].to_vec();
let peer_id = buf[(pstrlen + 8 + 20)..].to_vec();
let handshake = Handshake {
pstrlen,
pstr,
reserved,
info_hash,
peer_id,
};
Ok(handshake)
}