2023-03-01 02:37:47 +00:00
|
|
|
package libbox
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"net"
|
|
|
|
"runtime"
|
|
|
|
"time"
|
|
|
|
|
2023-09-20 06:12:08 +00:00
|
|
|
"github.com/sagernet/sing-box/common/conntrack"
|
2023-07-16 06:08:45 +00:00
|
|
|
"github.com/sagernet/sing-box/experimental/clashapi"
|
2023-03-01 02:37:47 +00:00
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
2023-09-20 06:12:08 +00:00
|
|
|
"github.com/sagernet/sing/common/memory"
|
2023-03-01 02:37:47 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type StatusMessage struct {
|
2023-07-16 06:08:45 +00:00
|
|
|
Memory int64
|
|
|
|
Goroutines int32
|
|
|
|
ConnectionsIn int32
|
|
|
|
ConnectionsOut int32
|
|
|
|
TrafficAvailable bool
|
|
|
|
Uplink int64
|
|
|
|
Downlink int64
|
|
|
|
UplinkTotal int64
|
|
|
|
DownlinkTotal int64
|
2023-03-01 02:37:47 +00:00
|
|
|
}
|
|
|
|
|
2023-07-16 06:08:45 +00:00
|
|
|
func (s *CommandServer) readStatus() StatusMessage {
|
2023-03-01 02:37:47 +00:00
|
|
|
var message StatusMessage
|
2023-09-20 06:12:08 +00:00
|
|
|
message.Memory = int64(memory.Inuse())
|
2023-03-01 02:37:47 +00:00
|
|
|
message.Goroutines = int32(runtime.NumGoroutine())
|
2023-07-16 06:08:45 +00:00
|
|
|
message.ConnectionsOut = int32(conntrack.Count())
|
|
|
|
|
|
|
|
if s.service != nil {
|
|
|
|
if clashServer := s.service.instance.Router().ClashServer(); clashServer != nil {
|
|
|
|
message.TrafficAvailable = true
|
|
|
|
trafficManager := clashServer.(*clashapi.Server).TrafficManager()
|
|
|
|
message.Uplink, message.Downlink = trafficManager.Now()
|
|
|
|
message.UplinkTotal, message.DownlinkTotal = trafficManager.Total()
|
|
|
|
message.ConnectionsIn = int32(trafficManager.Connections())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-01 02:37:47 +00:00
|
|
|
return message
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *CommandServer) handleStatusConn(conn net.Conn) error {
|
|
|
|
var interval int64
|
|
|
|
err := binary.Read(conn, binary.BigEndian, &interval)
|
|
|
|
if err != nil {
|
|
|
|
return E.Cause(err, "read interval")
|
|
|
|
}
|
|
|
|
ticker := time.NewTicker(time.Duration(interval))
|
|
|
|
defer ticker.Stop()
|
|
|
|
ctx := connKeepAlive(conn)
|
|
|
|
for {
|
2023-07-16 06:08:45 +00:00
|
|
|
err = binary.Write(conn, binary.BigEndian, s.readStatus())
|
2023-03-01 02:37:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
2023-04-10 00:48:58 +00:00
|
|
|
return ctx.Err()
|
2023-03-01 02:37:47 +00:00
|
|
|
case <-ticker.C:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CommandClient) handleStatusConn(conn net.Conn) {
|
|
|
|
for {
|
|
|
|
var message StatusMessage
|
|
|
|
err := binary.Read(conn, binary.BigEndian, &message)
|
|
|
|
if err != nil {
|
|
|
|
c.handler.Disconnected(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
c.handler.WriteStatus(&message)
|
|
|
|
}
|
|
|
|
}
|