Skip to content
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

Merged
merged 69 commits into from
Jan 11, 2021

Conversation

kelmenhorst
Copy link
Collaborator

@kelmenhorst kelmenhorst commented Dec 8, 2020

Part of #1057.

kelmenhorst and others added 30 commits November 8, 2020 20:08
@kelmenhorst kelmenhorst marked this pull request as ready for review December 15, 2020 14:32
@bassosimone
Copy link
Contributor

👀

Copy link
Contributor

@bassosimone bassosimone left a 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:

  1. provides many small style-related suggestions;

  2. asks questions regarding the split between QUIC and normal errors;

  3. 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
Copy link
Contributor

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
Copy link
Contributor

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

"github.com/ooni/probe-engine/netx/trace"
)

// QUICBaseDialer is a system dialer for Quic
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// QUICBaseDialer is a system dialer for Quic
// QUICBaseDialer is a system dialer for QUIC

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.
Copy link
Contributor

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

Dial(network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error)
}

// QUICSystemDialer is a base dialer for QUIC
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// QUICSystemDialer is a base dialer for QUIC
// QUICSystemDialer is the base dialer for QUIC


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)
Copy link
Contributor

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.

if ev[1].Err != nil {
t.Fatal("unexpected Err", ev[1].Err)
}
if ev[1].Name != "quic_handshake_done" {
Copy link
Contributor

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

Copy link
Collaborator Author

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.

Copy link
Contributor

@bassosimone bassosimone Jan 7, 2021

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.

Copy link
Collaborator Author

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

Copy link
Contributor

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.

Comment on lines 174 to 177
failureString := toFailureString
if b.QuicErr {
failureString = toQUICFailureString
}
Copy link
Contributor

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?

Copy link
Collaborator Author

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?

Copy link
Contributor

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.)

Copy link
Collaborator Author

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/httptransport/http3transport.go Show resolved Hide resolved
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}
Copy link
Contributor

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?

Copy link
Contributor

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).

Copy link
Collaborator Author

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

@bassosimone bassosimone left a 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!

🐳

@bassosimone bassosimone merged commit 83d6d95 into ooni:master Jan 11, 2021
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.

None yet

2 participants