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.

stats_json.go 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package newstats
  2. import (
  3. "encoding/json"
  4. "net"
  5. "net/http"
  6. "sync/atomic"
  7. "time"
  8. "go.uber.org/zap"
  9. "github.com/9seconds/mtg/newprotocol"
  10. )
  11. type statsJSON struct {
  12. Connections statsJSONConnections `json:"connections"`
  13. Traffic statsJSONTraffic `json:"traffic"`
  14. Uptime statsJSONUptime `json:"uptime"`
  15. Crashes uint32 `json:"crashes"`
  16. AntiReplays uint32 `json:"anti_replay_detected"`
  17. }
  18. type statsBaseJSONConnections struct {
  19. All statsJSONConnectionType `json:"all"`
  20. Abridged statsJSONConnectionType `json:"abridged"`
  21. Intermediate statsJSONConnectionType `json:"intermediate"`
  22. Secured statsJSONConnectionType `json:"secured"`
  23. }
  24. type statsJSONConnections struct {
  25. statsBaseJSONConnections
  26. }
  27. type statsJSONConnectionType struct {
  28. IPv4 uint32 `json:"ipv4"`
  29. IPv6 uint32 `json:"ipv6"`
  30. }
  31. func (c statsJSONConnections) MarshalJSON() ([]byte, error) {
  32. c.All.IPv4 = c.Abridged.IPv4 + c.Intermediate.IPv4 + c.Secured.IPv4
  33. c.All.IPv6 = c.Abridged.IPv6 + c.Intermediate.IPv6 + c.Secured.IPv6
  34. return json.Marshal(c.statsBaseJSONConnections)
  35. }
  36. type statsJSONTraffic struct {
  37. Ingress uint64 `json:"ingress"`
  38. Egress uint64 `json:"egress"`
  39. }
  40. type statsJSONUptime time.Time
  41. func (s statsJSONUptime) MarshalJSON() ([]byte, error) {
  42. return json.Marshal(time.Since(time.Time(s)).Seconds())
  43. }
  44. func (s *statsJSON) IngressTraffic(traffic int) {
  45. atomic.AddUint64(&s.Traffic.Ingress, uint64(traffic))
  46. }
  47. func (s *statsJSON) EgressTraffic(traffic int) {
  48. atomic.AddUint64(&s.Traffic.Egress, uint64(traffic))
  49. }
  50. func (s *statsJSON) ClientConnected(connectionType newprotocol.ConnectionType, addr *net.TCPAddr) {
  51. s.changeConnections(connectionType, addr, 1)
  52. }
  53. func (s *statsJSON) ClientDisconnected(connectionType newprotocol.ConnectionType, addr *net.TCPAddr) {
  54. s.changeConnections(connectionType, addr, ^uint32(0))
  55. }
  56. func (s *statsJSON) changeConnections(connectionType newprotocol.ConnectionType, addr *net.TCPAddr, value uint32) {
  57. var connections *statsJSONConnectionType
  58. switch connectionType {
  59. case newprotocol.ConnectionTypeAbridged:
  60. connections = &s.Connections.Abridged
  61. case newprotocol.ConnectionTypeSecure:
  62. connections = &s.Connections.Secured
  63. default:
  64. connections = &s.Connections.Intermediate
  65. }
  66. if addr.IP.To4() == nil {
  67. atomic.AddUint32(&connections.IPv4, value)
  68. } else {
  69. atomic.AddUint32(&connections.IPv6, value)
  70. }
  71. }
  72. func (s *statsJSON) Crash() {
  73. atomic.AddUint32(&s.Crashes, 1)
  74. }
  75. func (s *statsJSON) AntiReplayDetected() {
  76. atomic.AddUint32(&s.AntiReplays, 1)
  77. }
  78. func newStatsJSON(mux *http.ServeMux) Stats {
  79. instance := &statsJSON{}
  80. logger := zap.S().Named("stats")
  81. mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
  82. w.Header().Set("Content-Type", "application/json")
  83. first, err := json.Marshal(instance)
  84. if err != nil {
  85. logger.Errorw("Cannot encode json", "error", err)
  86. http.Error(w, "Internal server error", http.StatusServiceUnavailable)
  87. return
  88. }
  89. interim := map[string]interface{}{}
  90. if err := json.Unmarshal(first, &interim); err != nil {
  91. panic(err)
  92. }
  93. encoder := json.NewEncoder(w)
  94. encoder.SetEscapeHTML(false)
  95. encoder.SetIndent("", " ")
  96. if err := encoder.Encode(interim); err != nil {
  97. logger.Errorw("Cannot encode json", "error", err)
  98. }
  99. })
  100. return instance
  101. }