/// <summary> /// Produces a data socket using Passive (PASV) or Extended Passive (EPSV) mode /// </summary> /// <returns></returns> internal async Task <Stream> ConnectDataStreamAsync() { Logger?.LogTrace("[FtpClient] Connecting to a data socket"); var epsvResult = await ControlStream.SendCommandAsync(FtpCommand.EPSV); int?passivePortNumber; if (epsvResult.FtpStatusCode == FtpStatusCode.EnteringExtendedPassive) { passivePortNumber = epsvResult.ResponseMessage.ExtractEpsvPortNumber(); } else { // EPSV failed - try regular PASV var pasvResult = await ControlStream.SendCommandAsync(FtpCommand.PASV); if (pasvResult.FtpStatusCode != FtpStatusCode.EnteringPassive) { throw new FtpException(pasvResult.ResponseMessage); } passivePortNumber = pasvResult.ResponseMessage.ExtractPasvPortNumber(); } if (!passivePortNumber.HasValue) { throw new FtpException("Could not determine EPSV/PASV data port"); } return(await ControlStream.OpenDataStreamAsync(Configuration.Host, passivePortNumber.Value, CancellationToken.None)); }