2024-05-15 23:15:00 +00:00
|
|
|
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2022-03-10 09:44:48 +00:00
|
|
|
package ice
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pion/logging"
|
|
|
|
)
|
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
type udpMuxedConnState int
|
|
|
|
|
|
|
|
const (
|
|
|
|
udpMuxedConnOpen udpMuxedConnState = iota
|
|
|
|
udpMuxedConnWaiting
|
|
|
|
udpMuxedConnClosed
|
|
|
|
)
|
|
|
|
|
|
|
|
type udpMuxedConnAddr struct {
|
|
|
|
ip [16]byte
|
|
|
|
port uint16
|
|
|
|
}
|
|
|
|
|
|
|
|
func newUDPMuxedConnAddr(addr *net.UDPAddr) (a udpMuxedConnAddr) {
|
|
|
|
copy(a.ip[:], addr.IP.To16())
|
|
|
|
a.port = uint16(addr.Port)
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
2022-03-10 09:44:48 +00:00
|
|
|
type udpMuxedConnParams struct {
|
|
|
|
Mux *UDPMuxDefault
|
|
|
|
AddrPool *sync.Pool
|
|
|
|
Key string
|
|
|
|
LocalAddr net.Addr
|
|
|
|
Logger logging.LeveledLogger
|
|
|
|
}
|
|
|
|
|
|
|
|
// udpMuxedConn represents a logical packet conn for a single remote as identified by ufrag
|
|
|
|
type udpMuxedConn struct {
|
|
|
|
params *udpMuxedConnParams
|
2024-05-15 23:15:00 +00:00
|
|
|
// Remote addresses that we have sent to on this conn
|
2024-06-05 20:10:03 +00:00
|
|
|
addresses []udpMuxedConnAddr
|
2022-03-10 09:44:48 +00:00
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
// FIFO queue holding incoming packets
|
|
|
|
bufHead, bufTail *bufferHolder
|
|
|
|
notify chan struct{}
|
|
|
|
closedChan chan struct{}
|
|
|
|
state udpMuxedConnState
|
|
|
|
mu sync.Mutex
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func newUDPMuxedConn(params *udpMuxedConnParams) *udpMuxedConn {
|
2024-06-05 20:10:03 +00:00
|
|
|
return &udpMuxedConn{
|
2022-03-10 09:44:48 +00:00
|
|
|
params: params,
|
2024-06-05 20:10:03 +00:00
|
|
|
notify: make(chan struct{}, 1),
|
2022-03-10 09:44:48 +00:00
|
|
|
closedChan: make(chan struct{}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-15 23:15:00 +00:00
|
|
|
func (c *udpMuxedConn) ReadFrom(b []byte) (n int, rAddr net.Addr, err error) {
|
2024-06-05 20:10:03 +00:00
|
|
|
for {
|
|
|
|
c.mu.Lock()
|
|
|
|
if c.bufTail != nil {
|
|
|
|
pkt := c.bufTail
|
|
|
|
c.bufTail = pkt.next
|
|
|
|
|
|
|
|
if pkt == c.bufHead {
|
|
|
|
c.bufHead = nil
|
|
|
|
}
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
|
|
|
if len(b) < len(pkt.buf) {
|
|
|
|
err = io.ErrShortBuffer
|
|
|
|
} else {
|
|
|
|
n = copy(b, pkt.buf)
|
|
|
|
rAddr = pkt.addr
|
|
|
|
}
|
|
|
|
|
|
|
|
pkt.reset()
|
|
|
|
c.params.AddrPool.Put(pkt)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2022-03-10 09:44:48 +00:00
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
if c.state == udpMuxedConnClosed {
|
|
|
|
c.mu.Unlock()
|
|
|
|
return 0, nil, io.EOF
|
|
|
|
}
|
2022-03-10 09:44:48 +00:00
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
c.state = udpMuxedConnWaiting
|
|
|
|
c.mu.Unlock()
|
2022-03-10 09:44:48 +00:00
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
select {
|
|
|
|
case <-c.notify:
|
|
|
|
case <-c.closedChan:
|
|
|
|
return 0, nil, io.EOF
|
|
|
|
}
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-15 23:15:00 +00:00
|
|
|
func (c *udpMuxedConn) WriteTo(buf []byte, rAddr net.Addr) (n int, err error) {
|
2022-03-10 09:44:48 +00:00
|
|
|
if c.isClosed() {
|
|
|
|
return 0, io.ErrClosedPipe
|
|
|
|
}
|
2024-05-15 23:15:00 +00:00
|
|
|
// Each time we write to a new address, we'll register it with the mux
|
2024-06-05 20:10:03 +00:00
|
|
|
addr := newUDPMuxedConnAddr(rAddr.(*net.UDPAddr))
|
2022-03-10 09:44:48 +00:00
|
|
|
if !c.containsAddress(addr) {
|
|
|
|
c.addAddress(addr)
|
|
|
|
}
|
|
|
|
|
2024-05-15 23:15:00 +00:00
|
|
|
return c.params.Mux.writeTo(buf, rAddr)
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *udpMuxedConn) LocalAddr() net.Addr {
|
|
|
|
return c.params.LocalAddr
|
|
|
|
}
|
|
|
|
|
2024-05-15 23:15:00 +00:00
|
|
|
func (c *udpMuxedConn) SetDeadline(time.Time) error {
|
2022-03-10 09:44:48 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-05-15 23:15:00 +00:00
|
|
|
func (c *udpMuxedConn) SetReadDeadline(time.Time) error {
|
2022-03-10 09:44:48 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-05-15 23:15:00 +00:00
|
|
|
func (c *udpMuxedConn) SetWriteDeadline(time.Time) error {
|
2022-03-10 09:44:48 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *udpMuxedConn) CloseChannel() <-chan struct{} {
|
|
|
|
return c.closedChan
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *udpMuxedConn) Close() error {
|
2024-06-05 20:10:03 +00:00
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
if c.state != udpMuxedConnClosed {
|
|
|
|
for pkt := c.bufTail; pkt != nil; {
|
|
|
|
next := pkt.next
|
|
|
|
|
|
|
|
pkt.reset()
|
|
|
|
c.params.AddrPool.Put(pkt)
|
|
|
|
|
|
|
|
pkt = next
|
|
|
|
}
|
|
|
|
c.bufHead = nil
|
|
|
|
c.bufTail = nil
|
|
|
|
|
|
|
|
c.state = udpMuxedConnClosed
|
2022-03-10 09:44:48 +00:00
|
|
|
close(c.closedChan)
|
2024-06-05 20:10:03 +00:00
|
|
|
}
|
|
|
|
return nil
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *udpMuxedConn) isClosed() bool {
|
2024-06-05 20:10:03 +00:00
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
return c.state == udpMuxedConnClosed
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
func (c *udpMuxedConn) getAddresses() []udpMuxedConnAddr {
|
2022-03-10 09:44:48 +00:00
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
2024-06-05 20:10:03 +00:00
|
|
|
addresses := make([]udpMuxedConnAddr, len(c.addresses))
|
2022-03-10 09:44:48 +00:00
|
|
|
copy(addresses, c.addresses)
|
|
|
|
return addresses
|
|
|
|
}
|
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
func (c *udpMuxedConn) addAddress(addr udpMuxedConnAddr) {
|
2022-03-10 09:44:48 +00:00
|
|
|
c.mu.Lock()
|
|
|
|
c.addresses = append(c.addresses, addr)
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
2024-05-15 23:15:00 +00:00
|
|
|
// Map it on mux
|
2022-03-10 09:44:48 +00:00
|
|
|
c.params.Mux.registerConnForAddress(c, addr)
|
|
|
|
}
|
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
func (c *udpMuxedConn) removeAddress(addr udpMuxedConnAddr) {
|
2022-03-10 09:44:48 +00:00
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
newAddresses := make([]udpMuxedConnAddr, 0, len(c.addresses))
|
2022-03-10 09:44:48 +00:00
|
|
|
for _, a := range c.addresses {
|
|
|
|
if a != addr {
|
|
|
|
newAddresses = append(newAddresses, a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.addresses = newAddresses
|
|
|
|
}
|
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
func (c *udpMuxedConn) containsAddress(addr udpMuxedConnAddr) bool {
|
2022-03-10 09:44:48 +00:00
|
|
|
c.mu.Lock()
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
for _, a := range c.addresses {
|
|
|
|
if addr == a {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *udpMuxedConn) writePacket(data []byte, addr *net.UDPAddr) error {
|
2024-06-05 20:10:03 +00:00
|
|
|
pkt := c.params.AddrPool.Get().(*bufferHolder) //nolint:forcetypeassert
|
|
|
|
if cap(pkt.buf) < len(data) {
|
|
|
|
c.params.AddrPool.Put(pkt)
|
2022-03-10 09:44:48 +00:00
|
|
|
return io.ErrShortBuffer
|
|
|
|
}
|
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
pkt.buf = append(pkt.buf[:0], data...)
|
|
|
|
pkt.addr = addr
|
2022-03-10 09:44:48 +00:00
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
c.mu.Lock()
|
|
|
|
if c.state == udpMuxedConnClosed {
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
|
|
|
pkt.reset()
|
|
|
|
c.params.AddrPool.Put(pkt)
|
2022-03-10 09:44:48 +00:00
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
return io.ErrClosedPipe
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
2024-06-05 20:10:03 +00:00
|
|
|
|
|
|
|
if c.bufHead != nil {
|
|
|
|
c.bufHead.next = pkt
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
2024-06-05 20:10:03 +00:00
|
|
|
c.bufHead = pkt
|
2022-03-10 09:44:48 +00:00
|
|
|
|
2024-06-05 20:10:03 +00:00
|
|
|
if c.bufTail == nil {
|
|
|
|
c.bufTail = pkt
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
2024-06-05 20:10:03 +00:00
|
|
|
|
|
|
|
state := c.state
|
|
|
|
c.state = udpMuxedConnOpen
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
|
|
|
if state == udpMuxedConnWaiting {
|
|
|
|
select {
|
|
|
|
case c.notify <- struct{}{}:
|
|
|
|
default:
|
|
|
|
}
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|
2024-06-05 20:10:03 +00:00
|
|
|
|
|
|
|
return nil
|
2022-03-10 09:44:48 +00:00
|
|
|
}
|