private static void InterruptCallback(TimerThread.Timer timer, int timeNoticed, object context) { AutoWebProxyScriptWrapper pThis = (AutoWebProxyScriptWrapper)context; GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(pThis) + "::InterruptCallback()"); if (!object.ReferenceEquals(timer, pThis.activeTimer)) { GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(pThis) + "::InterruptCallback() Spurious - returning."); return; } EXCEPINFO exceptionInfo; try { pThis.jscript.InterruptScriptThread(pThis.interruptThreadId, out exceptionInfo, 0); } catch (Exception ex) { if (NclUtilities.IsFatal(ex)) { throw; } GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(pThis) + "::InterruptCallback() InterruptScriptThread() threw:" + ValidationHelper.ToString(ex)); } catch { GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(pThis) + "::InterruptCallback() InterruptScriptThread() threw: Non-CLS Compliant Exception"); } }
internal void Close() { if (Interlocked.Increment(ref closed) != 1) { return; } GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::Close() Closing engine."); // Time out any running thread. TimerThread.Timer timer = activeTimer; if (timer != null) { if (timer.Cancel()) { InterruptCallback(timer, 0, this); } activeTimer = null; } jscript.Close(); jscriptObject = null; jscript = null; host = null; jscriptParser = null; dispatch = null; script = null; scriptText = null; lastModified = DateTime.MinValue; }
private static void CloseAppDomainCallback(TimerThread.Timer timer, int timeNoticed, object context) { try { AppDomain domain = context as AppDomain; if (domain == null) { CloseAppDomain((int)context); } else { if (object.ReferenceEquals(domain, s_ExcessAppDomain)) { try { AppDomain.Unload(domain); } catch (AppDomainUnloadedException) { } s_ExcessAppDomain = null; } } } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) { throw; } } }
internal string FindProxyForURL(string url, string host) { if (url == null || host == null) { throw new ArgumentNullException(url == null ? "url" : "host"); } if (closed != 0) { throw new ObjectDisposedException(GetType().Name); } EXCEPINFO exceptionInfo = new EXCEPINFO(); object result = null; jscript.GetCurrentScriptThreadID(out interruptThreadId); TimerThread.Timer timer = s_TimerQueue.CreateTimer(s_InterruptCallback, this); activeTimer = timer; try { GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::FindProxyForURL() Calling url:" + url + " host:" + host); result = script.FindProxyForURL(url, host); } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) { throw; } if (exception is TargetInvocationException) { exception = exception.InnerException; } COMException comException = exception as COMException; if (comException == null || comException.ErrorCode != (int)HRESULT.SCRIPT_E_REPORTED) { throw; } GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::FindProxyForURL() Script error:[" + this.host.ExceptionMessage == null ? "" : this.host.ExceptionMessage + "]"); } catch { GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::FindProxyForURL() Script error:[Non-CLS Compliant Exception]"); throw; } finally { activeTimer = null; timer.Cancel(); } string proxy = result as string; if (proxy != null) { GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::FindProxyForURL() found:" + proxy); return(proxy); } GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::FindProxyForURL() Returning null. result:" + ValidationHelper.ToString(exceptionInfo.bstrDescription) + " result:" + ValidationHelper.ToString(result) + " error:" + ValidationHelper.ToString(exceptionInfo.bstrDescription)); return(null); }
internal ServicePoint(Uri address, TimerThread.Queue defaultIdlingQueue, int defaultConnectionLimit, string lookupString, bool userChangedLimit, bool proxyServicePoint) { this.m_HostName = string.Empty; this.m_ProxyServicePoint = proxyServicePoint; this.m_Address = address; this.m_ConnectionName = address.Scheme; this.m_Host = address.DnsSafeHost; this.m_Port = address.Port; this.m_IdlingQueue = defaultIdlingQueue; this.m_ConnectionLimit = defaultConnectionLimit; this.m_HostLoopbackGuess = TriState.Unspecified; this.m_LookupString = lookupString; this.m_UserChangedLimit = userChangedLimit; this.m_UseNagleAlgorithm = ServicePointManager.UseNagleAlgorithm; this.m_Expect100Continue = ServicePointManager.Expect100Continue; this.m_ConnectionGroupList = new Hashtable(10); this.m_ConnectionLeaseTimeout = -1; this.m_ReceiveBufferSize = -1; this.m_UseTcpKeepAlive = ServicePointManager.s_UseTcpKeepAlive; this.m_TcpKeepAliveTime = ServicePointManager.s_TcpKeepAliveTime; this.m_TcpKeepAliveInterval = ServicePointManager.s_TcpKeepAliveInterval; this.m_Understands100Continue = true; this.m_HttpBehaviour = System.Net.HttpBehaviour.Unknown; this.m_IdleSince = DateTime.Now; this.m_ExpiringTimer = this.m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); }
internal ServicePoint(Uri address, TimerThread.Queue defaultIdlingQueue, int defaultConnectionLimit, string lookupString, bool userChangedLimit, bool proxyServicePoint) { this.m_HostName = string.Empty; this.m_ProxyServicePoint = proxyServicePoint; this.m_Address = address; this.m_ConnectionName = address.Scheme; this.m_Host = address.DnsSafeHost; this.m_Port = address.Port; this.m_IdlingQueue = defaultIdlingQueue; this.m_ConnectionLimit = defaultConnectionLimit; this.m_HostLoopbackGuess = TriState.Unspecified; this.m_LookupString = lookupString; this.m_UserChangedLimit = userChangedLimit; this.m_UseNagleAlgorithm = ServicePointManager.UseNagleAlgorithm; this.m_Expect100Continue = ServicePointManager.Expect100Continue; this.m_ConnectionGroupList = new Hashtable(10); this.m_ConnectionLeaseTimeout = -1; this.m_ReceiveBufferSize = -1; this.m_UseTcpKeepAlive = ServicePointManager.s_UseTcpKeepAlive; this.m_TcpKeepAliveTime = ServicePointManager.s_TcpKeepAliveTime; this.m_TcpKeepAliveInterval = ServicePointManager.s_TcpKeepAliveInterval; this.m_Understands100Continue = true; this.m_HttpBehaviour = System.Net.HttpBehaviour.Unknown; this.m_IdleSince = DateTime.Now; this.m_ExpiringTimer = this.m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); }
internal void Abort() { if (this.m_ResError == null) { this.m_ResError = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), WebExceptionStatus.RequestCanceled); } this.ErrorEvent.Set(); this.m_ErrorOccured = true; this.m_ErrorTimer = s_CancelErrorQueue.CreateTimer(s_CancelErrorCallback, this); }
internal void Abort() { if (this.m_ResError == null) { this.m_ResError = new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), WebExceptionStatus.RequestCanceled); } this.ErrorEvent.Set(); this.m_ErrorOccured = true; this.m_ErrorTimer = s_CancelErrorQueue.CreateTimer(s_CancelErrorCallback, this); }
private static void IdleServicePointTimeoutCallback(TimerThread.Timer timer, int timeNoticed, object context) { ServicePoint point = (ServicePoint)context; lock (s_ServicePointTable) { s_ServicePointTable.Remove(point.LookupString); } point.ReleaseAllConnectionGroups(); }
private void Initialize() { this.m_StackOld = new InterlockedStack(); this.m_StackNew = new InterlockedStack(); this.m_QueuedRequests = new System.Collections.Queue(); this.m_WaitHandles = new WaitHandle[] { new System.Net.Semaphore(0, 0x100000), new ManualResetEvent(false), new Mutex() }; this.m_ErrorTimer = null; this.m_ObjectList = new ArrayList(); this.m_State = State.Running; }
internal void CancelIdleTimer() { lock (m_ConnectionList) { TimerThread.Timer timer = m_ExpiringTimer; m_ExpiringTimer = null; if (timer != null) { timer.Cancel(); } } }
/// <summary> /// <para>Called on error, after we waited a set amount of time from aborting</para> /// </summary> private void CancelErrorCallback() { TimerThread.Timer timer = m_ErrorTimer; if (timer != null && timer.Cancel()) { m_ErrorOccured = false; ErrorEvent.Reset(); m_ErrorTimer = null; m_ResError = null; } }
private void CancelErrorCallback() { TimerThread.Timer errorTimer = this.m_ErrorTimer; if ((errorTimer != null) && errorTimer.Cancel()) { this.m_ErrorOccured = false; this.ErrorEvent.Reset(); this.m_ErrorTimer = null; this.m_ResError = null; } }
internal void IncrementConnection() { lock (this) { this.m_CurrentConnections++; if (this.m_CurrentConnections == 1) { this.m_ExpiringTimer.Cancel(); this.m_ExpiringTimer = null; } } }
private static void CleanupCallbackWrapper(TimerThread.Timer timer, int timeNoticed, object context) { ConnectionPool pool = (ConnectionPool)context; try { pool.CleanupCallback(); } finally { pool.m_CleanupQueue.CreateTimer(s_CleanupCallback, context); } }
internal void DecrementConnection() { lock (this) { this.m_CurrentConnections--; if (this.m_CurrentConnections == 0) { this.m_IdleSince = DateTime.Now; this.m_ExpiringTimer = this.m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); } else if (this.m_CurrentConnections < 0) { this.m_CurrentConnections = 0; } } }
private static void IdleServicePointTimeoutCallback(TimerThread.Timer timer, int timeNoticed, object context) { ServicePoint servicePoint = (ServicePoint)context; if (Logging.On) { Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_closed_idle, "ServicePoint", servicePoint.GetHashCode())); } lock (s_ServicePointTable) { s_ServicePointTable.Remove(servicePoint.LookupString); } servicePoint.ReleaseAllConnectionGroups(); }
/// <summary> /// <para>Internal init stuff, creates stacks, queue, wait handles etc</para> /// </summary> private void Initialize() { m_StackOld = new InterlockedStack(); m_StackNew = new InterlockedStack(); m_QueuedRequests = new Queue(); m_WaitHandles = new WaitHandle[3]; m_WaitHandles[SemaphoreHandleIndex] = new Semaphore(0, MaxQueueSize); m_WaitHandles[ErrorHandleIndex] = new ManualResetEvent(false); m_WaitHandles[CreationHandleIndex] = new Mutex(); m_ErrorTimer = null; // No error yet. m_ObjectList = new ArrayList(); m_State = State.Running; }
internal void DecrementConnection() { // we need these to be atomic operations lock (m_ConnectionList) { m_ActiveConnections--; if (m_ActiveConnections == 0) { Diagnostics.Debug.Assert(m_ExpiringTimer == null, "Timer not cleared"); m_ExpiringTimer = ServicePoint.CreateConnectionGroupTimer(this); } else if (m_ActiveConnections < 0) { m_ActiveConnections = 0; Diagnostics.Debug.Assert(false, "ConnectionGroup; Too many decrements."); } } }
internal ServicePoint(string host, int port, TimerThread.Queue defaultIdlingQueue, int defaultConnectionLimit, string lookupString, bool userChangedLimit, bool proxyServicePoint) { this.m_HostName = string.Empty; this.m_ProxyServicePoint = proxyServicePoint; this.m_ConnectionName = "ByHost:" + host + ":" + port.ToString(CultureInfo.InvariantCulture); this.m_IdlingQueue = defaultIdlingQueue; this.m_ConnectionLimit = defaultConnectionLimit; this.m_HostLoopbackGuess = TriState.Unspecified; this.m_LookupString = lookupString; this.m_UserChangedLimit = userChangedLimit; this.m_ConnectionGroupList = new Hashtable(10); this.m_ConnectionLeaseTimeout = -1; this.m_ReceiveBufferSize = -1; this.m_Host = host; this.m_Port = port; this.m_HostMode = true; this.m_IdleSince = DateTime.Now; this.m_ExpiringTimer = this.m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); }
/// <devdoc> /// <para> /// Returns a response from a request to an Internet resource. /// The response property. This property returns the WebResponse for this /// request. This may require that a request be submitted first. /// /// The idea is that we look and see if a request has already been /// submitted. If one has, we'll just return the existing response /// (if it's not null). If we haven't submitted a request yet, we'll /// do so now, possible multiple times while we handle redirects /// etc. /// </para> /// </devdoc> public override WebResponse GetResponse() { #if DEBUG using (GlobalLog.SetThreadKind(ThreadKinds.User | ThreadKinds.Sync)) { #endif GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::GetResponse"); if(Logging.On)Logging.Enter(Logging.Web, this, "GetResponse", ""); // No need to recheck the request parameters if we already did it in GetRequestStream(). // This prevents problems when redirects change verbs. if (!RequestSubmitted) { CheckProtocol(false); } // Many of these logics require GetResponse() to be called after all write-stream activity is done. You can't call it // simultaneously on another thread and expect it to block until it can run. Doing that can cause the request to // hang. ConnectStream stream = _OldSubmitWriteStream != null ? _OldSubmitWriteStream : _SubmitWriteStream; // Close the request stream if the user forgot to do so. Throw an exception if user has not written all of // the promised data. if (stream != null && !stream.IsClosed) { if (stream.BytesLeftToWrite > 0) { throw new ProtocolViolationException(SR.GetString(SR.net_entire_body_not_written)); } else { stream.Close(); } } else if (stream == null && HasEntityBody) { throw new ProtocolViolationException(SR.GetString(SR.net_must_provide_request_body)); } // return response, if the response is already set bool gotResponse = false; HttpWebResponse httpWebResponse = null; bool requestSubmitted; lock (this) { requestSubmitted = SetRequestSubmitted(); if (HaveResponse) { gotResponse = true; httpWebResponse = _ReadAResult.Result as HttpWebResponse; } else { if (_ReadAResult != null) { throw new InvalidOperationException(SR.GetString(SR.net_repcall)); } Async = false; // Since we don't really allow switching between [....] and async, if the request is already async, this needs to // capture context for use in the ongoing async operations as if it were BeginGetResponse(). if (Async) { #if !FEATURE_PAL ContextAwareResult readResult = new ContextAwareResult(IdentityRequired, true, this, null, null); #else ContextAwareResult readResult = new ContextAwareResult(false, true, this, null, null); #endif readResult.StartPostingAsyncOp(false); readResult.FinishPostingAsyncOp(); _ReadAResult = readResult; } else { _ReadAResult = new LazyAsyncResult(this, null, null); } } } // See if we need to do the call-done processing here. CheckDeferredCallDone(stream); if (!gotResponse) { //The previous call may have been async. If we are now doing a [....] call, we should //use the timeout if (_Timer == null){ _Timer = TimerQueue.CreateTimer(s_TimeoutCallback, this); } // Save Off verb, and use it to make the request if (!requestSubmitted) { GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + ": resetting CurrentMethod to " + _OriginVerb); CurrentMethod = _OriginVerb; } // If we're here it's because we don't have the response yet. We may have // already submitted the request, but if not do so now. while (m_Retry) { // Keep looping in case there are redirects, auth re-requests, etc BeginSubmitRequest(); } while(!Async && Aborted && !_ReadAResult.InternalPeekCompleted) { // spin untill the _CoreResponse is set if (!(_CoreResponse is Exception)) Thread.SpinWait(1); else CheckWriteSideResponseProcessing(); } httpWebResponse = _ReadAResult.InternalWaitForCompletion() as HttpWebResponse; _ReadAResult.EndCalled = true; } if (httpWebResponse == null) { if (Logging.On) Logging.Exception(Logging.Web, this, "GetResponse", _ReadAResult.Result as Exception); NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.HttpWebRequestFailed); throw (Exception) _ReadAResult.Result; } GlobalLog.Assert(httpWebResponse.ResponseStream != null, "HttpWebRequest#{0}::GetResponse()|httpWebResponse.ResponseStream == null", ValidationHelper.HashString(this)); if(Logging.On)Logging.Exit(Logging.Web, this, "GetResponse", httpWebResponse); GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::GetResponse", ValidationHelper.HashString(httpWebResponse)); if (!gotResponse) { InitLifetimeTracking(httpWebResponse); } return httpWebResponse; #if DEBUG } #endif }
/// <summary> /// <para>Internal init stuff, creates stacks, queue, wait handles etc</para> /// </summary> private void Initialize() { m_StackOld = new InterlockedStack(); m_StackNew = new InterlockedStack(); m_QueuedRequests = new Queue(); m_WaitHandles = new WaitHandle[3]; m_WaitHandles[SemaphoreHandleIndex] = new Semaphore(0, MaxQueueSize); m_WaitHandles[ErrorHandleIndex] = new ManualResetEvent(false); m_WaitHandles[CreationHandleIndex] = new Mutex(); m_ErrorTimer = null; // No error yet. m_ObjectList = new ArrayList(); m_State = State.Running; }
/* EndWriteHeaders: End write of headers This Typically called by a callback that wishes to proceed with the finalization of writing headers Input: Nothing. Returns: bool - true if success, false if we need to go pending --*/ internal bool EndWriteHeaders(bool async) { GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders async:" + async.ToString()); GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders"); try { // // if sending data and we sent a 100-continue to a 1.1 or better // server then synchronize with the 100-continue intermediate // response (or a final failure response) // GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders() ContentLength:" + ContentLength + " HttpWriteMode:" + HttpWriteMode + " _ServicePoint.Understands100Continue:" + _ServicePoint.Understands100Continue + " ExpectContinue:" + ExpectContinue); if ((ContentLength>0 || HttpWriteMode==HttpWriteMode.Chunked) && ExpectContinue && _ServicePoint.Understands100Continue) { if (async ? m_ContinueGate.StartTrigger(true) : m_ContinueGate.Trigger(true)) { if (async) { try { // If we haven't already received the continue, set a timer. GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders() starting timer for 100Continue, timeout:" + DefaultContinueTimeout.ToString()); GlobalLog.Assert(m_ContinueTimer == null, "HttpWebRequest#{0}::EndWriteHeaders()|Timer already set.", ValidationHelper.HashString(this)); m_ContinueTimer = s_ContinueTimerQueue.CreateTimer(s_ContinueTimeoutCallback, this); } finally { m_ContinueGate.FinishTrigger(); } GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders", false); return false; } else { GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders() calling PollAndRead()"); // On the Sync Path, we need to poll the Connection to see if there is any Data _SubmitWriteStream.PollAndRead(UserRetrievedWriteStream); GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders", true); return true; } } } // No continue expected or it was already received. Move forward. EndWriteHeaders_Part2(); } catch { // We depend on this to unblock possible response processing in case of unexpected failure ConnectStream chkStream = _SubmitWriteStream; if (chkStream != null) chkStream.CallDone(); throw; } GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::EndWriteHeaders", true); return true; }
/* SubmitRequest - Submit a request for sending. The core submit handler. This is called when a request needs to be submitted to the network. This routine is asynchronous; the caller passes in an HttpSubmitDelegate that we invoke when the caller can use the underlying network. The delegate is invoked with the stream that it can right to. On the Sync path, we work by attempting to gain control of the Connection for writing and reading. If some other thread is using the Connection, We wait inside of a LazyAsyncResult until it is availble. Input: request - request that's being submitted. SubmitDelegate - Delegate to be invoked. Returns: true when the request was correctly submitted --*/ // userReqeustThread says whether we can post IO from this thread or not. internal bool SubmitRequest(HttpWebRequest request) { GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "request#" + ValidationHelper.HashString(request)); GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest"); GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Free:" + m_Free.ToString() + " m_WaitList.Count:" + m_WaitList.Count.ToString()); TriState startRequestResult = TriState.Unspecified; ConnectionReturnResult returnResult = null; bool expiredIdleConnection = false; // See if the connection is free, and if the underlying socket or // stream is set up. If it is, we can assign this connection to the // request right now. Otherwise we'll have to put this request on // on the wait list until it its turn. lock(this) { request.AbortDelegate = m_AbortDelegate; if (request.Aborted) { // Note that request is not on the connection list yet and Abort() will push the response on the request GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - (Request was aborted before being submitted)", true); return true; } // // There is a race condition between FindConnection and PrepareCloseConnectionSocket // Some request may already try to submit themselves while the connection is dying. // // Retry if that's the case // if (!CanBePooled) { GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false - can't be pooled"); return false; } // See if our timer still matches the SerivcePoint. If not, get rid of it. if (m_RecycleTimer.Duration != ServicePoint.ConnectionLeaseTimerQueue.Duration) { m_RecycleTimer.Cancel(); m_RecycleTimer = ServicePoint.ConnectionLeaseTimerQueue.CreateTimer(); } if (m_RecycleTimer.HasExpired) { request.KeepAlive = false; } // // If the connection has already been locked by another request, then // we fail the submission on this Connection. // if (LockedRequest != null && LockedRequest != request) { GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false"); return false; } //free means no one in the wait list. We should only add a request //if the request can pipeline, or pipelining isn't available GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest WriteDone:" + m_WriteDone.ToString() + ", ReadDone:" + m_ReadDone.ToString() + ", m_WriteList.Count:" + m_WriteList.Count.ToString()); if (m_Free && m_WriteDone && (m_WriteList.Count == 0 || (request.Pipelined && !request.RequireBody && m_CanPipeline && m_Pipelining && !m_IsPipelinePaused))) { // Connection is free. Mark it as busy and see if underlying // socket is up. GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Free "); m_Free = false; startRequestResult = StartRequest(request); if (startRequestResult == TriState.Unspecified) { expiredIdleConnection = true; PrepareCloseConnectionSocket(ref returnResult); // Hard Close the socket. Close(0); } } else { m_WaitList.Add(request); GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Request added to WaitList#"+ValidationHelper.HashString(request)); CheckNonIdle(); } } if (expiredIdleConnection) { GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest(), expired idle connection", false); ConnectionReturnResult.SetResponses(returnResult); return false; } GlobalLog.DebugAddRequest(request, this, 0); if(Logging.On)Logging.Associate(Logging.Web, this, request); if (startRequestResult != TriState.Unspecified) { CompleteStartRequest(true, request, startRequestResult); } // On Sync, we wait for the Connection to be come availble here, if (!request.Async) { object responseObject = request.ConnectionAsyncResult.InternalWaitForCompletion(); ConnectStream writeStream = responseObject as ConnectStream; AsyncTriState triStateAsync = null; if (writeStream == null) triStateAsync = responseObject as AsyncTriState; GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Pipelining:"+m_Pipelining); if (startRequestResult == TriState.Unspecified && triStateAsync != null) { // May need to recreate Connection here (i.e. call Socket.Connect) CompleteStartRequest(true, request, triStateAsync.Value); } else if (writeStream != null) { // return the Stream to the Request request.SetRequestSubmitDone(writeStream); } #if DEBUG else if (responseObject is Exception) { Exception exception = responseObject as Exception; WebException webException = responseObject as WebException; GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest (SYNC) - Error waiting for a connection: " + exception.Message, "Status:" + (webException == null? exception.GetType().FullName: (webException.Status.ToString() + " Internal Status: " + webException.InternalStatus.ToString()))); return true; } #endif } GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", true); return true; }
internal bool FinishContinueWait() { if (m_ContinueGate.StartSignaling(false)) { try { TimerThread.Timer timer = m_ContinueTimer; m_ContinueTimer = null; if (timer != null) { timer.Cancel(); } } finally { m_ContinueGate.FinishSignaling(); } return true; } return false; }
/// <summary> /// <para>Called on error, after we waited a set amount of time from aborting</para> /// </summary> private void CancelErrorCallback() { TimerThread.Timer timer = m_ErrorTimer; if (timer != null && timer.Cancel()) { m_ErrorOccured = false; ErrorEvent.Reset(); m_ErrorTimer = null; m_ResError = null; } }
private void CancelErrorCallback() { TimerThread.Timer errorTimer = this.m_ErrorTimer; if ((errorTimer != null) && errorTimer.Cancel()) { this.m_ErrorOccured = false; this.ErrorEvent.Reset(); this.m_ErrorTimer = null; this.m_ResError = null; } }
private static void CancelErrorCallbackWrapper(TimerThread.Timer timer, int timeNoticed, object context) { ((ConnectionPool)context).CancelErrorCallback(); }
// Downloads and compiles the script from a given Uri. // This code can be called by config for a downloaded control, we need to assert. // This code is called holding the lock. private AutoWebProxyState DownloadAndCompile(Uri location) { GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() location:" + ValidationHelper.ToString(location)); AutoWebProxyState newState = AutoWebProxyState.DownloadFailure; WebResponse response = null; TimerThread.Timer timer = null; AutoWebProxyScriptWrapper newScriptInstance = null; // Can't assert this in declarative form (DCR?). This Assert() is needed to be able to create the request to download the proxy script. ExceptionHelper.WebPermissionUnrestricted.Assert(); try { lock (lockObject) { if (aborted) { throw new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), WebExceptionStatus.RequestCanceled); } request = WebRequest.Create(location); } request.Timeout = Timeout.Infinite; request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default); request.ConnectionGroupName = "__WebProxyScript"; // We have an opportunity here, if caching is disabled AppDomain-wide, to override it with a // custom, trivial cache-provider to get a similar semantic. // // We also want to have a backup caching key in the case when IE has locked an expired script response // if (request.CacheProtocol != null) { GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() Using backup caching."); request.CacheProtocol = new RequestCacheProtocol(backupCache, request.CacheProtocol.Validator); } HttpWebRequest httpWebRequest = request as HttpWebRequest; if (httpWebRequest != null) { httpWebRequest.Accept = "*/*"; httpWebRequest.UserAgent = this.GetType().FullName + "/" + Environment.Version; httpWebRequest.KeepAlive = false; httpWebRequest.Pipelined = false; httpWebRequest.InternalConnectionGroup = true; } else { FtpWebRequest ftpWebRequest = request as FtpWebRequest; if (ftpWebRequest != null) { ftpWebRequest.KeepAlive = false; } } // Use no proxy, default cache - initiate the download. request.Proxy = null; request.Credentials = Engine.Credentials; // Use our own timeout timer so that it can encompass the whole request, not just the headers. if (timerQueue == null) { timerQueue = TimerThread.GetOrCreateQueue(SettingsSectionInternal.Section.DownloadTimeout); } timer = timerQueue.CreateTimer(timerCallback, request); response = request.GetResponse(); // Check Last Modified. DateTime lastModified = DateTime.MinValue; HttpWebResponse httpResponse = response as HttpWebResponse; if (httpResponse != null) { lastModified = httpResponse.LastModified; } else { FtpWebResponse ftpResponse = response as FtpWebResponse; if (ftpResponse != null) { lastModified = ftpResponse.LastModified; } } GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() lastModified:" + lastModified.ToString() + " (script):" + (scriptInstance == null ? "(null)" : scriptInstance.LastModified.ToString())); if (scriptInstance != null && lastModified != DateTime.MinValue && scriptInstance.LastModified == lastModified) { newScriptInstance = scriptInstance; newState = AutoWebProxyState.Completed; } else { string scriptBody = null; byte[] scriptBuffer = null; using (Stream responseStream = response.GetResponseStream()) { SingleItemRequestCache.ReadOnlyStream ros = responseStream as SingleItemRequestCache.ReadOnlyStream; if (ros != null) { scriptBuffer = ros.Buffer; } if (scriptInstance != null && scriptBuffer != null && scriptBuffer == scriptInstance.Buffer) { scriptInstance.LastModified = lastModified; newScriptInstance = scriptInstance; newState = AutoWebProxyState.Completed; GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() Buffer matched - reusing Engine."); } else { using (StreamReader streamReader = new StreamReader(responseStream)) { scriptBody = streamReader.ReadToEnd(); } } } WebResponse tempResponse = response; response = null; tempResponse.Close(); timer.Cancel(); timer = null; if (newState != AutoWebProxyState.Completed) { GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() IsFromCache:" + tempResponse.IsFromCache.ToString() + " scriptInstance:" + ValidationHelper.HashString(scriptInstance)); if (scriptInstance != null && scriptBody == scriptInstance.ScriptBody) { GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() Script matched - using existing Engine."); scriptInstance.LastModified = lastModified; if (scriptBuffer != null) { scriptInstance.Buffer = scriptBuffer; } newScriptInstance = scriptInstance; newState = AutoWebProxyState.Completed; } else { GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() Creating AutoWebProxyScriptWrapper."); newScriptInstance = new AutoWebProxyScriptWrapper(); newScriptInstance.LastModified = lastModified; if (newScriptInstance.Compile(location, scriptBody, scriptBuffer)) { newState = AutoWebProxyState.Completed; } else { newState = AutoWebProxyState.CompilationFailure; } } } } } catch (Exception exception) { if (Logging.On) { Logging.PrintWarning(Logging.Web, SR.GetString(SR.net_log_proxy_script_download_compile_error, exception)); } GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() Download() threw:" + ValidationHelper.ToString(exception)); } finally { if (timer != null) { timer.Cancel(); } // try { if (response != null) { response.Close(); } } finally { WebPermission.RevertAssert(); // The request is not needed anymore. Set it to null, so if Abort() gets called, // after this point, it will result in a no-op. request = null; } } if ((newState == AutoWebProxyState.Completed) && (scriptInstance != newScriptInstance)) { if (scriptInstance != null) { scriptInstance.Close(); } scriptInstance = newScriptInstance; } GlobalLog.Print("NetWebProxyFinder#" + ValidationHelper.HashString(this) + "::DownloadAndCompile() retuning newState:" + ValidationHelper.ToString(newState)); return(newState); }
internal void SetRequestContinue(CoreResponseData continueResponse) { GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue"); GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue"); _RequestContinueCount++; if (HttpWriteMode == HttpWriteMode.None) { GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue - not a POST type request, return"); return; } GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue() _RequestContinueCount:" + _RequestContinueCount); if (m_ContinueGate.Complete()) { // Generally, in Sync mode there will not be a timer (instead PollAndRead times out). However, in mixed mode // there can be. If there is a timer, whether or not to call EndWriteHeaders_Part2 depends on whether // we can successfully cancel it here. Otherwise, the timeout callback should call it. // // m_ContinueGate guards the synchronization of m_ContinueTimer. TimerThread.Timer timer = m_ContinueTimer; m_ContinueTimer = null; // In the case there was no timer, just call EndWriteHeaders_Part2. if (timer == null || timer.Cancel()) { // Invoke the 100 continue delegate if the user supplied one and we received a 100 Continue. if (continueResponse != null && ContinueDelegate != null) { GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue() calling ContinueDelegate()"); ExecutionContext x = null; if (x == null) { ContinueDelegate((int) continueResponse.m_StatusCode, continueResponse.m_ResponseHeaders); } else { ExecutionContext.Run(x, new ContextCallback(CallContinueDelegateCallback), continueResponse); } } EndWriteHeaders_Part2(); } } GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestContinue"); }
private void SubmitRequest(ServicePoint servicePoint) { GlobalLog.Enter("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest"); GlobalLog.ThreadContract(ThreadKinds.Unknown, "HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest"); GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest() HaveResponse:" + HaveResponse + " Saw100Continue:" + Saw100Continue); if (!Async) { _ConnectionAResult = new LazyAsyncResult(this, null, null); _ConnectionReaderAResult = new LazyAsyncResult(this, null, null); OpenWriteSideResponseWindow(); } if (_Timer == null && !Async){ _Timer = TimerQueue.CreateTimer(s_TimeoutCallback, this); } try { if (_SubmitWriteStream != null && _SubmitWriteStream.IsPostStream) { // _OldSubmitWriteStream is the stream that holds real user data // In no case it can be overwritten. // For multiple resubmits the ContentLength was set already, so no need call it again. // on first resubmission the real user data hasn't been saved, so _OldSubmitWriteStream is null GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest() (resubmit) firstResubmission:" + (_OldSubmitWriteStream == null) + " NtlmKeepAlive:" + NtlmKeepAlive); if (_OldSubmitWriteStream == null && !_SubmitWriteStream.ErrorInStream && AllowWriteStreamBuffering) { // save the real user data. GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest() (resubmit) save the real user data _OldSubmitWriteStream#" + ValidationHelper.HashString(_OldSubmitWriteStream)); _OldSubmitWriteStream = _SubmitWriteStream; } // make sure we reformat the headers before resubmitting _WriteBuffer = null; } m_Retry = false; // If pre-authentication is requested call the AuthenticationManager // and add authorization header if there is response if (PreAuthenticate) { if (UsesProxySemantics && _Proxy != null && _Proxy.Credentials != null) ProxyAuthenticationState.PreAuthIfNeeded(this, _Proxy.Credentials); if (Credentials != null) ServerAuthenticationState.PreAuthIfNeeded(this, Credentials); } if (WriteBuffer == null) { UpdateHeaders(); } if (CheckCacheRetrieveBeforeSubmit()) { // We are done and internal Response processing is kicked in GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest CACHED RESPONSE"); return; } // At this point we are going to send a live request // _AbortDelegate is set on submission process. servicePoint.SubmitRequest(this, GetConnectionGroupLine()); } finally { if (!Async) CheckWriteSideResponseProcessing(); } GlobalLog.Leave("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SubmitRequest"); }
internal bool SubmitRequest(HttpWebRequest request, bool forcedsubmit) { GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "request#" + ValidationHelper.HashString(request)); GlobalLog.ThreadContract(ThreadKinds.Unknown, "Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest"); GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Free:" + m_Free.ToString() + " m_WaitList.Count:" + m_WaitList.Count.ToString()); TriState startRequestResult = TriState.Unspecified; ConnectionReturnResult returnResult = null; bool expiredIdleConnection = false; // See if the connection is free, and if the underlying socket or // stream is set up. If it is, we can assign this connection to the // request right now. Otherwise we'll have to put this request on // on the wait list until it its turn. lock(this) { request.AbortDelegate = m_AbortDelegate; if (request.Aborted) { // Note that request is not on the connection list yet and Abort() will push the response on the request GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - (Request was aborted before being submitted)", true); UnlockIfNeeded(request); return true; } // // There is a race condition between FindConnection and PrepareCloseConnectionSocket // Some request may already try to submit themselves while the connection is dying. // // Retry if that's the case // if (!CanBePooled) { GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false - can't be pooled"); UnlockIfNeeded(request); return false; } // // There is a race condition between SubmitRequest and FindConnection. A non keep-alive request may // get submitted on this connection just after we check for it. So make sure that if we are queueing // behind non keep-alive request then its a forced submit. // Retry if that's not the case. // if (!forcedsubmit && NonKeepAliveRequestPipelined) { GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false - behind non keep-alive request"); UnlockIfNeeded(request); return false; } // See if our timer still matches the SerivcePoint. If not, get rid of it. if (m_RecycleTimer.Duration != ServicePoint.ConnectionLeaseTimerQueue.Duration) { m_RecycleTimer.Cancel(); m_RecycleTimer = ServicePoint.ConnectionLeaseTimerQueue.CreateTimer(); } if (m_RecycleTimer.HasExpired) { request.KeepAlive = false; } // // If the connection has already been locked by another request, then // we fail the submission on this Connection. // if (LockedRequest != null && LockedRequest != request) { GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", "false"); return false; } //free means no one in the wait list. We should only add a request //if the request can pipeline, or pipelining isn't available GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest WriteDone:" + m_WriteDone.ToString() + ", ReadDone:" + m_ReadDone.ToString() + ", m_WriteList.Count:" + m_WriteList.Count.ToString()); // // If this request is marked as non keep-alive, we should stop pipelining more requests on this // connection. The keep-alive context is transfered to the connection from request only after we start // receiving response for the request. // if (!forcedsubmit && !m_NonKeepAliveRequestPipelined) { m_NonKeepAliveRequestPipelined = (!request.KeepAlive && !request.NtlmKeepAlive); } if (m_Free && m_WriteDone && !forcedsubmit && (m_WriteList.Count == 0 || (request.Pipelined && !request.HasEntityBody && m_CanPipeline && m_Pipelining && !m_IsPipelinePaused))) { // Connection is free. Mark it as busy and see if underlying // socket is up. GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Free "); m_Free = false; // This codepath handles the case where the server has closed the Connection by // returning false below: the request will be resubmitted on a different Connection. startRequestResult = StartRequest(request, true); if (startRequestResult == TriState.Unspecified) { expiredIdleConnection = true; PrepareCloseConnectionSocket(ref returnResult); // Hard Close the socket. Close(0); } } else { m_WaitList.Add(new WaitListItem(request, NetworkingPerfCounters.GetTimestamp())); NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.HttpWebRequestQueued); GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest - Request added to WaitList#"+ValidationHelper.HashString(request)); #if TRAVE if (q_Tunnelling) { GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() MyLocalPort:" + MyLocalPort + " ERROR: adding HttpWebRequest#" + ValidationHelper.HashString(request) +" to tunnelling WaitList"); } else { GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() MyLocalPort:" + MyLocalPort + " adding HttpWebRequest#" + ValidationHelper.HashString(request) +" to non-tunnelling WaitList m_WaitList.Count:" + m_WaitList.Count); } #endif CheckNonIdle(); } } if (expiredIdleConnection) { GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest(), expired idle connection", false); ConnectionReturnResult.SetResponses(returnResult); return false; } GlobalLog.DebugAddRequest(request, this, 0); if(Logging.On)Logging.Associate(Logging.Web, this, request); if (startRequestResult != TriState.Unspecified) { CompleteStartRequest(true, request, startRequestResult); } // On [....], we wait for the Connection to be come availble here, if (!request.Async) { object responseObject = request.ConnectionAsyncResult.InternalWaitForCompletion(); ConnectStream writeStream = responseObject as ConnectStream; AsyncTriState triStateAsync = null; if (writeStream == null) triStateAsync = responseObject as AsyncTriState; GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest() Pipelining:"+m_Pipelining); if (startRequestResult == TriState.Unspecified && triStateAsync != null) { // May need to recreate Connection here (i.e. call Socket.Connect) CompleteStartRequest(true, request, triStateAsync.Value); } else if (writeStream != null) { // return the Stream to the Request request.SetRequestSubmitDone(writeStream); } #if DEBUG else if (responseObject is Exception) { Exception exception = responseObject as Exception; WebException webException = responseObject as WebException; GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest (SYNC) - Error waiting for a connection: " + exception.Message, "Status:" + (webException == null? exception.GetType().FullName: (webException.Status.ToString() + " Internal Status: " + webException.InternalStatus.ToString()))); return true; } #endif } GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::SubmitRequest", true); return true; }
internal void StartAsync100ContinueTimer() { if (m_ContinueGate.StartTriggering(true)) { try { if (ShouldWaitFor100Continue()) { Debug.Assert(m_ContinueTimer == null, "Continue timer is already set"); m_ContinueTimer = ContinueTimerQueue.CreateTimer(s_ContinueTimeoutCallback, this); } } finally { m_ContinueGate.FinishTriggering(); } } else { Debug.Assert(false, "StartAsync100ContinueTimer failed."); } }
internal void IncrementConnection() { lock (this) { this.m_CurrentConnections++; if (this.m_CurrentConnections == 1) { this.m_ExpiringTimer.Cancel(); this.m_ExpiringTimer = null; } } }
internal AutoWebProxyState Compile(Uri engineScriptLocation, string scriptBody, byte[] buffer) { if (closed != 0) { throw new ObjectDisposedException(GetType().Name); } if (jscriptObject != null) { jscript.Close(); } scriptText = null; scriptBytes = null; jscriptObject = new JScriptEngine(); jscript = (IActiveScript)jscriptObject; host = new ScriptHost(); GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::Compile() Binding to ScriptHost#" + ValidationHelper.HashString(this)); jscriptParser = new ActiveScriptParseWrapper(jscriptObject); jscriptParser.InitNew(); jscript.SetScriptSite(host); jscript.SetScriptState(ScriptState.Initialized); // // Inform the script engine that this host implements the IInternetHostSecurityManager interface, which // is used to prevent the script code from using any ActiveX objects. // IObjectSafety objSafety = jscript as IObjectSafety; if (objSafety != null) { Guid guid = Guid.Empty; GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::Compile() Setting up IInternetHostSecurityManager"); objSafety.SetInterfaceSafetyOptions(ref guid, ComConstants.INTERFACE_USES_SECURITY_MANAGER, ComConstants.INTERFACE_USES_SECURITY_MANAGER); objSafety = null; } EXCEPINFO exceptionInfo = new EXCEPINFO(); object result = null; try { jscriptParser.ParseScriptText(scriptBody, null, null, null, IntPtr.Zero, 0, ScriptText.IsPersistent | ScriptText.IsVisible, out result, out exceptionInfo); GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::Compile() ParseScriptText() success:" + ValidationHelper.ToString(exceptionInfo.bstrDescription) + " result:" + ValidationHelper.ToString(result)); } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) { throw; } if (exception is TargetInvocationException) { exception = exception.InnerException; } COMException comException = exception as COMException; if (comException == null || comException.ErrorCode != (int)HRESULT.SCRIPT_E_REPORTED) { throw; } GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::Compile() Script load error:[" + host.ExceptionMessage == null ? "" : host.ExceptionMessage + "]"); throw new COMException(SR.GetString(SR.net_jscript_load, host.ExceptionMessage), comException.ErrorCode); } catch { GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::Compile() Script load error:[Non-CLS Compliant Exception]"); throw; } jscript.AddNamedItem(c_ScriptHelperName, ScriptItem.GlobalMembers | ScriptItem.IsPersistent | ScriptItem.IsVisible); // This part can run global code - time it out if necessary. jscript.GetCurrentScriptThreadID(out interruptThreadId); TimerThread.Timer timer = s_TimerQueue.CreateTimer(s_InterruptCallback, this); activeTimer = timer; try { jscript.SetScriptState(ScriptState.Started); jscript.SetScriptState(ScriptState.Connected); } finally { activeTimer = null; timer.Cancel(); } jscript.GetScriptDispatch(null, out script); GlobalLog.Print("AutoWebProxyScriptWrapper#" + ValidationHelper.HashString(this) + "::Compile() Got IDispatch:" + ValidationHelper.ToString(dispatch)); scriptText = scriptBody; scriptBytes = buffer; return(AutoWebProxyState.CompilationSuccess); }
internal ServicePoint(string host, int port, TimerThread.Queue defaultIdlingQueue, int defaultConnectionLimit, string lookupString, bool userChangedLimit, bool proxyServicePoint) { this.m_HostName = string.Empty; this.m_ProxyServicePoint = proxyServicePoint; this.m_ConnectionName = "ByHost:" + host + ":" + port.ToString(CultureInfo.InvariantCulture); this.m_IdlingQueue = defaultIdlingQueue; this.m_ConnectionLimit = defaultConnectionLimit; this.m_HostLoopbackGuess = TriState.Unspecified; this.m_LookupString = lookupString; this.m_UserChangedLimit = userChangedLimit; this.m_ConnectionGroupList = new Hashtable(10); this.m_ConnectionLeaseTimeout = -1; this.m_ReceiveBufferSize = -1; this.m_Host = host; this.m_Port = port; this.m_HostMode = true; this.m_IdleSince = DateTime.Now; this.m_ExpiringTimer = this.m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); }
private void Initialize() { this.m_StackOld = new InterlockedStack(); this.m_StackNew = new InterlockedStack(); this.m_QueuedRequests = new System.Collections.Queue(); this.m_WaitHandles = new WaitHandle[] { new System.Net.Semaphore(0, 0x100000), new ManualResetEvent(false), new Mutex() }; this.m_ErrorTimer = null; this.m_ObjectList = new ArrayList(); this.m_State = State.Running; }
// RequestTimeoutCallback - Called by the TimerThread to abort a request. This just posts ThreadPool work item - Abort() does too // much to be done on the timer thread (timer thread should never block or call user code). private static void RequestTimeoutCallback(TimerThread.Timer timer, int timeNoticed, object context) { ThreadPool.UnsafeQueueUserWorkItem(abortWrapper, context); }
internal Connection(System.Net.ConnectionGroup connectionGroup) : base(null) { this.m_IISVersion = -1; this.m_Free = true; this.m_Idle = true; this.m_KeepAlive = true; this.m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength; if (this.m_MaximumUnauthorizedUploadLength > 0L) { this.m_MaximumUnauthorizedUploadLength *= 0x400L; } this.m_ResponseData = new CoreResponseData(); this.m_ConnectionGroup = connectionGroup; this.m_ReadBuffer = new byte[0x1000]; this.m_ReadState = ReadState.Start; this.m_WaitList = new List<WaitListItem>(); this.m_WriteList = new ArrayList(); this.m_AbortDelegate = new HttpAbortDelegate(this.AbortOrDisassociate); this.m_ConnectionUnlock = new UnlockConnectionDelegate(this.UnlockRequest); this.m_StatusLineValues = new StatusLineValues(); this.m_RecycleTimer = this.ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer(); this.ConnectionGroup.Associate(this); this.m_ReadDone = true; this.m_WriteDone = true; this.m_Error = WebExceptionStatus.Success; }
internal void DecrementConnection() { // we need these to be atomic operations lock (m_ConnectionList) { m_ActiveConnections--; if (m_ActiveConnections == 0) { Diagnostics.Debug.Assert(m_ExpiringTimer == null, "Timer not cleared"); m_ExpiringTimer = ServicePoint.CreateConnectionGroupTimer(this); } else if (m_ActiveConnections < 0) { m_ActiveConnections = 0; Diagnostics.Debug.Assert(false, "ConnectionGroup; Too many decrements."); } } }
internal Connection(ConnectionGroup connectionGroup) : base(null) { // // add this Connection to the pool in the connection group, // keep a weak reference to it // m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength; if(m_MaximumUnauthorizedUploadLength > 0){ m_MaximumUnauthorizedUploadLength*=1024; } m_ResponseData = new CoreResponseData(); m_ConnectionGroup = connectionGroup; m_ReadBuffer = new byte[4096]; // Using a fixed 4k read buffer. m_ReadState = ReadState.Start; m_WaitList = new List<WaitListItem>(); m_WriteList = new ArrayList(); m_AbortDelegate = new HttpAbortDelegate(AbortOrDisassociate); m_ConnectionUnlock = new UnlockConnectionDelegate(UnlockRequest); // for status line parsing m_StatusLineValues = new StatusLineValues(); m_RecycleTimer = ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer(); // the following line must be the last line of the constructor ConnectionGroup.Associate(this); m_ReadDone = true; m_WriteDone = true; m_Error = WebExceptionStatus.Success; }
private BaseWebProxyFinder.AutoWebProxyState DownloadAndCompile(Uri location) { BaseWebProxyFinder.AutoWebProxyState downloadFailure = BaseWebProxyFinder.AutoWebProxyState.DownloadFailure; WebResponse response = null; TimerThread.Timer timer = null; AutoWebProxyScriptWrapper scriptInstance = null; ExceptionHelper.WebPermissionUnrestricted.Assert(); try { lock (this.lockObject) { if (this.aborted) { throw new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), WebExceptionStatus.RequestCanceled); } this.request = WebRequest.Create(location); } this.request.Timeout = -1; this.request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default); this.request.ConnectionGroupName = "__WebProxyScript"; if (this.request.CacheProtocol != null) { this.request.CacheProtocol = new RequestCacheProtocol(this.backupCache, this.request.CacheProtocol.Validator); } HttpWebRequest request = this.request as HttpWebRequest; if (request != null) { request.Accept = "*/*"; request.UserAgent = base.GetType().FullName + "/" + Environment.Version; request.KeepAlive = false; request.Pipelined = false; request.InternalConnectionGroup = true; } else { FtpWebRequest request2 = this.request as FtpWebRequest; if (request2 != null) { request2.KeepAlive = false; } } this.request.Proxy = null; this.request.Credentials = base.Engine.Credentials; if (timerQueue == null) { timerQueue = TimerThread.GetOrCreateQueue(SettingsSectionInternal.Section.DownloadTimeout); } timer = timerQueue.CreateTimer(timerCallback, this.request); response = this.request.GetResponse(); DateTime minValue = DateTime.MinValue; HttpWebResponse response2 = response as HttpWebResponse; if (response2 != null) { minValue = response2.LastModified; } else { FtpWebResponse response3 = response as FtpWebResponse; if (response3 != null) { minValue = response3.LastModified; } } if (((this.scriptInstance != null) && (minValue != DateTime.MinValue)) && (this.scriptInstance.LastModified == minValue)) { scriptInstance = this.scriptInstance; downloadFailure = BaseWebProxyFinder.AutoWebProxyState.Completed; } else { string scriptBody = null; byte[] buffer = null; using (Stream stream = response.GetResponseStream()) { SingleItemRequestCache.ReadOnlyStream stream2 = stream as SingleItemRequestCache.ReadOnlyStream; if (stream2 != null) { buffer = stream2.Buffer; } if (((this.scriptInstance != null) && (buffer != null)) && (buffer == this.scriptInstance.Buffer)) { this.scriptInstance.LastModified = minValue; scriptInstance = this.scriptInstance; downloadFailure = BaseWebProxyFinder.AutoWebProxyState.Completed; } else { using (StreamReader reader = new StreamReader(stream)) { scriptBody = reader.ReadToEnd(); } } } WebResponse response4 = response; response = null; response4.Close(); timer.Cancel(); timer = null; if (downloadFailure != BaseWebProxyFinder.AutoWebProxyState.Completed) { if ((this.scriptInstance != null) && (scriptBody == this.scriptInstance.ScriptBody)) { this.scriptInstance.LastModified = minValue; if (buffer != null) { this.scriptInstance.Buffer = buffer; } scriptInstance = this.scriptInstance; downloadFailure = BaseWebProxyFinder.AutoWebProxyState.Completed; } else { scriptInstance = new AutoWebProxyScriptWrapper { LastModified = minValue }; if (scriptInstance.Compile(location, scriptBody, buffer)) { downloadFailure = BaseWebProxyFinder.AutoWebProxyState.Completed; } else { downloadFailure = BaseWebProxyFinder.AutoWebProxyState.CompilationFailure; } } } } } catch (Exception exception) { if (Logging.On) { Logging.PrintWarning(Logging.Web, SR.GetString("net_log_proxy_script_download_compile_error", new object[] { exception })); } } finally { if (timer != null) { timer.Cancel(); } try { if (response != null) { response.Close(); } } finally { CodeAccessPermission.RevertAssert(); this.request = null; } } if ((downloadFailure == BaseWebProxyFinder.AutoWebProxyState.Completed) && (this.scriptInstance != scriptInstance)) { if (this.scriptInstance != null) { this.scriptInstance.Close(); } this.scriptInstance = scriptInstance; } return(downloadFailure); }
internal void DecrementConnection() { lock (this) { this.m_CurrentConnections--; if (this.m_CurrentConnections == 0) { this.m_IdleSince = DateTime.Now; this.m_ExpiringTimer = this.m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); } else if (this.m_CurrentConnections < 0) { this.m_CurrentConnections = 0; } } }
internal ServicePoint(string host, int port, TimerThread.Queue defaultIdlingQueue, int defaultConnectionLimit, string lookupString, bool userChangedLimit, bool proxyServicePoint) { GlobalLog.Print("ServicePoint#" + ValidationHelper.HashString(this) + "::.ctor(" + lookupString+")"); if (Logging.On) Logging.Enter(Logging.Web, this, "ServicePoint", host + ":" + port); m_ProxyServicePoint = proxyServicePoint; m_ConnectionName = "ByHost:"+host+":"+port.ToString(CultureInfo.InvariantCulture); m_IdlingQueue = defaultIdlingQueue; m_ConnectionLimit = defaultConnectionLimit; m_HostLoopbackGuess = TriState.Unspecified; m_LookupString = lookupString; m_UserChangedLimit = userChangedLimit; m_ConnectionGroupList = new Hashtable(10); m_ConnectionLeaseTimeout = System.Threading.Timeout.Infinite; m_ReceiveBufferSize = -1; m_Host = host; m_Port = port; m_HostMode = true; // upon creation, the service point should be idle, by default m_IdleSince = DateTime.Now; m_ExpiringTimer = m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); m_IdleConnectionGroupTimeoutDelegate = new TimerThread.Callback(IdleConnectionGroupTimeoutCallback); }
internal bool SubmitRequest(HttpWebRequest request, bool forcedsubmit) { TriState unspecified = TriState.Unspecified; ConnectionReturnResult returnResult = null; bool flag = false; lock (this) { request.AbortDelegate = this.m_AbortDelegate; if (request.Aborted) { return true; } if (!base.CanBePooled) { return false; } if (!forcedsubmit && this.NonKeepAliveRequestPipelined) { return false; } if (this.m_RecycleTimer.Duration != this.ServicePoint.ConnectionLeaseTimerQueue.Duration) { this.m_RecycleTimer.Cancel(); this.m_RecycleTimer = this.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer(); } if (this.m_RecycleTimer.HasExpired) { request.KeepAlive = false; } if ((this.LockedRequest != null) && (this.LockedRequest != request)) { return false; } if (!forcedsubmit && !this.m_NonKeepAliveRequestPipelined) { this.m_NonKeepAliveRequestPipelined = !request.KeepAlive && !request.NtlmKeepAlive; } if (((this.m_Free && this.m_WriteDone) && !forcedsubmit) && ((this.m_WriteList.Count == 0) || (((request.Pipelined && !request.HasEntityBody) && (this.m_CanPipeline && this.m_Pipelining)) && !this.m_IsPipelinePaused))) { this.m_Free = false; unspecified = this.StartRequest(request, true); if (unspecified == TriState.Unspecified) { flag = true; this.PrepareCloseConnectionSocket(ref returnResult); base.Close(0); } } else { this.m_WaitList.Add(new WaitListItem(request, NetworkingPerfCounters.GetTimestamp())); NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.HttpWebRequestQueued); this.CheckNonIdle(); } } if (flag) { ConnectionReturnResult.SetResponses(returnResult); return false; } if (Logging.On) { Logging.Associate(Logging.Web, this, request); } if (unspecified != TriState.Unspecified) { this.CompleteStartRequest(true, request, unspecified); } if (!request.Async) { object obj2 = request.ConnectionAsyncResult.InternalWaitForCompletion(); ConnectStream submitStream = obj2 as ConnectStream; AsyncTriState state2 = null; if (submitStream == null) { state2 = obj2 as AsyncTriState; } if ((unspecified == TriState.Unspecified) && (state2 != null)) { this.CompleteStartRequest(true, request, state2.Value); } else if (submitStream != null) { request.SetRequestSubmitDone(submitStream); } } return true; }
// // IncrementConnection // // call to indicate that we now are starting a new // connection within this service point // internal void IncrementConnection() { GlobalLog.Enter("ServicePoint#" + ValidationHelper.HashString(this) + "::IncrementConnection()", m_CurrentConnections.ToString()); // we need these to be atomic operations lock(this) { m_CurrentConnections++; if (m_CurrentConnections==1) { GlobalLog.Assert(m_ExpiringTimer != null, "ServicePoint#{0}::IncrementConnection|First connection active, but ServicePoint wasn't idle.", ValidationHelper.HashString(this)); // m_ExpiringTimer.Cancel(); m_ExpiringTimer = null; } } GlobalLog.Leave("ServicePoint#" + ValidationHelper.HashString(this) + "::IncrementConnection()", m_CurrentConnections.ToString()); }
// // DecrementConnection // // call to indicate that we now are removing // a connection within this connection group // internal void DecrementConnection() { // The timer thread is allowed to call this. (It doesn't call user code and doesn't block.) GlobalLog.ThreadContract(ThreadKinds.Unknown, ThreadKinds.SafeSources | ThreadKinds.Timer, "ServicePoint#" + ValidationHelper.HashString(this) + "::DecrementConnection"); GlobalLog.Enter("ServicePoint#" + ValidationHelper.HashString(this) + "::DecrementConnection()", m_CurrentConnections.ToString()); // we need these to be atomic operations lock(this) { m_CurrentConnections--; if (m_CurrentConnections==0) { GlobalLog.Assert(m_ExpiringTimer == null, "ServicePoint#{0}::DecrementConnection|Expiring timer set on non-idle ServicePoint.", ValidationHelper.HashString(this)); m_IdleSince = DateTime.Now; m_ExpiringTimer = m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); } else if ( m_CurrentConnections < 0 ) { m_CurrentConnections = 0; Diagnostics.Debug.Assert(false, "ServicePoint; Too many decrements."); } } GlobalLog.Leave("ServicePoint#" + ValidationHelper.HashString(this) + "::DecrementConnection()", m_CurrentConnections.ToString()); }
internal Connection(ConnectionGroup connectionGroup) : base(null) { // // add this Connection to the pool in the connection group, // keep a weak reference to it // m_MaximumUnauthorizedUploadLength = SettingsSectionInternal.Section.MaximumUnauthorizedUploadLength; if(m_MaximumUnauthorizedUploadLength > 0){ m_MaximumUnauthorizedUploadLength*=1024; } m_ResponseData = new CoreResponseData(); m_ConnectionGroup = connectionGroup; m_ReadBuffer = s_PinnableBufferCache.AllocateBuffer(); m_ReadBufferFromPinnableCache = true; m_ReadState = ReadState.Start; m_WaitList = new List<WaitListItem>(); m_WriteList = new ArrayList(); m_AbortDelegate = new HttpAbortDelegate(AbortOrDisassociate); m_ConnectionUnlock = new UnlockConnectionDelegate(UnlockRequest); // for status line parsing m_StatusLineValues = new StatusLineValues(); m_RecycleTimer = ConnectionGroup.ServicePoint.ConnectionLeaseTimerQueue.CreateTimer(); // the following line must be the last line of the constructor ConnectionGroup.Associate(this); m_ReadDone = true; m_WriteDone = true; m_Error = WebExceptionStatus.Success; if (PinnableBufferCacheEventSource.Log.IsEnabled()) { PinnableBufferCacheEventSource.Log.DebugMessage1("CTOR: In System.Net.Connection.Connnection", this.GetHashCode()); } }
internal void CancelIdleTimer() { lock (m_ConnectionList) { TimerThread.Timer timer = m_ExpiringTimer; m_ExpiringTimer = null; if (timer != null) { timer.Cancel(); } } }
// // constructors // internal ServicePoint(Uri address, TimerThread.Queue defaultIdlingQueue, int defaultConnectionLimit, string lookupString, bool userChangedLimit, bool proxyServicePoint) { GlobalLog.Print("ServicePoint#" + ValidationHelper.HashString(this) + "::.ctor(" + lookupString+")"); if (Logging.On) Logging.Enter(Logging.Web, this, "ServicePoint", address.DnsSafeHost + ":" + address.Port); m_ProxyServicePoint = proxyServicePoint; m_Address = address; m_ConnectionName = address.Scheme; m_Host = address.DnsSafeHost; m_Port = address.Port; m_IdlingQueue = defaultIdlingQueue; m_ConnectionLimit = defaultConnectionLimit; m_HostLoopbackGuess = TriState.Unspecified; m_LookupString = lookupString; m_UserChangedLimit = userChangedLimit; m_UseNagleAlgorithm = ServicePointManager.UseNagleAlgorithm; m_Expect100Continue = ServicePointManager.Expect100Continue; m_ConnectionGroupList = new Hashtable(10); m_ConnectionLeaseTimeout = System.Threading.Timeout.Infinite; m_ReceiveBufferSize = -1; m_UseTcpKeepAlive = ServicePointManager.s_UseTcpKeepAlive; m_TcpKeepAliveTime = ServicePointManager.s_TcpKeepAliveTime; m_TcpKeepAliveInterval = ServicePointManager.s_TcpKeepAliveInterval; // it would be safer to make sure the server is 1.1 // but assume it is at the beginning, and update it later m_Understands100Continue = true; m_HttpBehaviour = HttpBehaviour.Unknown; // upon creation, the service point should be idle, by default m_IdleSince = DateTime.Now; m_ExpiringTimer = m_IdlingQueue.CreateTimer(ServicePointManager.IdleServicePointTimeoutDelegate, this); m_IdleConnectionGroupTimeoutDelegate = new TimerThread.Callback(IdleConnectionGroupTimeoutCallback); }