/// <summary> /// Accepts incoming connections. /// </summary> public void AcceptConnections() { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; byte protocolVersion; GenuineConnectionType genuineConnectionType; try { IParameterProvider parameters = this.ITransportContext.IParameterProvider; string mutexName = GenuineSharedMemoryChannel.ConstructSharedObjectName( "MUTEX" + this.ShareName, parameters); string clientConnected = GenuineSharedMemoryChannel.ConstructSharedObjectName( "CC" + this.ShareName, parameters); string clientAccepted = GenuineSharedMemoryChannel.ConstructSharedObjectName( "CA" + this.ShareName, parameters); this._mutex = WindowsAPI.CreateMutex(mutexName); this._clientConnectedEvent = NamedEvent.CreateNamedEvent(clientConnected, false, false); this._clientAcceptedEvent = NamedEvent.CreateNamedEvent(clientAccepted, false, true); WaitHandle[] handles = new WaitHandle[2] { this._clientConnectedEvent.ManualResetEvent, this.StopListening }; for ( ; ;) { try { // listen WaitHandle.WaitAny(handles); // if shutting down if (this.StopListening.WaitOne(0, false)) { return; } // set timeout int timeout = GenuineUtility.GetTimeout((TimeSpan)this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout]); // client is connecting using (Stream headerStream = this.SharedMemoryConnection.LowLevel_ReadSync(timeout)) { BinaryReader binaryReader = new BinaryReader(headerStream); string connectionId; MessageCoder.DeserializeConnectionHeader(binaryReader, out protocolVersion, out genuineConnectionType, out connectionId); string shareName = binaryReader.ReadString(); this._clientAcceptedEvent.ManualResetEvent.Set(); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0) { binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "SMAcceptConnectionClosure.AcceptConnections", LogMessageType.ConnectionAccepting, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "An inbound Shared Memory connection is being accepted."); } AcceptConnectionInformation acceptConnectionInformation = new AcceptConnectionInformation(); acceptConnectionInformation.ShareName = shareName; acceptConnectionInformation.ProtocolVersion = protocolVersion; GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.AcceptConnection), acceptConnectionInformation, true); } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0) { binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "SMAcceptConnectionClosure.AcceptConnections", LogMessageType.ConnectionAccepting, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Can't accept a connection."); } } } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.AcceptingConnection] > 0) { binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "SMAcceptConnectionClosure.AcceptConnections", LogMessageType.CriticalError, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Critical listener failure. No connections will be accepted."); } this.SharedMemoryConnectionManager.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GeneralListenerFailure, ex, null, this.ShareName)); } finally { this.SharedMemoryConnection.ReleaseUnmanagedResources(); if (this._mutex != null) { this._mutex.Close(); } } }
/// <summary> /// Constructs an instance of the SharedMemoryConnection class. /// </summary> /// <param name="iTransportContext">The transport context.</param> /// <param name="name">The name of the shared chunk.</param> /// <param name="isServer">The role.</param> /// <param name="setCloseStatusOnExit">Indicates whether it is necessary to set the "closed" status on exit.</param> internal SharedMemoryConnection(ITransportContext iTransportContext, string name, bool isServer, bool setCloseStatusOnExit) { this.ITransportContext = iTransportContext; this.ShareName = "GenuineChannels_GShMem_" + name; this.IsServer = isServer; this._setCloseStatusOnExit = setCloseStatusOnExit; this._shareSize = (int)iTransportContext.IParameterProvider[GenuineParameter.SMShareSize]; this._pingTimeOut = GenuineUtility.ConvertToMilliseconds(iTransportContext.IParameterProvider[GenuineParameter.PersistentConnectionSendPingAfterInactivity]); this._closeAfterInactivity = GenuineUtility.ConvertToMilliseconds(iTransportContext.IParameterProvider[GenuineParameter.ClosePersistentConnectionAfterInactivity]); string localSideName = (isServer ? "Server" : "Client"); string remoteSideName = (isServer ? "Client" : "Server"); IParameterProvider parameters = this.ITransportContext.IParameterProvider; // construct shared object names for the local side string readCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName( this.ShareName + localSideName + "ReadCompleted", parameters); string writeCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName( this.ShareName + localSideName + "WriteCompleted", parameters); // construct shared object names for the remote side string remoteReadCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName( this.ShareName + remoteSideName + "ReadCompleted", parameters); string remoteWriteCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName( this.ShareName + remoteSideName + "WriteCompleted", parameters); if (isServer) { if (this._shareSize < MIN_SHARE_SIZE || this._shareSize > MAX_SHARE_SIZE) { throw GenuineExceptions.Get_Channel_InvalidParameter("SMShareSize"); } this.LowLevel_CreateSharedMemory(); this._closed = 0; this._writtenShareSize = this._shareSize; this._receiveOffset = 5; this._sendOffset = (this._shareSize - 5) / 2; this._receiveSpaceSize = this._sendOffset - 5 - 8; this._sendSpaceSize = this._shareSize - this._sendOffset - 8; this._namedEventReadCompleted = NamedEvent.CreateNamedEvent(readCompletedEventName, false, true); this._namedEventWriteCompleted = NamedEvent.CreateNamedEvent(writeCompletedEventName, false, true); this._namedEventRemoteReadCompleted = NamedEvent.CreateNamedEvent(remoteReadCompletedEventName, false, true); this._namedEventRemoteWriteCompleted = NamedEvent.CreateNamedEvent(remoteWriteCompletedEventName, false, true); } else { this.OpenSharedMemory(); if (this._closed != 0) { throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(name, "Remote host has already closed the connection."); } this._shareSize = this._writtenShareSize; if (this._shareSize < MIN_SHARE_SIZE || this._shareSize > MAX_SHARE_SIZE) { throw GenuineExceptions.Get_Channel_InvalidParameter("SMShareSize"); } this._receiveOffset = (this._shareSize - 5) / 2; this._sendOffset = 5; this._receiveSpaceSize = this._shareSize - this._receiveOffset - 8; this._sendSpaceSize = this._receiveOffset - 5 - 8; this._namedEventReadCompleted = NamedEvent.OpenNamedEvent(readCompletedEventName); this._namedEventWriteCompleted = NamedEvent.OpenNamedEvent(writeCompletedEventName); this._namedEventRemoteReadCompleted = NamedEvent.OpenNamedEvent(remoteReadCompletedEventName); this._namedEventRemoteWriteCompleted = NamedEvent.OpenNamedEvent(remoteWriteCompletedEventName); } this._sendBuffer = new byte[this._sendSpaceSize]; }