|
@@ -5,13 +5,21 @@ import (
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
|
|
|
+ "github.com/go-nunu/nunu-layout-advanced/internal/model"
|
|
|
+ "maps"
|
|
|
+ "sort"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
|
|
|
"github.com/spf13/cast"
|
|
|
- "strconv"
|
|
|
)
|
|
|
|
|
|
type FormatterService interface {
|
|
|
- FormatBackendData(ctx context.Context, req *v1.GameShieldSubmitRequest) (string, error)
|
|
|
+ FormatBackendData(ctx context.Context, req *v1.GameShieldBackendArrayRequest, output map[string]v1.SendGameShieldBackend) (string, int, error)
|
|
|
+ FormatPort(ctx context.Context, req interface{}) []int
|
|
|
+ OldFormat(ctx context.Context, req *[]model.GameShieldBackend) (map[string]v1.SendGameShieldBackend, error)
|
|
|
+ TidyFormatBackendData(ctx context.Context, req *v1.GameShieldBackendArrayRequest, keyCounter int) (map[string]v1.SendGameShieldBackend, error)
|
|
|
+ Sort(ctx context.Context, mapData map[string]v1.SendGameShieldBackend) (map[string]v1.SendGameShieldBackend, error)
|
|
|
}
|
|
|
|
|
|
func NewFormatterService(
|
|
@@ -30,63 +38,162 @@ type formatterService struct {
|
|
|
gameShieldPublicIpService GameShieldPublicIpService
|
|
|
}
|
|
|
|
|
|
-func (service *formatterService) FormatBackendData(ctx context.Context, req *v1.GameShieldSubmitRequest) (string, error) {
|
|
|
- output := make(map[string]map[string]interface{})
|
|
|
+func (service *formatterService) FormatBackendData(ctx context.Context, req *v1.GameShieldBackendArrayRequest, oldFormat map[string]v1.SendGameShieldBackend) (string, int, error) {
|
|
|
+ keyCounter := len(oldFormat)
|
|
|
+ formData, err := service.TidyFormatBackendData(ctx, req, keyCounter)
|
|
|
+ if err != nil {
|
|
|
+ return "", 0, err
|
|
|
+ }
|
|
|
+ maps.Copy(formData, oldFormat)
|
|
|
|
|
|
- userIp, err := service.gameShieldPublicIpService.GetUserIp(ctx, req.Uid)
|
|
|
+ sortedOutput, err := service.Sort(ctx, formData)
|
|
|
if err != nil {
|
|
|
- return "", err
|
|
|
+ return "", 0, err
|
|
|
}
|
|
|
- if len(req.Data) == 0 {
|
|
|
- return "", fmt.Errorf("data is required")
|
|
|
+ jsonBytes, err := json.Marshal(sortedOutput)
|
|
|
+ if err != nil {
|
|
|
+ return "", 0, err
|
|
|
}
|
|
|
- // 解析 JSON 数据为 map[string]map[string]interface{}
|
|
|
- var backend map[string]map[string]interface{}
|
|
|
- if err := json.Unmarshal([]byte(req.Data), &backend); err != nil {
|
|
|
- return "", fmt.Errorf("failed to unmarshal req.Data: %w", err)
|
|
|
+
|
|
|
+ return string(jsonBytes), keyCounter, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (service *formatterService) FormatPort(ctx context.Context, req interface{}) []int {
|
|
|
+ if req == nil {
|
|
|
+ return []int{}
|
|
|
}
|
|
|
|
|
|
- for i := 0; i < len(backend); i++ {
|
|
|
- key := "key" + strconv.Itoa(i)
|
|
|
+ reqStr := cast.ToString(req)
|
|
|
|
|
|
- innerMap, ok := backend[key]
|
|
|
- if !ok {
|
|
|
- continue
|
|
|
+ if reqStr == "" {
|
|
|
+ return []int{}
|
|
|
+ }
|
|
|
+
|
|
|
+ reqStr = strings.ReplaceAll(reqStr, ",", ",")
|
|
|
+
|
|
|
+ // 分割字符串并转换为整数
|
|
|
+ var res []int
|
|
|
+ for _, v := range strings.Split(reqStr, ",") {
|
|
|
+ // 去除空格
|
|
|
+ v = strings.TrimSpace(v)
|
|
|
+ if v != "" {
|
|
|
+ port := cast.ToInt(v)
|
|
|
+ res = append(res, port)
|
|
|
}
|
|
|
+ }
|
|
|
+ return res
|
|
|
+}
|
|
|
+
|
|
|
+func (service *formatterService) OldFormat(ctx context.Context, req *[]model.GameShieldBackend) (map[string]v1.SendGameShieldBackend, error) {
|
|
|
+ res := make(map[string]v1.SendGameShieldBackend)
|
|
|
+ for _, v := range *req {
|
|
|
+ addr := fmt.Sprintf("%s:%s", v.SourceMachineIP, v.ConnectPort)
|
|
|
+ sdkPort, err := strconv.Atoi(v.SdkPort)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ keyName := fmt.Sprintf("key%d", v.Key)
|
|
|
+ res[keyName] = v1.SendGameShieldBackend{
|
|
|
+ Addr: []string{addr},
|
|
|
+ Protocol: v.Protocol,
|
|
|
+ ProxyAddr: v.ProxyAddr,
|
|
|
+ SdkPort: sdkPort,
|
|
|
+ UdpSessionTimeout: "300s",
|
|
|
+ SdkIp: v.PublicIp,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return res, nil
|
|
|
+}
|
|
|
|
|
|
- addr := fmt.Sprintf("%s:%s", innerMap["source_machineIP"], cast.ToString(innerMap["connect_port"]))
|
|
|
+func (service *formatterService) TidyFormatBackendData(ctx context.Context, req *v1.GameShieldBackendArrayRequest, keyCounter int) (map[string]v1.SendGameShieldBackend, error) {
|
|
|
+ output := make(map[string]v1.SendGameShieldBackend)
|
|
|
+ userIp, err := service.gameShieldPublicIpService.GetUserIp(ctx, req.Uid)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
|
|
|
- itemMap := map[string]interface{}{
|
|
|
- "addr": []string{addr},
|
|
|
- "protocol": innerMap["protocol"],
|
|
|
+ for _, item := range req.Items {
|
|
|
+ // 提取必要字段
|
|
|
+ sourceIP := item.SourceMachineIP // 假设结构体中有这个字段
|
|
|
+ if sourceIP == "" {
|
|
|
+ continue // 跳过没有有效源IP的配置
|
|
|
}
|
|
|
|
|
|
- if host, ok := innerMap["host"]; ok && host != "" {
|
|
|
- itemMap["host"] = host
|
|
|
+ protocol := item.Protocol // 假设结构体中有这个字段
|
|
|
+ if protocol == "" {
|
|
|
+ continue // 跳过没有有效协议的配置
|
|
|
}
|
|
|
|
|
|
- if innerMap["protocol"] != "udp" {
|
|
|
- if req.Checked == 1 {
|
|
|
- itemMap["agent_addr"] = fmt.Sprintf("%s:%s", innerMap["source_machineIP"], "23350")
|
|
|
- }
|
|
|
- itemMap["proxy_addr"] = userIp + ":32353"
|
|
|
- } else {
|
|
|
- itemMap["proxy_addr"] = ""
|
|
|
- itemMap["udp_session_timeout"] = "300s"
|
|
|
+ // 获取端口数组
|
|
|
+ conPorts := service.FormatPort(ctx, item.ConnectPort)
|
|
|
+ sdkPorts := service.FormatPort(ctx, item.SdkPort)
|
|
|
+
|
|
|
+ if len(conPorts) != len(sdkPorts) {
|
|
|
+ return nil, fmt.Errorf("源端口和目标端口数量不匹配")
|
|
|
}
|
|
|
|
|
|
- if sdkPort, ok := innerMap["sdk_port"]; ok {
|
|
|
- itemMap["sdk_port"] = sdkPort
|
|
|
- } else {
|
|
|
- itemMap["sdk_port"] = 0
|
|
|
+ // 处理每一对端口
|
|
|
+ for i := 0; i < len(conPorts); i++ {
|
|
|
+ keyCounter++
|
|
|
+ key := fmt.Sprintf("key%d", keyCounter)
|
|
|
+
|
|
|
+ // 使用数组中的具体端口
|
|
|
+ addr := fmt.Sprintf("%s:%d", sourceIP, conPorts[i])
|
|
|
+
|
|
|
+ itemMap := v1.SendGameShieldBackend{
|
|
|
+ Addr: []string{addr},
|
|
|
+ Protocol: protocol,
|
|
|
+ }
|
|
|
+
|
|
|
+ //// 设置主机名(如果存在)
|
|
|
+ //if item.Host != "" {
|
|
|
+ // itemMap["host"] = item.Host
|
|
|
+ //}
|
|
|
+
|
|
|
+ // 根据协议设置不同属性
|
|
|
+ if protocol != "udp" {
|
|
|
+ if req.Checked == 1 {
|
|
|
+ itemMap.AgentAddr = fmt.Sprintf("%s:%s", sourceIP, "23350")
|
|
|
+ }
|
|
|
+ itemMap.ProxyAddr = userIp + ":32353"
|
|
|
+ } else {
|
|
|
+ itemMap.ProxyAddr = ""
|
|
|
+ itemMap.UdpSessionTimeout = "300s"
|
|
|
+ }
|
|
|
+ if item.Type == "mobile" {
|
|
|
+ itemMap.SdkIp = "127.0.0.1"
|
|
|
+ } else {
|
|
|
+ itemMap.SdkIp = item.PublicIp
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置SDK端口 - 使用数组中的具体端口
|
|
|
+ itemMap.SdkPort = sdkPorts[i]
|
|
|
+
|
|
|
+ output[key] = itemMap
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- output[key] = itemMap
|
|
|
+ return output, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (service *formatterService) Sort(ctx context.Context, mapData map[string]v1.SendGameShieldBackend) (map[string]v1.SendGameShieldBackend, error) {
|
|
|
+ var keys []int
|
|
|
+ for key := range mapData {
|
|
|
+ intKey, err := strconv.Atoi(strings.TrimPrefix(key, "key"))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ keys = append(keys, intKey)
|
|
|
}
|
|
|
|
|
|
- jsonBytes, err := json.Marshal(output)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
+ // 2. 排序键
|
|
|
+ sort.Ints(keys)
|
|
|
+ // 3. 创建一个新的 output 切片或 map 来存储排序后的值
|
|
|
+ sortedOutput := make(map[string]v1.SendGameShieldBackend)
|
|
|
+
|
|
|
+ // 4. 按排序后的键遍历 map,并存储对应的值到 sortedOutput
|
|
|
+ for _, key := range keys {
|
|
|
+ sortedOutput["key"+strconv.Itoa(key)] = mapData["key"+strconv.Itoa(key)]
|
|
|
}
|
|
|
- return string(jsonBytes), nil
|
|
|
+ return sortedOutput, nil
|
|
|
}
|