command_status.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. //go:build darwin
  2. package libbox
  3. import (
  4. "encoding/binary"
  5. "net"
  6. "runtime"
  7. "time"
  8. "github.com/sagernet/sing-box/common/dialer/conntrack"
  9. E "github.com/sagernet/sing/common/exceptions"
  10. )
  11. type StatusMessage struct {
  12. Memory int64
  13. Goroutines int32
  14. Connections int32
  15. }
  16. func readStatus() StatusMessage {
  17. var memStats runtime.MemStats
  18. runtime.ReadMemStats(&memStats)
  19. var message StatusMessage
  20. message.Memory = int64(memStats.StackInuse + memStats.HeapInuse + memStats.HeapIdle - memStats.HeapReleased)
  21. message.Goroutines = int32(runtime.NumGoroutine())
  22. message.Connections = int32(conntrack.Count())
  23. return message
  24. }
  25. func (s *CommandServer) handleStatusConn(conn net.Conn) error {
  26. var interval int64
  27. err := binary.Read(conn, binary.BigEndian, &interval)
  28. if err != nil {
  29. return E.Cause(err, "read interval")
  30. }
  31. ticker := time.NewTicker(time.Duration(interval))
  32. defer ticker.Stop()
  33. ctx := connKeepAlive(conn)
  34. for {
  35. err = binary.Write(conn, binary.BigEndian, readStatus())
  36. if err != nil {
  37. return err
  38. }
  39. select {
  40. case <-ctx.Done():
  41. return nil
  42. case <-ticker.C:
  43. }
  44. }
  45. }
  46. func (c *CommandClient) handleStatusConn(conn net.Conn) {
  47. for {
  48. var message StatusMessage
  49. err := binary.Read(conn, binary.BigEndian, &message)
  50. if err != nil {
  51. c.handler.Disconnected(err.Error())
  52. return
  53. }
  54. c.handler.WriteStatus(&message)
  55. }
  56. }