diff --git a/Bootstrap.go b/Bootstrap.go index f69edc2..3ea90f0 100644 --- a/Bootstrap.go +++ b/Bootstrap.go @@ -198,13 +198,13 @@ func contactArbitraryPeer(publicKey *btcec.PublicKey, addresses []*net.UDPAddr) return } - packets, err := msgEncodeAnnouncement(true, true, nil, nil, nil) - if len(packets) == 0 || err != nil { + packets := msgEncodeAnnouncement(true, true, nil, nil, nil) + if len(packets) == 0 || packets[0].err != nil { return } for _, address := range addresses { - sendAllNetworks(publicKey, &PacketRaw{Command: CommandAnnouncement, Payload: packets[0], Sequence: msgArbitrarySequence(publicKey)}, address) + sendAllNetworks(publicKey, &PacketRaw{Command: CommandAnnouncement, Payload: packets[0].raw, Sequence: msgArbitrarySequence(publicKey)}, address) } } diff --git a/Message Encoding.go b/Message Encoding.go index 7d4a8dd..7c424f5 100644 --- a/Message Encoding.go +++ b/Message Encoding.go @@ -453,13 +453,24 @@ func selfFeatureSupport() (feature byte) { return feature } +// 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 uint32 // Sequence number once sent + err error // Sending error, if any +} + // 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 // files is a list of files stored to inform about -func msgEncodeAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore) (packetsRaw [][]byte, err error) { +func msgEncodeAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore) (packets []*announcementPacket) { createPacketLoop: for { + packet := &announcementPacket{} + packets = append(packets, packet) + raw := make([]byte, 64*1024) // max UDP packet size packetSize := announcementPayloadHeaderSize @@ -484,13 +495,15 @@ 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) { - packetsRaw = append(packetsRaw, raw[:packetSize]) + packet.raw = raw[:packetSize] continue createPacketLoop } @@ -501,7 +514,7 @@ createPacketLoop: for n, find := range findPeer { // check if minimum length is available in packet if isPacketSizeExceed(packetSize, 32) { - packetsRaw = append(packetsRaw, raw[:packetSize]) + packet.raw = raw[:packetSize] findPeer = findPeer[n:] continue createPacketLoop } @@ -509,6 +522,8 @@ 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 @@ -518,7 +533,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) { - packetsRaw = append(packetsRaw, raw[:packetSize]) + packet.raw = raw[:packetSize] continue createPacketLoop } @@ -529,7 +544,7 @@ createPacketLoop: for n, find := range findValue { // check if minimum length is available in packet if isPacketSizeExceed(packetSize, 32) { - packetsRaw = append(packetsRaw, raw[:packetSize]) + packet.raw = raw[:packetSize] findValue = findValue[n:] continue createPacketLoop } @@ -537,6 +552,8 @@ 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 @@ -546,7 +563,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) { - packetsRaw = append(packetsRaw, raw[:packetSize]) + packet.raw = raw[:packetSize] continue createPacketLoop } @@ -557,7 +574,7 @@ createPacketLoop: for n, file := range files { // check if minimum length is available in packet if isPacketSizeExceed(packetSize, 41) { - packetsRaw = append(packetsRaw, raw[:packetSize]) + packet.raw = raw[:packetSize] files = files[n:] continue createPacketLoop } @@ -574,7 +591,7 @@ createPacketLoop: files = nil } - packetsRaw = append(packetsRaw, raw[:packetSize]) + packet.raw = raw[:packetSize] if len(findPeer) == 0 && len(findValue) == 0 && len(files) == 0 { return @@ -758,14 +775,15 @@ func (peer *PeerInfo) Chat(text string) { } // sendAnnouncement sends the announcement message -func (peer *PeerInfo) sendAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore) (err error) { - packets, err := msgEncodeAnnouncement(sendUA, findSelf, findPeer, findValue, files) +func (peer *PeerInfo) sendAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore) (packets []*announcementPacket) { + packets = msgEncodeAnnouncement(sendUA, findSelf, findPeer, findValue, files) for _, packet := range packets { - peer.send(&PacketRaw{Command: CommandAnnouncement, Payload: packet, Sequence: peer.msgNewSequence()}) + packet.sequence = peer.msgNewSequence() + packet.err = peer.send(&PacketRaw{Command: CommandAnnouncement, Payload: packet.raw, Sequence: packet.sequence}) } - return err + return } // sendResponse sends the response message diff --git a/Network IPv4 Broadcast.go b/Network IPv4 Broadcast.go index 838cafa..6f6f02b 100644 --- a/Network IPv4 Broadcast.go +++ b/Network IPv4 Broadcast.go @@ -90,12 +90,12 @@ func (network *Network) BroadcastIPv4Listen() { // BroadcastIPv4Send sends out a single broadcast messages to discover peers func (network *Network) BroadcastIPv4Send() (err error) { - packets, err := msgEncodeAnnouncement(true, true, nil, nil, nil) - if len(packets) == 0 || err != nil { - return err + packets := msgEncodeAnnouncement(true, true, nil, nil, nil) + if len(packets) == 0 || packets[0].err != nil { + return packets[0].err } - raw, err := PacketEncrypt(peerPrivateKey, ipv4BroadcastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandLocalDiscovery, Payload: packets[0]}) + raw, err := PacketEncrypt(peerPrivateKey, ipv4BroadcastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandLocalDiscovery, Payload: packets[0].raw}) if err != nil { return err } diff --git a/Network IPv6 Multicast.go b/Network IPv6 Multicast.go index 538ad2b..cdaa360 100644 --- a/Network IPv6 Multicast.go +++ b/Network IPv6 Multicast.go @@ -136,12 +136,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) { - packets, err := msgEncodeAnnouncement(true, true, nil, nil, nil) - if len(packets) == 0 || err != nil { - return err + packets := msgEncodeAnnouncement(true, true, nil, nil, nil) + if len(packets) == 0 || packets[0].err != nil { + return packets[0].err } - raw, err := PacketEncrypt(peerPrivateKey, ipv6MulticastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandLocalDiscovery, Payload: packets[0]}) + raw, err := PacketEncrypt(peerPrivateKey, ipv6MulticastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandLocalDiscovery, Payload: packets[0].raw}) if err != nil { return err }