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_intermediate.go 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package wrappers
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "io"
  6. "net"
  7. "github.com/9seconds/mtg/mtproto"
  8. "github.com/juju/errors"
  9. )
  10. const mtprotoIntermediateQuickAckLength = 0x80000000
  11. type MTProtoIntermediate struct {
  12. conn StreamReadWriteCloser
  13. opts *mtproto.ConnectionOpts
  14. readCounter uint32
  15. writeCounter uint32
  16. }
  17. func (m *MTProtoIntermediate) Read() ([]byte, error) {
  18. m.LogDebug("Read packet",
  19. "simple_ack", m.opts.ReadHacks.SimpleAck,
  20. "quick_ack", m.opts.ReadHacks.QuickAck,
  21. "counter", m.readCounter,
  22. )
  23. buf := &bytes.Buffer{}
  24. buf.Grow(4)
  25. if _, err := io.CopyN(buf, m.conn, 4); err != nil {
  26. return nil, errors.Annotate(err, "Cannot read message length")
  27. }
  28. length := binary.LittleEndian.Uint32(buf.Bytes())
  29. m.LogDebug("Packet message length",
  30. "simple_ack", m.opts.ReadHacks.SimpleAck,
  31. "quick_ack", m.opts.ReadHacks.QuickAck,
  32. "counter", m.readCounter,
  33. "length", length,
  34. )
  35. if length > mtprotoIntermediateQuickAckLength {
  36. m.opts.ReadHacks.QuickAck = true
  37. length -= mtprotoIntermediateQuickAckLength
  38. }
  39. buf.Reset()
  40. buf.Grow(int(length))
  41. if _, err := io.CopyN(buf, m.conn, int64(length)); err != nil {
  42. return nil, errors.Annotate(err, "Cannot read the message")
  43. }
  44. if length%4 != 0 {
  45. length -= length % 4
  46. }
  47. m.readCounter++
  48. return buf.Bytes()[:length], nil
  49. }
  50. func (m *MTProtoIntermediate) Write(p []byte) (int, error) {
  51. m.LogDebug("Write packet",
  52. "simple_ack", m.opts.WriteHacks.SimpleAck,
  53. "quick_ack", m.opts.WriteHacks.QuickAck,
  54. "counter", m.writeCounter,
  55. )
  56. m.writeCounter++
  57. if m.opts.ReadHacks.SimpleAck {
  58. return m.conn.Write(p)
  59. }
  60. var length [4]byte
  61. binary.LittleEndian.PutUint32(length[:], uint32(len(p)))
  62. return m.conn.Write(append(length[:], p...))
  63. }
  64. func (m *MTProtoIntermediate) LogDebug(msg string, data ...interface{}) {
  65. data = append(data, []interface{}{"type", "intermediate"})
  66. m.conn.LogDebug(msg, data...)
  67. }
  68. func (m *MTProtoIntermediate) LogInfo(msg string, data ...interface{}) {
  69. data = append(data, []interface{}{"type", "intermediate"})
  70. m.conn.LogInfo(msg, data...)
  71. }
  72. func (m *MTProtoIntermediate) LogWarn(msg string, data ...interface{}) {
  73. data = append(data, []interface{}{"type", "intermediate"})
  74. m.conn.LogWarn(msg, data...)
  75. }
  76. func (m *MTProtoIntermediate) LogError(msg string, data ...interface{}) {
  77. data = append(data, []interface{}{"type", "intermediate"})
  78. m.conn.LogError(msg, data...)
  79. }
  80. func (m *MTProtoIntermediate) LocalAddr() *net.TCPAddr {
  81. return m.conn.LocalAddr()
  82. }
  83. func (m *MTProtoIntermediate) RemoteAddr() *net.TCPAddr {
  84. return m.conn.RemoteAddr()
  85. }
  86. func (m *MTProtoIntermediate) Close() error {
  87. return m.conn.Close()
  88. }
  89. func NewMTProtoIntermediate(conn StreamReadWriteCloser, opts *mtproto.ConnectionOpts) PacketReadWriteCloser {
  90. return &MTProtoIntermediate{
  91. conn: conn,
  92. opts: opts,
  93. }
  94. }