mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
Termination of networks upon removal of their network adapter.
This commit is contained in:
@@ -170,22 +170,41 @@ func networkChangeMonitor() {
|
|||||||
|
|
||||||
// networkChangeInterfaceNew is called when a new interface is detected
|
// networkChangeInterfaceNew is called when a new interface is detected
|
||||||
func networkChangeInterfaceNew(iface net.Interface, addresses []net.Addr) {
|
func networkChangeInterfaceNew(iface net.Interface, addresses []net.Addr) {
|
||||||
fmt.Printf("Interface new: %s\n", iface.Name)
|
log.Printf("networkChangeInterfaceNew new interface '%s' (%d IPs)\n", iface.Name, len(addresses))
|
||||||
|
|
||||||
for _, addr := range addresses {
|
|
||||||
fmt.Printf(" IP: %s\n", addr.String())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// networkChangeInterfaceRemove is called when an existing interface is removed
|
// networkChangeInterfaceRemove is called when an existing interface is removed
|
||||||
func networkChangeInterfaceRemove(iface string, addresses []net.Addr) {
|
func networkChangeInterfaceRemove(iface string, addresses []net.Addr) {
|
||||||
//networksMutex.RLock()
|
networksMutex.RLock()
|
||||||
//defer networksMutex.RUnlock()
|
defer networksMutex.RUnlock()
|
||||||
|
|
||||||
fmt.Printf("Interface removed: %s\n", iface)
|
log.Printf("networkChangeInterfaceRemove removing interface '%s' (%d IPs)\n", iface, len(addresses))
|
||||||
|
|
||||||
for _, addr := range addresses {
|
for n, network := range networks6 {
|
||||||
fmt.Printf(" IP: %s\n", addr.String())
|
if network.iface != nil && network.iface.Name == iface {
|
||||||
|
network.Terminate()
|
||||||
|
|
||||||
|
// remove from list
|
||||||
|
networksNew := networks6[:n]
|
||||||
|
if n < len(networks6)-1 {
|
||||||
|
networksNew = append(networksNew, networks6[n+1:]...)
|
||||||
|
}
|
||||||
|
networks6 = networksNew
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for n, network := range networks4 {
|
||||||
|
if network.iface != nil && network.iface.Name == iface {
|
||||||
|
network.Terminate()
|
||||||
|
|
||||||
|
// remove from list
|
||||||
|
networksNew := networks4[:n]
|
||||||
|
if n < len(networks4)-1 {
|
||||||
|
networksNew = append(networksNew, networks4[n+1:]...)
|
||||||
|
}
|
||||||
|
networks4 = networksNew
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ func networkPrepareListen(ipA string, port int) (network *Network, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
network = new(Network)
|
network = new(Network)
|
||||||
|
network.terminateSignal = make(chan interface{})
|
||||||
|
|
||||||
// get the network interface that belongs to the IP
|
// get the network interface that belongs to the IP
|
||||||
if ipA != "0.0.0.0" && ipA != "::" {
|
if ipA != "0.0.0.0" && ipA != "::" {
|
||||||
|
|||||||
41
Network.go
41
Network.go
@@ -18,14 +18,17 @@ import (
|
|||||||
// Network is a connection adapter through one network interface (adapter).
|
// Network is a connection adapter through one network interface (adapter).
|
||||||
// Note that for each IP on the same adapter separate network entries are created.
|
// Note that for each IP on the same adapter separate network entries are created.
|
||||||
type Network struct {
|
type Network struct {
|
||||||
iface *net.Interface // Network interface belonging to the IP. May not be set.
|
iface *net.Interface // Network interface belonging to the IP. May not be set.
|
||||||
ipnet *net.IPNet // IP network the listening address belongs to. May not be set.
|
ipnet *net.IPNet // IP network the listening address belongs to. May not be set.
|
||||||
address *net.UDPAddr // IP:Port where the server listens
|
address *net.UDPAddr // IP:Port where the server listens
|
||||||
socket *net.UDPConn // active socket for send/receive
|
socket *net.UDPConn // active socket for send/receive
|
||||||
multicastIP net.IP // Multicast IP, IPv6 only.
|
multicastIP net.IP // Multicast IP, IPv6 only.
|
||||||
multicastSocket net.PacketConn // Multicast socket, IPv6 only.
|
multicastSocket net.PacketConn // Multicast socket, IPv6 only.
|
||||||
broadcastSocket net.PacketConn // Broadcast socket, IPv4 only.
|
broadcastSocket net.PacketConn // Broadcast socket, IPv4 only.
|
||||||
broadcastIPv4 []net.IP // Broadcast IPs, IPv4 only.
|
broadcastIPv4 []net.IP // Broadcast IPs, IPv4 only.
|
||||||
|
isTerminated bool // If true, the network was signaled for termination
|
||||||
|
terminateSignal chan interface{} // gets closed on termination signal, can be used in select via "case _ = <- network.terminateSignal:"
|
||||||
|
sync.RWMutex // for sychronized closing
|
||||||
}
|
}
|
||||||
|
|
||||||
// networks is a list of all connected networks
|
// networks is a list of all connected networks
|
||||||
@@ -92,13 +95,18 @@ const maxPacketSize = 4096
|
|||||||
|
|
||||||
// Listen starts listening for incoming packets on the given UDP connection
|
// Listen starts listening for incoming packets on the given UDP connection
|
||||||
func (network *Network) Listen() {
|
func (network *Network) Listen() {
|
||||||
for {
|
for !network.isTerminated {
|
||||||
// Buffer: Must be created for each packet as it is passed as pointer.
|
// 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."
|
// 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)
|
buffer := make([]byte, maxPacketSize)
|
||||||
length, sender, err := network.socket.ReadFromUDP(buffer)
|
length, sender, err := network.socket.ReadFromUDP(buffer)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Exit on closed socket. Error will be "use of closed network connection".
|
||||||
|
if network.isTerminated {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Listen Error receiving UDP message: %v\n", err) // Only log for debug purposes.
|
log.Printf("Listen Error 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.
|
time.Sleep(time.Millisecond * 50) // In case of endless errors, prevent ddos of CPU.
|
||||||
continue
|
continue
|
||||||
@@ -193,3 +201,18 @@ func (network *Network) GetAdapterName() string {
|
|||||||
}
|
}
|
||||||
return "[unknown adapter]"
|
return "[unknown adapter]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Terminate sends the termination signal to all workers. It is safe to call Terminate multiple times.
|
||||||
|
func (network *Network) Terminate() {
|
||||||
|
network.Lock()
|
||||||
|
defer network.Unlock()
|
||||||
|
|
||||||
|
if network.isTerminated {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the termination signal
|
||||||
|
network.isTerminated = true
|
||||||
|
close(network.terminateSignal) // safety guaranteed via lock
|
||||||
|
network.socket.Close() // Will stop the listener from blocking on network.socket.ReadFromUDP
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user