remove redundant recursion in p2p::io

This commit is contained in:
debris 2017-08-04 14:05:58 +02:00
parent e9f217a6de
commit 5b8bf322b0
3 changed files with 127 additions and 161 deletions

View File

@ -58,7 +58,6 @@ enum HandshakeState<A> {
version: Option<Version>, version: Option<Version>,
future: ReadMessage<Verack, A>, future: ReadMessage<Verack, A>,
}, },
Finished,
} }
enum AcceptHandshakeState<A> { enum AcceptHandshakeState<A> {
@ -74,7 +73,6 @@ enum AcceptHandshakeState<A> {
version: Option<Version>, version: Option<Version>,
future: WriteMessage<Verack, A>, future: WriteMessage<Verack, A>,
}, },
Finished,
} }
pub struct Handshake<A> { pub struct Handshake<A> {
@ -98,65 +96,56 @@ impl<A> Future for Handshake<A> where A: AsyncRead + AsyncWrite {
type Error = io::Error; type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let (next, result) = match self.state { loop {
HandshakeState::SendVersion(ref mut future) => { let next_state = match self.state {
let (stream, _) = try_ready!(future.poll()); HandshakeState::SendVersion(ref mut future) => {
(HandshakeState::ReceiveVersion(read_message(stream, self.magic, 0)), Async::NotReady) let (stream, _) = try_ready!(future.poll());
}, HandshakeState::ReceiveVersion(read_message(stream, self.magic, 0))
HandshakeState::ReceiveVersion(ref mut future) => { },
let (stream, version) = try_ready!(future.poll()); HandshakeState::ReceiveVersion(ref mut future) => {
let version = match version { let (stream, version) = try_ready!(future.poll());
Ok(version) => version, let version = match version {
Err(err) => return Ok((stream, Err(err.into())).into()), Ok(version) => version,
}; Err(err) => return Ok((stream, Err(err.into())).into()),
};
if version.version() < self.min_version { if version.version() < self.min_version {
return Ok((stream, Err(Error::InvalidVersion)).into());
}
if let (Some(self_nonce), Some(nonce)) = (self.nonce, version.nonce()) {
if self_nonce == nonce {
return Ok((stream, Err(Error::InvalidVersion)).into()); return Ok((stream, Err(Error::InvalidVersion)).into());
} }
} if let (Some(self_nonce), Some(nonce)) = (self.nonce, version.nonce()) {
if self_nonce == nonce {
return Ok((stream, Err(Error::InvalidVersion)).into());
}
}
let next = HandshakeState::SendVerack { HandshakeState::SendVerack {
version: Some(version), version: Some(version),
future: write_message(stream, verack_message(self.magic)), future: write_message(stream, verack_message(self.magic)),
}; }
},
HandshakeState::SendVerack { ref mut version, ref mut future } => {
let (stream, _) = try_ready!(future.poll());
(next, Async::NotReady) let version = version.take().expect("verack must be preceded by version");
},
HandshakeState::SendVerack { ref mut version, ref mut future } => {
let (stream, _) = try_ready!(future.poll());
let version = version.take().expect("verack must be preceded by version"); HandshakeState::ReceiveVerack {
version: Some(version),
future: read_message(stream, self.magic, 0),
}
},
HandshakeState::ReceiveVerack { ref mut version, ref mut future } => {
let (stream, _verack) = try_ready!(future.poll());
let version = version.take().expect("verack must be preceded by version");
let next = HandshakeState::ReceiveVerack { let result = HandshakeResult {
version: Some(version), negotiated_version: negotiate_version(self.version, version.version()),
future: read_message(stream, self.magic, 0), version: version,
}; };
(next, Async::NotReady) return Ok(Async::Ready((stream, Ok(result))));
}, },
HandshakeState::ReceiveVerack { ref mut version, ref mut future } => { };
let (stream, _verack) = try_ready!(future.poll()); self.state = next_state;
let version = version.take().expect("verack must be preceded by version");
let result = HandshakeResult {
negotiated_version: negotiate_version(self.version, version.version()),
version: version,
};
(HandshakeState::Finished, Async::Ready((stream, Ok(result))))
},
HandshakeState::Finished => panic!("poll Handshake after it's done"),
};
self.state = next;
match result {
// by polling again, we register new future
Async::NotReady => self.poll(),
result => Ok(result)
} }
} }
} }
@ -166,60 +155,51 @@ impl<A> Future for AcceptHandshake<A> where A: AsyncRead + AsyncWrite {
type Error = io::Error; type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let (next, result) = match self.state { loop {
AcceptHandshakeState::ReceiveVersion { ref mut local_version, ref mut future } => { let next_state = match self.state {
let (stream, version) = try_ready!(future.poll()); AcceptHandshakeState::ReceiveVersion { ref mut local_version, ref mut future } => {
let version = match version { let (stream, version) = try_ready!(future.poll());
Ok(version) => version, let version = match version {
Err(err) => return Ok((stream, Err(err.into())).into()), Ok(version) => version,
}; Err(err) => return Ok((stream, Err(err.into())).into()),
};
if version.version() < self.min_version { if version.version() < self.min_version {
return Ok((stream, Err(Error::InvalidVersion)).into());
}
if let (Some(self_nonce), Some(nonce)) = (self.nonce, version.nonce()) {
if self_nonce == nonce {
return Ok((stream, Err(Error::InvalidVersion)).into()); return Ok((stream, Err(Error::InvalidVersion)).into());
} }
} if let (Some(self_nonce), Some(nonce)) = (self.nonce, version.nonce()) {
if self_nonce == nonce {
return Ok((stream, Err(Error::InvalidVersion)).into());
}
}
let local_version = local_version.take().expect("local version must be set"); let local_version = local_version.take().expect("local version must be set");
let next = AcceptHandshakeState::SendVersion { AcceptHandshakeState::SendVersion {
version: Some(version), version: Some(version),
future: write_message(stream, version_message(self.magic, local_version)), future: write_message(stream, version_message(self.magic, local_version)),
}; }
},
AcceptHandshakeState::SendVersion { ref mut version, ref mut future } => {
let (stream, _) = try_ready!(future.poll());
AcceptHandshakeState::SendVerack {
version: version.take(),
future: write_message(stream, verack_message(self.magic)),
}
},
AcceptHandshakeState::SendVerack { ref mut version, ref mut future } => {
let (stream, _) = try_ready!(future.poll());
(next, Async::NotReady) let version = version.take().expect("verack must be preceded by version");
},
AcceptHandshakeState::SendVersion { ref mut version, ref mut future } => {
let (stream, _) = try_ready!(future.poll());
let next = AcceptHandshakeState::SendVerack {
version: version.take(),
future: write_message(stream, verack_message(self.magic)),
};
(next, Async::NotReady) let result = HandshakeResult {
}, negotiated_version: negotiate_version(self.version, version.version()),
AcceptHandshakeState::SendVerack { ref mut version, ref mut future } => { version: version,
let (stream, _) = try_ready!(future.poll()); };
let version = version.take().expect("verack must be preceded by version"); return Ok(Async::Ready((stream, Ok(result))));
},
let result = HandshakeResult { };
negotiated_version: negotiate_version(self.version, version.version()), self.state = next_state;
version: version,
};
(AcceptHandshakeState::Finished, Async::Ready((stream, Ok(result))))
},
AcceptHandshakeState::Finished => panic!("poll AcceptHandshake after it's done"),
};
self.state = next;
match result {
// by polling again, we register new future
Async::NotReady => self.poll(),
result => Ok(result)
} }
} }
} }

