blob: c19a5c06353dc9f15f60eeda7622176a96536adc [file] [log] [blame]
Adam Langleyc9064102012-08-07 12:02:26 -04001// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package proxy
6
7import (
Mikio Haracd34c462013-01-29 03:24:44 +09008 "io"
Adam Langleyc9064102012-08-07 12:02:26 -04009 "net"
10 "net/url"
Mikio Haracd34c462013-01-29 03:24:44 +090011 "strconv"
12 "sync"
Adam Langleyc9064102012-08-07 12:02:26 -040013 "testing"
14)
15
Adam Langleyc9064102012-08-07 12:02:26 -040016func TestFromURL(t *testing.T) {
Mikio Hara5a456bd2013-02-10 10:45:18 +090017 endSystem, err := net.Listen("tcp", "127.0.0.1:0")
Adam Langleyc9064102012-08-07 12:02:26 -040018 if err != nil {
Mikio Hara5a456bd2013-02-10 10:45:18 +090019 t.Fatalf("net.Listen failed: %v", err)
Adam Langleyc9064102012-08-07 12:02:26 -040020 }
Mikio Hara5a456bd2013-02-10 10:45:18 +090021 defer endSystem.Close()
22 gateway, err := net.Listen("tcp", "127.0.0.1:0")
Adam Langleyc9064102012-08-07 12:02:26 -040023 if err != nil {
Mikio Hara5a456bd2013-02-10 10:45:18 +090024 t.Fatalf("net.Listen failed: %v", err)
Adam Langleyc9064102012-08-07 12:02:26 -040025 }
Mikio Hara5a456bd2013-02-10 10:45:18 +090026 defer gateway.Close()
Adam Langleyc9064102012-08-07 12:02:26 -040027
Mikio Hara5a456bd2013-02-10 10:45:18 +090028 var wg sync.WaitGroup
29 wg.Add(1)
30 go socks5Gateway(t, gateway, endSystem, socks5Domain, &wg)
31
32 url, err := url.Parse("socks5://user:password@" + gateway.Addr().String())
33 if err != nil {
34 t.Fatalf("url.Parse failed: %v", err)
Adam Langleyc9064102012-08-07 12:02:26 -040035 }
Mikio Hara5a456bd2013-02-10 10:45:18 +090036 proxy, err := FromURL(url, Direct)
37 if err != nil {
38 t.Fatalf("FromURL failed: %v", err)
39 }
40 _, port, err := net.SplitHostPort(endSystem.Addr().String())
41 if err != nil {
42 t.Fatalf("net.SplitHostPort failed: %v", err)
43 }
44 if c, err := proxy.Dial("tcp", "localhost:"+port); err != nil {
45 t.Fatalf("FromURL.Dial failed: %v", err)
Adam Langleyc9064102012-08-07 12:02:26 -040046 } else {
Mikio Hara5a456bd2013-02-10 10:45:18 +090047 c.Close()
Adam Langleyc9064102012-08-07 12:02:26 -040048 }
Mikio Hara5a456bd2013-02-10 10:45:18 +090049
50 wg.Wait()
Adam Langleyc9064102012-08-07 12:02:26 -040051}
Mikio Haracd34c462013-01-29 03:24:44 +090052
53func TestSOCKS5(t *testing.T) {
54 endSystem, err := net.Listen("tcp", "127.0.0.1:0")
55 if err != nil {
56 t.Fatalf("net.Listen failed: %v", err)
57 }
58 defer endSystem.Close()
59 gateway, err := net.Listen("tcp", "127.0.0.1:0")
60 if err != nil {
61 t.Fatalf("net.Listen failed: %v", err)
62 }
63 defer gateway.Close()
64
Mikio Hara5a456bd2013-02-10 10:45:18 +090065 var wg sync.WaitGroup
Mikio Haracd34c462013-01-29 03:24:44 +090066 wg.Add(1)
Mikio Hara5a456bd2013-02-10 10:45:18 +090067 go socks5Gateway(t, gateway, endSystem, socks5IP4, &wg)
Mikio Haracd34c462013-01-29 03:24:44 +090068
69 proxy, err := SOCKS5("tcp", gateway.Addr().String(), nil, Direct)
70 if err != nil {
71 t.Fatalf("SOCKS5 failed: %v", err)
72 }
73 if c, err := proxy.Dial("tcp", endSystem.Addr().String()); err != nil {
74 t.Fatalf("SOCKS5.Dial failed: %v", err)
75 } else {
76 c.Close()
77 }
78
79 wg.Wait()
80}
81
Mikio Hara5a456bd2013-02-10 10:45:18 +090082func socks5Gateway(t *testing.T, gateway, endSystem net.Listener, typ byte, wg *sync.WaitGroup) {
Mikio Haracd34c462013-01-29 03:24:44 +090083 defer wg.Done()
84
85 c, err := gateway.Accept()
86 if err != nil {
Mikio Hara5a456bd2013-02-10 10:45:18 +090087 t.Errorf("net.Listener.Accept failed: %v", err)
88 return
Mikio Haracd34c462013-01-29 03:24:44 +090089 }
90 defer c.Close()
91
92 b := make([]byte, 32)
Mikio Hara5a456bd2013-02-10 10:45:18 +090093 var n int
94 if typ == socks5Domain {
95 n = 4
96 } else {
97 n = 3
98 }
99 if _, err := io.ReadFull(c, b[:n]); err != nil {
100 t.Errorf("io.ReadFull failed: %v", err)
101 return
Mikio Haracd34c462013-01-29 03:24:44 +0900102 }
103 if _, err := c.Write([]byte{socks5Version, socks5AuthNone}); err != nil {
Mikio Hara5a456bd2013-02-10 10:45:18 +0900104 t.Errorf("net.Conn.Write failed: %v", err)
105 return
Mikio Haracd34c462013-01-29 03:24:44 +0900106 }
Mikio Hara5a456bd2013-02-10 10:45:18 +0900107 if typ == socks5Domain {
108 n = 16
109 } else {
110 n = 10
Mikio Haracd34c462013-01-29 03:24:44 +0900111 }
Mikio Hara5a456bd2013-02-10 10:45:18 +0900112 if _, err := io.ReadFull(c, b[:n]); err != nil {
113 t.Errorf("io.ReadFull failed: %v", err)
114 return
Mikio Haracd34c462013-01-29 03:24:44 +0900115 }
Mikio Hara5a456bd2013-02-10 10:45:18 +0900116 if b[0] != socks5Version || b[1] != socks5Connect || b[2] != 0x00 || b[3] != typ {
117 t.Errorf("got an unexpected packet: %#02x %#02x %#02x %#02x", b[0], b[1], b[2], b[3])
118 return
119 }
120 if typ == socks5Domain {
121 copy(b[:5], []byte{socks5Version, 0x00, 0x00, socks5Domain, 9})
122 b = append(b, []byte("localhost")...)
123 } else {
124 copy(b[:4], []byte{socks5Version, 0x00, 0x00, socks5IP4})
125 }
Mikio Haracd34c462013-01-29 03:24:44 +0900126 host, port, err := net.SplitHostPort(endSystem.Addr().String())
127 if err != nil {
Mikio Hara5a456bd2013-02-10 10:45:18 +0900128 t.Errorf("net.SplitHostPort failed: %v", err)
129 return
Mikio Haracd34c462013-01-29 03:24:44 +0900130 }
131 b = append(b, []byte(net.ParseIP(host).To4())...)
132 p, err := strconv.Atoi(port)
133 if err != nil {
Mikio Hara5a456bd2013-02-10 10:45:18 +0900134 t.Errorf("strconv.Atoi failed: %v", err)
135 return
Mikio Haracd34c462013-01-29 03:24:44 +0900136 }
137 b = append(b, []byte{byte(p >> 8), byte(p)}...)
138 if _, err := c.Write(b); err != nil {
Mikio Hara5a456bd2013-02-10 10:45:18 +0900139 t.Errorf("net.Conn.Write failed: %v", err)
140 return
Mikio Haracd34c462013-01-29 03:24:44 +0900141 }
142}