-
Notifications
You must be signed in to change notification settings - Fork 439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[conn-manager] denying connections before they're established #418
Comments
To deny more connections I can think of these 2 options:
Option 1 looks more efficient, but harder to implement due to changes. @diasdavid Do you have an opinion on this? |
Looks like the interface defined in Whether the specific transports can themselves handle recycling listeners (listen, close, listen) is another question. If some of them don't allow this, it should be categorised as a bug, since the interface does not state that this can't happen. A problem could exist in specific transports that also do relaying, like websockets-star. If I understand correctly, when closing a listener, the connection to the signaling web socket server is closed. Since this connection may contain internal streams with other peers, besides not accepting new incoming dials, this would also close the existing connections. If this is true, I think option 2 would work best. If, for instance, the Perhaps @dryajov could shed some light on this? |
Also, @mkg20001, you have any insight / opinion on this? |
Quick hack for wrtc-star would be to just don't accept webrtc offers after a threshold is reached. For the long term solution: Maybe instead of closing the listener there could simply be new functions like ".startReject()" and ".startAccept()" (for example this would tell wrtc-star to start/stop accepting offers, yet this wouldn't require reconnecting to the wrtc-star server everytime) |
TL;DR
@pgte Relay uses muxed connections exclusively, so I think it might be out of scope for this?
I also like this approach and I think we should look into it further. If we would still want to stop listening on relay, we can always unregister the multistream handler and that should basically prevent it from listening, while still allowing to dial. Also, once the *-star protocols migrate to libp2p we can probably do the same thing (they use an ad-hoc socket-io implementation right now).
Yeah, we'll need to look into each proto and figure out how it's doing it right now. Looking at libp2p-tcp, it will call Another issues I'm thinking about is weather limiting connections like this will solve our issues? What I mean is that, the bulk of connections are muxed, and many peers will only have one underlying raw connection to it, though, I believe the exception might be webrtc? From @kumavis original issue
Are these connections to different peers or webrtc connections to a single peer? Which leads me to the next question, are we trying to limit the amount of peers we're connected to or the amount of raw connections to a single peer over a single transport? |
After taking a closer look at the readme, I can see we're limiting the amount of peers being connected to, which can be either over a raw connection or a muxed connection in the case of circuit (and ws-star currently).
Agreed, we should make the transports "reentrant", so that we can selectively start/stop them. |
@dryajob thank you for your insights! The goal here is to save resources. An active connection to a peer consumes memory and CPU (varying on connection activity), which may still be relevant in mobile contexts even if we're relaying through websockets. And in JS, memory pressure equals CPU overhead because of GC. Also, webrct is specially taxing, but I think we could solve this in general independently of transport. So, even if the p2p connections are relayed and muxed, a connection to a new peer still induces a considerable overhead (a lot of time spent on crypto, etc), which is still taxing on the peer and the relay server. I think we should, in the API, distinguish between closing the transport ( For this, I really like your idea of, much like TCP, being able to specify a @dryajov thoughts? |
Of course, having a |
Sorry, totally missed your reply!
I agree, we still need the ability to stop accepting connections on demand - maybe we need a There is one more thing thats bugging me (perhaps it even needs it's own issue?), which is, there are some connections that are more important than others. For example, dropping some connections that circuit ( |
Sounds good!
Can you explain me in a gist how circuit works (both in the cases where a) I'm dialing out and b) accepting new connections)? |
Sure thing! TL;DR
Dropping the underlying connection to the relay or from the relay (raw or muxed) will drop all the other connections that are established on top of it. So, circuit has three parts
Both the dialer and listener are borrowed from the All dialing happens over muxed connections, and once the connection between the two relayed points is established, it gets encrypted and muxed once again. Borrowing this from the circuit tutorial, this is more or less how the flow looks:
The reason why, dropping a connection might drop a bunch of circuited connections, is because that underlying connection can be to a
|
@dryajov thank you, that was very clear to me! Looks to me that a connection to a HOP node should be valued by the peer itself + the values of all the peers we are connected to through it. |
@dryajov also, I guess this would have to be applied recursively, because it looks to me like it's possible to have infinite nesting of HOP connections, or no? |
That sounds correct to me too.
Hmm - yes. But multi hop dialing is not yet here, so we can probably postpone implementing it for now, tho the reasoning is correct 👍. I also want to bring up one more thing - the go implementation has a concept of tagging peers, maybe we can borrow that as well... Basically, as far as I can tell, tagging boils down to being able to set an arbitrary value for a peer - all tags contribute to the peers value - https://github.com/libp2p/go-libp2p-connmgr/blob/master/connmgr.go#L136...L148, the peers with the lowest value then get disconnected - https://github.com/libp2p/go-libp2p-connmgr/blob/master/connmgr.go#L61...L108. Peers with higher importance, get a higher number libp2p/go-libp2p-circuit#20 and libp2p/go-libp2p-kad-dht#95. IMO, this is a reasonable and simple way of prioritizing certain peers over others... Maybe we set the default to 0.5 and go from there, tho if we're going to do this, it might make sense to switch to whole numbers, since it makes things easier(?) to handle... |
@dryajov thanks for showing that, I wasn't aware that go managed it like this (I thought it disconnected peers by order of how old the connection was). Currently, here we have a global value per peer, which defaults to 1 and can be overridden by the app. |
Yep, we're pretty close in essence to the Go approach.
I believe tagging can be applied to that as well (tho, I'm not sure what was the initial use case that Go was going after). My only aim with this (which I believe can be achieved without tagging), is to allow peers to be marked as having higher priority than another peer. i.e.: We can allow a service/app/transport to increase a peer's In this case, our concept of peer value works just as well and if we can allow for it to be adjusted arbitrarily, it'll essentially be the same thing without namespaces/tags. // cc @Stebalien @whyrusleeping @vyzo |
On the go side we don't currently have the facilities in place to close out connections before they are established. The main issue with that is that you have to do a full secio handshake anyways before you can know which peer it is, and you don't want to blanket ignore all new connections |
There is a case where a node is really resource constraint and can only afford to pay for the connections it is interested on dialing. Once those connections are set up then asks can go both ways (Protocol and Stream Muxing FTW), but letting every other node dial and force it to do the SECIO handshake is too much. For the browser, SECIO in JS is expensive. When the day comes that we can piggy back on WebRTC DTLS handshake or QUIC TLS 1.3 handshake, then the situation will be different. Still, the case will exist for IoT devices. |
Opened "peer value should be HOP-aware" issue: https://github.com/libp2p/js-libp2p-connection-manager/issues/10 |
Moving the interface discussion to here: libp2p/interface-transport#34 |
Now tracking here: https://github.com/libp2p/js-libp2p-switch/issues/251 |
@pgte is there value to keep this issue open? |
@diasdavid yes, I think so, since it's the job of the connection manager to tell the transports whether they should be accepting more connections or not. |
I think making .start()/.stop() not close existing connections is a bad idea because when the libp2p instance gets stopped it might leave unclosed connections around. Edit: With .start()/.stop() I actually meant the functions .listen() and .close() |
@mkg20001 I think that the transport interface discussion is happening here: libp2p/interface-transport#34 |
@mkg20001 I see the issue I pointed you to is closed. Perhaps create a new issue there? |
@pgte Created the issue: https://github.com/libp2p/interface-transport/issues/39 |
This was implemented with the ConnectionGater feature |
Allow hooks for denying connections before they are established.
First (and wisely) requested by @kumavis here.
The text was updated successfully, but these errors were encountered: