package natpmp

import (
	
	
	
)

const nAT_PMP_PORT = 5351
const nAT_TRIES = 9
const nAT_INITIAL_MS = 250

// A caller that implements the NAT-PMP RPC protocol.
type network struct {
	gateway net.IP
}

func ( *network) ( []byte,  time.Duration) ( []byte,  error) {
	var  net.UDPAddr
	.IP = .gateway
	.Port = nAT_PMP_PORT
	,  := net.DialUDP("udp", nil, &)
	if  != nil {
		return
	}
	defer .Close()

	// 16 bytes is the maximum result size.
	 = make([]byte, 16)

	var  time.Time
	if  != 0 {
		 = time.Now().Add()
	}

	 := true

	var  uint
	for  = 0; ( < nAT_TRIES && .IsZero()) || time.Now().Before(); {
		if  {
			 := time.Now().Add((nAT_INITIAL_MS << ) * time.Millisecond)
			 = .SetDeadline(minTime(, ))
			if  != nil {
				return
			}
			 = false
		}
		_,  = .Write()
		if  != nil {
			return
		}
		var  int
		var  *net.UDPAddr
		, ,  = .ReadFromUDP()
		if  != nil {
			if .(net.Error).Timeout() {
				++
				 = true
				continue
			}
			return
		}
		if !.IP.Equal(.gateway) {
			// Ignore this packet.
			// Continue without increasing retransmission timeout or deadline.
			continue
		}
		// Trim result to actual number of bytes received
		if  < len() {
			 = [:]
		}
		return
	}
	 = fmt.Errorf("Timed out trying to contact gateway")
	return
}

func minTime(,  time.Time) time.Time {
	if .IsZero() {
		return 
	}
	if .IsZero() {
		return 
	}
	if .Before() {
		return 
	}
	return 
}