/*
 *  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.
 */

#ifndef PC_JSEP_TRANSPORT_CONTROLLER_H_
#define PC_JSEP_TRANSPORT_CONTROLLER_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "api/async_dns_resolver.h"
#include "api/candidate.h"
#include "api/crypto/crypto_options.h"
#include "api/environment/environment.h"
#include "api/ice_transport_interface.h"
#include "api/jsep.h"
#include "api/local_network_access_permission.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/rtp_header_extension_id.h"
#include "api/rtp_transport_factory.h"
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "api/transport/data_channel_transport_interface.h"
#include "api/transport/ecn_marking.h"
#include "api/transport/sctp_transport_factory_interface.h"
#include "api/units/timestamp.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "p2p/base/ice_transport_internal.h"
#include "p2p/base/packet_transport_internal.h"
#include "p2p/base/port.h"
#include "p2p/base/port_allocator.h"
#include "p2p/base/transport_description.h"
#include "p2p/base/transport_info.h"
#include "p2p/dtls/dtls_transport_factory.h"
#include "p2p/dtls/dtls_transport_internal.h"
#include "pc/dtls_srtp_transport.h"
#include "pc/dtls_transport.h"
#include "pc/jsep_transport.h"
#include "pc/jsep_transport_collection.h"
#include "pc/rtp_transport.h"
#include "pc/rtp_transport_internal.h"
#include "pc/sctp_transport.h"
#include "pc/session_description.h"
#include "pc/transport_stats.h"
#include "rtc_base/containers/flat_map.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/ssl_certificate.h"
#include "rtc_base/ssl_stream_adapter.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h"

namespace webrtc {

class JsepTransportController final {
 public:
  // Used when the RtpTransport/DtlsTransport of the m= section is changed
  // because the section is rejected or BUNDLE is enabled.
  class Observer {
   public:
    virtual ~Observer() {}

    // Returns true if media associated with `mid` was successfully set up to be
    // demultiplexed on `rtp_transport`. Could return false if two bundled m=
    // sections use the same SSRC, for example.
    //
    // If a data channel transport must be negotiated, `data_channel_transport`
    // and `negotiation_state` indicate negotiation status.  If
    // `data_channel_transport` is null, the data channel transport should not
    // be used.  Otherwise, the value is a pointer to the transport to be used
    // for data channels on `mid`, if any.
    //
    // The observer should not send data on `data_channel_transport` until
    // `negotiation_state` is provisional or final.  It should not delete
    // `data_channel_transport` or any fallback transport until
    // `negotiation_state` is final.
    virtual bool OnTransportChanged(
        absl::string_view mid,
        RtpTransportInternal* rtp_transport,
        scoped_refptr<DtlsTransport> dtls_transport,
        DataChannelTransportInterface* data_channel_transport) = 0;
  };

  struct Config {
    // If `redetermine_role_on_ice_restart` is true, ICE role is redetermined
    // upon setting a local transport description that indicates an ICE
    // restart.
    bool redetermine_role_on_ice_restart = true;
    SSLProtocolVersion ssl_max_version = SSL_PROTOCOL_DTLS_12;
    // `crypto_options` is used to determine if created DTLS transports
    // negotiate GCM crypto suites or not.
    CryptoOptions crypto_options;
    PeerConnectionInterface::BundlePolicy bundle_policy =
        PeerConnectionInterface::kBundlePolicyBalanced;
    PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy =
        PeerConnectionInterface::kRtcpMuxPolicyRequire;
    bool disable_encryption = false;
    // Used to inject the ICE/DTLS/SRTP transports created externally.
    IceTransportFactory* ice_transport_factory = nullptr;
    DtlsTransportFactory* dtls_transport_factory = nullptr;
    RtpTransportFactory* rtp_transport_factory = nullptr;
    Observer* transport_observer = nullptr;
    // Must be provided and valid for the lifetime of the
    // JsepTransportController instance.
    absl::AnyInvocable<void(const CopyOnWriteBuffer& packet,
                            int64_t packet_time_us) const>
        rtcp_handler;
    absl::AnyInvocable<void(const RtpPacketReceived& parsed_packet) const>
        un_demuxable_packet_handler;

