6f607de5d5
This PR adds enode.LocalNode and integrates it into the p2p subsystem. This new object is the keeper of the local node record. For now, a new version of the record is produced every time the client restarts. We'll make it smarter to avoid that in the future. There are a couple of other changes in this commit: discovery now waits for all of its goroutines at shutdown and the p2p server now closes the node database after discovery has shut down. This fixes a leveldb crash in tests. p2p server startup is faster because it doesn't need to wait for the external IP query anymore.
84 lines
2.7 KiB
Go
84 lines
2.7 KiB
Go
// Copyright 2014 The go-ethereum Authors
|
|
// This file is part of the go-ethereum library.
|
|
//
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package p2p
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
|
)
|
|
|
|
// Protocol represents a P2P subprotocol implementation.
|
|
type Protocol struct {
|
|
// Name should contain the official protocol name,
|
|
// often a three-letter word.
|
|
Name string
|
|
|
|
// Version should contain the version number of the protocol.
|
|
Version uint
|
|
|
|
// Length should contain the number of message codes used
|
|
// by the protocol.
|
|
Length uint64
|
|
|
|
// Run is called in a new goroutine when the protocol has been
|
|
// negotiated with a peer. It should read and write messages from
|
|
// rw. The Payload for each message must be fully consumed.
|
|
//
|
|
// The peer connection is closed when Start returns. It should return
|
|
// any protocol-level error (such as an I/O error) that is
|
|
// encountered.
|
|
Run func(peer *Peer, rw MsgReadWriter) error
|
|
|
|
// NodeInfo is an optional helper method to retrieve protocol specific metadata
|
|
// about the host node.
|
|
NodeInfo func() interface{}
|
|
|
|
// PeerInfo is an optional helper method to retrieve protocol specific metadata
|
|
// about a certain peer in the network. If an info retrieval function is set,
|
|
// but returns nil, it is assumed that the protocol handshake is still running.
|
|
PeerInfo func(id enode.ID) interface{}
|
|
|
|
// Attributes contains protocol specific information for the node record.
|
|
Attributes []enr.Entry
|
|
}
|
|
|
|
func (p Protocol) cap() Cap {
|
|
return Cap{p.Name, p.Version}
|
|
}
|
|
|
|
// Cap is the structure of a peer capability.
|
|
type Cap struct {
|
|
Name string
|
|
Version uint
|
|
}
|
|
|
|
func (cap Cap) String() string {
|
|
return fmt.Sprintf("%s/%d", cap.Name, cap.Version)
|
|
}
|
|
|
|
type capsByNameAndVersion []Cap
|
|
|
|
func (cs capsByNameAndVersion) Len() int { return len(cs) }
|
|
func (cs capsByNameAndVersion) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] }
|
|
func (cs capsByNameAndVersion) Less(i, j int) bool {
|
|
return cs[i].Name < cs[j].Name || (cs[i].Name == cs[j].Name && cs[i].Version < cs[j].Version)
|
|
}
|
|
|
|
func (capsByNameAndVersion) ENRKey() string { return "cap" }
|