[FIX] FTPClient LoginFailedException

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[FIX] FTPClient LoginFailedException

Florian Minjat
Hi,
   Since some weeks I got a LoginFailedException very often when
accessing an MCFtpRepository. My ftp server is ProFTPD 1.2.10 Server
and didn't change for a long time. This bug was very annoying because
I needed to save my changes many times before I could get no error.
   I traced the network exchange between the server and squeak and
found that sometimes, the server just cut the connection after squeak
sent the 'PASS' request. So I did a new method which checks when the
connection is curtailed by a LoginFailedException, test if the socket
was cut by the remote end and then do the login sequence again. It is
pretty hackish but now it works fine.
   I didn't saw anything about this problem on the mailing list so I
don't know if it is specific to my image, but here is the fix anyway.

Florian


A test to show my problem :
___________________________________________
TestFTPClient>>testFTPClientOpenOnHostNamed
     |client host user password nbOk nbBad|
     host := 'myHost'.
     user := 'myUser'.
     password := 'myPass'.
     nbOk := 0.
     nbBad := 0.

10 timesRepeat: [[[
     self halt.
     client := FTPClient openOnHostNamed: host.
     client user: user.
     client password: password.

     client sendCommand: 'USER ', user.
     "331 Password required"
     client lookForCode: 331.
     "will ask user, if needed"
     client sendCommand: 'PASS ', password.
     "230 User logged in"
     client lookForCode: 230.
     nbOk := nbOk + 1.
] on: TelnetProtocolError do: [:ex | nbBad := nbBad +1]
] ensure: [client close]
].
self assert: (nbBad = 0)
--------------------------------------------

A 'fix' in FTPClient :
____________________________________________
FTPClient class>>openOnHostNamed: host logUser: user password: password
     "this method comes from a recurent recent problem with ftp access
with login/pass which are cut from the ftp server inexpectantly
     it just tests when the login sequence failed if the other end had
cut the connection and retry it"
     |client|
     [
          client := super openOnHostNamed: host.
          client loginUser: user password: password
     ] on: LoginFailedException do: [:ex |
          client stream socket isOtherEndClosed
               ifFalse: [ (LoginFailedException protocolInstance:
client) signal: client lastResponse ]
               ifTrue: [
                    client close.
                    client := FTPClient openOnHostNamed: host
andLogUser: user password: password ]
     ].
     ^ client
----------------------------------------------


A new test to ensure it's working well :
____________________________________________
TestFTPClient>>testFTPClientOpenOnHostNamed
     |client host user password nbOk nbBad|
     host := 'myHost'.
     user := 'myUser'.
     password := 'myPass'.
     nbOk := 0.
     nbBad := 0.

10 timesRepeat: [[[
     client := FTPClient openOnHostNamed: host andLogUser: user
password: password.
     (client getDirectory notNil)
          ifTrue: [ nbOk := nbOk + 1 ]
          ifFalse: [ nbBad := nbBad + 1 ]

] on: TelnetProtocolError do: [:ex | nbBad := nbBad +1]
] ensure: [client close]
].
self assert: (nbBad = 0)
--------------------------------------------


And the fix in MCFtpRepository>>clientDo: to use my change
____________________________________________
MCFtpRepository>>clientDo: aBlock
| client |
client := FTPClient openOnHostNamed: host andLogUser: user password:
password.
directory isEmpty ifFalse: [client changeDirectoryTo: directory].
^ [aBlock value: client] ensure: [client close]
--------------------------------------------