    // Factory for SCTP transports.
    SctpTransportFactoryInterface* sctp_factory = nullptr;
    absl::AnyInvocable<void(SSLHandshakeError) const> on_dtls_handshake_error =
        [](SSLHandshakeError s) {};
    absl::AnyInvocable<void(absl::string_view, const std::vector<Candidate>&)
                           const>
        signal_ice_candidates_gathered =
            [](absl::string_view, const std::vector<Candidate>&) {};
    absl::AnyInvocable<void(IceConnectionState) const>
        signal_ice_connection_state = [](IceConnectionState) {};
    absl::AnyInvocable<void(PeerConnectionInterface::PeerConnectionState) const>
        signal_connection_state =
            [](PeerConnectionInterface::PeerConnectionState) {};
    absl::AnyInvocable<void(PeerConnectionInterface::IceConnectionState) const>
        signal_standardized_ice_connection_state =
            [](PeerConnectionInterface::IceConnectionState) {};
    absl::AnyInvocable<void(webrtc::IceGatheringState) const>
        signal_ice_gathering_state = [](webrtc::IceGatheringState) {};
    absl::AnyInvocable<void(const webrtc::IceCandidateErrorEvent&) const>
        signal_ice_candidate_error =
            [](const webrtc::IceCandidateErrorEvent&) {};
    absl::AnyInvocable<void(IceTransportInternal*,
                            const std::vector<webrtc::Candidate>&) const>
        signal_ice_candidates_removed =
            [](IceTransportInternal*, const std::vector<webrtc::Candidate>&) {};
    absl::AnyInvocable<void(const webrtc::CandidatePairChangeEvent&) const>
        signal_ice_candidate_pair_changed =
            [](const webrtc::CandidatePairChangeEvent&) {};
  };

  struct TransportState {
    std::optional<SSLRole> dtls_role;
    bool needs_ice_restart = false;
  };

  // The ICE related events are fired on the `network_thread`.
  // All the transport related methods are called on the `network_thread`
  // and destruction of the JsepTransportController must occur on the
  // `network_thread`.
  JsepTransportController(
      const Environment& env,
      TaskQueueBase* signaling_thread,
      Thread* network_thread,
      PortAllocator* port_allocator,
      AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
      LocalNetworkAccessPermissionFactoryInterface* lna_permission_factory,
      Config config);
  ~JsepTransportController();

  JsepTransportController(const JsepTransportController&) = delete;
  JsepTransportController& operator=(const JsepTransportController&) = delete;

  // The main method to be called; applies a description at the transport
  // level, creating/destroying transport objects as needed and updating their
  // properties. This includes RTP, DTLS, and ICE (but not SCTP). At least not
  // yet? May make sense to in the future.
  //
  // `local_desc` must always be valid. If a remote description has previously
  // been set via a call to `SetRemoteDescription()` then `remote_desc` should
  // point to that description object in order to keep the current local and
  // remote session descriptions in sync.
  //
  // Must be called on the signaling thread.
  RTCError SetLocalDescription(SdpType type,
                               const SessionDescription* local_desc,
                               const SessionDescription* remote_desc);

  // Call to apply a remote description (See `SetLocalDescription()` for local).
  //
  // `remote_desc` must always be valid. If a local description has previously
  // been set via a call to `SetLocalDescription()` then `local_desc` should
  // point to that description object in order to keep the current local and
  // remote session descriptions in sync.
  //
  // Must be called on the signaling thread.
  RTCError SetRemoteDescription(SdpType type,
                                const SessionDescription* local_desc,
                                const SessionDescription* remote_desc);

  // Get transports to be used for the provided `mid`. If bundling is enabled,
  // calling GetRtpTransport for multiple MIDs may yield the same object.
  RtpTransportInternal* GetRtpTransport(absl::string_view mid) const;
  DtlsTransportInternal* GetDtlsTransport(absl::string_view mid);
  // Gets the externally sharable version of the DtlsTransport.
  scoped_refptr<DtlsTransport> LookupDtlsTransportByMid_n(
      absl::string_view mid);
  scoped_refptr<DtlsTransport> LookupDtlsTransportByMid(absl::string_view mid);
  scoped_refptr<SctpTransport> GetSctpTransport(absl::string_view mid) const;

