From 072b6fed24688490e76242caac96e3c795fdb920 Mon Sep 17 00:00:00 2001 From: lionsoul2014 Date: Sat, 16 May 2026 10:58:49 +0800 Subject: [PATCH] segments iterate with CIDR supports --- data/sample/segments.tests.mixed | 8 ++++++++ maker/golang/xdb/segment.go | 25 +++++++++++++++++-------- maker/golang/xdb/util.go | 30 +++--------------------------- maker/golang/xdb/util_test.go | 9 +++++++-- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/data/sample/segments.tests.mixed b/data/sample/segments.tests.mixed index 632b8ef..96dabff 100644 --- a/data/sample/segments.tests.mixed +++ b/data/sample/segments.tests.mixed @@ -3,8 +3,16 @@ 192.168.2.31|192.168.2.60|0|0|内网IP|办公室B 192.168.2.61|192.168.2.91|0|0|内网IP|办公室B 223.255.236.0|223.255.239.255|中国|上海|上海市|电信 +# ipv4 cidr +14.32.46.0/24|3491 4766 9696|IGP +24.104.37.0/24|14537 174 7922 7016 401657 401657|IGP +45.15.32.0/22|14537 29119 206496 206496 206496 206496 206496 206496 206496 206496 206496|IGP 2c0f:fff1::|2c0f:ffff:ffff:ffff:ffff:ffff:ffff:ffff|毛里求斯|威廉平原区|卡特勒博尔纳|专线用户 2e00::|2fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff|德国|黑森|美因河畔法兰克福|专线用户 3000::|fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff|瑞士|弗里堡州||专线用户 fe00::|fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff|瑞士|弗里堡州||专线用户 fe80::|febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff|瑞士|弗里堡州||专线用户 +# ipv6 cidr +2c0f:fda8::/32|4635 6939 37662 37662 37035 37349|IGP +2c0f:fdb0::/32|3491 33765|IGP +2c0f:fe08:7::/48|2497 6939 36914|IGP diff --git a/maker/golang/xdb/segment.go b/maker/golang/xdb/segment.go index 94ad1e8..8792129 100644 --- a/maker/golang/xdb/segment.go +++ b/maker/golang/xdb/segment.go @@ -15,7 +15,7 @@ type Segment struct { Region *Region } -func SegmentFrom(seg string, cRegion func(string) *Region) (*Segment, error) { +func ParseSegment(seg string) ([]byte, []byte, string, error) { var count = 0 var ps = StringTokenizer(strings.TrimSpace(seg), "|", func(s string, start int) bool { // CIDR format @@ -36,36 +36,45 @@ func SegmentFrom(seg string, cRegion func(string) *Region) (*Segment, error) { rIdx = 1 sip, eip, err = CIDR2Range(ps[0]) if err != nil { - return nil, fmt.Errorf("parse cidr: %s", err) + return nil, nil, "", fmt.Errorf("parse cidr: %s", err) } case 3: // triditional ip range rIdx = 2 sip, err = ParseIP(ps[0]) if err != nil { - return nil, fmt.Errorf("parse start ip `%s`: %s", ps[0], err) + return nil, nil, "", fmt.Errorf("parse start ip `%s`: %s", ps[0], err) } eip, err = ParseIP(ps[1]) if err != nil { - return nil, fmt.Errorf("check end ip `%s`: %s", ps[1], err) + return nil, nil, "", fmt.Errorf("check end ip `%s`: %s", ps[1], err) } default: - return nil, fmt.Errorf("invalid ip segment `%s`", seg) + return nil, nil, "", fmt.Errorf("invalid ip segment `%s`", seg) } if len(sip) != len(eip) { - return nil, fmt.Errorf("invalid ip segment line `%s`, sip/eip version not match", seg) + return nil, nil, "", fmt.Errorf("invalid ip segment line `%s`, sip/eip version not match", seg) } if IPCompare(sip, eip) > 0 { - return nil, fmt.Errorf("start ip(%s) should not be greater than end ip(%s)", ps[0], ps[1]) + return nil, nil, "", fmt.Errorf("start ip(%s) should not be greater than end ip(%s)", ps[0], ps[1]) + } + + return sip, eip, ps[rIdx], nil +} + +func SegmentFrom(seg string, cRegion func(string) *Region) (*Segment, error) { + sip, eip, region, err := ParseSegment(seg) + if err != nil { + return nil, err } return &Segment{ StartIP: sip, EndIP: eip, - Region: cRegion(ps[rIdx]), + Region: cRegion(region), }, nil } diff --git a/maker/golang/xdb/util.go b/maker/golang/xdb/util.go index 8f5acd7..6566c91 100644 --- a/maker/golang/xdb/util.go +++ b/maker/golang/xdb/util.go @@ -200,38 +200,14 @@ func IterateSegments(handle *os.File, autoMerge bool, before func(l string), fil before(l) } - var ps = strings.SplitN(l, "|", 3) - if len(ps) != 3 { - return totalCount, mergeCount, fmt.Errorf("invalid ip segment line `%s`", l) - } - - sip, err := ParseIP(ps[0]) + sip, eip, region, err := ParseSegment(l) if err != nil { - return totalCount, mergeCount, fmt.Errorf("check start ip `%s`: %s", ps[0], err) + return totalCount, mergeCount, err } - eip, err := ParseIP(ps[1]) - if err != nil { - return totalCount, mergeCount, fmt.Errorf("check end ip `%s`: %s", ps[1], err) - } - - if len(sip) != len(eip) { - return totalCount, mergeCount, fmt.Errorf("invalid ip segment line `%s`, sip/eip version not match", l) - } - - if IPCompare(sip, eip) > 0 { - return totalCount, mergeCount, fmt.Errorf("start ip(%s) should not be greater than end ip(%s)", ps[0], ps[1]) - } - - // Allow empty region info since 2024/09/24 - // if len(ps[2]) < 1 { - // return fmt.Errorf("empty region info in segment line `%s`", l) - // } - // check and do the region filter - var region = ps[2] if filter != nil { - region, err = filter(ps[2]) + region, err = filter(region) if err != nil { return totalCount, mergeCount, fmt.Errorf("failed to filter region `%s`: %s", region, err) } diff --git a/maker/golang/xdb/util_test.go b/maker/golang/xdb/util_test.go index c297b47..296c506 100644 --- a/maker/golang/xdb/util_test.go +++ b/maker/golang/xdb/util_test.go @@ -292,12 +292,17 @@ func TestIterateSegments(t *testing.T) { t.Fatalf("failed to open tests file: %s", err) } - _, _, _ = IterateSegments(handle, true, func(l string) { + total, merged, err := IterateSegments(handle, true, func(l string) { // fmt.Printf("load segment: `%s`\n", l) }, nil, NewRegion, func(seg *Segment) error { - fmt.Printf("get segment: `%s`\n", seg) + fmt.Printf("{%s, %s} -> `%s`\n", IP2String(seg.StartIP), IP2String(seg.EndIP), seg.Region) return nil }) + if err != nil { + t.Fatalf("iterate error: %s", err) + } + + fmt.Printf("done iterate -> total:%d, merged:%d\n", total, merged) } func TestStringTokenizer(t *testing.T) {