Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 80 additions & 4 deletions candidate_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
"strings"
"sync"
"sync/atomic"
"syscall"
"time"

"github.com/pion/stun/v3"
"github.com/pion/transport/v3"
)

type candidateBase struct {
Expand Down Expand Up @@ -240,8 +242,12 @@
return
}

c.enableSocketOptions()
oob := make([]byte, 128) // buffer for out of band packet attributes
attr := transport.NewPacketAttributesWithLen(1)

Check failure on line 247 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

undefined: transport.NewPacketAttributesWithLen

Check failure on line 247 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

undefined: transport.NewPacketAttributesWithLen

Check failure on line 247 in candidate_base.go

View workflow job for this annotation

GitHub Actions / lint / Go

undefined: transport.NewPacketAttributesWithLen

Check failure on line 247 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.NewPacketAttributesWithLen

Check failure on line 247 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.NewPacketAttributesWithLen

Check failure on line 247 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.NewPacketAttributesWithLen

Check failure on line 247 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.NewPacketAttributesWithLen
for {
n, srcAddr, err := c.conn.ReadFrom(buf)
attr.Reset()
n, srcAddr, err := c.readPacketWithAttributes(buf, oob, attr)
if err != nil {
if !errors.Is(err, io.EOF) && !errors.Is(err, net.ErrClosed) {
agent.log.Warnf("Failed to read from candidate %s: %v", c, err)
Expand All @@ -250,10 +256,80 @@
return
}

c.handleInboundPacket(buf[:n], srcAddr)
c.handleInboundPacket(buf[:n], attr.GetReadPacketAttributes(), srcAddr)
}
}

func (c *candidateBase) enableSocketOptions() {
if uc, ok := c.conn.(*net.UDPConn); ok {
raw, _ := uc.SyscallConn()
_ = raw.Control(func(fd uintptr) {
syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_RECVTOS, 1) // TOS/ECN

Check failure on line 267 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

undefined: syscall.IP_RECVTOS

Check failure on line 267 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

undefined: syscall.IP_RECVTOS
})
}
}

// Reads a packet including its out of band attributes like ECN
// if the underlying conn supports it.
func (c *candidateBase) readPacketWithAttributes(
buf []byte, oob []byte, attr *transport.PacketAttributes) (n int, srcAddr net.Addr, err error) {

Check failure on line 275 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

undefined: transport.PacketAttributes

Check failure on line 275 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

undefined: transport.PacketAttributes

Check failure on line 275 in candidate_base.go

View workflow job for this annotation

GitHub Actions / lint / Go

undefined: transport.PacketAttributes

Check failure on line 275 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.PacketAttributes

Check failure on line 275 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.PacketAttributes

Check failure on line 275 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.PacketAttributes

Check failure on line 275 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.PacketAttributes
var uc *net.UDPConn
var ok bool

// in case the underlying socket is not udp socket (not a net.UDPConn)
if uc, ok = c.conn.(*net.UDPConn); !ok {
n, srcAddr, err = c.conn.ReadFrom(buf)
return
}

return c.doReadPacketWithAttributes(buf, oob, attr, uc)
}

// Reads a packet including its out of band attributes like ECN if possible.
func (c *candidateBase) doReadPacketWithAttributes(
buf []byte, oob []byte, attr *transport.PacketAttributes, uc *net.UDPConn) (n int, srcAddr net.Addr, err error) {

Check failure on line 290 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

undefined: transport.PacketAttributes

Check failure on line 290 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

undefined: transport.PacketAttributes

Check failure on line 290 in candidate_base.go

View workflow job for this annotation

GitHub Actions / lint / Go

undefined: transport.PacketAttributes

Check failure on line 290 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.PacketAttributes

Check failure on line 290 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.PacketAttributes

Check failure on line 290 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.PacketAttributes

Check failure on line 290 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.PacketAttributes
var oobn int
var flags int
var udpAddr *net.UDPAddr
n, oobn, flags, udpAddr, err = uc.ReadMsgUDP(buf, oob)
srcAddr = udpAddr

if oobn <= 0 {
return
}

_ = flags

// Parse control messages for ECN/TOS
cms, err := syscall.ParseSocketControlMessage(oob[:oobn])
if err != nil {
return
}

for _, cm := range cms {
// IPv4 TOS
if cm.Header.Level == syscall.IPPROTO_IP && cm.Header.Type == syscall.IP_TOS {
if len(cm.Data) > 0 {
tos := cm.Data[0]
ecn := tos & 0x03 // ECN is the two least significant bits
attr.Buffer[0] = ecn
attr.BytesCopied = 1
}
}
// IPv6 Traffic Class
if cm.Header.Level == syscall.IPPROTO_IPV6 && cm.Header.Type == syscall.IPV6_TCLASS {
if len(cm.Data) > 0 {
tos := cm.Data[0]
ecn := tos & 0x03 // ECN is the two least significant bits
attr.Buffer[0] = ecn
attr.BytesCopied = 1
}
}
}

return
}

