go-libp2p-pubsub icon indicating copy to clipboard operation
go-libp2p-pubsub copied to clipboard

Limit the number of inbound streams

Open Stebalien opened this issue 4 years ago • 11 comments

Currently, peers can open as many inbound streams as they want.

Stebalien avatar Jun 11 '20 19:06 Stebalien

Well, it's not a correctness problem, but indeed a malicious peer could cause us to allocate an unlimited number of streams so it is a bug. We can add a check in the stream handler that goes through the open streams in the connection and closes it if there is already an open one.

vyzo avatar Jun 12 '20 08:06 vyzo

We can add a check in the stream handler that goes through the open streams in the connection and closes it if there is already an open one.

We can't quite do this, unfortunately, as stream closing is async (the other side might think the stream is closed already). We could try killing the old stream, but that would also be racy. Maybe wait for either the old stream to die, or for some timeout, and if we hit the timeout, close the new stream? Also maybe disconnect from peers that flood us with new streams?

Stebalien avatar Jun 12 '20 15:06 Stebalien

I still think we actually can do it. There is nothing in the protocol that requires more than two streams and we use a single stream created at connection time. Granted, it might interfere with stop/start logic, but that would be a breaking change that is hard to implement anyway.

TL;DR: I think we should just drop all the extra streams.

vyzo avatar Jun 12 '20 17:06 vyzo

We really can't.

  1. Starting with a single connection.
  2. Peer A opens a stream, peer B receives it.
  3. Peer A sees the connection die.
  4. Peer A creates a new connection.
  5. Peer B sees both connections (hasn't yet seen the first die).
  6. Peer A opens a new stream, peer B receives it and kills it.
  7. Peer B finally sees the original connection die, and the original stream dies.

Now there are no streams.

Stebalien avatar Jun 12 '20 17:06 Stebalien

I meant looking at the number of streams within the connection. The new connection shouldn't be affected by the old streams.

vyzo avatar Jun 12 '20 17:06 vyzo

Sure, but there are likely many reasons we could temporarily end up with multiple streams. For example, if we implement #332, we may open a stream, close it, then open a new one. The other side may see the new stream before it sees the old one close.

Basically, we cannot rely on the ordering of events across the network, except within a single stream.

Stebalien avatar Jun 12 '20 18:06 Stebalien

I think that #332 is kind of hard to implement without breaking changes anyway.

vyzo avatar Jun 12 '20 18:06 vyzo

Hm. Yes, we'd need to be able to react to protocol change events like we now do in the DHT.

Stebalien avatar Jun 12 '20 18:06 Stebalien

  1. Peer B sees both connections (hasn't yet seen the first die).

I think peer B able to send a PING message to check the stream, isn't it?

chiro-hiro avatar Jun 13 '20 03:06 chiro-hiro

In theory, yes. But the pubsub protocol would need to support a PING protocol for that to work. Even then, we'd still have to wait for a timeout to determine if the stream is actually live or dead. Given that, it's simpler to just wait the timeout, then cut one of the streams if both still appear to be live.

Honestly, thinking through this, I think we can just make a rule where:

  1. If the remote side resets the stream, we retry some number of times per time period.
  2. If we see a new stream, we cut the old stream. There's a small race here where we may pick the wrong stream, but that's fine because the other side will just open a new one.

Stebalien avatar Jun 15 '20 19:06 Stebalien

I think we are overthinking this; if the remote closes the stream we currently do nothing. If we want to allow a retry, then we can allow up to two concurrent stream and force reset the third attempt.

vyzo avatar Jun 15 '20 20:06 vyzo