github.com/sagernet/sing-box@v1.9.0-rc.20/option/types.go (about)

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