package natpmp
import (
"fmt"
"net"
"time"
)
const nAT_PMP_PORT = 5351
const nAT_TRIES = 9
const nAT_INITIAL_MS = 250
type network struct {
gateway net .IP
}
func (n *network ) call (msg []byte , timeout time .Duration ) (result []byte , err error ) {
var server net .UDPAddr
server .IP = n .gateway
server .Port = nAT_PMP_PORT
conn , err := net .DialUDP ("udp" , nil , &server )
if err != nil {
return
}
defer conn .Close ()
result = make ([]byte , 16 )
var finalTimeout time .Time
if timeout != 0 {
finalTimeout = time .Now ().Add (timeout )
}
needNewDeadline := true
var tries uint
for tries = 0 ; (tries < nAT_TRIES && finalTimeout .IsZero ()) || time .Now ().Before (finalTimeout ); {
if needNewDeadline {
nextDeadline := time .Now ().Add ((nAT_INITIAL_MS << tries ) * time .Millisecond )
err = conn .SetDeadline (minTime (nextDeadline , finalTimeout ))
if err != nil {
return
}
needNewDeadline = false
}
_, err = conn .Write (msg )
if err != nil {
return
}
var bytesRead int
var remoteAddr *net .UDPAddr
bytesRead , remoteAddr , err = conn .ReadFromUDP (result )
if err != nil {
if err .(net .Error ).Timeout () {
tries ++
needNewDeadline = true
continue
}
return
}
if !remoteAddr .IP .Equal (n .gateway ) {
continue
}
if bytesRead < len (result ) {
result = result [:bytesRead ]
}
return
}
err = fmt .Errorf ("Timed out trying to contact gateway" )
return
}
func minTime(a , b time .Time ) time .Time {
if a .IsZero () {
return b
}
if b .IsZero () {
return a
}
if a .Before (b ) {
return a
}
return b
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .