node: Improve framing code
Thanks to @fintohaps for these suggestions.
This commit is contained in:
parent
5a4d0fff3f
commit
fd3a6583d0
|
|
@ -85,36 +85,27 @@ impl StreamId {
|
||||||
/// Get the kind of stream this is.
|
/// Get the kind of stream this is.
|
||||||
pub fn kind(&self) -> Result<StreamKind, u8> {
|
pub fn kind(&self) -> Result<StreamKind, u8> {
|
||||||
let id = *self.0;
|
let id = *self.0;
|
||||||
match (id >> 1) & 0b11 {
|
let kind = ((id >> 1) & 0b11) as u8;
|
||||||
0 => Ok(StreamKind::Control),
|
|
||||||
1 => Ok(StreamKind::Gossip),
|
StreamKind::try_from(kind)
|
||||||
2 => Ok(StreamKind::Git),
|
|
||||||
n => Err(n as u8),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a control identifier.
|
/// Create a control identifier.
|
||||||
pub fn control(link: Link) -> Self {
|
pub fn control(link: Link) -> Self {
|
||||||
match link {
|
let link = if link.is_outbound() { 0 } else { 1 };
|
||||||
Link::Outbound => Self(VarInt::from(0b000u8)),
|
Self(VarInt::from((StreamKind::Control as u8) << 1 | link))
|
||||||
Link::Inbound => Self(VarInt::from(0b001u8)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a gossip identifier.
|
/// Create a gossip identifier.
|
||||||
pub fn gossip(link: Link) -> Self {
|
pub fn gossip(link: Link) -> Self {
|
||||||
match link {
|
let link = if link.is_outbound() { 0 } else { 1 };
|
||||||
Link::Outbound => Self(VarInt::from(0b010u8)),
|
Self(VarInt::from((StreamKind::Gossip as u8) << 1 | link))
|
||||||
Link::Inbound => Self(VarInt::from(0b011u8)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a git identifier.
|
/// Create a git identifier.
|
||||||
pub fn git(link: Link) -> Self {
|
pub fn git(link: Link) -> Self {
|
||||||
match link {
|
let link = if link.is_outbound() { 0 } else { 1 };
|
||||||
Link::Outbound => Self(VarInt::from(0b100u8)),
|
Self(VarInt::from((StreamKind::Git as u8) << 1 | link))
|
||||||
Link::Inbound => Self(VarInt::from(0b101u8)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the nth identifier while preserving the stream type and initiator.
|
/// Get the nth identifier while preserving the stream type and initiator.
|
||||||
|
|
@ -157,13 +148,27 @@ impl wire::Encode for StreamId {
|
||||||
|
|
||||||
/// Type of stream.
|
/// Type of stream.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum StreamKind {
|
pub enum StreamKind {
|
||||||
/// Control stream, used to open and close streams.
|
/// Control stream, used to open and close streams.
|
||||||
Control,
|
Control = 0b00,
|
||||||
/// Gossip stream, used to exchange messages.
|
/// Gossip stream, used to exchange messages.
|
||||||
Gossip,
|
Gossip = 0b01,
|
||||||
/// Git stream, used for replication.
|
/// Git stream, used for replication.
|
||||||
Git,
|
Git = 0b10,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for StreamKind {
|
||||||
|
type Error = u8;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
0b00 => Ok(StreamKind::Control),
|
||||||
|
0b01 => Ok(StreamKind::Gossip),
|
||||||
|
0b10 => Ok(StreamKind::Git),
|
||||||
|
n => Err(n),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Protocol frame.
|
/// Protocol frame.
|
||||||
|
|
@ -357,3 +362,27 @@ impl wire::Encode for Frame {
|
||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stream_id() {
|
||||||
|
assert_eq!(StreamId(VarInt(0b000)).kind().unwrap(), StreamKind::Control);
|
||||||
|
assert_eq!(StreamId(VarInt(0b010)).kind().unwrap(), StreamKind::Gossip);
|
||||||
|
assert_eq!(StreamId(VarInt(0b100)).kind().unwrap(), StreamKind::Git);
|
||||||
|
assert_eq!(StreamId(VarInt(0b001)).link(), Link::Inbound);
|
||||||
|
assert_eq!(StreamId(VarInt(0b000)).link(), Link::Outbound);
|
||||||
|
assert_eq!(StreamId(VarInt(0b101)).link(), Link::Inbound);
|
||||||
|
assert_eq!(StreamId(VarInt(0b100)).link(), Link::Outbound);
|
||||||
|
|
||||||
|
assert_eq!(StreamId::git(Link::Outbound), StreamId(VarInt(0b100)));
|
||||||
|
assert_eq!(StreamId::control(Link::Outbound), StreamId(VarInt(0b000)));
|
||||||
|
assert_eq!(StreamId::gossip(Link::Outbound), StreamId(VarInt(0b010)));
|
||||||
|
|
||||||
|
assert_eq!(StreamId::git(Link::Inbound), StreamId(VarInt(0b101)));
|
||||||
|
assert_eq!(StreamId::control(Link::Inbound), StreamId(VarInt(0b001)));
|
||||||
|
assert_eq!(StreamId::gossip(Link::Inbound), StreamId(VarInt(0b011)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ impl<T: AsRef<[u8]>> ChannelWriter<T> {
|
||||||
/// the protocol via the usual means, which is to close the connection. Git also doesn't have
|
/// the protocol via the usual means, which is to close the connection. Git also doesn't have
|
||||||
/// any special message we can send to signal the end of the protocol.
|
/// any special message we can send to signal the end of the protocol.
|
||||||
///
|
///
|
||||||
/// Hence, we there's no other way for the server to know that we're done sending requests
|
/// Hence, there's no other way for the server to know that we're done sending requests
|
||||||
/// than to send a special message outside the git protocol. This message can then be processed
|
/// than to send a special message outside the git protocol. This message can then be processed
|
||||||
/// by the remote worker to end the protocol. We use the special "eof" control message for this.
|
/// by the remote worker to end the protocol. We use the special "eof" control message for this.
|
||||||
pub fn eof(&self) -> Result<(), chan::SendError<ChannelEvent<T>>> {
|
pub fn eof(&self) -> Result<(), chan::SendError<ChannelEvent<T>>> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue