浏览代码

p2p/discover: map listening port using configured mechanism

Felix Lange 10 年之前
父节点
当前提交
170eb3ac68
共有 4 个文件被更改,包括 35 次插入18 次删除
  1. 10 3
      cmd/bootnode/main.go
  2. 17 6
      p2p/discover/udp.go
  3. 7 7
      p2p/discover/udp_test.go
  4. 1 2
      p2p/server.go

+ 10 - 3
cmd/bootnode/main.go

@@ -30,6 +30,7 @@ import (
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/p2p/discover"
+	"github.com/ethereum/go-ethereum/p2p/nat"
 )
 
 func main() {
@@ -38,8 +39,10 @@ func main() {
 		genKey      = flag.String("genkey", "", "generate a node key and quit")
 		nodeKeyFile = flag.String("nodekey", "", "private key filename")
 		nodeKeyHex  = flag.String("nodekeyhex", "", "private key as hex (for testing)")
-		nodeKey     *ecdsa.PrivateKey
-		err         error
+		natdesc     = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
+
+		nodeKey *ecdsa.PrivateKey
+		err     error
 	)
 	flag.Parse()
 	logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.DebugLevel))
@@ -49,6 +52,10 @@ func main() {
 		os.Exit(0)
 	}
 
+	natm, err := nat.Parse(*natdesc)
+	if err != nil {
+		log.Fatalf("-nat: %v", err)
+	}
 	switch {
 	case *nodeKeyFile == "" && *nodeKeyHex == "":
 		log.Fatal("Use -nodekey or -nodekeyhex to specify a private key")
@@ -64,7 +71,7 @@ func main() {
 		}
 	}
 
-	if _, err := discover.ListenUDP(nodeKey, *listenAddr); err != nil {
+	if _, err := discover.ListenUDP(nodeKey, *listenAddr, natm); err != nil {
 		log.Fatal(err)
 	}
 	select {}

+ 17 - 6
p2p/discover/udp.go

@@ -10,6 +10,7 @@ import (
 
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/logger"
+	"github.com/ethereum/go-ethereum/p2p/nat"
 	"github.com/ethereum/go-ethereum/rlp"
 )
 
@@ -82,6 +83,7 @@ type udp struct {
 	addpending chan *pending
 	replies    chan reply
 	closing    chan struct{}
+	nat        nat.Interface
 
 	*Table
 }
@@ -121,17 +123,26 @@ type reply struct {
 }
 
 // ListenUDP returns a new table that listens for UDP packets on laddr.
-func ListenUDP(priv *ecdsa.PrivateKey, laddr string) (*Table, error) {
-	net, realaddr, err := listen(priv, laddr)
+func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface) (*Table, error) {
+	t, realaddr, err := listen(priv, laddr, natm)
 	if err != nil {
 		return nil, err
 	}
-	net.Table = newTable(net, PubkeyID(&priv.PublicKey), realaddr)
-	log.Debugf("Listening, %v\n", net.self)
-	return net.Table, nil
+	if natm != nil {
+		if !realaddr.IP.IsLoopback() {
+			go nat.Map(natm, t.closing, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
+		}
+		// TODO: react to external IP changes over time.
+		if ext, err := natm.ExternalIP(); err == nil {
+			realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
+		}
+	}
+	t.Table = newTable(t, PubkeyID(&priv.PublicKey), realaddr)
+	log.Infoln("Listening, ", t.self)
+	return t.Table, nil
 }
 
-func listen(priv *ecdsa.PrivateKey, laddr string) (*udp, *net.UDPAddr, error) {
+func listen(priv *ecdsa.PrivateKey, laddr string, nat nat.Interface) (*udp, *net.UDPAddr, error) {
 	addr, err := net.ResolveUDPAddr("udp", laddr)
 	if err != nil {
 		return nil, nil, err

+ 7 - 7
p2p/discover/udp_test.go

@@ -18,8 +18,8 @@ func init() {
 func TestUDP_ping(t *testing.T) {
 	t.Parallel()
 
-	n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
-	n2, _ := ListenUDP(newkey(), "127.0.0.1:0")
+	n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
+	n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
 	defer n1.Close()
 	defer n2.Close()
 
@@ -48,8 +48,8 @@ func find(tab *Table, id NodeID) *Node {
 func TestUDP_findnode(t *testing.T) {
 	t.Parallel()
 
-	n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
-	n2, _ := ListenUDP(newkey(), "127.0.0.1:0")
+	n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
+	n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
 	defer n1.Close()
 	defer n2.Close()
 
@@ -98,7 +98,7 @@ func TestUDP_replytimeout(t *testing.T) {
 	}
 	defer fd.Close()
 
-	n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
+	n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
 	defer n1.Close()
 	n2 := n1.bumpOrAdd(randomID(n1.self.ID, 10), fd.LocalAddr().(*net.UDPAddr))
 
@@ -116,8 +116,8 @@ func TestUDP_replytimeout(t *testing.T) {
 func TestUDP_findnodeMultiReply(t *testing.T) {
 	t.Parallel()
 
-	n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
-	n2, _ := ListenUDP(newkey(), "127.0.0.1:0")
+	n1, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
+	n2, _ := ListenUDP(newkey(), "127.0.0.1:0", nil)
 	udp2 := n2.net.(*udp)
 	defer n1.Close()
 	defer n2.Close()

+ 1 - 2
p2p/server.go

@@ -182,7 +182,7 @@ func (srv *Server) Start() (err error) {
 	}
 
 	// dial stuff
-	dt, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr)
+	dt, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr, srv.NAT)
 	if err != nil {
 		return err
 	}
@@ -194,7 +194,6 @@ func (srv *Server) Start() (err error) {
 		srv.loopWG.Add(1)
 		go srv.dialLoop()
 	}
-
 	if srv.NoDial && srv.ListenAddr == "" {
 		srvlog.Warnln("I will be kind-of useless, neither dialing nor listening.")
 	}