github.com/sagernet/sing-box@v1.9.0-rc.20/common/srs/ip_set.go (about)

     1  package srs
     2  
     3  import (
     4  	"encoding/binary"
     5  	"io"
     6  	"net/netip"
     7  	"unsafe"
     8  
     9  	"github.com/sagernet/sing/common/rw"
    10  
    11  	"go4.org/netipx"
    12  )
    13  
    14  type myIPSet struct {
    15  	rr []myIPRange
    16  }
    17  
    18  type myIPRange struct {
    19  	from netip.Addr
    20  	to   netip.Addr
    21  }
    22  
    23  func readIPSet(reader io.Reader) (*netipx.IPSet, error) {
    24  	var version uint8
    25  	err := binary.Read(reader, binary.BigEndian, &version)
    26  	if err != nil {
    27  		return nil, err
    28  	}
    29  	var length uint64
    30  	err = binary.Read(reader, binary.BigEndian, &length)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	mySet := &myIPSet{
    35  		rr: make([]myIPRange, length),
    36  	}
    37  	for i := uint64(0); i < length; i++ {
    38  		var (
    39  			fromLen  uint64
    40  			toLen    uint64
    41  			fromAddr netip.Addr
    42  			toAddr   netip.Addr
    43  		)
    44  		fromLen, err = rw.ReadUVariant(reader)
    45  		if err != nil {
    46  			return nil, err
    47  		}
    48  		fromBytes := make([]byte, fromLen)
    49  		_, err = io.ReadFull(reader, fromBytes)
    50  		if err != nil {
    51  			return nil, err
    52  		}
    53  		err = fromAddr.UnmarshalBinary(fromBytes)
    54  		if err != nil {
    55  			return nil, err
    56  		}
    57  		toLen, err = rw.ReadUVariant(reader)
    58  		if err != nil {
    59  			return nil, err
    60  		}
    61  		toBytes := make([]byte, toLen)
    62  		_, err = io.ReadFull(reader, toBytes)
    63  		if err != nil {
    64  			return nil, err
    65  		}
    66  		err = toAddr.UnmarshalBinary(toBytes)
    67  		if err != nil {
    68  			return nil, err
    69  		}
    70  		mySet.rr[i] = myIPRange{fromAddr, toAddr}
    71  	}
    72  	return (*netipx.IPSet)(unsafe.Pointer(mySet)), nil
    73  }
    74  
    75  func writeIPSet(writer io.Writer, set *netipx.IPSet) error {
    76  	err := binary.Write(writer, binary.BigEndian, uint8(1))
    77  	if err != nil {
    78  		return err
    79  	}
    80  	mySet := (*myIPSet)(unsafe.Pointer(set))
    81  	err = binary.Write(writer, binary.BigEndian, uint64(len(mySet.rr)))
    82  	if err != nil {
    83  		return err
    84  	}
    85  	for _, rr := range mySet.rr {
    86  		var (
    87  			fromBinary []byte
    88  			toBinary   []byte
    89  		)
    90  		fromBinary, err = rr.from.MarshalBinary()
    91  		if err != nil {
    92  			return err
    93  		}
    94  		err = rw.WriteUVariant(writer, uint64(len(fromBinary)))
    95  		if err != nil {
    96  			return err
    97  		}
    98  		_, err = writer.Write(fromBinary)
    99  		if err != nil {
   100  			return err
   101  		}
   102  		toBinary, err = rr.to.MarshalBinary()
   103  		if err != nil {
   104  			return err
   105  		}
   106  		err = rw.WriteUVariant(writer, uint64(len(toBinary)))
   107  		if err != nil {
   108  			return err
   109  		}
   110  		_, err = writer.Write(toBinary)
   111  		if err != nil {
   112  			return err
   113  		}
   114  	}
   115  	return nil
   116  }