From 605978b9c3f7bd84b33dfbcecd7392280cb62469 Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Thu, 28 Aug 2014 20:49:41 +0200 Subject: [PATCH 01/54] e3x: working on channel implementation --- LICENSE | 191 ++++++++++++++++++++++++++++++++ README.md | 3 + _examples/nat-tester.go | 67 +++++++++++ nat.go | 42 +++++++ natpmp.go | 178 ++++++++++++++++++++++++++++++ upnp.go | 239 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 720 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 _examples/nat-tester.go create mode 100644 nat.go create mode 100644 natpmp.go create mode 100644 upnp.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..37ec93a14f --- /dev/null +++ b/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..24ddea09e6 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# go-nat + +[![GoDoc](https://godoc.org/github.com/fd/go-nat?status.svg)](https://godoc.org/github.com/fd/go-nat) [![status](https://sourcegraph.com/api/repos/github.com/fd/go-nat/.badges/status.png)](https://sourcegraph.com/github.com/fd/go-nat) diff --git a/_examples/nat-tester.go b/_examples/nat-tester.go new file mode 100644 index 0000000000..1033293888 --- /dev/null +++ b/_examples/nat-tester.go @@ -0,0 +1,67 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "time" + + "bitbucket.org/simonmenke/go-telehash/util/nat" +) + +func main() { + nat, err := nat.Discover() + if err != nil { + log.Fatalf("error: %s", err) + } + log.Printf("nat type: %s", nat.Type()) + + daddr, err := nat.GetDeviceAddress() + if err != nil { + log.Fatalf("error: %s", err) + } + log.Printf("device address: %s", daddr) + + iaddr, err := nat.GetInternalAddress() + if err != nil { + log.Fatalf("error: %s", err) + } + log.Printf("internal address: %s", iaddr) + + eaddr, err := nat.GetExternalAddress() + if err != nil { + log.Fatalf("error: %s", err) + } + log.Printf("external address: %s", eaddr) + + eport, err := nat.AddPortMapping("tcp", 3080, "http", 60) + if err != nil { + log.Fatalf("error: %s", err) + } + + log.Printf("test-page: http://%s:%d/", eaddr, eport) + + go func() { + for { + time.Sleep(30 * time.Second) + + _, err = nat.AddPortMapping("tcp", 3080, "http", 60) + if err != nil { + log.Fatalf("error: %s", err) + } + } + }() + + defer nat.DeletePortMapping("txp", 3080) + + http.ListenAndServe(":3080", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Set("Content-Type", "text/plain") + rw.WriteHeader(200) + fmt.Fprintf(rw, "Hello there!\n") + fmt.Fprintf(rw, "nat type: %s\n", nat.Type()) + fmt.Fprintf(rw, "device address: %s\n", daddr) + fmt.Fprintf(rw, "internal address: %s\n", iaddr) + fmt.Fprintf(rw, "external address: %s\n", eaddr) + fmt.Fprintf(rw, "test-page: http://%s:%d/\n", eaddr, eport) + })) +} diff --git a/nat.go b/nat.go new file mode 100644 index 0000000000..59b970f4f4 --- /dev/null +++ b/nat.go @@ -0,0 +1,42 @@ +package nat + +import ( + "errors" + "math" + "math/rand" + "net" + "time" +) + +var ErrNoExternalAddress = errors.New("nat: no external address") +var ErrNoInternalAddress = errors.New("nat: no internal address") +var ErrNoNATFound = errors.New("nat: no NAT found") + +// protocol is either "udp" or "tcp" +type NAT interface { + Type() string + GetDeviceAddress() (addr net.IP, err error) + GetInternalAddress() (addr net.IP, err error) + GetExternalAddress() (addr net.IP, err error) + + AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (mappedExternalPort int, err error) + DeletePortMapping(protocol string, internalPort int) (err error) +} + +func Discover() (NAT, error) { + select { + case nat := <-discoverUPNP_IG1(): + return nat, nil + case nat := <-discoverUPNP_IG2(): + return nat, nil + case nat := <-discoverNATPMP(): + return nat, nil + case <-time.After(10 * time.Second): + return nil, ErrNoNATFound + } +} + +func randomPort() int { + rand.Seed(time.Now().UnixNano()) + return rand.Intn(math.MaxUint16-10000) + 10000 +} diff --git a/natpmp.go b/natpmp.go new file mode 100644 index 0000000000..8bc6c07171 --- /dev/null +++ b/natpmp.go @@ -0,0 +1,178 @@ +package nat + +import ( + "net" + "time" + + "github.com/jackpal/go-nat-pmp" +) + +var ( + _ NAT = (*natpmp_NAT)(nil) +) + +func natpmp_PotentialGateways() ([]net.IP, error) { + _, ipNet_10, err := net.ParseCIDR("10.0.0.0/8") + if err != nil { + panic(err) + } + + _, ipNet_172_16, err := net.ParseCIDR("172.16.0.0/12") + if err != nil { + panic(err) + } + + _, ipNet_192_168, err := net.ParseCIDR("192.168.0.0/16") + if err != nil { + panic(err) + } + + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + var ips []net.IP + + for _, iface := range ifaces { + addrs, err := iface.Addrs() + if err != nil { + return nil, err + } + + for _, addr := range addrs { + switch x := addr.(type) { + case *net.IPNet: + var ipNet *net.IPNet + if ipNet_10.Contains(x.IP) { + ipNet = ipNet_10 + } else if ipNet_172_16.Contains(x.IP) { + ipNet = ipNet_172_16 + } else if ipNet_192_168.Contains(x.IP) { + ipNet = ipNet_192_168 + } + + if ipNet != nil { + ip := x.IP.Mask(x.Mask) + ip = ip.To4() + if ip != nil { + ip[3] = ip[3] | 0x01 + ips = append(ips, ip) + } + } + } + } + } + + if len(ips) == 0 { + return nil, ErrNoNATFound + } + + return ips, nil +} + +func discoverNATPMP() <-chan NAT { + ips, err := natpmp_PotentialGateways() + if err != nil { + return nil + } + + res := make(chan NAT, len(ips)) + + for _, ip := range ips { + go discoverNATPMPWithAddr(res, ip) + } + + return res +} + +func discoverNATPMPWithAddr(c chan NAT, ip net.IP) { + client := natpmp.NewClient(ip) + _, err := client.GetExternalAddress() + if err != nil { + return + } + + c <- &natpmp_NAT{client, ip, make(map[int]int)} +} + +type natpmp_NAT struct { + c *natpmp.Client + gateway net.IP + ports map[int]int +} + +func (n *natpmp_NAT) GetDeviceAddress() (addr net.IP, err error) { + return n.gateway, nil +} + +func (n *natpmp_NAT) GetInternalAddress() (addr net.IP, err error) { + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + for _, iface := range ifaces { + addrs, err := iface.Addrs() + if err != nil { + return nil, err + } + + for _, addr := range addrs { + switch x := addr.(type) { + case *net.IPNet: + if x.Contains(n.gateway) { + return x.IP, nil + } + } + } + } + + return nil, ErrNoInternalAddress +} + +func (n *natpmp_NAT) GetExternalAddress() (addr net.IP, err error) { + res, err := n.c.GetExternalAddress() + if err != nil { + return nil, err + } + + d := res.ExternalIPAddress + return net.IPv4(d[0], d[1], d[2], d[3]), nil +} + +func (n *natpmp_NAT) AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (int, error) { + var ( + err error + ) + + timeoutInSeconds := int(timeout / time.Second) + + if externalPort := n.ports[internalPort]; externalPort > 0 { + _, err = n.c.AddPortMapping(protocol, internalPort, externalPort, timeoutInSeconds) + if err == nil { + n.ports[internalPort] = externalPort + return externalPort, nil + } + } + + for i := 0; i < 3; i++ { + externalPort := randomPort() + _, err = n.c.AddPortMapping(protocol, internalPort, externalPort, timeoutInSeconds) + if err == nil { + n.ports[internalPort] = externalPort + return externalPort, nil + } + } + + return 0, err +} + +func (n *natpmp_NAT) DeletePortMapping(protocol string, internalPort int) (err error) { + delete(n.ports, internalPort) + return nil +} + +func (n *natpmp_NAT) Type() string { + return "NAT-PMP" +} diff --git a/upnp.go b/upnp.go new file mode 100644 index 0000000000..b27ca1e9a9 --- /dev/null +++ b/upnp.go @@ -0,0 +1,239 @@ +package nat + +import ( + "net" + "time" + + "github.com/huin/goupnp" + "github.com/huin/goupnp/dcps/internetgateway1" + "github.com/huin/goupnp/dcps/internetgateway2" +) + +var ( + _ NAT = (*upnp_NAT)(nil) +) + +func discoverUPNP_IG1() <-chan NAT { + res := make(chan NAT, 1) + go func() { + + // find devices + devs, err := goupnp.DiscoverDevices(internetgateway1.URN_WANConnectionDevice_1) + if err != nil { + return + } + + for _, dev := range devs { + if dev.Root == nil { + continue + } + + dev.Root.Device.VisitServices(func(srv *goupnp.Service) { + switch srv.ServiceType { + case internetgateway1.URN_WANIPConnection_1: + client := &internetgateway1.WANIPConnection1{goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: dev.Root, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatus() + if err == nil && isNat { + res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", dev.Root} + return + } + + case internetgateway1.URN_WANPPPConnection_1: + client := &internetgateway1.WANPPPConnection1{goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: dev.Root, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatus() + if err == nil && isNat { + res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", dev.Root} + return + } + + } + }) + } + + }() + return res +} + +func discoverUPNP_IG2() <-chan NAT { + res := make(chan NAT, 1) + go func() { + + // find devices + devs, err := goupnp.DiscoverDevices(internetgateway2.URN_WANConnectionDevice_2) + if err != nil { + return + } + + for _, dev := range devs { + if dev.Root == nil { + continue + } + + dev.Root.Device.VisitServices(func(srv *goupnp.Service) { + switch srv.ServiceType { + case internetgateway2.URN_WANIPConnection_1: + client := &internetgateway2.WANIPConnection1{goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: dev.Root, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatus() + if err == nil && isNat { + res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP1)", dev.Root} + return + } + + case internetgateway2.URN_WANIPConnection_2: + client := &internetgateway2.WANIPConnection2{goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: dev.Root, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatus() + if err == nil && isNat { + res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP2)", dev.Root} + return + } + + case internetgateway2.URN_WANPPPConnection_1: + client := &internetgateway2.WANPPPConnection1{goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: dev.Root, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatus() + if err == nil && isNat { + res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-PPP1)", dev.Root} + return + } + + } + }) + } + + }() + return res +} + +type upnp_NAT_Client interface { + GetExternalIPAddress() (string, error) + AddPortMapping(string, uint16, string, uint16, string, bool, string, uint32) error + DeletePortMapping(string, uint16, string) error +} + +type upnp_NAT struct { + c upnp_NAT_Client + ports map[int]int + typ string + rootDevice *goupnp.RootDevice +} + +func (u *upnp_NAT) GetExternalAddress() (addr net.IP, err error) { + ipString, err := u.c.GetExternalIPAddress() + if err != nil { + return nil, err + } + + ip := net.ParseIP(ipString) + if ip == nil { + return nil, ErrNoExternalAddress + } + + return ip, nil +} + +func mapProtocol(s string) string { + switch s { + case "udp": + return "UDP" + case "tcp": + return "TCP" + default: + panic("invalid protocol: " + s) + } +} + +func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (int, error) { + ip, err := u.GetInternalAddress() + if err != nil { + return 0, nil + } + + timeoutInSeconds := uint32(timeout / time.Second) + + if externalPort := u.ports[internalPort]; externalPort > 0 { + err = u.c.AddPortMapping("", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) + if err == nil { + return externalPort, nil + } + } + + for i := 0; i < 3; i++ { + externalPort := randomPort() + err = u.c.AddPortMapping("", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) + if err == nil { + u.ports[internalPort] = externalPort + return externalPort, nil + } + } + + return 0, err +} + +func (u *upnp_NAT) DeletePortMapping(protocol string, internalPort int) error { + if externalPort := u.ports[internalPort]; externalPort > 0 { + delete(u.ports, internalPort) + return u.c.DeletePortMapping("", uint16(externalPort), mapProtocol(protocol)) + } + + return nil +} + +func (u *upnp_NAT) GetDeviceAddress() (net.IP, error) { + addr, err := net.ResolveUDPAddr("udp4", u.rootDevice.URLBase.Host) + if err != nil { + return nil, err + } + + return addr.IP, nil +} + +func (u *upnp_NAT) GetInternalAddress() (net.IP, error) { + devAddr, err := u.GetDeviceAddress() + if err != nil { + return nil, err + } + + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + for _, iface := range ifaces { + addrs, err := iface.Addrs() + if err != nil { + return nil, err + } + + for _, addr := range addrs { + switch x := addr.(type) { + case *net.IPNet: + if x.Contains(devAddr) { + return x.IP, nil + } + } + } + } + + return nil, ErrNoInternalAddress +} + +func (n *upnp_NAT) Type() string { return n.typ } From d827c54a1e8044b91c5c20885ad53524432fa83e Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Mon, 27 Oct 2014 08:07:06 +0100 Subject: [PATCH 02/54] Moving to github --- _examples/nat-tester.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_examples/nat-tester.go b/_examples/nat-tester.go index 1033293888..592125639f 100644 --- a/_examples/nat-tester.go +++ b/_examples/nat-tester.go @@ -6,7 +6,7 @@ import ( "net/http" "time" - "bitbucket.org/simonmenke/go-telehash/util/nat" + "github.com/telehash/gogotelehash/util/nat" ) func main() { From 83bf98db65f0e298f73df271e80b35d42eebe4a5 Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Mon, 27 Oct 2014 17:39:55 +0100 Subject: [PATCH 03/54] Vendored dependencies --- natpmp.go | 2 +- upnp.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/natpmp.go b/natpmp.go index 8bc6c07171..33fb5028a7 100644 --- a/natpmp.go +++ b/natpmp.go @@ -4,7 +4,7 @@ import ( "net" "time" - "github.com/jackpal/go-nat-pmp" + "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/jackpal/go-nat-pmp" ) var ( diff --git a/upnp.go b/upnp.go index b27ca1e9a9..4cabd661aa 100644 --- a/upnp.go +++ b/upnp.go @@ -4,9 +4,9 @@ import ( "net" "time" - "github.com/huin/goupnp" - "github.com/huin/goupnp/dcps/internetgateway1" - "github.com/huin/goupnp/dcps/internetgateway2" + "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/huin/goupnp" + "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway1" + "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway2" ) var ( From 4dbe9af9ab7666bc2ee453e9d08cd59448ca4bbb Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Thu, 30 Oct 2014 16:41:18 +0100 Subject: [PATCH 04/54] WIP go vet and golint --- upnp.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/upnp.go b/upnp.go index 4cabd661aa..b6c3bfa1ab 100644 --- a/upnp.go +++ b/upnp.go @@ -31,7 +31,7 @@ func discoverUPNP_IG1() <-chan NAT { dev.Root.Device.VisitServices(func(srv *goupnp.Service) { switch srv.ServiceType { case internetgateway1.URN_WANIPConnection_1: - client := &internetgateway1.WANIPConnection1{goupnp.ServiceClient{ + client := &internetgateway1.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ SOAPClient: srv.NewSOAPClient(), RootDevice: dev.Root, Service: srv, @@ -43,7 +43,7 @@ func discoverUPNP_IG1() <-chan NAT { } case internetgateway1.URN_WANPPPConnection_1: - client := &internetgateway1.WANPPPConnection1{goupnp.ServiceClient{ + client := &internetgateway1.WANPPPConnection1{ServiceClient: goupnp.ServiceClient{ SOAPClient: srv.NewSOAPClient(), RootDevice: dev.Root, Service: srv, @@ -80,7 +80,7 @@ func discoverUPNP_IG2() <-chan NAT { dev.Root.Device.VisitServices(func(srv *goupnp.Service) { switch srv.ServiceType { case internetgateway2.URN_WANIPConnection_1: - client := &internetgateway2.WANIPConnection1{goupnp.ServiceClient{ + client := &internetgateway2.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ SOAPClient: srv.NewSOAPClient(), RootDevice: dev.Root, Service: srv, @@ -92,7 +92,7 @@ func discoverUPNP_IG2() <-chan NAT { } case internetgateway2.URN_WANIPConnection_2: - client := &internetgateway2.WANIPConnection2{goupnp.ServiceClient{ + client := &internetgateway2.WANIPConnection2{ServiceClient: goupnp.ServiceClient{ SOAPClient: srv.NewSOAPClient(), RootDevice: dev.Root, Service: srv, @@ -104,7 +104,7 @@ func discoverUPNP_IG2() <-chan NAT { } case internetgateway2.URN_WANPPPConnection_1: - client := &internetgateway2.WANPPPConnection1{goupnp.ServiceClient{ + client := &internetgateway2.WANPPPConnection1{ServiceClient: goupnp.ServiceClient{ SOAPClient: srv.NewSOAPClient(), RootDevice: dev.Root, Service: srv, From c0902fb9c1dabc41dd65e0189061594b37726af0 Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Wed, 5 Nov 2014 12:43:11 +0100 Subject: [PATCH 05/54] Extracted from gogotelehash --- _examples/nat-tester.go | 2 +- nat.go | 22 +++++++++++++++++----- natpmp.go | 2 +- upnp.go | 6 +++--- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/_examples/nat-tester.go b/_examples/nat-tester.go index 592125639f..e534d3f11d 100644 --- a/_examples/nat-tester.go +++ b/_examples/nat-tester.go @@ -6,7 +6,7 @@ import ( "net/http" "time" - "github.com/telehash/gogotelehash/util/nat" + "github.com/fd/go-nat" ) func main() { diff --git a/nat.go b/nat.go index 59b970f4f4..3cf9648585 100644 --- a/nat.go +++ b/nat.go @@ -1,3 +1,4 @@ +// Package nat implements NAT handling facilities package nat import ( @@ -8,22 +9,33 @@ import ( "time" ) -var ErrNoExternalAddress = errors.New("nat: no external address") -var ErrNoInternalAddress = errors.New("nat: no internal address") -var ErrNoNATFound = errors.New("nat: no NAT found") +var ErrNoExternalAddress = errors.New("no external address") +var ErrNoInternalAddress = errors.New("no internal address") +var ErrNoNATFound = errors.New("no NAT found") // protocol is either "udp" or "tcp" type NAT interface { + // Type returns the kind of NAT port mapping service that is used Type() string + + // GetDeviceAddress returns the internal address of the gateway device. GetDeviceAddress() (addr net.IP, err error) - GetInternalAddress() (addr net.IP, err error) + + // GetExternalAddress returns the external address of the gateway device. GetExternalAddress() (addr net.IP, err error) + // GetInternalAddress returns the address of the local host. + GetInternalAddress() (addr net.IP, err error) + + // 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) + + // DeletePortMapping removes a port mapping. DeletePortMapping(protocol string, internalPort int) (err error) } -func Discover() (NAT, error) { +// DiscoverGateway attempts to find a gateway device. +func DiscoverGateway() (NAT, error) { select { case nat := <-discoverUPNP_IG1(): return nat, nil diff --git a/natpmp.go b/natpmp.go index 33fb5028a7..8bc6c07171 100644 --- a/natpmp.go +++ b/natpmp.go @@ -4,7 +4,7 @@ import ( "net" "time" - "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/jackpal/go-nat-pmp" + "github.com/jackpal/go-nat-pmp" ) var ( diff --git a/upnp.go b/upnp.go index b6c3bfa1ab..86d6e9b3ba 100644 --- a/upnp.go +++ b/upnp.go @@ -4,9 +4,9 @@ import ( "net" "time" - "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/huin/goupnp" - "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway1" - "github.com/telehash/gogotelehash/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway2" + "github.com/huin/goupnp" + "github.com/huin/goupnp/dcps/internetgateway1" + "github.com/huin/goupnp/dcps/internetgateway2" ) var ( From 50e7633d5f27d81490026a13e5b92d2e42d8c6bb Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Wed, 5 Nov 2014 13:04:22 +0100 Subject: [PATCH 06/54] Fixed the example --- _examples/nat-tester.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_examples/nat-tester.go b/_examples/nat-tester.go index e534d3f11d..f2f3bc9afc 100644 --- a/_examples/nat-tester.go +++ b/_examples/nat-tester.go @@ -10,7 +10,7 @@ import ( ) func main() { - nat, err := nat.Discover() + nat, err := nat.DiscoverGateway() if err != nil { log.Fatalf("error: %s", err) } From dcaf50131e4810440bed2cbb6f7f32c4f4cc95dd Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Fri, 8 May 2015 11:37:58 +0200 Subject: [PATCH 07/54] Using github.com/jackpal/gateway to discover NAT-PMP/PCP gateways This change also removes the restriction on what IP ranges can be used with NAT-PMP/PCP. Fixes: #1, #2 --- natpmp.go | 89 ++++++++----------------------------------------------- 1 file changed, 13 insertions(+), 76 deletions(-) diff --git a/natpmp.go b/natpmp.go index 8bc6c07171..395a5dd578 100644 --- a/natpmp.go +++ b/natpmp.go @@ -4,82 +4,19 @@ import ( "net" "time" + "github.com/jackpal/gateway" "github.com/jackpal/go-nat-pmp" ) var ( - _ NAT = (*natpmp_NAT)(nil) + _ NAT = (*natpmpNAT)(nil) ) -func natpmp_PotentialGateways() ([]net.IP, error) { - _, ipNet_10, err := net.ParseCIDR("10.0.0.0/8") - if err != nil { - panic(err) - } - - _, ipNet_172_16, err := net.ParseCIDR("172.16.0.0/12") - if err != nil { - panic(err) - } - - _, ipNet_192_168, err := net.ParseCIDR("192.168.0.0/16") - if err != nil { - panic(err) - } - - ifaces, err := net.Interfaces() - if err != nil { - return nil, err - } - - var ips []net.IP - - for _, iface := range ifaces { - addrs, err := iface.Addrs() - if err != nil { - return nil, err - } - - for _, addr := range addrs { - switch x := addr.(type) { - case *net.IPNet: - var ipNet *net.IPNet - if ipNet_10.Contains(x.IP) { - ipNet = ipNet_10 - } else if ipNet_172_16.Contains(x.IP) { - ipNet = ipNet_172_16 - } else if ipNet_192_168.Contains(x.IP) { - ipNet = ipNet_192_168 - } - - if ipNet != nil { - ip := x.IP.Mask(x.Mask) - ip = ip.To4() - if ip != nil { - ip[3] = ip[3] | 0x01 - ips = append(ips, ip) - } - } - } - } - } - - if len(ips) == 0 { - return nil, ErrNoNATFound - } - - return ips, nil -} - func discoverNATPMP() <-chan NAT { - ips, err := natpmp_PotentialGateways() - if err != nil { - return nil - } - - res := make(chan NAT, len(ips)) + res := make(chan NAT, 1) - for _, ip := range ips { + ip, err := gateway.DiscoverGateway() + if err == nil { go discoverNATPMPWithAddr(res, ip) } @@ -93,20 +30,20 @@ func discoverNATPMPWithAddr(c chan NAT, ip net.IP) { return } - c <- &natpmp_NAT{client, ip, make(map[int]int)} + c <- &natpmpNAT{client, ip, make(map[int]int)} } -type natpmp_NAT struct { +type natpmpNAT struct { c *natpmp.Client gateway net.IP ports map[int]int } -func (n *natpmp_NAT) GetDeviceAddress() (addr net.IP, err error) { +func (n *natpmpNAT) GetDeviceAddress() (addr net.IP, err error) { return n.gateway, nil } -func (n *natpmp_NAT) GetInternalAddress() (addr net.IP, err error) { +func (n *natpmpNAT) GetInternalAddress() (addr net.IP, err error) { ifaces, err := net.Interfaces() if err != nil { return nil, err @@ -131,7 +68,7 @@ func (n *natpmp_NAT) GetInternalAddress() (addr net.IP, err error) { return nil, ErrNoInternalAddress } -func (n *natpmp_NAT) GetExternalAddress() (addr net.IP, err error) { +func (n *natpmpNAT) GetExternalAddress() (addr net.IP, err error) { res, err := n.c.GetExternalAddress() if err != nil { return nil, err @@ -141,7 +78,7 @@ func (n *natpmp_NAT) GetExternalAddress() (addr net.IP, err error) { return net.IPv4(d[0], d[1], d[2], d[3]), nil } -func (n *natpmp_NAT) AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (int, error) { +func (n *natpmpNAT) AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (int, error) { var ( err error ) @@ -168,11 +105,11 @@ func (n *natpmp_NAT) AddPortMapping(protocol string, internalPort int, descripti return 0, err } -func (n *natpmp_NAT) DeletePortMapping(protocol string, internalPort int) (err error) { +func (n *natpmpNAT) DeletePortMapping(protocol string, internalPort int) (err error) { delete(n.ports, internalPort) return nil } -func (n *natpmp_NAT) Type() string { +func (n *natpmpNAT) Type() string { return "NAT-PMP" } From bad65a492f32121a87197f4a085905c35e2a367e Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Fri, 25 May 2018 15:02:20 +0200 Subject: [PATCH 08/54] Added go.mod file --- go.mod | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 0000000000..d7f4b28787 --- /dev/null +++ b/go.mod @@ -0,0 +1,9 @@ +module github.com/fd/go-nat + +require ( + github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324 + github.com/jackpal/gateway v1.0.4 + github.com/jackpal/go-nat-pmp v1.0.1 + golang.org/x/net v0.0.0-20180524181706-dfa909b99c79 + golang.org/x/text v0.3.0 +) From 66a3ad4c648a674f402de64e127780bff064126d Mon Sep 17 00:00:00 2001 From: Can ZHANG Date: Thu, 13 Sep 2018 15:04:26 +0800 Subject: [PATCH 09/54] Fix test --- _examples/nat-tester.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_examples/nat-tester.go b/_examples/nat-tester.go index f2f3bc9afc..e3b616b2a5 100644 --- a/_examples/nat-tester.go +++ b/_examples/nat-tester.go @@ -6,7 +6,7 @@ import ( "net/http" "time" - "github.com/fd/go-nat" + "github.com/libp2p/go-nat" ) func main() { @@ -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") From 3fa58ced20b2ff6110ae7eca6c22e18c06c8da6f Mon Sep 17 00:00:00 2001 From: Can ZHANG Date: Thu, 13 Sep 2018 15:11:48 +0800 Subject: [PATCH 10/54] Try to map external port the same as internal port --- natpmp.go | 7 +++++++ upnp.go | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/natpmp.go b/natpmp.go index 395a5dd578..9a2c27d9e7 100644 --- a/natpmp.go +++ b/natpmp.go @@ -93,6 +93,13 @@ func (n *natpmpNAT) AddPortMapping(protocol string, internalPort int, descriptio } } + // try to map external port the same as internal port + _, err = n.c.AddPortMapping(protocol, internalPort, internalPort, timeoutInSeconds) + if err == nil { + n.ports[internalPort] = internalPort + return internalPort, nil + } + for i := 0; i < 3; i++ { externalPort := randomPort() _, err = n.c.AddPortMapping(protocol, internalPort, externalPort, timeoutInSeconds) diff --git a/upnp.go b/upnp.go index 86d6e9b3ba..8b0975783b 100644 --- a/upnp.go +++ b/upnp.go @@ -176,6 +176,12 @@ func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description } } + // try to map external port the same as internal port + err = u.c.AddPortMapping("", uint16(internalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) + if err == nil { + return internalPort, nil + } + for i := 0; i < 3; i++ { externalPort := randomPort() err = u.c.AddPortMapping("", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) From 329756a8946a72449a3d3277865331ff52c0fd7b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 17 Sep 2018 13:51:20 -0700 Subject: [PATCH 11/54] gx import --- .gx/lastpubver | 1 + package.json | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 .gx/lastpubver create mode 100644 package.json diff --git a/.gx/lastpubver b/.gx/lastpubver new file mode 100644 index 0000000000..79ffaca958 --- /dev/null +++ b/.gx/lastpubver @@ -0,0 +1 @@ +1.0.1: QmZ4g5TSk6EKQHrR61FgnE1ytJfirDHKvquL93a3Na1wJT diff --git a/package.json b/package.json new file mode 100644 index 0000000000..1155730974 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "author": "fd", + "bugs": { + "url": "https://github.com/issues/go-nat/issues" + }, + "gx": { + "dvcsimport": "github.com/libp2p/go-nat" + }, + "gxDependencies": [ + { + "author": "huin", + "hash": "QmVwfv63beSAAirq3tiLY6fkNqvjThLnCofL7363YkaScy", + "name": "goupnp", + "version": "0.1.0" + }, + { + "author": "jackpal", + "hash": "Qmf2fBLzCvFxs3vvZaoQyKSTv2rjApek4F1kzRxAfK6P4P", + "name": "gateway", + "version": "1.0.4" + }, + { + "author": "jackpal", + "hash": "QmYsYNh6saxUYHajdj49uiRzdxQgiFTtymrjf3d1f2Cer4", + "name": "go-nat-pmp", + "version": "1.0.1" + } + ], + "gxVersion": "0.9.0", + "language": "go", + "license": "Apache-2.0", + "name": "go-nat", + "version": "1.0.1" +} + From 78a6e612d20233659382cd253145d38d6d24cdd7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 17 Sep 2018 13:56:12 -0700 Subject: [PATCH 12/54] finish fd -> libp2p migration --- README.md | 4 +++- go.mod | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 24ddea09e6..eec79193e6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # go-nat -[![GoDoc](https://godoc.org/github.com/fd/go-nat?status.svg)](https://godoc.org/github.com/fd/go-nat) [![status](https://sourcegraph.com/api/repos/github.com/fd/go-nat/.badges/status.png)](https://sourcegraph.com/github.com/fd/go-nat) +[![GoDoc](https://godoc.org/github.com/libp2p/go-nat?status.svg)](https://godoc.org/github.com/libp2p/go-nat) [![status](https://sourcegraph.com/api/repos/github.com/libp2p/go-nat/.badges/status.png)](https://sourcegraph.com/github.com/libp2p/go-nat) + +Forked from: [fd/go-nat](https://github.com/fd/go-nat). diff --git a/go.mod b/go.mod index d7f4b28787..4ac4a3dec7 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/fd/go-nat +module github.com/libp2p/go-nat require ( github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324 From ab584c7bce7cd20eb179845a3c93059661fedc0c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 17 Sep 2018 13:56:40 -0700 Subject: [PATCH 13/54] gx release 1.0.2 --- .gx/lastpubver | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gx/lastpubver b/.gx/lastpubver index 79ffaca958..d816451dee 100644 --- a/.gx/lastpubver +++ b/.gx/lastpubver @@ -1 +1 @@ -1.0.1: QmZ4g5TSk6EKQHrR61FgnE1ytJfirDHKvquL93a3Na1wJT +1.0.2: QmUTkdfn3e6EDb15C4XMHfooD5AoQxt5joYMeaqU56LU8h diff --git a/package.json b/package.json index 1155730974..61cdf82719 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,6 @@ "language": "go", "license": "Apache-2.0", "name": "go-nat", - "version": "1.0.1" + "version": "1.0.2" } From 2d37539e73354531e1aa084b68823775bf739c6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 12 Feb 2019 12:02:01 +0000 Subject: [PATCH 14/54] Bump github.com/jackpal/gateway from 1.0.4 to 1.0.5 Bumps [github.com/jackpal/gateway](https://github.com/jackpal/gateway) from 1.0.4 to 1.0.5. - [Release notes](https://github.com/jackpal/gateway/releases) - [Commits](https://github.com/jackpal/gateway/compare/v1.0.4...v1.0.5) Signed-off-by: dependabot[bot] --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d7f4b28787..73255a0b80 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/fd/go-nat require ( github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324 - github.com/jackpal/gateway v1.0.4 + github.com/jackpal/gateway v1.0.5 github.com/jackpal/go-nat-pmp v1.0.1 golang.org/x/net v0.0.0-20180524181706-dfa909b99c79 golang.org/x/text v0.3.0 From 06c184b582abc99b71b8c53ea783e8778759c7f5 Mon Sep 17 00:00:00 2001 From: Ryan Skidmore Date: Fri, 1 Mar 2019 15:09:57 +0000 Subject: [PATCH 15/54] Added method to generically discover IG Devices --- nat.go | 2 ++ upnp.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/nat.go b/nat.go index 3cf9648585..eb574d63c2 100644 --- a/nat.go +++ b/nat.go @@ -41,6 +41,8 @@ func DiscoverGateway() (NAT, error) { return nat, nil case nat := <-discoverUPNP_IG2(): return nat, nil + case nat := <-discoverUPNP_GenIGDev(): + return nat, nil case nat := <-discoverNATPMP(): return nat, nil case <-time.After(10 * time.Second): diff --git a/upnp.go b/upnp.go index 86d6e9b3ba..caad350114 100644 --- a/upnp.go +++ b/upnp.go @@ -2,11 +2,15 @@ package nat import ( "net" + "net/url" + "strings" "time" "github.com/huin/goupnp" "github.com/huin/goupnp/dcps/internetgateway1" "github.com/huin/goupnp/dcps/internetgateway2" + + "github.com/koron/go-ssdp" ) var ( @@ -123,6 +127,62 @@ func discoverUPNP_IG2() <-chan NAT { return res } +func discoverUPNP_GenIGDev() <-chan NAT { + res := make(chan NAT, 1) + go func() { + DeviceList, err := ssdp.Search(ssdp.All, 5, "") + if err != nil { + return + } + var gw ssdp.Service + for _, Service := range DeviceList { + if strings.Contains(Service.Type, "InternetGatewayDevice") { + gw = Service + break + } + } + + DeviceURL, err := url.Parse(gw.Location) + if err != nil { + return + } + RootDevice, err := goupnp.DeviceByURL(DeviceURL) + if err != nil { + return + } + + RootDevice.Device.VisitServices(func(srv *goupnp.Service) { + switch srv.ServiceType { + case internetgateway1.URN_WANIPConnection_1: + client := &internetgateway1.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: RootDevice, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatus() + if err == nil && isNat { + res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", RootDevice} + return + } + + case internetgateway1.URN_WANPPPConnection_1: + client := &internetgateway1.WANPPPConnection1{ServiceClient: goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: RootDevice, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatus() + if err == nil && isNat { + res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", RootDevice} + return + } + + } + }) + }() + return res +} + type upnp_NAT_Client interface { GetExternalIPAddress() (string, error) AddPortMapping(string, uint16, string, uint16, string, bool, string, uint32) error From 900ec35643486e5263aff91711dd2bf949945d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 1 Mar 2019 16:43:50 +0000 Subject: [PATCH 16/54] add gomod support // tag v0.0.1. --- .travis.yml | 32 ++++++++++++++++++++++++++++++++ go.mod | 4 +--- go.sum | 11 +++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 .travis.yml create mode 100644 go.sum diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..4cfe98c242 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +os: + - linux + +language: go + +go: + - 1.11.x + +env: + global: + - GOTFLAGS="-race" + matrix: + - BUILD_DEPTYPE=gx + - BUILD_DEPTYPE=gomod + + +# disable travis install +install: + - true + +script: + - bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh) + + +cache: + directories: + - $GOPATH/src/gx + - $GOPATH/pkg/mod + - $HOME/.cache/go-build + +notifications: + email: false diff --git a/go.mod b/go.mod index eb7991248d..bc8f7bcac9 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,7 @@ module github.com/libp2p/go-nat require ( - github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324 + github.com/huin/goupnp v1.0.0 github.com/jackpal/gateway v1.0.5 github.com/jackpal/go-nat-pmp v1.0.1 - golang.org/x/net v0.0.0-20180524181706-dfa909b99c79 - golang.org/x/text v0.3.0 ) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000000..cf1f0624a3 --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= +github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= +github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= +github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 943d7b398fc871282f7d14b0e16171ac0d3fbd2e Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 6 Mar 2019 09:58:32 -0800 Subject: [PATCH 17/54] expose all discovered NATs This change makes it possible to configure all discovered NATs, not just the first one found. --- nat.go | 65 +++++++++++++++++++++++++++++++++++++++++++++--------- natpmp.go | 40 +++++++++++++++++++++++---------- upnp.go | 66 +++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 131 insertions(+), 40 deletions(-) diff --git a/nat.go b/nat.go index eb574d63c2..4505df60bb 100644 --- a/nat.go +++ b/nat.go @@ -2,6 +2,7 @@ package nat import ( + "context" "errors" "math" "math/rand" @@ -34,20 +35,64 @@ type NAT interface { DeletePortMapping(protocol string, internalPort int) (err error) } +// DiscoverNATs returns all NATs discovered in the network. +func DiscoverNATs(ctx context.Context) <-chan NAT { + nats := make(chan NAT) + + go func() { + defer close(nats) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + upnpIg1 := discoverUPNP_IG1(ctx) + upnpIg2 := discoverUPNP_IG2(ctx) + natpmp := discoverNATPMP(ctx) + upnpGenIGDev := discoverUPNP_GenIGDev(ctx) + for upnpIg1 != nil || upnpIg2 != nil || natpmp != nil { + var ( + nat NAT + ok bool + ) + select { + case nat, ok = <-upnpIg1: + if !ok { + upnpIg1 = nil + } + case nat, ok = <-upnpIg2: + if !ok { + upnpIg2 = nil + } + case nat, ok = <-upnpGenIGDev: + if !ok { + upnpGenIGDev = nil + } + case nat, ok = <-natpmp: + if !ok { + natpmp = nil + } + } + if ok { + select { + case nats <- nat: + case <-ctx.Done(): + return + } + } + } + }() + return nats +} + // DiscoverGateway attempts to find a gateway device. func DiscoverGateway() (NAT, error) { - select { - case nat := <-discoverUPNP_IG1(): - return nat, nil - case nat := <-discoverUPNP_IG2(): - return nat, nil - case nat := <-discoverUPNP_GenIGDev(): - return nat, nil - case nat := <-discoverNATPMP(): - return nat, nil - case <-time.After(10 * time.Second): + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + nat := <-DiscoverNATs(ctx) + if nat == nil { return nil, ErrNoNATFound } + return nat, nil } func randomPort() int { diff --git a/natpmp.go b/natpmp.go index 395a5dd578..a31a499988 100644 --- a/natpmp.go +++ b/natpmp.go @@ -1,6 +1,7 @@ package nat import ( + "context" "net" "time" @@ -12,25 +13,42 @@ var ( _ NAT = (*natpmpNAT)(nil) ) -func discoverNATPMP() <-chan NAT { +func discoverNATPMP(ctx context.Context) <-chan NAT { res := make(chan NAT, 1) ip, err := gateway.DiscoverGateway() if err == nil { - go discoverNATPMPWithAddr(res, ip) + go func() { + defer close(res) + // Unfortunately, we can't actually _stop_ the natpmp + // library. However, we can at least close _our_ channel + // and walk away. + select { + case client, ok := <-discoverNATPMPWithAddr(ip): + if ok { + res <- &natpmpNAT{client, ip, make(map[int]int)} + } + case <-ctx.Done(): + } + }() + } else { + close(res) } - return res } -func discoverNATPMPWithAddr(c chan NAT, ip net.IP) { - client := natpmp.NewClient(ip) - _, err := client.GetExternalAddress() - if err != nil { - return - } - - c <- &natpmpNAT{client, ip, make(map[int]int)} +func discoverNATPMPWithAddr(ip net.IP) <-chan *natpmp.Client { + res := make(chan *natpmp.Client, 1) + go func() { + defer close(res) + client := natpmp.NewClient(ip) + _, err := client.GetExternalAddress() + if err != nil { + return + } + res <- client + }() + return res } type natpmpNAT struct { diff --git a/upnp.go b/upnp.go index caad350114..ccfeb14a2f 100644 --- a/upnp.go +++ b/upnp.go @@ -1,6 +1,7 @@ package nat import ( + "context" "net" "net/url" "strings" @@ -17,9 +18,10 @@ var ( _ NAT = (*upnp_NAT)(nil) ) -func discoverUPNP_IG1() <-chan NAT { - res := make(chan NAT, 1) +func discoverUPNP_IG1(ctx context.Context) <-chan NAT { + res := make(chan NAT) go func() { + defer close(res) // find devices devs, err := goupnp.DiscoverDevices(internetgateway1.URN_WANConnectionDevice_1) @@ -33,6 +35,9 @@ func discoverUPNP_IG1() <-chan NAT { } dev.Root.Device.VisitServices(func(srv *goupnp.Service) { + if ctx.Err() != nil { + return + } switch srv.ServiceType { case internetgateway1.URN_WANIPConnection_1: client := &internetgateway1.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ @@ -42,8 +47,10 @@ func discoverUPNP_IG1() <-chan NAT { }} _, isNat, err := client.GetNATRSIPStatus() if err == nil && isNat { - res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", dev.Root} - return + select { + case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", dev.Root}: + case <-ctx.Done(): + } } case internetgateway1.URN_WANPPPConnection_1: @@ -54,8 +61,10 @@ func discoverUPNP_IG1() <-chan NAT { }} _, isNat, err := client.GetNATRSIPStatus() if err == nil && isNat { - res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", dev.Root} - return + select { + case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", dev.Root}: + case <-ctx.Done(): + } } } @@ -66,9 +75,10 @@ func discoverUPNP_IG1() <-chan NAT { return res } -func discoverUPNP_IG2() <-chan NAT { - res := make(chan NAT, 1) +func discoverUPNP_IG2(ctx context.Context) <-chan NAT { + res := make(chan NAT) go func() { + defer close(res) // find devices devs, err := goupnp.DiscoverDevices(internetgateway2.URN_WANConnectionDevice_2) @@ -82,6 +92,9 @@ func discoverUPNP_IG2() <-chan NAT { } dev.Root.Device.VisitServices(func(srv *goupnp.Service) { + if ctx.Err() != nil { + return + } switch srv.ServiceType { case internetgateway2.URN_WANIPConnection_1: client := &internetgateway2.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ @@ -91,8 +104,10 @@ func discoverUPNP_IG2() <-chan NAT { }} _, isNat, err := client.GetNATRSIPStatus() if err == nil && isNat { - res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP1)", dev.Root} - return + select { + case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP1)", dev.Root}: + case <-ctx.Done(): + } } case internetgateway2.URN_WANIPConnection_2: @@ -103,8 +118,10 @@ func discoverUPNP_IG2() <-chan NAT { }} _, isNat, err := client.GetNATRSIPStatus() if err == nil && isNat { - res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP2)", dev.Root} - return + select { + case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP2)", dev.Root}: + case <-ctx.Done(): + } } case internetgateway2.URN_WANPPPConnection_1: @@ -115,8 +132,10 @@ func discoverUPNP_IG2() <-chan NAT { }} _, isNat, err := client.GetNATRSIPStatus() if err == nil && isNat { - res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-PPP1)", dev.Root} - return + select { + case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-PPP1)", dev.Root}: + case <-ctx.Done(): + } } } @@ -127,9 +146,11 @@ func discoverUPNP_IG2() <-chan NAT { return res } -func discoverUPNP_GenIGDev() <-chan NAT { +func discoverUPNP_GenIGDev(ctx context.Context) <-chan NAT { res := make(chan NAT, 1) go func() { + defer close(res) + DeviceList, err := ssdp.Search(ssdp.All, 5, "") if err != nil { return @@ -152,6 +173,9 @@ func discoverUPNP_GenIGDev() <-chan NAT { } RootDevice.Device.VisitServices(func(srv *goupnp.Service) { + if ctx.Err() != nil { + return + } switch srv.ServiceType { case internetgateway1.URN_WANIPConnection_1: client := &internetgateway1.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ @@ -161,8 +185,10 @@ func discoverUPNP_GenIGDev() <-chan NAT { }} _, isNat, err := client.GetNATRSIPStatus() if err == nil && isNat { - res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", RootDevice} - return + select { + case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", RootDevice}: + case <-ctx.Done(): + } } case internetgateway1.URN_WANPPPConnection_1: @@ -173,8 +199,10 @@ func discoverUPNP_GenIGDev() <-chan NAT { }} _, isNat, err := client.GetNATRSIPStatus() if err == nil && isNat { - res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", RootDevice} - return + select { + case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", RootDevice}: + case <-ctx.Done(): + } } } From c8594db014d29a36fe16880224818429f2a867c2 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 6 Mar 2019 10:44:40 -0800 Subject: [PATCH 18/54] try to pick the best NAT when multiple NATs are discovered --- nat.go | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/nat.go b/nat.go index 4505df60bb..727ae2a2e9 100644 --- a/nat.go +++ b/nat.go @@ -8,6 +8,8 @@ import ( "math/rand" "net" "time" + + "github.com/jackpal/gateway" ) var ErrNoExternalAddress = errors.New("no external address") @@ -88,11 +90,37 @@ func DiscoverNATs(ctx context.Context) <-chan NAT { func DiscoverGateway() (NAT, error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - nat := <-DiscoverNATs(ctx) - if nat == nil { + + var nats []NAT + for nat := range DiscoverNATs(ctx) { + nats = append(nats, nat) + } + switch len(nats) { + case 0: return nil, ErrNoNATFound + case 1: + return nats[0], nil + } + gw, _ := gateway.DiscoverGateway() + bestNAT := nats[0] + natGw, _ := bestNAT.GetDeviceAddress() + bestNATIsGw := gw != nil && natGw.Equal(gw) + // 1. Prefer gateways discovered _last_. This is an OK heuristic for + // discovering the most-upstream (furthest) NAT. + // 2. Prefer gateways that actually match our known gateway address. + // Some relays like to claim to be NATs even if they aren't. + for _, nat := range nats[1:] { + natGw, _ := nat.GetDeviceAddress() + natIsGw := gw != nil && natGw.Equal(gw) + + if bestNATIsGw && !natIsGw { + continue + } + + bestNATIsGw = natIsGw + bestNAT = nat } - return nat, nil + return bestNAT, nil } func randomPort() int { From e426ef9d27106ae2b62c8284a54059ec4c9fd263 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 11 Mar 2019 18:53:11 -0700 Subject: [PATCH 19/54] gx import go-ssdp --- package.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.json b/package.json index 61cdf82719..b8fa3361bb 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,12 @@ "hash": "QmYsYNh6saxUYHajdj49uiRzdxQgiFTtymrjf3d1f2Cer4", "name": "go-nat-pmp", "version": "1.0.1" + }, + { + "author": "koron", + "hash": "QmfDrLLyLVTLbDFfYvPsMqj3hgacxFCXyShZ5YjobqUAtr", + "name": "go-ssdp", + "version": "0.0.0" } ], "gxVersion": "0.9.0", From ab32e615c4b32a07ccbe9a857901c7e60a291754 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 12 Mar 2019 10:40:02 -0700 Subject: [PATCH 20/54] gx release 1.0.3 --- .gx/lastpubver | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gx/lastpubver b/.gx/lastpubver index d816451dee..0306793c53 100644 --- a/.gx/lastpubver +++ b/.gx/lastpubver @@ -1 +1 @@ -1.0.2: QmUTkdfn3e6EDb15C4XMHfooD5AoQxt5joYMeaqU56LU8h +1.0.3: QmdwkZHamNNrj7k3G29rnurmW3mFzsDhnyXppNcgYsiBVz diff --git a/package.json b/package.json index b8fa3361bb..7e176a89b2 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,6 @@ "language": "go", "license": "Apache-2.0", "name": "go-nat", - "version": "1.0.2" + "version": "1.0.3" } From 4a84cb455f3eddc5e46927656256c56b1e5c5cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 11 Apr 2019 21:11:16 +0100 Subject: [PATCH 21/54] farewell gx; thanks for serving us well. --- .gx/lastpubver | 1 - .travis.yml | 2 -- README.md | 4 ++++ package.json | 41 ----------------------------------------- 4 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 .gx/lastpubver delete mode 100644 package.json diff --git a/.gx/lastpubver b/.gx/lastpubver deleted file mode 100644 index 0306793c53..0000000000 --- a/.gx/lastpubver +++ /dev/null @@ -1 +0,0 @@ -1.0.3: QmdwkZHamNNrj7k3G29rnurmW3mFzsDhnyXppNcgYsiBVz diff --git a/.travis.yml b/.travis.yml index 4cfe98c242..5163d693fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ env: global: - GOTFLAGS="-race" matrix: - - BUILD_DEPTYPE=gx - BUILD_DEPTYPE=gomod @@ -24,7 +23,6 @@ script: cache: directories: - - $GOPATH/src/gx - $GOPATH/pkg/mod - $HOME/.cache/go-build diff --git a/README.md b/README.md index eec79193e6..61b5cc8891 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,7 @@ [![GoDoc](https://godoc.org/github.com/libp2p/go-nat?status.svg)](https://godoc.org/github.com/libp2p/go-nat) [![status](https://sourcegraph.com/api/repos/github.com/libp2p/go-nat/.badges/status.png)](https://sourcegraph.com/github.com/libp2p/go-nat) Forked from: [fd/go-nat](https://github.com/fd/go-nat). + +--- + +The last gx published version of this module was: 1.0.3: QmdwkZHamNNrj7k3G29rnurmW3mFzsDhnyXppNcgYsiBVz diff --git a/package.json b/package.json deleted file mode 100644 index 7e176a89b2..0000000000 --- a/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "author": "fd", - "bugs": { - "url": "https://github.com/issues/go-nat/issues" - }, - "gx": { - "dvcsimport": "github.com/libp2p/go-nat" - }, - "gxDependencies": [ - { - "author": "huin", - "hash": "QmVwfv63beSAAirq3tiLY6fkNqvjThLnCofL7363YkaScy", - "name": "goupnp", - "version": "0.1.0" - }, - { - "author": "jackpal", - "hash": "Qmf2fBLzCvFxs3vvZaoQyKSTv2rjApek4F1kzRxAfK6P4P", - "name": "gateway", - "version": "1.0.4" - }, - { - "author": "jackpal", - "hash": "QmYsYNh6saxUYHajdj49uiRzdxQgiFTtymrjf3d1f2Cer4", - "name": "go-nat-pmp", - "version": "1.0.1" - }, - { - "author": "koron", - "hash": "QmfDrLLyLVTLbDFfYvPsMqj3hgacxFCXyShZ5YjobqUAtr", - "name": "go-ssdp", - "version": "0.0.0" - } - ], - "gxVersion": "0.9.0", - "language": "go", - "license": "Apache-2.0", - "name": "go-nat", - "version": "1.0.3" -} - From 3f647da3badec64ef95ad393e159386e171204fb Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 11 Apr 2019 22:31:41 -0700 Subject: [PATCH 22/54] fix detection of GenIG NATs fixes #6 --- nat.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nat.go b/nat.go index 727ae2a2e9..371fdb0354 100644 --- a/nat.go +++ b/nat.go @@ -51,7 +51,7 @@ func DiscoverNATs(ctx context.Context) <-chan NAT { upnpIg2 := discoverUPNP_IG2(ctx) natpmp := discoverNATPMP(ctx) upnpGenIGDev := discoverUPNP_GenIGDev(ctx) - for upnpIg1 != nil || upnpIg2 != nil || natpmp != nil { + for upnpIg1 != nil || upnpIg2 != nil || natpmp != nil || upnpGenIGDev != nil { var ( nat NAT ok bool From 523cb01fafd52a886eff7de2af8c2846322e761f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 11 Apr 2019 22:34:27 -0700 Subject: [PATCH 23/54] Revert "Try to map external port the same as internal port" This reverts commit 3fa58ced20b2ff6110ae7eca6c22e18c06c8da6f. Its safer to just pick a random port. Unfortunately, some NATs (e.g., mine) suck and will happily map a port that's already been mapped elsewhere (e.g., in the port forwarding config). While this patch does the _nice_ thing, it was mostly cosmetic. --- natpmp.go | 7 ------- upnp.go | 6 ------ 2 files changed, 13 deletions(-) diff --git a/natpmp.go b/natpmp.go index e437250c3f..a31a499988 100644 --- a/natpmp.go +++ b/natpmp.go @@ -111,13 +111,6 @@ func (n *natpmpNAT) AddPortMapping(protocol string, internalPort int, descriptio } } - // try to map external port the same as internal port - _, err = n.c.AddPortMapping(protocol, internalPort, internalPort, timeoutInSeconds) - if err == nil { - n.ports[internalPort] = internalPort - return internalPort, nil - } - for i := 0; i < 3; i++ { externalPort := randomPort() _, err = n.c.AddPortMapping(protocol, internalPort, externalPort, timeoutInSeconds) diff --git a/upnp.go b/upnp.go index dddf7e7047..ccfeb14a2f 100644 --- a/upnp.go +++ b/upnp.go @@ -264,12 +264,6 @@ func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description } } - // try to map external port the same as internal port - err = u.c.AddPortMapping("", uint16(internalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) - if err == nil { - return internalPort, nil - } - for i := 0; i < 3; i++ { externalPort := randomPort() err = u.c.AddPortMapping("", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) From 0938e5d8a2a3ad5f5d8706159eefec54c7fe0230 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 3 May 2019 10:27:04 -0700 Subject: [PATCH 24/54] don't mask context --- nat.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/nat.go b/nat.go index 371fdb0354..c38030075c 100644 --- a/nat.go +++ b/nat.go @@ -44,9 +44,6 @@ func DiscoverNATs(ctx context.Context) <-chan NAT { go func() { defer close(nats) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - upnpIg1 := discoverUPNP_IG1(ctx) upnpIg2 := discoverUPNP_IG2(ctx) natpmp := discoverNATPMP(ctx) From 93d0ace99efa5d8be6a0ddf83f601d304ddb0ee7 Mon Sep 17 00:00:00 2001 From: iulianpascalau Date: Thu, 21 Nov 2019 20:16:09 +0200 Subject: [PATCH 25/54] updated go.mod and go.sum to the latest version of github.com/koron/go-ssdp library that has the race condition fixed --- go.mod | 4 +++- go.sum | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 718fdbdff7..a6dd7e1e41 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,7 @@ require ( github.com/huin/goupnp v1.0.0 github.com/jackpal/gateway v1.0.5 github.com/jackpal/go-nat-pmp v1.0.1 - github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b + github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d ) + +go 1.12 diff --git a/go.sum b/go.sum index 1a3a280ed3..399175cc00 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= -github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= From 199acda704ad6efe375ad8dcd39eb44f8017a6f7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 22 Nov 2019 08:20:25 -0800 Subject: [PATCH 26/54] fix: really obey the context The internal nat discovery logic doesn't properly propagate the context. --- nat.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nat.go b/nat.go index c38030075c..d38ad52c12 100644 --- a/nat.go +++ b/nat.go @@ -70,6 +70,9 @@ func DiscoverNATs(ctx context.Context) <-chan NAT { if !ok { natpmp = nil } + case <-ctx.Done(): + // timeout. + return } if ok { select { From c437f7a097d61f1a7cabac8c4ef4a32e0f35961f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2019 17:39:48 +0000 Subject: [PATCH 27/54] Bump github.com/jackpal/go-nat-pmp from 1.0.1 to 1.0.2 Bumps [github.com/jackpal/go-nat-pmp](https://github.com/jackpal/go-nat-pmp) from 1.0.1 to 1.0.2. - [Release notes](https://github.com/jackpal/go-nat-pmp/releases) - [Commits](https://github.com/jackpal/go-nat-pmp/compare/v1.0.1...v1.0.2) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index a6dd7e1e41..3b3c622235 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/libp2p/go-nat require ( github.com/huin/goupnp v1.0.0 github.com/jackpal/gateway v1.0.5 - github.com/jackpal/go-nat-pmp v1.0.1 + github.com/jackpal/go-nat-pmp v1.0.2 github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d ) diff --git a/go.sum b/go.sum index 399175cc00..547800b2b7 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= From 4b6e89e7d7f1616b924bd44b8fc8bb8b432957a8 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 6 Dec 2019 16:33:55 -0500 Subject: [PATCH 28/54] ci: bump to go 1.13 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5163d693fc..a156d3eb5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ os: language: go go: - - 1.11.x + - 1.13.x env: global: From d4146fbf230ffc7c46cc165761908501cb5db8c1 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 30 Mar 2020 14:05:40 -0700 Subject: [PATCH 29/54] feat: switch to go-netroute This library makes the correct syscalls instead of shelling out to a binary. --- gateway.go | 17 +++++++++++++++++ go.mod | 2 +- go.sum | 17 +++++++++++++---- nat.go | 4 +--- natpmp.go | 35 +++++++++++++++++------------------ 5 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 gateway.go diff --git a/gateway.go b/gateway.go new file mode 100644 index 0000000000..a87e46a892 --- /dev/null +++ b/gateway.go @@ -0,0 +1,17 @@ +package nat + +import ( + "net" + + "github.com/libp2p/go-netroute" +) + +func getDefaultGateway() (net.IP, error) { + router, err := netroute.New() + if err != nil { + return nil, err + } + + _, ip, _, err := router.Route(net.IPv4zero) + return ip, err +} diff --git a/go.mod b/go.mod index 3b3c622235..605525ba0c 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,9 @@ module github.com/libp2p/go-nat require ( github.com/huin/goupnp v1.0.0 - github.com/jackpal/gateway v1.0.5 github.com/jackpal/go-nat-pmp v1.0.2 github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d + github.com/libp2p/go-netroute v0.1.2 ) go 1.12 diff --git a/go.sum b/go.sum index 547800b2b7..70ef62784e 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,24 @@ +github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= -github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= -github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= -github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR4Xg= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-sockaddr v0.0.2 h1:tCuXfpA9rq7llM/v834RKc/Xvovy/AqM9kHvTV/jY/Q= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/nat.go b/nat.go index d38ad52c12..a2606794fe 100644 --- a/nat.go +++ b/nat.go @@ -8,8 +8,6 @@ import ( "math/rand" "net" "time" - - "github.com/jackpal/gateway" ) var ErrNoExternalAddress = errors.New("no external address") @@ -101,7 +99,7 @@ func DiscoverGateway() (NAT, error) { case 1: return nats[0], nil } - gw, _ := gateway.DiscoverGateway() + gw, _ := getDefaultGateway() bestNAT := nats[0] natGw, _ := bestNAT.GetDeviceAddress() bestNATIsGw := gw != nil && natGw.Equal(gw) diff --git a/natpmp.go b/natpmp.go index a31a499988..495d42b49e 100644 --- a/natpmp.go +++ b/natpmp.go @@ -5,7 +5,6 @@ import ( "net" "time" - "github.com/jackpal/gateway" "github.com/jackpal/go-nat-pmp" ) @@ -16,24 +15,24 @@ var ( func discoverNATPMP(ctx context.Context) <-chan NAT { res := make(chan NAT, 1) - ip, err := gateway.DiscoverGateway() - if err == nil { - go func() { - defer close(res) - // Unfortunately, we can't actually _stop_ the natpmp - // library. However, we can at least close _our_ channel - // and walk away. - select { - case client, ok := <-discoverNATPMPWithAddr(ip): - if ok { - res <- &natpmpNAT{client, ip, make(map[int]int)} - } - case <-ctx.Done(): - } - }() - } else { - close(res) + ip, err := getDefaultGateway() + if err != nil { + return nil } + + go func() { + defer close(res) + // Unfortunately, we can't actually _stop_ the natpmp + // library. However, we can at least close _our_ channel + // and walk away. + select { + case client, ok := <-discoverNATPMPWithAddr(ip): + if ok { + res <- &natpmpNAT{client, ip, make(map[int]int)} + } + case <-ctx.Done(): + } + }() return res } From c7e6c5b5c607520f521088ce957563618b8588e5 Mon Sep 17 00:00:00 2001 From: web3-bot <81333946+web3-bot@users.noreply.github.com> Date: Thu, 22 Apr 2021 06:09:21 -0400 Subject: [PATCH 30/54] sync: update CI config files (#20) --- .github/workflows/automerge.yml | 27 ++++++++++++++++++++++ .github/workflows/go-check.yml | 41 +++++++++++++++++++++++++++++++++ .github/workflows/go-test.yml | 38 ++++++++++++++++++++++++++++++ .travis.yml | 30 ------------------------ go.mod | 2 +- go.sum | 1 - 6 files changed, 107 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/automerge.yml create mode 100644 .github/workflows/go-check.yml create mode 100644 .github/workflows/go-test.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 0000000000..840618d88f --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,27 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +# Automatically merge pull requests opened by web3-bot, as soon as (and only if) all tests pass. +# This reduces the friction associated with updating with our workflows. + +on: [ pull_request ] + +jobs: + automerge: + if: github.event.pull_request.user.login == 'web3-bot' + runs-on: ubuntu-latest + steps: + - name: Wait on tests + uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 10 + running-workflow-name: 'automerge' # the name of this job + - name: Merge PR + uses: pascalgn/automerge-action@741c311a47881be9625932b0a0de1b0937aab1ae # v0.13.1 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + MERGE_LABELS: "" + MERGE_METHOD: "squash" + MERGE_DELETE_BRANCH: true diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml new file mode 100644 index 0000000000..862d49fc9f --- /dev/null +++ b/.github/workflows/go-check.yml @@ -0,0 +1,41 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +on: [push, pull_request] + +jobs: + unit: + runs-on: ubuntu-latest + name: Go checks + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: "1.16.x" + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@be534f007836a777104a15f2456cd1fffd3ddee8 # v2020.2.2 + - name: Check that go.mod is tidy + run: | + go mod tidy + if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then + echo "go.sum was added by go mod tidy" + exit 1 + fi + git diff --exit-code -- go.sum go.mod + - name: gofmt + if: ${{ success() || failure() }} # run this step even if the previous one failed + run: | + out=$(gofmt -s -l .) + if [[ -n "$out" ]]; then + echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}' + exit 1 + fi + - name: go vet + if: ${{ success() || failure() }} # run this step even if the previous one failed + run: go vet ./... + - name: staticcheck + if: ${{ success() || failure() }} # run this step even if the previous one failed + run: | + set -o pipefail + staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' + diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml new file mode 100644 index 0000000000..9b38420862 --- /dev/null +++ b/.github/workflows/go-test.yml @@ -0,0 +1,38 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +on: [push, pull_request] + +jobs: + unit: + strategy: + fail-fast: false + matrix: + os: [ "ubuntu", "windows", "macos" ] + go: [ "1.15.x", "1.16.x" ] + runs-on: ${{ matrix.os }}-latest + name: Unit tests (${{ matrix.os}}, Go ${{ matrix.go }}) + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + - name: Go information + run: | + go version + go env + - name: Run tests + run: go test -v -coverprofile coverage.txt ./... + - name: Run tests (32 bit) + if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. + env: + GOARCH: 386 + run: go test -v ./... + - name: Run tests with race detector + if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow + run: go test -v -race ./... + - name: Upload coverage to Codecov + uses: codecov/codecov-action@967e2b38a85a62bd61be5529ada27ebc109948c2 # v1.4.1 + with: + file: coverage.txt + env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a156d3eb5e..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -os: - - linux - -language: go - -go: - - 1.13.x - -env: - global: - - GOTFLAGS="-race" - matrix: - - BUILD_DEPTYPE=gomod - - -# disable travis install -install: - - true - -script: - - bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh) - - -cache: - directories: - - $GOPATH/pkg/mod - - $HOME/.cache/go-build - -notifications: - email: false diff --git a/go.mod b/go.mod index 605525ba0c..1157feea8e 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,4 @@ require ( github.com/libp2p/go-netroute v0.1.2 ) -go 1.12 +go 1.15 diff --git a/go.sum b/go.sum index 70ef62784e..be2d04ac02 100644 --- a/go.sum +++ b/go.sum @@ -12,7 +12,6 @@ github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdm github.com/libp2p/go-sockaddr v0.0.2 h1:tCuXfpA9rq7llM/v834RKc/Xvovy/AqM9kHvTV/jY/Q= github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= From 18d105319b4b4595a3b44f9c47999b8f9795c54c Mon Sep 17 00:00:00 2001 From: web3-bot <81333946+web3-bot@users.noreply.github.com> Date: Tue, 1 Jun 2021 13:59:30 -0400 Subject: [PATCH 31/54] sync: update CI config files (#21) --- .github/workflows/automerge.yml | 26 +++++++++++++++++++++++- .github/workflows/go-check.yml | 35 +++++++++++++++++++++------------ .github/workflows/go-test.yml | 19 +++++++++++++----- 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 840618d88f..32bcc2e6e5 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -5,11 +5,35 @@ # This reduces the friction associated with updating with our workflows. on: [ pull_request ] +name: Automerge jobs: - automerge: + automerge-check: if: github.event.pull_request.user.login == 'web3-bot' runs-on: ubuntu-latest + outputs: + status: ${{ steps.should-automerge.outputs.status }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Check if we should automerge + id: should-automerge + run: | + for commit in $(git rev-list --first-parent origin/${{ github.event.pull_request.base.ref }}..${{ github.event.pull_request.head.sha }}); do + committer=$(git show --format=$'%ce' -s $commit) + echo "Committer: $committer" + if [[ "$committer" != "web3-bot@users.noreply.github.com" ]]; then + echo "Commit $commit wasn't committed by web3-bot, but by $committer." + echo "::set-output name=status::false" + exit + fi + done + echo "::set-output name=status::true" + automerge: + needs: automerge-check + runs-on: ubuntu-latest + if: ${{ needs.automerge-check.outputs.status == 'true' }} steps: - name: Wait on tests uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2 diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index 862d49fc9f..00ce947c82 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -2,26 +2,31 @@ # See https://github.com/protocol/.github/ for details. on: [push, pull_request] +name: Go Checks jobs: unit: runs-on: ubuntu-latest - name: Go checks + name: All steps: - uses: actions/checkout@v2 + with: + submodules: recursive - uses: actions/setup-go@v2 with: go-version: "1.16.x" - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@be534f007836a777104a15f2456cd1fffd3ddee8 # v2020.2.2 + run: go install honnef.co/go/tools/cmd/staticcheck@434f5f3816b358fe468fa83dcba62d794e7fe04b # 2021.1 (v0.2.0) - name: Check that go.mod is tidy - run: | - go mod tidy - if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then - echo "go.sum was added by go mod tidy" - exit 1 - fi - git diff --exit-code -- go.sum go.mod + uses: protocol/multiple-go-modules@v1.0 + with: + run: | + go mod tidy + if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then + echo "go.sum was added by go mod tidy" + exit 1 + fi + git diff --exit-code -- go.sum go.mod - name: gofmt if: ${{ success() || failure() }} # run this step even if the previous one failed run: | @@ -32,10 +37,14 @@ jobs: fi - name: go vet if: ${{ success() || failure() }} # run this step even if the previous one failed - run: go vet ./... + uses: protocol/multiple-go-modules@v1.0 + with: + run: go vet ./... - name: staticcheck if: ${{ success() || failure() }} # run this step even if the previous one failed - run: | - set -o pipefail - staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' + uses: protocol/multiple-go-modules@v1.0 + with: + run: | + set -o pipefail + staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 9b38420862..4c7138b01d 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -2,6 +2,7 @@ # See https://github.com/protocol/.github/ for details. on: [push, pull_request] +name: Go Test jobs: unit: @@ -11,9 +12,11 @@ jobs: os: [ "ubuntu", "windows", "macos" ] go: [ "1.15.x", "1.16.x" ] runs-on: ${{ matrix.os }}-latest - name: Unit tests (${{ matrix.os}}, Go ${{ matrix.go }}) + name: ${{ matrix.os}} (go ${{ matrix.go }}) steps: - uses: actions/checkout@v2 + with: + submodules: recursive - uses: actions/setup-go@v2 with: go-version: ${{ matrix.go }} @@ -22,17 +25,23 @@ jobs: go version go env - name: Run tests - run: go test -v -coverprofile coverage.txt ./... + uses: protocol/multiple-go-modules@v1.0 + with: + run: go test -v -coverprofile coverage.txt ./... - name: Run tests (32 bit) if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. + uses: protocol/multiple-go-modules@v1.0 env: GOARCH: 386 - run: go test -v ./... + with: + run: go test -v ./... - name: Run tests with race detector if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow - run: go test -v -race ./... + uses: protocol/multiple-go-modules@v1.0 + with: + run: go test -v -race ./... - name: Upload coverage to Codecov - uses: codecov/codecov-action@967e2b38a85a62bd61be5529ada27ebc109948c2 # v1.4.1 + uses: codecov/codecov-action@a1ed4b322b4b38cb846afb5a0ebfa17086917d27 # v1.5.0 with: file: coverage.txt env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} From 558869fa7f90efdfdc9058e206ad79e28d8bd2eb Mon Sep 17 00:00:00 2001 From: web3-bot <81333946+web3-bot@users.noreply.github.com> Date: Tue, 17 Aug 2021 10:45:47 -0400 Subject: [PATCH 32/54] sync: update CI config files (#22) --- .github/workflows/automerge.yml | 4 +++- .github/workflows/go-check.yml | 34 ++++++++++++++++++++++++++++----- .github/workflows/go-test.yml | 22 ++++++++++++++------- go.mod | 2 +- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 32bcc2e6e5..44fad65fc1 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -33,7 +33,9 @@ jobs: automerge: needs: automerge-check runs-on: ubuntu-latest - if: ${{ needs.automerge-check.outputs.status == 'true' }} + # The check for the user is redundant here, as this job depends on the automerge-check job, + # but it prevents this job from spinning up, just to be skipped shortly after. + if: github.event.pull_request.user.login == 'web3-bot' && needs.automerge-check.outputs.status == 'true' steps: - name: Wait on tests uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2 diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index 00ce947c82..6acdd48f97 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -8,17 +8,28 @@ jobs: unit: runs-on: ubuntu-latest name: All + env: + RUNGOGENERATE: false steps: - uses: actions/checkout@v2 with: submodules: recursive - uses: actions/setup-go@v2 with: - go-version: "1.16.x" + go-version: "1.17.x" + - name: Run repo-specific setup + uses: ./.github/actions/go-check-setup + if: hashFiles('./.github/actions/go-check-setup') != '' + - name: Read config + if: hashFiles('./.github/workflows/go-check-config.json') != '' + run: | + if jq -re .gogenerate ./.github/workflows/go-check-config.json; then + echo "RUNGOGENERATE=true" >> $GITHUB_ENV + fi - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@434f5f3816b358fe468fa83dcba62d794e7fe04b # 2021.1 (v0.2.0) + run: go install honnef.co/go/tools/cmd/staticcheck@df71e5d0e0ed317ebf43e6e59cf919430fa4b8f2 # 2021.1.1 (v0.2.1) - name: Check that go.mod is tidy - uses: protocol/multiple-go-modules@v1.0 + uses: protocol/multiple-go-modules@v1.2 with: run: | go mod tidy @@ -37,14 +48,27 @@ jobs: fi - name: go vet if: ${{ success() || failure() }} # run this step even if the previous one failed - uses: protocol/multiple-go-modules@v1.0 + uses: protocol/multiple-go-modules@v1.2 with: run: go vet ./... - name: staticcheck if: ${{ success() || failure() }} # run this step even if the previous one failed - uses: protocol/multiple-go-modules@v1.0 + uses: protocol/multiple-go-modules@v1.2 with: run: | set -o pipefail staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' + - name: go generate + uses: protocol/multiple-go-modules@v1.2 + if: (success() || failure()) && env.RUNGOGENERATE == 'true' + with: + run: | + git clean -fd # make sure there aren't untracked files / directories + go generate ./... + # check if go generate modified or added any files + if ! $(git add . && git diff-index HEAD --exit-code --quiet); then + echo "go generated caused changes to the repository:" + git status --short + exit 1 + fi diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 4c7138b01d..7010dccec4 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -10,7 +10,9 @@ jobs: fail-fast: false matrix: os: [ "ubuntu", "windows", "macos" ] - go: [ "1.15.x", "1.16.x" ] + go: [ "1.16.x", "1.17.x" ] + env: + COVERAGES: "" runs-on: ${{ matrix.os }}-latest name: ${{ matrix.os}} (go ${{ matrix.go }}) steps: @@ -24,24 +26,30 @@ jobs: run: | go version go env + - name: Run repo-specific setup + uses: ./.github/actions/go-test-setup + if: hashFiles('./.github/actions/go-test-setup') != '' - name: Run tests - uses: protocol/multiple-go-modules@v1.0 + uses: protocol/multiple-go-modules@v1.2 with: - run: go test -v -coverprofile coverage.txt ./... + run: go test -v -coverprofile module-coverage.txt ./... - name: Run tests (32 bit) if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. - uses: protocol/multiple-go-modules@v1.0 + uses: protocol/multiple-go-modules@v1.2 env: GOARCH: 386 with: run: go test -v ./... - name: Run tests with race detector if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow - uses: protocol/multiple-go-modules@v1.0 + uses: protocol/multiple-go-modules@v1.2 with: run: go test -v -race ./... + - name: Collect coverage files + shell: bash + run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV - name: Upload coverage to Codecov - uses: codecov/codecov-action@a1ed4b322b4b38cb846afb5a0ebfa17086917d27 # v1.5.0 + uses: codecov/codecov-action@51d810878be5422784e86451c0e7c14e5860ec47 # v2.0.2 with: - file: coverage.txt + files: '${{ env.COVERAGES }}' env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} diff --git a/go.mod b/go.mod index 1157feea8e..53fe02c477 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,4 @@ require ( github.com/libp2p/go-netroute v0.1.2 ) -go 1.15 +go 1.16 From d0d64ea585d6f0f677454ade85f59fbccdf35b06 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Sun, 19 Sep 2021 10:02:49 +0100 Subject: [PATCH 33/54] pass a context to DiscoverGateway --- nat.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nat.go b/nat.go index a2606794fe..6d295e66f5 100644 --- a/nat.go +++ b/nat.go @@ -85,10 +85,7 @@ func DiscoverNATs(ctx context.Context) <-chan NAT { } // DiscoverGateway attempts to find a gateway device. -func DiscoverGateway() (NAT, error) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - +func DiscoverGateway(ctx context.Context) (NAT, error) { var nats []NAT for nat := range DiscoverNATs(ctx) { nats = append(nats, nat) From 763460e5306c204c55bcdd411675184de2ea137a Mon Sep 17 00:00:00 2001 From: web3-bot <81333946+web3-bot@users.noreply.github.com> Date: Fri, 10 Dec 2021 10:50:40 -0500 Subject: [PATCH 34/54] sync: update CI config files (#24) --- .github/workflows/go-check.yml | 2 +- .github/workflows/go-test.yml | 15 +++++++++++++-- .github/workflows/release-check.yml | 11 +++++++++++ .github/workflows/releaser.yml | 11 +++++++++++ .github/workflows/tagpush.yml | 12 ++++++++++++ version.json | 3 +++ 6 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/release-check.yml create mode 100644 .github/workflows/releaser.yml create mode 100644 .github/workflows/tagpush.yml create mode 100644 version.json diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index 6acdd48f97..e127cf1792 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -27,7 +27,7 @@ jobs: echo "RUNGOGENERATE=true" >> $GITHUB_ENV fi - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@df71e5d0e0ed317ebf43e6e59cf919430fa4b8f2 # 2021.1.1 (v0.2.1) + run: go install honnef.co/go/tools/cmd/staticcheck@c8caa92bad8c27ae734c6725b8a04932d54a147b # 2021.1.2 (v0.2.2) - name: Check that go.mod is tidy uses: protocol/multiple-go-modules@v1.2 with: diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 7010dccec4..606e0c7f3d 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -26,13 +26,24 @@ jobs: run: | go version go env + - name: Use msys2 on windows + if: ${{ matrix.os == 'windows' }} + shell: bash + # The executable for msys2 is also called bash.cmd + # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells + # If we prepend its location to the PATH + # subsequent 'shell: bash' steps will use msys2 instead of gitbash + run: echo "C:/msys64/usr/bin" >> $GITHUB_PATH - name: Run repo-specific setup uses: ./.github/actions/go-test-setup if: hashFiles('./.github/actions/go-test-setup') != '' - name: Run tests uses: protocol/multiple-go-modules@v1.2 with: - run: go test -v -coverprofile module-coverage.txt ./... + # Use -coverpkg=./..., so that we include cross-package coverage. + # If package ./A imports ./B, and ./A's tests also cover ./B, + # this means ./B's coverage will be significantly higher than 0%. + run: go test -v -coverprofile=module-coverage.txt -coverpkg=./... ./... - name: Run tests (32 bit) if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. uses: protocol/multiple-go-modules@v1.2 @@ -49,7 +60,7 @@ jobs: shell: bash run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV - name: Upload coverage to Codecov - uses: codecov/codecov-action@51d810878be5422784e86451c0e7c14e5860ec47 # v2.0.2 + uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: files: '${{ env.COVERAGES }}' env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} diff --git a/.github/workflows/release-check.yml b/.github/workflows/release-check.yml new file mode 100644 index 0000000000..fde81c1f88 --- /dev/null +++ b/.github/workflows/release-check.yml @@ -0,0 +1,11 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +name: Release Checker +on: + pull_request: + paths: [ 'version.json' ] + +jobs: + release-check: + uses: protocol/.github/.github/workflows/release-check.yml@master diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml new file mode 100644 index 0000000000..cdccbf873d --- /dev/null +++ b/.github/workflows/releaser.yml @@ -0,0 +1,11 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +name: Releaser +on: + push: + paths: [ 'version.json' ] + +jobs: + releaser: + uses: protocol/.github/.github/workflows/releaser.yml@master diff --git a/.github/workflows/tagpush.yml b/.github/workflows/tagpush.yml new file mode 100644 index 0000000000..d84996187a --- /dev/null +++ b/.github/workflows/tagpush.yml @@ -0,0 +1,12 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +name: Tag Push Checker +on: + push: + tags: + - v* + +jobs: + releaser: + uses: protocol/.github/.github/workflows/tagpush.yml@master diff --git a/version.json b/version.json new file mode 100644 index 0000000000..557859c534 --- /dev/null +++ b/version.json @@ -0,0 +1,3 @@ +{ + "version": "v0.1.0" +} From f775be19d726fa7532c58cfabb4a8c1640722b06 Mon Sep 17 00:00:00 2001 From: web3-bot <81333946+web3-bot@users.noreply.github.com> Date: Mon, 4 Apr 2022 18:58:11 +0200 Subject: [PATCH 35/54] sync: update CI config files (#25) --- .github/workflows/automerge.yml | 50 +++------------------------------ .github/workflows/go-check.yml | 5 ++-- .github/workflows/go-test.yml | 10 ++++--- go.mod | 10 ++++++- 4 files changed, 21 insertions(+), 54 deletions(-) diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 44fad65fc1..3833fc2291 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -1,53 +1,11 @@ # File managed by web3-bot. DO NOT EDIT. # See https://github.com/protocol/.github/ for details. -# Automatically merge pull requests opened by web3-bot, as soon as (and only if) all tests pass. -# This reduces the friction associated with updating with our workflows. - -on: [ pull_request ] name: Automerge +on: [ pull_request ] jobs: - automerge-check: - if: github.event.pull_request.user.login == 'web3-bot' - runs-on: ubuntu-latest - outputs: - status: ${{ steps.should-automerge.outputs.status }} - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Check if we should automerge - id: should-automerge - run: | - for commit in $(git rev-list --first-parent origin/${{ github.event.pull_request.base.ref }}..${{ github.event.pull_request.head.sha }}); do - committer=$(git show --format=$'%ce' -s $commit) - echo "Committer: $committer" - if [[ "$committer" != "web3-bot@users.noreply.github.com" ]]; then - echo "Commit $commit wasn't committed by web3-bot, but by $committer." - echo "::set-output name=status::false" - exit - fi - done - echo "::set-output name=status::true" automerge: - needs: automerge-check - runs-on: ubuntu-latest - # The check for the user is redundant here, as this job depends on the automerge-check job, - # but it prevents this job from spinning up, just to be skipped shortly after. - if: github.event.pull_request.user.login == 'web3-bot' && needs.automerge-check.outputs.status == 'true' - steps: - - name: Wait on tests - uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2 - with: - ref: ${{ github.event.pull_request.head.sha }} - repo-token: ${{ secrets.GITHUB_TOKEN }} - wait-interval: 10 - running-workflow-name: 'automerge' # the name of this job - - name: Merge PR - uses: pascalgn/automerge-action@741c311a47881be9625932b0a0de1b0937aab1ae # v0.13.1 - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - MERGE_LABELS: "" - MERGE_METHOD: "squash" - MERGE_DELETE_BRANCH: true + uses: protocol/.github/.github/workflows/automerge.yml@master + with: + job: 'automerge' diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index e127cf1792..25e1afde5f 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -16,7 +16,7 @@ jobs: submodules: recursive - uses: actions/setup-go@v2 with: - go-version: "1.17.x" + go-version: "1.18.x" - name: Run repo-specific setup uses: ./.github/actions/go-check-setup if: hashFiles('./.github/actions/go-check-setup') != '' @@ -27,7 +27,7 @@ jobs: echo "RUNGOGENERATE=true" >> $GITHUB_ENV fi - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@c8caa92bad8c27ae734c6725b8a04932d54a147b # 2021.1.2 (v0.2.2) + run: go install honnef.co/go/tools/cmd/staticcheck@d7e217c1ff411395475b2971c0824e1e7cc1af98 # 2022.1 (v0.3.0) - name: Check that go.mod is tidy uses: protocol/multiple-go-modules@v1.2 with: @@ -71,4 +71,3 @@ jobs: git status --short exit 1 fi - diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 606e0c7f3d..b86241a96a 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -10,11 +10,11 @@ jobs: fail-fast: false matrix: os: [ "ubuntu", "windows", "macos" ] - go: [ "1.16.x", "1.17.x" ] + go: [ "1.17.x", "1.18.x" ] env: COVERAGES: "" - runs-on: ${{ matrix.os }}-latest - name: ${{ matrix.os}} (go ${{ matrix.go }}) + runs-on: ${{ format('{0}-latest', matrix.os) }} + name: ${{ matrix.os }} (go ${{ matrix.go }}) steps: - uses: actions/checkout@v2 with: @@ -50,7 +50,9 @@ jobs: env: GOARCH: 386 with: - run: go test -v ./... + run: | + export "PATH=${{ env.PATH_386 }}:$PATH" + go test -v ./... - name: Run tests with race detector if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow uses: protocol/multiple-go-modules@v1.2 diff --git a/go.mod b/go.mod index 53fe02c477..bd6064ff3e 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,12 @@ require ( github.com/libp2p/go-netroute v0.1.2 ) -go 1.16 +require ( + github.com/google/gopacket v1.1.17 // indirect + github.com/libp2p/go-sockaddr v0.0.2 // indirect + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect + golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 // indirect + golang.org/x/text v0.3.0 // indirect +) + +go 1.17 From afac959aa59868d8fdc27055763d1caa8617e23e Mon Sep 17 00:00:00 2001 From: web3-bot <81333946+web3-bot@users.noreply.github.com> Date: Tue, 23 Aug 2022 17:39:57 +0200 Subject: [PATCH 36/54] sync: update CI config files (#26) --- .github/workflows/go-check.yml | 8 ++++---- .github/workflows/go-test.yml | 12 ++++++------ go.mod | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index 25e1afde5f..251f7faa99 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -11,12 +11,12 @@ jobs: env: RUNGOGENERATE: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: recursive - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: - go-version: "1.18.x" + go-version: "1.19.x" - name: Run repo-specific setup uses: ./.github/actions/go-check-setup if: hashFiles('./.github/actions/go-check-setup') != '' @@ -27,7 +27,7 @@ jobs: echo "RUNGOGENERATE=true" >> $GITHUB_ENV fi - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@d7e217c1ff411395475b2971c0824e1e7cc1af98 # 2022.1 (v0.3.0) + run: go install honnef.co/go/tools/cmd/staticcheck@376210a89477dedbe6fdc4484b233998650d7b3c # 2022.1.3 (v0.3.3) - name: Check that go.mod is tidy uses: protocol/multiple-go-modules@v1.2 with: diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index b86241a96a..8a1697b2d0 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -10,16 +10,16 @@ jobs: fail-fast: false matrix: os: [ "ubuntu", "windows", "macos" ] - go: [ "1.17.x", "1.18.x" ] + go: [ "1.18.x", "1.19.x" ] env: COVERAGES: "" runs-on: ${{ format('{0}-latest', matrix.os) }} name: ${{ matrix.os }} (go ${{ matrix.go }}) steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: recursive - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: go-version: ${{ matrix.go }} - name: Go information @@ -43,7 +43,7 @@ jobs: # Use -coverpkg=./..., so that we include cross-package coverage. # If package ./A imports ./B, and ./A's tests also cover ./B, # this means ./B's coverage will be significantly higher than 0%. - run: go test -v -coverprofile=module-coverage.txt -coverpkg=./... ./... + run: go test -v -shuffle=on -coverprofile=module-coverage.txt -coverpkg=./... ./... - name: Run tests (32 bit) if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. uses: protocol/multiple-go-modules@v1.2 @@ -52,7 +52,7 @@ jobs: with: run: | export "PATH=${{ env.PATH_386 }}:$PATH" - go test -v ./... + go test -v -shuffle=on ./... - name: Run tests with race detector if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow uses: protocol/multiple-go-modules@v1.2 @@ -62,7 +62,7 @@ jobs: shell: bash run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV - name: Upload coverage to Codecov - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 with: files: '${{ env.COVERAGES }}' env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} diff --git a/go.mod b/go.mod index bd6064ff3e..58a070bdb0 100644 --- a/go.mod +++ b/go.mod @@ -15,4 +15,4 @@ require ( golang.org/x/text v0.3.0 // indirect ) -go 1.17 +go 1.18 From 5b1afd6fe97cd85af0777e7603e8f10a064cba74 Mon Sep 17 00:00:00 2001 From: "libp2p-mgmt-read-write[bot]" <104492852+libp2p-mgmt-read-write[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 13:40:11 +0000 Subject: [PATCH 37/54] chore: Update .github/workflows/stale.yml [skip ci] --- .github/workflows/stale.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000000..6f6d895d19 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,26 @@ +name: Close and mark stale issue + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'Oops, seems like we needed more information for this issue, please comment with more details or this issue will be closed in 7 days.' + close-issue-message: 'This issue was closed because it is missing author input.' + stale-issue-label: 'kind/stale' + any-of-labels: 'need/author-input' + exempt-issue-labels: 'need/triage,need/community-input,need/maintainer-input,need/maintainers-input,need/analysis,status/blocked,status/in-progress,status/ready,status/deferred,status/inactive' + days-before-issue-stale: 6 + days-before-issue-close: 7 + enable-statistics: true From dc44869708bb967ad8c354a9d89b5b96e9494d71 Mon Sep 17 00:00:00 2001 From: web3-bot <81333946+web3-bot@users.noreply.github.com> Date: Sat, 8 Apr 2023 07:00:14 +0200 Subject: [PATCH 38/54] sync: update CI config files (#28) * bump go.mod to Go 1.19 and run go fix * stop using the deprecated io/ioutil package * update .github/workflows/go-test.yml * update .github/workflows/go-check.yml * update .github/workflows/release-check.yml * don't use rand.Seed any more --------- Co-authored-by: web3-bot Co-authored-by: Marten Seemann --- .github/workflows/go-check.yml | 24 +++++++++--------------- .github/workflows/go-test.yml | 22 +++++++++++++++------- .github/workflows/release-check.yml | 4 +++- go.mod | 2 +- nat.go | 5 +++-- natpmp.go | 2 +- 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index 251f7faa99..cc65ce68a9 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -8,26 +8,20 @@ jobs: unit: runs-on: ubuntu-latest name: All - env: - RUNGOGENERATE: false steps: - uses: actions/checkout@v3 with: submodules: recursive + - id: config + uses: protocol/.github/.github/actions/read-config@master - uses: actions/setup-go@v3 with: - go-version: "1.19.x" + go-version: 1.20.x - name: Run repo-specific setup uses: ./.github/actions/go-check-setup if: hashFiles('./.github/actions/go-check-setup') != '' - - name: Read config - if: hashFiles('./.github/workflows/go-check-config.json') != '' - run: | - if jq -re .gogenerate ./.github/workflows/go-check-config.json; then - echo "RUNGOGENERATE=true" >> $GITHUB_ENV - fi - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@376210a89477dedbe6fdc4484b233998650d7b3c # 2022.1.3 (v0.3.3) + run: go install honnef.co/go/tools/cmd/staticcheck@4970552d932f48b71485287748246cf3237cebdf # 2023.1 (v0.4.0) - name: Check that go.mod is tidy uses: protocol/multiple-go-modules@v1.2 with: @@ -39,7 +33,7 @@ jobs: fi git diff --exit-code -- go.sum go.mod - name: gofmt - if: ${{ success() || failure() }} # run this step even if the previous one failed + if: success() || failure() # run this step even if the previous one failed run: | out=$(gofmt -s -l .) if [[ -n "$out" ]]; then @@ -47,12 +41,12 @@ jobs: exit 1 fi - name: go vet - if: ${{ success() || failure() }} # run this step even if the previous one failed + if: success() || failure() # run this step even if the previous one failed uses: protocol/multiple-go-modules@v1.2 with: run: go vet ./... - name: staticcheck - if: ${{ success() || failure() }} # run this step even if the previous one failed + if: success() || failure() # run this step even if the previous one failed uses: protocol/multiple-go-modules@v1.2 with: run: | @@ -60,11 +54,11 @@ jobs: staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' - name: go generate uses: protocol/multiple-go-modules@v1.2 - if: (success() || failure()) && env.RUNGOGENERATE == 'true' + if: (success() || failure()) && fromJSON(steps.config.outputs.json).gogenerate == true with: run: | git clean -fd # make sure there aren't untracked files / directories - go generate ./... + go generate -x ./... # check if go generate modified or added any files if ! $(git add . && git diff-index HEAD --exit-code --quiet); then echo "go generated caused changes to the repository:" diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 8a1697b2d0..c5cb3efc7a 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -10,15 +10,17 @@ jobs: fail-fast: false matrix: os: [ "ubuntu", "windows", "macos" ] - go: [ "1.18.x", "1.19.x" ] + go: ["1.19.x","1.20.x"] env: COVERAGES: "" - runs-on: ${{ format('{0}-latest', matrix.os) }} + runs-on: ${{ fromJSON(vars[format('UCI_GO_TEST_RUNNER_{0}', matrix.os)] || format('"{0}-latest"', matrix.os)) }} name: ${{ matrix.os }} (go ${{ matrix.go }}) steps: - uses: actions/checkout@v3 with: submodules: recursive + - id: config + uses: protocol/.github/.github/actions/read-config@master - uses: actions/setup-go@v3 with: go-version: ${{ matrix.go }} @@ -27,7 +29,7 @@ jobs: go version go env - name: Use msys2 on windows - if: ${{ matrix.os == 'windows' }} + if: matrix.os == 'windows' shell: bash # The executable for msys2 is also called bash.cmd # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells @@ -38,6 +40,7 @@ jobs: uses: ./.github/actions/go-test-setup if: hashFiles('./.github/actions/go-test-setup') != '' - name: Run tests + if: contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false uses: protocol/multiple-go-modules@v1.2 with: # Use -coverpkg=./..., so that we include cross-package coverage. @@ -45,16 +48,21 @@ jobs: # this means ./B's coverage will be significantly higher than 0%. run: go test -v -shuffle=on -coverprofile=module-coverage.txt -coverpkg=./... ./... - name: Run tests (32 bit) - if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. + # can't run 32 bit tests on OSX. + if: matrix.os != 'macos' && + fromJSON(steps.config.outputs.json).skip32bit != true && + contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false uses: protocol/multiple-go-modules@v1.2 env: GOARCH: 386 with: run: | - export "PATH=${{ env.PATH_386 }}:$PATH" + export "PATH=$PATH_386:$PATH" go test -v -shuffle=on ./... - name: Run tests with race detector - if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow + # speed things up. Windows and OSX VMs are slow + if: matrix.os == 'ubuntu' && + contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false uses: protocol/multiple-go-modules@v1.2 with: run: go test -v -race ./... @@ -62,7 +70,7 @@ jobs: shell: bash run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV - name: Upload coverage to Codecov - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 with: files: '${{ env.COVERAGES }}' env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} diff --git a/.github/workflows/release-check.yml b/.github/workflows/release-check.yml index fde81c1f88..e2408e37c4 100644 --- a/.github/workflows/release-check.yml +++ b/.github/workflows/release-check.yml @@ -3,9 +3,11 @@ name: Release Checker on: - pull_request: + pull_request_target: paths: [ 'version.json' ] jobs: release-check: uses: protocol/.github/.github/workflows/release-check.yml@master + with: + go-version: 1.20.x diff --git a/go.mod b/go.mod index 58a070bdb0..b814e3f3fa 100644 --- a/go.mod +++ b/go.mod @@ -15,4 +15,4 @@ require ( golang.org/x/text v0.3.0 // indirect ) -go 1.18 +go 1.19 diff --git a/nat.go b/nat.go index 6d295e66f5..6f2ae187cb 100644 --- a/nat.go +++ b/nat.go @@ -118,7 +118,8 @@ func DiscoverGateway(ctx context.Context) (NAT, error) { return bestNAT, nil } +var random = rand.New(rand.NewSource(time.Now().UnixNano())) + func randomPort() int { - rand.Seed(time.Now().UnixNano()) - return rand.Intn(math.MaxUint16-10000) + 10000 + return random.Intn(math.MaxUint16-10000) + 10000 } diff --git a/natpmp.go b/natpmp.go index 495d42b49e..a573f09ec8 100644 --- a/natpmp.go +++ b/natpmp.go @@ -5,7 +5,7 @@ import ( "net" "time" - "github.com/jackpal/go-nat-pmp" + natpmp "github.com/jackpal/go-nat-pmp" ) var ( From 25823d784182059ed256340aec46a2c34d07d8c6 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 1 Jun 2023 12:14:35 +0300 Subject: [PATCH 39/54] update deps, use contexts on UPnP functions (#29) * update deps, use contexts on UPnP functions * add contexts to NAT.AddPortMapping and NAT.DeletePortMapping --- go.mod | 15 +++++++-------- go.sum | 39 ++++++++++++++++++++++----------------- nat.go | 4 ++-- natpmp.go | 4 ++-- upnp.go | 38 ++++++++++++++++++-------------------- 5 files changed, 51 insertions(+), 49 deletions(-) diff --git a/go.mod b/go.mod index b814e3f3fa..9abe6b0017 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,17 @@ module github.com/libp2p/go-nat require ( - github.com/huin/goupnp v1.0.0 + github.com/huin/goupnp v1.1.0 github.com/jackpal/go-nat-pmp v1.0.2 - github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d - github.com/libp2p/go-netroute v0.1.2 + github.com/koron/go-ssdp v0.0.4 + github.com/libp2p/go-netroute v0.2.1 ) require ( - github.com/google/gopacket v1.1.17 // indirect - github.com/libp2p/go-sockaddr v0.0.2 // indirect - golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect - golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 // indirect - golang.org/x/text v0.3.0 // indirect + github.com/google/gopacket v1.1.19 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.5.0 // indirect ) go 1.19 diff --git a/go.sum b/go.sum index be2d04ac02..7e568f4998 100644 --- a/go.sum +++ b/go.sum @@ -1,23 +1,28 @@ -github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= -github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= +github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= -github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR4Xg= -github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-sockaddr v0.0.2 h1:tCuXfpA9rq7llM/v834RKc/Xvovy/AqM9kHvTV/jY/Q= -github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= +github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= +github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= +github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/nat.go b/nat.go index 6f2ae187cb..6b3e19c444 100644 --- a/nat.go +++ b/nat.go @@ -29,10 +29,10 @@ type NAT interface { GetInternalAddress() (addr net.IP, err error) // 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) + AddPortMapping(ctx context.Context, protocol string, internalPort int, description string, timeout time.Duration) (mappedExternalPort int, err error) // DeletePortMapping removes a port mapping. - DeletePortMapping(protocol string, internalPort int) (err error) + DeletePortMapping(ctx context.Context, protocol string, internalPort int) (err error) } // DiscoverNATs returns all NATs discovered in the network. diff --git a/natpmp.go b/natpmp.go index a573f09ec8..2378d8d7ec 100644 --- a/natpmp.go +++ b/natpmp.go @@ -95,7 +95,7 @@ func (n *natpmpNAT) GetExternalAddress() (addr net.IP, err error) { return net.IPv4(d[0], d[1], d[2], d[3]), nil } -func (n *natpmpNAT) AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (int, error) { +func (n *natpmpNAT) AddPortMapping(_ context.Context, protocol string, internalPort int, _ string, timeout time.Duration) (int, error) { var ( err error ) @@ -122,7 +122,7 @@ func (n *natpmpNAT) AddPortMapping(protocol string, internalPort int, descriptio return 0, err } -func (n *natpmpNAT) DeletePortMapping(protocol string, internalPort int) (err error) { +func (n *natpmpNAT) DeletePortMapping(_ context.Context, _ string, internalPort int) (err error) { delete(n.ports, internalPort) return nil } diff --git a/upnp.go b/upnp.go index ccfeb14a2f..c50b952bbe 100644 --- a/upnp.go +++ b/upnp.go @@ -14,9 +14,7 @@ import ( "github.com/koron/go-ssdp" ) -var ( - _ NAT = (*upnp_NAT)(nil) -) +var _ NAT = (*upnp_NAT)(nil) func discoverUPNP_IG1(ctx context.Context) <-chan NAT { res := make(chan NAT) @@ -24,7 +22,7 @@ func discoverUPNP_IG1(ctx context.Context) <-chan NAT { defer close(res) // find devices - devs, err := goupnp.DiscoverDevices(internetgateway1.URN_WANConnectionDevice_1) + devs, err := goupnp.DiscoverDevicesCtx(ctx, internetgateway1.URN_WANConnectionDevice_1) if err != nil { return } @@ -45,7 +43,7 @@ func discoverUPNP_IG1(ctx context.Context) <-chan NAT { RootDevice: dev.Root, Service: srv, }} - _, isNat, err := client.GetNATRSIPStatus() + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) if err == nil && isNat { select { case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", dev.Root}: @@ -59,7 +57,7 @@ func discoverUPNP_IG1(ctx context.Context) <-chan NAT { RootDevice: dev.Root, Service: srv, }} - _, isNat, err := client.GetNATRSIPStatus() + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) if err == nil && isNat { select { case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", dev.Root}: @@ -81,7 +79,7 @@ func discoverUPNP_IG2(ctx context.Context) <-chan NAT { defer close(res) // find devices - devs, err := goupnp.DiscoverDevices(internetgateway2.URN_WANConnectionDevice_2) + devs, err := goupnp.DiscoverDevicesCtx(ctx, internetgateway2.URN_WANConnectionDevice_2) if err != nil { return } @@ -102,7 +100,7 @@ func discoverUPNP_IG2(ctx context.Context) <-chan NAT { RootDevice: dev.Root, Service: srv, }} - _, isNat, err := client.GetNATRSIPStatus() + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) if err == nil && isNat { select { case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP1)", dev.Root}: @@ -116,7 +114,7 @@ func discoverUPNP_IG2(ctx context.Context) <-chan NAT { RootDevice: dev.Root, Service: srv, }} - _, isNat, err := client.GetNATRSIPStatus() + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) if err == nil && isNat { select { case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP2)", dev.Root}: @@ -130,7 +128,7 @@ func discoverUPNP_IG2(ctx context.Context) <-chan NAT { RootDevice: dev.Root, Service: srv, }} - _, isNat, err := client.GetNATRSIPStatus() + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) if err == nil && isNat { select { case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-PPP1)", dev.Root}: @@ -167,7 +165,7 @@ func discoverUPNP_GenIGDev(ctx context.Context) <-chan NAT { if err != nil { return } - RootDevice, err := goupnp.DeviceByURL(DeviceURL) + RootDevice, err := goupnp.DeviceByURLCtx(ctx, DeviceURL) if err != nil { return } @@ -183,7 +181,7 @@ func discoverUPNP_GenIGDev(ctx context.Context) <-chan NAT { RootDevice: RootDevice, Service: srv, }} - _, isNat, err := client.GetNATRSIPStatus() + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) if err == nil && isNat { select { case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", RootDevice}: @@ -197,7 +195,7 @@ func discoverUPNP_GenIGDev(ctx context.Context) <-chan NAT { RootDevice: RootDevice, Service: srv, }} - _, isNat, err := client.GetNATRSIPStatus() + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) if err == nil && isNat { select { case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", RootDevice}: @@ -213,8 +211,8 @@ func discoverUPNP_GenIGDev(ctx context.Context) <-chan NAT { type upnp_NAT_Client interface { GetExternalIPAddress() (string, error) - AddPortMapping(string, uint16, string, uint16, string, bool, string, uint32) error - DeletePortMapping(string, uint16, string) error + AddPortMappingCtx(context.Context, string, uint16, string, uint16, string, bool, string, uint32) error + DeletePortMappingCtx(context.Context, string, uint16, string) error } type upnp_NAT struct { @@ -249,7 +247,7 @@ func mapProtocol(s string) string { } } -func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description string, timeout time.Duration) (int, error) { +func (u *upnp_NAT) AddPortMapping(ctx context.Context, protocol string, internalPort int, description string, timeout time.Duration) (int, error) { ip, err := u.GetInternalAddress() if err != nil { return 0, nil @@ -258,7 +256,7 @@ func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description timeoutInSeconds := uint32(timeout / time.Second) if externalPort := u.ports[internalPort]; externalPort > 0 { - err = u.c.AddPortMapping("", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) + err = u.c.AddPortMappingCtx(ctx, "", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) if err == nil { return externalPort, nil } @@ -266,7 +264,7 @@ func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description for i := 0; i < 3; i++ { externalPort := randomPort() - err = u.c.AddPortMapping("", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) + err = u.c.AddPortMappingCtx(ctx, "", uint16(externalPort), mapProtocol(protocol), uint16(internalPort), ip.String(), true, description, timeoutInSeconds) if err == nil { u.ports[internalPort] = externalPort return externalPort, nil @@ -276,10 +274,10 @@ func (u *upnp_NAT) AddPortMapping(protocol string, internalPort int, description return 0, err } -func (u *upnp_NAT) DeletePortMapping(protocol string, internalPort int) error { +func (u *upnp_NAT) DeletePortMapping(ctx context.Context, protocol string, internalPort int) error { if externalPort := u.ports[internalPort]; externalPort > 0 { delete(u.ports, internalPort) - return u.c.DeletePortMapping("", uint16(externalPort), mapProtocol(protocol)) + return u.c.DeletePortMappingCtx(ctx, "", uint16(externalPort), mapProtocol(protocol)) } return nil From 2366bb0b0085a84ede39c3015286d9895a24106a Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 1 Jun 2023 15:59:46 +0300 Subject: [PATCH 40/54] chore: update deps (#31) --- go.mod | 8 ++++---- go.sum | 15 ++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 9abe6b0017..b6ad822f81 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/libp2p/go-nat require ( - github.com/huin/goupnp v1.1.0 + github.com/huin/goupnp v1.2.0 github.com/jackpal/go-nat-pmp v1.0.2 github.com/koron/go-ssdp v0.0.4 github.com/libp2p/go-netroute v0.2.1 @@ -9,9 +9,9 @@ require ( require ( github.com/google/gopacket v1.1.19 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.5.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sync v0.2.0 // indirect + golang.org/x/sys v0.8.0 // indirect ) go 1.19 diff --git a/go.sum b/go.sum index 7e568f4998..b20c1c6226 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= -github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= +github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= @@ -14,15 +14,16 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 14ce74b6949ca4d3f4889568e20840bdf0b05009 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Thu, 1 Jun 2023 16:09:11 +0300 Subject: [PATCH 41/54] release v0.2.0 (#30) --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 557859c534..1437d5b735 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "v0.1.0" + "version": "v0.2.0" } From 29fad80565ee0398475348242019bf489601fb78 Mon Sep 17 00:00:00 2001 From: GitHub Date: Wed, 14 Jun 2023 09:07:42 +0000 Subject: [PATCH 42/54] chore: Update .github/workflows/stale.yml [skip ci] --- .github/workflows/stale.yml | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 6f6d895d19..668bd07d49 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -6,21 +6,4 @@ on: jobs: stale: - - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - - steps: - - uses: actions/stale@v3 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: 'Oops, seems like we needed more information for this issue, please comment with more details or this issue will be closed in 7 days.' - close-issue-message: 'This issue was closed because it is missing author input.' - stale-issue-label: 'kind/stale' - any-of-labels: 'need/author-input' - exempt-issue-labels: 'need/triage,need/community-input,need/maintainer-input,need/maintainers-input,need/analysis,status/blocked,status/in-progress,status/ready,status/deferred,status/inactive' - days-before-issue-stale: 6 - days-before-issue-close: 7 - enable-statistics: true + uses: pl-strflt/.github/.github/workflows/reusable-stale-issue.yml@v0.3 From 5cc65f94aef93f7ded9b79ebd878620482346b07 Mon Sep 17 00:00:00 2001 From: GitHub Date: Wed, 28 Jun 2023 08:54:32 +0000 Subject: [PATCH 43/54] chore: Update .github/workflows/stale.yml [skip ci] --- .github/workflows/stale.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 668bd07d49..16d65d7217 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,11 @@ name: Close and mark stale issue on: schedule: - - cron: '0 0 * * *' + - cron: '0 0 * * *' + +permissions: + issues: write + pull-requests: write jobs: stale: From da1dc6d581c0bf0778cc01c451d89858e50b6dd5 Mon Sep 17 00:00:00 2001 From: web3-bot Date: Sun, 13 Aug 2023 20:53:39 +0200 Subject: [PATCH 44/54] chore: delete templates [skip ci] (#32) --- .github/workflows/automerge.yml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 .github/workflows/automerge.yml diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml deleted file mode 100644 index 3833fc2291..0000000000 --- a/.github/workflows/automerge.yml +++ /dev/null @@ -1,11 +0,0 @@ -# File managed by web3-bot. DO NOT EDIT. -# See https://github.com/protocol/.github/ for details. - -name: Automerge -on: [ pull_request ] - -jobs: - automerge: - uses: protocol/.github/.github/workflows/automerge.yml@master - with: - job: 'automerge' From 90336fa854d3e187745eb0c58e954f300b134302 Mon Sep 17 00:00:00 2001 From: web3-bot Date: Mon, 14 Aug 2023 08:20:38 +0200 Subject: [PATCH 45/54] ci: uci/copy-templates (#33) * chore: add or force update .github/workflows/go-test.yml * chore: add or force update .github/workflows/go-check.yml * chore: add or force update .github/workflows/releaser.yml * chore: add or force update .github/workflows/release-check.yml * chore: add or force update .github/workflows/tagpush.yml --- .github/workflows/go-check.yml | 79 +++++--------------------- .github/workflows/go-test.yml | 88 +++++------------------------ .github/workflows/release-check.yml | 18 ++++-- .github/workflows/releaser.yml | 14 +++-- .github/workflows/tagpush.yml | 14 +++-- 5 files changed, 62 insertions(+), 151 deletions(-) diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index cc65ce68a9..9ce6260de9 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -1,67 +1,18 @@ -# File managed by web3-bot. DO NOT EDIT. -# See https://github.com/protocol/.github/ for details. - -on: [push, pull_request] name: Go Checks +on: + pull_request: + push: + branches: ["master"] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }} + cancel-in-progress: true + jobs: - unit: - runs-on: ubuntu-latest - name: All - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - id: config - uses: protocol/.github/.github/actions/read-config@master - - uses: actions/setup-go@v3 - with: - go-version: 1.20.x - - name: Run repo-specific setup - uses: ./.github/actions/go-check-setup - if: hashFiles('./.github/actions/go-check-setup') != '' - - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@4970552d932f48b71485287748246cf3237cebdf # 2023.1 (v0.4.0) - - name: Check that go.mod is tidy - uses: protocol/multiple-go-modules@v1.2 - with: - run: | - go mod tidy - if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then - echo "go.sum was added by go mod tidy" - exit 1 - fi - git diff --exit-code -- go.sum go.mod - - name: gofmt - if: success() || failure() # run this step even if the previous one failed - run: | - out=$(gofmt -s -l .) - if [[ -n "$out" ]]; then - echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}' - exit 1 - fi - - name: go vet - if: success() || failure() # run this step even if the previous one failed - uses: protocol/multiple-go-modules@v1.2 - with: - run: go vet ./... - - name: staticcheck - if: success() || failure() # run this step even if the previous one failed - uses: protocol/multiple-go-modules@v1.2 - with: - run: | - set -o pipefail - staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' - - name: go generate - uses: protocol/multiple-go-modules@v1.2 - if: (success() || failure()) && fromJSON(steps.config.outputs.json).gogenerate == true - with: - run: | - git clean -fd # make sure there aren't untracked files / directories - go generate -x ./... - # check if go generate modified or added any files - if ! $(git add . && git diff-index HEAD --exit-code --quiet); then - echo "go generated caused changes to the repository:" - git status --short - exit 1 - fi + go-check: + uses: pl-strflt/uci/.github/workflows/go-check.yml@v0.0 diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index c5cb3efc7a..d4ca588cd4 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -1,76 +1,18 @@ -# File managed by web3-bot. DO NOT EDIT. -# See https://github.com/protocol/.github/ for details. - -on: [push, pull_request] name: Go Test +on: + pull_request: + push: + branches: ["master"] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }} + cancel-in-progress: true + jobs: - unit: - strategy: - fail-fast: false - matrix: - os: [ "ubuntu", "windows", "macos" ] - go: ["1.19.x","1.20.x"] - env: - COVERAGES: "" - runs-on: ${{ fromJSON(vars[format('UCI_GO_TEST_RUNNER_{0}', matrix.os)] || format('"{0}-latest"', matrix.os)) }} - name: ${{ matrix.os }} (go ${{ matrix.go }}) - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - id: config - uses: protocol/.github/.github/actions/read-config@master - - uses: actions/setup-go@v3 - with: - go-version: ${{ matrix.go }} - - name: Go information - run: | - go version - go env - - name: Use msys2 on windows - if: matrix.os == 'windows' - shell: bash - # The executable for msys2 is also called bash.cmd - # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells - # If we prepend its location to the PATH - # subsequent 'shell: bash' steps will use msys2 instead of gitbash - run: echo "C:/msys64/usr/bin" >> $GITHUB_PATH - - name: Run repo-specific setup - uses: ./.github/actions/go-test-setup - if: hashFiles('./.github/actions/go-test-setup') != '' - - name: Run tests - if: contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false - uses: protocol/multiple-go-modules@v1.2 - with: - # Use -coverpkg=./..., so that we include cross-package coverage. - # If package ./A imports ./B, and ./A's tests also cover ./B, - # this means ./B's coverage will be significantly higher than 0%. - run: go test -v -shuffle=on -coverprofile=module-coverage.txt -coverpkg=./... ./... - - name: Run tests (32 bit) - # can't run 32 bit tests on OSX. - if: matrix.os != 'macos' && - fromJSON(steps.config.outputs.json).skip32bit != true && - contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false - uses: protocol/multiple-go-modules@v1.2 - env: - GOARCH: 386 - with: - run: | - export "PATH=$PATH_386:$PATH" - go test -v -shuffle=on ./... - - name: Run tests with race detector - # speed things up. Windows and OSX VMs are slow - if: matrix.os == 'ubuntu' && - contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false - uses: protocol/multiple-go-modules@v1.2 - with: - run: go test -v -race ./... - - name: Collect coverage files - shell: bash - run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV - - name: Upload coverage to Codecov - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 - with: - files: '${{ env.COVERAGES }}' - env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} + go-test: + uses: pl-strflt/uci/.github/workflows/go-test.yml@v0.0 diff --git a/.github/workflows/release-check.yml b/.github/workflows/release-check.yml index e2408e37c4..bda616005b 100644 --- a/.github/workflows/release-check.yml +++ b/.github/workflows/release-check.yml @@ -1,13 +1,19 @@ -# File managed by web3-bot. DO NOT EDIT. -# See https://github.com/protocol/.github/ for details. - name: Release Checker + on: pull_request_target: paths: [ 'version.json' ] + types: [ opened, synchronize, reopened, labeled, unlabeled ] + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: release-check: - uses: protocol/.github/.github/workflows/release-check.yml@master - with: - go-version: 1.20.x + uses: pl-strflt/uci/.github/workflows/release-check.yml@v0.0 diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index cdccbf873d..dd8081b919 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -1,11 +1,17 @@ -# File managed by web3-bot. DO NOT EDIT. -# See https://github.com/protocol/.github/ for details. - name: Releaser + on: push: paths: [ 'version.json' ] + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: ${{ github.workflow }}-${{ github.sha }} + cancel-in-progress: true jobs: releaser: - uses: protocol/.github/.github/workflows/releaser.yml@master + uses: pl-strflt/uci/.github/workflows/releaser.yml@v0.0 diff --git a/.github/workflows/tagpush.yml b/.github/workflows/tagpush.yml index d84996187a..59de8cb917 100644 --- a/.github/workflows/tagpush.yml +++ b/.github/workflows/tagpush.yml @@ -1,12 +1,18 @@ -# File managed by web3-bot. DO NOT EDIT. -# See https://github.com/protocol/.github/ for details. - name: Tag Push Checker + on: push: tags: - v* +permissions: + contents: read + issues: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: releaser: - uses: protocol/.github/.github/workflows/tagpush.yml@master + uses: pl-strflt/uci/.github/workflows/tagpush.yml@v0.0 From 002425958110f89f4ae4f49fca50de2cac0ee0e1 Mon Sep 17 00:00:00 2001 From: web3-bot Date: Mon, 14 Aug 2023 15:36:26 +0200 Subject: [PATCH 46/54] chore: bump go.mod to Go 1.20 and run go fix (#34) --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index b6ad822f81..f00189c711 100644 --- a/go.mod +++ b/go.mod @@ -14,4 +14,4 @@ require ( golang.org/x/sys v0.8.0 // indirect ) -go 1.19 +go 1.20 From 07ada58a73ca51b1ca7560c9d31d4d2a1938986d Mon Sep 17 00:00:00 2001 From: GitHub Date: Wed, 31 Jan 2024 16:49:14 +0000 Subject: [PATCH 47/54] chore: Update .github/workflows/stale.yml [skip ci] From 7083c1cde25266ef70ad52d147aaa70373f935ca Mon Sep 17 00:00:00 2001 From: web3-bot Date: Thu, 14 Mar 2024 12:26:06 +0100 Subject: [PATCH 48/54] ci: uci/update-go (#36) * chore: bump go.mod to Go 1.21 and run go fix * chore: run go mod tidy --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f00189c711..972d997ab3 100644 --- a/go.mod +++ b/go.mod @@ -14,4 +14,4 @@ require ( golang.org/x/sys v0.8.0 // indirect ) -go 1.20 +go 1.21 From 01a3d9956ae145b41d9a72bb1e3a2bdad57a7606 Mon Sep 17 00:00:00 2001 From: web3-bot Date: Fri, 22 Mar 2024 07:17:23 +0000 Subject: [PATCH 49/54] ci: uci/copy-templates (#37) * chore: add or force update .github/workflows/go-test.yml * chore: add or force update .github/workflows/go-check.yml * chore: add or force update .github/workflows/releaser.yml * chore: add or force update .github/workflows/release-check.yml * chore: add or force update .github/workflows/tagpush.yml * chore: add or force update .github/workflows/go-test.yml * chore: add or force update .github/workflows/go-check.yml * chore: add or force update .github/workflows/releaser.yml * chore: add or force update .github/workflows/release-check.yml * chore: add or force update .github/workflows/tagpush.yml * chore: add or force update .github/workflows/go-test.yml * chore: add or force update .github/workflows/go-check.yml * chore: add or force update .github/workflows/releaser.yml * chore: add or force update .github/workflows/release-check.yml * chore: add or force update .github/workflows/tagpush.yml --- .github/workflows/go-check.yml | 2 +- .github/workflows/go-test.yml | 4 +++- .github/workflows/release-check.yml | 2 +- .github/workflows/releaser.yml | 2 +- .github/workflows/tagpush.yml | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml index 9ce6260de9..26f63bc126 100644 --- a/.github/workflows/go-check.yml +++ b/.github/workflows/go-check.yml @@ -15,4 +15,4 @@ concurrency: jobs: go-check: - uses: pl-strflt/uci/.github/workflows/go-check.yml@v0.0 + uses: ipdxco/unified-github-workflows/.github/workflows/go-check.yml@v1.0 diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index d4ca588cd4..778de6ed48 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -15,4 +15,6 @@ concurrency: jobs: go-test: - uses: pl-strflt/uci/.github/workflows/go-test.yml@v0.0 + uses: ipdxco/unified-github-workflows/.github/workflows/go-test.yml@v1.0 + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/release-check.yml b/.github/workflows/release-check.yml index bda616005b..0b5ff6070f 100644 --- a/.github/workflows/release-check.yml +++ b/.github/workflows/release-check.yml @@ -16,4 +16,4 @@ concurrency: jobs: release-check: - uses: pl-strflt/uci/.github/workflows/release-check.yml@v0.0 + uses: ipdxco/unified-github-workflows/.github/workflows/release-check.yml@v1.0 diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index dd8081b919..2ebdbed31a 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -14,4 +14,4 @@ concurrency: jobs: releaser: - uses: pl-strflt/uci/.github/workflows/releaser.yml@v0.0 + uses: ipdxco/unified-github-workflows/.github/workflows/releaser.yml@v1.0 diff --git a/.github/workflows/tagpush.yml b/.github/workflows/tagpush.yml index 59de8cb917..5ef3fb9ede 100644 --- a/.github/workflows/tagpush.yml +++ b/.github/workflows/tagpush.yml @@ -15,4 +15,4 @@ concurrency: jobs: releaser: - uses: pl-strflt/uci/.github/workflows/tagpush.yml@v0.0 + uses: ipdxco/unified-github-workflows/.github/workflows/tagpush.yml@v1.0 From 2fac9092f3fc908fb38bc52fa99234c9fc5f175c Mon Sep 17 00:00:00 2001 From: web3-bot Date: Mon, 26 Aug 2024 11:26:47 +0100 Subject: [PATCH 50/54] chore: bump go.mod to Go 1.22 and run go fix (#38) --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 972d997ab3..837511836b 100644 --- a/go.mod +++ b/go.mod @@ -14,4 +14,4 @@ require ( golang.org/x/sys v0.8.0 // indirect ) -go 1.21 +go 1.22 From f8bd11c239c3f2a874d0e5b82244a92db03d2ab8 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Thu, 23 Jan 2025 19:01:50 -0800 Subject: [PATCH 51/54] Make changes to internal nat library --- go.mod | 7 +- go.sum | 2 - .../nat/.github/workflows/go-check.yml | 18 -- .../nat/.github/workflows/go-test.yml | 20 -- .../nat/.github/workflows/release-check.yml | 19 -- .../nat/.github/workflows/releaser.yml | 17 -- .../internal/nat/.github/workflows/stale.yml | 13 - .../nat/.github/workflows/tagpush.yml | 18 -- p2p/net/nat/internal/nat/README.md | 10 +- .../nat/internal/nat/_examples/nat-tester.go | 67 ----- p2p/net/nat/internal/nat/gateway.go | 17 -- p2p/net/nat/internal/nat/go.mod | 17 -- p2p/net/nat/internal/nat/go.sum | 29 -- p2p/net/nat/internal/nat/nat.go | 156 +++++++---- p2p/net/nat/internal/nat/natpmp.go | 58 ++-- p2p/net/nat/internal/nat/upnp.go | 258 ++++++------------ p2p/net/nat/internal/nat/version.json | 3 - p2p/net/nat/mock_nat_test.go | 4 +- p2p/net/nat/nat.go | 2 +- p2p/net/nat/nat_test.go | 5 +- test-plans/go.mod | 1 - test-plans/go.sum | 2 - 22 files changed, 236 insertions(+), 507 deletions(-) delete mode 100644 p2p/net/nat/internal/nat/.github/workflows/go-check.yml delete mode 100644 p2p/net/nat/internal/nat/.github/workflows/go-test.yml delete mode 100644 p2p/net/nat/internal/nat/.github/workflows/release-check.yml delete mode 100644 p2p/net/nat/internal/nat/.github/workflows/releaser.yml delete mode 100644 p2p/net/nat/internal/nat/.github/workflows/stale.yml delete mode 100644 p2p/net/nat/internal/nat/.github/workflows/tagpush.yml delete mode 100644 p2p/net/nat/internal/nat/_examples/nat-tester.go delete mode 100644 p2p/net/nat/internal/nat/gateway.go delete mode 100644 p2p/net/nat/internal/nat/go.mod delete mode 100644 p2p/net/nat/internal/nat/go.sum delete mode 100644 p2p/net/nat/internal/nat/version.json diff --git a/go.mod b/go.mod index 28abae8ffc..228959510b 100644 --- a/go.mod +++ b/go.mod @@ -15,19 +15,21 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/hashicorp/golang-lru/arc/v2 v2.0.7 github.com/hashicorp/golang-lru/v2 v2.0.7 + github.com/huin/goupnp v1.3.0 github.com/ipfs/go-cid v0.4.1 github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-ds-badger v0.3.0 github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-log/v2 v2.5.1 + github.com/jackpal/go-nat-pmp v1.0.2 github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/klauspost/compress v1.17.11 + github.com/koron/go-ssdp v0.0.4 github.com/libp2p/go-buffer-pool v0.1.0 github.com/libp2p/go-flow-metrics v0.2.0 github.com/libp2p/go-libp2p-asn-util v0.4.1 github.com/libp2p/go-libp2p-testing v0.12.0 github.com/libp2p/go-msgio v0.3.0 - github.com/libp2p/go-nat v0.2.0 github.com/libp2p/go-netroute v0.2.2 github.com/libp2p/go-reuseport v0.4.0 github.com/libp2p/go-yamux/v4 v4.0.1 @@ -90,11 +92,8 @@ require ( github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/google/uuid v1.6.0 // indirect - github.com/huin/goupnp v1.3.0 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/goprocess v0.1.4 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect - github.com/koron/go-ssdp v0.0.4 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/miekg/dns v1.1.62 // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect diff --git a/go.sum b/go.sum index 2d8fb16cf3..ca26d76a08 100644 --- a/go.sum +++ b/go.sum @@ -188,8 +188,6 @@ github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUI github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= -github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk= github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8= github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE= github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= diff --git a/p2p/net/nat/internal/nat/.github/workflows/go-check.yml b/p2p/net/nat/internal/nat/.github/workflows/go-check.yml deleted file mode 100644 index 26f63bc126..0000000000 --- a/p2p/net/nat/internal/nat/.github/workflows/go-check.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Go Checks - -on: - pull_request: - push: - branches: ["master"] - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }} - cancel-in-progress: true - -jobs: - go-check: - uses: ipdxco/unified-github-workflows/.github/workflows/go-check.yml@v1.0 diff --git a/p2p/net/nat/internal/nat/.github/workflows/go-test.yml b/p2p/net/nat/internal/nat/.github/workflows/go-test.yml deleted file mode 100644 index 778de6ed48..0000000000 --- a/p2p/net/nat/internal/nat/.github/workflows/go-test.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Go Test - -on: - pull_request: - push: - branches: ["master"] - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }} - cancel-in-progress: true - -jobs: - go-test: - uses: ipdxco/unified-github-workflows/.github/workflows/go-test.yml@v1.0 - secrets: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/p2p/net/nat/internal/nat/.github/workflows/release-check.yml b/p2p/net/nat/internal/nat/.github/workflows/release-check.yml deleted file mode 100644 index 0b5ff6070f..0000000000 --- a/p2p/net/nat/internal/nat/.github/workflows/release-check.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Release Checker - -on: - pull_request_target: - paths: [ 'version.json' ] - types: [ opened, synchronize, reopened, labeled, unlabeled ] - workflow_dispatch: - -permissions: - contents: write - pull-requests: write - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - release-check: - uses: ipdxco/unified-github-workflows/.github/workflows/release-check.yml@v1.0 diff --git a/p2p/net/nat/internal/nat/.github/workflows/releaser.yml b/p2p/net/nat/internal/nat/.github/workflows/releaser.yml deleted file mode 100644 index 2ebdbed31a..0000000000 --- a/p2p/net/nat/internal/nat/.github/workflows/releaser.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Releaser - -on: - push: - paths: [ 'version.json' ] - workflow_dispatch: - -permissions: - contents: write - -concurrency: - group: ${{ github.workflow }}-${{ github.sha }} - cancel-in-progress: true - -jobs: - releaser: - uses: ipdxco/unified-github-workflows/.github/workflows/releaser.yml@v1.0 diff --git a/p2p/net/nat/internal/nat/.github/workflows/stale.yml b/p2p/net/nat/internal/nat/.github/workflows/stale.yml deleted file mode 100644 index 16d65d7217..0000000000 --- a/p2p/net/nat/internal/nat/.github/workflows/stale.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Close and mark stale issue - -on: - schedule: - - cron: '0 0 * * *' - -permissions: - issues: write - pull-requests: write - -jobs: - stale: - uses: pl-strflt/.github/.github/workflows/reusable-stale-issue.yml@v0.3 diff --git a/p2p/net/nat/internal/nat/.github/workflows/tagpush.yml b/p2p/net/nat/internal/nat/.github/workflows/tagpush.yml deleted file mode 100644 index 5ef3fb9ede..0000000000 --- a/p2p/net/nat/internal/nat/.github/workflows/tagpush.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Tag Push Checker - -on: - push: - tags: - - v* - -permissions: - contents: read - issues: write - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - releaser: - uses: ipdxco/unified-github-workflows/.github/workflows/tagpush.yml@v1.0 diff --git a/p2p/net/nat/internal/nat/README.md b/p2p/net/nat/internal/nat/README.md index 61b5cc8891..a856a83072 100644 --- a/p2p/net/nat/internal/nat/README.md +++ b/p2p/net/nat/internal/nat/README.md @@ -1,9 +1 @@ -# go-nat - -[![GoDoc](https://godoc.org/github.com/libp2p/go-nat?status.svg)](https://godoc.org/github.com/libp2p/go-nat) [![status](https://sourcegraph.com/api/repos/github.com/libp2p/go-nat/.badges/status.png)](https://sourcegraph.com/github.com/libp2p/go-nat) - -Forked from: [fd/go-nat](https://github.com/fd/go-nat). - ---- - -The last gx published version of this module was: 1.0.3: QmdwkZHamNNrj7k3G29rnurmW3mFzsDhnyXppNcgYsiBVz +Originally forked from: [fd/go-nat](https://github.com/fd/go-nat). diff --git a/p2p/net/nat/internal/nat/_examples/nat-tester.go b/p2p/net/nat/internal/nat/_examples/nat-tester.go deleted file mode 100644 index e3b616b2a5..0000000000 --- a/p2p/net/nat/internal/nat/_examples/nat-tester.go +++ /dev/null @@ -1,67 +0,0 @@ -package main - -import ( - "fmt" - "log" - "net/http" - "time" - - "github.com/libp2p/go-nat" -) - -func main() { - nat, err := nat.DiscoverGateway() - if err != nil { - log.Fatalf("error: %s", err) - } - log.Printf("nat type: %s", nat.Type()) - - daddr, err := nat.GetDeviceAddress() - if err != nil { - log.Fatalf("error: %s", err) - } - log.Printf("device address: %s", daddr) - - iaddr, err := nat.GetInternalAddress() - if err != nil { - log.Fatalf("error: %s", err) - } - log.Printf("internal address: %s", iaddr) - - eaddr, err := nat.GetExternalAddress() - if err != nil { - log.Fatalf("error: %s", err) - } - log.Printf("external address: %s", eaddr) - - eport, err := nat.AddPortMapping("tcp", 3080, "http", 60) - if err != nil { - log.Fatalf("error: %s", err) - } - - log.Printf("test-page: http://%s:%d/", eaddr, eport) - - go func() { - for { - time.Sleep(30 * time.Second) - - _, err = nat.AddPortMapping("tcp", 3080, "http", 60) - if err != nil { - log.Fatalf("error: %s", err) - } - } - }() - - defer nat.DeletePortMapping("tcp", 3080) - - http.ListenAndServe(":3080", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - rw.Header().Set("Content-Type", "text/plain") - rw.WriteHeader(200) - fmt.Fprintf(rw, "Hello there!\n") - fmt.Fprintf(rw, "nat type: %s\n", nat.Type()) - fmt.Fprintf(rw, "device address: %s\n", daddr) - fmt.Fprintf(rw, "internal address: %s\n", iaddr) - fmt.Fprintf(rw, "external address: %s\n", eaddr) - fmt.Fprintf(rw, "test-page: http://%s:%d/\n", eaddr, eport) - })) -} diff --git a/p2p/net/nat/internal/nat/gateway.go b/p2p/net/nat/internal/nat/gateway.go deleted file mode 100644 index a87e46a892..0000000000 --- a/p2p/net/nat/internal/nat/gateway.go +++ /dev/null @@ -1,17 +0,0 @@ -package nat - -import ( - "net" - - "github.com/libp2p/go-netroute" -) - -func getDefaultGateway() (net.IP, error) { - router, err := netroute.New() - if err != nil { - return nil, err - } - - _, ip, _, err := router.Route(net.IPv4zero) - return ip, err -} diff --git a/p2p/net/nat/internal/nat/go.mod b/p2p/net/nat/internal/nat/go.mod deleted file mode 100644 index 837511836b..0000000000 --- a/p2p/net/nat/internal/nat/go.mod +++ /dev/null @@ -1,17 +0,0 @@ -module github.com/libp2p/go-nat - -require ( - github.com/huin/goupnp v1.2.0 - github.com/jackpal/go-nat-pmp v1.0.2 - github.com/koron/go-ssdp v0.0.4 - github.com/libp2p/go-netroute v0.2.1 -) - -require ( - github.com/google/gopacket v1.1.19 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sync v0.2.0 // indirect - golang.org/x/sys v0.8.0 // indirect -) - -go 1.22 diff --git a/p2p/net/nat/internal/nat/go.sum b/p2p/net/nat/internal/nat/go.sum deleted file mode 100644 index b20c1c6226..0000000000 --- a/p2p/net/nat/internal/nat/go.sum +++ /dev/null @@ -1,29 +0,0 @@ -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= -github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= -github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= -github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/p2p/net/nat/internal/nat/nat.go b/p2p/net/nat/internal/nat/nat.go index 6b3e19c444..c32ff7c461 100644 --- a/p2p/net/nat/internal/nat/nat.go +++ b/p2p/net/nat/internal/nat/nat.go @@ -4,15 +4,33 @@ package nat import ( "context" "errors" + "fmt" "math" "math/rand" "net" + "strings" "time" + + logging "github.com/ipfs/go-log/v2" + "github.com/libp2p/go-netroute" ) +var log = logging.Logger("internal/nat") + var ErrNoExternalAddress = errors.New("no external address") var ErrNoInternalAddress = errors.New("no internal address") -var ErrNoNATFound = errors.New("no NAT found") + +type ErrNoNATFound struct { + Errs []error +} + +func (e ErrNoNATFound) Error() string { + var errStrs []string + for _, err := range e.Errs { + errStrs = append(errStrs, err.Error()) + } + return fmt.Sprintf("no NAT found: [%s]", strings.Join(errStrs, "; ")) +} // protocol is either "udp" or "tcp" type NAT interface { @@ -35,65 +53,91 @@ type NAT interface { DeletePortMapping(ctx context.Context, protocol string, internalPort int) (err error) } -// DiscoverNATs returns all NATs discovered in the network. -func DiscoverNATs(ctx context.Context) <-chan NAT { - nats := make(chan NAT) +// discoverNATs returns all NATs discovered in the network. +func discoverNATs(ctx context.Context) ([]NAT, []error) { + type natsAndErrs struct { + nats []NAT + errs []error + } + upnpCh := make(chan natsAndErrs) + pmpCh := make(chan natsAndErrs) go func() { - defer close(nats) - - upnpIg1 := discoverUPNP_IG1(ctx) - upnpIg2 := discoverUPNP_IG2(ctx) - natpmp := discoverNATPMP(ctx) - upnpGenIGDev := discoverUPNP_GenIGDev(ctx) - for upnpIg1 != nil || upnpIg2 != nil || natpmp != nil || upnpGenIGDev != nil { - var ( - nat NAT - ok bool - ) - select { - case nat, ok = <-upnpIg1: - if !ok { - upnpIg1 = nil - } - case nat, ok = <-upnpIg2: - if !ok { - upnpIg2 = nil - } - case nat, ok = <-upnpGenIGDev: - if !ok { - upnpGenIGDev = nil - } - case nat, ok = <-natpmp: - if !ok { - natpmp = nil - } - case <-ctx.Done(): - // timeout. - return - } - if ok { - select { - case nats <- nat: - case <-ctx.Done(): - return - } - } + defer close(upnpCh) + + // We do these UPNP queries sequentially because some routers will fail to handle parallel requests. + nats, errs := discoverUPNP_IG1(ctx) + + // Do IG2 after IG1 so that its NAT devices will appear as "better" when we + // find the best NAT to return below. + n, e := discoverUPNP_IG2(ctx) + nats = append(nats, n...) + errs = append(errs, e...) + + if len(nats) == 0 { + // We don't have a NAT. We should try querying all devices over + // SSDP to find a InternetGatewayDevice. This shouldn't be necessary for + // a well behaved router. + n, e = discoverUPNP_GenIGDev(ctx) + nats = append(nats, n...) + errs = append(errs, e...) + } + + select { + case upnpCh <- natsAndErrs{nats, errs}: + case <-ctx.Done(): + } + }() + + go func() { + defer close(pmpCh) + nat, err := discoverNATPMP(ctx) + var nats []NAT + var errs []error + if err != nil { + errs = append(errs, err) + } else { + nats = append(nats, nat) + } + select { + case pmpCh <- natsAndErrs{nats, errs}: + case <-ctx.Done(): } }() - return nats + + var nats []NAT + var errs []error + + for upnpCh != nil && pmpCh != nil { + select { + case res := <-pmpCh: + pmpCh = nil + nats = append(nats, res.nats...) + errs = append(errs, res.errs...) + case res := <-upnpCh: + upnpCh = nil + nats = append(nats, res.nats...) + errs = append(errs, res.errs...) + case <-ctx.Done(): + errs = append(errs, ctx.Err()) + return nats, errs + } + } + return nats, errs } // DiscoverGateway attempts to find a gateway device. func DiscoverGateway(ctx context.Context) (NAT, error) { - var nats []NAT - for nat := range DiscoverNATs(ctx) { - nats = append(nats, nat) - } + nats, errs := discoverNATs(ctx) + switch len(nats) { case 0: - return nil, ErrNoNATFound + return nil, ErrNoNATFound{Errs: errs} case 1: + if len(errs) > 0 { + log.Debugf("NAT found, but some potentially unrelated errors occurred: %v", errs) + } + return nats[0], nil } gw, _ := getDefaultGateway() @@ -115,6 +159,10 @@ func DiscoverGateway(ctx context.Context) (NAT, error) { bestNATIsGw = natIsGw bestNAT = nat } + + if len(errs) > 0 { + log.Debugf("NAT found, but some potentially unrelated errors occurred: %v", errs) + } return bestNAT, nil } @@ -123,3 +171,13 @@ var random = rand.New(rand.NewSource(time.Now().UnixNano())) func randomPort() int { return random.Intn(math.MaxUint16-10000) + 10000 } + +func getDefaultGateway() (net.IP, error) { + router, err := netroute.New() + if err != nil { + return nil, err + } + + _, ip, _, err := router.Route(net.IPv4zero) + return ip, err +} diff --git a/p2p/net/nat/internal/nat/natpmp.go b/p2p/net/nat/internal/nat/natpmp.go index 2378d8d7ec..a83bc805c9 100644 --- a/p2p/net/nat/internal/nat/natpmp.go +++ b/p2p/net/nat/internal/nat/natpmp.go @@ -12,42 +12,48 @@ var ( _ NAT = (*natpmpNAT)(nil) ) -func discoverNATPMP(ctx context.Context) <-chan NAT { - res := make(chan NAT, 1) - +func discoverNATPMP(ctx context.Context) (NAT, error) { ip, err := getDefaultGateway() if err != nil { - return nil + return nil, err } - go func() { - defer close(res) - // Unfortunately, we can't actually _stop_ the natpmp - // library. However, we can at least close _our_ channel - // and walk away. - select { - case client, ok := <-discoverNATPMPWithAddr(ip): - if ok { - res <- &natpmpNAT{client, ip, make(map[int]int)} - } - case <-ctx.Done(): - } - }() - return res -} + clientCh := make(chan *natpmp.Client) + errCh := make(chan error) -func discoverNATPMPWithAddr(ip net.IP) <-chan *natpmp.Client { - res := make(chan *natpmp.Client, 1) + // We can't cancel the natpmp library, but we can at least still return + // on context cancellation by putting this in a goroutine go func() { - defer close(res) - client := natpmp.NewClient(ip) - _, err := client.GetExternalAddress() + client, err := discoverNATPMPWithAddr(ctx, ip) if err != nil { + errCh <- err return } - res <- client + clientCh <- client }() - return res + + select { + case client := <-clientCh: + return &natpmpNAT{client, ip, make(map[int]int)}, nil + case err := <-errCh: + return nil, err + case <-ctx.Done(): + return nil, ctx.Err() + } +} + +func discoverNATPMPWithAddr(ctx context.Context, ip net.IP) (*natpmp.Client, error) { + var client *natpmp.Client + if deadline, ok := ctx.Deadline(); ok { + client = natpmp.NewClientWithTimeout(ip, time.Until(deadline)) + } else { + client = natpmp.NewClient(ip) + } + _, err := client.GetExternalAddress() + if err != nil { + return nil, err + } + return client, nil } type natpmpNAT struct { diff --git a/p2p/net/nat/internal/nat/upnp.go b/p2p/net/nat/internal/nat/upnp.go index c50b952bbe..761a89e7a8 100644 --- a/p2p/net/nat/internal/nat/upnp.go +++ b/p2p/net/nat/internal/nat/upnp.go @@ -16,197 +16,115 @@ import ( var _ NAT = (*upnp_NAT)(nil) -func discoverUPNP_IG1(ctx context.Context) <-chan NAT { - res := make(chan NAT) - go func() { - defer close(res) - - // find devices - devs, err := goupnp.DiscoverDevicesCtx(ctx, internetgateway1.URN_WANConnectionDevice_1) - if err != nil { - return - } - - for _, dev := range devs { - if dev.Root == nil { - continue - } - - dev.Root.Device.VisitServices(func(srv *goupnp.Service) { - if ctx.Err() != nil { - return - } - switch srv.ServiceType { - case internetgateway1.URN_WANIPConnection_1: - client := &internetgateway1.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ - SOAPClient: srv.NewSOAPClient(), - RootDevice: dev.Root, - Service: srv, - }} - _, isNat, err := client.GetNATRSIPStatusCtx(ctx) - if err == nil && isNat { - select { - case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", dev.Root}: - case <-ctx.Done(): - } - } - - case internetgateway1.URN_WANPPPConnection_1: - client := &internetgateway1.WANPPPConnection1{ServiceClient: goupnp.ServiceClient{ - SOAPClient: srv.NewSOAPClient(), - RootDevice: dev.Root, - Service: srv, - }} - _, isNat, err := client.GetNATRSIPStatusCtx(ctx) - if err == nil && isNat { - select { - case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", dev.Root}: - case <-ctx.Done(): - } - } - - } - }) - } - - }() - return res +func discoverUPNP_IG1(ctx context.Context) ([]NAT, []error) { + return discoverSearchTarget(ctx, internetgateway1.URN_WANConnectionDevice_1) } -func discoverUPNP_IG2(ctx context.Context) <-chan NAT { - res := make(chan NAT) - go func() { - defer close(res) - - // find devices - devs, err := goupnp.DiscoverDevicesCtx(ctx, internetgateway2.URN_WANConnectionDevice_2) - if err != nil { - return - } - - for _, dev := range devs { - if dev.Root == nil { - continue - } +func discoverUPNP_IG2(ctx context.Context) ([]NAT, []error) { + return discoverSearchTarget(ctx, internetgateway2.URN_WANConnectionDevice_2) +} - dev.Root.Device.VisitServices(func(srv *goupnp.Service) { - if ctx.Err() != nil { - return - } - switch srv.ServiceType { - case internetgateway2.URN_WANIPConnection_1: - client := &internetgateway2.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ - SOAPClient: srv.NewSOAPClient(), - RootDevice: dev.Root, - Service: srv, - }} - _, isNat, err := client.GetNATRSIPStatusCtx(ctx) - if err == nil && isNat { - select { - case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP1)", dev.Root}: - case <-ctx.Done(): - } - } - - case internetgateway2.URN_WANIPConnection_2: - client := &internetgateway2.WANIPConnection2{ServiceClient: goupnp.ServiceClient{ - SOAPClient: srv.NewSOAPClient(), - RootDevice: dev.Root, - Service: srv, - }} - _, isNat, err := client.GetNATRSIPStatusCtx(ctx) - if err == nil && isNat { - select { - case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-IP2)", dev.Root}: - case <-ctx.Done(): - } - } - - case internetgateway2.URN_WANPPPConnection_1: - client := &internetgateway2.WANPPPConnection1{ServiceClient: goupnp.ServiceClient{ - SOAPClient: srv.NewSOAPClient(), - RootDevice: dev.Root, - Service: srv, - }} - _, isNat, err := client.GetNATRSIPStatusCtx(ctx) - if err == nil && isNat { - select { - case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG2-PPP1)", dev.Root}: - case <-ctx.Done(): - } - } +func discoverSearchTarget(ctx context.Context, target string) (nats []NAT, errs []error) { + // find devices + devs, err := goupnp.DiscoverDevicesCtx(ctx, target) + if err != nil { + errs = append(errs, err) + return + } - } - }) + for _, dev := range devs { + if dev.Err != nil { + errs = append(errs, dev.Err) + continue } - - }() - return res + dev.Root.Device.VisitServices(serviceVisitor(ctx, dev.Root, &nats, &errs)) + } + return } -func discoverUPNP_GenIGDev(ctx context.Context) <-chan NAT { - res := make(chan NAT, 1) - go func() { - defer close(res) +// discoverUPNP_GenIGDev is a fallback for routers that fail to respond to our +// targetted SSDP queries. It will query all devices and try to find any +// InternetGatewayDevice. +func discoverUPNP_GenIGDev(ctx context.Context) (nats []NAT, errs []error) { + DeviceList, err := ssdp.Search(ssdp.All, 5, "") + if err != nil { + errs = append(errs, err) + return + } - DeviceList, err := ssdp.Search(ssdp.All, 5, "") - if err != nil { - return + const maxIGDevs = 3 + foundIGDevs := 0 + for _, Service := range DeviceList { + if !strings.Contains(Service.Type, "InternetGatewayDevice") { + continue } - var gw ssdp.Service - for _, Service := range DeviceList { - if strings.Contains(Service.Type, "InternetGatewayDevice") { - gw = Service - break - } + if foundIGDevs >= maxIGDevs { + break } + foundIGDevs++ - DeviceURL, err := url.Parse(gw.Location) + DeviceURL, err := url.Parse(Service.Location) if err != nil { - return + errs = append(errs, err) + continue } RootDevice, err := goupnp.DeviceByURLCtx(ctx, DeviceURL) if err != nil { - return + errs = append(errs, err) + continue } - RootDevice.Device.VisitServices(func(srv *goupnp.Service) { - if ctx.Err() != nil { - return + RootDevice.Device.VisitServices(serviceVisitor(ctx, RootDevice, &nats, &errs)) + } + return +} + +func serviceVisitor(ctx context.Context, rootDevice *goupnp.RootDevice, outNats *[]NAT, outErrs *[]error) func(srv *goupnp.Service) { + return func(srv *goupnp.Service) { + if ctx.Err() != nil { + return + } + switch srv.ServiceType { + case internetgateway2.URN_WANIPConnection_1: + client := &internetgateway2.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: rootDevice, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) + if err != nil { + *outErrs = append(*outErrs, err) + } else if isNat { + *outNats = append(*outNats, &upnp_NAT{client, make(map[int]int), "UPNP (IP1)", rootDevice}) } - switch srv.ServiceType { - case internetgateway1.URN_WANIPConnection_1: - client := &internetgateway1.WANIPConnection1{ServiceClient: goupnp.ServiceClient{ - SOAPClient: srv.NewSOAPClient(), - RootDevice: RootDevice, - Service: srv, - }} - _, isNat, err := client.GetNATRSIPStatusCtx(ctx) - if err == nil && isNat { - select { - case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-IP1)", RootDevice}: - case <-ctx.Done(): - } - } - case internetgateway1.URN_WANPPPConnection_1: - client := &internetgateway1.WANPPPConnection1{ServiceClient: goupnp.ServiceClient{ - SOAPClient: srv.NewSOAPClient(), - RootDevice: RootDevice, - Service: srv, - }} - _, isNat, err := client.GetNATRSIPStatusCtx(ctx) - if err == nil && isNat { - select { - case res <- &upnp_NAT{client, make(map[int]int), "UPNP (IG1-PPP1)", RootDevice}: - case <-ctx.Done(): - } - } + case internetgateway2.URN_WANIPConnection_2: + client := &internetgateway2.WANIPConnection2{ServiceClient: goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: rootDevice, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) + if err != nil { + *outErrs = append(*outErrs, err) + } else if isNat { + *outNats = append(*outNats, &upnp_NAT{client, make(map[int]int), "UPNP (IP2)", rootDevice}) + } + case internetgateway2.URN_WANPPPConnection_1: + client := &internetgateway2.WANPPPConnection1{ServiceClient: goupnp.ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: rootDevice, + Service: srv, + }} + _, isNat, err := client.GetNATRSIPStatusCtx(ctx) + if err != nil { + *outErrs = append(*outErrs, err) + } else if isNat { + *outNats = append(*outNats, &upnp_NAT{client, make(map[int]int), "UPNP (PPP1)", rootDevice}) } - }) - }() - return res + } + } } type upnp_NAT_Client interface { diff --git a/p2p/net/nat/internal/nat/version.json b/p2p/net/nat/internal/nat/version.json deleted file mode 100644 index 1437d5b735..0000000000 --- a/p2p/net/nat/internal/nat/version.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "version": "v0.2.0" -} diff --git a/p2p/net/nat/mock_nat_test.go b/p2p/net/nat/mock_nat_test.go index c8023344ea..ed8b6a1a61 100644 --- a/p2p/net/nat/mock_nat_test.go +++ b/p2p/net/nat/mock_nat_test.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/libp2p/go-nat (interfaces: NAT) +// Source: github.com/libp2p/go-libp2p/p2p/net/nat/internal/nat (interfaces: NAT) // // Generated by this command: // -// mockgen -package nat -destination mock_nat_test.go github.com/libp2p/go-nat NAT +// mockgen -package nat -destination mock_nat_test.go github.com/libp2p/go-libp2p/p2p/net/nat/internal/nat NAT // // Package nat is a generated GoMock package. diff --git a/p2p/net/nat/nat.go b/p2p/net/nat/nat.go index ebaa167568..c45b067f9c 100644 --- a/p2p/net/nat/nat.go +++ b/p2p/net/nat/nat.go @@ -11,7 +11,7 @@ import ( logging "github.com/ipfs/go-log/v2" - "github.com/libp2p/go-nat" + "github.com/libp2p/go-libp2p/p2p/net/nat/internal/nat" ) // ErrNoMapping signals no mapping exists for an address diff --git a/p2p/net/nat/nat_test.go b/p2p/net/nat/nat_test.go index e370fc8907..5779a27e6c 100644 --- a/p2p/net/nat/nat_test.go +++ b/p2p/net/nat/nat_test.go @@ -7,13 +7,12 @@ import ( "net/netip" "testing" - "github.com/libp2p/go-nat" - + "github.com/libp2p/go-libp2p/p2p/net/nat/internal/nat" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ) -//go:generate sh -c "go run go.uber.org/mock/mockgen -package nat -destination mock_nat_test.go github.com/libp2p/go-nat NAT" +//go:generate sh -c "go run go.uber.org/mock/mockgen -package nat -destination mock_nat_test.go github.com/libp2p/go-libp2p/p2p/net/nat/internal/nat NAT" func setupMockNAT(t *testing.T) (mockNAT *MockNAT, reset func()) { t.Helper() diff --git a/test-plans/go.mod b/test-plans/go.mod index 6bd58c0b95..172151f4fa 100644 --- a/test-plans/go.mod +++ b/test-plans/go.mod @@ -41,7 +41,6 @@ require ( github.com/libp2p/go-flow-metrics v0.2.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-nat v0.2.0 // indirect github.com/libp2p/go-netroute v0.2.2 // indirect github.com/libp2p/go-reuseport v0.4.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.1 // indirect diff --git a/test-plans/go.sum b/test-plans/go.sum index 439614d540..329a2475d2 100644 --- a/test-plans/go.sum +++ b/test-plans/go.sum @@ -144,8 +144,6 @@ github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUI github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= -github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk= github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8= github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE= github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= From 92a5d9129d13a54095f393c95e8a212bfa032ca1 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Thu, 30 Jan 2025 14:02:11 -0800 Subject: [PATCH 52/54] use buffered chan --- p2p/net/nat/internal/nat/natpmp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/p2p/net/nat/internal/nat/natpmp.go b/p2p/net/nat/internal/nat/natpmp.go index a83bc805c9..bffc0a99f2 100644 --- a/p2p/net/nat/internal/nat/natpmp.go +++ b/p2p/net/nat/internal/nat/natpmp.go @@ -18,8 +18,8 @@ func discoverNATPMP(ctx context.Context) (NAT, error) { return nil, err } - clientCh := make(chan *natpmp.Client) - errCh := make(chan error) + clientCh := make(chan *natpmp.Client, 1) + errCh := make(chan error, 1) // We can't cancel the natpmp library, but we can at least still return // on context cancellation by putting this in a goroutine From 33a5f73869a05a0e81b15a723f6d02708ec92c22 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Thu, 30 Jan 2025 14:19:17 -0800 Subject: [PATCH 53/54] PR comments --- p2p/net/nat/internal/nat/nat.go | 4 ++++ p2p/net/nat/internal/nat/upnp.go | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/p2p/net/nat/internal/nat/nat.go b/p2p/net/nat/internal/nat/nat.go index c32ff7c461..4b39ded40f 100644 --- a/p2p/net/nat/internal/nat/nat.go +++ b/p2p/net/nat/internal/nat/nat.go @@ -24,6 +24,10 @@ type ErrNoNATFound struct { Errs []error } +func (e ErrNoNATFound) Unwrap() []error { + return e.Errs +} + func (e ErrNoNATFound) Error() string { var errStrs []string for _, err := range e.Errs { diff --git a/p2p/net/nat/internal/nat/upnp.go b/p2p/net/nat/internal/nat/upnp.go index 761a89e7a8..4ad729fe39 100644 --- a/p2p/net/nat/internal/nat/upnp.go +++ b/p2p/net/nat/internal/nat/upnp.go @@ -2,6 +2,7 @@ package nat import ( "context" + "fmt" "net" "net/url" "strings" @@ -52,6 +53,9 @@ func discoverUPNP_GenIGDev(ctx context.Context) (nats []NAT, errs []error) { return } + // Limit the number of InternetGateways we'll query. Normally we'd only + // expect 1 or 2, but in case of a weird network we also don't want to do + // too much work. const maxIGDevs = 3 foundIGDevs := 0 for _, Service := range DeviceList { @@ -79,6 +83,10 @@ func discoverUPNP_GenIGDev(ctx context.Context) (nats []NAT, errs []error) { return } +// serviceVisitor is a vistor function that visits all services of a root +// device and collects NATs. +// +// It works on InternetGateway V1 and V2 devices. For V1 devices, V2 services should not be encountered, and the visitor will collect an error in that case. func serviceVisitor(ctx context.Context, rootDevice *goupnp.RootDevice, outNats *[]NAT, outErrs *[]error) func(srv *goupnp.Service) { return func(srv *goupnp.Service) { if ctx.Err() != nil { @@ -99,6 +107,10 @@ func serviceVisitor(ctx context.Context, rootDevice *goupnp.RootDevice, outNats } case internetgateway2.URN_WANIPConnection_2: + if rootDevice.Device.DeviceType == internetgateway2.URN_WANConnectionDevice_1 { + *outErrs = append(*outErrs, fmt.Errorf("found V2 service on V1 device")) + return + } client := &internetgateway2.WANIPConnection2{ServiceClient: goupnp.ServiceClient{ SOAPClient: srv.NewSOAPClient(), RootDevice: rootDevice, From 027bdd8db8a9abd030175c9756a80f4fae2e66fa Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Fri, 31 Jan 2025 09:22:17 -0800 Subject: [PATCH 54/54] fix for loop condition --- p2p/net/nat/internal/nat/nat.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p2p/net/nat/internal/nat/nat.go b/p2p/net/nat/internal/nat/nat.go index 4b39ded40f..ccbf87deca 100644 --- a/p2p/net/nat/internal/nat/nat.go +++ b/p2p/net/nat/internal/nat/nat.go @@ -112,7 +112,7 @@ func discoverNATs(ctx context.Context) ([]NAT, []error) { var nats []NAT var errs []error - for upnpCh != nil && pmpCh != nil { + for upnpCh != nil || pmpCh != nil { select { case res := <-pmpCh: pmpCh = nil