Home | History | Annotate | Download | only in xmpp
      1 // Copyright 2011 Google Inc. All Rights Reserved.
      2 
      3 
      4 #include "talk/xmpp/pingtask.h"
      5 
      6 #include "talk/xmpp/constants.h"
      7 #include "webrtc/base/logging.h"
      8 #include "webrtc/base/scoped_ptr.h"
      9 
     10 namespace buzz {
     11 
     12 PingTask::PingTask(buzz::XmppTaskParentInterface* parent,
     13                    rtc::MessageQueue* message_queue,
     14                    uint32 ping_period_millis,
     15                    uint32 ping_timeout_millis)
     16     : buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE),
     17       message_queue_(message_queue),
     18       ping_period_millis_(ping_period_millis),
     19       ping_timeout_millis_(ping_timeout_millis),
     20       next_ping_time_(0),
     21       ping_response_deadline_(0) {
     22   ASSERT(ping_period_millis >= ping_timeout_millis);
     23 }
     24 
     25 bool PingTask::HandleStanza(const buzz::XmlElement* stanza) {
     26   if (!MatchResponseIq(stanza, Jid(STR_EMPTY), task_id())) {
     27     return false;
     28   }
     29 
     30   if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_RESULT &&
     31       stanza->Attr(buzz::QN_TYPE) != buzz::STR_ERROR) {
     32     return false;
     33   }
     34 
     35   QueueStanza(stanza);
     36   return true;
     37 }
     38 
     39 // This task runs indefinitely and remains in either the start or blocked
     40 // states.
     41 int PingTask::ProcessStart() {
     42   if (ping_period_millis_ < ping_timeout_millis_) {
     43     LOG(LS_ERROR) << "ping_period_millis should be >= ping_timeout_millis";
     44     return STATE_ERROR;
     45   }
     46   const buzz::XmlElement* stanza = NextStanza();
     47   if (stanza != NULL) {
     48     // Received a ping response of some sort (don't care what it is).
     49     ping_response_deadline_ = 0;
     50   }
     51 
     52   uint32 now = rtc::Time();
     53 
     54   // If the ping timed out, signal.
     55   if (ping_response_deadline_ != 0 && now >= ping_response_deadline_) {
     56     SignalTimeout();
     57     return STATE_ERROR;
     58   }
     59 
     60   // Send a ping if it's time.
     61   if (now >= next_ping_time_) {
     62     rtc::scoped_ptr<buzz::XmlElement> stanza(
     63         MakeIq(buzz::STR_GET, Jid(STR_EMPTY), task_id()));
     64     stanza->AddElement(new buzz::XmlElement(QN_PING));
     65     SendStanza(stanza.get());
     66 
     67     ping_response_deadline_ = now + ping_timeout_millis_;
     68     next_ping_time_ = now + ping_period_millis_;
     69 
     70     // Wake ourselves up when it's time to send another ping or when the ping
     71     // times out (so we can fire a signal).
     72     message_queue_->PostDelayed(ping_timeout_millis_, this);
     73     message_queue_->PostDelayed(ping_period_millis_, this);
     74   }
     75 
     76   return STATE_BLOCKED;
     77 }
     78 
     79 void PingTask::OnMessage(rtc::Message* msg) {
     80   // Get the task manager to run this task so we can send a ping or signal or
     81   // process a ping response.
     82   Wake();
     83 }
     84 
     85 } // namespace buzz
     86