/
msg_stream_srv.go
114 lines (110 loc) · 2.77 KB
/
msg_stream_srv.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package obfuscated
import (
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"github.com/geovex/tgp/internal/tgcrypt"
)
func (s *msgStream) ReadSrvMsg() (m *message, err error) {
switch s.sock.Protocol() {
case tgcrypt.Abridged:
var l [4]byte
// read length
_, err = io.ReadFull(s.sock, l[:1])
if err != nil {
return
}
var msgLen uint32
if l[0] < 0x7f {
msgLen = uint32(l[0])
} else {
_, err = io.ReadFull(s.sock, l[1:4])
if err != nil {
return
}
if l[0]&0x80 != 0 {
m = &message{[]byte{l[3], l[2], l[1], l[0]}, true, 0}
fmt.Printf("server read quickack abridged %v\n", m.data)
return
}
msgLen = binary.LittleEndian.Uint32(l[:]) >> 8
}
msgLen = msgLen * 4
// read message
if msgLen > tgcrypt.MaxPayloadSize {
err = fmt.Errorf("message too big: %d", msgLen)
return
}
msg := make([]byte, msgLen)
_, err = io.ReadFull(s.sock, msg)
if err != nil {
return
}
m = &message{msg, false, 0}
return
case tgcrypt.Intermediate, tgcrypt.Padded:
// read length
var l [4]byte
_, err = io.ReadFull(s.sock, l[:])
if err != nil {
return
}
msgLen := binary.LittleEndian.Uint32(l[:])
if msgLen&0x80000000 != 0 {
fmt.Printf("server read quickack %d\n", msgLen)
m = &message{l[:], true, 0}
return
}
// read message
if msgLen > tgcrypt.MaxPayloadSize {
err = fmt.Errorf("message too big: %d", msgLen)
return
}
msg := make([]byte, msgLen)
_, err = io.ReadFull(s.sock, msg)
if err != nil {
return
}
m = &message{msg, false, 0}
return
default:
return nil, fmt.Errorf("unsupported protocol: %x", s.sock.Protocol())
}
}
func (s *msgStream) WriteSrvMsg(m *message) (err error) {
sendmsg := make([]byte, 0, len(m.data)+20)
switch s.sock.Protocol() {
case tgcrypt.Abridged:
l := uint32(len(m.data))
if l%4 != 0 {
return fmt.Errorf("message size not multiple of 4")
}
l = l / 4
if l >= 0x7f {
sendmsg = append(sendmsg, 0x7f)
sendmsg = append(sendmsg, binary.LittleEndian.AppendUint32([]byte{}, l)[:3]...)
} else {
sendmsg = append(sendmsg, byte(l))
}
sendmsg = append(sendmsg, m.data...)
if m.quickack {
sendmsg[0] |= 0x80
sendmsg = []byte{sendmsg[3], sendmsg[2], sendmsg[1], sendmsg[0]}
fmt.Printf("server write quickack abridged %v\n", sendmsg)
}
case tgcrypt.Intermediate, tgcrypt.Padded:
sendmsg = binary.LittleEndian.AppendUint32(sendmsg, uint32(len(m.data)))
sendmsg = append(sendmsg, m.data...)
if m.quickack {
sendmsg[3] |= 0x80
fmt.Printf("server write quickack %d\n", sendmsg[3])
}
default:
fmt.Printf("Srv unsupported protocol: %x\n", s.sock.Protocol())
return fmt.Errorf("unsupported protocol: %x", s.sock.Protocol())
}
fmt.Printf("msg write seq: %d hex: %s\n", m.seq, hex.EncodeToString(sendmsg))
_, err = s.sock.Write(sendmsg)
return
}