Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mtproto_proxy.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package wrappers
  2. import (
  3. "bytes"
  4. "net"
  5. "github.com/9seconds/mtg/mtproto/rpc"
  6. "github.com/juju/errors"
  7. )
  8. type MTProtoProxy struct {
  9. conn WrapPacketReadWriteCloser
  10. req *rpc.ProxyRequest
  11. readCounter uint32
  12. writeCounter uint32
  13. }
  14. func (m *MTProtoProxy) Read() ([]byte, error) {
  15. m.LogDebug("Read packet",
  16. "counter", m.readCounter,
  17. "simple_ack", m.req.Options.WriteHacks.SimpleAck,
  18. "quick_ack", m.req.Options.WriteHacks.QuickAck,
  19. )
  20. packet, err := m.conn.Read()
  21. if err != nil {
  22. return nil, errors.Annotate(err, "Cannot read packet")
  23. }
  24. m.LogDebug("Read packet length",
  25. "counter", m.readCounter,
  26. "simple_ack", m.req.Options.WriteHacks.SimpleAck,
  27. "quick_ack", m.req.Options.WriteHacks.QuickAck,
  28. "length", len(packet),
  29. )
  30. if len(packet) < 4 {
  31. return nil, errors.Annotate(err, "Incorrect packet length")
  32. }
  33. tag, packet := packet[:4], packet[4:]
  34. m.LogDebug("Read RPC tag",
  35. "counter", m.readCounter,
  36. "simple_ack", m.req.Options.WriteHacks.SimpleAck,
  37. "quick_ack", m.req.Options.WriteHacks.QuickAck,
  38. "tag", tag,
  39. )
  40. m.readCounter++
  41. switch {
  42. case bytes.Equal(tag, rpc.TagProxyAns):
  43. return m.readProxyAns(packet)
  44. case bytes.Equal(tag, rpc.TagSimpleAck):
  45. return m.readSimpleAck(packet)
  46. case bytes.Equal(tag, rpc.TagCloseExt):
  47. return m.readCloseExt(packet)
  48. }
  49. return nil, errors.Errorf("Unknown RPC answer %v", tag)
  50. }
  51. func (m *MTProtoProxy) readProxyAns(data []byte) ([]byte, error) {
  52. if len(data) < 12 {
  53. return nil, errors.Errorf("Incorrect data of proxy answer: %d", len(data))
  54. }
  55. return data[12:], nil
  56. }
  57. func (m *MTProtoProxy) readSimpleAck(data []byte) ([]byte, error) {
  58. if len(data) != 12 {
  59. return nil, errors.Errorf("Incorrect data of simple ack: %d", len(data))
  60. }
  61. return data[8:12], nil // 0:8 - connection id
  62. }
  63. func (m *MTProtoProxy) readCloseExt(data []byte) ([]byte, error) {
  64. return nil, errors.New("Connection has been closed remotely by RPC call")
  65. }
  66. func (m *MTProtoProxy) Write(p []byte) (int, error) {
  67. m.LogDebug("Write packet",
  68. "length", len(p),
  69. "counter", m.writeCounter,
  70. "simple_ack", m.req.Options.ReadHacks.SimpleAck,
  71. "quick_ack", m.req.Options.ReadHacks.QuickAck,
  72. )
  73. m.writeCounter++
  74. if _, err := m.conn.Write(p); err != nil {
  75. return 0, err
  76. }
  77. return len(p), nil
  78. }
  79. func (m *MTProtoProxy) LogDebug(msg string, data ...interface{}) {
  80. data = append(data, []interface{}{"type", "proxy"})
  81. m.conn.LogDebug(msg, data...)
  82. }
  83. func (m *MTProtoProxy) LogInfo(msg string, data ...interface{}) {
  84. data = append(data, []interface{}{"type", "proxy"})
  85. m.conn.LogInfo(msg, data...)
  86. }
  87. func (m *MTProtoProxy) LogWarn(msg string, data ...interface{}) {
  88. data = append(data, []interface{}{"type", "proxy"})
  89. m.conn.LogWarn(msg, data...)
  90. }
  91. func (m *MTProtoProxy) LogError(msg string, data ...interface{}) {
  92. data = append(data, []interface{}{"type", "proxy"})
  93. m.conn.LogError(msg, data...)
  94. }
  95. func (m *MTProtoProxy) LocalAddr() *net.TCPAddr {
  96. return m.conn.LocalAddr()
  97. }
  98. func (m *MTProtoProxy) RemoteAddr() *net.TCPAddr {
  99. return m.conn.RemoteAddr()
  100. }
  101. func (m *MTProtoProxy) Close() error {
  102. return m.conn.Close()
  103. }
  104. func NewMTProtoProxy(conn WrapPacketReadWriteCloser, req *rpc.ProxyRequest) WrapPacketReadWriteCloser {
  105. return &MTProtoProxy{
  106. conn: conn,
  107. req: req,
  108. }
  109. }