blob: 4c70e1f04226ad5df7791438c11d20a6cc24de0c [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/protocol/webrtc_transport.h"
#include <utility>
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "jingle/glue/thread_wrapper.h"
#include "net/base/io_buffer.h"
#include "net/url_request/url_request_context_getter.h"
#include "remoting/protocol/chromium_port_allocator.h"
#include "remoting/protocol/connection_tester.h"
#include "remoting/protocol/fake_authenticator.h"
#include "remoting/protocol/network_settings.h"
#include "remoting/protocol/p2p_stream_socket.h"
#include "remoting/protocol/transport_context.h"
#include "remoting/signaling/fake_signal_strategy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
namespace remoting {
namespace protocol {
namespace {
const char kChannelName[] = "test_channel";
class TestTransportEventHandler : public WebrtcTransport::EventHandler {
public:
typedef base::Callback<void(ErrorCode error)> ErrorCallback;
TestTransportEventHandler() {}
~TestTransportEventHandler() {}
// Both callbacks must be set before the test handler is passed to a Transport
// object.
void set_connected_callback(const base::Closure& callback) {
connected_callback_ = callback;
}
void set_error_callback(const ErrorCallback& callback) {
error_callback_ = callback;
}
// WebrtcTransport::EventHandler interface.
void OnWebrtcTransportConnected() override {
connected_callback_.Run();
}
void OnWebrtcTransportError(ErrorCode error) override {
error_callback_.Run(error);
}
private:
base::Closure connected_callback_;
ErrorCallback error_callback_;
DISALLOW_COPY_AND_ASSIGN(TestTransportEventHandler);
};
} // namespace
class WebrtcTransportTest : public testing::Test {
public:
WebrtcTransportTest() {
jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
network_settings_ =
NetworkSettings(NetworkSettings::NAT_TRAVERSAL_OUTGOING);
}
void ProcessTransportInfo(scoped_ptr<WebrtcTransport>* target_transport,
scoped_ptr<buzz::XmlElement> transport_info) {
ASSERT_TRUE(target_transport);
EXPECT_TRUE((*target_transport)
->ProcessTransportInfo(transport_info.get()));
}
protected:
void InitializeConnection() {
host_transport_.reset(
new WebrtcTransport(jingle_glue::JingleThreadWrapper::current(),
TransportContext::ForTests(TransportRole::SERVER),
&host_event_handler_));
host_authenticator_.reset(new FakeAuthenticator(
FakeAuthenticator::HOST, 0, FakeAuthenticator::ACCEPT, false));
client_transport_.reset(
new WebrtcTransport(jingle_glue::JingleThreadWrapper::current(),
TransportContext::ForTests(TransportRole::CLIENT),
&client_event_handler_));
client_authenticator_.reset(new FakeAuthenticator(
FakeAuthenticator::CLIENT, 0, FakeAuthenticator::ACCEPT, false));
}
void StartConnection() {
host_event_handler_.set_connected_callback(base::Bind(&base::DoNothing));
client_event_handler_.set_connected_callback(base::Bind(&base::DoNothing));
host_event_handler_.set_error_callback(base::Bind(
&WebrtcTransportTest::OnSessionError, base::Unretained(this)));
client_event_handler_.set_error_callback(base::Bind(
&WebrtcTransportTest::OnSessionError, base::Unretained(this)));
// Start both transports.
host_transport_->Start(
host_authenticator_.get(),
base::Bind(&WebrtcTransportTest::ProcessTransportInfo,
base::Unretained(this), &client_transport_));
client_transport_->Start(
client_authenticator_.get(),
base::Bind(&WebrtcTransportTest::ProcessTransportInfo,
base::Unretained(this), &host_transport_));
}
void WaitUntilConnected() {
int counter = 2;
host_event_handler_.set_connected_callback(
base::Bind(&WebrtcTransportTest::QuitRunLoopOnCounter,
base::Unretained(this), &counter));
client_event_handler_.set_connected_callback(
base::Bind(&WebrtcTransportTest::QuitRunLoopOnCounter,
base::Unretained(this), &counter));
run_loop_.reset(new base::RunLoop());
run_loop_->Run();
EXPECT_EQ(OK, error_);
}
void CreateDataStream() {
client_transport_->GetStreamChannelFactory()->CreateChannel(
kChannelName, base::Bind(&WebrtcTransportTest::OnClientChannelCreated,
base::Unretained(this)));
host_transport_->GetStreamChannelFactory()->CreateChannel(
kChannelName, base::Bind(&WebrtcTransportTest::OnHostChannelCreated,
base::Unretained(this)));
}
void OnClientChannelCreated(scoped_ptr<P2PStreamSocket> socket) {
client_socket_ = std::move(socket);
if (run_loop_ && host_socket_)
run_loop_->Quit();
}
void OnHostChannelCreated(scoped_ptr<P2PStreamSocket> socket) {
host_socket_ = std::move(socket);
if (run_loop_ && client_socket_)
run_loop_->Quit();
}
void OnSessionError(ErrorCode error) {
error_ = error;
run_loop_->Quit();
}
void QuitRunLoopOnCounter(int* counter) {
--(*counter);
if (*counter == 0)
run_loop_->Quit();
}
protected:
base::MessageLoopForIO message_loop_;
scoped_ptr<base::RunLoop> run_loop_;
NetworkSettings network_settings_;
scoped_ptr<WebrtcTransport> host_transport_;
TestTransportEventHandler host_event_handler_;
scoped_ptr<FakeAuthenticator> host_authenticator_;
scoped_ptr<WebrtcTransport> client_transport_;
TestTransportEventHandler client_event_handler_;
scoped_ptr<FakeAuthenticator> client_authenticator_;
scoped_ptr<P2PStreamSocket> client_socket_;
scoped_ptr<P2PStreamSocket> host_socket_;
ErrorCode error_ = OK;
};
TEST_F(WebrtcTransportTest, Connects) {
InitializeConnection();
StartConnection();
WaitUntilConnected();
}
TEST_F(WebrtcTransportTest, DataStream) {
InitializeConnection();
CreateDataStream();
StartConnection();
run_loop_.reset(new base::RunLoop());
run_loop_->Run();
const int kMessageSize = 1024;
const int kMessages = 100;
StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
kMessageSize, kMessages);
tester.Start();
message_loop_.Run();
tester.CheckResults();
}
} // namespace protocol
} // namespace remoting