  DataChannelTransportInterface* GetDataChannelTransport(
      absl::string_view mid) const;

  /*********************
   * ICE-related methods
   ********************/
  // This method is public to allow PeerConnection to update it from
  // SetConfiguration.
  void SetIceConfig(const IceConfig& config);
  // Set the "needs-ice-restart" flag as described in JSEP. After the flag is
  // set, offers should generate new ufrags/passwords until an ICE restart
  // occurs.
  void SetNeedsIceRestartFlag();
  // Returns true if the ICE restart flag above was set, and no ICE restart has
  // occurred yet for this transport (by applying a local description with
  // changed ufrag/password). If the transport has been deleted as a result of
  // bundling, returns false.
  //
  // Must be called on the signaling thread.
  bool NeedsIceRestart(absl::string_view mid) const;
  // Start gathering candidates for any new transports, or transports doing an
  // ICE restart. Returns the pooled ICE credentials from the port allocator.
  //
  // Must be called on the signaling thread.
  std::vector<IceParameters> MaybeStartGathering();
  RTCError AddRemoteCandidates(absl::string_view mid,
                               const std::vector<Candidate>& candidates);
  // Must be called on the signaling thread.
  bool RemoveRemoteCandidate(const IceCandidate* candidate);

  /**********************
   * DTLS-related methods
   *********************/
  // Specifies the identity to use in this session.
  // Can only be called once.
  //
  // Must be called on the signaling thread.
  bool SetLocalCertificate(const scoped_refptr<RTCCertificate>& certificate);
  scoped_refptr<RTCCertificate> GetLocalCertificate(
      absl::string_view mid) const;
  // Caller owns returned certificate chain. This method mainly exists for
  // stats reporting.
  std::unique_ptr<SSLCertChain> GetRemoteSSLCertChain(
      absl::string_view mid) const;
  // Get negotiated role, if one has been negotiated.
  //
  // Must be called on the signaling thread.
  std::optional<SSLRole> GetDtlsRole(absl::string_view mid) const;

  // Must be called on the signaling thread.
  void SetTransportStates(flat_map<std::string, TransportState> states);

  // Must be called on the network thread.
  flat_map<std::string, TransportState> GetTransportStates_n();

  bool GetStats(absl::string_view transport_name, TransportStats* stats) const;

  // Must be called on the signaling thread.
  RTCError RollbackTransports();

  // Must be called on the signaling thread.
  absl::AnyInvocable<void() &&> MakeCloseTask();

 private:
  // Always called via a blocking call from the signaling thread.
  RTCError SetLocalDescription_n(SdpType type,
                                 const SessionDescription* local_desc,
                                 const SessionDescription* remote_desc)
      RTC_RUN_ON(network_thread_);

  bool HasIceRestart_n(const SessionDescription* local_desc) const
      RTC_RUN_ON(network_thread_);

  // Always called via a blocking call from the signaling thread.
  RTCError SetRemoteDescription_n(SdpType type,
                                  const SessionDescription* local_desc,
                                  const SessionDescription* remote_desc)
      RTC_RUN_ON(network_thread_);

  // Always called via a blocking call from the signaling thread.
  bool RemoveRemoteCandidate_n(const IceCandidate* candidate)
      RTC_RUN_ON(network_thread_);

  // Always called via a blocking call from the signaling thread.
  RTCError RollbackTransports_n() RTC_RUN_ON(network_thread_);

  // Always called via a blocking call from the signaling thread.
  void MaybeStartGathering_n() RTC_RUN_ON(network_thread_);

  // Always called via a blocking call from the signaling thread.
  bool SetLocalCertificate_n(const scoped_refptr<RTCCertificate>& certificate)
      RTC_RUN_ON(network_thread_);

