use core::{borrow::Borrow, fmt, time::Duration};
use gen_value::{index::Allocator, unmanaged::UnmanagedGenVec, Incrementable};
use serde_derive::{Deserialize, Serialize};
use crate::{
conn,
piece::{self, Index, IndexBitfield},
protocol::{BitfieldMsg, CancelMsg, Frame, HaveMsg, PieceMsg, RequestMsg, ReservedBytes},
time,
};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::{string::String, vec::Vec};
#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Id(pub [u8; 20]);
impl Id {
#[must_use]
pub fn new(bytes: [u8; 20]) -> Self {
Self(bytes)
}
}
impl AsRef<[u8]> for Id {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Borrow<[u8]> for Id {
fn borrow(&self) -> &[u8] {
&self.0
}
}
impl From<[u8; 20]> for Id {
fn from(bytes: [u8; 20]) -> Self {
Self(bytes)
}
}
impl From<Id> for Vec<u8> {
fn from(id: Id) -> Self {
Vec::from(id.0)
}
}
impl From<Id> for [u8; 20] {
fn from(id: Id) -> Self {
id.0
}
}
fmt_byte_array!(Id);
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct LocalId(pub Id);
impl AsRef<[u8]> for LocalId {
fn as_ref(&self) -> &[u8] {
&(self.0).0
}
}
impl Borrow<[u8]> for LocalId {
fn borrow(&self) -> &[u8] {
&(self.0).0
}
}
impl From<Id> for LocalId {
fn from(id: Id) -> LocalId {
LocalId(id)
}
}
impl From<LocalId> for Id {
fn from(local_id: LocalId) -> Id {
local_id.0
}
}
impl fmt::Display for LocalId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for b in &(self.0).0 {
write!(f, "{b:02x}")?;
}
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Choke {
NotChoked,
Choked,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Interest {
NotInterested,
Interested,
}
#[cfg(feature = "std")]
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Addr {
IpAddr(std::net::IpAddr),
String(String),
}
#[cfg(feature = "std")]
impl fmt::Display for Addr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IpAddr(addr) => addr.fmt(f),
Self::String(s) => s.fmt(f),
}
}
}
#[cfg(feature = "std")]
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct SocketAddr {
pub addr: Addr,
pub port: u16,
}
#[cfg(feature = "std")]
impl std::net::ToSocketAddrs for SocketAddr {
type Iter = std::vec::IntoIter<std::net::SocketAddr>;
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
match &self.addr {
Addr::IpAddr(ip_addr) => (*ip_addr, self.port)
.to_socket_addrs()
.map(|i| i.into_iter().collect::<Vec<_>>().into_iter()),
Addr::String(s) => (s.clone(), self.port).to_socket_addrs(),
}
}
}
#[cfg(feature = "std")]
impl From<std::net::SocketAddr> for SocketAddr {
fn from(socket_addr: std::net::SocketAddr) -> Self {
Self {
addr: Addr::IpAddr(socket_addr.ip()),
port: socket_addr.port(),
}
}
}
#[cfg(feature = "std")]
impl<I> From<(I, u16)> for SocketAddr
where
I: Into<std::net::IpAddr>,
{
fn from(socket_addr: (I, u16)) -> Self {
let addr = Addr::IpAddr(socket_addr.0.into());
Self {
addr,
port: socket_addr.1,
}
}
}
#[cfg(feature = "std")]
impl fmt::Display for SocketAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.addr, self.port)
}
}
#[cfg(feature = "std")]
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct SocketAddrWithOptId {
pub socket_addr: SocketAddr,
pub id: Option<Id>,
}
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct SessionId<G, I> {
pub index: I,
pub gen: G,
}
impl<G, I> From<(I, G)> for SessionId<G, I> {
fn from(value: (I, G)) -> Self {
Self {
index: value.0,
gen: value.1,
}
}
}
impl<G, I> From<SessionId<G, I>> for (I, G) {
fn from(value: SessionId<G, I>) -> Self {
(value.index, value.gen)
}
}
pub type SessionIdGenVec<T, PeerGen, PeerIndex> =
UnmanagedGenVec<T, PeerGen, PeerIndex, SessionId<PeerGen, PeerIndex>>;
#[derive(Clone, Copy, Default, Debug)]
pub struct Metrics {
pub current: conn::Metrics,
pub total: conn::Metrics,
}
impl Metrics {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn add_sent_frame(&mut self, frame: &Frame<'_>) {
self.current.sent.add_frame(frame);
self.total.sent.add_frame(frame);
}
pub fn add_received_frame(&mut self, frame: &Frame<'_>) {
self.current.received.add_frame(frame);
self.total.received.add_frame(frame);
}
pub fn reset_current(&mut self) {
self.current = conn::Metrics::default();
}
#[inline]
#[must_use]
pub fn has_been_unchoked(&self) -> bool {
self.total.sent.unchoke_msgs != 0
}
#[inline]
#[must_use]
pub fn has_received_any(&self) -> bool {
self.total.received.is_any_nonzero()
}
}
#[derive(Clone, Copy, Debug)]
pub struct MetricsHistory<const SIZE: usize> {
history: [conn::Metrics; SIZE],
history_index: usize,
}
impl<const SIZE: usize> Default for MetricsHistory<SIZE> {
fn default() -> Self {
assert!(SIZE > 0);
Self {
history: [conn::Metrics::default(); SIZE],
history_index: SIZE - 1,
}
}
}
impl<const SIZE: usize> MetricsHistory<SIZE> {
#[must_use]
pub fn prev_metrics(&self, count: usize) -> conn::Metrics {
assert!(count <= SIZE, "Requested more metrics than available");
let mut index = self.history_index;
let mut metrics = self.history[index];
for _ in 0..count {
if index == 0 {
index = self.history.len();
}
index -= 1;
metrics += self.history[index];
}
metrics
}
pub fn insert(&mut self, metrics: conn::Metrics) {
self.history_index = (self.history_index + 1) % self.history.len();
self.history[self.history_index] = metrics;
}
}
#[derive(Debug)]
enum SendState<T> {
NotSent(T),
Sent(T),
}
#[derive(Debug)]
struct State<Instant> {
local_choke: SendState<Choke>,
next_choke_deadline: Instant,
local_interest: SendState<Interest>,
next_interest_deadline: Instant,
remote_choke: Choke,
remote_interest: Interest,
read_deadline: Instant,
write_deadline: Instant,
}
impl<Instant> State<Instant>
where
Instant: time::Instant,
{
#[must_use]
fn new(now: Instant, read_timeout: Duration, write_timeout: Duration) -> Self {
Self {
local_choke: SendState::Sent(Choke::Choked),
next_choke_deadline: now.clone(),
local_interest: SendState::Sent(Interest::NotInterested),
next_interest_deadline: now.clone(),
remote_choke: Choke::Choked,
remote_interest: Interest::NotInterested,
read_deadline: now.clone() + read_timeout,
write_deadline: now + write_timeout,
}
}
#[must_use]
#[inline]
fn local_interest_as_remote_sees(&self) -> Interest {
match self.local_interest {
SendState::NotSent(state) => match state {
Interest::Interested => Interest::NotInterested,
Interest::NotInterested => Interest::Interested,
},
SendState::Sent(state) => state,
}
}
#[must_use]
#[inline]
fn local_interest_as_local_sees(&self) -> Interest {
match self.local_interest {
SendState::NotSent(state) => state,
SendState::Sent(state) => match state {
Interest::Interested => Interest::NotInterested,
Interest::NotInterested => Interest::Interested,
},
}
}
#[must_use]
#[inline]
fn local_choke_as_remote_sees(&self) -> Choke {
match self.local_choke {
SendState::NotSent(state) => match state {
Choke::Choked => Choke::NotChoked,
Choke::NotChoked => Choke::Choked,
},
SendState::Sent(state) => state,
}
}
#[must_use]
#[inline]
fn local_choke_as_local_sees(&self) -> Choke {
match self.local_choke {
SendState::NotSent(state) => state,
SendState::Sent(state) => match state {
Choke::Choked => Choke::NotChoked,
Choke::NotChoked => Choke::Choked,
},
}
}
#[must_use]
#[inline]
fn unchoked_and_remote_interested(&self) -> bool {
self.remote_interest == Interest::Interested
&& self.local_choke_as_local_sees() == Choke::NotChoked
}
#[must_use]
fn should_write(&self, now: &Instant) -> bool {
if self.write_deadline <= *now {
return true;
}
match self.local_choke {
SendState::NotSent(_) => {
if self.next_choke_deadline < *now {
return true;
}
}
SendState::Sent(_) => {}
}
match self.local_interest {
SendState::NotSent(_) => {
if self.next_interest_deadline < *now {
return true;
}
}
SendState::Sent(_) => {}
}
false
}
}
#[derive(Debug)]
pub struct Writer<'a, Instant> {
state: &'a mut State<Instant>,
peer_have_pieces: &'a IndexBitfield,
}
impl<'a, Instant> Writer<'a, Instant>
where
Instant: time::Instant,
{
#[must_use]
#[inline]
pub fn peer_have_pieces(&self) -> &IndexBitfield {
self.peer_have_pieces
}
pub fn choke(&mut self, next_state_change: Duration, now: Instant) -> Option<Choke> {
if self.state.next_choke_deadline <= now {
match self.state.local_choke {
SendState::NotSent(choke_state) => {
self.state.local_choke = SendState::Sent(choke_state);
self.state.next_choke_deadline = now + next_state_change;
return Some(choke_state);
}
SendState::Sent(_) => {}
}
}
None
}
pub fn interest(&mut self, next_state_change: Duration, now: Instant) -> Option<Interest> {
if self.state.next_interest_deadline <= now {
match self.state.local_interest {
SendState::NotSent(interest_state) => {
self.state.local_interest = SendState::Sent(interest_state);
self.state.next_interest_deadline = now + next_state_change;
return Some(interest_state);
}
SendState::Sent(_) => {}
}
}
None
}
#[must_use]
#[inline]
pub fn can_request_blocks(&mut self) -> bool {
self.state.remote_choke == Choke::NotChoked
&& self.state.local_interest_as_remote_sees() == Interest::Interested
}
#[must_use]
#[inline]
pub fn can_provide_blocks(&mut self) -> bool {
self.state.local_choke_as_remote_sees() == Choke::NotChoked
&& self.state.remote_interest == Interest::Interested
}
#[must_use]
#[inline]
pub fn should_send_keepalive(&mut self, now: &Instant) -> bool {
self.state.write_deadline <= *now
}
#[inline]
pub fn on_write(&mut self, timeout: Duration, now: Instant) {
self.state.write_deadline = now + timeout;
}
}
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(feature = "std", error("an identifier could not be allocated"))]
pub struct CouldNotAllocateId;
#[cfg(feature = "std")]
impl From<CouldNotAllocateId> for std::io::Error {
fn from(error: CouldNotAllocateId) -> Self {
std::io::Error::new(std::io::ErrorKind::Other, error)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(feature = "std", error("peer sent invalid input"))]
pub struct InvalidInput;
#[cfg(feature = "std")]
impl From<InvalidInput> for std::io::Error {
fn from(error: InvalidInput) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidInput, error)
}
}
#[derive(Debug)]
pub struct Session<Instant, PeerGen = usize, PeerIndex = usize> {
id_alloc: Allocator<PeerGen, PeerIndex, SessionId<PeerGen, PeerIndex>>,
reserved_bytes: SessionIdGenVec<ReservedBytes, PeerGen, PeerIndex>,
id: SessionIdGenVec<Id, PeerGen, PeerIndex>,
state: SessionIdGenVec<State<Instant>, PeerGen, PeerIndex>,
have_pieces: SessionIdGenVec<IndexBitfield, PeerGen, PeerIndex>,
unchoked_and_interested_count: usize,
}
impl<Instant, PeerGen, PeerIndex> Default for Session<Instant, PeerGen, PeerIndex>
where
PeerIndex: Default,
{
fn default() -> Self {
Self {
id_alloc: Allocator::default(),
reserved_bytes: SessionIdGenVec::default(),
id: SessionIdGenVec::default(),
state: SessionIdGenVec::default(),
have_pieces: SessionIdGenVec::default(),
unchoked_and_interested_count: 0,
}
}
}
impl<Instant, PeerGen, PeerIndex> Session<Instant, PeerGen, PeerIndex> {
#[inline]
#[must_use]
pub fn unchoked_and_interested_count(&self) -> usize {
self.unchoked_and_interested_count
}
}
impl<Instant, PeerGen, PeerIndex> Session<Instant, PeerGen, PeerIndex>
where
Instant: time::Instant,
PeerGen: PartialEq,
PeerIndex: Into<usize>,
{
#[inline]
#[must_use]
pub fn get_reserved_bytes(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> ReservedBytes {
self.reserved_bytes[peer_id]
}
#[inline]
#[must_use]
pub fn get_id(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> Id {
self.id[peer_id]
}
#[inline]
#[must_use]
pub fn get_choke(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> Choke {
self.state[peer_id].local_choke_as_local_sees()
}
#[inline]
#[must_use]
pub fn get_interest(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> Interest {
self.state[peer_id].local_interest_as_local_sees()
}
#[inline]
#[must_use]
pub fn get_remote_choke(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> Choke {
self.state[peer_id].remote_choke
}
#[inline]
#[must_use]
pub fn get_remote_interest(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> Interest {
self.state[peer_id].remote_interest
}
#[inline]
#[must_use]
pub fn get_have_pieces(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> &IndexBitfield {
&self.have_pieces[peer_id]
}
#[inline]
#[must_use]
pub fn get_read_deadline(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> Instant {
self.state[peer_id].read_deadline.clone()
}
#[inline]
#[must_use]
pub fn get_write_deadline(&self, peer_id: SessionId<PeerGen, PeerIndex>) -> Instant {
self.state[peer_id].write_deadline.clone()
}
#[inline]
#[must_use]
pub fn should_write(&self, peer_id: SessionId<PeerGen, PeerIndex>, now: &Instant) -> bool {
self.state[peer_id].should_write(now)
}
#[must_use]
pub fn choke(&mut self, peer_id: SessionId<PeerGen, PeerIndex>) -> bool {
let state = &mut self.state[peer_id];
match state.local_choke {
SendState::NotSent(choke_state) => match choke_state {
Choke::Choked => true,
Choke::NotChoked => {
if state.remote_interest == Interest::Interested {
self.unchoked_and_interested_count =
self.unchoked_and_interested_count.checked_sub(1).unwrap();
}
state.local_choke = SendState::Sent(Choke::Choked);
true
}
},
SendState::Sent(choke_state) => match choke_state {
Choke::Choked => false,
Choke::NotChoked => {
if state.remote_interest == Interest::Interested {
self.unchoked_and_interested_count =
self.unchoked_and_interested_count.checked_sub(1).unwrap();
}
state.local_choke = SendState::NotSent(Choke::Choked);
true
}
},
}
}
#[must_use]
pub fn unchoke(&mut self, peer_id: SessionId<PeerGen, PeerIndex>) -> bool {
let state = &mut self.state[peer_id];
match state.local_choke {
SendState::NotSent(choke_state) => match choke_state {
Choke::Choked => {
if state.remote_interest == Interest::Interested {
self.unchoked_and_interested_count =
self.unchoked_and_interested_count.checked_add(1).unwrap();
}
state.local_choke = SendState::Sent(Choke::NotChoked);
true
}
Choke::NotChoked => true,
},
SendState::Sent(choke_state) => match choke_state {
Choke::Choked => {
if state.remote_interest == Interest::Interested {
self.unchoked_and_interested_count =
self.unchoked_and_interested_count.checked_add(1).unwrap();
}
state.local_choke = SendState::NotSent(Choke::NotChoked);
true
}
Choke::NotChoked => false,
},
}
}
#[must_use]
#[inline]
pub fn interested(&mut self, peer_id: SessionId<PeerGen, PeerIndex>) -> bool {
let state = &mut self.state[peer_id];
match state.local_interest {
SendState::NotSent(interest_state) => match interest_state {
Interest::Interested => true,
Interest::NotInterested => {
state.local_interest = SendState::Sent(Interest::Interested);
true
}
},
SendState::Sent(interest_state) => match interest_state {
Interest::Interested => false,
Interest::NotInterested => {
state.local_interest = SendState::NotSent(Interest::Interested);
true
}
},
}
}
#[must_use]
#[inline]
pub fn not_interested(&mut self, peer_id: SessionId<PeerGen, PeerIndex>) -> bool {
let state = &mut self.state[peer_id];
match state.local_interest {
SendState::NotSent(interest_state) => match interest_state {
Interest::Interested => {
state.local_interest = SendState::Sent(Interest::NotInterested);
true
}
Interest::NotInterested => true,
},
SendState::Sent(interest_state) => match interest_state {
Interest::Interested => {
state.local_interest = SendState::NotSent(Interest::NotInterested);
true
}
Interest::NotInterested => false,
},
}
}
#[inline]
pub fn on_read_choke(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
state.remote_choke = Choke::Choked;
Ok(())
}
#[inline]
pub fn on_read_unchoke(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
state.remote_choke = Choke::NotChoked;
Ok(())
}
#[inline]
pub fn on_read_interested(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
if state.remote_interest == Interest::NotInterested
&& state.local_choke_as_local_sees() == Choke::NotChoked
{
self.unchoked_and_interested_count =
self.unchoked_and_interested_count.checked_add(1).unwrap();
}
state.remote_interest = Interest::Interested;
Ok(())
}
#[inline]
pub fn on_read_not_interested(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
if state.unchoked_and_remote_interested() {
self.unchoked_and_interested_count =
self.unchoked_and_interested_count.checked_sub(1).unwrap();
}
state.remote_interest = Interest::NotInterested;
Ok(())
}
#[inline]
pub fn on_read_piece(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
_piece_msg: &PieceMsg<'_>,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
Ok(())
}
#[inline]
pub fn on_read_cancel(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
_cancel_msg: &CancelMsg,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
Ok(())
}
#[inline]
pub fn on_read_keepalive(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
Ok(())
}
#[inline]
pub fn on_read_unknown(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
_msg_type: u8,
_msg_data: &[u8],
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id];
state.read_deadline = now + next_read;
Ok(())
}
}
impl<Instant, PeerGen, PeerIndex> Session<Instant, PeerGen, PeerIndex>
where
Instant: time::Instant,
PeerGen: Clone + PartialEq,
PeerIndex: Clone + Into<usize>,
{
#[inline]
pub fn on_read_have(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
have_msg: &HaveMsg,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id.clone()];
state.read_deadline = now + next_read;
let have_pieces = &mut self.have_pieces[peer_id];
if have_pieces.get(have_msg.0) {
return Err(InvalidInput);
}
have_pieces.set(have_msg.0, true);
Ok(())
}
#[inline]
pub fn on_read_bitfield(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
bitfield_msg: &BitfieldMsg<'_>,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id.clone()];
state.read_deadline = now + next_read;
let have_pieces = &mut self.have_pieces[peer_id];
if piece::verify_bitfield(have_pieces.max_index(), bitfield_msg.0).is_err() {
return Err(InvalidInput);
}
*have_pieces = IndexBitfield::from_slice(bitfield_msg.0, have_pieces.max_index());
Ok(())
}
#[inline]
pub fn on_read_request(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
request_msg: &RequestMsg,
next_read: Duration,
now: Instant,
) -> Result<(), InvalidInput> {
let state = &mut self.state[peer_id.clone()];
state.read_deadline = now + next_read;
match state.remote_interest {
Interest::NotInterested => {
return Err(InvalidInput);
}
Interest::Interested => {}
}
if self.have_pieces[peer_id].get(request_msg.0.index) {
return Err(InvalidInput);
}
Ok(())
}
#[must_use]
#[inline]
pub fn get_writer(&mut self, peer_id: SessionId<PeerGen, PeerIndex>) -> Writer<'_, Instant> {
Writer {
state: &mut self.state[peer_id.clone()],
peer_have_pieces: &mut self.have_pieces[peer_id],
}
}
}
impl<Instant, PeerGen, PeerIndex> Session<Instant, PeerGen, PeerIndex>
where
Instant: time::Instant,
{
pub fn insert(
&mut self,
reserved_bytes: ReservedBytes,
id: Id,
max_index: Index,
read_timeout: Duration,
write_timeout: Duration,
now: Instant,
) -> Result<SessionId<PeerGen, PeerIndex>, CouldNotAllocateId>
where
PeerGen: Clone + Default + PartialOrd,
PeerIndex: Clone + Into<usize> + Incrementable,
{
let peer_id = self.id_alloc.alloc().ok_or(CouldNotAllocateId)?;
self.reserved_bytes
.set_or_push(peer_id.clone(), reserved_bytes)
.unwrap();
self.id.set_or_push(peer_id.clone(), id).unwrap();
self.state
.set_or_push(
peer_id.clone(),
State::new(now, read_timeout, write_timeout),
)
.unwrap();
if let Ok(have_pieces) = self.have_pieces.get_mut(peer_id.clone()) {
have_pieces.clear_with_max_index(max_index);
} else {
self.have_pieces
.set_or_push(peer_id.clone(), IndexBitfield::with_max_index(max_index))
.unwrap();
}
Ok(peer_id)
}
pub fn remove(
&mut self,
peer_id: SessionId<PeerGen, PeerIndex>,
) -> Option<&SessionId<PeerGen, PeerIndex>>
where
PeerGen: Clone + Incrementable,
PeerIndex: Clone + Into<usize>,
{
if self.state[peer_id.clone()].unchoked_and_remote_interested() {
self.unchoked_and_interested_count =
self.unchoked_and_interested_count.checked_sub(1).unwrap();
}
let next_gen_id = self.id_alloc.dealloc(peer_id);
if let Some(next_gen_id) = next_gen_id {
self.reserved_bytes
.set_next_gen(next_gen_id.clone())
.unwrap();
self.id.set_next_gen(next_gen_id.clone()).unwrap();
self.state.set_next_gen(next_gen_id.clone()).unwrap();
self.have_pieces.set_next_gen(next_gen_id.clone()).unwrap();
}
next_gen_id
}
}