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  }