Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

feat: Use internal TURN server for proxying #322

Merged
merged 3 commits into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion agent/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ func (s *stream) processMessage(msg proto.Message) {
}

if msg.Offer != nil {
rtc, err := xwebrtc.NewPeerConnection()
if msg.Servers == nil {
s.fatal(fmt.Errorf("servers must be sent with offer"))
return
}
rtc, err := xwebrtc.NewPeerConnection(msg.Servers)
if err != nil {
s.fatal(fmt.Errorf("create connection: %w", err))
return
Expand Down
30 changes: 20 additions & 10 deletions internal/cmd/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io"
"net"
"net/url"
"os"
"strconv"
"time"
Expand Down Expand Up @@ -57,7 +58,7 @@ coder tunnel my-dev 3000 3000
}
baseURL := sdk.BaseURL()

envs, err := sdk.Environments(ctx)
envs, err := getEnvs(ctx, sdk, coder.Me)
if err != nil {
return err
}
Expand All @@ -79,8 +80,8 @@ coder tunnel my-dev 3000 3000
localPort: uint16(localPort),
remotePort: uint16(remotePort),
ctx: context.Background(),
logger: log,
brokerAddr: baseURL.String(),
logger: log.Leveled(slog.LevelDebug),
brokerAddr: baseURL,
token: sdk.Token(),
}

Expand All @@ -98,7 +99,7 @@ coder tunnel my-dev 3000 3000

type client struct {
ctx context.Context
brokerAddr string
brokerAddr url.URL
token string
logger slog.Logger
id string
Expand All @@ -108,9 +109,9 @@ type client struct {
}

func (c *client) start() error {
url := fmt.Sprintf("%s%s%s%s%s", c.brokerAddr, "/api/private/envagent/", c.id, "/connect?session_token=", c.token)
c.logger.Info(c.ctx, "connecting to broker", slog.F("url", url))

url := fmt.Sprintf("%s%s%s%s%s", c.brokerAddr.String(), "/api/private/envagent/", c.id, "/connect?session_token=", c.token)
tcpProxy := fmt.Sprintf("turns:%s:5349?transport=tcp", c.brokerAddr.Host)
c.logger.Info(c.ctx, "connecting to broker", slog.F("url", url), slog.F("tcp-proxy", tcpProxy))
conn, resp, err := websocket.Dial(c.ctx, url, nil)
if err != nil && resp == nil {
return fmt.Errorf("dial: %w", err)
Expand All @@ -122,7 +123,15 @@ func (c *client) start() error {
}
nconn := websocket.NetConn(context.Background(), conn, websocket.MessageBinary)

rtc, err := xwebrtc.NewPeerConnection()
// Only enabled under a private feature flag for now,
// so insecure connections are entirely fine to allow.
servers := []webrtc.ICEServer{{
URLs: []string{tcpProxy},
Username: "insecure",
Credential: "pass",
CredentialType: webrtc.ICECredentialTypePassword,
}}
rtc, err := xwebrtc.NewPeerConnection(servers)
if err != nil {
return fmt.Errorf("create connection: %w", err)
}
Expand Down Expand Up @@ -150,16 +159,17 @@ func (c *client) start() error {
if err != nil {
return fmt.Errorf("set local desc: %w", err)
}
flushCandidates()

c.logger.Debug(context.Background(), "writing offer")
b, _ := json.Marshal(&proto.Message{
Offer: &localDesc,
Offer: &localDesc,
Servers: servers,
})
_, err = nconn.Write(b)
if err != nil {
return fmt.Errorf("write offer: %w", err)
}
flushCandidates()

go func() {
err = xwebrtc.WaitForDataChannelOpen(context.Background(), channel)
Expand Down
15 changes: 8 additions & 7 deletions internal/x/xwebrtc/conn.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package xwebrtc

import "github.com/pion/webrtc/v3"
import (
"time"

"github.com/pion/webrtc/v3"
)

// NewPeerConnection creates a new peer connection.
// It uses the Google stun server by default.
func NewPeerConnection() (*webrtc.PeerConnection, error) {
func NewPeerConnection(servers []webrtc.ICEServer) (*webrtc.PeerConnection, error) {
se := webrtc.SettingEngine{}
se.DetachDataChannels()
se.SetICETimeouts(time.Second*5, time.Second*5, time.Second*2)
api := webrtc.NewAPI(webrtc.WithSettingEngine(se))

return api.NewPeerConnection(webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
ICEServers: servers,
})
}
1 change: 1 addition & 0 deletions pkg/proto/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Message struct {
Error string `json:"error"`
Candidate string `json:"candidate"`
Offer *webrtc.SessionDescription `json:"offer"`
Servers []webrtc.ICEServer `json:"servers"`
Answer *webrtc.SessionDescription `json:"answer"`
}

Expand Down