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
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

mtproto_intermediate.go 2.7KB

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