private static void AcceptCallback(IAsyncResult asyncResult) { FtpControlStream asyncState = (FtpControlStream)asyncResult.AsyncState; LazyAsyncResult result = asyncResult as LazyAsyncResult; Socket asyncObject = (Socket)result.AsyncObject; try { asyncState.m_DataSocket = asyncObject.EndAccept(asyncResult); if (!asyncState.ServerAddress.Equals(((IPEndPoint)asyncState.m_DataSocket.RemoteEndPoint).Address)) { asyncState.m_DataSocket.Close(); throw new WebException(SR.GetString("net_ftp_active_address_different"), WebExceptionStatus.ProtocolError); } asyncState.ContinueCommandPipeline(); } catch (Exception exception) { asyncState.CloseSocket(); asyncState.InvokeRequestCallback(exception); } finally { asyncObject.Close(); } }
/// <summary> /// Provides a wrapper for the async accept operations. /// </summary> private static void AcceptCallback(IAsyncResult asyncResult) { FtpControlStream connection = (FtpControlStream)asyncResult.AsyncState; Socket listenSocket = connection._dataSocket; try { connection._dataSocket = listenSocket.EndAccept(asyncResult); if (!connection.ServerAddress.Equals(((IPEndPoint)connection._dataSocket.RemoteEndPoint).Address)) { connection._dataSocket.Close(); throw new WebException(SR.net_ftp_active_address_different, WebExceptionStatus.ProtocolError); } connection.ContinueCommandPipeline(); } catch (Exception e) { connection.CloseSocket(); connection.InvokeRequestCallback(e); } finally { listenSocket.Close(); } }
private static void SSLHandshakeCallback(IAsyncResult asyncResult) { FtpControlStream asyncState = (FtpControlStream)asyncResult.AsyncState; try { asyncState.ContinueCommandPipeline(); } catch (Exception exception) { asyncState.CloseSocket(); asyncState.InvokeRequestCallback(exception); } }
private static void SSLHandshakeCallback(IAsyncResult asyncResult) { FtpControlStream connection = (FtpControlStream)asyncResult.AsyncState; try { connection._tlsStream.EndAuthenticateAsClient(asyncResult); connection.ContinueCommandPipeline(); } catch (Exception e) { connection.CloseSocket(); connection.InvokeRequestCallback(e); } }
/// <summary> /// <para>Provides a wrapper for the async accept operations</para> /// </summary> private static void ConnectCallback(IAsyncResult asyncResult) { FtpControlStream connection = (FtpControlStream)asyncResult.AsyncState; try { connection._dataSocket.EndConnect(asyncResult); connection.ContinueCommandPipeline(); } catch (Exception e) { connection.CloseSocket(); connection.InvokeRequestCallback(e); } }
private static void ConnectCallback(IAsyncResult asyncResult) { FtpControlStream asyncState = (FtpControlStream)asyncResult.AsyncState; try { LazyAsyncResult result = asyncResult as LazyAsyncResult; ((Socket)result.AsyncObject).EndConnect(asyncResult); asyncState.ContinueCommandPipeline(); } catch (Exception exception) { asyncState.CloseSocket(); asyncState.InvokeRequestCallback(exception); } }
// // Only executed for Async requests // private void AsyncRequestCallback(object obj) { GlobalLog.Enter("FtpWebRequest#" + ValidationHelper.HashString(this) + "::AsyncRequestCallback", "#"+ValidationHelper.HashString(obj)); RequestStage stageMode = RequestStage.CheckForError; try { FtpControlStream connection; connection = obj as FtpControlStream; FtpDataStream stream = obj as FtpDataStream; Exception exception = obj as Exception; bool completedRequest = (obj == null); GlobalLog.Print("AsyncRequestCallback() stream:"+ValidationHelper.HashString(stream)+" conn:"+ValidationHelper.HashString(connection)+" exp:"+ValidationHelper.HashString(exception)+" completedRequest:"+ValidationHelper.HashString(completedRequest)); while (true) { if (exception != null) { if (AttemptedRecovery(exception)) { connection = QueueOrCreateConnection(); if (connection == null) return; exception = null; } if (exception != null) { SetException(exception); break; } } if (connection != null) { lock(m_SyncObject) { if (m_Aborted) { if (Logging.On) Logging.PrintInfo(Logging.Web, this, "", SR.GetString(SR.net_log_releasing_connection, ValidationHelper.HashString(connection))); m_ConnectionPool.PutConnection(connection, this, Timeout); break; } m_Connection = connection; if (Logging.On) Logging.Associate(Logging.Web, this, m_Connection); } try { stream = (FtpDataStream)TimedSubmitRequestHelper(true); } catch (Exception e) { exception = e; continue; } return; } else if (stream != null) { lock (m_SyncObject) { if (m_Aborted) { ((ICloseEx)stream).CloseEx(CloseExState.Abort|CloseExState.Silent); break; } m_Stream = stream; } stream.SetSocketTimeoutOption(SocketShutdown.Both, Timeout, true); EnsureFtpWebResponse(null); // This one may update the Stream member on m_FtpWebResponse based on the CacheProtocol feedback. CheckCacheRetrieveOnResponse(); CheckCacheUpdateOnResponse(); stageMode = stream.CanRead? RequestStage.ReadReady: RequestStage.WriteReady; } else if (completedRequest) { connection = m_Connection; bool isRevalidatedOrRetried = false; if (connection != null) { EnsureFtpWebResponse(null); // This to update response status and exit message if any // Note that due to a design of FtpControlStream the status 221 "Service closing control connection" is always suppresses. m_FtpWebResponse.UpdateStatus(connection.StatusCode, connection.StatusLine, connection.ExitMessage); isRevalidatedOrRetried =!m_CacheDone && (CacheProtocol.ProtocolStatus == CacheValidationStatus.Continue || CacheProtocol.ProtocolStatus == CacheValidationStatus.RetryResponseFromServer); lock (m_SyncObject) { if(!CheckCacheRetrieveOnResponse()) continue; if (m_FtpWebResponse.IsFromCache) isRevalidatedOrRetried = false; CheckCacheUpdateOnResponse(); } } if (!isRevalidatedOrRetried) stageMode = RequestStage.ReleaseConnection; } else { throw new InternalException(); } break; } } catch (Exception exception) { SetException(exception); } finally { FinishRequestStage(stageMode); GlobalLog.Leave("FtpWebRequest#" + ValidationHelper.HashString(this) + "::AsyncRequestCallback"); } }
// // NOTE1: The caller must synchronize access to SubmitRequest(), only one call is allowed for a particular request. // NOTE2: This method eats all exceptions so the caller must rethrow them. // private void SubmitRequest(bool isAsync) { try { _async = isAsync; // // FYI: Will do 2 attempts max as per AttemptedRecovery // Stream stream; while (true) { FtpControlStream connection = _connection; if (connection == null) { if (isAsync) { CreateConnectionAsync(); return; } connection = CreateConnection(); _connection = connection; } if (!isAsync) { if (Timeout != System.Threading.Timeout.Infinite) { _remainingTimeout = Timeout - (int)((DateTime.UtcNow - _startTime).TotalMilliseconds); if (_remainingTimeout <= 0) { throw ExceptionHelper.TimeoutException; } } } if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Request being submitted"); connection.SetSocketTimeoutOption(RemainingTimeout); try { stream = TimedSubmitRequestHelper(isAsync); } catch (Exception e) { if (AttemptedRecovery(e)) { if (!isAsync) { if (Timeout != System.Threading.Timeout.Infinite) { _remainingTimeout = Timeout - (int)((DateTime.UtcNow - _startTime).TotalMilliseconds); if (_remainingTimeout <= 0) { throw; } } } continue; } throw; } // no retry needed break; } } catch (WebException webException) { // If this was a timeout, throw a timeout exception IOException ioEx = webException.InnerException as IOException; if (ioEx != null) { SocketException sEx = ioEx.InnerException as SocketException; if (sEx != null) { if (sEx.SocketErrorCode == SocketError.TimedOut) { SetException(new WebException(SR.net_timeout, WebExceptionStatus.Timeout)); } } } SetException(webException); } catch (Exception exception) { SetException(exception); } }
// // Returns a previous stage // private RequestStage FinishRequestStage(RequestStage stage) { if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"state:{stage}"); if (_exception != null) stage = RequestStage.ReleaseConnection; RequestStage prev; LazyAsyncResult writeResult; LazyAsyncResult readResult; FtpControlStream connection; lock (_syncObject) { prev = _requestStage; if (stage == RequestStage.CheckForError) return prev; if (prev == RequestStage.ReleaseConnection && stage == RequestStage.ReleaseConnection) { return RequestStage.ReleaseConnection; } if (stage > prev) _requestStage = stage; if (stage <= RequestStage.RequestStarted) return prev; writeResult = _writeAsyncResult; readResult = _readAsyncResult; connection = _connection; if (stage == RequestStage.ReleaseConnection) { if (_exception == null && !_aborted && prev != RequestStage.ReadReady && _methodInfo.IsDownload && !_ftpWebResponse.IsFromCache) { return prev; } _connection = null; } } try { // First check to see on releasing the connection if ((stage == RequestStage.ReleaseConnection || prev == RequestStage.ReleaseConnection) && connection != null) { try { if (_exception != null) { connection.Abort(_exception); } } finally { if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Releasing connection: {connection}"); connection.CloseSocket(); if (_async) if (_requestCompleteAsyncResult != null) _requestCompleteAsyncResult.InvokeCallback(); } } return prev; } finally { try { // In any case we want to signal the writer if came here if (stage >= RequestStage.WriteReady) { // If writeResult == null and this is an upload request, it means // that the user has called GetResponse() without calling // GetRequestStream() first. So they are not interested in a // stream. Therefore we close the stream so that the // request/pipeline can continue if (_methodInfo.IsUpload && !_getRequestStreamStarted) { if (_stream != null) _stream.Close(); } else if (writeResult != null && !writeResult.InternalPeekCompleted) writeResult.InvokeCallback(); } } finally { // The response is ready either with or without a stream if (stage >= RequestStage.ReadReady && readResult != null && !readResult.InternalPeekCompleted) readResult.InvokeCallback(); } } }
// // Only executed for Async requests // private void AsyncRequestCallback(object obj) { if (NetEventSource.IsEnabled) NetEventSource.Enter(this, obj); RequestStage stageMode = RequestStage.CheckForError; try { FtpControlStream connection; connection = obj as FtpControlStream; FtpDataStream stream = obj as FtpDataStream; Exception exception = obj as Exception; bool completedRequest = (obj == null); if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"stream:{stream} conn:{connection} exp:{exception} completedRequest:{completedRequest}"); while (true) { if (exception != null) { if (AttemptedRecovery(exception)) { connection = CreateConnection(); if (connection == null) return; exception = null; } if (exception != null) { SetException(exception); break; } } if (connection != null) { lock (_syncObject) { if (_aborted) { if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Releasing connect:{connection}"); connection.CloseSocket(); break; } _connection = connection; if (NetEventSource.IsEnabled) NetEventSource.Associate(this, _connection); } try { stream = (FtpDataStream)TimedSubmitRequestHelper(true); } catch (Exception e) { exception = e; continue; } return; } else if (stream != null) { lock (_syncObject) { if (_aborted) { ((ICloseEx)stream).CloseEx(CloseExState.Abort | CloseExState.Silent); break; } _stream = stream; } stream.SetSocketTimeoutOption(Timeout); EnsureFtpWebResponse(null); stageMode = stream.CanRead ? RequestStage.ReadReady : RequestStage.WriteReady; } else if (completedRequest) { connection = _connection; if (connection != null) { EnsureFtpWebResponse(null); // This to update response status and exit message if any. // Note that the status 221 "Service closing control connection" is always suppressed. _ftpWebResponse.UpdateStatus(connection.StatusCode, connection.StatusLine, connection.ExitMessage); } stageMode = RequestStage.ReleaseConnection; } else { throw new InternalException(); } break; } } catch (Exception exception) { SetException(exception); } finally { FinishRequestStage(stageMode); if (NetEventSource.IsEnabled) NetEventSource.Exit(this); } }
/// <summary> /// <para>Returns true if we should restart the request after an error</para> /// </summary> private bool AttemptedRecovery(Exception e) { if (e is OutOfMemoryException || _onceFailed || _aborted || _timedOut || _connection == null || !_connection.RecoverableFailure) { return false; } _onceFailed = true; lock (_syncObject) { if (_connection != null) { _connection.CloseSocket(); if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Releasing connection: {_connection}"); _connection = null; } else { return false; } } return true; }
private async void CreateConnectionAsync() { string hostname = _uri.Host; int port = _uri.Port; TcpClient client = new TcpClient(); object result; try { await client.ConnectAsync(hostname, port).ConfigureAwait(false); result = new FtpControlStream(client); } catch (Exception e) { result = TranslateConnectException(e); } AsyncRequestCallback(result); }
// // Only executed for Async requests // private void AsyncRequestCallback(object obj) { if (GlobalLog.IsEnabled) { GlobalLog.Enter("FtpWebRequest#" + LoggingHash.HashString(this) + "::AsyncRequestCallback", "#" + LoggingHash.HashString(obj)); } RequestStage stageMode = RequestStage.CheckForError; try { FtpControlStream connection; connection = obj as FtpControlStream; FtpDataStream stream = obj as FtpDataStream; Exception exception = obj as Exception; bool completedRequest = (obj == null); if (GlobalLog.IsEnabled) { GlobalLog.Print("AsyncRequestCallback() stream:" + LoggingHash.HashString(stream) + " conn:" + LoggingHash.HashString(connection) + " exp:" + LoggingHash.HashString(exception) + " completedRequest:" + LoggingHash.HashString(completedRequest)); } while (true) { if (exception != null) { if (AttemptedRecovery(exception)) { connection = CreateConnection(); if (connection == null) return; exception = null; } if (exception != null) { SetException(exception); break; } } if (connection != null) { lock (_syncObject) { if (_aborted) { if (NetEventSource.Log.IsEnabled()) NetEventSource.PrintInfo(NetEventSource.ComponentType.Web, this, "", string.Format("Releasing connection: {0}", LoggingHash.HashString(connection))); connection.CloseSocket(); break; } _connection = connection; if (NetEventSource.Log.IsEnabled()) NetEventSource.Associate(NetEventSource.ComponentType.Web, this, _connection); } try { stream = (FtpDataStream)TimedSubmitRequestHelper(true); } catch (Exception e) { exception = e; continue; } return; } else if (stream != null) { lock (_syncObject) { if (_aborted) { ((ICloseEx)stream).CloseEx(CloseExState.Abort | CloseExState.Silent); break; } _stream = stream; } stream.SetSocketTimeoutOption(Timeout); EnsureFtpWebResponse(null); stageMode = stream.CanRead ? RequestStage.ReadReady : RequestStage.WriteReady; } else if (completedRequest) { connection = _connection; if (connection != null) { EnsureFtpWebResponse(null); // This to update response status and exit message if any. // Note that the status 221 "Service closing control connection" is always suppressed. _ftpWebResponse.UpdateStatus(connection.StatusCode, connection.StatusLine, connection.ExitMessage); } stageMode = RequestStage.ReleaseConnection; } else { throw new InternalException(); } break; } } catch (Exception exception) { SetException(exception); } finally { FinishRequestStage(stageMode); if (GlobalLog.IsEnabled) { GlobalLog.Leave("FtpWebRequest#" + LoggingHash.HashString(this) + "::AsyncRequestCallback"); } } }
/// <summary> /// <para>Returns true if we should restart the request after an error</para> /// </summary> private bool AttemptedRecovery(Exception e) { if (e is OutOfMemoryException || _onceFailed || _aborted || _timedOut || _connection == null || !_connection.RecoverableFailure) { return false; } _onceFailed = true; lock (_syncObject) { if (_connection != null) { _connection.CloseSocket(); if (NetEventSource.Log.IsEnabled()) NetEventSource.PrintInfo(NetEventSource.ComponentType.Web, this, "", string.Format("Releasing connection: {0}", LoggingHash.HashString(_connection))); _connection = null; } else { return false; } } return true; }
private void AsyncRequestCallback(object obj) { RequestStage checkForError = RequestStage.CheckForError; try { FtpControlStream objectValue = obj as FtpControlStream; FtpDataStream stream2 = obj as FtpDataStream; Exception e = obj as Exception; bool flag = obj == null; Label_001D: if (e != null) { if (this.AttemptedRecovery(e)) { objectValue = this.QueueOrCreateConnection(); if (objectValue == null) { return; } e = null; } if (e != null) { this.SetException(e); return; } } if (objectValue != null) { lock (this.m_SyncObject) { if (this.m_Aborted) { if (Logging.On) { Logging.PrintInfo(Logging.Web, this, "", SR.GetString("net_log_releasing_connection", new object[] { ValidationHelper.HashString(objectValue) })); } this.m_ConnectionPool.PutConnection(objectValue, this, this.Timeout); return; } this.m_Connection = objectValue; if (Logging.On) { Logging.Associate(Logging.Web, this, this.m_Connection); } } try { stream2 = (FtpDataStream) this.TimedSubmitRequestHelper(true); } catch (Exception exception2) { e = exception2; goto Label_001D; } } else if (stream2 != null) { lock (this.m_SyncObject) { if (this.m_Aborted) { ((ICloseEx) stream2).CloseEx(CloseExState.Silent | CloseExState.Abort); return; } this.m_Stream = stream2; } stream2.SetSocketTimeoutOption(SocketShutdown.Both, this.Timeout, true); this.EnsureFtpWebResponse(null); this.CheckCacheRetrieveOnResponse(); this.CheckCacheUpdateOnResponse(); checkForError = stream2.CanRead ? RequestStage.ReadReady : RequestStage.WriteReady; } else { if (!flag) { throw new InternalException(); } objectValue = this.m_Connection; bool flag4 = false; if (objectValue != null) { this.EnsureFtpWebResponse(null); this.m_FtpWebResponse.UpdateStatus(objectValue.StatusCode, objectValue.StatusLine, objectValue.ExitMessage); flag4 = !this.m_CacheDone && ((base.CacheProtocol.ProtocolStatus == CacheValidationStatus.Continue) || (base.CacheProtocol.ProtocolStatus == CacheValidationStatus.RetryResponseFromServer)); lock (this.m_SyncObject) { if (!this.CheckCacheRetrieveOnResponse()) { goto Label_001D; } if (this.m_FtpWebResponse.IsFromCache) { flag4 = false; } this.CheckCacheUpdateOnResponse(); } } if (!flag4) { checkForError = RequestStage.ReleaseConnection; } } } catch (Exception exception3) { this.SetException(exception3); } finally { this.FinishRequestStage(checkForError); } }
/// <summary> /// <para>Returns true if we should restart the request after an error</para> /// </summary> private bool AttemptedRecovery(Exception e) { // The first 'if' is just checking whether the exception is thrown due to the // relogin failure which is a recoverable error if (!(e is WebException && ((WebException)e).InternalStatus == WebExceptionInternalStatus.Isolated)) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException || m_OnceFailed || m_Aborted || m_TimedOut || m_Connection==null || !m_Connection.RecoverableFailure) { return false; } m_OnceFailed = true; } lock (m_SyncObject) { if (m_ConnectionPool != null && m_Connection != null) { m_Connection.CloseSocket(); if (Logging.On) Logging.PrintInfo(Logging.Web, this, "", SR.GetString(SR.net_log_releasing_connection, ValidationHelper.HashString(m_Connection))); m_ConnectionPool.PutConnection(m_Connection, this, RemainingTimeout); m_Connection = null; } else { return false; } } return true; }
// // // private FtpControlStream QueueOrCreateConnection() { FtpControlStream connection = (FtpControlStream) m_ConnectionPool.GetConnection((object)this, (m_Async ? m_AsyncCallback : null), (m_Async ? -1: RemainingTimeout)); if (connection == null) { GlobalLog.Assert(m_Async, "QueueOrCreateConnection|m_ConnectionPool.GetConnection() returned null on a Sync Request."); return null; } lock (m_SyncObject) { if (m_Aborted) { if (Logging.On) Logging.PrintInfo(Logging.Web, this, "", SR.GetString(SR.net_log_releasing_connection, ValidationHelper.HashString(connection))); m_ConnectionPool.PutConnection(connection, this, RemainingTimeout); CheckError(); //must throw throw new InternalException(); } m_Connection = connection; if (Logging.On) Logging.Associate(Logging.Web, this, m_Connection); } return connection; }
private bool AttemptedRecovery(Exception e) { if (!(e is WebException) || (((WebException) e).InternalStatus != WebExceptionInternalStatus.Isolated)) { if ((((e is ThreadAbortException) || (e is StackOverflowException)) || ((e is OutOfMemoryException) || this.m_OnceFailed)) || ((this.m_Aborted || this.m_TimedOut) || ((this.m_Connection == null) || !this.m_Connection.RecoverableFailure))) { return false; } this.m_OnceFailed = true; } lock (this.m_SyncObject) { if ((this.m_ConnectionPool != null) && (this.m_Connection != null)) { this.m_Connection.CloseSocket(); if (Logging.On) { Logging.PrintInfo(Logging.Web, this, "", SR.GetString("net_log_releasing_connection", new object[] { ValidationHelper.HashString(this.m_Connection) })); } this.m_ConnectionPool.PutConnection(this.m_Connection, this, this.RemainingTimeout); this.m_Connection = null; } else { return false; } } return true; }
private RequestStage FinishRequestStage(RequestStage stage) { RequestStage requestStage; LazyAsyncResult writeAsyncResult; LazyAsyncResult readAsyncResult; FtpControlStream connection; RequestStage stage3; if (this.m_Exception != null) { stage = RequestStage.ReleaseConnection; } lock (this.m_SyncObject) { requestStage = this.m_RequestStage; if (stage == RequestStage.CheckForError) { return requestStage; } if ((requestStage == RequestStage.ReleaseConnection) && (stage == RequestStage.ReleaseConnection)) { return RequestStage.ReleaseConnection; } if (stage > requestStage) { this.m_RequestStage = stage; } if (stage <= RequestStage.RequestStarted) { return requestStage; } writeAsyncResult = this.m_WriteAsyncResult; readAsyncResult = this.m_ReadAsyncResult; connection = this.m_Connection; if (stage == RequestStage.ReleaseConnection) { if ((((this.m_Exception == null) && !this.m_Aborted) && ((requestStage != RequestStage.ReadReady) && this.m_MethodInfo.IsDownload)) && !this.m_FtpWebResponse.IsFromCache) { return requestStage; } if (((this.m_Exception != null) || !this.m_FtpWebResponse.IsFromCache) || this.KeepAlive) { this.m_Connection = null; } } } try { if (((stage == RequestStage.ReleaseConnection) || (requestStage == RequestStage.ReleaseConnection)) && (connection != null)) { try { if (this.m_Exception != null) { connection.Abort(this.m_Exception); } else if (this.m_FtpWebResponse.IsFromCache && !this.KeepAlive) { connection.Quit(); } } finally { if (Logging.On) { Logging.PrintInfo(Logging.Web, this, "", SR.GetString("net_log_releasing_connection", new object[] { ValidationHelper.HashString(connection) })); } this.m_ConnectionPool.PutConnection(connection, this, this.RemainingTimeout); if (this.m_Async && (this.m_RequestCompleteAsyncResult != null)) { this.m_RequestCompleteAsyncResult.InvokeCallback(); } } } stage3 = requestStage; } finally { try { if (stage >= RequestStage.WriteReady) { if (this.m_MethodInfo.IsUpload && !this.m_GetRequestStreamStarted) { if (this.m_Stream != null) { this.m_Stream.Close(); } } else if ((writeAsyncResult != null) && !writeAsyncResult.InternalPeekCompleted) { writeAsyncResult.InvokeCallback(); } } } finally { if (((stage >= RequestStage.ReadReady) && (readAsyncResult != null)) && !readAsyncResult.InternalPeekCompleted) { readAsyncResult.InvokeCallback(); } } } return stage3; }
// // Returns a previous stage // private RequestStage FinishRequestStage(RequestStage stage) { GlobalLog.Print("FtpWebRequest#" + ValidationHelper.HashString(this) + "::FinishRequestStage : stage="+stage); if (m_Exception != null) stage = RequestStage.ReleaseConnection; RequestStage prev; LazyAsyncResult writeResult; LazyAsyncResult readResult; FtpControlStream connection; lock (m_SyncObject) { prev = m_RequestStage; if (stage == RequestStage.CheckForError) return prev; if (prev == RequestStage.ReleaseConnection && stage == RequestStage.ReleaseConnection) { return RequestStage.ReleaseConnection; } if (stage > prev) m_RequestStage = stage; if (stage <= RequestStage.RequestStarted) return prev; writeResult = m_WriteAsyncResult; readResult = m_ReadAsyncResult; connection = m_Connection; if (stage == RequestStage.ReleaseConnection) { if (m_Exception == null && !m_Aborted && prev != RequestStage.ReadReady && this.m_MethodInfo.IsDownload && !m_FtpWebResponse.IsFromCache) { return prev; } if (m_Exception != null || !(m_FtpWebResponse.IsFromCache && !KeepAlive)) m_Connection = null; } } try { // First check to see on releasing the connection if ((stage == RequestStage.ReleaseConnection || prev == RequestStage.ReleaseConnection) && connection != null) { try { if (m_Exception != null) { connection.Abort(m_Exception); } else if (m_FtpWebResponse.IsFromCache && !KeepAlive) { // This means the response has been revalidated and found as good means the commands pipleline is completed. // Now if this request was NOT KeepAlive we want to be fair and close the control connection. // That becomes unnecessary complicated in the async case to support "QUIT" command semantic, so simply close the socket // and let pool collect the object. connection.Quit(); } } finally { if (Logging.On) Logging.PrintInfo(Logging.Web, this, "", SR.GetString(SR.net_log_releasing_connection, ValidationHelper.HashString(connection))); m_ConnectionPool.PutConnection(connection, this, RemainingTimeout); if (m_Async) if (m_RequestCompleteAsyncResult != null) m_RequestCompleteAsyncResult.InvokeCallback(); } } return prev; } finally { try { // In any case we want to signal the writer if came here if (stage >= RequestStage.WriteReady) { // If writeResult == null and this is an upload request, it means // that the user has called GetResponse() without calling // GetRequestStream() first. So they are not interested in a // stream. Therefore we close the stream so that the // request/pipeline can continue if (m_MethodInfo.IsUpload && !m_GetRequestStreamStarted) { if (m_Stream != null) m_Stream.Close(); } else if (writeResult != null && !writeResult.InternalPeekCompleted) writeResult.InvokeCallback(); } } finally { // The response is ready either with or without a stream if (stage >= RequestStage.ReadReady && readResult != null && !readResult.InternalPeekCompleted) readResult.InvokeCallback(); } } }
private FtpControlStream QueueOrCreateConnection() { FtpControlStream objectValue = (FtpControlStream) this.m_ConnectionPool.GetConnection(this, this.m_Async ? m_AsyncCallback : null, this.m_Async ? -1 : this.RemainingTimeout); if (objectValue == null) { return null; } lock (this.m_SyncObject) { if (this.m_Aborted) { if (Logging.On) { Logging.PrintInfo(Logging.Web, this, "", SR.GetString("net_log_releasing_connection", new object[] { ValidationHelper.HashString(objectValue) })); } this.m_ConnectionPool.PutConnection(objectValue, this, this.RemainingTimeout); this.CheckError(); throw new InternalException(); } this.m_Connection = objectValue; if (Logging.On) { Logging.Associate(Logging.Web, this, this.m_Connection); } } return objectValue; }