View File

@ -20,7 +20,6 @@ pub enum ReadAnyMessageState<A> {
header: MessageHeader, header: MessageHeader,
future: ReadExact<A, Bytes> future: ReadExact<A, Bytes>
}, },
Finished,
} }
pub struct ReadAnyMessage<A> { pub struct ReadAnyMessage<A> {
@ -32,36 +31,30 @@ impl<A> Future for ReadAnyMessage<A> where A: AsyncRead {
type Error = io::Error; type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let (next, result) = match self.state { loop {
ReadAnyMessageState::ReadHeader(ref mut header) => { let next_state = match self.state {
let (stream, header) = try_ready!(header.poll()); ReadAnyMessageState::ReadHeader(ref mut header) => {
let header = match header { let (stream, header) = try_ready!(header.poll());
Ok(header) => header, let header = match header {
Err(err) => return Ok(Err(err).into()), Ok(header) => header,
}; Err(err) => return Ok(Err(err).into()),
let future = read_exact(stream, Bytes::new_with_len(header.len as usize)); };
let next = ReadAnyMessageState::ReadPayload { ReadAnyMessageState::ReadPayload {
header: header, future: read_exact(stream, Bytes::new_with_len(header.len as usize)),
future: future, header: header,
}; }
(next, Async::NotReady) },
}, ReadAnyMessageState::ReadPayload { ref mut header, ref mut future } => {
ReadAnyMessageState::ReadPayload { ref mut header, ref mut future } => { let (_stream, bytes) = try_ready!(future.poll());
let (_stream, bytes) = try_ready!(future.poll()); if checksum(&bytes) != header.checksum {
if checksum(&bytes) != header.checksum { return Ok(Err(Error::InvalidChecksum).into());
return Ok(Err(Error::InvalidChecksum).into()); }
}
let next = ReadAnyMessageState::Finished;
(next, Ok((header.command.clone(), bytes)).into())
},
ReadAnyMessageState::Finished => panic!("poll ReadAnyMessage after it's done"),
};
self.state = next; return Ok(Async::Ready(Ok((header.command.clone(), bytes))));
match result { },
// by polling again, we register new future };
Async::NotReady => self.poll(),
result => Ok(result) self.state = next_state;
} }
} }
} }

