Просмотр исходного кода

Add pool support everywhere

tags/v1.0.4^2
9seconds 6 лет назад
Родитель
Сommit
837d96dc43

+ 6
- 1
faketls/client_protocol.go Просмотреть файл

63
 		return fmt.Errorf("cannot read initial record: %w", err)
63
 		return fmt.Errorf("cannot read initial record: %w", err)
64
 	}
64
 	}
65
 
65
 
66
-	clientHello, err := tlstypes.ParseClientHello(helloRecord.Data.Bytes())
66
+	buf := acquireBytesBuffer()
67
+	defer releaseBytesBuffer(buf)
68
+
69
+	helloRecord.Data.WriteBytes(buf)
70
+
71
+	clientHello, err := tlstypes.ParseClientHello(buf.Bytes())
67
 	if err != nil {
72
 	if err != nil {
68
 		return fmt.Errorf("cannot parse client hello: %w", err)
73
 		return fmt.Errorf("cannot parse client hello: %w", err)
69
 	}
74
 	}

+ 11
- 8
faketls/cloak.go Просмотреть файл

28
 
28
 
29
 	wg.Add(2)
29
 	wg.Add(2)
30
 
30
 
31
-	go func() {
32
-		defer wg.Done()
33
-		io.Copy(one, another) // nolint: errcheck
34
-	}()
31
+	go cloakPipe(one, another, wg)
35
 
32
 
36
-	go func() {
37
-		defer wg.Done()
38
-		io.Copy(another, one) // nolint: errcheck
39
-	}()
33
+	go cloakPipe(another, one, wg)
40
 
34
 
41
 	go func() {
35
 	go func() {
42
 		wg.Wait()
36
 		wg.Wait()
69
 
63
 
70
 	<-ctx.Done()
64
 	<-ctx.Done()
71
 }
65
 }
66
+
67
+func cloakPipe(one io.Writer, another io.Reader, wg *sync.WaitGroup) {
68
+	defer wg.Done()
69
+
70
+	buf := acquireCloakBuffer()
71
+	defer releaseCloakBuffer(buf)
72
+
73
+	io.CopyBuffer(one, another, *buf) // nolint: errcheck
74
+}

+ 38
- 0
faketls/pools.go Просмотреть файл

1
+package faketls
2
+
3
+import (
4
+	"bytes"
5
+	"sync"
6
+)
7
+
8
+const cloakBufferSize = 1024
9
+
10
+var (
11
+	poolBytesBuffer = sync.Pool{
12
+		New: func() interface{} {
13
+			return &bytes.Buffer{}
14
+		},
15
+	}
16
+	poolCloakBuffer = sync.Pool{
17
+		New: func() interface{} {
18
+			rv := make([]byte, cloakBufferSize)
19
+			return &rv
20
+		},
21
+	}
22
+)
23
+
24
+func acquireBytesBuffer() *bytes.Buffer {
25
+	return poolBytesBuffer.Get().(*bytes.Buffer)
26
+}
27
+
28
+func acquireCloakBuffer() *[]byte {
29
+	return poolCloakBuffer.Get().(*[]byte)
30
+}
31
+
32
+func releaseBytesBuffer(buf *bytes.Buffer) {
33
+	poolBytesBuffer.Put(buf)
34
+}
35
+
36
+func releaseCloakBuffer(buf *[]byte) {
37
+	poolCloakBuffer.Put(buf)
38
+}

+ 1
- 1
tlstypes/client_hello.go Просмотреть файл

25
 	}
25
 	}
26
 
26
 
27
 	mac := hmac.New(sha256.New, config.C.Secret)
27
 	mac := hmac.New(sha256.New, config.C.Secret)
28
-	mac.Write(rec.Bytes()) // nolint: errcheck
28
+	rec.WriteBytes(mac)
29
 	computedDigest := mac.Sum(nil)
29
 	computedDigest := mac.Sum(nil)
30
 
30
 
31
 	for i := range computedDigest {
31
 	for i := range computedDigest {

+ 10
- 3
tlstypes/consts.go Просмотреть файл

1
 package tlstypes
1
 package tlstypes
2
 
2
 
3
+import "io"
4
+
3
 type RecordType uint8
5
 type RecordType uint8
4
 
6
 
5
 const (
7
 const (
69
 )
71
 )
70
 
72
 
71
 type Byter interface {
73
 type Byter interface {
72
-	Bytes() []byte
74
+	WriteBytes(io.Writer)
75
+	Len() int
73
 }
76
 }
74
 
77
 
75
 type RawBytes []byte
78
 type RawBytes []byte
76
 
79
 
77
-func (r RawBytes) Bytes() []byte {
78
-	return []byte(r)
80
+func (r RawBytes) WriteBytes(writer io.Writer) {
81
+	writer.Write(r) // nolint: errcheck
82
+}
83
+
84
+func (r RawBytes) Len() int {
85
+	return len(r)
79
 }
86
 }

+ 16
- 9
tlstypes/handshake.go Просмотреть файл

1
 package tlstypes
1
 package tlstypes
2
 
2
 
3
 import (
3
 import (
4
-	"bytes"
4
+	"io"
5
 
5
 
6
 	"github.com/9seconds/mtg/utils"
6
 	"github.com/9seconds/mtg/utils"
7
 )
7
 )
14
 	Tail      Byter
14
 	Tail      Byter
15
 }
15
 }
