Browse Source

Retry UDP receive on Windows in some receive error cases (#1404)

brad-defined 3 months ago
parent
commit
04d7a8ccba
1 changed files with 17 additions and 2 deletions
  1. 17 2
      udp/udp_rio_windows.go

+ 17 - 2
udp/udp_rio_windows.go

@@ -14,6 +14,7 @@ import (
 	"sync"
 	"sync/atomic"
 	"syscall"
+	"time"
 	"unsafe"
 
 	"github.com/sirupsen/logrus"
@@ -125,14 +126,28 @@ func (u *RIOConn) ListenOut(r EncReader, lhf LightHouseHandlerFunc, cache *firew
 	fwPacket := &firewall.Packet{}
 	nb := make([]byte, 12, 12)
 
+	consecutiveErrors := 0
 	for {
 		// Just read one packet at a time
 		n, rua, err := u.receive(buffer)
 		if err != nil {
-			u.l.WithError(err).Debug("udp socket is closed, exiting read loop")
-			return
+			if errors.Is(err, net.ErrClosed) {
+				u.l.WithError(err).Debug("udp socket is closed, exiting read loop")
+				return
+			}
+			// Try to suss out whether this is a transient error or something more permanent
+			consecutiveErrors++
+			u.l.WithError(err).WithField("consecutiveErrors", consecutiveErrors).Error("unexpected udp socket recieve error")
+			if consecutiveErrors > 15 {
+				panic("too many consecutive UDP receive errors")
+			} else if consecutiveErrors > 10 {
+				time.Sleep(100 * time.Millisecond)
+			}
+			continue
 		}
 
+		consecutiveErrors = 0
+
 		r(
 			netip.AddrPortFrom(netip.AddrFrom16(rua.Addr).Unmap(), (rua.Port>>8)|((rua.Port&0xff)<<8)),
 			plaintext[:0],