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

fix handshake #52

Merged
merged 1 commit into from
Jun 21, 2017
Merged

fix handshake #52

merged 1 commit into from
Jun 21, 2017

Conversation

damoye
Copy link

@damoye damoye commented Jun 10, 2017

Use io.ReadAll to do SOCKS handshake.

@damoye damoye mentioned this pull request Jun 10, 2017
@damoye
Copy link
Author

damoye commented Jun 12, 2017

Is there any problem with this pull request?

@damoye
Copy link
Author

damoye commented Jun 14, 2017

I improved the code by reusing the ReadAddr function

@riobard
Copy link

riobard commented Jun 15, 2017

You should try to reduce memory allocation with make(). Just make a MaxReqLen buffer at the beginning and reuse it. Also, no need to call ReadAddr because it does another allocation.

@damoye
Copy link
Author

damoye commented Jun 16, 2017

It allocates only the needed memory. So actually in most cases It allocates less memory than MaxReqLen, but more frequently. So which one is more important? Less memory or less allocation frequency?

@riobard
Copy link

riobard commented Jun 16, 2017

Memory allocation is done in page size typically 4KB. Even if you allocate just 1 byte, you still waste 4KB.

@damoye
Copy link
Author

damoye commented Jun 16, 2017

OK. I get it! I will rewrite the code. Thanks for reminding me that.

@damoye
Copy link
Author

damoye commented Jun 16, 2017

Done! Please review the code again.

socks/socks.go Outdated

_, err = rw.Write([]byte{5, 0}) // SOCKS v5, no auth required
if err != nil {
if buf[0] != 5 { // VER: 5
Copy link

Choose a reason for hiding this comment

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

No need to be very strict about SOCKS version. SOCKS4 is about the same. In general the program should be less picky about its input.

socks/socks.go Outdated
}
}
if !noAuthExist {
return nil, fmt.Errorf("SOCKS no method noAuth: %v", buf)
Copy link

Choose a reason for hiding this comment

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

Again, no need to be strict if the auth method is not specified.

socks/socks.go Outdated
if buf[1] != CmdConnect {
return nil, ErrCommandNotSupported
}
buf = buf[3:]
var err error
switch buf[0] {
Copy link

Choose a reason for hiding this comment

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

On the second thought, you were right in the previous commit. It's actually better to call ReadAddr here instead of duplicating the same error-prone code path.

@damoye
Copy link
Author

damoye commented Jun 19, 2017

OK. Please review again.

Copy link

@riobard riobard left a comment

Choose a reason for hiding this comment

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

Some minor changes and we're good to go :)

socks/socks.go Outdated
@@ -162,30 +159,33 @@ func ParseAddr(s string) Addr {
}

// Handshake fast-tracks SOCKS initialization to get target address to connect.
// Read RFC 1928 for request and reply structure and sizes.
Copy link

Choose a reason for hiding this comment

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

This line of comment is implementation detail. It should NOT be at the function level because it'll be exposed by Godoc.

socks/socks.go Outdated

_, err := rw.Read(buf) // SOCKS version and auth methods
if err != nil {
buf := make([]byte, 0xff)
Copy link

@riobard riobard Jun 19, 2017

Choose a reason for hiding this comment

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

The magic number 0xff should be defined as a meaningful constant. Reuse MaxReqLen should not hurt (remember the min 4KB page size).

Copy link
Author

Choose a reason for hiding this comment

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

If I reuse the ReadAddr I will allocate memory twice. Once here for 255 which is the maximum
of byte, Once inside the ReadAddr function for MaxAddrLen. Is that OK?
Or I can pass the buffer into ReadAddr, which will change the ReadAddr function.

Copy link

Choose a reason for hiding this comment

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

Good point. I thought he double allocation a tradeoff in order to avoid code duplication. There's a way to avoid double allocation and code duplication though:

  1. Write a helper internal function e.g. readAddr that takes a buffer argument.
  2. Rewrite the exposed function ReadAddr to call readAddr with a new buffer.
  3. Call readAddr in Handshake with the existing buffer.

In general we do not change the signature of exposed functions in Go to be backward-compatible.

socks/socks.go Outdated

_, err = rw.Write([]byte{5, 0}) // SOCKS v5, no auth required
if err != nil {
len := buf[1]
Copy link

Choose a reason for hiding this comment

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

len is a builtin function. Use another name e.g. nmethod.

@damoye
Copy link
Author

damoye commented Jun 20, 2017

I use array instead of slice to control the buffer size and reduce memory allocation. Please review again.

@riobard
Copy link

riobard commented Jun 20, 2017

No need to use array. In fact it's pretty rare to use arrays in Go. A slice would be just fine. Also, please note there's a bug fix that just got merged which affects this code too.

@damoye
Copy link
Author

damoye commented Jun 21, 2017

OK. Please review again.

socks/socks.go Outdated
b := make([]byte, MaxAddrLen)
func readAddr(r io.Reader, b []byte) (Addr, error) {
if len(b) < MaxAddrLen {
return nil, fmt.Errorf("readAddr needs at least %d bytes of buffer", MaxAddrLen)
Copy link

Choose a reason for hiding this comment

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

Return io.ErrShortBuffer here instead of generating a custom error string.

@damoye
Copy link
Author

damoye commented Jun 21, 2017

OK. Please review again.

@riobard riobard merged commit 3334af5 into shadowsocks:master Jun 21, 2017
@riobard
Copy link

riobard commented Jun 21, 2017

Thanks a lot!

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