Index: webrtc/p2p/base/faketransportcontroller.h |
diff --git a/webrtc/p2p/base/faketransportcontroller.h b/webrtc/p2p/base/faketransportcontroller.h |
index d42a93ddae9f95cf1558f9d32f3273f5e9a113c3..9598b822ce0dcf43dff855ebc95b4de475ddf661 100644 |
--- a/webrtc/p2p/base/faketransportcontroller.h |
+++ b/webrtc/p2p/base/faketransportcontroller.h |
@@ -17,6 +17,7 @@ |
#include <vector> |
#include "webrtc/p2p/base/candidatepairinterface.h" |
+#include "webrtc/p2p/base/transport.h" |
#include "webrtc/p2p/base/transportchannel.h" |
#include "webrtc/p2p/base/transportcontroller.h" |
#include "webrtc/p2p/base/transportchannelimpl.h" |
@@ -33,6 +34,8 @@ |
#endif |
namespace cricket { |
+ |
+class FakeTransport; |
namespace { |
struct PacketMessageData : public rtc::MessageData { |
@@ -340,6 +343,146 @@ |
bool had_connection_ = false; |
}; |
+// Fake transport class, which can be passed to anything that needs a Transport. |
+// Can be informed of another FakeTransport via SetDestination (low-tech way |
+// of doing candidates) |
+class FakeTransport : public Transport { |
+ public: |
+ typedef std::map<int, FakeTransportChannel*> ChannelMap; |
+ |
+ explicit FakeTransport(const std::string& name) : Transport(name, nullptr) {} |
+ |
+ // Note that we only have a constructor with the allocator parameter so it can |
+ // be wrapped by a DtlsTransport. |
+ FakeTransport(const std::string& name, PortAllocator* allocator) |
+ : Transport(name, nullptr) {} |
+ |
+ ~FakeTransport() { DestroyAllChannels(); } |
+ |
+ const ChannelMap& channels() const { return channels_; } |
+ |
+ // If async, will send packets by "Post"-ing to message queue instead of |
+ // synchronously "Send"-ing. |
+ void SetAsync(bool async) { async_ = async; } |
+ void SetAsyncDelay(int delay_ms) { async_delay_ms_ = delay_ms; } |
+ |
+ // If |asymmetric| is true, only set the destination for this transport, and |
+ // not |dest|. |
+ void SetDestination(FakeTransport* dest, bool asymmetric = false) { |
+ dest_ = dest; |
+ for (const auto& kv : channels_) { |
+ kv.second->SetLocalCertificate(certificate_); |
+ SetChannelDestination(kv.first, kv.second, asymmetric); |
+ } |
+ } |
+ |
+ void SetWritable(bool writable) { |
+ for (const auto& kv : channels_) { |
+ kv.second->SetWritable(writable); |
+ } |
+ } |
+ |
+ void SetLocalCertificate( |
+ const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override { |
+ certificate_ = certificate; |
+ } |
+ bool GetLocalCertificate( |
+ rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override { |
+ if (!certificate_) |
+ return false; |
+ |
+ *certificate = certificate_; |
+ return true; |
+ } |
+ |
+ bool GetSslRole(rtc::SSLRole* role) const override { |
+ if (channels_.empty()) { |
+ return false; |
+ } |
+ return channels_.begin()->second->GetSslRole(role); |
+ } |
+ |
+ bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override { |
+ ssl_max_version_ = version; |
+ for (const auto& kv : channels_) { |
+ kv.second->set_ssl_max_protocol_version(ssl_max_version_); |
+ } |
+ return true; |
+ } |
+ rtc::SSLProtocolVersion ssl_max_protocol_version() const { |
+ return ssl_max_version_; |
+ } |
+ |
+ using Transport::local_description; |
+ using Transport::remote_description; |
+ using Transport::VerifyCertificateFingerprint; |
+ using Transport::NegotiateRole; |
+ |
+ protected: |
+ TransportChannelImpl* CreateTransportChannel(int component) override { |
+ if (channels_.find(component) != channels_.end()) { |
+ return nullptr; |
+ } |
+ FakeTransportChannel* channel = new FakeTransportChannel(name(), component); |
+ channel->set_ssl_max_protocol_version(ssl_max_version_); |
+ channel->SetAsync(async_); |
+ channel->SetAsyncDelay(async_delay_ms_); |
+ SetChannelDestination(component, channel, false); |
+ channels_[component] = channel; |
+ return channel; |
+ } |
+ |
+ void DestroyTransportChannel(TransportChannelImpl* channel) override { |
+ channels_.erase(channel->component()); |
+ delete channel; |
+ } |
+ |
+ private: |
+ FakeTransportChannel* GetFakeChannel(int component) { |
+ auto it = channels_.find(component); |
+ return (it != channels_.end()) ? it->second : nullptr; |
+ } |
+ |
+ void SetChannelDestination(int component, |
+ FakeTransportChannel* channel, |
+ bool asymmetric) { |
+ FakeTransportChannel* dest_channel = nullptr; |
+ if (dest_) { |
+ dest_channel = dest_->GetFakeChannel(component); |
+ if (dest_channel && !asymmetric) { |
+ dest_channel->SetLocalCertificate(dest_->certificate_); |
+ } |
+ } |
+ channel->SetDestination(dest_channel, asymmetric); |
+ } |
+ |
+ // Note, this is distinct from the Channel map owned by Transport. |
+ // This map just tracks the FakeTransportChannels created by this class. |
+ // It's mainly needed so that we can access a FakeTransportChannel directly, |
+ // even if wrapped by a DtlsTransportChannelWrapper. |
+ ChannelMap channels_; |
+ FakeTransport* dest_ = nullptr; |
+ bool async_ = false; |
+ int async_delay_ms_ = 0; |
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate_; |
+ rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; |
+}; |
+ |
+#ifdef HAVE_QUIC |
+class FakeQuicTransport : public QuicTransport { |
+ public: |
+ FakeQuicTransport(const std::string& transport_name) |
+ : QuicTransport(transport_name, nullptr, nullptr) {} |
+ |
+ protected: |
+ QuicTransportChannel* CreateTransportChannel(int component) override { |
+ FakeTransportChannel* fake_ice_transport_channel = |
+ new FakeTransportChannel(name(), component); |
+ return new QuicTransportChannel(fake_ice_transport_channel); |
+ } |
+}; |
+#endif |
+ |
// Fake candidate pair class, which can be passed to BaseChannel for testing |
// purposes. |
class FakeCandidatePair : public CandidatePairInterface { |
@@ -369,66 +512,52 @@ |
FakeTransportController() |
: TransportController(rtc::Thread::Current(), |
rtc::Thread::Current(), |
- nullptr) {} |
+ nullptr), |
+ fail_create_channel_(false) {} |
explicit FakeTransportController(bool redetermine_role_on_ice_restart) |
: TransportController(rtc::Thread::Current(), |
rtc::Thread::Current(), |
nullptr, |
- redetermine_role_on_ice_restart) {} |
+ redetermine_role_on_ice_restart), |
+ fail_create_channel_(false) {} |
explicit FakeTransportController(IceRole role) |
: TransportController(rtc::Thread::Current(), |
rtc::Thread::Current(), |
- nullptr) { |
+ nullptr), |
+ fail_create_channel_(false) { |
SetIceRole(role); |
} |
explicit FakeTransportController(rtc::Thread* network_thread) |
- : TransportController(rtc::Thread::Current(), network_thread, nullptr) {} |
+ : TransportController(rtc::Thread::Current(), network_thread, nullptr), |
+ fail_create_channel_(false) {} |
FakeTransportController(rtc::Thread* network_thread, IceRole role) |
- : TransportController(rtc::Thread::Current(), network_thread, nullptr) { |
+ : TransportController(rtc::Thread::Current(), network_thread, nullptr), |
+ fail_create_channel_(false) { |
SetIceRole(role); |
} |
- FakeTransportChannel* GetFakeTransportChannel_n( |
- const std::string& transport_name, |
- int component) { |
- return static_cast<FakeTransportChannel*>( |
- get_channel_for_testing(transport_name, component)); |
- } |
- |
- // Simulate the exchange of transport descriptions, and the gathering and |
- // exchange of ICE candidates. |
+ FakeTransport* GetTransport_n(const std::string& transport_name) { |
+ return static_cast<FakeTransport*>( |
+ TransportController::GetTransport_n(transport_name)); |
+ } |
+ |
void Connect(FakeTransportController* dest) { |
- for (const std::string& transport_name : transport_names_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, nullptr); |
- 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, nullptr); |
- 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)); |
+ rtc::Bind(&FakeTransportController::Connect_n, this, dest)); |
+ } |
+ |
+ TransportChannel* CreateTransportChannel_n(const std::string& transport_name, |
+ int component) override { |
+ if (fail_create_channel_) { |
+ return nullptr; |
+ } |
+ return TransportController::CreateTransportChannel_n(transport_name, |
+ component); |
} |
FakeCandidatePair* CreateFakeCandidatePair( |
@@ -443,35 +572,50 @@ |
return new FakeCandidatePair(local_candidate, remote_candidate); |
} |
+ void set_fail_channel_creation(bool fail_channel_creation) { |
+ fail_create_channel_ = fail_channel_creation; |
+ } |
+ |
protected: |
- // The ICE channel is never actually used by TransportController directly, |
- // since (currently) the DTLS channel pretends to be both ICE + DTLS. This |
- // will change when we get rid of TransportChannelImpl. |
- TransportChannelImpl* CreateIceTransportChannel_n( |
- const std::string& transport_name, |
- int component) override { |
- return nullptr; |
- } |
- |
- TransportChannelImpl* CreateDtlsTransportChannel_n( |
- const std::string& transport_name, |
- int component, |
- TransportChannelImpl*) override { |
- return new FakeTransportChannel(transport_name, component); |
+ Transport* CreateTransport_n(const std::string& transport_name) override { |
+#ifdef HAVE_QUIC |
+ if (quic()) { |
+ return new FakeQuicTransport(transport_name); |
+ } |
+#endif |
+ return new FakeTransport(transport_name); |
+ } |
+ |
+ void Connect_n(FakeTransportController* dest) { |
+ // Simulate the exchange of candidates. |
+ ConnectChannels_n(); |
+ dest->ConnectChannels_n(); |
+ for (auto& kv : transports()) { |
+ FakeTransport* transport = static_cast<FakeTransport*>(kv.second); |
+ transport->SetDestination(dest->GetTransport_n(kv.first)); |
+ } |
+ } |
+ |
+ void ConnectChannels_n() { |
+ TransportDescription faketransport_desc( |
+ std::vector<std::string>(), |
+ rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), |
+ rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), cricket::ICEMODE_FULL, |
+ cricket::CONNECTIONROLE_NONE, nullptr); |
+ for (auto& kv : transports()) { |
+ FakeTransport* transport = static_cast<FakeTransport*>(kv.second); |
+ // Set local transport description for FakeTransport before connecting. |
+ // Otherwise, the RTC_CHECK in Transport.ConnectChannel will fail. |
+ if (!transport->local_description()) { |
+ transport->SetLocalTransportDescription(faketransport_desc, |
+ cricket::CA_OFFER, nullptr); |
+ } |
+ transport->MaybeStartGathering(); |
+ } |
} |
private: |
- void SetChannelDestinations_n(FakeTransportController* dest) { |
- for (TransportChannelImpl* tc : channels_for_testing()) { |
- FakeTransportChannel* local = static_cast<FakeTransportChannel*>(tc); |
- FakeTransportChannel* remote = dest->GetFakeTransportChannel_n( |
- local->transport_name(), local->component()); |
- if (remote) { |
- bool asymmetric = false; |
- local->SetDestination(remote, asymmetric); |
- } |
- } |
- } |
+ bool fail_create_channel_; |
}; |
} // namespace cricket |