blob: b55fb96060a5154211341404d9cb9b6b24bd4a8e [file] [log] [blame]
sergeyu0fc40f92015-12-10 18:42:431// Copyright 2015 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/webrtc_connection_to_client.h"
6
sergeyu89d088b2015-12-24 00:22:447#include <utility>
8
sergeyu0fc40f92015-12-10 18:42:439#include "base/bind.h"
10#include "base/location.h"
sergeyue5767602015-12-28 19:49:0311#include "jingle/glue/thread_wrapper.h"
sergeyu0fc40f92015-12-10 18:42:4312#include "net/base/io_buffer.h"
13#include "remoting/codec/video_encoder.h"
isheriff3b9c0972016-05-11 18:08:5814#include "remoting/codec/webrtc_video_encoder_vpx.h"
sergeyucd16e2062016-09-12 19:28:3515#include "remoting/protocol/audio_source.h"
16#include "remoting/protocol/audio_stream.h"
sergeyu0fc40f92015-12-10 18:42:4317#include "remoting/protocol/clipboard_stub.h"
18#include "remoting/protocol/host_control_dispatcher.h"
19#include "remoting/protocol/host_event_dispatcher.h"
20#include "remoting/protocol/host_stub.h"
21#include "remoting/protocol/input_stub.h"
sergeyud059c462016-07-20 19:34:1022#include "remoting/protocol/message_pipe.h"
sergeyue5767602015-12-28 19:49:0323#include "remoting/protocol/transport_context.h"
sergeyu24b257a12016-10-09 02:46:2824#include "remoting/protocol/webrtc_audio_stream.h"
sergeyu0fc40f92015-12-10 18:42:4325#include "remoting/protocol/webrtc_transport.h"
sergeyu0fc40f92015-12-10 18:42:4326#include "remoting/protocol/webrtc_video_stream.h"
kjellander97705452016-02-10 14:51:2427#include "third_party/webrtc/api/mediastreaminterface.h"
28#include "third_party/webrtc/api/peerconnectioninterface.h"
sergeyu0fc40f92015-12-10 18:42:4329
30namespace remoting {
31namespace protocol {
32
sergeyue5767602015-12-28 19:49:0333// Currently the network thread is also used as worker thread for webrtc.
34//
35// TODO(sergeyu): Figure out if we would benefit from using a separate
36// thread as a worker thread.
sergeyu0fc40f92015-12-10 18:42:4337WebrtcConnectionToClient::WebrtcConnectionToClient(
dcheng0765c492016-04-06 22:41:5338 std::unique_ptr<protocol::Session> session,
isheriff87c2fbd2016-04-13 21:21:4439 scoped_refptr<protocol::TransportContext> transport_context,
sergeyu24b257a12016-10-09 02:46:2840 scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
41 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner)
isheriff87c2fbd2016-04-13 21:21:4442 : transport_(
43 new WebrtcTransport(jingle_glue::JingleThreadWrapper::current(),
44 transport_context,
45 this)),
sergeyue5767602015-12-28 19:49:0346 session_(std::move(session)),
isheriff87c2fbd2016-04-13 21:21:4447 video_encode_task_runner_(video_encode_task_runner),
sergeyu24b257a12016-10-09 02:46:2848 audio_task_runner_(audio_task_runner),
sergeyu4b00d042015-12-18 19:41:4249 control_dispatcher_(new HostControlDispatcher()),
sergeyu9102cff2016-04-07 19:14:0150 event_dispatcher_(new HostEventDispatcher()),
51 weak_factory_(this) {
sergeyu0fc40f92015-12-10 18:42:4352 session_->SetEventHandler(this);
isheriff87c2fbd2016-04-13 21:21:4453 session_->SetTransport(transport_.get());
sergeyu0fc40f92015-12-10 18:42:4354}
55
joedow18837eb2017-05-17 18:28:2456WebrtcConnectionToClient::~WebrtcConnectionToClient() {
57 DCHECK(thread_checker_.CalledOnValidThread());
58}
sergeyu0fc40f92015-12-10 18:42:4359
60void WebrtcConnectionToClient::SetEventHandler(
61 ConnectionToClient::EventHandler* event_handler) {
62 DCHECK(thread_checker_.CalledOnValidThread());
63 event_handler_ = event_handler;
64}
65
66protocol::Session* WebrtcConnectionToClient::session() {
67 DCHECK(thread_checker_.CalledOnValidThread());
68 return session_.get();
69}
70
71void WebrtcConnectionToClient::Disconnect(ErrorCode error) {
72 DCHECK(thread_checker_.CalledOnValidThread());
73
sergeyu0fc40f92015-12-10 18:42:4374 // This should trigger OnConnectionClosed() event and this object
75 // may be destroyed as the result.
76 session_->Close(error);
77}
78
dcheng0765c492016-04-06 22:41:5379std::unique_ptr<VideoStream> WebrtcConnectionToClient::StartVideoStream(
80 std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer) {
sergeyu24b257a12016-10-09 02:46:2881 DCHECK(thread_checker_.CalledOnValidThread());
82 DCHECK(transport_);
83
Zijie Heba571512017-11-20 20:22:2384 std::unique_ptr<WebrtcVideoStream> stream(
85 new WebrtcVideoStream(session_options_));
sergeyu24b257a12016-10-09 02:46:2886 stream->Start(std::move(desktop_capturer), transport_.get(),
87 video_encode_task_runner_);
sergeyue84cc622016-10-15 06:54:0388 stream->SetEventTimestampsSource(
89 event_dispatcher_->event_timestamps_source());
sergeyubf81cd62016-01-10 08:00:4290 return std::move(stream);
sergeyu0fc40f92015-12-10 18:42:4391}
92
sergeyucd16e2062016-09-12 19:28:3593std::unique_ptr<AudioStream> WebrtcConnectionToClient::StartAudioStream(
94 std::unique_ptr<AudioSource> audio_source) {
sergeyu24b257a12016-10-09 02:46:2895 DCHECK(thread_checker_.CalledOnValidThread());
96 DCHECK(transport_);
97
98 std::unique_ptr<WebrtcAudioStream> stream(new WebrtcAudioStream());
99 stream->Start(audio_task_runner_, std::move(audio_source), transport_.get());
100 return std::move(stream);
sergeyu0fc40f92015-12-10 18:42:43101}
102
103// Return pointer to ClientStub.
104ClientStub* WebrtcConnectionToClient::client_stub() {
105 DCHECK(thread_checker_.CalledOnValidThread());
106 return control_dispatcher_.get();
107}
108
109void WebrtcConnectionToClient::set_clipboard_stub(
110 protocol::ClipboardStub* clipboard_stub) {
111 DCHECK(thread_checker_.CalledOnValidThread());
112 control_dispatcher_->set_clipboard_stub(clipboard_stub);
113}
114
115void WebrtcConnectionToClient::set_host_stub(protocol::HostStub* host_stub) {
116 DCHECK(thread_checker_.CalledOnValidThread());
117 control_dispatcher_->set_host_stub(host_stub);
118}
119
120void WebrtcConnectionToClient::set_input_stub(protocol::InputStub* input_stub) {
121 DCHECK(thread_checker_.CalledOnValidThread());
122 event_dispatcher_->set_input_stub(input_stub);
123}
124
Zijie Heba571512017-11-20 20:22:23125void WebrtcConnectionToClient::ApplySessionOptions(
126 const SessionOptions& options) {
127 session_options_ = options;
Zijie Hecd945d732017-10-02 18:14:34128 DCHECK(transport_);
Zijie Heba571512017-11-20 20:22:23129 transport_->ApplySessionOptions(options);
Zijie Hecd945d732017-10-02 18:14:34130}
131
sergeyu0fc40f92015-12-10 18:42:43132void WebrtcConnectionToClient::OnSessionStateChange(Session::State state) {
133 DCHECK(thread_checker_.CalledOnValidThread());
134
135 DCHECK(event_handler_);
isheriff87c2fbd2016-04-13 21:21:44136 switch (state) {
sergeyu0fc40f92015-12-10 18:42:43137 case Session::INITIALIZING:
138 case Session::CONNECTING:
139 case Session::ACCEPTING:
140 case Session::ACCEPTED:
141 // Don't care about these events.
142 break;
sergeyu9102cff2016-04-07 19:14:01143
sergeyu0fc40f92015-12-10 18:42:43144 case Session::AUTHENTICATING:
sergeyu4e1f4cd2016-09-27 00:42:52145 event_handler_->OnConnectionAuthenticating();
sergeyu0fc40f92015-12-10 18:42:43146 break;
sergeyu9102cff2016-04-07 19:14:01147
148 case Session::AUTHENTICATED: {
149 base::WeakPtr<WebrtcConnectionToClient> self = weak_factory_.GetWeakPtr();
sergeyu4e1f4cd2016-09-27 00:42:52150 event_handler_->OnConnectionAuthenticated();
sergeyu9102cff2016-04-07 19:14:01151
152 // OnConnectionAuthenticated() call above may result in the connection
153 // being torn down.
154 if (self)
sergeyu4e1f4cd2016-09-27 00:42:52155 event_handler_->CreateMediaStreams();
sergeyu0fc40f92015-12-10 18:42:43156 break;
sergeyu9102cff2016-04-07 19:14:01157 }
158
sergeyu0fc40f92015-12-10 18:42:43159 case Session::CLOSED:
160 case Session::FAILED:
161 control_dispatcher_.reset();
162 event_dispatcher_.reset();
sergeyud059c462016-07-20 19:34:10163 transport_->Close(state == Session::CLOSED ? OK : session_->error());
sergeyu24b257a12016-10-09 02:46:28164 transport_.reset();
sergeyu0fc40f92015-12-10 18:42:43165 event_handler_->OnConnectionClosed(
sergeyu4e1f4cd2016-09-27 00:42:52166 state == Session::CLOSED ? OK : session_->error());
sergeyu0fc40f92015-12-10 18:42:43167 break;
168 }
169}
170
sergeyu62936a82016-01-06 23:27:52171void WebrtcConnectionToClient::OnWebrtcTransportConnecting() {
sergeyu24b257a12016-10-09 02:46:28172 DCHECK(thread_checker_.CalledOnValidThread());
sergeyucc40af912016-07-22 03:49:19173 // Create outgoing control channel. |event_dispatcher_| is initialized later
174 // because event channel is expected to be created by the client.
175 control_dispatcher_->Init(
176 transport_->CreateOutgoingChannel(control_dispatcher_->channel_name()),
177 this);
sergeyu62936a82016-01-06 23:27:52178}
179
sergeyue5767602015-12-28 19:49:03180void WebrtcConnectionToClient::OnWebrtcTransportConnected() {
sergeyu62936a82016-01-06 23:27:52181 DCHECK(thread_checker_.CalledOnValidThread());
sergeyue5767602015-12-28 19:49:03182}
183
184void WebrtcConnectionToClient::OnWebrtcTransportError(ErrorCode error) {
185 DCHECK(thread_checker_.CalledOnValidThread());
186 Disconnect(error);
sergeyu0fc40f92015-12-10 18:42:43187}
188
sergeyud059c462016-07-20 19:34:10189void WebrtcConnectionToClient::OnWebrtcTransportIncomingDataChannel(
190 const std::string& name,
191 std::unique_ptr<MessagePipe> pipe) {
sergeyu24b257a12016-10-09 02:46:28192 DCHECK(thread_checker_.CalledOnValidThread());
Joseph Arhar5f69f392017-07-01 00:33:20193 DCHECK(event_handler_);
194
sergeyud059c462016-07-20 19:34:10195 if (name == event_dispatcher_->channel_name() &&
196 !event_dispatcher_->is_connected()) {
sergeyud059c462016-07-20 19:34:10197 event_dispatcher_->Init(std::move(pipe), this);
Joseph Arhar5f69f392017-07-01 00:33:20198 return;
sergeyud059c462016-07-20 19:34:10199 }
Joseph Arhar5f69f392017-07-01 00:33:20200
201 event_handler_->OnIncomingDataChannel(name, std::move(pipe));
sergeyud059c462016-07-20 19:34:10202}
203
sergeyua4541602016-01-19 17:42:06204void WebrtcConnectionToClient::OnWebrtcTransportMediaStreamAdded(
205 scoped_refptr<webrtc::MediaStreamInterface> stream) {
sergeyu24b257a12016-10-09 02:46:28206 DCHECK(thread_checker_.CalledOnValidThread());
sergeyua4541602016-01-19 17:42:06207 LOG(WARNING) << "The client created an unexpected media stream.";
208}
209
210void WebrtcConnectionToClient::OnWebrtcTransportMediaStreamRemoved(
sergeyu24b257a12016-10-09 02:46:28211 scoped_refptr<webrtc::MediaStreamInterface> stream) {
212 DCHECK(thread_checker_.CalledOnValidThread());
213}
sergeyua4541602016-01-19 17:42:06214
sergeyu0fc40f92015-12-10 18:42:43215void WebrtcConnectionToClient::OnChannelInitialized(
216 ChannelDispatcherBase* channel_dispatcher) {
217 DCHECK(thread_checker_.CalledOnValidThread());
sergeyuf1005f62016-02-03 21:11:30218
219 if (control_dispatcher_ && control_dispatcher_->is_connected() &&
220 event_dispatcher_ && event_dispatcher_->is_connected()) {
sergeyu4e1f4cd2016-09-27 00:42:52221 event_handler_->OnConnectionChannelsConnected();
sergeyuf1005f62016-02-03 21:11:30222 }
sergeyu0fc40f92015-12-10 18:42:43223}
224
sergeyud059c462016-07-20 19:34:10225void WebrtcConnectionToClient::OnChannelClosed(
226 ChannelDispatcherBase* channel_dispatcher) {
227 DCHECK(thread_checker_.CalledOnValidThread());
228
229 LOG(ERROR) << "Channel " << channel_dispatcher->channel_name()
230 << " was closed unexpectedly.";
231 Disconnect(INCOMPATIBLE_PROTOCOL);
232}
233
sergeyu0fc40f92015-12-10 18:42:43234} // namespace protocol
235} // namespace remoting