Index: remoting/host/simple_host.cc |
=================================================================== |
--- remoting/host/simple_host.cc (revision 0) |
+++ remoting/host/simple_host.cc (revision 0) |
@@ -0,0 +1,201 @@ |
+// 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/host/simple_host.h" |
+ |
+#include "base/stl_util-inl.h" |
+#include "build/build_config.h" |
+#include "remoting/base/protocol_decoder.h" |
+#include "remoting/host/session_manager.h" |
+#include "remoting/jingle_glue/jingle_channel.h" |
+ |
+namespace remoting { |
+ |
+SimpleHost::SimpleHost(const std::string& username, |
+ const std::string& password, |
+ Capturer* capturer, |
+ Encoder* encoder, |
+ EventExecutor* executor) |
+ : capture_thread_("CaptureThread"), |
+ encode_thread_("EncodeThread"), |
+ username_(username), |
+ password_(password), |
+ capturer_(capturer), |
+ encoder_(encoder), |
+ executor_(executor) { |
+} |
+ |
+void SimpleHost::Run() { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // Submit a task to perform host registration. We'll also start |
+ // listening to connection if registration is done. |
+ RegisterHost(); |
+ |
+ // Run the main message loop. This is the main loop of this host |
+ // object. |
+ main_loop_.Run(); |
+} |
+ |
+// This method is called when we need to the host process. |
+void SimpleHost::DestroySession() { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // First we tell the session to pause and then we wait until all |
+ // the tasks are done. |
+ session_->Pause(); |
+ |
+ // TODO(hclam): Revise the order. |
+ encode_thread_.Stop(); |
+ capture_thread_.Stop(); |
+} |
+ |
+// This method talks to the cloud to register the host process. If |
+// successful we will start listening to network requests. |
+void SimpleHost::RegisterHost() { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ DCHECK(!jingle_client_); |
+ |
+ // Connect to the talk network with a JingleClient. |
+ jingle_client_ = new JingleClient(); |
+ jingle_client_->Init(username_, password_, this); |
+} |
+ |
+// This method is called if a client is connected to this object. |
+void SimpleHost::OnClientConnected(ClientConnection* client) { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // Create a new RecordSession if there was none. |
+ if (!session_) { |
+ // The first we need to make sure capture and encode thread are |
+ // running. |
+ capture_thread_.Start(); |
+ encode_thread_.Start(); |
+ |
+ // Then we create a SessionManager passing the message loops that |
+ // it should run on. |
+ // Note that we pass the ownership of the capturer and encoder to |
+ // the session manager. |
+ DCHECK(capturer_.get()); |
+ DCHECK(encoder_.get()); |
+ session_ = new SessionManager(capture_thread_.message_loop(), |
+ encode_thread_.message_loop(), |
+ &main_loop_, |
+ capturer_.release(), |
+ encoder_.release()); |
+ |
+ // Immediately add the client and start the session. |
+ session_->AddClient(client); |
+ session_->Start(); |
+ LOG(INFO) << "Session manager started"; |
+ } else { |
+ // If a session manager already exists we simply add the new client. |
+ session_->AddClient(client); |
+ } |
+} |
+ |
+void SimpleHost::OnClientDisconnected(ClientConnection* client) { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // Remove the client from the session manager. |
+ DCHECK(session_); |
+ session_->RemoveClient(client); |
+ |
+ // Also remove reference to ClientConnection from this object. |
+ client_ = NULL; |
+ |
+ // TODO(hclam): If the last client has disconnected we need destroy |
+ // the session manager and shutdown the capture and encode threads. |
+ // Right now we assume there's only one client. |
+ DestroySession(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////// |
+// ClientConnection::EventHandler implementations |
+void SimpleHost::HandleMessages(ClientConnection* client, |
+ ClientMessageList* messages) { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // Delegate the messages to EventExecutor and delete the unhandled |
+ // messages. |
+ DCHECK(executor_.get()); |
+ executor_->HandleInputEvents(messages); |
+ STLDeleteElements<ClientMessageList>(messages); |
+} |
+ |
+void SimpleHost::OnConnectionOpened(ClientConnection* client) { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // Completes the client connection. |
+ LOG(INFO) << "Connection to client established."; |
+ OnClientConnected(client_.get()); |
+} |
+ |
+void SimpleHost::OnConnectionClosed(ClientConnection* client) { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // Completes the client connection. |
+ LOG(INFO) << "Connection to client closed."; |
+ OnClientDisconnected(client_.get()); |
+} |
+ |
+void SimpleHost::OnConnectionFailed(ClientConnection* client) { |
+ DCHECK_EQ(&main_loop_, MessageLoop::current()); |
+ |
+ // The client has disconnected. |
+ LOG(ERROR) << "Connection failed unexpectedly."; |
+ OnClientDisconnected(client_.get()); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////// |
+// JingleClient::Callback implementations |
+void SimpleHost::OnStateChange(JingleClient* jingle_client, |
+ JingleClient::State state) { |
+ DCHECK_EQ(jingle_client_.get(), jingle_client); |
+ |
+ if (state == JingleClient::CONNECTED) { |
+ // TODO(hclam): Change to use LOG(INFO). |
+ // LOG(INFO) << "Host connected as " |
+ // << jingle_client->GetFullJid() << "." << std::endl; |
+ printf("Host connected as %s\n", jingle_client->GetFullJid().c_str()); |
+ |
+ // Start heartbeating after we connected |
+ heartbeat_sender_ = new HeartbeatSender(); |
+ // TODO(sergeyu): where do we get host id? |
+ heartbeat_sender_->Start(jingle_client_.get(), "HostID"); |
+ } else if (state == JingleClient::CLOSED) { |
+ LOG(INFO) << "Host disconnected from talk network." << std::endl; |
+ |
+ heartbeat_sender_ = NULL; |
+ } |
+} |
+ |
+bool SimpleHost::OnAcceptConnection( |
+ JingleClient* jingle_client, const std::string& jid, |
+ JingleChannel::Callback** channel_callback) { |
+ DCHECK_EQ(jingle_client_.get(), jingle_client); |
+ |
+ if (client_.get()) |
+ return false; |
+ |
+ LOG(INFO) << "Client connected: " << jid << std::endl; |
+ |
+ // If we accept the connected then create a client object and set the |
+ // callback. |
+ client_ = new ClientConnection(&main_loop_, new ProtocolDecoder(), this); |
+ *channel_callback = client_.get(); |
+ return true; |
+} |
+ |
+void SimpleHost::OnNewConnection(JingleClient* jingle_client, |
+ scoped_refptr<JingleChannel> channel) { |
+ DCHECK_EQ(jingle_client_.get(), jingle_client); |
+ |
+ // Since the session manager has not started, it is still safe to access |
+ // the client directly. Note that we give the ownership of the channel |
+ // to the client. |
+ client_->set_jingle_channel(channel); |
+} |
+ |
+} // namespace remoting |
Property changes on: remoting/host/simple_host.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |