github.com/tumi8/quic-go@v0.37.4-tum/send_conn.go (about)

     1  package quic
     2  
     3  import (
     4  	"math"
     5  	"net"
     6  
     7  	"github.com/tumi8/quic-go/noninternal/protocol"
     8  )
     9  
    10  // A sendConn allows sending using a simple Write() on a non-connected packet conn.
    11  type sendConn interface {
    12  	Write(b []byte, size protocol.ByteCount) error
    13  	Close() error
    14  	LocalAddr() net.Addr
    15  	RemoteAddr() net.Addr
    16  
    17  	capabilities() connCapabilities
    18  }
    19  
    20  type sconn struct {
    21  	rawConn
    22  
    23  	remoteAddr net.Addr
    24  	info       packetInfo
    25  	oob        []byte
    26  }
    27  
    28  var _ sendConn = &sconn{}
    29  
    30  func newSendConn(c rawConn, remote net.Addr) *sconn {
    31  	sc := &sconn{
    32  		rawConn:    c,
    33  		remoteAddr: remote,
    34  	}
    35  	if c.capabilities().GSO {
    36  		// add 32 bytes, so we can add the UDP_SEGMENT msg
    37  		sc.oob = make([]byte, 0, 32)
    38  	}
    39  	return sc
    40  }
    41  
    42  func newSendConnWithPacketInfo(c rawConn, remote net.Addr, info packetInfo) *sconn {
    43  	oob := info.OOB()
    44  	if c.capabilities().GSO {
    45  		// add 32 bytes, so we can add the UDP_SEGMENT msg
    46  		l := len(oob)
    47  		oob = append(oob, make([]byte, 32)...)
    48  		oob = oob[:l]
    49  	}
    50  	return &sconn{
    51  		rawConn:    c,
    52  		remoteAddr: remote,
    53  		info:       info,
    54  		oob:        oob,
    55  	}
    56  }
    57  
    58  func (c *sconn) Write(p []byte, size protocol.ByteCount) error {
    59  	if size > math.MaxUint16 {
    60  		panic("size overflow")
    61  	}
    62  	_, err := c.WritePacket(p, uint16(size), c.remoteAddr, c.oob)
    63  	return err
    64  }
    65  
    66  func (c *sconn) RemoteAddr() net.Addr {
    67  	return c.remoteAddr
    68  }
    69  
    70  func (c *sconn) LocalAddr() net.Addr {
    71  	addr := c.rawConn.LocalAddr()
    72  	if c.info.addr.IsValid() {
    73  		if udpAddr, ok := addr.(*net.UDPAddr); ok {
    74  			addrCopy := *udpAddr
    75  			addrCopy.IP = c.info.addr.AsSlice()
    76  			addr = &addrCopy
    77  		}
    78  	}
    79  	return addr
    80  }