github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/option/types.go (about) 1 package option 2 3 import ( 4 "net/netip" 5 "strings" 6 "time" 7 8 "github.com/inazumav/sing-box/common/json" 9 "github.com/sagernet/sing-dns" 10 E "github.com/sagernet/sing/common/exceptions" 11 F "github.com/sagernet/sing/common/format" 12 N "github.com/sagernet/sing/common/network" 13 14 mDNS "github.com/miekg/dns" 15 ) 16 17 type ListenAddress netip.Addr 18 19 func NewListenAddress(addr netip.Addr) *ListenAddress { 20 address := ListenAddress(addr) 21 return &address 22 } 23 24 func (a ListenAddress) MarshalJSON() ([]byte, error) { 25 addr := netip.Addr(a) 26 if !addr.IsValid() { 27 return nil, nil 28 } 29 return json.Marshal(addr.String()) 30 } 31 32 func (a *ListenAddress) UnmarshalJSON(content []byte) error { 33 var value string 34 err := json.Unmarshal(content, &value) 35 if err != nil { 36 return err 37 } 38 addr, err := netip.ParseAddr(value) 39 if err != nil { 40 return err 41 } 42 *a = ListenAddress(addr) 43 return nil 44 } 45 46 func (a *ListenAddress) Build() netip.Addr { 47 if a == nil { 48 return netip.AddrFrom4([4]byte{127, 0, 0, 1}) 49 } 50 return (netip.Addr)(*a) 51 } 52 53 type NetworkList string 54 55 func (v *NetworkList) UnmarshalJSON(content []byte) error { 56 var networkList []string 57 err := json.Unmarshal(content, &networkList) 58 if err != nil { 59 var networkItem string 60 err = json.Unmarshal(content, &networkItem) 61 if err != nil { 62 return err 63 } 64 networkList = []string{networkItem} 65 } 66 for _, networkName := range networkList { 67 switch networkName { 68 case N.NetworkTCP, N.NetworkUDP: 69 break 70 default: 71 return E.New("unknown network: " + networkName) 72 } 73 } 74 *v = NetworkList(strings.Join(networkList, "\n")) 75 return nil 76 } 77 78 func (v NetworkList) Build() []string { 79 if v == "" { 80 return []string{N.NetworkTCP, N.NetworkUDP} 81 } 82 return strings.Split(string(v), "\n") 83 } 84 85 type Listable[T comparable] []T 86 87 func (l Listable[T]) MarshalJSON() ([]byte, error) { 88 arrayList := []T(l) 89 if len(arrayList) == 1 { 90 return json.Marshal(arrayList[0]) 91 } 92 return json.Marshal(arrayList) 93 } 94 95 func (l *Listable[T]) UnmarshalJSON(content []byte) error { 96 err := json.Unmarshal(content, (*[]T)(l)) 97 if err == nil { 98 return nil 99 } 100 var singleItem T 101 newError := json.Unmarshal(content, &singleItem) 102 if newError != nil { 103 return E.Errors(err, newError) 104 } 105 *l = []T{singleItem} 106 return nil 107 } 108 109 type DomainStrategy dns.DomainStrategy 110 111 func (s DomainStrategy) MarshalJSON() ([]byte, error) { 112 var value string 113 switch dns.DomainStrategy(s) { 114 case dns.DomainStrategyAsIS: 115 value = "" 116 // value = "AsIS" 117 case dns.DomainStrategyPreferIPv4: 118 value = "prefer_ipv4" 119 case dns.DomainStrategyPreferIPv6: 120 value = "prefer_ipv6" 121 case dns.DomainStrategyUseIPv4: 122 value = "ipv4_only" 123 case dns.DomainStrategyUseIPv6: 124 value = "ipv6_only" 125 default: 126 return nil, E.New("unknown domain strategy: ", s) 127 } 128 return json.Marshal(value) 129 } 130 131 func (s *DomainStrategy) UnmarshalJSON(bytes []byte) error { 132 var value string 133 err := json.Unmarshal(bytes, &value) 134 if err != nil { 135 return err 136 } 137 switch value { 138 case "", "as_is": 139 *s = DomainStrategy(dns.DomainStrategyAsIS) 140 case "prefer_ipv4": 141 *s = DomainStrategy(dns.DomainStrategyPreferIPv4) 142 case "prefer_ipv6": 143 *s = DomainStrategy(dns.DomainStrategyPreferIPv6) 144 case "ipv4_only": 145 *s = DomainStrategy(dns.DomainStrategyUseIPv4) 146 case "ipv6_only": 147 *s = DomainStrategy(dns.DomainStrategyUseIPv6) 148 default: 149 return E.New("unknown domain strategy: ", value) 150 } 151 return nil 152 } 153 154 type Duration time.Duration 155 156 func (d Duration) MarshalJSON() ([]byte, error) { 157 return json.Marshal((time.Duration)(d).String()) 158 } 159 160 func (d *Duration) UnmarshalJSON(bytes []byte) error { 161 var value string 162 err := json.Unmarshal(bytes, &value) 163 if err != nil { 164 return err 165 } 166 duration, err := time.ParseDuration(value) 167 if err != nil { 168 return err 169 } 170 *d = Duration(duration) 171 return nil 172 } 173 174 type ListenPrefix netip.Prefix 175 176 func (p ListenPrefix) MarshalJSON() ([]byte, error) { 177 prefix := netip.Prefix(p) 178 if !prefix.IsValid() { 179 return json.Marshal(nil) 180 } 181 return json.Marshal(prefix.String()) 182 } 183 184 func (p *ListenPrefix) UnmarshalJSON(bytes []byte) error { 185 var value string 186 err := json.Unmarshal(bytes, &value) 187 if err != nil { 188 return err 189 } 190 prefix, err := netip.ParsePrefix(value) 191 if err != nil { 192 return err 193 } 194 *p = ListenPrefix(prefix) 195 return nil 196 } 197 198 func (p ListenPrefix) Build() netip.Prefix { 199 return netip.Prefix(p) 200 } 201 202 type DNSQueryType uint16 203 204 func (t DNSQueryType) MarshalJSON() ([]byte, error) { 205 typeName, loaded := mDNS.TypeToString[uint16(t)] 206 if loaded { 207 return json.Marshal(typeName) 208 } 209 return json.Marshal(uint16(t)) 210 } 211 212 func (t *DNSQueryType) UnmarshalJSON(bytes []byte) error { 213 var valueNumber uint16 214 err := json.Unmarshal(bytes, &valueNumber) 215 if err == nil { 216 *t = DNSQueryType(valueNumber) 217 return nil 218 } 219 var valueString string 220 err = json.Unmarshal(bytes, &valueString) 221 if err == nil { 222 queryType, loaded := mDNS.StringToType[valueString] 223 if loaded { 224 *t = DNSQueryType(queryType) 225 return nil 226 } 227 } 228 return E.New("unknown DNS query type: ", string(bytes)) 229 } 230 231 func DNSQueryTypeToString(queryType uint16) string { 232 typeName, loaded := mDNS.TypeToString[queryType] 233 if loaded { 234 return typeName 235 } 236 return F.ToString(queryType) 237 }