// // called by HttpWebRequest if AllowWriteStreamBuffering is true on that instance // internal void EnableWriteBuffering() { GlobalLog.Assert(WriteStream, "ConnectStream#{0}::EnableWriteBuffering()|!WriteStream", ValidationHelper.HashString(this)); if (BufferedData==null) { // create stream on demand, only if needed GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::EnableWriteBuffering() Write() creating ScatterGatherBuffers WriteChunked:" + WriteChunked.ToString() + " BytesLeftToWrite:" + BytesLeftToWrite.ToString()); if (WriteChunked) { BufferedData = new ScatterGatherBuffers(); } else { BufferedData = new ScatterGatherBuffers(BytesLeftToWrite); } } }
internal void Write(ScatterGatherBuffers writeBuffer) { BufferOffsetSize[] buffers = writeBuffer.GetBuffers(); if (buffers != null) { base.MultipleWrite(buffers); } }
// This method is called by ConnectStream, only when resubmitting // We have sent the headers already in HttpWebRequest.EndSubmitRequest() // which calls ConnectStream.WriteHeaders() which calls to HttpWebRequest.EndWriteHeaders() // which calls ConnectStream.ResubmitWrite() which calls in here internal void Write(ScatterGatherBuffers writeBuffer) { GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::Write(ScatterGatherBuffers) networkstream#" + ValidationHelper.HashString(NetworkStream)); // // parameter validation // GlobalLog.Assert(writeBuffer != null, "Connection#{0}::Write(ScatterGatherBuffers)|writeBuffer == null", ValidationHelper.HashString(this)); // // set up array for MultipleWrite call // note that GetBuffers returns null if we never wrote to it. // BufferOffsetSize[] buffers = writeBuffer.GetBuffers(); if (buffers!=null) { // // This will block writing the buffers out. // MultipleWrite(buffers); } GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::Write(ScatterGatherBuffers) this:" + ValidationHelper.HashString(this) + " writeBuffer.Size:" + writeBuffer.Length.ToString()); }
internal void WriteStartNextRequest(ScatterGatherBuffers writeBuffer, ref ConnectionReturnResult returnResult) { GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::WriteStartNextRequest"); // // If we've been buffering, data in order to determina // data size length for eing/Put, then now at this // point do the actual upload // if (writeBuffer!=null) { try { // // Upload entity body data that has been buffered now // Write(writeBuffer); } catch (Exception exception) { GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::WriteStartNextRequest(ScatterGatherBuffers) caught Exception:" + exception.Message); m_Error = WebExceptionStatus.SendFailure; } } Monitor.Enter(this); GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::WriteStartNextRequest() setting m_WriteDone:" + m_WriteDone.ToString() + " to true"); m_WriteDone = true; HttpWebRequest NextRequest = null; // // If we're not doing keep alive, and the read on this connection // has already completed, now is the time to close the // connection. // if (!m_KeepAlive || m_Error != WebExceptionStatus.Success) { GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::WriteStartNextRequest() _WriteList (size) " + m_WriteList.Count.ToString() + " - cnt#" + ValidationHelper.HashString(this)); if (m_ReadDone) { // We could be closing because of an unexpected keep-alive // failure, ie we pipelined a few requests and in the middle // the remote server stopped doing keep alive. In this // case m_Error could be success, which would be misleading. // So in that case we'll set it to connection closed. if (m_Error == WebExceptionStatus.Success) { // Only reason we could have gotten here is because // we're not keeping the connection alive. GlobalLog.Assert(!m_KeepAlive, "WriteStartNextRequest: m_KeepAlive is true", "Closing connection with both keepalive true and m_Error == success" ); m_Error = WebExceptionStatus.KeepAliveFailure; } // CloseConnectionSocket is called with the critical section // held. Note that we know since it's not a keep-alive // connection the read half wouldn't have posted a receive // for this connection, so it's OK to call // CloseConnectionSocket now. CloseConnectionSocket(m_Error, ref returnResult); } else { if (m_Error!=WebExceptionStatus.Success) { GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::WriteStartNextRequest() Send Failire"); } Monitor.Exit(this); } GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::WriteStartNextRequest[2]"); return; } // If we're pipelining, we get get the next request going // as soon as the write is done. Otherwise we have to wait // until both read and write are done. if (m_Pipelining || m_ReadDone) { NextRequest = CheckNextRequest(); } if (NextRequest != null) { // need to disable read done, since we're about to post // another read callback, and add a request if (m_WriteList.Count == 0) { m_ReadDone = false; } StartRequest(NextRequest, false); } else { Monitor.Exit(this); } GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::WriteStartNextRequest"); }
// // this API is called by ConnectStream, only when resubmitting // so we sent the headers already in HttpWebRequest.EndSubmitRequest() // which calls ConnectStream.WriteHeaders() // only after it queues async call to HttpWebRequest.EndWriteHeaders() // which calls ConnectStream.ResubmitWrite() // which calls in here // internal void Write(ScatterGatherBuffers writeBuffer) { // // parameter validation // GlobalLog.Assert( writeBuffer!=null, "writeBuffer==null", "Connection.Write(ScatterGatherBuffers) - failed internal parameter validation" ); GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::Write(ScatterGatherBuffers) cnt#" + ValidationHelper.HashString(this) + "trns#" + ValidationHelper.HashString(Transport)); NetworkStream chkTransport = Transport; if (chkTransport==null) { Exception exception = new IOException(SR.GetString(SR.net_io_writefailure)); GlobalLog.LeaveException("Connection#" + ValidationHelper.HashString(this) + "::Write(ScatterGatherBuffers)", exception); throw exception; } try { // // set up array for MultipleWrite call // note that GetBuffers returns null if we never wrote to it. // BufferOffsetSize[] buffers = writeBuffer.GetBuffers(); if (buffers!=null) { // // when buffering this write will happend on a worker thread, so for async // operating apps, this will not block // IAsyncResult asyncResult = chkTransport.BeginMultipleWrite(buffers, null, null); chkTransport.EndMultipleWrite(asyncResult); } } catch (Exception exception) { m_Error = WebExceptionStatus.SendFailure; GlobalLog.LeaveException("Connection#" + ValidationHelper.HashString(this) + "::Write(ScatterGatherBuffers)", exception); throw; } GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::Write(ScatterGatherBuffers) this:" + ValidationHelper.HashString(this) + " writeBuffer.Size:" + writeBuffer.Length.ToString()); }
// // called by HttpWebRequest if AllowWriteStreamBuffering is true on that instance // internal void EnableWriteBuffering() { if (m_WriteStream && BufferedData==null) { // // create stream on demand, only if needed // GlobalLog.Print("ConnectStream#" + ValidationHelper.HashString(this) + "::WriteBufferEnable_set() Write() creating ScatterGatherBuffers"); BufferedData = new ScatterGatherBuffers(); } m_WriteBufferEnable = true; }
internal int SetResponse(WebResponse response) { ContentLength = response.ContentLength; if (ContentLength == -1 || ContentLength > DefaultDownloadBufferLength) { Length = DefaultDownloadBufferLength; // Read buffer length } else { Length = ContentLength; // Read buffer length } // If we are not writing to a stream, we are accumulating in memory if (WriteStream == null) { // We are putting a cap on the size we will accumulate in memory if (ContentLength > Int32.MaxValue) { throw new WebException(SR.GetString(SR.net_webstatus_MessageLengthLimitExceeded), WebExceptionStatus.MessageLengthLimitExceeded); } SgBuffers = new ScatterGatherBuffers(Length); // Write buffer } InnerBuffer = new byte[(int)Length]; ReadStream = response.GetResponseStream(); if (Async && response.ContentLength >= 0) Progress.TotalBytesToReceive = response.ContentLength; if (Async) { if (ReadStream == null || ReadStream == Stream.Null) DownloadBitsReadCallbackState(this, null); else ReadStream.BeginRead(InnerBuffer, Offset, (int)Length-Offset, new AsyncCallback(DownloadBitsReadCallback), this); } else { if (ReadStream == null || ReadStream == Stream.Null) return 0; else return ReadStream.Read(InnerBuffer, Offset, (int)Length-Offset); } return -1; }
internal int SetResponse(WebResponse response) { this.ContentLength = response.ContentLength; if ((this.ContentLength == -1L) || (this.ContentLength > 0x10000L)) { this.Length = 0x10000L; } else { this.Length = this.ContentLength; } if (this.WriteStream == null) { if (this.ContentLength > 0x7fffffffL) { throw new WebException(SR.GetString("net_webstatus_MessageLengthLimitExceeded"), WebExceptionStatus.MessageLengthLimitExceeded); } this.SgBuffers = new ScatterGatherBuffers(this.Length); } this.InnerBuffer = new byte[(int) this.Length]; this.ReadStream = response.GetResponseStream(); if (this.Async && (response.ContentLength >= 0L)) { this.Progress.TotalBytesToReceive = response.ContentLength; } if (this.Async) { if ((this.ReadStream == null) || (this.ReadStream == Stream.Null)) { System.Net.WebClient.DownloadBitsReadCallbackState(this, null); } else { this.ReadStream.BeginRead(this.InnerBuffer, this.Offset, ((int) this.Length) - this.Offset, new AsyncCallback(System.Net.WebClient.DownloadBitsReadCallback), this); } return -1; } if ((this.ReadStream != null) && (this.ReadStream != Stream.Null)) { return this.ReadStream.Read(this.InnerBuffer, this.Offset, ((int) this.Length) - this.Offset); } return 0; }