You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

393 lines
10 KiB

9 years ago
9 years ago
return an error if we fail to parse external IP ``` I[06-08|11:51:57.234] Getting UPNP external address module=p2p I[06-08|11:51:58.867] Got UPNP external address module=p2p address= ``` Fixes #1717 ``` I[06-08|11:51:56.952] Starting multiAppConn module=proxy impl=multiAppConn I[06-08|11:51:56.952] Starting localClient module=abci-client connection=query impl=localClient I[06-08|11:51:56.952] Starting localClient module=abci-client connection=mempool impl=localClient I[06-08|11:51:56.952] Starting localClient module=abci-client connection=consensus impl=localClient I[06-08|11:51:56.952] ABCI Handshake module=consensus appHeight=0 appHash= I[06-08|11:51:56.952] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 I[06-08|11:51:57.053] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=0 appHash= I[06-08|11:51:57.053] This node is a validator module=consensus addr=6816B5D9BAC32A3CDF07884D9D3D2650694C371D pubKey=PubKeyEd25519{27A40CD032DD2467342D0CF27C5EC92052D966FEC714B6CF2F3BF3146AFD0D51} I[06-08|11:51:57.234] Starting Node module=main impl=Node I[06-08|11:51:57.234] Starting EventBus module=events impl=EventBus I[06-08|11:51:57.234] Local listener module=p2p ip=:: port=46656 I[06-08|11:51:57.234] Getting UPNP external address module=p2p I[06-08|11:51:58.867] Got UPNP external address module=p2p address= I[06-08|11:51:58.867] Starting DefaultListener module=p2p impl=Listener(@<nil>:46656) I[06-08|11:51:58.867] P2P Node ID module=main ID=3629b516392e494ae717ac4c6a1ea7eb0fe421c3 file=/home/tpb/.tendermint/config/node_key.json I[06-08|11:51:58.868] Add our address to book module=p2p book=/home/tpb/.tendermint/config/addrbook.json addr=null panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x89fb86] goroutine 1 [running]: github.com/tendermint/tendermint/p2p.(*NetAddress).String(0x0, 0xc96e24, 0x17) /home/tpb/code/go/src/github.com/tendermint/tendermint/p2p/netaddress.go:171 +0x26 github.com/tendermint/tendermint/p2p/pex.(*addrBook).AddOurAddress(0xc420190620, 0x0) /home/tpb/code/go/src/github.com/tendermint/tendermint/p2p/pex/addrbook.go:160 +0x116 github.com/tendermint/tendermint/node.(*Node).OnStart(0xc420286d00, 0xc4201b8010, 0xd) /home/tpb/code/go/src/github.com/tendermint/tendermint/node/node.go:402 +0x547 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start(0xc420286d00, 0xe51c40, 0xc42000bd40) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x3bd github.com/tendermint/tendermint/cmd/tendermint/commands.NewRunNodeCmd.func1(0xc42022e000, 0xc4200acdc0, 0x0, 0x1, 0x0, 0x0) /home/tpb/code/go/src/github.com/tendermint/tendermint/cmd/tendermint/commands/run_node.go:58 +0xfe github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).execute(0xc42022e000, 0xc4200acda0, 0x1, 0x1, 0xc42022e000, 0xc4200acda0) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:762 +0x468 github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0x1289280, 0xbbdda0, 0xc420015e01, 0xc4201bc640) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:852 +0x30a github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).Execute(0x1289280, 0xc4201bc640, 0xc420015e98) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:800 +0x2b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/cli.Executor.Execute(0x1289280, 0xde5798, 0x2, 0xc4200332c0) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/cli/setup.go:89 +0x4e main.main() /home/tpb/code/go/src/github.com/tendermint/tendermint/cmd/tendermint/main.go:45 +0x24d ```
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
return an error if we fail to parse external IP ``` I[06-08|11:51:57.234] Getting UPNP external address module=p2p I[06-08|11:51:58.867] Got UPNP external address module=p2p address= ``` Fixes #1717 ``` I[06-08|11:51:56.952] Starting multiAppConn module=proxy impl=multiAppConn I[06-08|11:51:56.952] Starting localClient module=abci-client connection=query impl=localClient I[06-08|11:51:56.952] Starting localClient module=abci-client connection=mempool impl=localClient I[06-08|11:51:56.952] Starting localClient module=abci-client connection=consensus impl=localClient I[06-08|11:51:56.952] ABCI Handshake module=consensus appHeight=0 appHash= I[06-08|11:51:56.952] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 I[06-08|11:51:57.053] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=0 appHash= I[06-08|11:51:57.053] This node is a validator module=consensus addr=6816B5D9BAC32A3CDF07884D9D3D2650694C371D pubKey=PubKeyEd25519{27A40CD032DD2467342D0CF27C5EC92052D966FEC714B6CF2F3BF3146AFD0D51} I[06-08|11:51:57.234] Starting Node module=main impl=Node I[06-08|11:51:57.234] Starting EventBus module=events impl=EventBus I[06-08|11:51:57.234] Local listener module=p2p ip=:: port=46656 I[06-08|11:51:57.234] Getting UPNP external address module=p2p I[06-08|11:51:58.867] Got UPNP external address module=p2p address= I[06-08|11:51:58.867] Starting DefaultListener module=p2p impl=Listener(@<nil>:46656) I[06-08|11:51:58.867] P2P Node ID module=main ID=3629b516392e494ae717ac4c6a1ea7eb0fe421c3 file=/home/tpb/.tendermint/config/node_key.json I[06-08|11:51:58.868] Add our address to book module=p2p book=/home/tpb/.tendermint/config/addrbook.json addr=null panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x89fb86] goroutine 1 [running]: github.com/tendermint/tendermint/p2p.(*NetAddress).String(0x0, 0xc96e24, 0x17) /home/tpb/code/go/src/github.com/tendermint/tendermint/p2p/netaddress.go:171 +0x26 github.com/tendermint/tendermint/p2p/pex.(*addrBook).AddOurAddress(0xc420190620, 0x0) /home/tpb/code/go/src/github.com/tendermint/tendermint/p2p/pex/addrbook.go:160 +0x116 github.com/tendermint/tendermint/node.(*Node).OnStart(0xc420286d00, 0xc4201b8010, 0xd) /home/tpb/code/go/src/github.com/tendermint/tendermint/node/node.go:402 +0x547 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start(0xc420286d00, 0xe51c40, 0xc42000bd40) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x3bd github.com/tendermint/tendermint/cmd/tendermint/commands.NewRunNodeCmd.func1(0xc42022e000, 0xc4200acdc0, 0x0, 0x1, 0x0, 0x0) /home/tpb/code/go/src/github.com/tendermint/tendermint/cmd/tendermint/commands/run_node.go:58 +0xfe github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).execute(0xc42022e000, 0xc4200acda0, 0x1, 0x1, 0xc42022e000, 0xc4200acda0) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:762 +0x468 github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0x1289280, 0xbbdda0, 0xc420015e01, 0xc4201bc640) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:852 +0x30a github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).Execute(0x1289280, 0xc4201bc640, 0xc420015e98) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:800 +0x2b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/cli.Executor.Execute(0x1289280, 0xde5798, 0x2, 0xc4200332c0) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/cli/setup.go:89 +0x4e main.main() /home/tpb/code/go/src/github.com/tendermint/tendermint/cmd/tendermint/main.go:45 +0x24d ```
7 years ago
9 years ago
return an error if we fail to parse external IP ``` I[06-08|11:51:57.234] Getting UPNP external address module=p2p I[06-08|11:51:58.867] Got UPNP external address module=p2p address= ``` Fixes #1717 ``` I[06-08|11:51:56.952] Starting multiAppConn module=proxy impl=multiAppConn I[06-08|11:51:56.952] Starting localClient module=abci-client connection=query impl=localClient I[06-08|11:51:56.952] Starting localClient module=abci-client connection=mempool impl=localClient I[06-08|11:51:56.952] Starting localClient module=abci-client connection=consensus impl=localClient I[06-08|11:51:56.952] ABCI Handshake module=consensus appHeight=0 appHash= I[06-08|11:51:56.952] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 I[06-08|11:51:57.053] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=0 appHash= I[06-08|11:51:57.053] This node is a validator module=consensus addr=6816B5D9BAC32A3CDF07884D9D3D2650694C371D pubKey=PubKeyEd25519{27A40CD032DD2467342D0CF27C5EC92052D966FEC714B6CF2F3BF3146AFD0D51} I[06-08|11:51:57.234] Starting Node module=main impl=Node I[06-08|11:51:57.234] Starting EventBus module=events impl=EventBus I[06-08|11:51:57.234] Local listener module=p2p ip=:: port=46656 I[06-08|11:51:57.234] Getting UPNP external address module=p2p I[06-08|11:51:58.867] Got UPNP external address module=p2p address= I[06-08|11:51:58.867] Starting DefaultListener module=p2p impl=Listener(@<nil>:46656) I[06-08|11:51:58.867] P2P Node ID module=main ID=3629b516392e494ae717ac4c6a1ea7eb0fe421c3 file=/home/tpb/.tendermint/config/node_key.json I[06-08|11:51:58.868] Add our address to book module=p2p book=/home/tpb/.tendermint/config/addrbook.json addr=null panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x89fb86] goroutine 1 [running]: github.com/tendermint/tendermint/p2p.(*NetAddress).String(0x0, 0xc96e24, 0x17) /home/tpb/code/go/src/github.com/tendermint/tendermint/p2p/netaddress.go:171 +0x26 github.com/tendermint/tendermint/p2p/pex.(*addrBook).AddOurAddress(0xc420190620, 0x0) /home/tpb/code/go/src/github.com/tendermint/tendermint/p2p/pex/addrbook.go:160 +0x116 github.com/tendermint/tendermint/node.(*Node).OnStart(0xc420286d00, 0xc4201b8010, 0xd) /home/tpb/code/go/src/github.com/tendermint/tendermint/node/node.go:402 +0x547 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start(0xc420286d00, 0xe51c40, 0xc42000bd40) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x3bd github.com/tendermint/tendermint/cmd/tendermint/commands.NewRunNodeCmd.func1(0xc42022e000, 0xc4200acdc0, 0x0, 0x1, 0x0, 0x0) /home/tpb/code/go/src/github.com/tendermint/tendermint/cmd/tendermint/commands/run_node.go:58 +0xfe github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).execute(0xc42022e000, 0xc4200acda0, 0x1, 0x1, 0xc42022e000, 0xc4200acda0) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:762 +0x468 github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0x1289280, 0xbbdda0, 0xc420015e01, 0xc4201bc640) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:852 +0x30a github.com/tendermint/tendermint/vendor/github.com/spf13/cobra.(*Command).Execute(0x1289280, 0xc4201bc640, 0xc420015e98) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/spf13/cobra/command.go:800 +0x2b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/cli.Executor.Execute(0x1289280, 0xde5798, 0x2, 0xc4200332c0) /home/tpb/code/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/cli/setup.go:89 +0x4e main.main() /home/tpb/code/go/src/github.com/tendermint/tendermint/cmd/tendermint/main.go:45 +0x24d ```
7 years ago
9 years ago
9 years ago
9 years ago
  1. // Taken from taipei-torrent.
  2. // Just enough UPnP to be able to forward ports
  3. // For more information, see: http://www.upnp-hacks.org/upnp.html
  4. package upnp
  5. // TODO: use syscalls to get actual ourIP, see issue #712
  6. import (
  7. "bytes"
  8. "encoding/xml"
  9. "errors"
  10. "fmt"
  11. "io/ioutil"
  12. "net"
  13. "net/http"
  14. "strconv"
  15. "strings"
  16. "time"
  17. )
  18. type upnpNAT struct {
  19. serviceURL string
  20. ourIP string
  21. urnDomain string
  22. }
  23. // protocol is either "udp" or "tcp"
  24. type NAT interface {
  25. GetExternalAddress() (addr net.IP, err error)
  26. AddPortMapping(protocol string, externalPort, internalPort int, description string, timeout int) (mappedExternalPort int, err error)
  27. DeletePortMapping(protocol string, externalPort, internalPort int) (err error)
  28. }
  29. func Discover() (nat NAT, err error) {
  30. ssdp, err := net.ResolveUDPAddr("udp4", "239.255.255.250:1900")
  31. if err != nil {
  32. return
  33. }
  34. conn, err := net.ListenPacket("udp4", ":0")
  35. if err != nil {
  36. return
  37. }
  38. socket := conn.(*net.UDPConn)
  39. defer socket.Close() // nolint: errcheck
  40. if err := socket.SetDeadline(time.Now().Add(3 * time.Second)); err != nil {
  41. return nil, err
  42. }
  43. st := "InternetGatewayDevice:1"
  44. buf := bytes.NewBufferString(
  45. "M-SEARCH * HTTP/1.1\r\n" +
  46. "HOST: 239.255.255.250:1900\r\n" +
  47. "ST: ssdp:all\r\n" +
  48. "MAN: \"ssdp:discover\"\r\n" +
  49. "MX: 2\r\n\r\n")
  50. message := buf.Bytes()
  51. answerBytes := make([]byte, 1024)
  52. for i := 0; i < 3; i++ {
  53. _, err = socket.WriteToUDP(message, ssdp)
  54. if err != nil {
  55. return
  56. }
  57. var n int
  58. _, _, err = socket.ReadFromUDP(answerBytes)
  59. if err != nil {
  60. return
  61. }
  62. for {
  63. n, _, err = socket.ReadFromUDP(answerBytes)
  64. if err != nil {
  65. break
  66. }
  67. answer := string(answerBytes[0:n])
  68. if !strings.Contains(answer, st) {
  69. continue
  70. }
  71. // HTTP header field names are case-insensitive.
  72. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
  73. locString := "\r\nlocation:"
  74. answer = strings.ToLower(answer)
  75. locIndex := strings.Index(answer, locString)
  76. if locIndex < 0 {
  77. continue
  78. }
  79. loc := answer[locIndex+len(locString):]
  80. endIndex := strings.Index(loc, "\r\n")
  81. if endIndex < 0 {
  82. continue
  83. }
  84. locURL := strings.TrimSpace(loc[0:endIndex])
  85. var serviceURL, urnDomain string
  86. serviceURL, urnDomain, err = getServiceURL(locURL)
  87. if err != nil {
  88. return
  89. }
  90. var ourIP net.IP
  91. ourIP, err = localIPv4()
  92. if err != nil {
  93. return
  94. }
  95. nat = &upnpNAT{serviceURL: serviceURL, ourIP: ourIP.String(), urnDomain: urnDomain}
  96. return
  97. }
  98. }
  99. err = errors.New("UPnP port discovery failed")
  100. return
  101. }
  102. type Envelope struct {
  103. XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
  104. Soap *SoapBody
  105. }
  106. type SoapBody struct {
  107. XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`
  108. ExternalIP *ExternalIPAddressResponse
  109. }
  110. type ExternalIPAddressResponse struct {
  111. XMLName xml.Name `xml:"GetExternalIPAddressResponse"`
  112. IPAddress string `xml:"NewExternalIPAddress"`
  113. }
  114. type ExternalIPAddress struct {
  115. XMLName xml.Name `xml:"NewExternalIPAddress"`
  116. IP string
  117. }
  118. type UPNPService struct {
  119. ServiceType string `xml:"serviceType"`
  120. ControlURL string `xml:"controlURL"`
  121. }
  122. type DeviceList struct {
  123. Device []Device `xml:"device"`
  124. }
  125. type ServiceList struct {
  126. Service []UPNPService `xml:"service"`
  127. }
  128. type Device struct {
  129. XMLName xml.Name `xml:"device"`
  130. DeviceType string `xml:"deviceType"`
  131. DeviceList DeviceList `xml:"deviceList"`
  132. ServiceList ServiceList `xml:"serviceList"`
  133. }
  134. type Root struct {
  135. Device Device
  136. }
  137. func getChildDevice(d *Device, deviceType string) *Device {
  138. dl := d.DeviceList.Device
  139. for i := 0; i < len(dl); i++ {
  140. if strings.Contains(dl[i].DeviceType, deviceType) {
  141. return &dl[i]
  142. }
  143. }
  144. return nil
  145. }
  146. func getChildService(d *Device, serviceType string) *UPNPService {
  147. sl := d.ServiceList.Service
  148. for i := 0; i < len(sl); i++ {
  149. if strings.Contains(sl[i].ServiceType, serviceType) {
  150. return &sl[i]
  151. }
  152. }
  153. return nil
  154. }
  155. func localIPv4() (net.IP, error) {
  156. tt, err := net.Interfaces()
  157. if err != nil {
  158. return nil, err
  159. }
  160. for _, t := range tt {
  161. aa, err := t.Addrs()
  162. if err != nil {
  163. return nil, err
  164. }
  165. for _, a := range aa {
  166. ipnet, ok := a.(*net.IPNet)
  167. if !ok {
  168. continue
  169. }
  170. v4 := ipnet.IP.To4()
  171. if v4 == nil || v4[0] == 127 { // loopback address
  172. continue
  173. }
  174. return v4, nil
  175. }
  176. }
  177. return nil, errors.New("cannot find local IP address")
  178. }
  179. func getServiceURL(rootURL string) (url, urnDomain string, err error) {
  180. r, err := http.Get(rootURL) // nolint: gosec
  181. if err != nil {
  182. return
  183. }
  184. defer r.Body.Close() // nolint: errcheck
  185. if r.StatusCode >= 400 {
  186. err = errors.New(string(r.StatusCode))
  187. return
  188. }
  189. var root Root
  190. err = xml.NewDecoder(r.Body).Decode(&root)
  191. if err != nil {
  192. return
  193. }
  194. a := &root.Device
  195. if !strings.Contains(a.DeviceType, "InternetGatewayDevice:1") {
  196. err = errors.New("No InternetGatewayDevice")
  197. return
  198. }
  199. b := getChildDevice(a, "WANDevice:1")
  200. if b == nil {
  201. err = errors.New("No WANDevice")
  202. return
  203. }
  204. c := getChildDevice(b, "WANConnectionDevice:1")
  205. if c == nil {
  206. err = errors.New("No WANConnectionDevice")
  207. return
  208. }
  209. d := getChildService(c, "WANIPConnection:1")
  210. if d == nil {
  211. // Some routers don't follow the UPnP spec, and put WanIPConnection under WanDevice,
  212. // instead of under WanConnectionDevice
  213. d = getChildService(b, "WANIPConnection:1")
  214. if d == nil {
  215. err = errors.New("No WANIPConnection")
  216. return
  217. }
  218. }
  219. // Extract the domain name, which isn't always 'schemas-upnp-org'
  220. urnDomain = strings.Split(d.ServiceType, ":")[1]
  221. url = combineURL(rootURL, d.ControlURL)
  222. return
  223. }
  224. func combineURL(rootURL, subURL string) string {
  225. protocolEnd := "://"
  226. protoEndIndex := strings.Index(rootURL, protocolEnd)
  227. a := rootURL[protoEndIndex+len(protocolEnd):]
  228. rootIndex := strings.Index(a, "/")
  229. return rootURL[0:protoEndIndex+len(protocolEnd)+rootIndex] + subURL
  230. }
  231. func soapRequest(url, function, message, domain string) (r *http.Response, err error) {
  232. fullMessage := "<?xml version=\"1.0\" ?>" +
  233. "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n" +
  234. "<s:Body>" + message + "</s:Body></s:Envelope>"
  235. req, err := http.NewRequest("POST", url, strings.NewReader(fullMessage))
  236. if err != nil {
  237. return nil, err
  238. }
  239. req.Header.Set("Content-Type", "text/xml ; charset=\"utf-8\"")
  240. req.Header.Set("User-Agent", "Darwin/10.0.0, UPnP/1.0, MiniUPnPc/1.3")
  241. //req.Header.Set("Transfer-Encoding", "chunked")
  242. req.Header.Set("SOAPAction", "\"urn:"+domain+":service:WANIPConnection:1#"+function+"\"")
  243. req.Header.Set("Connection", "Close")
  244. req.Header.Set("Cache-Control", "no-cache")
  245. req.Header.Set("Pragma", "no-cache")
  246. // log.Stderr("soapRequest ", req)
  247. r, err = http.DefaultClient.Do(req)
  248. if err != nil {
  249. return nil, err
  250. }
  251. /*if r.Body != nil {
  252. defer r.Body.Close()
  253. }*/
  254. if r.StatusCode >= 400 {
  255. // log.Stderr(function, r.StatusCode)
  256. err = errors.New("Error " + strconv.Itoa(r.StatusCode) + " for " + function)
  257. r = nil
  258. return
  259. }
  260. return
  261. }
  262. type statusInfo struct {
  263. externalIpAddress string
  264. }
  265. func (n *upnpNAT) getExternalIPAddress() (info statusInfo, err error) {
  266. message := "<u:GetExternalIPAddress xmlns:u=\"urn:" + n.urnDomain + ":service:WANIPConnection:1\">\r\n" +
  267. "</u:GetExternalIPAddress>"
  268. var response *http.Response
  269. response, err = soapRequest(n.serviceURL, "GetExternalIPAddress", message, n.urnDomain)
  270. if response != nil {
  271. defer response.Body.Close() // nolint: errcheck
  272. }
  273. if err != nil {
  274. return
  275. }
  276. var envelope Envelope
  277. data, err := ioutil.ReadAll(response.Body)
  278. if err != nil {
  279. return
  280. }
  281. reader := bytes.NewReader(data)
  282. err = xml.NewDecoder(reader).Decode(&envelope)
  283. if err != nil {
  284. return
  285. }
  286. info = statusInfo{envelope.Soap.ExternalIP.IPAddress}
  287. if err != nil {
  288. return
  289. }
  290. return
  291. }
  292. // GetExternalAddress returns an external IP. If GetExternalIPAddress action
  293. // fails or IP returned is invalid, GetExternalAddress returns an error.
  294. func (n *upnpNAT) GetExternalAddress() (addr net.IP, err error) {
  295. info, err := n.getExternalIPAddress()
  296. if err != nil {
  297. return
  298. }
  299. addr = net.ParseIP(info.externalIpAddress)
  300. if addr == nil {
  301. err = fmt.Errorf("Failed to parse IP: %v", info.externalIpAddress)
  302. }
  303. return
  304. }
  305. func (n *upnpNAT) AddPortMapping(protocol string, externalPort, internalPort int, description string, timeout int) (mappedExternalPort int, err error) {
  306. // A single concatenation would break ARM compilation.
  307. message := "<u:AddPortMapping xmlns:u=\"urn:" + n.urnDomain + ":service:WANIPConnection:1\">\r\n" +
  308. "<NewRemoteHost></NewRemoteHost><NewExternalPort>" + strconv.Itoa(externalPort)
  309. message += "</NewExternalPort><NewProtocol>" + protocol + "</NewProtocol>"
  310. message += "<NewInternalPort>" + strconv.Itoa(internalPort) + "</NewInternalPort>" +
  311. "<NewInternalClient>" + n.ourIP + "</NewInternalClient>" +
  312. "<NewEnabled>1</NewEnabled><NewPortMappingDescription>"
  313. message += description +
  314. "</NewPortMappingDescription><NewLeaseDuration>" + strconv.Itoa(timeout) +
  315. "</NewLeaseDuration></u:AddPortMapping>"
  316. var response *http.Response
  317. response, err = soapRequest(n.serviceURL, "AddPortMapping", message, n.urnDomain)
  318. if response != nil {
  319. defer response.Body.Close() // nolint: errcheck
  320. }
  321. if err != nil {
  322. return
  323. }
  324. // TODO: check response to see if the port was forwarded
  325. // log.Println(message, response)
  326. // JAE:
  327. // body, err := ioutil.ReadAll(response.Body)
  328. // fmt.Println(string(body), err)
  329. mappedExternalPort = externalPort
  330. _ = response
  331. return
  332. }
  333. func (n *upnpNAT) DeletePortMapping(protocol string, externalPort, internalPort int) (err error) {
  334. message := "<u:DeletePortMapping xmlns:u=\"urn:" + n.urnDomain + ":service:WANIPConnection:1\">\r\n" +
  335. "<NewRemoteHost></NewRemoteHost><NewExternalPort>" + strconv.Itoa(externalPort) +
  336. "</NewExternalPort><NewProtocol>" + protocol + "</NewProtocol>" +
  337. "</u:DeletePortMapping>"
  338. var response *http.Response
  339. response, err = soapRequest(n.serviceURL, "DeletePortMapping", message, n.urnDomain)
  340. if response != nil {
  341. defer response.Body.Close() // nolint: errcheck
  342. }
  343. if err != nil {
  344. return
  345. }
  346. // TODO: check response to see if the port was deleted
  347. // log.Println(message, response)
  348. _ = response
  349. return
  350. }