{
struct flow *f = flow_heap[1];
HEAP_DELMIN(struct flow *, flow_heap, tcp_num_flows, FLOW_HEAP_LESS, FLOW_HEAP_SWAP);
- DBG("%s for flow %p(%s/%s)\n", (doomsday ? "DOOMSDAY" : "TIMEOUT"), f,
- pipe_state_names[f->pipe[0].state], pipe_state_names[f->pipe[1].state]);
+ DBG("%s for flow %p(%s/%s) now=%d\n", (doomsday ? "DOOMSDAY" : "TIMEOUT"), f,
+ flow_state_names[f->pipe[0].state], flow_state_names[f->pipe[1].state], now);
if (f->pipe[0].state != FLOW_FINISHED || f->pipe[1].state != FLOW_FINISHED)
{
uns cause;
DBG("DATA:");
if (tcp_seq_lt(b->queue_start_seq, p->seq) && p->seq - b->queue_start_seq >= 0x40000)
{
- DBG(" OUT OF WINDOW (q-start=%u)\n", b->queue_start_seq);
+ DBG(" OUT OF WINDOW (q-start=%u)", b->queue_start_seq);
pkt_free(p);
return;
}
} fakehdr;
struct pkt *q;
uns now = timestamp_to_now(p->timestamp);
+ struct flow *f = NULL;
tcp_time_step(now, 0);
u32 seq = ntohl(tcph->seq);
u32 ack = ntohl(tcph->ack_seq);
- DBG("TCP %08x %08x %04x %04x seq=%u len=%u end=%u ack=%u%s%s%s%s%s%s\n",
+ DBG("TCP %08x %08x %04x %04x seq=%u len=%u end=%u ack=%u%s%s%s%s%s%s now=%d\n",
ntohl(iph->saddr), ntohl(iph->daddr), ntohs(tcph->source), ntohs(tcph->dest),
seq, pkt_len(p) - hdrlen, seq + pkt_len(p) - hdrlen, ack,
(tcph->fin ? " FIN" : ""),
(tcph->rst ? " RST" : ""),
(tcph->psh ? " PSH" : ""),
(tcph->ack ? " ACK" : ""),
- (tcph->urg ? " URG" : ""));
+ (tcph->urg ? " URG" : ""),
+ now);
- struct flow *f;
struct pipe *a, *b;
if (f = flow_lookup(iph->saddr, iph->daddr, tcph->source, tcph->dest))
{
pkt_account(&f->stat_raw, p);
pkt_pop(p, hdrlen);
- DBG("\t%p %s (%s/%s) ", f, (a == &f->pipe[0] ? "A->B" : "B->A"), pipe_state_names[f->pipe[0].state], pipe_state_names[f->pipe[1].state]);
+ DBG("\t%p %s (%s/%s) ", f, (a == &f->pipe[0] ? "A->B" : "B->A"), flow_state_names[f->pipe[0].state], flow_state_names[f->pipe[1].state]);
if (a->state == FLOW_FINISHED && b->state == FLOW_FINISHED)
{
+ /* XXX: Here we probably should handle SYN (fast recycling of ports) */
DBG("closed\n");
pkt_account(&stat_tcp_on_closed, p);
+ f = NULL; /* Avoid shifting flow timeout */
goto drop;
}
cnt_tcp_causes[CAUSE_RESET]++;
f->appl->close(f, CAUSE_RESET, p->timestamp);
a->state = b->state = FLOW_FINISHED;
- flow_set_timeout(f, now + 120);
goto drop;
}
- flow_set_timeout(f, now + 3000); /* Somewhat arbitrary timeout */
-
if (tcph->syn)
{
if (tcph->fin || pkt_len(p))
DBG("CLOSED BOTH WAYS\n");
cnt_tcp_causes[CAUSE_CLOSE]++;
f->appl->close(f, CAUSE_CLOSE, p->timestamp);
- flow_set_timeout(f, now + 300); /* FIXME */
goto drop;
}
else
}
}
DBG("\n");
- return;
+ goto done;
}
else
goto unex;
+ /* Not reached */
+ dup:
+ DBG("DUP\n");
drop:
pkt_free(p);
+ done:
+ if (f)
+ {
+ int timeout = 60; /* Connection setup timeout */
+ if (f->pipe[0].state == FLOW_FINISHED && f->pipe[1].state == FLOW_FINISHED)
+ timeout = 30; /* After connection close; later the packets are just unmatched */
+ else if ((f->pipe[0].state == FLOW_ESTABLISHED || f->pipe[0].state == FLOW_FIN_SENT || f->pipe[0].state == FLOW_FINISHED) &&
+ (f->pipe[1].state == FLOW_ESTABLISHED || f->pipe[1].state == FLOW_FIN_SENT || f->pipe[1].state == FLOW_FINISHED))
+ timeout = 900; /* Data phase timeout */
+ DBG("timeout at %d\n", now+timeout);
+ flow_set_timeout(f, now + timeout);
+ }
return;
- dup:
- DBG("DUP\n");
- goto drop;
-
unex:
DBG("UNEXPECTED\n");
unexpected: