Update WebFrameTestProxy and WebTestProxy to mostly follow Chrome style.
[chromium-blink-merge.git] / remoting / protocol / connection_to_host.cc
blobd2ce7ff3112e38ca2ac0af19ca3b04041a399475
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.
5 #include "remoting/protocol/connection_to_host.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/location.h"
10 #include "remoting/base/constants.h"
11 #include "remoting/jingle_glue/signal_strategy.h"
12 #include "remoting/protocol/audio_reader.h"
13 #include "remoting/protocol/audio_stub.h"
14 #include "remoting/protocol/auth_util.h"
15 #include "remoting/protocol/authenticator.h"
16 #include "remoting/protocol/client_control_dispatcher.h"
17 #include "remoting/protocol/client_event_dispatcher.h"
18 #include "remoting/protocol/client_stub.h"
19 #include "remoting/protocol/clipboard_stub.h"
20 #include "remoting/protocol/errors.h"
21 #include "remoting/protocol/jingle_session_manager.h"
22 #include "remoting/protocol/transport.h"
23 #include "remoting/protocol/video_reader.h"
24 #include "remoting/protocol/video_stub.h"
26 namespace remoting {
27 namespace protocol {
29 ConnectionToHost::ConnectionToHost(
30 bool allow_nat_traversal)
31 : allow_nat_traversal_(allow_nat_traversal),
32 event_callback_(NULL),
33 client_stub_(NULL),
34 clipboard_stub_(NULL),
35 audio_stub_(NULL),
36 signal_strategy_(NULL),
37 state_(INITIALIZING),
38 error_(OK) {
41 ConnectionToHost::~ConnectionToHost() {
42 CloseChannels();
44 if (session_.get())
45 session_.reset();
47 if (session_manager_.get())
48 session_manager_.reset();
50 if (signal_strategy_)
51 signal_strategy_->RemoveListener(this);
54 ClipboardStub* ConnectionToHost::clipboard_stub() {
55 return &clipboard_forwarder_;
58 HostStub* ConnectionToHost::host_stub() {
59 // TODO(wez): Add a HostFilter class, equivalent to input filter.
60 return control_dispatcher_.get();
63 InputStub* ConnectionToHost::input_stub() {
64 return &event_forwarder_;
67 void ConnectionToHost::Connect(SignalStrategy* signal_strategy,
68 const std::string& host_jid,
69 const std::string& host_public_key,
70 scoped_ptr<TransportFactory> transport_factory,
71 scoped_ptr<Authenticator> authenticator,
72 HostEventCallback* event_callback,
73 ClientStub* client_stub,
74 ClipboardStub* clipboard_stub,
75 VideoStub* video_stub,
76 AudioStub* audio_stub) {
77 signal_strategy_ = signal_strategy;
78 event_callback_ = event_callback;
79 client_stub_ = client_stub;
80 clipboard_stub_ = clipboard_stub;
81 monitored_video_stub_.reset(new MonitoredVideoStub(
82 video_stub,
83 base::TimeDelta::FromSeconds(
84 MonitoredVideoStub::kConnectivityCheckDelaySeconds),
85 base::Bind(&ConnectionToHost::OnVideoChannelStatus,
86 base::Unretained(this))));
87 audio_stub_ = audio_stub;
88 authenticator_ = authenticator.Pass();
90 // Save jid of the host. The actual connection is created later after
91 // |signal_strategy_| is connected.
92 host_jid_ = host_jid;
93 host_public_key_ = host_public_key;
95 signal_strategy_->AddListener(this);
96 signal_strategy_->Connect();
98 session_manager_.reset(new JingleSessionManager(transport_factory.Pass()));
99 session_manager_->Init(signal_strategy_, this);
101 SetState(CONNECTING, OK);
104 const SessionConfig& ConnectionToHost::config() {
105 return session_->config();
108 void ConnectionToHost::OnSignalStrategyStateChange(
109 SignalStrategy::State state) {
110 DCHECK(CalledOnValidThread());
111 DCHECK(event_callback_);
113 if (state == SignalStrategy::CONNECTED) {
114 VLOG(1) << "Connected as: " << signal_strategy_->GetLocalJid();
115 } else if (state == SignalStrategy::DISCONNECTED) {
116 VLOG(1) << "Connection closed.";
117 CloseOnError(SIGNALING_ERROR);
121 bool ConnectionToHost::OnSignalStrategyIncomingStanza(
122 const buzz::XmlElement* stanza) {
123 return false;
126 void ConnectionToHost::OnSessionManagerReady() {
127 DCHECK(CalledOnValidThread());
129 // After SessionManager is initialized we can try to connect to the host.
130 scoped_ptr<CandidateSessionConfig> candidate_config =
131 CandidateSessionConfig::CreateDefault();
132 if (!audio_stub_)
133 CandidateSessionConfig::DisableAudioChannel(candidate_config.get());
135 session_ = session_manager_->Connect(
136 host_jid_, authenticator_.Pass(), candidate_config.Pass());
137 session_->SetEventHandler(this);
140 void ConnectionToHost::OnIncomingSession(
141 Session* session,
142 SessionManager::IncomingSessionResponse* response) {
143 DCHECK(CalledOnValidThread());
144 // Client always rejects incoming sessions.
145 *response = SessionManager::DECLINE;
148 void ConnectionToHost::OnSessionStateChange(
149 Session::State state) {
150 DCHECK(CalledOnValidThread());
151 DCHECK(event_callback_);
153 switch (state) {
154 case Session::INITIALIZING:
155 case Session::CONNECTING:
156 case Session::ACCEPTING:
157 case Session::CONNECTED:
158 case Session::AUTHENTICATING:
159 // Don't care about these events.
160 break;
162 case Session::AUTHENTICATED:
163 SetState(AUTHENTICATED, OK);
165 control_dispatcher_.reset(new ClientControlDispatcher());
166 control_dispatcher_->Init(
167 session_.get(), session_->config().control_config(),
168 base::Bind(&ConnectionToHost::OnChannelInitialized,
169 base::Unretained(this)));
170 control_dispatcher_->set_client_stub(client_stub_);
171 control_dispatcher_->set_clipboard_stub(clipboard_stub_);
173 event_dispatcher_.reset(new ClientEventDispatcher());
174 event_dispatcher_->Init(
175 session_.get(), session_->config().event_config(),
176 base::Bind(&ConnectionToHost::OnChannelInitialized,
177 base::Unretained(this)));
179 video_reader_ = VideoReader::Create(session_->config());
180 video_reader_->Init(session_.get(), monitored_video_stub_.get(),
181 base::Bind(&ConnectionToHost::OnChannelInitialized,
182 base::Unretained(this)));
184 audio_reader_ = AudioReader::Create(session_->config());
185 if (audio_reader_.get()) {
186 audio_reader_->Init(session_.get(), session_->config().audio_config(),
187 base::Bind(&ConnectionToHost::OnChannelInitialized,
188 base::Unretained(this)));
189 audio_reader_->set_audio_stub(audio_stub_);
191 break;
193 case Session::CLOSED:
194 CloseChannels();
195 SetState(CLOSED, OK);
196 break;
198 case Session::FAILED:
199 // If we were connected then treat signaling timeout error as if
200 // the connection was closed by the peer.
202 // TODO(sergeyu): This logic belongs to the webapp, but we
203 // currently don't expose this error code to the webapp, and it
204 // would be hard to add it because client plugin and webapp
205 // versions may not be in sync. It should be easy to do after we
206 // are finished moving the client plugin to NaCl.
207 if (state_ == CONNECTED && session_->error() == SIGNALING_TIMEOUT) {
208 CloseChannels();
209 SetState(CLOSED, OK);
210 } else {
211 CloseOnError(session_->error());
213 break;
217 void ConnectionToHost::OnSessionRouteChange(const std::string& channel_name,
218 const TransportRoute& route) {
219 event_callback_->OnRouteChanged(channel_name, route);
222 void ConnectionToHost::OnVideoChannelStatus(bool active) {
223 event_callback_->OnConnectionReady(active);
226 ConnectionToHost::State ConnectionToHost::state() const {
227 return state_;
230 void ConnectionToHost::OnChannelInitialized(bool successful) {
231 if (!successful) {
232 LOG(ERROR) << "Failed to connect video channel";
233 CloseOnError(CHANNEL_CONNECTION_ERROR);
234 return;
237 NotifyIfChannelsReady();
240 void ConnectionToHost::NotifyIfChannelsReady() {
241 if (!control_dispatcher_.get() || !control_dispatcher_->is_connected())
242 return;
243 if (!event_dispatcher_.get() || !event_dispatcher_->is_connected())
244 return;
245 if (!video_reader_.get() || !video_reader_->is_connected())
246 return;
247 if ((!audio_reader_.get() || !audio_reader_->is_connected()) &&
248 session_->config().is_audio_enabled()) {
249 return;
251 if (state_ != AUTHENTICATED)
252 return;
254 // Start forwarding clipboard and input events.
255 clipboard_forwarder_.set_clipboard_stub(control_dispatcher_.get());
256 event_forwarder_.set_input_stub(event_dispatcher_.get());
257 SetState(CONNECTED, OK);
260 void ConnectionToHost::CloseOnError(ErrorCode error) {
261 CloseChannels();
262 SetState(FAILED, error);
265 void ConnectionToHost::CloseChannels() {
266 control_dispatcher_.reset();
267 event_dispatcher_.reset();
268 clipboard_forwarder_.set_clipboard_stub(NULL);
269 event_forwarder_.set_input_stub(NULL);
270 video_reader_.reset();
271 audio_reader_.reset();
274 void ConnectionToHost::SetState(State state, ErrorCode error) {
275 DCHECK(CalledOnValidThread());
276 // |error| should be specified only when |state| is set to FAILED.
277 DCHECK(state == FAILED || error == OK);
279 if (state != state_) {
280 state_ = state;
281 error_ = error;
282 event_callback_->OnConnectionState(state_, error_);
286 } // namespace protocol
287 } // namespace remoting