private bool DrainSocket() {
GlobalLog.Enter("ConnectStream::DrainSocket");
GlobalLog.ThreadContract(ThreadKinds.Unknown, "ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket");
if (IgnoreSocketErrors)
{
GlobalLog.Leave("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() IgnoreSocketErrors == true, stream is dead.", true);
return true;
}
//
// If its not chunked and we have a read buffer, don't waste time coping the data
// around againg, just pretend its gone, i.exception. make it die
//
long ReadBytes = m_ReadBytes;
if (!m_Chunked) {
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() m_ReadBytes:" + m_ReadBytes.ToString() + " m_ReadBufferSize:" + m_ReadBufferSize.ToString());
if (m_ReadBufferSize != 0) {
//
// There's stuff in our read buffer.
// Update our internal read buffer state with what we took.
//
m_ReadOffset += m_ReadBufferSize;
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() m_ReadBytes:" + m_ReadBytes.ToString() + " m_ReadOffset:" + m_ReadOffset.ToString());
if (m_ReadBytes != -1) {
m_ReadBytes -= m_ReadBufferSize;
GlobalLog.Print("m_ReadBytes = "+m_ReadBytes);
// error handling, we shouldn't hang here if trying to drain, and there
// is a mismatch with Content-Length and actual bytes.
//
// Note: I've seen this often happen with some sites where they return 204
// in violation of HTTP/1.1 with a Content-Length > 0
if (m_ReadBytes < 0) {
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() m_ReadBytes:" + m_ReadBytes.ToString() + " incorrect Content-Length? setting m_ReadBytes to 0 and returning false.");
m_ReadBytes = 0;
GlobalLog.Leave("ConnectStream::DrainSocket", false);
return false;
}
}
m_ReadBufferSize = 0;
// If the read buffer size has gone to 0, null out our pointer
// to it so maybe it'll be garbage-collected faster.
m_ReadBuffer = null;
}
// exit out of drain Socket when there is no connection-length,
// it doesn't make sense to drain a possible empty socket,
// when we're just going to close it.
if (ReadBytes == -1) {
GlobalLog.Leave("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() ReadBytes==-1, returning true");
return true;
}
}
//
// in error or Eof, we may be in a weird state
// so we need return if we as if we don't have any more
// space to read, note Eof is true when there is an error
//
if (this.Eof) {
GlobalLog.Leave("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() Eof, returning true");
return true;
}
//
// If we're draining more than 64K, then we should
// just close the socket, since it would be costly to
// do this.
//
if (m_ReadBytes > c_MaxDrainBytes) {
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() m_ReadBytes:" + m_ReadBytes.ToString() + " too large, Closing the Connection");
m_Connection.AbortSocket(false);
GlobalLog.Leave("ConnectStream::DrainSocket", true);
return true;
}
//
// Now drain the socket the old, slow way by reading or pasing Chunked stuff
//
m_Draining = true;
int bytesRead;
for (;;) {
try {
bytesRead = ReadWithoutValidation(s_DrainingBuffer, 0, s_DrainingBuffer.Length, false);
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::DrainSocket() drained bytesRead:" + bytesRead.ToString() + " bytes");
if (bytesRead<=0) {
break;
}
}
catch (Exception exception) {
if (NclUtilities.IsFatal(exception)) throw;
GlobalLog.Print("exception" + exception.ToString());
bytesRead = -1;
break;
}
}
GlobalLog.Leave("ConnectStream::DrainSocket", true);
return bytesRead > 0;
}