@@ -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"
6461
6562type 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.
8781type 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
113106type 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-
372318func (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-
472350func (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.
983797func (a * agent ) isClosed () bool {
984798 select {
0 commit comments