github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/infra/conf/common.go (about)

     1  package conf
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     6  
     7  	"github.com/xmplusdev/xmcore/common/net"
     8  	"github.com/xmplusdev/xmcore/common/platform"
     9  	"github.com/xmplusdev/xmcore/common/protocol"
    10  )
    11  
    12  type StringList []string
    13  
    14  func NewStringList(raw []string) *StringList {
    15  	list := StringList(raw)
    16  	return &list
    17  }
    18  
    19  func (v StringList) Len() int {
    20  	return len(v)
    21  }
    22  
    23  func (v *StringList) UnmarshalJSON(data []byte) error {
    24  	var strarray []string
    25  	if err := json.Unmarshal(data, &strarray); err == nil {
    26  		*v = *NewStringList(strarray)
    27  		return nil
    28  	}
    29  
    30  	var rawstr string
    31  	if err := json.Unmarshal(data, &rawstr); err == nil {
    32  		strlist := strings.Split(rawstr, ",")
    33  		*v = *NewStringList(strlist)
    34  		return nil
    35  	}
    36  	return newError("unknown format of a string list: " + string(data))
    37  }
    38  
    39  type Address struct {
    40  	net.Address
    41  }
    42  
    43  func (v *Address) UnmarshalJSON(data []byte) error {
    44  	var rawStr string
    45  	if err := json.Unmarshal(data, &rawStr); err != nil {
    46  		return newError("invalid address: ", string(data)).Base(err)
    47  	}
    48  	if strings.HasPrefix(rawStr, "env:") {
    49  		rawStr = platform.NewEnvFlag(rawStr[4:]).GetValue(func() string { return "" })
    50  	}
    51  	v.Address = net.ParseAddress(rawStr)
    52  
    53  	return nil
    54  }
    55  
    56  func (v *Address) Build() *net.IPOrDomain {
    57  	return net.NewIPOrDomain(v.Address)
    58  }
    59  
    60  type Network string
    61  
    62  func (v Network) Build() net.Network {
    63  	switch strings.ToLower(string(v)) {
    64  	case "tcp":
    65  		return net.Network_TCP
    66  	case "udp":
    67  		return net.Network_UDP
    68  	case "unix":
    69  		return net.Network_UNIX
    70  	default:
    71  		return net.Network_Unknown
    72  	}
    73  }
    74  
    75  type NetworkList []Network
    76  
    77  func (v *NetworkList) UnmarshalJSON(data []byte) error {
    78  	var strarray []Network
    79  	if err := json.Unmarshal(data, &strarray); err == nil {
    80  		nl := NetworkList(strarray)
    81  		*v = nl
    82  		return nil
    83  	}
    84  
    85  	var rawstr Network
    86  	if err := json.Unmarshal(data, &rawstr); err == nil {
    87  		strlist := strings.Split(string(rawstr), ",")
    88  		nl := make([]Network, len(strlist))
    89  		for idx, network := range strlist {
    90  			nl[idx] = Network(network)
    91  		}
    92  		*v = nl
    93  		return nil
    94  	}
    95  	return newError("unknown format of a string list: " + string(data))
    96  }
    97  
    98  func (v *NetworkList) Build() []net.Network {
    99  	if v == nil {
   100  		return []net.Network{net.Network_TCP}
   101  	}
   102  
   103  	list := make([]net.Network, 0, len(*v))
   104  	for _, network := range *v {
   105  		list = append(list, network.Build())
   106  	}
   107  	return list
   108  }
   109  
   110  func parseIntPort(data []byte) (net.Port, error) {
   111  	var intPort uint32
   112  	err := json.Unmarshal(data, &intPort)
   113  	if err != nil {
   114  		return net.Port(0), err
   115  	}
   116  	return net.PortFromInt(intPort)
   117  }
   118  
   119  func parseStringPort(s string) (net.Port, net.Port, error) {
   120  	if strings.HasPrefix(s, "env:") {
   121  		s = platform.NewEnvFlag(s[4:]).GetValue(func() string { return "" })
   122  	}
   123  
   124  	pair := strings.SplitN(s, "-", 2)
   125  	if len(pair) == 0 {
   126  		return net.Port(0), net.Port(0), newError("invalid port range: ", s)
   127  	}
   128  	if len(pair) == 1 {
   129  		port, err := net.PortFromString(pair[0])
   130  		return port, port, err
   131  	}
   132  
   133  	fromPort, err := net.PortFromString(pair[0])
   134  	if err != nil {
   135  		return net.Port(0), net.Port(0), err
   136  	}
   137  	toPort, err := net.PortFromString(pair[1])
   138  	if err != nil {
   139  		return net.Port(0), net.Port(0), err
   140  	}
   141  	return fromPort, toPort, nil
   142  }
   143  
   144  func parseJSONStringPort(data []byte) (net.Port, net.Port, error) {
   145  	var s string
   146  	err := json.Unmarshal(data, &s)
   147  	if err != nil {
   148  		return net.Port(0), net.Port(0), err
   149  	}
   150  	return parseStringPort(s)
   151  }
   152  
   153  type PortRange struct {
   154  	From uint32
   155  	To   uint32
   156  }
   157  
   158  func (v *PortRange) Build() *net.PortRange {
   159  	return &net.PortRange{
   160  		From: v.From,
   161  		To:   v.To,
   162  	}
   163  }
   164  
   165  // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
   166  func (v *PortRange) UnmarshalJSON(data []byte) error {
   167  	port, err := parseIntPort(data)
   168  	if err == nil {
   169  		v.From = uint32(port)
   170  		v.To = uint32(port)
   171  		return nil
   172  	}
   173  
   174  	from, to, err := parseJSONStringPort(data)
   175  	if err == nil {
   176  		v.From = uint32(from)
   177  		v.To = uint32(to)
   178  		if v.From > v.To {
   179  			return newError("invalid port range ", v.From, " -> ", v.To)
   180  		}
   181  		return nil
   182  	}
   183  
   184  	return newError("invalid port range: ", string(data))
   185  }
   186  
   187  type PortList struct {
   188  	Range []PortRange
   189  }
   190  
   191  func (list *PortList) Build() *net.PortList {
   192  	portList := new(net.PortList)
   193  	for _, r := range list.Range {
   194  		portList.Range = append(portList.Range, r.Build())
   195  	}
   196  	return portList
   197  }
   198  
   199  // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
   200  func (list *PortList) UnmarshalJSON(data []byte) error {
   201  	var listStr string
   202  	var number uint32
   203  	if err := json.Unmarshal(data, &listStr); err != nil {
   204  		if err2 := json.Unmarshal(data, &number); err2 != nil {
   205  			return newError("invalid port: ", string(data)).Base(err2)
   206  		}
   207  	}
   208  	rangelist := strings.Split(listStr, ",")
   209  	for _, rangeStr := range rangelist {
   210  		trimmed := strings.TrimSpace(rangeStr)
   211  		if len(trimmed) > 0 {
   212  			if strings.Contains(trimmed, "-") || strings.Contains(trimmed, "env:") {
   213  				from, to, err := parseStringPort(trimmed)
   214  				if err != nil {
   215  					return newError("invalid port range: ", trimmed).Base(err)
   216  				}
   217  				list.Range = append(list.Range, PortRange{From: uint32(from), To: uint32(to)})
   218  			} else {
   219  				port, err := parseIntPort([]byte(trimmed))
   220  				if err != nil {
   221  					return newError("invalid port: ", trimmed).Base(err)
   222  				}
   223  				list.Range = append(list.Range, PortRange{From: uint32(port), To: uint32(port)})
   224  			}
   225  		}
   226  	}
   227  	if number != 0 {
   228  		list.Range = append(list.Range, PortRange{From: number, To: number})
   229  	}
   230  	return nil
   231  }
   232  
   233  type User struct {
   234  	EmailString string `json:"email"`
   235  	LevelByte   byte   `json:"level"`
   236  }
   237  
   238  func (v *User) Build() *protocol.User {
   239  	return &protocol.User{
   240  		Email: v.EmailString,
   241  		Level: uint32(v.LevelByte),
   242  	}
   243  }