commit 15d8df1cd780ddb0bb1710b08a5546f2a8f027bf
Merge: f17a5f2 93bcaf4
Author: David Fifield <[email protected]>
Date:   Sun May 1 23:29:42 2016 -0700

    Merge remote-tracking branch 'yawning/bug12535_v2'

 pt.go         |   5 +-
 socks.go      | 386 +++++++++++++++++++++++++++++++++++++--------
 socks_test.go | 495 +++++++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 677 insertions(+), 209 deletions(-)

diff --cc pt.go
index 28e5bb7,45cf67f..82c42d5
--- a/pt.go
+++ b/pt.go
@@@ -125,13 -119,11 +125,14 @@@
  // Extended ORPort Authentication:
  // 
https://gitweb.torproject.org/torspec.git/tree/proposals/217-ext-orport-auth.txt.
  //
 +// Pluggable Transport through SOCKS proxy:
 +// 
https://gitweb.torproject.org/torspec.git/tree/proposals/232-pluggable-transports-through-proxy.txt
 +//
- // The package implements a SOCKS4a server sufficient for a Tor client 
transport
+ // The package implements a SOCKS5 server sufficient for a Tor client 
transport
  // plugin.
  //
- // http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol
+ // https://www.ietf.org/rfc/rfc1928.txt
+ // https://www.ietf.org/rfc/rfc1929.txt
  package pt
  
  import (
diff --cc socks.go
index 9a764b8,e4488e8..29827d9
--- a/socks.go
+++ b/socks.go
@@@ -137,13 -175,12 +176,13 @@@ retry
        conn.Conn = c
        err = conn.SetDeadline(time.Now().Add(socksRequestTimeout))
        if err != nil {
 -              return nil, err
 +              conn.Close()
 +              goto retry
        }
-       conn.Req, err = readSocks4aConnect(conn)
+       conn.Req, err = socks5Handshake(conn)
        if err != nil {
                conn.Close()
 -              return nil, err
 +              goto retry
        }
        err = conn.SetDeadline(time.Time{})
        if err != nil {
diff --cc socks_test.go
index 7fee46a,aa27d4c..d82e823
--- a/socks_test.go
+++ b/socks_test.go
@@@ -1,129 -1,78 +1,80 @@@
  package pt
  
  import (
+       "bufio"
        "bytes"
 +      "errors"
+       "encoding/hex"
        "io"
        "net"
        "testing"
 +      "time"
  )
  
- func TestReadSocks4aConnect(t *testing.T) {
-       badTests := [...][]byte{
-               []byte(""),
-               // missing userid
-               []byte("\x04\x01\x12\x34\x01\x02\x03\x04"),
-               // missing \x00 after userid
-               []byte("\x04\x01\x12\x34\x01\x02\x03\x04key=value"),
-               // missing hostname
-               []byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00"),
-               // missing \x00 after hostname
-               []byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00hostname"),
-               // bad name–value mapping
-               
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01userid\x00hostname\x00"),
-               // bad version number
-               []byte("\x03\x01\x12\x34\x01\x02\x03\x04\x00"),
-               // BIND request
-               []byte("\x04\x02\x12\x34\x01\x02\x03\x04\x00"),
-               // SOCKS5
-               []byte("\x05\x01\x00"),
-       }
-       ipTests := [...]struct {
-               input  []byte
-               addr   net.TCPAddr
-               userid string
-       }{
-               {
-                       []byte("\x04\x01\x12\x34\x01\x02\x03\x04key=value\x00"),
-                       net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 0x1234},
-                       "key=value",
-               },
-               {
-                       []byte("\x04\x01\x12\x34\x01\x02\x03\x04\x00"),
-                       net.TCPAddr{IP: net.ParseIP("1.2.3.4"), Port: 0x1234},
-                       "",
-               },
-       }
-       hostnameTests := [...]struct {
-               input  []byte
-               target string
-               userid string
-       }{
-               {
-                       
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00hostname\x00"),
-                       "hostname:4660",
-                       "key=value",
-               },
-               {
-                       
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01\x00hostname\x00"),
-                       "hostname:4660",
-                       "",
-               },
-               {
-                       
[]byte("\x04\x01\x12\x34\x00\x00\x00\x01key=value\x00\x00"),
-                       ":4660",
-                       "key=value",
-               },
-               {
-                       []byte("\x04\x01\x12\x34\x00\x00\x00\x01\x00\x00"),
-                       ":4660",
-                       "",
-               },
-       }
- 
-       for _, input := range badTests {
-               var buf bytes.Buffer
-               buf.Write(input)
-               _, err := readSocks4aConnect(&buf)
-               if err == nil {
-                       t.Errorf("%q unexpectedly succeeded", input)
-               }
+ // testReadWriter is a bytes.Buffer backed io.ReadWriter used for testing.  
The
+ // Read and Write routines are to be used by the component being tested.  Data
+ // can be written to and read back via the writeHex and readHex routines.
+ type testReadWriter struct {
+       readBuf  bytes.Buffer
+       writeBuf bytes.Buffer
+ }
+ 
+ func (c *testReadWriter) Read(buf []byte) (n int, err error) {
+       return c.readBuf.Read(buf)
+ }
+ 
+ func (c *testReadWriter) Write(buf []byte) (n int, err error) {
+       return c.writeBuf.Write(buf)
+ }
+ 
+ func (c *testReadWriter) writeHex(str string) (n int, err error) {
+       var buf []byte
+       if buf, err = hex.DecodeString(str); err != nil {
+               return
        }
+       return c.readBuf.Write(buf)
+ }
  
-       for _, test := range ipTests {
-               var buf bytes.Buffer
-               buf.Write(test.input)
-               req, err := readSocks4aConnect(&buf)
-               if err != nil {
-                       t.Errorf("%q unexpectedly returned an error: %s", 
test.input, err)
-               }
-               addr, err := net.ResolveTCPAddr("tcp", req.Target)
-               if err != nil {
-                       t.Errorf("%q → target %q: cannot resolve: %s", 
test.input,
-                               req.Target, err)
-               }
-               if !tcpAddrsEqual(addr, &test.addr) {
-                       t.Errorf("%q → address %s (expected %s)", test.input,
-                               req.Target, test.addr.String())
-               }
-               if req.Username != test.userid {
-                       t.Errorf("%q → username %q (expected %q)", test.input,
-                               req.Username, test.userid)
-               }
-               if req.Args == nil {
-                       t.Errorf("%q → unexpected nil Args from username %q", 
test.input, req.Username)
-               }
+ func (c *testReadWriter) readHex() string {
+       return hex.EncodeToString(c.writeBuf.Bytes())
+ }
+ 
+ func (c *testReadWriter) toBufio() *bufio.ReadWriter {
+       return bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c))
+ }
+ 
+ func (c *testReadWriter) reset() {
+       c.readBuf.Reset()
+       c.writeBuf.Reset()
+ }
+ 
+ // TestAuthInvalidVersion tests auth negotiation with an invalid version.
+ func TestAuthInvalidVersion(t *testing.T) {
+       c := new(testReadWriter)
+ 
+       // VER = 03, NMETHODS = 01, METHODS = [00]
+       c.writeHex("030100")
+       if _, err := socksNegotiateAuth(c.toBufio()); err == nil {
+               t.Error("socksNegotiateAuth(InvalidVersion) succeded")
        }
+ }
  
-       for _, test := range hostnameTests {
-               var buf bytes.Buffer
-               buf.Write(test.input)
-               req, err := readSocks4aConnect(&buf)
-               if err != nil {
-                       t.Errorf("%q unexpectedly returned an error: %s", 
test.input, err)
-               }
-               if req.Target != test.target {
-                       t.Errorf("%q → target %q (expected %q)", test.input,
-                               req.Target, test.target)
-               }
-               if req.Username != test.userid {
-                       t.Errorf("%q → username %q (expected %q)", test.input,
-                               req.Username, test.userid)
-               }
-               if req.Args == nil {
-                       t.Errorf("%q → unexpected nil Args from username %q", 
test.input, req.Username)
-               }
+ // TestAuthInvalidNMethods tests auth negotiaton with no methods.
+ func TestAuthInvalidNMethods(t *testing.T) {
+       c := new(testReadWriter)
+       var err error
+       var method byte
+ 
+       // VER = 05, NMETHODS = 00
+       c.writeHex("0500")
+       if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
+               t.Error("socksNegotiateAuth(No Methods) failed:", err)
+       }
+       if method != socksAuthNoAcceptableMethods {
+               t.Error("socksNegotiateAuth(No Methods) picked unexpected 
method:", method)
+       }
+       if msg := c.readHex(); msg != "05ff" {
+               t.Error("socksNegotiateAuth(No Methods) invalid response:", msg)
        }
  }
  
@@@ -164,106 -114,255 +116,359 @@@ func TestAuthUsernamePassword(t *testin
        }
  }
  
 +var fakeListenerDistinguishedError = errors.New("distinguished error")
 +
 +// fakeListener is a fake dummy net.Listener that returns the given net.Conn 
and
 +// error the first time Accept is called. After the first call, it returns
 +// (nil, fakeListenerDistinguishedError).
 +type fakeListener struct {
 +      c   net.Conn
 +      err error
 +}
 +
 +func (ln *fakeListener) Accept() (net.Conn, error) {
 +      c := ln.c
 +      err := ln.err
 +      ln.c = nil
 +      ln.err = fakeListenerDistinguishedError
 +      return c, err
 +}
 +
 +func (ln *fakeListener) Close() error {
 +      return nil
 +}
 +
 +func (ln *fakeListener) Addr() net.Addr {
 +      return &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0, Zone: ""}
 +}
 +
 +// A trivial net.Error that lets you control whether it is considered 
Temporary.
 +type netError struct {
 +      errString string
 +      temporary bool
 +}
 +
 +func (e *netError) Error() string {
 +      return e.errString
 +}
 +
 +func (e *netError) Temporary() bool {
 +      return e.temporary
 +}
 +
 +func (e *netError) Timeout() bool {
 +      return false
 +}
 +
 +// The purpose of ignoreDeadlineConn is to wrap net.Pipe so that the deadline
 +// functions don't return an error ("net.Pipe does not support deadlines").
 +type ignoreDeadlineConn struct {
 +      net.Conn
 +}
 +
 +func (c *ignoreDeadlineConn) SetDeadline(t time.Time) error {
 +      return nil
 +}
 +
 +func (c *ignoreDeadlineConn) SetReadDeadline(t time.Time) error {
 +      return nil
 +}
 +
 +func (c *ignoreDeadlineConn) SetWriteDeadline(t time.Time) error {
 +      return nil
 +}
 +
 +func TestAcceptErrors(t *testing.T) {
 +      // Check that AcceptSocks accurately reflects net.Errors returned by the
 +      // underlying call to Accept. This is important for the handling of
 +      // Temporary and non-Temporary errors. The loop iterates over
 +      // non-net.Error, non-Temporary net.Error, and Temporary net.Error.
 +      for _, expectedErr := range []error{io.EOF, &netError{"non-temp", 
false}, &netError{"temp", true}} {
 +              ln := NewSocksListener(&fakeListener{nil, expectedErr})
 +              _, err := ln.AcceptSocks()
 +              if expectedNerr, ok := expectedErr.(net.Error); ok {
 +                      nerr, ok := err.(net.Error)
 +                      if !ok {
 +                              t.Errorf("AcceptSocks returned non-net.Error 
%v", nerr)
 +                      } else {
 +                              if expectedNerr.Temporary() != 
expectedNerr.Temporary() {
 +                                      t.Errorf("AcceptSocks did not keep 
Temporary status of net.Error: %v", nerr)
 +                              }
 +                      }
 +              }
 +      }
 +
 +      c1, c2 := net.Pipe()
 +      go func() {
 +              // Bogus request: SOCKS 5 then EOF.
 +              c2.Write([]byte("\x05\x01\x00"))
 +              c2.Close()
 +      }()
 +      ln := NewSocksListener(&fakeListener{c: &ignoreDeadlineConn{c1}, err: 
nil})
 +      _, err := ln.AcceptSocks()
 +      // The error in parsing the SOCKS request must be either silently
 +      // ignored, or else must be a Temporary net.Error. I.e., it must not be
 +      // the io.ErrUnexpectedEOF caused by the short request.
 +      if err == fakeListenerDistinguishedError {
 +              // Was silently ignored.
 +      } else if nerr, ok := err.(net.Error); ok {
 +              if !nerr.Temporary() {
 +                      t.Errorf("AcceptSocks returned non-Temporary net.Error: 
%v", nerr)
 +              }
 +      } else {
 +              t.Errorf("AcceptSocks returned non-net.Error: %v", err)
 +      }
 +}
++
+ // TestAuthBoth tests auth negotiation containing both NO AUTHENTICATION
+ // REQUIRED and USERNAME/PASSWORD.
+ func TestAuthBoth(t *testing.T) {
+       c := new(testReadWriter)
+       var err error
+       var method byte
+ 
+       // VER = 05, NMETHODS = 02, METHODS = [00, 02]
+       c.writeHex("05020002")
+       if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
+               t.Error("socksNegotiateAuth(Both) failed:", err)
+       }
+       if method != socksAuthUsernamePassword {
+               t.Error("socksNegotiateAuth(Both) unexpected method:", method)
+       }
+       if msg := c.readHex(); msg != "0502" {
+               t.Error("socksNegotiateAuth(Both) invalid response:", msg)
+       }
+ }
+ 
+ // TestAuthUnsupported tests auth negotiation with a unsupported method.
+ func TestAuthUnsupported(t *testing.T) {
+       c := new(testReadWriter)
+       var err error
+       var method byte
+ 
+       // VER = 05, NMETHODS = 01, METHODS = [01] (GSSAPI)
+       c.writeHex("050101")
+       if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
+               t.Error("socksNegotiateAuth(Unknown) failed:", err)
+       }
+       if method != socksAuthNoAcceptableMethods {
+               t.Error("socksNegotiateAuth(Unknown) picked unexpected 
method:", method)
+       }
+       if msg := c.readHex(); msg != "05ff" {
+               t.Error("socksNegotiateAuth(Unknown) invalid response:", msg)
+       }
+ }
+ 
+ // TestAuthUnsupported2 tests auth negotiation with supported and unsupported
+ // methods.
+ func TestAuthUnsupported2(t *testing.T) {
+       c := new(testReadWriter)
+       var err error
+       var method byte
+ 
+       // VER = 05, NMETHODS = 03, METHODS = [00,01,02]
+       c.writeHex("0503000102")
+       if method, err = socksNegotiateAuth(c.toBufio()); err != nil {
+               t.Error("socksNegotiateAuth(Unknown2) failed:", err)
+       }
+       if method != socksAuthUsernamePassword {
+               t.Error("socksNegotiateAuth(Unknown2) picked unexpected 
method:", method)
+       }
+       if msg := c.readHex(); msg != "0502" {
+               t.Error("socksNegotiateAuth(Unknown2) invalid response:", msg)
+       }
+ }
+ 
+ // TestRFC1929InvalidVersion tests RFC1929 auth with an invalid version.
+ func TestRFC1929InvalidVersion(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 03, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
+       c.writeHex("03054142434445056162636465")
+       if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
+               t.Error("socksAuthenticate(InvalidVersion) succeded")
+       }
+       if msg := c.readHex(); msg != "0101" {
+               t.Error("socksAuthenticate(InvalidVersion) invalid response:", 
msg)
+       }
+ }
+ 
+ // TestRFC1929InvalidUlen tests RFC1929 auth with an invalid ULEN.
+ func TestRFC1929InvalidUlen(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 01, ULEN = 0, UNAME = "", PLEN = 5, PASSWD = "abcde"
+       c.writeHex("0100056162636465")
+       if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
+               t.Error("socksAuthenticate(InvalidUlen) succeded")
+       }
+       if msg := c.readHex(); msg != "0101" {
+               t.Error("socksAuthenticate(InvalidUlen) invalid response:", msg)
+       }
+ }
+ 
+ // TestRFC1929InvalidPlen tests RFC1929 auth with an invalid PLEN.
+ func TestRFC1929InvalidPlen(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 0, PASSWD = ""
+       c.writeHex("0105414243444500")
+       if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
+               t.Error("socksAuthenticate(InvalidPlen) succeded")
+       }
+       if msg := c.readHex(); msg != "0101" {
+               t.Error("socksAuthenticate(InvalidPlen) invalid response:", msg)
+       }
+ }
+ 
+ // TestRFC1929InvalidArgs tests RFC1929 auth with invalid pt args.
+ func TestRFC1929InvalidPTArgs(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
+       c.writeHex("01054142434445056162636465")
+       if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err == nil {
+               t.Error("socksAuthenticate(InvalidArgs) succeded")
+       }
+       if msg := c.readHex(); msg != "0101" {
+               t.Error("socksAuthenticate(InvalidArgs) invalid response:", msg)
+       }
+ }
+ 
+ // TestRFC1929Success tests RFC1929 auth with valid pt args.
+ func TestRFC1929Success(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 01, ULEN = 9, UNAME = "key=value", PLEN = 1, PASSWD = "\0"
+       c.writeHex("01096b65793d76616c75650100")
+       if err := socksAuthenticate(c.toBufio(), socksAuthUsernamePassword, 
&req); err != nil {
+               t.Error("socksAuthenticate(Success) failed:", err)
+       }
+       if msg := c.readHex(); msg != "0100" {
+               t.Error("socksAuthenticate(Success) invalid response:", msg)
+       }
+       v, ok := req.Args.Get("key")
+       if v != "value" || !ok {
+               t.Error("RFC1929 k,v parse failure:", v)
+       }
+ }
+ 
+ // TestRequestInvalidHdr tests SOCKS5 requests with invalid VER/CMD/RSV/ATYPE
+ func TestRequestInvalidHdr(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 03, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
+       c.writeHex("030100017f000001235a")
+       if err := socksReadCommand(c.toBufio(), &req); err == nil {
+               t.Error("socksReadCommand(InvalidVer) succeded")
+       }
+       if msg := c.readHex(); msg != "05010001000000000000" {
+               t.Error("socksReadCommand(InvalidVer) invalid response:", msg)
+       }
+       c.reset()
+ 
+       // VER = 05, CMD = 05, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
+       c.writeHex("050500017f000001235a")
+       if err := socksReadCommand(c.toBufio(), &req); err == nil {
+               t.Error("socksReadCommand(InvalidCmd) succeded")
+       }
+       if msg := c.readHex(); msg != "05070001000000000000" {
+               t.Error("socksReadCommand(InvalidCmd) invalid response:", msg)
+       }
+       c.reset()
+ 
+       // VER = 05, CMD = 01, RSV = 30, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
+       c.writeHex("050130017f000001235a")
+       if err := socksReadCommand(c.toBufio(), &req); err == nil {
+               t.Error("socksReadCommand(InvalidRsv) succeded")
+       }
+       if msg := c.readHex(); msg != "05010001000000000000" {
+               t.Error("socksReadCommand(InvalidRsv) invalid response:", msg)
+       }
+       c.reset()
+ 
+       // VER = 05, CMD = 01, RSV = 01, ATYPE = 05, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
+       c.writeHex("050100057f000001235a")
+       if err := socksReadCommand(c.toBufio(), &req); err == nil {
+               t.Error("socksReadCommand(InvalidAtype) succeded")
+       }
+       if msg := c.readHex(); msg != "05080001000000000000" {
+               t.Error("socksAuthenticate(InvalidAtype) invalid response:", 
msg)
+       }
+       c.reset()
+ }
+ 
+ // TestRequestIPv4 tests IPv4 SOCKS5 requests.
+ func TestRequestIPv4(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 05, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, 
DST.PORT = 9050
+       c.writeHex("050100017f000001235a")
+       if err := socksReadCommand(c.toBufio(), &req); err != nil {
+               t.Error("socksReadCommand(IPv4) failed:", err)
+       }
+       addr, err := net.ResolveTCPAddr("tcp", req.Target)
+       if err != nil {
+               t.Error("net.ResolveTCPAddr failed:", err)
+       }
+       if !tcpAddrsEqual(addr, &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), 
Port: 9050}) {
+               t.Error("Unexpected target:", addr)
+       }
+ }
+ 
+ // TestRequestIPv6 tests IPv4 SOCKS5 requests.
+ func TestRequestIPv6(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = 
0102:0304:0506:0708:090a:0b0c:0d0e:0f10, DST.PORT = 9050
+       c.writeHex("050100040102030405060708090a0b0c0d0e0f10235a")
+       if err := socksReadCommand(c.toBufio(), &req); err != nil {
+               t.Error("socksReadCommand(IPv6) failed:", err)
+       }
+       addr, err := net.ResolveTCPAddr("tcp", req.Target)
+       if err != nil {
+               t.Error("net.ResolveTCPAddr failed:", err)
+       }
+       if !tcpAddrsEqual(addr, &net.TCPAddr{IP: 
net.ParseIP("0102:0304:0506:0708:090a:0b0c:0d0e:0f10"), Port: 9050}) {
+               t.Error("Unexpected target:", addr)
+       }
+ }
+ 
+ // TestRequestFQDN tests FQDN (DOMAINNAME) SOCKS5 requests.
+ func TestRequestFQDN(t *testing.T) {
+       c := new(testReadWriter)
+       var req SocksRequest
+ 
+       // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = example.com, 
DST.PORT = 9050
+       c.writeHex("050100030b6578616d706c652e636f6d235a")
+       if err := socksReadCommand(c.toBufio(), &req); err != nil {
+               t.Error("socksReadCommand(FQDN) failed:", err)
+       }
+       if req.Target != "example.com:9050" {
+               t.Error("Unexpected target:", req.Target)
+       }
+ }
+ 
+ // TestResponseNil tests nil address SOCKS5 responses.
+ func TestResponseNil(t *testing.T) {
+       c := new(testReadWriter)
+ 
+       b := c.toBufio()
+       if err := sendSocks5ResponseGranted(b); err != nil {
+               t.Error("sendSocks5ResponseGranted() failed:", err)
+       }
+       b.Flush()
+       if msg := c.readHex(); msg != "05000001000000000000" {
+               t.Error("sendSocks5ResponseGranted(nil) invalid response:", msg)
+       }
+ }
+ 
+ var _ io.ReadWriter = (*testReadWriter)(nil)

_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to