sing-box/experimental/libbox/command_log.go

161 lines
3.1 KiB
Go
Raw Permalink Normal View History

2023-03-01 02:37:47 +00:00
package libbox
import (
2024-06-18 09:49:06 +00:00
"bufio"
2023-03-01 02:37:47 +00:00
"context"
"io"
"net"
2024-06-18 09:49:06 +00:00
"time"
"github.com/sagernet/sing/common/binary"
E "github.com/sagernet/sing/common/exceptions"
2024-06-24 01:49:15 +00:00
"github.com/sagernet/sing/common/varbin"
2023-03-01 02:37:47 +00:00
)
2024-06-24 01:49:15 +00:00
func (s *CommandServer) ResetLog() {
s.access.Lock()
defer s.access.Unlock()
s.savedLines.Init()
select {
case s.logReset <- struct{}{}:
default:
}
}
2023-03-01 02:37:47 +00:00
func (s *CommandServer) WriteMessage(message string) {
s.subscriber.Emit(message)
s.access.Lock()
s.savedLines.PushBack(message)
2023-07-02 08:45:30 +00:00
if s.savedLines.Len() > s.maxLines {
2023-03-01 02:37:47 +00:00
s.savedLines.Remove(s.savedLines.Front())
}
s.access.Unlock()
}
func (s *CommandServer) handleLogConn(conn net.Conn) error {
2024-06-18 09:49:06 +00:00
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
}
2023-03-01 02:37:47 +00:00
var savedLines []string
s.access.Lock()
savedLines = make([]string, 0, s.savedLines.Len())
for element := s.savedLines.Front(); element != nil; element = element.Next() {
savedLines = append(savedLines, element.Value)
}
s.access.Unlock()
subscription, done, err := s.observer.Subscribe()
if err != nil {
return err
}
defer s.observer.UnSubscribe(subscription)
2024-06-18 09:49:06 +00:00
writer := bufio.NewWriter(conn)
2024-06-24 01:49:15 +00:00
select {
case <-s.logReset:
err = writer.WriteByte(1)
if err != nil {
return err
}
err = writer.Flush()
if err != nil {
return err
}
default:
}
2024-06-18 09:49:06 +00:00
if len(savedLines) > 0 {
2024-06-24 01:49:15 +00:00
err = writer.WriteByte(0)
if err != nil {
return err
}
err = varbin.Write(writer, binary.BigEndian, savedLines)
2023-03-01 02:37:47 +00:00
if err != nil {
return err
}
}
ctx := connKeepAlive(conn)
2024-06-18 09:49:06 +00:00
var logLines []string
2023-03-01 02:37:47 +00:00
for {
2024-06-24 01:49:15 +00:00
err = writer.Flush()
if err != nil {
return err
}
2023-03-01 02:37:47 +00:00
select {
case <-ctx.Done():
2023-04-10 00:48:58 +00:00
return ctx.Err()
2023-10-02 14:27:48 +00:00
case <-s.logReset:
2024-06-24 01:49:15 +00:00
err = writer.WriteByte(1)
2023-10-02 14:27:48 +00:00
if err != nil {
return err
}
2023-03-01 02:37:47 +00:00
case <-done:
return nil
2024-06-18 09:49:06 +00:00
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
}
}
2024-06-24 01:49:15 +00:00
err = writer.WriteByte(0)
if err != nil {
return err
}
err = varbin.Write(writer, binary.BigEndian, logLines)
2024-06-18 09:49:06 +00:00
if err != nil {
return err
}
2023-03-01 02:37:47 +00:00
}
}
}
func (c *CommandClient) handleLogConn(conn net.Conn) {
2024-06-18 09:49:06 +00:00
reader := bufio.NewReader(conn)
2023-03-01 02:37:47 +00:00
for {
2024-06-24 01:49:15 +00:00
messageType, err := reader.ReadByte()
2023-03-01 02:37:47 +00:00
if err != nil {
c.handler.Disconnected(err.Error())
return
}
2024-06-18 09:49:06 +00:00
var messages []string
2023-10-02 14:27:48 +00:00
switch messageType {
case 0:
2024-06-24 01:49:15 +00:00
err = varbin.Read(reader, binary.BigEndian, &messages)
2023-10-02 14:27:48 +00:00
if err != nil {
c.handler.Disconnected(err.Error())
return
}
2024-06-18 09:49:06 +00:00
c.handler.WriteLogs(newIterator(messages))
2023-10-02 14:27:48 +00:00
case 1:
2024-06-18 09:49:06 +00:00
c.handler.ClearLogs()
2023-10-02 14:27:48 +00:00
}
2023-03-01 02:37:47 +00:00
}
}
func connKeepAlive(reader io.Reader) context.Context {
ctx, cancel := context.WithCancelCause(context.Background())
go func() {
for {
2024-06-18 09:49:06 +00:00
_, err := reader.Read(make([]byte, 1))
2023-03-01 02:37:47 +00:00
if err != nil {
cancel(err)
return
}
}
}()
return ctx
}