1// Copyright (c) 2012 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 5#include "remoting/host/log_to_server.h" 6 7#include "base/bind.h" 8#include "base/message_loop/message_loop_proxy.h" 9#include "remoting/base/constants.h" 10#include "remoting/host/host_status_monitor.h" 11#include "remoting/host/server_log_entry.h" 12#include "remoting/jingle_glue/iq_sender.h" 13#include "remoting/jingle_glue/signal_strategy.h" 14#include "remoting/protocol/transport.h" 15#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" 16#include "third_party/libjingle/source/talk/xmpp/constants.h" 17 18using buzz::QName; 19using buzz::XmlElement; 20 21namespace remoting { 22 23LogToServer::LogToServer(base::WeakPtr<HostStatusMonitor> monitor, 24 ServerLogEntry::Mode mode, 25 SignalStrategy* signal_strategy, 26 const std::string& directory_bot_jid) 27 : monitor_(monitor), 28 mode_(mode), 29 signal_strategy_(signal_strategy), 30 directory_bot_jid_(directory_bot_jid) { 31 monitor_->AddStatusObserver(this); 32 signal_strategy_->AddListener(this); 33} 34 35LogToServer::~LogToServer() { 36 signal_strategy_->RemoveListener(this); 37 if (monitor_.get()) 38 monitor_->RemoveStatusObserver(this); 39} 40 41void LogToServer::LogSessionStateChange(const std::string& jid, 42 bool connected) { 43 DCHECK(CalledOnValidThread()); 44 45 scoped_ptr<ServerLogEntry> entry( 46 ServerLogEntry::MakeForSessionStateChange(connected)); 47 entry->AddHostFields(); 48 entry->AddModeField(mode_); 49 50 if (connected) { 51 DCHECK(connection_route_type_.count(jid) == 1); 52 entry->AddConnectionTypeField(connection_route_type_[jid]); 53 } 54 Log(*entry.get()); 55} 56 57void LogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) { 58 DCHECK(CalledOnValidThread()); 59 60 if (state == SignalStrategy::CONNECTED) { 61 iq_sender_.reset(new IqSender(signal_strategy_)); 62 SendPendingEntries(); 63 } else if (state == SignalStrategy::DISCONNECTED) { 64 iq_sender_.reset(); 65 } 66} 67 68bool LogToServer::OnSignalStrategyIncomingStanza( 69 const buzz::XmlElement* stanza) { 70 return false; 71} 72 73void LogToServer::OnClientConnected(const std::string& jid) { 74 DCHECK(CalledOnValidThread()); 75 LogSessionStateChange(jid, true); 76} 77 78void LogToServer::OnClientDisconnected(const std::string& jid) { 79 DCHECK(CalledOnValidThread()); 80 LogSessionStateChange(jid, false); 81 connection_route_type_.erase(jid); 82} 83 84void LogToServer::OnClientRouteChange(const std::string& jid, 85 const std::string& channel_name, 86 const protocol::TransportRoute& route) { 87 // Store connection type for the video channel. It is logged later 88 // when client authentication is finished. 89 if (channel_name == kVideoChannelName) { 90 connection_route_type_[jid] = route.type; 91 } 92} 93 94void LogToServer::Log(const ServerLogEntry& entry) { 95 pending_entries_.push_back(entry); 96 SendPendingEntries(); 97} 98 99void LogToServer::SendPendingEntries() { 100 if (iq_sender_ == NULL) { 101 return; 102 } 103 if (pending_entries_.empty()) { 104 return; 105 } 106 // Make one stanza containing all the pending entries. 107 scoped_ptr<XmlElement> stanza(ServerLogEntry::MakeStanza()); 108 while (!pending_entries_.empty()) { 109 ServerLogEntry& entry = pending_entries_.front(); 110 stanza->AddElement(entry.ToStanza().release()); 111 pending_entries_.pop_front(); 112 } 113 // Send the stanza to the server. 114 scoped_ptr<IqRequest> req = iq_sender_->SendIq( 115 buzz::STR_SET, directory_bot_jid_, stanza.Pass(), 116 IqSender::ReplyCallback()); 117 // We ignore any response, so let the IqRequest be destroyed. 118 return; 119} 120 121} // namespace remoting 122