Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/v1/bandwidthRtc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,42 @@ describe("bandwidthRtcV1 addStreamToPublishingPeerConnection", () => {
});
});

describe("bandwidthRtcV1 init reconnect replay", () => {
function stubSetupPeerConnection(brtc: BandwidthRtc) {
// init() only needs a stand-in RTCPeerConnection; the real
// negotiation performed by setupPeerConnection is exercised elsewhere.
(brtc as any).setupPeerConnection = jest.fn().mockResolvedValue({});
}

test("does not replay when no streams were previously published (first connect)", async () => {
const brtc = new BandwidthRtc();
stubSetupPeerConnection(brtc);
const addSpy = jest.spyOn(brtc as any, "addStreamToPublishingPeerConnection");
const offerSpy = jest.spyOn(brtc as any, "offerPublishSdp").mockResolvedValue(undefined);

await brtc.init({ publishSdpOffer: {}, subscribeSdpOffer: {} } as any);

expect(addSpy).not.toHaveBeenCalled();
expect(offerSpy).not.toHaveBeenCalled();
});

test("re-attaches previously published streams to the new publishing peer connection on reconnect", async () => {
const brtc = new BandwidthRtc();
stubSetupPeerConnection(brtc);
const addSpy = jest.spyOn(brtc as any, "addStreamToPublishingPeerConnection").mockImplementation(() => {});
const offerSpy = jest.spyOn(brtc as any, "offerPublishSdp").mockResolvedValue(undefined);

const mediaStream = { id: "stream-1" } as any;
(brtc as any).publishedStreams.set(mediaStream.id, { mediaStream });

// Simulate the websocket "open" handler re-emitting "init" after a reconnect.
await brtc.init({ publishSdpOffer: {}, subscribeSdpOffer: {} } as any);

expect(addSpy).toHaveBeenCalledWith(mediaStream);
expect(offerSpy).toHaveBeenCalledTimes(1);
});
});

describe("bandwidthRtcV1 connect method", () => {
beforeAll(() => {
setupNavigatorMocks();
Expand Down
11 changes: 11 additions & 0 deletions src/v1/bandwidthRtc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,17 @@ export class BandwidthRtc {
subscriptionOnTrackHandler,
setMediaPreferencesResponse.subscribeSdpOffer.sdpOffer,
);

// On a fresh connect, publishedStreams is empty and this is a no-op. On a
// reconnect (the websocket re-opened and re-emitted "init"), the new
// publishingPeerConnection above is trackless, so re-attach every
// previously published stream and renegotiate to carry them over.
if (this.publishedStreams.size > 0) {
for (const { mediaStream } of this.publishedStreams.values()) {
this.addStreamToPublishingPeerConnection(mediaStream);
}
await this.offerPublishSdp();
}
}

private async setupPeerConnection(
Expand Down