| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- package router
- import (
- "encoding/gob"
- "errors"
- "io"
- "runtime"
- "github.com/xtls/xray-core/common/strmatcher"
- )
- type geoSiteListGob struct {
- Sites map[string][]byte
- Deps map[string][]string
- Hosts map[string][]string
- }
- func SerializeGeoSiteList(sites []*GeoSite, deps map[string][]string, hosts map[string][]string, w io.Writer) error {
- data := geoSiteListGob{
- Sites: make(map[string][]byte),
- Deps: deps,
- Hosts: hosts,
- }
- for _, site := range sites {
- if site == nil {
- continue
- }
- var buf bytesWriter
- if err := SerializeDomainMatcher(site.Domain, &buf); err != nil {
- return err
- }
- data.Sites[site.CountryCode] = buf.Bytes()
- }
- return gob.NewEncoder(w).Encode(data)
- }
- type bytesWriter struct {
- data []byte
- }
- func (w *bytesWriter) Write(p []byte) (n int, err error) {
- w.data = append(w.data, p...)
- return len(p), nil
- }
- func (w *bytesWriter) Bytes() []byte {
- return w.data
- }
- func LoadGeoSiteMatcher(r io.Reader, countryCode string) (strmatcher.IndexMatcher, error) {
- var data geoSiteListGob
- if err := gob.NewDecoder(r).Decode(&data); err != nil {
- return nil, err
- }
- return loadWithDeps(&data, countryCode, make(map[string]bool))
- }
- func loadWithDeps(data *geoSiteListGob, code string, visited map[string]bool) (strmatcher.IndexMatcher, error) {
- if visited[code] {
- return nil, errors.New("cyclic dependency")
- }
- visited[code] = true
- var matchers []strmatcher.IndexMatcher
- if siteData, ok := data.Sites[code]; ok {
- m, err := NewDomainMatcherFromBuffer(siteData)
- if err == nil {
- matchers = append(matchers, m)
- }
- }
- if deps, ok := data.Deps[code]; ok {
- for _, dep := range deps {
- m, err := loadWithDeps(data, dep, visited)
- if err == nil {
- matchers = append(matchers, m)
- }
- }
- }
- if len(matchers) == 0 {
- return nil, errors.New("matcher not found for: " + code)
- }
- if len(matchers) == 1 {
- return matchers[0], nil
- }
- runtime.GC()
- return &strmatcher.IndexMatcherGroup{Matchers: matchers}, nil
- }
- func LoadGeoSiteHosts(r io.Reader) (map[string][]string, error) {
- var data geoSiteListGob
- if err := gob.NewDecoder(r).Decode(&data); err != nil {
- return nil, err
- }
- return data.Hosts, nil
- }
|