command_status.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package libbox
  2. import (
  3. "encoding/binary"
  4. "net"
  5. "runtime"
  6. "time"
  7. "github.com/sagernet/sing-box/experimental/clashapi"
  8. E "github.com/sagernet/sing/common/exceptions"
  9. "github.com/sagernet/sing/common/memory"
  10. )
  11. type StatusMessage struct {
  12. Memory int64
  13. Goroutines int32
  14. ConnectionsIn int32
  15. ConnectionsOut int32
  16. TrafficAvailable bool
  17. Uplink int64
  18. Downlink int64
  19. UplinkTotal int64
  20. DownlinkTotal int64
  21. }
  22. func (s *CommandServer) readStatus() StatusMessage {
  23. var message StatusMessage
  24. message.Memory = int64(memory.Inuse())
  25. message.Goroutines = int32(runtime.NumGoroutine())
  26. message.ConnectionsOut = int32(tracker.Count())
  27. if s.service != nil {
  28. message.TrafficAvailable = true
  29. trafficManager := s.service.clashServer.(*clashapi.Server).TrafficManager()
  30. message.UplinkTotal, message.DownlinkTotal = trafficManager.Total()
  31. message.ConnectionsIn = int32(trafficManager.ConnectionsLen())
  32. }
  33. return message
  34. }
  35. func (s *CommandServer) handleStatusConn(conn net.Conn) error {
  36. var interval int64
  37. err := binary.Read(conn, binary.BigEndian, &interval)
  38. if err != nil {
  39. return E.Cause(err, "read interval")
  40. }
  41. ticker := time.NewTicker(time.Duration(interval))
  42. defer ticker.Stop()
  43. ctx := connKeepAlive(conn)
  44. status := s.readStatus()
  45. uploadTotal := status.UplinkTotal
  46. downloadTotal := status.DownlinkTotal
  47. for {
  48. err = binary.Write(conn, binary.BigEndian, status)
  49. if err != nil {
  50. return err
  51. }
  52. select {
  53. case <-ctx.Done():
  54. return ctx.Err()
  55. case <-ticker.C:
  56. }
  57. status = s.readStatus()
  58. upload := status.UplinkTotal - uploadTotal
  59. download := status.DownlinkTotal - downloadTotal
  60. uploadTotal = status.UplinkTotal
  61. downloadTotal = status.DownlinkTotal
  62. status.Uplink = upload
  63. status.Downlink = download
  64. }
  65. }
  66. func (c *CommandClient) handleStatusConn(conn net.Conn) {
  67. for {
  68. var message StatusMessage
  69. err := binary.Read(conn, binary.BigEndian, &message)
  70. if err != nil {
  71. c.handler.Disconnected(err.Error())
  72. return
  73. }
  74. c.handler.WriteStatus(&message)
  75. }
  76. }