|
From: | Iordan Neshev |
Subject: | [lwip-users] pcb->acked no longer updated in RC1? |
Date: | Tue, 22 Jan 2008 16:03:10 +0100 |
User-agent: | Thunderbird 1.5.0.12 (Windows/20070509) |
Hello :) I'm developing a ftp client based on the raw API (with callbacks). It is almost finished and soon will be available for everybody. I also made a BSD-like sockets API that does not need OS. I have no real hardware right now, so I'm using the msvc6 port. I began my work with the cvs from 2007-11-01. There is a stripped version of the function that sends a stream of data over a socket : int SendData(struct tcp_pcb *pcb, const void* src, unsigned int len_arg, unsigned int *progress) { err_t err; u16_t len; unsigned loop_ack; /*unsigned*/ int remaining = len_arg; while (remaining != 0) { if (tcp_sndbuf(pcb) < remaining) {// We cannot send more data than space available in the send buffer. len = tcp_sndbuf(pcb); printf("\n sending data in parts of %d bytes\n", len); } else { len = remaining; printf("\n sending all %d bytes at once,they fit in tcp_sndbuf==%d :) \n\n", len, tcp_sndbuf(pcb)); } // try to send len bytes in this loop do { timers_update(); // handle timers (done in tcpip.c when OS present) update_adapter(); // check for packets tcp_output(pcb); // prompt the system to send data now err = tcp_write(pcb, src, len, 0); // to do: if (err != ERR_OK) { ... retry?} tcp_output(pcb);// prompt the system to send data now timers_update(); update_adapter(); if (err == ERR_MEM) { len /= 2; } printf("\n Bytes ACKed by peer: %d ", pcb->acked); /// !!!!! } while (err == ERR_MEM && len > 1); // run timers until peer acknowledges all bytes loop_ack = LOOPS_ACK_WAIT; // defined as 100 for example while (pcb->acked < len) { timers_update(); update_adapter(); printf("\nACKed: %d", pcb->acked); if(pcb->acked == 0) // this happens when remote host closes connection { // is this indication of a closing connection? if (((pcb->state) > ESTABLISHED) || ((pcb->state) == CLOSED))// waiting to close connection or already close break; // no, I have to wait... if (!loop_ack--){ printf("\n exit by timeout\7\n"); break; } } } // now len should be == pcb->acked printf("\n sent (maybe in parts) %d bytes\n\n ", len); //... remaining -= len; // len bytes sent ...... } //while (remaining != 0) printf("\n everything is now sent ) --> [%s]\n\n", src); return ERR_OK; } Then I made the following test: { //... open control connection with server //... login, open file, open data connection, et.. for (i = 0; i < 100; i++) { sprintf(databuf, "[%d]", i); ftp_append(ctrl_s, data_s, databuf, strlen(databuf)); // this uses int SendData() } } This works fine, peer acknowledges all bytes, the contents of the uploaded file are as expected: [0][1][2][3][4][5][6][7][8] ..... [99] Recently I updated the stack to RC1 and observed quite strange results. First, the data is corrupted, the file now contains something like [0][2][2][4][5][5][6][8][9][10][10][11][12][14][16][16][17][17][18][20].... Some packets are dropped, other are dupplicated I was trying different situations with putting tcp_output(pcb); and running the timers in different places. Sometimes the file contained just parts of a packet: [0][2]]4]5][5][6]8][9][1... When I make a simple delay between the packets (with no calls to timers_update(); and update_adapter(); in the Delay loop) for (i = 0; i < 100; i++) { sprintf(databuf, "[%d]", i); ftp_append(ctrl_s, data_s, databuf, strlen(databuf)); // this uses int SendData() Delay(100); // 100 milliseconds } things get better 100ms -> results are better 200ms -> almost perfect >300 ms -> no corruption I thouht the problem is due to retransmision of packets. I noticed that the queue gets full, so I inserted another loop that runs the timers until the queue is empty again, but this did not solve the problem :( I think that there may be mistmatch of sequence numbers of retransmitted packets (maybe they are incremented when they should not be?) I dont know why some of the packets are not received at all. There is also something else which may be the key to the problem: with RC1 I do not receive ACKs by the server !!! this line: printf("\n Bytes ACKed by peer: %d ", pcb->acked); /// !!!!! in the older release showed exactly how many bytes are acknowledged As you can see, I don't call tcp_output(pcb); before I get Ack of my "len" bytes. while (pcb->acked < len) { timers_update(); update_adapter(); printf("\nACKed: %d", pcb->acked); ........ if(pcb->acked == 0) // this happens when remote host closes connection if (!loop_ack--){ printf("\n exit by timeout\7\n"); break; } } } I never get ACK and the loop is exited by the timeout. pcb->acked stays 0 forever and so does pcb->unacked This retry-loop_ack-times loop worked well before RC1. there is a part of the debug messages: sending [[0] ]tcp_write(pcb=00917CE8, data="" len=4, apiflags=0) tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0) tcp_enqueue: queuelen: 0 tcp_enqueue: queueing 6537:6541 (0x0) tcp_enqueue: 2 (after enqueued) tcp_output_segment: rtseq 6537 tcp_output_segment: 6537:6541 Bytes ACKed by peer: 0 SendDataNoPayload():ACKed: 0 exit by timeout ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sent (maybe partial) 4 byte =================================================================== sending this: [[1] ]tcp_write(pcb=00917CE8, data="" len=4, apiflags=0) tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0) tcp_enqueue: queuelen: 2 tcp_enqueue: queueing 6541:6545 (0x0) tcp_enqueue: 4 (after enqueued) Bytes ACKed by peer: 0 SendDataNoPayload():ACKed: 0 exit by timeout ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ sent (maybe partial) 4 bytes =================================================================== sending throug socket 1, pcb 0x917CE8 ... sending this: [[2] ]tcp_write(pcb=00917CE8, data="" len=4, apiflags=0) tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0) tcp_enqueue: queuelen: 4 tcp_enqueue: queueing 6545:6549 (0x0) tcp_enqueue: chaining segments, new len 8 tcp_enqueue: 6 (after enqueued) tcp_receive: queuelen 6 ... 4 (after freeing unacked) tcp_receive: pcb->rttest 13 rtseq 6537 ackno 6541 tcp_receive: experienced rtt 1 ticks (500 msec). tcp_receive: RTO 6 (3000 milliseconds) Data [4] successfully sent over socket 1 CB_active_sent, len = 4 tcp_output_segment: rtseq 6541 tcp_output_segment: 6541:6549 tcp_receive: pcb->rttest 14 rtseq 6541 ackno 6541 ..... Any suggestions? Regards Iordan Neshev Daisy Technology |
[Prev in Thread] | Current Thread | [Next in Thread] |