1 // Copyright 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_client.h"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "net/base/io_buffer.h"
11 #include "remoting/protocol/clipboard_stub.h"
12 #include "remoting/protocol/host_control_dispatcher.h"
13 #include "remoting/protocol/host_event_dispatcher.h"
14 #include "remoting/protocol/host_stub.h"
15 #include "remoting/protocol/host_video_dispatcher.h"
16 #include "remoting/protocol/input_stub.h"
21 ConnectionToClient::ConnectionToClient(protocol::Session
* session
)
24 session_
->SetEventHandler(this);
27 ConnectionToClient::~ConnectionToClient() {
30 void ConnectionToClient::SetEventHandler(EventHandler
* event_handler
) {
31 DCHECK(CalledOnValidThread());
32 handler_
= event_handler
;
35 protocol::Session
* ConnectionToClient::session() {
36 DCHECK(CalledOnValidThread());
37 return session_
.get();
40 void ConnectionToClient::Disconnect() {
41 DCHECK(CalledOnValidThread());
45 // This should trigger OnConnectionClosed() event and this object
46 // may be destroyed as the result.
50 void ConnectionToClient::OnEventTimestamp(int64 sequence_number
) {
51 DCHECK(CalledOnValidThread());
52 handler_
->OnEventTimestamp(this, sequence_number
);
55 VideoStub
* ConnectionToClient::video_stub() {
56 DCHECK(CalledOnValidThread());
57 return video_dispatcher_
.get();
60 AudioStub
* ConnectionToClient::audio_stub() {
61 DCHECK(CalledOnValidThread());
62 return audio_writer_
.get();
65 // Return pointer to ClientStub.
66 ClientStub
* ConnectionToClient::client_stub() {
67 DCHECK(CalledOnValidThread());
68 return control_dispatcher_
.get();
71 void ConnectionToClient::set_clipboard_stub(
72 protocol::ClipboardStub
* clipboard_stub
) {
73 DCHECK(CalledOnValidThread());
74 control_dispatcher_
->set_clipboard_stub(clipboard_stub
);
77 void ConnectionToClient::set_host_stub(protocol::HostStub
* host_stub
) {
78 DCHECK(CalledOnValidThread());
79 control_dispatcher_
->set_host_stub(host_stub
);
82 void ConnectionToClient::set_input_stub(protocol::InputStub
* input_stub
) {
83 DCHECK(CalledOnValidThread());
84 event_dispatcher_
->set_input_stub(input_stub
);
87 void ConnectionToClient::set_video_feedback_stub(
88 VideoFeedbackStub
* video_feedback_stub
) {
89 DCHECK(CalledOnValidThread());
90 video_dispatcher_
->set_video_feedback_stub(video_feedback_stub
);
93 void ConnectionToClient::OnSessionStateChange(Session::State state
) {
94 DCHECK(CalledOnValidThread());
98 case Session::INITIALIZING
:
99 case Session::CONNECTING
:
100 case Session::ACCEPTING
:
101 case Session::CONNECTED
:
102 // Don't care about these events.
104 case Session::AUTHENTICATING
:
105 handler_
->OnConnectionAuthenticating(this);
107 case Session::AUTHENTICATED
:
108 // Initialize channels.
109 control_dispatcher_
.reset(new HostControlDispatcher());
110 control_dispatcher_
->Init(session_
.get(),
111 session_
->config().control_config(), this);
113 event_dispatcher_
.reset(new HostEventDispatcher());
114 event_dispatcher_
->Init(session_
.get(), session_
->config().event_config(),
116 event_dispatcher_
->set_event_timestamp_callback(base::Bind(
117 &ConnectionToClient::OnEventTimestamp
, base::Unretained(this)));
119 video_dispatcher_
.reset(new HostVideoDispatcher());
120 video_dispatcher_
->Init(session_
.get(), session_
->config().video_config(),
123 audio_writer_
= AudioWriter::Create(session_
->config());
124 if (audio_writer_
.get()) {
125 audio_writer_
->Init(session_
.get(), session_
->config().audio_config(),
129 // Notify the handler after initializing the channels, so that
130 // ClientSession can get a client clipboard stub.
131 handler_
->OnConnectionAuthenticated(this);
134 case Session::CLOSED
:
138 case Session::FAILED
:
139 Close(session_
->error());
144 void ConnectionToClient::OnSessionRouteChange(
145 const std::string
& channel_name
,
146 const TransportRoute
& route
) {
147 handler_
->OnRouteChange(this, channel_name
, route
);
150 void ConnectionToClient::OnChannelInitialized(
151 ChannelDispatcherBase
* channel_dispatcher
) {
152 DCHECK(CalledOnValidThread());
154 NotifyIfChannelsReady();
157 void ConnectionToClient::OnChannelError(
158 ChannelDispatcherBase
* channel_dispatcher
,
160 DCHECK(CalledOnValidThread());
162 LOG(ERROR
) << "Failed to connect channel "
163 << channel_dispatcher
->channel_name();
164 Close(CHANNEL_CONNECTION_ERROR
);
167 void ConnectionToClient::NotifyIfChannelsReady() {
168 DCHECK(CalledOnValidThread());
170 if (!control_dispatcher_
|| !control_dispatcher_
->is_connected())
172 if (!event_dispatcher_
|| !event_dispatcher_
->is_connected())
174 if (!video_dispatcher_
|| !video_dispatcher_
->is_connected())
176 if ((!audio_writer_
|| !audio_writer_
->is_connected()) &&
177 session_
->config().is_audio_enabled()) {
180 handler_
->OnConnectionChannelsConnected(this);
183 void ConnectionToClient::Close(ErrorCode error
) {
185 handler_
->OnConnectionClosed(this, error
);
188 void ConnectionToClient::CloseChannels() {
189 control_dispatcher_
.reset();
190 event_dispatcher_
.reset();
191 video_dispatcher_
.reset();
192 audio_writer_
.reset();
195 } // namespace protocol
196 } // namespace remoting