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
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

proxy_request.go 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. var (
  13. rpcCloseExtTag = [4]byte{0xa2, 0x34, 0xb6, 0x5e}
  14. rpcProxyAnsTag = [4]byte{0x0d, 0xda, 0x03, 0x44}
  15. rpcSimpleAckTag = [4]byte{0x9b, 0x40, 0xac, 0x3b}
  16. )
  17. type ProxyRequestReadWriteCloserWithAddr struct {
  18. wrappers.BufferedReader
  19. conn wrappers.ReadWriteCloserWithAddr
  20. req *rpc.RPCProxyRequest
  21. }
  22. func (p *ProxyRequestReadWriteCloserWithAddr) Read(buf []byte) (int, error) {
  23. return p.BufferedRead(buf, func() error {
  24. ansBuf := &bytes.Buffer{}
  25. ansBuf.Grow(4)
  26. if _, err := io.CopyN(ansBuf, p.conn, 4); err != nil {
  27. return errors.Annotate(err, "Cannot read RPC tag")
  28. }
  29. if bytes.Equal(ansBuf.Bytes(), rpcCloseExtTag[:]) {
  30. return errors.New("Connection has been closed remotely")
  31. } else if bytes.Equal(ansBuf.Bytes(), rpcProxyAnsTag[:]) {
  32. if _, err := io.CopyN(ioutil.Discard, p.conn, 8+4); err != nil {
  33. return errors.Annotate(err, "Cannot skip flags and connid")
  34. }
  35. for {
  36. n, err := p.conn.Read(buf)
  37. if err != nil {
  38. return errors.Annotate(err, "Cannot read proxy answer")
  39. }
  40. if n == 0 {
  41. break
  42. }
  43. p.Buffer.Write(buf[:n])
  44. }
  45. return nil
  46. } else if bytes.Equal(ansBuf.Bytes(), rpcSimpleAckTag[:]) {
  47. if _, err := io.CopyN(ioutil.Discard, p.conn, 8); err != nil {
  48. return errors.Annotate(err, "Cannot skip connid")
  49. }
  50. if _, err := io.CopyN(p.Buffer, p.conn, 4); err != nil {
  51. return errors.Annotate(err, "Cannot read simple ack")
  52. }
  53. p.req.Options.SimpleAck = true
  54. return nil
  55. }
  56. return nil
  57. })
  58. }
  59. func (p *ProxyRequestReadWriteCloserWithAddr) Write(raw []byte) (int, error) {
  60. if _, err := p.conn.Write(p.req.Bytes(raw)); err != nil {
  61. return 0, err
  62. }
  63. p.req.Options.SimpleAck = false
  64. p.req.Options.QuickAck = false
  65. return len(raw), nil
  66. }
  67. func (p *ProxyRequestReadWriteCloserWithAddr) Close() error {
  68. return p.conn.Close()
  69. }
  70. func (p *ProxyRequestReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
  71. return p.conn.LocalAddr()
  72. }
  73. func (p *ProxyRequestReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
  74. return p.conn.RemoteAddr()
  75. }
  76. func NewProxyRequestRWC(conn wrappers.ReadWriteCloserWithAddr, connOpts *mtproto.ConnectionOpts, adTag []byte) (wrappers.ReadWriteCloserWithAddr, error) {
  77. req, err := rpc.NewRPCProxyRequest(connOpts.ClientAddr, conn.LocalAddr(), connOpts, adTag)
  78. if err != nil {
  79. return nil, errors.Annotate(err, "Cannot create new RPC proxy request")
  80. }
  81. return &ProxyRequestReadWriteCloserWithAddr{
  82. conn: conn,
  83. req: req,
  84. }, nil
  85. }