/// <summary> /// Creates shared memory object. /// </summary> public void LowLevel_CreateSharedMemory() { if (WindowsAPI.FailureReason != null) { throw OperationException.WrapException(WindowsAPI.FailureReason); } IParameterProvider parameters = this.ITransportContext.IParameterProvider; string fileMappingName = GenuineSharedMemoryChannel.ConstructSharedObjectName( this.ShareName, parameters); this._mapHandle = WindowsAPI.CreateFileMapping((IntPtr)(int)-1, WindowsAPI.AttributesWithNullDACL, WindowsAPI.PAGE_READWRITE, 0, (uint)this._shareSize, fileMappingName); if (this._mapHandle == IntPtr.Zero) { throw GenuineExceptions.Get_Windows_CanNotCreateOrOpenSharedMemory(Marshal.GetLastWin32Error()); } this._pointer = WindowsAPI.MapViewOfFile(this._mapHandle, WindowsAPI.SECTION_MAP_READ | WindowsAPI.SECTION_MAP_WRITE, 0, 0, 0); if (this._pointer == IntPtr.Zero) { int lastWinError = Marshal.GetLastWin32Error(); WindowsAPI.CloseHandle(this._mapHandle); throw GenuineExceptions.Get_Windows_SharedMemoryError(lastWinError); } }
/// <summary> /// Sends the content to the specified remote host and returns a response sent by the remote /// host in reply. /// </summary> /// <param name="destination">The remote host.</param> /// <param name="serviceName">The name of the service.</param> /// <param name="content">The content.</param> /// <returns>The response.</returns> public Stream SendSync(HostInformation destination, string serviceName, Stream content) { // create the message Message message = new Message(this.ITransportContext, destination, 0, new TransportHeaders(), content); message.IsSynchronous = true; message.GenuineMessageType = GenuineMessageType.ExternalStreamConsumer; message.DestinationMarshalByRef = serviceName; // register the response catcher SyncResponseProcessorWithEvent syncResponseProcessorWithEvent = new SyncResponseProcessorWithEvent(message); this.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, syncResponseProcessorWithEvent); // and send the message this.ITransportContext.ConnectionManager.Send(message); int timeSpanInMilliseconds = GenuineUtility.GetMillisecondsLeft(message.FinishTime); if (timeSpanInMilliseconds <= 0) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } if (!syncResponseProcessorWithEvent.IsReceivedEvent.WaitOne(timeSpanInMilliseconds, false)) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } if (syncResponseProcessorWithEvent.DispatchedException != null) { throw OperationException.WrapException(syncResponseProcessorWithEvent.DispatchedException); } return(syncResponseProcessorWithEvent.Response.Stream); }
/// <summary> /// Renews the Security Session life time. /// The first call of this method is always reset the lifetime value to the specified value. /// </summary> /// <param name="timeSpan">A time period to renew all host-related information.</param> /// <param name="canMakeShorter">Indicates whether this call may reduce the host expiration time.</param> public void Renew(int timeSpan, bool canMakeShorter) { if (this._firstRenewing) { this._firstRenewing = false; canMakeShorter = true; } lock (this.DisposeLock) { if (this.IsDisposed) { throw OperationException.WrapException(this.DisposeReason); } lock (this._accessToLocalMembers) { int proposedTime = GenuineUtility.GetTimeout(timeSpan); if (canMakeShorter || GenuineUtility.IsTimeoutExpired(this._expireTime, proposedTime)) { this._expireTime = proposedTime; } } } }
/// <summary> /// Gets a Security Session. /// </summary> /// <param name="securitySessionName">The name of the Security Session.</param> /// <param name="keyStore">The store of all keys.</param> /// <returns>An object implementing ISecuritySession interface.</returns> public SecuritySession GetSecuritySession(string securitySessionName, IKeyStore keyStore) { lock (this.DisposeLock) { if (this.IsDisposed) { throw OperationException.WrapException(this.DisposeReason); } lock (_securitySessions) { SecuritySession iSecuritySession = _securitySessions[securitySessionName] as SecuritySession; if (iSecuritySession == null) { IKeyProvider iKeyProvider = keyStore.GetKey(securitySessionName); if (iKeyProvider == null) { throw GenuineExceptions.Get_Security_ContextNotFound(securitySessionName); } iSecuritySession = iKeyProvider.CreateSecuritySession(securitySessionName, this); _securitySessions[securitySessionName] = iSecuritySession; } return(iSecuritySession); } } }
/// <summary> /// Creates named event object. /// </summary> /// <param name="name">The name of the event object.</param> /// <param name="initialState">If this parameter is TRUE, the initial state of the event object is signaled; otherwise, it is nonsignaled.</param> /// <param name="manualReset">If this parameter is FALSE, the function creates an auto-reset event object, and system automatically resets the state to nonsignaled after a single waiting thread has been released.</param> /// <returns>Created event object.</returns> public static NamedEvent CreateNamedEvent(string name, bool initialState, bool manualReset) { if (WindowsAPI.FailureReason != null) { throw OperationException.WrapException(WindowsAPI.FailureReason); } IntPtr handler = WindowsAPI.CreateEvent(WindowsAPI.AttributesWithNullDACL, manualReset ? 1 : 0, (initialState ? 1 : 0), name); if (handler == IntPtr.Zero) { throw GenuineExceptions.Get_Windows_CanNotCreateOrOpenNamedEvent(Marshal.GetLastWin32Error()); } return(new NamedEvent(handler)); }
/// <summary> /// Destroys the Security Session with the specified name. /// Releases all Security Session resources. /// </summary> /// <param name="securitySessionName">The name of the Security Session.</param> public void DestroySecuritySession(string securitySessionName) { lock (this.DisposeLock) { if (this.IsDisposed) { throw OperationException.WrapException(this.DisposeReason); } lock (_securitySessions) { SecuritySession iSecuritySession = _securitySessions[securitySessionName] as SecuritySession; if (iSecuritySession != null) { IDisposable iDisposable = iSecuritySession as IDisposable; if (iDisposable != null) { iDisposable.Dispose(); } // LOG: BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0) { binaryLogWriter.WriteEvent(LogCategory.Security, "HostInformation.DestroySecuritySession", LogMessageType.SecuritySessionDestroyed, null, null, iSecuritySession.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, iSecuritySession, iSecuritySession.Name, -1, 0, 0, 0, iSecuritySession.GetType().Name, iSecuritySession.Name, null, null, "Security Session has been destroyed manually."); } _securitySessions.Remove(securitySessionName); } } } }
/// <summary> /// Increases all queue counters according to the provided message and /// puts a message into the queue. /// </summary> /// <param name="message">The message being put into the queue.</param> /// <param name="onlyCheckIn">Check the message in without adding it to any queues.</param> public void AddMessage(Message message, bool onlyCheckIn) { BinaryLogWriter binaryLogWriter = GenuineLoggingServices.BinaryLogWriter; using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) { throw OperationException.WrapException(this._disposeException); } int maxContentSize = 0; if (message.SecuritySessionParameters != null) { maxContentSize = message.SecuritySessionParameters.MaxContentSize; } if (maxContentSize == 0) { maxContentSize = this._maxContentSize; } if (maxContentSize > 0 && !this._noSizeChecking) { // calculate message effective size try { if (message.SerializedContent != null && message.SerializedContent.CanSeek) { message.EffectiveMessageSize = (int)message.SerializedContent.Length; } // else if (message.Stream != null && message.Stream.CanSeek) // message.EffectiveMessageSize = (int) message.Stream.Length; } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.ImplementationWarning] > 0) { binaryLogWriter.WriteEvent(LogCategory.ImplementationWarning, "MessageContainer.AddMessage", LogMessageType.Warning, ex, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Message stream doesn't support the Length property. Set the NoSizeChecking parameter to true to increase performance"); } } try { if (message.SerializedContent != null && message.EffectiveMessageSize == 0 && message.SerializedContent.CanSeek) { message.EffectiveMessageSize = Math.Min(message.EffectiveMessageSize, (int)message.SerializedContent.Length); } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.ImplementationWarning] > 0) { binaryLogWriter.WriteEvent(LogCategory.ImplementationWarning, "MessageContainer.AddMessage", LogMessageType.Warning, ex, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Message stream doesn't support the Length property. Set the NoSizeChecking parameter to true to increase performance"); } } // check the message size if (message.EffectiveMessageSize > maxContentSize) { throw GenuineExceptions.Get_Send_TooLargePacketSize((int)message.EffectiveMessageSize, maxContentSize); } } bool overloaded = false; lock (this._queue) { // check on total size if (this._currentTotalMessages + 1 > this._maxQueuedItems || message.EffectiveMessageSize + this._currentTotalSize > this._maxTotalSize) { // to prevent a deadlock overloaded = true; } else { this._currentTotalMessages++; this._currentTotalSize += message.EffectiveMessageSize; // put it into the queue or awaiting list if (!onlyCheckIn) { this._queue.Enqueue(message); // reflect the change in the queue state if (message.Recipient != null) { message.Recipient.QueueLength = this._queue.Count; } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "MessageContainer.AddMessage", LogMessageType.MessageIsEnqueued, null, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "The message has been enqueued because no connections are available. Messages in the queue: {0}. Queue size: {1}.", this._currentTotalMessages, this._currentTotalSize); } } } } // lock (this._queue) if (overloaded) { Exception exception = GenuineExceptions.Get_Send_QueueIsOverloaded(this._maxQueuedItems, this._currentTotalMessages + 1, this._maxTotalSize, message.EffectiveMessageSize + this._currentTotalSize); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "MessageContainer.AddMessage", LogMessageType.MessageIsEnqueued, exception, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "Queue is overrun."); } this.Dispose(exception); throw exception; } } }
/// <summary> /// Sends a message to the remote host. /// </summary> /// <param name="message">The message to be sent.</param> public void Send(Message message) { #if TRIAL _messagesBeingSent[message.MessageId] = message; #endif BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; try { using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) { throw OperationException.WrapException(this._disposeReason); } } SecuritySession session = null; if (this._disposed) { throw OperationException.WrapException(this._disposeReason); } // get the security session descriptor if (message.SecuritySessionParameters == null) { SecuritySessionParameters securitySessionParameters = SecuritySessionServices.GetCurrentSecurityContext(); if (securitySessionParameters == null) { securitySessionParameters = message.Recipient.SecuritySessionParameters; } if (securitySessionParameters == null) { securitySessionParameters = this.ITransportContext.SecuritySessionParameters; } if (securitySessionParameters == null) { securitySessionParameters = SecuritySessionServices.DefaultSecuritySession; } message.SecuritySessionParameters = securitySessionParameters; } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteSecuritySessionParametersEvent("ConnectionManager.Send", LogMessageType.SecuritySessionParametersAssembled, null, message, message.Recipient, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, message.SecuritySessionParameters, "Security Session Parameters have been assembled."); } // determine the type of sending message.IsSynchronous = (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceSync) != 0 || (message.IsSynchronous && (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceAsync) == 0); // the time until invocation times out if (!message.FinishTime_Initialized) { TimeSpan messageTimeout = message.SecuritySessionParameters.Timeout; if (messageTimeout == TimeSpan.MinValue) { messageTimeout = (TimeSpan)this.ITransportContext.IParameterProvider[GenuineParameter.InvocationTimeout]; } message.FinishTime = GenuineUtility.GetTimeout(messageTimeout); message.FinishTime_Initialized = true; } // checks whether the message has been already processed by Security Session if (message.SerializedContent == null) { session = message.Recipient.GetSecuritySession(message.SecuritySessionParameters.Name, this.ITransportContext.IKeyStore); if (!session.IsEstablished) { if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0) { binaryLogWriter.WriteEvent(LogCategory.Security, "ConnectionManager.Send", LogMessageType.SecuritySessionHasNotBeenEstablishedYet, null, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, session, session.Name, -1, 0, 0, 0, null, null, null, null, "The requested Security Session is not established."); } session.InitiateEstablishingSecuritySession(message.SecuritySessionParameters); // if it's a sync sending, then wait until security session will be established if (message.IsSynchronous) { int timeSpanToWait = GenuineUtility.GetMillisecondsLeft(message.FinishTime); if (timeSpanToWait <= 0) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } // wait until Security Session will be established or a failure will be detected int firedEvent = 0; if (message.CancelSending != null) { firedEvent = WaitHandle.WaitAny(new WaitHandle[] { session.IsEstablishedEvent, session.Failed, message.CancelSending }, timeSpanToWait, false); } else { firedEvent = WaitHandle.WaitAny(new WaitHandle[] { session.IsEstablishedEvent, session.Failed }, timeSpanToWait, false); } if (firedEvent == WaitHandle.WaitTimeout) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } // analyze the problem, if any Exception exception = session.ReasonOfFailure; if (firedEvent == 1) { if (exception != null) { throw OperationException.WrapException(exception); } else { throw GenuineExceptions.Get_Security_ContextWasNotEstablished(session.Name); } } // if the message has been cancelled, let the sender to understand the reason if (firedEvent == 2) { return; } } else if (!session.IsEstablished) { // it's async and SS still isn't established session.PutMessageToAwaitingQueue(message); return; } } } // if serialization is necessary if (message.SerializedContent == null) { // serialize the message GenuineChunkedStream serializedMessageStream = new GenuineChunkedStream(false); MessageCoder.Serialize(serializedMessageStream, message, (message.SecuritySessionParameters.Attributes & SecuritySessionAttributes.EnableCompression) != 0); // save the name of the Security Session GenuineChunkedStream resultStream = new GenuineChunkedStream(false); BinaryWriter writer = new BinaryWriter(resultStream); writer.Write(message.SecuritySessionParameters.Name); session.Encrypt(serializedMessageStream, resultStream); message.SerializedContent = resultStream; // LOG: put down the log record if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0) { binaryLogWriter.WriteEvent(LogCategory.Security, "ConnectionManager.Send", LogMessageType.SecuritySessionApplied, null, message, message.Recipient, binaryLogWriter[LogCategory.Security] > 1 ? message.SerializedContent : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, session, session.Name, -1, 0, 0, 0, null, null, null, null, "The message has been processed by the established Security Session."); } } #if TRIAL if (message.MessageId > 3005) { throw GenuineExceptions.Get_Channel_TrialConditionExceeded("The maximum number of messages restriction has been exceeded. You can not send more than 3000 messages using TRIAL version."); } #endif message.Sender = this.Local; this.InternalSend(message); } catch (Exception ex) { if (binaryLogWriter != null && binaryLogWriter[LogCategory.Security] > 0) { binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "ConnectionManager.Send", LogMessageType.Error, ex, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, null, null, null, null, "An exception occurred while processing the message."); } throw; } }
/// <summary> /// Accepts an incoming connection. /// </summary> /// <param name="url">The name of the share.</param> /// <param name="localUri">URI of the local host.</param> /// <param name="protocolVersion">The version of the protocol supported by the remote host.</param> /// <param name="remoteUri">Uri of the remote host.</param> /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param> /// <returns>The established connection.</returns> private SharedMemoryConnection LowLevel_AcceptConnection_1(string url, string localUri, byte protocolVersion, out string remoteUri, out int remoteHostUniqueIdentifier) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) { throw OperationException.WrapException(this._disposeReason); } } remoteUri = null; Stream inputStream = null; Stream outputStream = null; remoteHostUniqueIdentifier = 0; // the maximum time during which the connection must be established int timeout = GenuineUtility.GetTimeout((TimeSpan)this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout]); // open the client's share SharedMemoryConnection sharedMemoryConnection = new SharedMemoryConnection(this.ITransportContext, url, false, true); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "SharedMemoryConnectionManager.LowLevel_AcceptConnection", LogMessageType.ConnectionParameters, null, null, this.ITransportContext.IParameterProvider, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, sharedMemoryConnection.DbgConnectionId, "The connection is being established to \"{0}\".", url); } // get the connection-level Security Session string connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string; SecuritySession securitySession = null; if (connectionLevelSSName != null) { securitySession = this.ITransportContext.IKeyStore.GetKey(connectionLevelSSName).CreateSecuritySession(connectionLevelSSName, null); } // establish it if (securitySession != null && !securitySession.IsEstablished) { for ( ; ;) { inputStream = Stream.Null; try { // prepare streams inputStream = sharedMemoryConnection.LowLevel_ReadSync(timeout); outputStream = securitySession.EstablishSession(inputStream, true); if (outputStream == null) { break; } // send a packet to the remote host sharedMemoryConnection.LowLevel_SendSync(outputStream, timeout); if (securitySession.IsEstablished) { break; } } finally { if (inputStream != null) { inputStream.Close(); } if (outputStream != null) { outputStream.Close(); } } } } sharedMemoryConnection.ConnectionLevelSecurity = securitySession; HostInformation remote = null; // read remote info using (Stream remoteUriStream = sharedMemoryConnection.LowLevel_ReadSync(timeout)) { BinaryReader binaryReader = new BinaryReader(remoteUriStream); remoteUri = binaryReader.ReadString(); remote = this.ITransportContext.KnownHosts[remoteUri]; if (protocolVersion > 0) { remoteHostUniqueIdentifier = binaryReader.ReadInt32(); } } // now send connection info through the established connection using (GenuineChunkedStream serializedLocalInfo = new GenuineChunkedStream(false)) { // serialize local info BinaryWriter binaryWriter = new BinaryWriter(serializedLocalInfo); binaryWriter.Write((string)localUri); if (protocolVersion > 0) { binaryWriter.Write((int)remote.LocalHostUniqueIdentifier); } // and send it sharedMemoryConnection.LowLevel_SendSync(serializedLocalInfo, timeout); } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.LowLevel_AcceptConnection_1", LogMessageType.ConnectionEstablished, null, null, remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, securitySession, connectionLevelSSName, sharedMemoryConnection.DbgConnectionId, (int)GenuineConnectionType.Persistent, 0, 0, this.GetType().Name, null, null, null, "The connection to the remote host has been established."); } return(sharedMemoryConnection); }
/// <summary> /// Opens a connection to the host specified by the url. /// </summary> /// <param name="remote">The HostInformation of the Remote Host.</param> /// <param name="localUri">The uri of the local host.</param> /// <param name="remoteUri">The uri of the remote host.</param> /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param> /// <returns>The established connection.</returns> private SharedMemoryConnection LowLevel_OpenConnection(HostInformation remote, string localUri, out string remoteUri, out int remoteHostUniqueIdentifier) { using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) { throw OperationException.WrapException(this._disposeReason); } } remoteUri = null; Stream inputStream = null; Stream outputStream = null; string url = remote.Url; // the maximum time during which the connection must be established int timeout = GenuineUtility.GetTimeout((TimeSpan)this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout]); IParameterProvider parameters = this.ITransportContext.IParameterProvider; string mutexName = GenuineSharedMemoryChannel.ConstructSharedObjectName( "MUTEX" + url, parameters); string clientConnected = GenuineSharedMemoryChannel.ConstructSharedObjectName( "CC" + url, parameters); string clientAccepted = GenuineSharedMemoryChannel.ConstructSharedObjectName( "CA" + url, parameters); // open the server share SharedMemoryConnection serverSharedMemoryConnection = new SharedMemoryConnection(this.ITransportContext, url, false, false); // LOG: BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "SharedMemoryConnectionManager.LowLevel_OpenConnection", LogMessageType.ConnectionParameters, null, remote, this.ITransportContext.IParameterProvider, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, serverSharedMemoryConnection.DbgConnectionId, "A Shared Memory connection is being established."); } // and create the local share string shareName = "gshmem://" + Guid.NewGuid().ToString("N"); SharedMemoryConnection sharedMemoryConnection = new SharedMemoryConnection(this.ITransportContext, shareName, true, true); BinaryWriter connectionInformation = MessageCoder.SerializeConnectionHeader(MessageCoder.PROTOCOL_VERSION, GenuineConnectionType.Persistent, "Default"); connectionInformation.Write(shareName); // let the server know that a client's share is ready Mutex mutex = null; try { mutex = WindowsAPI.OpenMutex(mutexName); NamedEvent _clientConnected = NamedEvent.OpenNamedEvent(clientConnected); NamedEvent _clientAccepted = NamedEvent.OpenNamedEvent(clientAccepted); if (!GenuineUtility.WaitOne(mutex, GenuineUtility.GetMillisecondsLeft(timeout))) { throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, "Can not acquire the lock for the global mutex."); } // wait until server accepts this client _clientAccepted.ManualResetEvent.Reset(); _clientConnected.ManualResetEvent.Set(); // copy client's name serverSharedMemoryConnection.LowLevel_SendSync(connectionInformation.BaseStream, timeout); if (!GenuineUtility.WaitOne(_clientAccepted.ManualResetEvent, GenuineUtility.GetMillisecondsLeft(timeout))) { throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, "Remote server did not accept a request within the specified time span."); } } finally { if (mutex != null) { try { mutex.ReleaseMutex(); } catch { } try { mutex.Close(); } catch { } } } // get the connection-level Security Session string connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string; SecuritySession securitySession = null; if (connectionLevelSSName != null) { securitySession = this.ITransportContext.IKeyStore.GetKey(connectionLevelSSName).CreateSecuritySession(connectionLevelSSName, null); } // establish it if (securitySession != null && !securitySession.IsEstablished) { bool firstPass = true; for ( ; ;) { inputStream = Stream.Null; try { // prepare streams if (!firstPass) { inputStream = sharedMemoryConnection.LowLevel_ReadSync(timeout); } else { firstPass = false; } outputStream = securitySession.EstablishSession(inputStream, true); if (outputStream == null) { break; } // send a packet to the remote host sharedMemoryConnection.LowLevel_SendSync(outputStream, timeout); if (securitySession.IsEstablished) { break; } } finally { if (inputStream != null) { inputStream.Close(); } if (outputStream != null) { outputStream.Close(); } } } } sharedMemoryConnection.ConnectionLevelSecurity = securitySession; // now send connection info through the established connection using (GenuineChunkedStream serializedLocalInfo = new GenuineChunkedStream(false)) { // serialize local info BinaryWriter binaryWriter = new BinaryWriter(serializedLocalInfo); binaryWriter.Write((string)localUri); binaryWriter.Write((int)remote.LocalHostUniqueIdentifier); // and send it sharedMemoryConnection.LowLevel_SendSync(serializedLocalInfo, timeout); // read remote info using (Stream remoteUriStream = sharedMemoryConnection.LowLevel_ReadSync(timeout)) { BinaryReader binaryReader = new BinaryReader(remoteUriStream); remoteUri = binaryReader.ReadString(); remoteHostUniqueIdentifier = binaryReader.ReadInt32(); } } sharedMemoryConnection.Remote = remote; sharedMemoryConnection.Remote.UpdateUri(remoteUri, remoteHostUniqueIdentifier); sharedMemoryConnection.Remote.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Opened; // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.HostInformation] > 0) { binaryLogWriter.WriteHostInformationEvent("SharedMemoryConnectionManager.LowLevel_OpenConnection", LogMessageType.HostInformationCreated, null, remote, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, sharedMemoryConnection.DbgConnectionId, "HostInformation is ready for actions."); } // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.LowLevel_OpenConnection", LogMessageType.ConnectionEstablished, null, null, remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, securitySession, connectionLevelSSName, sharedMemoryConnection.DbgConnectionId, (int)GenuineConnectionType.Persistent, 0, 0, this.GetType().Name, null, null, null, "The connection to the remote host is established."); } return(sharedMemoryConnection); }
/// <summary> /// Starts listening to the specified end point and accepting incoming connections. /// </summary> /// <param name="endPoint">The end point.</param> public override void StartListening(object endPoint) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if (this._smAcceptConnectionClosure != null) { throw GenuineExceptions.Get_Server_EndPointIsAlreadyBeingListenedTo(this._smAcceptConnectionClosure.ShareName); } SharedMemoryConnection sharedMemoryConnection = null; using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) { throw OperationException.WrapException(this._disposeReason); } } string shareName = endPoint as string; if (shareName == null || shareName.Length <= 0 || !shareName.StartsWith("gshmem")) { throw GenuineExceptions.Get_Server_IncorrectAddressToListen(shareName); } try { sharedMemoryConnection = new SharedMemoryConnection(this.ITransportContext, shareName, true, true); this._smAcceptConnectionClosure = new SMAcceptConnectionClosure(this.ITransportContext, sharedMemoryConnection, this, shareName); this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GeneralListenerStarted, null, this.Local, endPoint)); Thread thread = new Thread(new ThreadStart(this._smAcceptConnectionClosure.AcceptConnections)); thread.IsBackground = true; thread.Start(); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "SharedMemoryConnectionManager.StartListening", LogMessageType.ListeningStarted, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, shareName, null, null, null, "\"{0}\" is now listened.", shareName); } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.AcceptingConnection, "SharedMemoryConnectionManager.StartListening", LogMessageType.ListeningStarted, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, 0, 0, 0, shareName, null, null, null, "Listening to \"{0}\" cannot be started.", shareName); } if (sharedMemoryConnection != null) { sharedMemoryConnection.ReleaseUnmanagedResources(); } throw; } }
/// <summary> /// Requests message processing from the current sink. /// </summary> /// <param name="msg">The message to process.</param> /// <param name="requestHeaders">The headers to add to the outgoing message heading to the server.</param> /// <param name="requestStream">The stream headed to the transport sink.</param> /// <param name="responseHeaders">When this method returns, contains an ITransportHeaders interface that holds the headers that the server returned. This parameter is passed uninitialized.</param> /// <param name="responseStream">When this method returns, contains a Stream coming back from the transport sink. This parameter is passed uninitialized.</param> public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, out ITransportHeaders responseHeaders, out Stream responseStream) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; ITransportContext iTransportContext = this.ITransportContext; if (!GenuineUtility.CheckUrlOnConnectivity(this._recipientUri)) { // get the transport context from the Uri Storage iTransportContext = UriStorage.GetTransportContext(this._recipientUri); if (iTransportContext == null) { iTransportContext = this.ITransportContext; } } Message message = Message.CreateOutcomingMessage(iTransportContext, msg, requestHeaders, requestStream, true); try { message.Recipient = iTransportContext.KnownHosts[this._recipientUri]; // LOG: put down the log record if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteMessageCreatedEvent("GenuineTcpClientTransportSink.ProcessMessage", LogMessageType.MessageCreated, null, message, true, message.Recipient, this.ITransportContext.BinaryLogWriter[LogCategory.MessageProcessing] > 1 ? message.Stream : null, msg.Properties["__Uri"] as string, BinaryLogWriter.ParseInvocationMethod(msg.Properties["__MethodName"] as string, msg.Properties["__TypeName"] as string), GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, -1, -1, null, -1, null, "Synchronous .NET Remoting invocaiton is being initiated."); message.ITransportHeaders[Message.TransportHeadersInvocationTarget] = msg.Properties["__Uri"] as string; message.ITransportHeaders[Message.TransportHeadersMethodName] = BinaryLogWriter.ParseInvocationMethod(msg.Properties["__MethodName"] as string, msg.Properties["__TypeName"] as string); binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineTcpClientTransportSink.ProcessMessage", LogMessageType.MessageRequestInvoking, null, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, GenuineUtility.TickCount, 0, 0, null, null, null, null, "The .NET Remoting synchronous invocation has been made."); } SyncSinkStackResponseProcessor syncSinkStackResponseProcessor = new SyncSinkStackResponseProcessor(iTransportContext, message); iTransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, syncSinkStackResponseProcessor); message.CancelSending = syncSinkStackResponseProcessor.IsReceivedEvent; try { // send the message or initiate the sending iTransportContext.ConnectionManager.Send(message); } catch (Exception ex) { // if it's a response processor's problem, force its exception to be fired if (syncSinkStackResponseProcessor.DispatchedException != null) { throw OperationException.WrapException(syncSinkStackResponseProcessor.DispatchedException); } syncSinkStackResponseProcessor.DispatchException(ex); throw; } if (!GenuineUtility.WaitOne(syncSinkStackResponseProcessor.IsReceivedEvent, GenuineUtility.GetMillisecondsLeft(message.FinishTime))) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } if (syncSinkStackResponseProcessor.DispatchedException != null) { throw OperationException.WrapException(syncSinkStackResponseProcessor.DispatchedException); } // LOG: put down the log record if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineTcpClientTransportSink.ProcessMessage", LogMessageType.MessageDispatched, null, syncSinkStackResponseProcessor.Response, syncSinkStackResponseProcessor.Response.Sender, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null, "The .NET Remoting synchronous invocation has been completed."); } responseHeaders = syncSinkStackResponseProcessor.Response.ITransportHeaders; responseStream = syncSinkStackResponseProcessor.Response.Stream; } catch (Exception ex) { // LOG: put down the log record if (binaryLogWriter != null && binaryLogWriter[LogCategory.MessageProcessing] > 0) { binaryLogWriter.WriteEvent(LogCategory.MessageProcessing, "GenuineTcpClientTransportSink.ProcessMessage", LogMessageType.MessageDispatched, ex, message, message.Recipient, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, -1, GenuineUtility.TickCount, 0, message.SeqNo, null, null, null, null, "The exception is dispatched to the caller context."); } throw; } }