16
 
16
 
17
-func (h *Handshake) Bytes() []byte {
18
-	buf := bytes.Buffer{}
19
-	packetBuf := bytes.Buffer{}
17
+func (h *Handshake) WriteBytes(writer io.Writer) {
18
+	packetBuf := acquireBytesBuffer()
19
+	defer releaseBytesBuffer(packetBuf)
20
 
20
 
21
-	buf.WriteByte(byte(h.Type))
21
+	writer.Write([]byte{byte(h.Type)}) // nolint: errcheck
22
 
22
 
23
 	packetBuf.Write(h.Version.Bytes())
23
 	packetBuf.Write(h.Version.Bytes())
24
 	packetBuf.Write(h.Random[:])
24
 	packetBuf.Write(h.Random[:])
25
 	packetBuf.WriteByte(byte(len(h.SessionID)))
25
 	packetBuf.WriteByte(byte(len(h.SessionID)))
26
 	packetBuf.Write(h.SessionID)
26
 	packetBuf.Write(h.SessionID)
27
-	packetBuf.Write(h.Tail.Bytes())
27
+	h.Tail.WriteBytes(packetBuf)
28
 
28
 
29
 	sizeUint24 := utils.ToUint24(uint32(packetBuf.Len()))
29
 	sizeUint24 := utils.ToUint24(uint32(packetBuf.Len()))
30
 	sizeUint24Bytes := sizeUint24[:]
30
 	sizeUint24Bytes := sizeUint24[:]
31
 	sizeUint24Bytes[0], sizeUint24Bytes[2] = sizeUint24Bytes[2], sizeUint24Bytes[0]
31
 	sizeUint24Bytes[0], sizeUint24Bytes[2] = sizeUint24Bytes[2], sizeUint24Bytes[0]
32
 
32
 
33
-	buf.Write(sizeUint24Bytes)
34
-	packetBuf.WriteTo(&buf) // nolint: errcheck
33
+	writer.Write(sizeUint24Bytes) // nolint: errcheck
34
+	packetBuf.WriteTo(writer)     // nolint: errcheck
35
+}
36
+
37
+func (h *Handshake) Len() int {
38
+	buf := acquireBytesBuffer()
39
+	defer releaseBytesBuffer(buf)
40
+
41
+	h.WriteBytes(buf)
35
 
42
 
36
-	return buf.Bytes()
43
+	return buf.Len()
37
 }
44
 }

+ 23
- 0
tlstypes/pools.go Просмотреть файл

1
+package tlstypes
2
+
3
+import (
4
+	"bytes"
5
+	"sync"
6
+)
7
+
8
+var (
9
+	poolBytesBuffer = sync.Pool{
10
+		New: func() interface{} {
11
+			return &bytes.Buffer{}
12
+		},
13
+	}
14
+)
15
+
16
+func acquireBytesBuffer() *bytes.Buffer {
17
+	return poolBytesBuffer.Get().(*bytes.Buffer)
18
+}
19
+
20
+func releaseBytesBuffer(buf *bytes.Buffer) {
21
+	buf.Reset()
22
+	poolBytesBuffer.Put(buf)
23
+}

+ 8
- 9
tlstypes/record.go Просмотреть файл

15
 	Data    Byter
15
 	Data    Byter
16
 }
16
 }
17
 
17
 
18
-func (r Record) Bytes() []byte {
19
-	buf := bytes.Buffer{}
20
-	data := r.Data.Bytes()
21
-
22
-	buf.WriteByte(byte(r.Type))
23
-	buf.Write(r.Version.Bytes())
24
-	binary.Write(&buf, binary.BigEndian, uint16(len(data))) // nolint: errcheck
25
-	buf.Write(data)
18
+func (r Record) WriteBytes(writer io.Writer) {
19
+	writer.Write([]byte{byte(r.Type)})                           // nolint: errcheck
20
+	writer.Write(r.Version.Bytes())                              // nolint: errcheck
21
+	binary.Write(writer, binary.BigEndian, uint16(r.Data.Len())) // nolint: errcheck
22
+	r.Data.WriteBytes(writer)
23
+}
26
 
24
 
27
-	return buf.Bytes()
25
+func (r Record) Len() int {
26
+	return 1 + 2 + 2 + r.Data.Len()
28
 }
27
 }
