log_server.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //go:build ios
  2. package libbox
  3. import (
  4. "encoding/binary"
  5. "io"
  6. "net"
  7. "os"
  8. "path/filepath"
  9. "sync"
  10. "github.com/sagernet/sing-box/log"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. "github.com/sagernet/sing/common/observable"
  13. "github.com/sagernet/sing/common/x/list"
  14. )
  15. type LogServer struct {
  16. sockPath string
  17. listener net.Listener
  18. access sync.Mutex
  19. savedLines *list.List[string]
  20. subscriber *observable.Subscriber[string]
  21. observer *observable.Observer[string]
  22. }
  23. func NewLogServer(sharedDirectory string) *LogServer {
  24. server := &LogServer{
  25. sockPath: filepath.Join(sharedDirectory, "log.sock"),
  26. savedLines: new(list.List[string]),
  27. subscriber: observable.NewSubscriber[string](128),
  28. }
  29. server.observer = observable.NewObserver[string](server.subscriber, 64)
  30. return server
  31. }
  32. func (s *LogServer) Start() error {
  33. os.Remove(s.sockPath)
  34. listener, err := net.ListenUnix("unix", &net.UnixAddr{
  35. Name: s.sockPath,
  36. Net: "unix",
  37. })
  38. if err != nil {
  39. return err
  40. }
  41. go s.loopConnection(listener)
  42. return nil
  43. }
  44. func (s *LogServer) Close() error {
  45. return s.listener.Close()
  46. }
  47. func (s *LogServer) WriteMessage(message string) {
  48. s.subscriber.Emit(message)
  49. s.access.Lock()
  50. s.savedLines.PushBack(message)
  51. if s.savedLines.Len() > 100 {
  52. s.savedLines.Remove(s.savedLines.Front())
  53. }
  54. s.access.Unlock()
  55. }
  56. func (s *LogServer) loopConnection(listener net.Listener) {
  57. for {
  58. conn, err := listener.Accept()
  59. if err != nil {
  60. return
  61. }
  62. go func() {
  63. hErr := s.handleConnection(&messageConn{conn})
  64. if hErr != nil && !E.IsClosed(err) {
  65. log.Warn("log-server: process connection: ", hErr)
  66. }
  67. }()
  68. }
  69. }
  70. func (s *LogServer) handleConnection(conn *messageConn) error {
  71. var savedLines []string
  72. s.access.Lock()
  73. savedLines = make([]string, 0, s.savedLines.Len())
  74. for element := s.savedLines.Front(); element != nil; element = element.Next() {
  75. savedLines = append(savedLines, element.Value)
  76. }
  77. s.access.Unlock()
  78. subscription, done, err := s.observer.Subscribe()
  79. if err != nil {
  80. return err
  81. }
  82. defer s.observer.UnSubscribe(subscription)
  83. for _, line := range savedLines {
  84. err = conn.Write([]byte(line))
  85. if err != nil {
  86. return err
  87. }
  88. }
  89. for {
  90. select {
  91. case message := <-subscription:
  92. err = conn.Write([]byte(message))
  93. if err != nil {
  94. return err
  95. }
  96. case <-done:
  97. conn.Close()
  98. return nil
  99. }
  100. }
  101. }
  102. type messageConn struct {
  103. net.Conn
  104. }
  105. func (c *messageConn) Read() ([]byte, error) {
  106. var messageLength uint16
  107. err := binary.Read(c.Conn, binary.BigEndian, &messageLength)
  108. if err != nil {
  109. return nil, err
  110. }
  111. data := make([]byte, messageLength)
  112. _, err = io.ReadFull(c.Conn, data)
  113. if err != nil {
  114. return nil, err
  115. }
  116. return data, nil
  117. }
  118. func (c *messageConn) Write(message []byte) error {
  119. err := binary.Write(c.Conn, binary.BigEndian, uint16(len(message)))
  120. if err != nil {
  121. return err
  122. }
  123. _, err = c.Conn.Write(message)
  124. return err
  125. }