blob: 9c9285660d6870c56a9e5982cdbe4668d0de28e4 [file] [log] [blame]
[email protected]44f60762011-03-23 12:13:351// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]cb3b1f9312010-06-07 19:58:232// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]cd8d2372010-11-04 01:18:045#include "remoting/protocol/connection_to_client.h"
[email protected]cb3b1f9312010-06-07 19:58:236
[email protected]182ec8f22011-08-11 02:14:357#include "base/bind.h"
[email protected]c62dd9d2011-09-21 18:05:418#include "base/location.h"
[email protected]60fc96002011-08-12 23:07:059#include "base/message_loop_proxy.h"
[email protected]cb3b1f9312010-06-07 19:58:2310#include "google/protobuf/message.h"
[email protected]c3af26f332010-10-06 22:46:0011#include "net/base/io_buffer.h"
[email protected]35b9c562010-11-09 02:22:4312#include "remoting/protocol/client_control_sender.h"
[email protected]6fd3d6a12010-11-16 19:53:3513#include "remoting/protocol/host_message_dispatcher.h"
[email protected]f0a9d1b2011-03-04 21:31:4414#include "remoting/protocol/host_stub.h"
15#include "remoting/protocol/input_stub.h"
[email protected]cb3b1f9312010-06-07 19:58:2316
[email protected]cd8d2372010-11-04 01:18:0417// TODO(hclam): Remove this header once MessageDispatcher is used.
[email protected]b3c03402010-11-16 01:27:4618#include "remoting/base/compound_buffer.h"
[email protected]cd8d2372010-11-04 01:18:0419
[email protected]cb3b1f9312010-06-07 19:58:2320namespace remoting {
[email protected]d87c4042010-11-04 00:46:0121namespace protocol {
[email protected]cb3b1f9312010-06-07 19:58:2322
23// Determine how many update streams we should count to find the size of
24// average update stream.
[email protected]887cec82010-06-15 22:13:4325static const size_t kAverageUpdateStream = 10;
[email protected]cb3b1f9312010-06-07 19:58:2326
[email protected]60fc96002011-08-12 23:07:0527ConnectionToClient::ConnectionToClient(base::MessageLoopProxy* message_loop,
[email protected]4ea2c7c2011-03-31 14:20:0628 EventHandler* handler)
[email protected]60fc96002011-08-12 23:07:0529 : message_loop_(message_loop),
[email protected]6fd3d6a12010-11-16 19:53:3530 handler_(handler),
[email protected]44f60762011-03-23 12:13:3531 host_stub_(NULL),
[email protected]182ec8f22011-08-11 02:14:3532 input_stub_(NULL),
33 control_connected_(false),
34 input_connected_(false),
35 video_connected_(false) {
[email protected]60fc96002011-08-12 23:07:0536 DCHECK(message_loop_);
[email protected]cb3b1f9312010-06-07 19:58:2337 DCHECK(handler_);
38}
39
[email protected]cd8d2372010-11-04 01:18:0440ConnectionToClient::~ConnectionToClient() {
[email protected]cb3b1f9312010-06-07 19:58:2341 // TODO(hclam): When we shut down the viewer we may have to close the
[email protected]c3af26f332010-10-06 22:46:0042 // connection.
[email protected]cb3b1f9312010-06-07 19:58:2343}
44
[email protected]cd8d2372010-11-04 01:18:0445void ConnectionToClient::Init(protocol::Session* session) {
[email protected]60fc96002011-08-12 23:07:0546 DCHECK(message_loop_->BelongsToCurrentThread());
[email protected]964bd392011-07-06 17:25:2547 session_.reset(session);
[email protected]230d2fd2010-11-03 21:56:4248 session_->SetStateChangeCallback(
[email protected]9e2a3132011-10-07 05:07:4049 base::Bind(&ConnectionToClient::OnSessionStateChange,
50 base::Unretained(this)));
[email protected]e295ff062010-07-15 22:56:0451}
52
[email protected]cd8d2372010-11-04 01:18:0453protocol::Session* ConnectionToClient::session() {
[email protected]964bd392011-07-06 17:25:2554 return session_.get();
[email protected]d6e6d13c2010-10-27 19:11:4455}
56
[email protected]cd8d2372010-11-04 01:18:0457void ConnectionToClient::Disconnect() {
[email protected]28876a72010-11-30 22:12:3358 // This method can be called from main thread so perform threading switching.
[email protected]60fc96002011-08-12 23:07:0559 if (!message_loop_->BelongsToCurrentThread()) {
60 message_loop_->PostTask(
[email protected]1e1cb3b2011-11-10 02:07:4161 FROM_HERE, base::Bind(&ConnectionToClient::Disconnect, this));
[email protected]28876a72010-11-30 22:12:3362 return;
63 }
[email protected]cb3b1f9312010-06-07 19:58:2364
[email protected]86dbc722011-06-30 23:23:3065 CloseChannels();
66
[email protected]3962b772011-07-07 21:07:5467 // If there is a session then release it, causing it to close.
68 if (session_.get())
[email protected]964bd392011-07-06 17:25:2569 session_.reset();
[email protected]cb3b1f9312010-06-07 19:58:2370}
71
[email protected]c0f70822011-05-06 21:19:2972void ConnectionToClient::UpdateSequenceNumber(int64 sequence_number) {
73 handler_->OnSequenceNumberUpdated(this, sequence_number);
74}
75
[email protected]c56acf54ff2010-11-19 23:44:4576VideoStub* ConnectionToClient::video_stub() {
77 return video_writer_.get();
78}
[email protected]b104b502010-10-18 20:21:3179
[email protected]c56acf54ff2010-11-19 23:44:4580// Return pointer to ClientStub.
81ClientStub* ConnectionToClient::client_stub() {
[email protected]86dbc722011-06-30 23:23:3082 return client_control_sender_.get();
[email protected]c56acf54ff2010-11-19 23:44:4583}
84
[email protected]44f60762011-03-23 12:13:3585void ConnectionToClient::set_host_stub(protocol::HostStub* host_stub) {
86 host_stub_ = host_stub;
87}
88
[email protected]4ea2c7c2011-03-31 14:20:0689void ConnectionToClient::set_input_stub(protocol::InputStub* input_stub) {
90 input_stub_ = input_stub;
91}
92
[email protected]c56acf54ff2010-11-19 23:44:4593void ConnectionToClient::OnSessionStateChange(protocol::Session::State state) {
[email protected]60fc96002011-08-12 23:07:0594 DCHECK(message_loop_->BelongsToCurrentThread());
[email protected]cb3b1f9312010-06-07 19:58:2395
96 DCHECK(handler_);
97 switch(state) {
[email protected]230d2fd2010-11-03 21:56:4298 case protocol::Session::CONNECTING:
[email protected]182ec8f22011-08-11 02:14:3599 // Don't care about this message.
[email protected]cb3b1f9312010-06-07 19:58:23100 break;
[email protected]182ec8f22011-08-11 02:14:35101
[email protected]230d2fd2010-11-03 21:56:42102 case protocol::Session::CONNECTED:
[email protected]60fc96002011-08-12 23:07:05103 video_writer_.reset(
104 VideoWriter::Create(message_loop_, session_->config()));
[email protected]182ec8f22011-08-11 02:14:35105 video_writer_->Init(
106 session_.get(), base::Bind(&ConnectionToClient::OnVideoInitialized,
107 base::Unretained(this)));
108 break;
109
110 case protocol::Session::CONNECTED_CHANNELS:
[email protected]86dbc722011-06-30 23:23:30111 client_control_sender_.reset(
[email protected]60fc96002011-08-12 23:07:05112 new ClientControlSender(message_loop_, session_->control_channel()));
[email protected]86dbc722011-06-30 23:23:30113 dispatcher_.reset(new HostMessageDispatcher());
114 dispatcher_->Initialize(this, host_stub_, input_stub_);
[email protected]1290af92011-08-10 01:05:31115
[email protected]182ec8f22011-08-11 02:14:35116 control_connected_ = true;
117 input_connected_ = true;
118 NotifyIfChannelsReady();
[email protected]cb3b1f9312010-06-07 19:58:23119 break;
[email protected]182ec8f22011-08-11 02:14:35120
[email protected]230d2fd2010-11-03 21:56:42121 case protocol::Session::CLOSED:
[email protected]86dbc722011-06-30 23:23:30122 CloseChannels();
[email protected]cb3b1f9312010-06-07 19:58:23123 handler_->OnConnectionClosed(this);
124 break;
[email protected]182ec8f22011-08-11 02:14:35125
[email protected]230d2fd2010-11-03 21:56:42126 case protocol::Session::FAILED:
[email protected]182ec8f22011-08-11 02:14:35127 CloseOnError();
[email protected]cb3b1f9312010-06-07 19:58:23128 break;
[email protected]182ec8f22011-08-11 02:14:35129
[email protected]cb3b1f9312010-06-07 19:58:23130 default:
131 // We shouldn't receive other states.
132 NOTREACHED();
133 }
134}
135
[email protected]182ec8f22011-08-11 02:14:35136void ConnectionToClient::OnVideoInitialized(bool successful) {
137 if (!successful) {
138 LOG(ERROR) << "Failed to connect video channel";
139 CloseOnError();
140 return;
141 }
142
143 video_connected_ = true;
144 NotifyIfChannelsReady();
145}
146
147void ConnectionToClient::NotifyIfChannelsReady() {
148 if (control_connected_ && input_connected_ && video_connected_)
149 handler_->OnConnectionOpened(this);
150}
151
152void ConnectionToClient::CloseOnError() {
153 CloseChannels();
154 handler_->OnConnectionFailed(this);
155}
156
[email protected]86dbc722011-06-30 23:23:30157void ConnectionToClient::CloseChannels() {
158 if (video_writer_.get())
159 video_writer_->Close();
160 if (client_control_sender_.get())
161 client_control_sender_->Close();
162}
163
[email protected]d87c4042010-11-04 00:46:01164} // namespace protocol
[email protected]cb3b1f9312010-06-07 19:58:23165} // namespace remoting