private void PrepareCloseConnectionSocket(ref ConnectionReturnResult returnResult)
{
GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::PrepareCloseConnectionSocket", m_Error.ToString());
// Effectivelly, closing a connection makes it exempted from the "Idling" logic
m_IdleSinceUtc = DateTime.MinValue;
CanBePooled = false;
if (m_WriteList.Count != 0 || m_WaitList.Count != 0)
{
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::PrepareCloseConnectionSocket() m_WriteList.Count:" + m_WriteList.Count);
DebugDumpArrayListEntries(m_WriteList,"WriteList");
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::PrepareCloseConnectionSocket() m_WaitList.Count:" + m_WaitList.Count);
DebugDumpArrayListEntries(m_WaitList,"WaitList");
HttpWebRequest lockedRequest = LockedRequest;
if (lockedRequest != null)
{
bool callUnlockRequest = false;
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::PrepareCloseConnectionSocket() looking for HttpWebRequest#" + ValidationHelper.HashString(lockedRequest));
foreach (HttpWebRequest request in m_WriteList)
{
if (request == lockedRequest) {
callUnlockRequest = true;
}
}
if (!callUnlockRequest) {
foreach (HttpWebRequest request in m_WaitList) {
if (request == lockedRequest) {
callUnlockRequest = true;
break;
}
}
}
if (callUnlockRequest) {
UnlockRequest();
}
}
HttpWebRequest[] requestArray = null;
// WaitList gets Isolated exception status, free to retry multiple times
if (m_WaitList.Count != 0)
{
requestArray = new HttpWebRequest[m_WaitList.Count];
m_WaitList.CopyTo(requestArray, 0);
ConnectionReturnResult.AddExceptionRange(ref returnResult, requestArray, ExceptionHelper.IsolatedException);
}
//
// WriteList (except for single request list) gets Recoverable exception status, may be retired if not failed once
// For a single request list the exception is computed here
// InnerExeption if any may tell more details in both cases
//
if (m_WriteList.Count != 0)
{
Exception theException = m_InnerException;
if(theException != null)
GlobalLog.Print(theException.ToString());
GlobalLog.Print("m_Error = "+ m_Error.ToString());
if (!(theException is WebException) && !(theException is SecurityException))
{
if (m_Error == WebExceptionStatus.ServerProtocolViolation)
{
string errorString = NetRes.GetWebStatusString(m_Error);
string detailedInfo = "";
if (m_ParseError.Section != WebParseErrorSection.Generic)
detailedInfo += " Section=" + m_ParseError.Section.ToString();
if (m_ParseError.Code != WebParseErrorCode.Generic) {
detailedInfo += " Detail=" + SR.GetString("net_WebResponseParseError_" + m_ParseError.Code.ToString());
}
if (detailedInfo.Length != 0)
errorString += "." + detailedInfo;
theException = new WebException(errorString,
theException,
m_Error,
null,
WebExceptionInternalStatus.RequestFatal);
}
else if (m_Error == WebExceptionStatus.SecureChannelFailure)
{
theException = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.SecureChannelFailure),
WebExceptionStatus.SecureChannelFailure);
}
else if (m_Error == WebExceptionStatus.Timeout)
{
theException = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.Timeout),
WebExceptionStatus.Timeout);
}
else if(m_Error == WebExceptionStatus.RequestCanceled)
{
theException = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled),
WebExceptionStatus.RequestCanceled,
WebExceptionInternalStatus.RequestFatal,
theException);
}
else if(m_Error == WebExceptionStatus.MessageLengthLimitExceeded ||
m_Error == WebExceptionStatus.TrustFailure)
{
theException = new WebException(NetRes.GetWebStatusString("net_connclosed", m_Error),
m_Error,
WebExceptionInternalStatus.RequestFatal,
theException);
}
else
{
if (m_Error == WebExceptionStatus.Success)
{
throw new InternalException();
}
bool retry = false;
bool isolatedKeepAliveFailure = false;
if (m_WriteList.Count != 1)
{
// Real scenario: SSL against IIS-5 would fail if pipelinning.
// retry = true will cover a general case when >>the server<< aborts a pipeline
// Basically all pipelined requests are marked with recoverable error including the very active request.
retry = true;
}
else if (m_Error == WebExceptionStatus.KeepAliveFailure)
{
HttpWebRequest request = (HttpWebRequest) m_WriteList[0];
// Check that the active request did not start the body yet
if (!request.BodyStarted)
isolatedKeepAliveFailure = true;
}
else{
retry = (!AtLeastOneResponseReceived && !((HttpWebRequest) m_WriteList[0]).BodyStarted);
}
theException = new WebException(NetRes.GetWebStatusString("net_connclosed", m_Error),
m_Error,
(isolatedKeepAliveFailure? WebExceptionInternalStatus.Isolated:
retry? WebExceptionInternalStatus.Recoverable:
WebExceptionInternalStatus.RequestFatal),
theException);
}
}
WebException pipelineException = new WebException(NetRes.GetWebStatusString("net_connclosed", WebExceptionStatus.PipelineFailure),
WebExceptionStatus.PipelineFailure,
WebExceptionInternalStatus.Recoverable,
theException);
requestArray = new HttpWebRequest[m_WriteList.Count];
m_WriteList.CopyTo(requestArray, 0);
ConnectionReturnResult.AddExceptionRange(ref returnResult, requestArray, pipelineException, theException);
}
m_WriteList.Clear();
m_WaitList.Clear();
}
CheckIdle();
if (m_Idle)
{
GC.SuppressFinalize(this);
}
if (!m_RemovedFromConnectionList && ConnectionGroup != null)
{
m_RemovedFromConnectionList = true;
ConnectionGroup.Disassociate(this);
}
GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::PrepareCloseConnectionSocket");
}