mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-16 18:37:51 +01:00
Support for feature bits: IPv4_LISTEN and IPv6_LISTEN
Share IPv4/IPv6 peer connections only if supported by the remote peer.
This commit is contained in:
26
Commands.go
26
Commands.go
@@ -10,6 +10,8 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/PeernetOfficial/core/dht"
|
||||
)
|
||||
|
||||
// respondClosesContactsCount is the number of closest contact to respond.
|
||||
@@ -31,19 +33,29 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement) {
|
||||
fmt.Printf("Incoming secondary announcement from %s\n", msg.connection.Address.String())
|
||||
}
|
||||
|
||||
// Filter function to only share peers that are "connectable" to the remote one. It checks IPv4, IPv6, and local connection.
|
||||
filterFunc := func(allowLocal, allowIPv4, allowIPv6 bool) dht.NodeFilterFunc {
|
||||
return func(node *dht.Node) (accept bool) {
|
||||
return node.Info.(*PeerInfo).IsConnectable(allowLocal, allowIPv4, allowIPv6)
|
||||
}
|
||||
}
|
||||
|
||||
allowIPv4 := msg.Features&(1<<FeatureIPv4Listen) > 0
|
||||
allowIPv6 := msg.Features&(1<<FeatureIPv6Listen) > 0
|
||||
|
||||
var hash2Peers []Hash2Peer
|
||||
|
||||
// Requesting peers close to the sender? FIND_SELF
|
||||
// FIND_SELF: Requesting peers close to the sender?
|
||||
if msg.Actions&(1<<ActionFindSelf) > 0 {
|
||||
for _, node := range nodesDHT.GetClosestContacts(respondClosesContactsCount, peer.NodeID, peer.NodeID) {
|
||||
// do not respond the caller's own peer
|
||||
if info := node.Info.(*PeerInfo).peer2Info(msg.connection.IsLocal()); info != nil {
|
||||
// do not respond the caller's own peer (add to ignore list)
|
||||
for _, node := range nodesDHT.GetClosestContacts(respondClosesContactsCount, peer.NodeID, filterFunc(msg.connection.IsLocal(), allowIPv4, allowIPv6), peer.NodeID) {
|
||||
if info := node.Info.(*PeerInfo).peer2Info(msg.connection.IsLocal(), allowIPv4, allowIPv6); info != nil {
|
||||
hash2Peers = append(hash2Peers, Hash2Peer{ID: KeyHash{node.ID}, Closest: []InfoPeer{*info}})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find a different peer?
|
||||
// FIND_PEER: Find a different peer? Note that in this case no IPv4/IPv6 connectivity check is performed.
|
||||
if msg.Actions&(1<<ActionFindPeer) > 0 {
|
||||
// TODO
|
||||
}
|
||||
@@ -62,8 +74,8 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement) {
|
||||
peer.sendResponse(added, hash2Peers, nil, nil)
|
||||
}
|
||||
|
||||
func (peer *PeerInfo) peer2Info(allowLocal bool) (result *InfoPeer) {
|
||||
if connection := peer.GetConnection2Share(allowLocal); connection != nil {
|
||||
func (peer *PeerInfo) peer2Info(allowLocal, allowIPv4, allowIPv6 bool) (result *InfoPeer) {
|
||||
if connection := peer.GetConnection2Share(allowLocal, allowIPv4, allowIPv6); connection != nil {
|
||||
return &InfoPeer{
|
||||
PublicKey: peer.PublicKey,
|
||||
NodeID: peer.NodeID,
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// Version is the current core library version
|
||||
const Version = "0.1"
|
||||
const Version = "0.2"
|
||||
|
||||
var config struct {
|
||||
LogFile string `yaml:"LogFile"` // Log file
|
||||
|
||||
@@ -56,18 +56,36 @@ func (peer *PeerInfo) GetConnections(active bool) (connections []*Connection) {
|
||||
return peer.connectionInactive
|
||||
}
|
||||
|
||||
// GetConnection2Share returns a connection to share. Nil if none.
|
||||
// allowLocal specifies whether it is OK to return local IPs.
|
||||
func (peer *PeerInfo) GetConnection2Share(allowLocal bool) (connections *Connection) {
|
||||
// IsConnectable checks if the peer is connectable to the given IP parameters.
|
||||
func (peer *PeerInfo) IsConnectable(allowLocal, allowIPv4, allowIPv6 bool) bool {
|
||||
peer.RLock()
|
||||
defer peer.RUnlock()
|
||||
|
||||
if peer.connectionLatest != nil && !(!allowLocal && peer.connectionLatest.IsLocal()) {
|
||||
// Only 1 active connection must be allowed for being connectable.
|
||||
for _, connection := range peer.connectionActive {
|
||||
if IsIPv4(connection.Address.IP) && allowIPv4 || IsIPv6(connection.Address.IP) && allowIPv6 {
|
||||
if !(!allowLocal && connection.IsLocal()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// GetConnection2Share returns a connection to share. Nil if none.
|
||||
// allowLocal specifies whether it is OK to return local IPs.
|
||||
func (peer *PeerInfo) GetConnection2Share(allowLocal, allowIPv4, allowIPv6 bool) (connections *Connection) {
|
||||
peer.RLock()
|
||||
defer peer.RUnlock()
|
||||
|
||||
if peer.connectionLatest != nil && !(!allowLocal && peer.connectionLatest.IsLocal()) &&
|
||||
(IsIPv4(peer.connectionLatest.Address.IP) && allowIPv4 || IsIPv6(peer.connectionLatest.Address.IP) && allowIPv6) {
|
||||
return peer.connectionLatest
|
||||
}
|
||||
|
||||
for _, connection := range peer.connectionActive {
|
||||
if !(!allowLocal && connection.IsLocal()) {
|
||||
if (IsIPv4(connection.Address.IP) && allowIPv4 || IsIPv6(connection.Address.IP) && allowIPv6) && !(!allowLocal && connection.IsLocal()) {
|
||||
return connection
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,6 @@ import (
|
||||
// ProtocolVersion is the current protocol version
|
||||
const ProtocolVersion = 0
|
||||
|
||||
// FeatureSupport is for future use
|
||||
var FeatureSupport = 0
|
||||
|
||||
// UserAgent should be set by the caller
|
||||
var UserAgent = "Peernet Core/0.1"
|
||||
|
||||
@@ -53,6 +50,12 @@ const (
|
||||
ActionInfoStore = 3 // INFO_STORE Sender indicates storing provided data
|
||||
)
|
||||
|
||||
// Features are sent as bit array in the Announcement message.
|
||||
const (
|
||||
FeatureIPv4Listen = 0 // Sender listens on IPv4
|
||||
FeatureIPv6Listen = 1 // Sender listens on IPv6
|
||||
)
|
||||
|
||||
// MessageRaw is a high-level message between peers that has not been decoded
|
||||
type MessageRaw struct {
|
||||
PacketRaw
|
||||
@@ -258,8 +261,8 @@ func msgDecodeResponse(msg *MessageRaw) (result *MessageResponse, err error) {
|
||||
return nil, errors.New("response: invalid minimum length")
|
||||
}
|
||||
|
||||
result.Protocol = msg.Payload[0] & 0x0F // Protocol version support is stored in the first 4 bits
|
||||
result.Features = msg.Payload[1] // Feature support
|
||||
result.Protocol = msg.Payload[0] & 0x0F // Protocol version support is stored in the first 4 bits
|
||||
result.Features = decodeFeatureSupport(msg.Payload[1]) // Feature support
|
||||
result.Actions = msg.Payload[2]
|
||||
result.BlockchainHeight = binary.LittleEndian.Uint32(msg.Payload[3:7])
|
||||
result.BlockchainVersion = binary.LittleEndian.Uint64(msg.Payload[7:15])
|
||||
@@ -418,6 +421,15 @@ func decodeEmbeddedFile(data []byte, count int) (filesEmbed []EmbeddedFileData,
|
||||
return filesEmbed, read, true
|
||||
}
|
||||
|
||||
func decodeFeatureSupport(feature byte) byte {
|
||||
// Compatibility with Alpha 1: Set both IPv4/IPv6 bits if none is set.
|
||||
if feature&(1<<FeatureIPv4Listen|1<<FeatureIPv6Listen) == 0 {
|
||||
feature = 1<<FeatureIPv4Listen | 1<<FeatureIPv6Listen
|
||||
}
|
||||
|
||||
return feature
|
||||
}
|
||||
|
||||
// ---- message encoding ----
|
||||
|
||||
const udpMaxPacketSize = 65507
|
||||
@@ -427,6 +439,17 @@ func isPacketSizeExceed(currentSize int, testSize int) bool {
|
||||
return currentSize+testSize > udpMaxPacketSize-packetLengthMin
|
||||
}
|
||||
|
||||
func selfFeatureSupport() (feature byte) {
|
||||
// networksMutex not needed here
|
||||
if len(networks4) > 0 {
|
||||
feature |= 1 << FeatureIPv4Listen
|
||||
}
|
||||
if len(networks6) > 0 {
|
||||
feature |= 1 << FeatureIPv6Listen
|
||||
}
|
||||
return feature
|
||||
}
|
||||
|
||||
// msgEncodeAnnouncement encodes an announcement message. It may return multiple messages if the input does not fit into one.
|
||||
// findPeer is a list of node IDs (blake3 hash of peer ID compressed form)
|
||||
// findValue is a list of hashes
|
||||
@@ -438,7 +461,7 @@ createPacketLoop:
|
||||
packetSize := announcementPayloadHeaderSize
|
||||
|
||||
raw[0] = byte(ProtocolVersion) // Protocol
|
||||
raw[1] = byte(FeatureSupport) // Feature support
|
||||
raw[1] = selfFeatureSupport() // Feature support
|
||||
//raw[2] = Actions // Action bit array
|
||||
binary.LittleEndian.PutUint32(raw[3:7], BlockchainHeight)
|
||||
binary.LittleEndian.PutUint64(raw[7:15], BlockchainVersion)
|
||||
@@ -574,7 +597,7 @@ createPacketLoop:
|
||||
packetSize := announcementPayloadHeaderSize
|
||||
|
||||
raw[0] = byte(ProtocolVersion) // Protocol
|
||||
raw[1] = byte(FeatureSupport) // Feature support
|
||||
raw[1] = selfFeatureSupport() // Feature support
|
||||
//raw[2] = Actions // Action bit array
|
||||
binary.LittleEndian.PutUint32(raw[3:7], BlockchainHeight)
|
||||
binary.LittleEndian.PutUint64(raw[7:15], BlockchainVersion)
|
||||
|
||||
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module github.com/PeernetOfficial/core
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/PeernetOfficial/core/dht v0.0.0-20210316211915-8b329f7258d1
|
||||
github.com/PeernetOfficial/core/dht v0.0.0-20210405124533-d83123bf46c9
|
||||
github.com/PeernetOfficial/core/reuseport v0.0.0-20210316211915-8b329f7258d1
|
||||
github.com/btcsuite/btcd v0.21.0-beta
|
||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1,5 +1,5 @@
|
||||
github.com/PeernetOfficial/core/dht v0.0.0-20210316211915-8b329f7258d1 h1:kbSPQTir7JrBAR7OL6TZIwWsRuqroafeXnFpKXOyEvk=
|
||||
github.com/PeernetOfficial/core/dht v0.0.0-20210316211915-8b329f7258d1/go.mod h1:sb2H21VIVTohCXVrDFo/Skl2tN8Yzba+MXSS6NgCYXw=
|
||||
github.com/PeernetOfficial/core/dht v0.0.0-20210405124533-d83123bf46c9 h1:J3SCdaAy8XnuwgwdqYimNzyt4HFQv+EKCPYbItoky8c=
|
||||
github.com/PeernetOfficial/core/dht v0.0.0-20210405124533-d83123bf46c9/go.mod h1:sb2H21VIVTohCXVrDFo/Skl2tN8Yzba+MXSS6NgCYXw=
|
||||
github.com/PeernetOfficial/core/reuseport v0.0.0-20210316211915-8b329f7258d1 h1:m1dEg5E8ZwT3l/F6xiDrU2Q/ZJ9BeVFAZt/OUBxtr4M=
|
||||
github.com/PeernetOfficial/core/reuseport v0.0.0-20210316211915-8b329f7258d1/go.mod h1:j5lvi5jDpdDyuQrsUkCv4kkibVhPWj87sMol41sXIxc=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
|
||||
Reference in New Issue
Block a user