Hi Steen
I had some time so decided to test the FTP with an old Win98 laptop - based on the fact that I found it quite easy to overload it with fast TCP data (running a browser).
However I found that I couldn't get such an effect with FTP (DOS), presumably because it is a much more efficient client - even on an even older laptop that I found in the cellar. Therefore all that I could do was to add some code to ensure that no more data was sent than the client could really accept - this was missing in the previous version.
Based on this experience I would suggest that nothing more is actually needed in normal use.
Thinking about it, I don't actually expect that even a very slow embedded FTP client, with limited memory, should have any problems with the present implementation. So I think that we can leave it like this.
If anyone does ever find that a data transfer does fail due to the client's window closing (not continue) please send a recording to me so that I can play it through the uTasker simulator. The only reason that I could think of it failing - even if someone manages to find a client that can't handle the rate - is if the client's TCP stack doesn't send a correct window update, or if this gets lost (would hardly be repeatable..).
So here's the change (and final solution..... probably..):
case MSG_UPLOAD:
#ifdef FTP_DATA_WINDOWS
{
unsigned short usTxLength = present_tcp->usTxWindowSize;
if (usTxLength > FTP_DATA_BUFFER_LENGTH) { // if the destination rx buffer can accept a full TCP frame send a full frame
usTxLength = FTP_DATA_BUFFER_LENGTH; // full frame size
}
if ((usLastSentSize = (unsigned short)uGetFileData(ptrFile, FileOffset, FTP_Data_Tx.ucTCP_Message, usTxLength)) != 0) {
unsigned short usNextSent;
signed short sSend = fnSendTCP(Socket, (unsigned char *)&FTP_Data_Tx.tTCP_Header, usLastSentSize, TCP_FLAG_PUSH);
if (sSend <= 0) { // if transmission error
return sSend; // return transmission status
}
present_tcp->usOpenCnt += usLastSentSize; // the destination receivers input buffer size after receiving teh previous frame
usTxLength = (present_tcp->usTxWindowSize - usLastSentSize);
if (usTxLength > FTP_DATA_BUFFER_LENGTH) { // if the destination rx buffer can still accept a full TCP frame send a full frame
usTxLength = FTP_DATA_BUFFER_LENGTH; // full frame size
}
usNextSent = (unsigned short)uGetFileData(ptrFile, (FileOffset + usLastSentSize), FTP_Data_Tx.ucTCP_Message, usTxLength );
if (usNextSent == 0) { // end of file reached
return sSend;
}
usLastSentSize += usNextSent; // complete outstanding data to be acked
return (fnSendTCP(Socket, (unsigned char *)&FTP_Data_Tx.tTCP_Header, usNextSent, TCP_FLAG_PUSH)); // send second buffer
}
else {
return 0; // end of file reached
}
}
#else
if ((usLastSentSize = (unsigned short)uGetFileData(ptrFile, FileOffset, FTP_Data_Tx.ucTCP_Message, FTP_DATA_BUFFER_LENGTH)) != 0) {
return (fnSendTCP(Socket, (unsigned char *)&FTP_Data_Tx.tTCP_Header, usLastSentSize, TCP_FLAG_PUSH));
}
else {
return 0; // end of file reached
}
#endif
#endif
Regards
Mark