ch_->Schedule(next_time);
}
+bool PingPongController::MaySendData() {
+ return ch_->data_out_.empty();
+}
+
+void PingPongController::OnDataSent(bin64_t b) {
+ Schedule(NOW+ch_->rtt_avg_+std::max(ch_->dev_avg_*4,500*TINT_MSEC));
+ if (++sent_>=10)
+ Swap(new KeepAliveController(this));
+ else if (++unanswered_>=3)
+ Schedule(TINT_NEVER);
+}
+
+void PingPongController::OnDataRecvd(bin64_t b) {
+ unanswered_ = 0;
+ Schedule(NOW); // pong
+}
+
+void PingPongController::OnAckRcvd(bin64_t ackd) {
+ if (ackd!=bin64_t::NONE)
+ Swap(new SlowStartController(this));
+}
KeepAliveController::KeepAliveController (Channel* ch) : SendController(ch), delay_(ch->rtt_avg_) {
if (b!=bin64_t::NONE && b!=bin64_t::ALL) { // channel is alive
delay_ = ch_->rtt_avg_;
Schedule(NOW); // schedule an ACK; TODO: aggregate
- } else {
- delay_ = ch_->rtt_avg_;
- Schedule(NOW);
}
}
virtual ~SendController() {}
};
-
+struct PingPongController : public SendController {
+
+ int sent_, unanswered_;
+
+ PingPongController (SendController* orig) :
+ SendController(orig), sent_(0), unanswered_(0) {}
+ PingPongController (Channel* ch) :
+ unanswered_(0), sent_(0), SendController(ch) {}
+ const char* type() const { return "PingPong"; }
+ bool MaySendData();
+ void OnDataSent(bin64_t b);
+ void OnDataRecvd(bin64_t b);
+ void OnAckRcvd(bin64_t ackd) ;
+ ~PingPongController() {}
+
+};
/** Mission of the keepalive controller to keep the channel
alive as no data sending happens; If no data is transmitted
in either direction, inter-packet times grow exponentially
peer_ = tracker;
this->id = channels.size();
channels.push_back(this);
- cc_ = new KeepAliveController(this);
+ cc_ = new PingPongController(this);
Schedule(NOW); // FIXME ugly
}