Browse Source

feat(game-shield): 重构 IP 生成逻辑

- 移除 GenerateIpService 接口和实现
- 新增 GameShieldSdkIp 相关的 model、repository 和 service
- 更新 GameShieldService,集成新的 IP 生成逻辑
- 添加处理 SDK IP 的新 handler
fusu 3 months ago
parent
commit
12139c3475

+ 3 - 0
cmd/server/wire/wire.go

@@ -36,6 +36,7 @@ var repositorySet = wire.NewSet(
 	repository.NewTcpLimitRepository,
 	repository.NewTcpLimitRepository,
 	repository.NewUdpLimitRepository,
 	repository.NewUdpLimitRepository,
 	repository.NewGameShieldBackendRepository,
 	repository.NewGameShieldBackendRepository,
+	repository.NewGameShieldSdkIpRepository,
 )
 )
 
 
 var serviceSet = wire.NewSet(
 var serviceSet = wire.NewSet(
@@ -56,6 +57,7 @@ var serviceSet = wire.NewSet(
 	service.NewTcpLimitService,
 	service.NewTcpLimitService,
 	service.NewUdpLimitService,
 	service.NewUdpLimitService,
 	service.NewGameShieldBackendService,
 	service.NewGameShieldBackendService,
+	service.NewGameShieldSdkIpService,
 )
 )
 
 
 var handlerSet = wire.NewSet(
 var handlerSet = wire.NewSet(
@@ -71,6 +73,7 @@ var handlerSet = wire.NewSet(
 	handler.NewTcpLimitHandler,
 	handler.NewTcpLimitHandler,
 	handler.NewUdpLimitHandler,
 	handler.NewUdpLimitHandler,
 	handler.NewGameShieldBackendHandler,
 	handler.NewGameShieldBackendHandler,
+	handler.NewGameShieldSdkIpHandler,
 )
 )
 
 
 var jobSet = wire.NewSet(
 var jobSet = wire.NewSet(

+ 6 - 4
cmd/server/wire/wire_gen.go

@@ -47,7 +47,9 @@ func NewWire(viperViper *viper.Viper, logger *log.Logger) (*app.App, func(), err
 	duedateService := service.NewDuedateService(serviceService, gameShieldRepository)
 	duedateService := service.NewDuedateService(serviceService, gameShieldRepository)
 	formatterService := service.NewFormatterService(serviceService, gameShieldPublicIpService)
 	formatterService := service.NewFormatterService(serviceService, gameShieldPublicIpService)
 	requiredService := service.NewRequiredService(serviceService, crawlerService, viperViper)
 	requiredService := service.NewRequiredService(serviceService, crawlerService, viperViper)
-	gameShieldService := service.NewGameShieldService(serviceService, gameShieldRepository, crawlerService, gameShieldPublicIpService, duedateService, formatterService, parserService, requiredService, viperViper)
+	gameShieldSdkIpRepository := repository.NewGameShieldSdkIpRepository(repositoryRepository)
+	gameShieldSdkIpService := service.NewGameShieldSdkIpService(serviceService, gameShieldSdkIpRepository)
+	gameShieldService := service.NewGameShieldService(serviceService, gameShieldRepository, crawlerService, gameShieldPublicIpService, duedateService, formatterService, parserService, requiredService, viperViper, gameShieldSdkIpService)
 	gameShieldHandler := handler.NewGameShieldHandler(handlerHandler, gameShieldService, crawlerService)
 	gameShieldHandler := handler.NewGameShieldHandler(handlerHandler, gameShieldService, crawlerService)
 	gameShieldBackendRepository := repository.NewGameShieldBackendRepository(repositoryRepository)
 	gameShieldBackendRepository := repository.NewGameShieldBackendRepository(repositoryRepository)
 	gameShieldBackendService := service.NewGameShieldBackendService(serviceService, gameShieldBackendRepository, gameShieldRepository, crawlerService, gameShieldPublicIpService, duedateService, formatterService, parserService, requiredService, viperViper)
 	gameShieldBackendService := service.NewGameShieldBackendService(serviceService, gameShieldBackendRepository, gameShieldRepository, crawlerService, gameShieldPublicIpService, duedateService, formatterService, parserService, requiredService, viperViper)
@@ -81,11 +83,11 @@ func NewWire(viperViper *viper.Viper, logger *log.Logger) (*app.App, func(), err
 
 
 // wire.go:
 // wire.go:
 
 
-var repositorySet = wire.NewSet(repository.NewDB, repository.NewRepository, repository.NewTransaction, repository.NewUserRepository, repository.NewGameShieldRepository, repository.NewGameShieldPublicIpRepository, repository.NewWebForwardingRepository, repository.NewTcpforwardingRepository, repository.NewUdpForWardingRepository, repository.NewGameShieldUserIpRepository, repository.NewWebLimitRepository, repository.NewTcpLimitRepository, repository.NewUdpLimitRepository, repository.NewGameShieldBackendRepository)
+var repositorySet = wire.NewSet(repository.NewDB, repository.NewRepository, repository.NewTransaction, repository.NewUserRepository, repository.NewGameShieldRepository, repository.NewGameShieldPublicIpRepository, repository.NewWebForwardingRepository, repository.NewTcpforwardingRepository, repository.NewUdpForWardingRepository, repository.NewGameShieldUserIpRepository, repository.NewWebLimitRepository, repository.NewTcpLimitRepository, repository.NewUdpLimitRepository, repository.NewGameShieldBackendRepository, repository.NewGameShieldSdkIpRepository)
 
 
-var serviceSet = wire.NewSet(service.NewService, service.NewUserService, service.NewGameShieldService, service.NewCrawlerService, service.NewGameShieldPublicIpService, service.NewDuedateService, service.NewFormatterService, service.NewParserService, service.NewRequiredService, service.NewWebForwardingService, service.NewTcpforwardingService, service.NewUdpForWardingService, service.NewGameShieldUserIpService, service.NewWebLimitService, service.NewTcpLimitService, service.NewUdpLimitService, service.NewGameShieldBackendService)
+var serviceSet = wire.NewSet(service.NewService, service.NewUserService, service.NewGameShieldService, service.NewCrawlerService, service.NewGameShieldPublicIpService, service.NewDuedateService, service.NewFormatterService, service.NewParserService, service.NewRequiredService, service.NewWebForwardingService, service.NewTcpforwardingService, service.NewUdpForWardingService, service.NewGameShieldUserIpService, service.NewWebLimitService, service.NewTcpLimitService, service.NewUdpLimitService, service.NewGameShieldBackendService, service.NewGameShieldSdkIpService)
 
 
-var handlerSet = wire.NewSet(handler.NewHandler, handler.NewUserHandler, handler.NewGameShieldHandler, handler.NewGameShieldPublicIpHandler, handler.NewWebForwardingHandler, handler.NewTcpforwardingHandler, handler.NewUdpForWardingHandler, handler.NewGameShieldUserIpHandler, handler.NewWebLimitHandler, handler.NewTcpLimitHandler, handler.NewUdpLimitHandler, handler.NewGameShieldBackendHandler)
+var handlerSet = wire.NewSet(handler.NewHandler, handler.NewUserHandler, handler.NewGameShieldHandler, handler.NewGameShieldPublicIpHandler, handler.NewWebForwardingHandler, handler.NewTcpforwardingHandler, handler.NewUdpForWardingHandler, handler.NewGameShieldUserIpHandler, handler.NewWebLimitHandler, handler.NewTcpLimitHandler, handler.NewUdpLimitHandler, handler.NewGameShieldBackendHandler, handler.NewGameShieldSdkIpHandler)
 
 
 var jobSet = wire.NewSet(job.NewJob, job.NewUserJob)
 var jobSet = wire.NewSet(job.NewJob, job.NewUserJob)
 
 

+ 0 - 1
go.sum

@@ -234,7 +234,6 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
 github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
 github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
 github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
 github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
 github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
 github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
 github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=

+ 25 - 0
internal/handler/gameshieldsdkip.go

@@ -0,0 +1,25 @@
+package handler
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/go-nunu/nunu-layout-advanced/internal/service"
+)
+
+type GameShieldSdkIpHandler struct {
+	*Handler
+	gameShieldSdkIpService service.GameShieldSdkIpService
+}
+
+func NewGameShieldSdkIpHandler(
+	handler *Handler,
+	gameShieldSdkIpService service.GameShieldSdkIpService,
+) *GameShieldSdkIpHandler {
+	return &GameShieldSdkIpHandler{
+		Handler:                handler,
+		gameShieldSdkIpService: gameShieldSdkIpService,
+	}
+}
+
+func (h *GameShieldSdkIpHandler) GetGameShieldSdkIp(ctx *gin.Context) {
+
+}

+ 0 - 2
internal/model/gameshield.go

@@ -6,13 +6,11 @@ type GameShield struct {
 	Id             int `gorm:"primarykey"`
 	Id             int `gorm:"primarykey"`
 	AppName        string
 	AppName        string
 	GatewayGroupId int
 	GatewayGroupId int
-	Backend        string
 	RuleId         int
 	RuleId         int
 	Key            string
 	Key            string
 	AddTime        time.Time
 	AddTime        time.Time
 	Uid            int
 	Uid            int
 	HostId         string
 	HostId         string
-	AppIp          string
 	Checked        int
 	Checked        int
 	DunName        string
 	DunName        string
 }
 }

+ 15 - 0
internal/model/gameshieldsdkip.go

@@ -0,0 +1,15 @@
+package model
+
+import "time"
+
+type GameShieldSdkIp struct {
+	Id        int    `gorm:"primarykey"`
+	Uid       int    `gorm:"not null"`
+	HostId    int    `gorm:"not null"`
+	SdkIp     string `gorm:"not null unique"`
+	CreatedAt time.Time
+}
+
+func (m *GameShieldSdkIp) TableName() string {
+	return "shd_game_shield_sdk_ip"
+}

+ 0 - 10
internal/repository/gameshield.go

@@ -13,7 +13,6 @@ type GameShieldRepository interface {
 	DeleteGameShield(ctx context.Context, ruleId int) error
 	DeleteGameShield(ctx context.Context, ruleId int) error
 	GetGameShieldIsBuy(ctx context.Context, uid int64) (int64, error)
 	GetGameShieldIsBuy(ctx context.Context, uid int64) (int64, error)
 	GetGameShieldNextduedate(ctx context.Context, uid int64, productID string) (string, error)
 	GetGameShieldNextduedate(ctx context.Context, uid int64, productID string) (string, error)
-	GetGameShieldExistingIps(ctx context.Context, ip string) ([]string, error)
 	GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error)
 	GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error)
 	GetGameShieldIdByDunName(ctx context.Context, id int64) (string, error)
 	GetGameShieldIdByDunName(ctx context.Context, id int64) (string, error)
 	GetGameShieldRuleIdByAppName(ctx context.Context, appName string) (int, error)
 	GetGameShieldRuleIdByAppName(ctx context.Context, appName string) (int, error)
@@ -97,15 +96,6 @@ func (r *gameShieldRepository) GetGameShieldNextduedate(ctx context.Context, uid
 
 
 	return nextDueDate, nil
 	return nextDueDate, nil
 }
 }
-func (r *gameShieldRepository) GetGameShieldExistingIps(ctx context.Context, ip string) ([]string, error) {
-	var res []string
-	if err := r.DB(ctx).Model(&model.GameShield{}).
-		Where("app_ip LIKE ?", ip+"%").
-		Pluck("app_ip", &res).Error; err != nil {
-		return nil, err
-	}
-	return res, nil
-}
 
 
 func (r *gameShieldRepository) GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error) {
 func (r *gameShieldRepository) GetGameShieldNameByDunName(ctx context.Context, appName string) (string, error) {
 	var res string
 	var res string

+ 81 - 0
internal/repository/gameshieldsdkip.go

@@ -0,0 +1,81 @@
+package repository
+
+import (
+	"context"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+)
+
+type GameShieldSdkIpRepository interface {
+	GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error)
+	AddGameShieldSdkIp(ctx context.Context, req *model.GameShieldSdkIp) error
+	UpdateGameShieldSdkIp(ctx context.Context, gameShieldSdkIp *model.GameShieldSdkIp) error
+	DeleteGameShieldSdkIp(ctx context.Context, id int64) error
+	GetGameShieldSdkIpByHostId(ctx context.Context, hostId int) (*model.GameShieldSdkIp, error)
+	GetGameShieldSdkIpNewByHostId(ctx context.Context, hostId int) (string, error)
+	GetGameShieldSdkIpCountByHostId(ctx context.Context, hostId int) (int64, error)
+}
+
+func NewGameShieldSdkIpRepository(
+	repository *Repository,
+) GameShieldSdkIpRepository {
+	return &gameShieldSdkIpRepository{
+		Repository: repository,
+	}
+}
+
+type gameShieldSdkIpRepository struct {
+	*Repository
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error) {
+	var res model.GameShieldSdkIp
+	if err := r.DB(ctx).Where("id = ?", id).First(&res).Error; err != nil {
+		return nil, err
+	}
+	return &res, nil
+}
+
+func (r *gameShieldSdkIpRepository) AddGameShieldSdkIp(ctx context.Context, req *model.GameShieldSdkIp) error {
+	if err := r.DB(ctx).Create(req).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *gameShieldSdkIpRepository) UpdateGameShieldSdkIp(ctx context.Context, gameShieldSdkIp *model.GameShieldSdkIp) error {
+	if err := r.DB(ctx).Updates(gameShieldSdkIp).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *gameShieldSdkIpRepository) DeleteGameShieldSdkIp(ctx context.Context, id int64) error {
+	if err := r.DB(ctx).Where("id = ?", id).Delete(&model.GameShieldSdkIp{}).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIpByHostId(ctx context.Context, hostId int) (*model.GameShieldSdkIp, error) {
+	var res model.GameShieldSdkIp
+	if err := r.DB(ctx).Where("host_id = ?", hostId).Select(&model.GameShieldSdkIp{}).Error; err != nil {
+		return nil, err
+	}
+	return &res, nil
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIpNewByHostId(ctx context.Context, hostId int) (string, error) {
+	var res model.GameShieldSdkIp
+	if err := r.DB(ctx).Where("host_id = ?", hostId).Order("id DESC").First(&model.GameShieldSdkIp{}).Error; err != nil {
+		return "", err
+	}
+	return res.SdkIp, nil
+}
+
+func (r *gameShieldSdkIpRepository) GetGameShieldSdkIpCountByHostId(ctx context.Context, hostId int) (int64, error) {
+	var res int64
+	if err := r.DB(ctx).Model(&model.GameShieldSdkIp{}).Where("host_id = ?", hostId).Count(&res).Error; err != nil {
+		return 0, err
+	}
+	return res, nil
+}

+ 15 - 0
internal/service/gameshield.go

@@ -28,6 +28,7 @@ func NewGameShieldService(
 	parser ParserService,
 	parser ParserService,
 	required RequiredService,
 	required RequiredService,
 	conf *viper.Viper,
 	conf *viper.Viper,
+	gameShieldSdkIp GameShieldSdkIpService,
 ) GameShieldService {
 ) GameShieldService {
 	return &gameShieldService{
 	return &gameShieldService{
 		Service:                   service,
 		Service:                   service,
@@ -39,6 +40,7 @@ func NewGameShieldService(
 		parser:                    parser,
 		parser:                    parser,
 		required:                  required,
 		required:                  required,
 		Url:                       conf.GetString("crawler.Url"),
 		Url:                       conf.GetString("crawler.Url"),
+		gameShieldSdkIp:           gameShieldSdkIp,
 	}
 	}
 }
 }
 
 
@@ -53,6 +55,7 @@ type gameShieldService struct {
 	Url                       string
 	Url                       string
 	parser                    ParserService
 	parser                    ParserService
 	required                  RequiredService
 	required                  RequiredService
+	gameShieldSdkIp           GameShieldSdkIpService
 }
 }
 
 
 func (service *gameShieldService) SubmitGameShield(ctx context.Context, req *v1.GameShieldSubmitRequest) (string, error) {
 func (service *gameShieldService) SubmitGameShield(ctx context.Context, req *v1.GameShieldSubmitRequest) (string, error) {
@@ -63,6 +66,17 @@ func (service *gameShieldService) SubmitGameShield(ctx context.Context, req *v1.
 	if nameCount > 0 {
 	if nameCount > 0 {
 		return "", fmt.Errorf("应用名称已存在")
 		return "", fmt.Errorf("应用名称已存在")
 	}
 	}
+
+	hostIdInt, err := strconv.Atoi(req.HostId)
+	if err != nil {
+		return "", fmt.Errorf("转换hostId失败: %v", err)
+	}
+
+	// 调用IP生成服务
+	if err := service.gameShieldSdkIp.GenerateMultipleLoopbackIps(ctx, req.Uid, hostIdInt); err != nil {
+		return "", fmt.Errorf("生成IP地址失败: %w", err)
+	}
+
 	dunName := strconv.Itoa(req.Uid) + "_" + strconv.FormatInt(time.Now().Unix(), 10) + "_hostId" + req.HostId
 	dunName := strconv.Itoa(req.Uid) + "_" + strconv.FormatInt(time.Now().Unix(), 10) + "_hostId" + req.HostId
 	formData := map[string]interface{}{
 	formData := map[string]interface{}{
 		"app_name":         dunName,
 		"app_name":         dunName,
@@ -98,6 +112,7 @@ func (service *gameShieldService) SubmitGameShield(ctx context.Context, req *v1.
 	}); err != nil {
 	}); err != nil {
 		return "", err
 		return "", err
 	}
 	}
+
 	return "", nil
 	return "", nil
 }
 }
 
 

+ 147 - 0
internal/service/gameshieldsdkip.go

@@ -0,0 +1,147 @@
+package service
+
+import (
+	"context"
+	"fmt"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
+	"strconv"
+	"strings"
+)
+
+type GameShieldSdkIpService interface {
+	GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error)
+	GenerateMultipleLoopbackIps(ctx context.Context, uid int, hostId int, count ...int) error
+}
+
+func NewGameShieldSdkIpService(
+	service *Service,
+	gameShieldSdkIpRepository repository.GameShieldSdkIpRepository,
+) GameShieldSdkIpService {
+	return &gameShieldSdkIpService{
+		Service:                   service,
+		gameShieldSdkIpRepository: gameShieldSdkIpRepository,
+	}
+}
+
+type gameShieldSdkIpService struct {
+	*Service
+	gameShieldSdkIpRepository repository.GameShieldSdkIpRepository
+}
+
+func (s *gameShieldSdkIpService) GetGameShieldSdkIp(ctx context.Context, id int64) (*model.GameShieldSdkIp, error) {
+	return s.gameShieldSdkIpRepository.GetGameShieldSdkIp(ctx, id)
+}
+
+// GenerateMultipleLoopbackIps 生成多个唯一127.0.0.0/8范围IP地址
+// count 指定需要生成的IP地址数量,默认为10
+// 返回生成的唯一IP地址数组和可能的错误
+// GenerateMultipleLoopbackIps 生成并保存多个唯一127.0.0.0/8范围IP地址到数据库
+// uid 用户ID
+// hostId 实例ID
+// count 指定需要生成的IP地址数量,默认为10
+// 返回生成并保存的唯一IP地址数组和可能的错误
+func (s *gameShieldSdkIpService) GenerateMultipleLoopbackIps(ctx context.Context, uid int, hostId int, count ...int) error {
+	requiredCount := 10
+	if len(count) > 0 && count[0] > 0 {
+		requiredCount = count[0]
+	}
+	haveCount, err := s.gameShieldSdkIpRepository.GetGameShieldSdkIpCountByHostId(ctx, hostId)
+	if err != nil {
+		return err
+	}
+	if int(haveCount) >= requiredCount {
+		return nil
+	}
+	// 从数据库获取最新的一条IP记录
+	latestIp, err := s.gameShieldSdkIpRepository.GetGameShieldSdkIpNewByHostId(ctx, hostId)
+	if err != nil {
+		// 如果没有记录,默认从127.0.0.2开始(避免使用127.0.0.1)
+		latestIp = "127.0.0.1"
+	}
+
+	// 解析IP成四个段
+	ipParts := strings.Split(latestIp, ".")
+	if len(ipParts) != 4 {
+		return fmt.Errorf("无效的IP格式: %s", latestIp)
+	}
+
+	// 将IP段转换为整数
+	a, err1 := strconv.Atoi(ipParts[0])
+	b, err2 := strconv.Atoi(ipParts[1])
+	c, err3 := strconv.Atoi(ipParts[2])
+	d, err4 := strconv.Atoi(ipParts[3])
+
+	if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
+		return fmt.Errorf("IP段转换失败: %s", latestIp)
+	}
+
+	// 确保第一段是127(保持在回环地址范围内)
+	if a != 127 {
+		a = 127
+		b, c, d = 0, 0, 1 // 重置为127.0.0.1
+	}
+
+	// 从最新IP的下一个地址开始
+	d++
+	if d > 255 {
+		d = 0
+		c++
+		if c > 255 {
+			c = 0
+			b++
+			if b > 255 {
+				return fmt.Errorf("IP地址池已耗尽")
+			}
+		}
+	}
+
+	// 收集生成的唯一IP
+	result := make([]string, 0, requiredCount)
+	attempts := 0
+	maxAttempts := 10000 // 防止无限循环
+
+	for len(result) < requiredCount && attempts < maxAttempts {
+		currentIp := fmt.Sprintf("127.%d.%d.%d", b, c, d)
+
+		// 尝试将IP保存到数据库
+		err := s.gameShieldSdkIpRepository.AddGameShieldSdkIp(ctx, &model.GameShieldSdkIp{
+			HostId: hostId,
+			Uid:    uid,
+			SdkIp:  currentIp,
+		})
+		if err == nil {
+			// 保存成功,添加到结果列表
+			result = append(result, currentIp)
+		} else {
+			// 如果是因为IP已存在导致的错误,我们忽略并继续
+			// 其他错误则返回
+			if !strings.Contains(err.Error(), "unique_sdk_ip") {
+				return fmt.Errorf("保存IP到数据库失败: %w", err)
+			}
+			// IP已存在,继续尝试下一个
+		}
+
+		// 递增IP地址
+		d++
+		if d > 255 {
+			d = 0
+			c++
+			if c > 255 {
+				c = 0
+				b++
+				if b > 255 {
+					break
+				}
+			}
+		}
+
+		attempts++
+	}
+
+	if len(result) < requiredCount {
+		return fmt.Errorf("无法生成足够的唯一IP地址,地址池可能已耗尽,仅生成了%d个", len(result))
+	}
+
+	return nil
+}

+ 0 - 219
internal/service/generateip.go

@@ -1,219 +0,0 @@
-package service
-
-import (
-	"context"
-	"fmt"
-	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
-	"github.com/sourcegraph/conc/pool"
-	"math/rand"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-)
-
-type GenerateIpService interface {
-	GenerateMultipleLoopbackIps(ctx context.Context, count ...int) ([]string, error)
-}
-
-func NewGenerateIpService(
-	service *Service,
-	gameShieldRepository repository.GameShieldRepository,
-) GenerateIpService {
-	return &generateIpService{
-		Service:              service,
-		gameShieldRepository: gameShieldRepository,
-	}
-}
-
-type generateIpService struct {
-	*Service
-	gameShieldRepository repository.GameShieldRepository
-}
-
-// GenerateMultipleLoopbackIps 生成多个唯一127.0.0.0/8范围IP地址
-// count 指定需要生成的IP地址数量,默认为10
-// 返回生成的唯一IP地址数组和可能的错误
-func (s *generateIpService) GenerateMultipleLoopbackIps(ctx context.Context, count ...int) ([]string, error) {
-	requiredCount := 10
-	if len(count) > 0 && count[0] > 0 {
-		requiredCount = count[0]
-	}
-
-	maxAttempts := 1000 // 最大尝试次数
-	attempts := 0
-
-	// 使用互斥锁保护结果集
-	var mu sync.Mutex
-	collected := make([]string, 0, requiredCount)
-	checkedSegments := make(map[string]struct{}, maxAttempts)
-
-	// 使用一个固定的随机源以提高性能
-	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
-
-	for len(collected) < requiredCount && attempts < maxAttempts {
-		// 随机生成多个x/z段组合,批量处理
-		candidates := make([]struct{ x, z int }, 0, 5)
-		for i := 0; i < 5 && len(candidates) < 5; i++ {
-			x := rnd.Intn(256)
-			z := rnd.Intn(256)
-			segmentKey := fmt.Sprintf("%d-%d", x, z)
-
-			// 跳过已检查过的段
-			mu.Lock()
-			_, exists := checkedSegments[segmentKey]
-			if !exists {
-				checkedSegments[segmentKey] = struct{}{}
-				mu.Unlock()
-				candidates = append(candidates, struct{ x, z int }{x, z})
-			} else {
-				mu.Unlock()
-			}
-		}
-
-		// 使用conc/pool包并发处理候选IP段
-		// 创建一个工作池,限制并发数为4,并收集错误
-		p := pool.New().WithMaxGoroutines(4).WithErrors()
-
-		// 存储结果
-		var results [][]string
-
-		// 对每个候选项并发处理
-		for _, candidate := range candidates {
-			// 创建副本避免闭包捕获循环变量
-			candidate := candidate
-
-			p.Go(func() error {
-				if ctx.Err() != nil {
-					return ctx.Err()
-				}
-
-				x, z := candidate.x, candidate.z
-				prefix := fmt.Sprintf("127.%d.%d.", x, z)
-
-				// 查询数据库中该前缀已存在的IP
-				existingIps, err := s.gameShieldRepository.GetGameShieldExistingIps(ctx, prefix)
-				if err != nil {
-					// 返回错误以便收集
-					return fmt.Errorf("获取IP %s 前缀已存在的记录失败: %w", prefix, err)
-				}
-
-				// 使用map标记已存在的第四段
-				existingFourth := make(map[int]bool, len(existingIps))
-				for _, ip := range existingIps {
-					parts := strings.Split(ip, ".")
-					if len(parts) == 4 {
-						fourth, err := strconv.Atoi(parts[3])
-						if err == nil {
-							// 排除127.0.0.1的情况
-							if x == 0 && z == 0 && fourth == 1 {
-								continue
-							}
-							existingFourth[fourth] = true
-						}
-					}
-				}
-
-				// 快速估算可用数量
-				availableCount := 256 - len(existingFourth)
-				// 排除127.0.0.1的特殊情况
-				if x == 0 && z == 0 && !existingFourth[1] {
-					availableCount--
-				}
-
-				// 如果可用数量太少,可以跳过
-				if availableCount <= 0 {
-					return nil
-				}
-
-				// 预分配足够大的切片避免多次扩容
-				available := make([]string, 0, availableCount)
-
-				// 如果可用数量很多,可以只收集部分,避免不必要的工作
-				collectLimit := min(availableCount, requiredCount*2)
-				collectCount := 0
-
-				// 随机选择起始点,避免每次都从0开始
-				startPoint := rnd.Intn(256)
-				for i := 0; i < 256 && collectCount < collectLimit; i++ {
-					fourth := (startPoint + i) % 256
-
-					if existingFourth[fourth] {
-						continue
-					}
-
-					// 确保不生成127.0.0.1
-					if x == 0 && z == 0 && fourth == 1 {
-						continue
-					}
-
-					available = append(available, fmt.Sprintf("127.%d.%d.%d", x, z, fourth))
-					collectCount++
-				}
-
-				// 随机打乱结果
-				for i := len(available) - 1; i > 0; i-- {
-					j := rnd.Intn(i + 1)
-					available[i], available[j] = available[j], available[i]
-				}
-
-				// 将结果添加到结果集
-				mu.Lock()
-				results = append(results, available)
-				mu.Unlock()
-
-				return nil
-			})
-		}
-
-		// 等待所有goroutine完成并检查错误
-		if err := p.Wait(); err != nil {
-			// 这里可以选择记录错误但继续尝试,或者直接返回错误
-			// 我们选择只有当收集的IP不足时才返回错误
-			if len(collected) < requiredCount {
-				// 如果已经是最后一次尝试且收集的IP不足,返回错误
-				if attempts >= maxAttempts-1 {
-					return nil, fmt.Errorf("生成IP地址失败: %w", err)
-				}
-				// 否则继续尝试下一批候选IP段
-			}
-		}
-
-		// 收集结果
-		for _, ips := range results {
-			mu.Lock()
-			for _, ip := range ips {
-				if len(collected) >= requiredCount {
-					break
-				}
-				collected = append(collected, ip)
-			}
-			mu.Unlock()
-		}
-
-		attempts++
-
-		// 如果已经收集足够的IP,跳出循环
-		mu.Lock()
-		hasEnough := len(collected) >= requiredCount
-		mu.Unlock()
-		if hasEnough {
-			break
-		}
-	}
-
-	mu.Lock()
-	defer mu.Unlock()
-
-	if len(collected) < requiredCount {
-		return nil, fmt.Errorf("无法生成足够的唯一IP地址,地址池可能已耗尽,仅生成了%d个", len(collected))
-	}
-
-	// 最终随机排序
-	for i := len(collected) - 1; i > 0; i-- {
-		j := rand.Intn(i + 1)
-		collected[i], collected[j] = collected[j], collected[i]
-	}
-
-	return collected[:requiredCount], nil
-}