text: /*
   *  Copyright 2009 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 WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_
  #define WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_
  
  #include <memory>
  #include <string>
  #include <vector>
  
  #include "webrtc/base/bind.h"
  #include "webrtc/base/sslfingerprint.h"
  #include "webrtc/base/thread.h"
  #include "webrtc/p2p/base/fakedtlstransport.h"
  #include "webrtc/p2p/base/fakeicetransport.h"
  #include "webrtc/p2p/base/transportcontroller.h"
  
  namespace cricket {
  
  // Fake TransportController class, which can be passed into a WebRtcSession
  // object for test purposes. Can be connected to other FakeTransportControllers
  // via Connect().
  //
  // This fake is unusual in that for the most part, it's implemented with the
  // real TransportController code, but with fake TransportChannels underneath.
  class FakeTransportController : public TransportController {
   public:
    FakeTransportController()
        : TransportController(rtc::Thread::Current(),
                              rtc::Thread::Current(),
                              nullptr) {}
  
    explicit FakeTransportController(bool redetermine_role_on_ice_restart)
        : TransportController(rtc::Thread::Current(),
                              rtc::Thread::Current(),
                              nullptr,
                              redetermine_role_on_ice_restart) {}
  
    explicit FakeTransportController(IceRole role)
        : TransportController(rtc::Thread::Current(),
                              rtc::Thread::Current(),
                              nullptr) {
      SetIceRole(role);
    }
  
    explicit FakeTransportController(rtc::Thread* network_thread)
        : TransportController(rtc::Thread::Current(), network_thread, nullptr) {}
  
    FakeTransportController(rtc::Thread* network_thread, IceRole role)
        : TransportController(rtc::Thread::Current(), network_thread, nullptr) {
      SetIceRole(role);
    }
  
    FakeDtlsTransport* GetFakeDtlsTransport_n(const std::string& transport_name,
                                              int component) {
      return static_cast<FakeDtlsTransport*>(
          get_channel_for_testing(transport_name, component));
    }
  
    // Simulate the exchange of transport descriptions, and the gathering and
    // exchange of ICE candidates.
    void Connect(FakeTransportController* dest) {
      for (const std::string& transport_name : transport_names_for_testing()) {
        std::unique_ptr<rtc::SSLFingerprint> local_fingerprint;
        std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint;
        if (certificate_for_testing()) {
          local_fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate(
              certificate_for_testing()));
        }
        if (dest->certificate_for_testing()) {
          remote_fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate(
              dest->certificate_for_testing()));
        }
        TransportDescription local_desc(
            std::vector<std::string>(),
            rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH),
            rtc::CreateRandomString(cricket::ICE_PWD_LENGTH),
            cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE,
            local_fingerprint.get());
        TransportDescription remote_desc(
            std::vector<std::string>(),
            rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH),
            rtc::CreateRandomString(cricket::ICE_PWD_LENGTH),
            cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE,
            remote_fingerprint.get());
        std::string err;
        SetLocalTransportDescription(transport_name, local_desc,
                                     cricket::CA_OFFER, &err);
        dest->SetRemoteTransportDescription(transport_name, local_desc,
                                            cricket::CA_OFFER, &err);
        dest->SetLocalTransportDescription(transport_name, remote_desc,
                                           cricket::CA_ANSWER, &err);
        SetRemoteTransportDescription(transport_name, remote_desc,
                                      cricket::CA_ANSWER, &err);
      }
      MaybeStartGathering();
      dest->MaybeStartGathering();
      network_thread()->Invoke<void>(
          RTC_FROM_HERE,
          rtc::Bind(&FakeTransportController::SetChannelDestinations_n, this,
                    dest));
    }
  
    void DestroyRtcpTransport(const std::string& transport_name) {
      DestroyDtlsTransport_n(transport_name,
                             cricket::ICE_CANDIDATE_COMPONENT_RTCP);
    }
  
   protected:
    IceTransportInternal* CreateIceTransportChannel_n(
        const std::string& transport_name,
        int component) override {
      return new FakeIceTransport(transport_name, component);
    }
  
    DtlsTransportInternal* CreateDtlsTransportChannel_n(
        const std::string& transport_name,
        int component,
        IceTransportInternal* ice) override {
      return new FakeDtlsTransport(static_cast<FakeIceTransport*>(ice));
    }
  
   private:
    void SetChannelDestinations_n(FakeTransportController* dest) {
      for (DtlsTransportInternal* tc : channels_for_testing()) {
        FakeDtlsTransport* local = static_cast<FakeDtlsTransport*>(tc);
        FakeDtlsTransport* remote = dest->GetFakeDtlsTransport_n(
            local->transport_name(), local->component());
        if (remote) {
          bool asymmetric = false;
          local->SetDestination(remote, asymmetric);
        }
      }
    }
  };
  
  }  // namespace cricket
  
  #endif  // WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_
  