diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-09-20 09:33:40 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-09-20 09:33:40 +0200 |
commit | 9a06f93b71e339741ac6078a0246e11e789aa784 (patch) | |
tree | 48312aa7a5c42c174f1c6b94f7bcd6e9a83d15d3 /sys/src/boot | |
parent | 9d182f906d2d97316b151851039ffb33bb4e79e0 (diff) |
tftp: prevent it from hanging if ack packets get lost
send ACK reply for duplicate data packets in case our ack response
got lost. make sure packets are in sequence and ignore out of
oder packets (except the ones we'v already acked).
Diffstat (limited to 'sys/src/boot')
-rw-r--r-- | sys/src/boot/pc/pxe.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/src/boot/pc/pxe.c b/sys/src/boot/pc/pxe.c index 97ee259cb..9f6d74b29 100644 --- a/sys/src/boot/pc/pxe.c +++ b/sys/src/boot/pc/pxe.c @@ -249,16 +249,21 @@ read(void *f, void *data, int len) switch(nhgets(t->pkt)){ case Tftp_DATA: seq = nhgets(t->pkt+2); - if(seq <= t->seq){ - putc('@'); + if(seq > t->seq){ + putc('?'); continue; } hnputs(t->pkt, Tftp_ACK); while(udpwrite(t->dip, t->gip, t->sport, t->dport, 4, t->pkt)) putc('!'); - t->seq = seq; + if(seq < t->seq){ + putc('@'); + continue; + } + t->seq = seq+1; + n -= 4; t->rp = t->pkt + 4; - t->ep = t->pkt + n; + t->ep = t->rp + n; t->eof = n < Segsize; break; case Tftp_ERROR: @@ -300,7 +305,7 @@ tftpopen(Tftp *t, char *path, IP4 sip, IP4 dip, IP4 gip) t->sport = xport++; t->dport = 0; t->rp = t->ep = 0; - t->seq = -1; + t->seq = 1; t->eof = 0; t->nul = 0; if(r = udpopen(t->sip)) |