Files
netbird/relay/teste2c/turn.go
Zoltán Papp b31f25ec70 Add test code
2024-08-12 15:32:01 +02:00

157 lines
3.2 KiB
Go

package main
import (
"fmt"
"net"
"time"
"github.com/pion/logging"
"github.com/pion/turn/v3"
log "github.com/sirupsen/logrus"
)
type TurnConn struct {
conn net.Conn
turnClient *turn.Client
relayConn net.PacketConn
}
func (tc *TurnConn) Address() net.Addr {
return tc.relayConn.LocalAddr()
}
func (tc *TurnConn) Close() {
_ = tc.relayConn.Close()
tc.turnClient.Close()
_ = tc.conn.Close()
}
func AllocateTurnClient(serverAddr string) *TurnConn {
conn, err := net.Dial("tcp", serverAddr)
if err != nil {
log.Fatal(err)
}
turnClient, err := getTurnClient(serverAddr, conn)
if err != nil {
log.Fatal(err)
}
relayConn, err := turnClient.Allocate()
if err != nil {
log.Fatal(err)
}
return &TurnConn{
conn: conn,
turnClient: turnClient,
relayConn: relayConn,
}
}
func (tc *TurnConn) WriteTestData(testData []byte, dstAddr net.Addr) {
log.Infof("write test data to: %s", dstAddr)
testDataSize := len(testData)
si := NewStartInidication(time.Now(), testDataSize)
_, err := tc.relayConn.WriteTo(si, dstAddr)
if err != nil {
log.Errorf("failed to write to: %s, %s", dstAddr, err)
return
}
pieceSize := 1024
ackBuff := make([]byte, 1)
pipelineSize := 10
for j := 0; j < testDataSize; j += pieceSize {
end := j + pieceSize
if end > testDataSize {
end = testDataSize
}
_, err := tc.relayConn.WriteTo(testData[j:end], dstAddr)
if err != nil {
log.Fatalf("failed to write to channel: %s", err)
}
if pipelineSize == 0 {
_, _, _ = tc.relayConn.ReadFrom(ackBuff)
} else {
pipelineSize--
}
}
}
func getTurnClient(address string, conn net.Conn) (*turn.Client, error) {
// Dial TURN Server
addrStr := fmt.Sprintf("%s:%d", address, 443)
fac := logging.NewDefaultLoggerFactory()
//fac.DefaultLogLevel = logging.LogLevelTrace
// Start a new TURN Client and wrap our net.Conn in a STUNConn
// This allows us to simulate datagram based communication over a net.Conn
cfg := &turn.ClientConfig{
TURNServerAddr: address,
Conn: turn.NewSTUNConn(conn),
Username: "test",
Password: "test",
LoggerFactory: fac,
}
client, err := turn.NewClient(cfg)
if err != nil {
return nil, fmt.Errorf("failed to create TURN client for server %s: %s", addrStr, err)
}
// Start listening on the conn provided.
err = client.Listen()
if err != nil {
client.Close()
return nil, fmt.Errorf("failed to listen on TURN client for server %s: %s", addrStr, err)
}
return client, nil
}
type UDPConn struct {
net.Conn
}
func Dial(addr string) (*UDPConn, error) {
conn, err := net.Dial("udp", addr)
if err != nil {
return nil, err
}
return &UDPConn{conn}, nil
}
func (c UDPConn) ReadTestData(c2 *UDPConn) time.Duration {
log.Infof("reading test data from TURN relay")
var (
tb int
ack = make([]byte, 1)
)
buff := make([]byte, 8192)
n, err := c.Conn.Read(buff)
if err != nil {
log.Errorf("failed to read from channel: %s", err)
return 0
}
si := DecodeStartIndication(buff[:n])
log.Infof("received start indication: %v", si)
for {
n, e := c.Conn.Read(buff)
if e != nil {
return 0
}
tb += n
_, _ = c.Conn.Write(ack)
if tb >= si.TransferSize {
break
}
}
return time.Since(si.Started)
}