From d73124cc5ef432a7d9f9da8b4383d5c5b726e523 Mon Sep 17 00:00:00 2001 From: adamdunkels Date: Fri, 31 Oct 2008 18:10:24 +0000 Subject: [PATCH] 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). --- core/net/psock.c | 57 +++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/core/net/psock.c b/core/net/psock.c index 6e17ed2fa..1a47438cd 100644 --- a/core/net/psock.c +++ b/core/net/psock.c @@ -30,7 +30,7 @@ * * Author: Adam Dunkels * - * $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 @@ -140,8 +140,11 @@ buf_bufto(CC_REGISTER_ARG struct psock_buf *buf, u8_t endmarker, } /*---------------------------------------------------------------------------*/ 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->sendlen > 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); } s->state = STATE_DATA_SENT; - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -static char -data_acked(CC_REGISTER_ARG struct psock *s) -{ - if(s->state == STATE_DATA_SENT && uip_acked()) { + return 0; + } else if(s->state == STATE_DATA_SENT && uip_acked()) { if(s->sendlen > uip_mss()) { s->sendlen -= 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) { /* - * The condition for this PT_WAIT_UNTIL is a little tricky: the - * protothread will wait here until all data has been acknowledged - * (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. + * The protothread will wait here until all data has been + * acknowledged and sent (data_is_acked_and_send() returns 1). */ - 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; @@ -220,21 +211,23 @@ PT_THREAD(psock_generator_send(CC_REGISTER_ARG struct psock *s, PT_EXIT(&s->psockpt); } - /* Call the generator function to generate the data in the - uip_appdata buffer. */ - s->sendlen = generate(arg); - s->sendptr = uip_appdata; - - s->state = STATE_NONE; + s->state = STATE_NONE; do { - /* Call the generator function again if we are called to perform a - retransmission. */ - if(uip_rexmit()) { - generate(arg); + /* Call the generator function to generate the data in the + uip_appdata buffer. */ + s->sendlen = 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. */ - PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s)); - } while(s->sendlen > 0); + PT_YIELD_UNTIL(&s->psockpt, uip_acked() || uip_rexmit()); + } while(!uip_acked()); s->state = STATE_NONE;