ice_connection_to_host.cc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // 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. #include "remoting/protocol/ice_connection_to_host.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/location.h"
  10. #include "remoting/base/constants.h"
  11. #include "remoting/protocol/audio_decode_scheduler.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/client_control_dispatcher.h"
  16. #include "remoting/protocol/client_event_dispatcher.h"
  17. #include "remoting/protocol/client_stub.h"
  18. #include "remoting/protocol/client_video_dispatcher.h"
  19. #include "remoting/protocol/clipboard_stub.h"
  20. #include "remoting/protocol/errors.h"
  21. #include "remoting/protocol/ice_transport.h"
  22. #include "remoting/protocol/transport_context.h"
  23. #include "remoting/protocol/video_renderer.h"
  24. namespace remoting {
  25. namespace protocol {
  26. IceConnectionToHost::IceConnectionToHost() = default;
  27. IceConnectionToHost::~IceConnectionToHost() {
  28. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  29. }
  30. void IceConnectionToHost::Connect(
  31. std::unique_ptr<Session> session,
  32. scoped_refptr<TransportContext> transport_context,
  33. HostEventCallback* event_callback) {
  34. DCHECK(client_stub_);
  35. DCHECK(clipboard_stub_);
  36. DCHECK(video_renderer_);
  37. transport_ = std::make_unique<IceTransport>(transport_context, this);
  38. session_ = std::move(session);
  39. session_->SetEventHandler(this);
  40. session_->SetTransport(transport_.get());
  41. event_callback_ = event_callback;
  42. SetState(CONNECTING, OK);
  43. }
  44. void IceConnectionToHost::Disconnect(ErrorCode error) {
  45. session_->Close(error);
  46. }
  47. const SessionConfig& IceConnectionToHost::config() {
  48. return session_->config();
  49. }
  50. ClipboardStub* IceConnectionToHost::clipboard_forwarder() {
  51. return &clipboard_forwarder_;
  52. }
  53. HostStub* IceConnectionToHost::host_stub() {
  54. // TODO(wez): Add a HostFilter class, equivalent to input filter.
  55. return control_dispatcher_.get();
  56. }
  57. InputStub* IceConnectionToHost::input_stub() {
  58. return &event_forwarder_;
  59. }
  60. void IceConnectionToHost::set_client_stub(ClientStub* client_stub) {
  61. client_stub_ = client_stub;
  62. }
  63. void IceConnectionToHost::set_clipboard_stub(ClipboardStub* clipboard_stub) {
  64. clipboard_stub_ = clipboard_stub;
  65. }
  66. void IceConnectionToHost::set_video_renderer(VideoRenderer* video_renderer) {
  67. DCHECK(video_renderer);
  68. DCHECK(!monitored_video_stub_);
  69. video_renderer_ = video_renderer;
  70. }
  71. void IceConnectionToHost::InitializeAudio(
  72. scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
  73. base::WeakPtr<AudioStub> audio_stub) {
  74. audio_decode_scheduler_ = std::make_unique<AudioDecodeScheduler>(
  75. audio_decode_task_runner, audio_stub);
  76. }
  77. void IceConnectionToHost::OnSessionStateChange(Session::State state) {
  78. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  79. DCHECK(event_callback_);
  80. switch (state) {
  81. case Session::INITIALIZING:
  82. case Session::CONNECTING:
  83. case Session::ACCEPTING:
  84. case Session::ACCEPTED:
  85. case Session::AUTHENTICATING:
  86. // Don't care about these events.
  87. break;
  88. case Session::AUTHENTICATED:
  89. SetState(AUTHENTICATED, OK);
  90. // Setup control channel.
  91. control_dispatcher_ = std::make_unique<ClientControlDispatcher>();
  92. control_dispatcher_->Init(transport_->GetMultiplexedChannelFactory(),
  93. this);
  94. control_dispatcher_->set_client_stub(client_stub_);
  95. control_dispatcher_->set_clipboard_stub(clipboard_stub_);
  96. // Setup event channel.
  97. event_dispatcher_ = std::make_unique<ClientEventDispatcher>();
  98. event_dispatcher_->Init(transport_->GetMultiplexedChannelFactory(), this);
  99. // Configure video pipeline.
  100. video_renderer_->OnSessionConfig(session_->config());
  101. monitored_video_stub_ = std::make_unique<MonitoredVideoStub>(
  102. video_renderer_->GetVideoStub(),
  103. base::Seconds(MonitoredVideoStub::kConnectivityCheckDelaySeconds),
  104. base::BindRepeating(&IceConnectionToHost::OnVideoChannelStatus,
  105. base::Unretained(this)));
  106. video_dispatcher_ = std::make_unique<ClientVideoDispatcher>(
  107. monitored_video_stub_.get(), client_stub_);
  108. video_dispatcher_->Init(transport_->GetChannelFactory(), this);
  109. // Configure audio pipeline if necessary.
  110. if (session_->config().is_audio_enabled()) {
  111. audio_reader_ =
  112. std::make_unique<AudioReader>(audio_decode_scheduler_.get());
  113. audio_reader_->Init(transport_->GetMultiplexedChannelFactory(), this);
  114. audio_decode_scheduler_->Initialize(session_->config());
  115. }
  116. break;
  117. case Session::CLOSED:
  118. CloseChannels();
  119. SetState(CLOSED, OK);
  120. break;
  121. case Session::FAILED:
  122. // If we were connected then treat signaling timeout error as if
  123. // the connection was closed by the peer.
  124. //
  125. // TODO(sergeyu): This logic belongs to the webapp, but we
  126. // currently don't expose this error code to the webapp, and it
  127. // would be hard to add it because client plugin and webapp
  128. // versions may not be in sync. It should be easy to do after we
  129. // are finished moving the client plugin to NaCl.
  130. CloseChannels();
  131. if (state_ == CONNECTED && session_->error() == SIGNALING_TIMEOUT) {
  132. SetState(CLOSED, OK);
  133. } else {
  134. SetState(FAILED, session_->error());
  135. }
  136. break;
  137. }
  138. }
  139. void IceConnectionToHost::OnIceTransportRouteChange(
  140. const std::string& channel_name,
  141. const TransportRoute& route) {
  142. event_callback_->OnRouteChanged(channel_name, route);
  143. }
  144. void IceConnectionToHost::OnIceTransportError(ErrorCode error) {
  145. session_->Close(error);
  146. }
  147. void IceConnectionToHost::OnChannelInitialized(
  148. ChannelDispatcherBase* channel_dispatcher) {
  149. NotifyIfChannelsReady();
  150. }
  151. void IceConnectionToHost::OnChannelClosed(
  152. ChannelDispatcherBase* channel_dispatcher) {
  153. session_->Close(OK);
  154. }
  155. void IceConnectionToHost::OnVideoChannelStatus(bool active) {
  156. event_callback_->OnConnectionReady(active);
  157. }
  158. ConnectionToHost::State IceConnectionToHost::state() const {
  159. return state_;
  160. }
  161. void IceConnectionToHost::NotifyIfChannelsReady() {
  162. if (!control_dispatcher_.get() || !control_dispatcher_->is_connected())
  163. return;
  164. if (!event_dispatcher_.get() || !event_dispatcher_->is_connected())
  165. return;
  166. if (!video_dispatcher_.get() || !video_dispatcher_->is_connected())
  167. return;
  168. if ((!audio_reader_.get() || !audio_reader_->is_connected()) &&
  169. session_->config().is_audio_enabled()) {
  170. return;
  171. }
  172. if (state_ != AUTHENTICATED)
  173. return;
  174. // Start forwarding clipboard and input events.
  175. clipboard_forwarder_.set_clipboard_stub(control_dispatcher_.get());
  176. event_forwarder_.set_input_stub(event_dispatcher_.get());
  177. SetState(CONNECTED, OK);
  178. }
  179. void IceConnectionToHost::CloseChannels() {
  180. control_dispatcher_.reset();
  181. event_dispatcher_.reset();
  182. clipboard_forwarder_.set_clipboard_stub(nullptr);
  183. event_forwarder_.set_input_stub(nullptr);
  184. video_dispatcher_.reset();
  185. audio_reader_.reset();
  186. }
  187. void IceConnectionToHost::SetState(State state, ErrorCode error) {
  188. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  189. // |error| should be specified only when |state| is set to FAILED.
  190. DCHECK(state == FAILED || error == OK);
  191. if (state != state_) {
  192. state_ = state;
  193. error_ = error;
  194. event_callback_->OnConnectionState(state_, error_);
  195. }
  196. }
  197. } // namespace protocol
  198. } // namespace remoting