github.com/quic-go/quic-go@v0.44.0/send_conn_test.go (about) 1 package quic 2 3 import ( 4 "net" 5 "net/netip" 6 "runtime" 7 8 "github.com/quic-go/quic-go/internal/protocol" 9 "github.com/quic-go/quic-go/internal/utils" 10 11 . "github.com/onsi/ginkgo/v2" 12 . "github.com/onsi/gomega" 13 "go.uber.org/mock/gomock" 14 ) 15 16 // Only if appendUDPSegmentSizeMsg actually appends a message (and isn't only a stub implementation), 17 // GSO is actually supported on this platform. 18 var platformSupportsGSO = len(appendUDPSegmentSizeMsg([]byte{}, 1337)) > 0 19 20 var _ = Describe("Connection (for sending packets)", func() { 21 remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 100, 200), Port: 1337} 22 23 It("gets the local and remote addresses", func() { 24 localAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1234} 25 rawConn := NewMockRawConn(mockCtrl) 26 rawConn.EXPECT().LocalAddr().Return(localAddr) 27 c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger) 28 Expect(c.LocalAddr().String()).To(Equal("192.168.0.1:1234")) 29 Expect(c.RemoteAddr().String()).To(Equal("192.168.100.200:1337")) 30 }) 31 32 It("uses the local address from the packet info", func() { 33 localAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1234} 34 rawConn := NewMockRawConn(mockCtrl) 35 rawConn.EXPECT().LocalAddr().Return(localAddr) 36 c := newSendConn(rawConn, remoteAddr, packetInfo{addr: netip.AddrFrom4([4]byte{127, 0, 0, 42})}, utils.DefaultLogger) 37 Expect(c.LocalAddr().String()).To(Equal("127.0.0.42:1234")) 38 }) 39 40 // We're not using an OOB conn on windows, and packetInfo.OOB() always returns an empty slice. 41 if runtime.GOOS != "windows" { 42 It("sets the OOB", func() { 43 rawConn := NewMockRawConn(mockCtrl) 44 rawConn.EXPECT().LocalAddr() 45 rawConn.EXPECT().capabilities().AnyTimes() 46 pi := packetInfo{addr: netip.IPv6Loopback()} 47 Expect(pi.OOB()).ToNot(BeEmpty()) 48 c := newSendConn(rawConn, remoteAddr, pi, utils.DefaultLogger) 49 rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, pi.OOB(), uint16(0), protocol.ECT1) 50 Expect(c.Write([]byte("foobar"), 0, protocol.ECT1)).To(Succeed()) 51 }) 52 } 53 54 It("writes", func() { 55 rawConn := NewMockRawConn(mockCtrl) 56 rawConn.EXPECT().LocalAddr() 57 rawConn.EXPECT().capabilities().AnyTimes() 58 c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger) 59 rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), uint16(3), protocol.ECNCE) 60 Expect(c.Write([]byte("foobar"), 3, protocol.ECNCE)).To(Succeed()) 61 }) 62 63 if platformSupportsGSO { 64 It("disables GSO if sending fails", func() { 65 rawConn := NewMockRawConn(mockCtrl) 66 rawConn.EXPECT().LocalAddr() 67 rawConn.EXPECT().capabilities().Return(connCapabilities{GSO: true}).AnyTimes() 68 c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger) 69 Expect(c.capabilities().GSO).To(BeTrue()) 70 gomock.InOrder( 71 rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), uint16(4), protocol.ECNCE).Return(0, errGSO), 72 rawConn.EXPECT().WritePacket([]byte("foob"), remoteAddr, gomock.Any(), uint16(0), protocol.ECNCE).Return(4, nil), 73 rawConn.EXPECT().WritePacket([]byte("ar"), remoteAddr, gomock.Any(), uint16(0), protocol.ECNCE).Return(2, nil), 74 ) 75 Expect(c.Write([]byte("foobar"), 4, protocol.ECNCE)).To(Succeed()) 76 Expect(c.capabilities().GSO).To(BeFalse()) 77 }) 78 } 79 80 if runtime.GOOS == "linux" { 81 It("doesn't fail if the very first sendmsg call fails", func() { 82 rawConn := NewMockRawConn(mockCtrl) 83 rawConn.EXPECT().LocalAddr() 84 rawConn.EXPECT().capabilities().AnyTimes() 85 c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger) 86 gomock.InOrder( 87 rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), gomock.Any(), protocol.ECNCE).Return(0, errNotPermitted), 88 rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), uint16(0), protocol.ECNCE).Return(6, nil), 89 ) 90 Expect(c.Write([]byte("foobar"), 0, protocol.ECNCE)).To(Succeed()) 91 }) 92 93 It("fails if the sendmsg calls fail multiple times", func() { 94 rawConn := NewMockRawConn(mockCtrl) 95 rawConn.EXPECT().LocalAddr() 96 rawConn.EXPECT().capabilities().AnyTimes() 97 c := newSendConn(rawConn, remoteAddr, packetInfo{}, utils.DefaultLogger) 98 rawConn.EXPECT().WritePacket([]byte("foobar"), remoteAddr, gomock.Any(), gomock.Any(), protocol.ECNCE).Return(0, errNotPermitted).Times(2) 99 Expect(c.Write([]byte("foobar"), 0, protocol.ECNCE)).To(MatchError(errNotPermitted)) 100 }) 101 } 102 })