Bugfix: there was a problem with TCP segments not being properly retransmitted for protosockets-based applications. Cleaning up the logic around acknowledgements and retransmissions fixed the bugs pertaining to retransmissions of lost packets. This bugfix affects both the telnet server and the web server (which now work as expected wrt packet loss).

This commit is contained in:
adamdunkels 2008-10-31 18:10:24 +00:00
parent 7b87c2f5dc
commit d73124cc5e
1 changed files with 25 additions and 32 deletions

View File

@ -30,7 +30,7 @@
* *
* Author: Adam Dunkels <adam@sics.se> * Author: Adam Dunkels <adam@sics.se>
* *
* $Id: psock.c,v 1.5 2007/11/17 18:05:21 adamdunkels Exp $ * $Id: psock.c,v 1.6 2008/10/31 18:10:24 adamdunkels Exp $
*/ */
#include <stdio.h> #include <stdio.h>
@ -140,8 +140,11 @@ buf_bufto(CC_REGISTER_ARG struct psock_buf *buf, u8_t endmarker,
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static char static char
send_data(CC_REGISTER_ARG struct psock *s) data_is_sent_and_acked(CC_REGISTER_ARG struct psock *s)
{ {
/* If data has previously been sent, and the data has been acked, we
increase the send pointer and call send_data() to send more
data. */
if(s->state != STATE_DATA_SENT || uip_rexmit()) { if(s->state != STATE_DATA_SENT || uip_rexmit()) {
if(s->sendlen > uip_mss()) { if(s->sendlen > uip_mss()) {
uip_send(s->sendptr, uip_mss()); uip_send(s->sendptr, uip_mss());
@ -149,15 +152,8 @@ send_data(CC_REGISTER_ARG struct psock *s)
uip_send(s->sendptr, s->sendlen); uip_send(s->sendptr, s->sendlen);
} }
s->state = STATE_DATA_SENT; s->state = STATE_DATA_SENT;
return 1; return 0;
} } else if(s->state == STATE_DATA_SENT && uip_acked()) {
return 0;
}
/*---------------------------------------------------------------------------*/
static char
data_acked(CC_REGISTER_ARG struct psock *s)
{
if(s->state == STATE_DATA_SENT && uip_acked()) {
if(s->sendlen > uip_mss()) { if(s->sendlen > uip_mss()) {
s->sendlen -= uip_mss(); s->sendlen -= uip_mss();
s->sendptr += uip_mss(); s->sendptr += uip_mss();
@ -193,16 +189,11 @@ PT_THREAD(psock_send(CC_REGISTER_ARG struct psock *s, const uint8_t *buf,
while(s->sendlen > 0) { while(s->sendlen > 0) {
/* /*
* The condition for this PT_WAIT_UNTIL is a little tricky: the * The protothread will wait here until all data has been
* protothread will wait here until all data has been acknowledged * acknowledged and sent (data_is_acked_and_send() returns 1).
* (data_acked() returns true) and until all data has been sent
* (send_data() returns true). The two functions data_acked() and
* send_data() must be called in succession to ensure that all
* data is sent. Therefore the & operator is used instead of the
* && operator, which would cause only the data_acked() function
* to be called when it returns false.
*/ */
PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s)); PT_YIELD_UNTIL(&s->psockpt, data_is_sent_and_acked(s));
printf("sendlen %d\n", s->sendlen);
} }
s->state = STATE_NONE; s->state = STATE_NONE;
@ -220,21 +211,23 @@ PT_THREAD(psock_generator_send(CC_REGISTER_ARG struct psock *s,
PT_EXIT(&s->psockpt); PT_EXIT(&s->psockpt);
} }
/* Call the generator function to generate the data in the s->state = STATE_NONE;
uip_appdata buffer. */
s->sendlen = generate(arg);
s->sendptr = uip_appdata;
s->state = STATE_NONE;
do { do {
/* Call the generator function again if we are called to perform a /* Call the generator function to generate the data in the
retransmission. */ uip_appdata buffer. */
if(uip_rexmit()) { s->sendlen = generate(arg);
generate(arg); s->sendptr = uip_appdata;
if(s->sendlen > uip_mss()) {
uip_send(s->sendptr, uip_mss());
} else {
uip_send(s->sendptr, s->sendlen);
} }
s->state = STATE_DATA_SENT;
/* Wait until all data is sent and acknowledged. */ /* Wait until all data is sent and acknowledged. */
PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s)); PT_YIELD_UNTIL(&s->psockpt, uip_acked() || uip_rexmit());
} while(s->sendlen > 0); } while(!uip_acked());
s->state = STATE_NONE; s->state = STATE_NONE;