Skip to content

Commit 757241e

Browse files
committed
conn: fix StdNetBind fallback on Windows
If RIO is unavailable, NewWinRingBind() falls back to StdNetBind. StdNetBind uses x/net/ipv{4,6}.PacketConn for sending and receiving datagrams, specifically via the {Read,Write}Batch methods. These methods are unimplemented on Windows and will return runtime errors as a result. This commit updates StdNetBind to fall back to the standard library net package for Windows. Signed-off-by: James Tucker <[email protected]> Signed-off-by: Jordan Whited <[email protected]>
1 parent b6a68cf commit 757241e

File tree

1 file changed

+65
-21
lines changed

1 file changed

+65
-21
lines changed

conn/bind_std.go

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"errors"
1111
"net"
1212
"net/netip"
13+
"runtime"
1314
"strconv"
1415
"sync"
1516
"syscall"
@@ -22,15 +23,16 @@ var (
2223
_ Bind = (*StdNetBind)(nil)
2324
)
2425

25-
// StdNetBind implements Bind for all platforms except Windows.
26+
// StdNetBind implements Bind for all platforms. While Windows has its own Bind
27+
// (see bind_windows.go), it may fall back to StdNetBind.
2628
type StdNetBind struct {
2729
mu sync.Mutex // protects following fields
2830
ipv4 *net.UDPConn
2931
ipv6 *net.UDPConn
3032
blackhole4 bool
3133
blackhole6 bool
32-
ipv4PC *ipv4.PacketConn
33-
ipv6PC *ipv6.PacketConn
34+
ipv4PC *ipv4.PacketConn // will be nil on Windows
35+
ipv6PC *ipv6.PacketConn // will be nil on Windows
3436
udpAddrPool sync.Pool
3537
ipv4MsgsPool sync.Pool
3638
ipv6MsgsPool sync.Pool
@@ -184,8 +186,12 @@ again:
184186
return nil, 0, syscall.EAFNOSUPPORT
185187
}
186188

187-
s.ipv4PC = ipv4.NewPacketConn(s.ipv4)
188-
s.ipv6PC = ipv6.NewPacketConn(s.ipv6)
189+
// x/net/ipv{4,6} packages do not implement PacketConn.{Read,Write}Batch()
190+
// for Windows (runtime error).
191+
if runtime.GOOS != "windows" {
192+
s.ipv4PC = ipv4.NewPacketConn(s.ipv4)
193+
s.ipv6PC = ipv6.NewPacketConn(s.ipv6)
194+
}
189195

190196
return fns, uint16(port), nil
191197
}
@@ -196,9 +202,19 @@ func (s *StdNetBind) receiveIPv4(buffs [][]byte, sizes []int, eps []Endpoint) (n
196202
for i := range buffs {
197203
(*msgs)[i].Buffers[0] = buffs[i]
198204
}
199-
numMsgs, err := s.ipv4PC.ReadBatch(*msgs, 0)
200-
if err != nil {
201-
return 0, err
205+
var numMsgs int
206+
if runtime.GOOS != "windows" {
207+
numMsgs, err = s.ipv4PC.ReadBatch(*msgs, 0)
208+
if err != nil {
209+
return 0, err
210+
}
211+
} else {
212+
msg := &(*msgs)[0]
213+
msg.N, msg.NN, _, msg.Addr, err = s.ipv4.ReadMsgUDP(msg.Buffers[0], msg.OOB)
214+
if err != nil {
215+
return 0, err
216+
}
217+
numMsgs = 1
202218
}
203219
for i := 0; i < numMsgs; i++ {
204220
msg := &(*msgs)[i]
@@ -217,9 +233,19 @@ func (s *StdNetBind) receiveIPv6(buffs [][]byte, sizes []int, eps []Endpoint) (n
217233
for i := range buffs {
218234
(*msgs)[i].Buffers[0] = buffs[i]
219235
}
220-
numMsgs, err := s.ipv6PC.ReadBatch(*msgs, 0)
221-
if err != nil {
222-
return 0, err
236+
var numMsgs int
237+
if runtime.GOOS != "windows" {
238+
numMsgs, err = s.ipv6PC.ReadBatch(*msgs, 0)
239+
if err != nil {
240+
return 0, err
241+
}
242+
} else {
243+
msg := &(*msgs)[0]
244+
msg.N, msg.NN, _, msg.Addr, err = s.ipv6.ReadMsgUDP(msg.Buffers[0], msg.OOB)
245+
if err != nil {
246+
return 0, err
247+
}
248+
numMsgs = 1
223249
}
224250
for i := 0; i < numMsgs; i++ {
225251
msg := &(*msgs)[i]
@@ -301,12 +327,21 @@ func (s *StdNetBind) send4(conn *ipv4.PacketConn, ep Endpoint, buffs [][]byte) e
301327
err error
302328
start int
303329
)
304-
for {
305-
n, err = conn.WriteBatch((*msgs)[start:len(buffs)], 0)
306-
if err != nil || n == len((*msgs)[start:len(buffs)]) {
307-
break
330+
if runtime.GOOS != "windows" {
331+
for {
332+
n, err = conn.WriteBatch((*msgs)[start:len(buffs)], 0)
333+
if err != nil || n == len((*msgs)[start:len(buffs)]) {
334+
break
335+
}
336+
start += n
337+
}
338+
} else {
339+
for i, buff := range buffs {
340+
_, _, err = s.ipv4.WriteMsgUDP(buff, (*msgs)[i].OOB, ua)
341+
if err != nil {
342+
break
343+
}
308344
}
309-
start += n
310345
}
311346
s.udpAddrPool.Put(ua)
312347
s.ipv4MsgsPool.Put(msgs)
@@ -330,12 +365,21 @@ func (s *StdNetBind) send6(conn *ipv6.PacketConn, ep Endpoint, buffs [][]byte) e
330365
err error
331366
start int
332367
)
333-
for {
334-
n, err = conn.WriteBatch((*msgs)[start:len(buffs)], 0)
335-
if err != nil || n == len((*msgs)[start:len(buffs)]) {
336-
break
368+
if runtime.GOOS != "windows" {
369+
for {
370+
n, err = conn.WriteBatch((*msgs)[start:len(buffs)], 0)
371+
if err != nil || n == len((*msgs)[start:len(buffs)]) {
372+
break
373+
}
374+
start += n
375+
}
376+
} else {
377+
for i, buff := range buffs {
378+
_, _, err = s.ipv6.WriteMsgUDP(buff, (*msgs)[i].OOB, ua)
379+
if err != nil {
380+
break
381+
}
337382
}
338-
start += n
339383
}
340384
s.udpAddrPool.Put(ua)
341385
s.ipv6MsgsPool.Put(msgs)

0 commit comments

Comments
 (0)