private int ReadCore(byte[] buffer, int offset, int size) { uint dataRead = 0; if (_dataChunkIndex != -1) { dataRead = Interop.HttpApi.GetChunks(_httpContext.Request.RequestBuffer, _httpContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); } if (_dataChunkIndex == -1 && dataRead < size) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "size:" + size + " offset:" + offset); } uint statusCode = 0; uint extraDataRead = 0; offset += (int)dataRead; size -= (int)dataRead; //the http.sys team recommends that we limit the size to 128kb if (size > MaxReadSize) { size = MaxReadSize; } fixed(byte *pBuffer = buffer) { // issue unmanaged blocking call if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpReceiveRequestEntityBody"); } uint flags = 0; if (!_inOpaqueMode) { flags = (uint)Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY; } statusCode = Interop.HttpApi.HttpReceiveRequestEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, flags, (void *)(pBuffer + offset), (uint)size, out extraDataRead, null); dataRead += extraDataRead; if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } throw exception; } UpdateAfterRead(statusCode, dataRead); } if (NetEventSource.IsEnabled) { NetEventSource.DumpBuffer(this, buffer, offset, (int)dataRead); NetEventSource.Info(this, "returning dataRead:" + dataRead); NetEventSource.Exit(this, "dataRead:" + dataRead); } return((int)dataRead); }
protected override void Dispose(bool disposing) { if (NetEventSource.IsEnabled) { NetEventSource.Enter(this); } try { if (disposing) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "_closed:" + _closed); } if (_closed) { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } return; } _closed = true; Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_leftToWrite > 0 && !_inOpaqueMode) { throw new InvalidOperationException(SR.net_io_notenoughbyteswritten); } bool sentHeaders = _httpContext.Response.SentHeaders; if (sentHeaders && _leftToWrite == 0) { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } return; } uint statusCode = 0; if ((_httpContext.Response.BoundaryType == BoundaryType.Chunked || _httpContext.Response.BoundaryType == BoundaryType.None) && (String.Compare(_httpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) != 0)) { if (_httpContext.Response.BoundaryType == BoundaryType.None) { flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } fixed(void *pBuffer = &s_chunkTerminator[0]) { Interop.HttpApi.HTTP_DATA_CHUNK *pDataChunk = null; if (_httpContext.Response.BoundaryType == BoundaryType.Chunked) { Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = new Interop.HttpApi.HTTP_DATA_CHUNK(); dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte *)pBuffer; dataChunk.BufferLength = (uint)s_chunkTerminator.Length; pDataChunk = &dataChunk; } if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(pDataChunk, null, flags, false); } else { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, pDataChunk != null ? (ushort)1 : (ushort)0, pDataChunk, null, SafeLocalAllocHandle.Zero, 0, null, null); if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } if (_httpContext.Listener.IgnoreWriteExceptions) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Suppressing error"); } statusCode = Interop.HttpApi.ERROR_SUCCESS; } } } } else { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, null, flags, false); } } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } _httpContext.Abort(); throw exception; } _leftToWrite = 0; } } finally { base.Dispose(disposing); } if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } }
public IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (size == 0 || _closed) { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } HttpRequestStreamAsyncResult result = new HttpRequestStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return(result); } HttpRequestStreamAsyncResult asyncResult = null; uint dataRead = 0; if (_dataChunkIndex != -1) { dataRead = Interop.HttpApi.GetChunks(_httpContext.Request.RequestBuffer, _httpContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); if (_dataChunkIndex != -1 && dataRead == size) { asyncResult = new HttpRequestStreamAsyncResult(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, 0); asyncResult.InvokeCallback(dataRead); } } if (_dataChunkIndex == -1 && dataRead < size) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "size:" + size + " offset:" + offset); } uint statusCode = 0; offset += (int)dataRead; size -= (int)dataRead; //the http.sys team recommends that we limit the size to 128kb if (size > MaxReadSize) { size = MaxReadSize; } asyncResult = new HttpRequestStreamAsyncResult(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, dataRead); uint bytesReturned; try { fixed(byte *pBuffer = buffer) { // issue unmanaged blocking call if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpReceiveRequestEntityBody"); } uint flags = 0; if (!_inOpaqueMode) { flags = (uint)Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY; } statusCode = Interop.HttpApi.HttpReceiveRequestEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, flags, asyncResult._pPinnedBuffer, (uint)size, out bytesReturned, asyncResult._pOverlapped); if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead); } } } catch (Exception e) { if (NetEventSource.IsEnabled) { NetEventSource.Error(this, e.ToString()); } asyncResult.InternalCleanup(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (statusCode == Interop.HttpApi.ERROR_HANDLE_EOF) { asyncResult = new HttpRequestStreamAsyncResult(this, state, callback, dataRead); asyncResult.InvokeCallback((uint)0); } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } asyncResult.InternalCleanup(); throw exception; } } else if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesReturned); } } if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } return(asyncResult); }
public override void Write(byte[] buffer, int offset, int size) { if (NetEventSource.IsEnabled) { NetEventSource.Enter(this); NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " size:" + size + " offset:" + offset); } if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (size < 0 || size > buffer.Length - offset) { throw new ArgumentOutOfRangeException(nameof(size)); } Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_closed || (size == 0 && _leftToWrite != 0)) { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } return; } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint dataToWrite = (uint)size; SafeLocalAllocHandle bufferAsIntPtr = null; IntPtr pBufferAsIntPtr = IntPtr.Zero; bool sentHeaders = _httpContext.Response.SentHeaders; try { if (size == 0) { statusCode = _httpContext.Response.SendHeaders(null, null, flags, false); } else { fixed(byte *pDataBuffer = buffer) { byte *pBuffer = pDataBuffer; if (_httpContext.Response.BoundaryType == BoundaryType.Chunked) { string chunkHeader = size.ToString("x", CultureInfo.InvariantCulture); dataToWrite = dataToWrite + (uint)(chunkHeader.Length + 4); bufferAsIntPtr = SafeLocalAllocHandle.LocalAlloc((int)dataToWrite); pBufferAsIntPtr = bufferAsIntPtr.DangerousGetHandle(); for (int i = 0; i < chunkHeader.Length; i++) { Marshal.WriteByte(pBufferAsIntPtr, i, (byte)chunkHeader[i]); } Marshal.WriteInt16(pBufferAsIntPtr, chunkHeader.Length, 0x0A0D); Marshal.Copy(buffer, offset, pBufferAsIntPtr + chunkHeader.Length + 2, size); Marshal.WriteInt16(pBufferAsIntPtr, (int)(dataToWrite - 2), 0x0A0D); pBuffer = (byte *)pBufferAsIntPtr; offset = 0; } Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = new Interop.HttpApi.HTTP_DATA_CHUNK(); dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte *)(pBuffer + offset); dataChunk.BufferLength = dataToWrite; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(&dataChunk, null, flags, false); } else { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, 1, &dataChunk, null, SafeLocalAllocHandle.Zero, 0, null, null); if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } if (_httpContext.Listener.IgnoreWriteExceptions) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Write() suppressing error"); } statusCode = Interop.HttpApi.ERROR_SUCCESS; } } } } } finally { // free unmanaged buffer bufferAsIntPtr?.Close(); } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } _closed = true; _httpContext.Abort(); throw exception; } UpdateAfterWrite(dataToWrite); if (NetEventSource.IsEnabled) { NetEventSource.DumpBuffer(this, buffer, offset, (int)dataToWrite); } if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " size:" + size + " offset:" + offset); } if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (size < 0 || size > buffer.Length - offset) { throw new ArgumentOutOfRangeException(nameof(size)); } Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_closed || (size == 0 && _leftToWrite != 0)) { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return(result); } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint bytesSent = 0; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = _httpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle); // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite. UpdateAfterWrite((uint)((_httpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size)); try { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, asyncResult, flags, false); } else { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, &bytesSent, SafeLocalAllocHandle.Zero, 0, asyncResult._pOverlapped, null); if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } } } catch (Exception e) { if (NetEventSource.IsEnabled) { NetEventSource.Error(this, e.ToString()); } asyncResult.InternalCleanup(); _closed = true; _httpContext.Abort(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (_httpContext.Listener.IgnoreWriteExceptions && sentHeaders) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "BeginWrite() Suppressing error"); } } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(this, exception.ToString()); } _closed = true; _httpContext.Abort(); throw exception; } } if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. asyncResult.IOCompleted(statusCode, bytesSent); } // Last write, cache it for special cancelation handling. if ((flags & Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0) { _lastWrite = asyncResult; } if (NetEventSource.IsEnabled) { NetEventSource.Exit(this); } return(asyncResult); }
private IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback?callback, object?state) { Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (_closed || (size == 0 && _leftToWrite != 0)) { HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback); result.InvokeCallback((uint)0); return(result); } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint bytesSent = 0; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; bool sentHeaders = _httpContext.Response.SentHeaders; HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle); // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite. UpdateAfterWrite((uint)((_httpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size)); try { if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(null, asyncResult, flags, false); } else { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, &bytesSent, SafeLocalAllocHandle.Zero, 0, asyncResult._pOverlapped, null); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } } } catch (Exception e) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(this, e.ToString()); } asyncResult.InternalCleanup(); _closed = true; _httpContext.Abort(); throw; } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { asyncResult.InternalCleanup(); if (_httpContext.Listener !.IgnoreWriteExceptions && sentHeaders) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "BeginWrite() Suppressing error"); } } else { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(this, exception.ToString()); } _closed = true; _httpContext.Abort(); throw exception; } }
// // Security: We temporarily reset thread token to open the cert store under process account. // internal static X509Store EnsureStoreOpened(bool isMachineStore) { X509Store store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx; // TODO #3862 Investigate if this can be switched to either the static or Lazy<T> patterns. if (store == null) { lock (s_syncObject) { store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx; if (store == null) { // NOTE: that if this call fails we won't keep track and the next time we enter we will try to open the store again. StoreLocation storeLocation = isMachineStore ? StoreLocation.LocalMachine : StoreLocation.CurrentUser; store = new X509Store(StoreName.My, storeLocation); try { // For app-compat We want to ensure the store is opened under the **process** account. try { WindowsIdentity.RunImpersonated(SafeAccessTokenHandle.InvalidHandle, () => { store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"storeLocation {storeLocation} returned store: {store}"); } }); } catch { throw; } if (isMachineStore) { s_myMachineCertStoreEx = store; } else { s_myCertStoreEx = store; } return(store); } catch (Exception exception) { if (exception is CryptographicException || exception is SecurityException) { NetEventSource.Fail(null, $"Failed to open cert store, location: {storeLocation} exception: {exception}"); return(null); } if (NetEventSource.IsEnabled) { NetEventSource.Error(null, SR.Format(SR.net_log_open_store_failed, storeLocation, exception)); } throw; } } } } return(store); }
/// <summary> /// <para>Thread for the timer. Ignores all exceptions. If no activity occurs for a while, /// the thread will shut down.</para> /// </summary> private static void ThreadProc() { if (NetEventSource.IsEnabled) { NetEventSource.Enter(null); } #if DEBUG DebugThreadTracking.SetThreadSource(ThreadKinds.Timer); using (DebugThreadTracking.SetThreadKind(ThreadKinds.System | ThreadKinds.Async)) { #endif // Set this thread as a background thread. On AppDomain/Process shutdown, the thread will just be killed. Thread.CurrentThread.IsBackground = true; // Keep a permanent lock on s_Queues. This lets for example Shutdown() know when this thread isn't running. lock (s_queues) { // If shutdown was recently called, abort here. if (Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Running, (int)TimerThreadState.Running) != (int)TimerThreadState.Running) { return; } bool running = true; while (running) { try { s_threadReadyEvent.Reset(); while (true) { // Copy all the new queues to the real queues. Since only this thread modifies the real queues, it doesn't have to lock it. if (s_newQueues.Count > 0) { lock (s_newQueues) { for (LinkedListNode <WeakReference> node = s_newQueues.First; node != null; node = s_newQueues.First) { s_newQueues.Remove(node); s_queues.AddLast(node); } } } int now = Environment.TickCount; int nextTick = 0; bool haveNextTick = false; for (LinkedListNode <WeakReference> node = s_queues.First; node != null; /* node = node.Next must be done in the body */) { TimerQueue queue = (TimerQueue)node.Value.Target; if (queue == null) { LinkedListNode <WeakReference> next = node.Next; s_queues.Remove(node); node = next; continue; } // Fire() will always return values that should be interpreted as later than 'now' (that is, even if 'now' is // returned, it is 0x100000000 milliseconds in the future). There's also a chance that Fire() will return a value // intended as > 0x100000000 milliseconds from 'now'. Either case will just cause an extra scan through the timers. int nextTickInstance; if (queue.Fire(out nextTickInstance) && (!haveNextTick || IsTickBetween(now, nextTick, nextTickInstance))) { nextTick = nextTickInstance; haveNextTick = true; } node = node.Next; } // Figure out how long to wait, taking into account how long the loop took. // Add 15 ms to compensate for poor TickCount resolution (want to guarantee a firing). int newNow = Environment.TickCount; int waitDuration = haveNextTick ? (int)(IsTickBetween(now, nextTick, newNow) ? Math.Min(unchecked ((uint)(nextTick - newNow)), (uint)(int.MaxValue - TickCountResolution)) + TickCountResolution : 0) : ThreadIdleTimeoutMilliseconds; if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"Waiting for {waitDuration}ms"); } int waitResult = WaitHandle.WaitAny(s_threadEvents, waitDuration, false); // 0 is s_ThreadShutdownEvent - die. if (waitResult == 0) { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, "Awoke, cause: Shutdown"); } running = false; break; } if (NetEventSource.IsEnabled) { NetEventSource.Info(null, $"Awoke, cause {(waitResult == WaitHandle.WaitTimeout ? "Timeout" : "Prod")}"); } // If we timed out with nothing to do, shut down. if (waitResult == WaitHandle.WaitTimeout && !haveNextTick) { Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Idle, (int)TimerThreadState.Running); // There could have been one more prod between the wait and the exchange. Check, and abort if necessary. if (s_threadReadyEvent.WaitOne(0, false)) { if (Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Running, (int)TimerThreadState.Idle) == (int)TimerThreadState.Idle) { continue; } } running = false; break; } } } catch (Exception exception) { if (ExceptionCheck.IsFatal(exception)) { throw; } if (NetEventSource.IsEnabled) { NetEventSource.Error(null, exception); } // The only options are to continue processing and likely enter an error-loop, // shut down timers for this AppDomain, or shut down the AppDomain. Go with shutting // down the AppDomain in debug, and going into a loop in retail, but try to make the // loop somewhat slow. Note that in retail, this can only be triggered by OutOfMemory or StackOverflow, // or an exception thrown within TimerThread - the rest are caught in Fire(). #if !DEBUG Thread.Sleep(1000); #else throw; #endif } } } if (NetEventSource.IsEnabled) { NetEventSource.Info(null, "Stop"); } #if DEBUG } #endif }
/// <summary> /// <para>Fires the timer if it is still active and has expired. Returns /// true if it can be deleted, or false if it is still timing.</para> /// </summary> internal bool Fire() { if (_timerState == TimerState.Sentinel) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "TimerQueue tried to Fire a Sentinel."); } } if (_timerState != TimerState.Ready) { return(true); } // Must get the current tick count within this method so it is guaranteed not to be before // StartTime, which is set in the constructor. int nowMilliseconds = Environment.TickCount; if (IsTickBetween(StartTime, Expiration, nowMilliseconds)) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, $"TimerThreadTimer#{StartTime}::Fire() Not firing ({StartTime} <= {nowMilliseconds} < {Expiration})"); } return(false); } bool needCallback = false; lock (_queueLock) { if (_timerState == TimerState.Ready) { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, $"TimerThreadTimer#{StartTime}::Fire() Firing ({StartTime} <= {nowMilliseconds} >= " + Expiration + ")"); } _timerState = TimerState.Fired; // Remove it from the list. Next.Prev = Prev; Prev.Next = Next; Next = null; Prev = null; needCallback = _callback != null; } } if (needCallback) { try { Callback callback = _callback; object context = _context; _callback = null; _context = null; callback(this, nowMilliseconds, context); } catch (Exception exception) { if (ExceptionCheck.IsFatal(exception)) { throw; } if (NetEventSource.IsEnabled) { NetEventSource.Error(this, $"exception in callback: {exception}"); } // This thread is not allowed to go into user code, so we should never get an exception here. // So, in debug, throw it up, killing the AppDomain. In release, we'll just ignore it. #if DEBUG throw; #endif } } return(true); }
} // GetHostByAddress // Does internal IPAddress reverse and then forward lookups (for Legacy and current public methods). private static IPHostEntry InternalGetHostByAddress(IPAddress address, bool includeIPv6) { if (NetEventSource.IsEnabled) { NetEventSource.Info(null, address); } // // IPv6 Changes: We need to use the new getnameinfo / getaddrinfo functions // for resolution of IPv6 addresses. // if (SocketProtocolSupportPal.OSSupportsIPv6 || includeIPv6) { // // Try to get the data for the host from it's address // // We need to call getnameinfo first, because getaddrinfo w/ the ipaddress string // will only return that address and not the full list. // Do a reverse lookup to get the host name. SocketError errorCode; int nativeErrorCode; string name = NameResolutionPal.TryGetNameInfo(address, out errorCode, out nativeErrorCode); if (errorCode == SocketError.Success) { // Do the forward lookup to get the IPs for that host name IPHostEntry hostEntry; errorCode = NameResolutionPal.TryGetAddrInfo(name, out hostEntry, out nativeErrorCode); if (errorCode == SocketError.Success) { return(hostEntry); } if (NetEventSource.IsEnabled) { NetEventSource.Error(null, SocketExceptionFactory.CreateSocketException(errorCode, nativeErrorCode)); } // One of two things happened: // 1. There was a ptr record in dns, but not a corollary A/AAA record. // 2. The IP was a local (non-loopback) IP that resolved to a connection specific dns suffix. // - Workaround, Check "Use this connection's dns suffix in dns registration" on that network // adapter's advanced dns settings. // Just return the resolved host name and no IPs. return(hostEntry); } throw SocketExceptionFactory.CreateSocketException(errorCode, nativeErrorCode); } // // If IPv6 is not enabled (maybe config switch) but we've been // given an IPv6 address then we need to bail out now. // else { if (address.AddressFamily == AddressFamily.InterNetworkV6) { // // Protocol not supported // throw new SocketException((int)SocketError.ProtocolNotSupported); } // // Use gethostbyaddr() to try to resolve the IP address // // End IPv6 Changes // return(NameResolutionPal.GetHostByAddr(address)); } } // InternalGetHostByAddress
internal static X509Store?EnsureStoreOpened(bool isMachineStore) { X509Store?store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx; if (store == null) { StoreLocation storeLocation = isMachineStore ? StoreLocation.LocalMachine : StoreLocation.CurrentUser; // On Windows and OSX CheckSupportsStore is not defined, so the call is eliminated and the // if should be folded out. // // On Unix it will prevent the lock from being held and released over and over for the LocalMachine store. bool supportsStore = true; CheckSupportsStore(storeLocation, ref supportsStore); if (!supportsStore) { return(null); } lock (s_syncObject) { store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx; if (store == null) { try { // NOTE: that if this call fails we won't keep track and the next time we enter we will try to open the store again. store = OpenStore(storeLocation); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(null, $"storeLocation: {storeLocation} returned store {store}"); } if (isMachineStore) { s_myMachineCertStoreEx = store; } else { s_myCertStoreEx = store; } } catch (Exception exception) { if (exception is CryptographicException || exception is SecurityException) { Debug.Fail($"Failed to open cert store, location: {storeLocation} exception: {exception}"); return(null); } if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, SR.Format(SR.net_log_open_store_failed, storeLocation, exception)); } throw; } } } } return(store); }
private static unsafe int EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) { Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(input.Length); var unmanagedBuffer = new Interop.SspiCli.SecBuffer[input.Length]; fixed(Interop.SspiCli.SecBuffer *unmanagedBufferPtr = unmanagedBuffer) { sdcInOut.pBuffers = unmanagedBufferPtr; GCHandle[] pinnedBuffers = new GCHandle[input.Length]; byte[][] buffers = new byte[input.Length][]; try { for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; unmanagedBuffer[i].cbBuffer = iBuffer.size; unmanagedBuffer[i].BufferType = iBuffer.type; if (iBuffer.token == null || iBuffer.token.Length == 0) { unmanagedBuffer[i].pvBuffer = IntPtr.Zero; } else { pinnedBuffers[i] = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned); unmanagedBuffer[i].pvBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset); buffers[i] = iBuffer.token; } } // The result is written in the input Buffer passed as type=BufferType.Data. int errorCode; switch (op) { case OP.Encrypt: errorCode = secModule.EncryptMessage(context, ref sdcInOut, sequenceNumber); break; case OP.Decrypt: errorCode = secModule.DecryptMessage(context, ref sdcInOut, sequenceNumber); break; case OP.MakeSignature: errorCode = secModule.MakeSignature(context, ref sdcInOut, sequenceNumber); break; case OP.VerifySignature: errorCode = secModule.VerifySignature(context, ref sdcInOut, sequenceNumber); break; default: NetEventSource.Fail(null, $"Unknown OP: {op}"); throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); } // Marshalling back returned sizes / data. for (int i = 0; i < input.Length; i++) { SecurityBuffer iBuffer = input[i]; iBuffer.size = unmanagedBuffer[i].cbBuffer; iBuffer.type = unmanagedBuffer[i].BufferType; if (iBuffer.size == 0) { iBuffer.offset = 0; iBuffer.token = null; } else { checked { // Find the buffer this is inside of. Usually they all point inside buffer 0. int j; for (j = 0; j < input.Length; j++) { if (buffers[j] == null) { continue; } byte *bufferAddress = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(buffers[j], 0); if ((byte *)unmanagedBuffer[i].pvBuffer >= bufferAddress && (byte *)unmanagedBuffer[i].pvBuffer + iBuffer.size <= bufferAddress + buffers[j].Length) { iBuffer.offset = (int)((byte *)unmanagedBuffer[i].pvBuffer - bufferAddress); iBuffer.token = buffers[j]; break; } } if (j >= input.Length) { NetEventSource.Fail(null, "Output buffer out of range."); iBuffer.size = 0; iBuffer.offset = 0; iBuffer.token = null; } } } // Backup validate the new sizes. if (iBuffer.offset < 0 || iBuffer.offset > (iBuffer.token == null ? 0 : iBuffer.token.Length)) { NetEventSource.Fail(null, $"'offset' out of range. [{iBuffer.offset}]"); } if (iBuffer.size < 0 || iBuffer.size > (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset)) { NetEventSource.Fail(null, $"'size' out of range. [{iBuffer.size}]"); } } if (NetEventSource.IsEnabled && errorCode != 0) { if (errorCode == Interop.SspiCli.SEC_I_RENEGOTIATE) { NetEventSource.Error(null, SR.Format(SR.event_OperationReturnedSomething, op, "SEC_I_RENEGOTIATE")); } else { NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, op, $"0x{0:X}")); } } return(errorCode); } finally { for (int i = 0; i < pinnedBuffers.Length; ++i) { if (pinnedBuffers[i].IsAllocated) { pinnedBuffers[i].Free(); } } } } }