natpmp.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package eth
  2. import (
  3. "fmt"
  4. "net"
  5. natpmp "github.com/jackpal/go-nat-pmp"
  6. )
  7. // Adapt the NAT-PMP protocol to the NAT interface
  8. // TODO:
  9. // + Register for changes to the external address.
  10. // + Re-register port mapping when router reboots.
  11. // + A mechanism for keeping a port mapping registered.
  12. type natPMPClient struct {
  13. client *natpmp.Client
  14. }
  15. func NewNatPMP(gateway net.IP) (nat NAT) {
  16. return &natPMPClient{natpmp.NewClient(gateway)}
  17. }
  18. func (n *natPMPClient) GetExternalAddress() (addr net.IP, err error) {
  19. response, err := n.client.GetExternalAddress()
  20. if err != nil {
  21. return
  22. }
  23. ip := response.ExternalIPAddress
  24. addr = net.IPv4(ip[0], ip[1], ip[2], ip[3])
  25. return
  26. }
  27. func (n *natPMPClient) AddPortMapping(protocol string, externalPort, internalPort int,
  28. description string, timeout int) (mappedExternalPort int, err error) {
  29. if timeout <= 0 {
  30. err = fmt.Errorf("timeout must not be <= 0")
  31. return
  32. }
  33. // Note order of port arguments is switched between our AddPortMapping and the client's AddPortMapping.
  34. response, err := n.client.AddPortMapping(protocol, internalPort, externalPort, timeout)
  35. if err != nil {
  36. return
  37. }
  38. mappedExternalPort = int(response.MappedExternalPort)
  39. return
  40. }
  41. func (n *natPMPClient) DeletePortMapping(protocol string, externalPort, internalPort int) (err error) {
  42. // To destroy a mapping, send an add-port with
  43. // an internalPort of the internal port to destroy, an external port of zero and a time of zero.
  44. _, err = n.client.AddPortMapping(protocol, internalPort, 0, 0)
  45. return
  46. }