merijnb 4 Posted November 3, 2021 We've run into a bug with regards the FTP client in ICS, it boils down to the Listen() method of TCustomWSocket in OverbyteIcsWSocket.pas At the top of the method, fLastError should be set to 0: procedure TCustomWSocket.Listen; var iStatus : Integer; optval : Integer; optlen : Integer; mreq : ip_mreq; mreqv6 : TIpv6MReq; Success : Boolean; FriendlyMsg : String; ErrorCode : Integer; {$IFDEF MSWINDOWS} dwBufferInLen : DWORD; dwBufferOutLen : DWORD; dwDummy : DWORD; {$ENDIF} begin fLastError := 0; // <-- this should be added FriendlyMsg := ''; The reason this is needed is as follows: If you start an active FTP connection to a server, while using a data port range the client will try to setup a server for the data connection on port X, if this fails it will try again on X + 1 until it's able to start a server (or runs out of ports to try). This is found inTCustomFtpCli.PortAsync() in OverbyteIcsFtpCli: StartDataPort := DataPort; while TRUE do begin FDataSocket.Port := IntToStr(DataPort); try FDataSocket.Listen; break; { Found a free port } except if FDataSocket.LastError = WSAEADDRINUSE then begin DataPort := DataPort + 1; if DataPort > FDataPortRangeEnd then DataPort := FDataPortRangeStart; if DataPort = StartDataPort then begin HandleError('All ports in DataPortRange are in use'); Exit; end; end else begin HandleError('Data connection winsock bind failed - ' + GetWinsockErr(FDataSocket.LastError)); Exit; end; end; end; If you make a new FTP connection while one of the ports is already in use, but PortAsync() is able to find another port, the fLastError is still set to something <> 0 due to the earlier failed port. If you then end up in TCustomFtpCli.PutAsync(), it will still see that LastError and raise an exception over that while we're currently happily listening without problems. procedure TCustomFtpCli.PutAsync; begin DataSocket.LastError := 0; { V2.100 } HighLevelAsync(ftpPutAsync, [ftpFctPort, ftpFctPut]); if DataSocket.LastError <> 0 then { V2.100 } raise FtpException.Create('Socket Error - ' + GetWinsockErr(DataSocket.LastError)); { V2.100 } end; Share this post Link to post
Angus Robertson 577 Posted November 3, 2021 Thanks, updated my copy, should be in SVN in a few days. Angus 1 Share this post Link to post