Home | History | Annotate | Download | only in host
      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