summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--conn/bind_windows.go16
1 files changed, 14 insertions, 2 deletions
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)
}