Comments (1)
Currently struggling to come up with a good way to push certain messages down to nested protocols.
The problem is that we handle the ExtendedMessage
as specified in the handshake extension bits, as part of the PeerWireProtocol
. Anytime a peer or us sends an ExtendedMessage
(which contains the mapping of extension identifier to message id), the PeerWireProtocol
handles it. However, ExtendedMessage
is special in that it affects the logic of any nested protocols in that they will have to look for (at runtime) the id they are responsible for parsing messages from.
The nested protocols can't know about that message if our outer PeerWireProtocol
is the only protocol that sees and handles that message. We would ideally like a mechanism to notify nested protocols of messages that were sent/received from outer protocols, so that the inner protocols can adapt as necessary to such "control" messages.
Currently, our impl for our PeerWireProtocol
looks like:
impl<P> PeerProtocol for PeerWireProtocol<P> where P: PeerProtocol {
type ProtocolMessage = PeerWireProtocolMessage<P>;
fn bytes_needed(&mut self, bytes: &[u8]) -> io::Result<Option<usize>> {
PeerWireProtocolMessage::bytes_needed(bytes, &mut self.ext_protocol)
}
fn parse_bytes(&mut self, bytes: Bytes) -> io::Result<Self::ProtocolMessage> {
PeerWireProtocolMessage::parse_bytes(bytes, &mut self.ext_protocol)
}
fn write_bytes<W>(&mut self, message: &Self::ProtocolMessage, writer: W) -> io::Result<()>
where W: Write {
message.write_bytes(writer, &mut self.ext_protocol)
}
fn message_size(&mut self, message: &Self::ProtocolMessage) -> usize {
message.message_size(&mut self.ext_protocol)
}
}
We can see that we pass no state information down to the nested protocol P
. And we should keep in mind, maybe the nested protocols don't want to accept any outer protocol message sent/recvd information (we shouldnt require them to if they dont want to). We could decide to have another impl to pass our entire message down to the nested protocol (but it could get tricky with type nesting). The other option is to pass just certain messages down, which is easier for nested types to reason about.
A new trait is proposed as being introduced:
pub trait NestedPeerProtocol<M> {
fn received_message(&mut self, message: &M);
fn sent_message(&mut self, message: &M);
}
So protocols that are expected to be nested could implement this trait, and it is up to the outer protocol to recognize that the inner protocol implements this trait (maybe for a specific message that the outer protocol handles), and call the appropriate methods.
That being said, we could update our PeerWireProtocol
impl as such:
impl<P> PeerProtocol for PeerWireProtocol<P> where P: PeerProtocol {
type ProtocolMessage = PeerWireProtocolMessage<P>;
fn bytes_needed(&mut self, bytes: &[u8]) -> io::Result<Option<usize>> {
PeerWireProtocolMessage::bytes_needed(bytes, &mut self.ext_protocol)
}
default fn parse_bytes(&mut self, bytes: Bytes) -> io::Result<Self::ProtocolMessage> {
PeerWireProtocolMessage::parse_bytes(bytes, &mut self.ext_protocol)
}
default fn write_bytes<W>(&mut self, message: &Self::ProtocolMessage, writer: W) -> io::Result<()>
where W: Write {
message.write_bytes(writer, &mut self.ext_protocol)
}
fn message_size(&mut self, message: &Self::ProtocolMessage) -> usize {
message.message_size(&mut self.ext_protocol)
}
}
impl<P> PeerProtocol for PeerWireProtocol<P> where P: PeerProtocol + NestedPeerProtocol<ExtendedMessage> {
fn parse_bytes(&mut self, bytes: Bytes) -> io::Result<Self::ProtocolMessage> {
match PeerWireProtocolMessage::parse_bytes(bytes, &mut self.ext_protocol) {
Ok(PeerWireProtocolMessage::BitsExtension(BitsExtensionMessage::Extended(msg))) => {
self.ext_protocol.received_message(&msg);
Ok(PeerWireProtocolMessage::BitsExtension(BitsExtensionMessage::Extended(msg)))
},
other => other
}
}
fn write_bytes<W>(&mut self, message: &Self::ProtocolMessage, writer: W) -> io::Result<()>
where W: Write {
match (message.write_bytes(writer, &mut self.ext_protocol), message) {
(Ok(()), &PeerWireProtocolMessage::BitsExtension(BitsExtensionMessage::Extended(ref msg))) => {
self.ext_protocol.sent_message(msg);
Ok(())
},
(other, _) => other
}
}
}
This is fine, though as we said before, we would have to have a new impl for every message we think our inner protocol would like to see (which may be fine in that ExtendedMessage
is a bit special...). We also are taking advantage of impl specialization which afaik is nightly only, which is definitely a major downside of this approach.
from bip-rs.
Related Issues (20)
- Shared/Reusable Buffer For Block Checksums
- Follow Sink Buffer Conventions For DiskManager
- Debug High CPU Usage For simple_torrent HOT 3
- Extract Compact Ip Parsing Logic To bip_util
- Using bip_utracker HOT 2
- Unable to run bip_dht example HOT 2
- Lifetimes and construction of BencodeMut trees HOT 4
- Accept Two Transport Types In Handshaker
- Add Extensions Info To PeerInfo
- Add Builder For ExtendedMessage
- Support Write Interface For Bencode Encoding HOT 1
- Integrate Hashed Timing Wheel (Data Structure) Into bip_select
- Extract Extended Logic In bip_select Into Separate Module
- Unused mut warning when using ben_map macro HOT 1
- Create BlockIdentifier Message Type HOT 1
- Re-Evaluate Backpressure In bip_select
- Setters of `MetainfoBuilder` incorrectly works with result of `BTreeMap::insert` method. HOT 4
- How to make a bittorent dht crawler with using bip-rs
- Support arbitrary data in DHT (BEP 44)?
- Publish a new version of bip_metainfo?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bip-rs.