29
 
28
 
30
 func ReadRecord(reader io.Reader) (Record, error) {
29
 func ReadRecord(reader io.Reader) (Record, error) {

+ 6
- 3
tlstypes/server_hello.go Просмотреть файл

20
 }
20
 }
21
 
21
 
22
 func (s ServerHello) WelcomePacket() []byte {
22
 func (s ServerHello) WelcomePacket() []byte {
23
+	buf := &bytes.Buffer{}
24
+
23
 	s.Random = [32]byte{}
25
 	s.Random = [32]byte{}
24
 	rec := Record{
26
 	rec := Record{
25
 		Type:    RecordTypeHandshake,
27
 		Type:    RecordTypeHandshake,
26
 		Version: Version12,
28
 		Version: Version12,
27
 		Data:    &s,
29
 		Data:    &s,
28
 	}
30
 	}
29
-	buf := bytes.NewBuffer(rec.Bytes())
31
+	rec.WriteBytes(buf)
30
 
32
 
31
 	recChangeCipher := Record{
33
 	recChangeCipher := Record{
32
 		Type:    RecordTypeChangeCipherSpec,
34
 		Type:    RecordTypeChangeCipherSpec,
33
 		Version: Version12,
35
 		Version: Version12,
34
 		Data:    RawBytes([]byte{0x01}),
36
 		Data:    RawBytes([]byte{0x01}),
35
 	}
37
 	}
36
-	buf.Write(recChangeCipher.Bytes())
38
+	recChangeCipher.WriteBytes(buf)
37
 
39
 
38
 	hostCert := make([]byte, 1024+mrand.Intn(3092))
40
 	hostCert := make([]byte, 1024+mrand.Intn(3092))
39
 	rand.Read(hostCert) // nolint: errcheck
41
 	rand.Read(hostCert) // nolint: errcheck
43
 		Version: Version12,
45
 		Version: Version12,
44
 		Data:    RawBytes(hostCert),
46
 		Data:    RawBytes(hostCert),
45
 	}
47
 	}
46
-	buf.Write(recData.Bytes())
48
+	recData.WriteBytes(buf)
49
+
47
 	packet := buf.Bytes()
50
 	packet := buf.Bytes()
48
 
51
 
49
 	mac := hmac.New(sha256.New, config.C.Secret)
52
 	mac := hmac.New(sha256.New, config.C.Secret)

+ 13
- 3
wrappers/stream/faketls.go Просмотреть файл

1
 package stream
1
 package stream
2
 
2
 
