/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { _disposed = true; Timer timer = Interlocked.Exchange(ref _connectionCheckTimer, null); if (timer != null) { timer.Change(Timeout.Infinite, Timeout.Infinite); timer.Dispose(); } NamedPipeServerLogger logger = Interlocked.Exchange(ref _logger, null); if (logger != null) { Log.RemoveLogger(logger); logger.Dispose(); } lock (_namedPipeConnections) { foreach (NamedPipeConnection connection in _namedPipeConnections.ToArray()) { // ReSharper disable once PossibleNullReferenceException connection.OnDisconnect(); } // Should already be clear, but do anyway. _namedPipeConnections.Clear(); } }
/// <summary> /// Initializes a new instance of the <see cref="NamedPipeServer" /> class. /// </summary> /// <param name="service">The service.</param> /// <param name="configuration">The configuration.</param> /// <exception cref="ServiceException"> /// </exception> public NamedPipeServer( [NotNull] BaseService service, [NotNull] ServerConfig configuration) { if (service == null) { throw new ArgumentNullException("service"); } if (configuration == null) { throw new ArgumentNullException("configuration"); } if (configuration.MaximumConnections < 1) { throw new ArgumentOutOfRangeException("configuration", CommonResources.NamedPipeServer_MaxConnections); } Service = service; MaximumConnections = configuration.MaximumConnections; if (!string.IsNullOrWhiteSpace(configuration.Name)) { // ReSharper disable once AssignNullToNotNullAttribute Name = configuration.Name; } else { StringBuilder builder = new StringBuilder(); builder.Append(Guid.NewGuid().ToString("D")) .Append('_'); Debug.Assert(service.ServiceName != null); foreach (char c in service.ServiceName) { builder.Append(char.IsLetterOrDigit(c) ? c : '_'); } builder.Append(Constants.NameSuffix); Name = builder.ToString(); } // Create security context try { WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent(); if (currentIdentity == null || currentIdentity.Owner == null) { throw new ServiceException(() => ServiceResources.Err_NamedPipeServer_CannotGetCurrentOwner); } _pipeSecurity = new PipeSecurity(); _pipeSecurity.AddAccessRule( new PipeAccessRule( configuration.Identity, PipeAccessRights.ReadWrite, AccessControlType.Allow)); _pipeSecurity.AddAccessRule( new PipeAccessRule( currentIdentity.Owner, PipeAccessRights.FullControl, AccessControlType.Allow)); } catch (Exception exception) { throw new ServiceException(exception, () => ServiceResources.Err_NamedPipeServer_Fatal_Error_Securing); } // Check no one has tried to create the pipe before us, combined with the GUID name this makes the most common // form of pipe attack (pre-registration) impossible. if (File.Exists(@"\\.\pipe\" + Name)) { throw new ServiceException(() => ServiceResources.Err_NamedPipeServer_PipeAlreadyExists); } // Create a connection, before adding it to the list and starting. NamedPipeConnection connection = new NamedPipeConnection(this); _namedPipeConnections = new List <NamedPipeConnection>(MaximumConnections) { connection }; connection.Start(); _logger = new NamedPipeServerLogger(this); Log.AddLogger(_logger); _heartbeat = configuration.Heartbeat; if (_heartbeat < TimeSpan.Zero) { return; } _connectionCheckTimer = new Timer(CheckConnections); _connectionCheckTimer.Change(_heartbeat, Timeout.InfiniteTimeSpan); }
/// <summary> /// Initializes a new instance of the <see cref="NamedPipeServer" /> class. /// </summary> /// <param name="service">The service.</param> /// <param name="configuration">The configuration.</param> /// <exception cref="ServiceException"> /// </exception> public NamedPipeServer( [NotNull] BaseService service, [NotNull] ServerConfig configuration) { if (service == null) throw new ArgumentNullException("service"); if (configuration == null) throw new ArgumentNullException("configuration"); if (configuration.MaximumConnections < 1) throw new ArgumentOutOfRangeException("configuration", CommonResources.NamedPipeServer_MaxConnections); Service = service; MaximumConnections = configuration.MaximumConnections; if (!string.IsNullOrWhiteSpace(configuration.Name)) // ReSharper disable once AssignNullToNotNullAttribute Name = configuration.Name; else { StringBuilder builder = new StringBuilder(); builder.Append(Guid.NewGuid().ToString("D")) .Append('_'); Debug.Assert(service.ServiceName != null); foreach (char c in service.ServiceName) builder.Append(char.IsLetterOrDigit(c) ? c : '_'); builder.Append(Constants.NameSuffix); Name = builder.ToString(); } // Create security context try { WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent(); if (currentIdentity == null || currentIdentity.Owner == null) throw new ServiceException(() => ServiceResources.Err_NamedPipeServer_CannotGetCurrentOwner); _pipeSecurity = new PipeSecurity(); _pipeSecurity.AddAccessRule( new PipeAccessRule( configuration.Identity, PipeAccessRights.ReadWrite, AccessControlType.Allow)); _pipeSecurity.AddAccessRule( new PipeAccessRule( currentIdentity.Owner, PipeAccessRights.FullControl, AccessControlType.Allow)); } catch (Exception exception) { throw new ServiceException(exception, () => ServiceResources.Err_NamedPipeServer_Fatal_Error_Securing); } // Check no one has tried to create the pipe before us, combined with the GUID name this makes the most common // form of pipe attack (pre-registration) impossible. if (File.Exists(@"\\.\pipe\" + Name)) throw new ServiceException(() => ServiceResources.Err_NamedPipeServer_PipeAlreadyExists); // Create a connection, before adding it to the list and starting. NamedPipeConnection connection = new NamedPipeConnection(this); _namedPipeConnections = new List<NamedPipeConnection>(MaximumConnections) { connection }; connection.Start(); _logger = new NamedPipeServerLogger(this); Log.AddLogger(_logger); _heartbeat = configuration.Heartbeat; if (_heartbeat < TimeSpan.Zero) return; _connectionCheckTimer = new Timer(CheckConnections); _connectionCheckTimer.Change(_heartbeat, Timeout.InfiniteTimeSpan); }