mirror of
https://github.com/coder/coder.git
synced 2025-07-08 11:39:50 +00:00
feat: Add TURN proxying to enable offline deployments (#1000)
* Add turnconn * Add option for passing ICE servers * Log TURN remote address * Add TURN server to coder start
This commit is contained in:
106
coderd/turnconn/turnconn_test.go
Normal file
106
coderd/turnconn/turnconn_test.go
Normal file
@ -0,0 +1,106 @@
|
||||
package turnconn_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
"cdr.dev/slog"
|
||||
"cdr.dev/slog/sloggers/slogtest"
|
||||
"github.com/coder/coder/coderd/turnconn"
|
||||
"github.com/coder/coder/peer"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
goleak.VerifyTestMain(m)
|
||||
}
|
||||
|
||||
func TestTURNConn(t *testing.T) {
|
||||
t.Parallel()
|
||||
turnServer, err := turnconn.New(nil)
|
||||
require.NoError(t, err)
|
||||
defer turnServer.Close()
|
||||
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
|
||||
clientDialer, clientTURN := net.Pipe()
|
||||
turnServer.Accept(clientTURN, &net.TCPAddr{
|
||||
IP: net.IPv4(127, 0, 0, 1),
|
||||
Port: 16000,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
clientSettings := webrtc.SettingEngine{}
|
||||
clientSettings.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4, webrtc.NetworkTypeTCP6})
|
||||
clientSettings.SetRelayAcceptanceMinWait(0)
|
||||
clientSettings.SetICEProxyDialer(turnconn.ProxyDialer(func() (net.Conn, error) {
|
||||
return clientDialer, nil
|
||||
}))
|
||||
client, err := peer.Client([]webrtc.ICEServer{turnconn.Proxy}, &peer.ConnOptions{
|
||||
SettingEngine: clientSettings,
|
||||
Logger: logger.Named("client"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
serverDialer, serverTURN := net.Pipe()
|
||||
turnServer.Accept(serverTURN, &net.TCPAddr{
|
||||
IP: net.IPv4(127, 0, 0, 1),
|
||||
Port: 16001,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
serverSettings := webrtc.SettingEngine{}
|
||||
serverSettings.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4, webrtc.NetworkTypeTCP6})
|
||||
serverSettings.SetRelayAcceptanceMinWait(0)
|
||||
serverSettings.SetICEProxyDialer(turnconn.ProxyDialer(func() (net.Conn, error) {
|
||||
return serverDialer, nil
|
||||
}))
|
||||
server, err := peer.Server([]webrtc.ICEServer{turnconn.Proxy}, &peer.ConnOptions{
|
||||
SettingEngine: serverSettings,
|
||||
Logger: logger.Named("server"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
exchange(t, client, server)
|
||||
|
||||
_, err = client.Ping()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func exchange(t *testing.T, client, server *peer.Conn) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
t.Cleanup(func() {
|
||||
_ = client.Close()
|
||||
_ = server.Close()
|
||||
|
||||
wg.Wait()
|
||||
})
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for {
|
||||
select {
|
||||
case c := <-server.LocalCandidate():
|
||||
client.AddRemoteCandidate(c)
|
||||
case c := <-server.LocalSessionDescription():
|
||||
client.SetRemoteSessionDescription(c)
|
||||
case <-server.Closed():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for {
|
||||
select {
|
||||
case c := <-client.LocalCandidate():
|
||||
server.AddRemoteCandidate(c)
|
||||
case c := <-client.LocalSessionDescription():
|
||||
server.SetRemoteSessionDescription(c)
|
||||
case <-client.Closed():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
Reference in New Issue
Block a user