case SLOW_START_CONTROL: return SlowStartNextSendTime();
case AIMD_CONTROL: return AimdNextSendTime();
case LEDBAT_CONTROL: return LedbatNextSendTime();
+ case CLOSE_CONTROL: return TINT_NEVER;
default: assert(false);
}
}
break;
case LEDBAT_CONTROL:
break;
+ case CLOSE_CONTROL:
+ break;
default:
assert(false);
}
tint Channel::KeepAliveNextSendTime () {
if (sent_since_recv_>=3 && last_recv_time_<NOW-TINT_MIN)
- return TINT_NEVER;
+ return SwitchSendControl(CLOSE_CONTROL);
if (ack_rcvd_recent_)
return SwitchSendControl(SLOW_START_CONTROL);
if (data_in_.time!=TINT_NEVER)
if (!SELF_CONN_OK) {
uint32_t try_id = DecodeID(peer_channel_id_);
if (channel(try_id) && !channel(try_id)->peer_channel_id_) {
- delete this;
- return;
+ peer_channel_id_ = 0;
+ Close();
+ return; // this is a self-connection
}
}
// FUTURE: channel forking
Channel* sender(NULL);
while (!sender && !send_queue.is_empty()) { // dequeue
tintbin next = send_queue.pop();
- send_time = next.time;
sender = channel((int)next.bin);
+ send_time = next.time;
if (sender && sender->next_send_time_!=send_time &&
sender->next_send_time_!=TINT_NEVER )
sender = NULL; // it was a stale entry
if ( sender!=NULL && send_time<=NOW ) { // it's time
- if (sender->next_send_time_<NOW+TINT_MIN) { // either send
- dprintf("%s #%u sch_send %s\n",tintstr(),sender->id(),
- tintstr(send_time));
- sender->Send();
- sender->Reschedule();
- } else { // or close the channel
- dprintf("%s #%u closed sendctrl\n",tintstr(),sender->id());
- delete sender;
- }
+ dprintf("%s #%u sch_send %s\n",tintstr(),sender->id(),
+ tintstr(send_time));
+ sender->Send();
+ sender->Reschedule();
} else { // it's too early, wait
}
+void Channel::Close () {
+ this->SwitchSendControl(CLOSE_CONTROL);
+}
+
+
void Channel::Reschedule () {
next_send_time_ = NextSendTime();
if (next_send_time_!=TINT_NEVER) {
assert(next_send_time_<NOW+TINT_MIN);
send_queue.push(tintbin(next_send_time_,id_));
- } else
- send_queue.push(tintbin(NOW+TINT_MIN,id_));
- dprintf("%s requeue #%u for %s\n",tintstr(),id_,tintstr(next_send_time_));
+ dprintf("%s requeue #%u for %s\n",tintstr(),id_,tintstr(next_send_time_));
+ } else {
+ dprintf("%s #%u closed\n",tintstr(),id_);
+ delete this;
+ }
}