forked from shadowsocks/shadowsocks-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathudp.go
94 lines (74 loc) · 1.98 KB
/
udp.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
84
85
86
87
88
89
90
91
92
93
94
package shadowsocks
import (
"fmt"
"net"
"time"
)
const (
maxPacketSize = 4096 // increase it if error occurs
)
var (
errPacketTooSmall = fmt.Errorf("[udp]read error: cannot decrypt, received packet is smaller than ivLen")
errPacketTooLarge = fmt.Errorf("[udp]read error: received packet is latger than maxPacketSize(%d)", maxPacketSize)
errBufferTooSmall = fmt.Errorf("[udp]read error: given buffer is too small to hold data")
)
type SecurePacketConn struct {
net.PacketConn
*Cipher
}
func NewSecurePacketConn(c net.PacketConn, cipher *Cipher) *SecurePacketConn {
return &SecurePacketConn{
PacketConn: c,
Cipher: cipher,
}
}
func (c *SecurePacketConn) Close() error {
return c.PacketConn.Close()
}
func (c *SecurePacketConn) ReadFrom(b []byte) (n int, src net.Addr, err error) {
cipher := c.Copy()
buf := make([]byte, 4096)
n, src, err = c.PacketConn.ReadFrom(buf)
if err != nil {
return
}
if n < c.info.ivLen {
return 0, nil, errPacketTooSmall
}
if len(b) < n-c.info.ivLen {
err = errBufferTooSmall // just a warning
}
iv := make([]byte, c.info.ivLen)
copy(iv, buf[:c.info.ivLen])
if err = cipher.initDecrypt(iv); err != nil {
return
}
cipher.decrypt(b[0:], buf[c.info.ivLen:n])
n -= c.info.ivLen
return
}
func (c *SecurePacketConn) WriteTo(b []byte, dst net.Addr) (n int, err error) {
cipher := c.Copy()
iv, err := cipher.initEncrypt()
if err != nil {
return
}
packetLen := len(b) + len(iv)
cipherData := make([]byte, packetLen)
copy(cipherData, iv)
cipher.encrypt(cipherData[len(iv):], b)
n, err = c.PacketConn.WriteTo(cipherData, dst)
return
}
func (c *SecurePacketConn) LocalAddr() net.Addr {
return c.PacketConn.LocalAddr()
}
func (c *SecurePacketConn) SetDeadline(t time.Time) error {
return c.PacketConn.SetDeadline(t)
}
func (c *SecurePacketConn) SetReadDeadline(t time.Time) error {
return c.PacketConn.SetReadDeadline(t)
}
func (c *SecurePacketConn) SetWriteDeadline(t time.Time) error {
return c.PacketConn.SetWriteDeadline(t)
}