15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/daemon_process.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <algorithm> 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string> 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/single_thread_task_runner.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/auto_thread_task_runner.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "remoting/base/url_request_context.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/branding.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/chromoting_messages.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "remoting/host/config_file_watcher.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/desktop_session.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/host_event_logger.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/host_status_observer.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/screen_resolution.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/protocol/transport.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is used for tagging system event logs. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kApplicationName[] = "chromoting"; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::ostream& operator<<(std::ostream& os, const ScreenResolution& resolution) { 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return os << resolution.dimensions().width() << "x" 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << resolution.dimensions().height() << " at " 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) << resolution.dpi().x() << "x" << resolution.dpi().y() << " DPI"; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DaemonProcess::~DaemonProcess() { 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) host_event_logger_.reset(); 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) config_watcher_.reset(); 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DeleteAllDesktopSessions(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DaemonProcess::OnConfigUpdated(const std::string& serialized_config) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (serialized_config_ != serialized_config) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serialized_config_ = serialized_config; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendToNetwork( 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ChromotingDaemonNetworkMsg_Configuration(serialized_config_)); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DaemonProcess::OnConfigWatcherError() { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::AddStatusObserver(HostStatusObserver* observer) { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_observers_.AddObserver(observer); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::RemoveStatusObserver(HostStatusObserver* observer) { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_observers_.RemoveObserver(observer); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DaemonProcess::OnChannelConnected(int32 peer_pid) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "IPC: daemon <- network (" << peer_pid << ")"; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAllDesktopSessions(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the last known terminal ID because no IDs have been allocated 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by the the newly started process yet. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_terminal_id_ = 0; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the configuration to the network process. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendToNetwork( 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ChromotingDaemonNetworkMsg_Configuration(serialized_config_)); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DaemonProcess::OnMessageReceived(const IPC::Message& message) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(DaemonProcess, message) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_ConnectTerminal, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateDesktopSession) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_DisconnectTerminal, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseDesktopSession) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_SetScreenResolution, 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetScreenResolution) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_AccessDenied, 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnAccessDenied) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_ClientAuthenticated, 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientAuthenticated) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_ClientConnected, 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientConnected) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_ClientDisconnected, 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientDisconnected) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_ClientRouteChange, 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientRouteChange) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_HostStarted, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnHostStarted) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(ChromotingNetworkDaemonMsg_HostShutdown, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnHostShutdown) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!handled) { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Received unexpected IPC type: " << message.type(); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrashNetworkProcess(FROM_HERE); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DaemonProcess::OnPermanentError(int exit_code) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DaemonProcess::CloseDesktopSession(int terminal_id) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Validate the supplied terminal ID. An attempt to use a desktop session ID 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that couldn't possibly have been allocated is considered a protocol error 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and the network process will be restarted. 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!WasTerminalIdAllocated(terminal_id)) { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Invalid terminal ID: " << terminal_id; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashNetworkProcess(FROM_HERE); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DesktopSessionList::iterator i; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = desktop_sessions_.begin(); i != desktop_sessions_.end(); ++i) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*i)->id() == terminal_id) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is OK if the terminal ID wasn't found. There is a race between 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the network and daemon processes. Each frees its own recources first and 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notifies the other party if there was something to clean up. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == desktop_sessions_.end()) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete *i; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desktop_sessions_.erase(i); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Daemon: closed desktop session " << terminal_id; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendToNetwork( 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ChromotingDaemonNetworkMsg_TerminalDisconnected(terminal_id)); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DaemonProcess::DaemonProcess( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> caller_task_runner, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> io_task_runner, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& stopped_callback) 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : caller_task_runner_(caller_task_runner), 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_task_runner_(io_task_runner), 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_terminal_id_(0), 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stopped_callback_(stopped_callback), 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner->BelongsToCurrentThread()); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::CreateDesktopSession(int terminal_id, 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ScreenResolution& resolution, 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool virtual_terminal) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate the supplied terminal ID. An attempt to create a desktop session 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with an ID that could possibly have been allocated already is considered 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a protocol error and the network process will be restarted. 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (WasTerminalIdAllocated(terminal_id)) { 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Invalid terminal ID: " << terminal_id; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashNetworkProcess(FROM_HERE); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Terminal IDs cannot be reused. Update the expected next terminal ID. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_terminal_id_ = std::max(next_terminal_id_, terminal_id + 1); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the desktop session. 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<DesktopSession> session = DoCreateDesktopSession( 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) terminal_id, resolution, virtual_terminal); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!session) { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to create a desktop session."; 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendToNetwork( 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new ChromotingDaemonNetworkMsg_TerminalDisconnected(terminal_id)); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Daemon: opened desktop session " << terminal_id; 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desktop_sessions_.push_back(session.release()); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::SetScreenResolution(int terminal_id, 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ScreenResolution& resolution) { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Validate the supplied terminal ID. An attempt to use a desktop session ID 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that couldn't possibly have been allocated is considered a protocol error 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and the network process will be restarted. 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!WasTerminalIdAllocated(terminal_id)) { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Invalid terminal ID: " << terminal_id; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrashNetworkProcess(FROM_HERE); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Validate |resolution| and restart the sender if it is not valid. 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (resolution.IsEmpty()) { 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Invalid resolution specified: " << resolution; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrashNetworkProcess(FROM_HERE); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DesktopSessionList::iterator i; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = desktop_sessions_.begin(); i != desktop_sessions_.end(); ++i) { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*i)->id() == terminal_id) { 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It is OK if the terminal ID wasn't found. There is a race between 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the network and daemon processes. Each frees its own resources first and 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // notifies the other party if there was something to clean up. 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i == desktop_sessions_.end()) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*i)->SetScreenResolution(resolution); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DaemonProcess::CrashNetworkProcess( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& location) { 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCrashNetworkProcess(location); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteAllDesktopSessions(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DaemonProcess::Initialize() { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const CommandLine* command_line = CommandLine::ForCurrentProcess(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the name of the host configuration file. 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath default_config_dir = remoting::GetConfigDir(); 265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::FilePath config_path = default_config_dir.Append( 266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kDefaultHostConfigFile); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_line->HasSwitch(kHostConfigSwitchName)) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_path = command_line->GetSwitchValuePath(kHostConfigSwitchName); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) config_watcher_.reset(new ConfigFileWatcher( 271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) caller_task_runner(), io_task_runner(), config_path)); 272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) config_watcher_->Watch(this); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_event_logger_ = 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HostEventLogger::Create(weak_factory_.GetWeakPtr(), kApplicationName); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the process. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LaunchNetworkProcess(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DaemonProcess::Stop() { 281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!stopped_callback_.is_null()) { 284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Closure stopped_callback = stopped_callback_; 285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stopped_callback_.Reset(); 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stopped_callback.Run(); 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DaemonProcess::WasTerminalIdAllocated(int terminal_id) { 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return terminal_id < next_terminal_id_; 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::OnAccessDenied(const std::string& jid) { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnAccessDenied(jid)); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::OnClientAuthenticated(const std::string& jid) { 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientAuthenticated(jid)); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::OnClientConnected(const std::string& jid) { 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientConnected(jid)); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::OnClientDisconnected(const std::string& jid) { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientDisconnected(jid)); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::OnClientRouteChange(const std::string& jid, 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& channel_name, 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SerializedTransportRoute& route) { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Validate |route|. 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (route.type != protocol::TransportRoute::DIRECT && 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) route.type != protocol::TransportRoute::STUN && 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) route.type != protocol::TransportRoute::RELAY) { 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "An invalid RouteType " << route.type << " passed."; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrashNetworkProcess(FROM_HERE); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (route.remote_address.size() != net::kIPv4AddressSize && 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) route.remote_address.size() != net::kIPv6AddressSize) { 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "An invalid net::IPAddressNumber size " 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << route.remote_address.size() << " passed."; 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrashNetworkProcess(FROM_HERE); 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (route.local_address.size() != net::kIPv4AddressSize && 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) route.local_address.size() != net::kIPv6AddressSize) { 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "An invalid net::IPAddressNumber size " 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << route.local_address.size() << " passed."; 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrashNetworkProcess(FROM_HERE); 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protocol::TransportRoute parsed_route; 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parsed_route.type = 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<protocol::TransportRoute::RouteType>(route.type); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parsed_route.remote_address = 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::IPEndPoint(route.remote_address, route.remote_port); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parsed_route.local_address = 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::IPEndPoint(route.local_address, route.local_port); 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnClientRouteChange(jid, channel_name, parsed_route)); 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::OnHostStarted(const std::string& xmpp_login) { 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnStart(xmpp_login)); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DaemonProcess::OnHostShutdown() { 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(caller_task_runner()->BelongsToCurrentThread()); 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnShutdown()); 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DaemonProcess::DeleteAllDesktopSessions() { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!desktop_sessions_.empty()) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete desktop_sessions_.front(); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desktop_sessions_.pop_front(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 380