0

I am receiving an EIdTFTPAllocationExceeded exception when transferring a file from me (the server - using the Indy TIdTrivialFTPServer component) to a device. I cannot find any information about what that exception might mean except maybe a disk space problem on the client (which I know is not the case because if I transfer the file through a different TFTP server, there is no problem).

  1. What is the exception trying to tell me?
  2. How do I get around it?
  3. Is there any code that I'm missing?

My TFTP Server code (all of it) for the server is:

__fastcall TTrivialFTPServer::TTrivialFTPServer(TComponent* Owner) : TDataModule(Owner)
{
    root = IncludeTrailingPathDelimiter(GetCurrentDir());
}

// ---------------------------------------------------------------------------
void __fastcall TTrivialFTPServer::tftpReadFile(TObject *Sender, UnicodeString &FileName, const TPeerInfo &PeerInfo, bool &GrantAccess, TStream *&AStream, bool &FreeStreamOnComplete)
{
    FreeStreamOnComplete = true;
    FileName = StringReplace(FileName, "/", "\\", TReplaceFlags() << rfReplaceAll);
    FileName = ExtractFileName(FileName);
    if (FileExists(root + "files\\" + FileName, false))
    {
        AStream = new TFileStream(root + "files\\" + FileName, fmOpenRead | fmShareDenyWrite);
        GrantAccess = true;
    }
    else
    {
        GrantAccess = false;
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Brian P.
  • 206
  • 3
  • 14

1 Answers1

0

After much searching and head scratching, I finally opened the IdTrivialFTPServer.pas file and found the problem. The code states:

if FBlkCounter = High(UInt16) then begin
    raise EIdTFTPAllocationExceeded.Create('');
end;

When I added text to the exception I received the added text, so this is where the error is occurring. I tried converting from UInt16 to UInt32, but caused many more problems, so I wanted to see what would happen if I just commented out the check and let the counter roll back to zero.

As It turns out, nothing at all bad happens and the file transfers just fine!

Brian P.
  • 206
  • 3
  • 14
  • The 16bit counter on data blocks starts at 1. 0 is used only when replying to a request for a transfer. The TFTP protocol does not define how the 16bit counter should wrap, if at all, to 0 or 1 after 65535 data packets have been sent. The default block size per data packet is 512 bytes, so the default max file size is 32MB. For larger files, the client can ask for a larger block size when requesting a file transfer, which effectively increases the max file size to 91MB. That is the only *official* option. Anything beyond that is non-standard behavior. See https://www.compuphase.com/tftp.htm – Remy Lebeau Jan 10 '19 at 23:35
  • I may decide to add customizable options to the TFTP components to control the wrap behavior. See https://github.com/IndySockets/Indy/issues/242 – Remy Lebeau Jan 10 '19 at 23:41
  • Interesting reads both. Thank you. The compuphase article talks about the rollover method, as well as others. Apparently this is what was implemented in one of the commercial TFTP servers I had used for testing purposes as well as what I unintentionally implemented in the code. I think giving the option in the properties would be the best choice - as well as some documentation on what it is and why it's needed (links link those given above were very helpful to me). – Brian P. Jan 11 '19 at 15:25