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=00129794, 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=00129794, 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=00129794, 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

_______________________________________________
lwip-users mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/lwip-users

Reply via email to