diff --git a/cmd/tendermint/commands/probe_upnp.go b/cmd/tendermint/commands/probe_upnp.go
deleted file mode 100644
index 4c71e099a..000000000
--- a/cmd/tendermint/commands/probe_upnp.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package commands
-
-import (
- "fmt"
-
- "github.com/spf13/cobra"
-
- "github.com/tendermint/tendermint/internal/p2p/upnp"
- tmjson "github.com/tendermint/tendermint/libs/json"
-)
-
-// ProbeUpnpCmd adds capabilities to test the UPnP functionality.
-var ProbeUpnpCmd = &cobra.Command{
- Use: "probe-upnp",
- Short: "Test UPnP functionality",
- RunE: probeUpnp,
-}
-
-func probeUpnp(cmd *cobra.Command, args []string) error {
- capabilities, err := upnp.Probe(logger)
- if err != nil {
- fmt.Println("Probe failed: ", err)
- } else {
- fmt.Println("Probe success!")
- jsonBytes, err := tmjson.Marshal(capabilities)
- if err != nil {
- return err
- }
- fmt.Println(string(jsonBytes))
- }
- return nil
-}
diff --git a/cmd/tendermint/main.go b/cmd/tendermint/main.go
index 52a00e4c0..b461c8e7b 100644
--- a/cmd/tendermint/main.go
+++ b/cmd/tendermint/main.go
@@ -17,7 +17,6 @@ func main() {
cmd.GenValidatorCmd,
cmd.ReIndexEventCmd,
cmd.InitFilesCmd,
- cmd.ProbeUpnpCmd,
cmd.LightCmd,
cmd.ReplayCmd,
cmd.ReplayConsoleCmd,
diff --git a/internal/p2p/upnp/probe.go b/internal/p2p/upnp/probe.go
deleted file mode 100644
index ae641abbb..000000000
--- a/internal/p2p/upnp/probe.go
+++ /dev/null
@@ -1,111 +0,0 @@
-package upnp
-
-import (
- "fmt"
- "net"
- "time"
-
- "github.com/tendermint/tendermint/libs/log"
-)
-
-type Capabilities struct {
- PortMapping bool
- Hairpin bool
-}
-
-func makeUPNPListener(intPort int, extPort int, logger log.Logger) (NAT, net.Listener, net.IP, error) {
- nat, err := Discover()
- if err != nil {
- return nil, nil, nil, fmt.Errorf("nat upnp could not be discovered: %v", err)
- }
- logger.Info(fmt.Sprintf("ourIP: %v", nat.(*upnpNAT).ourIP))
-
- ext, err := nat.GetExternalAddress()
- if err != nil {
- return nat, nil, nil, fmt.Errorf("external address error: %v", err)
- }
- logger.Info(fmt.Sprintf("External address: %v", ext))
-
- port, err := nat.AddPortMapping("tcp", extPort, intPort, "Tendermint UPnP Probe", 0)
- if err != nil {
- return nat, nil, ext, fmt.Errorf("port mapping error: %v", err)
- }
- logger.Info(fmt.Sprintf("Port mapping mapped: %v", port))
-
- // also run the listener, open for all remote addresses.
- listener, err := net.Listen("tcp", fmt.Sprintf(":%v", intPort))
- if err != nil {
- return nat, nil, ext, fmt.Errorf("error establishing listener: %v", err)
- }
- return nat, listener, ext, nil
-}
-
-func testHairpin(listener net.Listener, extAddr string, logger log.Logger) (supportsHairpin bool) {
- // Listener
- go func() {
- inConn, err := listener.Accept()
- if err != nil {
- logger.Info(fmt.Sprintf("Listener.Accept() error: %v", err))
- return
- }
- logger.Info(fmt.Sprintf("Accepted incoming connection: %v -> %v", inConn.LocalAddr(), inConn.RemoteAddr()))
- buf := make([]byte, 1024)
- n, err := inConn.Read(buf)
- if err != nil {
- logger.Info(fmt.Sprintf("Incoming connection read error: %v", err))
- return
- }
- logger.Info(fmt.Sprintf("Incoming connection read %v bytes: %X", n, buf))
- if string(buf) == "test data" {
- supportsHairpin = true
- return
- }
- }()
-
- // Establish outgoing
- outConn, err := net.Dial("tcp", extAddr)
- if err != nil {
- logger.Info(fmt.Sprintf("Outgoing connection dial error: %v", err))
- return
- }
-
- n, err := outConn.Write([]byte("test data"))
- if err != nil {
- logger.Info(fmt.Sprintf("Outgoing connection write error: %v", err))
- return
- }
- logger.Info(fmt.Sprintf("Outgoing connection wrote %v bytes", n))
-
- // Wait for data receipt
- time.Sleep(1 * time.Second)
- return supportsHairpin
-}
-
-func Probe(logger log.Logger) (caps Capabilities, err error) {
- logger.Info("Probing for UPnP!")
-
- intPort, extPort := 8001, 8001
-
- nat, listener, ext, err := makeUPNPListener(intPort, extPort, logger)
- if err != nil {
- return
- }
- caps.PortMapping = true
-
- // Deferred cleanup
- defer func() {
- if err := nat.DeletePortMapping("tcp", intPort, extPort); err != nil {
- logger.Error(fmt.Sprintf("Port mapping delete error: %v", err))
- }
- if err := listener.Close(); err != nil {
- logger.Error(fmt.Sprintf("Listener closing error: %v", err))
- }
- }()
-
- supportsHairpin := testHairpin(listener, fmt.Sprintf("%v:%v", ext, extPort), logger)
- if supportsHairpin {
- caps.Hairpin = true
- }
-
- return
-}
diff --git a/internal/p2p/upnp/upnp.go b/internal/p2p/upnp/upnp.go
deleted file mode 100644
index e2c8f3fcf..000000000
--- a/internal/p2p/upnp/upnp.go
+++ /dev/null
@@ -1,404 +0,0 @@
-// Taken from taipei-torrent.
-// Just enough UPnP to be able to forward ports
-// For more information, see: http://www.upnp-hacks.org/upnp.html
-package upnp
-
-// TODO: use syscalls to get actual ourIP, see issue #712
-
-import (
- "bytes"
- "encoding/xml"
- "errors"
- "fmt"
- "io"
- "net"
- "net/http"
- "strconv"
- "strings"
- "time"
-)
-
-type upnpNAT struct {
- serviceURL string
- ourIP string
- urnDomain string
-}
-
-// protocol is either "udp" or "tcp"
-type NAT interface {
- GetExternalAddress() (addr net.IP, err error)
- AddPortMapping(
- protocol string,
- externalPort,
- internalPort int,
- description string,
- timeout int) (mappedExternalPort int, err error)
- DeletePortMapping(protocol string, externalPort, internalPort int) (err error)
-}
-
-func Discover() (nat NAT, err error) {
- ssdp, err := net.ResolveUDPAddr("udp4", "239.255.255.250:1900")
- if err != nil {
- return
- }
- conn, err := net.ListenPacket("udp4", ":0")
- if err != nil {
- return
- }
- socket := conn.(*net.UDPConn)
- defer socket.Close()
-
- if err := socket.SetDeadline(time.Now().Add(3 * time.Second)); err != nil {
- return nil, err
- }
-
- st := "InternetGatewayDevice:1"
-
- buf := bytes.NewBufferString(
- "M-SEARCH * HTTP/1.1\r\n" +
- "HOST: 239.255.255.250:1900\r\n" +
- "ST: ssdp:all\r\n" +
- "MAN: \"ssdp:discover\"\r\n" +
- "MX: 2\r\n\r\n")
- message := buf.Bytes()
- answerBytes := make([]byte, 1024)
- for i := 0; i < 3; i++ {
- _, err = socket.WriteToUDP(message, ssdp)
- if err != nil {
- return
- }
- var n int
- _, _, err = socket.ReadFromUDP(answerBytes)
- if err != nil {
- return
- }
- for {
- n, _, err = socket.ReadFromUDP(answerBytes)
- if err != nil {
- break
- }
- answer := string(answerBytes[0:n])
- if !strings.Contains(answer, st) {
- continue
- }
- // HTTP header field names are case-insensitive.
- // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
- locString := "\r\nlocation:"
- answer = strings.ToLower(answer)
- locIndex := strings.Index(answer, locString)
- if locIndex < 0 {
- continue
- }
- loc := answer[locIndex+len(locString):]
- endIndex := strings.Index(loc, "\r\n")
- if endIndex < 0 {
- continue
- }
- locURL := strings.TrimSpace(loc[0:endIndex])
- var serviceURL, urnDomain string
- serviceURL, urnDomain, err = getServiceURL(locURL)
- if err != nil {
- return
- }
- var ourIP net.IP
- ourIP, err = localIPv4()
- if err != nil {
- return
- }
- nat = &upnpNAT{serviceURL: serviceURL, ourIP: ourIP.String(), urnDomain: urnDomain}
- return
- }
- }
- err = errors.New("upnp port discovery failed")
- return nat, err
-}
-
-type Envelope struct {
- XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
- Soap *SoapBody
-}
-type SoapBody struct {
- XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`
- ExternalIP *ExternalIPAddressResponse
-}
-
-type ExternalIPAddressResponse struct {
- XMLName xml.Name `xml:"GetExternalIPAddressResponse"`
- IPAddress string `xml:"NewExternalIPAddress"`
-}
-
-type ExternalIPAddress struct {
- XMLName xml.Name `xml:"NewExternalIPAddress"`
- IP string
-}
-
-type Service struct {
- ServiceType string `xml:"serviceType"`
- ControlURL string `xml:"controlURL"`
-}
-
-type DeviceList struct {
- Device []Device `xml:"device"`
-}
-
-type ServiceList struct {
- Service []Service `xml:"service"`
-}
-
-type Device struct {
- XMLName xml.Name `xml:"device"`
- DeviceType string `xml:"deviceType"`
- DeviceList DeviceList `xml:"deviceList"`
- ServiceList ServiceList `xml:"serviceList"`
-}
-
-type Root struct {
- Device Device
-}
-
-func getChildDevice(d *Device, deviceType string) *Device {
- dl := d.DeviceList.Device
- for i := 0; i < len(dl); i++ {
- if strings.Contains(dl[i].DeviceType, deviceType) {
- return &dl[i]
- }
- }
- return nil
-}
-
-func getChildService(d *Device, serviceType string) *Service {
- sl := d.ServiceList.Service
- for i := 0; i < len(sl); i++ {
- if strings.Contains(sl[i].ServiceType, serviceType) {
- return &sl[i]
- }
- }
- return nil
-}
-
-func localIPv4() (net.IP, error) {
- tt, err := net.Interfaces()
- if err != nil {
- return nil, err
- }
- for _, t := range tt {
- aa, err := t.Addrs()
- if err != nil {
- return nil, err
- }
- for _, a := range aa {
- ipnet, ok := a.(*net.IPNet)
- if !ok {
- continue
- }
- v4 := ipnet.IP.To4()
- if v4 == nil || v4[0] == 127 { // loopback address
- continue
- }
- return v4, nil
- }
- }
- return nil, errors.New("cannot find local IP address")
-}
-
-func getServiceURL(rootURL string) (url, urnDomain string, err error) {
- r, err := http.Get(rootURL) // nolint: gosec
- if err != nil {
- return
- }
- defer r.Body.Close()
-
- if r.StatusCode >= 400 {
- err = errors.New(string(rune(r.StatusCode)))
- return
- }
- var root Root
- err = xml.NewDecoder(r.Body).Decode(&root)
- if err != nil {
- return
- }
- a := &root.Device
- if !strings.Contains(a.DeviceType, "InternetGatewayDevice:1") {
- err = errors.New("no InternetGatewayDevice")
- return
- }
- b := getChildDevice(a, "WANDevice:1")
- if b == nil {
- err = errors.New("no WANDevice")
- return
- }
- c := getChildDevice(b, "WANConnectionDevice:1")
- if c == nil {
- err = errors.New("no WANConnectionDevice")
- return
- }
- d := getChildService(c, "WANIPConnection:1")
- if d == nil {
- // Some routers don't follow the UPnP spec, and put WanIPConnection under WanDevice,
- // instead of under WanConnectionDevice
- d = getChildService(b, "WANIPConnection:1")
-
- if d == nil {
- err = errors.New("no WANIPConnection")
- return
- }
- }
- // Extract the domain name, which isn't always 'schemas-upnp-org'
- urnDomain = strings.Split(d.ServiceType, ":")[1]
- url = combineURL(rootURL, d.ControlURL)
- return url, urnDomain, err
-}
-
-func combineURL(rootURL, subURL string) string {
- protocolEnd := "://"
- protoEndIndex := strings.Index(rootURL, protocolEnd)
- a := rootURL[protoEndIndex+len(protocolEnd):]
- rootIndex := strings.Index(a, "/")
- return rootURL[0:protoEndIndex+len(protocolEnd)+rootIndex] + subURL
-}
-
-func soapRequest(url, function, message, domain string) (r *http.Response, err error) {
- fullMessage := "" +
- "\r\n" +
- "" + message + ""
-
- req, err := http.NewRequest("POST", url, strings.NewReader(fullMessage))
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", "text/xml ; charset=\"utf-8\"")
- req.Header.Set("User-Agent", "Darwin/10.0.0, UPnP/1.0, MiniUPnPc/1.3")
- // req.Header.Set("Transfer-Encoding", "chunked")
- req.Header.Set("SOAPAction", "\"urn:"+domain+":service:WANIPConnection:1#"+function+"\"")
- req.Header.Set("Connection", "Close")
- req.Header.Set("Cache-Control", "no-cache")
- req.Header.Set("Pragma", "no-cache")
-
- // log.Stderr("soapRequest ", req)
-
- r, err = http.DefaultClient.Do(req)
- if err != nil {
- return nil, err
- }
- /*if r.Body != nil {
- defer r.Body.Close()
- }*/
-
- if r.StatusCode >= 400 {
- // log.Stderr(function, r.StatusCode)
- err = errors.New("error " + strconv.Itoa(r.StatusCode) + " for " + function)
- r = nil
- return
- }
- return r, err
-}
-
-type statusInfo struct {
- externalIPAddress string
-}
-
-func (n *upnpNAT) getExternalIPAddress() (info statusInfo, err error) {
-
- message := "\r\n" +
- ""
-
- var response *http.Response
- response, err = soapRequest(n.serviceURL, "GetExternalIPAddress", message, n.urnDomain)
- if response != nil {
- defer response.Body.Close()
- }
- if err != nil {
- return
- }
- var envelope Envelope
- data, err := io.ReadAll(response.Body)
- if err != nil {
- return
- }
- reader := bytes.NewReader(data)
- err = xml.NewDecoder(reader).Decode(&envelope)
- if err != nil {
- return
- }
-
- info = statusInfo{envelope.Soap.ExternalIP.IPAddress}
-
- if err != nil {
- return
- }
-
- return info, err
-}
-
-// GetExternalAddress returns an external IP. If GetExternalIPAddress action
-// fails or IP returned is invalid, GetExternalAddress returns an error.
-func (n *upnpNAT) GetExternalAddress() (addr net.IP, err error) {
- info, err := n.getExternalIPAddress()
- if err != nil {
- return
- }
- addr = net.ParseIP(info.externalIPAddress)
- if addr == nil {
- err = fmt.Errorf("failed to parse IP: %v", info.externalIPAddress)
- }
- return
-}
-
-func (n *upnpNAT) AddPortMapping(
- protocol string,
- externalPort,
- internalPort int,
- description string,
- timeout int) (mappedExternalPort int, err error) {
- // A single concatenation would break ARM compilation.
- message := "\r\n" +
- "" + strconv.Itoa(externalPort)
- message += "" + protocol + ""
- message += "" + strconv.Itoa(internalPort) + "" +
- "" + n.ourIP + "" +
- "1"
- message += description +
- "" + strconv.Itoa(timeout) +
- ""
-
- var response *http.Response
- response, err = soapRequest(n.serviceURL, "AddPortMapping", message, n.urnDomain)
- if response != nil {
- defer response.Body.Close()
- }
- if err != nil {
- return
- }
-
- // TODO: check response to see if the port was forwarded
- // log.Println(message, response)
- // JAE:
- // body, err := io.ReadAll(response.Body)
- // fmt.Println(string(body), err)
- mappedExternalPort = externalPort
- _ = response
- return mappedExternalPort, err
-}
-
-func (n *upnpNAT) DeletePortMapping(protocol string, externalPort, internalPort int) (err error) {
-
- message := "\r\n" +
- "" + strconv.Itoa(externalPort) +
- "" + protocol + "" +
- ""
-
- var response *http.Response
- response, err = soapRequest(n.serviceURL, "DeletePortMapping", message, n.urnDomain)
- if response != nil {
- defer response.Body.Close()
- }
- if err != nil {
- return
- }
-
- // TODO: check response to see if the port was deleted
- // log.Println(message, response)
- _ = response
- return
-}