Kaynağa Gözat

Add rpc proxy request

tags/0.9
9seconds 7 yıl önce
ebeveyn
işleme
96bb6fbe98

+ 32
- 0
mtproto/bufferpool/bufferpool.go Dosyayı Görüntüle

@@ -0,0 +1,32 @@
1
+package bufferpool
2
+
3
+import (
4
+	"bytes"
5
+	"sync"
6
+)
7
+
8
+const bufferPoolSize = 4 * 1024
9
+
10
+var bufferPool sync.Pool
11
+
12
+func Get() *bytes.Buffer {
13
+	buf := bufferPool.Get().(*bytes.Buffer)
14
+	buf.Reset()
15
+
16
+	return buf
17
+}
18
+
19
+func Return(buf *bytes.Buffer) {
20
+	bufferPool.Put(buf)
21
+}
22
+
23
+func init() {
24
+	bufferPool = sync.Pool{
25
+		New: func() interface{} {
26
+			buf := &bytes.Buffer{}
27
+			buf.Grow(bufferPoolSize)
28
+
29
+			return buf
30
+		},
31
+	}
32
+}

+ 6
- 0
mtproto/extras.go Dosyayı Görüntüle

@@ -0,0 +1,6 @@
1
+package mtproto
2
+
3
+type Extras struct {
4
+	QuickAck  bool
5
+	SimpleAck bool
6
+}

+ 1
- 28
mtproto/rpc/rpc_proxy_flags.go Dosyayı Görüntüle

@@ -1,11 +1,6 @@
1 1
 package rpc
2 2
 
3
-import (
4
-	"bytes"
5
-	"encoding/binary"
6
-
7
-	"github.com/9seconds/mtg/mtproto"
8
-)
3
+import "encoding/binary"
9 4
 
10 5
 type RPCProxyRequestFlags uint32
11 6
 
@@ -27,25 +22,3 @@ func (r RPCProxyRequestFlags) Bytes() []byte {
27 22
 
28 23
 	return converted
29 24
 }
30
-
31
-func NewRPCRproxyRequestFlags(connectionType mtproto.ConnectionType, quickAck bool, message []byte) RPCProxyRequestFlags {
32
-	flags := RPCProxyRequestFlagsHasAdTag
33
-	flags |= RPCProxyRequestFlagsMagic
34
-	flags |= RPCProxyRequestFlagsExtMode2
35
-
36
-	switch connectionType {
37
-	case mtproto.ConnectionTypeAbridged:
38
-		flags |= RPCProxyRequestFlagsAbdridged
39
-	case mtproto.ConnectionTypeIntermediate:
40
-		flags |= RPCProxyRequestFlagsIntermediate
41
-	}
42
-
43
-	if quickAck {
44
-		flags |= RPCProxyRequestFlagsQuickAck
45
-	}
46
-	if bytes.HasPrefix(message, rpcProxyRequestFlagsEncryptedPrefix[:]) {
47
-		flags |= RPCProxyRequestFlagsEncrypted
48
-	}
49
-
50
-	return flags
51
-}

+ 98
- 0
mtproto/rpc/rpc_proxy_request.go Dosyayı Görüntüle

@@ -0,0 +1,98 @@
1
+package rpc
2
+
3
+import (
4
+	"bytes"
5
+	"crypto/rand"
6
+	"encoding/binary"
7
+	"net"
8
+
9
+	"github.com/9seconds/mtg/mtproto"
10
+	"github.com/9seconds/mtg/mtproto/bufferpool"
11
+	"github.com/juju/errors"
12
+)
13
+
14
+const (
15
+	rpcProxyRequestConnectionIDLength = 8
16
+	rpcProxyRequestIPPortLength       = 16 + 4
17
+)
18
+
19
+var (
20
+	rpcProxyRequestTag       = []byte{0xee, 0xf1, 0xce, 0x36}
21
+	rpcProxyRequestExtraSize = []byte{0x18, 0x00, 0x00, 0x00}
22
+	rpcProxyRequestProxyTag  = []byte{0xae, 0x26, 0x1e, 0xdb}
23
+)
24
+
25
+type RPCProxyRequest struct {
26
+	Flags        RPCProxyRequestFlags
27
+	ConnectionID [rpcProxyRequestConnectionIDLength]byte
28
+	RemoteIPPort [rpcProxyRequestIPPortLength]byte
29
+	LocalIPPort  [rpcProxyRequestIPPortLength]byte
30
+	ADTag        []byte
31
+	Message      *bytes.Buffer
32
+	Extras       *mtproto.Extras
33
+}
34
+
35
+func (r *RPCProxyRequest) Bytes() *bytes.Buffer {
36
+	buf := bufferpool.Get()
37
+
38
+	flags := r.Flags
39
+	if r.Extras.QuickAck {
40
+		flags |= RPCProxyRequestFlagsQuickAck
41
+	}
42
+
43
+	messageBytes := r.Message.Bytes()
44
+	if bytes.HasPrefix(messageBytes, rpcProxyRequestFlagsEncryptedPrefix[:]) {
45
+		flags |= RPCProxyRequestFlagsEncrypted
46
+	}
47
+
48
+	buf.Write(rpcProxyRequestTag)
49
+	buf.Write(flags.Bytes())
50
+	buf.Write(r.ConnectionID[:])
51
+	buf.Write(r.RemoteIPPort[:])
52
+	buf.Write(r.LocalIPPort[:])
53
+	buf.Write(rpcProxyRequestExtraSize)
54
+	buf.Write(rpcProxyRequestProxyTag)
55
+	buf.WriteByte(byte(len(r.ADTag)))
56
+	buf.Write(r.ADTag)
57
+
58
+	for i := 0; i < (buf.Len() % 4); i++ {
59
+		buf.WriteByte(0x00)
60
+	}
61
+	if r.Message != nil {
62
+		buf.Write(messageBytes)
63
+	}
64
+
65
+	return buf
66
+}
67
+
68
+func NewRPCProxyRequest(connectionType mtproto.ConnectionType, local, remote *net.TCPAddr, adTag []byte, extras *mtproto.Extras) (*RPCProxyRequest, error) {
69
+	flags := RPCProxyRequestFlagsHasAdTag | RPCProxyRequestFlagsMagic | RPCProxyRequestFlagsExtMode2
70
+
71
+	switch connectionType {
72
+	case mtproto.ConnectionTypeAbridged:
73
+		flags |= RPCProxyRequestFlagsAbdridged
74
+	case mtproto.ConnectionTypeIntermediate:
75
+		flags |= RPCProxyRequestFlagsIntermediate
76
+	}
77
+
78
+	request := RPCProxyRequest{
79
+		Flags:  flags,
80
+		ADTag:  adTag,
81
+		Extras: extras,
82
+	}
83
+
84
+	if _, err := rand.Read(request.ConnectionID[:]); err != nil {
85
+		return nil, errors.Annotate(err, "Cannot generate connection ID")
86
+	}
87
+
88
+	port := make([]byte, 4)
89
+	copy(request.LocalIPPort[:], local.IP.To16())
90
+	binary.LittleEndian.PutUint32(port, uint32(local.Port))
91
+	copy(request.LocalIPPort[16:], port)
92
+
93
+	copy(request.RemoteIPPort[:], remote.IP.To16())
94
+	binary.LittleEndian.PutUint32(port, uint32(remote.Port))
95
+	copy(request.RemoteIPPort[16:], port)
96
+
97
+	return &request, nil
98
+}

Loading…
İptal
Kaydet