github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/conn.go (about) 1 package quic 2 3 import ( 4 "io" 5 "net" 6 "syscall" 7 "time" 8 9 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol" 10 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/utils" 11 ) 12 13 type connection interface { 14 ReadPacket() (*receivedPacket, error) 15 WritePacket(b []byte, addr net.Addr, oob []byte) (int, error) 16 LocalAddr() net.Addr 17 io.Closer 18 } 19 20 // If the PacketConn passed to Dial or Listen satisfies this interface, quic-go will read the ECN bits from the IP header. 21 // In this case, ReadMsgUDP() will be used instead of ReadFrom() to read packets. 22 type OOBCapablePacketConn interface { 23 net.PacketConn 24 SyscallConn() (syscall.RawConn, error) 25 ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error) 26 WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) 27 } 28 29 var _ OOBCapablePacketConn = &net.UDPConn{} 30 31 func wrapConn(pc net.PacketConn) (connection, error) { 32 conn, ok := pc.(interface { 33 SyscallConn() (syscall.RawConn, error) 34 }) 35 if ok { 36 rawConn, err := conn.SyscallConn() 37 if err != nil { 38 return nil, err 39 } 40 err = setDF(rawConn) 41 if err != nil { 42 return nil, err 43 } 44 } 45 c, ok := pc.(OOBCapablePacketConn) 46 if !ok { 47 utils.DefaultLogger.Infof("PacketConn is not a net.UDPConn. Disabling optimizations possible on UDP connections.") 48 return &basicConn{PacketConn: pc}, nil 49 } 50 return newConn(c) 51 } 52 53 type basicConn struct { 54 net.PacketConn 55 } 56 57 var _ connection = &basicConn{} 58 59 func (c *basicConn) ReadPacket() (*receivedPacket, error) { 60 buffer := getPacketBuffer() 61 // The packet size should not exceed protocol.MaxPacketBufferSize bytes 62 // If it does, we only read a truncated packet, which will then end up undecryptable 63 buffer.Data = buffer.Data[:protocol.MaxPacketBufferSize] 64 n, addr, err := c.PacketConn.ReadFrom(buffer.Data) 65 if err != nil { 66 return nil, err 67 } 68 return &receivedPacket{ 69 remoteAddr: addr, 70 rcvTime: time.Now(), 71 data: buffer.Data[:n], 72 buffer: buffer, 73 }, nil 74 } 75 76 func (c *basicConn) WritePacket(b []byte, addr net.Addr, _ []byte) (n int, err error) { 77 return c.PacketConn.WriteTo(b, addr) 78 }