diff --git a/conn/bind_windows.go b/conn/bind_windows.go index fdd1c24..42208b1 100644 --- a/conn/bind_windows.go +++ b/conn/bind_windows.go @@ -352,8 +352,11 @@ func (bind *afWinRingBind) Receive(buf []byte, isOpen *uint32) (int, Endpoint, e } bind.rx.mu.Lock() defer bind.rx.mu.Unlock() + + var err error var count uint32 var results [1]winrio.Result +retry: for tries := 0; count == 0 && tries < receiveSpins; tries++ { if tries > 0 { if atomic.LoadUint32(isOpen) != 1 { @@ -364,7 +367,7 @@ func (bind *afWinRingBind) Receive(buf []byte, isOpen *uint32) (int, Endpoint, e count = winrio.DequeueCompletion(bind.rx.cq, results[:]) } if count == 0 { - err := winrio.Notify(bind.rx.cq) + err = winrio.Notify(bind.rx.cq) if err != nil { return 0, nil, err } @@ -385,10 +388,19 @@ func (bind *afWinRingBind) Receive(buf []byte, isOpen *uint32) (int, Endpoint, e } } bind.rx.Return(1) - err := bind.InsertReceiveRequest() + err = bind.InsertReceiveRequest() if err != nil { return 0, nil, err } + // We limit the MTU well below the 65k max for practicality, but this means a remote host can still send us + // huge packets. Just try again when this happens. The infinite loop this could cause is still limited to + // attacker bandwidth, just like the rest of the receive path. + if windows.Errno(results[0].Status) == windows.WSAEMSGSIZE { + if atomic.LoadUint32(isOpen) != 1 { + return 0, nil, net.ErrClosed + } + goto retry + } if results[0].Status != 0 { return 0, nil, windows.Errno(results[0].Status) }