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.

hub.go 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package hub
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "strings"
  6. "sync"
  7. "go.uber.org/zap"
  8. "github.com/9seconds/mtg/conntypes"
  9. "github.com/9seconds/mtg/protocol"
  10. )
  11. type hub struct {
  12. logger *zap.SugaredLogger
  13. subs map[string]*connectionHub
  14. mutex sync.RWMutex
  15. }
  16. func (h *hub) Write(packet conntypes.Packet, req *protocol.TelegramRequest) error {
  17. sub := h.getHub(req)
  18. connections := make(chan *connection)
  19. sub.channelConnectionRequests <- &connectionHubRequest{
  20. request: req,
  21. response: connections,
  22. }
  23. conn, ok := <-connections
  24. if !ok {
  25. return ErrCannotCreateConnection
  26. }
  27. if err := conn.write(packet); err != nil {
  28. conn.shutdown()
  29. return fmt.Errorf("cannot send packet: %w", err)
  30. }
  31. sub.channelReturnConnections <- conn
  32. return nil
  33. }
  34. func (h *hub) getHub(req *protocol.TelegramRequest) *connectionHub {
  35. keyBuilder := strings.Builder{}
  36. binary.Write(&keyBuilder, binary.LittleEndian, int16(req.ClientProtocol.DC())) // nolint: errcheck
  37. keyBuilder.WriteRune('_')
  38. binary.Write(&keyBuilder, binary.LittleEndian, uint8(req.ClientProtocol.ConnectionProtocol())) // nolint: errcheck
  39. key := keyBuilder.String()
  40. h.mutex.RLock()
  41. rv, ok := h.subs[key]
  42. h.mutex.RUnlock()
  43. if !ok {
  44. h.mutex.Lock()
  45. defer h.mutex.Unlock()
  46. rv, ok = h.subs[key]
  47. if !ok {
  48. h.logger.Debugw("Create new connection hub",
  49. "dc", req.ClientProtocol.DC(),
  50. "protocol", req.ClientProtocol.ConnectionProtocol())
  51. rv = newConnectionHub(h.logger.With(
  52. "dc", req.ClientProtocol.DC(),
  53. "protocol", req.ClientProtocol.ConnectionProtocol(),
  54. ))
  55. h.subs[key] = rv
  56. }
  57. }
  58. return rv
  59. }