github.com/decred/dcrlnd@v0.7.6/channeldb/addr.go (about)

     1  package channeldb
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"net"
     9  
    10  	"github.com/decred/dcrlnd/tor"
    11  )
    12  
    13  // addressType specifies the network protocol and version that should be used
    14  // when connecting to a node at a particular address.
    15  type addressType uint8
    16  
    17  const (
    18  	// tcp4Addr denotes an IPv4 TCP address.
    19  	tcp4Addr addressType = 0
    20  
    21  	// tcp6Addr denotes an IPv6 TCP address.
    22  	tcp6Addr addressType = 1
    23  
    24  	// v2OnionAddr denotes a version 2 Tor onion service address.
    25  	v2OnionAddr addressType = 2
    26  
    27  	// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
    28  	v3OnionAddr addressType = 3
    29  )
    30  
    31  // encodeTCPAddr serializes a TCP address into its compact raw bytes
    32  // representation.
    33  func encodeTCPAddr(w io.Writer, addr *net.TCPAddr) error {
    34  	var (
    35  		addrType byte
    36  		ip       []byte
    37  	)
    38  
    39  	if addr.IP.To4() != nil {
    40  		addrType = byte(tcp4Addr)
    41  		ip = addr.IP.To4()
    42  	} else {
    43  		addrType = byte(tcp6Addr)
    44  		ip = addr.IP.To16()
    45  	}
    46  
    47  	if ip == nil {
    48  		return fmt.Errorf("unable to encode IP %v", addr.IP)
    49  	}
    50  
    51  	if _, err := w.Write([]byte{addrType}); err != nil {
    52  		return err
    53  	}
    54  
    55  	if _, err := w.Write(ip); err != nil {
    56  		return err
    57  	}
    58  
    59  	var port [2]byte
    60  	byteOrder.PutUint16(port[:], uint16(addr.Port))
    61  	if _, err := w.Write(port[:]); err != nil {
    62  		return err
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  // encodeOnionAddr serializes an onion address into its compact raw bytes
    69  // representation.
    70  func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
    71  	var suffixIndex int
    72  	hostLen := len(addr.OnionService)
    73  	switch hostLen {
    74  	case tor.V2Len:
    75  		if _, err := w.Write([]byte{byte(v2OnionAddr)}); err != nil {
    76  			return err
    77  		}
    78  		suffixIndex = tor.V2Len - tor.OnionSuffixLen
    79  	case tor.V3Len:
    80  		if _, err := w.Write([]byte{byte(v3OnionAddr)}); err != nil {
    81  			return err
    82  		}
    83  		suffixIndex = tor.V3Len - tor.OnionSuffixLen
    84  	default:
    85  		return errors.New("unknown onion service length")
    86  	}
    87  
    88  	suffix := addr.OnionService[suffixIndex:]
    89  	if suffix != tor.OnionSuffix {
    90  		return fmt.Errorf("invalid suffix \"%v\"", suffix)
    91  	}
    92  
    93  	host, err := tor.Base32Encoding.DecodeString(
    94  		addr.OnionService[:suffixIndex],
    95  	)
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	// Sanity check the decoded length.
   101  	switch {
   102  	case hostLen == tor.V2Len && len(host) != tor.V2DecodedLen:
   103  		return fmt.Errorf("onion service %v decoded to invalid host %x",
   104  			addr.OnionService, host)
   105  
   106  	case hostLen == tor.V3Len && len(host) != tor.V3DecodedLen:
   107  		return fmt.Errorf("onion service %v decoded to invalid host %x",
   108  			addr.OnionService, host)
   109  	}
   110  
   111  	if _, err := w.Write(host); err != nil {
   112  		return err
   113  	}
   114  
   115  	var port [2]byte
   116  	byteOrder.PutUint16(port[:], uint16(addr.Port))
   117  	if _, err := w.Write(port[:]); err != nil {
   118  		return err
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  // deserializeAddr reads the serialized raw representation of an address and
   125  // deserializes it into the actual address. This allows us to avoid address
   126  // resolution within the channeldb package.
   127  func deserializeAddr(r io.Reader) (net.Addr, error) {
   128  	var addrType [1]byte
   129  	if _, err := r.Read(addrType[:]); err != nil {
   130  		return nil, err
   131  	}
   132  
   133  	var address net.Addr
   134  	switch addressType(addrType[0]) {
   135  	case tcp4Addr:
   136  		var ip [4]byte
   137  		if _, err := r.Read(ip[:]); err != nil {
   138  			return nil, err
   139  		}
   140  
   141  		var port [2]byte
   142  		if _, err := r.Read(port[:]); err != nil {
   143  			return nil, err
   144  		}
   145  
   146  		address = &net.TCPAddr{
   147  			IP:   net.IP(ip[:]),
   148  			Port: int(binary.BigEndian.Uint16(port[:])),
   149  		}
   150  	case tcp6Addr:
   151  		var ip [16]byte
   152  		if _, err := r.Read(ip[:]); err != nil {
   153  			return nil, err
   154  		}
   155  
   156  		var port [2]byte
   157  		if _, err := r.Read(port[:]); err != nil {
   158  			return nil, err
   159  		}
   160  
   161  		address = &net.TCPAddr{
   162  			IP:   net.IP(ip[:]),
   163  			Port: int(binary.BigEndian.Uint16(port[:])),
   164  		}
   165  	case v2OnionAddr:
   166  		var h [tor.V2DecodedLen]byte
   167  		if _, err := r.Read(h[:]); err != nil {
   168  			return nil, err
   169  		}
   170  
   171  		var p [2]byte
   172  		if _, err := r.Read(p[:]); err != nil {
   173  			return nil, err
   174  		}
   175  
   176  		onionService := tor.Base32Encoding.EncodeToString(h[:])
   177  		onionService += tor.OnionSuffix
   178  		port := int(binary.BigEndian.Uint16(p[:]))
   179  
   180  		address = &tor.OnionAddr{
   181  			OnionService: onionService,
   182  			Port:         port,
   183  		}
   184  	case v3OnionAddr:
   185  		var h [tor.V3DecodedLen]byte
   186  		if _, err := r.Read(h[:]); err != nil {
   187  			return nil, err
   188  		}
   189  
   190  		var p [2]byte
   191  		if _, err := r.Read(p[:]); err != nil {
   192  			return nil, err
   193  		}
   194  
   195  		onionService := tor.Base32Encoding.EncodeToString(h[:])
   196  		onionService += tor.OnionSuffix
   197  		port := int(binary.BigEndian.Uint16(p[:]))
   198  
   199  		address = &tor.OnionAddr{
   200  			OnionService: onionService,
   201  			Port:         port,
   202  		}
   203  	default:
   204  		return nil, ErrUnknownAddressType
   205  	}
   206  
   207  	return address, nil
   208  }
   209  
   210  // serializeAddr serializes an address into its raw bytes representation so that
   211  // it can be deserialized without requiring address resolution.
   212  func serializeAddr(w io.Writer, address net.Addr) error {
   213  	switch addr := address.(type) {
   214  	case *net.TCPAddr:
   215  		return encodeTCPAddr(w, addr)
   216  	case *tor.OnionAddr:
   217  		return encodeOnionAddr(w, addr)
   218  	default:
   219  		return ErrUnknownAddressType
   220  	}
   221  }