Skip to content
/ turn Public
forked from gortc/turn

RFC 5766 TURN implementation in go

License

Notifications You must be signed in to change notification settings

godeep/turn

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status Master status Build status GoDoc codecov Go Report stability-beta FOSSA Status

TURN

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.

Example

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)
	}
}

Server for experiments

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!"}

Supported RFCs

  • 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

Testing

Client behavior is tested and verified in many ways:

  • End-To-End with long-term credentials
    • coturn: The coturn server (linux)
    • gortcd: The gortcd server (windows)
  • 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.

Benchmarks

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

About

RFC 5766 TURN implementation in go

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 96.2%
  • Shell 2.2%
  • Makefile 1.3%
  • Dockerfile 0.3%