View File

@ -25,7 +25,6 @@ enum ReadMessageState<M, A> {
ReadPayload { ReadPayload {
future: ReadPayload<M, A>, future: ReadPayload<M, A>,
}, },
Finished,
} }
pub struct ReadMessage<M, A> { pub struct ReadMessage<M, A> {
@ -38,36 +37,30 @@ impl<M, A> Future for ReadMessage<M, A> where A: AsyncRead, M: Payload {
type Error = io::Error; type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let (next, result) = match self.state { loop {
ReadMessageState::ReadHeader { version, ref mut future } => { let next_state = match self.state {
let (read, header) = try_ready!(future.poll()); ReadMessageState::ReadHeader { version, ref mut future } => {
let header = match header { let (read, header) = try_ready!(future.poll());
Ok(header) => header, let header = match header {
Err(err) => return Ok((read, Err(err)).into()), Ok(header) => header,
}; Err(err) => return Ok((read, Err(err)).into()),
if header.command != M::command() { };
return Ok((read, Err(Error::InvalidCommand)).into()); if header.command != M::command() {
} return Ok((read, Err(Error::InvalidCommand)).into());
let future = read_payload( }
read, version, header.len as usize, header.checksum, let future = read_payload(
); read, version, header.len as usize, header.checksum,
let next = ReadMessageState::ReadPayload { );
future: future, ReadMessageState::ReadPayload {
}; future: future,
(next, Async::NotReady) }
}, },
ReadMessageState::ReadPayload { ref mut future } => { ReadMessageState::ReadPayload { ref mut future } => {
let (read, payload) = try_ready!(future.poll()); let (read, payload) = try_ready!(future.poll());
(ReadMessageState::Finished, Async::Ready((read, payload))) return Ok(Async::Ready((read, payload)));
}, },
ReadMessageState::Finished => panic!("poll ReadMessage after it's done"), };
}; self.state = next_state;
self.state = next;
match result {
// by polling again, we register new future
Async::NotReady => self.poll(),
result => Ok(result)
} }
} }
} }