mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
httpd: account for the bytes actually sent
uip_mss() is the limit on the next segment, not a record of the last one: uIP recomputes it from the window the peer advertises in every incoming segment, before the application is called. The ACK path subtracted it from slen and added it to o_idx, and the retransmit path handed it to uip_send(), so whenever the window moved between a segment going out and its ACK coming back, the file being served lost or repeated the difference. A window shrinking from 1460 to 600 between the two repeats 860 bytes under fresh sequence numbers, which a browser writes into the file; a window opening the same way skips 860. Remember the length in tx_send() and use it in both places. The retransmit path then repeats exactly the segment uIP still counts as outstanding, which is what uip_connr->len makes it put on the wire.
This commit is contained in:
1 parent
10dd330e3c
commit
072edb36a8
1 file changed
+19
-15
+19
-15
@@ -37,6 +37,7 @@ __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
|
|||||||
__xdata uint8_t entry;
|
__xdata uint8_t entry;
|
||||||
__xdata uint16_t slen;
|
__xdata uint16_t slen;
|
||||||
__xdata uint16_t o_idx;
|
__xdata uint16_t o_idx;
|
||||||
|
__xdata uint16_t sent_len;
|
||||||
__xdata uint16_t len_left;
|
__xdata uint16_t len_left;
|
||||||
__xdata uint16_t cont_len;
|
__xdata uint16_t cont_len;
|
||||||
__xdata uint32_t cont_addr;
|
__xdata uint32_t cont_addr;
|
||||||
@@ -826,6 +827,13 @@ void handle_post(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void tx_send(uint16_t len)
|
||||||
|
{
|
||||||
|
sent_len = len;
|
||||||
|
uip_send(outbuf + o_idx, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void httpd_appcall(void)
|
void httpd_appcall(void)
|
||||||
{
|
{
|
||||||
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
__xdata struct httpd_state * __xdata s = &(uip_conn->appstate);
|
||||||
@@ -861,9 +869,9 @@ void httpd_appcall(void)
|
|||||||
}
|
}
|
||||||
} else if (uip_acked() && s->tstate == TSTATE_TX) {
|
} else if (uip_acked() && s->tstate == TSTATE_TX) {
|
||||||
dbg_string("ACK\n");
|
dbg_string("ACK\n");
|
||||||
if (slen > uip_mss()) {
|
if (slen > sent_len) {
|
||||||
slen -= uip_mss();
|
slen -= sent_len;
|
||||||
o_idx += uip_mss();
|
o_idx += sent_len;
|
||||||
} else {
|
} else {
|
||||||
slen = 0;
|
slen = 0;
|
||||||
}
|
}
|
||||||
@@ -872,11 +880,11 @@ void httpd_appcall(void)
|
|||||||
|
|
||||||
if (slen > uip_mss()) {
|
if (slen > uip_mss()) {
|
||||||
dbg_string("Sending A: "); dbg_short(slen); dbg_char('\n');
|
dbg_string("Sending A: "); dbg_short(slen); dbg_char('\n');
|
||||||
uip_send(outbuf + o_idx, uip_mss());
|
tx_send(uip_mss());
|
||||||
s->tstate = TSTATE_TX;
|
s->tstate = TSTATE_TX;
|
||||||
} else if (slen > 0) {
|
} else if (slen > 0) {
|
||||||
dbg_string("Sending B: "); dbg_short(slen); dbg_char('\n');
|
dbg_string("Sending B: "); dbg_short(slen); dbg_char('\n');
|
||||||
uip_send(outbuf + o_idx, slen);
|
tx_send(slen);
|
||||||
s->tstate = TSTATE_TX;
|
s->tstate = TSTATE_TX;
|
||||||
} else if (cont_len) {
|
} else if (cont_len) {
|
||||||
dbg_string("CONT cont_len: "); dbg_short(cont_len);
|
dbg_string("CONT cont_len: "); dbg_short(cont_len);
|
||||||
@@ -887,7 +895,7 @@ void httpd_appcall(void)
|
|||||||
flash_region.len = slen;
|
flash_region.len = slen;
|
||||||
flash_read_bulk(outbuf);
|
flash_read_bulk(outbuf);
|
||||||
o_idx = 0;
|
o_idx = 0;
|
||||||
uip_send(outbuf + o_idx, slen);
|
tx_send(slen);
|
||||||
cont_len -= slen;
|
cont_len -= slen;
|
||||||
cont_addr += slen;
|
cont_addr += slen;
|
||||||
s->tstate = TSTATE_TX;
|
s->tstate = TSTATE_TX;
|
||||||
@@ -1045,24 +1053,20 @@ do_send:
|
|||||||
o_idx = 0;
|
o_idx = 0;
|
||||||
if (slen > uip_mss()) {
|
if (slen > uip_mss()) {
|
||||||
dbg_string("Sending a: "); dbg_short(slen); dbg_char('\n');
|
dbg_string("Sending a: "); dbg_short(slen); dbg_char('\n');
|
||||||
uip_send(outbuf + o_idx, uip_mss());
|
tx_send(uip_mss());
|
||||||
dbg_string("Sending a done\n");
|
dbg_string("Sending a done\n");
|
||||||
} else {
|
} else {
|
||||||
dbg_string("Sending b: "); dbg_short(slen); dbg_char('\n');
|
dbg_string("Sending b: "); dbg_short(slen); dbg_char('\n');
|
||||||
uip_send(outbuf + o_idx, slen);
|
tx_send(slen);
|
||||||
dbg_string("Sending b done\n");
|
dbg_string("Sending b done\n");
|
||||||
}
|
}
|
||||||
s->tstate = TSTATE_TX;
|
s->tstate = TSTATE_TX;
|
||||||
} else if (uip_rexmit()) { // Connection established, need to rexmit?
|
} else if (uip_rexmit()) { // Connection established, need to rexmit?
|
||||||
dbg_string("RETRANSMIT requested\n");
|
dbg_string("RETRANSMIT requested\n");
|
||||||
if (slen > uip_mss()) {
|
if (sent_len) {
|
||||||
dbg_string("Sending C: "); dbg_short(slen); dbg_char('\n');
|
dbg_string("Sending C: "); dbg_short(sent_len); dbg_char('\n');
|
||||||
uip_send(outbuf + o_idx, uip_mss());
|
tx_send(sent_len);
|
||||||
dbg_string("Sending C done\n");
|
dbg_string("Sending C done\n");
|
||||||
} else if (slen > 0) {
|
|
||||||
dbg_string("Sending D: "); dbg_short(slen); dbg_char('\n');
|
|
||||||
uip_send(outbuf + o_idx, slen);
|
|
||||||
dbg_string("Sending D done\n");
|
|
||||||
}
|
}
|
||||||
s->tstate = TSTATE_TX;
|
s->tstate = TSTATE_TX;
|
||||||
uip_len = 0;
|
uip_len = 0;
|
||||||
|
|||||||
Reference in new issue
Block a user