mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
* feat: Add stage to build logs This adds a stage property to logs, and refactors the job logs cliui. It also adds tests to the cliui for build logs! * feat: Add stage to build logs This adds a stage property to logs, and refactors the job logs cliui. It also adds tests to the cliui for build logs! * feat: Add config-ssh and tests for resiliency * Rename "Echo" test to "ImmediateExit" * Fix Terraform resource agent association * Fix logs post-cancel * Fix select on Windows * Remove terraform init logs * Move timer into it's own loop * Fix race condition in provisioner jobs * Fix requested changes
88 lines
2.5 KiB
Go
88 lines
2.5 KiB
Go
package peerbroker
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"reflect"
|
|
|
|
"github.com/pion/webrtc/v3"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/coder/coder/peer"
|
|
"github.com/coder/coder/peerbroker/proto"
|
|
)
|
|
|
|
// Dial consumes the PeerBroker gRPC connection negotiation stream to produce a WebRTC peered connection.
|
|
func Dial(stream proto.DRPCPeerBroker_NegotiateConnectionClient, iceServers []webrtc.ICEServer, opts *peer.ConnOptions) (*peer.Conn, error) {
|
|
peerConn, err := peer.Client(iceServers, opts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("create peer connection: %w", err)
|
|
}
|
|
go func() {
|
|
defer stream.Close()
|
|
// Exchanging messages from the peer connection to negotiate a connection.
|
|
for {
|
|
select {
|
|
case <-peerConn.Closed():
|
|
return
|
|
case sessionDescription := <-peerConn.LocalSessionDescription():
|
|
err = stream.Send(&proto.Exchange{
|
|
Message: &proto.Exchange_Sdp{
|
|
Sdp: &proto.WebRTCSessionDescription{
|
|
SdpType: int32(sessionDescription.Type),
|
|
Sdp: sessionDescription.SDP,
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
_ = peerConn.CloseWithError(xerrors.Errorf("send local session description: %w", err))
|
|
return
|
|
}
|
|
case iceCandidate := <-peerConn.LocalCandidate():
|
|
err = stream.Send(&proto.Exchange{
|
|
Message: &proto.Exchange_IceCandidate{
|
|
IceCandidate: iceCandidate.Candidate,
|
|
},
|
|
})
|
|
if err != nil {
|
|
_ = peerConn.CloseWithError(xerrors.Errorf("send local candidate: %w", err))
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
go func() {
|
|
// Exchanging messages from the server to negotiate a connection.
|
|
for {
|
|
serverToClientMessage, err := stream.Recv()
|
|
if err != nil {
|
|
// p2p connections should never die if this stream does due
|
|
// to proper closure or context cancellation!
|
|
if errors.Is(err, io.EOF) || errors.Is(err, context.Canceled) {
|
|
return
|
|
}
|
|
_ = peerConn.CloseWithError(xerrors.Errorf("recv: %w", err))
|
|
return
|
|
}
|
|
|
|
switch {
|
|
case serverToClientMessage.GetSdp() != nil:
|
|
peerConn.SetRemoteSessionDescription(webrtc.SessionDescription{
|
|
Type: webrtc.SDPType(serverToClientMessage.GetSdp().SdpType),
|
|
SDP: serverToClientMessage.GetSdp().Sdp,
|
|
})
|
|
case serverToClientMessage.GetIceCandidate() != "":
|
|
peerConn.AddRemoteCandidate(webrtc.ICECandidateInit{
|
|
Candidate: serverToClientMessage.GetIceCandidate(),
|
|
})
|
|
default:
|
|
_ = peerConn.CloseWithError(xerrors.Errorf("unhandled message: %s", reflect.TypeOf(serverToClientMessage).String()))
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
return peerConn, nil
|
|
}
|