mirror of
https://github.com/hanzokms/turn.git
synced 2026-10-30 20:50:36 +00:00
117 lines
2.9 KiB
Go
117 lines
2.9 KiB
Go
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package turn
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/pion/randutil"
|
|
"github.com/pion/transport/v3"
|
|
"github.com/pion/transport/v3/stdnet"
|
|
)
|
|
|
|
// RelayAddressGeneratorPortRange can be used to only allocate connections inside a defined port range.
|
|
// Similar to the RelayAddressGeneratorStatic a static ip address can be set.
|
|
type RelayAddressGeneratorPortRange struct {
|
|
// RelayAddress is the IP returned to the user when the relay is created
|
|
RelayAddress net.IP
|
|
|
|
// MinPort the minimum port to allocate
|
|
MinPort uint16
|
|
// MaxPort the maximum (inclusive) port to allocate
|
|
MaxPort uint16
|
|
|
|
// MaxRetries the amount of tries to allocate a random port in the defined range
|
|
MaxRetries int
|
|
|
|
// Rand the random source of numbers
|
|
Rand randutil.MathRandomGenerator
|
|
|
|
// Address is passed to Listen/ListenPacket when creating the Relay
|
|
Address string
|
|
|
|
Net transport.Net
|
|
}
|
|
|
|
// Validate is called on server startup and confirms the RelayAddressGenerator is properly configured.
|
|
func (r *RelayAddressGeneratorPortRange) Validate() error {
|
|
if r.Net == nil {
|
|
var err error
|
|
r.Net, err = stdnet.NewNet()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create network: %w", err)
|
|
}
|
|
}
|
|
|
|
if r.Rand == nil {
|
|
r.Rand = randutil.NewMathRandomGenerator()
|
|
}
|
|
|
|
if r.MaxRetries == 0 {
|
|
r.MaxRetries = 10
|
|
}
|
|
|
|
switch {
|
|
case r.MinPort == 0:
|
|
return errMinPortNotZero
|
|
case r.MaxPort == 0:
|
|
return errMaxPortNotZero
|
|
case r.RelayAddress == nil:
|
|
return errRelayAddressInvalid
|
|
case r.Address == "":
|
|
return errListeningAddressInvalid
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// AllocatePacketConn generates a new PacketConn to receive traffic on and the IP/Port
|
|
// to populate the allocation response with.
|
|
func (r *RelayAddressGeneratorPortRange) AllocatePacketConn(
|
|
network string,
|
|
requestedPort int,
|
|
) (net.PacketConn, net.Addr, error) {
|
|
if requestedPort != 0 {
|
|
conn, err := r.Net.ListenPacket(network, fmt.Sprintf("%s:%d", r.Address, requestedPort))
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
relayAddr, ok := conn.LocalAddr().(*net.UDPAddr)
|
|
if !ok {
|
|
return nil, nil, errNilConn
|
|
}
|
|
|
|
relayAddr.IP = r.RelayAddress
|
|
|
|
return conn, relayAddr, nil
|
|
}
|
|
|
|
for try := 0; try < r.MaxRetries; try++ {
|
|
port := r.MinPort + uint16(r.Rand.Intn(int((r.MaxPort+1)-r.MinPort))) // nolint:gosec // G115 false positive
|
|
conn, err := r.Net.ListenPacket(network, fmt.Sprintf("%s:%d", r.Address, port))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
relayAddr, ok := conn.LocalAddr().(*net.UDPAddr)
|
|
if !ok {
|
|
return nil, nil, errNilConn
|
|
}
|
|
|
|
relayAddr.IP = r.RelayAddress
|
|
|
|
return conn, relayAddr, nil
|
|
}
|
|
|
|
return nil, nil, errMaxRetriesExceeded
|
|
}
|
|
|
|
// AllocateConn generates a new Conn to receive traffic on and the IP/Port
|
|
// to populate the allocation response with.
|
|
func (r *RelayAddressGeneratorPortRange) AllocateConn(string, int) (net.Conn, net.Addr, error) {
|
|
return nil, nil, errTODO
|
|
}
|