|
|
|
@ -322,11 +322,6 @@ type Conn struct {
|
|
|
|
|
// bind is the wireguard-go conn.Bind for Conn.
|
|
|
|
|
bind *connBind
|
|
|
|
|
|
|
|
|
|
// ippEndpoint4 and ippEndpoint6 are owned by receiveIPv4 and
|
|
|
|
|
// receiveIPv6, respectively, to cache an IPPort->endpoint for
|
|
|
|
|
// hot flows.
|
|
|
|
|
ippEndpoint4, ippEndpoint6 ippEndpointCache
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
// Fields that must be accessed via atomic load/stores.
|
|
|
|
|
|
|
|
|
@ -1851,80 +1846,64 @@ func (c *Conn) putReceiveBatch(batch *receiveBatch) {
|
|
|
|
|
c.receiveBatchPool.Put(batch)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Conn) receiveIPv6(buffs [][]byte, sizes []int, eps []conn.Endpoint) (int, error) {
|
|
|
|
|
health.ReceiveIPv6.Enter()
|
|
|
|
|
defer health.ReceiveIPv6.Exit()
|
|
|
|
|
// receiveIPv4 creates an IPv4 ReceiveFunc reading from c.pconn4.
|
|
|
|
|
func (c *Conn) receiveIPv4() conn.ReceiveFunc {
|
|
|
|
|
return c.mkReceiveFunc(&c.pconn4, &health.ReceiveIPv4, metricRecvDataIPv4)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
batch := c.getReceiveBatchForBuffs(buffs)
|
|
|
|
|
defer c.putReceiveBatch(batch)
|
|
|
|
|
for {
|
|
|
|
|
numMsgs, err := c.pconn6.ReadBatch(batch.msgs[:len(buffs)], 0)
|
|
|
|
|
if err != nil {
|
|
|
|
|
if neterror.PacketWasTruncated(err) {
|
|
|
|
|
// TODO(raggi): discuss whether to log?
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
// receiveIPv6 creates an IPv6 ReceiveFunc reading from c.pconn6.
|
|
|
|
|
func (c *Conn) receiveIPv6() conn.ReceiveFunc {
|
|
|
|
|
return c.mkReceiveFunc(&c.pconn6, &health.ReceiveIPv6, metricRecvDataIPv6)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reportToCaller := false
|
|
|
|
|
for i, msg := range batch.msgs[:numMsgs] {
|
|
|
|
|
if msg.N == 0 {
|
|
|
|
|
sizes[i] = 0
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
ipp := msg.Addr.(*net.UDPAddr).AddrPort()
|
|
|
|
|
if ep, ok := c.receiveIP(msg.Buffers[0][:msg.N], ipp, &c.ippEndpoint6); ok {
|
|
|
|
|
metricRecvDataIPv6.Add(1)
|
|
|
|
|
eps[i] = ep
|
|
|
|
|
sizes[i] = msg.N
|
|
|
|
|
reportToCaller = true
|
|
|
|
|
} else {
|
|
|
|
|
sizes[i] = 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// mkReceiveFunc creates a ReceiveFunc reading from ruc.
|
|
|
|
|
// The provided healthItem and metric are updated if non-nil.
|
|
|
|
|
func (c *Conn) mkReceiveFunc(ruc *RebindingUDPConn, healthItem *health.ReceiveFuncStats, metric *clientmetric.Metric) conn.ReceiveFunc {
|
|
|
|
|
// epCache caches an IPPort->endpoint for hot flows.
|
|
|
|
|
var epCache ippEndpointCache
|
|
|
|
|
|
|
|
|
|
if reportToCaller {
|
|
|
|
|
return numMsgs, nil
|
|
|
|
|
return func(buffs [][]byte, sizes []int, eps []conn.Endpoint) (int, error) {
|
|
|
|
|
if healthItem != nil {
|
|
|
|
|
healthItem.Enter()
|
|
|
|
|
defer healthItem.Exit()
|
|
|
|
|
}
|
|
|
|
|
if ruc == nil {
|
|
|
|
|
panic("nil RebindingUDPConn")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Conn) receiveIPv4(buffs [][]byte, sizes []int, eps []conn.Endpoint) (int, error) {
|
|
|
|
|
health.ReceiveIPv4.Enter()
|
|
|
|
|
defer health.ReceiveIPv4.Exit()
|
|
|
|
|
|
|
|
|
|
batch := c.getReceiveBatchForBuffs(buffs)
|
|
|
|
|
defer c.putReceiveBatch(batch)
|
|
|
|
|
for {
|
|
|
|
|
numMsgs, err := c.pconn4.ReadBatch(batch.msgs[:len(buffs)], 0)
|
|
|
|
|
if err != nil {
|
|
|
|
|
if neterror.PacketWasTruncated(err) {
|
|
|
|
|
// TODO(raggi): discuss whether to log?
|
|
|
|
|
continue
|
|
|
|
|
batch := c.getReceiveBatchForBuffs(buffs)
|
|
|
|
|
defer c.putReceiveBatch(batch)
|
|
|
|
|
for {
|
|
|
|
|
numMsgs, err := ruc.ReadBatch(batch.msgs[:len(buffs)], 0)
|
|
|
|
|
if err != nil {
|
|
|
|
|
if neterror.PacketWasTruncated(err) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reportToCaller := false
|
|
|
|
|
for i, msg := range batch.msgs[:numMsgs] {
|
|
|
|
|
if msg.N == 0 {
|
|
|
|
|
sizes[i] = 0
|
|
|
|
|
continue
|
|
|
|
|
reportToCaller := false
|
|
|
|
|
for i, msg := range batch.msgs[:numMsgs] {
|
|
|
|
|
if msg.N == 0 {
|
|
|
|
|
sizes[i] = 0
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
ipp := msg.Addr.(*net.UDPAddr).AddrPort()
|
|
|
|
|
if ep, ok := c.receiveIP(msg.Buffers[0][:msg.N], ipp, &epCache); ok {
|
|
|
|
|
if metric != nil {
|
|
|
|
|
metric.Add(1)
|
|
|
|
|
}
|
|
|
|
|
eps[i] = ep
|
|
|
|
|
sizes[i] = msg.N
|
|
|
|
|
reportToCaller = true
|
|
|
|
|
} else {
|
|
|
|
|
sizes[i] = 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ipp := msg.Addr.(*net.UDPAddr).AddrPort()
|
|
|
|
|
if ep, ok := c.receiveIP(msg.Buffers[0][:msg.N], ipp, &c.ippEndpoint4); ok {
|
|
|
|
|
metricRecvDataIPv4.Add(1)
|
|
|
|
|
eps[i] = ep
|
|
|
|
|
sizes[i] = msg.N
|
|
|
|
|
reportToCaller = true
|
|
|
|
|
} else {
|
|
|
|
|
sizes[i] = 0
|
|
|
|
|
if reportToCaller {
|
|
|
|
|
return numMsgs, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if reportToCaller {
|
|
|
|
|
return numMsgs, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3044,7 +3023,7 @@ func (c *connBind) Open(ignoredPort uint16) ([]conn.ReceiveFunc, uint16, error)
|
|
|
|
|
return nil, 0, errors.New("magicsock: connBind already open")
|
|
|
|
|
}
|
|
|
|
|
c.closed = false
|
|
|
|
|
fns := []conn.ReceiveFunc{c.receiveIPv4, c.receiveIPv6, c.receiveDERP}
|
|
|
|
|
fns := []conn.ReceiveFunc{c.receiveIPv4(), c.receiveIPv6(), c.receiveDERP}
|
|
|
|
|
if runtime.GOOS == "js" {
|
|
|
|
|
fns = []conn.ReceiveFunc{c.receiveDERP}
|
|
|
|
|
}
|
|
|
|
|