// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "remoting/protocol/connection_to_client.h" #include "google/protobuf/message.h" #include "net/base/io_buffer.h" #include "remoting/protocol/client_control_sender.h" #include "remoting/protocol/host_message_dispatcher.h" // TODO(hclam): Remove this header once MessageDispatcher is used. #include "remoting/base/compound_buffer.h" namespace remoting { namespace protocol { // Determine how many update streams we should count to find the size of // average update stream. static const size_t kAverageUpdateStream = 10; ConnectionToClient::ConnectionToClient(MessageLoop* message_loop, EventHandler* handler, HostStub* host_stub, InputStub* input_stub) : loop_(message_loop), handler_(handler), host_stub_(host_stub), input_stub_(input_stub) { DCHECK(loop_); DCHECK(handler_); } ConnectionToClient::~ConnectionToClient() { // TODO(hclam): When we shut down the viewer we may have to close the // connection. } void ConnectionToClient::Init(protocol::Session* session) { DCHECK_EQ(session->message_loop(), MessageLoop::current()); session_ = session; session_->SetStateChangeCallback( NewCallback(this, &ConnectionToClient::OnSessionStateChange)); } protocol::Session* ConnectionToClient::session() { return session_; } void ConnectionToClient::Disconnect() { // This method can be called from main thread so perform threading switching. if (MessageLoop::current() != loop_) { loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &ConnectionToClient::Disconnect)); return; } // If there is a channel then close it and release the reference. if (session_) { session_->Close(NewRunnableMethod(this, &ConnectionToClient::OnClosed)); session_ = NULL; } } VideoStub* ConnectionToClient::video_stub() { return video_writer_.get(); } // Return pointer to ClientStub. ClientStub* ConnectionToClient::client_stub() { return client_stub_.get(); } ConnectionToClient::ConnectionToClient() { } void ConnectionToClient::OnSessionStateChange(protocol::Session::State state) { if (state == protocol::Session::CONNECTED) { client_stub_.reset(new ClientControlSender(session_->control_channel())); video_writer_.reset(VideoWriter::Create(session_->config())); video_writer_->Init(session_); dispatcher_.reset(new HostMessageDispatcher()); dispatcher_->Initialize(session_.get(), host_stub_, input_stub_); } // This method can be called from main thread so perform threading switching. if (MessageLoop::current() != loop_) { loop_->PostTask( FROM_HERE, NewRunnableMethod(this, &ConnectionToClient::StateChangeTask, state)); } else { StateChangeTask(state); } } void ConnectionToClient::StateChangeTask(protocol::Session::State state) { DCHECK_EQ(loop_, MessageLoop::current()); DCHECK(handler_); switch(state) { case protocol::Session::CONNECTING: break; // Don't care about this message. case protocol::Session::CONNECTED: handler_->OnConnectionOpened(this); break; case protocol::Session::CLOSED: handler_->OnConnectionClosed(this); break; case protocol::Session::FAILED: handler_->OnConnectionFailed(this); break; default: // We shouldn't receive other states. NOTREACHED(); } } // OnClosed() is used as a callback for protocol::Session::Close(). void ConnectionToClient::OnClosed() { } } // namespace protocol } // namespace remoting