| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/protocol/connection_to_client.h" | 5 #include "remoting/protocol/connection_to_client.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
| 10 #include "google/protobuf/message.h" | 10 #include "google/protobuf/message.h" |
| 11 #include "net/base/io_buffer.h" | 11 #include "net/base/io_buffer.h" |
| 12 #include "remoting/protocol/client_control_sender.h" | 12 #include "remoting/protocol/client_control_sender.h" |
| 13 #include "remoting/protocol/host_message_dispatcher.h" | 13 #include "remoting/protocol/host_message_dispatcher.h" |
| 14 #include "remoting/protocol/host_stub.h" | 14 #include "remoting/protocol/host_stub.h" |
| 15 #include "remoting/protocol/input_stub.h" | 15 #include "remoting/protocol/input_stub.h" |
| 16 | 16 |
| 17 // TODO(hclam): Remove this header once MessageDispatcher is used. | 17 // TODO(hclam): Remove this header once MessageDispatcher is used. |
| 18 #include "remoting/base/compound_buffer.h" | 18 #include "remoting/base/compound_buffer.h" |
| 19 | 19 |
| 20 namespace remoting { | 20 namespace remoting { |
| 21 namespace protocol { | 21 namespace protocol { |
| 22 | 22 |
| 23 // Determine how many update streams we should count to find the size of | 23 // Determine how many update streams we should count to find the size of |
| 24 // average update stream. | 24 // average update stream. |
| 25 static const size_t kAverageUpdateStream = 10; | 25 static const size_t kAverageUpdateStream = 10; |
| 26 | 26 |
| 27 ConnectionToClient::ConnectionToClient(base::MessageLoopProxy* message_loop, | 27 ConnectionToClient::ConnectionToClient(base::MessageLoopProxy* message_loop, |
| 28 EventHandler* handler) | 28 protocol::Session* session) |
| 29 : message_loop_(message_loop), | 29 : message_loop_(message_loop), |
| 30 handler_(handler), | 30 handler_(NULL), |
| 31 host_stub_(NULL), | 31 host_stub_(NULL), |
| 32 input_stub_(NULL), | 32 input_stub_(NULL), |
| 33 session_(session), |
| 33 control_connected_(false), | 34 control_connected_(false), |
| 34 input_connected_(false), | 35 input_connected_(false), |
| 35 video_connected_(false) { | 36 video_connected_(false) { |
| 36 DCHECK(message_loop_); | 37 DCHECK(message_loop_); |
| 37 DCHECK(handler_); | 38 session_->SetStateChangeCallback( |
| 39 base::Bind(&ConnectionToClient::OnSessionStateChange, |
| 40 base::Unretained(this))); |
| 38 } | 41 } |
| 39 | 42 |
| 40 ConnectionToClient::~ConnectionToClient() { | 43 ConnectionToClient::~ConnectionToClient() { |
| 41 // TODO(hclam): When we shut down the viewer we may have to close the | 44 // TODO(hclam): When we shut down the viewer we may have to close the |
| 42 // connection. | 45 // connection. |
| 43 } | 46 } |
| 44 | 47 |
| 45 void ConnectionToClient::Init(protocol::Session* session) { | 48 void ConnectionToClient::SetEventHandler(EventHandler* event_handler) { |
| 46 DCHECK(message_loop_->BelongsToCurrentThread()); | 49 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 47 session_.reset(session); | 50 handler_ = event_handler; |
| 48 session_->SetStateChangeCallback( | |
| 49 base::Bind(&ConnectionToClient::OnSessionStateChange, | |
| 50 base::Unretained(this))); | |
| 51 } | 51 } |
| 52 | 52 |
| 53 protocol::Session* ConnectionToClient::session() { | 53 protocol::Session* ConnectionToClient::session() { |
| 54 return session_.get(); | 54 return session_.get(); |
| 55 } | 55 } |
| 56 | 56 |
| 57 void ConnectionToClient::Disconnect() { | 57 void ConnectionToClient::Disconnect() { |
| 58 // This method can be called from main thread so perform threading switching. | 58 // This method can be called from main thread so perform threading switching. |
| 59 if (!message_loop_->BelongsToCurrentThread()) { | 59 if (!message_loop_->BelongsToCurrentThread()) { |
| 60 message_loop_->PostTask( | 60 message_loop_->PostTask( |
| 61 FROM_HERE, | 61 FROM_HERE, |
| 62 NewRunnableMethod(this, &ConnectionToClient::Disconnect)); | 62 NewRunnableMethod(this, &ConnectionToClient::Disconnect)); |
| 63 return; | 63 return; |
| 64 } | 64 } |
| 65 | 65 |
| 66 CloseChannels(); | 66 CloseChannels(); |
| 67 | 67 |
| 68 // If there is a session then release it, causing it to close. | 68 // If there is a session then release it, causing it to close. |
| 69 if (session_.get()) | 69 if (session_.get()) |
| 70 session_.reset(); | 70 session_.reset(); |
| 71 } | 71 } |
| 72 | 72 |
| 73 void ConnectionToClient::UpdateSequenceNumber(int64 sequence_number) { | 73 void ConnectionToClient::UpdateSequenceNumber(int64 sequence_number) { |
| 74 handler_->OnSequenceNumberUpdated(this, sequence_number); | 74 if (handler_) |
| 75 handler_->OnSequenceNumberUpdated(this, sequence_number); |
| 75 } | 76 } |
| 76 | 77 |
| 77 VideoStub* ConnectionToClient::video_stub() { | 78 VideoStub* ConnectionToClient::video_stub() { |
| 78 return video_writer_.get(); | 79 return video_writer_.get(); |
| 79 } | 80 } |
| 80 | 81 |
| 81 // Return pointer to ClientStub. | 82 // Return pointer to ClientStub. |
| 82 ClientStub* ConnectionToClient::client_stub() { | 83 ClientStub* ConnectionToClient::client_stub() { |
| 83 return client_control_sender_.get(); | 84 return client_control_sender_.get(); |
| 84 } | 85 } |
| 85 | 86 |
| 86 void ConnectionToClient::set_host_stub(protocol::HostStub* host_stub) { | 87 void ConnectionToClient::set_host_stub(protocol::HostStub* host_stub) { |
| 87 host_stub_ = host_stub; | 88 host_stub_ = host_stub; |
| 88 } | 89 } |
| 89 | 90 |
| 90 void ConnectionToClient::set_input_stub(protocol::InputStub* input_stub) { | 91 void ConnectionToClient::set_input_stub(protocol::InputStub* input_stub) { |
| 91 input_stub_ = input_stub; | 92 input_stub_ = input_stub; |
| 92 } | 93 } |
| 93 | 94 |
| 94 void ConnectionToClient::OnSessionStateChange(protocol::Session::State state) { | 95 void ConnectionToClient::OnSessionStateChange(protocol::Session::State state) { |
| 95 DCHECK(message_loop_->BelongsToCurrentThread()); | 96 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 96 | 97 |
| 97 DCHECK(handler_); | |
| 98 switch(state) { | 98 switch(state) { |
| 99 case protocol::Session::CONNECTING: | 99 case protocol::Session::CONNECTING: |
| 100 // Don't care about this message. | 100 // Don't care about this message. |
| 101 break; | 101 break; |
| 102 | 102 |
| 103 case protocol::Session::CONNECTED: | 103 case protocol::Session::CONNECTED: |
| 104 video_writer_.reset( | 104 video_writer_.reset( |
| 105 VideoWriter::Create(message_loop_, session_->config())); | 105 VideoWriter::Create(message_loop_, session_->config())); |
| 106 video_writer_->Init( | 106 video_writer_->Init( |
| 107 session_.get(), base::Bind(&ConnectionToClient::OnVideoInitialized, | 107 session_.get(), base::Bind(&ConnectionToClient::OnVideoInitialized, |
| 108 base::Unretained(this))); | 108 base::Unretained(this))); |
| 109 break; | 109 break; |
| 110 | 110 |
| 111 case protocol::Session::CONNECTED_CHANNELS: | 111 case protocol::Session::CONNECTED_CHANNELS: |
| 112 client_control_sender_.reset( | 112 client_control_sender_.reset( |
| 113 new ClientControlSender(message_loop_, session_->control_channel())); | 113 new ClientControlSender(message_loop_, session_->control_channel())); |
| 114 dispatcher_.reset(new HostMessageDispatcher()); | 114 dispatcher_.reset(new HostMessageDispatcher()); |
| 115 dispatcher_->Initialize(this, host_stub_, input_stub_); | 115 dispatcher_->Initialize(this, host_stub_, input_stub_); |
| 116 | 116 |
| 117 control_connected_ = true; | 117 control_connected_ = true; |
| 118 input_connected_ = true; | 118 input_connected_ = true; |
| 119 NotifyIfChannelsReady(); | 119 NotifyIfChannelsReady(); |
| 120 break; | 120 break; |
| 121 | 121 |
| 122 case protocol::Session::CLOSED: | 122 case protocol::Session::CLOSED: |
| 123 CloseChannels(); | 123 CloseChannels(); |
| 124 handler_->OnConnectionClosed(this); | 124 if (handler_) |
| 125 handler_->OnConnectionClosed(this); |
| 125 break; | 126 break; |
| 126 | 127 |
| 127 case protocol::Session::FAILED: | 128 case protocol::Session::FAILED: |
| 128 CloseOnError(); | 129 CloseOnError(); |
| 129 break; | 130 break; |
| 130 | 131 |
| 131 default: | 132 default: |
| 132 // We shouldn't receive other states. | 133 // We shouldn't receive other states. |
| 133 NOTREACHED(); | 134 NOTREACHED(); |
| 134 } | 135 } |
| 135 } | 136 } |
| 136 | 137 |
| 137 void ConnectionToClient::OnVideoInitialized(bool successful) { | 138 void ConnectionToClient::OnVideoInitialized(bool successful) { |
| 138 if (!successful) { | 139 if (!successful) { |
| 139 LOG(ERROR) << "Failed to connect video channel"; | 140 LOG(ERROR) << "Failed to connect video channel"; |
| 140 CloseOnError(); | 141 CloseOnError(); |
| 141 return; | 142 return; |
| 142 } | 143 } |
| 143 | 144 |
| 144 video_connected_ = true; | 145 video_connected_ = true; |
| 145 NotifyIfChannelsReady(); | 146 NotifyIfChannelsReady(); |
| 146 } | 147 } |
| 147 | 148 |
| 148 void ConnectionToClient::NotifyIfChannelsReady() { | 149 void ConnectionToClient::NotifyIfChannelsReady() { |
| 149 if (control_connected_ && input_connected_ && video_connected_) | 150 if (control_connected_ && input_connected_ && video_connected_) { |
| 150 handler_->OnConnectionOpened(this); | 151 if (handler_) |
| 152 handler_->OnConnectionOpened(this); |
| 153 } |
| 151 } | 154 } |
| 152 | 155 |
| 153 void ConnectionToClient::CloseOnError() { | 156 void ConnectionToClient::CloseOnError() { |
| 154 CloseChannels(); | 157 CloseChannels(); |
| 155 handler_->OnConnectionFailed(this); | 158 if (handler_) |
| 159 handler_->OnConnectionFailed(this); |
| 156 } | 160 } |
| 157 | 161 |
| 158 void ConnectionToClient::CloseChannels() { | 162 void ConnectionToClient::CloseChannels() { |
| 159 if (video_writer_.get()) | 163 if (video_writer_.get()) |
| 160 video_writer_->Close(); | 164 video_writer_->Close(); |
| 161 if (client_control_sender_.get()) | 165 if (client_control_sender_.get()) |
| 162 client_control_sender_->Close(); | 166 client_control_sender_->Close(); |
| 163 } | 167 } |
| 164 | 168 |
| 165 } // namespace protocol | 169 } // namespace protocol |
| 166 } // namespace remoting | 170 } // namespace remoting |
| OLD | NEW |