Skip to content

Commit be0263c

Browse files
committed
use NewFileReader
1 parent 490f39e commit be0263c

5 files changed

Lines changed: 65 additions & 127 deletions

File tree

app/router/condition_serialize_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func TestGeoSiteSerialization(t *testing.T) {
9191
data, _ := filesystem.ReadFile(path)
9292

9393
// cn
94-
gp, err := router.LoadGeoSiteMatcher(data, "CN")
94+
gp, err := router.LoadGeoSiteMatcher(bytes.NewReader(data), "CN")
9595
if err != nil {
9696
t.Fatalf("LoadGeoSiteMatcher(CN) failed: %v", err)
9797
}
@@ -108,7 +108,7 @@ func TestGeoSiteSerialization(t *testing.T) {
108108
}
109109

110110
// us
111-
gp, err = router.LoadGeoSiteMatcher(data, "US")
111+
gp, err = router.LoadGeoSiteMatcher(bytes.NewReader(data), "US")
112112
if err != nil {
113113
t.Fatalf("LoadGeoSiteMatcher(US) failed: %v", err)
114114
}
@@ -124,7 +124,7 @@ func TestGeoSiteSerialization(t *testing.T) {
124124
}
125125

126126
// unknown
127-
_, err = router.LoadGeoSiteMatcher(data, "unknown")
127+
_, err = router.LoadGeoSiteMatcher(bytes.NewReader(data), "unknown")
128128
if err == nil {
129129
t.Error("LoadGeoSiteMatcher(unknown) should fail")
130130
}

app/router/condition_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ func TestRoutingRule(t *testing.T) {
288288
}
289289

290290
for _, test := range cases {
291-
cond, err := test.rule.BuildCondition()
291+
cond, err := test.rule.BuildCondition("")
292292
common.Must(err)
293293

294294
for _, subtest := range test.test {

app/router/config.go

Lines changed: 4 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/xtls/xray-core/common/platform/filesystem"
1111
"github.com/xtls/xray-core/features/outbound"
1212
"github.com/xtls/xray-core/features/routing"
13-
"google.golang.org/protobuf/proto"
1413
)
1514

1615
type Rule struct {
@@ -109,16 +108,6 @@ func (rr *RoutingRule) BuildCondition(domainMatcherPath string) (Condition, erro
109108
if len(rr.Domain) > 0 {
110109
var matcher *DomainMatcher
111110
var err error
112-
113-
domains := rr.Domain
114-
if runtime.GOOS != "windows" && runtime.GOOS != "wasm" && domainMatcherPath == "" {
115-
var err error
116-
domains, err = GetDomainList(rr.Domain)
117-
if err != nil {
118-
return nil, errors.New("failed to build domains from mmap").Base(err)
119-
}
120-
}
121-
122111
if domainMatcherPath != "" {
123112
matcher, err = GetDomainMathcerWithRuleTag(domainMatcherPath, rr.RuleTag)
124113
if err != nil {
@@ -196,89 +185,14 @@ func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatch
196185
}
197186
}
198187

199-
func GetGeoIPList(ips []*GeoIP) ([]*GeoIP, error) {
200-
geoipList := []*GeoIP{}
201-
for _, ip := range ips {
202-
if ip.CountryCode != "" {
203-
val := strings.Split(ip.CountryCode, "_")
204-
fileName := "geoip.dat"
205-
if len(val) == 2 {
206-
fileName = strings.ToLower(val[0])
207-
}
208-
bs, err := filesystem.ReadAsset(fileName)
209-
if err != nil {
210-
return nil, errors.New("failed to load file: ", fileName).Base(err)
211-
}
212-
bs = filesystem.Find(bs, []byte(ip.CountryCode))
213-
214-
var geoip GeoIP
215-
216-
if err := proto.Unmarshal(bs, &geoip); err != nil {
217-
return nil, errors.New("failed Unmarshal :").Base(err)
218-
}
219-
geoipList = append(geoipList, &geoip)
220-
221-
} else {
222-
geoipList = append(geoipList, ip)
223-
}
224-
}
225-
return geoipList, nil
226-
227-
}
228-
229-
func GetDomainList(domains []*Domain) ([]*Domain, error) {
230-
domainList := []*Domain{}
231-
for _, domain := range domains {
232-
val := strings.Split(domain.Value, "_")
233-
234-
if len(val) >= 2 {
235-
236-
fileName := val[0]
237-
code := val[1]
238-
239-
bs, err := filesystem.ReadAsset(fileName)
240-
if err != nil {
241-
return nil, errors.New("failed to load file: ", fileName).Base(err)
242-
}
243-
bs = filesystem.Find(bs, []byte(code))
244-
var geosite GeoSite
245-
246-
if err := proto.Unmarshal(bs, &geosite); err != nil {
247-
return nil, errors.New("failed Unmarshal :").Base(err)
248-
}
249-
250-
// parse attr
251-
if len(val) == 3 {
252-
siteWithAttr := strings.Split(val[2], ",")
253-
attrs := ParseAttrs(siteWithAttr)
254-
255-
if !attrs.IsEmpty() {
256-
filteredDomains := make([]*Domain, 0, len(domains))
257-
for _, domain := range geosite.Domain {
258-
if attrs.Match(domain) {
259-
filteredDomains = append(filteredDomains, domain)
260-
}
261-
}
262-
geosite.Domain = filteredDomains
263-
}
264-
265-
}
266-
267-
domainList = append(domainList, geosite.Domain...)
268-
269-
} else {
270-
domainList = append(domainList, domain)
271-
}
272-
}
273-
return domainList, nil
274-
}
275-
276188
func GetDomainMathcerWithRuleTag(domainMatcherPath string, ruleTag string) (*DomainMatcher, error) {
277-
bs, err := filesystem.ReadFile(domainMatcherPath)
189+
f, err := filesystem.NewFileReader(domainMatcherPath)
278190
if err != nil {
279191
return nil, errors.New("failed to load file: ", domainMatcherPath).Base(err)
280192
}
281-
g, err := LoadGeoSiteMatcher(bs, ruleTag)
193+
defer f.Close()
194+
195+
g, err := LoadGeoSiteMatcher(f, ruleTag)
282196
if err != nil {
283197
return nil, errors.New("failed to load file:", domainMatcherPath).Base(err)
284198
}

app/router/geosite_compact.go

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package router
22

33
import (
4+
"bufio"
45
"bytes"
56
"encoding/binary"
67
"errors"
@@ -80,47 +81,68 @@ func SerializeGeoSiteList(sites []*GeoSite, w io.Writer) error {
8081
return nil
8182
}
8283

83-
func LoadGeoSiteMatcher(data []byte, countryCode string) (*strmatcher.MphMatcherGroup, error) {
84-
if len(data) < 4 {
85-
return nil, errors.New("invalid data length")
84+
func LoadGeoSiteMatcher(r io.Reader, countryCode string) (*strmatcher.MphMatcherGroup, error) {
85+
br := bufio.NewReaderSize(r, 64*1024)
86+
var count uint32
87+
if err := binary.Read(br, binary.LittleEndian, &count); err != nil {
88+
return nil, err
8689
}
8790

88-
count := binary.LittleEndian.Uint32(data[0:4])
89-
90-
offset := 4
9191
targetBytes := []byte(countryCode)
92+
var dataOffset, dataSize uint64
93+
var found bool
9294

93-
for range count {
94-
if offset >= len(data) {
95-
return nil, errors.New("index truncated")
96-
}
95+
bytesRead := uint64(4)
9796

98-
codeLen := int(data[offset])
99-
offset++
97+
for i := uint32(0); i < count; i++ {
98+
codeLen, err := br.ReadByte()
99+
if err != nil {
100+
return nil, err
101+
}
102+
bytesRead++
100103

101-
if offset+codeLen > len(data) {
102-
return nil, errors.New("index code truncated")
104+
code := make([]byte, int(codeLen))
105+
if _, err := io.ReadFull(br, code); err != nil {
106+
return nil, err
103107
}
108+
bytesRead += uint64(codeLen)
104109

105-
code := data[offset : offset+codeLen]
106-
offset += codeLen
110+
var offsetValue, sizeValue uint64
111+
if err := binary.Read(br, binary.LittleEndian, &offsetValue); err != nil {
112+
return nil, err
113+
}
114+
bytesRead += 8
115+
if err := binary.Read(br, binary.LittleEndian, &sizeValue); err != nil {
116+
return nil, err
117+
}
118+
bytesRead += 8
107119

108-
if offset+16 > len(data) {
109-
return nil, errors.New("index meta truncated")
120+
if bytes.Equal(code, targetBytes) {
121+
dataOffset = offsetValue
122+
dataSize = sizeValue
123+
found = true
110124
}
125+
}
111126

112-
dataOffset := binary.LittleEndian.Uint64(data[offset : offset+8])
113-
dataSize := binary.LittleEndian.Uint64(data[offset+8 : offset+16])
114-
offset += 16
127+
if !found {
128+
return nil, errors.New("country code not found")
129+
}
115130

116-
// match?
117-
if bytes.Equal(code, targetBytes) {
118-
if dataOffset+dataSize > uint64(len(data)) {
119-
return nil, errors.New("data truncated")
120-
}
121-
return NewDomainMatcherFromBuffer(data[dataOffset : dataOffset+dataSize])
131+
if dataOffset < bytesRead {
132+
return nil, errors.New("invalid data offset")
133+
}
134+
135+
toSkip := dataOffset - bytesRead
136+
if toSkip > 0 {
137+
if _, err := io.CopyN(io.Discard, br, int64(toSkip)); err != nil {
138+
return nil, err
122139
}
123140
}
124141

125-
return nil, errors.New("country code not found")
142+
data := make([]byte, dataSize)
143+
if _, err := io.ReadFull(br, data); err != nil {
144+
return nil, err
145+
}
146+
147+
return NewDomainMatcherFromBuffer(data)
126148
}

infra/conf/router.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,12 @@ func loadIP(file, code string) ([]*router.CIDR, error) {
217217
}
218218

219219
func loadSite(file, code string) ([]*router.Domain, error) {
220+
221+
// TODO
222+
// if os.Getenv("XRAY_CACHED_MATCHER") == "1" {
223+
// return []*router.Domain{&router.Domain{}}, nil
224+
// }
225+
220226
bs, err := loadFile(file, code)
221227
if err != nil {
222228
return nil, err
@@ -690,12 +696,8 @@ func (c *RouterConfig) BuildDomainMatcherCache() error {
690696
}
691697

692698
for _, rule := range routerConfig.Rule {
693-
domains, err := router.GetDomainList(rule.Domain)
694-
if err != nil {
695-
return errors.New("failed to build domains from mmap").Base(err)
696-
}
697699
// write it with ruleTag key
698-
simpleGeoSite := router.GeoSite{CountryCode: rule.RuleTag, Domain: domains}
700+
simpleGeoSite := router.GeoSite{CountryCode: rule.RuleTag, Domain: rule.Domain}
699701

700702
geosite = append(geosite, &simpleGeoSite)
701703
}

0 commit comments

Comments
 (0)