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 }