  // Called from SetLocalDescription and SetRemoteDescription.
  // When `local` is true, local_desc must be valid. Similarly when
  // `local` is false, remote_desc must be valid. The description counterpart
  // to the one that's being applied, may be nullptr but when it's supplied
  // the counterpart description's content groups will  be kept up to date for
  // `type == SdpType::kAnswer`.
  RTCError ApplyDescription_n(bool local,
                              SdpType type,
                              const SessionDescription* local_desc,
                              const SessionDescription* remote_desc)
      RTC_RUN_ON(network_thread_);

  RTCError ValidateAndMaybeUpdateBundleGroups(
      bool local,
      SdpType type,
      const SessionDescription* local_desc,
      const SessionDescription* remote_desc) RTC_RUN_ON(network_thread_);
  RTCError ValidateContent(const ContentInfo& content_info);

  void HandleRejectedContent(const ContentInfo& content_info)
      RTC_RUN_ON(network_thread_);
  bool HandleBundledContent(const ContentInfo& content_info,
                            const ContentGroup& bundle_group)
      RTC_RUN_ON(network_thread_);

  JsepTransportDescription CreateJsepTransportDescription(
      const ContentInfo& content_info,
      const TransportInfo& transport_info,
      const std::vector<RtpHeaderExtensionId>& encrypted_extension_ids);

  std::map<const ContentGroup*, std::vector<RtpHeaderExtensionId>>
  MergeEncryptedHeaderExtensionIdsForBundles(
      const SessionDescription* description);
  std::vector<RtpHeaderExtensionId> GetEncryptedHeaderExtensionIds(
      const ContentInfo& content_info);

  // This method takes the BUNDLE group into account. If the JsepTransport is
  // destroyed because of BUNDLE, it would return the transport which other
  // transports are bundled on (In current implementation, it is the first
  // content in the BUNDLE group).
  const JsepTransport* GetJsepTransportForMid(absl::string_view mid) const
      RTC_RUN_ON(network_thread_);
  JsepTransport* GetJsepTransportForMid(absl::string_view mid)
      RTC_RUN_ON(network_thread_);

  // Get the JsepTransport without considering the BUNDLE group. Return nullptr
  // if the JsepTransport is destroyed.
  const JsepTransport* GetJsepTransportByName(
      absl::string_view transport_name) const RTC_RUN_ON(network_thread_);
  JsepTransport* GetJsepTransportByName(absl::string_view transport_name)
      RTC_RUN_ON(network_thread_);

  // Creates jsep transport. Noop if transport is already created.
  // Transport is created either during SetLocalDescription (`local` == true) or
  // during SetRemoteDescription (`local` == false). Passing `local` helps to
  // differentiate initiator (caller) from answerer (callee).
  RTCError MaybeCreateJsepTransport(bool local,
                                    const ContentInfo& content_info,
                                    const SessionDescription& description)
      RTC_RUN_ON(network_thread_);

  void DestroyAllJsepTransports_n() RTC_RUN_ON(network_thread_);

  void SetIceRole_n(IceRole ice_role) RTC_RUN_ON(network_thread_);

  IceRole DetermineIceRole(JsepTransport* jsep_transport,
                           const TransportInfo& transport_info,
                           SdpType type,
                           bool local);

  std::unique_ptr<DtlsTransportInternal> CreateDtlsTransport(
      const ContentInfo& content_info,
      bool rtcp);
  scoped_refptr<IceTransportInterface> CreateIceTransport(
      absl::string_view transport_name,
      bool rtcp);
  std::unique_ptr<RtpTransport> CreateUnencryptedRtpTransport(
      absl::string_view transport_name,
      std::unique_ptr<PacketTransportInternal> rtp_packet_transport,
      std::unique_ptr<PacketTransportInternal> rtcp_packet_transport);

  // Creates a DTLS SRTP transport.
  std::unique_ptr<DtlsSrtpTransport> CreateDtlsSrtpTransport(
      absl::string_view transport_name,
      std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
      std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport);

  std::unique_ptr<RtpTransport> CreateRtpTransport(
      absl::string_view transport_name,
      std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
      std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport);

