private PipelineInstruction QueueOrCreateDataConection(PipelineEntry entry, ResponseDescription response, bool timeout, ref Stream stream, out bool isSocketReady)
{
isSocketReady = false;
if (_dataHandshakeStarted)
{
isSocketReady = true;
return PipelineInstruction.Pause; //if we already started then this is re-entering into the callback where we proceed with the stream
}
_dataHandshakeStarted = true;
// Handle passive responses by parsing the port and later doing a Connect(...)
bool isPassive = false;
int port = -1;
if (entry.Command == "PASV\r\n" || entry.Command == "EPSV\r\n")
{
if (!response.PositiveCompletion)
{
_abortReason = SR.Format(SR.net_ftp_server_failed_passive, response.Status);
return PipelineInstruction.Abort;
}
if (entry.Command == "PASV\r\n")
{
port = GetPortV4(response.StatusDescription);
}
else
{
port = GetPortV6(response.StatusDescription);
}
isPassive = true;
}
if (isPassive)
{
if (port == -1)
{
NetEventSource.Fail(this, "'port' not set.");
}
try
{
_dataSocket = CreateFtpDataSocket((FtpWebRequest)_request, Socket);
}
catch (ObjectDisposedException)
{
throw ExceptionHelper.RequestAbortedException;
}
IPEndPoint localEndPoint = new IPEndPoint(((IPEndPoint)Socket.LocalEndPoint).Address, 0);
_dataSocket.Bind(localEndPoint);
_passiveEndPoint = new IPEndPoint(ServerAddress, port);
}
PipelineInstruction result;
if (_passiveEndPoint != null)
{
IPEndPoint passiveEndPoint = _passiveEndPoint;
_passiveEndPoint = null;
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "starting Connect()");
if (_isAsync)
{
_dataSocket.BeginConnect(passiveEndPoint, s_connectCallbackDelegate, this);
result = PipelineInstruction.Pause;
}
else
{
_dataSocket.Connect(passiveEndPoint);
result = PipelineInstruction.Advance; // for passive mode we end up going to the next command
}
}
else
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "starting Accept()");
if (_isAsync)
{
_dataSocket.BeginAccept(s_acceptCallbackDelegate, this);
result = PipelineInstruction.Pause;
}
else
{
Socket listenSocket = _dataSocket;
try
{
_dataSocket = _dataSocket.Accept();
if (!ServerAddress.Equals(((IPEndPoint)_dataSocket.RemoteEndPoint).Address))
{
_dataSocket.Close();
throw new WebException(SR.net_ftp_active_address_different, WebExceptionStatus.ProtocolError);
}
isSocketReady = true; // for active mode we end up creating a stream before advancing the pipeline
result = PipelineInstruction.Pause;
}
finally
{
listenSocket.Close();
}
}
}
return result;
}