command_status.go 1.9 KB

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