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.UplinkTotal, message.DownlinkTotal = trafficManager.Total()
|
2024-06-11 13:16:33 +00:00
|
|
|
message.ConnectionsIn = int32(trafficManager.ConnectionsLen())
|
2023-07-16 06:08:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-01 02:37:47 +00:00
|
|
|
return message
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *CommandServer) handleStatusConn(conn net.Conn) error {
|
|
|
|
var interval int64
|
2024-11-05 12:03:39 +00:00
|
|
|
err := binary.Read(conn, binary.BigEndian, &interval)
|
2023-03-01 02:37:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return E.Cause(err, "read interval")
|
|
|
|
}
|
|
|
|
ticker := time.NewTicker(time.Duration(interval))
|
|
|
|
defer ticker.Stop()
|
|
|
|
ctx := connKeepAlive(conn)
|
2024-11-27 10:05:30 +00:00
|
|
|
var (
|
|
|
|
status StatusMessage
|
|
|
|
uploadTotal int64
|
|
|
|
downloadTotal int64
|
|
|
|
)
|
2024-11-05 12:03:39 +00:00
|
|
|
for {
|
2024-11-27 10:05:30 +00:00
|
|
|
status = s.readStatus()
|
|
|
|
upload := status.UplinkTotal - uploadTotal
|
|
|
|
download := status.DownlinkTotal - downloadTotal
|
|
|
|
uploadTotal = status.UplinkTotal
|
|
|
|
downloadTotal = status.DownlinkTotal
|
|
|
|
status.Uplink = upload
|
|
|
|
status.Downlink = download
|
|
|
|
err = binary.Write(conn, binary.BigEndian, status)
|
2024-11-05 12:03:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2023-03-01 02:37:47 +00:00
|
|
|
}
|
2024-11-05 12:03:39 +00:00
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return ctx.Err()
|
|
|
|
case <-ticker.C:
|
2023-03-01 02:37:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CommandClient) handleStatusConn(conn net.Conn) {
|
|
|
|
for {
|
|
|
|
var message StatusMessage
|
2024-11-05 12:03:39 +00:00
|
|
|
err := binary.Read(conn, binary.BigEndian, &message)
|
2023-03-01 02:37:47 +00:00
|
|
|
if err != nil {
|
|
|
|
c.handler.Disconnected(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
c.handler.WriteStatus(&message)
|
|
|
|
}
|
|
|
|
}
|