@@ -25,6 +25,10 @@ import (
2525// a resource may register with a SharedConn which supports WebRTC.
2626type OnTrackCB func (tr * webrtc.TrackRemote , r * webrtc.RTPReceiver )
2727
28+ //nolint
29+ // The following describes the SharedConn lifetime for viam-server's modmanager communicating with
30+ // modules it has spawned.
31+ //
2832// SharedConn wraps both a GRPC connection & (optionally) a peer connection & controls access to both.
2933// For modules, the grpc connection is over a Unix socket. The WebRTC `PeerConnection` is made
3034// separately. The `SharedConn` continues to implement the `rpc.ClientConn` interface by pairing up
@@ -71,20 +75,70 @@ type SharedConn struct {
7175 // `peerConnMu` synchronizes changes to the underlying `peerConn`. Such that calls consecutive
7276 // calls to `GrpcConn` and `PeerConn` will return connections from the same (or newer, but not
7377 // prior) "generations".
74- peerConnMu sync.Mutex
75- peerConn * webrtc.PeerConnection
76- peerConnReady <- chan struct {}
77- peerConnClosed <- chan struct {}
78+ peerConnMu sync.Mutex
79+ peerConn * webrtc.PeerConnection
80+ peerConnReady <- chan struct {}
7881 // peerConnFailed gets closed when a PeerConnection fails to connect. The peerConn pointer is
7982 // set to nil before this channel is closed.
8083 peerConnFailed chan struct {}
8184
8285 onTrackCBByTrackNameMu sync.Mutex
8386 onTrackCBByTrackName map [string ]OnTrackCB
8487
88+ // isConnectedToViamServer identifies whether this SharedConn is running inside a viam-server
89+ // talking to a module, or a module talking to a viam-server. We use this to determine whether
90+ // to use long names or short names for PeerConnection video (or audio) track names.
91+ isConnectedToViamServer bool
92+
8593 logger logging.Logger
8694}
8795
96+ // NewSharedConnForModule acts as a constructor for `SharedConn` for modules that are communicating
97+ // back to their parent viam-server.
98+ func NewSharedConnForModule (grpcConn rpc.ClientConn , peerConn * webrtc.PeerConnection , logger logging.Logger ) * SharedConn {
99+ // We must be passed a ready connection.
100+ pcReady := make (chan struct {})
101+ close (pcReady )
102+
103+ ret := & SharedConn {
104+ peerConn : peerConn ,
105+ peerConnReady : pcReady ,
106+ // We were passed in a ready connection. Only create this for when `Close` is called.
107+ peerConnFailed : make (chan struct {}),
108+ onTrackCBByTrackName : make (map [string ]OnTrackCB ),
109+ isConnectedToViamServer : true ,
110+ logger : logger ,
111+ }
112+ ret .grpcConn .ReplaceConn (grpcConn )
113+
114+ ret .peerConn .OnTrack (func (trackRemote * webrtc.TrackRemote , rtpReceiver * webrtc.RTPReceiver ) {
115+ ret .onTrackCBByTrackNameMu .Lock ()
116+ onTrackCB , ok := ret .onTrackCBByTrackName [trackRemote .StreamID ()]
117+ ret .onTrackCBByTrackNameMu .Unlock ()
118+ if ! ok {
119+ msg := "Callback not found for StreamID: %s, keys(resOnTrackCBs): %#v"
120+ ret .logger .Errorf (msg , trackRemote .StreamID (), maps .Keys (ret .onTrackCBByTrackName ))
121+ return
122+ }
123+ onTrackCB (trackRemote , rtpReceiver )
124+ })
125+
126+ return ret
127+ }
128+
129+ // IsConnectedToModule returns whether this shared conn is being used to communicate with a module.
130+ func (sc * SharedConn ) IsConnectedToModule () bool {
131+ return sc .isConnectedToViamServer
132+ }
133+
134+ // IsConnectedToViamServer returns whether this shared conn is being used to communicate with a
135+ // viam-server. Note this implies the client is running within a module process. Typical
136+ // clients/remote connections are a pure webrtc connection. As opposed to a frankenstein tcp/unix
137+ // socket + webrtc connection.
138+ func (sc * SharedConn ) IsConnectedToViamServer () bool {
139+ return ! sc .isConnectedToViamServer
140+ }
141+
88142// Invoke forwards to the underlying GRPC Connection.
89143func (sc * SharedConn ) Invoke (
90144 ctx context.Context ,
@@ -143,8 +197,8 @@ func (sc *SharedConn) PeerConn() *webrtc.PeerConnection {
143197 return ret
144198}
145199
146- // ResetConn acts as a constructor for `SharedConn`. ResetConn replaces the underlying
147- // connection objects in addition to some other initialization.
200+ // ResetConn acts as a constructor for `SharedConn` inside the viam-server (not modules). ResetConn
201+ // replaces the underlying connection objects in addition to some other initialization.
148202//
149203// The first call to `ResetConn` is guaranteed to happen before any access to connection objects
150204// happens. But subequent calls can be entirely asynchronous to components/services accessing
@@ -193,7 +247,7 @@ func (sc *SharedConn) ResetConn(conn rpc.ClientConn, moduleLogger logging.Logger
193247 }
194248
195249 sc .peerConn = peerConn
196- sc .peerConnReady , sc . peerConnClosed , err = rpc .ConfigureForRenegotiation (peerConn , rpc .PeerRoleClient , sc .logger )
250+ sc .peerConnReady , _ , err = rpc .ConfigureForRenegotiation (peerConn , rpc .PeerRoleServer , sc .logger )
197251 if err != nil {
198252 sc .logger .Warnw ("Unable to create optional renegotiation channel for module. Ignoring." , "err" , err )
199253 return
0 commit comments