Description
Summary
Receiving a STOP_SENDING
makes poll_close
fail. This is problematic in libp2p-identify
where a node expects to be able to close its write side before reading.
Expected behaviour
libp2p-identify
should successfully exchange identify information.
Actual behaviour
Say that node A and B connected. A opens a libp2p-identify
stream to B. A expects B to send its identify information.
After having negotiated the libp2p-identify
protocol via multistream-select
:
-
B sends its identify information and closes its write side.
rust-libp2p/protocols/identify/src/protocol.rs
Lines 202 to 203 in 0c85839
B then drops the stream. Dropping the stream results inlibp2p-quic
sending aSTOP_SENDING
.
rust-libp2p/transports/quic/src/connection/substream.rs
Lines 203 to 207 in 0c85839
-
In parallel A closes its write side.
This results inSubstream::poll_close
being called inlibp2p-quic
.
rust-libp2p/transports/quic/src/connection/substream.rs
Lines 177 to 192 in 0c85839
In case theSTOP_SENDING
from B already arived,poll_close
fails and thus the identify handshake fails.
Possible Solution
- Don't send a
STOP_SENDING
onDrop
.- That would be unfortunate, the remote might send data which will never be received.
- Don't send a
STOP_SENDING
onDROP
IFF the remote already closed the write side.- That would be in-line with what upstream
quinn
does. https://github.com/quinn-rs/quinn/blob/1d390af2facdf424c7feb470909fffc29a1dca6c/quinn/src/recv_stream.rs#L396-L400 - I am not sure it would entirely prevent this issue. E.g. A's close might not make it to B before B sends the
STOP_SENDING
.
- That would be in-line with what upstream
- Ignore the
STOP_SENDING
error inpoll_close
.- That would give a false sense to upstream users. While they think closing was successful and thus assume (one can never be sure) that ones data made it to the remote, there is actually a high likelihood that remote never received the data.
- Don't close the write side in
libp2p-identify
before reading the remote's identify information.- I would expect
libp2p-identify
to be an edge-case here, i.e. I would expect other protocols not to run into this issue. E.g. in a standard request response style protocol A would send a request, then close, then B would read, then B writes, then B closes and only then B drops.
- I would expect
I am tending towards (2) AND (4).
Version
- libp2p version (version number, commit, or branch):
I am using 055636e on #2712 but any commit on master
should work. E.g. 0c85839.
Would you like to work on fixing this bug?
Maybe. Let's find consensus on a good solution first.
//CC @elenaf9
Activity