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 18 using buzz::QName; 19 using buzz::XmlElement; 20 21 namespace remoting { 22 23 LogToServer::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 35 LogToServer::~LogToServer() { 36 signal_strategy_->RemoveListener(this); 37 if (monitor_.get()) 38 monitor_->RemoveStatusObserver(this); 39 } 40 41 void 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 57 void 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 68 bool LogToServer::OnSignalStrategyIncomingStanza( 69 const buzz::XmlElement* stanza) { 70 return false; 71 } 72 73 void LogToServer::OnClientConnected(const std::string& jid) { 74 DCHECK(CalledOnValidThread()); 75 LogSessionStateChange(jid, true); 76 } 77 78 void LogToServer::OnClientDisconnected(const std::string& jid) { 79 DCHECK(CalledOnValidThread()); 80 LogSessionStateChange(jid, false); 81 connection_route_type_.erase(jid); 82 } 83 84 void 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 94 void LogToServer::Log(const ServerLogEntry& entry) { 95 pending_entries_.push_back(entry); 96 SendPendingEntries(); 97 } 98 99 void 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