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  }