-
Notifications
You must be signed in to change notification settings - Fork 15
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
quic: TLS handshake saver, error classification #1126
Conversation
👀 |
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.
Thank you so much! This PR contains terrific work!
My review:
-
provides many small style-related suggestions;
-
asks questions regarding the split between QUIC and normal errors;
-
asks whether it's possible to have all savers in the same place.
🎸
) | ||
|
||
// ConnectionState returns an empty connection state | ||
// because the quic-go interface go 1.15 |
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 sentence here seems incomplete?
"github.com/lucas-clemente/quic-go" | ||
) | ||
|
||
// ConnectionState returns the connection state of a session which is only accessible using go 1.15 |
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 it's fine to avoid mentioning Go 1.15 explicitly here
netx/dialer/quic_dialer.go
Outdated
"github.com/ooni/probe-engine/netx/trace" | ||
) | ||
|
||
// QUICBaseDialer is a system dialer for Quic |
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.
// QUICBaseDialer is a system dialer for Quic | |
// QUICBaseDialer is a system dialer for QUIC |
netx/dialer/quic_dialer.go
Outdated
DialContext(ctx context.Context, network, addr string, host string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) | ||
} | ||
|
||
// QUICDialer is the definition of dialer for QUIC assumed by this package. |
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 documentation comment should be updated because we have several dialers now
netx/dialer/quic_dialer.go
Outdated
Dial(network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) | ||
} | ||
|
||
// QUICSystemDialer is a base dialer for QUIC |
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.
// QUICSystemDialer is a base dialer for QUIC | |
// QUICSystemDialer is the base dialer for QUIC |
netx/dialer/quicsaver_test.go
Outdated
|
||
func (d MockQUICDialer) DialContext(ctx context.Context, network, addr string, host string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) { | ||
if d.Dialer != nil { | ||
d.Dialer.DialContext(ctx, network, addr, host, tlsCfg, cfg) |
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 find it surprising that you don't return
here.
netx/dialer/quicsaver_test.go
Outdated
if ev[1].Err != nil { | ||
t.Fatal("unexpected Err", ev[1].Err) | ||
} | ||
if ev[1].Name != "quic_handshake_done" { |
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.
Yeah, these strings maybe should just be defined once in errorx
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 did this in correspondence to saver_test.go , seeing that, for instance, "tls_handshake_done" is also not defined in errorx.
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.
Yes, I've just checked saver.go
. It seems only the tls_handshake_{start,done}
events do not have a corresponding name inside of errorx.go
. I think I understand what is going on.
We have operations, whose name is defined in errorx.go
and then we have events. Some events have the same name of operations, so we use the names in errorx
while some others do not. This is the case of "tls_handshake_done"
.
It may be useful to have all these names in the same place to avoid typing errors, nonetheless. But maybe we can do this at a later time.
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.
yes, if so, it should be changed for TCP and QUIC both, I 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 agree with you. This does not seem a blocker to me. Let's do nothing for now. The code is already consistent as is.
netx/errorx/errorx.go
Outdated
failureString := toFailureString | ||
if b.QuicErr { | ||
failureString = toQUICFailureString | ||
} |
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.
We should chat about this part of the design. I would have instinctively put checks for QUIC related errors into the function we're already using for checking for errors. Maybe I'm missing something?
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.
Yes, this would probably be more clear. In doing that, should, for example, a timeout error, induce the same notation in the result file, regardless whether it happened during a QUIC or a TCP connection? Or do you prefer having a generic_timeout_error
and a quic_generic_timeout_error
?
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 would keep a generic_timeout_error
for now. I think maybe in the future we'll need to have more specific or different errors. But, for now, it seems to me we understand what is going on by combining operation and error.
(The error is generic_timeout_error
rather than just timeout
or timeout_error
for legacy reasons that I honestly do not remember. Every time I write a table in LaTeX, I regret that this name is so long.)
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 I moved the QUIC specific content from the toQUICFailureString
function into the toFailureString
function and updated the tests. I added the QUIC specific failures in a batch at the end of the function. I'm not sure if the order should instead be based on the failure type.
netx/netx.go
Outdated
if config.FullResolver == nil { | ||
config.FullResolver = NewResolver(config) | ||
} | ||
d := &dialer.HTTP3DNSDialer{Resolver: config.FullResolver} | ||
var dialer HTTP3Dialer = &httptransport.HTTP3WrapperDialer{Dialer: d} | ||
var d dialer.QUICContextDialer = &dialer.QUICSystemDialer{Saver: config.ReadWriteSaver} |
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 also mentioned above that I don't 100% understand this saver here. Maybe I'm missing something?
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.
Update: I think now I understand its purpose. Please refer to this comment: #1126 (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.
Do you think the ReadWriteSaver should be encapsulated in a higher-level Dialer? In this case I'd have to provide access to the UDPconn struct to higher level Dialers.
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'll ask you more details in chat. This part of the convo seems complex.
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, for the records. That is the only place where we can observe a UDP connection and wrap it. Doing this kind of wrapping elsewhere is possible, but seems also less practical.
Avoid names like quicdialer.QUICFoo. We're already into the quicdialer package, so we can save typing the QUIC prefix. Wrap lines that seem to long (a subjective call, of course). It seems there were two similar mockable dialers, so unify them such that we only have one. We gain a little in simplicity.
A couple of cosmetic changes. Removed likely redundant tests. Note that we still need to implement one more test 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.
I've read this diff very carefully, checked out the code myself, run tests, added formatting changes, and other minor changes to this pull request.
The code in this pull request is excellent! I am really looking forward to merging this code and having enhanced QUIC measurement capabilities.
Thank you so much, you did a great job! I'm going to merge as soon as checks are green!
🐳
Part of #1057.