github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/ipv4/addr.go (about)

     1  /* For license and copyright information please see LEGAL file in repository */
     2  
     3  package ipv4
     4  
     5  import "../protocol"
     6  
     7  // An Addr is an IP address version 4.
     8  type Addr [Addrlen]byte
     9  
    10  const (
    11  	// Addrlen address lengths 32 bit equal 4 byte.
    12  	Addrlen = 4
    13  )
    14  
    15  // Well-known IPv4 addresses
    16  var (
    17  	AddrZero       = Addr{0, 0, 0, 0}         // all zeros
    18  	AddrAllRouters = Addr{224, 0, 0, 2}       // all routers
    19  	AddrAllSystems = Addr{224, 0, 0, 1}       // all systems
    20  	AddrBroadcast  = Addr{255, 255, 255, 255} // limited broadcast
    21  
    22  	v4InV6Prefix = [12]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
    23  )
    24  
    25  // ToIPv6 returns the IPv4 address in 16-byte form
    26  func (addr Addr) ToIPv6() (v6 [16]byte) {
    27  	copy(v6[:], v4InV6Prefix)
    28  	copy(v6[12:], addr[:])
    29  	return
    30  }
    31  
    32  func (addr Addr) ToString() string {
    33  	const maxIPv4StringLen = len("255.255.255.255")
    34  	var b = make([]byte, maxIPv4StringLen)
    35  
    36  	var n = ubtoa(b, 0, addr[0])
    37  	b[n] = '.'
    38  	n++
    39  
    40  	n += ubtoa(b, n, addr[1])
    41  	b[n] = '.'
    42  	n++
    43  
    44  	n += ubtoa(b, n, addr[2])
    45  	b[n] = '.'
    46  	n++
    47  
    48  	n += ubtoa(b, n, addr[3])
    49  	return string(b[:n])
    50  }
    51  
    52  func (addr *Addr) FromString(ipv4 string) (err protocol.Error) {
    53  	for i := 0; i < Addrlen; i++ {
    54  		if len(ipv4) == 0 {
    55  			// err = Missing octets
    56  			return
    57  		}
    58  		if i > 0 {
    59  			if ipv4[0] != '.' {
    60  				// err =
    61  				return
    62  			}
    63  			ipv4 = ipv4[1:]
    64  		}
    65  		n, c, ok := dtoi(ipv4)
    66  		if !ok || n > 0xFF {
    67  			// err =
    68  			return
    69  		}
    70  		if c > 1 && ipv4[0] == '0' {
    71  			// err = Reject non-zero components with leading zeroes.
    72  			return
    73  		}
    74  		ipv4 = ipv4[c:]
    75  		*addr[i] = byte(n)
    76  	}
    77  	if len(ipv4) != 0 {
    78  		// Mask??
    79  		// err =
    80  	}
    81  	return
    82  }
    83  
    84  // ubtoa encodes the string form of the integer v to dst[start:] and
    85  // returns the number of bytes written to dst. The caller must ensure
    86  // that dst has sufficient length.
    87  func ubtoa(dst []byte, start int, v byte) int {
    88  	if v < 10 {
    89  		dst[start] = v + '0'
    90  		return 1
    91  	} else if v < 100 {
    92  		dst[start+1] = v%10 + '0'
    93  		dst[start] = v/10 + '0'
    94  		return 2
    95  	}
    96  
    97  	dst[start+2] = v%10 + '0'
    98  	dst[start+1] = (v/10)%10 + '0'
    99  	dst[start] = v/100 + '0'
   100  	return 3
   101  }
   102  
   103  // Decimal to integer.
   104  // Returns number, characters consumed, success.
   105  func dtoi(s string) (n int, i int, ok bool) {
   106  	n = 0
   107  	for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
   108  		n = n*10 + int(s[i]-'0')
   109  		if n >= big {
   110  			return big, i, false
   111  		}
   112  	}
   113  	if i == 0 {
   114  		return 0, 0, false
   115  	}
   116  	return n, i, true
   117  }