tokio-xmpp: Poll packets in a loop
This needs to be a loop in order to ignore packets we don’t care about, or those we want to handle elsewhere. Returning something isn’t correct in those two cases because it would signal to tokio that the XMPPStream is also done, while there could be additional packets waiting for us. The proper solution is thus a loop which we exit once we have something to return. Fixes a deadlock when we ignore some packets.
This commit is contained in:
parent
ac22765f21
commit
6ccc5ccace
1 changed files with 44 additions and 36 deletions
|
|
@ -243,42 +243,50 @@ impl Stream for Client {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Poll stream
|
// Poll stream
|
||||||
|
//
|
||||||
|
// This needs to be a loop in order to ignore packets we don’t care about, or those
|
||||||
|
// we want to handle elsewhere. Returning something isn’t correct in those two
|
||||||
|
// cases because it would signal to tokio that the XMPPStream is also done, while
|
||||||
|
// there could be additional packets waiting for us.
|
||||||
|
//
|
||||||
|
// The proper solution is thus a loop which we exit once we have something to
|
||||||
|
// return.
|
||||||
|
loop {
|
||||||
match Pin::new(&mut stream).poll_next(cx) {
|
match Pin::new(&mut stream).poll_next(cx) {
|
||||||
Poll::Ready(None) => {
|
Poll::Ready(None) => {
|
||||||
// EOF
|
// EOF
|
||||||
self.state = ClientState::Disconnected;
|
self.state = ClientState::Disconnected;
|
||||||
Poll::Ready(Some(Event::Disconnected(Error::Disconnected)))
|
return Poll::Ready(Some(Event::Disconnected(Error::Disconnected)));
|
||||||
}
|
}
|
||||||
Poll::Ready(Some(Ok(Packet::Stanza(stanza)))) => {
|
Poll::Ready(Some(Ok(Packet::Stanza(stanza)))) => {
|
||||||
// Receive stanza
|
// Receive stanza
|
||||||
self.state = ClientState::Connected(stream);
|
self.state = ClientState::Connected(stream);
|
||||||
Poll::Ready(Some(Event::Stanza(stanza)))
|
return Poll::Ready(Some(Event::Stanza(stanza)));
|
||||||
}
|
}
|
||||||
Poll::Ready(Some(Ok(Packet::Text(_)))) => {
|
Poll::Ready(Some(Ok(Packet::Text(_)))) => {
|
||||||
// Ignore text between stanzas
|
// Ignore text between stanzas
|
||||||
self.state = ClientState::Connected(stream);
|
|
||||||
Poll::Pending
|
|
||||||
}
|
}
|
||||||
Poll::Ready(Some(Ok(Packet::StreamStart(_)))) => {
|
Poll::Ready(Some(Ok(Packet::StreamStart(_)))) => {
|
||||||
// <stream:stream>
|
// <stream:stream>
|
||||||
self.state = ClientState::Disconnected;
|
self.state = ClientState::Disconnected;
|
||||||
Poll::Ready(Some(Event::Disconnected(
|
return Poll::Ready(Some(Event::Disconnected(
|
||||||
ProtocolError::InvalidStreamStart.into(),
|
ProtocolError::InvalidStreamStart.into(),
|
||||||
)))
|
)));
|
||||||
}
|
}
|
||||||
Poll::Ready(Some(Ok(Packet::StreamEnd))) => {
|
Poll::Ready(Some(Ok(Packet::StreamEnd))) => {
|
||||||
// End of stream: </stream:stream>
|
// End of stream: </stream:stream>
|
||||||
self.state = ClientState::Disconnected;
|
self.state = ClientState::Disconnected;
|
||||||
Poll::Ready(Some(Event::Disconnected(Error::Disconnected)))
|
return Poll::Ready(Some(Event::Disconnected(Error::Disconnected)));
|
||||||
}
|
}
|
||||||
Poll::Pending => {
|
Poll::Pending => {
|
||||||
// Try again later
|
// Try again later
|
||||||
self.state = ClientState::Connected(stream);
|
self.state = ClientState::Connected(stream);
|
||||||
Poll::Pending
|
return Poll::Pending;
|
||||||
}
|
}
|
||||||
Poll::Ready(Some(Err(e))) => {
|
Poll::Ready(Some(Err(e))) => {
|
||||||
self.state = ClientState::Disconnected;
|
self.state = ClientState::Disconnected;
|
||||||
Poll::Ready(Some(Event::Disconnected(e.into())))
|
return Poll::Ready(Some(Event::Disconnected(e.into())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue