Home | History | Annotate | Download | only in protocol
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "remoting/protocol/jingle_session.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/test/test_timeouts.h"
     10 #include "base/time/time.h"
     11 #include "net/socket/socket.h"
     12 #include "net/socket/stream_socket.h"
     13 #include "net/url_request/url_request_context_getter.h"
     14 #include "remoting/base/constants.h"
     15 #include "remoting/jingle_glue/chromium_port_allocator.h"
     16 #include "remoting/jingle_glue/fake_signal_strategy.h"
     17 #include "remoting/jingle_glue/network_settings.h"
     18 #include "remoting/protocol/authenticator.h"
     19 #include "remoting/protocol/channel_authenticator.h"
     20 #include "remoting/protocol/connection_tester.h"
     21 #include "remoting/protocol/fake_authenticator.h"
     22 #include "remoting/protocol/jingle_session_manager.h"
     23 #include "remoting/protocol/libjingle_transport_factory.h"
     24 #include "testing/gmock/include/gmock/gmock.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 
     27 using testing::_;
     28 using testing::AtLeast;
     29 using testing::AtMost;
     30 using testing::DeleteArg;
     31 using testing::DoAll;
     32 using testing::InSequence;
     33 using testing::Invoke;
     34 using testing::InvokeWithoutArgs;
     35 using testing::Return;
     36 using testing::SaveArg;
     37 using testing::SetArgumentPointee;
     38 using testing::WithArg;
     39 
     40 namespace remoting {
     41 namespace protocol {
     42 
     43 namespace {
     44 
     45 const char kHostJid[] = "host1 (at) gmail.com/123";
     46 const char kClientJid[] = "host2 (at) gmail.com/321";
     47 
     48 // Send 100 messages 1024 bytes each. UDP messages are sent with 10ms delay
     49 // between messages (about 1 second for 100 messages).
     50 const int kMessageSize = 1024;
     51 const int kMessages = 100;
     52 const char kChannelName[] = "test_channel";
     53 
     54 void QuitCurrentThread() {
     55   base::MessageLoop::current()->PostTask(FROM_HERE,
     56                                          base::MessageLoop::QuitClosure());
     57 }
     58 
     59 ACTION(QuitThread) {
     60   QuitCurrentThread();
     61 }
     62 
     63 ACTION_P(QuitThreadOnCounter, counter) {
     64   --(*counter);
     65   EXPECT_GE(*counter, 0);
     66   if (*counter == 0)
     67     QuitCurrentThread();
     68 }
     69 
     70 class MockSessionManagerListener : public SessionManager::Listener {
     71  public:
     72   MOCK_METHOD0(OnSessionManagerReady, void());
     73   MOCK_METHOD2(OnIncomingSession,
     74                void(Session*,
     75                     SessionManager::IncomingSessionResponse*));
     76 };
     77 
     78 class MockSessionEventHandler : public Session::EventHandler {
     79  public:
     80   MOCK_METHOD1(OnSessionStateChange, void(Session::State));
     81   MOCK_METHOD2(OnSessionRouteChange, void(const std::string& channel_name,
     82                                           const TransportRoute& route));
     83 };
     84 
     85 class MockStreamChannelCallback {
     86  public:
     87   MOCK_METHOD1(OnDone, void(net::StreamSocket* socket));
     88 };
     89 
     90 }  // namespace
     91 
     92 class JingleSessionTest : public testing::Test {
     93  public:
     94   JingleSessionTest() {
     95     message_loop_.reset(new base::MessageLoopForIO());
     96   }
     97 
     98   // Helper method that handles OnIncomingSession().
     99   void SetHostSession(Session* session) {
    100     DCHECK(session);
    101     host_session_.reset(session);
    102     host_session_->SetEventHandler(&host_session_event_handler_);
    103 
    104     session->set_config(SessionConfig::ForTest());
    105   }
    106 
    107   void OnClientChannelCreated(scoped_ptr<net::StreamSocket> socket) {
    108     client_channel_callback_.OnDone(socket.get());
    109     client_socket_ = socket.Pass();
    110   }
    111 
    112   void OnHostChannelCreated(scoped_ptr<net::StreamSocket> socket) {
    113     host_channel_callback_.OnDone(socket.get());
    114     host_socket_ = socket.Pass();
    115   }
    116 
    117  protected:
    118   virtual void SetUp() {
    119   }
    120 
    121   virtual void TearDown() {
    122     CloseSessions();
    123     CloseSessionManager();
    124     message_loop_->RunUntilIdle();
    125   }
    126 
    127   void CloseSessions() {
    128     host_socket_.reset();
    129     host_session_.reset();
    130     client_socket_.reset();
    131     client_session_.reset();
    132   }
    133 
    134   void CreateSessionManagers(int auth_round_trips,
    135                         FakeAuthenticator::Action auth_action) {
    136     host_signal_strategy_.reset(new FakeSignalStrategy(kHostJid));
    137     client_signal_strategy_.reset(new FakeSignalStrategy(kClientJid));
    138     FakeSignalStrategy::Connect(host_signal_strategy_.get(),
    139                                 client_signal_strategy_.get());
    140 
    141     EXPECT_CALL(host_server_listener_, OnSessionManagerReady())
    142         .Times(1);
    143 
    144     NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_OUTGOING);
    145 
    146     scoped_ptr<TransportFactory> host_transport(new LibjingleTransportFactory(
    147         NULL,
    148         ChromiumPortAllocator::Create(NULL, network_settings)
    149             .PassAs<cricket::HttpPortAllocatorBase>(),
    150         network_settings));
    151     host_server_.reset(new JingleSessionManager(host_transport.Pass()));
    152     host_server_->Init(host_signal_strategy_.get(), &host_server_listener_);
    153 
    154     scoped_ptr<AuthenticatorFactory> factory(
    155         new FakeHostAuthenticatorFactory(auth_round_trips, auth_action, true));
    156     host_server_->set_authenticator_factory(factory.Pass());
    157 
    158     EXPECT_CALL(client_server_listener_, OnSessionManagerReady())
    159         .Times(1);
    160     scoped_ptr<TransportFactory> client_transport(new LibjingleTransportFactory(
    161         NULL,
    162         ChromiumPortAllocator::Create(NULL, network_settings)
    163             .PassAs<cricket::HttpPortAllocatorBase>(),
    164         network_settings));
    165     client_server_.reset(
    166         new JingleSessionManager(client_transport.Pass()));
    167     client_server_->Init(client_signal_strategy_.get(),
    168                          &client_server_listener_);
    169   }
    170 
    171   void CloseSessionManager() {
    172     if (host_server_.get()) {
    173       host_server_->Close();
    174       host_server_.reset();
    175     }
    176     if (client_server_.get()) {
    177       client_server_->Close();
    178       client_server_.reset();
    179     }
    180     host_signal_strategy_.reset();
    181     client_signal_strategy_.reset();
    182   }
    183 
    184   void InitiateConnection(int auth_round_trips,
    185                           FakeAuthenticator::Action auth_action,
    186                           bool expect_fail) {
    187     EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
    188         .WillOnce(DoAll(
    189             WithArg<0>(Invoke(this, &JingleSessionTest::SetHostSession)),
    190             SetArgumentPointee<1>(protocol::SessionManager::ACCEPT)));
    191 
    192     {
    193       InSequence dummy;
    194 
    195       EXPECT_CALL(host_session_event_handler_,
    196                   OnSessionStateChange(Session::CONNECTED))
    197           .Times(AtMost(1));
    198       if (expect_fail) {
    199         EXPECT_CALL(host_session_event_handler_,
    200                     OnSessionStateChange(Session::FAILED))
    201             .Times(1);
    202       } else {
    203         EXPECT_CALL(host_session_event_handler_,
    204                     OnSessionStateChange(Session::AUTHENTICATED))
    205             .Times(1);
    206         // Expect that the connection will be closed eventually.
    207         EXPECT_CALL(host_session_event_handler_,
    208                     OnSessionStateChange(Session::CLOSED))
    209             .Times(AtMost(1));
    210       }
    211     }
    212 
    213     {
    214       InSequence dummy;
    215 
    216       EXPECT_CALL(client_session_event_handler_,
    217                   OnSessionStateChange(Session::CONNECTED))
    218           .Times(AtMost(1));
    219       if (expect_fail) {
    220         EXPECT_CALL(client_session_event_handler_,
    221                     OnSessionStateChange(Session::FAILED))
    222             .Times(1);
    223       } else {
    224         EXPECT_CALL(client_session_event_handler_,
    225                     OnSessionStateChange(Session::AUTHENTICATED))
    226             .Times(1);
    227         // Expect that the connection will be closed eventually.
    228         EXPECT_CALL(client_session_event_handler_,
    229                     OnSessionStateChange(Session::CLOSED))
    230             .Times(AtMost(1));
    231       }
    232     }
    233 
    234     scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
    235         FakeAuthenticator::CLIENT, auth_round_trips, auth_action, true));
    236 
    237     client_session_ = client_server_->Connect(
    238         kHostJid, authenticator.Pass(),
    239         CandidateSessionConfig::CreateDefault());
    240     client_session_->SetEventHandler(&client_session_event_handler_);
    241 
    242     message_loop_->RunUntilIdle();
    243   }
    244 
    245   void CreateChannel() {
    246     client_session_->GetTransportChannelFactory()->CreateStreamChannel(
    247         kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated,
    248                                  base::Unretained(this)));
    249     host_session_->GetTransportChannelFactory()->CreateStreamChannel(
    250         kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated,
    251                                  base::Unretained(this)));
    252 
    253     int counter = 2;
    254     ExpectRouteChange(kChannelName);
    255     EXPECT_CALL(client_channel_callback_, OnDone(_))
    256         .WillOnce(QuitThreadOnCounter(&counter));
    257     EXPECT_CALL(host_channel_callback_, OnDone(_))
    258         .WillOnce(QuitThreadOnCounter(&counter));
    259     message_loop_->Run();
    260 
    261     EXPECT_TRUE(client_socket_.get());
    262     EXPECT_TRUE(host_socket_.get());
    263   }
    264 
    265   void ExpectRouteChange(const std::string& channel_name) {
    266     EXPECT_CALL(host_session_event_handler_,
    267                 OnSessionRouteChange(channel_name, _))
    268         .Times(AtLeast(1));
    269     EXPECT_CALL(client_session_event_handler_,
    270                 OnSessionRouteChange(channel_name, _))
    271         .Times(AtLeast(1));
    272   }
    273 
    274   scoped_ptr<base::MessageLoopForIO> message_loop_;
    275 
    276   scoped_ptr<FakeSignalStrategy> host_signal_strategy_;
    277   scoped_ptr<FakeSignalStrategy> client_signal_strategy_;
    278 
    279   scoped_ptr<JingleSessionManager> host_server_;
    280   MockSessionManagerListener host_server_listener_;
    281   scoped_ptr<JingleSessionManager> client_server_;
    282   MockSessionManagerListener client_server_listener_;
    283 
    284   scoped_ptr<Session> host_session_;
    285   MockSessionEventHandler host_session_event_handler_;
    286   scoped_ptr<Session> client_session_;
    287   MockSessionEventHandler client_session_event_handler_;
    288 
    289   MockStreamChannelCallback client_channel_callback_;
    290   MockStreamChannelCallback host_channel_callback_;
    291 
    292   scoped_ptr<net::StreamSocket> client_socket_;
    293   scoped_ptr<net::StreamSocket> host_socket_;
    294 };
    295 
    296 
    297 // Verify that we can create and destroy session managers without a
    298 // connection.
    299 TEST_F(JingleSessionTest, CreateAndDestoy) {
    300   CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
    301 }
    302 
    303 // Verify that an incoming session can be rejected, and that the
    304 // status of the connection is set to FAILED in this case.
    305 TEST_F(JingleSessionTest, RejectConnection) {
    306   CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
    307 
    308   // Reject incoming session.
    309   EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _))
    310       .WillOnce(SetArgumentPointee<1>(protocol::SessionManager::DECLINE));
    311 
    312   {
    313     InSequence dummy;
    314     EXPECT_CALL(client_session_event_handler_,
    315                 OnSessionStateChange(Session::FAILED))
    316         .Times(1);
    317   }
    318 
    319   scoped_ptr<Authenticator> authenticator(new FakeAuthenticator(
    320       FakeAuthenticator::CLIENT, 1, FakeAuthenticator::ACCEPT, true));
    321   client_session_ = client_server_->Connect(
    322       kHostJid, authenticator.Pass(), CandidateSessionConfig::CreateDefault());
    323   client_session_->SetEventHandler(&client_session_event_handler_);
    324 
    325   message_loop_->RunUntilIdle();
    326 }
    327 
    328 // Verify that we can connect two endpoints with single-step authentication.
    329 TEST_F(JingleSessionTest, Connect) {
    330   CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
    331   InitiateConnection(1, FakeAuthenticator::ACCEPT, false);
    332 
    333   // Verify that the client specified correct initiator value.
    334   ASSERT_GT(host_signal_strategy_->received_messages().size(), 0U);
    335   const buzz::XmlElement* initiate_xml =
    336       host_signal_strategy_->received_messages().front();
    337   const buzz::XmlElement* jingle_element =
    338       initiate_xml->FirstNamed(buzz::QName(kJingleNamespace, "jingle"));
    339   ASSERT_TRUE(jingle_element);
    340   ASSERT_EQ(kClientJid,
    341             jingle_element->Attr(buzz::QName(std::string(), "initiator")));
    342 }
    343 
    344 // Verify that we can connect two endpoints with multi-step authentication.
    345 TEST_F(JingleSessionTest, ConnectWithMultistep) {
    346   CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
    347   InitiateConnection(3, FakeAuthenticator::ACCEPT, false);
    348 }
    349 
    350 // Verify that connection is terminated when single-step auth fails.
    351 TEST_F(JingleSessionTest, ConnectWithBadAuth) {
    352   CreateSessionManagers(1, FakeAuthenticator::REJECT);
    353   InitiateConnection(1, FakeAuthenticator::ACCEPT, true);
    354 }
    355 
    356 // Verify that connection is terminated when multi-step auth fails.
    357 TEST_F(JingleSessionTest, ConnectWithBadMultistepAuth) {
    358   CreateSessionManagers(3, FakeAuthenticator::REJECT);
    359   InitiateConnection(3, FakeAuthenticator::ACCEPT, true);
    360 }
    361 
    362 // Verify that data can be sent over stream channel.
    363 TEST_F(JingleSessionTest, TestStreamChannel) {
    364   CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
    365   ASSERT_NO_FATAL_FAILURE(
    366       InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
    367 
    368   ASSERT_NO_FATAL_FAILURE(CreateChannel());
    369 
    370   StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
    371                                 kMessageSize, kMessages);
    372   tester.Start();
    373   message_loop_->Run();
    374   tester.CheckResults();
    375 }
    376 
    377 // Verify that data can be sent over a multiplexed channel.
    378 TEST_F(JingleSessionTest, TestMuxStreamChannel) {
    379   CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
    380   ASSERT_NO_FATAL_FAILURE(
    381       InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
    382 
    383   client_session_->GetMultiplexedChannelFactory()->CreateStreamChannel(
    384       kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated,
    385                                base::Unretained(this)));
    386   host_session_->GetMultiplexedChannelFactory()->CreateStreamChannel(
    387       kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated,
    388                                base::Unretained(this)));
    389 
    390   int counter = 2;
    391   ExpectRouteChange("mux");
    392   EXPECT_CALL(client_channel_callback_, OnDone(_))
    393       .WillOnce(QuitThreadOnCounter(&counter));
    394   EXPECT_CALL(host_channel_callback_, OnDone(_))
    395       .WillOnce(QuitThreadOnCounter(&counter));
    396   message_loop_->Run();
    397 
    398   EXPECT_TRUE(client_socket_.get());
    399   EXPECT_TRUE(host_socket_.get());
    400 
    401   StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
    402                                 kMessageSize, kMessages);
    403   tester.Start();
    404   message_loop_->Run();
    405   tester.CheckResults();
    406 }
    407 
    408 // Verify that we can connect channels with multistep auth.
    409 TEST_F(JingleSessionTest, TestMultistepAuthStreamChannel) {
    410   CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
    411   ASSERT_NO_FATAL_FAILURE(
    412       InitiateConnection(3, FakeAuthenticator::ACCEPT, false));
    413 
    414   ASSERT_NO_FATAL_FAILURE(CreateChannel());
    415 
    416   StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
    417                                 kMessageSize, kMessages);
    418   tester.Start();
    419   message_loop_->Run();
    420   tester.CheckResults();
    421 }
    422 
    423 // Verify that we shutdown properly when channel authentication fails.
    424 TEST_F(JingleSessionTest, TestFailedChannelAuth) {
    425   CreateSessionManagers(1, FakeAuthenticator::REJECT_CHANNEL);
    426   ASSERT_NO_FATAL_FAILURE(
    427       InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
    428 
    429   client_session_->GetTransportChannelFactory()->CreateStreamChannel(
    430       kChannelName, base::Bind(&JingleSessionTest::OnClientChannelCreated,
    431                                base::Unretained(this)));
    432   host_session_->GetTransportChannelFactory()->CreateStreamChannel(
    433       kChannelName, base::Bind(&JingleSessionTest::OnHostChannelCreated,
    434                                base::Unretained(this)));
    435 
    436   // Terminate the message loop when we get rejection notification
    437   // from the host.
    438   EXPECT_CALL(host_channel_callback_, OnDone(NULL))
    439       .WillOnce(QuitThread());
    440   EXPECT_CALL(client_channel_callback_, OnDone(_))
    441       .Times(AtMost(1));
    442   ExpectRouteChange(kChannelName);
    443 
    444   message_loop_->Run();
    445 
    446   EXPECT_TRUE(!host_socket_.get());
    447 }
    448 
    449 }  // namespace protocol
    450 }  // namespace remoting
    451