diff --git a/_examples/nat-tester.go b/_examples/nat-tester.go index f2f3bc9..542f719 100644 --- a/_examples/nat-tester.go +++ b/_examples/nat-tester.go @@ -52,7 +52,7 @@ func main() { } }() - defer nat.DeletePortMapping("txp", 3080) + defer nat.DeletePortMapping("tcp", 3080) http.ListenAndServe(":3080", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Content-Type", "text/plain") diff --git a/nat.go b/nat.go index 3cf9648..613b610 100644 --- a/nat.go +++ b/nat.go @@ -30,6 +30,10 @@ type NAT interface { // 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) + // AddPortMappingSpecifyExternalPort maps a port on the local host to a specified external port. + AddPortMappingSpecifyExternalPort(protocol string, internalPort, externalPort int, + description string, timeout time.Duration) (mappedExternalPort int, err error) + // DeletePortMapping removes a port mapping. DeletePortMapping(protocol string, internalPort int) (err error) } diff --git a/natpmp.go b/natpmp.go index 395a5dd..6cc7e83 100644 --- a/natpmp.go +++ b/natpmp.go @@ -105,6 +105,24 @@ func (n *natpmpNAT) AddPortMapping(protocol string, internalPort int, descriptio return 0, err } +func (n *natpmpNAT) AddPortMappingSpecifyExternalPort(protocol string, internalPort, externalPort int, + description string, timeout time.Duration) (int, error) { + + var ( + err error + ) + + timeoutInSeconds := int(timeout / time.Second) + + _, err = n.c.AddPortMapping(protocol, internalPort, externalPort, timeoutInSeconds) + if err == nil { + n.ports[internalPort] = externalPort + return externalPort, nil + } + + return 0, err +} + func (n *natpmpNAT) DeletePortMapping(protocol string, internalPort int) (err error) { delete(n.ports, internalPort) return nil diff --git a/upnp.go b/upnp.go index 86d6e9b..b39a5c4 100644 --- a/upnp.go +++ b/upnp.go @@ -188,6 +188,24 @@ func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description return 0, err } +func (u *upnp_NAT) AddPortMappingSpecifyExternalPort(protocol string, internalPort, externalPort int, + description string, timeout time.Duration) (int, error) { + + ip, err := u.GetInternalAddress() + if err != nil { + return 0, nil + } + + timeoutInSeconds := uint32(timeout / time.Second) + + err = u.c.AddPortMapping("", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), + ip.String(), true, description, timeoutInSeconds) + if err != nil { + return 0, err + } + return externalPort, nil +} + func (u *upnp_NAT) DeletePortMapping(protocol string, internalPort int) error { if externalPort := u.ports[internalPort]; externalPort > 0 { delete(u.ports, internalPort)