-
Notifications
You must be signed in to change notification settings - Fork 66
feat(wstransport): add autotls support #1535
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
Conversation
0b12a03 to
5d34ffb
Compare
d84ec83 to
fd441f4
Compare
8950e08 to
f751324
Compare
| var retries = 0 | ||
| while not self.running and retries < DefaultAutotlsRetries: | ||
| retries += 1 | ||
| await sleepAsync(DefaultAutotlsWaitTimeout) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This loop is a bit ugly.
Wdyt of having an async event that is fired when running is set to true, and then here the code could look like
await self.onRunning.wait().withTimeout(someTimeout)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be a change introduced in a separate PR like so:
- add
onRunningasyncEvent field to baseTransporttype - make
Transport.startalsofireonRunning - change other transports to benefit from this too
In a note, I saw that many transports are redundant in the way they set self.running (i.e. they set self.running = true and also call the base Transport.start method, which does the same thing). We could clean that up as well in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a good thing to do in that separate PR, yes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if t of TcpTransport: | ||
| await fut | ||
| s.acceptFuts.add(s.accept(t)) | ||
| s.peerInfo.listenAddrs &= t.addrs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having this special condition for TcpTransport here and in line 380, wouldn't it be possible for AutoTLSService to asynsspawn a routine that will check the switch for the listenAddrs it has, and request the certificate when the switch has an available TCP addrs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem here runs a bit deeper. In line 369 we await all transports' futures, which include wstransport. For wstransport to be finished it needs certs from autotls, but autotls needs tcptransport to be running and accepting connections, which only happens in 382 if we don't have this condition here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ws transports -> accept blocked until auto tls is ready -> blocked until tcp transport is accepting
tcp transport -> no dependencies for accepting
does this graph represent what start dependency should be? if so, then these are separate processes that can happen in separate futures?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty much yes. The only thing missing there is the start functions:
ws transports -> start blocked until auto tls is ready -> blocked until tcp transport is accepting
tcp transport -> accept blocked until trasport started -> no dependencies to start
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ws transports -> start blocked until auto tls is ready -> blocked until tcp transport is accepting
tcp transport -> accept blocked until trasport started -> no dependencies to start
we just need to collect all futures to single wait:
wait allFutures = transport.start() + transport.accept()
ws started (gets blocked on auto tls) -> tcp started -> ws accept started (gets blocked because not started) -> tcp accept started -> ws start gets unblocked auto tls complets -> ws accept completes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having transports [ws, tc], code would call in this order:
ws start
tcp start
ws accept
tcp accept
since tcp is not depended on anything it is guaranteed to complete first (tcp start future completes -> then tcp accept completes).
ws will complete with delay after tcp completes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm I don't know if that's not going to break anything. Accept futures require self.running == true otherwise they fail (e.g. tcpTransport here). I think we should add a separate task to create asyncEvents that fire when running == true, making async dependencies cleaner and easier to work with (i suggested this here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it definitely would, but that what's coming should be fixable for wizards :)
libp2p/autotls/service.nim
Outdated
| let tcpTransports = switch.transports | ||
| .filterIt(it of TcpTransport and it.running) | ||
| .mapIt(TcpTransport(it)) | ||
|
|
||
| if tcpTransports.len == 0: | ||
| error "Could not find a running TcpTransport in switch" | ||
| return | ||
|
|
||
| let tcpTransport = tcpTransports[0] | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this code needed? why is running tcp transport needed here? what happens with tcpTransport variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens with tcpTransport variable?
Oops! My bad there.
why is this code needed? why is running tcp transport needed here?
We need a tcpTransport to receive a dial from the autotls broker. I remember we talked about having autotls spawn its own tcp server on DMs but I spoke to @richard-ramos and we decided to go with the other approach (i.e. using a tcpTransport from the switch). Edited the code to be more straightforward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so point of this code is to return error if tcp transport is not started ?
if so please consider improving understanding what's happening here and why. because looking at the code is not obvious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! Can you give me some pointers on how you'd do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create proc hasTcpTransportStarted that returns bool
call proc in this place:
# starting auto tls requires tcp transport to be running
if not hasTcpStarted():
error "Could not find a running TcpTransport in switch"
return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i dont see any change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1535 +/- ##
==========================================
- Coverage 82.91% 82.59% -0.32%
==========================================
Files 112 114 +2
Lines 18440 18672 +232
==========================================
+ Hits 15289 15422 +133
- Misses 3151 3250 +99
🚀 New features to boost your workflow:
|
695d2da to
3b87c43
Compare
libp2p/switch.nim
Outdated
|
|
||
| s.peerInfo.listenAddrs.keepItIf(it notin addrs) | ||
|
|
||
| debug "addresses", addrs = addrs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| debug "addresses", addrs = addrs | |
| debug "listen addresses", addrs = addrs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite understand the difference between addrs and listenAddrs, but apparently there is one. So addrs is technically not listenAddrs. I'm fine with whatever though. lmk what you think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i wanted to be more descriptive, what are these addresses used for? if you see log in in terminal:
DEBUG [TIME] addresses addresses={0x111, 0x222, 0x333}
what do we know here?
addresses for what?
current log message only looks usefully if you really know what are you look at...
if there is better log text then "listen addresses" consider using it
| if t of TcpTransport: | ||
| await fut | ||
| s.acceptFuts.add(s.accept(t)) | ||
| s.peerInfo.listenAddrs &= t.addrs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ws transports -> accept blocked until auto tls is ready -> blocked until tcp transport is accepting
tcp transport -> no dependencies for accepting
does this graph represent what start dependency should be? if so, then these are separate processes that can happen in separate futures?
0bd1a4b to
4dee37c
Compare
4dee37c to
2aeacd6
Compare
vladopajic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- this pr is still considered big +863 −423
- changes in switch.start proc are manually fixing problem of asynchronous start of transports, which works but is hacky and could bites us down the road; in other words it doesn't appear to be proper solution
9f92913 to
c606ac4
Compare
| await fut | ||
| s.acceptFuts.add(s.accept(t)) | ||
| s.peerInfo.listenAddrs &= t.addrs | ||
| debug "switch addresses", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably unneeded as later in the start() we have
debug "Started libp2p node", peer = s.peerInfo
which will log the same information

Use autotls installed certificates in
wstransport.