Quellcode durchsuchen

Use pool for frames

tags/0.9
9seconds vor 7 Jahren
Ursprung
Commit
c76d8307c2

+ 2
- 2
Gopkg.lock Datei anzeigen

@@ -43,8 +43,8 @@
43 43
 [[projects]]
44 44
   name = "github.com/stretchr/testify"
45 45
   packages = ["assert"]
46
-  revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
47
-  version = "v1.2.1"
46
+  revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
47
+  version = "v1.2.2"
48 48
 
49 49
 [[projects]]
50 50
   name = "go.uber.org/atomic"

+ 1
- 0
client/direct.go Datei anzeigen

@@ -18,6 +18,7 @@ func DirectInit(conn net.Conn, conf *config.Config) (int16, io.ReadWriteCloser,
18 18
 	if err != nil {
19 19
 		return 0, nil, errors.Annotate(err, "Cannot extract frame")
20 20
 	}
21
+	defer obfuscated2.ReturnFrame(frame)
21 22
 
22 23
 	obfs2, dc, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame)
23 24
 	if err != nil {

+ 16
- 10
obfuscated2/frame.go Datei anzeigen

@@ -68,29 +68,35 @@ func (f Frame) Valid() bool {
68 68
 
69 69
 // Invert inverts frame for extracting encryption keys. Pkease check that link:
70 70
 // https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/
71
-func (f Frame) Invert() Frame {
72
-	reversed := make(Frame, FrameLen)
73
-	copy(reversed, f)
71
+func (f Frame) Invert() *Frame {
72
+	reversed := MakeFrame()
73
+	copy(*reversed, f)
74 74
 
75 75
 	for i := 0; i < frameLenKey+frameLenIV; i++ {
76
-		reversed[frameOffsetFirst+i] = f[frameOffsetIV-1-i]
76
+		(*reversed)[frameOffsetFirst+i] = f[frameOffsetIV-1-i]
77 77
 	}
78 78
 
79 79
 	return reversed
80 80
 }
81 81
 
82 82
 // ExtractFrame extracts exact obfuscated2 handshake frame from given reader.
83
-func ExtractFrame(conn io.Reader) (Frame, error) {
84
-	buf := &bytes.Buffer{}
83
+func ExtractFrame(conn io.Reader) (*Frame, error) {
84
+	frame := MakeFrame()
85
+	buf := bytes.NewBuffer(*frame)
86
+	buf.Reset()
87
+
85 88
 	if _, err := io.CopyN(buf, conn, FrameLen); err != nil {
89
+		ReturnFrame(frame)
86 90
 		return nil, errors.Annotate(err, "Cannot extract obfuscated header")
87 91
 	}
92
+	copy(*frame, buf.Bytes())
88 93
 
89
-	return Frame(buf.Bytes()), nil
94
+	return frame, nil
90 95
 }
91 96
 
92
-func generateFrame() Frame {
93
-	data := make(Frame, FrameLen)
97
+func generateFrame() *Frame {
98
+	frame := MakeFrame()
99
+	data := *frame
94 100
 
95 101
 	for {
96 102
 		if _, err := rand.Read(data); err != nil {
@@ -112,6 +118,6 @@ func generateFrame() Frame {
112 118
 
113 119
 		copy(data.Magic(), tgMagicBytes)
114 120
 
115
-		return data
121
+		return frame
116 122
 	}
117 123
 }

+ 24
- 0
obfuscated2/frame_pool.go Datei anzeigen

@@ -0,0 +1,24 @@
1
+package obfuscated2
2
+
3
+import "sync"
4
+
5
+var framePool sync.Pool
6
+
7
+// MakeFrame returns new pointer to the handshake frame.
8
+func MakeFrame() *Frame {
9
+	return framePool.Get().(*Frame)
10
+}
11
+
12
+// ReturnFrame returns pointer to the handshake frame back to the pool.
13
+func ReturnFrame(f *Frame) {
14
+	framePool.Put(f)
15
+}
16
+
17
+func init() {
18
+	framePool = sync.Pool{
19
+		New: func() interface{} {
20
+			data := make(Frame, FrameLen)
21
+			return &data
22
+		},
23
+	}
24
+}

+ 5
- 4
obfuscated2/frame_test.go Datei anzeigen

@@ -1,6 +1,7 @@
1 1
 package obfuscated2
2 2
 
3 3
 import (
4
+	"bytes"
4 5
 	"testing"
5 6
 
6 7
 	"github.com/stretchr/testify/assert"
@@ -47,21 +48,21 @@ func TestFrameValid(t *testing.T) {
47 48
 
48 49
 func TestFrameDoubleInvert(t *testing.T) {
49 50
 	frame := makeFrame()
50
-	assert.Equal(t, frame, frame.Invert().Invert())
51
+	assert.True(t, bytes.Equal(frame, *frame.Invert().Invert()))
51 52
 }
52 53
 
53 54
 func TestFrameInvert(t *testing.T) {
54 55
 	frame := makeFrame()
55 56
 	reversed := frame.Invert()
56 57
 
57
-	assert.Exactly(t, frame[:8], reversed[:8])
58
-	assert.Exactly(t, frame[56:], reversed[56:])
58
+	assert.Exactly(t, frame[:8], (*reversed)[:8])
59
+	assert.Exactly(t, frame[56:], (*reversed)[56:])
59 60
 
60 61
 	toCompare := make([]byte, 48)
61 62
 	for i := 0; i < 48; i++ {
62 63
 		toCompare[i] = frame[55-i]
63 64
 	}
64
-	assert.Equal(t, []byte(reversed[8:56]), toCompare)
65
+	assert.Equal(t, []byte((*reversed)[8:56]), toCompare)
65 66
 }
66 67
 
67 68
 func TestFrameGenerateValid(t *testing.T) {

+ 10
- 8
obfuscated2/obfuscated2.go Datei anzeigen

@@ -19,7 +19,7 @@ type Obfuscated2 struct {
19 19
 // details: http://telegra.ph/telegram-blocks-wtf-05-26
20 20
 //
21 21
 // Beware, link above is in russian.
22
-func ParseObfuscated2ClientFrame(secret []byte, frame Frame) (*Obfuscated2, int16, error) {
22
+func ParseObfuscated2ClientFrame(secret []byte, frame *Frame) (*Obfuscated2, int16, error) {
23 23
 	decHasher := sha256.New()
24 24
 	decHasher.Write(frame.Key()) // nolint: errcheck
25 25
 	decHasher.Write(secret)      // nolint: errcheck
@@ -31,8 +31,9 @@ func ParseObfuscated2ClientFrame(secret []byte, frame Frame) (*Obfuscated2, int1
31 31
 	encHasher.Write(secret)              // nolint: errcheck
32 32
 	encryptor := makeStreamCipher(encHasher.Sum(nil), invertedFrame.IV())
33 33
 
34
-	decryptedFrame := make(Frame, FrameLen)
35
-	decryptor.XORKeyStream(decryptedFrame, frame)
34
+	decryptedFrame := MakeFrame()
35
+	defer ReturnFrame(decryptedFrame)
36
+	decryptor.XORKeyStream(*decryptedFrame, *frame)
36 37
 	if !decryptedFrame.Valid() {
37 38
 		return nil, 0, errors.New("Unknown protocol")
38 39
 	}
@@ -48,17 +49,18 @@ func ParseObfuscated2ClientFrame(secret []byte, frame Frame) (*Obfuscated2, int1
48 49
 // MakeTelegramObfuscated2Frame creates new handshake frame to send to
49 50
 // Telegram.
50 51
 // https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/
51
-func MakeTelegramObfuscated2Frame() (*Obfuscated2, Frame) {
52
+func MakeTelegramObfuscated2Frame() (*Obfuscated2, *Frame) {
52 53
 	frame := generateFrame()
53 54
 
54 55
 	encryptor := makeStreamCipher(frame.Key(), frame.IV())
55 56
 	decryptorFrame := frame.Invert()
56 57
 	decryptor := makeStreamCipher(decryptorFrame.Key(), decryptorFrame.IV())
57 58
 
58
-	copyFrame := make(Frame, frameOffsetIV)
59
-	copy(copyFrame, frame)
60
-	encryptor.XORKeyStream(frame, frame)
61
-	copy(frame, copyFrame)
59
+	copyFrame := MakeFrame()
60
+	defer ReturnFrame(copyFrame)
61
+	copy((*copyFrame)[:frameOffsetIV], (*frame)[:frameOffsetIV])
62
+	encryptor.XORKeyStream(*frame, *frame)
63
+	copy((*frame)[:frameOffsetIV], (*copyFrame)[:frameOffsetIV])
62 64
 
63 65
 	obfs := &Obfuscated2{
64 66
 		Decryptor: decryptor,

+ 5
- 5
obfuscated2/obfuscated2_test.go Datei anzeigen

@@ -12,7 +12,7 @@ func TestObfs2TelegramFrameDecrypt(t *testing.T) {
12 12
 	decryptor := makeStreamCipher(frame.Key(), frame.IV())
13 13
 
14 14
 	decrypted := make(Frame, FrameLen)
15
-	decryptor.XORKeyStream(decrypted, frame)
15
+	decryptor.XORKeyStream(decrypted, *frame)
16 16
 
17 17
 	assert.True(t, decrypted.Valid())
18 18
 }
@@ -42,8 +42,8 @@ func TestObfs2Full(t *testing.T) {
42 42
 
43 43
 	encryptor := makeStreamCipher(clientKey, clientFrame.IV())
44 44
 	encrypted := make(Frame, FrameLen)
45
-	encryptor.XORKeyStream(encrypted, clientFrame)
46
-	copy(encrypted[:56], clientFrame[:56])
45
+	encryptor.XORKeyStream(encrypted, *clientFrame)
46
+	copy(encrypted[:56], (*clientFrame)[:56])
47 47
 
48 48
 	invertedClientFrame := clientFrame.Invert()
49 49
 	clientHasher = sha256.New()
@@ -52,13 +52,13 @@ func TestObfs2Full(t *testing.T) {
52 52
 	invertedClientKey := clientHasher.Sum(nil)
53 53
 	clientDecryptor := makeStreamCipher(invertedClientKey, invertedClientFrame.IV())
54 54
 
55
-	clientObfs, _, err := ParseObfuscated2ClientFrame(secret, encrypted)
55
+	clientObfs, _, err := ParseObfuscated2ClientFrame(secret, &encrypted)
56 56
 	assert.Nil(t, err)
57 57
 
58 58
 	tgObfs, tgFrame := MakeTelegramObfuscated2Frame()
59 59
 	tgDecryptor := makeStreamCipher(tgFrame.Key(), tgFrame.IV())
60 60
 	decrypted := make(Frame, FrameLen)
61
-	tgDecryptor.XORKeyStream(decrypted, tgFrame)
61
+	tgDecryptor.XORKeyStream(decrypted, *tgFrame)
62 62
 	assert.True(t, decrypted.Valid())
63 63
 
64 64
 	tgInvertedFrame := tgFrame.Invert()

+ 3
- 1
telegram/direct.go Datei anzeigen

@@ -43,7 +43,9 @@ func (t *directTelegram) Dial(dcIdx int16) (io.ReadWriteCloser, error) {
43 43
 
44 44
 func (t *directTelegram) Init(conn io.ReadWriteCloser) (io.ReadWriteCloser, error) {
45 45
 	obfs2, frame := obfuscated2.MakeTelegramObfuscated2Frame()
46
-	if n, err := conn.Write(frame); err != nil || n != len(frame) {
46
+	defer obfuscated2.ReturnFrame(frame)
47
+
48
+	if n, err := conn.Write(*frame); err != nil || n != len(*frame) {
47 49
 		return nil, errors.Annotate(err, "Cannot write hadnshake frame")
48 50
 	}
49 51
 

Laden…
Abbrechen
Speichern