searcher_android.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package process
  2. import (
  3. "context"
  4. "encoding/xml"
  5. "io"
  6. "net/netip"
  7. "os"
  8. "strconv"
  9. "github.com/sagernet/sing-box/log"
  10. "github.com/sagernet/sing/common"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. "github.com/fsnotify/fsnotify"
  13. )
  14. var _ Searcher = (*androidSearcher)(nil)
  15. type androidSearcher struct {
  16. logger log.ContextLogger
  17. watcher *fsnotify.Watcher
  18. userMap map[string]int32
  19. packageMap map[int32]string
  20. sharedUserMap map[int32]string
  21. }
  22. func NewSearcher(logger log.ContextLogger) (Searcher, error) {
  23. return &androidSearcher{logger: logger}, nil
  24. }
  25. func (s *androidSearcher) Start() error {
  26. err := s.updatePackages()
  27. if err != nil {
  28. return E.Cause(err, "read packages list")
  29. }
  30. err = s.startWatcher()
  31. if err != nil {
  32. s.logger.Debug("create fsnotify watcher: ", err)
  33. }
  34. return nil
  35. }
  36. func (s *androidSearcher) startWatcher() error {
  37. watcher, err := fsnotify.NewWatcher()
  38. if err != nil {
  39. return err
  40. }
  41. err = watcher.Add("/data/system/packages.xml")
  42. if err != nil {
  43. return err
  44. }
  45. s.watcher = watcher
  46. go s.loopUpdate()
  47. return nil
  48. }
  49. func (s *androidSearcher) loopUpdate() {
  50. select {
  51. case _, ok := <-s.watcher.Events:
  52. if !ok {
  53. return
  54. }
  55. err := s.updatePackages()
  56. if err != nil {
  57. s.logger.Error(E.Cause(err, "update packages list"))
  58. }
  59. case err, ok := <-s.watcher.Errors:
  60. if !ok {
  61. return
  62. }
  63. s.logger.Error(E.Cause(err, "fsnotify error"))
  64. }
  65. }
  66. func (s *androidSearcher) Close() error {
  67. return common.Close(common.PtrOrNil(s.watcher))
  68. }
  69. func (s *androidSearcher) FindProcessInfo(ctx context.Context, network string, srcIP netip.Addr, srcPort int) (*Info, error) {
  70. _, uid, err := resolveSocketByNetlink(network, srcIP, srcPort)
  71. if err != nil {
  72. return nil, err
  73. }
  74. if sharedUser, loaded := s.sharedUserMap[uid]; loaded {
  75. return &Info{
  76. UserId: uid,
  77. PackageName: sharedUser,
  78. }, nil
  79. }
  80. if packageName, loaded := s.packageMap[uid]; loaded {
  81. return &Info{
  82. UserId: uid,
  83. PackageName: packageName,
  84. }, nil
  85. }
  86. return &Info{UserId: uid}, nil
  87. }
  88. func (s *androidSearcher) updatePackages() error {
  89. userMap := make(map[string]int32)
  90. packageMap := make(map[int32]string)
  91. sharedUserMap := make(map[int32]string)
  92. packagesData, err := os.Open("/data/system/packages.xml")
  93. if err != nil {
  94. return err
  95. }
  96. decoder := xml.NewDecoder(packagesData)
  97. var token xml.Token
  98. for {
  99. token, err = decoder.Token()
  100. if err == io.EOF {
  101. break
  102. } else if err != nil {
  103. return err
  104. }
  105. element, isStart := token.(xml.StartElement)
  106. if !isStart {
  107. continue
  108. }
  109. switch element.Name.Local {
  110. case "package":
  111. var name string
  112. var userID int64
  113. for _, attr := range element.Attr {
  114. switch attr.Name.Local {
  115. case "name":
  116. name = attr.Value
  117. case "userId", "sharedUserId":
  118. userID, err = strconv.ParseInt(attr.Value, 10, 32)
  119. if err != nil {
  120. return err
  121. }
  122. }
  123. }
  124. if userID == 0 && name == "" {
  125. continue
  126. }
  127. userMap[name] = int32(userID)
  128. packageMap[int32(userID)] = name
  129. case "shared-user":
  130. var name string
  131. var userID int64
  132. for _, attr := range element.Attr {
  133. switch attr.Name.Local {
  134. case "name":
  135. name = attr.Value
  136. case "userId":
  137. userID, err = strconv.ParseInt(attr.Value, 10, 32)
  138. if err != nil {
  139. return err
  140. }
  141. packageMap[int32(userID)] = name
  142. }
  143. }
  144. if userID == 0 && name == "" {
  145. continue
  146. }
  147. sharedUserMap[int32(userID)] = name
  148. }
  149. }
  150. s.logger.Info("updated packages list: ", len(packageMap), " packages, ", len(sharedUserMap), " shared users")
  151. s.userMap = userMap
  152. s.packageMap = packageMap
  153. s.sharedUserMap = sharedUserMap
  154. return nil
  155. }