Fixed blocking reader on closed socket
This commit is contained in:
parent
892276aa64
commit
566269275e
16
src/conn.go
16
src/conn.go
|
@ -37,15 +37,14 @@ func parseEndpoint(s string) (*net.UDPAddr, error) {
|
|||
/* Must hold device and net lock
|
||||
*/
|
||||
func unsafeCloseUDPListener(device *Device) error {
|
||||
var err error
|
||||
netc := &device.net
|
||||
if netc.bind != nil {
|
||||
if err := netc.bind.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
err = netc.bind.Close()
|
||||
netc.bind = nil
|
||||
netc.update.Broadcast()
|
||||
netc.update.Add(1)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// must inform all listeners
|
||||
|
@ -63,7 +62,7 @@ func UpdateUDPListener(device *Device) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// wait for reader
|
||||
// assumption: netc.update WaitGroup should be exactly 1
|
||||
|
||||
// open new sockets
|
||||
|
||||
|
@ -93,9 +92,10 @@ func UpdateUDPListener(device *Device) error {
|
|||
peer.mutex.Unlock()
|
||||
}
|
||||
|
||||
// inform readers of updated bind
|
||||
// decrease waitgroup to 0
|
||||
|
||||
netc.update.Broadcast()
|
||||
device.log.Debug.Println("UDP bind has been updated")
|
||||
netc.update.Done()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -84,9 +84,15 @@ func (bind NativeBind) SetMark(value uint32) error {
|
|||
)
|
||||
}
|
||||
|
||||
func closeUnblock(fd int) error {
|
||||
// shutdown to unblock readers
|
||||
unix.Shutdown(fd, unix.SHUT_RD)
|
||||
return unix.Close(fd)
|
||||
}
|
||||
|
||||
func (bind NativeBind) Close() error {
|
||||
err1 := unix.Close(bind.sock6)
|
||||
err2 := unix.Close(bind.sock4)
|
||||
err1 := closeUnblock(bind.sock6)
|
||||
err2 := closeUnblock(bind.sock4)
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
|
@ -125,13 +131,13 @@ func sockaddrToString(addr unix.RawSockaddrInet6) string {
|
|||
|
||||
switch addr.Family {
|
||||
case unix.AF_INET6:
|
||||
udpAddr.Port = int(addr.Port)
|
||||
udpAddr.Port = int(ntohs(addr.Port))
|
||||
udpAddr.IP = addr.Addr[:]
|
||||
return udpAddr.String()
|
||||
|
||||
case unix.AF_INET:
|
||||
ptr := (*unix.RawSockaddrInet4)(unsafe.Pointer(&addr))
|
||||
udpAddr.Port = int(ptr.Port)
|
||||
udpAddr.Port = int(ntohs(ptr.Port))
|
||||
udpAddr.IP = net.IPv4(
|
||||
ptr.Addr[0],
|
||||
ptr.Addr[1],
|
||||
|
|
|
@ -26,7 +26,7 @@ type Device struct {
|
|||
bind UDPBind // bind interface
|
||||
port uint16 // listening port
|
||||
fwmark uint32 // mark value (0 = disabled)
|
||||
update *sync.Cond // the bind was updated
|
||||
update sync.WaitGroup // the bind was updated (acting as a barrier)
|
||||
}
|
||||
mutex sync.RWMutex
|
||||
privateKey NoisePrivateKey
|
||||
|
@ -167,7 +167,7 @@ func NewDevice(tun TUNDevice, logLevel int) *Device {
|
|||
|
||||
device.net.port = 0
|
||||
device.net.bind = nil
|
||||
device.net.update = sync.NewCond(&device.net.mutex)
|
||||
device.net.update.Add(1)
|
||||
|
||||
// start workers
|
||||
|
||||
|
@ -209,9 +209,11 @@ func (device *Device) RemoveAllPeers() {
|
|||
}
|
||||
|
||||
func (device *Device) Close() {
|
||||
device.log.Info.Println("Closing device")
|
||||
device.RemoveAllPeers()
|
||||
close(device.signal.stop)
|
||||
CloseUDPListener(device)
|
||||
device.tun.device.Close()
|
||||
}
|
||||
|
||||
func (device *Device) WaitChannel() chan struct{} {
|
||||
|
|
|
@ -95,23 +95,22 @@ func (device *Device) addToHandshakeQueue(
|
|||
func (device *Device) RoutineReceiveIncomming(IPVersion int) {
|
||||
|
||||
logDebug := device.log.Debug
|
||||
logDebug.Println("Routine, receive incomming, started")
|
||||
logDebug.Println("Routine, receive incomming, IP version:", IPVersion)
|
||||
|
||||
for {
|
||||
|
||||
// wait for bind
|
||||
|
||||
logDebug.Println("Waiting for udp bind")
|
||||
device.net.mutex.Lock()
|
||||
logDebug.Println("Waiting for UDP socket, IP version:", IPVersion)
|
||||
|
||||
device.net.update.Wait()
|
||||
device.net.mutex.RLock()
|
||||
bind := device.net.bind
|
||||
device.net.mutex.Unlock()
|
||||
device.net.mutex.RUnlock()
|
||||
if bind == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
logDebug.Println("LISTEN\n\n\n")
|
||||
|
||||
// receive datagrams until conn is closed
|
||||
|
||||
buffer := device.GetMessageBuffer()
|
||||
|
@ -427,6 +426,8 @@ func (device *Device) RoutineHandshake() {
|
|||
err = peer.SendBuffer(packet)
|
||||
if err == nil {
|
||||
peer.TimerAnyAuthenticatedPacketTraversal()
|
||||
} else {
|
||||
logError.Println("Failed to send response to:", peer.String(), err)
|
||||
}
|
||||
|
||||
case MessageResponseType:
|
||||
|
|
Loading…
Reference in a new issue