Simplify EncodeAnnouncement. Return generic packetsRaw.

Fixes also a theoretical bug in announcement encoding for multicast/broadcast.
This commit is contained in:
Kleissner
2021-10-17 19:30:24 +02:00
parent b51579fb3f
commit 77579a8866
6 changed files with 29 additions and 46 deletions

View File

@@ -208,11 +208,11 @@ func autoMulticastBroadcast() {
func contactArbitraryPeer(publicKey *btcec.PublicKey, address *net.UDPAddr, receiverPortInternal uint16) (contacted bool) {
findSelf := ShouldSendFindSelf()
_, blockchainHeight, blockchainVersion := UserBlockchain.Header()
packets := msgEncodeAnnouncement(true, findSelf, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
if len(packets) == 0 || packets[0].err != nil {
packets := EncodeAnnouncement(true, findSelf, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
if len(packets) == 0 {
return false
}
raw := &protocol.PacketRaw{Command: protocol.CommandAnnouncement, Payload: packets[0].raw}
raw := &protocol.PacketRaw{Command: protocol.CommandAnnouncement, Payload: packets[0]}
Filters.MessageOutAnnouncement(publicKey, nil, raw, findSelf, nil, nil, nil)

View File

@@ -478,24 +478,13 @@ func isPacketSizeExceed(currentSize int, testSize int) bool {
return currentSize+testSize > udpMaxPacketSize-protocol.PacketLengthMin
}
// announcementPacket contains information about a single announcement message
type announcementPacket struct {
raw []byte // The raw packet
hashes [][]byte // List of hashes that are being searched for
sequence *sequenceExpiry // Sequence
err error // Sending error, if any
}
// msgEncodeAnnouncement encodes an announcement message. It may return multiple messages if the input does not fit into one.
// EncodeAnnouncement 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
// files is a list of files stored to inform about
func msgEncodeAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore, features byte, blockchainHeight, blockchainVersion uint64) (packets []*announcementPacket) {
func EncodeAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore, features byte, blockchainHeight, blockchainVersion uint64) (packetsRaw [][]byte) {
createPacketLoop:
for {
packet := &announcementPacket{}
packets = append(packets, packet)
raw := make([]byte, 64*1024) // max UDP packet size
packetSize := announcementPayloadHeaderSize
@@ -521,15 +510,13 @@ createPacketLoop:
// FIND_SELF
if findSelf {
raw[2] |= 1 << ActionFindSelf
packet.hashes = append(packet.hashes, nodeID)
}
// FIND_PEER
if len(findPeer) > 0 {
// check if there is enough space for at least the header and 1 record
if isPacketSizeExceed(packetSize, 2+32) {
packet.raw = raw[:packetSize]
packetsRaw = append(packetsRaw, raw[:packetSize])
continue createPacketLoop
}
@@ -540,7 +527,7 @@ createPacketLoop:
for n, find := range findPeer {
// check if minimum length is available in packet
if isPacketSizeExceed(packetSize, 32) {
packet.raw = raw[:packetSize]
packetsRaw = append(packetsRaw, raw[:packetSize])
findPeer = findPeer[n:]
continue createPacketLoop
}
@@ -548,8 +535,6 @@ createPacketLoop:
binary.LittleEndian.PutUint16(raw[index:index+2], uint16(n+1))
copy(raw[index+2+32*n:index+2+32*n+32], find.Hash)
packetSize += 32
packet.hashes = append(packet.hashes, find.Hash)
}
findPeer = nil
@@ -559,7 +544,7 @@ createPacketLoop:
if len(findValue) > 0 {
// check if there is enough space for at least the header and 1 record
if isPacketSizeExceed(packetSize, 2+32) {
packet.raw = raw[:packetSize]
packetsRaw = append(packetsRaw, raw[:packetSize])
continue createPacketLoop
}
@@ -570,7 +555,7 @@ createPacketLoop:
for n, find := range findValue {
// check if minimum length is available in packet
if isPacketSizeExceed(packetSize, 32) {
packet.raw = raw[:packetSize]
packetsRaw = append(packetsRaw, raw[:packetSize])
findValue = findValue[n:]
continue createPacketLoop
}
@@ -578,8 +563,6 @@ createPacketLoop:
binary.LittleEndian.PutUint16(raw[index:index+2], uint16(n+1))
copy(raw[index+2+32*n:index+2+32*n+32], find.Hash)
packetSize += 32
packet.hashes = append(packet.hashes, find.Hash)
}
findValue = nil
@@ -589,7 +572,7 @@ createPacketLoop:
if len(files) > 0 {
// check if there is enough space for at least the header and 1 record
if isPacketSizeExceed(packetSize, 2+41) {
packet.raw = raw[:packetSize]
packetsRaw = append(packetsRaw, raw[:packetSize])
continue createPacketLoop
}
@@ -600,7 +583,7 @@ createPacketLoop:
for n, file := range files {
// check if minimum length is available in packet
if isPacketSizeExceed(packetSize, 41) {
packet.raw = raw[:packetSize]
packetsRaw = append(packetsRaw, raw[:packetSize])
files = files[n:]
continue createPacketLoop
}
@@ -617,7 +600,7 @@ createPacketLoop:
files = nil
}
packet.raw = raw[:packetSize]
packetsRaw = append(packetsRaw, raw[:packetSize])
if len(findPeer) == 0 && len(findValue) == 0 && len(files) == 0 {
return

View File

@@ -32,18 +32,16 @@ func (peer *PeerInfo) Chat(text string) {
}
// sendAnnouncement sends the announcement message. It acquires a new sequence for each message.
func (peer *PeerInfo) sendAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore, sequenceData interface{}) (packets []*announcementPacket) {
func (peer *PeerInfo) sendAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore, sequenceData interface{}) {
_, blockchainHeight, blockchainVersion := UserBlockchain.Header()
packets = msgEncodeAnnouncement(sendUA, findSelf, findPeer, findValue, files, FeatureSupport(), blockchainHeight, blockchainVersion)
packets := EncodeAnnouncement(sendUA, findSelf, findPeer, findValue, files, FeatureSupport(), blockchainHeight, blockchainVersion)
for _, packet := range packets {
packet.sequence = msgNewSequence(peer.PublicKey, &peer.messageSequence, sequenceData)
raw := &protocol.PacketRaw{Command: protocol.CommandAnnouncement, Payload: packet.raw, Sequence: packet.sequence.sequence}
sequence := msgNewSequence(peer.PublicKey, &peer.messageSequence, sequenceData)
raw := &protocol.PacketRaw{Command: protocol.CommandAnnouncement, Payload: packet, Sequence: sequence.sequence}
Filters.MessageOutAnnouncement(peer.PublicKey, peer, raw, findSelf, findPeer, findValue, files)
packet.err = peer.send(raw)
peer.send(raw)
}
return
}
// sendResponse sends the response message

View File

@@ -10,6 +10,7 @@ package core
import (
"encoding/hex"
"errors"
"net"
"strconv"
"time"
@@ -91,12 +92,12 @@ func (network *Network) BroadcastIPv4Listen() {
// BroadcastIPv4Send sends out a single broadcast messages to discover peers
func (network *Network) BroadcastIPv4Send() (err error) {
_, blockchainHeight, blockchainVersion := UserBlockchain.Header()
packets := msgEncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
if len(packets) == 0 || packets[0].err != nil {
return packets[0].err
packets := EncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
if len(packets) == 0 {
return errors.New("error encoding broadcast announcement")
}
raw, err := protocol.PacketEncrypt(peerPrivateKey, ipv4BroadcastPublicKey, &protocol.PacketRaw{Protocol: ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0].raw})
raw, err := protocol.PacketEncrypt(peerPrivateKey, ipv4BroadcastPublicKey, &protocol.PacketRaw{Protocol: ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0]})
if err != nil {
return err
}

View File

@@ -18,6 +18,7 @@ package core
import (
"encoding/hex"
"errors"
"net"
"strconv"
"time"
@@ -137,12 +138,12 @@ func (network *Network) MulticastIPv6Listen() {
// MulticastIPv6Send sends out a single multicast messages to discover peers at the same site
func (network *Network) MulticastIPv6Send() (err error) {
_, blockchainHeight, blockchainVersion := UserBlockchain.Header()
packets := msgEncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
if len(packets) == 0 || packets[0].err != nil {
return packets[0].err
packets := EncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
if len(packets) == 0 {
return errors.New("error encoding multicast announcement")
}
raw, err := protocol.PacketEncrypt(peerPrivateKey, ipv6MulticastPublicKey, &protocol.PacketRaw{Protocol: ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0].raw})
raw, err := protocol.PacketEncrypt(peerPrivateKey, ipv6MulticastPublicKey, &protocol.PacketRaw{Protocol: ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0]})
if err != nil {
return err
}

View File

@@ -27,10 +27,10 @@ func TestMessageEncodingAnnouncement(t *testing.T) {
findPeer = append(findPeer, KeyHash{Hash: hash1})
findValue = append(findValue, KeyHash{Hash: hash2})
packets := msgEncodeAnnouncement(true, true, findPeer, findValue, files, 1<<FeatureIPv4Listen|1<<FeatureIPv6Listen, 0, 0)
packets := EncodeAnnouncement(true, true, findPeer, findValue, files, 1<<FeatureIPv4Listen|1<<FeatureIPv6Listen, 0, 0)
msg := &MessageRaw{PacketRaw: packetR, SenderPublicKey: publicKey}
msg.Payload = packets[0].raw
msg.Payload = packets[0]
result, err := msgDecodeAnnouncement(msg)
if err != nil {