  // Collect all the DtlsTransports, including RTP and RTCP, from the
  // JsepTransports, including those not mapped to a MID because they are being
  // kept alive in case of rollback.
  std::vector<DtlsTransportInternal*> GetDtlsTransports();
  // Same as the above, but doesn't include rollback transports.
  // JsepTransportController can iterate all the DtlsTransports and update the
  // aggregate states.
  std::vector<DtlsTransportInternal*> GetActiveDtlsTransports();

  // Handlers for signals from Transport.
  void OnTransportWritableState_n(PacketTransportInternal* transport)
      RTC_RUN_ON(network_thread_);
  void OnTransportReceivingState_n(PacketTransportInternal* transport)
      RTC_RUN_ON(network_thread_);
  void OnTransportGatheringState_n(IceTransportInternal* transport)
      RTC_RUN_ON(network_thread_);
  void OnTransportCandidateGathered_n(IceTransportInternal* transport,
                                      const Candidate& candidate)
      RTC_RUN_ON(network_thread_);
  void OnTransportCandidateError_n(IceTransportInternal* transport,
                                   const IceCandidateErrorEvent& event)
      RTC_RUN_ON(network_thread_);
  void OnTransportCandidatesRemoved_n(IceTransportInternal* transport,
                                      const Candidates& candidates)
      RTC_RUN_ON(network_thread_);
  void OnTransportRoleConflict_n(IceTransportInternal* transport)
      RTC_RUN_ON(network_thread_);
  void OnDtlsRoleChange_n(DtlsTransportInternal* transport, SSLRole role)
      RTC_RUN_ON(network_thread_);
  void OnTransportStateChanged_n(IceTransportInternal* transport)
      RTC_RUN_ON(network_thread_);
  void OnTransportCandidatePairChanged_n(const CandidatePairChangeEvent& event)
      RTC_RUN_ON(network_thread_);
  void UpdateAggregateStates_n() RTC_RUN_ON(network_thread_);

  void OnRtcpPacketReceived_n(CopyOnWriteBuffer packet,
                              std::optional<Timestamp> arrival_time,
                              EcnMarking ecn) RTC_RUN_ON(network_thread_);
  void OnUnDemuxableRtpPacketReceived_n(const RtpPacketReceived& packet)
      RTC_RUN_ON(network_thread_);

  void OnDtlsHandshakeError(SSLHandshakeError error);

  bool OnTransportChanged(absl::string_view mid, JsepTransport* transport);

  const Environment env_;
  TaskQueueBase* const signaling_thread_;
  Thread* const network_thread_;
  PortAllocator* const port_allocator_ = nullptr;
  AsyncDnsResolverFactoryInterface* const async_dns_resolver_factory_ = nullptr;
  LocalNetworkAccessPermissionFactoryInterface* const lna_permission_factory_ =
      nullptr;

  JsepTransportCollection transports_ RTC_GUARDED_BY(network_thread_);
  // Aggregate states for Transports.
  // standardized_ice_connection_state_ is intended to replace
  // ice_connection_state, see bugs.webrtc.org/9308
  IceConnectionState ice_connection_state_ = kIceConnectionConnecting;
  PeerConnectionInterface::IceConnectionState
      standardized_ice_connection_state_ =
          PeerConnectionInterface::kIceConnectionNew;
  PeerConnectionInterface::PeerConnectionState combined_connection_state_ =
      PeerConnectionInterface::PeerConnectionState::kNew;
  IceGatheringState ice_gathering_state_ = kIceGatheringNew;

  const Config config_;

  bool ice_role_initialized_ RTC_GUARDED_BY(network_thread_) = false;

  IceConfig ice_config_;
  IceRole ice_role_ = ICEROLE_CONTROLLING;
  scoped_refptr<RTCCertificate> certificate_;

  BundleManager bundles_;

  flat_map<std::string, TransportState> transport_states_
      RTC_GUARDED_BY(signaling_thread_);

  scoped_refptr<PendingTaskSafetyFlag> role_update_safety_flag_s_
      RTC_GUARDED_BY(signaling_thread_);
  scoped_refptr<PendingTaskSafetyFlag> role_update_safety_flag_n_
      RTC_GUARDED_BY(network_thread_);
};

}  // namespace webrtc

#endif  // PC_JSEP_TRANSPORT_CONTROLLER_H_
