};
struct PacketFormatV1 {
- // protocol version
- byte version:4;
- // type (formerly flags)
- byte type:4;
+ // packet_type (4 high bits)
+ // protocol version (4 low bits)
+ byte ver_type;
+ byte version() const { return ver_type & 0xf; }
+ byte type() const { return ver_type >> 4; }
+ void set_version(byte v) { ver_type = (ver_type & 0xf0) | (v & 0xf); }
+ void set_type(byte t) { ver_type = (ver_type & 0xf) | (t << 4); }
+
// Type of the first extension header
byte ext;
// connection ID
void shift(const uint32 offset)
{
// the offset should never be "negative"
- assert(offset < 0x10000000);
+ // assert(offset < 0x10000000);
// increase all of our base delays by this amount
// this is used to take clock skew into account
func.on_overhead(userdata, true, n, type);
}
#if g_log_utp_verbose
- int flags = version == 0 ? b->flags : b1->type;
+ int flags = version == 0 ? b->flags : b1->type();
uint16 seq_nr = version == 0 ? b->seq_nr : b1->seq_nr;
uint16 ack_nr = version == 0 ? b->ack_nr : b1->ack_nr;
LOG_UTPV("0x%08x: send %s len:%u id:%u timestamp:"I64u" reply_micro:%u flags:%s seq_nr:%u ack_nr:%u",
pfa.pf.windowsize = (byte)DIV_ROUND_UP(last_rcv_win, PACKET_SIZE);
len = sizeof(PacketFormat);
} else {
- pfa1.pf.version = 1;
- pfa1.pf.type = ST_STATE;
+ pfa1.pf.set_version(1);
+ pfa1.pf.set_type(ST_STATE);
pfa1.pf.ext = 0;
pfa1.pf.connid = conn_id_send;
pfa1.pf.ack_nr = ack_nr;
pf.windowsize = 0;
len = sizeof(PacketFormat);
} else {
- pf1.version = 1;
- pf1.type= ST_RESET;
+ pf1.set_version(1);
+ pf1.set_type(ST_RESET);
pf1.ext = 0;
pf1.connid = conn_id_send;
pf1.ack_nr = ack_nr;
p->ack_nr = ack_nr;
p->flags = flags;
} else {
- p1->version = 1;
- p1->type = flags;
+ p1->set_version(1);
+ p1->set_type(flags);
p1->ext = 0;
p1->connid = conn_id_send;
p1->windowsize = (uint32)last_rcv_win;
} else {
pk_seq_nr = pf1->seq_nr;
pk_ack_nr = pf1->ack_nr;
- pk_flags = pf1->type;
+ pk_flags = pf1->type();
}
if (pk_flags >= ST_NUM_STATES) return 0;
}
}
*/
+
+ // if the delay estimate exceeds the RTT, adjust the base_delay to
+ // compensate
+ if (conn->our_hist.get_value() > uint32(min_rtt)) {
+ conn->our_hist.shift(conn->our_hist.get_value() - min_rtt);
+ }
+
// only apply the congestion controller on acks
// if we don't have a delay measurement, there's
// no point in invoking the congestion control
// Fast timeout-retry
if (conn->fast_timeout) {
LOG_UTPV("Fast timeout %u,%u,%u?", (uint)conn->cur_window, conn->seq_nr - conn->timeout_seq_nr, conn->timeout_seq_nr);
- if (((conn->fast_resend_seq_nr - conn->timeout_seq_nr) & ACK_NR_MASK) >= 0 ||
- ((conn->seq_nr - conn->cur_window_packets) & ACK_NR_MASK) != conn->fast_resend_seq_nr) {
+ // if the fast_resend_seq_nr is not pointing to the oldest outstanding packet, it suggests that we've already
+ // resent the packet that timed out, and we should leave the fast-timeout mode.
+ if (((conn->seq_nr - conn->cur_window_packets) & ACK_NR_MASK) != conn->fast_resend_seq_nr) {
conn->fast_timeout = false;
} else {
+ // resend the oldest packet and increment fast_resend_seq_nr
+ // to not allow another fast resend on it again
OutgoingPacket *pkt = (OutgoingPacket*)conn->outbuf.get(conn->seq_nr - conn->cur_window_packets);
if (pkt && pkt->transmissions > 0) {
LOG_UTPV("0x%08x: Packet %u fast timeout-retry.", conn, conn->seq_nr - conn->cur_window_packets);
inline bool UTP_IsV1(PacketFormatV1 const* pf)
{
- return pf->version == 1 && pf->type < ST_NUM_STATES && pf->ext < 3;
+ return pf->version() == 1 && pf->type() < ST_NUM_STATES && pf->ext < 3;
}
void UTP_Free(UTPSocket *conn)
p->ext_len = 8;
memset(p->extensions, 0, 8);
} else {
- p1->pf.version = 1;
- p1->pf.type = ST_SYN;
+ p1->pf.set_version(1);
+ p1->pf.set_type(ST_SYN);
p1->pf.ext = 2;
p1->pf.connid = conn->conn_id_recv;
p1->pf.windowsize = (uint32)conn->last_rcv_win;
LOG_UTPV("recv id:%u seq_nr:%u ack_nr:%u", id, (uint)pf1->seq_nr, (uint)pf1->ack_nr);
}
- const byte flags = version == 0 ? pf->flags : pf1->type;
+ const byte flags = version == 0 ? pf->flags : pf1->type();
for (size_t i = 0; i < g_utp_sockets.GetCount(); i++) {
UTPSocket *conn = g_utp_sockets[i];