diff options
author | Olivier CrĂȘte <olivier.crete@collabora.com> | 2014-01-24 01:55:18 -0500 |
---|---|---|
committer | Olivier CrĂȘte <olivier.crete@collabora.com> | 2014-01-31 01:49:01 -0500 |
commit | a3abccdd36b299f864f61dde93d207b6fc5c13c6 (patch) | |
tree | de9dfc209bf7b98f6029e55df501afbbd7782fbd /agent | |
parent | 79866610c2eb69b8010beb0ac18f1237b1f879e7 (diff) |
pseudotcp: Don't fail when sending over 4GiB of data
Integer comparisons need to take care of rollovers
Diffstat (limited to 'agent')
-rw-r--r-- | agent/pseudotcp.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/agent/pseudotcp.c b/agent/pseudotcp.c index 3174946..58627dc 100644 --- a/agent/pseudotcp.c +++ b/agent/pseudotcp.c @@ -466,6 +466,10 @@ struct _PseudoTcpSocketPrivate { gboolean support_wnd_scale; }; +#define LARGER(a,b) (((a) - (b) - 1) < (G_MAXUINT32 >> 1)) +#define LARGER_OR_EQUAL(a,b) (((a) - (b)) < (G_MAXUINT32 >> 1)) +#define SMALLER(a,b) LARGER ((b),(a)) +#define SMALLER_OR_EQUAL(a,b) LARGER_OR_EQUAL ((b),(a)) /* properties */ enum @@ -1226,13 +1230,14 @@ process(PseudoTcpSocket *self, Segment *seg) } // Update timestamp - if ((seg->seq <= priv->ts_lastack) && - (priv->ts_lastack < seg->seq + seg->len)) { + if (SMALLER_OR_EQUAL (seg->seq, priv->ts_lastack) && + SMALLER (priv->ts_lastack, seg->seq + seg->len)) { priv->ts_recent = seg->tsval; } // Check if this is a valuable ack - if ((seg->ack > priv->snd_una) && (seg->ack <= priv->snd_nxt)) { + if (LARGER(seg->ack, priv->snd_una) && + SMALLER_OR_EQUAL(seg->ack, priv->snd_nxt)) { guint32 nAcked; guint32 nFree; @@ -1287,7 +1292,7 @@ process(PseudoTcpSocket *self, Segment *seg) } if (priv->dup_acks >= 3) { - if (priv->snd_una >= priv->recover) { // NewReno + if (LARGER_OR_EQUAL (priv->snd_una, priv->recover)) { // NewReno guint32 nInFlight = priv->snd_nxt - priv->snd_una; // (Fast Retransmit) priv->cwnd = min(priv->ssthresh, nInFlight + priv->mss); @@ -1383,13 +1388,13 @@ process(PseudoTcpSocket *self, Segment *seg) if (sflags == sfImmediateAck) { if (seg->seq > priv->rcv_nxt) { DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "too new"); - } else if (seg->seq + seg->len <= priv->rcv_nxt) { + } else if (SMALLER_OR_EQUAL(seg->seq + seg->len, priv->rcv_nxt)) { DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "too old"); } } // Adjust the incoming segment to fit our receive buffer - if (seg->seq < priv->rcv_nxt) { + if (SMALLER(seg->seq, priv->rcv_nxt)) { guint32 nAdjust = priv->rcv_nxt - seg->seq; if (nAdjust < seg->len) { seg->seq += nAdjust; @@ -1436,9 +1441,10 @@ process(PseudoTcpSocket *self, Segment *seg) bNewData = TRUE; iter = priv->rlist; - while (iter && (((RSegment *)iter->data)->seq <= priv->rcv_nxt)) { + while (iter && + SMALLER_OR_EQUAL(((RSegment *)iter->data)->seq, priv->rcv_nxt)) { RSegment *data = (RSegment *)(iter->data); - if (data->seq + data->len > priv->rcv_nxt) { + if (LARGER (data->seq + data->len, priv->rcv_nxt)) { guint32 nAdjust = (data->seq + data->len) - priv->rcv_nxt; sflags = sfImmediateAck; // (Fast Recovery) DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Recovered %d bytes (%d -> %d)", @@ -1460,7 +1466,7 @@ process(PseudoTcpSocket *self, Segment *seg) rseg->seq = seg->seq; rseg->len = seg->len; iter = priv->rlist; - while (iter && (((RSegment*)iter->data)->seq < rseg->seq)) { + while (iter && SMALLER (((RSegment*)iter->data)->seq, rseg->seq)) { iter = g_list_next (iter); } priv->rlist = g_list_insert_before(priv->rlist, iter, rseg); |