func (c *candidateBase) validateSTUNTrafficCache(addr net.Addr) bool {
if candidate, ok := c.remoteCandidateCaches[toAddrPort(addr)]; ok {
candidate.seen(false)
Expand All @@ -271,7 +347,7 @@
c.remoteCandidateCaches[toAddrPort(srcAddr)] = candidate
}

func (c *candidateBase) handleInboundPacket(buf []byte, srcAddr net.Addr) {
func (c *candidateBase) handleInboundPacket(buf []byte, attr *transport.PacketAttributes, srcAddr net.Addr) {

Check failure on line 350 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

undefined: transport.PacketAttributes

Check failure on line 350 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

undefined: transport.PacketAttributes

Check failure on line 350 in candidate_base.go

View workflow job for this annotation

GitHub Actions / lint / Go

undefined: transport.PacketAttributes

Check failure on line 350 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.PacketAttributes

Check failure on line 350 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.PacketAttributes
agent := c.agent()

if stun.IsMessage(buf) {
Expand Down Expand Up @@ -309,7 +385,7 @@
}

// Note: This will return packetio.ErrFull if the buffer ever manages to fill up.
n, err := agent.buf.Write(buf)
n, err := agent.buf.WriteWithAttributes(buf, attr)

Check failure on line 388 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

agent.buf.WriteWithAttributes undefined (type *packetio.Buffer has no field or method WriteWithAttributes)

Check failure on line 388 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

agent.buf.WriteWithAttributes undefined (type *packetio.Buffer has no field or method WriteWithAttributes)

Check failure on line 388 in candidate_base.go

View workflow job for this annotation

GitHub Actions / lint / Go

agent.buf.WriteWithAttributes undefined (type *packetio.Buffer has no field or method WriteWithAttributes)

Check failure on line 388 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

agent.buf.WriteWithAttributes undefined (type *packetio.Buffer has no field or method WriteWithAttributes)

Check failure on line 388 in candidate_base.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

agent.buf.WriteWithAttributes undefined (type *packetio.Buffer has no field or method WriteWithAttributes)
if err != nil {
agent.log.Warnf("Failed to write packet: %s", err)

Expand Down
14 changes: 14 additions & 0 deletions transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"time"

"github.com/pion/stun/v3"
"github.com/pion/transport/v3"
)

// Dial connects to the remote agent, acting as the controlling ice agent.
Expand Down Expand Up @@ -79,6 +80,19 @@
return n, err
}

// ReadWithAttributes implements the Conn ReadWithAttributes method.
func (c *Conn) ReadWithAttributes(b []byte, attr *transport.PacketAttributes) (n int, err error) {

Check failure on line 84 in transport.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

undefined: transport.PacketAttributes

Check failure on line 84 in transport.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

undefined: transport.PacketAttributes

Check failure on line 84 in transport.go

View workflow job for this annotation

GitHub Actions / lint / Go

undefined: transport.PacketAttributes

Check failure on line 84 in transport.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

undefined: transport.PacketAttributes

Check failure on line 84 in transport.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

undefined: transport.PacketAttributes
err = c.agent.loop.Err()
if err != nil {
return 0, err
}

n, err = c.agent.buf.ReadWithAttributes(b, attr)

Check failure on line 90 in transport.go

View workflow job for this annotation

GitHub Actions / test-macos (1.24) / Go macOS 1.24

c.agent.buf.ReadWithAttributes undefined (type *packetio.Buffer has no field or method ReadWithAttributes)

Check failure on line 90 in transport.go

View workflow job for this annotation

GitHub Actions / test-macos (1.25) / Go macOS 1.25

c.agent.buf.ReadWithAttributes undefined (type *packetio.Buffer has no field or method ReadWithAttributes)

Check failure on line 90 in transport.go

View workflow job for this annotation

GitHub Actions / lint / Go

c.agent.buf.ReadWithAttributes undefined (type *packetio.Buffer has no field or method ReadWithAttributes)) (typecheck)

Check failure on line 90 in transport.go

View workflow job for this annotation

GitHub Actions / test (1.24) / Go 1.24

c.agent.buf.ReadWithAttributes undefined (type *packetio.Buffer has no field or method ReadWithAttributes)

Check failure on line 90 in transport.go

View workflow job for this annotation

GitHub Actions / test (1.25) / Go 1.25

c.agent.buf.ReadWithAttributes undefined (type *packetio.Buffer has no field or method ReadWithAttributes)
c.bytesReceived.Add(uint64(n)) //nolint:gosec // G115

return n, err
}

// Write implements the Conn Write method.
func (c *Conn) Write(packet []byte) (int, error) {
err := c.agent.loop.Err()
Expand Down
Loading