Skip to content

fix: finish reading handshake on lazyConn close#115

Merged
MarcoPolo merged 4 commits intomasterfrom
marco/lz-finish-read-on-close
Nov 14, 2024
Merged

fix: finish reading handshake on lazyConn close#115
MarcoPolo merged 4 commits intomasterfrom
marco/lz-finish-read-on-close

Conversation

@MarcoPolo
Copy link
Contributor

@MarcoPolo MarcoPolo requested a review from sukunrt November 14, 2024 05:19
@MarcoPolo MarcoPolo self-assigned this Nov 14, 2024
Comment on lines +155 to +157
// Example:
// We open a QUIC stream, write the protocol `/a`, send 1 byte of application
// data, and immediately close.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we hit this case when, for example, we open a stream and then reset it immediately due to an application error?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would. But in that case, it's fine to not read the handshake message, as the other side may or may not receive the writes made before calling Reset.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was confused when this case happened in practice in our protocol, but I realized that Bitswap opens a streams, writes to it and closes it, potentially never reading handshake data.

Copy link
Member

@sukunrt sukunrt Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness, servers(the other end of the multistream here) can handle this situation with a fix like: #87 which ignores a reset on writing the multistream header, allowing the user of such a stream to Read all the data that's written.

Copy link
Member

@sukunrt sukunrt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find! ❤️

Comment on lines +159 to +162
// This can result in a single packet that contains the stream data along
// with a STOP_SENDING frame. The other side may be unable to negotiate
// multistream select since it can't write to the stream anymore and may
// drop the stream.
Copy link
Member

@sukunrt sukunrt Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should ask js and rust libp2p to fix this on their ends similar to what #87 does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First we probably want to define optimistic multistream select so that implementations can reference that: libp2p/specs#643

// drop the stream.
//
// Note: We currently handle this case in Go, but rust-libp2p does not.
l.rhandshakeOnce.Do(l.doReadHandshake)
Copy link

@Wondertan Wondertan Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the read handshake happened in both Flush and Write, but it was done asynchronously(loc 172 and 128), and the connection could be closed before readHandshake finishes.... Makes sense

I am really surprised that Kubo folk never triggered(or realized) this case. Bitswap works there in the exactly same way, without ever calling Read, and thus sometimes without reading handshake.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, the comment on Close states no flushing is happening, but it actually does above.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, as lazy wrapper always Flushes on close, do we actually need another wrapper in basichost https://github.com/libp2p/go-libp2p/blob/7268c98442c34d26a5d87cd72e37c48e1ffe2e6c/p2p/host/basic/basic_host.go#L1151-L1161?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out. I've been meaning to remove it. I'm not sure why we need to wrap the whole thing at all.

Copy link
Member

@sukunrt sukunrt Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am really surprised that Kubo folk never triggered(or realized) this case.

I guess it did at some point. Go clients handle this correctly with: #87

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, as lazy wrapper always Flushes on close, do we actually need another wrapper in basichost

I think yes because we want to flush on CloseWrite as well.

MarcoPolo and others added 2 commits November 14, 2024 10:58
@MarcoPolo MarcoPolo merged commit a7892ae into master Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Writing from browser to streams opened on webtransport connection sometimes raises StopSending

3 participants