55 lines
1.5 KiB
Go
55 lines
1.5 KiB
Go
// Package nat implements NAT handling facilities
|
|
package nat
|
|
|
|
import (
|
|
"errors"
|
|
"math"
|
|
"math/rand"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
var ErrNoExternalAddress = errors.New("no external address")
|
|
var ErrNoInternalAddress = errors.New("no internal address")
|
|
var ErrNoNATFound = errors.New("no NAT found")
|
|
|
|
// protocol is either "udp" or "tcp"
|
|
type NAT interface {
|
|
// Type returns the kind of NAT port mapping service that is used
|
|
Type() string
|
|
|
|
// GetDeviceAddress returns the internal address of the gateway device.
|
|
GetDeviceAddress() (addr net.IP, err error)
|
|
|
|
// GetExternalAddress returns the external address of the gateway device.
|
|
GetExternalAddress() (addr net.IP, err error)
|
|
|
|
// GetInternalAddress returns the address of the local host.
|
|
GetInternalAddress() (addr net.IP, err error)
|
|
|
|
// AddPortMapping maps a port on the local host to an external port.
|
|
AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (mappedExternalPort int, err error)
|
|
|
|
// DeletePortMapping removes a port mapping.
|
|
DeletePortMapping(protocol string, internalPort int) (err error)
|
|
}
|
|
|
|
// DiscoverGateway attempts to find a gateway device.
|
|
func DiscoverGateway() (NAT, error) {
|
|
select {
|
|
case nat := <-discoverUPNP_IG1():
|
|
return nat, nil
|
|
case nat := <-discoverUPNP_IG2():
|
|
return nat, nil
|
|
case nat := <-discoverNATPMP():
|
|
return nat, nil
|
|
case <-time.After(10 * time.Second):
|
|
return nil, ErrNoNATFound
|
|
}
|
|
}
|
|
|
|
func randomPort() int {
|
|
rand.Seed(time.Now().UnixNano())
|
|
return rand.Intn(math.MaxUint16-10000) + 10000
|
|
}
|