forked from shadowsocks/shadowsocks-go
/
dialer.go
83 lines (74 loc) · 2.29 KB
/
dialer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package shadowsocks
import (
"errors"
"fmt"
"net"
"strings"
"github.com/arthurkiller/shadowsocks-go/encrypt"
)
// Dialer provides client side connection support
// and also implements the Dialer interface described in golang.org/x/net/proxy
type Dialer struct {
cipher encrypt.Cipher
server string
timeout int
}
// NewDialer initializes a new Dialer
func NewDialer(server string, cipher encrypt.Cipher, timeout int) (dialer *Dialer, err error) {
// Currently shadowsocks-go supports UDP
// But you should not use Dialer to open an UDP connection
if cipher == nil {
return nil, ErrNilCipher
}
return &Dialer{
cipher: cipher,
server: server,
timeout: timeout,
}, nil
}
// Dial is intended for the Dialer interface described in golang.org/x/net/proxy
func (d *Dialer) Dial(network, addr string) (c net.Conn, err error) {
if strings.HasPrefix(network, "tcp") {
ra, err := rawAddr(addr)
if err != nil {
return nil, err
}
c, err = d.DialWithRawAddr(ra)
if err != nil {
return nil, err
}
return c, err
}
return nil, fmt.Errorf("unsupported connection type: %s", network)
}
// DialUDP is used to open an UDP connection on client side to and remote dst
func (d *Dialer) DialUDP(network, laddr, raddr string) (c net.PacketConn, err error) {
udpraddr, err := net.ResolveUDPAddr("udp", raddr)
return net.DialUDP("udp", nil, udpraddr)
}
// ListenPacket is used to open an UDP connection on client side
func (d *Dialer) ListenPacket(network, laddr string) (c net.PacketConn, err error) {
if strings.HasPrefix(network, "udp") {
return SecureListenPacket(network, laddr, d.cipher.Copy(), d.timeout)
}
return nil, fmt.Errorf("unsupported connection type: %s", network)
}
// DialWithRawAddr is intended for use by users implementing a local socks proxy.
// rawaddr shoud contain part of the data in socks request, starting from the
// ATYP field. (Refer to rfc1928 for more information.)
func (d *Dialer) DialWithRawAddr(rawaddr []byte) (conn net.Conn, err error) {
conn, err = net.Dial("tcp", d.server)
if err != nil {
return
}
tcpConn, ok := conn.(*net.TCPConn)
if !ok {
return nil, errors.New("error in convert into tcp connection")
}
c := NewSecureConn(tcpConn, d.cipher.Copy(), d.timeout)
if _, err = c.Write(rawaddr); err != nil {
c.Close()
return nil, err
}
return c, err
}