command_status.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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. if clashServer := s.service.instance.Router().ClashServer(); clashServer != nil {
  30. message.TrafficAvailable = true
  31. trafficManager := clashServer.(*clashapi.Server).TrafficManager()
  32. message.Uplink, message.Downlink = trafficManager.Now()
  33. message.UplinkTotal, message.DownlinkTotal = trafficManager.Total()
  34. message.ConnectionsIn = int32(trafficManager.Connections())
  35. }
  36. }
  37. return message
  38. }
  39. func (s *CommandServer) handleStatusConn(conn net.Conn) error {
  40. var interval int64
  41. err := binary.Read(conn, binary.BigEndian, &interval)
  42. if err != nil {
  43. return E.Cause(err, "read interval")
  44. }
  45. ticker := time.NewTicker(time.Duration(interval))
  46. defer ticker.Stop()
  47. ctx := connKeepAlive(conn)
  48. for {
  49. err = binary.Write(conn, binary.BigEndian, s.readStatus())
  50. if err != nil {
  51. return err
  52. }
  53. select {
  54. case <-ctx.Done():
  55. return ctx.Err()
  56. case <-ticker.C:
  57. }
  58. }
  59. }
  60. func (c *CommandClient) handleStatusConn(conn net.Conn) {
  61. for {
  62. var message StatusMessage
  63. err := binary.Read(conn, binary.BigEndian, &message)
  64. if err != nil {
  65. c.handler.Disconnected(err.Error())
  66. return
  67. }
  68. c.handler.WriteStatus(&message)
  69. }
  70. }