internal void SyncRead(HttpWebRequest request, bool userRetrievedStream, bool probeRead)
{
GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::SyncRead(byte[]) request#" + ValidationHelper.HashString(request) + (probeRead? ", Probe read = TRUE":string.Empty));
GlobalLog.ThreadContract(ThreadKinds.Sync, "Connection#" + ValidationHelper.HashString(this) + "::SyncRead");
// prevent recursive calls to this function
if (t_SyncReadNesting > 0) {
GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() - nesting");
return;
}
bool pollSuccess = probeRead? false: true;
try {
t_SyncReadNesting++;
// grab a counter to tell us whenever the SetRequestContinue is called
int requestContinueCount = probeRead ? request.RequestContinueCount : 0;
bool requestDone;
int bytesRead = -1;
WebExceptionStatus errorStatus = WebExceptionStatus.ReceiveFailure;
//Ensures that we'll timeout eventually on an appdomain unload.
//Will be a no-op if the timeout doesn't change from request to request.
ReadTimeout = request.Timeout;
if (m_BytesScanned < m_BytesRead)
{
// left over from previous read
pollSuccess = true;
bytesRead = 0; //tell it we want to use buffered data on the first iteration
errorStatus = WebExceptionStatus.Success;
}
do {
requestDone = true;
try {
if (bytesRead != 0)
{
errorStatus = WebExceptionStatus.ReceiveFailure;
if (!pollSuccess)
{
pollSuccess = Poll(HttpWebRequest.DefaultContinueTimeout * 1000, SelectMode.SelectRead); // Timeout is in microseconds
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() PollSuccess : " + pollSuccess);
}
if (pollSuccess)
{
bytesRead = Read(m_ReadBuffer, m_BytesRead, m_ReadBuffer.Length - m_BytesRead);
errorStatus = WebExceptionStatus.Success;
if (bytesRead == 0)
bytesRead = -1; // 0 is reserved for re-entry on already buffered data
}
}
}
catch (Exception exception)
{
if (NclUtilities.IsFatal(exception)) throw;
if (m_InnerException == null)
m_InnerException = exception;
if (exception.GetType() == typeof(ObjectDisposedException))
errorStatus = WebExceptionStatus.RequestCanceled;
// need to handle SSL errors too
else
{
SocketException socketException = exception.InnerException as SocketException;
if (socketException != null)
{
if (socketException.ErrorCode == (int) SocketError.TimedOut)
errorStatus = WebExceptionStatus.Timeout;
else
errorStatus = WebExceptionStatus.ReceiveFailure;
}
}
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() Read() threw errorStatus:" + errorStatus.ToString() + " bytesRead:" + bytesRead.ToString());
}
catch
{
if (m_InnerException == null)
m_InnerException = new Exception(SR.GetString(SR.net_nonClsCompliantException));
// need to handle SSL errors too
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() Read() threw errorStatus:" + errorStatus.ToString() + " bytesRead:" + bytesRead.ToString());
}
if (pollSuccess)
requestDone = ReadComplete(bytesRead, errorStatus);
bytesRead = -1;
} while (!requestDone && (userRetrievedStream || requestContinueCount == request.RequestContinueCount));
}
finally {
t_SyncReadNesting--;
}
if (probeRead)
{
if (pollSuccess)
{
if (!request.Saw100Continue && !userRetrievedStream)
{
//During polling, we got a response that wasn't a 100 continue.
request.SawInitialResponse = true;
}
}
else
{
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SyncRead() Poll has timed out, calling SetRequestContinue().");
request.SetRequestContinue();
}
}
GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SyncRead()");
}