3
 import (
3
 import (
4
+	"bytes"
4
 	"errors"
5
 	"errors"
5
 	"fmt"
6
 	"fmt"
6
 	"net"
7
 	"net"
39
 func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) {
40
 func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) {
40
 	sum := 0
41
 	sum := 0
41
 
42
 
43
+	buf := acquireBytesBuffer()
44
+	defer releaseBytesBuffer(buf)
45
+
42
 	for _, v := range tlstypes.MakeRecords(p) {
46
 	for _, v := range tlstypes.MakeRecords(p) {
43
-		_, err := writeFunc(v.Bytes())
47
+		buf.Reset()
48
+		v.WriteBytes(buf)
49
+
50
+		_, err := writeFunc(buf.Bytes())
44
 		if err != nil {
51
 		if err != nil {
45
 			return sum, err
52
 			return sum, err
46
 		}
53
 		}
47
 
54
 
48
-		sum += len(v.Data.Bytes())
55
+		sum += v.Data.Len()
49
 	}
56
 	}
50
 
57
 
51
 	return sum, nil
58
 	return sum, nil
86
 			switch rec.Type {
93
 			switch rec.Type {
87
 			case tlstypes.RecordTypeChangeCipherSpec:
94
 			case tlstypes.RecordTypeChangeCipherSpec:
88
 			case tlstypes.RecordTypeApplicationData:
95
 			case tlstypes.RecordTypeApplicationData:
89
-				return rec.Data.Bytes(), nil
96
+				buf := &bytes.Buffer{}
97
+				rec.Data.WriteBytes(buf)
98
+
99
+				return buf.Bytes(), nil
90
 			default:
100
 			default:
91
 				return nil, fmt.Errorf("unsupported record type %v", rec.Type)
101
 				return nil, fmt.Errorf("unsupported record type %v", rec.Type)
92
 			}
102
 			}

+ 3
- 2
wrappers/stream/mtproto_cipher.go Просмотреть файл

1
 package stream
1
 package stream
2
 
2
 
3
 import (
3
 import (
4
-	"bytes"
5
 	"crypto/aes"
4
 	"crypto/aes"
6
 	"crypto/cipher"
5
 	"crypto/cipher"
7
 	"crypto/md5"  // nolint: gosec
6
 	"crypto/md5"  // nolint: gosec
54
 	resp *rpc.NonceResponse,
53
 	resp *rpc.NonceResponse,
55
 	client, remote *net.TCPAddr,
54
 	client, remote *net.TCPAddr,
56
 	secret []byte) ([]byte, []byte) {
55
 	secret []byte) ([]byte, []byte) {
57
-	message := bytes.Buffer{}
56
+	message := acquireBytesBuffer()
57
+	defer releaseBytesBuffer(message)
58
+
58
 	message.Write(resp.Nonce)   // nolint: gosec
59
 	message.Write(resp.Nonce)   // nolint: gosec
59
 	message.Write(req.Nonce)    // nolint: gosec
60
 	message.Write(req.Nonce)    // nolint: gosec
60
 	message.Write(req.CryptoTS) // nolint: gosec
61
 	message.Write(req.CryptoTS) // nolint: gosec

+ 4
- 23
wrappers/stream/obfuscated2.go Просмотреть файл

1
 package stream
1
 package stream
2
 
2
 
3
 import (
3
 import (
4
-	"bytes"
5
 	"crypto/cipher"
4
 	"crypto/cipher"
6
 	"fmt"
5
 	"fmt"
7
 	"net"
6
 	"net"
8
-	"sync"
9
 	"time"
7
 	"time"
10
 
8
 
11
 	"go.uber.org/zap"
9
 	"go.uber.org/zap"
13
 	"github.com/9seconds/mtg/conntypes"
11
 	"github.com/9seconds/mtg/conntypes"
14
 )
12
 )
15
 
13
 
16
-var (
17
-	poolWrapperObfuscated2WritePool = sync.Pool{
18
-		New: func() interface{} {
19
-			return &bytes.Buffer{}
20
-		},
21
-	}
22
-)
23
-
24
-func poolWrapperObfuscated2WritePoolAcquire() *bytes.Buffer {
25
-	return poolWrapperObfuscated2WritePool.Get().(*bytes.Buffer)
26
-}
27
-
28
-func poolWrapperObfuscated2WritePoolRelease(buf *bytes.Buffer) {
29
-	buf.Reset()
30
-	poolWrapperObfuscated2WritePool.Put(buf)
31
-}
32
-
33
 type wrapperObfuscated2 struct {
14
 type wrapperObfuscated2 struct {
34
 	encryptor cipher.Stream
15
 	encryptor cipher.Stream
35
 	decryptor cipher.Stream
16
 	decryptor cipher.Stream
59
 }
40
 }
60
 
41
 
61
 func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
42
 func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
62
-	buffer := poolWrapperObfuscated2WritePoolAcquire()
63
-	defer poolWrapperObfuscated2WritePoolRelease(buffer)
43
+	buffer := acquireBytesBuffer()
44
+	defer releaseBytesBuffer(buffer)
64
 
45
 
65
 	buffer.Write(p)
46
 	buffer.Write(p)
66
 
47
 
72
 }
53
 }
73
 
54
 
74
 func (w *wrapperObfuscated2) Write(p []byte) (int, error) {
55
 func (w *wrapperObfuscated2) Write(p []byte) (int, error) {
75
-	buffer := poolWrapperObfuscated2WritePoolAcquire()
76
-	defer poolWrapperObfuscated2WritePoolRelease(buffer)
56
+	buffer := acquireBytesBuffer()
57
+	defer releaseBytesBuffer(buffer)
77
 
58
 
78
 	buffer.Write(p)
59
 	buffer.Write(p)
79
 
60
 

+ 23
- 0
wrappers/stream/pools.go Просмотреть файл

1
+package stream
2
+
3
+import (
4
+	"bytes"
5
+	"sync"
6
+)
7
+
8
+var (
9
+	poolBytesBuffer = sync.Pool{
10
+		New: func() interface{} {
11
+			return &bytes.Buffer{}
12
+		},
13
+	}
14
+)
15
+
16
+func acquireBytesBuffer() *bytes.Buffer {
17
+	return poolBytesBuffer.Get().(*bytes.Buffer)
18
+}
19
+
20
+func releaseBytesBuffer(buf *bytes.Buffer) {
21
+	buf.Reset()
22
+	poolBytesBuffer.Put(buf)
23
+}

Загрузка…
Отмена
Сохранить