// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	

	
)

// provided by runtime
func fastrand() uint32

func randInt() int {
	,  := fastrand(), fastrand()    // 32-bit halves
	 := uint()<<31 ^ uint(int32()) // full uint, even on 64-bit systems; avoid 32-bit shift on 32-bit systems
	 := int( >> 1)                  // clear sign bit, even on 32-bit systems
	return 
}

func randIntn( int) int {
	return randInt() % 
}

// reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
// address addr suitable for rDNS (PTR) record lookup or an error if it fails
// to parse the IP address.
func reverseaddr( string) ( string,  error) {
	 := ParseIP()
	if  == nil {
		return "", &DNSError{Err: "unrecognized address", Name: }
	}
	if .To4() != nil {
		return uitoa(uint([15])) + "." + uitoa(uint([14])) + "." + uitoa(uint([13])) + "." + uitoa(uint([12])) + ".in-addr.arpa.", nil
	}
	// Must be IPv6
	 := make([]byte, 0, len()*4+len("ip6.arpa."))
	// Add it, in reverse, to the buffer
	for  := len() - 1;  >= 0; -- {
		 := []
		 = append(, hexDigit[&0xF],
			'.',
			hexDigit[>>4],
			'.')
	}
	// Append "ip6.arpa." and return (buf already has the final .)
	 = append(, "ip6.arpa."...)
	return string(), nil
}

func equalASCIIName(,  dnsmessage.Name) bool {
	if .Length != .Length {
		return false
	}
	for  := 0;  < int(.Length); ++ {
		 := .Data[]
		 := .Data[]
		if 'A' <=  &&  <= 'Z' {
			 += 0x20
		}
		if 'A' <=  &&  <= 'Z' {
			 += 0x20
		}
		if  !=  {
			return false
		}
	}
	return true
}

// isDomainName checks if a string is a presentation-format domain name
// (currently restricted to hostname-compatible "preferred name" LDH labels and
// SRV-like "underscore labels"; see golang.org/issue/12421).
func isDomainName( string) bool {
	// See RFC 1035, RFC 3696.
	// Presentation format has dots before every label except the first, and the
	// terminal empty label is optional here because we assume fully-qualified
	// (absolute) input. We must therefore reserve space for the first and last
	// labels' length octets in wire format, where they are necessary and the
	// maximum total length is 255.
	// So our _effective_ maximum is 253, but 254 is not rejected if the last
	// character is a dot.
	 := len()
	if  == 0 ||  > 254 ||  == 254 && [-1] != '.' {
		return false
	}

	 := byte('.')
	 := false // true once we've seen a letter or hyphen
	 := 0
	for  := 0;  < len(); ++ {
		 := []
		switch {
		default:
			return false
		case 'a' <=  &&  <= 'z' || 'A' <=  &&  <= 'Z' ||  == '_':
			 = true
			++
		case '0' <=  &&  <= '9':
			// fine
			++
		case  == '-':
			// Byte before dash cannot be dot.
			if  == '.' {
				return false
			}
			++
			 = true
		case  == '.':
			// Byte before dot cannot be dot, dash.
			if  == '.' ||  == '-' {
				return false
			}
			if  > 63 ||  == 0 {
				return false
			}
			 = 0
		}
		 = 
	}
	if  == '-' ||  > 63 {
		return false
	}

	return 
}

// absDomainName returns an absolute domain name which ends with a
// trailing dot to match pure Go reverse resolver and all other lookup
// routines.
// See golang.org/issue/12189.
// But we don't want to add dots for local names from /etc/hosts.
// It's hard to tell so we settle on the heuristic that names without dots
// (like "localhost" or "myhost") do not get trailing dots, but any other
// names do.
func absDomainName( []byte) string {
	 := false
	for ,  := range  {
		if  == '.' {
			 = true
			break
		}
	}
	if  && [len()-1] != '.' {
		 = append(, '.')
	}
	return string()
}

// An SRV represents a single DNS SRV record.
type SRV struct {
	Target   string
	Port     uint16
	Priority uint16
	Weight   uint16
}

// byPriorityWeight sorts SRV records by ascending priority and weight.
type byPriorityWeight []*SRV

func ( byPriorityWeight) () int { return len() }
func ( byPriorityWeight) (,  int) bool {
	return [].Priority < [].Priority || ([].Priority == [].Priority && [].Weight < [].Weight)
}
func ( byPriorityWeight) (,  int) { [], [] = [], [] }

// shuffleByWeight shuffles SRV records by weight using the algorithm
// described in RFC 2782.
func ( byPriorityWeight) () {
	 := 0
	for ,  := range  {
		 += int(.Weight)
	}
	for  > 0 && len() > 1 {
		 := 0
		 := randIntn()
		for  := range  {
			 += int([].Weight)
			if  >  {
				if  > 0 {
					[0], [] = [], [0]
				}
				break
			}
		}
		 -= int([0].Weight)
		 = [1:]
	}
}

// sort reorders SRV records as specified in RFC 2782.
func ( byPriorityWeight) () {
	sort.Sort()
	 := 0
	for  := 1;  < len(); ++ {
		if [].Priority != [].Priority {
			[:].shuffleByWeight()
			 = 
		}
	}
	[:].shuffleByWeight()
}

// An MX represents a single DNS MX record.
type MX struct {
	Host string
	Pref uint16
}

// byPref implements sort.Interface to sort MX records by preference
type byPref []*MX

func ( byPref) () int           { return len() }
func ( byPref) (,  int) bool { return [].Pref < [].Pref }
func ( byPref) (,  int)      { [], [] = [], [] }

// sort reorders MX records as specified in RFC 5321.
func ( byPref) () {
	for  := range  {
		 := randIntn( + 1)
		[], [] = [], []
	}
	sort.Sort()
}

// An NS represents a single DNS NS record.
type NS struct {
	Host string
}