github.com/TugasAkhir-QUIC/quic-go@v0.0.2-0.20240215011318-d20e25a9054c/sys_conn.go (about) 1 package quic 2 3 import ( 4 "log" 5 "net" 6 "os" 7 "strconv" 8 "strings" 9 "syscall" 10 "time" 11 12 "github.com/TugasAkhir-QUIC/quic-go/internal/protocol" 13 "github.com/TugasAkhir-QUIC/quic-go/internal/utils" 14 ) 15 16 // OOBCapablePacketConn is a connection that allows the reading of ECN bits from the IP header. 17 // If the PacketConn passed to Dial or Listen satisfies this interface, quic-go will use it. 18 // In this case, ReadMsgUDP() will be used instead of ReadFrom() to read packets. 19 type OOBCapablePacketConn interface { 20 net.PacketConn 21 SyscallConn() (syscall.RawConn, error) 22 SetReadBuffer(int) error 23 ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error) 24 WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) 25 } 26 27 var _ OOBCapablePacketConn = &net.UDPConn{} 28 29 func wrapConn(pc net.PacketConn) (rawConn, error) { 30 if err := setReceiveBuffer(pc); err != nil { 31 if !strings.Contains(err.Error(), "use of closed network connection") { 32 setBufferWarningOnce.Do(func() { 33 if disable, _ := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING")); disable { 34 return 35 } 36 log.Printf("%s. See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details.", err) 37 }) 38 } 39 } 40 if err := setSendBuffer(pc); err != nil { 41 if !strings.Contains(err.Error(), "use of closed network connection") { 42 setBufferWarningOnce.Do(func() { 43 if disable, _ := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING")); disable { 44 return 45 } 46 log.Printf("%s. See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details.", err) 47 }) 48 } 49 } 50 51 conn, ok := pc.(interface { 52 SyscallConn() (syscall.RawConn, error) 53 }) 54 var supportsDF bool 55 if ok { 56 rawConn, err := conn.SyscallConn() 57 if err != nil { 58 return nil, err 59 } 60 61 if _, ok := pc.LocalAddr().(*net.UDPAddr); ok { 62 // Only set DF on sockets that we expect to be able to handle that configuration. 63 var err error 64 supportsDF, err = setDF(rawConn) 65 if err != nil { 66 return nil, err 67 } 68 } 69 } 70 c, ok := pc.(OOBCapablePacketConn) 71 if !ok { 72 utils.DefaultLogger.Infof("PacketConn is not a net.UDPConn. Disabling optimizations possible on UDP connections.") 73 return &basicConn{PacketConn: pc, supportsDF: supportsDF}, nil 74 } 75 return newConn(c, supportsDF) 76 } 77 78 // The basicConn is the most trivial implementation of a rawConn. 79 // It reads a single packet from the underlying net.PacketConn. 80 // It is used when 81 // * the net.PacketConn is not a OOBCapablePacketConn, and 82 // * when the OS doesn't support OOB. 83 type basicConn struct { 84 net.PacketConn 85 supportsDF bool 86 } 87 88 var _ rawConn = &basicConn{} 89 90 func (c *basicConn) ReadPacket() (receivedPacket, error) { 91 buffer := getPacketBuffer() 92 // The packet size should not exceed protocol.MaxPacketBufferSize bytes 93 // If it does, we only read a truncated packet, which will then end up undecryptable 94 buffer.Data = buffer.Data[:protocol.MaxPacketBufferSize] 95 n, addr, err := c.PacketConn.ReadFrom(buffer.Data) 96 if err != nil { 97 return receivedPacket{}, err 98 } 99 return receivedPacket{ 100 remoteAddr: addr, 101 rcvTime: time.Now(), 102 data: buffer.Data[:n], 103 buffer: buffer, 104 }, nil 105 } 106 107 func (c *basicConn) WritePacket(b []byte, addr net.Addr, _ []byte, gsoSize uint16, ecn protocol.ECN) (n int, err error) { 108 if gsoSize != 0 { 109 panic("cannot use GSO with a basicConn") 110 } 111 if ecn != protocol.ECNUnsupported { 112 panic("cannot use ECN with a basicConn") 113 } 114 return c.PacketConn.WriteTo(b, addr) 115 } 116 117 func (c *basicConn) capabilities() connCapabilities { return connCapabilities{DF: c.supportsDF} }