Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Oct : Re: TIdTrivialFTPServer and multi-homed server?

www.cryer.info
Managed Newsgroup Archive

Re: TIdTrivialFTPServer and multi-homed server?

Subject:Re: TIdTrivialFTPServer and multi-homed server?
Posted by:"Philippe Auphelle" (pauphelle.no.spam.please@wanadoo.fr)
Date:Thu, 12 Oct 2006 12:34:22

Gambit,

> You are using an old version that is over 11 months old.

<sigh>

There are at least three good reasons for this:

1) The current snapshot has been broken for a at least a few weeks and
requires changing an HashValueAsHex() call to an HashValue() in two
different places to properly compile and install. This is not a
complain, mind you, I realize this is just what it says: a snapshot.

2) I just checked, and this "old version" I was using is the one that is
still available on the AtoZed site with an automatic installer.

3) This AtoZed installer version is currently the only version of 10.1.5
that can be downloaded and that can compile, as far as I know.

IOW, yes, I used an 11 months old version, because this is the most
recent copy of the Indy code that I could find that is still available
and readily accessible, that's not a snapshot, and that compiles.


> What I described is how it works *today*, not how it worked
> *11+ months ago*.

I said from the very beginning (very precisely in my second message)
that I was using a version that I downloaded "over six month ago".
Furthermore, this version is still the only recent one that can be
downloaded, compiled and installed.
And finally, the only other one that's proposed for VCL / native
compilers on the Indy site is even older than the one I use, since it's
a 10.0.52.

> Your evidence is misunderstood, and thus completely wrong.
> TIdUDPServer has supported multi-homing for years, long
> before Indy 10 even existed.

Gambit, once again, facts are stubborn.
And here here are some news:
After fixing in yesterday's snapshot the couple of lines that don't
compile, I used the snapshot Indy, recompiled my app, and surprise! It
*does* work with two IPs, *without* changing anything else in my own code.
Once again, I have no doubt that TidUDPServer has been *designed* to
support multi-homing for years, but the hard fact is that the version I
used of a stable 10.1.5 as of today does *not* seem to work properly on
a multi-homed config. I define stable a minima here as: "compilable,
non-snapshot", because that's all there is anyway...

Now as I said from start, this could very well be something I'm not
doing right, so you'll find below the smallest app I could write that
reproduces the problem.
It's a console proggie with a datamodule containing the Indy TTP server,
and I have enclosed the source for both the .dpr and the data module
code. No need for the DFM, since it's just a datamodule with a dropped
in idTrivialFTPServer, all default properties. You can download the
exact same Indy I just reinstalled and used for this test (Setting it up
is a quickie using the automatic installer - courtesy of the AtoZed folks).

And if the .exe behaves like it does here, you'll notice that this code
1) takes and processes requests just great when the station it runs has
a single IP, and
2) Sits there doing nothing when when it gets a request on the IP that
was bound SECOND in its Bindings. In other words, it only listen at
startup on the IP that's bound first. You can tell the binding order by
the message that show each binding in the order they is added in.

If you reach this point, I then encourage you to recompile adding the
bindings from the last item in LocalAddresses backward (so the IP on
which the requests come in appears first), and try again. You'll then
notice then that the OnReadFile event triggers then, at least on the
first request.

Now, if this problem is due to some obvious mistake in my code, I'll be
very grateful if you could point it out. Sincerely. /Ph.


=================

program IndyTFTPTest;

{$APPTYPE CONSOLE}

uses
   SysUtils,
   TFTPServer in 'TFTPServer.pas' {DataModule1: TDataModule};

var
   ConsoleInput: string;

begin

   DataModule1 := TDataModule1.Create(nil);
   DataModule1.StartTFTP;

   // Block here while we're testing.
   while (ConsoleInput <> 'q')
         and (ConsoleInput <> 'x')
         and (ConsoleInput <> '*') do
     ReadLn(ConsoleInput);

end.

=================

unit TFTPServer;

interface

uses
   SysUtils, Classes, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer,
   IdTrivialFTPServer;

type
   TDataModule1 = class(TDataModule)
     IdTrivialFTPServer1: TIdTrivialFTPServer;
     procedure IdTrivialFTPServer1ReadFile(Sender: TObject;
       var FileName: String; const PeerInfo: TPeerInfo;
       var GrantAccess: Boolean; var AStream: TStream;
       var FreeStreamOnComplete: Boolean);
     procedure IdTrivialFTPServer1TransferComplete(Sender: TObject;
       const Success: Boolean; const PeerInfo: TPeerInfo;
       var AStream: TStream; const WriteOperation: Boolean);
   private
     { Private declarations }
   public
     { Public declarations }
     procedure StartTFTP;
   end;

var
   DataModule1: TDataModule1;

implementation

{$R *.dfm}

uses
   IdStack
   ;

procedure TDataModule1.StartTFTP;
var
   i: integer;

begin
   with DataModule1.IdTrivialFTPServer1 do
     begin
     Active := False;          // Just in case.
     Bindings.Clear;
     ThreadedEvent := True;    // No synch in a console.
     // All other component properties are the default ones.

     // For each of our IP addresses, create and init a binding.
     for i := 0 to GStack.LocalAddresses.Count - 1 do
       with Bindings.Add do
         begin
         IP := GStack.LocalAddresses[i];
         WriteLn('Created binding '
                  + IP
                  + ':'
                  + IntToStr(Port)
                 );
         end;
     Active := True;
     end;
end;

procedure TDataModule1.IdTrivialFTPServer1ReadFile(Sender: TObject;
   var FileName: String; const PeerInfo: TPeerInfo;
   var GrantAccess: Boolean; var AStream: TStream;
   var FreeStreamOnComplete: Boolean);
begin
   WriteLn('File request from IP:Port '
                  + PeerInfo.PeerIP
                  + ':'
                  + IntToStr(Peerinfo.PeerPort)
          );
   WriteLn('Requested file: ' + Filename);
   if FileExists(FileName) then
     try
       GrantAccess := True;
       AStream := TFileStream.Create(FileName, fmOpenRead or
fmShareDenyWrite);
       FreeStreamOnComplete := True;
     finally
       WriteLn('Transfer attempted.')
     end
   else
     begin
     WriteLn('File not found (or access denied).');
     GrantAccess := False;
     end;
end;

procedure TDataModule1.IdTrivialFTPServer1TransferComplete(Sender: TObject;
   const Success: Boolean; const PeerInfo: TPeerInfo; var AStream: TStream;
   const WriteOperation: Boolean);
begin
   if Success then
     WriteLn('Transfer completed OK.')
   else
     WriteLn('Transfer failed.');
end;

end.

=================

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive