command_status.go 2.1 KB

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