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 символов.

proxy_request.go 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package wrappers
  2. import (
  3. "bytes"
  4. "io"
  5. "io/ioutil"
  6. "net"
  7. "github.com/juju/errors"
  8. "github.com/9seconds/mtg/mtproto"
  9. "github.com/9seconds/mtg/mtproto/rpc"
  10. "github.com/9seconds/mtg/wrappers"
  11. )
  12. type ProxyRequestReadWriteCloserWithAddr struct {
  13. wrappers.BufferedReader
  14. conn wrappers.ReadWriteCloserWithAddr
  15. req *rpc.ProxyRequest
  16. }
  17. func (p *ProxyRequestReadWriteCloserWithAddr) Read(buf []byte) (int, error) {
  18. return p.BufferedRead(buf, func() error {
  19. ansBuf := &bytes.Buffer{}
  20. ansBuf.Grow(4)
  21. if _, err := io.CopyN(ansBuf, p.conn, 4); err != nil {
  22. return errors.Annotate(err, "Cannot read RPC tag")
  23. }
  24. if bytes.Equal(ansBuf.Bytes(), rpc.TagCloseExt) {
  25. return p.readCloseExt()
  26. } else if bytes.Equal(ansBuf.Bytes(), rpc.TagProxyAns) {
  27. return p.readProxyAns(buf)
  28. } else if bytes.Equal(ansBuf.Bytes(), rpc.TagSimpleAck) {
  29. return p.readSimpleAck()
  30. }
  31. return nil
  32. })
  33. }
  34. func (p *ProxyRequestReadWriteCloserWithAddr) readCloseExt() error {
  35. return errors.New("Connection has been closed remotely")
  36. }
  37. func (p *ProxyRequestReadWriteCloserWithAddr) readProxyAns(buf []byte) error {
  38. if _, err := io.CopyN(ioutil.Discard, p.conn, 8+4); err != nil {
  39. return errors.Annotate(err, "Cannot skip flags and connid")
  40. }
  41. for {
  42. n, err := p.conn.Read(buf)
  43. if err != nil {
  44. return errors.Annotate(err, "Cannot read proxy answer")
  45. }
  46. if n == 0 {
  47. break
  48. }
  49. p.Buffer.Write(buf[:n])
  50. }
  51. return nil
  52. }
  53. func (p *ProxyRequestReadWriteCloserWithAddr) readSimpleAck() error {
  54. if _, err := io.CopyN(ioutil.Discard, p.conn, 8); err != nil {
  55. return errors.Annotate(err, "Cannot skip connid")
  56. }
  57. if _, err := io.CopyN(p.Buffer, p.conn, 4); err != nil {
  58. return errors.Annotate(err, "Cannot read simple ack")
  59. }
  60. p.req.Options.SimpleAck = true
  61. return nil
  62. }
  63. func (p *ProxyRequestReadWriteCloserWithAddr) Write(raw []byte) (int, error) {
  64. if _, err := p.conn.Write(p.req.Bytes(raw)); err != nil {
  65. return 0, err
  66. }
  67. p.req.Options.SimpleAck = false
  68. p.req.Options.QuickAck = false
  69. return len(raw), nil
  70. }
  71. func (p *ProxyRequestReadWriteCloserWithAddr) Close() error {
  72. return p.conn.Close()
  73. }
  74. func (p *ProxyRequestReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
  75. return p.conn.LocalAddr()
  76. }
  77. func (p *ProxyRequestReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
  78. return p.conn.RemoteAddr()
  79. }
  80. func NewProxyRequestRWC(conn wrappers.ReadWriteCloserWithAddr, connOpts *mtproto.ConnectionOpts, adTag []byte) (wrappers.ReadWriteCloserWithAddr, error) {
  81. req, err := rpc.NewProxyRequest(connOpts.ClientAddr, conn.LocalAddr(), connOpts, adTag)
  82. if err != nil {
  83. return nil, errors.Annotate(err, "Cannot create new RPC proxy request")
  84. }
  85. return &ProxyRequestReadWriteCloserWithAddr{
  86. BufferedReader: wrappers.NewBufferedReader(),
  87. conn: conn,
  88. req: req,
  89. }, nil
  90. }