mirror of
				https://github.com/v2fly/v2ray-core.git
				synced 2025-11-03 22:07:11 -05:00 
			
		
		
		
	Refinement: geodata decoder removes unnecessary GC & exports methods for 3rd party (#965)
This commit is contained in:
		@@ -2,7 +2,6 @@ package geodata
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"google.golang.org/protobuf/proto"
 | 
						"google.golang.org/protobuf/proto"
 | 
				
			||||||
@@ -33,7 +32,7 @@ func (g GeoIPCache) Set(key string, value *router.GeoIP) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (g GeoIPCache) Unmarshal(filename, code string) (*router.GeoIP, error) {
 | 
					func (g GeoIPCache) Unmarshal(filename, code string) (*router.GeoIP, error) {
 | 
				
			||||||
	asset := platform.GetAssetLocation(filename)
 | 
						asset := platform.GetAssetLocation(filename)
 | 
				
			||||||
	idx := strings.ToUpper(asset + "|" + code)
 | 
						idx := strings.ToUpper(asset + "_" + code)
 | 
				
			||||||
	if g.Has(idx) {
 | 
						if g.Has(idx) {
 | 
				
			||||||
		return g.Get(idx), nil
 | 
							return g.Get(idx), nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -48,11 +47,11 @@ func (g GeoIPCache) Unmarshal(filename, code string) (*router.GeoIP, error) {
 | 
				
			|||||||
		g.Set(idx, &geoip)
 | 
							g.Set(idx, &geoip)
 | 
				
			||||||
		return &geoip, nil
 | 
							return &geoip, nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case errCodeNotFound:
 | 
						case ErrCodeNotFound:
 | 
				
			||||||
		return nil, newError(code, " not found in ", filename)
 | 
							return nil, newError(code, " not found in ", filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case errFailedToReadBytes, errFailedToReadExpectedLenBytes,
 | 
						case ErrFailedToReadBytes, ErrFailedToReadExpectedLenBytes,
 | 
				
			||||||
		errInvalidGeodataFile, errInvalidGeodataVarintLength:
 | 
							ErrInvalidGeodataFile, ErrInvalidGeodataVarintLength:
 | 
				
			||||||
		newError("failed to decode geodata file: ", filename, ". Fallback to the original ReadFile method.").AtWarning().WriteToLog()
 | 
							newError("failed to decode geodata file: ", filename, ". Fallback to the original ReadFile method.").AtWarning().WriteToLog()
 | 
				
			||||||
		geoipBytes, err = ioutil.ReadFile(asset)
 | 
							geoipBytes, err = ioutil.ReadFile(asset)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -62,13 +61,11 @@ func (g GeoIPCache) Unmarshal(filename, code string) (*router.GeoIP, error) {
 | 
				
			|||||||
		if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
 | 
							if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		runtime.GC()
 | 
					 | 
				
			||||||
		for _, geoip := range geoipList.GetEntry() {
 | 
							for _, geoip := range geoipList.GetEntry() {
 | 
				
			||||||
			if strings.EqualFold(code, geoip.GetCountryCode()) {
 | 
								if strings.EqualFold(code, geoip.GetCountryCode()) {
 | 
				
			||||||
				g.Set(idx, geoip)
 | 
									g.Set(idx, geoip)
 | 
				
			||||||
				return geoip, nil
 | 
									return geoip, nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			runtime.GC()
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
@@ -100,7 +97,7 @@ func (g GeoSiteCache) Set(key string, value *router.GeoSite) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (g GeoSiteCache) Unmarshal(filename, code string) (*router.GeoSite, error) {
 | 
					func (g GeoSiteCache) Unmarshal(filename, code string) (*router.GeoSite, error) {
 | 
				
			||||||
	asset := platform.GetAssetLocation(filename)
 | 
						asset := platform.GetAssetLocation(filename)
 | 
				
			||||||
	idx := strings.ToUpper(asset + "|" + code)
 | 
						idx := strings.ToUpper(asset + "_" + code)
 | 
				
			||||||
	if g.Has(idx) {
 | 
						if g.Has(idx) {
 | 
				
			||||||
		return g.Get(idx), nil
 | 
							return g.Get(idx), nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -115,11 +112,11 @@ func (g GeoSiteCache) Unmarshal(filename, code string) (*router.GeoSite, error)
 | 
				
			|||||||
		g.Set(idx, &geosite)
 | 
							g.Set(idx, &geosite)
 | 
				
			||||||
		return &geosite, nil
 | 
							return &geosite, nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case errCodeNotFound:
 | 
						case ErrCodeNotFound:
 | 
				
			||||||
		return nil, newError(code, " not found in ", filename)
 | 
							return nil, newError(code, " not found in ", filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case errFailedToReadBytes, errFailedToReadExpectedLenBytes,
 | 
						case ErrFailedToReadBytes, ErrFailedToReadExpectedLenBytes,
 | 
				
			||||||
		errInvalidGeodataFile, errInvalidGeodataVarintLength:
 | 
							ErrInvalidGeodataFile, ErrInvalidGeodataVarintLength:
 | 
				
			||||||
		newError("failed to decode geodata file: ", filename, ". Fallback to the original ReadFile method.").AtWarning().WriteToLog()
 | 
							newError("failed to decode geodata file: ", filename, ". Fallback to the original ReadFile method.").AtWarning().WriteToLog()
 | 
				
			||||||
		geositeBytes, err = ioutil.ReadFile(asset)
 | 
							geositeBytes, err = ioutil.ReadFile(asset)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -129,13 +126,11 @@ func (g GeoSiteCache) Unmarshal(filename, code string) (*router.GeoSite, error)
 | 
				
			|||||||
		if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
 | 
							if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		runtime.GC()
 | 
					 | 
				
			||||||
		for _, geosite := range geositeList.GetEntry() {
 | 
							for _, geosite := range geositeList.GetEntry() {
 | 
				
			||||||
			if strings.EqualFold(code, geosite.GetCountryCode()) {
 | 
								if strings.EqualFold(code, geosite.GetCountryCode()) {
 | 
				
			||||||
				g.Set(idx, geosite)
 | 
									g.Set(idx, geosite)
 | 
				
			||||||
				return geosite, nil
 | 
									return geosite, nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			runtime.GC()
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,6 @@ package geodata
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"google.golang.org/protobuf/encoding/protowire"
 | 
						"google.golang.org/protobuf/encoding/protowire"
 | 
				
			||||||
@@ -23,14 +22,14 @@ import (
 | 
				
			|||||||
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
 | 
					//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	errFailedToReadBytes            = errors.New("failed to read bytes")
 | 
						ErrFailedToReadBytes            = errors.New("failed to read bytes")
 | 
				
			||||||
	errFailedToReadExpectedLenBytes = errors.New("failed to read expected length of bytes")
 | 
						ErrFailedToReadExpectedLenBytes = errors.New("failed to read expected length of bytes")
 | 
				
			||||||
	errInvalidGeodataFile           = errors.New("invalid geodata file")
 | 
						ErrInvalidGeodataFile           = errors.New("invalid geodata file")
 | 
				
			||||||
	errInvalidGeodataVarintLength   = errors.New("invalid geodata varint length")
 | 
						ErrInvalidGeodataVarintLength   = errors.New("invalid geodata varint length")
 | 
				
			||||||
	errCodeNotFound                 = errors.New("code not found")
 | 
						ErrCodeNotFound                 = errors.New("code not found")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func emitBytes(f io.ReadSeeker, code string) ([]byte, error) {
 | 
					func EmitBytes(f io.ReadSeeker, code string) ([]byte, error) {
 | 
				
			||||||
	count := 1
 | 
						count := 1
 | 
				
			||||||
	isInner := false
 | 
						isInner := false
 | 
				
			||||||
	tempContainer := make([]byte, 0, 5)
 | 
						tempContainer := make([]byte, 0, 5)
 | 
				
			||||||
@@ -44,19 +43,19 @@ Loop:
 | 
				
			|||||||
		container := make([]byte, advancedN)
 | 
							container := make([]byte, advancedN)
 | 
				
			||||||
		bytesRead, err := f.Read(container)
 | 
							bytesRead, err := f.Read(container)
 | 
				
			||||||
		if err == io.EOF {
 | 
							if err == io.EOF {
 | 
				
			||||||
			return nil, errCodeNotFound
 | 
								return nil, ErrCodeNotFound
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, errFailedToReadBytes
 | 
								return nil, ErrFailedToReadBytes
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if bytesRead != len(container) {
 | 
							if bytesRead != len(container) {
 | 
				
			||||||
			return nil, errFailedToReadExpectedLenBytes
 | 
								return nil, ErrFailedToReadExpectedLenBytes
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch count {
 | 
							switch count {
 | 
				
			||||||
		case 1, 3: // data type ((field_number << 3) | wire_type)
 | 
							case 1, 3: // data type ((field_number << 3) | wire_type)
 | 
				
			||||||
			if container[0] != 10 { // byte `0A` equals to `10` in decimal
 | 
								if container[0] != 10 { // byte `0A` equals to `10` in decimal
 | 
				
			||||||
				return nil, errInvalidGeodataFile
 | 
									return nil, ErrInvalidGeodataFile
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			advancedN = 1
 | 
								advancedN = 1
 | 
				
			||||||
			count++
 | 
								count++
 | 
				
			||||||
@@ -68,7 +67,7 @@ Loop:
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			lenVarint, n := protowire.ConsumeVarint(tempContainer)
 | 
								lenVarint, n := protowire.ConsumeVarint(tempContainer)
 | 
				
			||||||
			if n < 0 {
 | 
								if n < 0 {
 | 
				
			||||||
				return nil, errInvalidGeodataVarintLength
 | 
									return nil, ErrInvalidGeodataVarintLength
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			tempContainer = nil
 | 
								tempContainer = nil
 | 
				
			||||||
			if !isInner {
 | 
								if !isInner {
 | 
				
			||||||
@@ -98,11 +97,8 @@ Loop:
 | 
				
			|||||||
			result = container
 | 
								result = container
 | 
				
			||||||
			break Loop
 | 
								break Loop
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		runtime.GC() // run GC every round to save memory
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	runtime.GC() // run GC at the end to save memory
 | 
					 | 
				
			||||||
	return result, nil
 | 
						return result, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -113,7 +109,7 @@ func Decode(filename, code string) ([]byte, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	defer f.Close()
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	geoBytes, err := emitBytes(f, code)
 | 
						geoBytes, err := EmitBytes(f, code)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user