internal void ResubmitWrite(ConnectStream oldStream, bool suppressWrite) {
GlobalLog.Enter("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite", ValidationHelper.HashString(oldStream));
GlobalLog.ThreadContract(ThreadKinds.Sync, "ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite");
//
//
try {
Interlocked.CompareExchange(ref m_CallNesting, Nesting.InternalIO, Nesting.Idle);
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite() Inc: " + m_CallNesting.ToString());
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite(), callNesting : " + m_CallNesting.ToString() + " IsClosed = " + IsClosed);
//
// no need to buffer here:
// we're already resubmitting buffered data give it to the connection to put it on the wire again
// we set BytesLeftToWrite to 0 'cause even on failure there can be no recovery,
// so just leave it to IOError() to clean up and don't call ResubmitWrite()
//
ScatterGatherBuffers bufferedData = oldStream.BufferedData;
SafeSetSocketTimeout(SocketShutdown.Send);
if (!WriteChunked) {
if (!suppressWrite)
m_Connection.Write(bufferedData);
}
else {
// we have the data buffered, but we still want to chunk.
// first set this to disable Close() from sending a chunk terminator.
GlobalLog.Assert(m_HttpWriteMode != HttpWriteMode.None, "ConnectStream#{0}::ResubmitWrite()|m_HttpWriteMode == HttpWriteMode.None", ValidationHelper.HashString(this));
m_HttpWriteMode = HttpWriteMode.ContentLength;
if (bufferedData.Length==0) {
m_Connection.Write(NclConstants.ChunkTerminator, 0, NclConstants.ChunkTerminator.Length);
}
else {
int chunkHeaderOffset = 0;
byte[] chunkHeaderBuffer = GetChunkHeader(bufferedData.Length, out chunkHeaderOffset);
BufferOffsetSize[] dataBuffers = bufferedData.GetBuffers();
BufferOffsetSize[] buffers = new BufferOffsetSize[dataBuffers.Length + 3];
buffers[0] = new BufferOffsetSize(chunkHeaderBuffer, chunkHeaderOffset, chunkHeaderBuffer.Length - chunkHeaderOffset, false);
int index = 0;
foreach (BufferOffsetSize buffer in dataBuffers) {
buffers[++index] = buffer;
}
buffers[++index] = new BufferOffsetSize(NclConstants.CRLF, 0, NclConstants.CRLF.Length, false);
buffers[++index] = new BufferOffsetSize(NclConstants.ChunkTerminator, 0, NclConstants.ChunkTerminator.Length, false);
SplitWritesState splitState = new SplitWritesState(buffers);
BufferOffsetSize[] sendBuffers = splitState.GetNextBuffers();
while(sendBuffers != null){
m_Connection.MultipleWrite(sendBuffers);
sendBuffers = splitState.GetNextBuffers();
}
}
}
if(Logging.On && bufferedData.GetBuffers() != null) {
foreach (BufferOffsetSize bufferOffsetSize in bufferedData.GetBuffers()) {
if (bufferOffsetSize == null) {
Logging.Dump(Logging.Web, this, "ResubmitWrite", null, 0, 0);
}
else {
Logging.Dump(Logging.Web, this, "ResubmitWrite", bufferOffsetSize.Buffer, bufferOffsetSize.Offset, bufferOffsetSize.Size);
}
}
}
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite() sent:" + bufferedData.Length.ToString() );
}
catch (Exception exception)
{
if (NclUtilities.IsFatal(exception)) throw;
// A Fatal error
WebException we = new WebException(NetRes.GetWebStatusString("net_connclosed", WebExceptionStatus.SendFailure),
WebExceptionStatus.SendFailure,
WebExceptionInternalStatus.RequestFatal,
exception);
IOError(we, false);
}
finally {
Interlocked.CompareExchange(ref m_CallNesting, Nesting.Idle, Nesting.InternalIO);
GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite(), callNesting : " + m_CallNesting.ToString() + " IsClosed = " + IsClosed);
}
m_BytesLeftToWrite = 0;
CallDone();
GlobalLog.Leave("ConnectStream#" + ValidationHelper.HashString(this) + "::ResubmitWrite", BytesLeftToWrite.ToString());
}