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

proxy: simplified packetIO and proxyv2 en(de)coding #17

Merged
merged 8 commits into from
Jul 27, 2022
Merged

proxy: simplified packetIO and proxyv2 en(de)coding #17

merged 8 commits into from
Jul 27, 2022

Conversation

xhebox
Copy link
Collaborator

@xhebox xhebox commented Jul 26, 2022

What problem does this PR solve?

Issue Number: ref #14

Problem Summary: Simplifying the interface of PacketIO will enable us to remove redundant authenticator.go.

What is changed and how it works: Included in the commit message.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code

Notable changes

  • Has configuration change
  • Has HTTP API interfaces change (Don't forget to add the declarative for API)
  • Has weirctl change
  • Other user behavior changes

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

None

@xhebox xhebox requested a review from djshow832 July 26, 2022 08:47
@xhebox xhebox mentioned this pull request Jul 26, 2022
2 tasks
@xhebox xhebox changed the title [WIP] proxy: simplified packetIO and proxyv2 en(de)coding [WIP][DNM] proxy: simplified packetIO and proxyv2 en(de)coding Jul 26, 2022
1. add `WError` to to wrap one error with another error. Refer the
	 example for `errors.Wrap(..) error`.
2. add `errors.Collect(...) error` to wrap one error with multiple errors.
3. let all API return `error` directly instead of pointers of struct.
	 Also remove `err.WithStack()` to keep errors imutable. Mutable errors
	 may have race if they are initialized as global variables of general
	 usage.
1. delete `buffered_read_conn.go`, use bufioRW direct.ly
2. close connection.
3. add methods to fake `initialHandshake`, expect `SSLRequest`.
4. add methods to read/write mysql packet.
5. add methods for proxy protocol encoding/decoding

Signed-off-by: xhe <xw897002528@gmail.com>
@xhebox xhebox changed the title [WIP][DNM] proxy: simplified packetIO and proxyv2 en(de)coding proxy: simplified packetIO and proxyv2 en(de)coding Jul 26, 2022

// probe proxy V2
refill := false
if p.proxy == nil && bytes.Compare(header[:], proxyV2Magic[:4]) == 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

How can you guarantee that the combination of length+sequence doesn't just happen to match proxyV2Magic?

Copy link
Collaborator Author

@xhebox xhebox Jul 27, 2022

Choose a reason for hiding this comment

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

There is an extra check in parseProxyV2. proxyV2Magic has 12 bytes in total with a length 0xD0A0D and sequence 0xA. The only possible matches are OK response which are sent by server, or COM_SLEEP which is not long enough, and will failed to match on the second packet due to unknown command.

So yes, as long as the client behave correctly, there is no way. And if it does not, server will abort the connection eventually because of invalid proxy header or mysql packet.

I can make it safer: semantically speaking, this header is prepended at the beginning of handshake. So instead of p.proxy == nil, one-shot boolean will make it even more safer. And for server, we can just disable the probing.

}
return data, nil
return data, length == 0xffffff, nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the difference of judging length == 0xffffff and len(data) < mysql.MaxPayloadLen?

Copy link
Collaborator Author

@xhebox xhebox Jul 27, 2022

Choose a reason for hiding this comment

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

Not much. This change comes from my preference:

  1. It is more natural for me to move the juding of hasMoreData? into ReadOnePacket, if the packet does said truth about following packets. Then ReadPacket has no assumptions on whether there is and why there is consecutive packets.
  2. I personally prefer == over <.

pkg/proxy/net/packetio.go Outdated Show resolved Hide resolved
pkg/proxy/net/packetio.go Outdated Show resolved Hide resolved
pkg/proxy/net/packetio.go Outdated Show resolved Hide resolved
pkg/proxy/net/mysql.go Show resolved Hide resolved
pkg/proxy/net/packetio_test.go Show resolved Hide resolved
Signed-off-by: xhe <xw897002528@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
if write with a multiple `MaxPayload`, an extra zero-length packet is
needed to end the packet continuous hint.

Signed-off-by: xhe <xw897002528@gmail.com>
@xhebox xhebox requested a review from djshow832 July 27, 2022 07:00
Signed-off-by: xhe <xw897002528@gmail.com>
@@ -54,7 +54,7 @@ func (auth *Authenticator) handshakeFirstTime(clientIO, backendIO *pnet.PacketIO
// Read initial handshake packet from the backend.
serverPkt, serverCapability, err = auth.readInitialHandshake(backendIO)
if serverPkt != nil {
writeErr := clientIO.WritePacket(serverPkt)
writeErr := clientIO.WritePacket(serverPkt, false)
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can merge the write and following flush() together here. But it's OK, I can do it in the next PR.

@djshow832 djshow832 merged commit df86464 into pingcap:main Jul 27, 2022
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.

2 participants