internal override IAsyncResult BeginExecuteUrl(string url, string method, string childHeaders, bool sendHeaders, bool addUserIndo, IntPtr token, string name, string authType, byte[] entity, AsyncCallback cb, object state) { if (((base._ecb == IntPtr.Zero) || (this._asyncResultOfExecuteUrl != null)) || (sendHeaders && this.HeadersSent())) { throw new InvalidOperationException(System.Web.SR.GetString("Cannot_execute_url_in_this_context")); } if (((entity != null) && (entity.Length > 0)) && (UnsafeNativeMethods.EcbGetExecUrlEntityInfo(entity.Length, entity, out this._entity) != 1)) { throw new HttpException(System.Web.SR.GetString("Failed_to_execute_url")); } HttpAsyncResult result = new HttpAsyncResult(cb, state); this._asyncResultOfExecuteUrl = result; this._executeUrlCompletionCallback = new ISAPIAsyncCompletionCallback(this.OnExecuteUrlCompletion); this._rootedThis = GCHandle.Alloc(this); if (UnsafeNativeMethods.EcbExecuteUrlUnicode(base._ecb, url, method, childHeaders, sendHeaders, addUserIndo, token, name, authType, this._entity, this._executeUrlCompletionCallback) != 1) { if (this._entity != IntPtr.Zero) { UnsafeNativeMethods.EcbFreeExecUrlEntityInfo(this._entity); } this._rootedThis.Free(); this._asyncResultOfExecuteUrl = null; throw new HttpException(System.Web.SR.GetString("Failed_to_execute_url")); } if (sendHeaders) { this._headersSentFromExecuteUrl = true; } return result; }
internal override IAsyncResult BeginExecuteUrl(string url, string method, string childHeaders, bool sendHeaders, bool addUserIndo, IntPtr token, string name, string authType, byte[] entity, AsyncCallback cb, object state) { if (((base._ecb == IntPtr.Zero) || (this._asyncResultOfExecuteUrl != null)) || (sendHeaders && this.HeadersSent())) { throw new InvalidOperationException(System.Web.SR.GetString("Cannot_execute_url_in_this_context")); } if (((entity != null) && (entity.Length > 0)) && (UnsafeNativeMethods.EcbGetExecUrlEntityInfo(entity.Length, entity, out this._entity) != 1)) { throw new HttpException(System.Web.SR.GetString("Failed_to_execute_url")); } HttpAsyncResult result = new HttpAsyncResult(cb, state); this._asyncResultOfExecuteUrl = result; this._executeUrlCompletionCallback = new ISAPIAsyncCompletionCallback(this.OnExecuteUrlCompletion); this._rootedThis = GCHandle.Alloc(this); if (UnsafeNativeMethods.EcbExecuteUrlUnicode(base._ecb, url, method, childHeaders, sendHeaders, addUserIndo, token, name, authType, this._entity, this._executeUrlCompletionCallback) != 1) { if (this._entity != IntPtr.Zero) { UnsafeNativeMethods.EcbFreeExecUrlEntityInfo(this._entity); } this._rootedThis.Free(); this._asyncResultOfExecuteUrl = null; throw new HttpException(System.Web.SR.GetString("Failed_to_execute_url")); } if (sendHeaders) { this._headersSentFromExecuteUrl = true; } return(result); }
internal /*public*/ static extern int EcbFlushCore(IntPtr pECB, byte[] status, byte[] header, int keepConnected, int totalBodySize, int numBodyFragments, IntPtr[] bodyFragments, int[] bodyFragmentLengths, int doneWithSession, int finalStatus, int kernelCache, int async, ISAPIAsyncCompletionCallback asyncCompletionCallback);
internal static extern int EcbExecuteUrlUnicode(IntPtr pECB, string url, string method, string childHeaders, bool sendHeaders, bool addUserIndo, IntPtr token, string name, string authType, IntPtr pEntity, ISAPIAsyncCompletionCallback asyncCompletionCallback);
internal static extern int EcbFlushCore(IntPtr pECB, byte[] status, byte[] header, int keepConnected, int totalBodySize, int numBodyFragments, IntPtr[] bodyFragments, int[] bodyFragmentLengths, int doneWithSession, int finalStatus, int kernelCache, int async, ISAPIAsyncCompletionCallback asyncCompletionCallback);
internal override IAsyncResult BeginExecuteUrl( String url, String method, String childHeaders, bool sendHeaders, bool addUserIndo, IntPtr token, String name, String authType, byte[] entity, AsyncCallback cb, Object state) { if (_ecb == IntPtr.Zero || // after done with session _asyncResultOfExecuteUrl != null || // another ExecuteUrl in progress (sendHeaders && HeadersSent())) // asked to send headers, but already sent them { throw new InvalidOperationException(SR.GetString(SR.Cannot_execute_url_in_this_context)); } if (entity != null && entity.Length > 0) { int ret = UnsafeNativeMethods.EcbGetExecUrlEntityInfo(entity.Length, entity, out _entity); if (ret != 1) { throw new HttpException(SR.GetString(SR.Failed_to_execute_url)); } } Debug.Trace("ExecuteUrl", "ISAPIWorkerRequestInProcForIIS6.BeginExecuteUrl: url=\"" + url + "\"."); HttpAsyncResult ar = new HttpAsyncResult(cb, state); _asyncResultOfExecuteUrl = ar; _executeUrlCompletionCallback = new ISAPIAsyncCompletionCallback(OnExecuteUrlCompletion); _rootedThis = GCHandle.Alloc(this); // root for the duration of ExecuteUrl int rc; try { ar.MarkCallToBeginMethodStarted(); rc = UnsafeNativeMethods.EcbExecuteUrlUnicode(_ecb, url, method, childHeaders, sendHeaders, addUserIndo, token, name, authType, _entity, _executeUrlCompletionCallback); } finally { ar.MarkCallToBeginMethodCompleted(); } if (rc != 1) { if (_entity != IntPtr.Zero) { UnsafeNativeMethods.EcbFreeExecUrlEntityInfo(_entity); } _rootedThis.Free(); _asyncResultOfExecuteUrl = null; Debug.Trace("ExecuteUrl", "ISAPIWorkerRequestInProcForIIS6.BeginExecuteUrl: failed!"); throw new HttpException(SR.GetString(SR.Failed_to_execute_url)); } if (sendHeaders) { // ExecuteUrl will send headers, worker request should not _headersSentFromExecuteUrl = true; } return ar; }
// ISAPIWorkerRequestInProcForIIS6 internal override void FlushCore(byte[] status, byte[] header, int keepConnected, int totalBodySize, int numBodyFragments, IntPtr[] bodyFragments, int[] bodyFragmentLengths, int doneWithSession, int finalStatus, out bool async) { async = false; if (_ecb == IntPtr.Zero) return; if (_headersSentFromExecuteUrl) { // don't send headers twice status = null; header = null; } bool inAsyncFlush = false; // async only for large responses and only on the last flush or if inAsyncFlush is true // don't do async if shutting down (async IO holds up app domain shutdown) if (doneWithSession != 0 && !HttpRuntime.ShutdownInProgress && (_ignoreMinAsyncSize || (totalBodySize >= MIN_ASYNC_SIZE))) { if (_requiresAsyncFlushCallback) { _asyncFlushCompletionCallback = new ISAPIAsyncCompletionCallback(OnAsyncFlushCompletion); _asyncFinalStatus = finalStatus; // remember to pass to DoneWithSession on completion _rootedThis = GCHandle.Alloc(this); // root for the duration of IO doneWithSession = 0; // will do on completion async = true; Interlocked.Increment(ref _asyncIoCount); // increment async io count } else { // buffers are native, so we don't need to return to managed code _asyncFlushCompletionCallback = null; doneWithSession = 0; // will do on completion async = true; } } else { inAsyncFlush = (_asyncResultBase is FlushAsyncResult); if (inAsyncFlush) { _requiresAsyncFlushCallback = true; _asyncFlushCompletionCallback = new ISAPIAsyncCompletionCallback(OnAsyncFlushCompletion); _asyncFinalStatus = finalStatus; // remember to pass to DoneWithSession on completion _rootedThis = GCHandle.Alloc(this); // root for the duration of IO async = true; Interlocked.Increment(ref _asyncIoCount); // increment async io count } } // finalStatus is either 0 to force for a flush, 1 to indicate HSE_STATUS_SUCCESS, or 2 to indicate HSE_STATUS_SUCCESS_AND_KEEP_CONN Debug.Assert(0 <= finalStatus && finalStatus <= 2); int flags = _trySkipIisCustomErrors ? finalStatus|TRY_SKIP_IIS_CUSTOM_ERRORS : finalStatus; int rc = UnsafeNativeMethods.EcbFlushCore( _ecb, status, header, keepConnected, totalBodySize, numBodyFragments, bodyFragments, bodyFragmentLengths, doneWithSession, flags, _cacheInKernelMode ? 1 : 0, async ? 1 : 0, _asyncFlushCompletionCallback); if (!_requiresAsyncFlushCallback && rc == 0 && async) { // unlock and reset cached response UnlockCachedResponseBytesOnceAfterIoComplete(); CallEndOfRequestCallbackOnceAfterAllIoComplete(); } else if (rc != 0 && async) { // on async failure default to [....] path async = false; if (!inAsyncFlush) { // call DoneWithSession UnsafeNativeMethods.EcbFlushCore(_ecb, null, null, 0, 0, 0, null, null, 1, _asyncFinalStatus, 0, 0, null); } if (_asyncFlushCompletionCallback != null) { // unroot _rootedThis.Free(); // decrement async io count Interlocked.Decrement(ref _asyncIoCount); } if (inAsyncFlush) { _asyncResultBase = null; // treat every error as if the client disconnected IncrementRequestsDisconnected(); throw new HttpException(SR.GetString(SR.ClientDisconnected), rc); } } else if (rc != 0 && !async && doneWithSession == 0 && !_serverSupportFunctionError) { //on non-async failure stop executing the request //only throw once _serverSupportFunctionError = true; string message = SR.Server_Support_Function_Error; //give different error if connection was closed if (rc == HResults.WSAECONNABORTED || rc == HResults.WSAECONNRESET) { message = SR.Server_Support_Function_Error_Disconnect; IncrementRequestsDisconnected(); } throw new HttpException(SR.GetString(message, rc.ToString("X8", CultureInfo.InvariantCulture)), rc); } }
internal override void FlushCore(byte[] status, byte[] header, int keepConnected, int totalBodySize, int numBodyFragments, IntPtr[] bodyFragments, int[] bodyFragmentLengths, int doneWithSession, int finalStatus, out bool async) { async = false; if (base._ecb != IntPtr.Zero) { if (this._headersSentFromExecuteUrl) { status = null; header = null; } if (((doneWithSession != 0) && !HttpRuntime.ShutdownInProgress) && (base._ignoreMinAsyncSize || (totalBodySize >= 0x800))) { if (base._requiresAsyncFlushCallback) { this._asyncFlushCompletionCallback = new ISAPIAsyncCompletionCallback(this.OnAsyncFlushCompletion); this._asyncFinalStatus = finalStatus; this._rootedThis = GCHandle.Alloc(this); doneWithSession = 0; async = true; Interlocked.Increment(ref _asyncIoCount); } else { this._asyncFlushCompletionCallback = null; doneWithSession = 0; async = true; } } int num = this._trySkipIisCustomErrors ? (finalStatus | 0x40) : finalStatus; int hr = UnsafeNativeMethods.EcbFlushCore(base._ecb, status, header, keepConnected, totalBodySize, numBodyFragments, bodyFragments, bodyFragmentLengths, doneWithSession, num, this._cacheInKernelMode ? 1 : 0, async ? 1 : 0, this._asyncFlushCompletionCallback); if ((!base._requiresAsyncFlushCallback && (hr == 0)) && async) { base.UnlockCachedResponseBytesOnceAfterIoComplete(); base.CallEndOfRequestCallbackOnceAfterAllIoComplete(); } else if ((hr != 0) && async) { async = false; UnsafeNativeMethods.EcbFlushCore(base._ecb, null, null, 0, 0, 0, null, null, 1, this._asyncFinalStatus, 0, 0, null); if (this._asyncFlushCompletionCallback != null) { this._rootedThis.Free(); Interlocked.Decrement(ref _asyncIoCount); } } else if (((hr != 0) && !async) && ((doneWithSession == 0) && !this._serverSupportFunctionError)) { this._serverSupportFunctionError = true; string name = "Server_Support_Function_Error"; switch (hr) { case -2147014843: case -2147014842: name = "Server_Support_Function_Error_Disconnect"; PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.REQUESTS_DISCONNECTED); break; } throw new HttpException(System.Web.SR.GetString(name, new object[] { hr.ToString("X8", CultureInfo.InvariantCulture) }), hr); } } }