github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/experimental/libbox/command_status.go (about)

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