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

233 lines
5.8 KiB
Rust

use crate::message::{Handshake, Message, PieceMessage, SelectionMessage};
use std::collections::{HashSet, VecDeque};
use std::net::SocketAddr;
use torment_core::infohash::v1::U160;
use torment_core::metainfo::MetaInfo;
use torment_core::Bitfield;
pub mod message;
#[derive(Copy, Clone, Debug)]
pub struct PeerState {
chocked: bool,
interested: bool,
}
impl PeerState {
const fn new() -> PeerState {
PeerState {
chocked: true,
interested: false,
}
}
}
impl Default for PeerState {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Copy, Clone)]
pub enum PeerProtocol {
TCP,
MuTP,
}
#[derive(Debug, Clone)]
pub struct Peer {
id: U160,
info_hash: U160,
address: SocketAddr,
protocol: PeerProtocol,
our_state: PeerState,
their_state: PeerState,
has: Bitfield,
request_state: HashSet<SelectionMessage>,
request_queue: VecDeque<SelectionMessage>,
requested_queue: HashSet<SelectionMessage>,
received_pieces: VecDeque<PieceMessage>,
queue: VecDeque<Message>,
have_queue: VecDeque<u32>,
}
impl Peer {
pub fn id(&self) -> U160 {
self.id
}
pub fn dump_queue(&mut self) -> VecDeque<Message> {
std::mem::replace(&mut self.queue, VecDeque::new())
}
pub fn new(
address: SocketAddr,
protocol: PeerProtocol,
header: Handshake,
meta_info: &MetaInfo,
) -> Self {
Peer {
id: header.peer_id(),
info_hash: header.info_hash(),
address,
protocol,
our_state: PeerState::new(),
their_state: PeerState::new(),
has: Bitfield::with_size(meta_info.pieces()),
request_state: Default::default(),
request_queue: Default::default(),
requested_queue: Default::default(),
received_pieces: Default::default(),
queue: Default::default(),
have_queue: Default::default(),
}
}
pub fn has(&mut self) -> Bitfield {
self.has.clone()
}
pub fn process(&mut self, message: Message) -> bool {
match message {
Message::Choke => self.their_state.chocked = true,
Message::Unchoke => self.their_state.chocked = false,
Message::Interested => self.their_state.interested = true,
Message::NotInterested => self.their_state.interested = false,
Message::Have(nr) => {
self.has.set(nr);
self.have_queue.push_back(nr);
}
Message::Bitfield(bitfield) => self.has.add(bitfield),
Message::Request(selection) => {
self.request_queue.push_back(selection);
self.request_state.insert(selection);
}
Message::Cancel(selection) => {
self.request_state.remove(&selection);
}
Message::Piece(piece) => {
self.requested_queue.remove(&SelectionMessage::new(
piece.index(),
piece.offset(),
piece.length(),
));
self.received_pieces.push_back(piece);
}
}
true
}
pub fn count_open_requests(&self) -> usize {
self.requested_queue.len()
}
pub fn is_choked(&self) -> bool {
self.their_state.chocked
}
pub fn is_interested(&self) -> bool {
self.their_state.interested
}
pub fn we_interested(&self) -> bool {
self.our_state.interested
}
pub fn we_choked(&self) -> bool {
self.our_state.chocked
}
pub fn set_we_choked(&mut self, choked: bool) {
if self.our_state.chocked != choked {
self.queue.push_back(if choked {
Message::Choke
} else {
Message::Unchoke
})
}
self.our_state.chocked = choked;
}
pub fn send_bitfield(&mut self, bitfield: &Bitfield) {
self.queue.push_back(Message::Bitfield(bitfield.clone()));
}
pub fn set_we_interested(&mut self, interested: bool) {
self.our_state.interested = interested;
}
pub fn request(&mut self, index: u32, offset: u32, length: u32) {
let msg = SelectionMessage::new(index, offset, length);
if self.requested(msg) {
self.queue.push_back(Message::Request(msg));
}
}
pub fn requested(&mut self, selection: SelectionMessage) -> bool {
self.requested_queue.insert(selection)
}
pub fn unchoke(&mut self) {
if !self.our_state.chocked {
return;
}
self.queue.push_back(Message::Unchoke);
}
pub fn choke(&mut self) {
if self.our_state.chocked {
return;
}
self.queue.push_back(Message::Choke);
}
pub fn interested(&mut self) {
if self.our_state.interested {
return;
}
self.our_state.interested = true;
self.queue.push_back(Message::Interested);
}
pub fn lost_interest(&mut self) {
if !self.our_state.interested {
return;
}
self.queue.push_back(Message::NotInterested);
}
pub fn next_piece(&mut self) -> Option<PieceMessage> {
self.received_pieces.pop_front()
}
pub fn next_request(&mut self) -> Option<SelectionMessage> {
while let Some(item) = self.request_queue.pop_front() {
if self.request_state.remove(&item) {
return Some(item);
}
}
None
}
pub fn addr(&self) -> SocketAddr {
self.address
}
pub fn has_piece(&self, index: u32) -> bool {
self.has.get(index as u32)
}
pub fn next(&mut self) -> Option<Message> {
self.queue.pop_front()
}
pub fn next_have(&mut self) -> Option<u32> {
self.have_queue.pop_front()
}
}