logic.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. package logic
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strings"
  6. C "github.com/metacubex/mihomo/constant"
  7. "github.com/metacubex/mihomo/rules/common"
  8. list "github.com/bahlo/generic-list-go"
  9. )
  10. type Logic struct {
  11. *common.Base
  12. payload string
  13. adapter string
  14. ruleType C.RuleType
  15. rules []C.Rule
  16. subRules map[string][]C.Rule
  17. needIP bool
  18. needProcess bool
  19. }
  20. type ParseRuleFunc func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (C.Rule, error)
  21. func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule ParseRuleFunc) (*Logic, error) {
  22. logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.SubRules}
  23. err := logic.parsePayload(fmt.Sprintf("(%s)", payload), parseRule)
  24. if err != nil {
  25. return nil, err
  26. }
  27. if len(logic.rules) != 1 {
  28. return nil, fmt.Errorf("Sub-Rule rule must contain one rule")
  29. }
  30. for _, rule := range subRules[adapter] {
  31. if rule.ShouldResolveIP() {
  32. logic.needIP = true
  33. }
  34. if rule.ShouldFindProcess() {
  35. logic.needProcess = true
  36. }
  37. }
  38. logic.subRules = subRules
  39. return logic, nil
  40. }
  41. func NewNOT(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
  42. logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.NOT}
  43. err := logic.parsePayload(payload, parseRule)
  44. if err != nil {
  45. return nil, err
  46. }
  47. if len(logic.rules) != 1 {
  48. return nil, fmt.Errorf("not rule must contain one rule")
  49. }
  50. logic.needIP = logic.rules[0].ShouldResolveIP()
  51. logic.needProcess = logic.rules[0].ShouldFindProcess()
  52. logic.payload = fmt.Sprintf("(!(%s,%s))", logic.rules[0].RuleType(), logic.rules[0].Payload())
  53. return logic, nil
  54. }
  55. func NewOR(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
  56. logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.OR}
  57. err := logic.parsePayload(payload, parseRule)
  58. if err != nil {
  59. return nil, err
  60. }
  61. payloads := make([]string, 0, len(logic.rules))
  62. for _, rule := range logic.rules {
  63. payloads = append(payloads, fmt.Sprintf("(%s,%s)", rule.RuleType().String(), rule.Payload()))
  64. if rule.ShouldResolveIP() {
  65. logic.needIP = true
  66. }
  67. if rule.ShouldFindProcess() {
  68. logic.needProcess = true
  69. }
  70. }
  71. logic.payload = fmt.Sprintf("(%s)", strings.Join(payloads, " || "))
  72. return logic, nil
  73. }
  74. func NewAND(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
  75. logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.AND}
  76. err := logic.parsePayload(payload, parseRule)
  77. if err != nil {
  78. return nil, err
  79. }
  80. payloads := make([]string, 0, len(logic.rules))
  81. for _, rule := range logic.rules {
  82. payloads = append(payloads, fmt.Sprintf("(%s,%s)", rule.RuleType().String(), rule.Payload()))
  83. if rule.ShouldResolveIP() {
  84. logic.needIP = true
  85. }
  86. if rule.ShouldFindProcess() {
  87. logic.needProcess = true
  88. }
  89. }
  90. logic.payload = fmt.Sprintf("(%s)", strings.Join(payloads, " && "))
  91. return logic, nil
  92. }
  93. type Range struct {
  94. start int
  95. end int
  96. index int
  97. }
  98. func (r Range) containRange(preStart, preEnd int) bool {
  99. return preStart < r.start && preEnd > r.end
  100. }
  101. func (logic *Logic) payloadToRule(subPayload string, parseRule ParseRuleFunc) (C.Rule, error) {
  102. splitStr := strings.SplitN(subPayload, ",", 2)
  103. if len(splitStr) < 2 {
  104. return nil, fmt.Errorf("[%s] format is error", subPayload)
  105. }
  106. tp := splitStr[0]
  107. payload := splitStr[1]
  108. switch tp {
  109. case "MATCH", "SUB-RULE":
  110. return nil, fmt.Errorf("unsupported rule type [%s] on logic rule", tp)
  111. case "NOT", "OR", "AND":
  112. return parseRule(tp, payload, "", nil, nil)
  113. }
  114. param := strings.Split(payload, ",")
  115. return parseRule(tp, param[0], "", param[1:], nil)
  116. }
  117. func (logic *Logic) format(payload string) ([]Range, error) {
  118. stack := list.New[Range]()
  119. num := 0
  120. subRanges := make([]Range, 0)
  121. for i, c := range payload {
  122. if c == '(' {
  123. sr := Range{
  124. start: i,
  125. index: num,
  126. }
  127. num++
  128. stack.PushBack(sr)
  129. } else if c == ')' {
  130. if stack.Len() == 0 {
  131. return nil, fmt.Errorf("missing '('")
  132. }
  133. sr := stack.Back()
  134. stack.Remove(sr)
  135. sr.Value.end = i
  136. subRanges = append(subRanges, sr.Value)
  137. }
  138. }
  139. if stack.Len() != 0 {
  140. return nil, fmt.Errorf("format error is missing )")
  141. }
  142. sortResult := make([]Range, len(subRanges))
  143. for _, sr := range subRanges {
  144. sortResult[sr.index] = sr
  145. }
  146. return sortResult, nil
  147. }
  148. func (logic *Logic) findSubRuleRange(payload string, ruleRanges []Range) []Range {
  149. payloadLen := len(payload)
  150. subRuleRange := make([]Range, 0)
  151. for _, rr := range ruleRanges {
  152. if rr.start == 0 && rr.end == payloadLen-1 {
  153. // 最大范围跳过
  154. continue
  155. }
  156. containInSub := false
  157. for _, r := range subRuleRange {
  158. if rr.containRange(r.start, r.end) {
  159. // The subRuleRange contains a range of rr, which is the next level node of the tree
  160. containInSub = true
  161. break
  162. }
  163. }
  164. if !containInSub {
  165. subRuleRange = append(subRuleRange, rr)
  166. }
  167. }
  168. return subRuleRange
  169. }
  170. func (logic *Logic) parsePayload(payload string, parseRule ParseRuleFunc) error {
  171. regex, err := regexp.Compile("\\(.*\\)")
  172. if err != nil {
  173. return err
  174. }
  175. if regex.MatchString(payload) {
  176. subAllRanges, err := logic.format(payload)
  177. if err != nil {
  178. return err
  179. }
  180. rules := make([]C.Rule, 0, len(subAllRanges))
  181. subRanges := logic.findSubRuleRange(payload, subAllRanges)
  182. for _, subRange := range subRanges {
  183. subPayload := payload[subRange.start+1 : subRange.end]
  184. rule, err := logic.payloadToRule(subPayload, parseRule)
  185. if err != nil {
  186. return err
  187. }
  188. if rule.ShouldResolveIP() {
  189. logic.needIP = true
  190. }
  191. if rule.ShouldFindProcess() {
  192. logic.needProcess = true
  193. }
  194. rules = append(rules, rule)
  195. }
  196. logic.rules = rules
  197. return nil
  198. }
  199. return fmt.Errorf("payload format error")
  200. }
  201. func (logic *Logic) RuleType() C.RuleType {
  202. return logic.ruleType
  203. }
  204. func matchSubRules(metadata *C.Metadata, name string, subRules map[string][]C.Rule) (bool, string) {
  205. for _, rule := range subRules[name] {
  206. if m, a := rule.Match(metadata); m {
  207. if rule.RuleType() == C.SubRules {
  208. return matchSubRules(metadata, rule.Adapter(), subRules)
  209. } else {
  210. return m, a
  211. }
  212. }
  213. }
  214. return false, ""
  215. }
  216. func (logic *Logic) Match(metadata *C.Metadata) (bool, string) {
  217. switch logic.ruleType {
  218. case C.SubRules:
  219. if m, _ := logic.rules[0].Match(metadata); m {
  220. return matchSubRules(metadata, logic.adapter, logic.subRules)
  221. }
  222. return false, ""
  223. case C.NOT:
  224. if m, _ := logic.rules[0].Match(metadata); !m {
  225. return true, logic.adapter
  226. }
  227. return false, ""
  228. case C.OR:
  229. for _, rule := range logic.rules {
  230. if m, _ := rule.Match(metadata); m {
  231. return true, logic.adapter
  232. }
  233. }
  234. return false, ""
  235. case C.AND:
  236. for _, rule := range logic.rules {
  237. if m, _ := rule.Match(metadata); !m {
  238. return false, logic.adapter
  239. }
  240. }
  241. return true, logic.adapter
  242. }
  243. return false, ""
  244. }
  245. func (logic *Logic) Adapter() string {
  246. return logic.adapter
  247. }
  248. func (logic *Logic) Payload() string {
  249. return logic.payload
  250. }
  251. func (logic *Logic) ShouldResolveIP() bool {
  252. return logic.needIP
  253. }
  254. func (logic *Logic) ShouldFindProcess() bool {
  255. return logic.needProcess
  256. }
  257. func (logic *Logic) ProviderNames() (names []string) {
  258. for _, rule := range logic.rules {
  259. names = append(names, rule.ProviderNames()...)
  260. }
  261. return
  262. }