github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/infra/conf/common.go (about) 1 package conf 2 3 import ( 4 "encoding/json" 5 "strings" 6 7 "github.com/xtls/xray-core/common/net" 8 "github.com/xtls/xray-core/common/platform" 9 "github.com/xtls/xray-core/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 }