From 50aca5cfd1f26555b4a289180f43b2e3bf948f01 Mon Sep 17 00:00:00 2001 From: Can ZHANG Date: Wed, 5 Sep 2018 17:58:46 +0800 Subject: [PATCH 1/2] Expose the ability to specify external port when adding port map --- nat.go | 3 +++ natpmp.go | 18 ++++++++++++++++++ upnp.go | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/nat.go b/nat.go index 3cf9648..cd1c489 100644 --- a/nat.go +++ b/nat.go @@ -30,6 +30,9 @@ 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(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) From 072b1fd4c5f7a25ef9b05ffdd4645c6140ac518d Mon Sep 17 00:00:00 2001 From: Can ZHANG Date: Wed, 5 Sep 2018 17:59:10 +0800 Subject: [PATCH 2/2] Add comments and fix test --- _examples/nat-tester.go | 2 +- nat.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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 cd1c489..613b610 100644 --- a/nat.go +++ b/nat.go @@ -30,6 +30,7 @@ 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)