mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-16 18:37:51 +01:00
Refactor message encoding into protocol package. User Agent must be now provided in the Init function.
This commit is contained in:
22
Bootstrap.go
22
Bootstrap.go
@@ -208,7 +208,7 @@ func (nets *Networks) autoMulticastBroadcast() {
|
||||
func contactArbitraryPeer(publicKey *btcec.PublicKey, address *net.UDPAddr, receiverPortInternal uint16) (contacted bool) {
|
||||
findSelf := ShouldSendFindSelf()
|
||||
_, blockchainHeight, blockchainVersion := UserBlockchain.Header()
|
||||
packets := EncodeAnnouncement(true, findSelf, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
|
||||
packets := protocol.EncodeAnnouncement(true, findSelf, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion, userAgent)
|
||||
if len(packets) == 0 {
|
||||
return false
|
||||
}
|
||||
@@ -230,13 +230,13 @@ type bootstrapFindSelf struct {
|
||||
const bootstrapAcceptContacts = 5
|
||||
|
||||
// cmdResponseBootstrapFindSelf processes FIND_SELF responses
|
||||
func (peer *PeerInfo) cmdResponseBootstrapFindSelf(msg *MessageResponse, closest []PeerRecord) {
|
||||
func (peer *PeerInfo) cmdResponseBootstrapFindSelf(msg *protocol.MessageResponse, closest []protocol.PeerRecord) {
|
||||
if len(closest) > bootstrapAcceptContacts {
|
||||
closest = closest[:bootstrapAcceptContacts]
|
||||
}
|
||||
|
||||
for _, closePeer := range closest {
|
||||
if IsReturnedPeerBadQuality(&closePeer) {
|
||||
if isReturnedPeerBadQuality(&closePeer) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -246,12 +246,12 @@ func (peer *PeerInfo) cmdResponseBootstrapFindSelf(msg *MessageResponse, closest
|
||||
}
|
||||
|
||||
// Check if the reported peer was recently contacted (in connection with the origin peer) for bootstrapping. This makes sure inactive peers are not contacted over and over again.
|
||||
recent, blacklisted := closePeer.IsRecent(peer.NodeID)
|
||||
recent, blacklisted := isReturnedPeerRecent(&closePeer, peer.NodeID)
|
||||
if blacklisted {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, address := range closePeer.ToAddresses() {
|
||||
for _, address := range peerRecordToAddresses(&closePeer) {
|
||||
// Check if the specific IP:Port was already contacted in the last 5-10 minutes.
|
||||
if recent.IsAddressContacted(address) {
|
||||
continue
|
||||
@@ -269,8 +269,8 @@ func ShouldSendFindSelf() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsReturnedPeerBadQuality checks if the returned peer record is bad quality and should be discarded
|
||||
func IsReturnedPeerBadQuality(record *PeerRecord) bool {
|
||||
// isReturnedPeerBadQuality checks if the returned peer record is bad quality and should be discarded
|
||||
func isReturnedPeerBadQuality(record *protocol.PeerRecord) bool {
|
||||
isIPv4 := record.IPv4 != nil && !record.IPv4.IsUnspecified()
|
||||
isIPv6 := record.IPv6 != nil && !record.IPv6.IsUnspecified()
|
||||
|
||||
@@ -294,8 +294,8 @@ func IsReturnedPeerBadQuality(record *PeerRecord) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ToAddresses returns the addresses in a usable way
|
||||
func (record *PeerRecord) ToAddresses() (addresses []*peerAddress) {
|
||||
// peerRecordToAddresses returns the addresses in a usable way
|
||||
func peerRecordToAddresses(record *protocol.PeerRecord) (addresses []*peerAddress) {
|
||||
// IPv4
|
||||
ipv4Port := record.IPv4Port
|
||||
if record.IPv4PortReportedExternal > 0 { // Use the external port if available
|
||||
@@ -352,8 +352,8 @@ func resetRecentContacts() {
|
||||
}
|
||||
}
|
||||
|
||||
// IsRecent checks if the peer is blacklisted related to the origin peer due to recent contact. It will create a "recent contact" if none exists.
|
||||
func (record *PeerRecord) IsRecent(originNodeID []byte) (recent *recentContactInfo, blacklisted bool) {
|
||||
// isReturnedPeerRecent checks if the peer is blacklisted related to the origin peer due to recent contact. It will create a "recent contact" if none exists.
|
||||
func isReturnedPeerRecent(record *protocol.PeerRecord, originNodeID []byte) (recent *recentContactInfo, blacklisted bool) {
|
||||
key := publicKey2Compressed(record.PublicKey)
|
||||
|
||||
recentContactsMutex.Lock()
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
// cmdTraverseForward handles an incoming traverse message that should be forwarded to another peer
|
||||
func (peer *PeerInfo) cmdTraverseForward(msg *MessageTraverse) {
|
||||
func (peer *PeerInfo) cmdTraverseForward(msg *protocol.MessageTraverse) {
|
||||
// Verify the signature. This makes sure that a fowarded message cannot be replayed by others.
|
||||
if !msg.SignerPublicKey.IsEqual(peer.PublicKey) || !msg.SignerPublicKey.IsEqual(msg.SenderPublicKey) {
|
||||
return
|
||||
@@ -35,8 +35,8 @@ func (peer *PeerInfo) cmdTraverseForward(msg *MessageTraverse) {
|
||||
}
|
||||
|
||||
// Get the right IP:Port of the original sender to share to the target peer.
|
||||
allowIPv4 := peerTarget.Features&(1<<FeatureIPv4Listen) > 0
|
||||
allowIPv6 := peerTarget.Features&(1<<FeatureIPv6Listen) > 0
|
||||
allowIPv4 := peerTarget.Features&(1<<protocol.FeatureIPv4Listen) > 0
|
||||
allowIPv6 := peerTarget.Features&(1<<protocol.FeatureIPv6Listen) > 0
|
||||
connectionIPv4 := peer.GetConnection2Share(false, allowIPv4, false)
|
||||
connectionIPv6 := peer.GetConnection2Share(false, false, allowIPv6)
|
||||
|
||||
@@ -58,14 +58,14 @@ func (peer *PeerInfo) cmdTraverseForward(msg *MessageTraverse) {
|
||||
PortIPv6ReportedExternal = connectionIPv6.PortExternal
|
||||
}
|
||||
|
||||
if err := msgEncodeTraverseSetAddress(msg.Payload, IPv4, PortIPv4, PortIPv4ReportedExternal, IPv6, PortIPv6, PortIPv6ReportedExternal); err != nil {
|
||||
if err := protocol.EncodeTraverseSetAddress(msg.Payload, IPv4, PortIPv4, PortIPv4ReportedExternal, IPv6, PortIPv6, PortIPv6ReportedExternal); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
peerTarget.send(&protocol.PacketRaw{Command: protocol.CommandTraverse, Payload: msg.Payload})
|
||||
}
|
||||
|
||||
func (peer *PeerInfo) cmdTraverseReceive(msg *MessageTraverse) {
|
||||
func (peer *PeerInfo) cmdTraverseReceive(msg *protocol.MessageTraverse) {
|
||||
if msg.Expires.Before(time.Now()) {
|
||||
return
|
||||
}
|
||||
@@ -114,13 +114,13 @@ func (peer *PeerInfo) cmdTraverseReceive(msg *MessageTraverse) {
|
||||
}
|
||||
|
||||
// process the packet and create a virtual peer
|
||||
raw := &MessageRaw{SenderPublicKey: senderPublicKey, PacketRaw: *decoded}
|
||||
raw := &protocol.MessageRaw{SenderPublicKey: senderPublicKey, PacketRaw: *decoded}
|
||||
peerV := &PeerInfo{PublicKey: senderPublicKey, connectionActive: nil, connectionLatest: nil, NodeID: protocol.PublicKey2NodeID(senderPublicKey), messageSequence: rand.Uint32(), isVirtual: true, targetAddresses: addresses}
|
||||
|
||||
// process it!
|
||||
switch decoded.Command {
|
||||
case protocol.CommandAnnouncement: // Announce
|
||||
if announce, _ := msgDecodeAnnouncement(raw); announce != nil {
|
||||
if announce, _ := protocol.DecodeAnnouncement(raw); announce != nil {
|
||||
if len(announce.UserAgent) > 0 {
|
||||
peerV.UserAgent = announce.UserAgent
|
||||
}
|
||||
|
||||
48
Commands.go
48
Commands.go
@@ -20,7 +20,7 @@ import (
|
||||
const respondClosesContactsCount = 5
|
||||
|
||||
// cmdAnouncement handles an incoming announcement. Connection may be nil for traverse relayed messages.
|
||||
func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement, connection *Connection) {
|
||||
func (peer *PeerInfo) cmdAnouncement(msg *protocol.MessageAnnouncement, connection *Connection) {
|
||||
// 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) {
|
||||
@@ -28,18 +28,18 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement, connection *Conne
|
||||
}
|
||||
}
|
||||
|
||||
allowIPv4 := msg.Features&(1<<FeatureIPv4Listen) > 0
|
||||
allowIPv6 := msg.Features&(1<<FeatureIPv6Listen) > 0
|
||||
allowIPv4 := msg.Features&(1<<protocol.FeatureIPv4Listen) > 0
|
||||
allowIPv6 := msg.Features&(1<<protocol.FeatureIPv6Listen) > 0
|
||||
|
||||
var hash2Peers []Hash2Peer
|
||||
var hash2Peers []protocol.Hash2Peer
|
||||
var hashesNotFound [][]byte
|
||||
var filesEmbed []EmbeddedFileData
|
||||
var filesEmbed []protocol.EmbeddedFileData
|
||||
|
||||
// FIND_SELF: Requesting peers close to the sender?
|
||||
if msg.Actions&(1<<ActionFindSelf) > 0 {
|
||||
Filters.IncomingRequest(peer, ActionFindSelf, peer.NodeID, nil)
|
||||
if msg.Actions&(1<<protocol.ActionFindSelf) > 0 {
|
||||
Filters.IncomingRequest(peer, protocol.ActionFindSelf, peer.NodeID, nil)
|
||||
|
||||
selfD := Hash2Peer{ID: KeyHash{peer.NodeID}}
|
||||
selfD := protocol.Hash2Peer{ID: protocol.KeyHash{Hash: peer.NodeID}}
|
||||
|
||||
// do not respond the caller's own peer (add to ignore list)
|
||||
for _, node := range nodesDHT.GetClosestContacts(respondClosesContactsCount, peer.NodeID, filterFunc(connection.IsLocal(), allowIPv4, allowIPv6), peer.NodeID) {
|
||||
@@ -56,11 +56,11 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement, connection *Conne
|
||||
}
|
||||
|
||||
// FIND_PEER: Find a different peer?
|
||||
if msg.Actions&(1<<ActionFindPeer) > 0 && len(msg.FindPeerKeys) > 0 {
|
||||
if msg.Actions&(1<<protocol.ActionFindPeer) > 0 && len(msg.FindPeerKeys) > 0 {
|
||||
for _, findPeer := range msg.FindPeerKeys {
|
||||
Filters.IncomingRequest(peer, ActionFindPeer, findPeer.Hash, nil)
|
||||
Filters.IncomingRequest(peer, protocol.ActionFindPeer, findPeer.Hash, nil)
|
||||
|
||||
details := Hash2Peer{ID: findPeer}
|
||||
details := protocol.Hash2Peer{ID: findPeer}
|
||||
|
||||
// Same as before, put self as ignoredNodes.
|
||||
for _, node := range nodesDHT.GetClosestContacts(respondClosesContactsCount, findPeer.Hash, filterFunc(connection.IsLocal(), allowIPv4, allowIPv6), peer.NodeID) {
|
||||
@@ -78,16 +78,16 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement, connection *Conne
|
||||
}
|
||||
|
||||
// Find a value?
|
||||
if msg.Actions&(1<<ActionFindValue) > 0 {
|
||||
if msg.Actions&(1<<protocol.ActionFindValue) > 0 {
|
||||
for _, findHash := range msg.FindDataKeys {
|
||||
Filters.IncomingRequest(peer, ActionFindValue, findHash.Hash, nil)
|
||||
Filters.IncomingRequest(peer, protocol.ActionFindValue, findHash.Hash, nil)
|
||||
|
||||
stored, data := announcementGetData(findHash.Hash)
|
||||
if stored && len(data) > 0 {
|
||||
filesEmbed = append(filesEmbed, EmbeddedFileData{ID: findHash, Data: data})
|
||||
filesEmbed = append(filesEmbed, protocol.EmbeddedFileData{ID: findHash, Data: data})
|
||||
} else if stored {
|
||||
selfRecord := selfPeerRecord()
|
||||
hash2Peers = append(hash2Peers, Hash2Peer{ID: findHash, Storing: []PeerRecord{selfRecord}})
|
||||
hash2Peers = append(hash2Peers, protocol.Hash2Peer{ID: findHash, Storing: []protocol.PeerRecord{selfRecord}})
|
||||
} else {
|
||||
hashesNotFound = append(hashesNotFound, findHash.Hash)
|
||||
}
|
||||
@@ -95,9 +95,9 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement, connection *Conne
|
||||
}
|
||||
|
||||
// Information about files stored by the sender?
|
||||
if msg.Actions&(1<<ActionInfoStore) > 0 && len(msg.InfoStoreFiles) > 0 {
|
||||
if msg.Actions&(1<<protocol.ActionInfoStore) > 0 && len(msg.InfoStoreFiles) > 0 {
|
||||
for n := range msg.InfoStoreFiles {
|
||||
Filters.IncomingRequest(peer, ActionInfoStore, msg.InfoStoreFiles[n].ID.Hash, &msg.InfoStoreFiles[n])
|
||||
Filters.IncomingRequest(peer, protocol.ActionInfoStore, msg.InfoStoreFiles[n].ID.Hash, &msg.InfoStoreFiles[n])
|
||||
}
|
||||
|
||||
peer.announcementStore(msg.InfoStoreFiles)
|
||||
@@ -107,14 +107,14 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement, connection *Conne
|
||||
peer.sendResponse(msg.Sequence, sendUA, hash2Peers, filesEmbed, hashesNotFound)
|
||||
}
|
||||
|
||||
func (peer *PeerInfo) peer2Record(allowLocal, allowIPv4, allowIPv6 bool) (result *PeerRecord) {
|
||||
func (peer *PeerInfo) peer2Record(allowLocal, allowIPv4, allowIPv6 bool) (result *protocol.PeerRecord) {
|
||||
connectionIPv4 := peer.GetConnection2Share(allowLocal, allowIPv4, false)
|
||||
connectionIPv6 := peer.GetConnection2Share(allowLocal, false, allowIPv6)
|
||||
if connectionIPv4 == nil && connectionIPv6 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
result = &PeerRecord{
|
||||
result = &protocol.PeerRecord{
|
||||
PublicKey: peer.PublicKey,
|
||||
NodeID: peer.NodeID,
|
||||
}
|
||||
@@ -137,7 +137,7 @@ func (peer *PeerInfo) peer2Record(allowLocal, allowIPv4, allowIPv6 bool) (result
|
||||
}
|
||||
|
||||
// cmdResponse handles the response to the announcement
|
||||
func (peer *PeerInfo) cmdResponse(msg *MessageResponse, connection *Connection) {
|
||||
func (peer *PeerInfo) cmdResponse(msg *protocol.MessageResponse, connection *Connection) {
|
||||
// The sequence data is used to correlate this response with the announcement.
|
||||
if msg.SequenceInfo == nil || msg.SequenceInfo.Data == nil {
|
||||
// If there is no sequence data but there were results returned, it means we received unsolicited response data. It will be rejected.
|
||||
@@ -191,7 +191,7 @@ func (peer *PeerInfo) cmdResponse(msg *MessageResponse, connection *Connection)
|
||||
}
|
||||
|
||||
// cmdPing handles an incoming ping message
|
||||
func (peer *PeerInfo) cmdPing(msg *MessageRaw, connection *Connection) {
|
||||
func (peer *PeerInfo) cmdPing(msg *protocol.MessageRaw, connection *Connection) {
|
||||
// If PortInternal is 0, it means no incoming announcement or response message was received on that connection.
|
||||
// This means the ping is unexpected. In that case for security reasons the remote peer is not asked for FIND_SELF.
|
||||
if connection.PortInternal == 0 {
|
||||
@@ -207,16 +207,16 @@ func (peer *PeerInfo) cmdPing(msg *MessageRaw, connection *Connection) {
|
||||
}
|
||||
|
||||
// cmdPong handles an incoming pong message
|
||||
func (peer *PeerInfo) cmdPong(msg *MessageRaw, connection *Connection) {
|
||||
func (peer *PeerInfo) cmdPong(msg *protocol.MessageRaw, connection *Connection) {
|
||||
}
|
||||
|
||||
// cmdChat handles a chat message [debug]
|
||||
func (peer *PeerInfo) cmdChat(msg *MessageRaw, connection *Connection) {
|
||||
func (peer *PeerInfo) cmdChat(msg *protocol.MessageRaw, connection *Connection) {
|
||||
fmt.Printf("Chat from '%s': %s\n", connection.Address.String(), string(msg.PacketRaw.Payload))
|
||||
}
|
||||
|
||||
// cmdLocalDiscovery handles an incoming announcement via local discovery
|
||||
func (peer *PeerInfo) cmdLocalDiscovery(msg *MessageAnnouncement, connection *Connection) {
|
||||
func (peer *PeerInfo) cmdLocalDiscovery(msg *protocol.MessageAnnouncement, connection *Connection) {
|
||||
// 21.04.2021 update: Local peer discovery from public IPv4s is possible in datacenter situations. Keep it enabled for now.
|
||||
// only accept local discovery message from private IPs for IPv4
|
||||
// IPv6 DHCP routers typically assign public IPv6s and they can join multicast in the local network.
|
||||
|
||||
@@ -325,7 +325,7 @@ func (c *Connection) send(packet *protocol.PacketRaw, receiverPublicKey *btcec.P
|
||||
return errors.New("invalid connection")
|
||||
}
|
||||
|
||||
packet.Protocol = ProtocolVersion
|
||||
packet.Protocol = protocol.ProtocolVersion
|
||||
packet.SetSelfReportedPorts(c.Network.SelfReportedPorts())
|
||||
|
||||
Filters.PacketOut(packet, receiverPublicKey, c)
|
||||
|
||||
12
Filter.go
12
Filter.go
@@ -45,14 +45,14 @@ var Filters struct {
|
||||
PacketOut func(packet *protocol.PacketRaw, receiverPublicKey *btcec.PublicKey, connection *Connection)
|
||||
|
||||
// MessageIn is a high-level filter for decoded incoming messages. message is of type nil, MessageAnnouncement, MessageResponse, or MessageTraverse
|
||||
MessageIn func(peer *PeerInfo, raw *MessageRaw, message interface{})
|
||||
MessageIn func(peer *PeerInfo, raw *protocol.MessageRaw, message interface{})
|
||||
|
||||
// MessageOutAnnouncement is a high-level filter for outgoing announcements. Peer is nil on first contact.
|
||||
// Broadcast and Multicast messages are not covered.
|
||||
MessageOutAnnouncement func(receiverPublicKey *btcec.PublicKey, peer *PeerInfo, packet *protocol.PacketRaw, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore)
|
||||
MessageOutAnnouncement func(receiverPublicKey *btcec.PublicKey, peer *PeerInfo, packet *protocol.PacketRaw, findSelf bool, findPeer []protocol.KeyHash, findValue []protocol.KeyHash, files []protocol.InfoStore)
|
||||
|
||||
// MessageOutResponse is a high-level filter for outgoing responses.
|
||||
MessageOutResponse func(peer *PeerInfo, packet *protocol.PacketRaw, hash2Peers []Hash2Peer, filesEmbed []EmbeddedFileData, hashesNotFound [][]byte)
|
||||
MessageOutResponse func(peer *PeerInfo, packet *protocol.PacketRaw, hash2Peers []protocol.Hash2Peer, filesEmbed []protocol.EmbeddedFileData, hashesNotFound [][]byte)
|
||||
|
||||
// MessageOutTraverse is a high-level filter for outgoing traverse messages.
|
||||
MessageOutTraverse func(peer *PeerInfo, packet *protocol.PacketRaw, embeddedPacket *protocol.PacketRaw, receiverEnd *btcec.PublicKey)
|
||||
@@ -90,14 +90,14 @@ func initFilters() {
|
||||
Filters.PacketOut = func(packet *protocol.PacketRaw, receiverPublicKey *btcec.PublicKey, c *Connection) {}
|
||||
}
|
||||
if Filters.MessageIn == nil {
|
||||
Filters.MessageIn = func(peer *PeerInfo, raw *MessageRaw, message interface{}) {}
|
||||
Filters.MessageIn = func(peer *PeerInfo, raw *protocol.MessageRaw, message interface{}) {}
|
||||
}
|
||||
if Filters.MessageOutAnnouncement == nil {
|
||||
Filters.MessageOutAnnouncement = func(receiverPublicKey *btcec.PublicKey, peer *PeerInfo, packet *protocol.PacketRaw, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore) {
|
||||
Filters.MessageOutAnnouncement = func(receiverPublicKey *btcec.PublicKey, peer *PeerInfo, packet *protocol.PacketRaw, findSelf bool, findPeer []protocol.KeyHash, findValue []protocol.KeyHash, files []protocol.InfoStore) {
|
||||
}
|
||||
}
|
||||
if Filters.MessageOutResponse == nil {
|
||||
Filters.MessageOutResponse = func(peer *PeerInfo, packet *protocol.PacketRaw, hash2Peers []Hash2Peer, filesEmbed []EmbeddedFileData, hashesNotFound [][]byte) {
|
||||
Filters.MessageOutResponse = func(peer *PeerInfo, packet *protocol.PacketRaw, hash2Peers []protocol.Hash2Peer, filesEmbed []protocol.EmbeddedFileData, hashesNotFound [][]byte) {
|
||||
}
|
||||
}
|
||||
if Filters.MessageOutTraverse == nil {
|
||||
|
||||
10
Kademlia.go
10
Kademlia.go
@@ -105,23 +105,23 @@ func (peer *PeerInfo) sendAnnouncementFindNode(request *dht.InformationRequest)
|
||||
if bytes.Equal(request.Key, nodeID) {
|
||||
peer.sendAnnouncement(false, true, nil, nil, nil, request)
|
||||
} else {
|
||||
peer.sendAnnouncement(false, false, []KeyHash{{Hash: request.Key}}, nil, nil, request)
|
||||
peer.sendAnnouncement(false, false, []protocol.KeyHash{{Hash: request.Key}}, nil, nil, request)
|
||||
}
|
||||
}
|
||||
|
||||
func (peer *PeerInfo) sendAnnouncementFindValue(request *dht.InformationRequest) {
|
||||
|
||||
findSelf := false
|
||||
var findPeer []KeyHash
|
||||
var findValue []KeyHash
|
||||
var findPeer []protocol.KeyHash
|
||||
var findValue []protocol.KeyHash
|
||||
|
||||
findValue = append(findValue, KeyHash{Hash: request.Key})
|
||||
findValue = append(findValue, protocol.KeyHash{Hash: request.Key})
|
||||
|
||||
peer.sendAnnouncement(false, findSelf, findPeer, findValue, nil, request)
|
||||
}
|
||||
|
||||
func (peer *PeerInfo) sendAnnouncementStore(fileHash []byte, fileSize uint64) {
|
||||
peer.sendAnnouncement(false, false, nil, nil, []InfoStore{{ID: KeyHash{Hash: fileHash}, Size: fileSize, Type: 0}}, nil)
|
||||
peer.sendAnnouncement(false, false, nil, nil, []protocol.InfoStore{{ID: protocol.KeyHash{Hash: fileHash}, Size: fileSize, Type: 0}}, nil)
|
||||
}
|
||||
|
||||
// ---- CORE DATA FUNCTIONS ----
|
||||
|
||||
@@ -32,9 +32,9 @@ 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{}) {
|
||||
func (peer *PeerInfo) sendAnnouncement(sendUA, findSelf bool, findPeer []protocol.KeyHash, findValue []protocol.KeyHash, files []protocol.InfoStore, sequenceData interface{}) {
|
||||
_, blockchainHeight, blockchainVersion := UserBlockchain.Header()
|
||||
packets := EncodeAnnouncement(sendUA, findSelf, findPeer, findValue, files, FeatureSupport(), blockchainHeight, blockchainVersion)
|
||||
packets := protocol.EncodeAnnouncement(sendUA, findSelf, findPeer, findValue, files, FeatureSupport(), blockchainHeight, blockchainVersion, userAgent)
|
||||
|
||||
for _, packet := range packets {
|
||||
raw := &protocol.PacketRaw{Command: protocol.CommandAnnouncement, Payload: packet, Sequence: networks.Sequences.NewSequence(peer.PublicKey, &peer.messageSequence, sequenceData).SequenceNumber}
|
||||
@@ -44,9 +44,9 @@ func (peer *PeerInfo) sendAnnouncement(sendUA, findSelf bool, findPeer []KeyHash
|
||||
}
|
||||
|
||||
// sendResponse sends the response message
|
||||
func (peer *PeerInfo) sendResponse(sequence uint32, sendUA bool, hash2Peers []Hash2Peer, filesEmbed []EmbeddedFileData, hashesNotFound [][]byte) (err error) {
|
||||
func (peer *PeerInfo) sendResponse(sequence uint32, sendUA bool, hash2Peers []protocol.Hash2Peer, filesEmbed []protocol.EmbeddedFileData, hashesNotFound [][]byte) (err error) {
|
||||
_, blockchainHeight, blockchainVersion := UserBlockchain.Header()
|
||||
packets, err := msgEncodeResponse(sendUA, hash2Peers, filesEmbed, hashesNotFound, FeatureSupport(), blockchainHeight, blockchainVersion)
|
||||
packets, err := protocol.EncodeResponse(sendUA, hash2Peers, filesEmbed, hashesNotFound, FeatureSupport(), blockchainHeight, blockchainVersion, userAgent)
|
||||
|
||||
for _, packet := range packets {
|
||||
raw := &protocol.PacketRaw{Command: protocol.CommandResponse, Payload: packet, Sequence: sequence}
|
||||
@@ -59,7 +59,7 @@ func (peer *PeerInfo) sendResponse(sequence uint32, sendUA bool, hash2Peers []Ha
|
||||
|
||||
// sendTraverse sends a traverse message
|
||||
func (peer *PeerInfo) sendTraverse(packet *protocol.PacketRaw, receiverEnd *btcec.PublicKey) (err error) {
|
||||
packet.Protocol = ProtocolVersion
|
||||
packet.Protocol = protocol.ProtocolVersion
|
||||
// self-reported ports are not set, as this isn't sent via a specific network but a relay
|
||||
//packet.SetSelfReportedPorts(c.Network.SelfReportedPorts())
|
||||
|
||||
@@ -68,7 +68,7 @@ func (peer *PeerInfo) sendTraverse(packet *protocol.PacketRaw, receiverEnd *btce
|
||||
return err
|
||||
}
|
||||
|
||||
packetRaw, err := msgEncodeTraverse(peerPrivateKey, embeddedPacketRaw, receiverEnd, peer.PublicKey)
|
||||
packetRaw, err := protocol.EncodeTraverse(peerPrivateKey, embeddedPacketRaw, receiverEnd, peer.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -92,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 := EncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
|
||||
packets := protocol.EncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion, userAgent)
|
||||
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, err := protocol.PacketEncrypt(peerPrivateKey, ipv4BroadcastPublicKey, &protocol.PacketRaw{Protocol: protocol.ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -138,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 := EncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion)
|
||||
packets := protocol.EncodeAnnouncement(true, true, nil, nil, nil, FeatureSupport(), blockchainHeight, blockchainVersion, userAgent)
|
||||
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, err := protocol.PacketEncrypt(peerPrivateKey, ipv6MulticastPublicKey, &protocol.PacketRaw{Protocol: protocol.ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
16
Network.go
16
Network.go
@@ -163,11 +163,11 @@ func (nets *Networks) packetWorker() {
|
||||
connection.LastPacketIn = time.Now()
|
||||
|
||||
// process the packet
|
||||
raw := &MessageRaw{SenderPublicKey: senderPublicKey, PacketRaw: *decoded}
|
||||
raw := &protocol.MessageRaw{SenderPublicKey: senderPublicKey, PacketRaw: *decoded}
|
||||
|
||||
switch decoded.Command {
|
||||
case protocol.CommandAnnouncement: // Announce
|
||||
if announce, _ := msgDecodeAnnouncement(raw); announce != nil {
|
||||
if announce, _ := protocol.DecodeAnnouncement(raw); announce != nil {
|
||||
// Update known internal/external port and User Agent
|
||||
connection.PortInternal = announce.PortInternal
|
||||
connection.PortExternal = announce.PortExternal
|
||||
@@ -184,9 +184,9 @@ func (nets *Networks) packetWorker() {
|
||||
}
|
||||
|
||||
case protocol.CommandResponse: // Response
|
||||
if response, _ := msgDecodeResponse(raw); response != nil {
|
||||
if response, _ := protocol.DecodeResponse(raw); response != nil {
|
||||
// Validate sequence number which prevents unsolicited responses.
|
||||
sequenceInfo, valid, rtt := nets.Sequences.ValidateSequence(raw.SenderPublicKey, raw.Sequence, response.Actions&(1<<ActionSequenceLast) > 0, true)
|
||||
sequenceInfo, valid, rtt := nets.Sequences.ValidateSequence(raw.SenderPublicKey, raw.Sequence, response.Actions&(1<<protocol.ActionSequenceLast) > 0, true)
|
||||
if !valid {
|
||||
//Filters.LogError("packetWorker", "message with invalid sequence %d command %d from %s\n", raw.Sequence, raw.Command, raw.connection.Address.String()) // Only log for debug purposes.
|
||||
continue
|
||||
@@ -211,7 +211,7 @@ func (nets *Networks) packetWorker() {
|
||||
}
|
||||
|
||||
case protocol.CommandLocalDiscovery: // Local discovery, sent via IPv4 broadcast and IPv6 multicast
|
||||
if announce, _ := msgDecodeAnnouncement(raw); announce != nil {
|
||||
if announce, _ := protocol.DecodeAnnouncement(raw); announce != nil {
|
||||
if len(announce.UserAgent) > 0 {
|
||||
peer.UserAgent = announce.UserAgent
|
||||
}
|
||||
@@ -248,7 +248,7 @@ func (nets *Networks) packetWorker() {
|
||||
peer.cmdChat(raw, connection)
|
||||
|
||||
case protocol.CommandTraverse:
|
||||
if traverse, _ := msgDecodeTraverse(raw); traverse != nil {
|
||||
if traverse, _ := protocol.DecodeTraverse(raw); traverse != nil {
|
||||
Filters.MessageIn(peer, raw, traverse)
|
||||
if traverse.TargetPeer.IsEqual(peerPublicKey) && traverse.AuthorizedRelayPeer.IsEqual(peer.PublicKey) {
|
||||
peer.cmdTraverseReceive(traverse)
|
||||
@@ -337,10 +337,10 @@ func (network *Network) SelfReportedPorts() (portI, portE uint16) {
|
||||
// FeatureSupport returns supported features by this peer
|
||||
func FeatureSupport() (feature byte) {
|
||||
if networks.countListen4 > 0 {
|
||||
feature |= 1 << FeatureIPv4Listen
|
||||
feature |= 1 << protocol.FeatureIPv4Listen
|
||||
}
|
||||
if networks.countListen6 > 0 {
|
||||
feature |= 1 << FeatureIPv6Listen
|
||||
feature |= 1 << protocol.FeatureIPv6Listen
|
||||
}
|
||||
return feature
|
||||
}
|
||||
|
||||
18
Peer ID.go
18
Peer ID.go
@@ -79,6 +79,11 @@ func SelfNodeID() []byte {
|
||||
return nodeID
|
||||
}
|
||||
|
||||
// SelfUserAgent returns the User Agent
|
||||
func SelfUserAgent() string {
|
||||
return userAgent
|
||||
}
|
||||
|
||||
// PeerInfo stores information about a single remote peer
|
||||
type PeerInfo struct {
|
||||
PublicKey *btcec.PublicKey // Public key
|
||||
@@ -179,8 +184,7 @@ func PeerlistLookup(publicKey *btcec.PublicKey) (peer *PeerInfo) {
|
||||
peerlistMutex.RLock()
|
||||
defer peerlistMutex.RUnlock()
|
||||
|
||||
peer, _ = peerList[publicKey2Compressed(publicKey)]
|
||||
return peer
|
||||
return peerList[publicKey2Compressed(publicKey)]
|
||||
}
|
||||
|
||||
// PeerlistCount returns the current count of peers in the peer list
|
||||
@@ -199,9 +203,9 @@ func publicKey2Compressed(publicKey *btcec.PublicKey) [btcec.PubKeyBytesLenCompr
|
||||
|
||||
// records2Nodes translates infoPeer structures to nodes. If the reported nodes are not in the peer table, it will create temporary PeerInfo structures.
|
||||
// LastContact is passed on in the Node.LastSeen field.
|
||||
func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Node) {
|
||||
func records2Nodes(records []protocol.PeerRecord, peerSource *PeerInfo) (nodes []*dht.Node) {
|
||||
for _, record := range records {
|
||||
if IsReturnedPeerBadQuality(&record) {
|
||||
if isReturnedPeerBadQuality(&record) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -212,7 +216,7 @@ func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Nod
|
||||
} else if peer = PeerlistLookup(record.PublicKey); peer == nil {
|
||||
// Create temporary peer which is not added to the global list and not added to Kademlia.
|
||||
// traversePeer is set to the peer who provided the node information.
|
||||
addresses := record.ToAddresses()
|
||||
addresses := peerRecordToAddresses(&record)
|
||||
if len(addresses) == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -227,8 +231,8 @@ func records2Nodes(records []PeerRecord, peerSource *PeerInfo) (nodes []*dht.Nod
|
||||
}
|
||||
|
||||
// selfPeerRecord returns self as peer record
|
||||
func selfPeerRecord() (result PeerRecord) {
|
||||
return PeerRecord{
|
||||
func selfPeerRecord() (result protocol.PeerRecord) {
|
||||
return protocol.PeerRecord{
|
||||
PublicKey: peerPublicKey,
|
||||
NodeID: nodeID,
|
||||
//IP: network.address.IP,
|
||||
|
||||
@@ -6,8 +6,15 @@ Author: Peter Kleissner
|
||||
|
||||
package core
|
||||
|
||||
var userAgent = "Peernet Core/0.1" // must be overwritten by the caller
|
||||
|
||||
// Init initializes the client. The config must be loaded first!
|
||||
func Init() {
|
||||
// The User Agent must be provided in the form "Application Name/1.0".
|
||||
func Init(UserAgent string) {
|
||||
if userAgent = UserAgent; userAgent == "" {
|
||||
return
|
||||
}
|
||||
|
||||
initFilters()
|
||||
initPeerID()
|
||||
initUserBlockchain()
|
||||
|
||||
5
Store.go
5
Store.go
@@ -7,6 +7,7 @@ Author: Peter Kleissner
|
||||
package core
|
||||
|
||||
import (
|
||||
"github.com/PeernetOfficial/core/protocol"
|
||||
"github.com/PeernetOfficial/core/store"
|
||||
)
|
||||
|
||||
@@ -27,7 +28,7 @@ func announcementGetData(hash []byte) (stored bool, data []byte) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if len(data) <= EmbeddedFileSizeMax {
|
||||
if len(data) <= protocol.EmbeddedFileSizeMax {
|
||||
return true, data
|
||||
}
|
||||
|
||||
@@ -35,7 +36,7 @@ func announcementGetData(hash []byte) (stored bool, data []byte) {
|
||||
}
|
||||
|
||||
// announcementStore handles an incoming announcement by another peer about storing data
|
||||
func (peer *PeerInfo) announcementStore(records []InfoStore) {
|
||||
func (peer *PeerInfo) announcementStore(records []protocol.InfoStore) {
|
||||
// TODO: Only store the other peers data if certain conditions are met:
|
||||
// - enough storage available
|
||||
// - not exceeding record count per peer
|
||||
|
||||
@@ -6,7 +6,7 @@ Author: Peter Kleissner
|
||||
Intermediary between low-level packets and high-level interpretation.
|
||||
*/
|
||||
|
||||
package core
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -16,16 +16,12 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/PeernetOfficial/core/protocol"
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
// ProtocolVersion is the current protocol version
|
||||
const ProtocolVersion = 0
|
||||
|
||||
// UserAgent should be set by the caller
|
||||
var UserAgent = "Peernet Core/0.1"
|
||||
|
||||
// Actions between peers, sent via Announcement message. They correspond to the bit array index.
|
||||
const (
|
||||
ActionFindSelf = 0 // FIND_SELF Request closest neighbors to self
|
||||
@@ -47,9 +43,9 @@ const (
|
||||
|
||||
// MessageRaw is a high-level message between peers that has not been decoded
|
||||
type MessageRaw struct {
|
||||
protocol.PacketRaw
|
||||
SenderPublicKey *btcec.PublicKey // Sender Public Key, ECDSA (secp256k1) 257-bit
|
||||
SequenceInfo *protocol.SequenceExpiry // Sequence
|
||||
PacketRaw
|
||||
SenderPublicKey *btcec.PublicKey // Sender Public Key, ECDSA (secp256k1) 257-bit
|
||||
SequenceInfo *SequenceExpiry // Sequence
|
||||
}
|
||||
|
||||
// MessageAnnouncement is the decoded announcement message.
|
||||
@@ -68,9 +64,6 @@ type MessageAnnouncement struct {
|
||||
InfoStoreFiles []InfoStore // INFO_STORE data
|
||||
}
|
||||
|
||||
// blake3 digest size in bytes
|
||||
const hashSize = 32
|
||||
|
||||
// KeyHash is a single blake3 key hash
|
||||
type KeyHash struct {
|
||||
Hash []byte
|
||||
@@ -151,8 +144,8 @@ type MessageTraverse struct {
|
||||
// Minimum length of Announcement payload header without User Agent
|
||||
const announcementPayloadHeaderSize = 20
|
||||
|
||||
// msgDecodeAnnouncement decodes the incoming announcement message. Returns nil if invalid.
|
||||
func msgDecodeAnnouncement(msg *MessageRaw) (result *MessageAnnouncement, err error) {
|
||||
// DecodeAnnouncement decodes the incoming announcement message. Returns nil if invalid.
|
||||
func DecodeAnnouncement(msg *MessageRaw) (result *MessageAnnouncement, err error) {
|
||||
result = &MessageAnnouncement{
|
||||
MessageRaw: msg,
|
||||
}
|
||||
@@ -228,19 +221,19 @@ func msgDecodeAnnouncement(msg *MessageRaw) (result *MessageAnnouncement, err er
|
||||
|
||||
// decodeKeys decodes keys. Header is 2 bytes (count) followed by the actual keys (each 32 bytes blake3 hash).
|
||||
func decodeKeys(data []byte) (keys []KeyHash, read int, valid bool) {
|
||||
if len(data) < 2+hashSize { // minimum length
|
||||
if len(data) < 2+HashSize { // minimum length
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
count := binary.LittleEndian.Uint16(data[0:2])
|
||||
|
||||
if read = 2 + int(count)*hashSize; len(data) < read {
|
||||
if read = 2 + int(count)*HashSize; len(data) < read {
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
for n := 0; n < int(count); n++ {
|
||||
key := make([]byte, hashSize)
|
||||
copy(key, data[2+n*hashSize:2+n*hashSize+hashSize])
|
||||
key := make([]byte, HashSize)
|
||||
copy(key, data[2+n*HashSize:2+n*HashSize+HashSize])
|
||||
keys = append(keys, KeyHash{Hash: key})
|
||||
}
|
||||
|
||||
@@ -260,8 +253,8 @@ func decodeInfoStore(data []byte) (files []InfoStore, read int, valid bool) {
|
||||
|
||||
for n := 0; n < int(count); n++ {
|
||||
file := InfoStore{}
|
||||
file.ID.Hash = make([]byte, hashSize)
|
||||
copy(file.ID.Hash, data[2+n*41:2+n*41+hashSize])
|
||||
file.ID.Hash = make([]byte, HashSize)
|
||||
copy(file.ID.Hash, data[2+n*41:2+n*41+HashSize])
|
||||
file.Size = binary.LittleEndian.Uint64(data[2+n*41+32 : 2+n*41+32+8])
|
||||
file.Type = data[2+n*41+40]
|
||||
|
||||
@@ -271,8 +264,8 @@ func decodeInfoStore(data []byte) (files []InfoStore, read int, valid bool) {
|
||||
return files, read, true
|
||||
}
|
||||
|
||||
// msgDecodeResponse decodes the incoming response message. Returns nil if invalid.
|
||||
func msgDecodeResponse(msg *MessageRaw) (result *MessageResponse, err error) {
|
||||
// DecodeResponse decodes the incoming response message. Returns nil if invalid.
|
||||
func DecodeResponse(msg *MessageRaw) (result *MessageResponse, err error) {
|
||||
result = &MessageResponse{
|
||||
MessageRaw: msg,
|
||||
}
|
||||
@@ -346,7 +339,7 @@ func msgDecodeResponse(msg *MessageRaw) (result *MessageResponse, err error) {
|
||||
}
|
||||
|
||||
for n := 0; n < int(countHashesNotFound); n++ {
|
||||
hash := make([]byte, hashSize)
|
||||
hash := make([]byte, HashSize)
|
||||
copy(hash, data[n*32:n*32+32])
|
||||
|
||||
result.HashesNotFound = append(result.HashesNotFound, hash)
|
||||
@@ -368,7 +361,7 @@ func decodePeerRecord(data []byte, count int) (hash2Peers []Hash2Peer, read int,
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
hash := make([]byte, hashSize)
|
||||
hash := make([]byte, HashSize)
|
||||
copy(hash, data[index:index+32])
|
||||
countField := binary.LittleEndian.Uint16(data[index+32:index+32+2]) & 0x7FFF
|
||||
isLast := binary.LittleEndian.Uint16(data[index+32:index+32+2])&0x8000 > 0
|
||||
@@ -418,7 +411,7 @@ func decodePeerRecord(data []byte, count int) (hash2Peers []Hash2Peer, read int,
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
peer.NodeID = protocol.PublicKey2NodeID(peer.PublicKey)
|
||||
peer.NodeID = PublicKey2NodeID(peer.PublicKey)
|
||||
|
||||
if reason == 0 { // Peer was returned because it is close to the requested hash
|
||||
hash2Peer.Closest = append(hash2Peer.Closest, peer)
|
||||
@@ -444,7 +437,7 @@ func decodeEmbeddedFile(data []byte, count int) (filesEmbed []EmbeddedFileData,
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
hash := make([]byte, hashSize)
|
||||
hash := make([]byte, HashSize)
|
||||
copy(hash, data[index:index+32])
|
||||
sizeField := int(binary.LittleEndian.Uint16(data[index+32 : index+32+2]))
|
||||
index += 34
|
||||
@@ -459,7 +452,7 @@ func decodeEmbeddedFile(data []byte, count int) (filesEmbed []EmbeddedFileData,
|
||||
index += sizeField
|
||||
|
||||
// validate the hash
|
||||
if !bytes.Equal(hash, protocol.HashData(fileData)) {
|
||||
if !bytes.Equal(hash, HashData(fileData)) {
|
||||
return nil, read, false
|
||||
}
|
||||
|
||||
@@ -475,14 +468,14 @@ const udpMaxPacketSize = 65507
|
||||
|
||||
// isPacketSizeExceed checks if the max packet size would be exceeded with the payload
|
||||
func isPacketSizeExceed(currentSize int, testSize int) bool {
|
||||
return currentSize+testSize > udpMaxPacketSize-protocol.PacketLengthMin
|
||||
return currentSize+testSize > udpMaxPacketSize-PacketLengthMin
|
||||
}
|
||||
|
||||
// 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 EncodeAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore, features byte, blockchainHeight, blockchainVersion uint64) (packetsRaw [][]byte) {
|
||||
func EncodeAnnouncement(sendUA, findSelf bool, findPeer []KeyHash, findValue []KeyHash, files []InfoStore, features byte, blockchainHeight, blockchainVersion uint64, userAgent string) (packetsRaw [][]byte) {
|
||||
createPacketLoop:
|
||||
for {
|
||||
raw := make([]byte, 64*1024) // max UDP packet size
|
||||
@@ -497,7 +490,7 @@ createPacketLoop:
|
||||
|
||||
// only on initial announcement the User Agent must be provided according to the protocol spec
|
||||
if sendUA {
|
||||
userAgentB := []byte(UserAgent)
|
||||
userAgentB := []byte(userAgent)
|
||||
if len(userAgentB) > 255 {
|
||||
userAgentB = userAgentB[:255]
|
||||
}
|
||||
@@ -609,11 +602,11 @@ createPacketLoop:
|
||||
}
|
||||
|
||||
// EmbeddedFileSizeMax is the maximum size of embedded files in response messages. Any file exceeding that must be shared via regular file transfer.
|
||||
const EmbeddedFileSizeMax = udpMaxPacketSize - protocol.PacketLengthMin - announcementPayloadHeaderSize - 2 - 35
|
||||
const EmbeddedFileSizeMax = udpMaxPacketSize - PacketLengthMin - announcementPayloadHeaderSize - 2 - 35
|
||||
|
||||
// msgEncodeResponse encodes a response message
|
||||
// EncodeResponse encodes a response message
|
||||
// hash2Peers will be modified.
|
||||
func msgEncodeResponse(sendUA bool, hash2Peers []Hash2Peer, filesEmbed []EmbeddedFileData, hashesNotFound [][]byte, features byte, blockchainHeight, blockchainVersion uint64) (packetsRaw [][]byte, err error) {
|
||||
func EncodeResponse(sendUA bool, hash2Peers []Hash2Peer, filesEmbed []EmbeddedFileData, hashesNotFound [][]byte, features byte, blockchainHeight, blockchainVersion uint64, userAgent string) (packetsRaw [][]byte, err error) {
|
||||
for n := range filesEmbed {
|
||||
if len(filesEmbed[n].Data) > EmbeddedFileSizeMax {
|
||||
return nil, errors.New("embedded file too big")
|
||||
@@ -634,7 +627,7 @@ createPacketLoop:
|
||||
|
||||
// only on initial response the User Agent must be provided according to the protocol spec
|
||||
if sendUA {
|
||||
userAgentB := []byte(UserAgent)
|
||||
userAgentB := []byte(userAgent)
|
||||
if len(userAgentB) > 255 {
|
||||
userAgentB = userAgentB[:255]
|
||||
}
|
||||
@@ -782,10 +775,10 @@ func encodePeerRecord(raw []byte, peer *PeerRecord, reason uint8) {
|
||||
|
||||
const traversePayloadHeaderSize = 76 + 65 + 28
|
||||
|
||||
// msgDecodeTraverse decodes a traverse message.
|
||||
// DecodeTraverse decodes a traverse message.
|
||||
// It does not verify if the receiver is authorized to read or forward this message.
|
||||
// It validates the signature, but does not validate the signer.
|
||||
func msgDecodeTraverse(msg *MessageRaw) (result *MessageTraverse, err error) {
|
||||
func DecodeTraverse(msg *MessageRaw) (result *MessageTraverse, err error) {
|
||||
result = &MessageTraverse{
|
||||
MessageRaw: msg,
|
||||
}
|
||||
@@ -821,7 +814,7 @@ func msgDecodeTraverse(msg *MessageRaw) (result *MessageTraverse, err error) {
|
||||
|
||||
signature := msg.Payload[76+sizePacketEmbed : 76+sizePacketEmbed+65]
|
||||
|
||||
result.SignerPublicKey, _, err = btcec.RecoverCompact(btcec.S256(), signature, protocol.HashData(msg.Payload[:76+sizePacketEmbed]))
|
||||
result.SignerPublicKey, _, err = btcec.RecoverCompact(btcec.S256(), signature, HashData(msg.Payload[:76+sizePacketEmbed]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -850,8 +843,8 @@ func msgDecodeTraverse(msg *MessageRaw) (result *MessageTraverse, err error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// msgEncodeTraverse encodes a traverse message
|
||||
func msgEncodeTraverse(senderPrivateKey *btcec.PrivateKey, embeddedPacketRaw []byte, receiverEnd *btcec.PublicKey, relayPeer *btcec.PublicKey) (packetRaw []byte, err error) {
|
||||
// EncodeTraverse encodes a traverse message
|
||||
func EncodeTraverse(senderPrivateKey *btcec.PrivateKey, embeddedPacketRaw []byte, receiverEnd *btcec.PublicKey, relayPeer *btcec.PublicKey) (packetRaw []byte, err error) {
|
||||
sizePacketEmbed := len(embeddedPacketRaw)
|
||||
if isPacketSizeExceed(traversePayloadHeaderSize, sizePacketEmbed) {
|
||||
return nil, errors.New("traverse encode: embedded packet too big")
|
||||
@@ -871,7 +864,7 @@ func msgEncodeTraverse(senderPrivateKey *btcec.PrivateKey, embeddedPacketRaw []b
|
||||
copy(raw[76:76+sizePacketEmbed], embeddedPacketRaw)
|
||||
|
||||
// add signature
|
||||
signature, err := btcec.SignCompact(btcec.S256(), senderPrivateKey, protocol.HashData(raw[:76+sizePacketEmbed]), true)
|
||||
signature, err := btcec.SignCompact(btcec.S256(), senderPrivateKey, HashData(raw[:76+sizePacketEmbed]), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -882,8 +875,8 @@ func msgEncodeTraverse(senderPrivateKey *btcec.PrivateKey, embeddedPacketRaw []b
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// msgEncodeTraverseSetAddress sets the IP and Port
|
||||
func msgEncodeTraverseSetAddress(raw []byte, IPv4 net.IP, PortIPv4, PortIPv4ReportedExternal uint16, IPv6 net.IP, PortIPv6, PortIPv6ReportedExternal uint16) (err error) {
|
||||
// EncodeTraverseSetAddress sets the IP and Port
|
||||
func EncodeTraverseSetAddress(raw []byte, IPv4 net.IP, PortIPv4, PortIPv4ReportedExternal uint16, IPv6 net.IP, PortIPv6, PortIPv6ReportedExternal uint16) (err error) {
|
||||
if isPacketSizeExceed(len(raw), 0) {
|
||||
return errors.New("traverse encode 2: embedded packet too big")
|
||||
} else if len(raw) < traversePayloadHeaderSize {
|
||||
@@ -896,14 +889,14 @@ func msgEncodeTraverseSetAddress(raw []byte, IPv4 net.IP, PortIPv4, PortIPv4Repo
|
||||
}
|
||||
|
||||
// IPv4
|
||||
if IPv4 != nil && IsIPv4(IPv4) {
|
||||
if IPv4 != nil && len(IPv4) == net.IPv4len {
|
||||
copy(raw[76+sizePacketEmbed+65:76+sizePacketEmbed+65+4], IPv4.To4())
|
||||
binary.LittleEndian.PutUint16(raw[76+sizePacketEmbed+65+4:76+sizePacketEmbed+65+4+2], PortIPv4)
|
||||
binary.LittleEndian.PutUint16(raw[76+sizePacketEmbed+65+6:76+sizePacketEmbed+65+6+2], PortIPv4ReportedExternal)
|
||||
}
|
||||
|
||||
// IPv6
|
||||
if IPv6 != nil && IsIPv6(IPv6) {
|
||||
if IPv6 != nil && len(IPv6) == net.IPv6len {
|
||||
copy(raw[76+sizePacketEmbed+65+8:76+sizePacketEmbed+65+8+16], IPv6.To16())
|
||||
binary.LittleEndian.PutUint16(raw[76+sizePacketEmbed+65+24:76+sizePacketEmbed+65+24+2], PortIPv6)
|
||||
binary.LittleEndian.PutUint16(raw[76+sizePacketEmbed+65+26:76+sizePacketEmbed+65+26+2], PortIPv6ReportedExternal)
|
||||
@@ -1,40 +1,41 @@
|
||||
// Functions to manually debug encoding/decoding. No actual automated unit tests.
|
||||
package core
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/PeernetOfficial/core/protocol"
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
func TestMessageEncodingAnnouncement(t *testing.T) {
|
||||
_, publicKey, err := Secp256k1NewPrivateKey()
|
||||
privateKey, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
publicKey := (*btcec.PublicKey)(&privateKey.PublicKey)
|
||||
|
||||
// encode and decode announcement
|
||||
packetR := protocol.PacketRaw{Protocol: 0, Command: protocol.CommandAnnouncement, Sequence: 123}
|
||||
packetR := PacketRaw{Protocol: 0, Command: CommandAnnouncement, Sequence: 123}
|
||||
|
||||
var findPeer []KeyHash
|
||||
var findValue []KeyHash
|
||||
var files []InfoStore
|
||||
|
||||
hash1 := protocol.HashData([]byte("test"))
|
||||
hash2 := protocol.HashData([]byte("test3"))
|
||||
hash1 := HashData([]byte("test"))
|
||||
hash2 := HashData([]byte("test3"))
|
||||
findPeer = append(findPeer, KeyHash{Hash: hash1})
|
||||
findValue = append(findValue, KeyHash{Hash: hash2})
|
||||
|
||||
packets := EncodeAnnouncement(true, true, findPeer, findValue, files, 1<<FeatureIPv4Listen|1<<FeatureIPv6Listen, 0, 0)
|
||||
packets := EncodeAnnouncement(true, true, findPeer, findValue, files, 1<<FeatureIPv4Listen|1<<FeatureIPv6Listen, 0, 0, "Debug Test/1.0")
|
||||
|
||||
msg := &MessageRaw{PacketRaw: packetR, SenderPublicKey: publicKey}
|
||||
msg.Payload = packets[0]
|
||||
|
||||
result, err := msgDecodeAnnouncement(msg)
|
||||
result, err := DecodeAnnouncement(msg)
|
||||
if err != nil {
|
||||
fmt.Printf("Error msgDecodeAnnouncement: %s\n", err.Error())
|
||||
fmt.Printf("Error DecodeAnnouncement: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -42,14 +43,15 @@ func TestMessageEncodingAnnouncement(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMessageEncodingResponse(t *testing.T) {
|
||||
_, publicKey, err := Secp256k1NewPrivateKey()
|
||||
privateKey, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
publicKey := (*btcec.PublicKey)(&privateKey.PublicKey)
|
||||
|
||||
// encode and decode response
|
||||
packetR := protocol.PacketRaw{Protocol: 0, Command: protocol.CommandResponse}
|
||||
packetR := PacketRaw{Protocol: 0, Command: CommandResponse}
|
||||
|
||||
var hash2Peers []Hash2Peer
|
||||
var filesEmbed []EmbeddedFileData
|
||||
@@ -57,14 +59,14 @@ func TestMessageEncodingResponse(t *testing.T) {
|
||||
|
||||
file1Data := []byte("test")
|
||||
file2Data := []byte("test3")
|
||||
file1 := EmbeddedFileData{ID: KeyHash{protocol.HashData(file1Data)}, Data: file1Data}
|
||||
file2 := EmbeddedFileData{ID: KeyHash{protocol.HashData(file2Data)}, Data: file2Data}
|
||||
file1 := EmbeddedFileData{ID: KeyHash{HashData(file1Data)}, Data: file1Data}
|
||||
file2 := EmbeddedFileData{ID: KeyHash{HashData(file2Data)}, Data: file2Data}
|
||||
filesEmbed = append(filesEmbed, file1)
|
||||
filesEmbed = append(filesEmbed, file2)
|
||||
|
||||
hashesNotFound = append(hashesNotFound, protocol.HashData([]byte("NA")))
|
||||
hashesNotFound = append(hashesNotFound, HashData([]byte("NA")))
|
||||
|
||||
packetsRaw, err := msgEncodeResponse(true, hash2Peers, filesEmbed, hashesNotFound, 1<<FeatureIPv4Listen|1<<FeatureIPv6Listen, 0, 0)
|
||||
packetsRaw, err := EncodeResponse(true, hash2Peers, filesEmbed, hashesNotFound, 1<<FeatureIPv4Listen|1<<FeatureIPv6Listen, 0, 0, "Debug Test/1.0")
|
||||
if err != nil {
|
||||
fmt.Printf("Error msgEncodeAnnouncement: %s\n", err.Error())
|
||||
return
|
||||
@@ -73,9 +75,9 @@ func TestMessageEncodingResponse(t *testing.T) {
|
||||
msg := &MessageRaw{PacketRaw: packetR, SenderPublicKey: publicKey}
|
||||
msg.Payload = packetsRaw[0]
|
||||
|
||||
result, err := msgDecodeResponse(msg)
|
||||
result, err := DecodeResponse(msg)
|
||||
if err != nil {
|
||||
fmt.Printf("Error msgDecodeAnnouncement: %s\n", err.Error())
|
||||
fmt.Printf("Error DecodeAnnouncement: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user