15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/connection_to_host.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/constants.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/audio_reader.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/audio_stub.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/auth_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/authenticator.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/client_control_dispatcher.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/client_event_dispatcher.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/client_stub.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/protocol/client_video_dispatcher.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/clipboard_stub.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/errors.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/jingle_session_manager.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/transport.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/video_stub.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protocol {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28116680a4aac90f2aa7413d9095a592090648e557Ben MurdochConnectionToHost::ConnectionToHost()
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : event_callback_(NULL),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_stub_(NULL),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clipboard_stub_(NULL),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_stub_(NULL),
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      signal_strategy_(NULL),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_(INITIALIZING),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_(OK) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ConnectionToHost::~ConnectionToHost() {
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CloseChannels();
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (session_.get())
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    session_.reset();
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (session_manager_.get())
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    session_manager_.reset();
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (signal_strategy_)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    signal_strategy_->RemoveListener(this);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ConnectionToHost::Connect(SignalStrategy* signal_strategy,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               scoped_ptr<TransportFactory> transport_factory,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               scoped_ptr<Authenticator> authenticator,
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               const std::string& host_jid,
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               HostEventCallback* event_callback) {
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(client_stub_);
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(clipboard_stub_);
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(monitored_video_stub_);
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Initialize default |candidate_config_| if set_candidate_config() wasn't
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // called.
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!candidate_config_) {
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    candidate_config_ = CandidateSessionConfig::CreateDefault();
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!audio_stub_) {
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      candidate_config_->DisableAudioChannel();
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    candidate_config_->EnableVideoCodec(ChannelConfig::CODEC_VP9);
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  signal_strategy_ = signal_strategy;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_callback_ = event_callback;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  authenticator_ = authenticator.Pass();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save jid of the host. The actual connection is created later after
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |signal_strategy_| is connected.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host_jid_ = host_jid;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal_strategy_->AddListener(this);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal_strategy_->Connect();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_manager_.reset(new JingleSessionManager(transport_factory.Pass()));
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  session_manager_->Init(signal_strategy_, this);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetState(CONNECTING, OK);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ConnectionToHost::set_candidate_config(
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<CandidateSessionConfig> config) {
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(state_, INITIALIZING);
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  candidate_config_ = config.Pass();
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SessionConfig& ConnectionToHost::config() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return session_->config();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ClipboardStub* ConnectionToHost::clipboard_forwarder() {
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return &clipboard_forwarder_;
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)HostStub* ConnectionToHost::host_stub() {
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(wez): Add a HostFilter class, equivalent to input filter.
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return control_dispatcher_.get();
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)InputStub* ConnectionToHost::input_stub() {
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return &event_forwarder_;
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ConnectionToHost::set_client_stub(ClientStub* client_stub) {
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  client_stub_ = client_stub;
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ConnectionToHost::set_clipboard_stub(ClipboardStub* clipboard_stub) {
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  clipboard_stub_ = clipboard_stub;
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ConnectionToHost::set_video_stub(VideoStub* video_stub) {
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(video_stub);
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  monitored_video_stub_.reset(new MonitoredVideoStub(
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      video_stub,
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::TimeDelta::FromSeconds(
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          MonitoredVideoStub::kConnectivityCheckDelaySeconds),
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&ConnectionToHost::OnVideoChannelStatus,
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Unretained(this))));
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ConnectionToHost::set_audio_stub(AudioStub* audio_stub) {
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  audio_stub_ = audio_stub;
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::OnSignalStrategyStateChange(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignalStrategy::State state) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(event_callback_);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state == SignalStrategy::CONNECTED) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Connected as: " << signal_strategy_->GetLocalJid();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (state == SignalStrategy::DISCONNECTED) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Connection closed.";
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseOnError(SIGNALING_ERROR);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ConnectionToHost::OnSignalStrategyIncomingStanza(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const buzz::XmlElement* stanza) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::OnSessionManagerReady() {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After SessionManager is initialized we can try to connect to the host.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_ = session_manager_->Connect(
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      host_jid_, authenticator_.Pass(), candidate_config_.Pass());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_->SetEventHandler(this);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::OnIncomingSession(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Session* session,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionManager::IncomingSessionResponse* response) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Client always rejects incoming sessions.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *response = SessionManager::DECLINE;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::OnSessionStateChange(
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Session::State state) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(event_callback_);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Session::INITIALIZING:
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Session::CONNECTING:
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case Session::ACCEPTING:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Session::CONNECTED:
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case Session::AUTHENTICATING:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't care about these events.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Session::AUTHENTICATED:
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SetState(AUTHENTICATED, OK);
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      control_dispatcher_.reset(new ClientControlDispatcher());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      control_dispatcher_->Init(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_.get(), session_->config().control_config(),
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ConnectionToHost::OnChannelInitialized,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      control_dispatcher_->set_client_stub(client_stub_);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      control_dispatcher_->set_clipboard_stub(clipboard_stub_);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_dispatcher_.reset(new ClientEventDispatcher());
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_dispatcher_->Init(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_.get(), session_->config().event_config(),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ConnectionToHost::OnChannelInitialized,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      video_dispatcher_.reset(
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          new ClientVideoDispatcher(monitored_video_stub_.get()));
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      video_dispatcher_->Init(session_.get(), session_->config().video_config(),
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          base::Bind(&ConnectionToHost::OnChannelInitialized,
2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     base::Unretained(this)));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_reader_ = AudioReader::Create(session_->config());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (audio_reader_.get()) {
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        audio_reader_->Init(session_.get(), session_->config().audio_config(),
2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            base::Bind(&ConnectionToHost::OnChannelInitialized,
2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       base::Unretained(this)));
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_reader_->set_audio_stub(audio_stub_);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Session::CLOSED:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseChannels();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetState(CLOSED, OK);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case Session::FAILED:
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we were connected then treat signaling timeout error as if
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the connection was closed by the peer.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(sergeyu): This logic belongs to the webapp, but we
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // currently don't expose this error code to the webapp, and it
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // would be hard to add it because client plugin and webapp
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // versions may not be in sync. It should be easy to do after we
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // are finished moving the client plugin to NaCl.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (state_ == CONNECTED && session_->error() == SIGNALING_TIMEOUT) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CloseChannels();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetState(CLOSED, OK);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CloseOnError(session_->error());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::OnSessionRouteChange(const std::string& channel_name,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const TransportRoute& route) {
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  event_callback_->OnRouteChanged(channel_name, route);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ConnectionToHost::OnVideoChannelStatus(bool active) {
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  event_callback_->OnConnectionReady(active);
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ConnectionToHost::State ConnectionToHost::state() const {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::OnChannelInitialized(bool successful) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!successful) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to connect video channel";
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseOnError(CHANNEL_CONNECTION_ERROR);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyIfChannelsReady();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::NotifyIfChannelsReady() {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!control_dispatcher_.get() || !control_dispatcher_->is_connected())
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!event_dispatcher_.get() || !event_dispatcher_->is_connected())
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!video_dispatcher_.get() || !video_dispatcher_->is_connected())
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((!audio_reader_.get() || !audio_reader_->is_connected()) &&
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_->config().is_audio_enabled()) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ != AUTHENTICATED)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start forwarding clipboard and input events.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard_forwarder_.set_clipboard_stub(control_dispatcher_.get());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_forwarder_.set_input_stub(event_dispatcher_.get());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetState(CONNECTED, OK);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::CloseOnError(ErrorCode error) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseChannels();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetState(FAILED, error);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::CloseChannels() {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  control_dispatcher_.reset();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_dispatcher_.reset();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clipboard_forwarder_.set_clipboard_stub(NULL);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_forwarder_.set_input_stub(NULL);
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  video_dispatcher_.reset();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_reader_.reset();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConnectionToHost::SetState(State state, ErrorCode error) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |error| should be specified only when |state| is set to FAILED.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(state == FAILED || error == OK);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state != state_) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = state;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = error;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_callback_->OnConnectionState(state_, error_);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protocol
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
310