mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
gofmt peernet (#103)
This commit is contained in:
committed by
GitHub
parent
3a1eece580
commit
9775525d35
@@ -1,181 +1,181 @@
|
||||
/*
|
||||
File Name: Network IPv4 Broadcast.go
|
||||
Copyright: 2021 Peernet s.r.o.
|
||||
Author: Peter Kleissner
|
||||
|
||||
IPv4 Multicast just sucks (can't use socket bound to 0.0.0.0:PortMain and send to 224.0.0.1:PortMulticast), so we rely on Broadcast instead.
|
||||
*/
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/PeernetOfficial/core/btcec"
|
||||
"github.com/PeernetOfficial/core/protocol"
|
||||
"github.com/PeernetOfficial/core/reuseport"
|
||||
)
|
||||
|
||||
const ipv4BroadcastPort = 12912
|
||||
|
||||
// special Public-Private Key pair for local discovery
|
||||
var ipv4BroadcastPrivateKey *btcec.PrivateKey
|
||||
var ipv4BroadcastPublicKey *btcec.PublicKey
|
||||
|
||||
const ipv4BroadcastPrivateKeyH = "5e27ecc8e54a24e71dca9ba84a9bf465400e27b8c46a977d34962d3d88558c8e"
|
||||
|
||||
func initBroadcastIPv4() {
|
||||
if configPK, err := hex.DecodeString(ipv4BroadcastPrivateKeyH); err == nil {
|
||||
ipv4BroadcastPrivateKey, ipv4BroadcastPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK)
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastIPv4 prepares sending Broadcasts
|
||||
func (network *Network) BroadcastIPv4() (err error) {
|
||||
if ipv4BroadcastPrivateKey == nil || ipv4BroadcastPublicKey == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// listen on a special socket
|
||||
network.broadcastSocket, err = reuseport.ListenPacket("udp4", net.JoinHostPort(network.address.IP.String(), strconv.Itoa(ipv4BroadcastPort)))
|
||||
if err != nil {
|
||||
network.backend.LogError("BroadcastIPv4", "broadcast socket listen on IP '%s' port '%d': %v\n", network.address.IP.String(), ipv4BroadcastPort, err)
|
||||
return err
|
||||
}
|
||||
|
||||
network.broadcastIPv4 = networkToIPv4BroadcastIPs(network.ipnet)
|
||||
|
||||
go network.BroadcastIPv4Listen()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastIPv4Listen listens for incoming broadcast packets
|
||||
// Fork from network.Listen! Keep any changes synced.
|
||||
func (network *Network) BroadcastIPv4Listen() {
|
||||
for {
|
||||
// Buffer: Must be created for each packet as it is passed as pointer.
|
||||
// If the buffer is too small, ReadFromUDP only reads until its length and returns this error: "wsarecvfrom: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself."
|
||||
buffer := make([]byte, maxPacketSize)
|
||||
length, sender, err := network.broadcastSocket.ReadFrom(buffer)
|
||||
|
||||
if err != nil {
|
||||
network.backend.LogError("BroadcastIPv4Listen", "receiving UDP message: %v\n", err) // Only log for debug purposes.
|
||||
time.Sleep(time.Millisecond * 50) // In case of endless errors, prevent ddos of CPU.
|
||||
continue
|
||||
}
|
||||
|
||||
if network.networkGroup.ipListen.IsAddressSelf(sender.(*net.UDPAddr)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// For good network practice (and reducing amount of parallel connections), do not allow link-local to talk to non-link-local addresses.
|
||||
if sender.(*net.UDPAddr).IP.IsLinkLocalUnicast() != network.address.IP.IsLinkLocalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
//fmt.Printf("BroadcastIPv4Listen from %s at network %s\n", sender.String(), network.address.String())
|
||||
|
||||
if length < protocol.PacketLengthMin {
|
||||
// Discard packets that do not meet the minimum length.
|
||||
continue
|
||||
}
|
||||
|
||||
// send the packet to a channel which is processed by multiple workers.
|
||||
network.networkGroup.rawPacketsIncoming <- networkWire{network: network, sender: sender.(*net.UDPAddr), raw: buffer[:length], receiverPublicKey: ipv4BroadcastPublicKey, unicast: false}
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastIPv4Send sends out a single broadcast messages to discover peers
|
||||
func (network *Network) BroadcastIPv4Send() (err error) {
|
||||
_, blockchainHeight, blockchainVersion := network.backend.UserBlockchain.Header()
|
||||
packets := protocol.EncodeAnnouncement(true, true, nil, nil, nil, network.backend.FeatureSupport(), blockchainHeight, blockchainVersion, network.backend.userAgent)
|
||||
if len(packets) == 0 {
|
||||
return errors.New("error encoding broadcast announcement")
|
||||
}
|
||||
|
||||
raw, err := protocol.PacketEncrypt(network.backend.PeerPrivateKey, ipv4BroadcastPublicKey, &protocol.PacketRaw{Protocol: protocol.ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// send out the wire
|
||||
for _, ip := range network.broadcastIPv4 {
|
||||
err = network.send(ip, ipv4BroadcastPort, raw)
|
||||
if err != nil {
|
||||
network.backend.LogError("BroadcastIPv4Send", "sending UDP packet: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// networkToIPv4BroadcastIPs generates the IPv4 addresses to send out the broadcast to
|
||||
func networkToIPv4BroadcastIPs(ipnet *net.IPNet) (broadcastIPs []net.IP) {
|
||||
broadcastIPs = append(broadcastIPs, net.IPv4bcast)
|
||||
|
||||
if ipnet != nil {
|
||||
if ip2 := ipv4DirectedBroadcast(ipnet); ip2 != nil {
|
||||
broadcastIPs = append(broadcastIPs, ip2)
|
||||
}
|
||||
} else {
|
||||
interfaceList, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, iface := range interfaceList {
|
||||
addresses, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, address := range addresses {
|
||||
net1 := address.(*net.IPNet)
|
||||
|
||||
// TODO: Does the rfc3927Net make sense?
|
||||
if !IsIPv4(net1.IP) || rfc3927Net.Contains(net1.IP) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ip2 := ipv4DirectedBroadcast(net1); ip2 != nil {
|
||||
broadcastIPs = append(broadcastIPs, ip2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Result could contain duplicates, filter them out
|
||||
|
||||
return broadcastIPs
|
||||
}
|
||||
|
||||
func ipv4DirectedBroadcast(n *net.IPNet) net.IP {
|
||||
ip4 := n.IP.To4()
|
||||
if ip4 == nil {
|
||||
return nil
|
||||
}
|
||||
last := make(net.IP, len(ip4))
|
||||
copy(last, ip4)
|
||||
for i := range ip4 {
|
||||
last[i] |= ^n.Mask[i]
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
var (
|
||||
// rfc3927Net specifies the IPv4 auto configuration address block as
|
||||
// defined by RFC3927 (169.254.0.0/16).
|
||||
rfc3927Net = ipNet("169.254.0.0", 16, 32)
|
||||
)
|
||||
|
||||
// ipNet returns a net.IPNet struct given the passed IP address string, number
|
||||
// of one bits to include at the start of the mask, and the total number of bits
|
||||
// for the mask.
|
||||
func ipNet(ip string, ones, bits int) net.IPNet {
|
||||
return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)}
|
||||
}
|
||||
/*
|
||||
File Name: Network IPv4 Broadcast.go
|
||||
Copyright: 2021 Peernet s.r.o.
|
||||
Author: Peter Kleissner
|
||||
|
||||
IPv4 Multicast just sucks (can't use socket bound to 0.0.0.0:PortMain and send to 224.0.0.1:PortMulticast), so we rely on Broadcast instead.
|
||||
*/
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/PeernetOfficial/core/btcec"
|
||||
"github.com/PeernetOfficial/core/protocol"
|
||||
"github.com/PeernetOfficial/core/reuseport"
|
||||
)
|
||||
|
||||
const ipv4BroadcastPort = 12912
|
||||
|
||||
// special Public-Private Key pair for local discovery
|
||||
var ipv4BroadcastPrivateKey *btcec.PrivateKey
|
||||
var ipv4BroadcastPublicKey *btcec.PublicKey
|
||||
|
||||
const ipv4BroadcastPrivateKeyH = "5e27ecc8e54a24e71dca9ba84a9bf465400e27b8c46a977d34962d3d88558c8e"
|
||||
|
||||
func initBroadcastIPv4() {
|
||||
if configPK, err := hex.DecodeString(ipv4BroadcastPrivateKeyH); err == nil {
|
||||
ipv4BroadcastPrivateKey, ipv4BroadcastPublicKey = btcec.PrivKeyFromBytes(btcec.S256(), configPK)
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastIPv4 prepares sending Broadcasts
|
||||
func (network *Network) BroadcastIPv4() (err error) {
|
||||
if ipv4BroadcastPrivateKey == nil || ipv4BroadcastPublicKey == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// listen on a special socket
|
||||
network.broadcastSocket, err = reuseport.ListenPacket("udp4", net.JoinHostPort(network.address.IP.String(), strconv.Itoa(ipv4BroadcastPort)))
|
||||
if err != nil {
|
||||
network.backend.LogError("BroadcastIPv4", "broadcast socket listen on IP '%s' port '%d': %v\n", network.address.IP.String(), ipv4BroadcastPort, err)
|
||||
return err
|
||||
}
|
||||
|
||||
network.broadcastIPv4 = networkToIPv4BroadcastIPs(network.ipnet)
|
||||
|
||||
go network.BroadcastIPv4Listen()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastIPv4Listen listens for incoming broadcast packets
|
||||
// Fork from network.Listen! Keep any changes synced.
|
||||
func (network *Network) BroadcastIPv4Listen() {
|
||||
for {
|
||||
// Buffer: Must be created for each packet as it is passed as pointer.
|
||||
// If the buffer is too small, ReadFromUDP only reads until its length and returns this error: "wsarecvfrom: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself."
|
||||
buffer := make([]byte, maxPacketSize)
|
||||
length, sender, err := network.broadcastSocket.ReadFrom(buffer)
|
||||
|
||||
if err != nil {
|
||||
network.backend.LogError("BroadcastIPv4Listen", "receiving UDP message: %v\n", err) // Only log for debug purposes.
|
||||
time.Sleep(time.Millisecond * 50) // In case of endless errors, prevent ddos of CPU.
|
||||
continue
|
||||
}
|
||||
|
||||
if network.networkGroup.ipListen.IsAddressSelf(sender.(*net.UDPAddr)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// For good network practice (and reducing amount of parallel connections), do not allow link-local to talk to non-link-local addresses.
|
||||
if sender.(*net.UDPAddr).IP.IsLinkLocalUnicast() != network.address.IP.IsLinkLocalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
//fmt.Printf("BroadcastIPv4Listen from %s at network %s\n", sender.String(), network.address.String())
|
||||
|
||||
if length < protocol.PacketLengthMin {
|
||||
// Discard packets that do not meet the minimum length.
|
||||
continue
|
||||
}
|
||||
|
||||
// send the packet to a channel which is processed by multiple workers.
|
||||
network.networkGroup.rawPacketsIncoming <- networkWire{network: network, sender: sender.(*net.UDPAddr), raw: buffer[:length], receiverPublicKey: ipv4BroadcastPublicKey, unicast: false}
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastIPv4Send sends out a single broadcast messages to discover peers
|
||||
func (network *Network) BroadcastIPv4Send() (err error) {
|
||||
_, blockchainHeight, blockchainVersion := network.backend.UserBlockchain.Header()
|
||||
packets := protocol.EncodeAnnouncement(true, true, nil, nil, nil, network.backend.FeatureSupport(), blockchainHeight, blockchainVersion, network.backend.userAgent)
|
||||
if len(packets) == 0 {
|
||||
return errors.New("error encoding broadcast announcement")
|
||||
}
|
||||
|
||||
raw, err := protocol.PacketEncrypt(network.backend.PeerPrivateKey, ipv4BroadcastPublicKey, &protocol.PacketRaw{Protocol: protocol.ProtocolVersion, Command: protocol.CommandLocalDiscovery, Payload: packets[0]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// send out the wire
|
||||
for _, ip := range network.broadcastIPv4 {
|
||||
err = network.send(ip, ipv4BroadcastPort, raw)
|
||||
if err != nil {
|
||||
network.backend.LogError("BroadcastIPv4Send", "sending UDP packet: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// networkToIPv4BroadcastIPs generates the IPv4 addresses to send out the broadcast to
|
||||
func networkToIPv4BroadcastIPs(ipnet *net.IPNet) (broadcastIPs []net.IP) {
|
||||
broadcastIPs = append(broadcastIPs, net.IPv4bcast)
|
||||
|
||||
if ipnet != nil {
|
||||
if ip2 := ipv4DirectedBroadcast(ipnet); ip2 != nil {
|
||||
broadcastIPs = append(broadcastIPs, ip2)
|
||||
}
|
||||
} else {
|
||||
interfaceList, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, iface := range interfaceList {
|
||||
addresses, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, address := range addresses {
|
||||
net1 := address.(*net.IPNet)
|
||||
|
||||
// TODO: Does the rfc3927Net make sense?
|
||||
if !IsIPv4(net1.IP) || rfc3927Net.Contains(net1.IP) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ip2 := ipv4DirectedBroadcast(net1); ip2 != nil {
|
||||
broadcastIPs = append(broadcastIPs, ip2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Result could contain duplicates, filter them out
|
||||
|
||||
return broadcastIPs
|
||||
}
|
||||
|
||||
func ipv4DirectedBroadcast(n *net.IPNet) net.IP {
|
||||
ip4 := n.IP.To4()
|
||||
if ip4 == nil {
|
||||
return nil
|
||||
}
|
||||
last := make(net.IP, len(ip4))
|
||||
copy(last, ip4)
|
||||
for i := range ip4 {
|
||||
last[i] |= ^n.Mask[i]
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
var (
|
||||
// rfc3927Net specifies the IPv4 auto configuration address block as
|
||||
// defined by RFC3927 (169.254.0.0/16).
|
||||
rfc3927Net = ipNet("169.254.0.0", 16, 32)
|
||||
)
|
||||
|
||||
// ipNet returns a net.IPNet struct given the passed IP address string, number
|
||||
// of one bits to include at the start of the mask, and the total number of bits
|
||||
// for the mask.
|
||||
func ipNet(ip string, ones, bits int) net.IPNet {
|
||||
return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user