[FIX] FTPClient LoginFailedException
Florian Minjat
florian.minjat at emn.fr
Tue Mar 20 14:49:54 UTC 2007
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]
--------------------------------------------
More information about the Squeak-dev
mailing list
|