Package turn implements TURN [RFC5766] Traversal Using Relays around NAT. Complies to gortc principles as core package. Based on gortc/stun package. See gortcd for TURN server.
If we have a TURN Server listening on example.com port 3478 (UDP) and know correct credentials, we can use it to relay data to peer which is listens on 10.0.0.1:34587 (UDP) and writing back any data it receives:
package main
import (
"flag"
"fmt"
"net"
"os"
"time"
"github.com/gortc/turn"
)
func main() {
// Resolving to TURN server.
raddr, err := net.ResolveUDPAddr("udp", "example.com:3478")
if err != nil {
panic(err)
}
c, err := net.DialUDP("udp", nil, raddr)
if err != nil {
panic(err)
}
client, clientErr := turn.NewClient(turn.ClientOptions{
Conn: c,
// Credentials:
Username: "user",
Password: "secret",
})
if clientErr != nil {
panic(clientErr)
}
a, allocErr := client.Allocate()
if allocErr != nil {
panic(allocErr)
}
peerAddr, resolveErr := net.ResolveUDPAddr("udp", "10.0.0.1:34587")
if resolveErr != nil {
panic(resolveErr)
}
permission, createErr := a.Create(peerAddr)
if createErr != nil {
panic(createErr)
}
// Permission implements net.Conn.
if _, writeRrr := fmt.Fprint(permission, "hello world!"); writeRrr != nil {
panic(peerAddr)
}
buf := make([]byte, 1500)
n, readErr := permission.Read(buf)
if readErr != nil {
panic(readErr)
}
fmt.Println("got message:", string(buf[:n]))
// Also you can use ChannelData messages to reduce overhead:
if err := permission.Bind(); err != nil {
panic(err)
}
}
You can use the turn.gortc.io:3478
gortcd TURN server instance for experiments.
The only allowed peer address is 127.0.0.1:56780
(that is running near the gortcd)
which will echo back any message it receives. Username is user
, password is secret
.
So just change example.com:3478
to turn.gortc.io:3478
and 10.0.0.1:34587
to 127.0.0.1:56780
in previous example and it should just work:
$ go get github.com/gortc/turn/cmd/turn-client
$ turn-client -server turn.gortc.io:3478 -peer 127.0.0.1:56780
0045 INFO dial server {"laddr": "192.168.88.10:36893", "raddr": "159.69.47.227:3478"}
0094 DEBUG multiplexer read {"n": 104}
0095 DEBUG multiplexer got STUN data
0095 DEBUG multiplexer stun message {"msg": "allocate error response l=84 attrs=5 id=PcPWfgQhiNnc7HR9"}
0144 DEBUG multiplexer read {"n": 140}
0144 DEBUG multiplexer got STUN data
0144 DEBUG multiplexer stun message {"msg": "allocate success response l=120 attrs=8 id=HNMg9zYhvO3D4wp8"}
0144 INFO allocated
0192 DEBUG multiplexer read {"n": 116}
0192 DEBUG multiplexer got STUN data
0192 DEBUG multiplexer stun message {"msg": "create permission success response l=96 attrs=6 id=NVfoJXcKV8VaHpvK"}
0193 DEBUG allocation.permission using STUN to write
0242 DEBUG multiplexer read {"n": 56}
0242 DEBUG multiplexer got STUN data
0242 DEBUG multiplexer stun message {"msg": "data indication l=36 attrs=3 id=RoZvzIOY3/NG9GkT"}
0242 INFO got message {"body": "hello world!"}
- RFC 5766 — Traversal Using Relays around NAT
- UDP transport for client
- TCP or TLS transport for client
- RFC 6156 — TURN Extension for IPv6
- RFC 7065 — TURN URI
- RFC 5928 — TURN Resolution Mechanism #13
- RFC 6062 — TURN Extension for TCP Allocations #14
Client behavior is tested and verified in many ways:
- End-To-End with long-term credentials
- Bunch of code static checkers (linters)
- Unit-tests (linux {amd64, arm64}, windows}
- Explicit API backward compatibility check, see
api
directory (relaxed until v1)
See TeamCity project and e2e
directory
for more information. Also the Wireshark .pcap
files are available for some of e2e tests in
artifacts for build.
goos: linux
goarch: amd64
pkg: github.com/gortc/turn
PASS
benchmark iter time/iter throughput bytes alloc allocs
--------- ---- --------- ---------- ----------- ------
BenchmarkIsChannelData-12 2000000000 1.64 ns/op 6694.29 MB/s 0 B/op 0 allocs/op
BenchmarkChannelData_Encode-12 200000000 9.11 ns/op 1317.35 MB/s 0 B/op 0 allocs/op
BenchmarkChannelData_Decode-12 500000000 3.92 ns/op 3061.45 MB/s 0 B/op 0 allocs/op
BenchmarkChannelNumber/AddTo-12 100000000 12.60 ns/op 0 B/op 0 allocs/op
BenchmarkChannelNumber/GetFrom-12 200000000 7.23 ns/op 0 B/op 0 allocs/op
BenchmarkData/AddTo-12 100000000 18.80 ns/op 0 B/op 0 allocs/op
BenchmarkData/AddToRaw-12 100000000 16.80 ns/op 0 B/op 0 allocs/op
BenchmarkLifetime/AddTo-12 100000000 13.70 ns/op 0 B/op 0 allocs/op
BenchmarkLifetime/GetFrom-12 200000000 7.10 ns/op 0 B/op 0 allocs/op
ok github.com/gortc/turn 19.110s