status-go/vendor/github.com/pion/ice/v2/udp_muxed_conn.go

249 lines
4.6 KiB
Go
Raw Normal View History

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
}