Commit c7504aec authored by Byron Campen's avatar Byron Campen
Browse files

Bug 1829667: Make JsepTransceiver non-refcounted. r=mjf,webidl,mccr8

Involves substantial refactoring to make most access by-value (or through
functional-style in-place modifications) for safety.

Differential Revision: https://phabricator.services.mozilla.com/D176423
parent e533a4c3
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -1391,11 +1391,14 @@ export class RTCPeerConnection {
        transceiver.setDirectionInternal("sendonly");
      }
    } else {
      transceiver = this._addTransceiverNoEvents(track, {
      transceiver = this._addTransceiverNoEvents(
        track,
        {
          streams,
          direction: "sendrecv",
      });
      transceiver.setAddTrackMagic();
        },
        true
      );
    }

    this.updateNegotiationNeeded();
@@ -1431,7 +1434,7 @@ export class RTCPeerConnection {
    this.updateNegotiationNeeded();
  }

  _addTransceiverNoEvents(sendTrackOrKind, init) {
  _addTransceiverNoEvents(sendTrackOrKind, init, addTrackMagic) {
    let sendTrack = null;
    let kind;
    if (typeof sendTrackOrKind == "string") {
@@ -1449,7 +1452,7 @@ export class RTCPeerConnection {
    }

    try {
      return this._pc.addTransceiver(init, kind, sendTrack);
      return this._pc.addTransceiver(init, kind, sendTrack, addTrackMagic);
    } catch (e) {
      // Exceptions thrown by c++ code do not propagate. In most cases, that's
      // fine because we're using Promises, which can be copied. But this is
+97 −102
Original line number Diff line number Diff line
@@ -877,17 +877,14 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
  *mmsset = false;
  transportId->clear();

  RefPtr<JsepTransceiver> datachannelTransceiver;
  for (const auto& transceiver : mJsepSession->GetTransceivers()) {
    if ((transceiver->GetMediaType() == SdpMediaSection::kApplication) &&
        transceiver->mSendTrack.GetNegotiatedDetails()) {
      datachannelTransceiver = transceiver;
      break;
    }
  }
  Maybe<const JsepTransceiver> datachannelTransceiver =
      mJsepSession->FindTransceiver([](const JsepTransceiver& aTransceiver) {
        return aTransceiver.GetMediaType() == SdpMediaSection::kApplication;
      });

  if (!datachannelTransceiver ||
      !datachannelTransceiver->mTransport.mComponents) {
      !datachannelTransceiver->mTransport.mComponents ||
      !datachannelTransceiver->mSendTrack.GetNegotiatedDetails()) {
    return NS_ERROR_FAILURE;
  }

@@ -942,7 +939,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
}

nsresult PeerConnectionImpl::AddRtpTransceiverToJsepSession(
    RefPtr<JsepTransceiver>& transceiver) {
    JsepTransceiver& transceiver) {
  nsresult res = ConfigureJsepSessionCodecs();
  if (NS_FAILED(res)) {
    CSFLogError(LOGTAG, "Failed to configure codecs");
@@ -965,7 +962,7 @@ static Maybe<SdpMediaSection::MediaType> ToSdpMediaType(

already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
    const dom::RTCRtpTransceiverInit& aInit, const nsAString& aKind,
    dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv) {
    dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv) {
  // Copy, because we might need to modify
  RTCRtpTransceiverInit init(aInit);

@@ -976,9 +973,8 @@ already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
    return nullptr;
  }

  RefPtr<JsepTransceiver> jsepTransceiver =
      new JsepTransceiver(*type, *mUuidGen);
  jsepTransceiver->SetRtxIsAllowed(mRtxIsAllowed);
  JsepTransceiver jsepTransceiver(*type, *mUuidGen);
  jsepTransceiver.SetRtxIsAllowed(mRtxIsAllowed);

  // Do this last, since it is not possible to roll back.
  nsresult rv = AddRtpTransceiverToJsepSession(jsepTransceiver);
@@ -1074,9 +1070,9 @@ already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
  }

  RefPtr<RTCRtpTransceiver> transceiver = CreateTransceiver(
      jsepTransceiver->GetUuid(),
      jsepTransceiver->GetMediaType() == SdpMediaSection::kVideo, init,
      aSendTrack, aRv);
      jsepTransceiver.GetUuid(),
      jsepTransceiver.GetMediaType() == SdpMediaSection::kVideo, init,
      aSendTrack, aAddTrackMagic, aRv);

  if (aRv.Failed()) {
    // Would be nice if we could peek at the rv without stealing it, so we
@@ -1177,21 +1173,18 @@ PeerConnectionImpl::CreateDataChannel(

  CSFLogDebug(LOGTAG, "%s: making DOMDataChannel", __FUNCTION__);

  RefPtr<JsepTransceiver> dcTransceiver;
  for (auto& transceiver : mJsepSession->GetTransceivers()) {
    if (transceiver->GetMediaType() == SdpMediaSection::kApplication) {
      dcTransceiver = transceiver;
      break;
    }
  }

  if (!dcTransceiver) {
    dcTransceiver = new JsepTransceiver(
        SdpMediaSection::MediaType::kApplication, *mUuidGen);
    mJsepSession->AddTransceiver(dcTransceiver);
  }
  Maybe<JsepTransceiver> dcTransceiver =
      mJsepSession->FindTransceiver([](const JsepTransceiver& aTransceiver) {
        return aTransceiver.GetMediaType() == SdpMediaSection::kApplication;
      });

  if (dcTransceiver) {
    dcTransceiver->RestartDatachannelTransceiver();
    mJsepSession->SetTransceiver(*dcTransceiver);
  } else {
    mJsepSession->AddTransceiver(
        JsepTransceiver(SdpMediaSection::MediaType::kApplication, *mUuidGen));
  }

  RefPtr<nsDOMDataChannel> retval;
  rv = NS_NewDOMDataChannel(dataChannel.forget(), mWindow,
@@ -1364,22 +1357,24 @@ void PeerConnectionImpl::RunNextOperation(ErrorResult& aError) {

void PeerConnectionImpl::SyncToJsep() {
  for (const auto& transceiver : mTransceivers) {
    transceiver->SyncToJsep();
    transceiver->SyncToJsep(*mJsepSession);
  }
}

void PeerConnectionImpl::SyncFromJsep() {
  CSFLogDebug(LOGTAG, "%s", __FUNCTION__);
  for (const auto& jsepTransceiver : mJsepSession->GetTransceivers()) {
    if (jsepTransceiver->GetMediaType() ==
  mJsepSession->ForEachTransceiver(
      [this, self = RefPtr<PeerConnectionImpl>(this)](
          const JsepTransceiver& jsepTransceiver) {
        if (jsepTransceiver.GetMediaType() ==
            SdpMediaSection::MediaType::kApplication) {
      continue;
          return;
        }

        CSFLogDebug(LOGTAG, "%s: Looking for match", __FUNCTION__);
        RefPtr<RTCRtpTransceiver> transceiver;
        for (auto& temp : mTransceivers) {
      if (temp->GetJsepTransceiverId() == jsepTransceiver->GetUuid()) {
          if (temp->GetJsepTransceiverId() == jsepTransceiver.GetUuid()) {
            CSFLogDebug(LOGTAG, "%s: Found match", __FUNCTION__);
            transceiver = temp;
            break;
@@ -1392,9 +1387,9 @@ void PeerConnectionImpl::SyncFromJsep() {
          init.mDirection = RTCRtpTransceiverDirection::Recvonly;
          IgnoredErrorResult rv;
          transceiver = CreateTransceiver(
          jsepTransceiver->GetUuid(),
          jsepTransceiver->GetMediaType() == SdpMediaSection::kVideo, init,
          nullptr, rv);
              jsepTransceiver.GetUuid(),
              jsepTransceiver.GetMediaType() == SdpMediaSection::kVideo, init,
              nullptr, false, rv);
          if (NS_WARN_IF(rv.Failed())) {
            MOZ_ASSERT(false);
            return;
@@ -1403,8 +1398,8 @@ void PeerConnectionImpl::SyncFromJsep() {
        }

        CSFLogDebug(LOGTAG, "%s: Syncing transceiver", __FUNCTION__);
    transceiver->SyncFromJsep();
  }
        transceiver->SyncFromJsep(*mJsepSession);
      });
}

already_AddRefed<dom::Promise> PeerConnectionImpl::MakePromise(
@@ -1592,9 +1587,6 @@ PeerConnectionImpl::CreateOffer(const JsepOfferOptions& aOptions) {
              *buildJSErrorData(result, errorString), rv);
        } else {
          mJsepSession = std::move(uncommittedJsepSession);
          for (auto& transceiver : mTransceivers) {
            transceiver->SetJsepSession(mJsepSession.get());
          }
          mPCObserver->OnCreateOfferSuccess(ObString(offer.c_str()), rv);
        }
      }));
@@ -1631,9 +1623,6 @@ PeerConnectionImpl::CreateAnswer() {
              *buildJSErrorData(result, errorString), rv);
        } else {
          mJsepSession = std::move(uncommittedJsepSession);
          for (auto& transceiver : mTransceivers) {
            transceiver->SetJsepSession(mJsepSession.get());
          }
          mPCObserver->OnCreateAnswerSuccess(ObString(answer.c_str()), rv);
        }
      }));
@@ -3012,9 +3001,6 @@ void PeerConnectionImpl::DoSetDescriptionSuccessPostProcessing(
        }

        mJsepSession = std::move(mUncommittedJsepSession);
        for (auto& transceiver : mTransceivers) {
          transceiver->SetJsepSession(mJsepSession.get());
        }

        auto newSignalingState = GetSignalingState();
        SyncFromJsep();
@@ -3981,30 +3967,33 @@ bool PeerConnectionImpl::ShouldForceProxy() const {
}

void PeerConnectionImpl::EnsureTransports(const JsepSession& aSession) {
  for (const auto& transceiver : aSession.GetTransceivers()) {
    if (transceiver->HasOwnTransport()) {
  mJsepSession->ForEachTransceiver([this,
                                    self = RefPtr<PeerConnectionImpl>(this)](
                                       const JsepTransceiver& transceiver) {
    if (transceiver.HasOwnTransport()) {
      mTransportHandler->EnsureProvisionalTransport(
          transceiver->mTransport.mTransportId,
          transceiver->mTransport.mLocalUfrag,
          transceiver->mTransport.mLocalPwd,
          transceiver->mTransport.mComponents);
    }
          transceiver.mTransport.mTransportId,
          transceiver.mTransport.mLocalUfrag, transceiver.mTransport.mLocalPwd,
          transceiver.mTransport.mComponents);
    }
  });

  GatherIfReady();
}

void PeerConnectionImpl::UpdateRTCDtlsTransports(bool aMarkAsStable) {
  for (const auto& jsepTransceiver : mJsepSession->GetTransceivers()) {
    std::string transportId = jsepTransceiver->mTransport.mTransportId;
  mJsepSession->ForEachTransceiver(
      [this, self = RefPtr<PeerConnectionImpl>(this)](
          const JsepTransceiver& jsepTransceiver) {
        std::string transportId = jsepTransceiver.mTransport.mTransportId;
        if (transportId.empty()) {
      continue;
          return;
        }
        if (!mTransportIdToRTCDtlsTransport.count(transportId)) {
          mTransportIdToRTCDtlsTransport.emplace(
              transportId, new RTCDtlsTransport(GetParentObject()));
        }
  }
      });

  for (auto& transceiver : mTransceivers) {
    std::string transportId = transceiver->GetTransportId();
@@ -4042,17 +4031,19 @@ nsresult PeerConnectionImpl::UpdateTransports(const JsepSession& aSession,
                                              const bool forceIceTcp) {
  std::set<std::string> finalTransports;
  Maybe<std::string> sctpTransport;
  for (const auto& transceiver : aSession.GetTransceivers()) {
    if (transceiver->GetMediaType() == SdpMediaSection::kApplication &&
        transceiver->HasTransport()) {
      sctpTransport = Some(transceiver->mTransport.mTransportId);
  mJsepSession->ForEachTransceiver(
      [&, this, self = RefPtr<PeerConnectionImpl>(this)](
          const JsepTransceiver& transceiver) {
        if (transceiver.GetMediaType() == SdpMediaSection::kApplication &&
            transceiver.HasTransport()) {
          sctpTransport = Some(transceiver.mTransport.mTransportId);
        }

    if (transceiver->HasOwnTransport()) {
      finalTransports.insert(transceiver->mTransport.mTransportId);
      UpdateTransport(*transceiver, forceIceTcp);
    }
        if (transceiver.HasOwnTransport()) {
          finalTransports.insert(transceiver.mTransport.mTransportId);
          UpdateTransport(transceiver, forceIceTcp);
        }
      });

  // clean up the unused RTCDtlsTransports
  RemoveRTCDtlsTransportsExcept(finalTransports);
@@ -4447,7 +4438,7 @@ void PeerConnectionImpl::EnsureIceGathering(bool aDefaultRouteOnly,

already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
    const std::string& aId, bool aIsVideo, const RTCRtpTransceiverInit& aInit,
    dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv) {
    dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv) {
  PeerConnectionCtx* ctx = PeerConnectionCtx::GetInstance();
  if (!mCall) {
    mCall = WebrtcCallWrapper::Create(
@@ -4458,6 +4449,12 @@ already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
        ctx->GetSharedWebrtcState());
  }

  if (aAddTrackMagic) {
    mJsepSession->ApplyToTransceiver(aId, [](JsepTransceiver& aTransceiver) {
      aTransceiver.SetAddTrackMagic();
    });
  }

  RefPtr<RTCRtpTransceiver> transceiver = new RTCRtpTransceiver(
      mWindow, PrivacyRequested(), this, mTransportHandler, mJsepSession.get(),
      aId, aIsVideo, mSTSThread.get(), aSendTrack, mCall.get(), mIdGenerator);
@@ -4467,8 +4464,6 @@ already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
    return nullptr;
  }

  transceiver->SyncToJsep();

  if (aSendTrack) {
    // implement checking for peerIdentity (where failure == black/silence)
    Document* doc = mWindow->GetExtantDoc();
+3 −3
Original line number Diff line number Diff line
@@ -296,7 +296,7 @@ class PeerConnectionImpl final

  already_AddRefed<dom::RTCRtpTransceiver> AddTransceiver(
      const dom::RTCRtpTransceiverInit& aInit, const nsAString& aKind,
      dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv);
      dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv);

  bool CheckNegotiationNeeded();
  bool CreatedSender(const dom::RTCRtpSender& aSender) const;
@@ -614,7 +614,7 @@ class PeerConnectionImpl final
                                    std::string* transportId,
                                    bool* client) const;

  nsresult AddRtpTransceiverToJsepSession(RefPtr<JsepTransceiver>& transceiver);
  nsresult AddRtpTransceiverToJsepSession(JsepTransceiver& transceiver);

  void RecordIceRestartStatistics(JsepSdpType type);

@@ -825,7 +825,7 @@ class PeerConnectionImpl final
  already_AddRefed<dom::RTCRtpTransceiver> CreateTransceiver(
      const std::string& aId, bool aIsVideo,
      const dom::RTCRtpTransceiverInit& aInit,
      dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv);
      dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv);

  std::string GetTransportIdMatchingSendTrack(
      const dom::MediaStreamTrack& aTrack) const;
+2 −2
Original line number Diff line number Diff line
@@ -892,12 +892,12 @@ std::string RTCRtpReceiver::GetMid() const {

JsepTransceiver& RTCRtpReceiver::GetJsepTransceiver() {
  MOZ_ASSERT(mTransceiver);
  return *mTransceiver->GetJsepTransceiver();
  return mTransceiver->GetJsepTransceiver();
}

const JsepTransceiver& RTCRtpReceiver::GetJsepTransceiver() const {
  MOZ_ASSERT(mTransceiver);
  return *mTransceiver->GetJsepTransceiver();
  return mTransceiver->GetJsepTransceiver();
}

}  // namespace mozilla::dom
+28 −25
Original line number Diff line number Diff line
@@ -74,10 +74,6 @@ RTCRtpSender::RTCRtpSender(nsPIDOMWindowInner* aWindow, PeerConnectionImpl* aPc,

  if (aConduit->type() == MediaSessionConduit::AUDIO) {
    mDtmf = new RTCDTMFSender(aWindow, mTransceiver);
    GetJsepTransceiver().mSendTrack.SetMaxEncodings(1);
  } else {
    GetJsepTransceiver().mSendTrack.SetMaxEncodings(
        webrtc::kMaxSimulcastStreams);
  }
  mPipeline->SetTrack(mSenderTrack);

@@ -91,7 +87,7 @@ RTCRtpSender::RTCRtpSender(nsPIDOMWindowInner* aWindow, PeerConnectionImpl* aPc,
  if (aEncodings.Length()) {
    // This sender was created by addTransceiver with sendEncodings.
    mParameters.mEncodings = aEncodings;
    SetJsepRids(mParameters);
    mSimulcastEnvelopeSet = true;
    mozilla::glean::rtcrtpsender::used_sendencodings.AddToNumerator(1);
  } else {
    // This sender was created by addTrack, sRD(offer), or addTransceiver
@@ -724,7 +720,7 @@ already_AddRefed<Promise> RTCRtpSender::SetParameters(
  MaybeUpdateConduit();

  if (compatModeAllowedRidChange) {
    SetJsepRids(paramsCopy);
    mSimulcastEnvelopeSet = true;
  }

  // If the media stack is successfully configured with parameters,
@@ -841,22 +837,6 @@ void RTCRtpSender::CheckAndRectifyEncodings(
  }
}

void RTCRtpSender::SetJsepRids(const RTCRtpSendParameters& aParameters) {
  MOZ_ASSERT(aParameters.mEncodings.Length());

  std::vector<std::string> rids;
  for (const auto& encoding : aParameters.mEncodings) {
    if (encoding.mRid.WasPassed()) {
      rids.push_back(NS_ConvertUTF16toUTF8(encoding.mRid.Value()).get());
    } else {
      rids.push_back("");
    }
  }

  GetJsepTransceiver().mSendTrack.SetRids(rids);
  mSimulcastEnvelopeSet = true;
}

void RTCRtpSender::GetParameters(RTCRtpSendParameters& aParameters) {
  MOZ_ASSERT(mParameters.mEncodings.Length());
  // If sender.[[LastReturnedParameters]] is not null, return
@@ -1206,10 +1186,10 @@ void RTCRtpSender::SetTrack(const RefPtr<MediaStreamTrack>& aTrack) {
  mSenderTrack = aTrack;
  SeamlessTrackSwitch(aTrack);
  if (aTrack) {
    // RFC says:
    // RFC says (in the section on remote rollback):
    // However, an RtpTransceiver MUST NOT be removed if a track was attached
    // to the RtpTransceiver via the addTrack method.
    GetJsepTransceiver().SetOnlyExistsBecauseOfSetRemote(false);
    mAddTrackCalled = true;
  }
}

@@ -1314,6 +1294,29 @@ void RTCRtpSender::SyncToJsep(JsepTransceiver& aJsepTransceiver) const {
  }

  aJsepTransceiver.mSendTrack.UpdateStreamIds(streamIds);

  if (mSimulcastEnvelopeSet) {
    std::vector<std::string> rids;
    for (const auto& encoding : mParameters.mEncodings) {
      if (encoding.mRid.WasPassed()) {
        rids.push_back(NS_ConvertUTF16toUTF8(encoding.mRid.Value()).get());
      } else {
        rids.push_back("");
      }
    }

    aJsepTransceiver.mSendTrack.SetRids(rids);
  }

  if (mTransceiver->IsVideo()) {
    aJsepTransceiver.mSendTrack.SetMaxEncodings(webrtc::kMaxSimulcastStreams);
  } else {
    aJsepTransceiver.mSendTrack.SetMaxEncodings(1);
  }

  if (mAddTrackCalled) {
    aJsepTransceiver.SetOnlyExistsBecauseOfSetRemote(false);
  }
}

Maybe<RTCRtpSender::VideoConfig> RTCRtpSender::GetNewVideoConfig() {
@@ -1579,7 +1582,7 @@ RefPtr<MediaPipelineTransmit> RTCRtpSender::GetPipeline() const {
std::string RTCRtpSender::GetMid() const { return mTransceiver->GetMidAscii(); }

JsepTransceiver& RTCRtpSender::GetJsepTransceiver() {
  return *mTransceiver->GetJsepTransceiver();
  return mTransceiver->GetJsepTransceiver();
}

void RTCRtpSender::UpdateDtmfSender() {
Loading