device: receive: do not exit immediately on transient UDP receive errors

Some users report seeing lines like:

> Routine: receive incoming IPv4 - stopped

Popping up unexpectedly. Let's sleep and try again before failing, and
also log the error, and perhaps we'll eventually understand this
situation better in future versions.

Because we have to distinguish between the socket being closed
explicitly and whatever error this is, we bump the module to require Go
1.16.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld
2021-01-08 14:25:37 +01:00
parent 3b3de758ec
commit ea6c1cd7e6
4 changed files with 32 additions and 23 deletions

View File

@@ -8,6 +8,7 @@ package device
import (
"bytes"
"encoding/binary"
"errors"
"net"
"strconv"
"sync"
@@ -17,6 +18,7 @@ import (
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
"golang.zx2c4.com/wireguard/conn"
)
@@ -117,15 +119,13 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind conn.Bind) {
buffer := device.GetMessageBuffer()
var (
err error
size int
endpoint conn.Endpoint
err error
size int
endpoint conn.Endpoint
deathSpiral int
)
for {
// read next datagram
switch IP {
case ipv4.Version:
size, endpoint, err = bind.ReceiveIPv4(buffer[:])
@@ -137,8 +137,18 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind conn.Bind) {
if err != nil {
device.PutMessageBuffer(buffer)
if errors.Is(err, net.ErrClosed) {
return
}
device.log.Error.Printf("Failed to receive packet: %v", err)
if deathSpiral < 10 {
deathSpiral++
time.Sleep(time.Second / 3)
continue
}
return
}
deathSpiral = 0
if size < MinMessageSize {
continue