private void BufferData(byte[] data, int offset, int size, bool needToCopyData) { int n; // try last buffer if (_lastBuffer != null) { n = _lastBuffer.Append(data, offset, size); size -= n; offset += n; } else if (!needToCopyData && offset == 0 && !_responseBufferingOn) { // when not buffering, there is no need for big buffer accumulating multiple writes // the byte[] data can be sent as is _buffers.Add(new HttpResponseBufferElement(data, size)); return; } // do other buffers if needed while (size > 0) { _lastBuffer = new HttpResponseBufferElement(); _buffers.Add(_lastBuffer); n = _lastBuffer.Append(data, offset, size); offset += n; size -= n; } }
// // Buffer management // internal void ClearBuffers() { ClearCharBuffer(); _buffers = new ArrayList(); _lastBuffer = null; }
private void BufferResource(IntPtr data, int offset, int size) { if (size > BufferingParams.MAX_RESOURCE_BYTES_TO_COPY || !_responseBufferingOn) { // for long response strings create its own buffer element to avoid copy cost // also, when not buffering, no need for an extra copy (nothing will get accumulated anyway) _lastBuffer = null; _buffers.Add(new HttpResourceResponseElement(data, offset, size)); return; } int n; // try last buffer if (_lastBuffer != null) { n = _lastBuffer.Append(data, offset, size); size -= n; offset += n; } // do other buffers if needed while (size > 0) { _lastBuffer = new HttpResponseBufferElement(); _buffers.Add(_lastBuffer); n = _lastBuffer.Append(data, offset, size); offset += n; size -= n; } }
internal void Filter(bool finalFiltering) { // no filter? if (_installedFilter == null) { return; } // flush char buffer and remember old buffers if (_charBufferLength != _charBufferFree) { FlushCharBuffer(true); } _lastBuffer = null; // no content to filter if (_buffers.Count == 0) { return; } // remember old buffers ArrayList oldBuffers = _buffers; _buffers = new ArrayList(); // push old buffer list through the filter Debug.Assert(_filterSink != null); _filterSink.Filtering = true; try { int n = oldBuffers.Count; for (int i = 0; i < n; i++) { IHttpResponseElement buf = (IHttpResponseElement)oldBuffers[i]; int len = buf.GetSize(); if (len > 0) { _installedFilter.Write(buf.GetBytes(), 0, len); } } _installedFilter.Flush(); if (finalFiltering) { _installedFilter.Close(); } } finally { _filterSink.Filtering = false; } }
private static CachedRawResponse Convert(OutputCacheEntry oce) { ArrayList headers = null; if ((oce.HeaderElements != null) && (oce.HeaderElements.Count > 0)) { headers = new ArrayList(oce.HeaderElements.Count); for (int i = 0; i < oce.HeaderElements.Count; i++) { HttpResponseHeader header = new HttpResponseHeader(oce.HeaderElements[i].Name, oce.HeaderElements[i].Value); headers.Add(header); } } ArrayList buffers = null; if ((oce.ResponseElements != null) && (oce.ResponseElements.Count > 0)) { buffers = new ArrayList(oce.ResponseElements.Count); for (int j = 0; j < oce.ResponseElements.Count; j++) { ResponseElement element = oce.ResponseElements[j]; IHttpResponseElement element2 = null; if (element is FileResponseElement) { HttpContext current = HttpContext.Current; HttpWorkerRequest request = (current != null) ? current.WorkerRequest : null; bool supportsLongTransmitFile = (request != null) && request.SupportsLongTransmitFile; bool isImpersonating = ((current != null) && current.IsClientImpersonationConfigured) || HttpRuntime.IsOnUNCShareInternal; FileResponseElement element3 = (FileResponseElement) element; element2 = new HttpFileResponseElement(element3.Path, element3.Offset, element3.Length, isImpersonating, supportsLongTransmitFile); } else if (element is MemoryResponseElement) { MemoryResponseElement element4 = (MemoryResponseElement) element; int size = System.Convert.ToInt32(element4.Length); element2 = new HttpResponseBufferElement(element4.Buffer, size); } else { if (!(element is SubstitutionResponseElement)) { throw new NotSupportedException(); } SubstitutionResponseElement element5 = (SubstitutionResponseElement) element; element2 = new HttpSubstBlockResponseElement(element5.Callback); } buffers.Add(element2); } } else { buffers = new ArrayList(); } return new CachedRawResponse(new HttpRawResponse(oce.StatusCode, oce.StatusDescription, headers, buffers, false), oce.Settings, oce.KernelCacheUrl, oce.CachedVaryId); }
internal void WriteFile(IntPtr fileHandle, long offset, long size) { if (_charBufferLength != _charBufferFree) { FlushCharBuffer(true); } _lastBuffer = null; _buffers.Add(new HttpFileResponseElement(fileHandle, offset, size)); if (!_responseBufferingOn) { _response.Flush(); } }
internal HttpWriter(HttpResponse response) { _response = response; _stream = new HttpResponseStream(this); _buffers = new ArrayList(); _lastBuffer = null; _charBuffer = (char[])s_Allocator.GetBuffer(); _charBufferLength = _charBuffer.Length; _charBufferFree = _charBufferLength; UpdateResponseBuffering(); UpdateResponseEncoding(); }
private void FlushCharBuffer(bool flushEncoder) { int numChars = _charBufferLength - _charBufferFree; Debug.Assert(numChars > 0); // remember that response required encoding (to indicate the charset= is needed) _responseEncodingUsed = true; // estimate conversion size int estByteSize = _responseEncoding.GetMaxByteCount(numChars); int realByteSize; if (estByteSize <= BufferingParams.MAX_BYTES_TO_COPY || !_responseBufferingOn) { // small size -- allocate intermediate buffer and copy into the output buffer byte[] byteBuffer = new byte[estByteSize]; realByteSize = _responseEncoder.GetBytes(_charBuffer, 0, numChars, byteBuffer, 0, flushEncoder); BufferData(byteBuffer, 0, realByteSize, false); } else { // convert right into the output buffer int free = (_lastBuffer != null) ? _lastBuffer.FreeBytes : 0; if (free < estByteSize) { // need new buffer -- last one doesn't have enough space _lastBuffer = new HttpResponseBufferElement(); _buffers.Add(_lastBuffer); free = _lastBuffer.FreeBytes; } // byte buffers must be long enough to keep everything in char buffer Debug.Assert(free >= estByteSize); realByteSize = _responseEncoder.GetBytes(_charBuffer, 0, numChars, _lastBuffer.ByteBuffer, _lastBuffer.ByteOffset, flushEncoder); _lastBuffer.FreeBytes = free - realByteSize; } _charBufferFree = _charBufferLength; }
// // Snapshot for caching // internal ArrayList GetSnapshot(out bool hasSubstBlocks) { if (_charBufferLength != _charBufferFree) { FlushCharBuffer(true); } _lastBuffer = null; // to make sure nothing gets appended after hasSubstBlocks = false; ArrayList buffers = new ArrayList(); // copy buffer references to the returned list, make non-recyclable int n = _buffers.Count; for (int i = 0; i < n; i++) { Object responseElement = _buffers[i]; HttpResponseBufferElement buffer = responseElement as HttpResponseBufferElement; if (buffer != null) { if (buffer.FreeBytes > BufferingParams.MAX_FREE_BYTES_TO_CACHE) { // copy data if too much is free responseElement = buffer.Clone(); } else { // cache the buffer as is with free bytes buffer.DisableRecycling(); } } else if (responseElement is HttpSubstBlockResponseElement) { hasSubstBlocks = true; } buffers.Add(responseElement); } return(buffers); }
// // Support for substitution blocks // internal void WriteSubstBlock(String name, String defaultValue) { if (_charBufferLength != _charBufferFree) { FlushCharBuffer(true); } _lastBuffer = null; // convert filler to byte array bytes int numChars = defaultValue.Length; int maxNumBytes = _responseEncoding.GetMaxByteCount(numChars); byte[] fillerBytes = new byte[maxNumBytes]; int numBytes = _responseEncoder.GetBytes(defaultValue.ToCharArray(), 0, numChars, fillerBytes, 0, true); // add new substitution block to the buffer list _buffers.Add(new HttpSubstBlockResponseElement(name, fillerBytes, numBytes)); }
internal void MakeSubstitution(String name, String value, bool canChangeSize) { // find the block by name int i = FindSubstitutionBlock(name); if (i < 0) { return; } HttpSubstBlockResponseElement block = (HttpSubstBlockResponseElement)_buffers[i]; // allocate byte array int size = block.GetSize(); int maxBytes = _responseEncoding.GetMaxByteCount(value.Length); if (maxBytes < size) { maxBytes = size; } byte[] bytes = new byte[maxBytes]; // prefill with filler System.Array.Copy(block.Data, bytes, size); // convert string int newSize = _responseEncoder.GetBytes(value.ToCharArray(), 0, value.Length, bytes, 0, true); // adjust size if allowed if (canChangeSize) { size = newSize; } // replace substitution block with memory block _buffers[i] = new HttpResponseBufferElement(bytes, size); }
private static CachedRawResponse Convert(OutputCacheEntry oce) { ArrayList headers = null; if (oce.HeaderElements != null && oce.HeaderElements.Count > 0) { headers = new ArrayList(oce.HeaderElements.Count); for (int i = 0; i < oce.HeaderElements.Count; i++) { HttpResponseHeader h = new HttpResponseHeader(oce.HeaderElements[i].Name, oce.HeaderElements[i].Value); headers.Add(h); } } ArrayList buffers = null; if (oce.ResponseElements != null && oce.ResponseElements.Count > 0) { buffers = new ArrayList(oce.ResponseElements.Count); for (int i = 0; i < oce.ResponseElements.Count; i++) { ResponseElement re = oce.ResponseElements[i]; IHttpResponseElement elem = null; if (re is FileResponseElement) { HttpContext context = HttpContext.Current; HttpWorkerRequest wr = (context != null) ? context.WorkerRequest : null; bool supportsLongTransmitFile = (wr != null && wr.SupportsLongTransmitFile); bool isImpersonating = ((context != null && context.IsClientImpersonationConfigured) || HttpRuntime.IsOnUNCShareInternal); FileResponseElement fre = (FileResponseElement)re; // DevDiv #21203: Need to verify permission to access the requested file since handled by native code. HttpRuntime.CheckFilePermission(fre.Path); elem = new HttpFileResponseElement(fre.Path, fre.Offset, fre.Length, isImpersonating, supportsLongTransmitFile); } else if (re is MemoryResponseElement) { MemoryResponseElement mre = (MemoryResponseElement)re; int size = System.Convert.ToInt32(mre.Length); elem = new HttpResponseBufferElement(mre.Buffer, size); } else if (re is SubstitutionResponseElement) { SubstitutionResponseElement sre = (SubstitutionResponseElement)re; elem = new HttpSubstBlockResponseElement(sre.Callback); } else { throw new NotSupportedException(); } buffers.Add(elem); } } else { buffers = new ArrayList(); } HttpRawResponse rawResponse = new HttpRawResponse(oce.StatusCode, oce.StatusDescription, headers, buffers, false /*hasSubstBlocks*/); CachedRawResponse cachedRawResponse = new CachedRawResponse(rawResponse, oce.Settings, oce.KernelCacheUrl, oce.CachedVaryId); return cachedRawResponse; }