mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-26 18:41:31 +00:00
platform: Add log update interval
This commit is contained in:
parent
25065d766a
commit
03f5d6e4f2
|
@ -25,8 +25,8 @@ type CommandClientOptions struct {
|
||||||
type CommandClientHandler interface {
|
type CommandClientHandler interface {
|
||||||
Connected()
|
Connected()
|
||||||
Disconnected(message string)
|
Disconnected(message string)
|
||||||
ClearLog()
|
ClearLogs()
|
||||||
WriteLog(message string)
|
WriteLogs(messageList StringIterator)
|
||||||
WriteStatus(message *StatusMessage)
|
WriteStatus(message *StatusMessage)
|
||||||
WriteGroups(message OutboundGroupIterator)
|
WriteGroups(message OutboundGroupIterator)
|
||||||
InitializeClashMode(modeList StringIterator, currentMode string)
|
InitializeClashMode(modeList StringIterator, currentMode string)
|
||||||
|
@ -84,6 +84,10 @@ func (c *CommandClient) Connect() error {
|
||||||
}
|
}
|
||||||
switch c.options.Command {
|
switch c.options.Command {
|
||||||
case CommandLog:
|
case CommandLog:
|
||||||
|
err = binary.Write(conn, binary.BigEndian, c.options.StatusInterval)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "write interval")
|
||||||
|
}
|
||||||
c.handler.Connected()
|
c.handler.Connected()
|
||||||
go c.handleLogConn(conn)
|
go c.handleLogConn(conn)
|
||||||
case CommandStatus:
|
case CommandStatus:
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package libbox
|
package libbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/binary"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *CommandServer) WriteMessage(message string) {
|
func (s *CommandServer) WriteMessage(message string) {
|
||||||
|
@ -17,43 +21,39 @@ func (s *CommandServer) WriteMessage(message string) {
|
||||||
s.access.Unlock()
|
s.access.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func readLog(reader io.Reader) ([]byte, error) {
|
func writeLog(writer *bufio.Writer, messages []string) error {
|
||||||
var messageLength uint16
|
|
||||||
err := binary.Read(reader, binary.BigEndian, &messageLength)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if messageLength == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
data := make([]byte, messageLength)
|
|
||||||
_, err = io.ReadFull(reader, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeLog(writer io.Writer, message []byte) error {
|
|
||||||
err := binary.Write(writer, binary.BigEndian, uint8(0))
|
err := binary.Write(writer, binary.BigEndian, uint8(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = binary.Write(writer, binary.BigEndian, uint16(len(message)))
|
err = binary.WriteData(writer, binary.BigEndian, messages)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(message) > 0 {
|
return writer.Flush()
|
||||||
_, err = writer.Write(message)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeClearLog(writer io.Writer) error {
|
func writeClearLog(writer *bufio.Writer) error {
|
||||||
return binary.Write(writer, binary.BigEndian, uint8(1))
|
err := binary.Write(writer, binary.BigEndian, uint8(1))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return writer.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleLogConn(conn net.Conn) error {
|
func (s *CommandServer) handleLogConn(conn net.Conn) error {
|
||||||
|
var (
|
||||||
|
interval int64
|
||||||
|
timer *time.Timer
|
||||||
|
)
|
||||||
|
err := binary.Read(conn, binary.BigEndian, &interval)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "read interval")
|
||||||
|
}
|
||||||
|
timer = time.NewTimer(time.Duration(interval))
|
||||||
|
if !timer.Stop() {
|
||||||
|
<-timer.C
|
||||||
|
}
|
||||||
var savedLines []string
|
var savedLines []string
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
savedLines = make([]string, 0, s.savedLines.Len())
|
savedLines = make([]string, 0, s.savedLines.Len())
|
||||||
|
@ -66,52 +66,67 @@ func (s *CommandServer) handleLogConn(conn net.Conn) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.observer.UnSubscribe(subscription)
|
defer s.observer.UnSubscribe(subscription)
|
||||||
for _, line := range savedLines {
|
writer := bufio.NewWriter(conn)
|
||||||
err = writeLog(conn, []byte(line))
|
if len(savedLines) > 0 {
|
||||||
|
err = writeLog(writer, savedLines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx := connKeepAlive(conn)
|
ctx := connKeepAlive(conn)
|
||||||
|
var logLines []string
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case message := <-subscription:
|
|
||||||
err = writeLog(conn, []byte(message))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case <-s.logReset:
|
case <-s.logReset:
|
||||||
err = writeClearLog(conn)
|
err = writeClearLog(writer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case <-done:
|
case <-done:
|
||||||
return nil
|
return nil
|
||||||
|
case logLine := <-subscription:
|
||||||
|
logLines = logLines[:0]
|
||||||
|
logLines = append(logLines, logLine)
|
||||||
|
timer.Reset(time.Duration(interval))
|
||||||
|
loopLogs:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case logLine = <-subscription:
|
||||||
|
logLines = append(logLines, logLine)
|
||||||
|
case <-timer.C:
|
||||||
|
break loopLogs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = writeLog(writer, logLines)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandClient) handleLogConn(conn net.Conn) {
|
func (c *CommandClient) handleLogConn(conn net.Conn) {
|
||||||
|
reader := bufio.NewReader(conn)
|
||||||
for {
|
for {
|
||||||
var messageType uint8
|
var messageType uint8
|
||||||
err := binary.Read(conn, binary.BigEndian, &messageType)
|
err := binary.Read(reader, binary.BigEndian, &messageType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.handler.Disconnected(err.Error())
|
c.handler.Disconnected(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var message []byte
|
var messages []string
|
||||||
switch messageType {
|
switch messageType {
|
||||||
case 0:
|
case 0:
|
||||||
message, err = readLog(conn)
|
err = binary.ReadData(reader, binary.BigEndian, &messages)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.handler.Disconnected(err.Error())
|
c.handler.Disconnected(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.handler.WriteLog(string(message))
|
c.handler.WriteLogs(newIterator(messages))
|
||||||
case 1:
|
case 1:
|
||||||
c.handler.ClearLog()
|
c.handler.ClearLogs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +135,7 @@ func connKeepAlive(reader io.Reader) context.Context {
|
||||||
ctx, cancel := context.WithCancelCause(context.Background())
|
ctx, cancel := context.WithCancelCause(context.Background())
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
_, err := readLog(reader)
|
_, err := reader.Read(make([]byte, 1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel(err)
|
cancel(err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -3,8 +3,9 @@ package libbox
|
||||||
import "github.com/sagernet/sing/common"
|
import "github.com/sagernet/sing/common"
|
||||||
|
|
||||||
type StringIterator interface {
|
type StringIterator interface {
|
||||||
Next() string
|
Len() int32
|
||||||
HasNext() bool
|
HasNext() bool
|
||||||
|
Next() string
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ StringIterator = (*iterator[string])(nil)
|
var _ StringIterator = (*iterator[string])(nil)
|
||||||
|
@ -21,6 +22,14 @@ func newPtrIterator[T any](values []T) *iterator[*T] {
|
||||||
return &iterator[*T]{common.Map(values, func(value T) *T { return &value })}
|
return &iterator[*T]{common.Map(values, func(value T) *T { return &value })}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *iterator[T]) Len() int32 {
|
||||||
|
return int32(len(i.values))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *iterator[T]) HasNext() bool {
|
||||||
|
return len(i.values) > 0
|
||||||
|
}
|
||||||
|
|
||||||
func (i *iterator[T]) Next() T {
|
func (i *iterator[T]) Next() T {
|
||||||
if len(i.values) == 0 {
|
if len(i.values) == 0 {
|
||||||
return common.DefaultValue[T]()
|
return common.DefaultValue[T]()
|
||||||
|
@ -30,10 +39,6 @@ func (i *iterator[T]) Next() T {
|
||||||
return nextValue
|
return nextValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *iterator[T]) HasNext() bool {
|
|
||||||
return len(i.values) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type abstractIterator[T any] interface {
|
type abstractIterator[T any] interface {
|
||||||
Next() T
|
Next() T
|
||||||
HasNext() bool
|
HasNext() bool
|
||||||
|
|
Loading…
Reference in a new issue