Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 536bb17

Browse files
committed
Add option for passing ICE servers
1 parent deae9e9 commit 536bb17

22 files changed

+307
-115
lines changed

agent/agent.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,23 @@ type Options struct {
3232
Logger slog.Logger
3333
}
3434

35-
type Dialer func(ctx context.Context, options *peer.ConnOptions) (*peerbroker.Listener, error)
35+
type Dialer func(ctx context.Context, logger slog.Logger) (*peerbroker.Listener, error)
3636

37-
func New(dialer Dialer, options *peer.ConnOptions) io.Closer {
37+
func New(dialer Dialer, logger slog.Logger) io.Closer {
3838
ctx, cancelFunc := context.WithCancel(context.Background())
3939
server := &agent{
40-
clientDialer: dialer,
41-
options: options,
42-
closeCancel: cancelFunc,
43-
closed: make(chan struct{}),
40+
dialer: dialer,
41+
logger: logger,
42+
closeCancel: cancelFunc,
43+
closed: make(chan struct{}),
4444
}
4545
server.init(ctx)
4646
return server
4747
}
4848

4949
type agent struct {
50-
clientDialer Dialer
51-
options *peer.ConnOptions
50+
dialer Dialer
51+
logger slog.Logger
5252

5353
connCloseWait sync.WaitGroup
5454
closeCancel context.CancelFunc
@@ -64,18 +64,18 @@ func (a *agent) run(ctx context.Context) {
6464
// An exponential back-off occurs when the connection is failing to dial.
6565
// This is to prevent server spam in case of a coderd outage.
6666
for retrier := retry.New(50*time.Millisecond, 10*time.Second); retrier.Wait(ctx); {
67-
peerListener, err = a.clientDialer(ctx, a.options)
67+
peerListener, err = a.dialer(ctx, a.logger)
6868
if err != nil {
6969
if errors.Is(err, context.Canceled) {
7070
return
7171
}
7272
if a.isClosed() {
7373
return
7474
}
75-
a.options.Logger.Warn(context.Background(), "failed to dial", slog.Error(err))
75+
a.logger.Warn(context.Background(), "failed to dial", slog.Error(err))
7676
continue
7777
}
78-
a.options.Logger.Info(context.Background(), "connected")
78+
a.logger.Info(context.Background(), "connected")
7979
break
8080
}
8181
select {
@@ -90,7 +90,7 @@ func (a *agent) run(ctx context.Context) {
9090
if a.isClosed() {
9191
return
9292
}
93-
a.options.Logger.Debug(ctx, "peer listener accept exited; restarting connection", slog.Error(err))
93+
a.logger.Debug(ctx, "peer listener accept exited; restarting connection", slog.Error(err))
9494
a.run(ctx)
9595
return
9696
}
@@ -105,10 +105,9 @@ func (a *agent) handlePeerConn(ctx context.Context, conn *peer.Conn) {
105105
go func() {
106106
select {
107107
case <-a.closed:
108-
_ = conn.Close()
109108
case <-conn.Closed():
110109
}
111-
<-conn.Closed()
110+
_ = conn.Close()
112111
a.connCloseWait.Done()
113112
}()
114113
for {
@@ -117,15 +116,15 @@ func (a *agent) handlePeerConn(ctx context.Context, conn *peer.Conn) {
117116
if errors.Is(err, peer.ErrClosed) || a.isClosed() {
118117
return
119118
}
120-
a.options.Logger.Debug(ctx, "accept channel from peer connection", slog.Error(err))
119+
a.logger.Debug(ctx, "accept channel from peer connection", slog.Error(err))
121120
return
122121
}
123122

124123
switch channel.Protocol() {
125124
case "ssh":
126125
go a.sshServer.HandleConn(channel.NetConn())
127126
default:
128-
a.options.Logger.Warn(ctx, "unhandled protocol from channel",
127+
a.logger.Warn(ctx, "unhandled protocol from channel",
129128
slog.F("protocol", channel.Protocol()),
130129
slog.F("label", channel.Label()),
131130
)
@@ -145,7 +144,7 @@ func (a *agent) init(ctx context.Context) {
145144
if err != nil {
146145
panic(err)
147146
}
148-
sshLogger := a.options.Logger.Named("ssh-server")
147+
sshLogger := a.logger.Named("ssh-server")
149148
forwardHandler := &ssh.ForwardedTCPHandler{}
150149
a.sshServer = &ssh.Server{
151150
ChannelHandlers: map[string]ssh.ChannelHandler{
@@ -158,7 +157,7 @@ func (a *agent) init(ctx context.Context) {
158157
Handler: func(session ssh.Session) {
159158
err := a.handleSSHSession(session)
160159
if err != nil {
161-
a.options.Logger.Warn(ctx, "ssh session failed", slog.Error(err))
160+
a.logger.Warn(ctx, "ssh session failed", slog.Error(err))
162161
_ = session.Exit(1)
163162
return
164163
}
@@ -194,15 +193,15 @@ func (a *agent) init(ctx context.Context) {
194193
"sftp": func(session ssh.Session) {
195194
server, err := sftp.NewServer(session)
196195
if err != nil {
197-
a.options.Logger.Debug(session.Context(), "initialize sftp server", slog.Error(err))
196+
a.logger.Debug(session.Context(), "initialize sftp server", slog.Error(err))
198197
return
199198
}
200199
defer server.Close()
201200
err = server.Serve()
202201
if errors.Is(err, io.EOF) {
203202
return
204203
}
205-
a.options.Logger.Debug(session.Context(), "sftp server exited with error", slog.Error(err))
204+
a.logger.Debug(session.Context(), "sftp server exited with error", slog.Error(err))
206205
},
207206
},
208207
}
@@ -250,7 +249,7 @@ func (a *agent) handleSSHSession(session ssh.Session) error {
250249
for win := range windowSize {
251250
err = ptty.Resize(uint16(win.Width), uint16(win.Height))
252251
if err != nil {
253-
a.options.Logger.Warn(context.Background(), "failed to resize tty", slog.Error(err))
252+
a.logger.Warn(context.Background(), "failed to resize tty", slog.Error(err))
254253
}
255254
}
256255
}()

agent/agent_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,9 @@ func setupSSHSession(t *testing.T) *ssh.Session {
173173

174174
func setupAgent(t *testing.T) *agent.Conn {
175175
client, server := provisionersdk.TransportPipe()
176-
closer := agent.New(func(ctx context.Context, opts *peer.ConnOptions) (*peerbroker.Listener, error) {
177-
return peerbroker.Listen(server, nil, opts)
178-
}, &peer.ConnOptions{
179-
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
180-
})
176+
closer := agent.New(func(ctx context.Context, logger slog.Logger) (*peerbroker.Listener, error) {
177+
return peerbroker.Listen(server, nil)
178+
}, slogtest.Make(t, nil).Leveled(slog.LevelDebug))
181179
t.Cleanup(func() {
182180
_ = client.Close()
183181
_ = server.Close()

cli/configssh_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"github.com/coder/coder/cli/clitest"
2020
"github.com/coder/coder/coderd/coderdtest"
2121
"github.com/coder/coder/codersdk"
22-
"github.com/coder/coder/peer"
2322
"github.com/coder/coder/provisioner/echo"
2423
"github.com/coder/coder/provisionersdk/proto"
2524
"github.com/coder/coder/pty/ptytest"
@@ -72,17 +71,15 @@ func TestConfigSSH(t *testing.T) {
7271
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
7372
agentClient := codersdk.New(client.URL)
7473
agentClient.SessionToken = authToken
75-
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &peer.ConnOptions{
76-
Logger: slogtest.Make(t, nil),
77-
})
74+
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, slogtest.Make(t, nil))
7875
t.Cleanup(func() {
7976
_ = agentCloser.Close()
8077
})
8178
tempFile, err := os.CreateTemp(t.TempDir(), "")
8279
require.NoError(t, err)
8380
_ = tempFile.Close()
8481
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
85-
agentConn, err := client.DialWorkspaceAgent(context.Background(), resources[0].Agents[0].ID, nil, nil)
82+
agentConn, err := client.DialWorkspaceAgent(context.Background(), resources[0].Agents[0].ID, nil)
8683
require.NoError(t, err)
8784
defer agentConn.Close()
8885

cli/gitssh_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func TestGitSSH(t *testing.T) {
8181
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
8282
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
8383
require.NoError(t, err)
84-
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil, nil)
84+
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil)
8585
require.NoError(t, err)
8686
defer dialer.Close()
8787
_, err = dialer.Ping()

cli/ssh.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"github.com/google/uuid"
1212
"github.com/mattn/go-isatty"
13-
"github.com/pion/webrtc/v3"
1413
"github.com/spf13/cobra"
1514
gossh "golang.org/x/crypto/ssh"
1615
"golang.org/x/term"
@@ -99,9 +98,7 @@ func ssh() *cobra.Command {
9998
return xerrors.Errorf("await agent: %w", err)
10099
}
101100

102-
conn, err := client.DialWorkspaceAgent(cmd.Context(), agent.ID, []webrtc.ICEServer{{
103-
URLs: []string{"stun:stun.l.google.com:19302"},
104-
}}, nil)
101+
conn, err := client.DialWorkspaceAgent(cmd.Context(), agent.ID, nil)
105102
if err != nil {
106103
return err
107104
}

cli/ssh_test.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/coder/coder/cli/clitest"
1818
"github.com/coder/coder/coderd/coderdtest"
1919
"github.com/coder/coder/codersdk"
20-
"github.com/coder/coder/peer"
2120
"github.com/coder/coder/provisioner/echo"
2221
"github.com/coder/coder/provisionersdk/proto"
2322
"github.com/coder/coder/pty/ptytest"
@@ -70,9 +69,7 @@ func TestSSH(t *testing.T) {
7069
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
7170
agentClient := codersdk.New(client.URL)
7271
agentClient.SessionToken = agentToken
73-
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &peer.ConnOptions{
74-
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
75-
})
72+
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, slogtest.Make(t, nil).Leveled(slog.LevelDebug))
7673
t.Cleanup(func() {
7774
_ = agentCloser.Close()
7875
})
@@ -115,9 +112,7 @@ func TestSSH(t *testing.T) {
115112
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
116113
agentClient := codersdk.New(client.URL)
117114
agentClient.SessionToken = agentToken
118-
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &peer.ConnOptions{
119-
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
120-
})
115+
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, slogtest.Make(t, nil).Leveled(slog.LevelDebug))
121116
t.Cleanup(func() {
122117
_ = agentCloser.Close()
123118
})

cli/start.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ func start() *cobra.Command {
6161
secureAuthCookie bool
6262
sshKeygenAlgorithmRaw string
6363
)
64+
6465
root := &cobra.Command{
6566
Use: "start",
6667
RunE: func(cmd *cobra.Command, args []string) error {

cli/workspaceagent.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"github.com/coder/coder/agent"
1717
"github.com/coder/coder/cli/cliflag"
1818
"github.com/coder/coder/codersdk"
19-
"github.com/coder/coder/peer"
2019
"github.com/coder/retry"
2120
)
2221

@@ -110,9 +109,7 @@ func workspaceAgent() *cobra.Command {
110109
return xerrors.Errorf("writing agent session token to config: %w", err)
111110
}
112111

113-
closer := agent.New(client.ListenWorkspaceAgent, &peer.ConnOptions{
114-
Logger: logger,
115-
})
112+
closer := agent.New(client.ListenWorkspaceAgent, logger)
116113
<-cmd.Context().Done()
117114
return closer.Close()
118115
},

cli/workspaceagent_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func TestWorkspaceAgent(t *testing.T) {
6161
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
6262
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
6363
require.NoError(t, err)
64-
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil, nil)
64+
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil)
6565
require.NoError(t, err)
6666
defer dialer.Close()
6767
_, err = dialer.Ping()
@@ -115,7 +115,7 @@ func TestWorkspaceAgent(t *testing.T) {
115115
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
116116
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
117117
require.NoError(t, err)
118-
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil, nil)
118+
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil)
119119
require.NoError(t, err)
120120
defer dialer.Close()
121121
_, err = dialer.Ping()

coderd/coderd.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/go-chi/chi/v5"
12+
"github.com/pion/webrtc/v3"
1213
"google.golang.org/api/idtoken"
1314

1415
chitrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-chi/chi.v5"
@@ -20,23 +21,25 @@ import (
2021
"github.com/coder/coder/coderd/gitsshkey"
2122
"github.com/coder/coder/coderd/httpapi"
2223
"github.com/coder/coder/coderd/httpmw"
24+
"github.com/coder/coder/coderd/turnconn"
2325
"github.com/coder/coder/codersdk"
2426
"github.com/coder/coder/site"
2527
)
2628

2729
// Options are requires parameters for Coder to start.
2830
type Options struct {
29-
AgentConnectionUpdateFrequency time.Duration
30-
AccessURL *url.URL
31-
Logger slog.Logger
32-
Database database.Store
33-
Pubsub database.Pubsub
34-
35-
AWSCertificates awsidentity.Certificates
36-
GoogleTokenValidator *idtoken.Validator
31+
AccessURL *url.URL
32+
Logger slog.Logger
33+
Database database.Store
34+
Pubsub database.Pubsub
3735

38-
SecureAuthCookie bool
39-
SSHKeygenAlgorithm gitsshkey.Algorithm
36+
AgentConnectionUpdateFrequency time.Duration
37+
AWSCertificates awsidentity.Certificates
38+
GoogleTokenValidator *idtoken.Validator
39+
ICEServers []webrtc.ICEServer
40+
SecureAuthCookie bool
41+
SSHKeygenAlgorithm gitsshkey.Algorithm
42+
TURNServer *turnconn.Server
4043
}
4144

4245
// New constructs the Coder API into an HTTP handler.
@@ -174,6 +177,8 @@ func New(options *Options) (http.Handler, func()) {
174177
r.Use(httpmw.ExtractWorkspaceAgent(options.Database))
175178
r.Get("/", api.workspaceAgentListen)
176179
r.Get("/gitsshkey", api.agentGitSSHKey)
180+
r.Get("/turn", api.workspaceAgentTurn)
181+
r.Get("/iceservers", api.workspaceAgentICEServers)
177182
})
178183
r.Route("/{workspaceagent}", func(r chi.Router) {
179184
r.Use(
@@ -182,6 +187,8 @@ func New(options *Options) (http.Handler, func()) {
182187
)
183188
r.Get("/", api.workspaceAgent)
184189
r.Get("/dial", api.workspaceAgentDial)
190+
r.Get("/turn", api.workspaceAgentTurn)
191+
r.Get("/iceservers", api.workspaceAgentICEServers)
185192
})
186193
})
187194
r.Route("/workspaceresources/{workspaceresource}", func(r chi.Router) {

coderd/coderdtest/coderdtest.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/coder/coder/coderd/database/databasefake"
4040
"github.com/coder/coder/coderd/database/postgres"
4141
"github.com/coder/coder/coderd/gitsshkey"
42+
"github.com/coder/coder/coderd/turnconn"
4243
"github.com/coder/coder/codersdk"
4344
"github.com/coder/coder/cryptorand"
4445
"github.com/coder/coder/provisioner/echo"
@@ -91,9 +92,8 @@ func New(t *testing.T, options *Options) *codersdk.Client {
9192
}
9293

9394
srv := httptest.NewUnstartedServer(nil)
95+
ctx, cancelFunc := context.WithCancel(context.Background())
9496
srv.Config.BaseContext = func(_ net.Listener) context.Context {
95-
ctx, cancelFunc := context.WithCancel(context.Background())
96-
t.Cleanup(cancelFunc)
9797
return ctx
9898
}
9999
srv.Start()
@@ -106,6 +106,9 @@ func New(t *testing.T, options *Options) *codersdk.Client {
106106
options.SSHKeygenAlgorithm = gitsshkey.AlgorithmEd25519
107107
}
108108

109+
turnServer, err := turnconn.New(nil)
110+
require.NoError(t, err)
111+
109112
// We set the handler after server creation for the access URL.
110113
srv.Config.Handler, closeWait = coderd.New(&coderd.Options{
111114
AgentConnectionUpdateFrequency: 150 * time.Millisecond,
@@ -117,8 +120,11 @@ func New(t *testing.T, options *Options) *codersdk.Client {
117120
AWSCertificates: options.AWSInstanceIdentity,
118121
GoogleTokenValidator: options.GoogleInstanceIdentity,
119122
SSHKeygenAlgorithm: options.SSHKeygenAlgorithm,
123+
TURNServer: turnServer,
120124
})
121125
t.Cleanup(func() {
126+
cancelFunc()
127+
_ = turnServer.Close()
122128
srv.Close()
123129
closeWait()
124130
})

coderd/httpmw/workspaceagent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func ExtractWorkspaceAgent(db database.Store) func(http.Handler) http.Handler {
3838
token, err := uuid.Parse(cookie.Value)
3939
if err != nil {
4040
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
41-
Message: fmt.Sprintf("parse token: %s", err),
41+
Message: fmt.Sprintf("parse token %q: %s", cookie.Value, err),
4242
})
4343
return
4444
}

0 commit comments

Comments
 (0)