node: Give each peer its own inbox
Instead of a shared queue, each peer gets its own inbox.
This commit is contained in:
parent
054655d79b
commit
c138cd062c
|
|
@ -66,7 +66,11 @@ enum Peer {
|
||||||
Connecting { link: Link, id: Option<NodeId> },
|
Connecting { link: Link, id: Option<NodeId> },
|
||||||
/// The state after handshake is completed.
|
/// The state after handshake is completed.
|
||||||
/// Peers in this state are handled by the underlying service.
|
/// Peers in this state are handled by the underlying service.
|
||||||
Connected { link: Link, id: NodeId },
|
Connected {
|
||||||
|
link: Link,
|
||||||
|
id: NodeId,
|
||||||
|
inbox: VecDeque<u8>,
|
||||||
|
},
|
||||||
/// The state after a peer was disconnected, either during handshake,
|
/// The state after a peer was disconnected, either during handshake,
|
||||||
/// or once connected.
|
/// or once connected.
|
||||||
Disconnected {
|
Disconnected {
|
||||||
|
|
@ -79,6 +83,7 @@ enum Peer {
|
||||||
fetch: Fetch,
|
fetch: Fetch,
|
||||||
link: Link,
|
link: Link,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
|
inbox: VecDeque<u8>,
|
||||||
},
|
},
|
||||||
/// The peer is now upgraded and we are in control of the socket.
|
/// The peer is now upgraded and we are in control of the socket.
|
||||||
Upgraded { link: Link, id: NodeId },
|
Upgraded { link: Link, id: NodeId },
|
||||||
|
|
@ -89,9 +94,11 @@ impl std::fmt::Debug for Peer {
|
||||||
match self {
|
match self {
|
||||||
Self::Connecting { link, id: Some(id) } => write!(f, "Connecting({link:?}, {id})"),
|
Self::Connecting { link, id: Some(id) } => write!(f, "Connecting({link:?}, {id})"),
|
||||||
Self::Connecting { link, id: None } => write!(f, "Connecting({link:?})"),
|
Self::Connecting { link, id: None } => write!(f, "Connecting({link:?})"),
|
||||||
Self::Connected { link, id } => write!(f, "Connected({link:?}, {id})"),
|
Self::Connected { link, id, .. } => write!(f, "Connected({link:?}, {id})"),
|
||||||
Self::Disconnected { .. } => write!(f, "Disconnected"),
|
Self::Disconnected { .. } => write!(f, "Disconnected"),
|
||||||
Self::Upgrading { fetch, link, id } => write!(
|
Self::Upgrading {
|
||||||
|
fetch, link, id, ..
|
||||||
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"Upgrading(initiated={}, {link:?}, {id})",
|
"Upgrading(initiated={}, {link:?}, {id})",
|
||||||
fetch.initiated
|
fetch.initiated
|
||||||
|
|
@ -121,7 +128,11 @@ impl Peer {
|
||||||
/// Switch to connected state.
|
/// Switch to connected state.
|
||||||
fn connected(&mut self, id: NodeId) {
|
fn connected(&mut self, id: NodeId) {
|
||||||
if let Self::Connecting { link, .. } = self {
|
if let Self::Connecting { link, .. } = self {
|
||||||
*self = Self::Connected { link: *link, id };
|
*self = Self::Connected {
|
||||||
|
link: *link,
|
||||||
|
id,
|
||||||
|
inbox: VecDeque::new(),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
panic!("Peer::connected: session for {id} is already established");
|
panic!("Peer::connected: session for {id} is already established");
|
||||||
}
|
}
|
||||||
|
|
@ -143,28 +154,37 @@ impl Peer {
|
||||||
|
|
||||||
/// Switch to upgrading state.
|
/// Switch to upgrading state.
|
||||||
fn upgrading(&mut self, fetch: Fetch) {
|
fn upgrading(&mut self, fetch: Fetch) {
|
||||||
if let Self::Connected { id, link } = self {
|
if let Self::Connected { id, link, inbox } = self {
|
||||||
*self = Self::Upgrading {
|
*self = Self::Upgrading {
|
||||||
fetch,
|
fetch,
|
||||||
id: *id,
|
id: *id,
|
||||||
link: *link,
|
link: *link,
|
||||||
|
inbox: inbox.clone(),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
panic!("Peer::upgrading: session is not connected");
|
panic!("Peer::upgrading: session is not connected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch to upgraded state.
|
/// Switch to upgraded state. Returns the unread bytes from the peer.
|
||||||
fn upgraded(&mut self) -> Fetch {
|
#[must_use]
|
||||||
if let Self::Upgrading { fetch, id, link } = self {
|
fn upgraded(&mut self) -> (Fetch, Vec<u8>) {
|
||||||
|
if let Self::Upgrading {
|
||||||
|
fetch,
|
||||||
|
id,
|
||||||
|
link,
|
||||||
|
inbox,
|
||||||
|
} = self
|
||||||
|
{
|
||||||
let fetch = fetch.clone();
|
let fetch = fetch.clone();
|
||||||
|
let inbox = inbox.drain(..).collect();
|
||||||
log::debug!(target: "wire", "Peer {id} upgraded for fetch {}", fetch.rid);
|
log::debug!(target: "wire", "Peer {id} upgraded for fetch {}", fetch.rid);
|
||||||
|
|
||||||
*self = Self::Upgraded {
|
*self = Self::Upgraded {
|
||||||
id: *id,
|
id: *id,
|
||||||
link: *link,
|
link: *link,
|
||||||
};
|
};
|
||||||
fetch
|
(fetch, inbox)
|
||||||
} else {
|
} else {
|
||||||
panic!("Peer::upgraded: can't upgrade before handover");
|
panic!("Peer::upgraded: can't upgrade before handover");
|
||||||
}
|
}
|
||||||
|
|
@ -176,6 +196,7 @@ impl Peer {
|
||||||
*self = Self::Connected {
|
*self = Self::Connected {
|
||||||
id: *id,
|
id: *id,
|
||||||
link: *link,
|
link: *link,
|
||||||
|
inbox: VecDeque::new(),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
panic!("Peer::downgrade: can't downgrade if not in upgraded state");
|
panic!("Peer::downgrade: can't downgrade if not in upgraded state");
|
||||||
|
|
@ -199,8 +220,6 @@ pub struct Wire<R, S, W, G: Signer + EcSign> {
|
||||||
peers: HashMap<RawFd, Peer>,
|
peers: HashMap<RawFd, Peer>,
|
||||||
/// SOCKS5 proxy address.
|
/// SOCKS5 proxy address.
|
||||||
proxy: net::SocketAddr,
|
proxy: net::SocketAddr,
|
||||||
/// Buffer for incoming peer data.
|
|
||||||
read_queue: VecDeque<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R, S, W, G> Wire<R, S, W, G>
|
impl<R, S, W, G> Wire<R, S, W, G>
|
||||||
|
|
@ -230,7 +249,6 @@ where
|
||||||
proxy,
|
proxy,
|
||||||
actions: VecDeque::new(),
|
actions: VecDeque::new(),
|
||||||
peers: HashMap::default(),
|
peers: HashMap::default(),
|
||||||
read_queue: VecDeque::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,7 +330,7 @@ where
|
||||||
fn upgraded(&mut self, transport: NetTransport<WireSession<G>>) {
|
fn upgraded(&mut self, transport: NetTransport<WireSession<G>>) {
|
||||||
let fd = transport.as_raw_fd();
|
let fd = transport.as_raw_fd();
|
||||||
let peer = self.peer_mut_by_fd(fd);
|
let peer = self.peer_mut_by_fd(fd);
|
||||||
let fetch = peer.upgraded();
|
let (fetch, drain) = peer.upgraded();
|
||||||
let session = match transport.into_session() {
|
let session = match transport.into_session() {
|
||||||
Ok(session) => session,
|
Ok(session) => session,
|
||||||
Err(_) => panic!("Transport::upgraded: peer write buffer not empty on upgrade"),
|
Err(_) => panic!("Transport::upgraded: peer write buffer not empty on upgrade"),
|
||||||
|
|
@ -323,7 +341,7 @@ where
|
||||||
.send(Task {
|
.send(Task {
|
||||||
fetch,
|
fetch,
|
||||||
session,
|
session,
|
||||||
drain: self.read_queue.drain(..).collect(),
|
drain,
|
||||||
})
|
})
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
|
|
@ -470,11 +488,11 @@ where
|
||||||
self.service.connected(node_id, link);
|
self.service.connected(node_id, link);
|
||||||
}
|
}
|
||||||
SessionEvent::Data(data) => {
|
SessionEvent::Data(data) => {
|
||||||
if let Some(Peer::Connected { id, .. }) = self.peers.get(&fd) {
|
if let Some(Peer::Connected { id, inbox, .. }) = self.peers.get_mut(&fd) {
|
||||||
self.read_queue.extend(data);
|
inbox.extend(data);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match Message::decode(&mut self.read_queue) {
|
match Message::decode(inbox) {
|
||||||
Ok(msg) => self.service.received_message(*id, msg),
|
Ok(msg) => self.service.received_message(*id, msg),
|
||||||
Err(err) if err.is_eof() => {
|
Err(err) if err.is_eof() => {
|
||||||
// Buffer is empty, or message isn't complete.
|
// Buffer is empty, or message isn't complete.
|
||||||
|
|
@ -488,7 +506,7 @@ where
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
leftover.extend(self.read_queue.drain(..));
|
leftover.extend(inbox.drain(..));
|
||||||
|
|
||||||
if !leftover.is_empty() {
|
if !leftover.is_empty() {
|
||||||
log::debug!(target: "wire", "Dropping read buffer with `{:?}`", &leftover);
|
log::debug!(target: "wire", "Dropping read buffer with `{:?}`", &leftover);
|
||||||
|
|
@ -502,8 +520,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let Some(Peer::Upgrading { inbox, .. }) = self.peers.get_mut(&fd) {
|
||||||
|
// If somehow the remote peer managed to send git data before the reactor
|
||||||
|
// unregistered our session, we'll hit this branch.
|
||||||
|
inbox.extend(data);
|
||||||
} else {
|
} else {
|
||||||
log::warn!(target: "wire", "Dropping message from unconnected peer with fd {fd}");
|
log::warn!(target: "wire", "Dropping message from unconnected peer (fd={fd})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SessionEvent::Terminated(err) => {
|
SessionEvent::Terminated(err) => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue