123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- package option
- import (
- "net/http"
- "net/netip"
- "strings"
- "time"
- "github.com/sagernet/sing-dns"
- E "github.com/sagernet/sing/common/exceptions"
- F "github.com/sagernet/sing/common/format"
- "github.com/sagernet/sing/common/json"
- N "github.com/sagernet/sing/common/network"
- mDNS "github.com/miekg/dns"
- )
- type ListenAddress netip.Addr
- func NewListenAddress(addr netip.Addr) *ListenAddress {
- address := ListenAddress(addr)
- return &address
- }
- func (a ListenAddress) MarshalJSON() ([]byte, error) {
- addr := netip.Addr(a)
- if !addr.IsValid() {
- return nil, nil
- }
- return json.Marshal(addr.String())
- }
- func (a *ListenAddress) UnmarshalJSON(content []byte) error {
- var value string
- err := json.Unmarshal(content, &value)
- if err != nil {
- return err
- }
- addr, err := netip.ParseAddr(value)
- if err != nil {
- return err
- }
- *a = ListenAddress(addr)
- return nil
- }
- func (a *ListenAddress) Build() netip.Addr {
- if a == nil {
- return netip.AddrFrom4([4]byte{127, 0, 0, 1})
- }
- return (netip.Addr)(*a)
- }
- type AddrPrefix netip.Prefix
- func (a AddrPrefix) MarshalJSON() ([]byte, error) {
- prefix := netip.Prefix(a)
- if prefix.Bits() == prefix.Addr().BitLen() {
- return json.Marshal(prefix.Addr().String())
- } else {
- return json.Marshal(prefix.String())
- }
- }
- func (a *AddrPrefix) UnmarshalJSON(content []byte) error {
- var value string
- err := json.Unmarshal(content, &value)
- if err != nil {
- return err
- }
- prefix, prefixErr := netip.ParsePrefix(value)
- if prefixErr == nil {
- *a = AddrPrefix(prefix)
- return nil
- }
- addr, addrErr := netip.ParseAddr(value)
- if addrErr == nil {
- *a = AddrPrefix(netip.PrefixFrom(addr, addr.BitLen()))
- return nil
- }
- return prefixErr
- }
- func (a *AddrPrefix) Build() netip.Prefix {
- if a == nil {
- return netip.Prefix{}
- }
- return netip.Prefix(*a)
- }
- type NetworkList string
- func (v *NetworkList) UnmarshalJSON(content []byte) error {
- var networkList []string
- err := json.Unmarshal(content, &networkList)
- if err != nil {
- var networkItem string
- err = json.Unmarshal(content, &networkItem)
- if err != nil {
- return err
- }
- networkList = []string{networkItem}
- }
- for _, networkName := range networkList {
- switch networkName {
- case N.NetworkTCP, N.NetworkUDP:
- break
- default:
- return E.New("unknown network: " + networkName)
- }
- }
- *v = NetworkList(strings.Join(networkList, "\n"))
- return nil
- }
- func (v NetworkList) Build() []string {
- if v == "" {
- return []string{N.NetworkTCP, N.NetworkUDP}
- }
- return strings.Split(string(v), "\n")
- }
- type Listable[T any] []T
- func (l Listable[T]) MarshalJSON() ([]byte, error) {
- arrayList := []T(l)
- if len(arrayList) == 1 {
- return json.Marshal(arrayList[0])
- }
- return json.Marshal(arrayList)
- }
- func (l *Listable[T]) UnmarshalJSON(content []byte) error {
- err := json.UnmarshalDisallowUnknownFields(content, (*[]T)(l))
- if err == nil {
- return nil
- }
- var singleItem T
- newError := json.UnmarshalDisallowUnknownFields(content, &singleItem)
- if newError != nil {
- return E.Errors(err, newError)
- }
- *l = []T{singleItem}
- return nil
- }
- type DomainStrategy dns.DomainStrategy
- func (s DomainStrategy) String() string {
- switch dns.DomainStrategy(s) {
- case dns.DomainStrategyAsIS:
- return ""
- case dns.DomainStrategyPreferIPv4:
- return "prefer_ipv4"
- case dns.DomainStrategyPreferIPv6:
- return "prefer_ipv6"
- case dns.DomainStrategyUseIPv4:
- return "ipv4_only"
- case dns.DomainStrategyUseIPv6:
- return "ipv6_only"
- default:
- panic(E.New("unknown domain strategy: ", s))
- }
- }
- func (s DomainStrategy) MarshalJSON() ([]byte, error) {
- var value string
- switch dns.DomainStrategy(s) {
- case dns.DomainStrategyAsIS:
- value = ""
- // value = "as_is"
- case dns.DomainStrategyPreferIPv4:
- value = "prefer_ipv4"
- case dns.DomainStrategyPreferIPv6:
- value = "prefer_ipv6"
- case dns.DomainStrategyUseIPv4:
- value = "ipv4_only"
- case dns.DomainStrategyUseIPv6:
- value = "ipv6_only"
- default:
- return nil, E.New("unknown domain strategy: ", s)
- }
- return json.Marshal(value)
- }
- func (s *DomainStrategy) UnmarshalJSON(bytes []byte) error {
- var value string
- err := json.Unmarshal(bytes, &value)
- if err != nil {
- return err
- }
- switch value {
- case "", "as_is":
- *s = DomainStrategy(dns.DomainStrategyAsIS)
- case "prefer_ipv4":
- *s = DomainStrategy(dns.DomainStrategyPreferIPv4)
- case "prefer_ipv6":
- *s = DomainStrategy(dns.DomainStrategyPreferIPv6)
- case "ipv4_only":
- *s = DomainStrategy(dns.DomainStrategyUseIPv4)
- case "ipv6_only":
- *s = DomainStrategy(dns.DomainStrategyUseIPv6)
- default:
- return E.New("unknown domain strategy: ", value)
- }
- return nil
- }
- type Duration time.Duration
- func (d Duration) MarshalJSON() ([]byte, error) {
- return json.Marshal((time.Duration)(d).String())
- }
- func (d *Duration) UnmarshalJSON(bytes []byte) error {
- var value string
- err := json.Unmarshal(bytes, &value)
- if err != nil {
- return err
- }
- duration, err := ParseDuration(value)
- if err != nil {
- return err
- }
- *d = Duration(duration)
- return nil
- }
- type DNSQueryType uint16
- func (t DNSQueryType) String() string {
- typeName, loaded := mDNS.TypeToString[uint16(t)]
- if loaded {
- return typeName
- }
- return F.ToString(uint16(t))
- }
- func (t DNSQueryType) MarshalJSON() ([]byte, error) {
- typeName, loaded := mDNS.TypeToString[uint16(t)]
- if loaded {
- return json.Marshal(typeName)
- }
- return json.Marshal(uint16(t))
- }
- func (t *DNSQueryType) UnmarshalJSON(bytes []byte) error {
- var valueNumber uint16
- err := json.Unmarshal(bytes, &valueNumber)
- if err == nil {
- *t = DNSQueryType(valueNumber)
- return nil
- }
- var valueString string
- err = json.Unmarshal(bytes, &valueString)
- if err == nil {
- queryType, loaded := mDNS.StringToType[valueString]
- if loaded {
- *t = DNSQueryType(queryType)
- return nil
- }
- }
- return E.New("unknown DNS query type: ", string(bytes))
- }
- func DNSQueryTypeToString(queryType uint16) string {
- typeName, loaded := mDNS.TypeToString[queryType]
- if loaded {
- return typeName
- }
- return F.ToString(queryType)
- }
- type HTTPHeader map[string]Listable[string]
- func (h HTTPHeader) Build() http.Header {
- header := make(http.Header)
- for name, values := range h {
- for _, value := range values {
- header.Add(name, value)
- }
- }
- return header
- }
|