Skip to content

Commit 714c366

Browse files
authored
chore: Remove WebRTC networking (#3881)
* chore: Remove WebRTC networking * Fix race condition * Fix WebSocket not closing
1 parent 1186e64 commit 714c366

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+315
-4230
lines changed

Makefile

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,6 @@ lint/shellcheck: $(shell shfmt -f .)
386386
gen: \
387387
coderd/database/dump.sql \
388388
coderd/database/querier.go \
389-
peerbroker/proto/peerbroker.pb.go \
390389
provisionersdk/proto/provisioner.pb.go \
391390
provisionerd/proto/provisionerd.pb.go \
392391
site/src/api/typesGenerated.ts
@@ -395,7 +394,7 @@ gen: \
395394
# Mark all generated files as fresh so make thinks they're up-to-date. This is
396395
# used during releases so we don't run generation scripts.
397396
gen/mark-fresh:
398-
files="coderd/database/dump.sql coderd/database/querier.go peerbroker/proto/peerbroker.pb.go provisionersdk/proto/provisioner.pb.go provisionerd/proto/provisionerd.pb.go site/src/api/typesGenerated.ts"
397+
files="coderd/database/dump.sql coderd/database/querier.go provisionersdk/proto/provisioner.pb.go provisionerd/proto/provisionerd.pb.go site/src/api/typesGenerated.ts"
399398
for file in $$files; do
400399
echo "$$file"
401400
if [ ! -f "$$file" ]; then
@@ -417,14 +416,6 @@ coderd/database/dump.sql: coderd/database/gen/dump/main.go $(wildcard coderd/dat
417416
coderd/database/querier.go: coderd/database/sqlc.yaml coderd/database/dump.sql $(wildcard coderd/database/queries/*.sql) coderd/database/gen/enum/main.go
418417
./coderd/database/generate.sh
419418

420-
peerbroker/proto/peerbroker.pb.go: peerbroker/proto/peerbroker.proto
421-
protoc \
422-
--go_out=. \
423-
--go_opt=paths=source_relative \
424-
--go-drpc_out=. \
425-
--go-drpc_opt=paths=source_relative \
426-
./peerbroker/proto/peerbroker.proto
427-
428419
provisionersdk/proto/provisioner.pb.go: provisionersdk/proto/provisioner.proto
429420
protoc \
430421
--go_out=. \

agent/agent.go

Lines changed: 1 addition & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"io"
1212
"net"
1313
"net/netip"
14-
"net/url"
1514
"os"
1615
"os/exec"
1716
"os/user"
@@ -34,8 +33,6 @@ import (
3433

3534
"cdr.dev/slog"
3635
"github.com/coder/coder/agent/usershell"
37-
"github.com/coder/coder/peer"
38-
"github.com/coder/coder/peerbroker"
3936
"github.com/coder/coder/pty"
4037
"github.com/coder/coder/tailnet"
4138
"github.com/coder/retry"
@@ -64,7 +61,6 @@ var (
6461

6562
type Options struct {
6663
CoordinatorDialer CoordinatorDialer
67-
WebRTCDialer WebRTCDialer
6864
FetchMetadata FetchMetadata
6965

7066
StatsReporter StatsReporter
@@ -80,8 +76,6 @@ type Metadata struct {
8076
Directory string `json:"directory"`
8177
}
8278

83-
type WebRTCDialer func(ctx context.Context, logger slog.Logger) (*peerbroker.Listener, error)
84-
8579
// CoordinatorDialer is a function that constructs a new broker.
8680
// A dialer must be passed in to allow for reconnects.
8781
type CoordinatorDialer func(ctx context.Context) (net.Conn, error)
@@ -95,7 +89,6 @@ func New(options Options) io.Closer {
9589
}
9690
ctx, cancelFunc := context.WithCancel(context.Background())
9791
server := &agent{
98-
webrtcDialer: options.WebRTCDialer,
9992
reconnectingPTYTimeout: options.ReconnectingPTYTimeout,
10093
logger: options.Logger,
10194
closeCancel: cancelFunc,
@@ -111,8 +104,7 @@ func New(options Options) io.Closer {
111104
}
112105

113106
type agent struct {
114-
webrtcDialer WebRTCDialer
115-
logger slog.Logger
107+
logger slog.Logger
116108

117109
reconnectingPTYs sync.Map
118110
reconnectingPTYTimeout time.Duration
@@ -173,9 +165,6 @@ func (a *agent) run(ctx context.Context) {
173165
}
174166
}()
175167

176-
if a.webrtcDialer != nil {
177-
go a.runWebRTCNetworking(ctx)
178-
}
179168
if metadata.DERPMap != nil {
180169
go a.runTailnet(ctx, metadata.DERPMap)
181170
}
@@ -326,49 +315,6 @@ func (a *agent) runCoordinator(ctx context.Context) {
326315
}
327316
}
328317

329-
func (a *agent) runWebRTCNetworking(ctx context.Context) {
330-
var peerListener *peerbroker.Listener
331-
var err error
332-
// An exponential back-off occurs when the connection is failing to dial.
333-
// This is to prevent server spam in case of a coderd outage.
334-
for retrier := retry.New(50*time.Millisecond, 10*time.Second); retrier.Wait(ctx); {
335-
peerListener, err = a.webrtcDialer(ctx, a.logger)
336-
if err != nil {
337-
if errors.Is(err, context.Canceled) {
338-
return
339-
}
340-
if a.isClosed() {
341-
return
342-
}
343-
a.logger.Warn(context.Background(), "failed to dial", slog.Error(err))
344-
continue
345-
}
346-
a.logger.Info(context.Background(), "connected to webrtc broker")
347-
break
348-
}
349-
select {
350-
case <-ctx.Done():
351-
return
352-
default:
353-
}
354-
355-
for {
356-
conn, err := peerListener.Accept()
357-
if err != nil {
358-
if a.isClosed() {
359-
return
360-
}
361-
a.logger.Debug(ctx, "peer listener accept exited; restarting connection", slog.Error(err))
362-
a.runWebRTCNetworking(ctx)
363-
return
364-
}
365-
a.closeMutex.Lock()
366-
a.connCloseWait.Add(1)
367-
a.closeMutex.Unlock()
368-
go a.handlePeerConn(ctx, conn)
369-
}
370-
}
371-
372318
func (a *agent) runStartupScript(ctx context.Context, script string) error {
373319
if script == "" {
374320
return nil
@@ -401,74 +347,6 @@ func (a *agent) runStartupScript(ctx context.Context, script string) error {
401347
return nil
402348
}
403349

404-
func (a *agent) handlePeerConn(ctx context.Context, peerConn *peer.Conn) {
405-
go func() {
406-
select {
407-
case <-a.closed:
408-
case <-peerConn.Closed():
409-
}
410-
_ = peerConn.Close()
411-
a.connCloseWait.Done()
412-
}()
413-
for {
414-
channel, err := peerConn.Accept(ctx)
415-
if err != nil {
416-
if errors.Is(err, peer.ErrClosed) || a.isClosed() {
417-
return
418-
}
419-
a.logger.Debug(ctx, "accept channel from peer connection", slog.Error(err))
420-
return
421-
}
422-
423-
conn := channel.NetConn()
424-
425-
switch channel.Protocol() {
426-
case ProtocolSSH:
427-
go a.sshServer.HandleConn(a.stats.wrapConn(conn))
428-
case ProtocolReconnectingPTY:
429-
rawID := channel.Label()
430-
// The ID format is referenced in conn.go.
431-
// <uuid>:<height>:<width>
432-
idParts := strings.SplitN(rawID, ":", 4)
433-
if len(idParts) != 4 {
434-
a.logger.Warn(ctx, "client sent invalid id format", slog.F("raw-id", rawID))
435-
continue
436-
}
437-
id := idParts[0]
438-
// Enforce a consistent format for IDs.
439-
_, err := uuid.Parse(id)
440-
if err != nil {
441-
a.logger.Warn(ctx, "client sent reconnection token that isn't a uuid", slog.F("id", id), slog.Error(err))
442-
continue
443-
}
444-
// Parse the initial terminal dimensions.
445-
height, err := strconv.Atoi(idParts[1])
446-
if err != nil {
447-
a.logger.Warn(ctx, "client sent invalid height", slog.F("id", id), slog.F("height", idParts[1]))
448-
continue
449-
}
450-
width, err := strconv.Atoi(idParts[2])
451-
if err != nil {
452-
a.logger.Warn(ctx, "client sent invalid width", slog.F("id", id), slog.F("width", idParts[2]))
453-
continue
454-
}
455-
go a.handleReconnectingPTY(ctx, reconnectingPTYInit{
456-
ID: id,
457-
Height: uint16(height),
458-
Width: uint16(width),
459-
Command: idParts[3],
460-
}, a.stats.wrapConn(conn))
461-
case ProtocolDial:
462-
go a.handleDial(ctx, channel.Label(), a.stats.wrapConn(conn))
463-
default:
464-
a.logger.Warn(ctx, "unhandled protocol from channel",
465-
slog.F("protocol", channel.Protocol()),
466-
slog.F("label", channel.Label()),
467-
)
468-
}
469-
}
470-
}
471-
472350
func (a *agent) init(ctx context.Context) {
473351
a.logger.Info(ctx, "generating host key")
474352
// Clients' should ignore the host key when connecting.
@@ -915,70 +793,6 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, msg reconnectingPTYIn
915793
}
916794
}
917795

918-
// dialResponse is written to datachannels with protocol "dial" by the agent as
919-
// the first packet to signify whether the dial succeeded or failed.
920-
type dialResponse struct {
921-
Error string `json:"error,omitempty"`
922-
}
923-
924-
func (a *agent) handleDial(ctx context.Context, label string, conn net.Conn) {
925-
defer conn.Close()
926-
927-
writeError := func(responseError error) error {
928-
msg := ""
929-
if responseError != nil {
930-
msg = responseError.Error()
931-
if !xerrors.Is(responseError, io.EOF) {
932-
a.logger.Warn(ctx, "handle dial", slog.F("label", label), slog.Error(responseError))
933-
}
934-
}
935-
b, err := json.Marshal(dialResponse{
936-
Error: msg,
937-
})
938-
if err != nil {
939-
a.logger.Warn(ctx, "write dial response", slog.F("label", label), slog.Error(err))
940-
return xerrors.Errorf("marshal agent webrtc dial response: %w", err)
941-
}
942-
943-
_, err = conn.Write(b)
944-
return err
945-
}
946-
947-
u, err := url.Parse(label)
948-
if err != nil {
949-
_ = writeError(xerrors.Errorf("parse URL %q: %w", label, err))
950-
return
951-
}
952-
953-
network := u.Scheme
954-
addr := u.Host + u.Path
955-
if strings.HasPrefix(network, "unix") {
956-
if runtime.GOOS == "windows" {
957-
_ = writeError(xerrors.New("Unix forwarding is not supported from Windows workspaces"))
958-
return
959-
}
960-
addr, err = ExpandRelativeHomePath(addr)
961-
if err != nil {
962-
_ = writeError(xerrors.Errorf("expand path %q: %w", addr, err))
963-
return
964-
}
965-
}
966-
967-
d := net.Dialer{Timeout: 3 * time.Second}
968-
nconn, err := d.DialContext(ctx, network, addr)
969-
if err != nil {
970-
_ = writeError(xerrors.Errorf("dial '%v://%v': %w", network, addr, err))
971-
return
972-
}
973-
974-
err = writeError(nil)
975-
if err != nil {
976-
return
977-
}
978-
979-
Bicopy(ctx, conn, nconn)
980-
}
981-
982796
// isClosed returns whether the API is closed or not.
983797
func (a *agent) isClosed() bool {
984798
select {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy