igd.go 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright (C) 2016 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. // Adapted from https://github.com/jackpal/Taipei-Torrent/blob/dd88a8bfac6431c01d959ce3c745e74b8a911793/IGD.go
  7. // Copyright (c) 2010 Jack Palevich (https://github.com/jackpal/Taipei-Torrent/blob/dd88a8bfac6431c01d959ce3c745e74b8a911793/LICENSE)
  8. package upnp
  9. import (
  10. "net"
  11. "net/url"
  12. "strings"
  13. )
  14. // An IGD is a UPnP InternetGatewayDevice.
  15. type IGD struct {
  16. uuid string
  17. friendlyName string
  18. services []IGDService
  19. url *url.URL
  20. localIPAddress net.IP
  21. }
  22. func (n *IGD) UUID() string {
  23. return n.uuid
  24. }
  25. func (n *IGD) FriendlyName() string {
  26. return n.friendlyName
  27. }
  28. // FriendlyIdentifier returns a friendly identifier (friendly name + IP
  29. // address) for the IGD.
  30. func (n *IGD) FriendlyIdentifier() string {
  31. return "'" + n.FriendlyName() + "' (" + strings.Split(n.URL().Host, ":")[0] + ")"
  32. }
  33. func (n *IGD) URL() *url.URL {
  34. return n.url
  35. }
  36. // AddPortMapping adds a port mapping to all relevant services on the
  37. // specified InternetGatewayDevice. Port mapping will fail and return an error
  38. // if action is fails for _any_ of the relevant services. For this reason, it
  39. // is generally better to configure port mapping for each individual service
  40. // instead.
  41. func (n *IGD) AddPortMapping(protocol Protocol, externalPort, internalPort int, description string, timeout int) error {
  42. for _, service := range n.services {
  43. err := service.AddPortMapping(n.localIPAddress, protocol, externalPort, internalPort, description, timeout)
  44. if err != nil {
  45. return err
  46. }
  47. }
  48. return nil
  49. }
  50. // DeletePortMapping deletes a port mapping from all relevant services on the
  51. // specified InternetGatewayDevice. Port mapping will fail and return an error
  52. // if action is fails for _any_ of the relevant services. For this reason, it
  53. // is generally better to configure port mapping for each individual service
  54. // instead.
  55. func (n *IGD) DeletePortMapping(protocol Protocol, externalPort int) error {
  56. for _, service := range n.services {
  57. err := service.DeletePortMapping(protocol, externalPort)
  58. if err != nil {
  59. return err
  60. }
  61. }
  62. return nil
  63. }
  64. // GetExternalIPAddress returns the external IP address of the IGD, or an error
  65. // if no service providing this feature exists.
  66. func (n *IGD) GetExternalIPAddress() (ip net.IP, err error) {
  67. for _, service := range n.services {
  68. ip, err = service.GetExternalIPAddress()
  69. if err == nil {
  70. break
  71. }
  72. }
  73. return
  74. }
  75. // GetLocalIPAddress returns the IP address of the local network interface
  76. // which is facing the IGD.
  77. func (n *IGD) GetLocalIPAddress() net.IP {
  78. return n.localIPAddress
  79. }