diff --git a/experimental/libbox/command_client.go b/experimental/libbox/command_client.go index 9701d949..f3c9ad2a 100644 --- a/experimental/libbox/command_client.go +++ b/experimental/libbox/command_client.go @@ -25,6 +25,7 @@ type CommandClientOptions struct { type CommandClientHandler interface { Connected() Disconnected(message string) + ClearLog() WriteLog(message string) WriteStatus(message *StatusMessage) WriteGroups(message OutboundGroupIterator) diff --git a/experimental/libbox/command_log.go b/experimental/libbox/command_log.go index 7cb1696b..ce72010d 100644 --- a/experimental/libbox/command_log.go +++ b/experimental/libbox/command_log.go @@ -23,6 +23,9 @@ func readLog(reader io.Reader) ([]byte, error) { if err != nil { return nil, err } + if messageLength == 0 { + return nil, nil + } data := make([]byte, messageLength) _, err = io.ReadFull(reader, data) if err != nil { @@ -32,14 +35,24 @@ func readLog(reader io.Reader) ([]byte, error) { } func writeLog(writer io.Writer, message []byte) error { - err := binary.Write(writer, binary.BigEndian, uint16(len(message))) + err := binary.Write(writer, binary.BigEndian, uint8(0)) if err != nil { return err } - _, err = writer.Write(message) + err = binary.Write(writer, binary.BigEndian, uint16(len(message))) + if err != nil { + return err + } + if len(message) > 0 { + _, err = writer.Write(message) + } return err } +func writeClearLog(writer io.Writer) error { + return binary.Write(writer, binary.BigEndian, uint8(1)) +} + func (s *CommandServer) handleLogConn(conn net.Conn) error { var savedLines []string s.access.Lock() @@ -69,6 +82,11 @@ func (s *CommandServer) handleLogConn(conn net.Conn) error { if err != nil { return err } + case <-s.logReset: + err = writeClearLog(conn) + if err != nil { + return err + } case <-done: return nil } @@ -77,12 +95,24 @@ func (s *CommandServer) handleLogConn(conn net.Conn) error { func (c *CommandClient) handleLogConn(conn net.Conn) { for { - message, err := readLog(conn) + var messageType uint8 + err := binary.Read(conn, binary.BigEndian, &messageType) if err != nil { c.handler.Disconnected(err.Error()) return } - c.handler.WriteLog(string(message)) + var message []byte + switch messageType { + case 0: + message, err = readLog(conn) + if err != nil { + c.handler.Disconnected(err.Error()) + return + } + c.handler.WriteLog(string(message)) + case 1: + c.handler.ClearLog() + } } } diff --git a/experimental/libbox/command_server.go b/experimental/libbox/command_server.go index 19f98870..f5aabb4a 100644 --- a/experimental/libbox/command_server.go +++ b/experimental/libbox/command_server.go @@ -23,14 +23,16 @@ type CommandServer struct { handler CommandServerHandler access sync.Mutex - savedLines *list.List[string] + savedLines list.List[string] maxLines int subscriber *observable.Subscriber[string] observer *observable.Observer[string] service *BoxService + // These channels only work with a single client. if multi-client support is needed, replace with Subscriber/Observer urlTestUpdate chan struct{} modeUpdate chan struct{} + logReset chan struct{} } type CommandServerHandler interface { @@ -42,11 +44,11 @@ type CommandServerHandler interface { func NewCommandServer(handler CommandServerHandler, maxLines int32) *CommandServer { server := &CommandServer{ handler: handler, - savedLines: new(list.List[string]), maxLines: int(maxLines), subscriber: observable.NewSubscriber[string](128), urlTestUpdate: make(chan struct{}, 1), modeUpdate: make(chan struct{}, 1), + logReset: make(chan struct{}, 1), } server.observer = observable.NewObserver[string](server.subscriber, 64) return server @@ -56,6 +58,11 @@ func (s *CommandServer) SetService(newService *BoxService) { if newService != nil { service.PtrFromContext[urltest.HistoryStorage](newService.ctx).SetHook(s.urlTestUpdate) newService.instance.Router().ClashServer().(*clashapi.Server).SetModeUpdateHook(s.modeUpdate) + s.savedLines.Init() + select { + case s.logReset <- struct{}{}: + default: + } } s.service = newService s.notifyURLTestUpdate()