|  | /* | 
|  | *  Copyright 2017 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "ortc/rtptransportadapter.h" | 
|  |  | 
|  | #include <algorithm>  // For std::find. | 
|  | #include <set> | 
|  | #include <sstream> | 
|  | #include <utility>  // For std::move. | 
|  |  | 
|  | #include "api/proxy.h" | 
|  | #include "rtc_base/logging.h" | 
|  | #include "rtc_base/ptr_util.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | BEGIN_OWNED_PROXY_MAP(RtpTransport) | 
|  | PROXY_SIGNALING_THREAD_DESTRUCTOR() | 
|  | PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtpPacketTransport) | 
|  | PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtcpPacketTransport) | 
|  | PROXY_METHOD1(RTCError, SetParameters, const RtpTransportParameters&) | 
|  | PROXY_CONSTMETHOD0(RtpTransportParameters, GetParameters) | 
|  | protected: | 
|  | RtpTransportAdapter* GetInternal() override { | 
|  | return internal(); | 
|  | } | 
|  | END_PROXY_MAP() | 
|  |  | 
|  | BEGIN_OWNED_PROXY_MAP(SrtpTransport) | 
|  | PROXY_SIGNALING_THREAD_DESTRUCTOR() | 
|  | PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtpPacketTransport) | 
|  | PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtcpPacketTransport) | 
|  | PROXY_METHOD1(RTCError, SetParameters, const RtpTransportParameters&) | 
|  | PROXY_CONSTMETHOD0(RtpTransportParameters, GetParameters) | 
|  | PROXY_METHOD1(RTCError, SetSrtpSendKey, const cricket::CryptoParams&) | 
|  | PROXY_METHOD1(RTCError, SetSrtpReceiveKey, const cricket::CryptoParams&) | 
|  | protected: | 
|  | RtpTransportAdapter* GetInternal() override { | 
|  | return internal(); | 
|  | } | 
|  | END_PROXY_MAP() | 
|  |  | 
|  | // static | 
|  | RTCErrorOr<std::unique_ptr<RtpTransportInterface>> | 
|  | RtpTransportAdapter::CreateProxied( | 
|  | const RtpTransportParameters& parameters, | 
|  | PacketTransportInterface* rtp, | 
|  | PacketTransportInterface* rtcp, | 
|  | RtpTransportControllerAdapter* rtp_transport_controller) { | 
|  | if (!rtp) { | 
|  | LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, | 
|  | "Must provide an RTP packet transport."); | 
|  | } | 
|  | if (!parameters.rtcp.mux && !rtcp) { | 
|  | LOG_AND_RETURN_ERROR( | 
|  | RTCErrorType::INVALID_PARAMETER, | 
|  | "Must provide an RTCP packet transport when RTCP muxing is not used."); | 
|  | } | 
|  | if (parameters.rtcp.mux && rtcp) { | 
|  | LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, | 
|  | "Creating an RtpTransport with RTCP muxing enabled, " | 
|  | "with a separate RTCP packet transport?"); | 
|  | } | 
|  | if (!rtp_transport_controller) { | 
|  | // Since OrtcFactory::CreateRtpTransport creates an RtpTransportController | 
|  | // automatically when one isn't passed in, this should never be reached. | 
|  | RTC_NOTREACHED(); | 
|  | LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, | 
|  | "Must provide an RTP transport controller."); | 
|  | } | 
|  | std::unique_ptr<RtpTransportAdapter> transport_adapter( | 
|  | new RtpTransportAdapter(parameters.rtcp, rtp, rtcp, | 
|  | rtp_transport_controller, | 
|  | false /*is_srtp_transport*/)); | 
|  | RTCError params_result = transport_adapter->SetParameters(parameters); | 
|  | if (!params_result.ok()) { | 
|  | return std::move(params_result); | 
|  | } | 
|  |  | 
|  | return RtpTransportProxyWithInternal<RtpTransportAdapter>::Create( | 
|  | rtp_transport_controller->signaling_thread(), | 
|  | rtp_transport_controller->worker_thread(), std::move(transport_adapter)); | 
|  | } | 
|  |  | 
|  | RTCErrorOr<std::unique_ptr<SrtpTransportInterface>> | 
|  | RtpTransportAdapter::CreateSrtpProxied( | 
|  | const RtpTransportParameters& parameters, | 
|  | PacketTransportInterface* rtp, | 
|  | PacketTransportInterface* rtcp, | 
|  | RtpTransportControllerAdapter* rtp_transport_controller) { | 
|  | if (!rtp) { | 
|  | LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, | 
|  | "Must provide an RTP packet transport."); | 
|  | } | 
|  | if (!parameters.rtcp.mux && !rtcp) { | 
|  | LOG_AND_RETURN_ERROR( | 
|  | RTCErrorType::INVALID_PARAMETER, | 
|  | "Must provide an RTCP packet transport when RTCP muxing is not used."); | 
|  | } | 
|  | if (parameters.rtcp.mux && rtcp) { | 
|  | LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, | 
|  | "Creating an RtpTransport with RTCP muxing enabled, " | 
|  | "with a separate RTCP packet transport?"); | 
|  | } | 
|  | if (!rtp_transport_controller) { | 
|  | // Since OrtcFactory::CreateRtpTransport creates an RtpTransportController | 
|  | // automatically when one isn't passed in, this should never be reached. | 
|  | RTC_NOTREACHED(); | 
|  | LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, | 
|  | "Must provide an RTP transport controller."); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<RtpTransportAdapter> transport_adapter; | 
|  | transport_adapter.reset(new RtpTransportAdapter(parameters.rtcp, rtp, rtcp, | 
|  | rtp_transport_controller, | 
|  | true /*is_srtp_transport*/)); | 
|  | RTCError params_result = transport_adapter->SetParameters(parameters); | 
|  | if (!params_result.ok()) { | 
|  | return std::move(params_result); | 
|  | } | 
|  |  | 
|  | return SrtpTransportProxyWithInternal<RtpTransportAdapter>::Create( | 
|  | rtp_transport_controller->signaling_thread(), | 
|  | rtp_transport_controller->worker_thread(), std::move(transport_adapter)); | 
|  | } | 
|  |  | 
|  | void RtpTransportAdapter::TakeOwnershipOfRtpTransportController( | 
|  | std::unique_ptr<RtpTransportControllerInterface> controller) { | 
|  | RTC_DCHECK_EQ(rtp_transport_controller_, controller->GetInternal()); | 
|  | RTC_DCHECK(owned_rtp_transport_controller_.get() == nullptr); | 
|  | owned_rtp_transport_controller_ = std::move(controller); | 
|  | } | 
|  |  | 
|  | RtpTransportAdapter::RtpTransportAdapter( | 
|  | const RtcpParameters& rtcp_params, | 
|  | PacketTransportInterface* rtp, | 
|  | PacketTransportInterface* rtcp, | 
|  | RtpTransportControllerAdapter* rtp_transport_controller, | 
|  | bool is_srtp_transport) | 
|  | : rtp_packet_transport_(rtp), | 
|  | rtcp_packet_transport_(rtcp), | 
|  | rtp_transport_controller_(rtp_transport_controller), | 
|  | network_thread_(rtp_transport_controller_->network_thread()) { | 
|  | parameters_.rtcp = rtcp_params; | 
|  | // CNAME should have been filled by OrtcFactory if empty. | 
|  | RTC_DCHECK(!parameters_.rtcp.cname.empty()); | 
|  | RTC_DCHECK(rtp_transport_controller); | 
|  |  | 
|  | if (is_srtp_transport) { | 
|  | srtp_transport_ = rtc::MakeUnique<SrtpTransport>(rtcp == nullptr); | 
|  | transport_ = srtp_transport_.get(); | 
|  | } else { | 
|  | unencrypted_rtp_transport_ = rtc::MakeUnique<RtpTransport>(rtcp == nullptr); | 
|  | transport_ = unencrypted_rtp_transport_.get(); | 
|  | } | 
|  | RTC_DCHECK(transport_); | 
|  |  | 
|  | network_thread_->Invoke<void>(RTC_FROM_HERE, [=] { | 
|  | SetRtpPacketTransport(rtp->GetInternal()); | 
|  | if (rtcp) { | 
|  | SetRtcpPacketTransport(rtcp->GetInternal()); | 
|  | } | 
|  | }); | 
|  |  | 
|  | transport_->SignalReadyToSend.connect(this, | 
|  | &RtpTransportAdapter::OnReadyToSend); | 
|  | transport_->SignalRtcpPacketReceived.connect( | 
|  | this, &RtpTransportAdapter::OnRtcpPacketReceived); | 
|  | transport_->SignalWritableState.connect( | 
|  | this, &RtpTransportAdapter::OnWritableState); | 
|  | } | 
|  |  | 
|  | RtpTransportAdapter::~RtpTransportAdapter() { | 
|  | SignalDestroyed(this); | 
|  | } | 
|  |  | 
|  | RTCError RtpTransportAdapter::SetParameters( | 
|  | const RtpTransportParameters& parameters) { | 
|  | if (!parameters.rtcp.mux && parameters_.rtcp.mux) { | 
|  | LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::INVALID_STATE, | 
|  | "Can't disable RTCP muxing after enabling."); | 
|  | } | 
|  | if (!parameters.rtcp.cname.empty() && | 
|  | parameters.rtcp.cname != parameters_.rtcp.cname) { | 
|  | LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::UNSUPPORTED_OPERATION, | 
|  | "Changing the RTCP CNAME is currently unsupported."); | 
|  | } | 
|  | // If the CNAME is empty, use the existing one. | 
|  | RtpTransportParameters copy = parameters; | 
|  | if (copy.rtcp.cname.empty()) { | 
|  | copy.rtcp.cname = parameters_.rtcp.cname; | 
|  | } | 
|  | RTCError err = | 
|  | rtp_transport_controller_->SetRtpTransportParameters(copy, this); | 
|  | if (!err.ok()) { | 
|  | return err; | 
|  | } | 
|  | parameters_ = copy; | 
|  | if (parameters_.rtcp.mux) { | 
|  | rtcp_packet_transport_ = nullptr; | 
|  | } | 
|  | return RTCError::OK(); | 
|  | } | 
|  |  | 
|  | RTCError RtpTransportAdapter::SetSrtpSendKey( | 
|  | const cricket::CryptoParams& params) { | 
|  | if (!network_thread_->IsCurrent()) { | 
|  | return network_thread_->Invoke<RTCError>( | 
|  | RTC_FROM_HERE, [&] { return SetSrtpSendKey(params); }); | 
|  | } | 
|  | return transport_->SetSrtpSendKey(params); | 
|  | } | 
|  |  | 
|  | RTCError RtpTransportAdapter::SetSrtpReceiveKey( | 
|  | const cricket::CryptoParams& params) { | 
|  | if (!network_thread_->IsCurrent()) { | 
|  | return network_thread_->Invoke<RTCError>( | 
|  | RTC_FROM_HERE, [&] { return SetSrtpReceiveKey(params); }); | 
|  | } | 
|  | return transport_->SetSrtpReceiveKey(params); | 
|  | } | 
|  |  | 
|  | }  // namespace webrtc |